From b32f66bfff7576bc2356448688f03ab973c6ee2d Mon Sep 17 00:00:00 2001 From: Sunmin Lee Date: Tue, 30 May 2017 18:53:16 +0900 Subject: [PATCH 2/3] Imported Upstream version 9.20 Change-Id: Ic7b17acf9b7bfcd1297adf5a6ca3919112ed5ede --- Asm/arm/7zCrcOpt.asm | 100 + Asm/x86/7zAsm.asm | 93 + Asm/x86/7zCrcOpt.asm | 147 ++ Asm/x86/AesOpt.asm | 237 ++ C/7z.h | 203 ++ C/7zAlloc.c | 76 + C/7zAlloc.h | 15 + C/7zBuf.c | 36 + C/7zBuf.h | 39 + C/7zBuf2.c | 45 + C/7zCrc.c | 74 + C/7zCrc.h | 25 + C/7zCrcOpt.c | 34 + C/7zDec.c | 470 ++++ C/7zFile.c | 284 +++ C/7zFile.h | 83 + C/7zIn.c | 1402 +++++++++++ C/7zStream.c | 169 ++ C/7zVersion.h | 7 + C/Aes.c | 282 +++ C/Aes.h | 38 + C/AesOpt.c | 182 ++ C/Alloc.c | 127 + C/Alloc.h | 38 + C/Bcj2.c | 132 + C/Bcj2.h | 38 + C/Bra.c | 133 + C/Bra.h | 68 + C/Bra86.c | 85 + C/BraIA64.c | 67 + C/BwtSort.c | 516 ++++ C/BwtSort.h | 30 + C/CpuArch.c | 168 ++ C/CpuArch.h | 155 ++ C/Delta.c | 62 + C/Delta.h | 23 + C/HuffEnc.c | 146 ++ C/HuffEnc.h | 27 + C/LzFind.c | 761 ++++++ C/LzFind.h | 115 + C/LzFindMt.c | 793 ++++++ C/LzFindMt.h | 105 + C/LzHash.h | 54 + C/Lzma2Dec.c | 356 +++ C/Lzma2Dec.h | 84 + C/Lzma2Enc.c | 477 ++++ C/Lzma2Enc.h | 66 + C/Lzma86.h | 111 + C/Lzma86Dec.c | 56 + C/Lzma86Enc.c | 108 + C/LzmaDec.c | 999 ++++++++ C/LzmaDec.h | 231 ++ C/LzmaEnc.c | 2268 +++++++++++++++++ C/LzmaEnc.h | 80 + C/LzmaLib.c | 46 + C/LzmaLib.h | 135 + C/MtCoder.c | 327 +++ C/MtCoder.h | 98 + C/Ppmd.h | 81 + C/Ppmd7.c | 708 ++++++ C/Ppmd7.h | 140 ++ C/Ppmd7Dec.c | 187 ++ C/Ppmd7Enc.c | 185 ++ C/Ppmd8.c | 1120 +++++++++ C/Ppmd8.h | 133 + C/Ppmd8Dec.c | 155 ++ C/Ppmd8Enc.c | 161 ++ C/RotateDefs.h | 20 + C/Sha256.c | 204 ++ C/Sha256.h | 26 + C/Sort.c | 93 + C/Sort.h | 20 + C/Threads.c | 84 + C/Threads.h | 59 + C/Types.h | 254 ++ C/Util/7z/7z.dsp | 214 ++ C/Util/7z/7z.dsw | 29 + C/Util/7z/7zMain.c | 501 ++++ C/Util/7z/makefile | 37 + C/Util/7z/makefile.gcc | 70 + C/Util/Lzma/LzmaUtil.c | 254 ++ C/Util/Lzma/LzmaUtil.dsp | 168 ++ C/Util/Lzma/LzmaUtil.dsw | 29 + C/Util/Lzma/makefile | 28 + C/Util/Lzma/makefile.gcc | 44 + C/Util/LzmaLib/LzmaLib.def | 4 + C/Util/LzmaLib/LzmaLib.dsp | 178 ++ C/Util/LzmaLib/LzmaLib.dsw | 29 + C/Util/LzmaLib/LzmaLibExports.c | 12 + C/Util/LzmaLib/makefile | 34 + C/Util/LzmaLib/resource.rc | 4 + C/Util/SfxSetup/SfxSetup.c | 592 +++++ C/Util/SfxSetup/SfxSetup.dsp | 198 ++ C/Util/SfxSetup/SfxSetup.dsw | 29 + C/Util/SfxSetup/makefile | 35 + C/Util/SfxSetup/makefile_con | 35 + C/Util/SfxSetup/resource.rc | 6 + C/Util/SfxSetup/setup.ico | Bin 0 -> 1078 bytes C/Xz.c | 88 + C/Xz.h | 252 ++ C/XzCrc64.c | 33 + C/XzCrc64.h | 26 + C/XzDec.c | 875 +++++++ C/XzEnc.c | 497 ++++ C/XzEnc.h | 25 + C/XzIn.c | 306 +++ CPP/7zip/Aes.mak | 7 + CPP/7zip/Archive/7z/7z.dsp | 650 +++++ CPP/7zip/Archive/7z/7z.dsw | 29 + CPP/7zip/Archive/7z/7zCompressionMode.cpp | 3 + CPP/7zip/Archive/7z/7zCompressionMode.h | 50 + CPP/7zip/Archive/7z/7zDecode.cpp | 332 +++ CPP/7zip/Archive/7z/7zDecode.h | 68 + CPP/7zip/Archive/7z/7zEncode.cpp | 444 ++++ CPP/7zip/Archive/7z/7zEncode.h | 55 + CPP/7zip/Archive/7z/7zExtract.cpp | 270 ++ CPP/7zip/Archive/7z/7zFolderInStream.cpp | 123 + CPP/7zip/Archive/7z/7zFolderInStream.h | 58 + CPP/7zip/Archive/7z/7zFolderOutStream.cpp | 149 ++ CPP/7zip/Archive/7z/7zFolderOutStream.h | 58 + CPP/7zip/Archive/7z/7zHandler.cpp | 482 ++++ CPP/7zip/Archive/7z/7zHandler.h | 119 + CPP/7zip/Archive/7z/7zHandlerOut.cpp | 483 ++++ CPP/7zip/Archive/7z/7zHeader.cpp | 14 + CPP/7zip/Archive/7z/7zHeader.h | 97 + CPP/7zip/Archive/7z/7zIn.cpp | 1276 ++++++++++ CPP/7zip/Archive/7z/7zIn.h | 245 ++ CPP/7zip/Archive/7z/7zItem.h | 268 ++ CPP/7zip/Archive/7z/7zOut.cpp | 866 +++++++ CPP/7zip/Archive/7z/7zOut.h | 152 ++ CPP/7zip/Archive/7z/7zProperties.cpp | 164 ++ CPP/7zip/Archive/7z/7zProperties.h | 22 + CPP/7zip/Archive/7z/7zRegister.cpp | 18 + CPP/7zip/Archive/7z/7zSpecStream.cpp | 24 + CPP/7zip/Archive/7z/7zSpecStream.h | 35 + CPP/7zip/Archive/7z/7zUpdate.cpp | 1177 +++++++++ CPP/7zip/Archive/7z/7zUpdate.h | 88 + CPP/7zip/Archive/7z/StdAfx.cpp | 3 + CPP/7zip/Archive/7z/StdAfx.h | 9 + CPP/7zip/Archive/7z/makefile | 110 + CPP/7zip/Archive/7z/resource.rc | 11 + CPP/7zip/Archive/ApmHandler.cpp | 356 +++ CPP/7zip/Archive/Archive.def | 6 + CPP/7zip/Archive/Archive2.def | 9 + CPP/7zip/Archive/ArchiveExports.cpp | 135 + CPP/7zip/Archive/ArjHandler.cpp | 798 ++++++ CPP/7zip/Archive/Bz2Handler.cpp | 423 ++++ CPP/7zip/Archive/Cab/CabBlockInStream.cpp | 189 ++ CPP/7zip/Archive/Cab/CabBlockInStream.h | 44 + CPP/7zip/Archive/Cab/CabHandler.cpp | 929 +++++++ CPP/7zip/Archive/Cab/CabHandler.h | 28 + CPP/7zip/Archive/Cab/CabHeader.cpp | 15 + CPP/7zip/Archive/Cab/CabHeader.h | 44 + CPP/7zip/Archive/Cab/CabIn.cpp | 272 ++ CPP/7zip/Archive/Cab/CabIn.h | 161 ++ CPP/7zip/Archive/Cab/CabItem.h | 63 + CPP/7zip/Archive/Cab/CabRegister.cpp | 13 + CPP/7zip/Archive/Cab/StdAfx.h | 8 + CPP/7zip/Archive/Chm/ChmHandler.cpp | 721 ++++++ CPP/7zip/Archive/Chm/ChmHandler.h | 29 + CPP/7zip/Archive/Chm/ChmHeader.cpp | 24 + CPP/7zip/Archive/Chm/ChmHeader.h | 28 + CPP/7zip/Archive/Chm/ChmIn.cpp | 937 +++++++ CPP/7zip/Archive/Chm/ChmIn.h | 244 ++ CPP/7zip/Archive/Chm/ChmRegister.cpp | 13 + CPP/7zip/Archive/Chm/StdAfx.h | 8 + CPP/7zip/Archive/Com/ComHandler.cpp | 239 ++ CPP/7zip/Archive/Com/ComHandler.h | 28 + CPP/7zip/Archive/Com/ComIn.cpp | 389 +++ CPP/7zip/Archive/Com/ComIn.h | 119 + CPP/7zip/Archive/Com/ComRegister.cpp | 13 + CPP/7zip/Archive/Common/CoderMixer.cpp | 19 + CPP/7zip/Archive/Common/CoderMixer.h | 32 + CPP/7zip/Archive/Common/CoderMixer2.cpp | 121 + CPP/7zip/Archive/Common/CoderMixer2.h | 174 ++ CPP/7zip/Archive/Common/CoderMixer2MT.cpp | 240 ++ CPP/7zip/Archive/Common/CoderMixer2MT.h | 80 + CPP/7zip/Archive/Common/CoderMixer2ST.cpp | 239 ++ CPP/7zip/Archive/Common/CoderMixer2ST.h | 88 + CPP/7zip/Archive/Common/CoderMixerMT.cpp | 99 + CPP/7zip/Archive/Common/CoderMixerMT.h | 69 + CPP/7zip/Archive/Common/CrossThreadProgress.cpp | 15 + CPP/7zip/Archive/Common/CrossThreadProgress.h | 37 + CPP/7zip/Archive/Common/DummyOutStream.cpp | 22 + CPP/7zip/Archive/Common/DummyOutStream.h | 24 + CPP/7zip/Archive/Common/FindSignature.cpp | 62 + CPP/7zip/Archive/Common/FindSignature.h | 12 + CPP/7zip/Archive/Common/HandlerOut.cpp | 623 +++++ CPP/7zip/Archive/Common/HandlerOut.h | 87 + CPP/7zip/Archive/Common/InStreamWithCRC.cpp | 42 + CPP/7zip/Archive/Common/InStreamWithCRC.h | 67 + CPP/7zip/Archive/Common/ItemNameUtils.cpp | 61 + CPP/7zip/Archive/Common/ItemNameUtils.h | 24 + CPP/7zip/Archive/Common/MultiStream.cpp | 190 ++ CPP/7zip/Archive/Common/MultiStream.h | 84 + CPP/7zip/Archive/Common/OutStreamWithCRC.cpp | 18 + CPP/7zip/Archive/Common/OutStreamWithCRC.h | 36 + CPP/7zip/Archive/Common/OutStreamWithSha1.cpp | 18 + CPP/7zip/Archive/Common/OutStreamWithSha1.h | 36 + CPP/7zip/Archive/Common/ParseProperties.cpp | 177 ++ CPP/7zip/Archive/Common/ParseProperties.h | 18 + CPP/7zip/Archive/Common/StdAfx.h | 9 + CPP/7zip/Archive/CpioHandler.cpp | 624 +++++ CPP/7zip/Archive/CramfsHandler.cpp | 644 +++++ CPP/7zip/Archive/DebHandler.cpp | 413 +++ CPP/7zip/Archive/DeflateProps.cpp | 118 + CPP/7zip/Archive/DeflateProps.h | 35 + CPP/7zip/Archive/DllExports.cpp | 47 + CPP/7zip/Archive/DllExports2.cpp | 74 + CPP/7zip/Archive/DmgHandler.cpp | 918 +++++++ CPP/7zip/Archive/ElfHandler.cpp | 534 ++++ CPP/7zip/Archive/FatHandler.cpp | 996 ++++++++ CPP/7zip/Archive/FlvHandler.cpp | 544 ++++ CPP/7zip/Archive/GzHandler.cpp | 698 ++++++ CPP/7zip/Archive/Hfs/HfsHandler.cpp | 243 ++ CPP/7zip/Archive/Hfs/HfsHandler.h | 26 + CPP/7zip/Archive/Hfs/HfsIn.cpp | 480 ++++ CPP/7zip/Archive/Hfs/HfsIn.h | 154 ++ CPP/7zip/Archive/Hfs/HfsRegister.cpp | 13 + CPP/7zip/Archive/IArchive.h | 234 ++ CPP/7zip/Archive/Icons/7z.ico | Bin 0 -> 4710 bytes CPP/7zip/Archive/Icons/arj.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Icons/bz2.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Icons/cab.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Icons/cpio.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Icons/deb.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Icons/dmg.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Icons/fat.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Icons/gz.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Icons/hfs.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Icons/iso.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Icons/lzh.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Icons/lzma.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Icons/ntfs.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Icons/rar.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Icons/rpm.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Icons/split.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Icons/squashfs.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Icons/tar.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Icons/vhd.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Icons/wim.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Icons/xar.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Icons/xz.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Icons/z.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Icons/zip.ico | Bin 0 -> 3638 bytes CPP/7zip/Archive/Iso/IsoHandler.cpp | 326 +++ CPP/7zip/Archive/Iso/IsoHandler.h | 30 + CPP/7zip/Archive/Iso/IsoHeader.cpp | 21 + CPP/7zip/Archive/Iso/IsoHeader.h | 61 + CPP/7zip/Archive/Iso/IsoIn.cpp | 453 ++++ CPP/7zip/Archive/Iso/IsoIn.h | 315 +++ CPP/7zip/Archive/Iso/IsoItem.h | 141 ++ CPP/7zip/Archive/Iso/IsoRegister.cpp | 13 + CPP/7zip/Archive/Iso/StdAfx.h | 9 + CPP/7zip/Archive/LzhHandler.cpp | 775 ++++++ CPP/7zip/Archive/LzmaHandler.cpp | 430 ++++ CPP/7zip/Archive/MachoHandler.cpp | 500 ++++ CPP/7zip/Archive/MbrHandler.cpp | 507 ++++ CPP/7zip/Archive/MslzHandler.cpp | 257 ++ CPP/7zip/Archive/MubHandler.cpp | 266 ++ CPP/7zip/Archive/Nsis/NsisDecode.cpp | 130 + CPP/7zip/Archive/Nsis/NsisDecode.h | 47 + CPP/7zip/Archive/Nsis/NsisHandler.cpp | 510 ++++ CPP/7zip/Archive/Nsis/NsisHandler.h | 43 + CPP/7zip/Archive/Nsis/NsisIn.cpp | 1461 +++++++++++ CPP/7zip/Archive/Nsis/NsisIn.h | 181 ++ CPP/7zip/Archive/Nsis/NsisRegister.cpp | 13 + CPP/7zip/Archive/Nsis/StdAfx.h | 9 + CPP/7zip/Archive/NtfsHandler.cpp | 1764 +++++++++++++ CPP/7zip/Archive/PeHandler.cpp | 1752 +++++++++++++ CPP/7zip/Archive/PpmdHandler.cpp | 456 ++++ CPP/7zip/Archive/Rar/RarHandler.cpp | 869 +++++++ CPP/7zip/Archive/Rar/RarHandler.h | 66 + CPP/7zip/Archive/Rar/RarHeader.cpp | 21 + CPP/7zip/Archive/Rar/RarHeader.h | 205 ++ CPP/7zip/Archive/Rar/RarIn.cpp | 478 ++++ CPP/7zip/Archive/Rar/RarIn.h | 123 + CPP/7zip/Archive/Rar/RarItem.cpp | 55 + CPP/7zip/Archive/Rar/RarItem.h | 79 + CPP/7zip/Archive/Rar/RarRegister.cpp | 13 + CPP/7zip/Archive/Rar/RarVolumeInStream.cpp | 78 + CPP/7zip/Archive/Rar/RarVolumeInStream.h | 49 + CPP/7zip/Archive/Rar/StdAfx.cpp | 3 + CPP/7zip/Archive/Rar/StdAfx.h | 8 + CPP/7zip/Archive/RpmHandler.cpp | 292 +++ CPP/7zip/Archive/SplitHandler.cpp | 366 +++ CPP/7zip/Archive/SquashfsHandler.cpp | 2155 ++++++++++++++++ CPP/7zip/Archive/StdAfx.h | 9 + CPP/7zip/Archive/SwfHandler.cpp | 706 ++++++ CPP/7zip/Archive/Tar/StdAfx.h | 9 + CPP/7zip/Archive/Tar/TarHandler.cpp | 386 +++ CPP/7zip/Archive/Tar/TarHandler.h | 61 + CPP/7zip/Archive/Tar/TarHandlerOut.cpp | 122 + CPP/7zip/Archive/Tar/TarHeader.cpp | 25 + CPP/7zip/Archive/Tar/TarHeader.h | 108 + CPP/7zip/Archive/Tar/TarIn.cpp | 207 ++ CPP/7zip/Archive/Tar/TarIn.h | 17 + CPP/7zip/Archive/Tar/TarItem.h | 72 + CPP/7zip/Archive/Tar/TarOut.cpp | 187 ++ CPP/7zip/Archive/Tar/TarOut.h | 28 + CPP/7zip/Archive/Tar/TarRegister.cpp | 18 + CPP/7zip/Archive/Tar/TarUpdate.cpp | 139 + CPP/7zip/Archive/Tar/TarUpdate.h | 34 + CPP/7zip/Archive/Udf/StdAfx.h | 9 + CPP/7zip/Archive/Udf/UdfHandler.cpp | 451 ++++ CPP/7zip/Archive/Udf/UdfHandler.h | 37 + CPP/7zip/Archive/Udf/UdfIn.cpp | 876 +++++++ CPP/7zip/Archive/Udf/UdfIn.h | 375 +++ CPP/7zip/Archive/Udf/UdfRegister.cpp | 13 + CPP/7zip/Archive/VhdHandler.cpp | 734 ++++++ CPP/7zip/Archive/Wim/StdAfx.h | 8 + CPP/7zip/Archive/Wim/WimHandler.cpp | 660 +++++ CPP/7zip/Archive/Wim/WimHandler.h | 77 + CPP/7zip/Archive/Wim/WimHandlerOut.cpp | 639 +++++ CPP/7zip/Archive/Wim/WimIn.cpp | 855 +++++++ CPP/7zip/Archive/Wim/WimIn.h | 297 +++ CPP/7zip/Archive/Wim/WimRegister.cpp | 18 + CPP/7zip/Archive/XarHandler.cpp | 588 +++++ CPP/7zip/Archive/XzHandler.cpp | 707 ++++++ CPP/7zip/Archive/ZHandler.cpp | 161 ++ CPP/7zip/Archive/Zip/StdAfx.h | 8 + CPP/7zip/Archive/Zip/ZipAddCommon.cpp | 379 +++ CPP/7zip/Archive/Zip/ZipAddCommon.h | 56 + CPP/7zip/Archive/Zip/ZipCompressionMode.h | 42 + CPP/7zip/Archive/Zip/ZipHandler.cpp | 822 ++++++ CPP/7zip/Archive/Zip/ZipHandler.h | 101 + CPP/7zip/Archive/Zip/ZipHandlerOut.cpp | 531 ++++ CPP/7zip/Archive/Zip/ZipHeader.cpp | 36 + CPP/7zip/Archive/Zip/ZipHeader.h | 284 +++ CPP/7zip/Archive/Zip/ZipIn.cpp | 893 +++++++ CPP/7zip/Archive/Zip/ZipIn.h | 125 + CPP/7zip/Archive/Zip/ZipItem.cpp | 172 ++ CPP/7zip/Archive/Zip/ZipItem.h | 281 +++ CPP/7zip/Archive/Zip/ZipItemEx.h | 34 + CPP/7zip/Archive/Zip/ZipOut.cpp | 289 +++ CPP/7zip/Archive/Zip/ZipOut.h | 56 + CPP/7zip/Archive/Zip/ZipRegister.cpp | 18 + CPP/7zip/Archive/Zip/ZipUpdate.cpp | 1068 ++++++++ CPP/7zip/Archive/Zip/ZipUpdate.h | 58 + CPP/7zip/Archive/makefile | 23 + CPP/7zip/Asm.mak | 7 + CPP/7zip/Bundles/Alone/Alone.dsp | 2928 ++++++++++++++++++++++ CPP/7zip/Bundles/Alone/Alone.dsw | 29 + CPP/7zip/Bundles/Alone/StdAfx.cpp | 3 + CPP/7zip/Bundles/Alone/StdAfx.h | 9 + CPP/7zip/Bundles/Alone/afxres.h | 1 + CPP/7zip/Bundles/Alone/makefile | 308 +++ CPP/7zip/Bundles/Alone/resource.rc | 3 + CPP/7zip/Bundles/Alone7z/StdAfx.cpp | 3 + CPP/7zip/Bundles/Alone7z/StdAfx.h | 9 + CPP/7zip/Bundles/Alone7z/makefile | 213 ++ CPP/7zip/Bundles/Alone7z/resource.rc | 3 + CPP/7zip/Bundles/Fm/FM.dsp | 1726 +++++++++++++ CPP/7zip/Bundles/Fm/FM.dsw | 29 + CPP/7zip/Bundles/Fm/StdAfx.cpp | 3 + CPP/7zip/Bundles/Fm/StdAfx.h | 23 + CPP/7zip/Bundles/Fm/makefile | 535 ++++ CPP/7zip/Bundles/Fm/resource.rc | 7 + CPP/7zip/Bundles/Format7z/StdAfx.cpp | 3 + CPP/7zip/Bundles/Format7z/StdAfx.h | 9 + CPP/7zip/Bundles/Format7z/makefile | 181 ++ CPP/7zip/Bundles/Format7z/resource.rc | 5 + CPP/7zip/Bundles/Format7zExtract/StdAfx.cpp | 3 + CPP/7zip/Bundles/Format7zExtract/StdAfx.h | 9 + CPP/7zip/Bundles/Format7zExtract/makefile | 150 ++ CPP/7zip/Bundles/Format7zExtract/resource.rc | 5 + CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp | 3 + CPP/7zip/Bundles/Format7zExtractR/StdAfx.h | 9 + CPP/7zip/Bundles/Format7zExtractR/makefile | 132 + CPP/7zip/Bundles/Format7zExtractR/resource.rc | 5 + CPP/7zip/Bundles/Format7zF/Format7z.dsp | 2627 +++++++++++++++++++ CPP/7zip/Bundles/Format7zF/Format7z.dsw | 29 + CPP/7zip/Bundles/Format7zF/StdAfx.cpp | 3 + CPP/7zip/Bundles/Format7zF/StdAfx.h | 9 + CPP/7zip/Bundles/Format7zF/makefile | 369 +++ CPP/7zip/Bundles/Format7zF/resource.rc | 37 + CPP/7zip/Bundles/Format7zR/StdAfx.cpp | 3 + CPP/7zip/Bundles/Format7zR/StdAfx.h | 9 + CPP/7zip/Bundles/Format7zR/makefile | 149 ++ CPP/7zip/Bundles/Format7zR/resource.rc | 5 + CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp | 525 ++++ CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp | 457 ++++ CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw | 29 + CPP/7zip/Bundles/LzmaCon/StdAfx.cpp | 3 + CPP/7zip/Bundles/LzmaCon/StdAfx.h | 8 + CPP/7zip/Bundles/LzmaCon/makefile | 87 + CPP/7zip/Bundles/LzmaCon/makefile.gcc | 155 ++ CPP/7zip/Bundles/SFXCon/7z.ico | Bin 0 -> 1078 bytes CPP/7zip/Bundles/SFXCon/Main.cpp | 444 ++++ CPP/7zip/Bundles/SFXCon/SFXCon.dsp | 821 ++++++ CPP/7zip/Bundles/SFXCon/SFXCon.dsw | 29 + CPP/7zip/Bundles/SFXCon/StdAfx.cpp | 3 + CPP/7zip/Bundles/SFXCon/StdAfx.h | 9 + CPP/7zip/Bundles/SFXCon/makefile | 164 ++ CPP/7zip/Bundles/SFXCon/resource.rc | 5 + CPP/7zip/Bundles/SFXSetup/ExtractCallback.cpp | 236 ++ CPP/7zip/Bundles/SFXSetup/ExtractCallback.h | 88 + CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp | 130 + CPP/7zip/Bundles/SFXSetup/ExtractEngine.h | 11 + CPP/7zip/Bundles/SFXSetup/Main.cpp | 336 +++ CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp | 748 ++++++ CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw | 29 + CPP/7zip/Bundles/SFXSetup/StdAfx.cpp | 3 + CPP/7zip/Bundles/SFXSetup/StdAfx.h | 10 + CPP/7zip/Bundles/SFXSetup/makefile | 153 ++ CPP/7zip/Bundles/SFXSetup/resource.h | 6 + CPP/7zip/Bundles/SFXSetup/resource.rc | 16 + CPP/7zip/Bundles/SFXSetup/setup.ico | Bin 0 -> 1078 bytes CPP/7zip/Bundles/SFXWin/7z.ico | Bin 0 -> 1078 bytes CPP/7zip/Bundles/SFXWin/Main.cpp | 173 ++ CPP/7zip/Bundles/SFXWin/SFXWin.dsp | 885 +++++++ CPP/7zip/Bundles/SFXWin/SFXWin.dsw | 29 + CPP/7zip/Bundles/SFXWin/StdAfx.cpp | 3 + CPP/7zip/Bundles/SFXWin/StdAfx.h | 12 + CPP/7zip/Bundles/SFXWin/makefile | 191 ++ CPP/7zip/Bundles/SFXWin/resource.h | 1 + CPP/7zip/Bundles/SFXWin/resource.rc | 43 + CPP/7zip/Bundles/makefile | 18 + CPP/7zip/Common/CWrappers.cpp | 226 ++ CPP/7zip/Common/CWrappers.h | 109 + CPP/7zip/Common/CreateCoder.cpp | 293 +++ CPP/7zip/Common/CreateCoder.h | 98 + CPP/7zip/Common/FilePathAutoRename.cpp | 55 + CPP/7zip/Common/FilePathAutoRename.h | 10 + CPP/7zip/Common/FileStreams.cpp | 422 ++++ CPP/7zip/Common/FileStreams.h | 144 ++ CPP/7zip/Common/FilterCoder.cpp | 247 ++ CPP/7zip/Common/FilterCoder.h | 128 + CPP/7zip/Common/InBuffer.cpp | 83 + CPP/7zip/Common/InBuffer.h | 81 + CPP/7zip/Common/InMemStream.cpp | 222 ++ CPP/7zip/Common/InMemStream.h | 284 +++ CPP/7zip/Common/InOutTempBuffer.cpp | 122 + CPP/7zip/Common/InOutTempBuffer.h | 48 + CPP/7zip/Common/LimitedStreams.cpp | 154 ++ CPP/7zip/Common/LimitedStreams.h | 125 + CPP/7zip/Common/LockedStream.cpp | 23 + CPP/7zip/Common/LockedStream.h | 38 + CPP/7zip/Common/MemBlocks.cpp | 183 ++ CPP/7zip/Common/MemBlocks.h | 71 + CPP/7zip/Common/MethodId.cpp | 27 + CPP/7zip/Common/MethodId.h | 10 + CPP/7zip/Common/MethodProps.cpp | 99 + CPP/7zip/Common/MethodProps.h | 41 + CPP/7zip/Common/OffsetStream.cpp | 35 + CPP/7zip/Common/OffsetStream.h | 25 + CPP/7zip/Common/OutBuffer.cpp | 116 + CPP/7zip/Common/OutBuffer.h | 64 + CPP/7zip/Common/OutMemStream.cpp | 142 ++ CPP/7zip/Common/OutMemStream.h | 96 + CPP/7zip/Common/ProgressMt.cpp | 53 + CPP/7zip/Common/ProgressMt.h | 46 + CPP/7zip/Common/ProgressUtils.cpp | 42 + CPP/7zip/Common/ProgressUtils.h | 34 + CPP/7zip/Common/RegisterArc.h | 32 + CPP/7zip/Common/RegisterCodec.h | 33 + CPP/7zip/Common/StdAfx.h | 9 + CPP/7zip/Common/StreamBinder.cpp | 150 ++ CPP/7zip/Common/StreamBinder.h | 32 + CPP/7zip/Common/StreamObjects.cpp | 221 ++ CPP/7zip/Common/StreamObjects.h | 135 + CPP/7zip/Common/StreamUtils.cpp | 56 + CPP/7zip/Common/StreamUtils.h | 13 + CPP/7zip/Common/VirtThread.cpp | 46 + CPP/7zip/Common/VirtThread.h | 23 + CPP/7zip/Compress/ArjDecoder1.cpp | 309 +++ CPP/7zip/Compress/ArjDecoder1.h | 98 + CPP/7zip/Compress/ArjDecoder2.cpp | 90 + CPP/7zip/Compress/ArjDecoder2.h | 59 + CPP/7zip/Compress/BZip2Const.h | 54 + CPP/7zip/Compress/BZip2Crc.cpp | 26 + CPP/7zip/Compress/BZip2Crc.h | 31 + CPP/7zip/Compress/BZip2Decoder.cpp | 943 +++++++ CPP/7zip/Compress/BZip2Decoder.h | 205 ++ CPP/7zip/Compress/BZip2Encoder.cpp | 895 +++++++ CPP/7zip/Compress/BZip2Encoder.h | 245 ++ CPP/7zip/Compress/BZip2Register.cpp | 20 + CPP/7zip/Compress/Bcj2Coder.cpp | 386 +++ CPP/7zip/Compress/Bcj2Coder.h | 115 + CPP/7zip/Compress/Bcj2Register.cpp | 19 + CPP/7zip/Compress/BcjCoder.cpp | 15 + CPP/7zip/Compress/BcjCoder.h | 19 + CPP/7zip/Compress/BcjRegister.cpp | 19 + CPP/7zip/Compress/BitlDecoder.cpp | 24 + CPP/7zip/Compress/BitlDecoder.h | 141 ++ CPP/7zip/Compress/BitlEncoder.h | 57 + CPP/7zip/Compress/BitmDecoder.h | 66 + CPP/7zip/Compress/BitmEncoder.h | 50 + CPP/7zip/Compress/BranchCoder.cpp | 19 + CPP/7zip/Compress/BranchCoder.h | 44 + CPP/7zip/Compress/BranchMisc.cpp | 37 + CPP/7zip/Compress/BranchMisc.h | 14 + CPP/7zip/Compress/BranchRegister.cpp | 30 + CPP/7zip/Compress/ByteSwap.cpp | 73 + CPP/7zip/Compress/Codec.def | 4 + CPP/7zip/Compress/CodecExports.cpp | 160 ++ CPP/7zip/Compress/CopyCoder.cpp | 67 + CPP/7zip/Compress/CopyCoder.h | 34 + CPP/7zip/Compress/CopyRegister.cpp | 14 + CPP/7zip/Compress/Deflate64Register.cpp | 20 + CPP/7zip/Compress/DeflateConst.h | 134 + CPP/7zip/Compress/DeflateDecoder.cpp | 353 +++ CPP/7zip/Compress/DeflateDecoder.h | 157 ++ CPP/7zip/Compress/DeflateEncoder.cpp | 986 ++++++++ CPP/7zip/Compress/DeflateEncoder.h | 211 ++ CPP/7zip/Compress/DeflateRegister.cpp | 21 + CPP/7zip/Compress/DeltaFilter.cpp | 112 + CPP/7zip/Compress/DllExports.cpp | 45 + CPP/7zip/Compress/DllExports2.cpp | 28 + CPP/7zip/Compress/HuffmanDecoder.h | 89 + CPP/7zip/Compress/ImplodeDecoder.cpp | 219 ++ CPP/7zip/Compress/ImplodeDecoder.h | 57 + CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp | 89 + CPP/7zip/Compress/ImplodeHuffmanDecoder.h | 34 + CPP/7zip/Compress/LzOutWindow.cpp | 14 + CPP/7zip/Compress/LzOutWindow.h | 66 + CPP/7zip/Compress/LzhDecoder.cpp | 220 ++ CPP/7zip/Compress/LzhDecoder.h | 106 + CPP/7zip/Compress/Lzma2Decoder.cpp | 189 ++ CPP/7zip/Compress/Lzma2Decoder.h | 73 + CPP/7zip/Compress/Lzma2Encoder.cpp | 94 + CPP/7zip/Compress/Lzma2Encoder.h | 36 + CPP/7zip/Compress/Lzma2Register.cpp | 20 + CPP/7zip/Compress/LzmaDecoder.cpp | 252 ++ CPP/7zip/Compress/LzmaDecoder.h | 84 + CPP/7zip/Compress/LzmaEncoder.cpp | 149 ++ CPP/7zip/Compress/LzmaEncoder.h | 36 + CPP/7zip/Compress/LzmaRegister.cpp | 20 + CPP/7zip/Compress/Lzx.h | 61 + CPP/7zip/Compress/Lzx86Converter.cpp | 90 + CPP/7zip/Compress/Lzx86Converter.h | 46 + CPP/7zip/Compress/LzxDecoder.cpp | 387 +++ CPP/7zip/Compress/LzxDecoder.h | 159 ++ CPP/7zip/Compress/Mtf8.h | 193 ++ CPP/7zip/Compress/PpmdDecoder.cpp | 167 ++ CPP/7zip/Compress/PpmdDecoder.h | 78 + CPP/7zip/Compress/PpmdEncoder.cpp | 119 + CPP/7zip/Compress/PpmdEncoder.h | 48 + CPP/7zip/Compress/PpmdRegister.cpp | 21 + CPP/7zip/Compress/PpmdZip.cpp | 223 ++ CPP/7zip/Compress/PpmdZip.h | 72 + CPP/7zip/Compress/QuantumDecoder.cpp | 175 ++ CPP/7zip/Compress/QuantumDecoder.h | 264 ++ CPP/7zip/Compress/RangeCoder.h | 205 ++ CPP/7zip/Compress/RangeCoderBit.h | 114 + CPP/7zip/Compress/Rar1Decoder.cpp | 480 ++++ CPP/7zip/Compress/Rar1Decoder.h | 88 + CPP/7zip/Compress/Rar2Decoder.cpp | 391 +++ CPP/7zip/Compress/Rar2Decoder.h | 174 ++ CPP/7zip/Compress/Rar3Decoder.cpp | 897 +++++++ CPP/7zip/Compress/Rar3Decoder.h | 267 ++ CPP/7zip/Compress/Rar3Vm.cpp | 1091 ++++++++ CPP/7zip/Compress/Rar3Vm.h | 179 ++ CPP/7zip/Compress/RarCodecsRegister.cpp | 26 + CPP/7zip/Compress/ShrinkDecoder.cpp | 145 ++ CPP/7zip/Compress/ShrinkDecoder.h | 38 + CPP/7zip/Compress/StdAfx.h | 8 + CPP/7zip/Compress/ZDecoder.cpp | 159 ++ CPP/7zip/Compress/ZDecoder.h | 42 + CPP/7zip/Compress/ZlibDecoder.cpp | 89 + CPP/7zip/Compress/ZlibDecoder.h | 48 + CPP/7zip/Compress/ZlibEncoder.cpp | 61 + CPP/7zip/Compress/ZlibEncoder.h | 48 + CPP/7zip/Compress/makefile | 7 + CPP/7zip/Crc.mak | 8 + CPP/7zip/Crypto/7zAes.cpp | 244 ++ CPP/7zip/Crypto/7zAes.h | 117 + CPP/7zip/Crypto/7zAesRegister.cpp | 18 + CPP/7zip/Crypto/Codec.def | 4 + CPP/7zip/Crypto/HmacSha1.cpp | 109 + CPP/7zip/Crypto/HmacSha1.h | 39 + CPP/7zip/Crypto/MyAes.cpp | 48 + CPP/7zip/Crypto/MyAes.h | 38 + CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp | 83 + CPP/7zip/Crypto/Pbkdf2HmacSha1.h | 21 + CPP/7zip/Crypto/RandGen.cpp | 107 + CPP/7zip/Crypto/RandGen.h | 21 + CPP/7zip/Crypto/Rar20Crypto.cpp | 133 + CPP/7zip/Crypto/Rar20Crypto.h | 50 + CPP/7zip/Crypto/RarAes.cpp | 134 + CPP/7zip/Crypto/RarAes.h | 47 + CPP/7zip/Crypto/Sha1.cpp | 229 ++ CPP/7zip/Crypto/Sha1.h | 68 + CPP/7zip/Crypto/StdAfx.h | 8 + CPP/7zip/Crypto/WzAes.cpp | 221 ++ CPP/7zip/Crypto/WzAes.h | 125 + CPP/7zip/Crypto/ZipCrypto.cpp | 88 + CPP/7zip/Crypto/ZipCrypto.h | 56 + CPP/7zip/Crypto/ZipStrong.cpp | 164 ++ CPP/7zip/Crypto/ZipStrong.h | 47 + CPP/7zip/GuiCommon.rc | 70 + CPP/7zip/Guid.txt | 170 ++ CPP/7zip/ICoder.h | 186 ++ CPP/7zip/IDecl.h | 15 + CPP/7zip/IPassword.h | 24 + CPP/7zip/IProgress.h | 33 + CPP/7zip/IStream.h | 58 + CPP/7zip/MyVersion.h | 8 + CPP/7zip/MyVersionInfo.rc | 52 + CPP/7zip/PropID.h | 76 + CPP/7zip/SubBuild.mak | 3 + CPP/7zip/UI/Agent/Agent.cpp | 645 +++++ CPP/7zip/UI/Agent/Agent.h | 251 ++ CPP/7zip/UI/Agent/AgentOut.cpp | 533 ++++ CPP/7zip/UI/Agent/AgentProxy.cpp | 246 ++ CPP/7zip/UI/Agent/AgentProxy.h | 53 + CPP/7zip/UI/Agent/ArchiveFolder.cpp | 59 + CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp | 142 ++ CPP/7zip/UI/Agent/ArchiveFolderOut.cpp | 214 ++ CPP/7zip/UI/Agent/IFolderArchive.h | 73 + CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp | 121 + CPP/7zip/UI/Agent/UpdateCallbackAgent.h | 19 + CPP/7zip/UI/Client7z/Client7z.cpp | 871 +++++++ CPP/7zip/UI/Client7z/Client7z.dsp | 226 ++ CPP/7zip/UI/Client7z/Client7z.dsw | 29 + CPP/7zip/UI/Client7z/StdAfx.cpp | 3 + CPP/7zip/UI/Client7z/StdAfx.h | 9 + CPP/7zip/UI/Client7z/makefile | 45 + CPP/7zip/UI/Common/ArchiveCommandLine.cpp | 1042 ++++++++ CPP/7zip/UI/Common/ArchiveCommandLine.h | 111 + CPP/7zip/UI/Common/ArchiveExtractCallback.cpp | 488 ++++ CPP/7zip/UI/Common/ArchiveExtractCallback.h | 143 ++ CPP/7zip/UI/Common/ArchiveName.cpp | 54 + CPP/7zip/UI/Common/ArchiveName.h | 10 + CPP/7zip/UI/Common/ArchiveOpenCallback.cpp | 133 + CPP/7zip/UI/Common/ArchiveOpenCallback.h | 103 + CPP/7zip/UI/Common/Bench.cpp | 1028 ++++++++ CPP/7zip/UI/Common/Bench.h | 42 + CPP/7zip/UI/Common/CompressCall.cpp | 246 ++ CPP/7zip/UI/Common/CompressCall.h | 24 + CPP/7zip/UI/Common/CompressCall2.cpp | 178 ++ CPP/7zip/UI/Common/DefaultName.cpp | 35 + CPP/7zip/UI/Common/DefaultName.h | 11 + CPP/7zip/UI/Common/DirItem.h | 69 + CPP/7zip/UI/Common/EnumDirItems.cpp | 361 +++ CPP/7zip/UI/Common/EnumDirItems.h | 25 + CPP/7zip/UI/Common/ExitCode.h | 27 + CPP/7zip/UI/Common/Extract.cpp | 263 ++ CPP/7zip/UI/Common/Extract.h | 76 + CPP/7zip/UI/Common/ExtractMode.h | 31 + CPP/7zip/UI/Common/ExtractingFilePath.cpp | 142 ++ CPP/7zip/UI/Common/ExtractingFilePath.h | 13 + CPP/7zip/UI/Common/IFileExtractCallback.h | 46 + CPP/7zip/UI/Common/LoadCodecs.cpp | 681 +++++ CPP/7zip/UI/Common/LoadCodecs.h | 235 ++ CPP/7zip/UI/Common/OpenArchive.cpp | 536 ++++ CPP/7zip/UI/Common/OpenArchive.h | 87 + CPP/7zip/UI/Common/PropIDUtils.cpp | 120 + CPP/7zip/UI/Common/PropIDUtils.h | 12 + CPP/7zip/UI/Common/Property.h | 14 + CPP/7zip/UI/Common/SetProperties.cpp | 79 + CPP/7zip/UI/Common/SetProperties.h | 10 + CPP/7zip/UI/Common/SortUtils.cpp | 22 + CPP/7zip/UI/Common/SortUtils.h | 10 + CPP/7zip/UI/Common/StdAfx.h | 9 + CPP/7zip/UI/Common/TempFiles.cpp | 22 + CPP/7zip/UI/Common/TempFiles.h | 16 + CPP/7zip/UI/Common/Update.cpp | 910 +++++++ CPP/7zip/UI/Common/Update.h | 175 ++ CPP/7zip/UI/Common/UpdateAction.cpp | 64 + CPP/7zip/UI/Common/UpdateAction.h | 57 + CPP/7zip/UI/Common/UpdateCallback.cpp | 249 ++ CPP/7zip/UI/Common/UpdateCallback.h | 74 + CPP/7zip/UI/Common/UpdatePair.cpp | 158 ++ CPP/7zip/UI/Common/UpdatePair.h | 25 + CPP/7zip/UI/Common/UpdateProduce.cpp | 58 + CPP/7zip/UI/Common/UpdateProduce.h | 35 + CPP/7zip/UI/Common/WorkDir.cpp | 59 + CPP/7zip/UI/Common/WorkDir.h | 10 + CPP/7zip/UI/Common/ZipRegistry.cpp | 293 +++ CPP/7zip/UI/Common/ZipRegistry.h | 105 + CPP/7zip/UI/Console/BenchCon.cpp | 297 +++ CPP/7zip/UI/Console/BenchCon.h | 16 + CPP/7zip/UI/Console/Console.dsp | 845 +++++++ CPP/7zip/UI/Console/Console.dsw | 29 + CPP/7zip/UI/Console/ConsoleClose.cpp | 73 + CPP/7zip/UI/Console/ConsoleClose.h | 24 + CPP/7zip/UI/Console/ExtractCallbackConsole.cpp | 228 ++ CPP/7zip/UI/Console/ExtractCallbackConsole.h | 73 + CPP/7zip/UI/Console/List.cpp | 654 +++++ CPP/7zip/UI/Console/List.h | 20 + CPP/7zip/UI/Console/Main.cpp | 598 +++++ CPP/7zip/UI/Console/MainAr.cpp | 125 + CPP/7zip/UI/Console/OpenCallbackConsole.cpp | 58 + CPP/7zip/UI/Console/OpenCallbackConsole.h | 24 + CPP/7zip/UI/Console/PercentPrinter.cpp | 90 + CPP/7zip/UI/Console/PercentPrinter.h | 31 + CPP/7zip/UI/Console/StdAfx.cpp | 3 + CPP/7zip/UI/Console/StdAfx.h | 9 + CPP/7zip/UI/Console/UpdateCallbackConsole.cpp | 261 ++ CPP/7zip/UI/Console/UpdateCallbackConsole.h | 62 + CPP/7zip/UI/Console/UserInputUtils.cpp | 87 + CPP/7zip/UI/Console/UserInputUtils.h | 24 + CPP/7zip/UI/Console/makefile | 124 + CPP/7zip/UI/Console/resource.rc | 3 + CPP/7zip/UI/Explorer/7-zip.dll.manifest | 1 + CPP/7zip/UI/Explorer/ContextMenu.cpp | 829 ++++++ CPP/7zip/UI/Explorer/ContextMenu.h | 70 + CPP/7zip/UI/Explorer/ContextMenuFlags.h | 24 + CPP/7zip/UI/Explorer/DllExports.cpp | 265 ++ CPP/7zip/UI/Explorer/Explorer.def | 9 + CPP/7zip/UI/Explorer/Explorer.dsp | 558 +++++ CPP/7zip/UI/Explorer/Explorer.dsw | 29 + CPP/7zip/UI/Explorer/MyMessages.cpp | 58 + CPP/7zip/UI/Explorer/MyMessages.h | 28 + CPP/7zip/UI/Explorer/OptionsDialog.cpp | 71 + CPP/7zip/UI/Explorer/OptionsDialog.h | 23 + CPP/7zip/UI/Explorer/RegistryContextMenu.cpp | 116 + CPP/7zip/UI/Explorer/RegistryContextMenu.h | 16 + CPP/7zip/UI/Explorer/StdAfx.cpp | 3 + CPP/7zip/UI/Explorer/StdAfx.h | 24 + CPP/7zip/UI/Explorer/makefile | 101 + CPP/7zip/UI/Explorer/resource.h | 28 + CPP/7zip/UI/Explorer/resource.rc | 8 + CPP/7zip/UI/Explorer/resource2.rc | 27 + CPP/7zip/UI/Far/ExtractEngine.cpp | 176 ++ CPP/7zip/UI/Far/ExtractEngine.h | 68 + CPP/7zip/UI/Far/Far.def | 34 + CPP/7zip/UI/Far/Far.dsp | 627 +++++ CPP/7zip/UI/Far/Far.dsw | 29 + CPP/7zip/UI/Far/FarPlugin.h | 519 ++++ CPP/7zip/UI/Far/FarUtils.cpp | 464 ++++ CPP/7zip/UI/Far/FarUtils.h | 187 ++ CPP/7zip/UI/Far/Main.cpp | 612 +++++ CPP/7zip/UI/Far/Messages.h | 184 ++ CPP/7zip/UI/Far/OverwriteDialog.cpp | 112 + CPP/7zip/UI/Far/OverwriteDialog.h | 37 + CPP/7zip/UI/Far/Plugin.cpp | 871 +++++++ CPP/7zip/UI/Far/Plugin.h | 88 + CPP/7zip/UI/Far/PluginCommon.cpp | 50 + CPP/7zip/UI/Far/PluginDelete.cpp | 161 ++ CPP/7zip/UI/Far/PluginRead.cpp | 286 +++ CPP/7zip/UI/Far/PluginWrite.cpp | 780 ++++++ CPP/7zip/UI/Far/ProgressBox.cpp | 112 + CPP/7zip/UI/Far/ProgressBox.h | 30 + CPP/7zip/UI/Far/StdAfx.cpp | 3 + CPP/7zip/UI/Far/StdAfx.h | 13 + CPP/7zip/UI/Far/UpdateCallback100.cpp | 66 + CPP/7zip/UI/Far/UpdateCallback100.h | 43 + CPP/7zip/UI/Far/makefile | 119 + CPP/7zip/UI/Far/resource.rc | 3 + CPP/7zip/UI/FileManager/7zFM.exe.manifest | 1 + CPP/7zip/UI/FileManager/7zipLogo.ico | Bin 0 -> 9150 bytes CPP/7zip/UI/FileManager/AboutDialog.cpp | 64 + CPP/7zip/UI/FileManager/AboutDialog.h | 18 + CPP/7zip/UI/FileManager/AboutDialog.rc | 26 + CPP/7zip/UI/FileManager/AboutDialogRes.h | 6 + CPP/7zip/UI/FileManager/Add.bmp | Bin 0 -> 982 bytes CPP/7zip/UI/FileManager/Add2.bmp | Bin 0 -> 406 bytes CPP/7zip/UI/FileManager/App.cpp | 827 ++++++ CPP/7zip/UI/FileManager/App.h | 315 +++ CPP/7zip/UI/FileManager/AppState.h | 114 + CPP/7zip/UI/FileManager/BrowseDialog.cpp | 514 ++++ CPP/7zip/UI/FileManager/BrowseDialog.h | 77 + CPP/7zip/UI/FileManager/BrowseDialog.rc | 17 + CPP/7zip/UI/FileManager/BrowseDialogRes.h | 4 + CPP/7zip/UI/FileManager/ClassDefs.cpp | 7 + CPP/7zip/UI/FileManager/ComboDialog.cpp | 72 + CPP/7zip/UI/FileManager/ComboDialog.h | 27 + CPP/7zip/UI/FileManager/ComboDialog.rc | 13 + CPP/7zip/UI/FileManager/ComboDialogRes.h | 4 + CPP/7zip/UI/FileManager/Copy.bmp | Bin 0 -> 982 bytes CPP/7zip/UI/FileManager/Copy2.bmp | Bin 0 -> 406 bytes CPP/7zip/UI/FileManager/CopyDialog.cpp | 114 + CPP/7zip/UI/FileManager/CopyDialog.h | 31 + CPP/7zip/UI/FileManager/CopyDialog.rc | 17 + CPP/7zip/UI/FileManager/CopyDialogRes.h | 8 + CPP/7zip/UI/FileManager/Delete.bmp | Bin 0 -> 982 bytes CPP/7zip/UI/FileManager/Delete2.bmp | Bin 0 -> 406 bytes CPP/7zip/UI/FileManager/DialogSize.h | 16 + CPP/7zip/UI/FileManager/EditPage.cpp | 99 + CPP/7zip/UI/FileManager/EditPage.h | 21 + CPP/7zip/UI/FileManager/EditPage.rc | 19 + CPP/7zip/UI/FileManager/EditPage2.rc | 9 + CPP/7zip/UI/FileManager/EditPageRes.h | 10 + CPP/7zip/UI/FileManager/EnumFormatEtc.cpp | 108 + CPP/7zip/UI/FileManager/EnumFormatEtc.h | 10 + CPP/7zip/UI/FileManager/Extract.bmp | Bin 0 -> 982 bytes CPP/7zip/UI/FileManager/Extract2.bmp | Bin 0 -> 406 bytes CPP/7zip/UI/FileManager/ExtractCallback.cpp | 453 ++++ CPP/7zip/UI/FileManager/ExtractCallback.h | 138 + CPP/7zip/UI/FileManager/FM.cpp | 855 +++++++ CPP/7zip/UI/FileManager/FM.dsp | 1576 ++++++++++++ CPP/7zip/UI/FileManager/FM.dsw | 29 + CPP/7zip/UI/FileManager/FM.ico | Bin 0 -> 4846 bytes CPP/7zip/UI/FileManager/FSDrives.cpp | 420 ++++ CPP/7zip/UI/FileManager/FSDrives.h | 53 + CPP/7zip/UI/FileManager/FSFolder.cpp | 665 +++++ CPP/7zip/UI/FileManager/FSFolder.h | 123 + CPP/7zip/UI/FileManager/FSFolderCopy.cpp | 547 ++++ CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp | 166 ++ CPP/7zip/UI/FileManager/FileFolderPluginOpen.h | 9 + CPP/7zip/UI/FileManager/FilePlugins.cpp | 119 + CPP/7zip/UI/FileManager/FilePlugins.h | 54 + CPP/7zip/UI/FileManager/FoldersPage.cpp | 151 ++ CPP/7zip/UI/FileManager/FoldersPage.h | 29 + CPP/7zip/UI/FileManager/FoldersPage.rc | 23 + CPP/7zip/UI/FileManager/FoldersPage2.rc | 16 + CPP/7zip/UI/FileManager/FoldersPageRes.h | 13 + CPP/7zip/UI/FileManager/FormatUtils.cpp | 40 + CPP/7zip/UI/FileManager/FormatUtils.h | 18 + CPP/7zip/UI/FileManager/HelpUtils.cpp | 27 + CPP/7zip/UI/FileManager/HelpUtils.h | 10 + CPP/7zip/UI/FileManager/IFolder.h | 161 ++ CPP/7zip/UI/FileManager/Info.bmp | Bin 0 -> 982 bytes CPP/7zip/UI/FileManager/Info2.bmp | Bin 0 -> 406 bytes CPP/7zip/UI/FileManager/LangPage.cpp | 83 + CPP/7zip/UI/FileManager/LangPage.h | 22 + CPP/7zip/UI/FileManager/LangPage.rc | 37 + CPP/7zip/UI/FileManager/LangPageRes.h | 8 + CPP/7zip/UI/FileManager/LangUtils.cpp | 208 ++ CPP/7zip/UI/FileManager/LangUtils.h | 41 + CPP/7zip/UI/FileManager/ListViewDialog.cpp | 150 ++ CPP/7zip/UI/FileManager/ListViewDialog.h | 30 + CPP/7zip/UI/FileManager/ListViewDialog.rc | 14 + CPP/7zip/UI/FileManager/ListViewDialogRes.h | 2 + CPP/7zip/UI/FileManager/MenuPage.cpp | 203 ++ CPP/7zip/UI/FileManager/MenuPage.h | 25 + CPP/7zip/UI/FileManager/MenuPage.rc | 24 + CPP/7zip/UI/FileManager/MenuPage2.rc | 14 + CPP/7zip/UI/FileManager/MenuPageRes.h | 7 + CPP/7zip/UI/FileManager/MessagesDialog.cpp | 93 + CPP/7zip/UI/FileManager/MessagesDialog.h | 23 + CPP/7zip/UI/FileManager/MessagesDialog.rc | 14 + CPP/7zip/UI/FileManager/MessagesDialogRes.h | 3 + CPP/7zip/UI/FileManager/Move.bmp | Bin 0 -> 982 bytes CPP/7zip/UI/FileManager/Move2.bmp | Bin 0 -> 406 bytes CPP/7zip/UI/FileManager/MyCom2.h | 39 + CPP/7zip/UI/FileManager/MyLoadMenu.cpp | 682 +++++ CPP/7zip/UI/FileManager/MyLoadMenu.h | 16 + CPP/7zip/UI/FileManager/NetFolder.cpp | 272 ++ CPP/7zip/UI/FileManager/NetFolder.h | 40 + CPP/7zip/UI/FileManager/OpenCallback.cpp | 123 + CPP/7zip/UI/FileManager/OpenCallback.h | 92 + CPP/7zip/UI/FileManager/OptionsDialog.cpp | 145 ++ CPP/7zip/UI/FileManager/OverwriteDialog.cpp | 137 + CPP/7zip/UI/FileManager/OverwriteDialog.h | 71 + CPP/7zip/UI/FileManager/OverwriteDialog.rc | 92 + CPP/7zip/UI/FileManager/OverwriteDialogRes.h | 20 + CPP/7zip/UI/FileManager/Panel.cpp | 991 ++++++++ CPP/7zip/UI/FileManager/Panel.h | 629 +++++ CPP/7zip/UI/FileManager/PanelCopy.cpp | 227 ++ CPP/7zip/UI/FileManager/PanelCrc.cpp | 342 +++ CPP/7zip/UI/FileManager/PanelDrag.cpp | 800 ++++++ CPP/7zip/UI/FileManager/PanelFolderChange.cpp | 613 +++++ CPP/7zip/UI/FileManager/PanelItemOpen.cpp | 757 ++++++ CPP/7zip/UI/FileManager/PanelItems.cpp | 806 ++++++ CPP/7zip/UI/FileManager/PanelKey.cpp | 335 +++ CPP/7zip/UI/FileManager/PanelListNotify.cpp | 429 ++++ CPP/7zip/UI/FileManager/PanelMenu.cpp | 679 +++++ CPP/7zip/UI/FileManager/PanelOperations.cpp | 465 ++++ CPP/7zip/UI/FileManager/PanelSelect.cpp | 306 +++ CPP/7zip/UI/FileManager/PanelSort.cpp | 160 ++ CPP/7zip/UI/FileManager/PanelSplitFile.cpp | 494 ++++ CPP/7zip/UI/FileManager/PasswordDialog.cpp | 51 + CPP/7zip/UI/FileManager/PasswordDialog.h | 21 + CPP/7zip/UI/FileManager/PasswordDialog.rc | 14 + CPP/7zip/UI/FileManager/PasswordDialogRes.h | 4 + CPP/7zip/UI/FileManager/PluginInterface.h | 31 + CPP/7zip/UI/FileManager/PluginLoader.h | 28 + CPP/7zip/UI/FileManager/PluginsPage.cpp | 207 ++ CPP/7zip/UI/FileManager/PluginsPage.h | 26 + CPP/7zip/UI/FileManager/PluginsPage.rc | 15 + CPP/7zip/UI/FileManager/PluginsPageRes.h | 4 + CPP/7zip/UI/FileManager/ProgramLocation.cpp | 24 + CPP/7zip/UI/FileManager/ProgramLocation.h | 10 + CPP/7zip/UI/FileManager/ProgressDialog.cpp | 204 ++ CPP/7zip/UI/FileManager/ProgressDialog.h | 170 ++ CPP/7zip/UI/FileManager/ProgressDialog.rc | 12 + CPP/7zip/UI/FileManager/ProgressDialog2.cpp | 1009 ++++++++ CPP/7zip/UI/FileManager/ProgressDialog2.h | 359 +++ CPP/7zip/UI/FileManager/ProgressDialog2.rc | 41 + CPP/7zip/UI/FileManager/ProgressDialog2Res.h | 41 + CPP/7zip/UI/FileManager/ProgressDialog2a.rc | 78 + CPP/7zip/UI/FileManager/ProgressDialogRes.h | 3 + CPP/7zip/UI/FileManager/PropertyName.cpp | 110 + CPP/7zip/UI/FileManager/PropertyName.h | 10 + CPP/7zip/UI/FileManager/PropertyName.rc | 60 + CPP/7zip/UI/FileManager/PropertyNameRes.h | 53 + CPP/7zip/UI/FileManager/RegistryAssociations.cpp | 312 +++ CPP/7zip/UI/FileManager/RegistryAssociations.h | 46 + CPP/7zip/UI/FileManager/RegistryPlugins.cpp | 141 ++ CPP/7zip/UI/FileManager/RegistryPlugins.h | 32 + CPP/7zip/UI/FileManager/RegistryUtils.cpp | 160 ++ CPP/7zip/UI/FileManager/RegistryUtils.h | 53 + CPP/7zip/UI/FileManager/RootFolder.cpp | 272 ++ CPP/7zip/UI/FileManager/RootFolder.h | 33 + CPP/7zip/UI/FileManager/SettingsPage.cpp | 117 + CPP/7zip/UI/FileManager/SettingsPage.h | 19 + CPP/7zip/UI/FileManager/SettingsPage.rc | 22 + CPP/7zip/UI/FileManager/SettingsPage2.rc | 24 + CPP/7zip/UI/FileManager/SettingsPageRes.h | 13 + CPP/7zip/UI/FileManager/SplitDialog.cpp | 116 + CPP/7zip/UI/FileManager/SplitDialog.h | 28 + CPP/7zip/UI/FileManager/SplitDialog.rc | 16 + CPP/7zip/UI/FileManager/SplitDialogRes.h | 7 + CPP/7zip/UI/FileManager/SplitUtils.cpp | 86 + CPP/7zip/UI/FileManager/SplitUtils.h | 15 + CPP/7zip/UI/FileManager/StdAfx.cpp | 3 + CPP/7zip/UI/FileManager/StdAfx.h | 23 + CPP/7zip/UI/FileManager/StringUtils.cpp | 68 + CPP/7zip/UI/FileManager/StringUtils.h | 13 + CPP/7zip/UI/FileManager/SysIconUtils.cpp | 159 ++ CPP/7zip/UI/FileManager/SysIconUtils.h | 57 + CPP/7zip/UI/FileManager/SystemPage.cpp | 402 +++ CPP/7zip/UI/FileManager/SystemPage.h | 41 + CPP/7zip/UI/FileManager/SystemPage.rc | 43 + CPP/7zip/UI/FileManager/SystemPageRes.h | 8 + CPP/7zip/UI/FileManager/Test.bmp | Bin 0 -> 982 bytes CPP/7zip/UI/FileManager/Test2.bmp | Bin 0 -> 406 bytes CPP/7zip/UI/FileManager/TextPairs.cpp | 189 ++ CPP/7zip/UI/FileManager/TextPairs.h | 31 + CPP/7zip/UI/FileManager/UpdateCallback100.cpp | 90 + CPP/7zip/UI/FileManager/UpdateCallback100.h | 54 + CPP/7zip/UI/FileManager/ViewSettings.cpp | 390 +++ CPP/7zip/UI/FileManager/ViewSettings.h | 98 + CPP/7zip/UI/FileManager/makefile | 223 ++ CPP/7zip/UI/FileManager/resource.h | 163 ++ CPP/7zip/UI/FileManager/resource.rc | 248 ++ CPP/7zip/UI/FileManager/resourceGui.h | 10 + CPP/7zip/UI/FileManager/resourceGui.rc | 13 + CPP/7zip/UI/GUI/7zG.exe.manifest | 1 + CPP/7zip/UI/GUI/BenchmarkDialog.cpp | 581 +++++ CPP/7zip/UI/GUI/BenchmarkDialog.h | 135 + CPP/7zip/UI/GUI/BenchmarkDialog.rc | 227 ++ CPP/7zip/UI/GUI/BenchmarkDialogRes.h | 55 + CPP/7zip/UI/GUI/CompressDialog.cpp | 1496 +++++++++++ CPP/7zip/UI/GUI/CompressDialog.h | 189 ++ CPP/7zip/UI/GUI/CompressDialog.rc | 187 ++ CPP/7zip/UI/GUI/CompressDialogRes.h | 81 + CPP/7zip/UI/GUI/Extract.rc | 33 + CPP/7zip/UI/GUI/ExtractDialog.cpp | 355 +++ CPP/7zip/UI/GUI/ExtractDialog.h | 83 + CPP/7zip/UI/GUI/ExtractDialog.rc | 83 + CPP/7zip/UI/GUI/ExtractDialogRes.h | 19 + CPP/7zip/UI/GUI/ExtractGUI.cpp | 205 ++ CPP/7zip/UI/GUI/ExtractGUI.h | 34 + CPP/7zip/UI/GUI/ExtractRes.h | 29 + CPP/7zip/UI/GUI/FM.ico | Bin 0 -> 4846 bytes CPP/7zip/UI/GUI/GUI.cpp | 283 +++ CPP/7zip/UI/GUI/GUI.dsp | 1018 ++++++++ CPP/7zip/UI/GUI/GUI.dsw | 29 + CPP/7zip/UI/GUI/StdAfx.cpp | 3 + CPP/7zip/UI/GUI/StdAfx.h | 13 + CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp | 228 ++ CPP/7zip/UI/GUI/UpdateCallbackGUI.h | 41 + CPP/7zip/UI/GUI/UpdateGUI.cpp | 399 +++ CPP/7zip/UI/GUI/UpdateGUI.h | 31 + CPP/7zip/UI/GUI/makefile | 165 ++ CPP/7zip/UI/GUI/resource.rc | 21 + CPP/7zip/UI/GUI/resource2.h | 3 + CPP/7zip/UI/GUI/resource2.rc | 11 + CPP/7zip/UI/makefile | 12 + CPP/7zip/makefile | 10 + CPP/Build.mak | 94 + CPP/Common/AutoPtr.h | 35 + CPP/Common/Buffer.h | 77 + CPP/Common/CRC.cpp | 7 + CPP/Common/C_FileIO.cpp | 88 + CPP/Common/C_FileIO.h | 47 + CPP/Common/ComTry.h | 17 + CPP/Common/CommandLineParser.cpp | 229 ++ CPP/Common/CommandLineParser.h | 72 + CPP/Common/Defs.h | 20 + CPP/Common/DynamicBuffer.h | 50 + CPP/Common/IntToString.cpp | 77 + CPP/Common/IntToString.h | 19 + CPP/Common/Lang.cpp | 130 + CPP/Common/Lang.h | 28 + CPP/Common/ListFileUtils.cpp | 75 + CPP/Common/ListFileUtils.h | 11 + CPP/Common/MyCom.h | 225 ++ CPP/Common/MyException.h | 14 + CPP/Common/MyGuidDef.h | 54 + CPP/Common/MyInitGuid.h | 22 + CPP/Common/MyMap.cpp | 140 ++ CPP/Common/MyMap.h | 28 + CPP/Common/MyString.cpp | 200 ++ CPP/Common/MyString.h | 625 +++++ CPP/Common/MyUnknown.h | 13 + CPP/Common/MyVector.cpp | 87 + CPP/Common/MyVector.h | 266 ++ CPP/Common/MyWindows.cpp | 109 + CPP/Common/MyWindows.h | 204 ++ CPP/Common/MyXml.cpp | 209 ++ CPP/Common/MyXml.h | 40 + CPP/Common/NewHandler.cpp | 116 + CPP/Common/NewHandler.h | 16 + CPP/Common/Random.cpp | 26 + CPP/Common/Random.h | 16 + CPP/Common/StdAfx.h | 9 + CPP/Common/StdInStream.cpp | 107 + CPP/Common/StdInStream.h | 32 + CPP/Common/StdOutStream.cpp | 104 + CPP/Common/StdOutStream.h | 35 + CPP/Common/StringConvert.cpp | 97 + CPP/Common/StringConvert.h | 73 + CPP/Common/StringToInt.cpp | 90 + CPP/Common/StringToInt.h | 18 + CPP/Common/TextConfig.cpp | 138 + CPP/Common/TextConfig.h | 22 + CPP/Common/Types.h | 11 + CPP/Common/UTFConvert.cpp | 145 ++ CPP/Common/UTFConvert.h | 11 + CPP/Common/Wildcard.cpp | 462 ++++ CPP/Common/Wildcard.h | 80 + CPP/Windows/COM.cpp | 37 + CPP/Windows/COM.h | 69 + CPP/Windows/Clipboard.cpp | 135 + CPP/Windows/Clipboard.h | 28 + CPP/Windows/CommonDialog.cpp | 184 ++ CPP/Windows/CommonDialog.h | 19 + CPP/Windows/Console.cpp | 10 + CPP/Windows/Console.h | 52 + CPP/Windows/Control/ComboBox.cpp | 58 + CPP/Windows/Control/ComboBox.h | 61 + CPP/Windows/Control/CommandBar.h | 48 + CPP/Windows/Control/Dialog.cpp | 201 ++ CPP/Windows/Control/Dialog.h | 205 ++ CPP/Windows/Control/Edit.h | 19 + CPP/Windows/Control/ImageList.cpp | 11 + CPP/Windows/Control/ImageList.h | 85 + CPP/Windows/Control/ListView.cpp | 96 + CPP/Windows/Control/ListView.h | 109 + CPP/Windows/Control/ProgressBar.h | 31 + CPP/Windows/Control/PropertyPage.cpp | 162 ++ CPP/Windows/Control/PropertyPage.h | 46 + CPP/Windows/Control/ReBar.h | 35 + CPP/Windows/Control/Static.h | 28 + CPP/Windows/Control/StatusBar.h | 43 + CPP/Windows/Control/StdAfx.h | 9 + CPP/Windows/Control/ToolBar.h | 43 + CPP/Windows/Control/Trackbar.h | 28 + CPP/Windows/Control/Window2.cpp | 209 ++ CPP/Windows/Control/Window2.h | 58 + CPP/Windows/DLL.cpp | 110 + CPP/Windows/DLL.h | 59 + CPP/Windows/Defs.h | 17 + CPP/Windows/Error.cpp | 50 + CPP/Windows/Error.h | 33 + CPP/Windows/FileDir.cpp | 909 +++++++ CPP/Windows/FileDir.h | 177 ++ CPP/Windows/FileFind.cpp | 462 ++++ CPP/Windows/FileFind.h | 161 ++ CPP/Windows/FileIO.cpp | 434 ++++ CPP/Windows/FileIO.h | 136 + CPP/Windows/FileMapping.cpp | 12 + CPP/Windows/FileMapping.h | 62 + CPP/Windows/FileName.cpp | 50 + CPP/Windows/FileName.h | 27 + CPP/Windows/FileSystem.cpp | 126 + CPP/Windows/FileSystem.h | 51 + CPP/Windows/Handle.h | 37 + CPP/Windows/Memory.cpp | 36 + CPP/Windows/Memory.h | 53 + CPP/Windows/MemoryLock.cpp | 82 + CPP/Windows/MemoryLock.h | 15 + CPP/Windows/Menu.cpp | 191 ++ CPP/Windows/Menu.h | 153 ++ CPP/Windows/NationalTime.cpp | 37 + CPP/Windows/NationalTime.h | 20 + CPP/Windows/Net.cpp | 380 +++ CPP/Windows/Net.h | 87 + CPP/Windows/NtCheck.h | 44 + CPP/Windows/Process.cpp | 81 + CPP/Windows/Process.h | 100 + CPP/Windows/ProcessMessages.cpp | 22 + CPP/Windows/ProcessMessages.h | 14 + CPP/Windows/PropVariant.cpp | 243 ++ CPP/Windows/PropVariant.h | 56 + CPP/Windows/PropVariantConversions.cpp | 105 + CPP/Windows/PropVariantConversions.h | 14 + CPP/Windows/PropVariantUtils.cpp | 78 + CPP/Windows/PropVariantUtils.h | 28 + CPP/Windows/Registry.cpp | 369 +++ CPP/Windows/Registry.h | 85 + CPP/Windows/ResourceString.cpp | 64 + CPP/Windows/ResourceString.h | 22 + CPP/Windows/Security.cpp | 179 ++ CPP/Windows/Security.h | 167 ++ CPP/Windows/Shell.cpp | 335 +++ CPP/Windows/Shell.h | 93 + CPP/Windows/StdAfx.h | 9 + CPP/Windows/Synchronization.cpp | 10 + CPP/Windows/Synchronization.h | 164 ++ CPP/Windows/System.cpp | 72 + CPP/Windows/System.h | 16 + CPP/Windows/Thread.h | 38 + CPP/Windows/Time.cpp | 170 ++ CPP/Windows/Time.h | 21 + CPP/Windows/Window.cpp | 169 ++ CPP/Windows/Window.h | 261 ++ DOC/7zC.txt | 194 ++ DOC/7zFormat.txt | 469 ++++ DOC/7zip.hhp | 70 + DOC/7zip.inf | 55 + DOC/7zip.nsi | 535 ++++ DOC/7zip.wxs | 353 +++ DOC/License.txt | 52 + DOC/Methods.txt | 152 ++ DOC/copying.txt | 504 ++++ DOC/history.txt | 456 ++++ DOC/lzma.txt | 598 +++++ DOC/readme.txt | 181 ++ DOC/unRarLicense.txt | 41 + 1105 files changed, 185855 insertions(+) create mode 100755 Asm/arm/7zCrcOpt.asm create mode 100755 Asm/x86/7zAsm.asm create mode 100755 Asm/x86/7zCrcOpt.asm create mode 100755 Asm/x86/AesOpt.asm create mode 100755 C/7z.h create mode 100755 C/7zAlloc.c create mode 100755 C/7zAlloc.h create mode 100755 C/7zBuf.c create mode 100755 C/7zBuf.h create mode 100755 C/7zBuf2.c create mode 100755 C/7zCrc.c create mode 100755 C/7zCrc.h create mode 100755 C/7zCrcOpt.c create mode 100755 C/7zDec.c create mode 100755 C/7zFile.c create mode 100755 C/7zFile.h create mode 100755 C/7zIn.c create mode 100755 C/7zStream.c create mode 100755 C/7zVersion.h create mode 100755 C/Aes.c create mode 100755 C/Aes.h create mode 100755 C/AesOpt.c create mode 100755 C/Alloc.c create mode 100755 C/Alloc.h create mode 100755 C/Bcj2.c create mode 100755 C/Bcj2.h create mode 100755 C/Bra.c create mode 100755 C/Bra.h create mode 100755 C/Bra86.c create mode 100755 C/BraIA64.c create mode 100755 C/BwtSort.c create mode 100755 C/BwtSort.h create mode 100755 C/CpuArch.c create mode 100755 C/CpuArch.h create mode 100755 C/Delta.c create mode 100755 C/Delta.h create mode 100755 C/HuffEnc.c create mode 100755 C/HuffEnc.h create mode 100755 C/LzFind.c create mode 100755 C/LzFind.h create mode 100755 C/LzFindMt.c create mode 100755 C/LzFindMt.h create mode 100755 C/LzHash.h create mode 100755 C/Lzma2Dec.c create mode 100755 C/Lzma2Dec.h create mode 100755 C/Lzma2Enc.c create mode 100755 C/Lzma2Enc.h create mode 100755 C/Lzma86.h create mode 100755 C/Lzma86Dec.c create mode 100755 C/Lzma86Enc.c create mode 100755 C/LzmaDec.c create mode 100755 C/LzmaDec.h create mode 100755 C/LzmaEnc.c create mode 100755 C/LzmaEnc.h create mode 100755 C/LzmaLib.c create mode 100755 C/LzmaLib.h create mode 100755 C/MtCoder.c create mode 100755 C/MtCoder.h create mode 100755 C/Ppmd.h create mode 100755 C/Ppmd7.c create mode 100755 C/Ppmd7.h create mode 100755 C/Ppmd7Dec.c create mode 100755 C/Ppmd7Enc.c create mode 100755 C/Ppmd8.c create mode 100755 C/Ppmd8.h create mode 100755 C/Ppmd8Dec.c create mode 100755 C/Ppmd8Enc.c create mode 100755 C/RotateDefs.h create mode 100755 C/Sha256.c create mode 100755 C/Sha256.h create mode 100755 C/Sort.c create mode 100755 C/Sort.h create mode 100755 C/Threads.c create mode 100755 C/Threads.h create mode 100755 C/Types.h create mode 100755 C/Util/7z/7z.dsp create mode 100755 C/Util/7z/7z.dsw create mode 100755 C/Util/7z/7zMain.c create mode 100755 C/Util/7z/makefile create mode 100755 C/Util/7z/makefile.gcc create mode 100755 C/Util/Lzma/LzmaUtil.c create mode 100755 C/Util/Lzma/LzmaUtil.dsp create mode 100755 C/Util/Lzma/LzmaUtil.dsw create mode 100755 C/Util/Lzma/makefile create mode 100755 C/Util/Lzma/makefile.gcc create mode 100755 C/Util/LzmaLib/LzmaLib.def create mode 100755 C/Util/LzmaLib/LzmaLib.dsp create mode 100755 C/Util/LzmaLib/LzmaLib.dsw create mode 100755 C/Util/LzmaLib/LzmaLibExports.c create mode 100755 C/Util/LzmaLib/makefile create mode 100755 C/Util/LzmaLib/resource.rc create mode 100755 C/Util/SfxSetup/SfxSetup.c create mode 100755 C/Util/SfxSetup/SfxSetup.dsp create mode 100755 C/Util/SfxSetup/SfxSetup.dsw create mode 100755 C/Util/SfxSetup/makefile create mode 100755 C/Util/SfxSetup/makefile_con create mode 100755 C/Util/SfxSetup/resource.rc create mode 100755 C/Util/SfxSetup/setup.ico create mode 100755 C/Xz.c create mode 100755 C/Xz.h create mode 100755 C/XzCrc64.c create mode 100755 C/XzCrc64.h create mode 100755 C/XzDec.c create mode 100755 C/XzEnc.c create mode 100755 C/XzEnc.h create mode 100755 C/XzIn.c create mode 100755 CPP/7zip/Aes.mak create mode 100755 CPP/7zip/Archive/7z/7z.dsp create mode 100755 CPP/7zip/Archive/7z/7z.dsw create mode 100755 CPP/7zip/Archive/7z/7zCompressionMode.cpp create mode 100755 CPP/7zip/Archive/7z/7zCompressionMode.h create mode 100755 CPP/7zip/Archive/7z/7zDecode.cpp create mode 100755 CPP/7zip/Archive/7z/7zDecode.h create mode 100755 CPP/7zip/Archive/7z/7zEncode.cpp create mode 100755 CPP/7zip/Archive/7z/7zEncode.h create mode 100755 CPP/7zip/Archive/7z/7zExtract.cpp create mode 100755 CPP/7zip/Archive/7z/7zFolderInStream.cpp create mode 100755 CPP/7zip/Archive/7z/7zFolderInStream.h create mode 100755 CPP/7zip/Archive/7z/7zFolderOutStream.cpp create mode 100755 CPP/7zip/Archive/7z/7zFolderOutStream.h create mode 100755 CPP/7zip/Archive/7z/7zHandler.cpp create mode 100755 CPP/7zip/Archive/7z/7zHandler.h create mode 100755 CPP/7zip/Archive/7z/7zHandlerOut.cpp create mode 100755 CPP/7zip/Archive/7z/7zHeader.cpp create mode 100755 CPP/7zip/Archive/7z/7zHeader.h create mode 100755 CPP/7zip/Archive/7z/7zIn.cpp create mode 100755 CPP/7zip/Archive/7z/7zIn.h create mode 100755 CPP/7zip/Archive/7z/7zItem.h create mode 100755 CPP/7zip/Archive/7z/7zOut.cpp create mode 100755 CPP/7zip/Archive/7z/7zOut.h create mode 100755 CPP/7zip/Archive/7z/7zProperties.cpp create mode 100755 CPP/7zip/Archive/7z/7zProperties.h create mode 100755 CPP/7zip/Archive/7z/7zRegister.cpp create mode 100755 CPP/7zip/Archive/7z/7zSpecStream.cpp create mode 100755 CPP/7zip/Archive/7z/7zSpecStream.h create mode 100755 CPP/7zip/Archive/7z/7zUpdate.cpp create mode 100755 CPP/7zip/Archive/7z/7zUpdate.h create mode 100755 CPP/7zip/Archive/7z/StdAfx.cpp create mode 100755 CPP/7zip/Archive/7z/StdAfx.h create mode 100755 CPP/7zip/Archive/7z/makefile create mode 100755 CPP/7zip/Archive/7z/resource.rc create mode 100755 CPP/7zip/Archive/ApmHandler.cpp create mode 100755 CPP/7zip/Archive/Archive.def create mode 100755 CPP/7zip/Archive/Archive2.def create mode 100755 CPP/7zip/Archive/ArchiveExports.cpp create mode 100755 CPP/7zip/Archive/ArjHandler.cpp create mode 100755 CPP/7zip/Archive/Bz2Handler.cpp create mode 100755 CPP/7zip/Archive/Cab/CabBlockInStream.cpp create mode 100755 CPP/7zip/Archive/Cab/CabBlockInStream.h create mode 100755 CPP/7zip/Archive/Cab/CabHandler.cpp create mode 100755 CPP/7zip/Archive/Cab/CabHandler.h create mode 100755 CPP/7zip/Archive/Cab/CabHeader.cpp create mode 100755 CPP/7zip/Archive/Cab/CabHeader.h create mode 100755 CPP/7zip/Archive/Cab/CabIn.cpp create mode 100755 CPP/7zip/Archive/Cab/CabIn.h create mode 100755 CPP/7zip/Archive/Cab/CabItem.h create mode 100755 CPP/7zip/Archive/Cab/CabRegister.cpp create mode 100755 CPP/7zip/Archive/Cab/StdAfx.h create mode 100755 CPP/7zip/Archive/Chm/ChmHandler.cpp create mode 100755 CPP/7zip/Archive/Chm/ChmHandler.h create mode 100755 CPP/7zip/Archive/Chm/ChmHeader.cpp create mode 100755 CPP/7zip/Archive/Chm/ChmHeader.h create mode 100755 CPP/7zip/Archive/Chm/ChmIn.cpp create mode 100755 CPP/7zip/Archive/Chm/ChmIn.h create mode 100755 CPP/7zip/Archive/Chm/ChmRegister.cpp create mode 100755 CPP/7zip/Archive/Chm/StdAfx.h create mode 100755 CPP/7zip/Archive/Com/ComHandler.cpp create mode 100755 CPP/7zip/Archive/Com/ComHandler.h create mode 100755 CPP/7zip/Archive/Com/ComIn.cpp create mode 100755 CPP/7zip/Archive/Com/ComIn.h create mode 100755 CPP/7zip/Archive/Com/ComRegister.cpp create mode 100755 CPP/7zip/Archive/Common/CoderMixer.cpp create mode 100755 CPP/7zip/Archive/Common/CoderMixer.h create mode 100755 CPP/7zip/Archive/Common/CoderMixer2.cpp create mode 100755 CPP/7zip/Archive/Common/CoderMixer2.h create mode 100755 CPP/7zip/Archive/Common/CoderMixer2MT.cpp create mode 100755 CPP/7zip/Archive/Common/CoderMixer2MT.h create mode 100755 CPP/7zip/Archive/Common/CoderMixer2ST.cpp create mode 100755 CPP/7zip/Archive/Common/CoderMixer2ST.h create mode 100755 CPP/7zip/Archive/Common/CoderMixerMT.cpp create mode 100755 CPP/7zip/Archive/Common/CoderMixerMT.h create mode 100755 CPP/7zip/Archive/Common/CrossThreadProgress.cpp create mode 100755 CPP/7zip/Archive/Common/CrossThreadProgress.h create mode 100755 CPP/7zip/Archive/Common/DummyOutStream.cpp create mode 100755 CPP/7zip/Archive/Common/DummyOutStream.h create mode 100755 CPP/7zip/Archive/Common/FindSignature.cpp create mode 100755 CPP/7zip/Archive/Common/FindSignature.h create mode 100755 CPP/7zip/Archive/Common/HandlerOut.cpp create mode 100755 CPP/7zip/Archive/Common/HandlerOut.h create mode 100755 CPP/7zip/Archive/Common/InStreamWithCRC.cpp create mode 100755 CPP/7zip/Archive/Common/InStreamWithCRC.h create mode 100755 CPP/7zip/Archive/Common/ItemNameUtils.cpp create mode 100755 CPP/7zip/Archive/Common/ItemNameUtils.h create mode 100755 CPP/7zip/Archive/Common/MultiStream.cpp create mode 100755 CPP/7zip/Archive/Common/MultiStream.h create mode 100755 CPP/7zip/Archive/Common/OutStreamWithCRC.cpp create mode 100755 CPP/7zip/Archive/Common/OutStreamWithCRC.h create mode 100755 CPP/7zip/Archive/Common/OutStreamWithSha1.cpp create mode 100755 CPP/7zip/Archive/Common/OutStreamWithSha1.h create mode 100755 CPP/7zip/Archive/Common/ParseProperties.cpp create mode 100755 CPP/7zip/Archive/Common/ParseProperties.h create mode 100755 CPP/7zip/Archive/Common/StdAfx.h create mode 100755 CPP/7zip/Archive/CpioHandler.cpp create mode 100755 CPP/7zip/Archive/CramfsHandler.cpp create mode 100755 CPP/7zip/Archive/DebHandler.cpp create mode 100755 CPP/7zip/Archive/DeflateProps.cpp create mode 100755 CPP/7zip/Archive/DeflateProps.h create mode 100755 CPP/7zip/Archive/DllExports.cpp create mode 100755 CPP/7zip/Archive/DllExports2.cpp create mode 100755 CPP/7zip/Archive/DmgHandler.cpp create mode 100755 CPP/7zip/Archive/ElfHandler.cpp create mode 100755 CPP/7zip/Archive/FatHandler.cpp create mode 100755 CPP/7zip/Archive/FlvHandler.cpp create mode 100755 CPP/7zip/Archive/GzHandler.cpp create mode 100755 CPP/7zip/Archive/Hfs/HfsHandler.cpp create mode 100755 CPP/7zip/Archive/Hfs/HfsHandler.h create mode 100755 CPP/7zip/Archive/Hfs/HfsIn.cpp create mode 100755 CPP/7zip/Archive/Hfs/HfsIn.h create mode 100755 CPP/7zip/Archive/Hfs/HfsRegister.cpp create mode 100755 CPP/7zip/Archive/IArchive.h create mode 100755 CPP/7zip/Archive/Icons/7z.ico create mode 100755 CPP/7zip/Archive/Icons/arj.ico create mode 100755 CPP/7zip/Archive/Icons/bz2.ico create mode 100755 CPP/7zip/Archive/Icons/cab.ico create mode 100755 CPP/7zip/Archive/Icons/cpio.ico create mode 100755 CPP/7zip/Archive/Icons/deb.ico create mode 100755 CPP/7zip/Archive/Icons/dmg.ico create mode 100755 CPP/7zip/Archive/Icons/fat.ico create mode 100755 CPP/7zip/Archive/Icons/gz.ico create mode 100755 CPP/7zip/Archive/Icons/hfs.ico create mode 100755 CPP/7zip/Archive/Icons/iso.ico create mode 100755 CPP/7zip/Archive/Icons/lzh.ico create mode 100755 CPP/7zip/Archive/Icons/lzma.ico create mode 100755 CPP/7zip/Archive/Icons/ntfs.ico create mode 100755 CPP/7zip/Archive/Icons/rar.ico create mode 100755 CPP/7zip/Archive/Icons/rpm.ico create mode 100755 CPP/7zip/Archive/Icons/split.ico create mode 100755 CPP/7zip/Archive/Icons/squashfs.ico create mode 100755 CPP/7zip/Archive/Icons/tar.ico create mode 100755 CPP/7zip/Archive/Icons/vhd.ico create mode 100755 CPP/7zip/Archive/Icons/wim.ico create mode 100755 CPP/7zip/Archive/Icons/xar.ico create mode 100755 CPP/7zip/Archive/Icons/xz.ico create mode 100755 CPP/7zip/Archive/Icons/z.ico create mode 100755 CPP/7zip/Archive/Icons/zip.ico create mode 100755 CPP/7zip/Archive/Iso/IsoHandler.cpp create mode 100755 CPP/7zip/Archive/Iso/IsoHandler.h create mode 100755 CPP/7zip/Archive/Iso/IsoHeader.cpp create mode 100755 CPP/7zip/Archive/Iso/IsoHeader.h create mode 100755 CPP/7zip/Archive/Iso/IsoIn.cpp create mode 100755 CPP/7zip/Archive/Iso/IsoIn.h create mode 100755 CPP/7zip/Archive/Iso/IsoItem.h create mode 100755 CPP/7zip/Archive/Iso/IsoRegister.cpp create mode 100755 CPP/7zip/Archive/Iso/StdAfx.h create mode 100755 CPP/7zip/Archive/LzhHandler.cpp create mode 100755 CPP/7zip/Archive/LzmaHandler.cpp create mode 100755 CPP/7zip/Archive/MachoHandler.cpp create mode 100755 CPP/7zip/Archive/MbrHandler.cpp create mode 100755 CPP/7zip/Archive/MslzHandler.cpp create mode 100755 CPP/7zip/Archive/MubHandler.cpp create mode 100755 CPP/7zip/Archive/Nsis/NsisDecode.cpp create mode 100755 CPP/7zip/Archive/Nsis/NsisDecode.h create mode 100755 CPP/7zip/Archive/Nsis/NsisHandler.cpp create mode 100755 CPP/7zip/Archive/Nsis/NsisHandler.h create mode 100755 CPP/7zip/Archive/Nsis/NsisIn.cpp create mode 100755 CPP/7zip/Archive/Nsis/NsisIn.h create mode 100755 CPP/7zip/Archive/Nsis/NsisRegister.cpp create mode 100755 CPP/7zip/Archive/Nsis/StdAfx.h create mode 100755 CPP/7zip/Archive/NtfsHandler.cpp create mode 100755 CPP/7zip/Archive/PeHandler.cpp create mode 100755 CPP/7zip/Archive/PpmdHandler.cpp create mode 100755 CPP/7zip/Archive/Rar/RarHandler.cpp create mode 100755 CPP/7zip/Archive/Rar/RarHandler.h create mode 100755 CPP/7zip/Archive/Rar/RarHeader.cpp create mode 100755 CPP/7zip/Archive/Rar/RarHeader.h create mode 100755 CPP/7zip/Archive/Rar/RarIn.cpp create mode 100755 CPP/7zip/Archive/Rar/RarIn.h create mode 100755 CPP/7zip/Archive/Rar/RarItem.cpp create mode 100755 CPP/7zip/Archive/Rar/RarItem.h create mode 100755 CPP/7zip/Archive/Rar/RarRegister.cpp create mode 100755 CPP/7zip/Archive/Rar/RarVolumeInStream.cpp create mode 100755 CPP/7zip/Archive/Rar/RarVolumeInStream.h create mode 100755 CPP/7zip/Archive/Rar/StdAfx.cpp create mode 100755 CPP/7zip/Archive/Rar/StdAfx.h create mode 100755 CPP/7zip/Archive/RpmHandler.cpp create mode 100755 CPP/7zip/Archive/SplitHandler.cpp create mode 100755 CPP/7zip/Archive/SquashfsHandler.cpp create mode 100755 CPP/7zip/Archive/StdAfx.h create mode 100755 CPP/7zip/Archive/SwfHandler.cpp create mode 100755 CPP/7zip/Archive/Tar/StdAfx.h create mode 100755 CPP/7zip/Archive/Tar/TarHandler.cpp create mode 100755 CPP/7zip/Archive/Tar/TarHandler.h create mode 100755 CPP/7zip/Archive/Tar/TarHandlerOut.cpp create mode 100755 CPP/7zip/Archive/Tar/TarHeader.cpp create mode 100755 CPP/7zip/Archive/Tar/TarHeader.h create mode 100755 CPP/7zip/Archive/Tar/TarIn.cpp create mode 100755 CPP/7zip/Archive/Tar/TarIn.h create mode 100755 CPP/7zip/Archive/Tar/TarItem.h create mode 100755 CPP/7zip/Archive/Tar/TarOut.cpp create mode 100755 CPP/7zip/Archive/Tar/TarOut.h create mode 100755 CPP/7zip/Archive/Tar/TarRegister.cpp create mode 100755 CPP/7zip/Archive/Tar/TarUpdate.cpp create mode 100755 CPP/7zip/Archive/Tar/TarUpdate.h create mode 100755 CPP/7zip/Archive/Udf/StdAfx.h create mode 100755 CPP/7zip/Archive/Udf/UdfHandler.cpp create mode 100755 CPP/7zip/Archive/Udf/UdfHandler.h create mode 100755 CPP/7zip/Archive/Udf/UdfIn.cpp create mode 100755 CPP/7zip/Archive/Udf/UdfIn.h create mode 100755 CPP/7zip/Archive/Udf/UdfRegister.cpp create mode 100755 CPP/7zip/Archive/VhdHandler.cpp create mode 100755 CPP/7zip/Archive/Wim/StdAfx.h create mode 100755 CPP/7zip/Archive/Wim/WimHandler.cpp create mode 100755 CPP/7zip/Archive/Wim/WimHandler.h create mode 100755 CPP/7zip/Archive/Wim/WimHandlerOut.cpp create mode 100755 CPP/7zip/Archive/Wim/WimIn.cpp create mode 100755 CPP/7zip/Archive/Wim/WimIn.h create mode 100755 CPP/7zip/Archive/Wim/WimRegister.cpp create mode 100755 CPP/7zip/Archive/XarHandler.cpp create mode 100755 CPP/7zip/Archive/XzHandler.cpp create mode 100755 CPP/7zip/Archive/ZHandler.cpp create mode 100755 CPP/7zip/Archive/Zip/StdAfx.h create mode 100755 CPP/7zip/Archive/Zip/ZipAddCommon.cpp create mode 100755 CPP/7zip/Archive/Zip/ZipAddCommon.h create mode 100755 CPP/7zip/Archive/Zip/ZipCompressionMode.h create mode 100755 CPP/7zip/Archive/Zip/ZipHandler.cpp create mode 100755 CPP/7zip/Archive/Zip/ZipHandler.h create mode 100755 CPP/7zip/Archive/Zip/ZipHandlerOut.cpp create mode 100755 CPP/7zip/Archive/Zip/ZipHeader.cpp create mode 100755 CPP/7zip/Archive/Zip/ZipHeader.h create mode 100755 CPP/7zip/Archive/Zip/ZipIn.cpp create mode 100755 CPP/7zip/Archive/Zip/ZipIn.h create mode 100755 CPP/7zip/Archive/Zip/ZipItem.cpp create mode 100755 CPP/7zip/Archive/Zip/ZipItem.h create mode 100755 CPP/7zip/Archive/Zip/ZipItemEx.h create mode 100755 CPP/7zip/Archive/Zip/ZipOut.cpp create mode 100755 CPP/7zip/Archive/Zip/ZipOut.h create mode 100755 CPP/7zip/Archive/Zip/ZipRegister.cpp create mode 100755 CPP/7zip/Archive/Zip/ZipUpdate.cpp create mode 100755 CPP/7zip/Archive/Zip/ZipUpdate.h create mode 100755 CPP/7zip/Archive/makefile create mode 100755 CPP/7zip/Asm.mak create mode 100755 CPP/7zip/Bundles/Alone/Alone.dsp create mode 100755 CPP/7zip/Bundles/Alone/Alone.dsw create mode 100755 CPP/7zip/Bundles/Alone/StdAfx.cpp create mode 100755 CPP/7zip/Bundles/Alone/StdAfx.h create mode 100755 CPP/7zip/Bundles/Alone/afxres.h create mode 100755 CPP/7zip/Bundles/Alone/makefile create mode 100755 CPP/7zip/Bundles/Alone/resource.rc create mode 100755 CPP/7zip/Bundles/Alone7z/StdAfx.cpp create mode 100755 CPP/7zip/Bundles/Alone7z/StdAfx.h create mode 100755 CPP/7zip/Bundles/Alone7z/makefile create mode 100755 CPP/7zip/Bundles/Alone7z/resource.rc create mode 100755 CPP/7zip/Bundles/Fm/FM.dsp create mode 100755 CPP/7zip/Bundles/Fm/FM.dsw create mode 100755 CPP/7zip/Bundles/Fm/StdAfx.cpp create mode 100755 CPP/7zip/Bundles/Fm/StdAfx.h create mode 100755 CPP/7zip/Bundles/Fm/makefile create mode 100755 CPP/7zip/Bundles/Fm/resource.rc create mode 100755 CPP/7zip/Bundles/Format7z/StdAfx.cpp create mode 100755 CPP/7zip/Bundles/Format7z/StdAfx.h create mode 100755 CPP/7zip/Bundles/Format7z/makefile create mode 100755 CPP/7zip/Bundles/Format7z/resource.rc create mode 100755 CPP/7zip/Bundles/Format7zExtract/StdAfx.cpp create mode 100755 CPP/7zip/Bundles/Format7zExtract/StdAfx.h create mode 100755 CPP/7zip/Bundles/Format7zExtract/makefile create mode 100755 CPP/7zip/Bundles/Format7zExtract/resource.rc create mode 100755 CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp create mode 100755 CPP/7zip/Bundles/Format7zExtractR/StdAfx.h create mode 100755 CPP/7zip/Bundles/Format7zExtractR/makefile create mode 100755 CPP/7zip/Bundles/Format7zExtractR/resource.rc create mode 100755 CPP/7zip/Bundles/Format7zF/Format7z.dsp create mode 100755 CPP/7zip/Bundles/Format7zF/Format7z.dsw create mode 100755 CPP/7zip/Bundles/Format7zF/StdAfx.cpp create mode 100755 CPP/7zip/Bundles/Format7zF/StdAfx.h create mode 100755 CPP/7zip/Bundles/Format7zF/makefile create mode 100755 CPP/7zip/Bundles/Format7zF/resource.rc create mode 100755 CPP/7zip/Bundles/Format7zR/StdAfx.cpp create mode 100755 CPP/7zip/Bundles/Format7zR/StdAfx.h create mode 100755 CPP/7zip/Bundles/Format7zR/makefile create mode 100755 CPP/7zip/Bundles/Format7zR/resource.rc create mode 100755 CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp create mode 100755 CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp create mode 100755 CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw create mode 100755 CPP/7zip/Bundles/LzmaCon/StdAfx.cpp create mode 100755 CPP/7zip/Bundles/LzmaCon/StdAfx.h create mode 100755 CPP/7zip/Bundles/LzmaCon/makefile create mode 100755 CPP/7zip/Bundles/LzmaCon/makefile.gcc create mode 100755 CPP/7zip/Bundles/SFXCon/7z.ico create mode 100755 CPP/7zip/Bundles/SFXCon/Main.cpp create mode 100755 CPP/7zip/Bundles/SFXCon/SFXCon.dsp create mode 100755 CPP/7zip/Bundles/SFXCon/SFXCon.dsw create mode 100755 CPP/7zip/Bundles/SFXCon/StdAfx.cpp create mode 100755 CPP/7zip/Bundles/SFXCon/StdAfx.h create mode 100755 CPP/7zip/Bundles/SFXCon/makefile create mode 100755 CPP/7zip/Bundles/SFXCon/resource.rc create mode 100755 CPP/7zip/Bundles/SFXSetup/ExtractCallback.cpp create mode 100755 CPP/7zip/Bundles/SFXSetup/ExtractCallback.h create mode 100755 CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp create mode 100755 CPP/7zip/Bundles/SFXSetup/ExtractEngine.h create mode 100755 CPP/7zip/Bundles/SFXSetup/Main.cpp create mode 100755 CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp create mode 100755 CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw create mode 100755 CPP/7zip/Bundles/SFXSetup/StdAfx.cpp create mode 100755 CPP/7zip/Bundles/SFXSetup/StdAfx.h create mode 100755 CPP/7zip/Bundles/SFXSetup/makefile create mode 100755 CPP/7zip/Bundles/SFXSetup/resource.h create mode 100755 CPP/7zip/Bundles/SFXSetup/resource.rc create mode 100755 CPP/7zip/Bundles/SFXSetup/setup.ico create mode 100755 CPP/7zip/Bundles/SFXWin/7z.ico create mode 100755 CPP/7zip/Bundles/SFXWin/Main.cpp create mode 100755 CPP/7zip/Bundles/SFXWin/SFXWin.dsp create mode 100755 CPP/7zip/Bundles/SFXWin/SFXWin.dsw create mode 100755 CPP/7zip/Bundles/SFXWin/StdAfx.cpp create mode 100755 CPP/7zip/Bundles/SFXWin/StdAfx.h create mode 100755 CPP/7zip/Bundles/SFXWin/makefile create mode 100755 CPP/7zip/Bundles/SFXWin/resource.h create mode 100755 CPP/7zip/Bundles/SFXWin/resource.rc create mode 100755 CPP/7zip/Bundles/makefile create mode 100755 CPP/7zip/Common/CWrappers.cpp create mode 100755 CPP/7zip/Common/CWrappers.h create mode 100755 CPP/7zip/Common/CreateCoder.cpp create mode 100755 CPP/7zip/Common/CreateCoder.h create mode 100755 CPP/7zip/Common/FilePathAutoRename.cpp create mode 100755 CPP/7zip/Common/FilePathAutoRename.h create mode 100755 CPP/7zip/Common/FileStreams.cpp create mode 100755 CPP/7zip/Common/FileStreams.h create mode 100755 CPP/7zip/Common/FilterCoder.cpp create mode 100755 CPP/7zip/Common/FilterCoder.h create mode 100755 CPP/7zip/Common/InBuffer.cpp create mode 100755 CPP/7zip/Common/InBuffer.h create mode 100755 CPP/7zip/Common/InMemStream.cpp create mode 100755 CPP/7zip/Common/InMemStream.h create mode 100755 CPP/7zip/Common/InOutTempBuffer.cpp create mode 100755 CPP/7zip/Common/InOutTempBuffer.h create mode 100755 CPP/7zip/Common/LimitedStreams.cpp create mode 100755 CPP/7zip/Common/LimitedStreams.h create mode 100755 CPP/7zip/Common/LockedStream.cpp create mode 100755 CPP/7zip/Common/LockedStream.h create mode 100755 CPP/7zip/Common/MemBlocks.cpp create mode 100755 CPP/7zip/Common/MemBlocks.h create mode 100755 CPP/7zip/Common/MethodId.cpp create mode 100755 CPP/7zip/Common/MethodId.h create mode 100755 CPP/7zip/Common/MethodProps.cpp create mode 100755 CPP/7zip/Common/MethodProps.h create mode 100755 CPP/7zip/Common/OffsetStream.cpp create mode 100755 CPP/7zip/Common/OffsetStream.h create mode 100755 CPP/7zip/Common/OutBuffer.cpp create mode 100755 CPP/7zip/Common/OutBuffer.h create mode 100755 CPP/7zip/Common/OutMemStream.cpp create mode 100755 CPP/7zip/Common/OutMemStream.h create mode 100755 CPP/7zip/Common/ProgressMt.cpp create mode 100755 CPP/7zip/Common/ProgressMt.h create mode 100755 CPP/7zip/Common/ProgressUtils.cpp create mode 100755 CPP/7zip/Common/ProgressUtils.h create mode 100755 CPP/7zip/Common/RegisterArc.h create mode 100755 CPP/7zip/Common/RegisterCodec.h create mode 100755 CPP/7zip/Common/StdAfx.h create mode 100755 CPP/7zip/Common/StreamBinder.cpp create mode 100755 CPP/7zip/Common/StreamBinder.h create mode 100755 CPP/7zip/Common/StreamObjects.cpp create mode 100755 CPP/7zip/Common/StreamObjects.h create mode 100755 CPP/7zip/Common/StreamUtils.cpp create mode 100755 CPP/7zip/Common/StreamUtils.h create mode 100755 CPP/7zip/Common/VirtThread.cpp create mode 100755 CPP/7zip/Common/VirtThread.h create mode 100755 CPP/7zip/Compress/ArjDecoder1.cpp create mode 100755 CPP/7zip/Compress/ArjDecoder1.h create mode 100755 CPP/7zip/Compress/ArjDecoder2.cpp create mode 100755 CPP/7zip/Compress/ArjDecoder2.h create mode 100755 CPP/7zip/Compress/BZip2Const.h create mode 100755 CPP/7zip/Compress/BZip2Crc.cpp create mode 100755 CPP/7zip/Compress/BZip2Crc.h create mode 100755 CPP/7zip/Compress/BZip2Decoder.cpp create mode 100755 CPP/7zip/Compress/BZip2Decoder.h create mode 100755 CPP/7zip/Compress/BZip2Encoder.cpp create mode 100755 CPP/7zip/Compress/BZip2Encoder.h create mode 100755 CPP/7zip/Compress/BZip2Register.cpp create mode 100755 CPP/7zip/Compress/Bcj2Coder.cpp create mode 100755 CPP/7zip/Compress/Bcj2Coder.h create mode 100755 CPP/7zip/Compress/Bcj2Register.cpp create mode 100755 CPP/7zip/Compress/BcjCoder.cpp create mode 100755 CPP/7zip/Compress/BcjCoder.h create mode 100755 CPP/7zip/Compress/BcjRegister.cpp create mode 100755 CPP/7zip/Compress/BitlDecoder.cpp create mode 100755 CPP/7zip/Compress/BitlDecoder.h create mode 100755 CPP/7zip/Compress/BitlEncoder.h create mode 100755 CPP/7zip/Compress/BitmDecoder.h create mode 100755 CPP/7zip/Compress/BitmEncoder.h create mode 100755 CPP/7zip/Compress/BranchCoder.cpp create mode 100755 CPP/7zip/Compress/BranchCoder.h create mode 100755 CPP/7zip/Compress/BranchMisc.cpp create mode 100755 CPP/7zip/Compress/BranchMisc.h create mode 100755 CPP/7zip/Compress/BranchRegister.cpp create mode 100755 CPP/7zip/Compress/ByteSwap.cpp create mode 100755 CPP/7zip/Compress/Codec.def create mode 100755 CPP/7zip/Compress/CodecExports.cpp create mode 100755 CPP/7zip/Compress/CopyCoder.cpp create mode 100755 CPP/7zip/Compress/CopyCoder.h create mode 100755 CPP/7zip/Compress/CopyRegister.cpp create mode 100755 CPP/7zip/Compress/Deflate64Register.cpp create mode 100755 CPP/7zip/Compress/DeflateConst.h create mode 100755 CPP/7zip/Compress/DeflateDecoder.cpp create mode 100755 CPP/7zip/Compress/DeflateDecoder.h create mode 100755 CPP/7zip/Compress/DeflateEncoder.cpp create mode 100755 CPP/7zip/Compress/DeflateEncoder.h create mode 100755 CPP/7zip/Compress/DeflateRegister.cpp create mode 100755 CPP/7zip/Compress/DeltaFilter.cpp create mode 100755 CPP/7zip/Compress/DllExports.cpp create mode 100755 CPP/7zip/Compress/DllExports2.cpp create mode 100755 CPP/7zip/Compress/HuffmanDecoder.h create mode 100755 CPP/7zip/Compress/ImplodeDecoder.cpp create mode 100755 CPP/7zip/Compress/ImplodeDecoder.h create mode 100755 CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp create mode 100755 CPP/7zip/Compress/ImplodeHuffmanDecoder.h create mode 100755 CPP/7zip/Compress/LzOutWindow.cpp create mode 100755 CPP/7zip/Compress/LzOutWindow.h create mode 100755 CPP/7zip/Compress/LzhDecoder.cpp create mode 100755 CPP/7zip/Compress/LzhDecoder.h create mode 100755 CPP/7zip/Compress/Lzma2Decoder.cpp create mode 100755 CPP/7zip/Compress/Lzma2Decoder.h create mode 100755 CPP/7zip/Compress/Lzma2Encoder.cpp create mode 100755 CPP/7zip/Compress/Lzma2Encoder.h create mode 100755 CPP/7zip/Compress/Lzma2Register.cpp create mode 100755 CPP/7zip/Compress/LzmaDecoder.cpp create mode 100755 CPP/7zip/Compress/LzmaDecoder.h create mode 100755 CPP/7zip/Compress/LzmaEncoder.cpp create mode 100755 CPP/7zip/Compress/LzmaEncoder.h create mode 100755 CPP/7zip/Compress/LzmaRegister.cpp create mode 100755 CPP/7zip/Compress/Lzx.h create mode 100755 CPP/7zip/Compress/Lzx86Converter.cpp create mode 100755 CPP/7zip/Compress/Lzx86Converter.h create mode 100755 CPP/7zip/Compress/LzxDecoder.cpp create mode 100755 CPP/7zip/Compress/LzxDecoder.h create mode 100755 CPP/7zip/Compress/Mtf8.h create mode 100755 CPP/7zip/Compress/PpmdDecoder.cpp create mode 100755 CPP/7zip/Compress/PpmdDecoder.h create mode 100755 CPP/7zip/Compress/PpmdEncoder.cpp create mode 100755 CPP/7zip/Compress/PpmdEncoder.h create mode 100755 CPP/7zip/Compress/PpmdRegister.cpp create mode 100755 CPP/7zip/Compress/PpmdZip.cpp create mode 100755 CPP/7zip/Compress/PpmdZip.h create mode 100755 CPP/7zip/Compress/QuantumDecoder.cpp create mode 100755 CPP/7zip/Compress/QuantumDecoder.h create mode 100755 CPP/7zip/Compress/RangeCoder.h create mode 100755 CPP/7zip/Compress/RangeCoderBit.h create mode 100755 CPP/7zip/Compress/Rar1Decoder.cpp create mode 100755 CPP/7zip/Compress/Rar1Decoder.h create mode 100755 CPP/7zip/Compress/Rar2Decoder.cpp create mode 100755 CPP/7zip/Compress/Rar2Decoder.h create mode 100755 CPP/7zip/Compress/Rar3Decoder.cpp create mode 100755 CPP/7zip/Compress/Rar3Decoder.h create mode 100755 CPP/7zip/Compress/Rar3Vm.cpp create mode 100755 CPP/7zip/Compress/Rar3Vm.h create mode 100755 CPP/7zip/Compress/RarCodecsRegister.cpp create mode 100755 CPP/7zip/Compress/ShrinkDecoder.cpp create mode 100755 CPP/7zip/Compress/ShrinkDecoder.h create mode 100755 CPP/7zip/Compress/StdAfx.h create mode 100755 CPP/7zip/Compress/ZDecoder.cpp create mode 100755 CPP/7zip/Compress/ZDecoder.h create mode 100755 CPP/7zip/Compress/ZlibDecoder.cpp create mode 100755 CPP/7zip/Compress/ZlibDecoder.h create mode 100755 CPP/7zip/Compress/ZlibEncoder.cpp create mode 100755 CPP/7zip/Compress/ZlibEncoder.h create mode 100755 CPP/7zip/Compress/makefile create mode 100755 CPP/7zip/Crc.mak create mode 100755 CPP/7zip/Crypto/7zAes.cpp create mode 100755 CPP/7zip/Crypto/7zAes.h create mode 100755 CPP/7zip/Crypto/7zAesRegister.cpp create mode 100755 CPP/7zip/Crypto/Codec.def create mode 100755 CPP/7zip/Crypto/HmacSha1.cpp create mode 100755 CPP/7zip/Crypto/HmacSha1.h create mode 100755 CPP/7zip/Crypto/MyAes.cpp create mode 100755 CPP/7zip/Crypto/MyAes.h create mode 100755 CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp create mode 100755 CPP/7zip/Crypto/Pbkdf2HmacSha1.h create mode 100755 CPP/7zip/Crypto/RandGen.cpp create mode 100755 CPP/7zip/Crypto/RandGen.h create mode 100755 CPP/7zip/Crypto/Rar20Crypto.cpp create mode 100755 CPP/7zip/Crypto/Rar20Crypto.h create mode 100755 CPP/7zip/Crypto/RarAes.cpp create mode 100755 CPP/7zip/Crypto/RarAes.h create mode 100755 CPP/7zip/Crypto/Sha1.cpp create mode 100755 CPP/7zip/Crypto/Sha1.h create mode 100755 CPP/7zip/Crypto/StdAfx.h create mode 100755 CPP/7zip/Crypto/WzAes.cpp create mode 100755 CPP/7zip/Crypto/WzAes.h create mode 100755 CPP/7zip/Crypto/ZipCrypto.cpp create mode 100755 CPP/7zip/Crypto/ZipCrypto.h create mode 100755 CPP/7zip/Crypto/ZipStrong.cpp create mode 100755 CPP/7zip/Crypto/ZipStrong.h create mode 100755 CPP/7zip/GuiCommon.rc create mode 100755 CPP/7zip/Guid.txt create mode 100755 CPP/7zip/ICoder.h create mode 100755 CPP/7zip/IDecl.h create mode 100755 CPP/7zip/IPassword.h create mode 100755 CPP/7zip/IProgress.h create mode 100755 CPP/7zip/IStream.h create mode 100755 CPP/7zip/MyVersion.h create mode 100755 CPP/7zip/MyVersionInfo.rc create mode 100755 CPP/7zip/PropID.h create mode 100755 CPP/7zip/SubBuild.mak create mode 100755 CPP/7zip/UI/Agent/Agent.cpp create mode 100755 CPP/7zip/UI/Agent/Agent.h create mode 100755 CPP/7zip/UI/Agent/AgentOut.cpp create mode 100755 CPP/7zip/UI/Agent/AgentProxy.cpp create mode 100755 CPP/7zip/UI/Agent/AgentProxy.h create mode 100755 CPP/7zip/UI/Agent/ArchiveFolder.cpp create mode 100755 CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp create mode 100755 CPP/7zip/UI/Agent/ArchiveFolderOut.cpp create mode 100755 CPP/7zip/UI/Agent/IFolderArchive.h create mode 100755 CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp create mode 100755 CPP/7zip/UI/Agent/UpdateCallbackAgent.h create mode 100755 CPP/7zip/UI/Client7z/Client7z.cpp create mode 100755 CPP/7zip/UI/Client7z/Client7z.dsp create mode 100755 CPP/7zip/UI/Client7z/Client7z.dsw create mode 100755 CPP/7zip/UI/Client7z/StdAfx.cpp create mode 100755 CPP/7zip/UI/Client7z/StdAfx.h create mode 100755 CPP/7zip/UI/Client7z/makefile create mode 100755 CPP/7zip/UI/Common/ArchiveCommandLine.cpp create mode 100755 CPP/7zip/UI/Common/ArchiveCommandLine.h create mode 100755 CPP/7zip/UI/Common/ArchiveExtractCallback.cpp create mode 100755 CPP/7zip/UI/Common/ArchiveExtractCallback.h create mode 100755 CPP/7zip/UI/Common/ArchiveName.cpp create mode 100755 CPP/7zip/UI/Common/ArchiveName.h create mode 100755 CPP/7zip/UI/Common/ArchiveOpenCallback.cpp create mode 100755 CPP/7zip/UI/Common/ArchiveOpenCallback.h create mode 100755 CPP/7zip/UI/Common/Bench.cpp create mode 100755 CPP/7zip/UI/Common/Bench.h create mode 100755 CPP/7zip/UI/Common/CompressCall.cpp create mode 100755 CPP/7zip/UI/Common/CompressCall.h create mode 100755 CPP/7zip/UI/Common/CompressCall2.cpp create mode 100755 CPP/7zip/UI/Common/DefaultName.cpp create mode 100755 CPP/7zip/UI/Common/DefaultName.h create mode 100755 CPP/7zip/UI/Common/DirItem.h create mode 100755 CPP/7zip/UI/Common/EnumDirItems.cpp create mode 100755 CPP/7zip/UI/Common/EnumDirItems.h create mode 100755 CPP/7zip/UI/Common/ExitCode.h create mode 100755 CPP/7zip/UI/Common/Extract.cpp create mode 100755 CPP/7zip/UI/Common/Extract.h create mode 100755 CPP/7zip/UI/Common/ExtractMode.h create mode 100755 CPP/7zip/UI/Common/ExtractingFilePath.cpp create mode 100755 CPP/7zip/UI/Common/ExtractingFilePath.h create mode 100755 CPP/7zip/UI/Common/IFileExtractCallback.h create mode 100755 CPP/7zip/UI/Common/LoadCodecs.cpp create mode 100755 CPP/7zip/UI/Common/LoadCodecs.h create mode 100755 CPP/7zip/UI/Common/OpenArchive.cpp create mode 100755 CPP/7zip/UI/Common/OpenArchive.h create mode 100755 CPP/7zip/UI/Common/PropIDUtils.cpp create mode 100755 CPP/7zip/UI/Common/PropIDUtils.h create mode 100755 CPP/7zip/UI/Common/Property.h create mode 100755 CPP/7zip/UI/Common/SetProperties.cpp create mode 100755 CPP/7zip/UI/Common/SetProperties.h create mode 100755 CPP/7zip/UI/Common/SortUtils.cpp create mode 100755 CPP/7zip/UI/Common/SortUtils.h create mode 100755 CPP/7zip/UI/Common/StdAfx.h create mode 100755 CPP/7zip/UI/Common/TempFiles.cpp create mode 100755 CPP/7zip/UI/Common/TempFiles.h create mode 100755 CPP/7zip/UI/Common/Update.cpp create mode 100755 CPP/7zip/UI/Common/Update.h create mode 100755 CPP/7zip/UI/Common/UpdateAction.cpp create mode 100755 CPP/7zip/UI/Common/UpdateAction.h create mode 100755 CPP/7zip/UI/Common/UpdateCallback.cpp create mode 100755 CPP/7zip/UI/Common/UpdateCallback.h create mode 100755 CPP/7zip/UI/Common/UpdatePair.cpp create mode 100755 CPP/7zip/UI/Common/UpdatePair.h create mode 100755 CPP/7zip/UI/Common/UpdateProduce.cpp create mode 100755 CPP/7zip/UI/Common/UpdateProduce.h create mode 100755 CPP/7zip/UI/Common/WorkDir.cpp create mode 100755 CPP/7zip/UI/Common/WorkDir.h create mode 100755 CPP/7zip/UI/Common/ZipRegistry.cpp create mode 100755 CPP/7zip/UI/Common/ZipRegistry.h create mode 100755 CPP/7zip/UI/Console/BenchCon.cpp create mode 100755 CPP/7zip/UI/Console/BenchCon.h create mode 100755 CPP/7zip/UI/Console/Console.dsp create mode 100755 CPP/7zip/UI/Console/Console.dsw create mode 100755 CPP/7zip/UI/Console/ConsoleClose.cpp create mode 100755 CPP/7zip/UI/Console/ConsoleClose.h create mode 100755 CPP/7zip/UI/Console/ExtractCallbackConsole.cpp create mode 100755 CPP/7zip/UI/Console/ExtractCallbackConsole.h create mode 100755 CPP/7zip/UI/Console/List.cpp create mode 100755 CPP/7zip/UI/Console/List.h create mode 100755 CPP/7zip/UI/Console/Main.cpp create mode 100755 CPP/7zip/UI/Console/MainAr.cpp create mode 100755 CPP/7zip/UI/Console/OpenCallbackConsole.cpp create mode 100755 CPP/7zip/UI/Console/OpenCallbackConsole.h create mode 100755 CPP/7zip/UI/Console/PercentPrinter.cpp create mode 100755 CPP/7zip/UI/Console/PercentPrinter.h create mode 100755 CPP/7zip/UI/Console/StdAfx.cpp create mode 100755 CPP/7zip/UI/Console/StdAfx.h create mode 100755 CPP/7zip/UI/Console/UpdateCallbackConsole.cpp create mode 100755 CPP/7zip/UI/Console/UpdateCallbackConsole.h create mode 100755 CPP/7zip/UI/Console/UserInputUtils.cpp create mode 100755 CPP/7zip/UI/Console/UserInputUtils.h create mode 100755 CPP/7zip/UI/Console/makefile create mode 100755 CPP/7zip/UI/Console/resource.rc create mode 100755 CPP/7zip/UI/Explorer/7-zip.dll.manifest create mode 100755 CPP/7zip/UI/Explorer/ContextMenu.cpp create mode 100755 CPP/7zip/UI/Explorer/ContextMenu.h create mode 100755 CPP/7zip/UI/Explorer/ContextMenuFlags.h create mode 100755 CPP/7zip/UI/Explorer/DllExports.cpp create mode 100755 CPP/7zip/UI/Explorer/Explorer.def create mode 100755 CPP/7zip/UI/Explorer/Explorer.dsp create mode 100755 CPP/7zip/UI/Explorer/Explorer.dsw create mode 100755 CPP/7zip/UI/Explorer/MyMessages.cpp create mode 100755 CPP/7zip/UI/Explorer/MyMessages.h create mode 100755 CPP/7zip/UI/Explorer/OptionsDialog.cpp create mode 100755 CPP/7zip/UI/Explorer/OptionsDialog.h create mode 100755 CPP/7zip/UI/Explorer/RegistryContextMenu.cpp create mode 100755 CPP/7zip/UI/Explorer/RegistryContextMenu.h create mode 100755 CPP/7zip/UI/Explorer/StdAfx.cpp create mode 100755 CPP/7zip/UI/Explorer/StdAfx.h create mode 100755 CPP/7zip/UI/Explorer/makefile create mode 100755 CPP/7zip/UI/Explorer/resource.h create mode 100755 CPP/7zip/UI/Explorer/resource.rc create mode 100755 CPP/7zip/UI/Explorer/resource2.rc create mode 100755 CPP/7zip/UI/Far/ExtractEngine.cpp create mode 100755 CPP/7zip/UI/Far/ExtractEngine.h create mode 100755 CPP/7zip/UI/Far/Far.def create mode 100755 CPP/7zip/UI/Far/Far.dsp create mode 100755 CPP/7zip/UI/Far/Far.dsw create mode 100755 CPP/7zip/UI/Far/FarPlugin.h create mode 100755 CPP/7zip/UI/Far/FarUtils.cpp create mode 100755 CPP/7zip/UI/Far/FarUtils.h create mode 100755 CPP/7zip/UI/Far/Main.cpp create mode 100755 CPP/7zip/UI/Far/Messages.h create mode 100755 CPP/7zip/UI/Far/OverwriteDialog.cpp create mode 100755 CPP/7zip/UI/Far/OverwriteDialog.h create mode 100755 CPP/7zip/UI/Far/Plugin.cpp create mode 100755 CPP/7zip/UI/Far/Plugin.h create mode 100755 CPP/7zip/UI/Far/PluginCommon.cpp create mode 100755 CPP/7zip/UI/Far/PluginDelete.cpp create mode 100755 CPP/7zip/UI/Far/PluginRead.cpp create mode 100755 CPP/7zip/UI/Far/PluginWrite.cpp create mode 100755 CPP/7zip/UI/Far/ProgressBox.cpp create mode 100755 CPP/7zip/UI/Far/ProgressBox.h create mode 100755 CPP/7zip/UI/Far/StdAfx.cpp create mode 100755 CPP/7zip/UI/Far/StdAfx.h create mode 100755 CPP/7zip/UI/Far/UpdateCallback100.cpp create mode 100755 CPP/7zip/UI/Far/UpdateCallback100.h create mode 100755 CPP/7zip/UI/Far/makefile create mode 100755 CPP/7zip/UI/Far/resource.rc create mode 100755 CPP/7zip/UI/FileManager/7zFM.exe.manifest create mode 100755 CPP/7zip/UI/FileManager/7zipLogo.ico create mode 100755 CPP/7zip/UI/FileManager/AboutDialog.cpp create mode 100755 CPP/7zip/UI/FileManager/AboutDialog.h create mode 100755 CPP/7zip/UI/FileManager/AboutDialog.rc create mode 100755 CPP/7zip/UI/FileManager/AboutDialogRes.h create mode 100755 CPP/7zip/UI/FileManager/Add.bmp create mode 100755 CPP/7zip/UI/FileManager/Add2.bmp create mode 100755 CPP/7zip/UI/FileManager/App.cpp create mode 100755 CPP/7zip/UI/FileManager/App.h create mode 100755 CPP/7zip/UI/FileManager/AppState.h create mode 100755 CPP/7zip/UI/FileManager/BrowseDialog.cpp create mode 100755 CPP/7zip/UI/FileManager/BrowseDialog.h create mode 100755 CPP/7zip/UI/FileManager/BrowseDialog.rc create mode 100755 CPP/7zip/UI/FileManager/BrowseDialogRes.h create mode 100755 CPP/7zip/UI/FileManager/ClassDefs.cpp create mode 100755 CPP/7zip/UI/FileManager/ComboDialog.cpp create mode 100755 CPP/7zip/UI/FileManager/ComboDialog.h create mode 100755 CPP/7zip/UI/FileManager/ComboDialog.rc create mode 100755 CPP/7zip/UI/FileManager/ComboDialogRes.h create mode 100755 CPP/7zip/UI/FileManager/Copy.bmp create mode 100755 CPP/7zip/UI/FileManager/Copy2.bmp create mode 100755 CPP/7zip/UI/FileManager/CopyDialog.cpp create mode 100755 CPP/7zip/UI/FileManager/CopyDialog.h create mode 100755 CPP/7zip/UI/FileManager/CopyDialog.rc create mode 100755 CPP/7zip/UI/FileManager/CopyDialogRes.h create mode 100755 CPP/7zip/UI/FileManager/Delete.bmp create mode 100755 CPP/7zip/UI/FileManager/Delete2.bmp create mode 100755 CPP/7zip/UI/FileManager/DialogSize.h create mode 100755 CPP/7zip/UI/FileManager/EditPage.cpp create mode 100755 CPP/7zip/UI/FileManager/EditPage.h create mode 100755 CPP/7zip/UI/FileManager/EditPage.rc create mode 100755 CPP/7zip/UI/FileManager/EditPage2.rc create mode 100755 CPP/7zip/UI/FileManager/EditPageRes.h create mode 100755 CPP/7zip/UI/FileManager/EnumFormatEtc.cpp create mode 100755 CPP/7zip/UI/FileManager/EnumFormatEtc.h create mode 100755 CPP/7zip/UI/FileManager/Extract.bmp create mode 100755 CPP/7zip/UI/FileManager/Extract2.bmp create mode 100755 CPP/7zip/UI/FileManager/ExtractCallback.cpp create mode 100755 CPP/7zip/UI/FileManager/ExtractCallback.h create mode 100755 CPP/7zip/UI/FileManager/FM.cpp create mode 100755 CPP/7zip/UI/FileManager/FM.dsp create mode 100755 CPP/7zip/UI/FileManager/FM.dsw create mode 100755 CPP/7zip/UI/FileManager/FM.ico create mode 100755 CPP/7zip/UI/FileManager/FSDrives.cpp create mode 100755 CPP/7zip/UI/FileManager/FSDrives.h create mode 100755 CPP/7zip/UI/FileManager/FSFolder.cpp create mode 100755 CPP/7zip/UI/FileManager/FSFolder.h create mode 100755 CPP/7zip/UI/FileManager/FSFolderCopy.cpp create mode 100755 CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp create mode 100755 CPP/7zip/UI/FileManager/FileFolderPluginOpen.h create mode 100755 CPP/7zip/UI/FileManager/FilePlugins.cpp create mode 100755 CPP/7zip/UI/FileManager/FilePlugins.h create mode 100755 CPP/7zip/UI/FileManager/FoldersPage.cpp create mode 100755 CPP/7zip/UI/FileManager/FoldersPage.h create mode 100755 CPP/7zip/UI/FileManager/FoldersPage.rc create mode 100755 CPP/7zip/UI/FileManager/FoldersPage2.rc create mode 100755 CPP/7zip/UI/FileManager/FoldersPageRes.h create mode 100755 CPP/7zip/UI/FileManager/FormatUtils.cpp create mode 100755 CPP/7zip/UI/FileManager/FormatUtils.h create mode 100755 CPP/7zip/UI/FileManager/HelpUtils.cpp create mode 100755 CPP/7zip/UI/FileManager/HelpUtils.h create mode 100755 CPP/7zip/UI/FileManager/IFolder.h create mode 100755 CPP/7zip/UI/FileManager/Info.bmp create mode 100755 CPP/7zip/UI/FileManager/Info2.bmp create mode 100755 CPP/7zip/UI/FileManager/LangPage.cpp create mode 100755 CPP/7zip/UI/FileManager/LangPage.h create mode 100755 CPP/7zip/UI/FileManager/LangPage.rc create mode 100755 CPP/7zip/UI/FileManager/LangPageRes.h create mode 100755 CPP/7zip/UI/FileManager/LangUtils.cpp create mode 100755 CPP/7zip/UI/FileManager/LangUtils.h create mode 100755 CPP/7zip/UI/FileManager/ListViewDialog.cpp create mode 100755 CPP/7zip/UI/FileManager/ListViewDialog.h create mode 100755 CPP/7zip/UI/FileManager/ListViewDialog.rc create mode 100755 CPP/7zip/UI/FileManager/ListViewDialogRes.h create mode 100755 CPP/7zip/UI/FileManager/MenuPage.cpp create mode 100755 CPP/7zip/UI/FileManager/MenuPage.h create mode 100755 CPP/7zip/UI/FileManager/MenuPage.rc create mode 100755 CPP/7zip/UI/FileManager/MenuPage2.rc create mode 100755 CPP/7zip/UI/FileManager/MenuPageRes.h create mode 100755 CPP/7zip/UI/FileManager/MessagesDialog.cpp create mode 100755 CPP/7zip/UI/FileManager/MessagesDialog.h create mode 100755 CPP/7zip/UI/FileManager/MessagesDialog.rc create mode 100755 CPP/7zip/UI/FileManager/MessagesDialogRes.h create mode 100755 CPP/7zip/UI/FileManager/Move.bmp create mode 100755 CPP/7zip/UI/FileManager/Move2.bmp create mode 100755 CPP/7zip/UI/FileManager/MyCom2.h create mode 100755 CPP/7zip/UI/FileManager/MyLoadMenu.cpp create mode 100755 CPP/7zip/UI/FileManager/MyLoadMenu.h create mode 100755 CPP/7zip/UI/FileManager/NetFolder.cpp create mode 100755 CPP/7zip/UI/FileManager/NetFolder.h create mode 100755 CPP/7zip/UI/FileManager/OpenCallback.cpp create mode 100755 CPP/7zip/UI/FileManager/OpenCallback.h create mode 100755 CPP/7zip/UI/FileManager/OptionsDialog.cpp create mode 100755 CPP/7zip/UI/FileManager/OverwriteDialog.cpp create mode 100755 CPP/7zip/UI/FileManager/OverwriteDialog.h create mode 100755 CPP/7zip/UI/FileManager/OverwriteDialog.rc create mode 100755 CPP/7zip/UI/FileManager/OverwriteDialogRes.h create mode 100755 CPP/7zip/UI/FileManager/Panel.cpp create mode 100755 CPP/7zip/UI/FileManager/Panel.h create mode 100755 CPP/7zip/UI/FileManager/PanelCopy.cpp create mode 100755 CPP/7zip/UI/FileManager/PanelCrc.cpp create mode 100755 CPP/7zip/UI/FileManager/PanelDrag.cpp create mode 100755 CPP/7zip/UI/FileManager/PanelFolderChange.cpp create mode 100755 CPP/7zip/UI/FileManager/PanelItemOpen.cpp create mode 100755 CPP/7zip/UI/FileManager/PanelItems.cpp create mode 100755 CPP/7zip/UI/FileManager/PanelKey.cpp create mode 100755 CPP/7zip/UI/FileManager/PanelListNotify.cpp create mode 100755 CPP/7zip/UI/FileManager/PanelMenu.cpp create mode 100755 CPP/7zip/UI/FileManager/PanelOperations.cpp create mode 100755 CPP/7zip/UI/FileManager/PanelSelect.cpp create mode 100755 CPP/7zip/UI/FileManager/PanelSort.cpp create mode 100755 CPP/7zip/UI/FileManager/PanelSplitFile.cpp create mode 100755 CPP/7zip/UI/FileManager/PasswordDialog.cpp create mode 100755 CPP/7zip/UI/FileManager/PasswordDialog.h create mode 100755 CPP/7zip/UI/FileManager/PasswordDialog.rc create mode 100755 CPP/7zip/UI/FileManager/PasswordDialogRes.h create mode 100755 CPP/7zip/UI/FileManager/PluginInterface.h create mode 100755 CPP/7zip/UI/FileManager/PluginLoader.h create mode 100755 CPP/7zip/UI/FileManager/PluginsPage.cpp create mode 100755 CPP/7zip/UI/FileManager/PluginsPage.h create mode 100755 CPP/7zip/UI/FileManager/PluginsPage.rc create mode 100755 CPP/7zip/UI/FileManager/PluginsPageRes.h create mode 100755 CPP/7zip/UI/FileManager/ProgramLocation.cpp create mode 100755 CPP/7zip/UI/FileManager/ProgramLocation.h create mode 100755 CPP/7zip/UI/FileManager/ProgressDialog.cpp create mode 100755 CPP/7zip/UI/FileManager/ProgressDialog.h create mode 100755 CPP/7zip/UI/FileManager/ProgressDialog.rc create mode 100755 CPP/7zip/UI/FileManager/ProgressDialog2.cpp create mode 100755 CPP/7zip/UI/FileManager/ProgressDialog2.h create mode 100755 CPP/7zip/UI/FileManager/ProgressDialog2.rc create mode 100755 CPP/7zip/UI/FileManager/ProgressDialog2Res.h create mode 100755 CPP/7zip/UI/FileManager/ProgressDialog2a.rc create mode 100755 CPP/7zip/UI/FileManager/ProgressDialogRes.h create mode 100755 CPP/7zip/UI/FileManager/PropertyName.cpp create mode 100755 CPP/7zip/UI/FileManager/PropertyName.h create mode 100755 CPP/7zip/UI/FileManager/PropertyName.rc create mode 100755 CPP/7zip/UI/FileManager/PropertyNameRes.h create mode 100755 CPP/7zip/UI/FileManager/RegistryAssociations.cpp create mode 100755 CPP/7zip/UI/FileManager/RegistryAssociations.h create mode 100755 CPP/7zip/UI/FileManager/RegistryPlugins.cpp create mode 100755 CPP/7zip/UI/FileManager/RegistryPlugins.h create mode 100755 CPP/7zip/UI/FileManager/RegistryUtils.cpp create mode 100755 CPP/7zip/UI/FileManager/RegistryUtils.h create mode 100755 CPP/7zip/UI/FileManager/RootFolder.cpp create mode 100755 CPP/7zip/UI/FileManager/RootFolder.h create mode 100755 CPP/7zip/UI/FileManager/SettingsPage.cpp create mode 100755 CPP/7zip/UI/FileManager/SettingsPage.h create mode 100755 CPP/7zip/UI/FileManager/SettingsPage.rc create mode 100755 CPP/7zip/UI/FileManager/SettingsPage2.rc create mode 100755 CPP/7zip/UI/FileManager/SettingsPageRes.h create mode 100755 CPP/7zip/UI/FileManager/SplitDialog.cpp create mode 100755 CPP/7zip/UI/FileManager/SplitDialog.h create mode 100755 CPP/7zip/UI/FileManager/SplitDialog.rc create mode 100755 CPP/7zip/UI/FileManager/SplitDialogRes.h create mode 100755 CPP/7zip/UI/FileManager/SplitUtils.cpp create mode 100755 CPP/7zip/UI/FileManager/SplitUtils.h create mode 100755 CPP/7zip/UI/FileManager/StdAfx.cpp create mode 100755 CPP/7zip/UI/FileManager/StdAfx.h create mode 100755 CPP/7zip/UI/FileManager/StringUtils.cpp create mode 100755 CPP/7zip/UI/FileManager/StringUtils.h create mode 100755 CPP/7zip/UI/FileManager/SysIconUtils.cpp create mode 100755 CPP/7zip/UI/FileManager/SysIconUtils.h create mode 100755 CPP/7zip/UI/FileManager/SystemPage.cpp create mode 100755 CPP/7zip/UI/FileManager/SystemPage.h create mode 100755 CPP/7zip/UI/FileManager/SystemPage.rc create mode 100755 CPP/7zip/UI/FileManager/SystemPageRes.h create mode 100755 CPP/7zip/UI/FileManager/Test.bmp create mode 100755 CPP/7zip/UI/FileManager/Test2.bmp create mode 100755 CPP/7zip/UI/FileManager/TextPairs.cpp create mode 100755 CPP/7zip/UI/FileManager/TextPairs.h create mode 100755 CPP/7zip/UI/FileManager/UpdateCallback100.cpp create mode 100755 CPP/7zip/UI/FileManager/UpdateCallback100.h create mode 100755 CPP/7zip/UI/FileManager/ViewSettings.cpp create mode 100755 CPP/7zip/UI/FileManager/ViewSettings.h create mode 100755 CPP/7zip/UI/FileManager/makefile create mode 100755 CPP/7zip/UI/FileManager/resource.h create mode 100755 CPP/7zip/UI/FileManager/resource.rc create mode 100755 CPP/7zip/UI/FileManager/resourceGui.h create mode 100755 CPP/7zip/UI/FileManager/resourceGui.rc create mode 100755 CPP/7zip/UI/GUI/7zG.exe.manifest create mode 100755 CPP/7zip/UI/GUI/BenchmarkDialog.cpp create mode 100755 CPP/7zip/UI/GUI/BenchmarkDialog.h create mode 100755 CPP/7zip/UI/GUI/BenchmarkDialog.rc create mode 100755 CPP/7zip/UI/GUI/BenchmarkDialogRes.h create mode 100755 CPP/7zip/UI/GUI/CompressDialog.cpp create mode 100755 CPP/7zip/UI/GUI/CompressDialog.h create mode 100755 CPP/7zip/UI/GUI/CompressDialog.rc create mode 100755 CPP/7zip/UI/GUI/CompressDialogRes.h create mode 100755 CPP/7zip/UI/GUI/Extract.rc create mode 100755 CPP/7zip/UI/GUI/ExtractDialog.cpp create mode 100755 CPP/7zip/UI/GUI/ExtractDialog.h create mode 100755 CPP/7zip/UI/GUI/ExtractDialog.rc create mode 100755 CPP/7zip/UI/GUI/ExtractDialogRes.h create mode 100755 CPP/7zip/UI/GUI/ExtractGUI.cpp create mode 100755 CPP/7zip/UI/GUI/ExtractGUI.h create mode 100755 CPP/7zip/UI/GUI/ExtractRes.h create mode 100755 CPP/7zip/UI/GUI/FM.ico create mode 100755 CPP/7zip/UI/GUI/GUI.cpp create mode 100755 CPP/7zip/UI/GUI/GUI.dsp create mode 100755 CPP/7zip/UI/GUI/GUI.dsw create mode 100755 CPP/7zip/UI/GUI/StdAfx.cpp create mode 100755 CPP/7zip/UI/GUI/StdAfx.h create mode 100755 CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp create mode 100755 CPP/7zip/UI/GUI/UpdateCallbackGUI.h create mode 100755 CPP/7zip/UI/GUI/UpdateGUI.cpp create mode 100755 CPP/7zip/UI/GUI/UpdateGUI.h create mode 100755 CPP/7zip/UI/GUI/makefile create mode 100755 CPP/7zip/UI/GUI/resource.rc create mode 100755 CPP/7zip/UI/GUI/resource2.h create mode 100755 CPP/7zip/UI/GUI/resource2.rc create mode 100755 CPP/7zip/UI/makefile create mode 100755 CPP/7zip/makefile create mode 100755 CPP/Build.mak create mode 100755 CPP/Common/AutoPtr.h create mode 100755 CPP/Common/Buffer.h create mode 100755 CPP/Common/CRC.cpp create mode 100755 CPP/Common/C_FileIO.cpp create mode 100755 CPP/Common/C_FileIO.h create mode 100755 CPP/Common/ComTry.h create mode 100755 CPP/Common/CommandLineParser.cpp create mode 100755 CPP/Common/CommandLineParser.h create mode 100755 CPP/Common/Defs.h create mode 100755 CPP/Common/DynamicBuffer.h create mode 100755 CPP/Common/IntToString.cpp create mode 100755 CPP/Common/IntToString.h create mode 100755 CPP/Common/Lang.cpp create mode 100755 CPP/Common/Lang.h create mode 100755 CPP/Common/ListFileUtils.cpp create mode 100755 CPP/Common/ListFileUtils.h create mode 100755 CPP/Common/MyCom.h create mode 100755 CPP/Common/MyException.h create mode 100755 CPP/Common/MyGuidDef.h create mode 100755 CPP/Common/MyInitGuid.h create mode 100755 CPP/Common/MyMap.cpp create mode 100755 CPP/Common/MyMap.h create mode 100755 CPP/Common/MyString.cpp create mode 100755 CPP/Common/MyString.h create mode 100755 CPP/Common/MyUnknown.h create mode 100755 CPP/Common/MyVector.cpp create mode 100755 CPP/Common/MyVector.h create mode 100755 CPP/Common/MyWindows.cpp create mode 100755 CPP/Common/MyWindows.h create mode 100755 CPP/Common/MyXml.cpp create mode 100755 CPP/Common/MyXml.h create mode 100755 CPP/Common/NewHandler.cpp create mode 100755 CPP/Common/NewHandler.h create mode 100755 CPP/Common/Random.cpp create mode 100755 CPP/Common/Random.h create mode 100755 CPP/Common/StdAfx.h create mode 100755 CPP/Common/StdInStream.cpp create mode 100755 CPP/Common/StdInStream.h create mode 100755 CPP/Common/StdOutStream.cpp create mode 100755 CPP/Common/StdOutStream.h create mode 100755 CPP/Common/StringConvert.cpp create mode 100755 CPP/Common/StringConvert.h create mode 100755 CPP/Common/StringToInt.cpp create mode 100755 CPP/Common/StringToInt.h create mode 100755 CPP/Common/TextConfig.cpp create mode 100755 CPP/Common/TextConfig.h create mode 100755 CPP/Common/Types.h create mode 100755 CPP/Common/UTFConvert.cpp create mode 100755 CPP/Common/UTFConvert.h create mode 100755 CPP/Common/Wildcard.cpp create mode 100755 CPP/Common/Wildcard.h create mode 100755 CPP/Windows/COM.cpp create mode 100755 CPP/Windows/COM.h create mode 100755 CPP/Windows/Clipboard.cpp create mode 100755 CPP/Windows/Clipboard.h create mode 100755 CPP/Windows/CommonDialog.cpp create mode 100755 CPP/Windows/CommonDialog.h create mode 100755 CPP/Windows/Console.cpp create mode 100755 CPP/Windows/Console.h create mode 100755 CPP/Windows/Control/ComboBox.cpp create mode 100755 CPP/Windows/Control/ComboBox.h create mode 100755 CPP/Windows/Control/CommandBar.h create mode 100755 CPP/Windows/Control/Dialog.cpp create mode 100755 CPP/Windows/Control/Dialog.h create mode 100755 CPP/Windows/Control/Edit.h create mode 100755 CPP/Windows/Control/ImageList.cpp create mode 100755 CPP/Windows/Control/ImageList.h create mode 100755 CPP/Windows/Control/ListView.cpp create mode 100755 CPP/Windows/Control/ListView.h create mode 100755 CPP/Windows/Control/ProgressBar.h create mode 100755 CPP/Windows/Control/PropertyPage.cpp create mode 100755 CPP/Windows/Control/PropertyPage.h create mode 100755 CPP/Windows/Control/ReBar.h create mode 100755 CPP/Windows/Control/Static.h create mode 100755 CPP/Windows/Control/StatusBar.h create mode 100755 CPP/Windows/Control/StdAfx.h create mode 100755 CPP/Windows/Control/ToolBar.h create mode 100755 CPP/Windows/Control/Trackbar.h create mode 100755 CPP/Windows/Control/Window2.cpp create mode 100755 CPP/Windows/Control/Window2.h create mode 100755 CPP/Windows/DLL.cpp create mode 100755 CPP/Windows/DLL.h create mode 100755 CPP/Windows/Defs.h create mode 100755 CPP/Windows/Error.cpp create mode 100755 CPP/Windows/Error.h create mode 100755 CPP/Windows/FileDir.cpp create mode 100755 CPP/Windows/FileDir.h create mode 100755 CPP/Windows/FileFind.cpp create mode 100755 CPP/Windows/FileFind.h create mode 100755 CPP/Windows/FileIO.cpp create mode 100755 CPP/Windows/FileIO.h create mode 100755 CPP/Windows/FileMapping.cpp create mode 100755 CPP/Windows/FileMapping.h create mode 100755 CPP/Windows/FileName.cpp create mode 100755 CPP/Windows/FileName.h create mode 100755 CPP/Windows/FileSystem.cpp create mode 100755 CPP/Windows/FileSystem.h create mode 100755 CPP/Windows/Handle.h create mode 100755 CPP/Windows/Memory.cpp create mode 100755 CPP/Windows/Memory.h create mode 100755 CPP/Windows/MemoryLock.cpp create mode 100755 CPP/Windows/MemoryLock.h create mode 100755 CPP/Windows/Menu.cpp create mode 100755 CPP/Windows/Menu.h create mode 100755 CPP/Windows/NationalTime.cpp create mode 100755 CPP/Windows/NationalTime.h create mode 100755 CPP/Windows/Net.cpp create mode 100755 CPP/Windows/Net.h create mode 100755 CPP/Windows/NtCheck.h create mode 100755 CPP/Windows/Process.cpp create mode 100755 CPP/Windows/Process.h create mode 100755 CPP/Windows/ProcessMessages.cpp create mode 100755 CPP/Windows/ProcessMessages.h create mode 100755 CPP/Windows/PropVariant.cpp create mode 100755 CPP/Windows/PropVariant.h create mode 100755 CPP/Windows/PropVariantConversions.cpp create mode 100755 CPP/Windows/PropVariantConversions.h create mode 100755 CPP/Windows/PropVariantUtils.cpp create mode 100755 CPP/Windows/PropVariantUtils.h create mode 100755 CPP/Windows/Registry.cpp create mode 100755 CPP/Windows/Registry.h create mode 100755 CPP/Windows/ResourceString.cpp create mode 100755 CPP/Windows/ResourceString.h create mode 100755 CPP/Windows/Security.cpp create mode 100755 CPP/Windows/Security.h create mode 100755 CPP/Windows/Shell.cpp create mode 100755 CPP/Windows/Shell.h create mode 100755 CPP/Windows/StdAfx.h create mode 100755 CPP/Windows/Synchronization.cpp create mode 100755 CPP/Windows/Synchronization.h create mode 100755 CPP/Windows/System.cpp create mode 100755 CPP/Windows/System.h create mode 100755 CPP/Windows/Thread.h create mode 100755 CPP/Windows/Time.cpp create mode 100755 CPP/Windows/Time.h create mode 100755 CPP/Windows/Window.cpp create mode 100755 CPP/Windows/Window.h create mode 100755 DOC/7zC.txt create mode 100755 DOC/7zFormat.txt create mode 100755 DOC/7zip.hhp create mode 100755 DOC/7zip.inf create mode 100755 DOC/7zip.nsi create mode 100755 DOC/7zip.wxs create mode 100755 DOC/License.txt create mode 100755 DOC/Methods.txt create mode 100755 DOC/copying.txt create mode 100755 DOC/history.txt create mode 100755 DOC/lzma.txt create mode 100755 DOC/readme.txt create mode 100755 DOC/unRarLicense.txt diff --git a/Asm/arm/7zCrcOpt.asm b/Asm/arm/7zCrcOpt.asm new file mode 100755 index 0000000..f008d65 --- /dev/null +++ b/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/Asm/x86/7zAsm.asm b/Asm/x86/7zAsm.asm new file mode 100755 index 0000000..5a5f271 --- /dev/null +++ b/Asm/x86/7zAsm.asm @@ -0,0 +1,93 @@ +; 7zAsm.asm -- ASM macros +; 2009-12-12 : 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 equ numParams + ifdef x64 + proc_name equ name + name PROC + else + proc_fastcall_name equ @CatStr(@,name,@, %numParams * 4) + public proc_fastcall_name + proc_fastcall_name: + endif +endm + +MY_ENDP macro + ifdef x64 + ret + proc_name ENDP + else + ret (proc_numParams - 2) * 4 + endif +endm + +ifdef x64 + REG_SIZE equ 8 +else + REG_SIZE equ 4 +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_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 + r0 equ RAX + r1 equ RCX + r2 equ RDX + r3 equ RBX + r4 equ RSP + r5 equ RBP + r6 equ RSI + r7 equ RDI +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 diff --git a/Asm/x86/7zCrcOpt.asm b/Asm/x86/7zCrcOpt.asm new file mode 100755 index 0000000..2de5171 --- /dev/null +++ b/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/Asm/x86/AesOpt.asm b/Asm/x86/AesOpt.asm new file mode 100755 index 0000000..c32e48f --- /dev/null +++ b/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/C/7z.h b/C/7z.h new file mode 100755 index 0000000..b7edd3b --- /dev/null +++ b/C/7z.h @@ -0,0 +1,203 @@ +/* 7z.h -- 7z interface +2010-03-11 : Igor Pavlov : Public domain */ + +#ifndef __7Z_H +#define __7Z_H + +#include "7zBuf.h" + +EXTERN_C_BEGIN + +#define k7zStartHeaderSize 0x20 +#define k7zSignatureSize 6 +extern Byte k7zSignature[k7zSignatureSize]; +#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, + k7zIdWinAttributes, + k7zIdComment, + k7zIdEncodedHeader, + k7zIdStartPos, + k7zIdDummy +}; + +typedef struct +{ + UInt32 NumInStreams; + UInt32 NumOutStreams; + UInt64 MethodID; + CBuf Props; +} CSzCoderInfo; + +void SzCoderInfo_Init(CSzCoderInfo *p); +void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc); + +typedef struct +{ + UInt32 InIndex; + UInt32 OutIndex; +} CSzBindPair; + +typedef struct +{ + CSzCoderInfo *Coders; + CSzBindPair *BindPairs; + UInt32 *PackStreams; + UInt64 *UnpackSizes; + UInt32 NumCoders; + UInt32 NumBindPairs; + UInt32 NumPackStreams; + int UnpackCRCDefined; + UInt32 UnpackCRC; + + UInt32 NumUnpackStreams; +} CSzFolder; + +void SzFolder_Init(CSzFolder *p); +UInt64 SzFolder_GetUnpackSize(CSzFolder *p); +int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex); +UInt32 SzFolder_GetNumOutStreams(CSzFolder *p); +UInt64 SzFolder_GetUnpackSize(CSzFolder *p); + +SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes, + ILookInStream *stream, UInt64 startPos, + Byte *outBuffer, size_t outSize, ISzAlloc *allocMain); + +typedef struct +{ + UInt32 Low; + UInt32 High; +} CNtfsFileTime; + +typedef struct +{ + CNtfsFileTime MTime; + UInt64 Size; + UInt32 Crc; + UInt32 Attrib; + Byte HasStream; + Byte IsDir; + Byte IsAnti; + Byte CrcDefined; + Byte MTimeDefined; + Byte AttribDefined; +} CSzFileItem; + +void SzFile_Init(CSzFileItem *p); + +typedef struct +{ + UInt64 *PackSizes; + Byte *PackCRCsDefined; + UInt32 *PackCRCs; + CSzFolder *Folders; + CSzFileItem *Files; + UInt32 NumPackStreams; + UInt32 NumFolders; + UInt32 NumFiles; +} CSzAr; + +void SzAr_Init(CSzAr *p); +void SzAr_Free(CSzAr *p, ISzAlloc *alloc); + + +/* + SzExtract 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. +*/ + +typedef struct +{ + CSzAr db; + + UInt64 startPosAfterHeader; + UInt64 dataPos; + + UInt32 *FolderStartPackStreamIndex; + UInt64 *PackStreamStartPositions; + UInt32 *FolderStartFileIndex; + UInt32 *FileIndexToFolderIndexMap; + + size_t *FileNameOffsets; /* in 2-byte steps */ + CBuf FileNames; /* UTF-16-LE */ +} CSzArEx; + +void SzArEx_Init(CSzArEx *p); +void SzArEx_Free(CSzArEx *p, ISzAlloc *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); + +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 */ + ISzAlloc *allocMain, + ISzAlloc *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, ISzAlloc *allocMain, ISzAlloc *allocTemp); + +EXTERN_C_END + +#endif diff --git a/C/7zAlloc.c b/C/7zAlloc.c new file mode 100755 index 0000000..8874496 --- /dev/null +++ b/C/7zAlloc.c @@ -0,0 +1,76 @@ +/* 7zAlloc.c -- Allocation functions +2010-10-29 : Igor Pavlov : Public domain */ + +#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(void *p, size_t size) +{ + p = p; + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); + g_allocCount++; + #endif + return malloc(size); +} + +void SzFree(void *p, void *address) +{ + p = p; + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + { + g_allocCount--; + fprintf(stderr, "\nFree; count = %10d", g_allocCount); + } + #endif + free(address); +} + +void *SzAllocTemp(void *p, size_t size) +{ + p = p; + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); + g_allocCountTemp++; + #ifdef _WIN32 + return HeapAlloc(GetProcessHeap(), 0, size); + #endif + #endif + return malloc(size); +} + +void SzFreeTemp(void *p, void *address) +{ + p = 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/C/7zAlloc.h b/C/7zAlloc.h new file mode 100755 index 0000000..860f116 --- /dev/null +++ b/C/7zAlloc.h @@ -0,0 +1,15 @@ +/* 7zAlloc.h -- Allocation functions +2010-10-29 : Igor Pavlov : Public domain */ + +#ifndef __7Z_ALLOC_H +#define __7Z_ALLOC_H + +#include + +void *SzAlloc(void *p, size_t size); +void SzFree(void *p, void *address); + +void *SzAllocTemp(void *p, size_t size); +void SzFreeTemp(void *p, void *address); + +#endif diff --git a/C/7zBuf.c b/C/7zBuf.c new file mode 100755 index 0000000..a35fa2f --- /dev/null +++ b/C/7zBuf.c @@ -0,0 +1,36 @@ +/* 7zBuf.c -- Byte Buffer +2008-03-28 +Igor Pavlov +Public domain */ + +#include "7zBuf.h" + +void Buf_Init(CBuf *p) +{ + p->data = 0; + p->size = 0; +} + +int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc) +{ + p->size = 0; + if (size == 0) + { + p->data = 0; + return 1; + } + p->data = (Byte *)alloc->Alloc(alloc, size); + if (p->data != 0) + { + p->size = size; + return 1; + } + return 0; +} + +void Buf_Free(CBuf *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->data); + p->data = 0; + p->size = 0; +} diff --git a/C/7zBuf.h b/C/7zBuf.h new file mode 100755 index 0000000..88ff0c2 --- /dev/null +++ b/C/7zBuf.h @@ -0,0 +1,39 @@ +/* 7zBuf.h -- Byte Buffer +2009-02-07 : Igor Pavlov : Public domain */ + +#ifndef __7Z_BUF_H +#define __7Z_BUF_H + +#include "Types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + Byte *data; + size_t size; +} CBuf; + +void Buf_Init(CBuf *p); +int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc); +void Buf_Free(CBuf *p, ISzAlloc *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, ISzAlloc *alloc); +void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/C/7zBuf2.c b/C/7zBuf2.c new file mode 100755 index 0000000..1c8b931 --- /dev/null +++ b/C/7zBuf2.c @@ -0,0 +1,45 @@ +/* 7zBuf2.c -- Byte Buffer +2008-10-04 : Igor Pavlov : Public domain */ + +#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, ISzAlloc *alloc) +{ + if (size > p->size - p->pos) + { + size_t newSize = p->pos + size; + Byte *data; + newSize += newSize / 4; + data = (Byte *)alloc->Alloc(alloc, newSize); + if (data == 0) + return 0; + p->size = newSize; + memcpy(data, p->data, p->pos); + alloc->Free(alloc, p->data); + p->data = data; + } + memcpy(p->data + p->pos, buf, size); + p->pos += size; + return 1; +} + +void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->data); + p->data = 0; + p->size = 0; + p->pos = 0; +} diff --git a/C/7zCrc.c b/C/7zCrc.c new file mode 100755 index 0000000..5801dab --- /dev/null +++ b/C/7zCrc.c @@ -0,0 +1,74 @@ +/* 7zCrc.c -- CRC32 calculation +2009-11-23 : Igor Pavlov : Public domain */ + +#include "7zCrc.h" +#include "CpuArch.h" + +#define kCrcPoly 0xEDB88320 + +#ifdef MY_CPU_LE +#define CRC_NUM_TABLES 8 +#else +#define CRC_NUM_TABLES 1 +#endif + +typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table); + +static CRC_FUNC g_CrcUpdate; +UInt32 g_CrcTable[256 * CRC_NUM_TABLES]; + +#if CRC_NUM_TABLES == 1 + +#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +static UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + return v; +} + +#else + +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 + +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; +} + +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 & ~((r & 1) - 1)); + g_CrcTable[i] = r; + } + #if CRC_NUM_TABLES == 1 + g_CrcUpdate = CrcUpdateT1; + #else + for (; i < 256 * CRC_NUM_TABLES; i++) + { + UInt32 r = g_CrcTable[i - 256]; + g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8); + } + g_CrcUpdate = CrcUpdateT4; + #ifdef MY_CPU_X86_OR_AMD64 + if (!CPU_Is_InOrder()) + g_CrcUpdate = CrcUpdateT8; + #endif + #endif +} diff --git a/C/7zCrc.h b/C/7zCrc.h new file mode 100755 index 0000000..4a1ec38 --- /dev/null +++ b/C/7zCrc.h @@ -0,0 +1,25 @@ +/* 7zCrc.h -- CRC32 calculation +2009-11-21 : Igor Pavlov : Public domain */ + +#ifndef __7Z_CRC_H +#define __7Z_CRC_H + +#include "Types.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/C/7zCrcOpt.c b/C/7zCrcOpt.c new file mode 100755 index 0000000..6205d71 --- /dev/null +++ b/C/7zCrcOpt.c @@ -0,0 +1,34 @@ +/* 7zCrcOpt.c -- CRC32 calculation : optimized version +2009-11-23 : Igor Pavlov : Public domain */ + +#include "CpuArch.h" + +#ifdef MY_CPU_LE + +#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) +{ + return CrcUpdateT4(v, data, size, table); +} + +#endif diff --git a/C/7zDec.c b/C/7zDec.c new file mode 100755 index 0000000..3386807 --- /dev/null +++ b/C/7zDec.c @@ -0,0 +1,470 @@ +/* 7zDec.c -- Decoding from 7z folder +2010-11-02 : Igor Pavlov : Public domain */ + +#include + +/* #define _7ZIP_PPMD_SUPPPORT */ + +#include "7z.h" + +#include "Bcj2.h" +#include "Bra.h" +#include "CpuArch.h" +#include "LzmaDec.h" +#include "Lzma2Dec.h" +#ifdef _7ZIP_PPMD_SUPPPORT +#include "Ppmd7.h" +#endif + +#define k_Copy 0 +#define k_LZMA2 0x21 +#define k_LZMA 0x30101 +#define k_BCJ 0x03030103 +#define k_PPC 0x03030205 +#define k_ARM 0x03030501 +#define k_ARMT 0x03030701 +#define k_SPARC 0x03030805 +#define k_BCJ2 0x0303011B + +#ifdef _7ZIP_PPMD_SUPPPORT + +#define k_PPMD 0x30401 + +typedef struct +{ + IByteIn p; + const Byte *cur; + const Byte *end; + const Byte *begin; + UInt64 processed; + Bool extra; + SRes res; + ILookInStream *inStream; +} CByteInToLook; + +static Byte ReadByte(void *pp) +{ + CByteInToLook *p = (CByteInToLook *)pp; + 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 = p->inStream->Skip(p->inStream, size); + size = (1 << 25); + p->res = p->inStream->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(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, + Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) +{ + CPpmd7 ppmd; + CByteInToLook s; + SRes res = SZ_OK; + + s.p.Read = ReadByte; + s.inStream = inStream; + s.begin = s.end = s.cur = NULL; + s.extra = False; + s.res = SZ_OK; + s.processed = 0; + + if (coder->Props.size != 5) + return SZ_ERROR_UNSUPPORTED; + + { + unsigned order = coder->Props.data[0]; + UInt32 memSize = GetUi32(coder->Props.data + 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.p; + 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.p); + 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(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, + Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) +{ + CLzmaDec state; + SRes res = SZ_OK; + + LzmaDec_Construct(&state); + RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain)); + state.dic = outBuffer; + state.dicBufSize = outSize; + LzmaDec_Init(&state); + + for (;;) + { + Byte *inBuf = NULL; + size_t lookahead = (1 << 18); + if (lookahead > inSize) + lookahead = (size_t)inSize; + res = inStream->Look((void *)inStream, (const void **)&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 (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos)) + { + if (state.dicBufSize != outSize || lookahead != 0 || + (status != LZMA_STATUS_FINISHED_WITH_MARK && + status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)) + res = SZ_ERROR_DATA; + break; + } + res = inStream->Skip((void *)inStream, inProcessed); + if (res != SZ_OK) + break; + } + } + + LzmaDec_FreeProbs(&state, allocMain); + return res; +} + +static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, + Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) +{ + CLzma2Dec state; + SRes res = SZ_OK; + + Lzma2Dec_Construct(&state); + if (coder->Props.size != 1) + return SZ_ERROR_DATA; + RINOK(Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain)); + state.decoder.dic = outBuffer; + state.decoder.dicBufSize = outSize; + Lzma2Dec_Init(&state); + + for (;;) + { + Byte *inBuf = NULL; + size_t lookahead = (1 << 18); + if (lookahead > inSize) + lookahead = (size_t)inSize; + res = inStream->Look((void *)inStream, (const void **)&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 (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos)) + { + if (state.decoder.dicBufSize != outSize || lookahead != 0 || + (status != LZMA_STATUS_FINISHED_WITH_MARK)) + res = SZ_ERROR_DATA; + break; + } + res = inStream->Skip((void *)inStream, inProcessed); + if (res != SZ_OK) + break; + } + } + + Lzma2Dec_FreeProbs(&state, allocMain); + return res; +} + +static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) +{ + while (inSize > 0) + { + void *inBuf; + size_t curSize = (1 << 18); + if (curSize > inSize) + curSize = (size_t)inSize; + RINOK(inStream->Look((void *)inStream, (const void **)&inBuf, &curSize)); + if (curSize == 0) + return SZ_ERROR_INPUT_EOF; + memcpy(outBuffer, inBuf, curSize); + outBuffer += curSize; + inSize -= curSize; + RINOK(inStream->Skip((void *)inStream, curSize)); + } + return SZ_OK; +} + +static Bool IS_MAIN_METHOD(UInt32 m) +{ + switch(m) + { + case k_Copy: + case k_LZMA: + case k_LZMA2: + #ifdef _7ZIP_PPMD_SUPPPORT + case k_PPMD: + #endif + return True; + } + return False; +} + +static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c) +{ + return + c->NumInStreams == 1 && + c->NumOutStreams == 1 && + c->MethodID <= (UInt32)0xFFFFFFFF && + IS_MAIN_METHOD((UInt32)c->MethodID); +} + +#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1) + +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->NumBindPairs != 0) + return SZ_ERROR_UNSUPPORTED; + return SZ_OK; + } + if (f->NumCoders == 2) + { + CSzCoderInfo *c = &f->Coders[1]; + if (c->MethodID > (UInt32)0xFFFFFFFF || + c->NumInStreams != 1 || + c->NumOutStreams != 1 || + f->NumPackStreams != 1 || + f->PackStreams[0] != 0 || + f->NumBindPairs != 1 || + f->BindPairs[0].InIndex != 1 || + f->BindPairs[0].OutIndex != 0) + return SZ_ERROR_UNSUPPORTED; + switch ((UInt32)c->MethodID) + { + case k_BCJ: + case k_ARM: + break; + default: + return SZ_ERROR_UNSUPPORTED; + } + return SZ_OK; + } + 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->NumBindPairs != 3 || + f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 || + f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 || + f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2) + return SZ_ERROR_UNSUPPORTED; + return SZ_OK; + } + return SZ_ERROR_UNSUPPORTED; +} + +static UInt64 GetSum(const UInt64 *values, UInt32 index) +{ + UInt64 sum = 0; + UInt32 i; + for (i = 0; i < index; i++) + sum += values[i]; + return sum; +} + +#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break; + +static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes, + ILookInStream *inStream, UInt64 startPos, + Byte *outBuffer, SizeT outSize, ISzAlloc *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++) + { + 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 = folder->UnpackSizes[ci]; + si = indices[ci]; + if (ci < 2) + { + Byte *temp; + outSizeCur = (SizeT)unpackSize; + if (outSizeCur != unpackSize) + return SZ_ERROR_MEM; + temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur); + if (temp == 0 && 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 = GetSum(packSizes, si); + inSize = packSizes[si]; + 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(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); + } + else if (coder->MethodID == k_LZMA2) + { + RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); + } + else + { + #ifdef _7ZIP_PPMD_SUPPPORT + RINOK(SzDecodePpmd(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); + #else + return SZ_ERROR_UNSUPPORTED; + #endif + } + } + else if (coder->MethodID == k_BCJ2) + { + UInt64 offset = GetSum(packSizes, 1); + UInt64 s3Size = packSizes[1]; + SRes res; + if (ci != 3) + return SZ_ERROR_UNSUPPORTED; + RINOK(LookInStream_SeekTo(inStream, startPos + offset)); + tempSizes[2] = (SizeT)s3Size; + if (tempSizes[2] != s3Size) + return SZ_ERROR_MEM; + tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]); + if (tempBuf[2] == 0 && tempSizes[2] != 0) + return SZ_ERROR_MEM; + res = SzDecodeCopy(s3Size, inStream, tempBuf[2]); + RINOK(res) + + res = Bcj2_Decode( + tempBuf3, tempSize3, + tempBuf[0], tempSizes[0], + tempBuf[1], tempSizes[1], + tempBuf[2], tempSizes[2], + outBuffer, outSize); + RINOK(res) + } + else + { + if (ci != 1) + 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(ARM) + default: + return SZ_ERROR_UNSUPPORTED; + } + } + } + return SZ_OK; +} + +SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes, + ILookInStream *inStream, UInt64 startPos, + Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) +{ + Byte *tempBuf[3] = { 0, 0, 0}; + int i; + SRes res = SzFolder_Decode2(folder, packSizes, inStream, startPos, + outBuffer, (SizeT)outSize, allocMain, tempBuf); + for (i = 0; i < 3; i++) + IAlloc_Free(allocMain, tempBuf[i]); + return res; +} diff --git a/C/7zFile.c b/C/7zFile.c new file mode 100755 index 0000000..6d82c79 --- /dev/null +++ b/C/7zFile.c @@ -0,0 +1,284 @@ +/* 7zFile.c -- File IO +2009-11-24 : Igor Pavlov : Public domain */ + +#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(void *pp, void *buf, size_t *size) +{ + CFileSeqInStream *p = (CFileSeqInStream *)pp; + return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ; +} + +void FileSeqInStream_CreateVTable(CFileSeqInStream *p) +{ + p->s.Read = FileSeqInStream_Read; +} + + +/* ---------- FileInStream ---------- */ + +static SRes FileInStream_Read(void *pp, void *buf, size_t *size) +{ + CFileInStream *p = (CFileInStream *)pp; + return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ; +} + +static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin) +{ + CFileInStream *p = (CFileInStream *)pp; + return File_Seek(&p->file, pos, origin); +} + +void FileInStream_CreateVTable(CFileInStream *p) +{ + p->s.Read = FileInStream_Read; + p->s.Seek = FileInStream_Seek; +} + + +/* ---------- FileOutStream ---------- */ + +static size_t FileOutStream_Write(void *pp, const void *data, size_t size) +{ + CFileOutStream *p = (CFileOutStream *)pp; + File_Write(&p->file, data, &size); + return size; +} + +void FileOutStream_CreateVTable(CFileOutStream *p) +{ + p->s.Write = FileOutStream_Write; +} diff --git a/C/7zFile.h b/C/7zFile.h new file mode 100755 index 0000000..5d85787 --- /dev/null +++ b/C/7zFile.h @@ -0,0 +1,83 @@ +/* 7zFile.h -- File IO +2009-11-24 : 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 "Types.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 s; + CSzFile file; +} CFileSeqInStream; + +void FileSeqInStream_CreateVTable(CFileSeqInStream *p); + + +typedef struct +{ + ISeekInStream s; + CSzFile file; +} CFileInStream; + +void FileInStream_CreateVTable(CFileInStream *p); + + +typedef struct +{ + ISeqOutStream s; + CSzFile file; +} CFileOutStream; + +void FileOutStream_CreateVTable(CFileOutStream *p); + +EXTERN_C_END + +#endif diff --git a/C/7zIn.c b/C/7zIn.c new file mode 100755 index 0000000..f1a4492 --- /dev/null +++ b/C/7zIn.c @@ -0,0 +1,1402 @@ +/* 7zIn.c -- 7z Input functions +2010-10-29 : Igor Pavlov : Public domain */ + +#include + +#include "7z.h" +#include "7zCrc.h" +#include "CpuArch.h" + +Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; + +#define RINOM(x) { if ((x) == 0) return SZ_ERROR_MEM; } + +#define NUM_FOLDER_CODERS_MAX 32 +#define NUM_CODER_STREAMS_MAX 32 + +void SzCoderInfo_Init(CSzCoderInfo *p) +{ + Buf_Init(&p->Props); +} + +void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc) +{ + Buf_Free(&p->Props, alloc); + SzCoderInfo_Init(p); +} + +void SzFolder_Init(CSzFolder *p) +{ + p->Coders = 0; + p->BindPairs = 0; + p->PackStreams = 0; + p->UnpackSizes = 0; + p->NumCoders = 0; + p->NumBindPairs = 0; + p->NumPackStreams = 0; + p->UnpackCRCDefined = 0; + p->UnpackCRC = 0; + p->NumUnpackStreams = 0; +} + +void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc) +{ + UInt32 i; + if (p->Coders) + for (i = 0; i < p->NumCoders; i++) + SzCoderInfo_Free(&p->Coders[i], alloc); + IAlloc_Free(alloc, p->Coders); + IAlloc_Free(alloc, p->BindPairs); + IAlloc_Free(alloc, p->PackStreams); + IAlloc_Free(alloc, p->UnpackSizes); + SzFolder_Init(p); +} + +UInt32 SzFolder_GetNumOutStreams(CSzFolder *p) +{ + UInt32 result = 0; + UInt32 i; + for (i = 0; i < p->NumCoders; i++) + result += p->Coders[i].NumOutStreams; + return result; +} + +int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex) +{ + UInt32 i; + for (i = 0; i < p->NumBindPairs; i++) + if (p->BindPairs[i].InIndex == inStreamIndex) + return i; + return -1; +} + + +int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex) +{ + UInt32 i; + for (i = 0; i < p->NumBindPairs; i++) + if (p->BindPairs[i].OutIndex == outStreamIndex) + return i; + return -1; +} + +UInt64 SzFolder_GetUnpackSize(CSzFolder *p) +{ + int i = (int)SzFolder_GetNumOutStreams(p); + if (i == 0) + return 0; + for (i--; i >= 0; i--) + if (SzFolder_FindBindPairForOutStream(p, i) < 0) + return p->UnpackSizes[i]; + /* throw 1; */ + return 0; +} + +void SzFile_Init(CSzFileItem *p) +{ + p->HasStream = 1; + p->IsDir = 0; + p->IsAnti = 0; + p->CrcDefined = 0; + p->MTimeDefined = 0; +} + +void SzAr_Init(CSzAr *p) +{ + p->PackSizes = 0; + p->PackCRCsDefined = 0; + p->PackCRCs = 0; + p->Folders = 0; + p->Files = 0; + p->NumPackStreams = 0; + p->NumFolders = 0; + p->NumFiles = 0; +} + +void SzAr_Free(CSzAr *p, ISzAlloc *alloc) +{ + UInt32 i; + if (p->Folders) + for (i = 0; i < p->NumFolders; i++) + SzFolder_Free(&p->Folders[i], alloc); + + IAlloc_Free(alloc, p->PackSizes); + IAlloc_Free(alloc, p->PackCRCsDefined); + IAlloc_Free(alloc, p->PackCRCs); + IAlloc_Free(alloc, p->Folders); + IAlloc_Free(alloc, p->Files); + SzAr_Init(p); +} + + +void SzArEx_Init(CSzArEx *p) +{ + SzAr_Init(&p->db); + p->FolderStartPackStreamIndex = 0; + p->PackStreamStartPositions = 0; + p->FolderStartFileIndex = 0; + p->FileIndexToFolderIndexMap = 0; + p->FileNameOffsets = 0; + Buf_Init(&p->FileNames); +} + +void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc) +{ + IAlloc_Free(alloc, p->FolderStartPackStreamIndex); + IAlloc_Free(alloc, p->PackStreamStartPositions); + IAlloc_Free(alloc, p->FolderStartFileIndex); + IAlloc_Free(alloc, p->FileIndexToFolderIndexMap); + + IAlloc_Free(alloc, p->FileNameOffsets); + Buf_Free(&p->FileNames, alloc); + + SzAr_Free(&p->db, alloc); + SzArEx_Init(p); +} + +/* +UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const +{ + return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; +} + +UInt64 GetFilePackSize(int fileIndex) const +{ + int folderIndex = FileIndexToFolderIndexMap[fileIndex]; + if (folderIndex >= 0) + { + const CSzFolder &folderInfo = Folders[folderIndex]; + if (FolderStartFileIndex[folderIndex] == fileIndex) + return GetFolderFullPackSize(folderIndex); + } + return 0; +} +*/ + +#define MY_ALLOC(T, p, size, alloc) { if ((size) == 0) p = 0; else \ + if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == 0) return SZ_ERROR_MEM; } + +static SRes SzArEx_Fill(CSzArEx *p, ISzAlloc *alloc) +{ + UInt32 startPos = 0; + UInt64 startPosSize = 0; + UInt32 i; + UInt32 folderIndex = 0; + UInt32 indexInFolder = 0; + MY_ALLOC(UInt32, p->FolderStartPackStreamIndex, p->db.NumFolders, alloc); + for (i = 0; i < p->db.NumFolders; i++) + { + p->FolderStartPackStreamIndex[i] = startPos; + startPos += p->db.Folders[i].NumPackStreams; + } + + MY_ALLOC(UInt64, p->PackStreamStartPositions, p->db.NumPackStreams, alloc); + + for (i = 0; i < p->db.NumPackStreams; i++) + { + p->PackStreamStartPositions[i] = startPosSize; + startPosSize += p->db.PackSizes[i]; + } + + MY_ALLOC(UInt32, p->FolderStartFileIndex, p->db.NumFolders, alloc); + MY_ALLOC(UInt32, p->FileIndexToFolderIndexMap, p->db.NumFiles, alloc); + + for (i = 0; i < p->db.NumFiles; i++) + { + CSzFileItem *file = p->db.Files + i; + int emptyStream = !file->HasStream; + if (emptyStream && indexInFolder == 0) + { + p->FileIndexToFolderIndexMap[i] = (UInt32)-1; + continue; + } + if (indexInFolder == 0) + { + /* + v3.13 incorrectly worked with empty folders + v4.07: Loop for skipping empty folders + */ + for (;;) + { + if (folderIndex >= p->db.NumFolders) + return SZ_ERROR_ARCHIVE; + p->FolderStartFileIndex[folderIndex] = i; + if (p->db.Folders[folderIndex].NumUnpackStreams != 0) + break; + folderIndex++; + } + } + p->FileIndexToFolderIndexMap[i] = folderIndex; + if (emptyStream) + continue; + indexInFolder++; + if (indexInFolder >= p->db.Folders[folderIndex].NumUnpackStreams) + { + folderIndex++; + indexInFolder = 0; + } + } + return SZ_OK; +} + + +UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder) +{ + return p->dataPos + + p->PackStreamStartPositions[p->FolderStartPackStreamIndex[folderIndex] + indexInFolder]; +} + +int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize) +{ + UInt32 packStreamIndex = p->FolderStartPackStreamIndex[folderIndex]; + CSzFolder *folder = p->db.Folders + folderIndex; + UInt64 size = 0; + UInt32 i; + for (i = 0; i < folder->NumPackStreams; i++) + { + UInt64 t = size + p->db.PackSizes[packStreamIndex + i]; + if (t < size) /* check it */ + return SZ_ERROR_FAIL; + size = t; + } + *resSize = size; + return SZ_OK; +} + + +/* +SRes SzReadTime(const CObjectVector &dataVector, + CObjectVector &files, UInt64 type) +{ + CBoolVector boolVector; + RINOK(ReadBoolVector2(files.Size(), boolVector)) + + CStreamSwitch streamSwitch; + RINOK(streamSwitch.Set(this, &dataVector)); + + for (int i = 0; i < files.Size(); i++) + { + CSzFileItem &file = files[i]; + CArchiveFileTime fileTime; + bool defined = boolVector[i]; + if (defined) + { + UInt32 low, high; + RINOK(SzReadUInt32(low)); + RINOK(SzReadUInt32(high)); + fileTime.dwLowDateTime = low; + fileTime.dwHighDateTime = high; + } + switch(type) + { + case k7zIdCTime: file.IsCTimeDefined = defined; if (defined) file.CTime = fileTime; break; + case k7zIdATime: file.IsATimeDefined = defined; if (defined) file.ATime = fileTime; break; + case k7zIdMTime: file.IsMTimeDefined = defined; if (defined) file.MTime = fileTime; break; + } + } + return SZ_OK; +} +*/ + +static int TestSignatureCandidate(Byte *testBytes) +{ + size_t i; + for (i = 0; i < k7zSignatureSize; i++) + if (testBytes[i] != k7zSignature[i]) + return 0; + return 1; +} + +typedef struct _CSzState +{ + Byte *Data; + size_t Size; +}CSzData; + +static SRes SzReadByte(CSzData *sd, Byte *b) +{ + if (sd->Size == 0) + return SZ_ERROR_ARCHIVE; + sd->Size--; + *b = *sd->Data++; + return SZ_OK; +} + +static SRes SzReadBytes(CSzData *sd, Byte *data, size_t size) +{ + size_t i; + for (i = 0; i < size; i++) + { + RINOK(SzReadByte(sd, data + i)); + } + return SZ_OK; +} + +static SRes SzReadUInt32(CSzData *sd, UInt32 *value) +{ + int i; + *value = 0; + for (i = 0; i < 4; i++) + { + Byte b; + RINOK(SzReadByte(sd, &b)); + *value |= ((UInt32)(b) << (8 * i)); + } + return SZ_OK; +} + +static SRes SzReadNumber(CSzData *sd, UInt64 *value) +{ + Byte firstByte; + Byte mask = 0x80; + int i; + RINOK(SzReadByte(sd, &firstByte)); + *value = 0; + for (i = 0; i < 8; i++) + { + Byte b; + if ((firstByte & mask) == 0) + { + UInt64 highPart = firstByte & (mask - 1); + *value += (highPart << (8 * i)); + return SZ_OK; + } + RINOK(SzReadByte(sd, &b)); + *value |= ((UInt64)b << (8 * i)); + mask >>= 1; + } + return SZ_OK; +} + +static SRes SzReadNumber32(CSzData *sd, UInt32 *value) +{ + UInt64 value64; + RINOK(SzReadNumber(sd, &value64)); + if (value64 >= 0x80000000) + return SZ_ERROR_UNSUPPORTED; + if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2))) + return SZ_ERROR_UNSUPPORTED; + *value = (UInt32)value64; + return SZ_OK; +} + +static SRes SzReadID(CSzData *sd, UInt64 *value) +{ + return SzReadNumber(sd, value); +} + +static SRes SzSkeepDataSize(CSzData *sd, UInt64 size) +{ + if (size > sd->Size) + return SZ_ERROR_ARCHIVE; + sd->Size -= (size_t)size; + sd->Data += (size_t)size; + return SZ_OK; +} + +static SRes SzSkeepData(CSzData *sd) +{ + UInt64 size; + RINOK(SzReadNumber(sd, &size)); + return SzSkeepDataSize(sd, size); +} + +static SRes SzReadArchiveProperties(CSzData *sd) +{ + for (;;) + { + UInt64 type; + RINOK(SzReadID(sd, &type)); + if (type == k7zIdEnd) + break; + SzSkeepData(sd); + } + return SZ_OK; +} + +static SRes SzWaitAttribute(CSzData *sd, UInt64 attribute) +{ + for (;;) + { + UInt64 type; + RINOK(SzReadID(sd, &type)); + if (type == attribute) + return SZ_OK; + if (type == k7zIdEnd) + return SZ_ERROR_ARCHIVE; + RINOK(SzSkeepData(sd)); + } +} + +static SRes SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc) +{ + Byte b = 0; + Byte mask = 0; + size_t i; + MY_ALLOC(Byte, *v, numItems, alloc); + for (i = 0; i < numItems; i++) + { + if (mask == 0) + { + RINOK(SzReadByte(sd, &b)); + mask = 0x80; + } + (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0); + mask >>= 1; + } + return SZ_OK; +} + +static SRes SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc) +{ + Byte allAreDefined; + size_t i; + RINOK(SzReadByte(sd, &allAreDefined)); + if (allAreDefined == 0) + return SzReadBoolVector(sd, numItems, v, alloc); + MY_ALLOC(Byte, *v, numItems, alloc); + for (i = 0; i < numItems; i++) + (*v)[i] = 1; + return SZ_OK; +} + +static SRes SzReadHashDigests( + CSzData *sd, + size_t numItems, + Byte **digestsDefined, + UInt32 **digests, + ISzAlloc *alloc) +{ + size_t i; + RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, alloc)); + MY_ALLOC(UInt32, *digests, numItems, alloc); + for (i = 0; i < numItems; i++) + if ((*digestsDefined)[i]) + { + RINOK(SzReadUInt32(sd, (*digests) + i)); + } + return SZ_OK; +} + +static SRes SzReadPackInfo( + CSzData *sd, + UInt64 *dataOffset, + UInt32 *numPackStreams, + UInt64 **packSizes, + Byte **packCRCsDefined, + UInt32 **packCRCs, + ISzAlloc *alloc) +{ + UInt32 i; + RINOK(SzReadNumber(sd, dataOffset)); + RINOK(SzReadNumber32(sd, numPackStreams)); + + RINOK(SzWaitAttribute(sd, k7zIdSize)); + + MY_ALLOC(UInt64, *packSizes, (size_t)*numPackStreams, alloc); + + for (i = 0; i < *numPackStreams; i++) + { + RINOK(SzReadNumber(sd, (*packSizes) + i)); + } + + for (;;) + { + UInt64 type; + RINOK(SzReadID(sd, &type)); + if (type == k7zIdEnd) + break; + if (type == k7zIdCRC) + { + RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, alloc)); + continue; + } + RINOK(SzSkeepData(sd)); + } + if (*packCRCsDefined == 0) + { + MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, alloc); + MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, alloc); + for (i = 0; i < *numPackStreams; i++) + { + (*packCRCsDefined)[i] = 0; + (*packCRCs)[i] = 0; + } + } + return SZ_OK; +} + +static SRes SzReadSwitch(CSzData *sd) +{ + Byte external; + RINOK(SzReadByte(sd, &external)); + return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED; +} + +static SRes SzGetNextFolderItem(CSzData *sd, CSzFolder *folder, ISzAlloc *alloc) +{ + UInt32 numCoders, numBindPairs, numPackStreams, i; + UInt32 numInStreams = 0, numOutStreams = 0; + + RINOK(SzReadNumber32(sd, &numCoders)); + if (numCoders > NUM_FOLDER_CODERS_MAX) + return SZ_ERROR_UNSUPPORTED; + folder->NumCoders = numCoders; + + MY_ALLOC(CSzCoderInfo, folder->Coders, (size_t)numCoders, alloc); + + for (i = 0; i < numCoders; i++) + SzCoderInfo_Init(folder->Coders + i); + + for (i = 0; i < numCoders; i++) + { + Byte mainByte; + CSzCoderInfo *coder = folder->Coders + i; + { + unsigned idSize, j; + Byte longID[15]; + RINOK(SzReadByte(sd, &mainByte)); + idSize = (unsigned)(mainByte & 0xF); + RINOK(SzReadBytes(sd, longID, idSize)); + if (idSize > sizeof(coder->MethodID)) + return SZ_ERROR_UNSUPPORTED; + coder->MethodID = 0; + for (j = 0; j < idSize; j++) + coder->MethodID |= (UInt64)longID[idSize - 1 - j] << (8 * j); + + if ((mainByte & 0x10) != 0) + { + RINOK(SzReadNumber32(sd, &coder->NumInStreams)); + RINOK(SzReadNumber32(sd, &coder->NumOutStreams)); + if (coder->NumInStreams > NUM_CODER_STREAMS_MAX || + coder->NumOutStreams > NUM_CODER_STREAMS_MAX) + return SZ_ERROR_UNSUPPORTED; + } + else + { + coder->NumInStreams = 1; + coder->NumOutStreams = 1; + } + if ((mainByte & 0x20) != 0) + { + UInt64 propertiesSize = 0; + RINOK(SzReadNumber(sd, &propertiesSize)); + if (!Buf_Create(&coder->Props, (size_t)propertiesSize, alloc)) + return SZ_ERROR_MEM; + RINOK(SzReadBytes(sd, coder->Props.data, (size_t)propertiesSize)); + } + } + while ((mainByte & 0x80) != 0) + { + RINOK(SzReadByte(sd, &mainByte)); + RINOK(SzSkeepDataSize(sd, (mainByte & 0xF))); + if ((mainByte & 0x10) != 0) + { + UInt32 n; + RINOK(SzReadNumber32(sd, &n)); + RINOK(SzReadNumber32(sd, &n)); + } + if ((mainByte & 0x20) != 0) + { + UInt64 propertiesSize = 0; + RINOK(SzReadNumber(sd, &propertiesSize)); + RINOK(SzSkeepDataSize(sd, propertiesSize)); + } + } + numInStreams += coder->NumInStreams; + numOutStreams += coder->NumOutStreams; + } + + if (numOutStreams == 0) + return SZ_ERROR_UNSUPPORTED; + + folder->NumBindPairs = numBindPairs = numOutStreams - 1; + MY_ALLOC(CSzBindPair, folder->BindPairs, (size_t)numBindPairs, alloc); + + for (i = 0; i < numBindPairs; i++) + { + CSzBindPair *bp = folder->BindPairs + i; + RINOK(SzReadNumber32(sd, &bp->InIndex)); + RINOK(SzReadNumber32(sd, &bp->OutIndex)); + } + + if (numInStreams < numBindPairs) + return SZ_ERROR_UNSUPPORTED; + + folder->NumPackStreams = numPackStreams = numInStreams - numBindPairs; + MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackStreams, alloc); + + if (numPackStreams == 1) + { + for (i = 0; i < numInStreams ; i++) + if (SzFolder_FindBindPairForInStream(folder, i) < 0) + break; + if (i == numInStreams) + return SZ_ERROR_UNSUPPORTED; + folder->PackStreams[0] = i; + } + else + for (i = 0; i < numPackStreams; i++) + { + RINOK(SzReadNumber32(sd, folder->PackStreams + i)); + } + return SZ_OK; +} + +static SRes SzReadUnpackInfo( + CSzData *sd, + UInt32 *numFolders, + CSzFolder **folders, /* for alloc */ + ISzAlloc *alloc, + ISzAlloc *allocTemp) +{ + UInt32 i; + RINOK(SzWaitAttribute(sd, k7zIdFolder)); + RINOK(SzReadNumber32(sd, numFolders)); + { + RINOK(SzReadSwitch(sd)); + + MY_ALLOC(CSzFolder, *folders, (size_t)*numFolders, alloc); + + for (i = 0; i < *numFolders; i++) + SzFolder_Init((*folders) + i); + + for (i = 0; i < *numFolders; i++) + { + RINOK(SzGetNextFolderItem(sd, (*folders) + i, alloc)); + } + } + + RINOK(SzWaitAttribute(sd, k7zIdCodersUnpackSize)); + + for (i = 0; i < *numFolders; i++) + { + UInt32 j; + CSzFolder *folder = (*folders) + i; + UInt32 numOutStreams = SzFolder_GetNumOutStreams(folder); + + MY_ALLOC(UInt64, folder->UnpackSizes, (size_t)numOutStreams, alloc); + + for (j = 0; j < numOutStreams; j++) + { + RINOK(SzReadNumber(sd, folder->UnpackSizes + j)); + } + } + + for (;;) + { + UInt64 type; + RINOK(SzReadID(sd, &type)); + if (type == k7zIdEnd) + return SZ_OK; + if (type == k7zIdCRC) + { + SRes res; + Byte *crcsDefined = 0; + UInt32 *crcs = 0; + res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp); + if (res == SZ_OK) + { + for (i = 0; i < *numFolders; i++) + { + CSzFolder *folder = (*folders) + i; + folder->UnpackCRCDefined = crcsDefined[i]; + folder->UnpackCRC = crcs[i]; + } + } + IAlloc_Free(allocTemp, crcs); + IAlloc_Free(allocTemp, crcsDefined); + RINOK(res); + continue; + } + RINOK(SzSkeepData(sd)); + } +} + +static SRes SzReadSubStreamsInfo( + CSzData *sd, + UInt32 numFolders, + CSzFolder *folders, + UInt32 *numUnpackStreams, + UInt64 **unpackSizes, + Byte **digestsDefined, + UInt32 **digests, + ISzAlloc *allocTemp) +{ + UInt64 type = 0; + UInt32 i; + UInt32 si = 0; + UInt32 numDigests = 0; + + for (i = 0; i < numFolders; i++) + folders[i].NumUnpackStreams = 1; + *numUnpackStreams = numFolders; + + for (;;) + { + RINOK(SzReadID(sd, &type)); + if (type == k7zIdNumUnpackStream) + { + *numUnpackStreams = 0; + for (i = 0; i < numFolders; i++) + { + UInt32 numStreams; + RINOK(SzReadNumber32(sd, &numStreams)); + folders[i].NumUnpackStreams = numStreams; + *numUnpackStreams += numStreams; + } + continue; + } + if (type == k7zIdCRC || type == k7zIdSize) + break; + if (type == k7zIdEnd) + break; + RINOK(SzSkeepData(sd)); + } + + if (*numUnpackStreams == 0) + { + *unpackSizes = 0; + *digestsDefined = 0; + *digests = 0; + } + else + { + *unpackSizes = (UInt64 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt64)); + RINOM(*unpackSizes); + *digestsDefined = (Byte *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(Byte)); + RINOM(*digestsDefined); + *digests = (UInt32 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt32)); + RINOM(*digests); + } + + for (i = 0; i < numFolders; i++) + { + /* + v3.13 incorrectly worked with empty folders + v4.07: we check that folder is empty + */ + UInt64 sum = 0; + UInt32 j; + UInt32 numSubstreams = folders[i].NumUnpackStreams; + if (numSubstreams == 0) + continue; + if (type == k7zIdSize) + for (j = 1; j < numSubstreams; j++) + { + UInt64 size; + RINOK(SzReadNumber(sd, &size)); + (*unpackSizes)[si++] = size; + sum += size; + } + (*unpackSizes)[si++] = SzFolder_GetUnpackSize(folders + i) - sum; + } + if (type == k7zIdSize) + { + RINOK(SzReadID(sd, &type)); + } + + for (i = 0; i < *numUnpackStreams; i++) + { + (*digestsDefined)[i] = 0; + (*digests)[i] = 0; + } + + + for (i = 0; i < numFolders; i++) + { + UInt32 numSubstreams = folders[i].NumUnpackStreams; + if (numSubstreams != 1 || !folders[i].UnpackCRCDefined) + numDigests += numSubstreams; + } + + + si = 0; + for (;;) + { + if (type == k7zIdCRC) + { + int digestIndex = 0; + Byte *digestsDefined2 = 0; + UInt32 *digests2 = 0; + SRes res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp); + if (res == SZ_OK) + { + for (i = 0; i < numFolders; i++) + { + CSzFolder *folder = folders + i; + UInt32 numSubstreams = folder->NumUnpackStreams; + if (numSubstreams == 1 && folder->UnpackCRCDefined) + { + (*digestsDefined)[si] = 1; + (*digests)[si] = folder->UnpackCRC; + si++; + } + else + { + UInt32 j; + for (j = 0; j < numSubstreams; j++, digestIndex++) + { + (*digestsDefined)[si] = digestsDefined2[digestIndex]; + (*digests)[si] = digests2[digestIndex]; + si++; + } + } + } + } + IAlloc_Free(allocTemp, digestsDefined2); + IAlloc_Free(allocTemp, digests2); + RINOK(res); + } + else if (type == k7zIdEnd) + return SZ_OK; + else + { + RINOK(SzSkeepData(sd)); + } + RINOK(SzReadID(sd, &type)); + } +} + + +static SRes SzReadStreamsInfo( + CSzData *sd, + UInt64 *dataOffset, + CSzAr *p, + UInt32 *numUnpackStreams, + UInt64 **unpackSizes, /* allocTemp */ + Byte **digestsDefined, /* allocTemp */ + UInt32 **digests, /* allocTemp */ + ISzAlloc *alloc, + ISzAlloc *allocTemp) +{ + for (;;) + { + UInt64 type; + RINOK(SzReadID(sd, &type)); + if ((UInt64)(int)type != type) + return SZ_ERROR_UNSUPPORTED; + switch((int)type) + { + case k7zIdEnd: + return SZ_OK; + case k7zIdPackInfo: + { + RINOK(SzReadPackInfo(sd, dataOffset, &p->NumPackStreams, + &p->PackSizes, &p->PackCRCsDefined, &p->PackCRCs, alloc)); + break; + } + case k7zIdUnpackInfo: + { + RINOK(SzReadUnpackInfo(sd, &p->NumFolders, &p->Folders, alloc, allocTemp)); + break; + } + case k7zIdSubStreamsInfo: + { + RINOK(SzReadSubStreamsInfo(sd, p->NumFolders, p->Folders, + numUnpackStreams, unpackSizes, digestsDefined, digests, allocTemp)); + break; + } + default: + return SZ_ERROR_UNSUPPORTED; + } + } +} + +size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest) +{ + size_t len = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex]; + if (dest != 0) + { + size_t i; + const Byte *src = p->FileNames.data + (p->FileNameOffsets[fileIndex] * 2); + for (i = 0; i < len; i++) + dest[i] = GetUi16(src + i * 2); + } + return len; +} + +static SRes SzReadFileNames(const Byte *p, size_t size, UInt32 numFiles, size_t *sizes) +{ + UInt32 i; + size_t pos = 0; + for (i = 0; i < numFiles; i++) + { + sizes[i] = pos; + for (;;) + { + if (pos >= size) + return SZ_ERROR_ARCHIVE; + if (p[pos * 2] == 0 && p[pos * 2 + 1] == 0) + break; + pos++; + } + pos++; + } + sizes[i] = pos; + return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE; +} + +static SRes SzReadHeader2( + CSzArEx *p, /* allocMain */ + CSzData *sd, + UInt64 **unpackSizes, /* allocTemp */ + Byte **digestsDefined, /* allocTemp */ + UInt32 **digests, /* allocTemp */ + Byte **emptyStreamVector, /* allocTemp */ + Byte **emptyFileVector, /* allocTemp */ + Byte **lwtVector, /* allocTemp */ + ISzAlloc *allocMain, + ISzAlloc *allocTemp) +{ + UInt64 type; + UInt32 numUnpackStreams = 0; + UInt32 numFiles = 0; + CSzFileItem *files = 0; + UInt32 numEmptyStreams = 0; + UInt32 i; + + RINOK(SzReadID(sd, &type)); + + if (type == k7zIdArchiveProperties) + { + RINOK(SzReadArchiveProperties(sd)); + RINOK(SzReadID(sd, &type)); + } + + + if (type == k7zIdMainStreamsInfo) + { + RINOK(SzReadStreamsInfo(sd, + &p->dataPos, + &p->db, + &numUnpackStreams, + unpackSizes, + digestsDefined, + digests, allocMain, allocTemp)); + p->dataPos += p->startPosAfterHeader; + RINOK(SzReadID(sd, &type)); + } + + if (type == k7zIdEnd) + return SZ_OK; + if (type != k7zIdFilesInfo) + return SZ_ERROR_ARCHIVE; + + RINOK(SzReadNumber32(sd, &numFiles)); + p->db.NumFiles = numFiles; + + MY_ALLOC(CSzFileItem, files, (size_t)numFiles, allocMain); + + p->db.Files = files; + for (i = 0; i < numFiles; i++) + SzFile_Init(files + i); + + for (;;) + { + UInt64 type; + UInt64 size; + RINOK(SzReadID(sd, &type)); + if (type == k7zIdEnd) + break; + RINOK(SzReadNumber(sd, &size)); + if (size > sd->Size) + return SZ_ERROR_ARCHIVE; + if ((UInt64)(int)type != type) + { + RINOK(SzSkeepDataSize(sd, size)); + } + else + switch((int)type) + { + case k7zIdName: + { + size_t namesSize; + RINOK(SzReadSwitch(sd)); + namesSize = (size_t)size - 1; + if ((namesSize & 1) != 0) + return SZ_ERROR_ARCHIVE; + if (!Buf_Create(&p->FileNames, namesSize, allocMain)) + return SZ_ERROR_MEM; + MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain); + memcpy(p->FileNames.data, sd->Data, namesSize); + RINOK(SzReadFileNames(sd->Data, namesSize >> 1, numFiles, p->FileNameOffsets)) + RINOK(SzSkeepDataSize(sd, namesSize)); + break; + } + case k7zIdEmptyStream: + { + RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp)); + numEmptyStreams = 0; + for (i = 0; i < numFiles; i++) + if ((*emptyStreamVector)[i]) + numEmptyStreams++; + break; + } + case k7zIdEmptyFile: + { + RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp)); + break; + } + case k7zIdWinAttributes: + { + RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp)); + RINOK(SzReadSwitch(sd)); + for (i = 0; i < numFiles; i++) + { + CSzFileItem *f = &files[i]; + Byte defined = (*lwtVector)[i]; + f->AttribDefined = defined; + f->Attrib = 0; + if (defined) + { + RINOK(SzReadUInt32(sd, &f->Attrib)); + } + } + IAlloc_Free(allocTemp, *lwtVector); + *lwtVector = NULL; + break; + } + case k7zIdMTime: + { + RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp)); + RINOK(SzReadSwitch(sd)); + for (i = 0; i < numFiles; i++) + { + CSzFileItem *f = &files[i]; + Byte defined = (*lwtVector)[i]; + f->MTimeDefined = defined; + f->MTime.Low = f->MTime.High = 0; + if (defined) + { + RINOK(SzReadUInt32(sd, &f->MTime.Low)); + RINOK(SzReadUInt32(sd, &f->MTime.High)); + } + } + IAlloc_Free(allocTemp, *lwtVector); + *lwtVector = NULL; + break; + } + default: + { + RINOK(SzSkeepDataSize(sd, size)); + } + } + } + + { + UInt32 emptyFileIndex = 0; + UInt32 sizeIndex = 0; + for (i = 0; i < numFiles; i++) + { + CSzFileItem *file = files + i; + file->IsAnti = 0; + if (*emptyStreamVector == 0) + file->HasStream = 1; + else + file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1); + if (file->HasStream) + { + file->IsDir = 0; + file->Size = (*unpackSizes)[sizeIndex]; + file->Crc = (*digests)[sizeIndex]; + file->CrcDefined = (Byte)(*digestsDefined)[sizeIndex]; + sizeIndex++; + } + else + { + if (*emptyFileVector == 0) + file->IsDir = 1; + else + file->IsDir = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); + emptyFileIndex++; + file->Size = 0; + file->Crc = 0; + file->CrcDefined = 0; + } + } + } + return SzArEx_Fill(p, allocMain); +} + +static SRes SzReadHeader( + CSzArEx *p, + CSzData *sd, + ISzAlloc *allocMain, + ISzAlloc *allocTemp) +{ + UInt64 *unpackSizes = 0; + Byte *digestsDefined = 0; + UInt32 *digests = 0; + Byte *emptyStreamVector = 0; + Byte *emptyFileVector = 0; + Byte *lwtVector = 0; + SRes res = SzReadHeader2(p, sd, + &unpackSizes, &digestsDefined, &digests, + &emptyStreamVector, &emptyFileVector, &lwtVector, + allocMain, allocTemp); + IAlloc_Free(allocTemp, unpackSizes); + IAlloc_Free(allocTemp, digestsDefined); + IAlloc_Free(allocTemp, digests); + IAlloc_Free(allocTemp, emptyStreamVector); + IAlloc_Free(allocTemp, emptyFileVector); + IAlloc_Free(allocTemp, lwtVector); + return res; +} + +static SRes SzReadAndDecodePackedStreams2( + ILookInStream *inStream, + CSzData *sd, + CBuf *outBuffer, + UInt64 baseOffset, + CSzAr *p, + UInt64 **unpackSizes, + Byte **digestsDefined, + UInt32 **digests, + ISzAlloc *allocTemp) +{ + + UInt32 numUnpackStreams = 0; + UInt64 dataStartPos; + CSzFolder *folder; + UInt64 unpackSize; + SRes res; + + RINOK(SzReadStreamsInfo(sd, &dataStartPos, p, + &numUnpackStreams, unpackSizes, digestsDefined, digests, + allocTemp, allocTemp)); + + dataStartPos += baseOffset; + if (p->NumFolders != 1) + return SZ_ERROR_ARCHIVE; + + folder = p->Folders; + unpackSize = SzFolder_GetUnpackSize(folder); + + RINOK(LookInStream_SeekTo(inStream, dataStartPos)); + + if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp)) + return SZ_ERROR_MEM; + + res = SzFolder_Decode(folder, p->PackSizes, + inStream, dataStartPos, + outBuffer->data, (size_t)unpackSize, allocTemp); + RINOK(res); + if (folder->UnpackCRCDefined) + if (CrcCalc(outBuffer->data, (size_t)unpackSize) != folder->UnpackCRC) + return SZ_ERROR_CRC; + return SZ_OK; +} + +static SRes SzReadAndDecodePackedStreams( + ILookInStream *inStream, + CSzData *sd, + CBuf *outBuffer, + UInt64 baseOffset, + ISzAlloc *allocTemp) +{ + CSzAr p; + UInt64 *unpackSizes = 0; + Byte *digestsDefined = 0; + UInt32 *digests = 0; + SRes res; + SzAr_Init(&p); + res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset, + &p, &unpackSizes, &digestsDefined, &digests, + allocTemp); + SzAr_Free(&p, allocTemp); + IAlloc_Free(allocTemp, unpackSizes); + IAlloc_Free(allocTemp, digestsDefined); + IAlloc_Free(allocTemp, digests); + return res; +} + +static SRes SzArEx_Open2( + CSzArEx *p, + ILookInStream *inStream, + ISzAlloc *allocMain, + ISzAlloc *allocTemp) +{ + Byte header[k7zStartHeaderSize]; + Int64 startArcPos; + UInt64 nextHeaderOffset, nextHeaderSize; + size_t nextHeaderSizeT; + UInt32 nextHeaderCRC; + CBuf buffer; + SRes res; + + startArcPos = 0; + RINOK(inStream->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(inStream->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(&buffer, nextHeaderSizeT, allocTemp)) + return SZ_ERROR_MEM; + + res = LookInStream_Read(inStream, buffer.data, nextHeaderSizeT); + if (res == SZ_OK) + { + res = SZ_ERROR_ARCHIVE; + if (CrcCalc(buffer.data, nextHeaderSizeT) == nextHeaderCRC) + { + CSzData sd; + UInt64 type; + sd.Data = buffer.data; + sd.Size = buffer.size; + res = SzReadID(&sd, &type); + if (res == SZ_OK) + { + if (type == k7zIdEncodedHeader) + { + CBuf outBuffer; + Buf_Init(&outBuffer); + res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, p->startPosAfterHeader, allocTemp); + if (res != SZ_OK) + Buf_Free(&outBuffer, allocTemp); + else + { + Buf_Free(&buffer, allocTemp); + buffer.data = outBuffer.data; + buffer.size = outBuffer.size; + sd.Data = buffer.data; + sd.Size = buffer.size; + res = SzReadID(&sd, &type); + } + } + } + if (res == SZ_OK) + { + if (type == k7zIdHeader) + res = SzReadHeader(p, &sd, allocMain, allocTemp); + else + res = SZ_ERROR_UNSUPPORTED; + } + } + } + Buf_Free(&buffer, allocTemp); + return res; +} + +SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *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 **outBuffer, + size_t *outBufferSize, + size_t *offset, + size_t *outSizeProcessed, + ISzAlloc *allocMain, + ISzAlloc *allocTemp) +{ + UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex]; + SRes res = SZ_OK; + *offset = 0; + *outSizeProcessed = 0; + if (folderIndex == (UInt32)-1) + { + IAlloc_Free(allocMain, *outBuffer); + *blockIndex = folderIndex; + *outBuffer = 0; + *outBufferSize = 0; + return SZ_OK; + } + + if (*outBuffer == 0 || *blockIndex != folderIndex) + { + CSzFolder *folder = p->db.Folders + folderIndex; + UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder); + size_t unpackSize = (size_t)unpackSizeSpec; + UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0); + + if (unpackSize != unpackSizeSpec) + return SZ_ERROR_MEM; + *blockIndex = folderIndex; + IAlloc_Free(allocMain, *outBuffer); + *outBuffer = 0; + + RINOK(LookInStream_SeekTo(inStream, startOffset)); + + if (res == SZ_OK) + { + *outBufferSize = unpackSize; + if (unpackSize != 0) + { + *outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize); + if (*outBuffer == 0) + res = SZ_ERROR_MEM; + } + if (res == SZ_OK) + { + res = SzFolder_Decode(folder, + p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex], + inStream, startOffset, + *outBuffer, unpackSize, allocTemp); + if (res == SZ_OK) + { + if (folder->UnpackCRCDefined) + { + if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC) + res = SZ_ERROR_CRC; + } + } + } + } + } + if (res == SZ_OK) + { + UInt32 i; + CSzFileItem *fileItem = p->db.Files + fileIndex; + *offset = 0; + for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) + *offset += (UInt32)p->db.Files[i].Size; + *outSizeProcessed = (size_t)fileItem->Size; + if (*offset + *outSizeProcessed > *outBufferSize) + return SZ_ERROR_FAIL; + if (fileItem->CrcDefined && CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->Crc) + res = SZ_ERROR_CRC; + } + return res; +} diff --git a/C/7zStream.c b/C/7zStream.c new file mode 100755 index 0000000..f0959fb --- /dev/null +++ b/C/7zStream.c @@ -0,0 +1,169 @@ +/* 7zStream.c -- 7z Stream functions +2010-03-11 : Igor Pavlov : Public domain */ + +#include + +#include "Types.h" + +SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType) +{ + while (size != 0) + { + size_t processed = size; + RINOK(stream->Read(stream, buf, &processed)); + if (processed == 0) + return errorType; + buf = (void *)((Byte *)buf + processed); + size -= processed; + } + return SZ_OK; +} + +SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size) +{ + return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); +} + +SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf) +{ + size_t processed = 1; + RINOK(stream->Read(stream, buf, &processed)); + return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF; +} + +SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset) +{ + Int64 t = offset; + return stream->Seek(stream, &t, SZ_SEEK_SET); +} + +SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size) +{ + const void *lookBuf; + if (*size == 0) + return SZ_OK; + RINOK(stream->Look(stream, &lookBuf, size)); + memcpy(buf, lookBuf, *size); + return stream->Skip(stream, *size); +} + +SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType) +{ + while (size != 0) + { + size_t processed = size; + RINOK(stream->Read(stream, buf, &processed)); + if (processed == 0) + return errorType; + buf = (void *)((Byte *)buf + processed); + size -= processed; + } + return SZ_OK; +} + +SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size) +{ + return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); +} + +static SRes LookToRead_Look_Lookahead(void *pp, const void **buf, size_t *size) +{ + SRes res = SZ_OK; + CLookToRead *p = (CLookToRead *)pp; + size_t size2 = p->size - p->pos; + if (size2 == 0 && *size > 0) + { + p->pos = 0; + size2 = LookToRead_BUF_SIZE; + res = p->realStream->Read(p->realStream, p->buf, &size2); + p->size = size2; + } + if (size2 < *size) + *size = size2; + *buf = p->buf + p->pos; + return res; +} + +static SRes LookToRead_Look_Exact(void *pp, const void **buf, size_t *size) +{ + SRes res = SZ_OK; + CLookToRead *p = (CLookToRead *)pp; + size_t size2 = p->size - p->pos; + if (size2 == 0 && *size > 0) + { + p->pos = 0; + if (*size > LookToRead_BUF_SIZE) + *size = LookToRead_BUF_SIZE; + res = p->realStream->Read(p->realStream, p->buf, size); + size2 = p->size = *size; + } + if (size2 < *size) + *size = size2; + *buf = p->buf + p->pos; + return res; +} + +static SRes LookToRead_Skip(void *pp, size_t offset) +{ + CLookToRead *p = (CLookToRead *)pp; + p->pos += offset; + return SZ_OK; +} + +static SRes LookToRead_Read(void *pp, void *buf, size_t *size) +{ + CLookToRead *p = (CLookToRead *)pp; + size_t rem = p->size - p->pos; + if (rem == 0) + return p->realStream->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 LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin) +{ + CLookToRead *p = (CLookToRead *)pp; + p->pos = p->size = 0; + return p->realStream->Seek(p->realStream, pos, origin); +} + +void LookToRead_CreateVTable(CLookToRead *p, int lookahead) +{ + p->s.Look = lookahead ? + LookToRead_Look_Lookahead : + LookToRead_Look_Exact; + p->s.Skip = LookToRead_Skip; + p->s.Read = LookToRead_Read; + p->s.Seek = LookToRead_Seek; +} + +void LookToRead_Init(CLookToRead *p) +{ + p->pos = p->size = 0; +} + +static SRes SecToLook_Read(void *pp, void *buf, size_t *size) +{ + CSecToLook *p = (CSecToLook *)pp; + return LookInStream_LookRead(p->realStream, buf, size); +} + +void SecToLook_CreateVTable(CSecToLook *p) +{ + p->s.Read = SecToLook_Read; +} + +static SRes SecToRead_Read(void *pp, void *buf, size_t *size) +{ + CSecToRead *p = (CSecToRead *)pp; + return p->realStream->Read(p->realStream, buf, size); +} + +void SecToRead_CreateVTable(CSecToRead *p) +{ + p->s.Read = SecToRead_Read; +} diff --git a/C/7zVersion.h b/C/7zVersion.h new file mode 100755 index 0000000..d4ac470 --- /dev/null +++ b/C/7zVersion.h @@ -0,0 +1,7 @@ +#define MY_VER_MAJOR 9 +#define MY_VER_MINOR 20 +#define MY_VER_BUILD 0 +#define MY_VERSION "9.20" +#define MY_DATE "2010-11-18" +#define MY_COPYRIGHT ": Igor Pavlov : Public domain" +#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE diff --git a/C/Aes.c b/C/Aes.c new file mode 100755 index 0000000..c632fda --- /dev/null +++ b/C/Aes.c @@ -0,0 +1,282 @@ +/* Aes.c -- AES encryption / decryption +2009-11-23 : Igor Pavlov : Public domain */ + +#include "Aes.h" +#include "CpuArch.h" + +static UInt32 T[256 * 4]; +static 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 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)) & 0xFF) + +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; + T[ i] = Ui32(a2, a1, a1, a3); + T[0x100 + i] = Ui32(a3, a2, a1, a1); + T[0x200 + i] = Ui32(a1, a3, a2, a1); + T[0x300 + 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; + D[ i] = Ui32(aE, a9, aD, aB); + D[0x100 + i] = Ui32(aB, aE, a9, aD); + D[0x200 + i] = Ui32(aD, aB, aE, a9); + D[0x300 + i] = Ui32(a9, aD, aB, aE); + } + } + g_AesCbc_Encode = AesCbc_Encode; + g_AesCbc_Decode = AesCbc_Decode; + g_AesCtr_Code = AesCtr_Code; + #ifdef MY_CPU_X86_OR_AMD64 + if (CPU_Is_Aes_Supported()) + { + g_AesCbc_Encode = AesCbc_Encode_Intel; + g_AesCbc_Decode = AesCbc_Decode_Intel; + g_AesCtr_Code = AesCtr_Code_Intel; + } + #endif +} + +#define HT(i, x, s) (T + (x << 8))[gb ## x(s[(i + x) & 3])] +#define HT4(m, i, s, p) m[i] = \ + HT(i, 0, s) ^ \ + HT(i, 1, s) ^ \ + HT(i, 2, s) ^ \ + HT(i, 3, s) ^ w[p + i] +/* such order (2031) in HT16 is for VC6/K8 speed optimization) */ +#define HT16(m, s, p) \ + HT4(m, 2, s, p); \ + HT4(m, 0, s, p); \ + HT4(m, 3, s, p); \ + HT4(m, 1, s, p); \ + +#define FT(i, x) Sbox[gb ## x(m[(i + x) & 3])] +#define FT4(i) dest[i] = Ui32(FT(i, 0), FT(i, 1), FT(i, 2), FT(i, 3)) ^ w[i]; + +#define HD(i, x, s) (D + (x << 8))[gb ## x(s[(i - x) & 3])] +#define HD4(m, i, s, p) m[i] = \ + HD(i, 0, s) ^ \ + HD(i, 1, s) ^ \ + HD(i, 2, s) ^ \ + HD(i, 3, s) ^ w[p + i]; +/* such order (0231) in HD16 is for VC6/K8 speed optimization) */ +#define HD16(m, s, p) \ + HD4(m, 0, s, p); \ + HD4(m, 2, s, p); \ + HD4(m, 3, s, p); \ + HD4(m, 1, s, p); \ + +#define FD(i, x) InvS[gb ## x(m[(i - x) & 3])] +#define FD4(i) dest[i] = Ui32(FD(i, 0), FD(i, 1), FD(i, 2), FD(i, 3)) ^ w[i]; + +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[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] = + D[ Sbox[gb0(r)]] ^ + D[0x100 + Sbox[gb1(r)]] ^ + D[0x200 + Sbox[gb2(r)]] ^ + D[0x300 + Sbox[gb3(r)]]; + } +} + +/* Aes_Encode and Aes_Decode functions work with little-endian words. + src and dest are pointers to 4 UInt32 words. + arc and dest can point to same block */ + +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]; + Byte buf[16]; + int i; + if (++p[0] == 0) + p[1]++; + Aes_Encode(p + 4, temp, p); + SetUi32(buf, temp[0]); + SetUi32(buf + 4, temp[1]); + SetUi32(buf + 8, temp[2]); + SetUi32(buf + 12, temp[3]); + for (i = 0; i < 16; i++) + *data++ ^= buf[i]; + } +} diff --git a/C/Aes.h b/C/Aes.h new file mode 100755 index 0000000..7c3c3d3 --- /dev/null +++ b/C/Aes.h @@ -0,0 +1,38 @@ +/* Aes.h -- AES encryption / decryption +2009-11-23 : Igor Pavlov : Public domain */ + +#ifndef __AES_H +#define __AES_H + +#include "Types.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/C/AesOpt.c b/C/AesOpt.c new file mode 100755 index 0000000..452e6ff --- /dev/null +++ b/C/AesOpt.c @@ -0,0 +1,182 @@ +/* AesOpt.c -- Intel's AES +2009-11-23 : Igor Pavlov : Public domain */ + +#include "CpuArch.h" + +#ifdef MY_CPU_X86_OR_AMD64 +#if _MSC_VER >= 1500 +#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/C/Alloc.c b/C/Alloc.c new file mode 100755 index 0000000..bb24a77 --- /dev/null +++ b/C/Alloc.c @@ -0,0 +1,127 @@ +/* Alloc.c -- Memory allocation functions +2008-09-24 +Igor Pavlov +Public domain */ + +#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; +#endif + +void *MyAlloc(size_t size) +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + { + void *p = malloc(size); + fprintf(stderr, "\nAlloc %10d bytes, count = %10d, addr = %8X", size, g_allocCount++, (unsigned)p); + return p; + } + #else + return malloc(size); + #endif +} + +void MyFree(void *address) +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree; count = %10d, addr = %8X", --g_allocCount, (unsigned)address); + #endif + free(address); +} + +#ifdef _WIN32 + +void *MidAlloc(size_t size) +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); + #endif + return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); +} + +void MidFree(void *address) +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); + #endif + if (address == 0) + 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 = 0; + GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) + GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); + if (largePageMinimum == 0) + return; + size = largePageMinimum(); + if (size == 0 || (size & (size - 1)) != 0) + return; + g_LargePageSize = size; + #endif +} + + +void *BigAlloc(size_t size) +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); + #endif + + #ifdef _7ZIP_LARGE_PAGES + if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18)) + { + void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), + MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); + if (res != 0) + return res; + } + #endif + return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); +} + +void BigFree(void *address) +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); + #endif + + if (address == 0) + return; + VirtualFree(address, 0, MEM_RELEASE); +} + +#endif diff --git a/C/Alloc.h b/C/Alloc.h new file mode 100755 index 0000000..6b3f034 --- /dev/null +++ b/C/Alloc.h @@ -0,0 +1,38 @@ +/* Alloc.h -- Memory allocation functions +2009-02-07 : Igor Pavlov : Public domain */ + +#ifndef __COMMON_ALLOC_H +#define __COMMON_ALLOC_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +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 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/C/Bcj2.c b/C/Bcj2.c new file mode 100755 index 0000000..474bdd4 --- /dev/null +++ b/C/Bcj2.c @@ -0,0 +1,132 @@ +/* Bcj2.c -- Converter for x86 code (BCJ2) +2008-10-04 : Igor Pavlov : Public domain */ + +#include "Bcj2.h" + +#ifdef _LZMA_PROB32 +#define CProb UInt32 +#else +#define CProb UInt16 +#endif + +#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80) +#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)) + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_READ_BYTE (*buffer++) +#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; } +#define RC_INIT2 code = 0; range = 0xFFFFFFFF; \ + { int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }} + +#define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; } + +#define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) +#define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE; +#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE; + +int Bcj2_Decode( + const Byte *buf0, SizeT size0, + const Byte *buf1, SizeT size1, + const Byte *buf2, SizeT size2, + const Byte *buf3, SizeT size3, + Byte *outBuf, SizeT outSize) +{ + CProb p[256 + 2]; + SizeT inPos = 0, outPos = 0; + + const Byte *buffer, *bufferLim; + UInt32 range, code; + Byte prevByte = 0; + + unsigned int i; + for (i = 0; i < sizeof(p) / sizeof(p[0]); i++) + p[i] = kBitModelTotal >> 1; + + buffer = buf3; + bufferLim = buffer + size3; + RC_INIT2 + + if (outSize == 0) + return SZ_OK; + + for (;;) + { + Byte b; + CProb *prob; + UInt32 bound; + UInt32 ttt; + + SizeT limit = size0 - inPos; + if (outSize - outPos < limit) + limit = outSize - outPos; + while (limit != 0) + { + Byte b = buf0[inPos]; + outBuf[outPos++] = b; + if (IsJ(prevByte, b)) + break; + inPos++; + prevByte = b; + limit--; + } + + if (limit == 0 || outPos == outSize) + break; + + b = buf0[inPos++]; + + if (b == 0xE8) + prob = p + prevByte; + else if (b == 0xE9) + prob = p + 256; + else + prob = p + 257; + + IF_BIT_0(prob) + { + UPDATE_0(prob) + prevByte = b; + } + else + { + UInt32 dest; + const Byte *v; + UPDATE_1(prob) + if (b == 0xE8) + { + v = buf1; + if (size1 < 4) + return SZ_ERROR_DATA; + buf1 += 4; + size1 -= 4; + } + else + { + v = buf2; + if (size2 < 4) + return SZ_ERROR_DATA; + buf2 += 4; + size2 -= 4; + } + dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) | + ((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4); + outBuf[outPos++] = (Byte)dest; + if (outPos == outSize) + break; + outBuf[outPos++] = (Byte)(dest >> 8); + if (outPos == outSize) + break; + outBuf[outPos++] = (Byte)(dest >> 16); + if (outPos == outSize) + break; + outBuf[outPos++] = prevByte = (Byte)(dest >> 24); + } + } + return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA; +} diff --git a/C/Bcj2.h b/C/Bcj2.h new file mode 100755 index 0000000..d9d857b --- /dev/null +++ b/C/Bcj2.h @@ -0,0 +1,38 @@ +/* Bcj2.h -- Converter for x86 code (BCJ2) +2009-02-07 : Igor Pavlov : Public domain */ + +#ifndef __BCJ2_H +#define __BCJ2_H + +#include "Types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* +Conditions: + outSize <= FullOutputSize, + where FullOutputSize is full size of output stream of x86_2 filter. + +If buf0 overlaps outBuf, there are two required conditions: + 1) (buf0 >= outBuf) + 2) (buf0 + size0 >= outBuf + FullOutputSize). + +Returns: + SZ_OK + SZ_ERROR_DATA - Data error +*/ + +int Bcj2_Decode( + const Byte *buf0, SizeT size0, + const Byte *buf1, SizeT size1, + const Byte *buf2, SizeT size2, + const Byte *buf3, SizeT size3, + Byte *outBuf, SizeT outSize); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/C/Bra.c b/C/Bra.c new file mode 100755 index 0000000..2a0f147 --- /dev/null +++ b/C/Bra.c @@ -0,0 +1,133 @@ +/* Bra.c -- Converters for RISC code +2010-04-16 : Igor Pavlov : Public domain */ + +#include "Bra.h" + +SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + SizeT i; + if (size < 4) + return 0; + size -= 4; + ip += 8; + for (i = 0; i <= size; i += 4) + { + if (data[i + 3] == 0xEB) + { + UInt32 dest; + UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]); + src <<= 2; + if (encoding) + dest = ip + (UInt32)i + src; + else + dest = src - (ip + (UInt32)i); + dest >>= 2; + data[i + 2] = (Byte)(dest >> 16); + data[i + 1] = (Byte)(dest >> 8); + data[i + 0] = (Byte)dest; + } + } + return i; +} + +SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + SizeT i; + if (size < 4) + return 0; + size -= 4; + ip += 4; + for (i = 0; i <= size; i += 2) + { + if ((data[i + 1] & 0xF8) == 0xF0 && + (data[i + 3] & 0xF8) == 0xF8) + { + UInt32 dest; + UInt32 src = + (((UInt32)data[i + 1] & 0x7) << 19) | + ((UInt32)data[i + 0] << 11) | + (((UInt32)data[i + 3] & 0x7) << 8) | + (data[i + 2]); + + src <<= 1; + if (encoding) + dest = ip + (UInt32)i + src; + else + dest = src - (ip + (UInt32)i); + dest >>= 1; + + data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7)); + data[i + 0] = (Byte)(dest >> 11); + data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7)); + data[i + 2] = (Byte)dest; + i += 2; + } + } + return i; +} + +SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + SizeT i; + if (size < 4) + return 0; + size -= 4; + for (i = 0; i <= size; i += 4) + { + if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1) + { + UInt32 src = ((UInt32)(data[i + 0] & 3) << 24) | + ((UInt32)data[i + 1] << 16) | + ((UInt32)data[i + 2] << 8) | + ((UInt32)data[i + 3] & (~3)); + + UInt32 dest; + if (encoding) + dest = ip + (UInt32)i + src; + else + dest = src - (ip + (UInt32)i); + data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3)); + data[i + 1] = (Byte)(dest >> 16); + data[i + 2] = (Byte)(dest >> 8); + data[i + 3] &= 0x3; + data[i + 3] |= dest; + } + } + return i; +} + +SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + UInt32 i; + if (size < 4) + return 0; + size -= 4; + for (i = 0; i <= size; i += 4) + { + if ((data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00) || + (data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0)) + { + UInt32 src = + ((UInt32)data[i + 0] << 24) | + ((UInt32)data[i + 1] << 16) | + ((UInt32)data[i + 2] << 8) | + ((UInt32)data[i + 3]); + UInt32 dest; + + src <<= 2; + if (encoding) + dest = ip + i + src; + else + dest = src - (ip + i); + dest >>= 2; + + dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000; + + data[i + 0] = (Byte)(dest >> 24); + data[i + 1] = (Byte)(dest >> 16); + data[i + 2] = (Byte)(dest >> 8); + data[i + 3] = (Byte)dest; + } + } + return i; +} diff --git a/C/Bra.h b/C/Bra.h new file mode 100755 index 0000000..9c91e33 --- /dev/null +++ b/C/Bra.h @@ -0,0 +1,68 @@ +/* Bra.h -- Branch converters for executables +2009-02-07 : Igor Pavlov : Public domain */ + +#ifndef __BRA_H +#define __BRA_H + +#include "Types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* +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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/C/Bra86.c b/C/Bra86.c new file mode 100755 index 0000000..93566cb --- /dev/null +++ b/C/Bra86.c @@ -0,0 +1,85 @@ +/* Bra86.c -- Converter for x86 code (BCJ) +2008-10-04 : Igor Pavlov : Public domain */ + +#include "Bra.h" + +#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) + +const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; +const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; + +SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) +{ + SizeT bufferPos = 0, prevPosT; + UInt32 prevMask = *state & 0x7; + if (size < 5) + return 0; + ip += 5; + prevPosT = (SizeT)0 - 1; + + for (;;) + { + Byte *p = data + bufferPos; + Byte *limit = data + size - 4; + for (; p < limit; p++) + if ((*p & 0xFE) == 0xE8) + break; + bufferPos = (SizeT)(p - data); + if (p >= limit) + break; + prevPosT = bufferPos - prevPosT; + if (prevPosT > 3) + prevMask = 0; + else + { + prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7; + if (prevMask != 0) + { + Byte b = p[4 - kMaskToBitNumber[prevMask]]; + if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b)) + { + prevPosT = bufferPos; + prevMask = ((prevMask << 1) & 0x7) | 1; + bufferPos++; + continue; + } + } + } + prevPosT = bufferPos; + + if (Test86MSByte(p[4])) + { + UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); + UInt32 dest; + for (;;) + { + Byte b; + int index; + if (encoding) + dest = (ip + (UInt32)bufferPos) + src; + else + dest = src - (ip + (UInt32)bufferPos); + if (prevMask == 0) + break; + index = kMaskToBitNumber[prevMask] * 8; + b = (Byte)(dest >> (24 - index)); + if (!Test86MSByte(b)) + break; + src = dest ^ ((1 << (32 - index)) - 1); + } + p[4] = (Byte)(~(((dest >> 24) & 1) - 1)); + p[3] = (Byte)(dest >> 16); + p[2] = (Byte)(dest >> 8); + p[1] = (Byte)dest; + bufferPos += 5; + } + else + { + prevMask = ((prevMask << 1) & 0x7) | 1; + bufferPos++; + } + } + prevPosT = bufferPos - prevPosT; + *state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7)); + return bufferPos; +} diff --git a/C/BraIA64.c b/C/BraIA64.c new file mode 100755 index 0000000..f359f16 --- /dev/null +++ b/C/BraIA64.c @@ -0,0 +1,67 @@ +/* BraIA64.c -- Converter for IA-64 code +2008-10-04 : Igor Pavlov : Public domain */ + +#include "Bra.h" + +static const Byte kBranchTable[32] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 6, 6, 0, 0, 7, 7, + 4, 4, 0, 0, 4, 4, 0, 0 +}; + +SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + SizeT i; + if (size < 16) + return 0; + size -= 16; + for (i = 0; i <= size; i += 16) + { + UInt32 instrTemplate = data[i] & 0x1F; + UInt32 mask = kBranchTable[instrTemplate]; + UInt32 bitPos = 5; + int slot; + for (slot = 0; slot < 3; slot++, bitPos += 41) + { + UInt32 bytePos, bitRes; + UInt64 instruction, instNorm; + int j; + if (((mask >> slot) & 1) == 0) + continue; + bytePos = (bitPos >> 3); + bitRes = bitPos & 0x7; + instruction = 0; + for (j = 0; j < 6; j++) + instruction += (UInt64)data[i + j + bytePos] << (8 * j); + + instNorm = instruction >> bitRes; + if (((instNorm >> 37) & 0xF) == 0x5 && ((instNorm >> 9) & 0x7) == 0) + { + UInt32 src = (UInt32)((instNorm >> 13) & 0xFFFFF); + UInt32 dest; + src |= ((UInt32)(instNorm >> 36) & 1) << 20; + + src <<= 4; + + if (encoding) + dest = ip + (UInt32)i + src; + else + dest = src - (ip + (UInt32)i); + + dest >>= 4; + + instNorm &= ~((UInt64)(0x8FFFFF) << 13); + instNorm |= ((UInt64)(dest & 0xFFFFF) << 13); + instNorm |= ((UInt64)(dest & 0x100000) << (36 - 20)); + + instruction &= (1 << bitRes) - 1; + instruction |= (instNorm << bitRes); + for (j = 0; j < 6; j++) + data[i + j + bytePos] = (Byte)(instruction >> (8 * j)); + } + } + } + return i; +} diff --git a/C/BwtSort.c b/C/BwtSort.c new file mode 100755 index 0000000..d6b545e --- /dev/null +++ b/C/BwtSort.c @@ -0,0 +1,516 @@ +/* BwtSort.c -- BWT block sorting +2008-08-17 +Igor Pavlov +Public domain */ + +#include "BwtSort.h" +#include "Sort.h" + +/* #define BLOCK_SORT_USE_HEAP_SORT */ + +#define NO_INLINE MY_FAST_CALL + +/* Don't change it !!! */ +#define kNumHashBytes 2 +#define kNumHashValues (1 << (kNumHashBytes * 8)) + +/* kNumRefBitsMax must be < (kNumHashBytes * 8) = 16 */ +#define kNumRefBitsMax 12 + +#define BS_TEMP_SIZE kNumHashValues + +#ifdef BLOCK_SORT_EXTERNAL_FLAGS + +/* 32 Flags in UInt32 word */ +#define kNumFlagsBits 5 +#define kNumFlagsInWord (1 << kNumFlagsBits) +#define kFlagsMask (kNumFlagsInWord - 1) +#define kAllFlags 0xFFFFFFFF + +#else + +#define kNumBitsMax 20 +#define kIndexMask ((1 << kNumBitsMax) - 1) +#define kNumExtraBits (32 - kNumBitsMax) +#define kNumExtra0Bits (kNumExtraBits - 2) +#define kNumExtra0Mask ((1 << kNumExtra0Bits) - 1) + +#define SetFinishedGroupSize(p, size) \ + { *(p) |= ((((size) - 1) & kNumExtra0Mask) << kNumBitsMax); \ + if ((size) > (1 << kNumExtra0Bits)) { \ + *(p) |= 0x40000000; *((p) + 1) |= ((((size) - 1)>> kNumExtra0Bits) << kNumBitsMax); } } \ + +static void SetGroupSize(UInt32 *p, UInt32 size) +{ + if (--size == 0) + return; + *p |= 0x80000000 | ((size & kNumExtra0Mask) << kNumBitsMax); + if (size >= (1 << kNumExtra0Bits)) + { + *p |= 0x40000000; + p[1] |= ((size >> kNumExtra0Bits) << kNumBitsMax); + } +} + +#endif + +/* +SortGroup - is recursive Range-Sort function with HeapSort optimization for small blocks + "range" is not real range. It's only for optimization. +returns: 1 - if there are groups, 0 - no more groups +*/ + +UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 groupOffset, UInt32 groupSize, int NumRefBits, UInt32 *Indices + #ifndef BLOCK_SORT_USE_HEAP_SORT + , UInt32 left, UInt32 range + #endif + ) +{ + UInt32 *ind2 = Indices + groupOffset; + UInt32 *Groups; + if (groupSize <= 1) + { + /* + #ifndef BLOCK_SORT_EXTERNAL_FLAGS + SetFinishedGroupSize(ind2, 1); + #endif + */ + return 0; + } + Groups = Indices + BlockSize + BS_TEMP_SIZE; + if (groupSize <= ((UInt32)1 << NumRefBits) + #ifndef BLOCK_SORT_USE_HEAP_SORT + && groupSize <= range + #endif + ) + { + UInt32 *temp = Indices + BlockSize; + UInt32 j; + UInt32 mask, thereAreGroups, group, cg; + { + UInt32 gPrev; + UInt32 gRes = 0; + { + UInt32 sp = ind2[0] + NumSortedBytes; + if (sp >= BlockSize) sp -= BlockSize; + gPrev = Groups[sp]; + temp[0] = (gPrev << NumRefBits); + } + + for (j = 1; j < groupSize; j++) + { + UInt32 sp = ind2[j] + NumSortedBytes; + UInt32 g; + if (sp >= BlockSize) sp -= BlockSize; + g = Groups[sp]; + temp[j] = (g << NumRefBits) | j; + gRes |= (gPrev ^ g); + } + if (gRes == 0) + { + #ifndef BLOCK_SORT_EXTERNAL_FLAGS + SetGroupSize(ind2, groupSize); + #endif + return 1; + } + } + + HeapSort(temp, groupSize); + mask = ((1 << NumRefBits) - 1); + thereAreGroups = 0; + + group = groupOffset; + cg = (temp[0] >> NumRefBits); + temp[0] = ind2[temp[0] & mask]; + + { + #ifdef BLOCK_SORT_EXTERNAL_FLAGS + UInt32 *Flags = Groups + BlockSize; + #else + UInt32 prevGroupStart = 0; + #endif + + for (j = 1; j < groupSize; j++) + { + UInt32 val = temp[j]; + UInt32 cgCur = (val >> NumRefBits); + + if (cgCur != cg) + { + cg = cgCur; + group = groupOffset + j; + + #ifdef BLOCK_SORT_EXTERNAL_FLAGS + { + UInt32 t = group - 1; + Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask)); + } + #else + SetGroupSize(temp + prevGroupStart, j - prevGroupStart); + prevGroupStart = j; + #endif + } + else + thereAreGroups = 1; + { + UInt32 ind = ind2[val & mask]; + temp[j] = ind; + Groups[ind] = group; + } + } + + #ifndef BLOCK_SORT_EXTERNAL_FLAGS + SetGroupSize(temp + prevGroupStart, j - prevGroupStart); + #endif + } + + for (j = 0; j < groupSize; j++) + ind2[j] = temp[j]; + return thereAreGroups; + } + + /* Check that all strings are in one group (cannot sort) */ + { + UInt32 group, j; + UInt32 sp = ind2[0] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize; + group = Groups[sp]; + for (j = 1; j < groupSize; j++) + { + sp = ind2[j] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize; + if (Groups[sp] != group) + break; + } + if (j == groupSize) + { + #ifndef BLOCK_SORT_EXTERNAL_FLAGS + SetGroupSize(ind2, groupSize); + #endif + return 1; + } + } + + #ifndef BLOCK_SORT_USE_HEAP_SORT + { + /* ---------- Range Sort ---------- */ + UInt32 i; + UInt32 mid; + for (;;) + { + UInt32 j; + if (range <= 1) + { + #ifndef BLOCK_SORT_EXTERNAL_FLAGS + SetGroupSize(ind2, groupSize); + #endif + return 1; + } + mid = left + ((range + 1) >> 1); + j = groupSize; + i = 0; + do + { + UInt32 sp = ind2[i] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize; + if (Groups[sp] >= mid) + { + for (j--; j > i; j--) + { + sp = ind2[j] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize; + if (Groups[sp] < mid) + { + UInt32 temp = ind2[i]; ind2[i] = ind2[j]; ind2[j] = temp; + break; + } + } + if (i >= j) + break; + } + } + while (++i < j); + if (i == 0) + { + range = range - (mid - left); + left = mid; + } + else if (i == groupSize) + range = (mid - left); + else + break; + } + + #ifdef BLOCK_SORT_EXTERNAL_FLAGS + { + UInt32 t = (groupOffset + i - 1); + UInt32 *Flags = Groups + BlockSize; + Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask)); + } + #endif + + { + UInt32 j; + for (j = i; j < groupSize; j++) + Groups[ind2[j]] = groupOffset + i; + } + + { + UInt32 res = SortGroup(BlockSize, NumSortedBytes, groupOffset, i, NumRefBits, Indices, left, mid - left); + return res | SortGroup(BlockSize, NumSortedBytes, groupOffset + i, groupSize - i, NumRefBits, Indices, mid, range - (mid - left)); + } + + } + + #else + + /* ---------- Heap Sort ---------- */ + + { + UInt32 j; + for (j = 0; j < groupSize; j++) + { + UInt32 sp = ind2[j] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize; + ind2[j] = sp; + } + + HeapSortRef(ind2, Groups, groupSize); + + /* Write Flags */ + { + UInt32 sp = ind2[0]; + UInt32 group = Groups[sp]; + + #ifdef BLOCK_SORT_EXTERNAL_FLAGS + UInt32 *Flags = Groups + BlockSize; + #else + UInt32 prevGroupStart = 0; + #endif + + for (j = 1; j < groupSize; j++) + { + sp = ind2[j]; + if (Groups[sp] != group) + { + group = Groups[sp]; + #ifdef BLOCK_SORT_EXTERNAL_FLAGS + { + UInt32 t = groupOffset + j - 1; + Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask)); + } + #else + SetGroupSize(ind2 + prevGroupStart, j - prevGroupStart); + prevGroupStart = j; + #endif + } + } + + #ifndef BLOCK_SORT_EXTERNAL_FLAGS + SetGroupSize(ind2 + prevGroupStart, j - prevGroupStart); + #endif + } + { + /* Write new Groups values and Check that there are groups */ + UInt32 thereAreGroups = 0; + for (j = 0; j < groupSize; j++) + { + UInt32 group = groupOffset + j; + #ifndef BLOCK_SORT_EXTERNAL_FLAGS + UInt32 subGroupSize = ((ind2[j] & ~0xC0000000) >> kNumBitsMax); + if ((ind2[j] & 0x40000000) != 0) + subGroupSize += ((ind2[j + 1] >> kNumBitsMax) << kNumExtra0Bits); + subGroupSize++; + for (;;) + { + UInt32 original = ind2[j]; + UInt32 sp = original & kIndexMask; + if (sp < NumSortedBytes) sp += BlockSize; sp -= NumSortedBytes; + ind2[j] = sp | (original & ~kIndexMask); + Groups[sp] = group; + if (--subGroupSize == 0) + break; + j++; + thereAreGroups = 1; + } + #else + UInt32 *Flags = Groups + BlockSize; + for (;;) + { + UInt32 sp = ind2[j]; if (sp < NumSortedBytes) sp += BlockSize; sp -= NumSortedBytes; + ind2[j] = sp; + Groups[sp] = group; + if ((Flags[(groupOffset + j) >> kNumFlagsBits] & (1 << ((groupOffset + j) & kFlagsMask))) == 0) + break; + j++; + thereAreGroups = 1; + } + #endif + } + return thereAreGroups; + } + } + #endif +} + +/* conditions: blockSize > 0 */ +UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize) +{ + UInt32 *counters = Indices + blockSize; + UInt32 i; + UInt32 *Groups; + #ifdef BLOCK_SORT_EXTERNAL_FLAGS + UInt32 *Flags; + #endif + + /* Radix-Sort for 2 bytes */ + for (i = 0; i < kNumHashValues; i++) + counters[i] = 0; + for (i = 0; i < blockSize - 1; i++) + counters[((UInt32)data[i] << 8) | data[i + 1]]++; + counters[((UInt32)data[i] << 8) | data[0]]++; + + Groups = counters + BS_TEMP_SIZE; + #ifdef BLOCK_SORT_EXTERNAL_FLAGS + Flags = Groups + blockSize; + { + UInt32 numWords = (blockSize + kFlagsMask) >> kNumFlagsBits; + for (i = 0; i < numWords; i++) + Flags[i] = kAllFlags; + } + #endif + + { + UInt32 sum = 0; + for (i = 0; i < kNumHashValues; i++) + { + UInt32 groupSize = counters[i]; + if (groupSize > 0) + { + #ifdef BLOCK_SORT_EXTERNAL_FLAGS + UInt32 t = sum + groupSize - 1; + Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask)); + #endif + sum += groupSize; + } + counters[i] = sum - groupSize; + } + + for (i = 0; i < blockSize - 1; i++) + Groups[i] = counters[((UInt32)data[i] << 8) | data[i + 1]]; + Groups[i] = counters[((UInt32)data[i] << 8) | data[0]]; + + for (i = 0; i < blockSize - 1; i++) + Indices[counters[((UInt32)data[i] << 8) | data[i + 1]]++] = i; + Indices[counters[((UInt32)data[i] << 8) | data[0]]++] = i; + + #ifndef BLOCK_SORT_EXTERNAL_FLAGS + { + UInt32 prev = 0; + for (i = 0; i < kNumHashValues; i++) + { + UInt32 prevGroupSize = counters[i] - prev; + if (prevGroupSize == 0) + continue; + SetGroupSize(Indices + prev, prevGroupSize); + prev = counters[i]; + } + } + #endif + } + + { + int NumRefBits; + UInt32 NumSortedBytes; + for (NumRefBits = 0; ((blockSize - 1) >> NumRefBits) != 0; NumRefBits++); + NumRefBits = 32 - NumRefBits; + if (NumRefBits > kNumRefBitsMax) + NumRefBits = kNumRefBitsMax; + + for (NumSortedBytes = kNumHashBytes; ; NumSortedBytes <<= 1) + { + #ifndef BLOCK_SORT_EXTERNAL_FLAGS + UInt32 finishedGroupSize = 0; + #endif + UInt32 newLimit = 0; + for (i = 0; i < blockSize;) + { + UInt32 groupSize; + #ifdef BLOCK_SORT_EXTERNAL_FLAGS + + if ((Flags[i >> kNumFlagsBits] & (1 << (i & kFlagsMask))) == 0) + { + i++; + continue; + } + for (groupSize = 1; + (Flags[(i + groupSize) >> kNumFlagsBits] & (1 << ((i + groupSize) & kFlagsMask))) != 0; + groupSize++); + + groupSize++; + + #else + + groupSize = ((Indices[i] & ~0xC0000000) >> kNumBitsMax); + { + Bool finishedGroup = ((Indices[i] & 0x80000000) == 0); + if ((Indices[i] & 0x40000000) != 0) + { + groupSize += ((Indices[i + 1] >> kNumBitsMax) << kNumExtra0Bits); + Indices[i + 1] &= kIndexMask; + } + Indices[i] &= kIndexMask; + groupSize++; + if (finishedGroup || groupSize == 1) + { + Indices[i - finishedGroupSize] &= kIndexMask; + if (finishedGroupSize > 1) + Indices[i - finishedGroupSize + 1] &= kIndexMask; + { + UInt32 newGroupSize = groupSize + finishedGroupSize; + SetFinishedGroupSize(Indices + i - finishedGroupSize, newGroupSize); + finishedGroupSize = newGroupSize; + } + i += groupSize; + continue; + } + finishedGroupSize = 0; + } + + #endif + + if (NumSortedBytes >= blockSize) + { + UInt32 j; + for (j = 0; j < groupSize; j++) + { + UInt32 t = (i + j); + /* Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask)); */ + Groups[Indices[t]] = t; + } + } + else + if (SortGroup(blockSize, NumSortedBytes, i, groupSize, NumRefBits, Indices + #ifndef BLOCK_SORT_USE_HEAP_SORT + , 0, blockSize + #endif + ) != 0) + newLimit = i + groupSize; + i += groupSize; + } + if (newLimit == 0) + break; + } + } + #ifndef BLOCK_SORT_EXTERNAL_FLAGS + for (i = 0; i < blockSize;) + { + UInt32 groupSize = ((Indices[i] & ~0xC0000000) >> kNumBitsMax); + if ((Indices[i] & 0x40000000) != 0) + { + groupSize += ((Indices[i + 1] >> kNumBitsMax) << kNumExtra0Bits); + Indices[i + 1] &= kIndexMask; + } + Indices[i] &= kIndexMask; + groupSize++; + i += groupSize; + } + #endif + return Groups[0]; +} + diff --git a/C/BwtSort.h b/C/BwtSort.h new file mode 100755 index 0000000..9f6e095 --- /dev/null +++ b/C/BwtSort.h @@ -0,0 +1,30 @@ +/* BwtSort.h -- BWT block sorting +2009-02-07 : Igor Pavlov : Public domain */ + +#ifndef __BWT_SORT_H +#define __BWT_SORT_H + +#include "Types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize can be > 1M */ +/* #define BLOCK_SORT_EXTERNAL_FLAGS */ + +#ifdef BLOCK_SORT_EXTERNAL_FLAGS +#define BLOCK_SORT_EXTERNAL_SIZE(blockSize) ((((blockSize) + 31) >> 5)) +#else +#define BLOCK_SORT_EXTERNAL_SIZE(blockSize) 0 +#endif + +#define BLOCK_SORT_BUF_SIZE(blockSize) ((blockSize) * 2 + BLOCK_SORT_EXTERNAL_SIZE(blockSize) + (1 << 16)) + +UInt32 BlockSort(UInt32 *indices, const Byte *data, UInt32 blockSize); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/C/CpuArch.c b/C/CpuArch.c new file mode 100755 index 0000000..36e7680 --- /dev/null +++ b/C/CpuArch.c @@ -0,0 +1,168 @@ +/* CpuArch.c -- CPU specific code +2010-10-26: Igor Pavlov : Public domain */ + +#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) && !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)); + #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 + +static 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__ ( + "cpuid" + : "=a" (*a) , + "=b" (*b) , + "=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 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); + model = x86cpuid_GetModel(&p); + firm = x86cpuid_GetFirm(&p); + switch (firm) + { + case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && model == 0x100C)); + 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) +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/C/CpuArch.h b/C/CpuArch.h new file mode 100755 index 0000000..0a709bb --- /dev/null +++ b/C/CpuArch.h @@ -0,0 +1,155 @@ +/* CpuArch.h -- CPU specific code +2010-10-26: Igor Pavlov : Public domain */ + +#ifndef __CPU_ARCH_H +#define __CPU_ARCH_H + +#include "Types.h" + +EXTERN_C_BEGIN + +/* +MY_CPU_LE means that CPU is LITTLE ENDIAN. +If MY_CPU_LE is not defined, we don't know about that property of platform (it can be LITTLE ENDIAN). + +MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses. +If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of platform. +*/ + +#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__) +#define MY_CPU_AMD64 +#endif + +#if defined(MY_CPU_AMD64) || defined(_M_IA64) +#define MY_CPU_64BIT +#endif + +#if defined(_M_IX86) || defined(__i386__) +#define MY_CPU_X86 +#endif + +#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64) +#define MY_CPU_X86_OR_AMD64 +#endif + +#if defined(MY_CPU_X86) || defined(_M_ARM) +#define MY_CPU_32BIT +#endif + +#if defined(_WIN32) && defined(_M_ARM) +#define MY_CPU_ARM_LE +#endif + +#if defined(_WIN32) && defined(_M_IA64) +#define MY_CPU_IA64_LE +#endif + +#if defined(MY_CPU_X86_OR_AMD64) +#define MY_CPU_LE_UNALIGN +#endif + +#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE) || defined(MY_CPU_IA64_LE) || defined(__ARMEL__) || defined(__MIPSEL__) || defined(__LITTLE_ENDIAN__) +#define MY_CPU_LE +#endif + +#if defined(__BIG_ENDIAN__) +#define MY_CPU_BE +#endif + +#if defined(MY_CPU_LE) && defined(MY_CPU_BE) +Stop_Compiling_Bad_Endian +#endif + +#ifdef MY_CPU_LE_UNALIGN + +#define GetUi16(p) (*(const UInt16 *)(p)) +#define GetUi32(p) (*(const UInt32 *)(p)) +#define GetUi64(p) (*(const UInt64 *)(p)) +#define SetUi16(p, d) *(UInt16 *)(p) = (d); +#define SetUi32(p, d) *(UInt32 *)(p) = (d); +#define SetUi64(p, d) *(UInt64 *)(p) = (d); + +#else + +#define GetUi16(p) (((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, d) { UInt32 _x_ = (d); \ + ((Byte *)(p))[0] = (Byte)_x_; \ + ((Byte *)(p))[1] = (Byte)(_x_ >> 8); } + +#define SetUi32(p, d) { UInt32 _x_ = (d); \ + ((Byte *)(p))[0] = (Byte)_x_; \ + ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \ + ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \ + ((Byte *)(p))[3] = (Byte)(_x_ >> 24); } + +#define SetUi64(p, d) { UInt64 _x64_ = (d); \ + SetUi32(p, (UInt32)_x64_); \ + SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); } + +#endif + +#if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) + +#pragma intrinsic(_byteswap_ulong) +#pragma intrinsic(_byteswap_uint64) +#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) +#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p)) + +#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)) + +#endif + +#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]) + + +#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 +}; + +Bool x86cpuid_CheckAndRead(Cx86cpuid *p); +int x86cpuid_GetFirm(const Cx86cpuid *p); + +#define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F) +#define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F) +#define x86cpuid_GetStepping(p) ((p)->ver & 0xF) + +Bool CPU_Is_InOrder(); +Bool CPU_Is_Aes_Supported(); + +#endif + +EXTERN_C_END + +#endif diff --git a/C/Delta.c b/C/Delta.c new file mode 100755 index 0000000..93c93a1 --- /dev/null +++ b/C/Delta.c @@ -0,0 +1,62 @@ +/* Delta.c -- Delta converter +2009-05-26 : Igor Pavlov : Public domain */ + +#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/C/Delta.h b/C/Delta.h new file mode 100755 index 0000000..776cd45 --- /dev/null +++ b/C/Delta.h @@ -0,0 +1,23 @@ +/* Delta.h -- Delta converter +2009-04-15 : Igor Pavlov : Public domain */ + +#ifndef __DELTA_H +#define __DELTA_H + +#include "Types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/C/HuffEnc.c b/C/HuffEnc.c new file mode 100755 index 0000000..82dfb9a --- /dev/null +++ b/C/HuffEnc.c @@ -0,0 +1,146 @@ +/* HuffEnc.c -- functions for Huffman encoding +2009-09-02 : Igor Pavlov : Public domain */ + +#include "HuffEnc.h" +#include "Sort.h" + +#define kMaxLen 16 +#define NUM_BITS 10 +#define MASK ((1 << NUM_BITS) - 1) + +#define NUM_COUNTERS 64 + +#define HUFFMAN_SPEED_OPT + +void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymbols, UInt32 maxLen) +{ + UInt32 num = 0; + /* if (maxLen > 10) maxLen = 10; */ + { + UInt32 i; + + #ifdef HUFFMAN_SPEED_OPT + + UInt32 counters[NUM_COUNTERS]; + for (i = 0; i < NUM_COUNTERS; i++) + counters[i] = 0; + for (i = 0; i < numSymbols; i++) + { + UInt32 freq = freqs[i]; + counters[(freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1]++; + } + + for (i = 1; i < NUM_COUNTERS; i++) + { + UInt32 temp = counters[i]; + counters[i] = num; + num += temp; + } + + for (i = 0; i < numSymbols; i++) + { + UInt32 freq = freqs[i]; + if (freq == 0) + lens[i] = 0; + else + p[counters[((freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1)]++] = i | (freq << NUM_BITS); + } + counters[0] = 0; + HeapSort(p + counters[NUM_COUNTERS - 2], counters[NUM_COUNTERS - 1] - counters[NUM_COUNTERS - 2]); + + #else + + for (i = 0; i < numSymbols; i++) + { + UInt32 freq = freqs[i]; + if (freq == 0) + lens[i] = 0; + else + p[num++] = i | (freq << NUM_BITS); + } + HeapSort(p, num); + + #endif + } + + if (num < 2) + { + unsigned minCode = 0; + unsigned maxCode = 1; + if (num == 1) + { + maxCode = (unsigned)p[0] & MASK; + if (maxCode == 0) + maxCode++; + } + p[minCode] = 0; + p[maxCode] = 1; + lens[minCode] = lens[maxCode] = 1; + return; + } + + { + UInt32 b, e, i; + + i = b = e = 0; + do + { + UInt32 n, m, freq; + n = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++; + freq = (p[n] & ~MASK); + p[n] = (p[n] & MASK) | (e << NUM_BITS); + m = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++; + freq += (p[m] & ~MASK); + p[m] = (p[m] & MASK) | (e << NUM_BITS); + p[e] = (p[e] & MASK) | freq; + e++; + } + while (num - e > 1); + + { + UInt32 lenCounters[kMaxLen + 1]; + for (i = 0; i <= kMaxLen; i++) + lenCounters[i] = 0; + + p[--e] &= MASK; + lenCounters[1] = 2; + while (e > 0) + { + UInt32 len = (p[p[--e] >> NUM_BITS] >> NUM_BITS) + 1; + p[e] = (p[e] & MASK) | (len << NUM_BITS); + if (len >= maxLen) + for (len = maxLen - 1; lenCounters[len] == 0; len--); + lenCounters[len]--; + lenCounters[len + 1] += 2; + } + + { + UInt32 len; + i = 0; + for (len = maxLen; len != 0; len--) + { + UInt32 num; + for (num = lenCounters[len]; num != 0; num--) + lens[p[i++] & MASK] = (Byte)len; + } + } + + { + UInt32 nextCodes[kMaxLen + 1]; + { + UInt32 code = 0; + UInt32 len; + for (len = 1; len <= kMaxLen; len++) + nextCodes[len] = code = (code + lenCounters[len - 1]) << 1; + } + /* if (code + lenCounters[kMaxLen] - 1 != (1 << kMaxLen) - 1) throw 1; */ + + { + UInt32 i; + for (i = 0; i < numSymbols; i++) + p[i] = nextCodes[lens[i]]++; + } + } + } + } +} diff --git a/C/HuffEnc.h b/C/HuffEnc.h new file mode 100755 index 0000000..6508a83 --- /dev/null +++ b/C/HuffEnc.h @@ -0,0 +1,27 @@ +/* HuffEnc.h -- Huffman encoding +2009-02-07 : Igor Pavlov : Public domain */ + +#ifndef __HUFF_ENC_H +#define __HUFF_ENC_H + +#include "Types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* +Conditions: + num <= 1024 = 2 ^ NUM_BITS + Sum(freqs) < 4M = 2 ^ (32 - NUM_BITS) + maxLen <= 16 = kMaxLen + Num_Items(p) >= HUFFMAN_TEMP_SIZE(num) +*/ + +void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 num, UInt32 maxLen); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/C/LzFind.c b/C/LzFind.c new file mode 100755 index 0000000..f6c9e66 --- /dev/null +++ b/C/LzFind.c @@ -0,0 +1,761 @@ +/* LzFind.c -- Match finder for LZ algorithms +2009-04-22 : Igor Pavlov : Public domain */ + +#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 (~(kNormalizeStepMin - 1)) +#define kMaxHistorySize ((UInt32)3 << 30) + +#define kStartMaxLen 3 + +static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) +{ + if (!p->directInput) + { + alloc->Free(alloc, p->bufferBase); + p->bufferBase = 0; + } +} + +/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ + +static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) +{ + UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; + if (p->directInput) + { + p->blockSize = blockSize; + return 1; + } + if (p->bufferBase == 0 || p->blockSize != blockSize) + { + LzInWindow_Free(p, alloc); + p->blockSize = blockSize; + p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize); + } + return (p->bufferBase != 0); +} + +Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } +Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } + +UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } + +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; + if (p->directInput) + { + UInt32 curSize = 0xFFFFFFFF - p->streamPos; + 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 = p->stream->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 = 0; + p->directInput = 0; + p->hash = 0; + MatchFinder_SetDefaultSettings(p); + + for (i = 0; i < 256; i++) + { + UInt32 r = i; + int j; + for (j = 0; j < 8; j++) + r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); + p->crc[i] = r; + } +} + +static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->hash); + p->hash = 0; +} + +void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) +{ + MatchFinder_FreeThisClassMemory(p, alloc); + LzInWindow_Free(p, alloc); +} + +static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) +{ + size_t sizeInBytes = (size_t)num * sizeof(CLzRef); + if (sizeInBytes / sizeof(CLzRef) != num) + return 0; + return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); +} + +int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, + UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, + ISzAlloc *alloc) +{ + UInt32 sizeReserv; + if (historySize > kMaxHistorySize) + { + MatchFinder_Free(p, alloc); + return 0; + } + sizeReserv = historySize >> 1; + 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 - 1; + 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; + } + } + 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; + } + + { + UInt32 prevSize = p->hashSizeSum + p->numSons; + UInt32 newSize; + p->historySize = historySize; + p->hashSizeSum = hs; + p->cyclicBufferSize = newCyclicBufferSize; + p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); + newSize = p->hashSizeSum + p->numSons; + if (p->hash != 0 && prevSize == newSize) + return 1; + MatchFinder_FreeThisClassMemory(p, alloc); + p->hash = AllocRefs(newSize, alloc); + if (p->hash != 0) + { + 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(CMatchFinder *p) +{ + UInt32 i; + for (i = 0; i < p->hashSizeSum; i++) + p->hash[i] = kEmptyHashValue; + p->cyclicBufferPos = 0; + p->buffer = p->bufferBase; + p->pos = p->streamPos = p->cyclicBufferSize; + p->result = SZ_OK; + p->streamEndWasReached = 0; + MatchFinder_ReadBlock(p); + MatchFinder_SetLimits(p); +} + +static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) +{ + return (p->pos - p->historySize - 1) & kNormalizeMask; +} + +void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) +{ + UInt32 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->hashSizeSum + p->numSons); + 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 hashValue; 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; + +static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 offset; + GET_MATCHES_HEADER(2) + HASH2_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + 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[hashValue]; + p->hash[hashValue] = p->pos; + offset = 0; + GET_MATCHES_FOOTER(offset, 2) +} + +static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 hash2Value, delta2, maxLen, offset; + GET_MATCHES_HEADER(3) + + HASH3_CALC; + + delta2 = p->pos - p->hash[hash2Value]; + curMatch = p->hash[kFix3HashSize + hashValue]; + + p->hash[hash2Value] = + p->hash[kFix3HashSize + hashValue] = p->pos; + + + maxLen = 2; + offset = 0; + if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) + { + for (; maxLen != lenLimit; maxLen++) + if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) + break; + distances[0] = maxLen; + distances[1] = delta2 - 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 hash2Value, hash3Value, delta2, delta3, maxLen, offset; + GET_MATCHES_HEADER(4) + + HASH4_CALC; + + delta2 = p->pos - p->hash[ hash2Value]; + delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; + curMatch = p->hash[kFix4HashSize + hashValue]; + + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = + p->hash[kFix4HashSize + hashValue] = p->pos; + + maxLen = 1; + offset = 0; + if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) + { + distances[0] = maxLen = 2; + distances[1] = delta2 - 1; + offset = 2; + } + if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) + { + maxLen = 3; + distances[offset + 1] = delta3 - 1; + offset += 2; + delta2 = delta3; + } + if (offset != 0) + { + for (; maxLen != lenLimit; maxLen++) + if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) + break; + distances[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 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; + GET_MATCHES_HEADER(4) + + HASH4_CALC; + + delta2 = p->pos - p->hash[ hash2Value]; + delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; + curMatch = p->hash[kFix4HashSize + hashValue]; + + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = + p->hash[kFix4HashSize + hashValue] = p->pos; + + maxLen = 1; + offset = 0; + if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) + { + distances[0] = maxLen = 2; + distances[1] = delta2 - 1; + offset = 2; + } + if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) + { + maxLen = 3; + distances[offset + 1] = delta3 - 1; + offset += 2; + delta2 = delta3; + } + if (offset != 0) + { + for (; maxLen != lenLimit; maxLen++) + if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) + break; + distances[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 +} + +UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 offset; + GET_MATCHES_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + 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[hashValue]; + p->hash[hashValue] = 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[hashValue]; + p->hash[hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 hash2Value; + SKIP_HEADER(3) + HASH3_CALC; + curMatch = p->hash[kFix3HashSize + hashValue]; + p->hash[hash2Value] = + p->hash[kFix3HashSize + hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 hash2Value, hash3Value; + SKIP_HEADER(4) + HASH4_CALC; + curMatch = p->hash[kFix4HashSize + hashValue]; + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = p->pos; + p->hash[kFix4HashSize + hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 hash2Value, hash3Value; + SKIP_HEADER(4) + HASH4_CALC; + curMatch = p->hash[kFix4HashSize + hashValue]; + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = + p->hash[kFix4HashSize + hashValue] = p->pos; + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS + } + while (--num != 0); +} + +void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + 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->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; + vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; + vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; + if (!p->btMode) + { + vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; + } + 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 + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; + } +} diff --git a/C/LzFind.h b/C/LzFind.h new file mode 100755 index 0000000..7ebdfa4 --- /dev/null +++ b/C/LzFind.h @@ -0,0 +1,115 @@ +/* LzFind.h -- Match finder for LZ algorithms +2009-04-22 : Igor Pavlov : Public domain */ + +#ifndef __LZ_FIND_H +#define __LZ_FIND_H + +#include "Types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +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) */ + + UInt32 matchMaxLen; + CLzRef *hash; + CLzRef *son; + UInt32 hashMask; + UInt32 cutValue; + + Byte *bufferBase; + ISeqInStream *stream; + int streamEndWasReached; + + UInt32 blockSize; + UInt32 keepSizeBefore; + UInt32 keepSizeAfter; + + UInt32 numHashBytes; + int directInput; + size_t directInputRem; + int btMode; + int bigHash; + UInt32 historySize; + UInt32 fixedHashSize; + UInt32 hashSizeSum; + UInt32 numSons; + SRes result; + UInt32 crc[256]; +} CMatchFinder; + +#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) +#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)]) + +#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) + +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, + ISzAlloc *alloc); +void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); +void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 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 Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index); +typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); +typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); +typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); +typedef void (*Mf_Skip_Func)(void *object, UInt32); + +typedef struct _IMatchFinder +{ + Mf_Init_Func Init; + Mf_GetIndexByte_Func GetIndexByte; + Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; + Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; + Mf_GetMatches_Func GetMatches; + Mf_Skip_Func Skip; +} IMatchFinder; + +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); + +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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/C/LzFindMt.c b/C/LzFindMt.c new file mode 100755 index 0000000..db95590 --- /dev/null +++ b/C/LzFindMt.c @@ -0,0 +1,793 @@ +/* LzFindMt.c -- multithreaded Match finder for LZ algorithms +2009-09-20 : Igor Pavlov : Public domain */ + +#include "LzHash.h" + +#include "LzFindMt.h" + +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); +} + +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); + } + 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 */ + +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; +} + +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, unsigned (MY_STD_CALL *startAddress)(void *), 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, unsigned (MY_STD_CALL *startAddress)(void *), 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)), hashMask = hashMask; crc = crc; ) +DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask) +DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask) +DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask) +/* DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) */ + +void HashThreadFunc(CMatchFinderMt *mt) +{ + CMtSync *p = &mt->hashSync; + for (;;) + { + UInt32 numProcessedBlocks = 0; + Event_Wait(&p->canStart); + Event_Set(&p->wasStarted); + 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 = MatchFinder_GetPointerToCurrentPos(mf); + const Byte *afterPtr; + MatchFinder_MoveBlock(mf); + afterPtr = MatchFinder_GetPointerToCurrentPos(mf); + mt->pointerToCurPos -= beforePtr - afterPtr; + mt->buffer -= beforePtr - afterPtr; + } + 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, 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] += num; + } + mf->pos += num; + mf->buffer += num; + } + } + + Semaphore_Release1(&p->filledSemaphore); + } + } +} + +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 + +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 + +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; + for (; p->hashNumAvail != 0; p->hashNumAvail--) + distances[curPos++] = 0; + break; + } + { + 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; +} + +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, 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 = 0; + MtSync_Construct(&p->hashSync); + MtSync_Construct(&p->btSync); +} + +void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->hashBuf); + p->hashBuf = 0; +} + +void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc) +{ + MtSync_Destruct(&p->hashSync); + MtSync_Destruct(&p->btSync); + MatchFinderMt_FreeMem(p, alloc); +} + +#define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks) +#define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks) + +static unsigned MY_STD_CALL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } +static unsigned MY_STD_CALL BtThreadFunc2(void *p) +{ + Byte allocaDummy[0x180]; + int i = 0; + for (i = 0; i < 16; i++) + allocaDummy[i] = (Byte)i; + BtThreadFunc((CMatchFinderMt *)p); + return 0; +} + +SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc) +{ + CMatchFinder *mf = p->MatchFinder; + p->historySize = historySize; + if (kMtBtBlockSize <= matchMaxLen * 4) + return SZ_ERROR_PARAM; + if (p->hashBuf == 0) + { + p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32)); + if (p->hashBuf == 0) + 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 */ +void MatchFinderMt_Init(CMatchFinderMt *p) +{ + CMatchFinder *mf = p->MatchFinder; + p->btBufPos = p->btBufPosLimit = 0; + p->hashBufPos = p->hashBufPosLimit = 0; + MatchFinder_Init(mf); + p->pointerToCurPos = 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(); */ +} + +void MatchFinderMt_Normalize(CMatchFinderMt *p) +{ + MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize); + p->lzPos = p->historySize + 1; +} + +void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p) +{ + 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); +} + +const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p) +{ + return p->pointerToCurPos; +} + +#define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p); + +UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p) +{ + GET_NEXT_BLOCK_IF_REQUIRED; + return p->btNumAvailBytes; +} + +Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index) +{ + return p->pointerToCurPos[index]; +} + +UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) +{ + UInt32 hash2Value, curMatch2; + UInt32 *hash = p->hash; + const Byte *cur = p->pointerToCurPos; + UInt32 lzPos = p->lzPos; + MT_HASH2_CALC + + curMatch2 = hash[hash2Value]; + hash[hash2Value] = lzPos; + + if (curMatch2 >= matchMinPos) + if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) + { + *distances++ = 2; + *distances++ = lzPos - curMatch2 - 1; + } + return distances; +} + +UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) +{ + UInt32 hash2Value, hash3Value, curMatch2, curMatch3; + UInt32 *hash = p->hash; + const Byte *cur = p->pointerToCurPos; + UInt32 lzPos = p->lzPos; + MT_HASH3_CALC + + curMatch2 = hash[ hash2Value]; + curMatch3 = hash[kFix3HashSize + hash3Value]; + + hash[ hash2Value] = + hash[kFix3HashSize + hash3Value] = + 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; +} + +/* +UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) +{ + UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4; + UInt32 *hash = p->hash; + const Byte *cur = p->pointerToCurPos; + UInt32 lzPos = p->lzPos; + MT_HASH4_CALC + + curMatch2 = hash[ hash2Value]; + curMatch3 = hash[kFix3HashSize + hash3Value]; + curMatch4 = hash[kFix4HashSize + hash4Value]; + + hash[ hash2Value] = + hash[kFix3HashSize + hash3Value] = + hash[kFix4HashSize + hash4Value] = + 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++; + +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) + { + *distances++ = *btBuf++; + *distances++ = *btBuf++; + } + } + INCREASE_LZ_POS + return len; +} + +UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances) +{ + const UInt32 *btBuf = p->btBuf + p->btBufPos; + UInt32 len = *btBuf++; + p->btBufPos += 1 + len; + + if (len == 0) + { + 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 + { + *distances2++ = *btBuf++; + *distances2++ = *btBuf++; + } + 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); + +void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num) +{ + SKIP_HEADER2_MT { p->btNumAvailBytes--; + SKIP_FOOTER_MT +} + +void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num) +{ + SKIP_HEADER_MT(2) + UInt32 hash2Value; + MT_HASH2_CALC + hash[hash2Value] = p->lzPos; + SKIP_FOOTER_MT +} + +void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num) +{ + SKIP_HEADER_MT(3) + UInt32 hash2Value, hash3Value; + MT_HASH3_CALC + hash[kFix3HashSize + hash3Value] = + hash[ hash2Value] = + p->lzPos; + SKIP_FOOTER_MT +} + +/* +void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num) +{ + SKIP_HEADER_MT(4) + UInt32 hash2Value, hash3Value, hash4Value; + MT_HASH4_CALC + hash[kFix4HashSize + hash4Value] = + hash[kFix3HashSize + hash3Value] = + hash[ hash2Value] = + p->lzPos; + SKIP_FOOTER_MT +} +*/ + +void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable) +{ + vTable->Init = (Mf_Init_Func)MatchFinderMt_Init; + vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte; + vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes; + vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos; + vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches; + switch(p->MatchFinder->numHashBytes) + { + case 2: + p->GetHeadsFunc = GetHeads2; + p->MixMatchesFunc = (Mf_Mix_Matches)0; + 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->GetHeadsFunc = 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/C/LzFindMt.h b/C/LzFindMt.h new file mode 100755 index 0000000..17ed237 --- /dev/null +++ b/C/LzFindMt.h @@ -0,0 +1,105 @@ +/* LzFindMt.h -- multithreaded Match finder for LZ algorithms +2009-02-07 : Igor Pavlov : Public domain */ + +#ifndef __LZ_FIND_MT_H +#define __LZ_FIND_MT_H + +#include "LzFind.h" +#include "Threads.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#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; + 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, ISzAlloc *alloc); +SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc); +void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable); +void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/C/LzHash.h b/C/LzHash.h new file mode 100755 index 0000000..b2f0e3c --- /dev/null +++ b/C/LzHash.h @@ -0,0 +1,54 @@ +/* LzHash.h -- HASH functions for LZ algorithms +2009-02-07 : 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 hashValue = cur[0] | ((UInt32)cur[1] << 8); + +#define HASH3_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } + +#define HASH4_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ + hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; } + +#define HASH5_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ + hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \ + hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \ + hash4Value &= (kHash4Size - 1); } + +/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ +#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; + + +#define MT_HASH2_CALC \ + hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); + +#define MT_HASH3_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } + +#define MT_HASH4_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ + hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } + +#endif diff --git a/C/Lzma2Dec.c b/C/Lzma2Dec.c new file mode 100755 index 0000000..8f24067 --- /dev/null +++ b/C/Lzma2Dec.c @@ -0,0 +1,356 @@ +/* Lzma2Dec.c -- LZMA2 Decoder +2009-05-03 : Igor Pavlov : Public domain */ + +/* #define SHOW_DEBUG_INFO */ + +#ifdef SHOW_DEBUG_INFO +#include +#endif + +#include + +#include "Lzma2Dec.h" + +/* +00000000 - EOS +00000001 U U - Uncompressed Reset Dic +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 + new prop +111uuuuu U U P P S - LZMA reset state + new prop + reset dic + + u, U - Unpack Size + P - Pack Size + S - Props +*/ + +#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_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0) + +#define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3) +#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2) + +#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, ISzAlloc *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, ISzAlloc *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->needInitDic = True; + p->needInitState = True; + p->needInitProp = True; + LzmaDec_Init(&p->decoder); +} + +static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b) +{ + switch(p->state) + { + case LZMA2_STATE_CONTROL: + p->control = b; + PRF(printf("\n %4X ", p->decoder.dicPos)); + PRF(printf(" %2X", b)); + if (p->control == 0) + return LZMA2_STATE_FINISHED; + if (LZMA2_IS_UNCOMPRESSED_STATE(p)) + { + if ((p->control & 0x7F) > 2) + return LZMA2_STATE_ERROR; + p->unpackSize = 0; + } + else + p->unpackSize = (UInt32)(p->control & 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(" %8d", 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++; + PRF(printf(" %8d", p->packSize)); + return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP: + (p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA); + + case LZMA2_STATE_PROP: + { + int lc, lp; + if (b >= (9 * 5 * 5)) + return LZMA2_STATE_ERROR; + lc = b % 9; + b /= 9; + p->decoder.prop.pb = b / 5; + lp = b % 5; + if (lc + lp > LZMA2_LCLP_MAX) + return LZMA2_STATE_ERROR; + p->decoder.prop.lc = lc; + p->decoder.prop.lp = lp; + p->needInitProp = False; + 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_FINISHED) + { + SizeT dicPos = p->decoder.dicPos; + if (p->state == LZMA2_STATE_ERROR) + return SZ_ERROR_DATA; + if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_OK; + } + if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT) + { + if (*srcLen == inSize) + { + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + (*srcLen)++; + p->state = Lzma2Dec_UpdateState(p, *src++); + continue; + } + { + SizeT destSizeCur = dicLimit - dicPos; + SizeT srcSizeCur = inSize - *srcLen; + ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY; + + if (p->unpackSize <= destSizeCur) + { + destSizeCur = (SizeT)p->unpackSize; + curFinishMode = LZMA_FINISH_END; + } + + if (LZMA2_IS_UNCOMPRESSED_STATE(p)) + { + if (*srcLen == inSize) + { + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + + if (p->state == LZMA2_STATE_DATA) + { + Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC); + if (initDic) + p->needInitProp = p->needInitState = True; + else if (p->needInitDic) + return SZ_ERROR_DATA; + p->needInitDic = False; + LzmaDec_InitDicAndState(&p->decoder, initDic, False); + } + + if (srcSizeCur > destSizeCur) + srcSizeCur = destSizeCur; + + if (srcSizeCur == 0) + return SZ_ERROR_DATA; + + LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur); + + src += srcSizeCur; + *srcLen += srcSizeCur; + p->unpackSize -= (UInt32)srcSizeCur; + p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT; + } + else + { + SizeT outSizeProcessed; + SRes res; + + if (p->state == LZMA2_STATE_DATA) + { + int mode = LZMA2_GET_LZMA_MODE(p); + Bool initDic = (mode == 3); + Bool initState = (mode > 0); + if ((!initDic && p->needInitDic) || (!initState && p->needInitState)) + return SZ_ERROR_DATA; + + LzmaDec_InitDicAndState(&p->decoder, initDic, initState); + p->needInitDic = False; + p->needInitState = False; + p->state = LZMA2_STATE_DATA_CONT; + } + if (srcSizeCur > p->packSize) + srcSizeCur = (SizeT)p->packSize; + + res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status); + + src += srcSizeCur; + *srcLen += srcSizeCur; + p->packSize -= (UInt32)srcSizeCur; + + outSizeProcessed = p->decoder.dicPos - dicPos; + p->unpackSize -= (UInt32)outSizeProcessed; + + RINOK(res); + if (*status == LZMA_STATUS_NEEDS_MORE_INPUT) + return res; + + if (srcSizeCur == 0 && outSizeProcessed == 0) + { + if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK || + p->unpackSize != 0 || p->packSize != 0) + return SZ_ERROR_DATA; + p->state = LZMA2_STATE_CONTROL; + } + if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) + *status = LZMA_STATUS_NOT_FINISHED; + } + } + } + *status = LZMA_STATUS_FINISHED_WITH_MARK; + return SZ_OK; +} + +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 srcSizeCur = inSize, outSizeCur, dicPos; + ELzmaFinishMode curFinishMode; + SRes res; + if (p->decoder.dicPos == p->decoder.dicBufSize) + p->decoder.dicPos = 0; + dicPos = p->decoder.dicPos; + if (outSize > p->decoder.dicBufSize - dicPos) + { + outSizeCur = p->decoder.dicBufSize; + curFinishMode = LZMA_FINISH_ANY; + } + else + { + outSizeCur = dicPos + outSize; + curFinishMode = finishMode; + } + + res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status); + src += srcSizeCur; + inSize -= srcSizeCur; + *srcLen += srcSizeCur; + outSizeCur = p->decoder.dicPos - dicPos; + memcpy(dest, p->decoder.dic + dicPos, outSizeCur); + dest += outSizeCur; + outSize -= outSizeCur; + *destLen += outSizeCur; + if (res != 0) + return res; + if (outSizeCur == 0 || outSize == 0) + return SZ_OK; + } +} + +SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc) +{ + CLzma2Dec decoder; + SRes res; + SizeT outSize = *destLen, inSize = *srcLen; + Byte props[LZMA_PROPS_SIZE]; + + Lzma2Dec_Construct(&decoder); + + *destLen = *srcLen = 0; + *status = LZMA_STATUS_NOT_SPECIFIED; + decoder.decoder.dic = dest; + decoder.decoder.dicBufSize = outSize; + + RINOK(Lzma2Dec_GetOldProps(prop, props)); + RINOK(LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc)); + + *srcLen = inSize; + res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status); + *destLen = decoder.decoder.dicPos; + if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) + res = SZ_ERROR_INPUT_EOF; + + LzmaDec_FreeProbs(&decoder.decoder, alloc); + return res; +} diff --git a/C/Lzma2Dec.h b/C/Lzma2Dec.h new file mode 100755 index 0000000..827698d --- /dev/null +++ b/C/Lzma2Dec.h @@ -0,0 +1,84 @@ +/* Lzma2Dec.h -- LZMA2 Decoder +2009-05-03 : Igor Pavlov : Public domain */ + +#ifndef __LZMA2_DEC_H +#define __LZMA2_DEC_H + +#include "LzmaDec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* ---------- State Interface ---------- */ + +typedef struct +{ + CLzmaDec decoder; + UInt32 packSize; + UInt32 unpackSize; + int state; + Byte control; + Bool needInitDic; + Bool needInitState; + Bool needInitProp; +} 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, ISzAlloc *alloc); +SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *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); + + +/* ---------- 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, ISzAlloc *alloc); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/C/Lzma2Enc.c b/C/Lzma2Enc.c new file mode 100755 index 0000000..35f6ed7 --- /dev/null +++ b/C/Lzma2Enc.c @@ -0,0 +1,477 @@ +/* Lzma2Enc.c -- LZMA2 Encoder +2010-09-24 : Igor Pavlov : Public domain */ + +/* #include */ +#include + +/* #define _7ZIP_ST */ + +#include "Lzma2Enc.h" + +#ifndef _7ZIP_ST +#include "MtCoder.h" +#else +#define NUM_MT_CODER_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 */ + +/* ---------- CLzma2EncInt ---------- */ + +typedef struct +{ + CLzmaEncHandle enc; + UInt64 srcPos; + Byte props; + Bool needInitState; + Bool needInitProp; +} CLzma2EncInt; + +static SRes Lzma2EncInt_Init(CLzma2EncInt *p, const CLzma2EncProps *props) +{ + Byte propsEncoded[LZMA_PROPS_SIZE]; + SizeT propsSize = LZMA_PROPS_SIZE; + RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps)); + RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize)); + p->srcPos = 0; + p->props = propsEncoded[0]; + p->needInitState = True; + p->needInitProp = True; + return SZ_OK; +} + +SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize, + ISzAlloc *alloc, ISzAlloc *allocBig); +SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, + UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *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); + + +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 (outStream->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->props; + + p->needInitProp = False; + p->needInitState = False; + destPos += packSize; + p->srcPos += unpackSize; + + if (outStream) + if (outStream->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->numTotalThreads = -1; + p->numBlockThreads = -1; + p->blockSize = 0; +} + +void Lzma2EncProps_Normalize(CLzma2EncProps *p) +{ + int t1, t1n, t2, t3; + { + CLzmaEncProps lzmaProps = p->lzmaProps; + LzmaEncProps_Normalize(&lzmaProps); + t1n = lzmaProps.numThreads; + } + + t1 = p->lzmaProps.numThreads; + t2 = p->numBlockThreads; + t3 = p->numTotalThreads; + + if (t2 > NUM_MT_CODER_THREADS_MAX) + t2 = NUM_MT_CODER_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 > NUM_MT_CODER_THREADS_MAX) + t2 = NUM_MT_CODER_THREADS_MAX; + } + else if (t1 <= 0) + { + t1 = t3 / t2; + if (t1 == 0) + t1 = 1; + } + else + t3 = t1n * t2; + + p->lzmaProps.numThreads = t1; + p->numBlockThreads = t2; + p->numTotalThreads = t3; + LzmaEncProps_Normalize(&p->lzmaProps); + + if (p->blockSize == 0) + { + UInt32 dictSize = p->lzmaProps.dictSize; + UInt64 blockSize = (UInt64)dictSize << 2; + const UInt32 kMinSize = (UInt32)1 << 20; + const UInt32 kMaxSize = (UInt32)1 << 28; + if (blockSize < kMinSize) blockSize = kMinSize; + if (blockSize > kMaxSize) blockSize = kMaxSize; + if (blockSize < dictSize) blockSize = dictSize; + p->blockSize = (size_t)blockSize; + } +} + +static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize) +{ + return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK; +} + +/* ---------- Lzma2 ---------- */ + +typedef struct +{ + Byte propEncoded; + CLzma2EncProps props; + + Byte *outBuf; + + ISzAlloc *alloc; + ISzAlloc *allocBig; + + CLzma2EncInt coders[NUM_MT_CODER_THREADS_MAX]; + + #ifndef _7ZIP_ST + CMtCoder mtCoder; + #endif + +} CLzma2Enc; + + +/* ---------- Lzma2EncThread ---------- */ + +static SRes Lzma2Enc_EncodeMt1(CLzma2EncInt *p, CLzma2Enc *mainEncoder, + ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress) +{ + UInt64 packTotal = 0; + SRes res = SZ_OK; + + if (mainEncoder->outBuf == 0) + { + mainEncoder->outBuf = (Byte *)IAlloc_Alloc(mainEncoder->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX); + if (mainEncoder->outBuf == 0) + return SZ_ERROR_MEM; + } + RINOK(Lzma2EncInt_Init(p, &mainEncoder->props)); + RINOK(LzmaEnc_PrepareForLzma2(p->enc, inStream, LZMA2_KEEP_WINDOW_SIZE, + mainEncoder->alloc, mainEncoder->allocBig)); + for (;;) + { + size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX; + res = Lzma2EncInt_EncodeSubblock(p, mainEncoder->outBuf, &packSize, outStream); + if (res != SZ_OK) + break; + packTotal += packSize; + res = Progress(progress, p->srcPos, packTotal); + if (res != SZ_OK) + break; + if (packSize == 0) + break; + } + LzmaEnc_Finish(p->enc); + if (res == SZ_OK) + { + Byte b = 0; + if (outStream->Write(outStream, &b, 1) != 1) + return SZ_ERROR_WRITE; + } + return res; +} + +#ifndef _7ZIP_ST + +typedef struct +{ + IMtCoderCallback funcTable; + CLzma2Enc *lzma2Enc; +} CMtCallbackImp; + +static SRes MtCallbackImp_Code(void *pp, unsigned index, Byte *dest, size_t *destSize, + const Byte *src, size_t srcSize, int finished) +{ + CMtCallbackImp *imp = (CMtCallbackImp *)pp; + CLzma2Enc *mainEncoder = imp->lzma2Enc; + CLzma2EncInt *p = &mainEncoder->coders[index]; + + SRes res = SZ_OK; + { + size_t destLim = *destSize; + *destSize = 0; + + if (srcSize != 0) + { + RINOK(Lzma2EncInt_Init(p, &mainEncoder->props)); + + RINOK(LzmaEnc_MemPrepare(p->enc, src, srcSize, LZMA2_KEEP_WINDOW_SIZE, + mainEncoder->alloc, mainEncoder->allocBig)); + + while (p->srcPos < srcSize) + { + size_t packSize = destLim - *destSize; + res = Lzma2EncInt_EncodeSubblock(p, dest + *destSize, &packSize, NULL); + if (res != SZ_OK) + break; + *destSize += packSize; + + if (packSize == 0) + { + res = SZ_ERROR_FAIL; + break; + } + + if (MtProgress_Set(&mainEncoder->mtCoder.mtProgress, index, p->srcPos, *destSize) != SZ_OK) + { + res = SZ_ERROR_PROGRESS; + break; + } + } + LzmaEnc_Finish(p->enc); + if (res != SZ_OK) + return res; + } + if (finished) + { + if (*destSize == destLim) + return SZ_ERROR_OUTPUT_EOF; + dest[(*destSize)++] = 0; + } + } + return res; +} + +#endif + +/* ---------- Lzma2Enc ---------- */ + +CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzma2Enc *p = (CLzma2Enc *)alloc->Alloc(alloc, sizeof(CLzma2Enc)); + if (p == 0) + return NULL; + Lzma2EncProps_Init(&p->props); + Lzma2EncProps_Normalize(&p->props); + p->outBuf = 0; + p->alloc = alloc; + p->allocBig = allocBig; + { + unsigned i; + for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++) + p->coders[i].enc = 0; + } + #ifndef _7ZIP_ST + MtCoder_Construct(&p->mtCoder); + #endif + + return p; +} + +void Lzma2Enc_Destroy(CLzma2EncHandle pp) +{ + CLzma2Enc *p = (CLzma2Enc *)pp; + unsigned i; + for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++) + { + CLzma2EncInt *t = &p->coders[i]; + if (t->enc) + { + LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig); + t->enc = 0; + } + } + + #ifndef _7ZIP_ST + MtCoder_Destruct(&p->mtCoder); + #endif + + IAlloc_Free(p->alloc, p->outBuf); + IAlloc_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; +} + +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; +} + +SRes Lzma2Enc_Encode(CLzma2EncHandle pp, + ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress) +{ + CLzma2Enc *p = (CLzma2Enc *)pp; + int i; + + for (i = 0; i < p->props.numBlockThreads; i++) + { + CLzma2EncInt *t = &p->coders[i]; + if (t->enc == NULL) + { + t->enc = LzmaEnc_Create(p->alloc); + if (t->enc == NULL) + return SZ_ERROR_MEM; + } + } + + #ifndef _7ZIP_ST + if (p->props.numBlockThreads <= 1) + #endif + return Lzma2Enc_EncodeMt1(&p->coders[0], p, outStream, inStream, progress); + + #ifndef _7ZIP_ST + + { + CMtCallbackImp mtCallback; + + mtCallback.funcTable.Code = MtCallbackImp_Code; + mtCallback.lzma2Enc = p; + + p->mtCoder.progress = progress; + p->mtCoder.inStream = inStream; + p->mtCoder.outStream = outStream; + p->mtCoder.alloc = p->alloc; + p->mtCoder.mtCallback = &mtCallback.funcTable; + + p->mtCoder.blockSize = p->props.blockSize; + p->mtCoder.destBlockSize = p->props.blockSize + (p->props.blockSize >> 10) + 16; + p->mtCoder.numThreads = p->props.numBlockThreads; + + return MtCoder_Code(&p->mtCoder); + } + #endif +} diff --git a/C/Lzma2Enc.h b/C/Lzma2Enc.h new file mode 100755 index 0000000..38830e5 --- /dev/null +++ b/C/Lzma2Enc.h @@ -0,0 +1,66 @@ +/* Lzma2Enc.h -- LZMA2 Encoder +2009-02-07 : Igor Pavlov : Public domain */ + +#ifndef __LZMA2_ENC_H +#define __LZMA2_ENC_H + +#include "LzmaEnc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + CLzmaEncProps lzmaProps; + size_t blockSize; + int numBlockThreads; + int numTotalThreads; +} CLzma2EncProps; + +void Lzma2EncProps_Init(CLzma2EncProps *p); +void Lzma2EncProps_Normalize(CLzma2EncProps *p); + +/* ---------- CLzmaEnc2Handle Interface ---------- */ + +/* Lzma2Enc_* functions can return the following exit codes: +Returns: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater in props + SZ_ERROR_WRITE - Write callback error + SZ_ERROR_PROGRESS - some break from progress callback + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) +*/ + +typedef void * CLzma2EncHandle; + +CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig); +void Lzma2Enc_Destroy(CLzma2EncHandle p); +SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props); +Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p); +SRes Lzma2Enc_Encode(CLzma2EncHandle p, + ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress); + +/* ---------- One Call Interface ---------- */ + +/* Lzma2Encode +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) +*/ + +/* +SRes Lzma2Encode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + const CLzmaEncProps *props, Byte *propsEncoded, int writeEndMark, + ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); +*/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/C/Lzma86.h b/C/Lzma86.h new file mode 100755 index 0000000..6425bb8 --- /dev/null +++ b/C/Lzma86.h @@ -0,0 +1,111 @@ +/* Lzma86.h -- LZMA + x86 (BCJ) Filter +2009-08-14 : Igor Pavlov : Public domain */ + +#ifndef __LZMA86_H +#define __LZMA86_H + +#include "Types.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/C/Lzma86Dec.c b/C/Lzma86Dec.c new file mode 100755 index 0000000..760a447 --- /dev/null +++ b/C/Lzma86Dec.c @@ -0,0 +1,56 @@ +/* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder +2009-08-14 : Igor Pavlov : Public domain */ + +#include "Lzma86.h" + +#include "Alloc.h" +#include "Bra.h" +#include "LzmaDec.h" + +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } +static void SzFree(void *p, void *address) { p = p; MyFree(address); } + +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) +{ + ISzAlloc g_Alloc = { SzAlloc, SzFree }; + 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/C/Lzma86Enc.c b/C/Lzma86Enc.c new file mode 100755 index 0000000..a29c605 --- /dev/null +++ b/C/Lzma86Enc.c @@ -0,0 +1,108 @@ +/* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder +2009-08-14 : Igor Pavlov : Public domain */ + +#include + +#include "Lzma86.h" + +#include "Alloc.h" +#include "Bra.h" +#include "LzmaEnc.h" + +#define SZE_OUT_OVERFLOW SZE_DATA_ERROR + +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } +static void SzFree(void *p, void *address) { p = p; MyFree(address); } + +int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, + int level, UInt32 dictSize, int filterMode) +{ + ISzAlloc g_Alloc = { SzAlloc, SzFree }; + 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] = (bestIsFiltered ? 1 : 0); + *destLen = LZMA86_HEADER_SIZE + minSize; + } + if (useFilter) + MyFree(filteredStream); + return mainResult; +} diff --git a/C/LzmaDec.c b/C/LzmaDec.c new file mode 100755 index 0000000..4fdc11d --- /dev/null +++ b/C/LzmaDec.c @@ -0,0 +1,999 @@ +/* LzmaDec.c -- LZMA Decoder +2009-09-20 : Igor Pavlov : Public domain */ + +#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 GET_BIT(p, i) GET_BIT2(p, i, ; , ;) + +#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } +#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 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 kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenChoice 0 +#define LenChoice2 (LenChoice + 1) +#define LenLow (LenChoice2 + 1) +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + + +#define kNumStates 12 +#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 + kLenNumMidSymbols + kLenNumHighSymbols) + +#define IsMatch 0 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define IsRep0Long (IsRepG2 + kNumStates) +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) +#define LenCoder (Align + kAlignTableSize) +#define RepLenCoder (LenCoder + kNumLenProbs) +#define Literal (RepLenCoder + kNumLenProbs) + +#define LZMA_BASE_SIZE 1846 +#define LZMA_LIT_SIZE 768 + +#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) + +#if Literal != LZMA_BASE_SIZE +StopCompilingDueBUG +#endif + +#define LZMA_DIC_MIN (1 << 12) + +/* First LZMA-symbol is always decoded. +And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization +Out: + Result: + SZ_OK - OK + SZ_ERROR_DATA - Error + p->remainLen: + < kMatchSpecLenStart : normal remain + = kMatchSpecLenStart : finished + = kMatchSpecLenStart + 1 : Flush marker + = kMatchSpecLenStart + 2 : State Init Marker +*/ + +static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +{ + CLzmaProb *probs = p->probs; + + unsigned state = 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 lpMask = ((unsigned)1 << (p->prop.lp)) - 1; + unsigned lc = p->prop.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 = processedPos & pbMask; + + prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; + IF_BIT_0(prob) + { + unsigned symbol; + UPDATE_0(prob); + prob = probs + Literal; + if (checkDicSize != 0 || processedPos != 0) + prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + + (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); + + if (state < kNumLitStates) + { + state -= (state < 4) ? state : 3; + symbol = 1; + do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); + } + else + { + unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + unsigned offs = 0x100; + state -= (state < 10) ? 3 : 6; + symbol = 1; + do + { + unsigned bit; + CLzmaProb *probLit; + matchByte <<= 1; + bit = (matchByte & offs); + probLit = prob + offs + bit + symbol; + GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) + } + while (symbol < 0x100); + } + dic[dicPos++] = (Byte)symbol; + processedPos++; + continue; + } + else + { + UPDATE_1(prob); + prob = probs + IsRep + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + state += kNumStates; + prob = probs + LenCoder; + } + else + { + UPDATE_1(prob); + if (checkDicSize == 0 && processedPos == 0) + return SZ_ERROR_DATA; + prob = probs + IsRepG0 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; + 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; + } + { + unsigned limit, offset; + CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + limit = (1 << kLenNumLowBits); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenChoice2; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + limit = (1 << kLenNumMidBits); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + limit = (1 << kLenNumHighBits); + } + } + TREE_DECODE(probLen, limit, len); + len += offset; + } + + 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; + int numDirectBits = (int)(((distance >> 1) - 1)); + distance = (2 | (distance & 1)); + if (posSlot < kEndPosModelIndex) + { + distance <<= numDirectBits; + prob = probs + SpecPos + distance - posSlot - 1; + { + UInt32 mask = 1; + unsigned i = 1; + do + { + GET_BIT2(prob + i, i, ; , distance |= mask); + mask <<= 1; + } + while (--numDirectBits != 0); + } + } + 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 != 0); + prob = probs + Align; + distance <<= kNumAlignBits; + { + unsigned i = 1; + GET_BIT2(prob + i, i, ; , distance |= 1); + GET_BIT2(prob + i, i, ; , distance |= 2); + GET_BIT2(prob + i, i, ; , distance |= 4); + GET_BIT2(prob + i, i, ; , distance |= 8); + } + if (distance == (UInt32)0xFFFFFFFF) + { + len += kMatchSpecLenStart; + state -= kNumStates; + break; + } + } + } + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + rep0 = distance + 1; + if (checkDicSize == 0) + { + if (distance >= processedPos) + return SZ_ERROR_DATA; + } + else if (distance >= checkDicSize) + return SZ_ERROR_DATA; + state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; + } + + len += kMatchMinLen; + + if (limit == dicPos) + return SZ_ERROR_DATA; + { + SizeT rem = limit - dicPos; + unsigned curLen = ((rem < len) ? (unsigned)rem : len); + SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); + + processedPos += curLen; + + len -= curLen; + if (pos + curLen <= dicBufSize) + { + 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; +} + +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 = p->remainLen; + UInt32 rep0 = p->reps[0]; + if (limit - dicPos < len) + len = (unsigned)(limit - dicPos); + + if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) + p->checkDicSize = p->prop.dicSize; + + p->processedPos += len; + p->remainLen -= len; + while (len-- != 0) + { + dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + dicPos++; + } + p->dicPos = dicPos; + } +} + +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; + } + RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); + if (p->processedPos >= p->prop.dicSize) + p->checkDicSize = p->prop.dicSize; + LzmaDec_WriteRem(p, limit); + } + while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); + + if (p->remainLen > kMatchSpecLenStart) + { + p->remainLen = kMatchSpecLenStart; + } + return 0; +} + +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; + CLzmaProb *probs = p->probs; + unsigned state = p->state; + ELzmaDummy res; + + { + CLzmaProb *prob; + UInt32 bound; + unsigned ttt; + unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); + + prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; + 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 += (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; + CLzmaProb *probLit; + matchByte <<= 1; + bit = (matchByte & offs); + probLit = prob + offs + bit + symbol; + GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, 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 + (state << kNumPosBitsMax) + posState; + 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; + CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0_CHECK(probLen) + { + UPDATE_0_CHECK; + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + limit = 1 << kLenNumLowBits; + } + else + { + UPDATE_1_CHECK; + probLen = prob + LenChoice2; + IF_BIT_0_CHECK(probLen) + { + UPDATE_0_CHECK; + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + limit = 1 << kLenNumMidBits; + } + else + { + UPDATE_1_CHECK; + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + limit = 1 << kLenNumHighBits; + } + } + TREE_DECODE_CHECK(probLen, limit, len); + len += offset; + } + + if (state < 4) + { + unsigned posSlot; + prob = probs + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << + kNumPosSlotBits); + TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); + if (posSlot >= kStartPosModelIndex) + { + int numDirectBits = ((posSlot >> 1) - 1); + + /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ + + if (posSlot < kEndPosModelIndex) + { + prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; + } + else + { + numDirectBits -= kNumAlignBits; + do + { + NORMALIZE_CHECK + range >>= 1; + code -= range & (((code - range) >> 31) - 1); + /* if (code >= range) code -= range; */ + } + while (--numDirectBits != 0); + prob = probs + Align; + numDirectBits = kNumAlignBits; + } + { + unsigned i = 1; + do + { + GET_BIT_CHECK(prob + i, i); + } + while (--numDirectBits != 0); + } + } + } + } + } + NORMALIZE_CHECK; + return res; +} + + +static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) +{ + p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); + p->range = 0xFFFFFFFF; + p->needFlush = 0; +} + +void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) +{ + p->needFlush = 1; + p->remainLen = 0; + p->tempBufSize = 0; + + if (initDic) + { + p->processedPos = 0; + p->checkDicSize = 0; + p->needInitState = 1; + } + if (initState) + p->needInitState = 1; +} + +void LzmaDec_Init(CLzmaDec *p) +{ + p->dicPos = 0; + LzmaDec_InitDicAndState(p, True, True); +} + +static void LzmaDec_InitStateReal(CLzmaDec *p) +{ + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); + UInt32 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->needInitState = 0; +} + +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, + ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT inSize = *srcLen; + (*srcLen) = 0; + LzmaDec_WriteRem(p, dicLimit); + + *status = LZMA_STATUS_NOT_SPECIFIED; + + while (p->remainLen != kMatchSpecLenStart) + { + int checkEndMarkNow; + + if (p->needFlush != 0) + { + for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) + p->tempBuf[p->tempBufSize++] = *src++; + if (p->tempBufSize < RC_INIT_SIZE) + { + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (p->tempBuf[0] != 0) + return SZ_ERROR_DATA; + + LzmaDec_InitRc(p, p->tempBuf); + p->tempBufSize = 0; + } + + 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->needInitState) + LzmaDec_InitStateReal(p); + + 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; + lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); + (*srcLen) += lookAhead; + src += lookAhead; + inSize -= lookAhead; + p->tempBufSize = 0; + } + } + if (p->code == 0) + *status = LZMA_STATUS_FINISHED_WITH_MARK; + return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; +} + +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, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->probs); + p->probs = 0; +} + +static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->dic); + p->dic = 0; +} + +void LzmaDec_Free(CLzmaDec *p, ISzAlloc *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 = d % 9; + d /= 9; + p->pb = d / 5; + p->lp = d % 5; + + return SZ_OK; +} + +static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) +{ + UInt32 numProbs = LzmaProps_GetNumProbs(propNew); + if (p->probs == 0 || numProbs != p->numProbs) + { + LzmaDec_FreeProbs(p, alloc); + p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); + p->numProbs = numProbs; + if (p->probs == 0) + return SZ_ERROR_MEM; + } + return SZ_OK; +} + +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *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, ISzAlloc *alloc) +{ + CLzmaProps propNew; + SizeT dicBufSize; + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + dicBufSize = propNew.dicSize; + if (p->dic == 0 || dicBufSize != p->dicBufSize) + { + LzmaDec_FreeDict(p, alloc); + p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); + if (p->dic == 0) + { + 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, ISzAlloc *alloc) +{ + CLzmaDec p; + SRes res; + SizeT inSize = *srcLen; + SizeT outSize = *destLen; + *srcLen = *destLen = 0; + if (inSize < RC_INIT_SIZE) + return SZ_ERROR_INPUT_EOF; + + LzmaDec_Construct(&p); + res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); + if (res != 0) + return res; + p.dic = dest; + p.dicBufSize = outSize; + + LzmaDec_Init(&p); + + *srcLen = inSize; + res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); + + if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) + res = SZ_ERROR_INPUT_EOF; + + (*destLen) = p.dicPos; + LzmaDec_FreeProbs(&p, alloc); + return res; +} diff --git a/C/LzmaDec.h b/C/LzmaDec.h new file mode 100755 index 0000000..6741a64 --- /dev/null +++ b/C/LzmaDec.h @@ -0,0 +1,231 @@ +/* LzmaDec.h -- LZMA Decoder +2009-02-07 : Igor Pavlov : Public domain */ + +#ifndef __LZMA_DEC_H +#define __LZMA_DEC_H + +#include "Types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* #define _LZMA_PROB32 */ +/* _LZMA_PROB32 can increase the speed on some CPUs, + but memory usage for CLzmaDec::probs will be doubled in that case */ + +#ifdef _LZMA_PROB32 +#define CLzmaProb UInt32 +#else +#define CLzmaProb UInt16 +#endif + + +/* ---------- LZMA Properties ---------- */ + +#define LZMA_PROPS_SIZE 5 + +typedef struct _CLzmaProps +{ + unsigned lc, lp, pb; + 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 +{ + CLzmaProps prop; + CLzmaProb *probs; + Byte *dic; + const Byte *buf; + UInt32 range, code; + SizeT dicPos; + SizeT dicBufSize; + UInt32 processedPos; + UInt32 checkDicSize; + unsigned state; + UInt32 reps[4]; + unsigned remainLen; + int needFlush; + int needInitState; + UInt32 numProbs; + unsigned tempBufSize; + Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; +} CLzmaDec; + +#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } + +void LzmaDec_Init(CLzmaDec *p); + +/* There are two types of LZMA streams: + 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. + 1) 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, ISzAlloc *alloc); +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); + +SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); +void LzmaDec_Free(CLzmaDec *state, ISzAlloc *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_Constr() + 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, ISzAlloc *alloc); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/C/LzmaEnc.c b/C/LzmaEnc.c new file mode 100755 index 0000000..9e6dbdb --- /dev/null +++ b/C/LzmaEnc.c @@ -0,0 +1,2268 @@ +/* LzmaEnc.c -- LZMA Encoder +2010-04-16 : Igor Pavlov : Public domain */ + +#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 int ttt = 0; +#endif + +#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1) + +#define kBlockSize (9 << 10) +#define kUnpackBlockSize (1 << 18) +#define kMatchArraySize (1 << 21) +#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX) + +#define kNumMaxDirectBits (31) + +#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->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 == 6 ? (1 << 25) : (1 << 26))); + 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; +} + +/* #define LZMA_LOG_BSR */ +/* Define it for Intel's CPU */ + + +#ifdef LZMA_LOG_BSR + +#define kDicLogSizeMaxCompress 30 + +#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); } + +UInt32 GetPosSlot1(UInt32 pos) +{ + UInt32 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 + (int)sizeof(size_t) / 2) +#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) + +void LzmaEnc_FastPosInit(Byte *g_FastPos) +{ + int c = 2, slotFast; + g_FastPos[0] = 0; + g_FastPos[1] = 1; + + for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++) + { + UInt32 k = (1 << ((slotFast >> 1) - 1)); + UInt32 j; + for (j = 0; j < k; j++, c++) + g_FastPos[c] = (Byte)slotFast; + } +} + +#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \ + (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ + res = p->g_FastPos[pos >> i] + (i * 2); } +/* +#define BSR2_RET(pos, res) { 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]; else BSR2_RET(pos, res); } + +#endif + + +#define LZMA_NUM_REPS 4 + +typedef unsigned CState; + +typedef struct +{ + UInt32 price; + + CState state; + int prev1IsChar; + int prev2; + + UInt32 posPrev2; + UInt32 backPrev2; + + UInt32 posPrev; + UInt32 backPrev; + UInt32 backs[LZMA_NUM_REPS]; +} COptimal; + +#define kNumOpts (1 << 12) + +#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 kNumPosModels (kEndPosModelIndex - kStartPosModelIndex) + +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#ifdef _LZMA_PROB32 +#define CLzmaProb UInt32 +#else +#define CLzmaProb UInt16 +#endif + +#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 kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) + +#define LZMA_MATCH_LEN_MIN 2 +#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1) + +#define kNumStates 12 + +typedef struct +{ + CLzmaProb choice; + CLzmaProb choice2; + CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits]; + CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits]; + CLzmaProb high[kLenNumHighSymbols]; +} CLenEnc; + +typedef struct +{ + CLenEnc p; + UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal]; + UInt32 tableSize; + UInt32 counters[LZMA_NUM_PB_STATES_MAX]; +} CLenPriceEnc; + +typedef struct +{ + UInt32 range; + Byte cache; + UInt64 low; + UInt64 cacheSize; + Byte *buf; + Byte *bufLim; + Byte *bufBase; + ISeqOutStream *outStream; + UInt64 processed; + SRes res; +} CRangeEnc; + +typedef struct +{ + CLzmaProb *litProbs; + + CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; + CLzmaProb isRep[kNumStates]; + CLzmaProb isRepG0[kNumStates]; + CLzmaProb isRepG1[kNumStates]; + CLzmaProb isRepG2[kNumStates]; + CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; + + CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; + CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; + CLzmaProb posAlignEncoder[1 << kNumAlignBits]; + + CLenPriceEnc lenEnc; + CLenPriceEnc repLenEnc; + + UInt32 reps[LZMA_NUM_REPS]; + UInt32 state; +} CSaveState; + +typedef struct +{ + IMatchFinder matchFinder; + void *matchFinderObj; + + #ifndef _7ZIP_ST + Bool mtMode; + CMatchFinderMt matchFinderMt; + #endif + + CMatchFinder matchFinderBase; + + #ifndef _7ZIP_ST + Byte pad[128]; + #endif + + UInt32 optimumEndIndex; + UInt32 optimumCurrentIndex; + + UInt32 longestMatchLength; + UInt32 numPairs; + UInt32 numAvail; + COptimal opt[kNumOpts]; + + #ifndef LZMA_LOG_BSR + Byte g_FastPos[1 << kNumLogBits]; + #endif + + UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; + UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1]; + UInt32 numFastBytes; + UInt32 additionalOffset; + UInt32 reps[LZMA_NUM_REPS]; + UInt32 state; + + UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; + UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; + UInt32 alignPrices[kAlignTableSize]; + UInt32 alignPriceCount; + + UInt32 distTableSize; + + unsigned lc, lp, pb; + unsigned lpMask, pbMask; + + CLzmaProb *litProbs; + + CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; + CLzmaProb isRep[kNumStates]; + CLzmaProb isRepG0[kNumStates]; + CLzmaProb isRepG1[kNumStates]; + CLzmaProb isRepG2[kNumStates]; + CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; + + CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; + CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; + CLzmaProb posAlignEncoder[1 << kNumAlignBits]; + + CLenPriceEnc lenEnc; + CLenPriceEnc repLenEnc; + + unsigned lclp; + + Bool fastMode; + + CRangeEnc rc; + + Bool writeEndMark; + UInt64 nowPos64; + UInt32 matchPriceCount; + Bool finished; + Bool multiThread; + + SRes result; + UInt32 dictSize; + UInt32 matchFinderCycles; + + int needInit; + + CSaveState saveState; +} CLzmaEnc; + +void LzmaEnc_SaveState(CLzmaEncHandle pp) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + CSaveState *dest = &p->saveState; + int i; + dest->lenEnc = p->lenEnc; + dest->repLenEnc = p->repLenEnc; + dest->state = p->state; + + for (i = 0; i < kNumStates; i++) + { + memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); + memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); + } + for (i = 0; i < kNumLenToPosStates; i++) + memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); + memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); + memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); + memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); + memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); + memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); + memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); + memcpy(dest->reps, p->reps, sizeof(p->reps)); + memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb)); +} + +void LzmaEnc_RestoreState(CLzmaEncHandle pp) +{ + CLzmaEnc *dest = (CLzmaEnc *)pp; + const CSaveState *p = &dest->saveState; + int i; + dest->lenEnc = p->lenEnc; + dest->repLenEnc = p->repLenEnc; + dest->state = p->state; + + for (i = 0; i < kNumStates; i++) + { + memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); + memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); + } + for (i = 0; i < kNumLenToPosStates; i++) + memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); + memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); + memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); + memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); + memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); + memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); + memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); + memcpy(dest->reps, p->reps, sizeof(p->reps)); + memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb)); +} + +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 > ((UInt32)1 << kDicLogSizeMaxCompress) || props.dictSize > ((UInt32)1 << 30)) + return SZ_ERROR_PARAM; + p->dictSize = props.dictSize; + p->matchFinderCycles = props.mc; + { + 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 = props.btMode; + { + UInt32 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; +} + +static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; +static const int kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; +static const int kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; +static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; + +#define IsCharState(s) ((s) < 7) + +#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1) + +#define kInfinityPrice (1 << 30) + +static void RangeEnc_Construct(CRangeEnc *p) +{ + p->outStream = 0; + p->bufBase = 0; +} + +#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) + +#define RC_BUF_SIZE (1 << 16) +static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc) +{ + if (p->bufBase == 0) + { + p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE); + if (p->bufBase == 0) + return 0; + p->bufLim = p->bufBase + RC_BUF_SIZE; + } + return 1; +} + +static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->bufBase); + p->bufBase = 0; +} + +static void RangeEnc_Init(CRangeEnc *p) +{ + /* Stream.Init(); */ + p->low = 0; + p->range = 0xFFFFFFFF; + p->cacheSize = 1; + p->cache = 0; + + p->buf = p->bufBase; + + p->processed = 0; + p->res = SZ_OK; +} + +static void RangeEnc_FlushStream(CRangeEnc *p) +{ + size_t num; + if (p->res != SZ_OK) + return; + num = p->buf - p->bufBase; + if (num != p->outStream->Write(p->outStream, p->bufBase, num)) + p->res = SZ_ERROR_WRITE; + p->processed += num; + p->buf = p->bufBase; +} + +static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) +{ + if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0) + { + Byte temp = p->cache; + do + { + Byte *buf = p->buf; + *buf++ = (Byte)(temp + (Byte)(p->low >> 32)); + p->buf = buf; + if (buf == p->bufLim) + RangeEnc_FlushStream(p); + temp = 0xFF; + } + while (--p->cacheSize != 0); + p->cache = (Byte)((UInt32)p->low >> 24); + } + p->cacheSize++; + p->low = (UInt32)p->low << 8; +} + +static void RangeEnc_FlushData(CRangeEnc *p) +{ + int i; + for (i = 0; i < 5; i++) + RangeEnc_ShiftLow(p); +} + +static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits) +{ + do + { + p->range >>= 1; + p->low += p->range & (0 - ((value >> --numBits) & 1)); + if (p->range < kTopValue) + { + p->range <<= 8; + RangeEnc_ShiftLow(p); + } + } + while (numBits != 0); +} + +static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol) +{ + UInt32 ttt = *prob; + UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt; + if (symbol == 0) + { + p->range = newBound; + ttt += (kBitModelTotal - ttt) >> kNumMoveBits; + } + else + { + p->low += newBound; + p->range -= newBound; + ttt -= ttt >> kNumMoveBits; + } + *prob = (CLzmaProb)ttt; + if (p->range < kTopValue) + { + p->range <<= 8; + RangeEnc_ShiftLow(p); + } +} + +static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol) +{ + symbol |= 0x100; + do + { + RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1); + symbol <<= 1; + } + while (symbol < 0x10000); +} + +static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte) +{ + UInt32 offs = 0x100; + symbol |= 0x100; + do + { + matchByte <<= 1; + RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1); + symbol <<= 1; + offs &= ~(matchByte ^ symbol); + } + while (symbol < 0x10000); +} + +void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) +{ + UInt32 i; + for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits)) + { + const int kCyclesBits = kNumBitPriceShiftBits; + UInt32 w = i; + UInt32 bitCount = 0; + int j; + for (j = 0; j < kCyclesBits; j++) + { + w = w * w; + bitCount <<= 1; + while (w >= ((UInt32)1 << 16)) + { + w >>= 1; + bitCount++; + } + } + ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); + } +} + + +#define GET_PRICE(prob, symbol) \ + p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; + +#define GET_PRICEa(prob, symbol) \ + ProbPrices[((prob) ^ ((-((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_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits] +#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] + +static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices) +{ + UInt32 price = 0; + symbol |= 0x100; + do + { + price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1); + symbol <<= 1; + } + while (symbol < 0x10000); + return price; +} + +static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *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_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) +{ + UInt32 m = 1; + int i; + for (i = numBitLevels; i != 0;) + { + UInt32 bit; + i--; + bit = (symbol >> i) & 1; + RangeEnc_EncodeBit(rc, probs + m, bit); + m = (m << 1) | bit; + } +} + +static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) +{ + UInt32 m = 1; + int i; + for (i = 0; i < numBitLevels; i++) + { + UInt32 bit = symbol & 1; + RangeEnc_EncodeBit(rc, probs + m, bit); + m = (m << 1) | bit; + symbol >>= 1; + } +} + +static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) +{ + UInt32 price = 0; + symbol |= (1 << numBitLevels); + while (symbol != 1) + { + price += GET_PRICEa(probs[symbol >> 1], symbol & 1); + symbol >>= 1; + } + return price; +} + +static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) +{ + UInt32 price = 0; + UInt32 m = 1; + int i; + for (i = numBitLevels; i != 0; i--) + { + UInt32 bit = symbol & 1; + symbol >>= 1; + price += GET_PRICEa(probs[m], bit); + m = (m << 1) | bit; + } + return price; +} + + +static void LenEnc_Init(CLenEnc *p) +{ + unsigned i; + p->choice = p->choice2 = kProbInitValue; + for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++) + p->low[i] = kProbInitValue; + for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++) + p->mid[i] = kProbInitValue; + for (i = 0; i < kLenNumHighSymbols; i++) + p->high[i] = kProbInitValue; +} + +static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState) +{ + if (symbol < kLenNumLowSymbols) + { + RangeEnc_EncodeBit(rc, &p->choice, 0); + RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol); + } + else + { + RangeEnc_EncodeBit(rc, &p->choice, 1); + if (symbol < kLenNumLowSymbols + kLenNumMidSymbols) + { + RangeEnc_EncodeBit(rc, &p->choice2, 0); + RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols); + } + else + { + RangeEnc_EncodeBit(rc, &p->choice2, 1); + RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols); + } + } +} + +static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices) +{ + UInt32 a0 = GET_PRICE_0a(p->choice); + UInt32 a1 = GET_PRICE_1a(p->choice); + UInt32 b0 = a1 + GET_PRICE_0a(p->choice2); + UInt32 b1 = a1 + GET_PRICE_1a(p->choice2); + UInt32 i = 0; + for (i = 0; i < kLenNumLowSymbols; i++) + { + if (i >= numSymbols) + return; + prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices); + } + for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++) + { + if (i >= numSymbols) + return; + prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices); + } + for (; i < numSymbols; i++) + prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices); +} + +static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices) +{ + LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices); + p->counters[posState] = p->tableSize; +} + +static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices) +{ + UInt32 posState; + for (posState = 0; posState < numPosStates; posState++) + LenPriceEnc_UpdateTable(p, posState, ProbPrices); +} + +static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices) +{ + LenEnc_Encode(&p->p, rc, symbol, posState); + if (updatePrice) + if (--p->counters[posState] == 0) + LenPriceEnc_UpdateTable(p, posState, ProbPrices); +} + + + + +static void MovePos(CLzmaEnc *p, UInt32 num) +{ + #ifdef SHOW_STAT + ttt += num; + printf("\n MovePos %d", num); + #endif + if (num != 0) + { + p->additionalOffset += num; + p->matchFinder.Skip(p->matchFinderObj, num); + } +} + +static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes) +{ + UInt32 lenRes = 0, numPairs; + p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); + numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); + #ifdef SHOW_STAT + printf("\n i = %d numPairs = %d ", ttt, numPairs / 2); + ttt++; + { + UInt32 i; + for (i = 0; i < numPairs; i += 2) + printf("%2d %6d | ", p->matches[i], p->matches[i + 1]); + } + #endif + if (numPairs > 0) + { + lenRes = p->matches[numPairs - 2]; + if (lenRes == p->numFastBytes) + { + const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + UInt32 distance = p->matches[numPairs - 1] + 1; + UInt32 numAvail = p->numAvail; + if (numAvail > LZMA_MATCH_LEN_MAX) + numAvail = LZMA_MATCH_LEN_MAX; + { + const Byte *pby2 = pby - distance; + for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++); + } + } + } + p->additionalOffset++; + *numDistancePairsRes = numPairs; + return lenRes; +} + + +#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False; +#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False; +#define IsShortRep(p) ((p)->backPrev == 0) + +static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState) +{ + return + GET_PRICE_0(p->isRepG0[state]) + + GET_PRICE_0(p->isRep0Long[state][posState]); +} + +static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState) +{ + UInt32 price; + if (repIndex == 0) + { + price = GET_PRICE_0(p->isRepG0[state]); + price += GET_PRICE_1(p->isRep0Long[state][posState]); + } + else + { + price = GET_PRICE_1(p->isRepG0[state]); + if (repIndex == 1) + price += GET_PRICE_0(p->isRepG1[state]); + else + { + price += GET_PRICE_1(p->isRepG1[state]); + price += GET_PRICE(p->isRepG2[state], repIndex - 2); + } + } + return price; +} + +static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState) +{ + return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] + + GetPureRepPrice(p, repIndex, state, posState); +} + +static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur) +{ + UInt32 posMem = p->opt[cur].posPrev; + UInt32 backMem = p->opt[cur].backPrev; + p->optimumEndIndex = cur; + do + { + if (p->opt[cur].prev1IsChar) + { + MakeAsChar(&p->opt[posMem]) + p->opt[posMem].posPrev = posMem - 1; + if (p->opt[cur].prev2) + { + p->opt[posMem - 1].prev1IsChar = False; + p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2; + p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2; + } + } + { + UInt32 posPrev = posMem; + UInt32 backCur = backMem; + + backMem = p->opt[posPrev].backPrev; + posMem = p->opt[posPrev].posPrev; + + p->opt[posPrev].backPrev = backCur; + p->opt[posPrev].posPrev = cur; + cur = posPrev; + } + } + while (cur != 0); + *backRes = p->opt[0].backPrev; + p->optimumCurrentIndex = p->opt[0].posPrev; + return p->optimumCurrentIndex; +} + +#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300) + +static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) +{ + UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur; + UInt32 matchPrice, repMatchPrice, normalMatchPrice; + UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS]; + UInt32 *matches; + const Byte *data; + Byte curByte, matchByte; + if (p->optimumEndIndex != p->optimumCurrentIndex) + { + const COptimal *opt = &p->opt[p->optimumCurrentIndex]; + UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex; + *backRes = opt->backPrev; + p->optimumCurrentIndex = opt->posPrev; + return lenRes; + } + p->optimumCurrentIndex = p->optimumEndIndex = 0; + + if (p->additionalOffset == 0) + mainLen = ReadMatchDistances(p, &numPairs); + else + { + mainLen = p->longestMatchLength; + numPairs = p->numPairs; + } + + numAvail = p->numAvail; + if (numAvail < 2) + { + *backRes = (UInt32)(-1); + 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++) + { + UInt32 lenTest; + const Byte *data2; + reps[i] = p->reps[i]; + data2 = data - (reps[i] + 1); + if (data[0] != data2[0] || data[1] != data2[1]) + { + repLens[i] = 0; + continue; + } + for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); + repLens[i] = lenTest; + if (lenTest > repLens[repMaxIndex]) + repMaxIndex = i; + } + if (repLens[repMaxIndex] >= p->numFastBytes) + { + UInt32 lenRes; + *backRes = repMaxIndex; + lenRes = repLens[repMaxIndex]; + MovePos(p, lenRes - 1); + return lenRes; + } + + matches = p->matches; + if (mainLen >= p->numFastBytes) + { + *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; + MovePos(p, mainLen - 1); + return mainLen; + } + curByte = *data; + matchByte = *(data - (reps[0] + 1)); + + if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2) + { + *backRes = (UInt32)-1; + 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]) + + (!IsCharState(p->state) ? + LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : + LitEnc_GetPrice(probs, curByte, p->ProbPrices)); + } + + MakeAsChar(&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 + GetRepLen1Price(p, p->state, posState); + if (shortRepPrice < p->opt[1].price) + { + p->opt[1].price = shortRepPrice; + MakeAsShortRep(&p->opt[1]); + } + } + lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]); + + if (lenEnd < 2) + { + *backRes = p->opt[1].backPrev; + return 1; + } + + p->opt[1].posPrev = 0; + for (i = 0; i < LZMA_NUM_REPS; i++) + p->opt[0].backs[i] = reps[i]; + + len = lenEnd; + do + p->opt[len--].price = kInfinityPrice; + while (len >= 2); + + for (i = 0; i < LZMA_NUM_REPS; i++) + { + UInt32 repLen = repLens[i]; + UInt32 price; + if (repLen < 2) + continue; + price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState); + do + { + UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2]; + COptimal *opt = &p->opt[repLen]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = 0; + opt->backPrev = i; + opt->prev1IsChar = False; + } + } + while (--repLen >= 2); + } + + normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]); + + len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); + if (len <= mainLen) + { + UInt32 offs = 0; + while (len > matches[offs]) + offs += 2; + for (; ; len++) + { + COptimal *opt; + UInt32 distance = matches[offs + 1]; + + UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN]; + UInt32 lenToPosState = GetLenToPosState(len); + if (distance < kNumFullDistances) + curAndLenPrice += p->distancesPrices[lenToPosState][distance]; + else + { + UInt32 slot; + GetPosSlot2(distance, slot); + curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot]; + } + opt = &p->opt[len]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = 0; + opt->backPrev = distance + LZMA_NUM_REPS; + opt->prev1IsChar = False; + } + 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 <= lenEnd; i++) + printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price); + } + #endif + + for (;;) + { + UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen; + UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice; + Bool nextIsChar; + Byte curByte, matchByte; + const Byte *data; + COptimal *curOpt; + COptimal *nextOpt; + + cur++; + if (cur == lenEnd) + return Backward(p, backRes, cur); + + newLen = ReadMatchDistances(p, &numPairs); + if (newLen >= p->numFastBytes) + { + p->numPairs = numPairs; + p->longestMatchLength = newLen; + return Backward(p, backRes, cur); + } + position++; + curOpt = &p->opt[cur]; + posPrev = curOpt->posPrev; + if (curOpt->prev1IsChar) + { + posPrev--; + if (curOpt->prev2) + { + state = p->opt[curOpt->posPrev2].state; + if (curOpt->backPrev2 < LZMA_NUM_REPS) + state = kRepNextStates[state]; + else + state = kMatchNextStates[state]; + } + else + state = p->opt[posPrev].state; + state = kLiteralNextStates[state]; + } + else + state = p->opt[posPrev].state; + if (posPrev == cur - 1) + { + if (IsShortRep(curOpt)) + state = kShortRepNextStates[state]; + else + state = kLiteralNextStates[state]; + } + else + { + UInt32 pos; + const COptimal *prevOpt; + if (curOpt->prev1IsChar && curOpt->prev2) + { + posPrev = curOpt->posPrev2; + pos = curOpt->backPrev2; + state = kRepNextStates[state]; + } + else + { + pos = curOpt->backPrev; + if (pos < LZMA_NUM_REPS) + state = kRepNextStates[state]; + else + state = kMatchNextStates[state]; + } + prevOpt = &p->opt[posPrev]; + if (pos < LZMA_NUM_REPS) + { + UInt32 i; + reps[0] = prevOpt->backs[pos]; + for (i = 1; i <= pos; i++) + reps[i] = prevOpt->backs[i - 1]; + for (; i < LZMA_NUM_REPS; i++) + reps[i] = prevOpt->backs[i]; + } + else + { + UInt32 i; + reps[0] = (pos - LZMA_NUM_REPS); + for (i = 1; i < LZMA_NUM_REPS; i++) + reps[i] = prevOpt->backs[i - 1]; + } + } + curOpt->state = (CState)state; + + curOpt->backs[0] = reps[0]; + curOpt->backs[1] = reps[1]; + curOpt->backs[2] = reps[2]; + curOpt->backs[3] = reps[3]; + + curPrice = curOpt->price; + nextIsChar = False; + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + curByte = *data; + matchByte = *(data - (reps[0] + 1)); + + posState = (position & p->pbMask); + + curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]); + { + const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); + curAnd1Price += + (!IsCharState(state) ? + LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : + LitEnc_GetPrice(probs, curByte, p->ProbPrices)); + } + + nextOpt = &p->opt[cur + 1]; + + if (curAnd1Price < nextOpt->price) + { + nextOpt->price = curAnd1Price; + nextOpt->posPrev = cur; + MakeAsChar(nextOpt); + nextIsChar = True; + } + + matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]); + repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]); + + if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0)) + { + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState); + if (shortRepPrice <= nextOpt->price) + { + nextOpt->price = shortRepPrice; + nextOpt->posPrev = cur; + MakeAsShortRep(nextOpt); + nextIsChar = True; + } + } + numAvailFull = p->numAvail; + { + UInt32 temp = kNumOpts - 1 - cur; + if (temp < numAvailFull) + numAvailFull = temp; + } + + if (numAvailFull < 2) + continue; + numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes); + + if (!nextIsChar && matchByte != curByte) /* speed optimization */ + { + /* try Literal + rep0 */ + UInt32 temp; + UInt32 lenTest2; + const Byte *data2 = data - (reps[0] + 1); + UInt32 limit = p->numFastBytes + 1; + if (limit > numAvailFull) + limit = numAvailFull; + + for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++); + lenTest2 = temp - 1; + if (lenTest2 >= 2) + { + UInt32 state2 = kLiteralNextStates[state]; + UInt32 posStateNext = (position + 1) & p->pbMask; + UInt32 nextRepMatchPrice = curAnd1Price + + GET_PRICE_1(p->isMatch[state2][posStateNext]) + + GET_PRICE_1(p->isRep[state2]); + /* for (; lenTest2 >= 2; lenTest2--) */ + { + UInt32 curAndLenPrice; + COptimal *opt; + UInt32 offset = cur + 1 + lenTest2; + while (lenEnd < offset) + p->opt[++lenEnd].price = kInfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); + opt = &p->opt[offset]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur + 1; + opt->backPrev = 0; + opt->prev1IsChar = True; + opt->prev2 = False; + } + } + } + } + + startLen = 2; /* speed optimization */ + { + UInt32 repIndex; + for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++) + { + UInt32 lenTest; + UInt32 lenTestTemp; + UInt32 price; + const Byte *data2 = data - (reps[repIndex] + 1); + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); + while (lenEnd < cur + lenTest) + p->opt[++lenEnd].price = kInfinityPrice; + lenTestTemp = lenTest; + price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState); + do + { + UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2]; + COptimal *opt = &p->opt[cur + lenTest]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur; + opt->backPrev = repIndex; + opt->prev1IsChar = False; + } + } + while (--lenTest >= 2); + lenTest = lenTestTemp; + + if (repIndex == 0) + startLen = lenTest + 1; + + /* if (_maxMode) */ + { + UInt32 lenTest2 = lenTest + 1; + UInt32 limit = lenTest2 + p->numFastBytes; + UInt32 nextRepMatchPrice; + if (limit > numAvailFull) + limit = numAvailFull; + for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); + lenTest2 -= lenTest + 1; + if (lenTest2 >= 2) + { + UInt32 state2 = kRepNextStates[state]; + UInt32 posStateNext = (position + lenTest) & p->pbMask; + UInt32 curAndLenCharPrice = + price + p->repLenEnc.prices[posState][lenTest - 2] + + GET_PRICE_0(p->isMatch[state2][posStateNext]) + + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), + data[lenTest], data2[lenTest], p->ProbPrices); + state2 = kLiteralNextStates[state2]; + posStateNext = (position + lenTest + 1) & p->pbMask; + nextRepMatchPrice = curAndLenCharPrice + + GET_PRICE_1(p->isMatch[state2][posStateNext]) + + GET_PRICE_1(p->isRep[state2]); + + /* for (; lenTest2 >= 2; lenTest2--) */ + { + UInt32 curAndLenPrice; + COptimal *opt; + UInt32 offset = cur + lenTest + 1 + lenTest2; + while (lenEnd < offset) + p->opt[++lenEnd].price = kInfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); + opt = &p->opt[offset]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur + lenTest + 1; + opt->backPrev = 0; + opt->prev1IsChar = True; + opt->prev2 = True; + opt->posPrev2 = cur; + opt->backPrev2 = repIndex; + } + } + } + } + } + } + /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */ + 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 offs, curBack, posSlot; + UInt32 lenTest; + while (lenEnd < cur + newLen) + p->opt[++lenEnd].price = kInfinityPrice; + + offs = 0; + while (startLen > matches[offs]) + offs += 2; + curBack = matches[offs + 1]; + GetPosSlot2(curBack, posSlot); + for (lenTest = /*2*/ startLen; ; lenTest++) + { + UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN]; + UInt32 lenToPosState = GetLenToPosState(lenTest); + COptimal *opt; + if (curBack < kNumFullDistances) + curAndLenPrice += p->distancesPrices[lenToPosState][curBack]; + else + curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask]; + + opt = &p->opt[cur + lenTest]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur; + opt->backPrev = curBack + LZMA_NUM_REPS; + opt->prev1IsChar = False; + } + + if (/*_maxMode && */lenTest == matches[offs]) + { + /* Try Match + Literal + Rep0 */ + const Byte *data2 = data - (curBack + 1); + UInt32 lenTest2 = lenTest + 1; + UInt32 limit = lenTest2 + p->numFastBytes; + UInt32 nextRepMatchPrice; + if (limit > numAvailFull) + limit = numAvailFull; + for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); + lenTest2 -= lenTest + 1; + if (lenTest2 >= 2) + { + UInt32 state2 = kMatchNextStates[state]; + UInt32 posStateNext = (position + lenTest) & p->pbMask; + UInt32 curAndLenCharPrice = curAndLenPrice + + GET_PRICE_0(p->isMatch[state2][posStateNext]) + + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), + data[lenTest], data2[lenTest], p->ProbPrices); + state2 = kLiteralNextStates[state2]; + posStateNext = (posStateNext + 1) & p->pbMask; + nextRepMatchPrice = curAndLenCharPrice + + GET_PRICE_1(p->isMatch[state2][posStateNext]) + + GET_PRICE_1(p->isRep[state2]); + + /* for (; lenTest2 >= 2; lenTest2--) */ + { + UInt32 offset = cur + lenTest + 1 + lenTest2; + UInt32 curAndLenPrice; + COptimal *opt; + while (lenEnd < offset) + p->opt[++lenEnd].price = kInfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); + opt = &p->opt[offset]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur + lenTest + 1; + opt->backPrev = 0; + opt->prev1IsChar = True; + opt->prev2 = True; + opt->posPrev2 = cur; + opt->backPrev2 = curBack + LZMA_NUM_REPS; + } + } + } + offs += 2; + if (offs == numPairs) + break; + curBack = matches[offs + 1]; + if (curBack >= kNumFullDistances) + GetPosSlot2(curBack, posSlot); + } + } + } + } +} + +#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist)) + +static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes) +{ + UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i; + const Byte *data; + const UInt32 *matches; + + if (p->additionalOffset == 0) + mainLen = ReadMatchDistances(p, &numPairs); + else + { + mainLen = p->longestMatchLength; + numPairs = p->numPairs; + } + + numAvail = p->numAvail; + *backRes = (UInt32)-1; + 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++) + { + UInt32 len; + const Byte *data2 = data - (p->reps[i] + 1); + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + for (len = 2; len < numAvail && data[len] == data2[len]; len++); + if (len >= p->numFastBytes) + { + *backRes = i; + MovePos(p, len - 1); + return len; + } + if (len > repLen) + { + repIndex = i; + repLen = len; + } + } + + matches = p->matches; + if (mainLen >= p->numFastBytes) + { + *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; + MovePos(p, mainLen - 1); + return mainLen; + } + + mainDist = 0; /* for GCC */ + if (mainLen >= 2) + { + mainDist = matches[numPairs - 1]; + while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1) + { + if (!ChangePair(matches[numPairs - 3], mainDist)) + break; + numPairs -= 2; + mainLen = matches[numPairs - 2]; + mainDist = matches[numPairs - 1]; + } + if (mainLen == 2 && mainDist >= 0x80) + mainLen = 1; + } + + if (repLen >= 2 && ( + (repLen + 1 >= mainLen) || + (repLen + 2 >= mainLen && mainDist >= (1 << 9)) || + (repLen + 3 >= mainLen && mainDist >= (1 << 15)))) + { + *backRes = repIndex; + MovePos(p, repLen - 1); + return repLen; + } + + if (mainLen < 2 || numAvail <= 2) + return 1; + + p->longestMatchLength = ReadMatchDistances(p, &p->numPairs); + if (p->longestMatchLength >= 2) + { + UInt32 newDistance = matches[p->numPairs - 1]; + if ((p->longestMatchLength >= mainLen && newDistance < mainDist) || + (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) || + (p->longestMatchLength > mainLen + 1) || + (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist))) + return 1; + } + + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + for (i = 0; i < LZMA_NUM_REPS; i++) + { + UInt32 len, limit; + const Byte *data2 = data - (p->reps[i] + 1); + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + limit = mainLen - 1; + for (len = 2; len < limit && data[len] == data2[len]; len++); + if (len >= limit) + return 1; + } + *backRes = mainDist + LZMA_NUM_REPS; + MovePos(p, mainLen - 2); + return mainLen; +} + +static void WriteEndMarker(CLzmaEnc *p, UInt32 posState) +{ + UInt32 len; + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); + RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); + p->state = kMatchNextStates[p->state]; + len = LZMA_MATCH_LEN_MIN; + LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); + RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1); + RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits); + RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask); +} + +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; +} + +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) +{ + UInt32 i; + for (i = 0; i < kAlignTableSize; i++) + p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices); + p->alignPriceCount = 0; +} + +static void FillDistancesPrices(CLzmaEnc *p) +{ + UInt32 tempPrices[kNumFullDistances]; + UInt32 i, lenToPosState; + for (i = kStartPosModelIndex; i < kNumFullDistances; i++) + { + UInt32 posSlot = GetPosSlot1(i); + UInt32 footerBits = ((posSlot >> 1) - 1); + UInt32 base = ((2 | (posSlot & 1)) << footerBits); + tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices); + } + + for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) + { + UInt32 posSlot; + const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState]; + UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState]; + for (posSlot = 0; posSlot < p->distTableSize; posSlot++) + posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices); + for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++) + posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits); + + { + UInt32 *distancesPrices = p->distancesPrices[lenToPosState]; + UInt32 i; + for (i = 0; i < kStartPosModelIndex; i++) + distancesPrices[i] = posSlotPrices[i]; + for (; i < kNumFullDistances; i++) + distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i]; + } + } + p->matchPriceCount = 0; +} + +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 = 0; + p->saveState.litProbs = 0; +} + +CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc) +{ + void *p; + p = alloc->Alloc(alloc, sizeof(CLzmaEnc)); + if (p != 0) + LzmaEnc_Construct((CLzmaEnc *)p); + return p; +} + +void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->litProbs); + alloc->Free(alloc, p->saveState.litProbs); + p->litProbs = 0; + p->saveState.litProbs = 0; +} + +void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + #ifndef _7ZIP_ST + MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); + #endif + MatchFinder_Free(&p->matchFinderBase, allocBig); + LzmaEnc_FreeLits(p, alloc); + RangeEnc_Free(&p->rc, alloc); +} + +void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig); + alloc->Free(alloc, p); +} + +static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, 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) + { + UInt32 numPairs; + Byte curByte; + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) + return Flush(p, nowPos32); + ReadMatchDistances(p, &numPairs); + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0); + p->state = kLiteralNextStates[p->state]; + curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset); + LitEnc_Encode(&p->rc, p->litProbs, curByte); + p->additionalOffset--; + nowPos32++; + } + + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0) + for (;;) + { + UInt32 pos, len, posState; + + if (p->fastMode) + len = GetOptimumFast(p, &pos); + else + len = GetOptimum(p, nowPos32, &pos); + + #ifdef SHOW_STAT2 + printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos); + #endif + + posState = nowPos32 & p->pbMask; + if (len == 1 && pos == (UInt32)-1) + { + Byte curByte; + CLzmaProb *probs; + const Byte *data; + + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0); + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; + curByte = *data; + probs = LIT_PROBS(nowPos32, *(data - 1)); + if (IsCharState(p->state)) + LitEnc_Encode(&p->rc, probs, curByte); + else + LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1)); + p->state = kLiteralNextStates[p->state]; + } + else + { + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); + if (pos < LZMA_NUM_REPS) + { + RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1); + if (pos == 0) + { + RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0); + RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1)); + } + else + { + UInt32 distance = p->reps[pos]; + RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1); + if (pos == 1) + RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0); + else + { + RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1); + RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2); + if (pos == 3) + p->reps[3] = p->reps[2]; + p->reps[2] = p->reps[1]; + } + p->reps[1] = p->reps[0]; + p->reps[0] = distance; + } + if (len == 1) + p->state = kShortRepNextStates[p->state]; + else + { + LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); + p->state = kRepNextStates[p->state]; + } + } + else + { + UInt32 posSlot; + RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); + p->state = kMatchNextStates[p->state]; + LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); + pos -= LZMA_NUM_REPS; + GetPosSlot(pos, posSlot); + RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot); + + if (posSlot >= kStartPosModelIndex) + { + UInt32 footerBits = ((posSlot >> 1) - 1); + UInt32 base = ((2 | (posSlot & 1)) << footerBits); + UInt32 posReduced = pos - base; + + if (posSlot < kEndPosModelIndex) + RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced); + else + { + RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits); + RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask); + p->alignPriceCount++; + } + } + p->reps[3] = p->reps[2]; + p->reps[2] = p->reps[1]; + p->reps[1] = p->reps[0]; + p->reps[0] = pos; + p->matchPriceCount++; + } + } + p->additionalOffset -= len; + nowPos32 += 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 (useLimits) + { + if (processed + kNumOpts + 300 >= maxUnpackSize || + RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize) + break; + } + else if (processed >= (1 << 15)) + { + 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, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + UInt32 beforeSize = kNumOpts; + Bool btMode; + if (!RangeEnc_Alloc(&p->rc, alloc)) + return SZ_ERROR_MEM; + btMode = (p->matchFinderBase.btMode != 0); + #ifndef _7ZIP_ST + p->mtMode = (p->multiThread && !p->fastMode && btMode); + #endif + + { + unsigned lclp = p->lc + p->lp; + if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp) + { + LzmaEnc_FreeLits(p, alloc); + p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); + p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); + if (p->litProbs == 0 || p->saveState.litProbs == 0) + { + LzmaEnc_FreeLits(p, alloc); + return SZ_ERROR_MEM; + } + p->lclp = lclp; + } + } + + p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit); + + 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, allocBig)); + p->matchFinderObj = &p->matchFinderMt; + 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) +{ + UInt32 i; + p->state = 0; + for (i = 0 ; i < LZMA_NUM_REPS; i++) + p->reps[i] = 0; + + RangeEnc_Init(&p->rc); + + + for (i = 0; i < kNumStates; i++) + { + UInt32 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; + } + + { + UInt32 num = 0x300 << (p->lp + p->lc); + for (i = 0; i < num; i++) + p->litProbs[i] = kProbInitValue; + } + + { + for (i = 0; i < kNumLenToPosStates; i++) + { + CLzmaProb *probs = p->posSlotEncoder[i]; + UInt32 j; + for (j = 0; j < (1 << kNumPosSlotBits); j++) + probs[j] = kProbInitValue; + } + } + { + for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) + p->posEncoders[i] = kProbInitValue; + } + + LenEnc_Init(&p->lenEnc.p); + LenEnc_Init(&p->repLenEnc.p); + + for (i = 0; i < (1 << kNumAlignBits); i++) + p->posAlignEncoder[i] = kProbInitValue; + + p->optimumEndIndex = 0; + p->optimumCurrentIndex = 0; + p->additionalOffset = 0; + + p->pbMask = (1 << p->pb) - 1; + p->lpMask = (1 << p->lp) - 1; +} + +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->ProbPrices); + LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices); +} + +static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + UInt32 i; + for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; 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, + ISzAlloc *alloc, ISzAlloc *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, + ISzAlloc *alloc, ISzAlloc *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, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + LzmaEnc_SetInputBuf(p, src, srcLen); + p->needInit = 1; + + 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 + pp = pp; + #endif +} + +typedef struct +{ + ISeqOutStream funcTable; + Byte *data; + SizeT rem; + Bool overflow; +} CSeqOutStreamBuf; + +static size_t MyWrite(void *pp, const void *data, size_t size) +{ + CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp; + 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; + CSeqOutStreamBuf outStream; + + outStream.funcTable.Write = MyWrite; + 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.funcTable; + + res = LzmaEnc_CodeOneBlock(p, True, 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]; + int i = 0; + for (i = 0; i < 16; i++) + allocaDummy[i] = (Byte)i; + #endif + + for (;;) + { + res = LzmaEnc_CodeOneBlock(p, False, 0, 0); + if (res != SZ_OK || p->finished != 0) + break; + if (progress != 0) + { + res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); + if (res != SZ_OK) + { + res = SZ_ERROR_PROGRESS; + break; + } + } + } + LzmaEnc_Finish(p); + return res; +} + +SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, + ISzAlloc *alloc, ISzAlloc *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; + int i; + UInt32 dictSize = p->dictSize; + if (*size < LZMA_PROPS_SIZE) + return SZ_ERROR_PARAM; + *size = LZMA_PROPS_SIZE; + props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); + + for (i = 11; i <= 30; i++) + { + if (dictSize <= ((UInt32)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; +} + +SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + SRes res; + CLzmaEnc *p = (CLzmaEnc *)pp; + + CSeqOutStreamBuf outStream; + + LzmaEnc_SetInputBuf(p, src, srcLen); + + outStream.funcTable.Write = MyWrite; + outStream.data = dest; + outStream.rem = *destLen; + outStream.overflow = False; + + p->writeEndMark = writeEndMark; + + p->rc.outStream = &outStream.funcTable; + res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig); + if (res == SZ_OK) + res = LzmaEnc_Encode2(p, progress); + + *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, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); + SRes res; + if (p == 0) + 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/C/LzmaEnc.h b/C/LzmaEnc.h new file mode 100755 index 0000000..999f5af --- /dev/null +++ b/C/LzmaEnc.h @@ -0,0 +1,80 @@ +/* LzmaEnc.h -- LZMA Encoder +2009-02-07 : Igor Pavlov : Public domain */ + +#ifndef __LZMA_ENC_H +#define __LZMA_ENC_H + +#include "Types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#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 <= (1 << 30) 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 */ +} 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: +Returns: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater in props + SZ_ERROR_WRITE - Write callback error. + SZ_ERROR_PROGRESS - some break from progress callback + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) +*/ + +typedef void * CLzmaEncHandle; + +CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc); +void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig); +SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); +SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); +SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, + ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); +SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); + +/* ---------- One Call Interface ---------- */ + +/* LzmaEncode +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) +*/ + +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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/C/LzmaLib.c b/C/LzmaLib.c new file mode 100755 index 0000000..3e3cf40 --- /dev/null +++ b/C/LzmaLib.c @@ -0,0 +1,46 @@ +/* LzmaLib.c -- LZMA library wrapper +2008-08-05 +Igor Pavlov +Public domain */ + +#include "LzmaEnc.h" +#include "LzmaDec.h" +#include "Alloc.h" +#include "LzmaLib.h" + +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } +static void SzFree(void *p, void *address) { p = p; MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, + 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/C/LzmaLib.h b/C/LzmaLib.h new file mode 100755 index 0000000..55e1e11 --- /dev/null +++ b/C/LzmaLib.h @@ -0,0 +1,135 @@ +/* LzmaLib.h -- LZMA library interface +2009-04-07 : Igor Pavlov : Public domain */ + +#ifndef __LZMA_LIB_H +#define __LZMA_LIB_H + +#include "Types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/C/MtCoder.c b/C/MtCoder.c new file mode 100755 index 0000000..9f0d268 --- /dev/null +++ b/C/MtCoder.c @@ -0,0 +1,327 @@ +/* MtCoder.c -- Multi-thread Coder +2010-09-24 : Igor Pavlov : Public domain */ + +#include + +#include "MtCoder.h" + +void LoopThread_Construct(CLoopThread *p) +{ + Thread_Construct(&p->thread); + Event_Construct(&p->startEvent); + Event_Construct(&p->finishedEvent); +} + +void LoopThread_Close(CLoopThread *p) +{ + Thread_Close(&p->thread); + Event_Close(&p->startEvent); + Event_Close(&p->finishedEvent); +} + +static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE LoopThreadFunc(void *pp) +{ + CLoopThread *p = (CLoopThread *)pp; + for (;;) + { + if (Event_Wait(&p->startEvent) != 0) + return SZ_ERROR_THREAD; + if (p->stop) + return 0; + p->res = p->func(p->param); + if (Event_Set(&p->finishedEvent) != 0) + return SZ_ERROR_THREAD; + } +} + +WRes LoopThread_Create(CLoopThread *p) +{ + p->stop = 0; + RINOK(AutoResetEvent_CreateNotSignaled(&p->startEvent)); + RINOK(AutoResetEvent_CreateNotSignaled(&p->finishedEvent)); + return Thread_Create(&p->thread, LoopThreadFunc, p); +} + +WRes LoopThread_StopAndWait(CLoopThread *p) +{ + p->stop = 1; + if (Event_Set(&p->startEvent) != 0) + return SZ_ERROR_THREAD; + return Thread_Wait(&p->thread); +} + +WRes LoopThread_StartSubThread(CLoopThread *p) { return Event_Set(&p->startEvent); } +WRes LoopThread_WaitSubThread(CLoopThread *p) { return Event_Wait(&p->finishedEvent); } + +static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize) +{ + return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK; +} + +static void MtProgress_Init(CMtProgress *p, ICompressProgress *progress) +{ + unsigned i; + for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++) + p->inSizes[i] = p->outSizes[i] = 0; + p->totalInSize = p->totalOutSize = 0; + p->progress = progress; + p->res = SZ_OK; +} + +static void MtProgress_Reinit(CMtProgress *p, unsigned index) +{ + p->inSizes[index] = 0; + p->outSizes[index] = 0; +} + +#define UPDATE_PROGRESS(size, prev, total) \ + if (size != (UInt64)(Int64)-1) { total += size - prev; prev = size; } + +SRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize) +{ + SRes res; + CriticalSection_Enter(&p->cs); + UPDATE_PROGRESS(inSize, p->inSizes[index], p->totalInSize) + UPDATE_PROGRESS(outSize, p->outSizes[index], p->totalOutSize) + if (p->res == SZ_OK) + p->res = Progress(p->progress, p->totalInSize, p->totalOutSize); + res = p->res; + CriticalSection_Leave(&p->cs); + return res; +} + +static void MtProgress_SetError(CMtProgress *p, SRes res) +{ + CriticalSection_Enter(&p->cs); + if (p->res == SZ_OK) + p->res = res; + CriticalSection_Leave(&p->cs); +} + +static void MtCoder_SetError(CMtCoder* p, SRes res) +{ + CriticalSection_Enter(&p->cs); + if (p->res == SZ_OK) + p->res = res; + CriticalSection_Leave(&p->cs); +} + +/* ---------- MtThread ---------- */ + +void CMtThread_Construct(CMtThread *p, CMtCoder *mtCoder) +{ + p->mtCoder = mtCoder; + p->outBuf = 0; + p->inBuf = 0; + Event_Construct(&p->canRead); + Event_Construct(&p->canWrite); + LoopThread_Construct(&p->thread); +} + +#define RINOK_THREAD(x) { if((x) != 0) return SZ_ERROR_THREAD; } + +static void CMtThread_CloseEvents(CMtThread *p) +{ + Event_Close(&p->canRead); + Event_Close(&p->canWrite); +} + +static void CMtThread_Destruct(CMtThread *p) +{ + CMtThread_CloseEvents(p); + + if (Thread_WasCreated(&p->thread.thread)) + { + LoopThread_StopAndWait(&p->thread); + LoopThread_Close(&p->thread); + } + + if (p->mtCoder->alloc) + IAlloc_Free(p->mtCoder->alloc, p->outBuf); + p->outBuf = 0; + + if (p->mtCoder->alloc) + IAlloc_Free(p->mtCoder->alloc, p->inBuf); + p->inBuf = 0; +} + +#define MY_BUF_ALLOC(buf, size, newSize) \ + if (buf == 0 || size != newSize) \ + { IAlloc_Free(p->mtCoder->alloc, buf); \ + size = newSize; buf = (Byte *)IAlloc_Alloc(p->mtCoder->alloc, size); \ + if (buf == 0) return SZ_ERROR_MEM; } + +static SRes CMtThread_Prepare(CMtThread *p) +{ + MY_BUF_ALLOC(p->inBuf, p->inBufSize, p->mtCoder->blockSize) + MY_BUF_ALLOC(p->outBuf, p->outBufSize, p->mtCoder->destBlockSize) + + p->stopReading = False; + p->stopWriting = False; + RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canRead)); + RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canWrite)); + + return SZ_OK; +} + +static SRes FullRead(ISeqInStream *stream, Byte *data, size_t *processedSize) +{ + size_t size = *processedSize; + *processedSize = 0; + while (size != 0) + { + size_t curSize = size; + SRes res = stream->Read(stream, data, &curSize); + *processedSize += curSize; + data += curSize; + size -= curSize; + RINOK(res); + if (curSize == 0) + return SZ_OK; + } + return SZ_OK; +} + +#define GET_NEXT_THREAD(p) &p->mtCoder->threads[p->index == p->mtCoder->numThreads - 1 ? 0 : p->index + 1] + +static SRes MtThread_Process(CMtThread *p, Bool *stop) +{ + CMtThread *next; + *stop = True; + if (Event_Wait(&p->canRead) != 0) + return SZ_ERROR_THREAD; + + next = GET_NEXT_THREAD(p); + + if (p->stopReading) + { + next->stopReading = True; + return Event_Set(&next->canRead) == 0 ? SZ_OK : SZ_ERROR_THREAD; + } + + { + size_t size = p->mtCoder->blockSize; + size_t destSize = p->outBufSize; + + RINOK(FullRead(p->mtCoder->inStream, p->inBuf, &size)); + next->stopReading = *stop = (size != p->mtCoder->blockSize); + if (Event_Set(&next->canRead) != 0) + return SZ_ERROR_THREAD; + + RINOK(p->mtCoder->mtCallback->Code(p->mtCoder->mtCallback, p->index, + p->outBuf, &destSize, p->inBuf, size, *stop)); + + MtProgress_Reinit(&p->mtCoder->mtProgress, p->index); + + if (Event_Wait(&p->canWrite) != 0) + return SZ_ERROR_THREAD; + if (p->stopWriting) + return SZ_ERROR_FAIL; + if (p->mtCoder->outStream->Write(p->mtCoder->outStream, p->outBuf, destSize) != destSize) + return SZ_ERROR_WRITE; + return Event_Set(&next->canWrite) == 0 ? SZ_OK : SZ_ERROR_THREAD; + } +} + +static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp) +{ + CMtThread *p = (CMtThread *)pp; + for (;;) + { + Bool stop; + CMtThread *next = GET_NEXT_THREAD(p); + SRes res = MtThread_Process(p, &stop); + if (res != SZ_OK) + { + MtCoder_SetError(p->mtCoder, res); + MtProgress_SetError(&p->mtCoder->mtProgress, res); + next->stopReading = True; + next->stopWriting = True; + Event_Set(&next->canRead); + Event_Set(&next->canWrite); + return res; + } + if (stop) + return 0; + } +} + +void MtCoder_Construct(CMtCoder* p) +{ + unsigned i; + p->alloc = 0; + for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++) + { + CMtThread *t = &p->threads[i]; + t->index = i; + CMtThread_Construct(t, p); + } + CriticalSection_Init(&p->cs); + CriticalSection_Init(&p->mtProgress.cs); +} + +void MtCoder_Destruct(CMtCoder* p) +{ + unsigned i; + for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++) + CMtThread_Destruct(&p->threads[i]); + CriticalSection_Delete(&p->cs); + CriticalSection_Delete(&p->mtProgress.cs); +} + +SRes MtCoder_Code(CMtCoder *p) +{ + unsigned i, numThreads = p->numThreads; + SRes res = SZ_OK; + p->res = SZ_OK; + + MtProgress_Init(&p->mtProgress, p->progress); + + for (i = 0; i < numThreads; i++) + { + RINOK(CMtThread_Prepare(&p->threads[i])); + } + + for (i = 0; i < numThreads; i++) + { + CMtThread *t = &p->threads[i]; + CLoopThread *lt = &t->thread; + + if (!Thread_WasCreated(<->thread)) + { + lt->func = ThreadFunc; + lt->param = t; + + if (LoopThread_Create(lt) != SZ_OK) + { + res = SZ_ERROR_THREAD; + break; + } + } + } + + if (res == SZ_OK) + { + unsigned j; + for (i = 0; i < numThreads; i++) + { + CMtThread *t = &p->threads[i]; + if (LoopThread_StartSubThread(&t->thread) != SZ_OK) + { + res = SZ_ERROR_THREAD; + p->threads[0].stopReading = True; + break; + } + } + + Event_Set(&p->threads[0].canWrite); + Event_Set(&p->threads[0].canRead); + + for (j = 0; j < i; j++) + LoopThread_WaitSubThread(&p->threads[j].thread); + } + + for (i = 0; i < numThreads; i++) + CMtThread_CloseEvents(&p->threads[i]); + return (res == SZ_OK) ? p->res : res; +} diff --git a/C/MtCoder.h b/C/MtCoder.h new file mode 100755 index 0000000..705208e --- /dev/null +++ b/C/MtCoder.h @@ -0,0 +1,98 @@ +/* MtCoder.h -- Multi-thread Coder +2009-11-19 : Igor Pavlov : Public domain */ + +#ifndef __MT_CODER_H +#define __MT_CODER_H + +#include "Threads.h" + +EXTERN_C_BEGIN + +typedef struct +{ + CThread thread; + CAutoResetEvent startEvent; + CAutoResetEvent finishedEvent; + int stop; + + THREAD_FUNC_TYPE func; + LPVOID param; + THREAD_FUNC_RET_TYPE res; +} CLoopThread; + +void LoopThread_Construct(CLoopThread *p); +void LoopThread_Close(CLoopThread *p); +WRes LoopThread_Create(CLoopThread *p); +WRes LoopThread_StopAndWait(CLoopThread *p); +WRes LoopThread_StartSubThread(CLoopThread *p); +WRes LoopThread_WaitSubThread(CLoopThread *p); + +#ifndef _7ZIP_ST +#define NUM_MT_CODER_THREADS_MAX 32 +#else +#define NUM_MT_CODER_THREADS_MAX 1 +#endif + +typedef struct +{ + UInt64 totalInSize; + UInt64 totalOutSize; + ICompressProgress *progress; + SRes res; + CCriticalSection cs; + UInt64 inSizes[NUM_MT_CODER_THREADS_MAX]; + UInt64 outSizes[NUM_MT_CODER_THREADS_MAX]; +} CMtProgress; + +SRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize); + +struct _CMtCoder; + +typedef struct +{ + struct _CMtCoder *mtCoder; + Byte *outBuf; + size_t outBufSize; + Byte *inBuf; + size_t inBufSize; + unsigned index; + CLoopThread thread; + + Bool stopReading; + Bool stopWriting; + CAutoResetEvent canRead; + CAutoResetEvent canWrite; +} CMtThread; + +typedef struct +{ + SRes (*Code)(void *p, unsigned index, Byte *dest, size_t *destSize, + const Byte *src, size_t srcSize, int finished); +} IMtCoderCallback; + +typedef struct _CMtCoder +{ + size_t blockSize; + size_t destBlockSize; + unsigned numThreads; + + ISeqInStream *inStream; + ISeqOutStream *outStream; + ICompressProgress *progress; + ISzAlloc *alloc; + + IMtCoderCallback *mtCallback; + CCriticalSection cs; + SRes res; + + CMtProgress mtProgress; + CMtThread threads[NUM_MT_CODER_THREADS_MAX]; +} CMtCoder; + +void MtCoder_Construct(CMtCoder* p); +void MtCoder_Destruct(CMtCoder* p); +SRes MtCoder_Code(CMtCoder *p); + +EXTERN_C_END + +#endif diff --git a/C/Ppmd.h b/C/Ppmd.h new file mode 100755 index 0000000..14344a7 --- /dev/null +++ b/C/Ppmd.h @@ -0,0 +1,81 @@ +/* Ppmd.h -- PPMD codec common code +2010-03-12 : Igor Pavlov : Public domain +This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ + +#ifndef __PPMD_H +#define __PPMD_H + +#include "Types.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) + +/* 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; + +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) \ + { unsigned i; for (i = 0; i < 256 / sizeof(p[0]); i += 8) { \ + p[i+7] = p[i+6] = p[i+5] = p[i+4] = p[i+3] = p[i+2] = p[i+1] = p[i+0] = ~(size_t)0; }} + +EXTERN_C_END + +#endif diff --git a/C/Ppmd7.c b/C/Ppmd7.c new file mode 100755 index 0000000..4b160cf --- /dev/null +++ b/C/Ppmd7.c @@ -0,0 +1,708 @@ +/* Ppmd7.c -- PPMdH codec +2010-03-12 : Igor Pavlov : Public domain +This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ + +#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[(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, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->Base); + p->Size = 0; + p->Base = 0; +} + +Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc) +{ + if (p->Base == 0 || p->Size != size) + { + Ppmd7_Free(p, alloc); + p->AlignOffset = + #ifdef PPMD_32BIT + (4 - size) & 3; + #else + 4 - (size & 3); + #endif + if ((p->Base = (Byte *)alloc->Alloc(alloc, p->AlignOffset + size + #ifndef PPMD_32BIT + + UNIT_SIZE + #endif + )) == 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(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[p->NS2Indx[nonMasked - 1]] + + (nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) + + 2 * (p->MinContext->SummFreq < 11 * p->MinContext->NumStats) + + 4 * (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/C/Ppmd7.h b/C/Ppmd7.h new file mode 100755 index 0000000..56e81eb --- /dev/null +++ b/C/Ppmd7.h @@ -0,0 +1,140 @@ +/* Ppmd7.h -- PPMdH compression codec +2010-03-12 : 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, ISzAlloc *alloc); +void Ppmd7_Free(CPpmd7 *p, ISzAlloc *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[Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \ + p->NS2BSIndx[Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \ + (p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \ + 2 * p->HB2Flag[Ppmd7Context_OneState(p->MinContext)->Symbol] + \ + ((p->RunLength >> 26) & 0x20)] + +CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale); + + +/* ---------- Decode ---------- */ + +typedef struct +{ + UInt32 (*GetThreshold)(void *p, UInt32 total); + void (*Decode)(void *p, UInt32 start, UInt32 size); + UInt32 (*DecodeBit)(void *p, UInt32 size0); +} IPpmd7_RangeDec; + +typedef struct +{ + IPpmd7_RangeDec p; + 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, 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/C/Ppmd7Dec.c b/C/Ppmd7Dec.c new file mode 100755 index 0000000..d6608e8 --- /dev/null +++ b/C/Ppmd7Dec.c @@ -0,0 +1,187 @@ +/* Ppmd7Dec.c -- PPMdH Decoder +2010-03-12 : Igor Pavlov : Public domain +This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ + +#include "Ppmd7.h" + +#define kTopValue (1 << 24) + +Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p) +{ + unsigned i; + p->Code = 0; + p->Range = 0xFFFFFFFF; + if (p->Stream->Read((void *)p->Stream) != 0) + return False; + for (i = 0; i < 4; i++) + p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream); + return (p->Code < 0xFFFFFFFF); +} + +static UInt32 Range_GetThreshold(void *pp, UInt32 total) +{ + CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp; + return (p->Code) / (p->Range /= total); +} + +static void Range_Normalize(CPpmd7z_RangeDec *p) +{ + if (p->Range < kTopValue) + { + p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream); + p->Range <<= 8; + if (p->Range < kTopValue) + { + p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream); + p->Range <<= 8; + } + } +} + +static void Range_Decode(void *pp, UInt32 start, UInt32 size) +{ + CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp; + p->Code -= start * p->Range; + p->Range *= size; + Range_Normalize(p); +} + +static UInt32 Range_DecodeBit(void *pp, UInt32 size0) +{ + CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp; + 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->p.GetThreshold = Range_GetThreshold; + p->p.Decode = Range_Decode; + p->p.DecodeBit = Range_DecodeBit; +} + + +#define MASK(sym) ((signed char *)charMask)[sym] + +int Ppmd7_DecodeSymbol(CPpmd7 *p, 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/C/Ppmd7Enc.c b/C/Ppmd7Enc.c new file mode 100755 index 0000000..b1fecae --- /dev/null +++ b/C/Ppmd7Enc.c @@ -0,0 +1,185 @@ +/* Ppmd7Enc.c -- PPMdH Encoder +2010-03-12 : Igor Pavlov : Public domain +This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ + +#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 + { + p->Stream->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/C/Ppmd8.c b/C/Ppmd8.c new file mode 100755 index 0000000..4fe723f --- /dev/null +++ b/C/Ppmd8.c @@ -0,0 +1,1120 @@ +/* Ppmd8.c -- PPMdI codec +2010-03-24 : Igor Pavlov : Public domain +This code is based on PPMd var.I (2002): Dmitry Shkarin : Public domain */ + +#include + +#include "Ppmd8.h" + +const Byte PPMD8_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[(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) ((CPpmd8_Context *)Ppmd8_GetContext(p, ref)) +#define STATS(ctx) Ppmd8_GetStats(p, ctx) +#define ONE_STATE(ctx) Ppmd8Context_OneState(ctx) +#define SUFFIX(ctx) CTX((ctx)->Suffix) + +typedef CPpmd8_Context * CTX_PTR; + +struct CPpmd8_Node_; + +typedef + #ifdef PPMD_32BIT + struct CPpmd8_Node_ * + #else + UInt32 + #endif + CPpmd8_Node_Ref; + +typedef struct CPpmd8_Node_ +{ + UInt32 Stamp; + CPpmd8_Node_Ref Next; + UInt32 NU; +} CPpmd8_Node; + +#ifdef PPMD_32BIT + #define NODE(ptr) (ptr) +#else + #define NODE(offs) ((CPpmd8_Node *)(p->Base + (offs))) +#endif + +#define EMPTY_NODE 0xFFFFFFFF + +void Ppmd8_Construct(CPpmd8 *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 < 5; i++) + p->NS2Indx[i] = (Byte)i; + for (m = i, k = 1; i < 260; i++) + { + p->NS2Indx[i] = (Byte)m; + if (--k == 0) + k = (++m) - 4; + } +} + +void Ppmd8_Free(CPpmd8 *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->Base); + p->Size = 0; + p->Base = 0; +} + +Bool Ppmd8_Alloc(CPpmd8 *p, UInt32 size, ISzAlloc *alloc) +{ + if (p->Base == 0 || p->Size != size) + { + Ppmd8_Free(p, alloc); + p->AlignOffset = + #ifdef PPMD_32BIT + (4 - size) & 3; + #else + 4 - (size & 3); + #endif + if ((p->Base = (Byte *)alloc->Alloc(alloc, p->AlignOffset + size)) == 0) + return False; + p->Size = size; + } + return True; +} + +static void InsertNode(CPpmd8 *p, void *node, unsigned indx) +{ + ((CPpmd8_Node *)node)->Stamp = EMPTY_NODE; + ((CPpmd8_Node *)node)->Next = (CPpmd8_Node_Ref)p->FreeList[indx]; + ((CPpmd8_Node *)node)->NU = I2U(indx); + p->FreeList[indx] = REF(node); + p->Stamps[indx]++; +} + +static void *RemoveNode(CPpmd8 *p, unsigned indx) +{ + CPpmd8_Node *node = NODE((CPpmd8_Node_Ref)p->FreeList[indx]); + p->FreeList[indx] = node->Next; + p->Stamps[indx]--; + return node; +} + +static void SplitBlock(CPpmd8 *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(CPpmd8 *p) +{ + CPpmd8_Node_Ref head = 0; + CPpmd8_Node_Ref *prev = &head; + unsigned i; + + p->GlueCount = 1 << 13; + memset(p->Stamps, 0, sizeof(p->Stamps)); + + /* Order-0 context is always at top UNIT, so we don't need guard NODE at the end. + All blocks up to p->LoUnit can be free, so we need guard NODE at LoUnit. */ + if (p->LoUnit != p->HiUnit) + ((CPpmd8_Node *)p->LoUnit)->Stamp = 0; + + /* Glue free blocks */ + for (i = 0; i < PPMD_NUM_INDEXES; i++) + { + CPpmd8_Node_Ref next = (CPpmd8_Node_Ref)p->FreeList[i]; + p->FreeList[i] = 0; + while (next != 0) + { + CPpmd8_Node *node = NODE(next); + if (node->NU != 0) + { + CPpmd8_Node *node2; + *prev = next; + prev = &(node->Next); + while ((node2 = node + node->NU)->Stamp == EMPTY_NODE) + { + node->NU += node2->NU; + node2->NU = 0; + } + } + next = node->Next; + } + } + *prev = 0; + + /* Fill lists of free blocks */ + while (head != 0) + { + CPpmd8_Node *node = NODE(head); + unsigned nu; + head = node->Next; + nu = node->NU; + if (nu == 0) + continue; + for (; 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); + } +} + +static void *AllocUnitsRare(CPpmd8 *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(CPpmd8 *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(CPpmd8 *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; +} + +static void FreeUnits(CPpmd8 *p, void *ptr, unsigned nu) +{ + InsertNode(p, ptr, U2I(nu)); +} + +static void SpecialFreeUnit(CPpmd8 *p, void *ptr) +{ + if ((Byte *)ptr != p->UnitsStart) + InsertNode(p, ptr, 0); + else + { + #ifdef PPMD8_FREEZE_SUPPORT + *(UInt32 *)ptr = EMPTY_NODE; /* it's used for (Flags == 0xFF) check in RemoveBinContexts */ + #endif + p->UnitsStart += UNIT_SIZE; + } +} + +static void *MoveUnitsUp(CPpmd8 *p, void *oldPtr, unsigned nu) +{ + unsigned indx = U2I(nu); + void *ptr; + if ((Byte *)oldPtr > p->UnitsStart + 16 * 1024 || REF(oldPtr) > p->FreeList[indx]) + return oldPtr; + ptr = RemoveNode(p, indx); + MyMem12Cpy(ptr, oldPtr, nu); + if ((Byte*)oldPtr != p->UnitsStart) + InsertNode(p, oldPtr, indx); + else + p->UnitsStart += U2B(I2U(indx)); + return ptr; +} + +static void ExpandTextArea(CPpmd8 *p) +{ + UInt32 count[PPMD_NUM_INDEXES]; + unsigned i; + memset(count, 0, sizeof(count)); + if (p->LoUnit != p->HiUnit) + ((CPpmd8_Node *)p->LoUnit)->Stamp = 0; + + { + CPpmd8_Node *node = (CPpmd8_Node *)p->UnitsStart; + for (; node->Stamp == EMPTY_NODE; node += node->NU) + { + node->Stamp = 0; + count[U2I(node->NU)]++; + } + p->UnitsStart = (Byte *)node; + } + + for (i = 0; i < PPMD_NUM_INDEXES; i++) + { + CPpmd8_Node_Ref *next = (CPpmd8_Node_Ref *)&p->FreeList[i]; + while (count[i] != 0) + { + CPpmd8_Node *node = NODE(*next); + while (node->Stamp == 0) + { + *next = node->Next; + node = NODE(*next); + p->Stamps[i]--; + if (--count[i] == 0) + break; + } + next = &node->Next; + } + } +} + +#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); +} + +#define RESET_TEXT(offs) { p->Text = p->Base + p->AlignOffset + (offs); } + +static void RestartModel(CPpmd8 *p) +{ + unsigned i, k, m, r; + + memset(p->FreeList, 0, sizeof(p->FreeList)); + memset(p->Stamps, 0, sizeof(p->Stamps)); + RESET_TEXT(0); + 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 = 255; + p->MinContext->Flags = 0; + 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 = m = 0; m < 25; m++) + { + while (p->NS2Indx[i] == m) + i++; + for (k = 0; k < 8; k++) + { + UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 1)); + UInt16 *dest = p->BinSumm[m] + k; + for (r = 0; r < 64; r += 8) + dest[r] = val; + } + } + + for (i = m = 0; m < 24; m++) + { + while (p->NS2Indx[i + 3] == m + 3) + i++; + for (k = 0; k < 32; k++) + { + CPpmd_See *s = &p->See[m][k]; + s->Summ = (UInt16)((2 * i + 5) << (s->Shift = PPMD_PERIOD_BITS - 4)); + s->Count = 7; + } + } +} + +void Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod) +{ + p->MaxOrder = maxOrder; + p->RestoreMethod = restoreMethod; + RestartModel(p); + p->DummySee.Shift = PPMD_PERIOD_BITS; + p->DummySee.Summ = 0; /* unused */ + p->DummySee.Count = 64; /* unused */ +} + +static void Refresh(CPpmd8 *p, CTX_PTR ctx, unsigned oldNU, unsigned scale) +{ + unsigned i = ctx->NumStats, escFreq, sumFreq, flags; + CPpmd_State *s = (CPpmd_State *)ShrinkUnits(p, STATS(ctx), oldNU, (i + 2) >> 1); + ctx->Stats = REF(s); + #ifdef PPMD8_FREEZE_SUPPORT + /* fixed over Shkarin's code. Fixed code is not compatible with original code for some files in FREEZE mode. */ + scale |= (ctx->SummFreq >= ((UInt32)1 << 15)); + #endif + flags = (ctx->Flags & (0x10 + 0x04 * scale)) + 0x08 * (s->Symbol >= 0x40); + escFreq = ctx->SummFreq - s->Freq; + sumFreq = (s->Freq = (Byte)((s->Freq + scale) >> scale)); + do + { + escFreq -= (++s)->Freq; + sumFreq += (s->Freq = (Byte)((s->Freq + scale) >> scale)); + flags |= 0x08 * (s->Symbol >= 0x40); + } + while (--i); + ctx->SummFreq = (UInt16)(sumFreq + ((escFreq + scale) >> scale)); + ctx->Flags = (Byte)flags; +} + +static void SwapStates(CPpmd_State *t1, CPpmd_State *t2) +{ + CPpmd_State tmp = *t1; + *t1 = *t2; + *t2 = tmp; +} + +static CPpmd_Void_Ref CutOff(CPpmd8 *p, CTX_PTR ctx, unsigned order) +{ + int i; + unsigned tmp; + CPpmd_State *s; + + if (!ctx->NumStats) + { + s = ONE_STATE(ctx); + if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) >= p->UnitsStart) + { + if (order < p->MaxOrder) + SetSuccessor(s, CutOff(p, CTX(SUCCESSOR(s)), order + 1)); + else + SetSuccessor(s, 0); + if (SUCCESSOR(s) || order <= 9) /* O_BOUND */ + return REF(ctx); + } + SpecialFreeUnit(p, ctx); + return 0; + } + + ctx->Stats = STATS_REF(MoveUnitsUp(p, STATS(ctx), tmp = ((unsigned)ctx->NumStats + 2) >> 1)); + + for (s = STATS(ctx) + (i = ctx->NumStats); s >= STATS(ctx); s--) + if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) < p->UnitsStart) + { + CPpmd_State *s2 = STATS(ctx) + (i--); + SetSuccessor(s, 0); + SwapStates(s, s2); + } + else if (order < p->MaxOrder) + SetSuccessor(s, CutOff(p, CTX(SUCCESSOR(s)), order + 1)); + else + SetSuccessor(s, 0); + + if (i != ctx->NumStats && order) + { + ctx->NumStats = (Byte)i; + s = STATS(ctx); + if (i < 0) + { + FreeUnits(p, s, tmp); + SpecialFreeUnit(p, ctx); + return 0; + } + if (i == 0) + { + ctx->Flags = (ctx->Flags & 0x10) + 0x08 * (s->Symbol >= 0x40); + *ONE_STATE(ctx) = *s; + FreeUnits(p, s, tmp); + ONE_STATE(ctx)->Freq = (Byte)((unsigned)ONE_STATE(ctx)->Freq + 11) >> 3; + } + else + Refresh(p, ctx, tmp, ctx->SummFreq > 16 * i); + } + return REF(ctx); +} + +#ifdef PPMD8_FREEZE_SUPPORT +static CPpmd_Void_Ref RemoveBinContexts(CPpmd8 *p, CTX_PTR ctx, unsigned order) +{ + CPpmd_State *s; + if (!ctx->NumStats) + { + s = ONE_STATE(ctx); + if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) >= p->UnitsStart && order < p->MaxOrder) + SetSuccessor(s, RemoveBinContexts(p, CTX(SUCCESSOR(s)), order + 1)); + else + SetSuccessor(s, 0); + /* Suffix context can be removed already, since different (high-order) + Successors may refer to same context. So we check Flags == 0xFF (Stamp == EMPTY_NODE) */ + if (!SUCCESSOR(s) && (!SUFFIX(ctx)->NumStats || SUFFIX(ctx)->Flags == 0xFF)) + { + FreeUnits(p, ctx, 1); + return 0; + } + else + return REF(ctx); + } + + for (s = STATS(ctx) + ctx->NumStats; s >= STATS(ctx); s--) + if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) >= p->UnitsStart && order < p->MaxOrder) + SetSuccessor(s, RemoveBinContexts(p, CTX(SUCCESSOR(s)), order + 1)); + else + SetSuccessor(s, 0); + + return REF(ctx); +} +#endif + +static UInt32 GetUsedMemory(const CPpmd8 *p) +{ + UInt32 v = 0; + unsigned i; + for (i = 0; i < PPMD_NUM_INDEXES; i++) + v += p->Stamps[i] * I2U(i); + return p->Size - (UInt32)(p->HiUnit - p->LoUnit) - (UInt32)(p->UnitsStart - p->Text) - U2B(v); +} + +#ifdef PPMD8_FREEZE_SUPPORT + #define RESTORE_MODEL(c1, fSuccessor) RestoreModel(p, c1, fSuccessor) +#else + #define RESTORE_MODEL(c1, fSuccessor) RestoreModel(p, c1) +#endif + +static void RestoreModel(CPpmd8 *p, CTX_PTR c1 + #ifdef PPMD8_FREEZE_SUPPORT + , CTX_PTR fSuccessor + #endif + ) +{ + CTX_PTR c; + CPpmd_State *s; + RESET_TEXT(0); + for (c = p->MaxContext; c != c1; c = SUFFIX(c)) + if (--(c->NumStats) == 0) + { + s = STATS(c); + c->Flags = (c->Flags & 0x10) + 0x08 * (s->Symbol >= 0x40); + *ONE_STATE(c) = *s; + SpecialFreeUnit(p, s); + ONE_STATE(c)->Freq = (ONE_STATE(c)->Freq + 11) >> 3; + } + else + Refresh(p, c, (c->NumStats+3) >> 1, 0); + + for (; c != p->MinContext; c = SUFFIX(c)) + if (!c->NumStats) + ONE_STATE(c)->Freq -= ONE_STATE(c)->Freq >> 1; + else if ((c->SummFreq += 4) > 128 + 4 * c->NumStats) + Refresh(p, c, (c->NumStats + 2) >> 1, 1); + + #ifdef PPMD8_FREEZE_SUPPORT + if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE) + { + p->MaxContext = fSuccessor; + p->GlueCount += !(p->Stamps[1] & 1); + } + else if (p->RestoreMethod == PPMD8_RESTORE_METHOD_FREEZE) + { + while (p->MaxContext->Suffix) + p->MaxContext = SUFFIX(p->MaxContext); + RemoveBinContexts(p, p->MaxContext, 0); + p->RestoreMethod++; + p->GlueCount = 0; + p->OrderFall = p->MaxOrder; + } + else + #endif + if (p->RestoreMethod == PPMD8_RESTORE_METHOD_RESTART || GetUsedMemory(p) < (p->Size >> 1)) + RestartModel(p); + else + { + while (p->MaxContext->Suffix) + p->MaxContext = SUFFIX(p->MaxContext); + do + { + CutOff(p, p->MaxContext, 0); + ExpandTextArea(p); + } + while (GetUsedMemory(p) > 3 * (p->Size >> 2)); + p->GlueCount = 0; + p->OrderFall = p->MaxOrder; + } +} + +static CTX_PTR CreateSuccessors(CPpmd8 *p, Bool skip, CPpmd_State *s1, CTX_PTR c) +{ + CPpmd_State upState; + Byte flags; + CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState); + /* fixed over Shkarin's code. Maybe it could work without + 1 too. */ + CPpmd_State *ps[PPMD8_MAX_ORDER + 1]; + unsigned numPs = 0; + + if (!skip) + ps[numPs++] = p->FoundState; + + while (c->Suffix) + { + CPpmd_Void_Ref successor; + CPpmd_State *s; + c = SUFFIX(c); + if (s1) + { + s = s1; + s1 = NULL; + } + else if (c->NumStats != 0) + { + for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++); + if (s->Freq < MAX_FREQ - 9) + { + s->Freq++; + c->SummFreq++; + } + } + else + { + s = ONE_STATE(c); + s->Freq += (!SUFFIX(c)->NumStats & (s->Freq < 24)); + } + successor = SUCCESSOR(s); + if (successor != upBranch) + { + c = CTX(successor); + if (numPs == 0) + return c; + break; + } + ps[numPs++] = s; + } + + upState.Symbol = *(const Byte *)Ppmd8_GetPtr(p, upBranch); + SetSuccessor(&upState, upBranch + 1); + flags = 0x10 * (p->FoundState->Symbol >= 0x40) + 0x08 * (upState.Symbol >= 0x40); + + if (c->NumStats == 0) + 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) : ((cf + 2 * s0 - 3) / 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 = 0; + c1->Flags = flags; + *ONE_STATE(c1) = upState; + c1->Suffix = REF(c); + SetSuccessor(ps[--numPs], REF(c1)); + c = c1; + } + while (numPs != 0); + + return c; +} + +static CTX_PTR ReduceOrder(CPpmd8 *p, CPpmd_State *s1, CTX_PTR c) +{ + CPpmd_State *s = NULL; + CTX_PTR c1 = c; + CPpmd_Void_Ref upBranch = REF(p->Text); + + #ifdef PPMD8_FREEZE_SUPPORT + /* The BUG in Shkarin's code was fixed: ps could overflow in CUT_OFF mode. */ + CPpmd_State *ps[PPMD8_MAX_ORDER + 1]; + unsigned numPs = 0; + ps[numPs++] = p->FoundState; + #endif + + SetSuccessor(p->FoundState, upBranch); + p->OrderFall++; + + for (;;) + { + if (s1) + { + c = SUFFIX(c); + s = s1; + s1 = NULL; + } + else + { + if (!c->Suffix) + { + #ifdef PPMD8_FREEZE_SUPPORT + if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE) + { + do { SetSuccessor(ps[--numPs], REF(c)); } while (numPs); + RESET_TEXT(1); + p->OrderFall = 1; + } + #endif + return c; + } + c = SUFFIX(c); + if (c->NumStats) + { + if ((s = STATS(c))->Symbol != p->FoundState->Symbol) + do { s++; } while (s->Symbol != p->FoundState->Symbol); + if (s->Freq < MAX_FREQ - 9) + { + s->Freq += 2; + c->SummFreq += 2; + } + } + else + { + s = ONE_STATE(c); + s->Freq += (s->Freq < 32); + } + } + if (SUCCESSOR(s)) + break; + #ifdef PPMD8_FREEZE_SUPPORT + ps[numPs++] = s; + #endif + SetSuccessor(s, upBranch); + p->OrderFall++; + } + + #ifdef PPMD8_FREEZE_SUPPORT + if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE) + { + c = CTX(SUCCESSOR(s)); + do { SetSuccessor(ps[--numPs], REF(c)); } while (numPs); + RESET_TEXT(1); + p->OrderFall = 1; + return c; + } + else + #endif + if (SUCCESSOR(s) <= upBranch) + { + CTX_PTR successor; + CPpmd_State *s1 = p->FoundState; + p->FoundState = s; + + successor = CreateSuccessors(p, False, NULL, c); + if (successor == NULL) + SetSuccessor(s, 0); + else + SetSuccessor(s, REF(successor)); + p->FoundState = s1; + } + + if (p->OrderFall == 1 && c1 == p->MaxContext) + { + SetSuccessor(p->FoundState, SUCCESSOR(s)); + p->Text--; + } + if (SUCCESSOR(s) == 0) + return NULL; + return CTX(SUCCESSOR(s)); +} + +static void UpdateModel(CPpmd8 *p) +{ + CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState); + CTX_PTR c; + unsigned s0, ns, fFreq = p->FoundState->Freq; + Byte flag, fSymbol = p->FoundState->Symbol; + CPpmd_State *s = NULL; + + if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0) + { + c = SUFFIX(p->MinContext); + + if (c->NumStats == 0) + { + s = ONE_STATE(c); + if (s->Freq < 32) + s->Freq++; + } + else + { + 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; + } + } + } + + c = p->MaxContext; + if (p->OrderFall == 0 && fSuccessor) + { + CTX_PTR cs = CreateSuccessors(p, True, s, p->MinContext); + if (cs == 0) + { + SetSuccessor(p->FoundState, 0); + RESTORE_MODEL(c, CTX(fSuccessor)); + } + else + { + SetSuccessor(p->FoundState, REF(cs)); + p->MaxContext = cs; + } + return; + } + + *p->Text++ = p->FoundState->Symbol; + successor = REF(p->Text); + if (p->Text >= p->UnitsStart) + { + RESTORE_MODEL(c, CTX(fSuccessor)); /* check it */ + return; + } + + if (!fSuccessor) + { + CTX_PTR cs = ReduceOrder(p, s, p->MinContext); + if (cs == NULL) + { + RESTORE_MODEL(c, 0); + return; + } + fSuccessor = REF(cs); + } + else if ((Byte *)Ppmd8_GetPtr(p, fSuccessor) < p->UnitsStart) + { + CTX_PTR cs = CreateSuccessors(p, False, s, p->MinContext); + if (cs == NULL) + { + RESTORE_MODEL(c, 0); + return; + } + fSuccessor = REF(cs); + } + + if (--p->OrderFall == 0) + { + successor = fSuccessor; + p->Text -= (p->MaxContext != p->MinContext); + } + #ifdef PPMD8_FREEZE_SUPPORT + else if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE) + { + successor = fSuccessor; + RESET_TEXT(0); + p->OrderFall = 0; + } + #endif + + s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - fFreq; + flag = 0x08 * (fSymbol >= 0x40); + + for (; c != p->MinContext; c = SUFFIX(c)) + { + unsigned ns1; + UInt32 cf, sf; + if ((ns1 = c->NumStats) != 0) + { + if ((ns1 & 1) != 0) + { + /* Expand for one UNIT */ + unsigned oldNU = (ns1 + 1) >> 1; + unsigned i = U2I(oldNU); + if (i != U2I(oldNU + 1)) + { + void *ptr = AllocUnits(p, i + 1); + void *oldPtr; + if (!ptr) + { + RESTORE_MODEL(c, CTX(fSuccessor)); + return; + } + oldPtr = STATS(c); + MyMem12Cpy(ptr, oldPtr, oldNU); + InsertNode(p, oldPtr, i); + c->Stats = STATS_REF(ptr); + } + } + c->SummFreq = (UInt16)(c->SummFreq + (3 * ns1 + 1 < ns)); + } + else + { + CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0); + if (!s) + { + RESTORE_MODEL(c, CTX(fSuccessor)); + 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 > 2)); + } + cf = 2 * fFreq * (c->SummFreq + 6); + sf = (UInt32)s0 + c->SummFreq; + if (cf < 6 * sf) + { + cf = 1 + (cf > sf) + (cf >= 4 * sf); + c->SummFreq += 4; + } + else + { + cf = 4 + (cf > 9 * sf) + (cf > 12 * sf) + (cf > 15 * sf); + c->SummFreq = (UInt16)(c->SummFreq + cf); + } + { + CPpmd_State *s = STATS(c) + ns1 + 1; + SetSuccessor(s, successor); + s->Symbol = fSymbol; + s->Freq = (Byte)cf; + c->Flags |= flag; + c->NumStats = (Byte)(ns1 + 1); + } + } + p->MaxContext = p->MinContext = CTX(fSuccessor); +} + +static void Rescale(CPpmd8 *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 + #ifdef PPMD8_FREEZE_SUPPORT + || p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE + #endif + ); + s->Freq = (Byte)((s->Freq + adder) >> 1); + sumFreq = s->Freq; + + i = p->MinContext->NumStats; + 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 = (Byte)(p->MinContext->NumStats - i); + if (p->MinContext->NumStats == 0) + { + CPpmd_State tmp = *stats; + tmp.Freq = (Byte)((2 * tmp.Freq + escFreq - 1) / escFreq); + if (tmp.Freq > MAX_FREQ / 3) + tmp.Freq = MAX_FREQ / 3; + InsertNode(p, stats, U2I((numStats + 2) >> 1)); + p->MinContext->Flags = (p->MinContext->Flags & 0x10) + 0x08 * (tmp.Symbol >= 0x40); + *(p->FoundState = ONE_STATE(p->MinContext)) = tmp; + return; + } + n0 = (numStats + 2) >> 1; + n1 = (p->MinContext->NumStats + 2) >> 1; + if (n0 != n1) + p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1)); + p->MinContext->Flags &= ~0x08; + p->MinContext->Flags |= 0x08 * ((s = STATS(p->MinContext))->Symbol >= 0x40); + i = p->MinContext->NumStats; + do { p->MinContext->Flags |= 0x08*((++s)->Symbol >= 0x40); } while (--i); + } + p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1)); + p->MinContext->Flags |= 0x4; + p->FoundState = STATS(p->MinContext); +} + +CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked1, UInt32 *escFreq) +{ + CPpmd_See *see; + if (p->MinContext->NumStats != 0xFF) + { + see = p->See[p->NS2Indx[p->MinContext->NumStats + 2] - 3] + + (p->MinContext->SummFreq > 11 * ((unsigned)p->MinContext->NumStats + 1)) + + 2 * (2 * (unsigned)p->MinContext->NumStats < + ((unsigned)SUFFIX(p->MinContext)->NumStats + numMasked1)) + + p->MinContext->Flags; + { + 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(CPpmd8 *p) +{ + CTX_PTR c = CTX(SUCCESSOR(p->FoundState)); + if (p->OrderFall == 0 && (Byte *)c >= p->UnitsStart) + p->MinContext = p->MaxContext = c; + else + { + UpdateModel(p); + p->MinContext = p->MaxContext; + } +} + +void Ppmd8_Update1(CPpmd8 *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 Ppmd8_Update1_0(CPpmd8 *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 Ppmd8_UpdateBin(CPpmd8 *p) +{ + p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 196)); + p->PrevSuccess = 1; + p->RunLength++; + NextContext(p); +} + +void Ppmd8_Update2(CPpmd8 *p) +{ + p->MinContext->SummFreq += 4; + if ((p->FoundState->Freq += 4) > MAX_FREQ) + Rescale(p); + p->RunLength = p->InitRL; + UpdateModel(p); + p->MinContext = p->MaxContext; +} + +/* H->I changes: + NS2Indx + GlewCount, and Glue method + BinSum + See / EscFreq + CreateSuccessors updates more suffix contexts + UpdateModel consts. + PrevSuccess Update +*/ diff --git a/C/Ppmd8.h b/C/Ppmd8.h new file mode 100755 index 0000000..6efd4ea --- /dev/null +++ b/C/Ppmd8.h @@ -0,0 +1,133 @@ +/* Ppmd8.h -- PPMdI codec +2010-03-24 : Igor Pavlov : Public domain +This code is based on: + PPMd var.I (2002): Dmitry Shkarin : Public domain + Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ + +#ifndef __PPMD8_H +#define __PPMD8_H + +#include "Ppmd.h" + +EXTERN_C_BEGIN + +#define PPMD8_MIN_ORDER 2 +#define PPMD8_MAX_ORDER 16 + +struct CPpmd8_Context_; + +typedef + #ifdef PPMD_32BIT + struct CPpmd8_Context_ * + #else + UInt32 + #endif + CPpmd8_Context_Ref; + +typedef struct CPpmd8_Context_ +{ + Byte NumStats; + Byte Flags; + UInt16 SummFreq; + CPpmd_State_Ref Stats; + CPpmd8_Context_Ref Suffix; +} CPpmd8_Context; + +#define Ppmd8Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq) + +/* The BUG in Shkarin's code for FREEZE mode was fixed, but that fixed + code is not compatible with original code for some files compressed + in FREEZE mode. So we disable FREEZE mode support. */ + +enum +{ + PPMD8_RESTORE_METHOD_RESTART, + PPMD8_RESTORE_METHOD_CUT_OFF + #ifdef PPMD8_FREEZE_SUPPORT + , PPMD8_RESTORE_METHOD_FREEZE + #endif +}; + +typedef struct +{ + CPpmd8_Context *MinContext, *MaxContext; + CPpmd_State *FoundState; + unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder; + Int32 RunLength, InitRL; /* must be 32-bit at least */ + + UInt32 Size; + UInt32 GlueCount; + Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart; + UInt32 AlignOffset; + unsigned RestoreMethod; + + /* Range Coder */ + UInt32 Range; + UInt32 Code; + UInt32 Low; + union + { + IByteIn *In; + IByteOut *Out; + } Stream; + + Byte Indx2Units[PPMD_NUM_INDEXES]; + Byte Units2Indx[128]; + CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES]; + UInt32 Stamps[PPMD_NUM_INDEXES]; + + Byte NS2BSIndx[256], NS2Indx[260]; + CPpmd_See DummySee, See[24][32]; + UInt16 BinSumm[25][64]; +} CPpmd8; + +void Ppmd8_Construct(CPpmd8 *p); +Bool Ppmd8_Alloc(CPpmd8 *p, UInt32 size, ISzAlloc *alloc); +void Ppmd8_Free(CPpmd8 *p, ISzAlloc *alloc); +void Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod); +#define Ppmd8_WasAllocated(p) ((p)->Base != NULL) + + +/* ---------- Internal Functions ---------- */ + +extern const Byte PPMD8_kExpEscape[16]; + +#ifdef PPMD_32BIT + #define Ppmd8_GetPtr(p, ptr) (ptr) + #define Ppmd8_GetContext(p, ptr) (ptr) + #define Ppmd8_GetStats(p, ctx) ((ctx)->Stats) +#else + #define Ppmd8_GetPtr(p, offs) ((void *)((p)->Base + (offs))) + #define Ppmd8_GetContext(p, offs) ((CPpmd8_Context *)Ppmd8_GetPtr((p), (offs))) + #define Ppmd8_GetStats(p, ctx) ((CPpmd_State *)Ppmd8_GetPtr((p), ((ctx)->Stats))) +#endif + +void Ppmd8_Update1(CPpmd8 *p); +void Ppmd8_Update1_0(CPpmd8 *p); +void Ppmd8_Update2(CPpmd8 *p); +void Ppmd8_UpdateBin(CPpmd8 *p); + +#define Ppmd8_GetBinSumm(p) \ + &p->BinSumm[p->NS2Indx[Ppmd8Context_OneState(p->MinContext)->Freq - 1]][ \ + p->NS2BSIndx[Ppmd8_GetContext(p, p->MinContext->Suffix)->NumStats] + \ + p->PrevSuccess + p->MinContext->Flags + ((p->RunLength >> 26) & 0x20)] + +CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked, UInt32 *scale); + + +/* ---------- Decode ---------- */ + +Bool Ppmd8_RangeDec_Init(CPpmd8 *p); +#define Ppmd8_RangeDec_IsFinishedOK(p) ((p)->Code == 0) +int Ppmd8_DecodeSymbol(CPpmd8 *p); /* returns: -1 as EndMarker, -2 as DataError */ + + +/* ---------- Encode ---------- */ + +#define Ppmd8_RangeEnc_Init(p) { (p)->Low = 0; (p)->Range = 0xFFFFFFFF; } +void Ppmd8_RangeEnc_FlushData(CPpmd8 *p); +void Ppmd8_EncodeSymbol(CPpmd8 *p, int symbol); /* symbol = -1 means EndMarker */ + +EXTERN_C_END + +#endif diff --git a/C/Ppmd8Dec.c b/C/Ppmd8Dec.c new file mode 100755 index 0000000..934eae7 --- /dev/null +++ b/C/Ppmd8Dec.c @@ -0,0 +1,155 @@ +/* Ppmd8Dec.c -- PPMdI Decoder +2010-04-16 : Igor Pavlov : Public domain +This code is based on: + PPMd var.I (2002): Dmitry Shkarin : Public domain + Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ + +#include "Ppmd8.h" + +#define kTop (1 << 24) +#define kBot (1 << 15) + +Bool Ppmd8_RangeDec_Init(CPpmd8 *p) +{ + unsigned i; + p->Low = 0; + p->Range = 0xFFFFFFFF; + p->Code = 0; + for (i = 0; i < 4; i++) + p->Code = (p->Code << 8) | p->Stream.In->Read(p->Stream.In); + return (p->Code < 0xFFFFFFFF); +} + +static UInt32 RangeDec_GetThreshold(CPpmd8 *p, UInt32 total) +{ + return p->Code / (p->Range /= total); +} + +static void RangeDec_Decode(CPpmd8 *p, UInt32 start, UInt32 size) +{ + start *= p->Range; + p->Low += start; + p->Code -= start; + p->Range *= size; + + while ((p->Low ^ (p->Low + p->Range)) < kTop || + (p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1))) + { + p->Code = (p->Code << 8) | p->Stream.In->Read(p->Stream.In); + p->Range <<= 8; + p->Low <<= 8; + } +} + +#define MASK(sym) ((signed char *)charMask)[sym] + +int Ppmd8_DecodeSymbol(CPpmd8 *p) +{ + size_t charMask[256 / sizeof(size_t)]; + if (p->MinContext->NumStats != 0) + { + CPpmd_State *s = Ppmd8_GetStats(p, p->MinContext); + unsigned i; + UInt32 count, hiCnt; + if ((count = RangeDec_GetThreshold(p, p->MinContext->SummFreq)) < (hiCnt = s->Freq)) + { + Byte symbol; + RangeDec_Decode(p, 0, s->Freq); + p->FoundState = s; + symbol = s->Symbol; + Ppmd8_Update1_0(p); + return symbol; + } + p->PrevSuccess = 0; + i = p->MinContext->NumStats; + do + { + if ((hiCnt += (++s)->Freq) > count) + { + Byte symbol; + RangeDec_Decode(p, hiCnt - s->Freq, s->Freq); + p->FoundState = s; + symbol = s->Symbol; + Ppmd8_Update1(p); + return symbol; + } + } + while (--i); + if (count >= p->MinContext->SummFreq) + return -2; + RangeDec_Decode(p, hiCnt, p->MinContext->SummFreq - hiCnt); + PPMD_SetAllBitsIn256Bytes(charMask); + MASK(s->Symbol) = 0; + i = p->MinContext->NumStats; + do { MASK((--s)->Symbol) = 0; } while (--i); + } + else + { + UInt16 *prob = Ppmd8_GetBinSumm(p); + if (((p->Code / (p->Range >>= 14)) < *prob)) + { + Byte symbol; + RangeDec_Decode(p, 0, *prob); + *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob); + symbol = (p->FoundState = Ppmd8Context_OneState(p->MinContext))->Symbol; + Ppmd8_UpdateBin(p); + return symbol; + } + RangeDec_Decode(p, *prob, (1 << 14) - *prob); + *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob); + p->InitEsc = PPMD8_kExpEscape[*prob >> 10]; + PPMD_SetAllBitsIn256Bytes(charMask); + MASK(Ppmd8Context_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 = Ppmd8_GetContext(p, p->MinContext->Suffix); + } + while (p->MinContext->NumStats == numMasked); + hiCnt = 0; + s = Ppmd8_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 = Ppmd8_MakeEscFreq(p, numMasked, &freqSum); + freqSum += hiCnt; + count = RangeDec_GetThreshold(p, freqSum); + + if (count < hiCnt) + { + Byte symbol; + CPpmd_State **pps = ps; + for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++); + s = *pps; + RangeDec_Decode(p, hiCnt - s->Freq, s->Freq); + Ppmd_See_Update(see); + p->FoundState = s; + symbol = s->Symbol; + Ppmd8_Update2(p); + return symbol; + } + if (count >= freqSum) + return -2; + RangeDec_Decode(p, hiCnt, freqSum - hiCnt); + see->Summ = (UInt16)(see->Summ + freqSum); + do { MASK(ps[--i]->Symbol) = 0; } while (i != 0); + } +} diff --git a/C/Ppmd8Enc.c b/C/Ppmd8Enc.c new file mode 100755 index 0000000..24b6383 --- /dev/null +++ b/C/Ppmd8Enc.c @@ -0,0 +1,161 @@ +/* Ppmd8Enc.c -- PPMdI Encoder +2010-04-16 : Igor Pavlov : Public domain +This code is based on: + PPMd var.I (2002): Dmitry Shkarin : Public domain + Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ + +#include "Ppmd8.h" + +#define kTop (1 << 24) +#define kBot (1 << 15) + +void Ppmd8_RangeEnc_FlushData(CPpmd8 *p) +{ + unsigned i; + for (i = 0; i < 4; i++, p->Low <<= 8 ) + p->Stream.Out->Write(p->Stream.Out, (Byte)(p->Low >> 24)); +} + +static void RangeEnc_Normalize(CPpmd8 *p) +{ + while ((p->Low ^ (p->Low + p->Range)) < kTop || + (p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1))) + { + p->Stream.Out->Write(p->Stream.Out, (Byte)(p->Low >> 24)); + p->Range <<= 8; + p->Low <<= 8; + } +} + +static void RangeEnc_Encode(CPpmd8 *p, UInt32 start, UInt32 size, UInt32 total) +{ + p->Low += start * (p->Range /= total); + p->Range *= size; + RangeEnc_Normalize(p); +} + +static void RangeEnc_EncodeBit_0(CPpmd8 *p, UInt32 size0) +{ + p->Range >>= 14; + p->Range *= size0; + RangeEnc_Normalize(p); +} + +static void RangeEnc_EncodeBit_1(CPpmd8 *p, UInt32 size0) +{ + p->Low += size0 * (p->Range >>= 14); + p->Range *= ((1 << 14) - size0); + RangeEnc_Normalize(p); +} + + +#define MASK(sym) ((signed char *)charMask)[sym] + +void Ppmd8_EncodeSymbol(CPpmd8 *p, int symbol) +{ + size_t charMask[256 / sizeof(size_t)]; + if (p->MinContext->NumStats != 0) + { + CPpmd_State *s = Ppmd8_GetStats(p, p->MinContext); + UInt32 sum; + unsigned i; + if (s->Symbol == symbol) + { + RangeEnc_Encode(p, 0, s->Freq, p->MinContext->SummFreq); + p->FoundState = s; + Ppmd8_Update1_0(p); + return; + } + p->PrevSuccess = 0; + sum = s->Freq; + i = p->MinContext->NumStats; + do + { + if ((++s)->Symbol == symbol) + { + RangeEnc_Encode(p, sum, s->Freq, p->MinContext->SummFreq); + p->FoundState = s; + Ppmd8_Update1(p); + return; + } + sum += s->Freq; + } + while (--i); + + PPMD_SetAllBitsIn256Bytes(charMask); + MASK(s->Symbol) = 0; + i = p->MinContext->NumStats; + do { MASK((--s)->Symbol) = 0; } while (--i); + RangeEnc_Encode(p, sum, p->MinContext->SummFreq - sum, p->MinContext->SummFreq); + } + else + { + UInt16 *prob = Ppmd8_GetBinSumm(p); + CPpmd_State *s = Ppmd8Context_OneState(p->MinContext); + if (s->Symbol == symbol) + { + RangeEnc_EncodeBit_0(p, *prob); + *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob); + p->FoundState = s; + Ppmd8_UpdateBin(p); + return; + } + else + { + RangeEnc_EncodeBit_1(p, *prob); + *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob); + p->InitEsc = PPMD8_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 = Ppmd8_GetContext(p, p->MinContext->Suffix); + } + while (p->MinContext->NumStats == numMasked); + + see = Ppmd8_MakeEscFreq(p, numMasked, &escFreq); + s = Ppmd8_GetStats(p, p->MinContext); + sum = 0; + i = p->MinContext->NumStats + 1; + 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(p, low, s1->Freq, sum + escFreq); + Ppmd_See_Update(see); + p->FoundState = s1; + Ppmd8_Update2(p); + return; + } + sum += (s->Freq & (int)(MASK(cur))); + MASK(cur) = 0; + s++; + } + while (--i); + + RangeEnc_Encode(p, sum, escFreq, sum + escFreq); + see->Summ = (UInt16)(see->Summ + sum + escFreq); + } +} diff --git a/C/RotateDefs.h b/C/RotateDefs.h new file mode 100755 index 0000000..ff9b722 --- /dev/null +++ b/C/RotateDefs.h @@ -0,0 +1,20 @@ +/* RotateDefs.h -- Rotate functions +2009-02-07 : Igor Pavlov : Public domain */ + +#ifndef __ROTATE_DEFS_H +#define __ROTATE_DEFS_H + +#ifdef _MSC_VER + +#include +#define rotlFixed(x, n) _rotl((x), (n)) +#define rotrFixed(x, n) _rotr((x), (n)) + +#else + +#define rotlFixed(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) +#define rotrFixed(x, n) (((x) >> (n)) | ((x) << (32 - (n)))) + +#endif + +#endif diff --git a/C/Sha256.c b/C/Sha256.c new file mode 100755 index 0000000..cfb9eac --- /dev/null +++ b/C/Sha256.c @@ -0,0 +1,204 @@ +/* Crypto/Sha256.c -- SHA-256 Hash +2010-06-11 : Igor Pavlov : Public domain +This code is based on public domain code from Wei Dai's Crypto++ library. */ + +#include "RotateDefs.h" +#include "Sha256.h" + +/* define it for speed optimization */ +/* #define _SHA256_UNROLL */ +/* #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] = data[i]) +#define blk2(i) (W[i&15] += s1(W[(i-2)&15]) + W[(i-7)&15] + s0(W[(i-15)&15])) + +#define Ch(x,y,z) (z^(x&(y^z))) +#define Maj(x,y,z) ((x&y)|(z&(x|y))) + +#define a(i) T[(0-(i))&7] +#define b(i) T[(1-(i))&7] +#define c(i) T[(2-(i))&7] +#define d(i) T[(3-(i))&7] +#define e(i) T[(4-(i))&7] +#define f(i) T[(5-(i))&7] +#define g(i) T[(6-(i))&7] +#define h(i) T[(7-(i))&7] + + +#ifdef _SHA256_UNROLL2 + +#define R(a,b,c,d,e,f,g,h, i) h += S1(e) + Ch(e,f,g) + K[i+j] + (j?blk2(i):blk0(i));\ + d += h; h += S0(a) + Maj(a, b, c) + +#define 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) + +#else + +#define R(i) h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[i+j] + (j?blk2(i):blk0(i));\ + d(i) += h(i); h(i) += S0(a(i)) + Maj(a(i), b(i), c(i)) + +#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); + +#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_Transform(UInt32 *state, const UInt32 *data) +{ + UInt32 W[16]; + unsigned j; + #ifdef _SHA256_UNROLL2 + UInt32 a,b,c,d,e,f,g,h; + 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 + UInt32 T[8]; + for (j = 0; j < 8; j++) + T[j] = state[j]; + #endif + + for (j = 0; j < 64; j += 16) + { + #if defined(_SHA256_UNROLL) || defined(_SHA256_UNROLL2) + RX_8(0); RX_8(8); + #else + unsigned i; + for (i = 0; i < 16; i++) { R(i); } + #endif + } + + #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 + +static void Sha256_WriteByteBlock(CSha256 *p) +{ + UInt32 data32[16]; + unsigned i; + for (i = 0; i < 16; i++) + data32[i] = + ((UInt32)(p->buffer[i * 4 ]) << 24) + + ((UInt32)(p->buffer[i * 4 + 1]) << 16) + + ((UInt32)(p->buffer[i * 4 + 2]) << 8) + + ((UInt32)(p->buffer[i * 4 + 3])); + Sha256_Transform(p->state, data32); +} + +void Sha256_Update(CSha256 *p, const Byte *data, size_t size) +{ + UInt32 curBufferPos = (UInt32)p->count & 0x3F; + while (size > 0) + { + p->buffer[curBufferPos++] = *data++; + p->count++; + size--; + if (curBufferPos == 64) + { + curBufferPos = 0; + Sha256_WriteByteBlock(p); + } + } +} + +void Sha256_Final(CSha256 *p, Byte *digest) +{ + UInt64 lenInBits = (p->count << 3); + UInt32 curBufferPos = (UInt32)p->count & 0x3F; + unsigned i; + p->buffer[curBufferPos++] = 0x80; + while (curBufferPos != (64 - 8)) + { + curBufferPos &= 0x3F; + if (curBufferPos == 0) + Sha256_WriteByteBlock(p); + p->buffer[curBufferPos++] = 0; + } + for (i = 0; i < 8; i++) + { + p->buffer[curBufferPos++] = (Byte)(lenInBits >> 56); + lenInBits <<= 8; + } + Sha256_WriteByteBlock(p); + + for (i = 0; i < 8; i++) + { + *digest++ = (Byte)(p->state[i] >> 24); + *digest++ = (Byte)(p->state[i] >> 16); + *digest++ = (Byte)(p->state[i] >> 8); + *digest++ = (Byte)(p->state[i]); + } + Sha256_Init(p); +} diff --git a/C/Sha256.h b/C/Sha256.h new file mode 100755 index 0000000..26d1e3a --- /dev/null +++ b/C/Sha256.h @@ -0,0 +1,26 @@ +/* Sha256.h -- SHA-256 Hash +2010-06-11 : Igor Pavlov : Public domain */ + +#ifndef __CRYPTO_SHA256_H +#define __CRYPTO_SHA256_H + +#include "Types.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/C/Sort.c b/C/Sort.c new file mode 100755 index 0000000..d06e565 --- /dev/null +++ b/C/Sort.c @@ -0,0 +1,93 @@ +/* Sort.c -- Sort functions +2010-09-17 : Igor Pavlov : Public domain */ + +#include "Sort.h" + +#define HeapSortDown(p, k, size, temp) \ + { for (;;) { \ + UInt32 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, UInt32 size) +{ + if (size <= 1) + return; + p--; + { + UInt32 i = size / 2; + do + { + UInt32 temp = p[i]; + UInt32 k = i; + HeapSortDown(p, k, size, temp) + } + while (--i != 0); + } + /* + do + { + UInt32 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]; + UInt32 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; + } +} + +/* +#define HeapSortRefDown(p, vals, n, size, temp) \ + { UInt32 k = n; UInt32 val = vals[temp]; for (;;) { \ + UInt32 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, UInt32 size) +{ + if (size <= 1) + return; + p--; + { + UInt32 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/C/Sort.h b/C/Sort.h new file mode 100755 index 0000000..7613039 --- /dev/null +++ b/C/Sort.h @@ -0,0 +1,20 @@ +/* Sort.h -- Sort functions +2009-02-07 : Igor Pavlov : Public domain */ + +#ifndef __7Z_SORT_H +#define __7Z_SORT_H + +#include "Types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void HeapSort(UInt32 *p, UInt32 size); +/* void HeapSortRef(UInt32 *p, UInt32 *vals, UInt32 size); */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/C/Threads.c b/C/Threads.c new file mode 100755 index 0000000..4be44fb --- /dev/null +++ b/C/Threads.c @@ -0,0 +1,84 @@ +/* Threads.c -- multithreading library +2009-09-20 : Igor Pavlov : Public domain */ + +#ifndef _WIN32_WCE +#include +#endif + +#include "Threads.h" + +static WRes GetError() +{ + DWORD res = GetLastError(); + return (res) ? (WRes)(res) : 1; +} + +WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); } +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) +{ + unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ + *p = + #ifdef UNDER_CE + CreateThread(0, 0, func, param, 0, &threadId); + #else + (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId); + #endif + /* maybe we must use errno here, but probably GetLastError() is also OK. */ + return HandleToWRes(*p); +} + +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/C/Threads.h b/C/Threads.h new file mode 100755 index 0000000..6a7afa8 --- /dev/null +++ b/C/Threads.h @@ -0,0 +1,59 @@ +/* Threads.h -- multithreading library +2009-03-27 : Igor Pavlov : Public domain */ + +#ifndef __7Z_THREADS_H +#define __7Z_THREADS_H + +#include "Types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +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 unsigned 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_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) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/C/Types.h b/C/Types.h new file mode 100755 index 0000000..f193ce2 --- /dev/null +++ b/C/Types.h @@ -0,0 +1,254 @@ +/* Types.h -- Basic types +2010-10-09 : Igor Pavlov : Public domain */ + +#ifndef __7Z_TYPES_H +#define __7Z_TYPES_H + +#include + +#ifdef _WIN32 +#include +#endif + +#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; +#else +typedef int WRes; +#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_CDECL __cdecl +#define MY_FAST_CALL __fastcall + +#else + +#define MY_CDECL +#define MY_FAST_CALL + +#endif + + +/* The following interfaces use first parameter as pointer to structure */ + +typedef struct +{ + Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */ +} IByteIn; + +typedef struct +{ + void (*Write)(void *p, Byte b); +} IByteOut; + +typedef struct +{ + SRes (*Read)(void *p, void *buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) < input(*size)) is allowed */ +} ISeqInStream; + +/* it can return SZ_ERROR_INPUT_EOF */ +SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); +SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); +SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); + +typedef struct +{ + size_t (*Write)(void *p, const void *buf, size_t size); + /* Returns: result - the number of actually written bytes. + (result < size) means error */ +} ISeqOutStream; + +typedef enum +{ + SZ_SEEK_SET = 0, + SZ_SEEK_CUR = 1, + SZ_SEEK_END = 2 +} ESzSeek; + +typedef struct +{ + SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ + SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); +} ISeekInStream; + +typedef struct +{ + SRes (*Look)(void *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)(void *p, size_t offset); + /* offset must be <= output(*size) of Look */ + + SRes (*Read)(void *p, void *buf, size_t *size); + /* reads directly (without buffer). It's same as ISeqInStream::Read */ + SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); +} ILookInStream; + +SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); +SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); + +/* reads via ILookInStream::Read */ +SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); +SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); + +#define LookToRead_BUF_SIZE (1 << 14) + +typedef struct +{ + ILookInStream s; + ISeekInStream *realStream; + size_t pos; + size_t size; + Byte buf[LookToRead_BUF_SIZE]; +} CLookToRead; + +void LookToRead_CreateVTable(CLookToRead *p, int lookahead); +void LookToRead_Init(CLookToRead *p); + +typedef struct +{ + ISeqInStream s; + ILookInStream *realStream; +} CSecToLook; + +void SecToLook_CreateVTable(CSecToLook *p); + +typedef struct +{ + ISeqInStream s; + ILookInStream *realStream; +} CSecToRead; + +void SecToRead_CreateVTable(CSecToRead *p); + +typedef struct +{ + SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); + /* Returns: result. (result != SZ_OK) means break. + Value (UInt64)(Int64)-1 for size means unknown value. */ +} ICompressProgress; + +typedef struct +{ + void *(*Alloc)(void *p, size_t size); + void (*Free)(void *p, void *address); /* address can be 0 */ +} ISzAlloc; + +#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) +#define IAlloc_Free(p, a) (p)->Free((p), a) + +#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/C/Util/7z/7z.dsp b/C/Util/7z/7z.dsp new file mode 100755 index 0000000..9f5806b --- /dev/null +++ b/C/Util/7z/7z.dsp @@ -0,0 +1,214 @@ +# 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 /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /FAs /YX /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/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 /Gm /GX /ZI /Od /D "_DEBUG" /D "_SZ_ALLOC_DEBUG2" /D "_SZ_NO_INT_64_A" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /YX /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/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=..\..\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=..\..\7zIn.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zStream.c +# 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=..\..\CpuArch.c +# End Source File +# Begin Source File + +SOURCE=..\..\CpuArch.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 +# SUBTRACT CPP /YX +# End Source File +# Begin Source File + +SOURCE=..\..\Ppmd7.h +# End Source File +# Begin Source File + +SOURCE=..\..\Ppmd7Dec.c +# SUBTRACT CPP /YX +# End Source File +# Begin Source File + +SOURCE=..\..\Types.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\7zMain.c +# End Source File +# End Target +# End Project diff --git a/C/Util/7z/7z.dsw b/C/Util/7z/7z.dsw new file mode 100755 index 0000000..23089fb --- /dev/null +++ b/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/C/Util/7z/7zMain.c b/C/Util/7z/7zMain.c new file mode 100755 index 0000000..f217340 --- /dev/null +++ b/C/Util/7z/7zMain.c @@ -0,0 +1,501 @@ +/* 7zMain.c - Test application for 7z Decoder +2010-10-28 : Igor Pavlov : Public domain */ + +#include +#include + +#include "../../7z.h" +#include "../../7zAlloc.h" +#include "../../7zCrc.h" +#include "../../7zFile.h" +#include "../../7zVersion.h" + +#ifndef USE_WINDOWS_FILE +/* for mkdir */ +#ifdef _WIN32 +#include +#else +#include +#include +#endif +#endif + +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +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 + +static Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + +static Bool Utf16_To_Utf8(Byte *dest, size_t *destLen, const UInt16 *src, size_t srcLen) +{ + size_t destPos = 0, srcPos = 0; + for (;;) + { + unsigned numAdds; + UInt32 value; + if (srcPos == srcLen) + { + *destLen = destPos; + return True; + } + value = src[srcPos++]; + if (value < 0x80) + { + if (dest) + dest[destPos] = (char)value; + destPos++; + continue; + } + if (value >= 0xD800 && value < 0xE000) + { + UInt32 c2; + if (value >= 0xDC00 || srcPos == srcLen) + break; + c2 = src[srcPos++]; + if (c2 < 0xDC00 || c2 >= 0xE000) + break; + value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000; + } + for (numAdds = 1; numAdds < 5; numAdds++) + if (value < (((UInt32)1) << (numAdds * 5 + 6))) + break; + if (dest) + dest[destPos] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); + destPos++; + do + { + numAdds--; + if (dest) + dest[destPos] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); + destPos++; + } + while (numAdds != 0); + } + *destLen = destPos; + return False; +} + +static SRes Utf16_To_Utf8Buf(CBuf *dest, const UInt16 *src, size_t srcLen) +{ + size_t destLen = 0; + Bool res; + Utf16_To_Utf8(NULL, &destLen, src, srcLen); + destLen += 1; + if (!Buf_EnsureSize(dest, destLen)) + return SZ_ERROR_MEM; + res = Utf16_To_Utf8(dest->data, &destLen, src, srcLen); + dest->data[destLen] = 0; + return res ? SZ_OK : SZ_ERROR_FAIL; +} +#endif + +static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s, int fileMode) +{ + int len = 0; + for (len = 0; s[len] != '\0'; len++); + + #ifdef _WIN32 + { + int size = len * 3 + 100; + if (!Buf_EnsureSize(buf, size)) + return SZ_ERROR_MEM; + { + char defaultChar = '_'; + BOOL defUsed; + int numChars = WideCharToMultiByte(fileMode ? + ( + #ifdef UNDER_CE + CP_ACP + #else + AreFileApisANSI() ? CP_ACP : CP_OEMCP + #endif + ) : CP_OEMCP, + 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 + fileMode = fileMode; + return Utf16_To_Utf8Buf(buf, s, len); + #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, 1)); + + 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, 1)); + 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, 0); + if (res == SZ_OK) + fputs((const char *)buf.data, stdout); + Buf_Free(&buf, &g_Alloc); + return res; +} + +static void UInt64ToStr(UInt64 value, char *s) +{ + char temp[32]; + int pos = 0; + do + { + temp[pos++] = (char)('0' + (unsigned)(value % 10)); + value /= 10; + } + while (value != 0); + 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; +} + +#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 *ft, char *s) +{ + unsigned year, mon, day, hour, min, sec; + UInt64 v64 = (ft->Low | ((UInt64)ft->High << 32)) / 10000000; + Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + unsigned t; + UInt32 v; + 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 = 1; mon <= 12; mon++) + { + unsigned s = ms[mon - 1]; + if (v < s) + break; + v -= s; + } + day = (unsigned)v + 1; + s = UIntToStr(s, year, 4); *s++ = '-'; + s = UIntToStr(s, mon, 2); *s++ = '-'; + s = UIntToStr(s, day, 2); *s++ = ' '; + s = UIntToStr(s, hour, 2); *s++ = ':'; + s = UIntToStr(s, min, 2); *s++ = ':'; + s = UIntToStr(s, sec, 2); +} + +void PrintError(char *sz) +{ + printf("\nERROR: %s\n", sz); +} + +#ifdef USE_WINDOWS_FILE +#define kEmptyAttribChar '.' +static void GetAttribString(UInt32 wa, Bool isDir, char *s) +{ + s[0] = (char)(((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : kEmptyAttribChar); + s[1] = (char)(((wa & FILE_ATTRIBUTE_READONLY) != 0) ? 'R': kEmptyAttribChar); + s[2] = (char)(((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? 'H': kEmptyAttribChar); + s[3] = (char)(((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? 'S': kEmptyAttribChar); + s[4] = (char)(((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? 'A': kEmptyAttribChar); + s[5] = '\0'; +} +#else +static void GetAttribString(UInt32, Bool, char *s) +{ + s[0] = '\0'; +} +#endif + +int MY_CDECL main(int numargs, char *args[]) +{ + CFileInStream archiveStream; + CLookToRead lookStream; + CSzArEx db; + SRes res; + ISzAlloc allocImp; + ISzAlloc allocTempImp; + UInt16 *temp = NULL; + size_t tempSize = 0; + + printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n\n"); + if (numargs == 1) + { + printf( + "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; + } + + allocImp.Alloc = SzAlloc; + allocImp.Free = SzFree; + + allocTempImp.Alloc = SzAllocTemp; + allocTempImp.Free = SzFreeTemp; + + if (InFile_Open(&archiveStream.file, args[2])) + { + PrintError("can not open input file"); + return 1; + } + + FileInStream_CreateVTable(&archiveStream); + LookToRead_CreateVTable(&lookStream, False); + + lookStream.realStream = &archiveStream.s; + LookToRead_Init(&lookStream); + + CrcGenerateTable(); + + SzArEx_Init(&db); + res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp); + if (res == SZ_OK) + { + char *command = args[1]; + int listCommand = 0, testCommand = 0, extractCommand = 0, fullPaths = 0; + if (strcmp(command, "l") == 0) listCommand = 1; + else if (strcmp(command, "t") == 0) testCommand = 1; + else if (strcmp(command, "e") == 0) extractCommand = 1; + else if (strcmp(command, "x") == 0) { extractCommand = 1; 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.db.NumFiles; i++) + { + size_t offset = 0; + size_t outSizeProcessed = 0; + const CSzFileItem *f = db.db.Files + i; + size_t len; + if (listCommand == 0 && f->IsDir && !fullPaths) + continue; + len = SzArEx_GetFileNameUtf16(&db, i, NULL); + + if (len > tempSize) + { + SzFree(NULL, temp); + tempSize = len; + temp = (UInt16 *)SzAlloc(NULL, tempSize * sizeof(temp[0])); + if (temp == 0) + { + res = SZ_ERROR_MEM; + break; + } + } + + SzArEx_GetFileNameUtf16(&db, i, temp); + if (listCommand) + { + char attr[8], s[32], t[32]; + + GetAttribString(f->AttribDefined ? f->Attrib : 0, f->IsDir, attr); + + UInt64ToStr(f->Size, s); + if (f->MTimeDefined) + ConvertFileTimeToString(&f->MTime, t); + else + { + size_t j; + for (j = 0; j < 19; j++) + t[j] = ' '; + t[j] = '\0'; + } + + printf("%s %s %10s ", t, attr, s); + res = PrintString(temp); + if (res != SZ_OK) + break; + if (f->IsDir) + printf("/"); + printf("\n"); + continue; + } + fputs(testCommand ? + "Testing ": + "Extracting ", + stdout); + res = PrintString(temp); + if (res != SZ_OK) + break; + if (f->IsDir) + printf("/"); + else + { + res = SzArEx_Extract(&db, &lookStream.s, 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 (f->IsDir) + { + MyCreateDir(destPath); + printf("\n"); + 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; + } + if (File_Close(&outFile)) + { + PrintError("can not close output file"); + res = SZ_ERROR_FAIL; + break; + } + #ifdef USE_WINDOWS_FILE + if (f->AttribDefined) + SetFileAttributesW(destPath, f->Attrib); + #endif + } + printf("\n"); + } + IAlloc_Free(&allocImp, outBuffer); + } + } + SzArEx_Free(&db, &allocImp); + SzFree(NULL, temp); + + File_Close(&archiveStream.file); + if (res == SZ_OK) + { + printf("\nEverything is Ok\n"); + return 0; + } + if (res == SZ_ERROR_UNSUPPORTED) + PrintError("decoder doesn't support this archive"); + else if (res == SZ_ERROR_MEM) + PrintError("can not allocate memory"); + else if (res == SZ_ERROR_CRC) + PrintError("CRC error"); + else + printf("\nERROR #%d\n", res); + return 1; +} diff --git a/C/Util/7z/makefile b/C/Util/7z/makefile new file mode 100755 index 0000000..3b85364 --- /dev/null +++ b/C/Util/7z/makefile @@ -0,0 +1,37 @@ +MY_STATIC_LINK=1 +CFLAGS = $(CFLAGS) -D_7ZIP_PPMD_SUPPPORT + +PROG = 7zDec.exe + +C_OBJS = \ + $O\7zAlloc.obj \ + $O\7zBuf.obj \ + $O\7zBuf2.obj \ + $O\7zCrc.obj \ + $O\7zCrcOpt.obj \ + $O\7zFile.obj \ + $O\7zDec.obj \ + $O\7zIn.obj \ + $O\7zStream.obj \ + $O\Bcj2.obj \ + $O\Bra.obj \ + $O\Bra86.obj \ + $O\CpuArch.obj \ + $O\Lzma2Dec.obj \ + $O\LzmaDec.obj \ + $O\Ppmd7.obj \ + $O\Ppmd7Dec.obj \ + +7Z_OBJS = \ + $O\7zMain.obj \ + +OBJS = \ + $(7Z_OBJS) \ + $(C_OBJS) \ + +!include "../../../CPP/Build.mak" + +$(7Z_OBJS): $(*B).c + $(COMPL_O1) +$(C_OBJS): ../../$(*B).c + $(COMPL_O2) diff --git a/C/Util/7z/makefile.gcc b/C/Util/7z/makefile.gcc new file mode 100755 index 0000000..2fb1576 --- /dev/null +++ b/C/Util/7z/makefile.gcc @@ -0,0 +1,70 @@ +PROG = 7zDec +CXX = g++ +LIB = +RM = rm -f +CFLAGS = -c -O2 -Wall + +OBJS = 7zMain.o 7zAlloc.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zCrcOpt.o 7zDec.o 7zIn.o CpuArch.o LzmaDec.o Lzma2Dec.o Bra.o Bra86.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 + +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 + +7zIn.o: ../../7zIn.c + $(CXX) $(CFLAGS) ../../7zIn.c + +CpuArch.o: ../../CpuArch.c + $(CXX) $(CFLAGS) ../../CpuArch.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 + +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/C/Util/Lzma/LzmaUtil.c b/C/Util/Lzma/LzmaUtil.c new file mode 100755 index 0000000..f8de4a2 --- /dev/null +++ b/C/Util/Lzma/LzmaUtil.c @@ -0,0 +1,254 @@ +/* LzmaUtil.c -- Test application for LZMA compression +2010-09-20 : Igor Pavlov : Public domain */ + +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include + +#include "../../Alloc.h" +#include "../../7zFile.h" +#include "../../7zVersion.h" +#include "../../LzmaDec.h" +#include "../../LzmaEnc.h" + +const char *kCantReadMessage = "Can not read input file"; +const char *kCantWriteMessage = "Can not write output file"; +const char *kCantAllocateMessage = "Can not allocate memory"; +const char *kDataErrorMessage = "Data error"; + +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } +static void SzFree(void *p, void *address) { p = p; MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +void PrintHelp(char *buffer) +{ + strcat(buffer, "\nLZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n" + "\nUsage: lzma inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n"); +} + +int PrintError(char *buffer, const char *message) +{ + strcat(buffer, "\nError: "); + strcat(buffer, message); + strcat(buffer, "\n"); + return 1; +} + +int PrintErrorNumber(char *buffer, SRes val) +{ + sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val); + return 1; +} + +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; + + rs = 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; +} + +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.s, &inStream.s, fileSize, rs); + } + else + { + res = Decode(&outStream.s, useOutFile ? &inStream.s : 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/C/Util/Lzma/LzmaUtil.dsp b/C/Util/Lzma/LzmaUtil.dsp new file mode 100755 index 0000000..4815511 --- /dev/null +++ b/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 /W3 /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 /W3 /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=..\..\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 +# Begin Source File + +SOURCE=..\..\Types.h +# End Source File +# End Target +# End Project diff --git a/C/Util/Lzma/LzmaUtil.dsw b/C/Util/Lzma/LzmaUtil.dsw new file mode 100755 index 0000000..f435487 --- /dev/null +++ b/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/C/Util/Lzma/makefile b/C/Util/Lzma/makefile new file mode 100755 index 0000000..e99e098 --- /dev/null +++ b/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/C/Util/Lzma/makefile.gcc b/C/Util/Lzma/makefile.gcc new file mode 100755 index 0000000..12a72bb --- /dev/null +++ b/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/C/Util/LzmaLib/LzmaLib.def b/C/Util/LzmaLib/LzmaLib.def new file mode 100755 index 0000000..43b9597 --- /dev/null +++ b/C/Util/LzmaLib/LzmaLib.def @@ -0,0 +1,4 @@ +EXPORTS + LzmaCompress + LzmaUncompress + diff --git a/C/Util/LzmaLib/LzmaLib.dsp b/C/Util/LzmaLib/LzmaLib.dsp new file mode 100755 index 0000000..bf52b63 --- /dev/null +++ b/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=..\..\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 +# Begin Source File + +SOURCE=..\..\Types.h +# End Source File +# End Target +# End Project diff --git a/C/Util/LzmaLib/LzmaLib.dsw b/C/Util/LzmaLib/LzmaLib.dsw new file mode 100755 index 0000000..f6c5559 --- /dev/null +++ b/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/C/Util/LzmaLib/LzmaLibExports.c b/C/Util/LzmaLib/LzmaLibExports.c new file mode 100755 index 0000000..7434536 --- /dev/null +++ b/C/Util/LzmaLib/LzmaLibExports.c @@ -0,0 +1,12 @@ +/* LzmaLibExports.c -- LZMA library DLL Entry point +2008-10-04 : Igor Pavlov : Public domain */ + +#include + +BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) +{ + hInstance = hInstance; + dwReason = dwReason; + lpReserved = lpReserved; + return TRUE; +} diff --git a/C/Util/LzmaLib/makefile b/C/Util/LzmaLib/makefile new file mode 100755 index 0000000..e0f3114 --- /dev/null +++ b/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/C/Util/LzmaLib/resource.rc b/C/Util/LzmaLib/resource.rc new file mode 100755 index 0000000..cb62ed9 --- /dev/null +++ b/C/Util/LzmaLib/resource.rc @@ -0,0 +1,4 @@ +#include "../../../CPP/7zip/MyVersionInfo.rc" + +MY_VERSION_INFO_DLL("LZMA library", "LZMA") + diff --git a/C/Util/SfxSetup/SfxSetup.c b/C/Util/SfxSetup/SfxSetup.c new file mode 100755 index 0000000..d4eb5c4 --- /dev/null +++ b/C/Util/SfxSetup/SfxSetup.c @@ -0,0 +1,592 @@ +/* SfxSetup.c - 7z SFX Setup +2010-11-11 : Igor Pavlov : Public domain */ + +#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" + +#define k_EXE_ExtIndex 1 + +static const char *kExts[] = +{ + "bat", + "exe", + "inf", + "msi", + #ifdef UNDER_CE + "cab", + #endif + "html", + "htm" +}; + +static const char *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 **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 = 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) +{ + ctrlType = 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 numTests, pos; + if (*resPos > kSignatureSearchLimit) + return False; + + do + { + size_t processed = kBufferSize - numPrevBytes; + if (File_Read(stream, buf + numPrevBytes, &processed) != 0) + return False; + if (processed == 0) + return False; + numPrevBytes += processed; + } + while (numPrevBytes <= k7zStartHeaderSize); + + numTests = numPrevBytes - k7zStartHeaderSize; + for (pos = 0; pos < numTests; pos++) + { + for (; buf[pos] != '7' && pos < numTests; pos++); + if (pos == numTests) + break; + if (memcmp(buf + pos, k7zSignature, k7zSignatureSize) == 0) + if (CrcCalc(buf + pos + 12, 20) == GetUi32(buf + pos + 8)) + { + *resPos += pos; + return True; + } + } + *resPos += numTests; + numPrevBytes -= numTests; + memmove(buf, buf + numTests, numPrevBytes); + } +} + +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, L"\\"); + 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; + CLookToRead lookStream; + CSzArEx db; + SRes res = SZ_OK; + ISzAlloc allocImp; + ISzAlloc allocTempImp; + WCHAR sfxPath[MAX_PATH + 2]; + WCHAR path[MAX_PATH * 3 + 2]; + size_t pathLen; + DWORD winRes; + const wchar_t *cmdLineParams; + const char *errorMessage = NULL; + Bool useShellExecute = True; + + #ifdef _CONSOLE + SetConsoleCtrlHandler(HandlerRoutine, TRUE); + #else + hInstance = hInstance; + hPrevInstance = hPrevInstance; + lpCmdLine = lpCmdLine; + nCmdShow = nCmdShow; + #endif + + CrcGenerateTable(); + + allocImp.Alloc = SzAlloc; + allocImp.Free = SzFree; + + allocTempImp.Alloc = SzAllocTemp; + allocTempImp.Free = SzFreeTemp; + + FileInStream_CreateVTable(&archiveStream); + LookToRead_CreateVTable(&lookStream, False); + + 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] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + } + s[k] = '\0'; + } + + if (DoesFileOrDirExist(path)) + continue; + if (CreateDirectoryW(path, NULL)) + { + wcscat(path, L"\\"); + pathLen = wcslen(path); + break; + } + if (GetLastError() != ERROR_ALREADY_EXISTS) + { + res = SZ_ERROR_FAIL; + break; + } + } + 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.realStream = &archiveStream.s; + LookToRead_Init(&lookStream); + } + + SzArEx_Init(&db); + if (res == SZ_OK) + { + res = SzArEx_Open(&db, &lookStream.s, &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.db.NumFiles; i++) + { + size_t offset = 0; + size_t outSizeProcessed = 0; + const CSzFileItem *f = db.db.Files + i; + size_t len; + WCHAR *temp; + len = SzArEx_GetFileNameUtf16(&db, i, NULL); + + if (len >= MAX_PATH) + { + res = SZ_ERROR_FAIL; + break; + } + + temp = path + pathLen; + + SzArEx_GetFileNameUtf16(&db, i, temp); + { + res = SzArEx_Extract(&db, &lookStream.s, 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 (f->IsDir) + { + 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 (f->MTimeDefined) + { + FILETIME mTime; + mTime.dwLowDateTime = f->MTime.Low; + mTime.dwHighDateTime = f->MTime.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 (f->AttribDefined) + SetFileAttributesW(path, f->Attrib); + #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; + } + } + IAlloc_Free(&allocImp, outBuffer); + } + SzArEx_Free(&db, &allocImp); + + File_Close(&archiveStream.file); + + if (res == SZ_OK) + { + HANDLE hProcess = 0; + 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); + CloseHandle(hProcess); + } + } + + path[pathLen] = L'\0'; + RemoveDirWithSubItems(path); + + if (res == SZ_OK) + return 0; + + { + 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/C/Util/SfxSetup/SfxSetup.dsp b/C/Util/SfxSetup/SfxSetup.dsp new file mode 100755 index 0000000..10814a5 --- /dev/null +++ b/C/Util/SfxSetup/SfxSetup.dsp @@ -0,0 +1,198 @@ +# 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 /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /YX /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 /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /YX /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=..\..\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=..\..\7zIn.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zStream.c +# 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=..\..\CpuArch.c +# End Source File +# Begin Source File + +SOURCE=..\..\CpuArch.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=..\..\Types.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\SfxSetup.c +# End Source File +# End Target +# End Project diff --git a/C/Util/SfxSetup/SfxSetup.dsw b/C/Util/SfxSetup/SfxSetup.dsw new file mode 100755 index 0000000..128fcdd --- /dev/null +++ b/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/C/Util/SfxSetup/makefile b/C/Util/SfxSetup/makefile new file mode 100755 index 0000000..5d91be1 --- /dev/null +++ b/C/Util/SfxSetup/makefile @@ -0,0 +1,35 @@ +PROG = 7zS2.sfx +LIBS = $(LIBS) +CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE + +C_OBJS = \ + $O\7zAlloc.obj \ + $O\7zBuf.obj \ + $O\7zBuf2.obj \ + $O\7zCrc.obj \ + $O\7zCrcOpt.obj \ + $O\7zFile.obj \ + $O\7zDec.obj \ + $O\7zIn.obj \ + $O\7zStream.obj \ + $O\Bcj2.obj \ + $O\Bra.obj \ + $O\Bra86.obj \ + $O\CpuArch.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/C/Util/SfxSetup/makefile_con b/C/Util/SfxSetup/makefile_con new file mode 100755 index 0000000..3fbb6b6 --- /dev/null +++ b/C/Util/SfxSetup/makefile_con @@ -0,0 +1,35 @@ +PROG = 7zS2con.sfx +LIBS = $(LIBS) +CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE -D_CONSOLE + +C_OBJS = \ + $O\7zAlloc.obj \ + $O\7zBuf.obj \ + $O\7zBuf2.obj \ + $O\7zCrc.obj \ + $O\7zCrcOpt.obj \ + $O\7zFile.obj \ + $O\7zDec.obj \ + $O\7zIn.obj \ + $O\7zStream.obj \ + $O\Bcj2.obj \ + $O\Bra.obj \ + $O\Bra86.obj \ + $O\CpuArch.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/C/Util/SfxSetup/resource.rc b/C/Util/SfxSetup/resource.rc new file mode 100755 index 0000000..efff95e --- /dev/null +++ b/C/Util/SfxSetup/resource.rc @@ -0,0 +1,6 @@ +#include "../../../CPP/7zip/MyVersionInfo.rc" + +MY_VERSION_INFO_APP("7z Setup SFX small", "7zS2.sfx") + +1 ICON "setup.ico" + diff --git a/C/Util/SfxSetup/setup.ico b/C/Util/SfxSetup/setup.ico new file mode 100755 index 0000000000000000000000000000000000000000..dbb6ca8b478520c64f5061355813df6a810a67f1 GIT binary patch literal 1078 zcmb7?zi!(w5XR3@0Bfq9C$Og?BLNN>oq<4x41Nobt%m{{H0S^i(kA3l0u<27p%3Dr zC^9-w5H)~->vtsO6lpr-q#uu;K2oPYM>L@`S}y0L@o+};8F@aB`f@__DI>bXwI#R) z6FSF8#8~@&FibeiF=51%y!XgzNH|GEX8?y@(&3-j*%&4{Z5hLky8C|9IoH{=pe?`M zmaZ&qTF|PG)20R357)tu8`=)8?jLpO+$~C+bQj~K$NJVZ4HJ#emswL3Ou4lyyoiXg zMh2!`m2{t}&aZ|(`n^%TtEwu!pe5*R82UEsmp<%YRab4($nT~Vo8x|2UngJs88n%? zJ>b*1wH%CUs@sbTdETtWxujq2MZSEM>= 7; + } + while (v != 0); + buf[i - 1] &= 0x7F; + return i; +} + +void Xz_Construct(CXzStream *p) +{ + p->numBlocks = p->numBlocksAllocated = 0; + p->blocks = 0; + p->flags = 0; +} + +void Xz_Free(CXzStream *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->blocks); + p->numBlocks = p->numBlocksAllocated = 0; + p->blocks = 0; +} + +unsigned XzFlags_GetCheckSize(CXzStreamFlags f) +{ + int t = XzFlags_GetCheckType(f); + return (t == 0) ? 0 : (4 << ((t - 1) / 3)); +} + +void XzCheck_Init(CXzCheck *p, int 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/C/Xz.h b/C/Xz.h new file mode 100755 index 0000000..d307963 --- /dev/null +++ b/C/Xz.h @@ -0,0 +1,252 @@ +/* Xz.h - Xz interface +2010-09-17 : 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) + +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 Byte XZ_SIG[XZ_SIG_SIZE]; +extern Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE]; + +#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 +{ + int mode; + UInt32 crc; + UInt64 crc64; + CSha256 sha; +} CXzCheck; + +void XzCheck_Init(CXzCheck *p, int 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; + size_t numBlocksAllocated; + CXzBlockSizes *blocks; + UInt64 startOffset; +} CXzStream; + +void Xz_Construct(CXzStream *p); +void Xz_Free(CXzStream *p, ISzAlloc *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, ISzAlloc *alloc); +SRes Xzs_ReadBackward(CXzs *p, ILookInStream *inStream, Int64 *startOffset, ICompressProgress *progress, ISzAlloc *alloc); + +UInt64 Xzs_GetNumBlocks(const CXzs *p); +UInt64 Xzs_GetUnpackSize(const CXzs *p); + +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; + +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, ISzAlloc *alloc); + SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAlloc *alloc); + void (*Init)(void *p); + SRes (*Code)(void *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished); +} IStateCoder; + +#define MIXCODER_NUM_FILTERS_MAX 4 + +typedef struct +{ + ISzAlloc *alloc; + Byte *buf; + int numCoders; + 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]; + IStateCoder coders[MIXCODER_NUM_FILTERS_MAX]; +} CMixCoder; + +void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc); +void MixCoder_Free(CMixCoder *p); +void MixCoder_Init(CMixCoder *p); +SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId); +SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, int srcWasFinished, + ECoderFinishMode finishMode, ECoderStatus *status); + +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; + UInt64 indexSize; + UInt64 indexPos; + UInt64 padSize; + + UInt64 numStreams; + + UInt32 crc; + CMixCoder decoder; + CXzBlock block; + CXzCheck check; + CSha256 sha; + Byte shaDigest[SHA256_DIGEST_SIZE]; + Byte buf[XZ_BLOCK_HEADER_SIZE_MAX]; +} CXzUnpacker; + +SRes XzUnpacker_Create(CXzUnpacker *p, ISzAlloc *alloc); +void XzUnpacker_Free(CXzUnpacker *p); + +/* +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 XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, /* int srcWasFinished, */ int finishMode, + ECoderStatus *status); + +Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p); + +EXTERN_C_END + +#endif diff --git a/C/XzCrc64.c b/C/XzCrc64.c new file mode 100755 index 0000000..f688b07 --- /dev/null +++ b/C/XzCrc64.c @@ -0,0 +1,33 @@ +/* XzCrc64.c -- CRC64 calculation +2010-04-16 : Igor Pavlov : Public domain */ + +#include "XzCrc64.h" + +#define kCrc64Poly UINT64_CONST(0xC96C5795D7870F42) +UInt64 g_Crc64Table[256]; + +void MY_FAST_CALL Crc64GenerateTable(void) +{ + UInt32 i; + for (i = 0; i < 256; i++) + { + UInt64 r = i; + int j; + for (j = 0; j < 8; j++) + r = (r >> 1) ^ ((UInt64)kCrc64Poly & ~((r & 1) - 1)); + g_Crc64Table[i] = r; + } +} + +UInt64 MY_FAST_CALL Crc64Update(UInt64 v, const void *data, size_t size) +{ + const Byte *p = (const Byte *)data; + for (; size > 0 ; size--, p++) + v = CRC64_UPDATE_BYTE(v, *p); + return v; +} + +UInt64 MY_FAST_CALL Crc64Calc(const void *data, size_t size) +{ + return CRC64_GET_DIGEST(Crc64Update(CRC64_INIT_VAL, data, size)); +} diff --git a/C/XzCrc64.h b/C/XzCrc64.h new file mode 100755 index 0000000..05d0d09 --- /dev/null +++ b/C/XzCrc64.h @@ -0,0 +1,26 @@ +/* XzCrc64.h -- CRC64 calculation +2010-04-16 : Igor Pavlov : Public domain */ + +#ifndef __XZ_CRC64_H +#define __XZ_CRC64_H + +#include + +#include "Types.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/C/XzDec.c b/C/XzDec.c new file mode 100755 index 0000000..2eca1af --- /dev/null +++ b/C/XzDec.c @@ -0,0 +1,875 @@ +/* XzDec.c -- Xz Decode +2010-04-16 : Igor Pavlov : Public domain */ + +/* #define XZ_DUMP */ + +#ifdef XZ_DUMP +#include +#endif + +#include +#include + +#include "7zCrc.h" +#include "Alloc.h" +#include "Bra.h" +#include "CpuArch.h" +#include "Delta.h" +#include "Lzma2Dec.h" + +#ifdef USE_SUBBLOCK +#include "SbDec.h" +#endif + +#include "Xz.h" + +#define XZ_CHECK_SIZE_MAX 64 + +#define CODER_BUF_SIZE (1 << 17) + +unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value) +{ + int i, limit; + *value = 0; + limit = (maxSize > 9) ? 9 : (int)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; + + UInt32 methodId; + int encodeMode; + UInt32 delta; + UInt32 ip; + UInt32 x86State; + Byte deltaState[DELTA_STATE_SIZE]; + + Byte buf[BRA_BUF_SIZE]; +} CBraState; + +void BraState_Free(void *pp, ISzAlloc *alloc) +{ + alloc->Free(alloc, pp); +} + +SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc) +{ + CBraState *p = ((CBraState *)pp); + alloc = alloc; + p->encodeMode = 0; + 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; +} + +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: p->bufConv = isa ## _Convert(p->buf, p->bufTotal, p->ip, p->encodeMode); break; + +static SRes BraState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished) +{ + CBraState *p = ((CBraState *)pp); + SizeT destLenOrig = *destLen; + SizeT srcLenOrig = *srcLen; + *destLen = 0; + *srcLen = 0; + finishMode = finishMode; + *wasFinished = 0; + while (destLenOrig > 0) + { + if (p->bufPos != p->bufConv) + { + size_t curSize = p->bufConv - p->bufPos; + if (curSize > destLenOrig) + curSize = destLenOrig; + memcpy(dest, p->buf + p->bufPos, curSize); + p->bufPos += curSize; + *destLen += curSize; + dest += curSize; + destLenOrig -= curSize; + continue; + } + p->bufTotal -= p->bufPos; + memmove(p->buf, p->buf + p->bufPos, p->bufTotal); + p->bufPos = 0; + p->bufConv = 0; + { + size_t curSize = BRA_BUF_SIZE - p->bufTotal; + if (curSize > srcLenOrig) + curSize = srcLenOrig; + memcpy(p->buf + p->bufTotal, src, curSize); + *srcLen += curSize; + src += curSize; + srcLenOrig -= curSize; + p->bufTotal += curSize; + } + if (p->bufTotal == 0) + break; + switch(p->methodId) + { + case XZ_ID_Delta: + if (p->encodeMode) + Delta_Encode(p->deltaState, p->delta, p->buf, p->bufTotal); + else + Delta_Decode(p->deltaState, p->delta, p->buf, p->bufTotal); + p->bufConv = p->bufTotal; + break; + case XZ_ID_X86: + p->bufConv = x86_Convert(p->buf, p->bufTotal, 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) + default: + return SZ_ERROR_UNSUPPORTED; + } + p->ip += (UInt32)p->bufConv; + + if (p->bufConv == 0) + { + if (!srcWasFinished) + break; + p->bufConv = p->bufTotal; + } + } + if (p->bufTotal == p->bufPos && srcLenOrig == 0 && srcWasFinished) + *wasFinished = 1; + return SZ_OK; +} + +SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, ISzAlloc *alloc) +{ + CBraState *decoder; + if (id != XZ_ID_Delta && + id != XZ_ID_X86 && + id != XZ_ID_PPC && + id != XZ_ID_IA64 && + id != XZ_ID_ARM && + id != XZ_ID_ARMT && + id != XZ_ID_SPARC) + return SZ_ERROR_UNSUPPORTED; + p->p = 0; + decoder = alloc->Alloc(alloc, sizeof(CBraState)); + if (decoder == 0) + return SZ_ERROR_MEM; + decoder->methodId = (UInt32)id; + p->p = decoder; + p->Free = BraState_Free; + p->SetProps = BraState_SetProps; + p->Init = BraState_Init; + p->Code = BraState_Code; + return SZ_OK; +} + +/* ---------- SbState ---------- */ + +#ifdef USE_SUBBLOCK + +static void SbState_Free(void *pp, ISzAlloc *alloc) +{ + CSubblockDec *p = (CSubblockDec *)pp; + SubblockDec_Free(p, alloc); + alloc->Free(alloc, pp); +} + +static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc) +{ + pp = pp; + props = props; + alloc = alloc; + return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED; +} + +static void SbState_Init(void *pp) +{ + SubblockDec_Init((CSubblockDec *)pp); +} + +static SRes SbState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished) +{ + ECoderStatus status; + SRes res = SubblockDec_Decode((CSubblockDec *)pp, dest, destLen, src, srcLen, finishMode, &status); + srcWasFinished = srcWasFinished; + *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK); + return res; +} + +SRes SbState_SetFromMethod(IStateCoder *p, ISzAlloc *alloc) +{ + CSubblockDec *decoder; + p->p = 0; + decoder = alloc->Alloc(alloc, sizeof(CSubblockDec)); + if (decoder == 0) + return SZ_ERROR_MEM; + p->p = decoder; + p->Free = SbState_Free; + p->SetProps = SbState_SetProps; + p->Init = SbState_Init; + p->Code = SbState_Code; + SubblockDec_Construct(decoder); + return SZ_OK; +} +#endif + +/* ---------- Lzma2State ---------- */ + +static void Lzma2State_Free(void *pp, ISzAlloc *alloc) +{ + Lzma2Dec_Free((CLzma2Dec *)pp, alloc); + alloc->Free(alloc, pp); +} + +static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc) +{ + if (propSize != 1) + return SZ_ERROR_UNSUPPORTED; + return Lzma2Dec_Allocate((CLzma2Dec *)pp, props[0], alloc); +} + +static void Lzma2State_Init(void *pp) +{ + Lzma2Dec_Init((CLzma2Dec *)pp); +} + +static SRes Lzma2State_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished) +{ + ELzmaStatus status; + /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */ + SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, finishMode, &status); + srcWasFinished = srcWasFinished; + *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK); + return res; +} + +static SRes Lzma2State_SetFromMethod(IStateCoder *p, ISzAlloc *alloc) +{ + CLzma2Dec *decoder = alloc->Alloc(alloc, sizeof(CLzma2Dec)); + p->p = decoder; + if (decoder == 0) + return SZ_ERROR_MEM; + p->Free = Lzma2State_Free; + p->SetProps = Lzma2State_SetProps; + p->Init = Lzma2State_Init; + p->Code = Lzma2State_Code; + Lzma2Dec_Construct(decoder); + return SZ_OK; +} + + +void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc) +{ + int i; + p->alloc = alloc; + p->buf = 0; + p->numCoders = 0; + for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++) + p->coders[i].p = NULL; +} + +void MixCoder_Free(CMixCoder *p) +{ + int i; + for (i = 0; i < p->numCoders; i++) + { + IStateCoder *sc = &p->coders[i]; + if (p->alloc && sc->p) + sc->Free(sc->p, p->alloc); + } + p->numCoders = 0; + if (p->buf) + p->alloc->Free(p->alloc, p->buf); +} + +void MixCoder_Init(CMixCoder *p) +{ + int i; + for (i = 0; i < p->numCoders - 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); + } +} + +SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId) +{ + IStateCoder *sc = &p->coders[coderIndex]; + p->ids[coderIndex] = methodId; + switch(methodId) + { + case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, 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, p->alloc); +} + +SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, int srcWasFinished, + ECoderFinishMode finishMode, ECoderStatus *status) +{ + SizeT destLenOrig = *destLen; + SizeT srcLenOrig = *srcLen; + Bool allFinished = True; + *destLen = 0; + *srcLen = 0; + *status = CODER_STATUS_NOT_FINISHED; + + if (p->buf == 0) + { + p->buf = p->alloc->Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1)); + if (p->buf == 0) + return SZ_ERROR_MEM; + } + + if (p->numCoders != 1) + finishMode = CODER_FINISH_ANY; + + for (;;) + { + Bool processed = False; + int i; + /* + 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 *destCur; + SizeT destLenCur, srcLenCur; + const Byte *srcCur; + int srcFinishedCur; + int encodingWasFinished; + + if (i == 0) + { + srcCur = src; + srcLenCur = srcLenOrig - *srcLen; + srcFinishedCur = srcWasFinished; + } + else + { + srcCur = p->buf + (CODER_BUF_SIZE * (i - 1)) + p->pos[i - 1]; + srcLenCur = p->size[i - 1] - p->pos[i - 1]; + srcFinishedCur = p->finished[i - 1]; + } + + if (i == p->numCoders - 1) + { + destCur = dest; + destLenCur = destLenOrig - *destLen; + } + else + { + if (p->pos[i] != p->size[i]) + continue; + destCur = p->buf + (CODER_BUF_SIZE * i); + destLenCur = CODER_BUF_SIZE; + } + + res = coder->Code(coder->p, destCur, &destLenCur, srcCur, &srcLenCur, srcFinishedCur, finishMode, &encodingWasFinished); + + if (!encodingWasFinished) + allFinished = False; + + if (i == 0) + { + *srcLen += srcLenCur; + src += srcLenCur; + } + else + { + p->pos[i - 1] += srcLenCur; + } + + if (i == p->numCoders - 1) + { + *destLen += destLenCur; + dest += destLenCur; + } + else + { + p->size[i] = destLenCur; + p->pos[i] = 0; + p->finished[i] = encodingWasFinished; + } + + if (res != SZ_OK) + return res; + + if (destLenCur != 0 || srcLenCur != 0) + processed = True; + } + if (!processed) + break; + } + if (allFinished) + *status = CODER_STATUS_FINISHED_WITH_MARK; + return SZ_OK; +} + +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) && + memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) == 0); +} + +#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_Parse(CXzBlock *p, const Byte *header) +{ + unsigned pos; + int numFilters, i; + UInt32 headerSize = (UInt32)header[0] << 2; + + if (CrcCalc(header, headerSize) != GetUi32(header + headerSize)) + return SZ_ERROR_ARCHIVE; + + pos = 1; + if (pos == headerSize) + return SZ_ERROR_ARCHIVE; + p->flags = header[pos++]; + + 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; + } + + 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[%d] = %2X: ", i, filter->id); + { + int i; + for (i = 0; i < size; i++) + printf(" %2X", filter->props[i]); + } + #endif + } + + while (pos < headerSize) + if (header[pos++] != 0) + return SZ_ERROR_ARCHIVE; + return SZ_OK; +} + +SRes XzDec_Init(CMixCoder *p, const CXzBlock *block) +{ + int i; + Bool needReInit = True; + int numFilters = XzBlock_GetNumFilters(block); + if (numFilters == p->numCoders) + { + for (i = 0; i < numFilters; i++) + if (p->ids[i] != block->filters[numFilters - 1 - i].id) + break; + needReInit = (i != numFilters); + } + if (needReInit) + { + MixCoder_Free(p); + p->numCoders = numFilters; + for (i = 0; i < numFilters; i++) + { + const CXzFilter *f = &block->filters[numFilters - 1 - i]; + RINOK(MixCoder_SetFromMethod(p, i, f->id)); + } + } + for (i = 0; i < numFilters; i++) + { + const CXzFilter *f = &block->filters[numFilters - 1 - i]; + IStateCoder *sc = &p->coders[i]; + RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc)); + } + MixCoder_Init(p); + return SZ_OK; +} + +SRes XzUnpacker_Create(CXzUnpacker *p, ISzAlloc *alloc) +{ + MixCoder_Construct(&p->decoder, alloc); + p->state = XZ_STATE_STREAM_HEADER; + p->pos = 0; + p->numStreams = 0; + return SZ_OK; +} + +void XzUnpacker_Free(CXzUnpacker *p) +{ + MixCoder_Free(&p->decoder); +} + +SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, int finishMode, ECoderStatus *status) +{ + SizeT destLenOrig = *destLen; + SizeT srcLenOrig = *srcLen; + *destLen = 0; + *srcLen = 0; + *status = CODER_STATUS_NOT_SPECIFIED; + for (;;) + { + SizeT srcRem = srcLenOrig - *srcLen; + + if (p->state == XZ_STATE_BLOCK) + { + SizeT destLen2 = destLenOrig - *destLen; + SizeT srcLen2 = srcLenOrig - *srcLen; + SRes res; + if (srcLen2 == 0 && destLen2 == 0) + { + *status = CODER_STATUS_NOT_FINISHED; + return SZ_OK; + } + + res = MixCoder_Code(&p->decoder, dest, &destLen2, src, &srcLen2, False, finishMode, status); + XzCheck_Update(&p->check, dest, destLen2); + + (*srcLen) += srcLen2; + src += srcLen2; + p->packSize += srcLen2; + + (*destLen) += destLen2; + dest += destLen2; + p->unpackSize += destLen2; + + RINOK(res); + + if (*status == CODER_STATUS_FINISHED_WITH_MARK) + { + Byte temp[32]; + unsigned num = Xz_WriteVarInt(temp, p->packSize + p->blockHeaderSize + XzFlags_GetCheckSize(p->streamFlags)); + num += Xz_WriteVarInt(temp + num, p->unpackSize); + Sha256_Update(&p->sha, temp, num); + p->indexSize += num; + p->numBlocks++; + + p->state = XZ_STATE_BLOCK_FOOTER; + p->pos = 0; + p->alignPos = 0; + } + else if (srcLen2 == 0 && destLen2 == 0) + return SZ_OK; + + continue; + } + + if (srcRem == 0) + { + *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; + p->buf[p->pos++] = *src++; + (*srcLen)++; + } + else + { + RINOK(Xz_ParseHeader(&p->streamFlags, p->buf)); + p->state = XZ_STATE_BLOCK_HEADER; + Sha256_Init(&p->sha); + p->indexSize = 0; + p->numBlocks = 0; + p->pos = 0; + } + break; + } + + case XZ_STATE_BLOCK_HEADER: + { + if (p->pos == 0) + { + p->buf[p->pos++] = *src++; + (*srcLen)++; + if (p->buf[0] == 0) + { + 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; + } + p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4; + } + else 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)); + p->state = XZ_STATE_BLOCK; + p->packSize = 0; + p->unpackSize = 0; + XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags)); + RINOK(XzDec_Init(&p->decoder, &p->block)); + } + break; + } + + case XZ_STATE_BLOCK_FOOTER: + { + if (((p->packSize + p->alignPos) & 3) != 0) + { + (*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 (cur > srcRem) + cur = (UInt32)srcRem; + memcpy(p->buf + p->pos, src, cur); + p->pos += cur; + (*srcLen) += cur; + src += cur; + } + else + { + 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; + } + } + 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->numStreams++; + 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; + */ +} + +Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p) +{ + return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0); +} diff --git a/C/XzEnc.c b/C/XzEnc.c new file mode 100755 index 0000000..e610140 --- /dev/null +++ b/C/XzEnc.c @@ -0,0 +1,497 @@ +/* XzEnc.c -- Xz Encode +2009-06-04 : Igor Pavlov : Public domain */ + +#include +#include + +#include "7zCrc.h" +#include "Alloc.h" +#include "Bra.h" +#include "CpuArch.h" +#ifdef USE_SUBBLOCK +#include "SbEnc.h" +#endif + +#include "XzEnc.h" + +static void *SzBigAlloc(void *p, size_t size) { p = p; return BigAlloc(size); } +static void SzBigFree(void *p, void *address) { p = p; BigFree(address); } +static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; + +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } +static void SzFree(void *p, void *address) { p = p; MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +#define XzBlock_ClearFlags(p) (p)->flags = 0; +#define XzBlock_SetNumFilters(p, n) (p)->flags |= ((n) - 1); +#define XzBlock_SetHasPackSize(p) (p)->flags |= XZ_BF_PACK_SIZE; +#define XzBlock_SetHasUnpackSize(p) (p)->flags |= XZ_BF_UNPACK_SIZE; + +static SRes WriteBytes(ISeqOutStream *s, const void *buf, UInt32 size) +{ + return (s->Write(s, buf, size) == size) ? SZ_OK : SZ_ERROR_WRITE; +} + +static SRes WriteBytesAndCrc(ISeqOutStream *s, const void *buf, UInt32 size, UInt32 *crc) +{ + *crc = CrcUpdate(*crc, buf, size); + return WriteBytes(s, buf, size); +} + +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); +} + +SRes XzBlock_WriteHeader(const CXzBlock *p, ISeqOutStream *s) +{ + Byte header[XZ_BLOCK_HEADER_SIZE_MAX]; + + unsigned pos = 1; + int 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); +} + +SRes Xz_WriteFooter(CXzStream *p, ISeqOutStream *s) +{ + Byte buf[32]; + UInt64 globalPos; + { + UInt32 crc = CRC_INIT_VAL; + unsigned pos = 1 + Xz_WriteVarInt(buf + 1, p->numBlocks); + size_t i; + + globalPos = pos; + buf[0] = 0; + RINOK(WriteBytesAndCrc(s, buf, pos, &crc)); + for (i = 0; i < p->numBlocks; i++) + { + const CXzBlockSizes *block = &p->blocks[i]; + pos = Xz_WriteVarInt(buf, block->totalSize); + pos += Xz_WriteVarInt(buf + pos, block->unpackSize); + globalPos += pos; + RINOK(WriteBytesAndCrc(s, buf, pos, &crc)); + } + pos = ((unsigned)globalPos & 3); + if (pos != 0) + { + buf[0] = buf[1] = buf[2] = 0; + RINOK(WriteBytesAndCrc(s, buf, 4 - pos, &crc)); + globalPos += 4 - pos; + } + { + SetUi32(buf, CRC_GET_DIGEST(crc)); + RINOK(WriteBytes(s, buf, 4)); + globalPos += 4; + } + } + + { + UInt32 indexSize = (UInt32)((globalPos >> 2) - 1); + SetUi32(buf + 4, indexSize); + buf[8] = (Byte)(p->flags >> 8); + buf[9] = (Byte)(p->flags & 0xFF); + SetUi32(buf, CrcCalc(buf + 4, 6)); + memcpy(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE); + return WriteBytes(s, buf, 12); + } +} + +SRes Xz_AddIndexRecord(CXzStream *p, UInt64 unpackSize, UInt64 totalSize, ISzAlloc *alloc) +{ + if (p->blocks == 0 || p->numBlocksAllocated == p->numBlocks) + { + size_t num = (p->numBlocks + 1) * 2; + size_t newSize = sizeof(CXzBlockSizes) * num; + CXzBlockSizes *blocks; + if (newSize / sizeof(CXzBlockSizes) != num) + return SZ_ERROR_MEM; + blocks = alloc->Alloc(alloc, newSize); + if (blocks == 0) + return SZ_ERROR_MEM; + if (p->numBlocks != 0) + { + memcpy(blocks, p->blocks, p->numBlocks * sizeof(CXzBlockSizes)); + Xz_Free(p, alloc); + } + p->blocks = blocks; + p->numBlocksAllocated = num; + } + { + CXzBlockSizes *block = &p->blocks[p->numBlocks++]; + block->totalSize = totalSize; + block->unpackSize = unpackSize; + } + return SZ_OK; +} + +/* ---------- CSeqCheckInStream ---------- */ + +typedef struct +{ + ISeqInStream p; + ISeqInStream *realStream; + UInt64 processed; + CXzCheck check; +} CSeqCheckInStream; + +void SeqCheckInStream_Init(CSeqCheckInStream *p, int mode) +{ + p->processed = 0; + XzCheck_Init(&p->check, mode); +} + +void SeqCheckInStream_GetDigest(CSeqCheckInStream *p, Byte *digest) +{ + XzCheck_Final(&p->check, digest); +} + +static SRes SeqCheckInStream_Read(void *pp, void *data, size_t *size) +{ + CSeqCheckInStream *p = (CSeqCheckInStream *)pp; + SRes res = p->realStream->Read(p->realStream, data, size); + XzCheck_Update(&p->check, data, *size); + p->processed += *size; + return res; +} + +/* ---------- CSeqSizeOutStream ---------- */ + +typedef struct +{ + ISeqOutStream p; + ISeqOutStream *realStream; + UInt64 processed; +} CSeqSizeOutStream; + +static size_t MyWrite(void *pp, const void *data, size_t size) +{ + CSeqSizeOutStream *p = (CSeqSizeOutStream *)pp; + size = p->realStream->Write(p->realStream, data, size); + p->processed += size; + return size; +} + +/* ---------- CSeqInFilter ---------- */ + +/* +typedef struct _IFilter +{ + void *p; + void (*Free)(void *p, ISzAlloc *alloc); + SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAlloc *alloc); + void (*Init)(void *p); + size_t (*Filter)(void *p, Byte *data, SizeT destLen); +} IFilter; + +#define FILT_BUF_SIZE (1 << 19) + +typedef struct +{ + ISeqInStream p; + ISeqInStream *realStream; + UInt32 x86State; + UInt32 ip; + UInt64 processed; + CXzCheck check; + Byte buf[FILT_BUF_SIZE]; + UInt32 bufferPos; + UInt32 convertedPosBegin; + UInt32 convertedPosEnd; + IFilter *filter; +} CSeqInFilter; + +static SRes SeqInFilter_Read(void *pp, void *data, size_t *size) +{ + CSeqInFilter *p = (CSeqInFilter *)pp; + size_t remSize = *size; + *size = 0; + + while (remSize > 0) + { + int i; + if (p->convertedPosBegin != p->convertedPosEnd) + { + UInt32 sizeTemp = p->convertedPosEnd - p->convertedPosBegin; + if (remSize < sizeTemp) + sizeTemp = (UInt32)remSize; + memmove(data, p->buf + p->convertedPosBegin, sizeTemp); + p->convertedPosBegin += sizeTemp; + data = (void *)((Byte *)data + sizeTemp); + remSize -= sizeTemp; + *size += sizeTemp; + break; + } + for (i = 0; p->convertedPosEnd + i < p->bufferPos; i++) + p->buf[i] = p->buf[i + p->convertedPosEnd]; + p->bufferPos = i; + p->convertedPosBegin = p->convertedPosEnd = 0; + { + size_t processedSizeTemp = FILT_BUF_SIZE - p->bufferPos; + RINOK(p->realStream->Read(p->realStream, p->buf + p->bufferPos, &processedSizeTemp)); + p->bufferPos = p->bufferPos + (UInt32)processedSizeTemp; + } + p->convertedPosEnd = (UInt32)p->filter->Filter(p->filter->p, p->buf, p->bufferPos); + if (p->convertedPosEnd == 0) + { + if (p->bufferPos == 0) + break; + else + { + p->convertedPosEnd = p->bufferPos; + continue; + } + } + if (p->convertedPosEnd > p->bufferPos) + { + for (; p->bufferPos < p->convertedPosEnd; p->bufferPos++) + p->buf[p->bufferPos] = 0; + p->convertedPosEnd = (UInt32)p->filter->Filter(p->filter->p, p->buf, p->bufferPos); + } + } + return SZ_OK; +} +*/ + +/* +typedef struct +{ + ISeqInStream p; + ISeqInStream *realStream; + CMixCoder mixCoder; + Byte buf[FILT_BUF_SIZE]; + UInt32 bufPos; + UInt32 bufSize; +} CMixCoderSeqInStream; + +static SRes CMixCoderSeqInStream_Read(void *pp, void *data, size_t *size) +{ + CMixCoderSeqInStream *p = (CMixCoderSeqInStream *)pp; + SRes res = SZ_OK; + size_t remSize = *size; + *size = 0; + while (remSize > 0) + { + if (p->bufPos == p->bufSize) + { + size_t curSize; + p->bufPos = p->bufSize = 0; + if (*size != 0) + break; + curSize = FILT_BUF_SIZE; + RINOK(p->realStream->Read(p->realStream, p->buf, &curSize)); + p->bufSize = (UInt32)curSize; + } + { + SizeT destLen = remSize; + SizeT srcLen = p->bufSize - p->bufPos; + res = MixCoder_Code(&p->mixCoder, data, &destLen, p->buf + p->bufPos, &srcLen, 0); + data = (void *)((Byte *)data + destLen); + remSize -= destLen; + *size += destLen; + p->bufPos += srcLen; + } + } + return res; +} +*/ + +#ifdef USE_SUBBLOCK +typedef struct +{ + ISeqInStream p; + CSubblockEnc sb; + UInt64 processed; +} CSbEncInStream; + +void SbEncInStream_Init(CSbEncInStream *p) +{ + p->processed = 0; + SubblockEnc_Init(&p->sb); +} + +static SRes SbEncInStream_Read(void *pp, void *data, size_t *size) +{ + CSbEncInStream *p = (CSbEncInStream *)pp; + SRes res = SubblockEnc_Read(&p->sb, data, size); + p->processed += *size; + return res; +} +#endif + +typedef struct +{ + /* CMixCoderSeqInStream inStream; */ + CLzma2EncHandle lzma2; + #ifdef USE_SUBBLOCK + CSbEncInStream sb; + #endif + ISzAlloc *alloc; + ISzAlloc *bigAlloc; +} CLzma2WithFilters; + + +static void Lzma2WithFilters_Construct(CLzma2WithFilters *p, ISzAlloc *alloc, ISzAlloc *bigAlloc) +{ + p->alloc = alloc; + p->bigAlloc = bigAlloc; + p->lzma2 = NULL; + #ifdef USE_SUBBLOCK + p->sb.p.Read = SbEncInStream_Read; + SubblockEnc_Construct(&p->sb.sb, p->alloc); + #endif +} + +static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p) +{ + p->lzma2 = Lzma2Enc_Create(p->alloc, p->bigAlloc); + if (p->lzma2 == 0) + return SZ_ERROR_MEM; + return SZ_OK; +} + +static void Lzma2WithFilters_Free(CLzma2WithFilters *p) +{ + #ifdef USE_SUBBLOCK + SubblockEnc_Free(&p->sb.sb); + #endif + if (p->lzma2) + { + Lzma2Enc_Destroy(p->lzma2); + p->lzma2 = NULL; + } +} + +static SRes Xz_Compress(CXzStream *xz, + CLzma2WithFilters *lzmaf, + ISeqOutStream *outStream, + ISeqInStream *inStream, + const CLzma2EncProps *lzma2Props, + Bool useSubblock, + ICompressProgress *progress) +{ + xz->flags = XZ_CHECK_CRC32; + + RINOK(Lzma2Enc_SetProps(lzmaf->lzma2, lzma2Props)); + RINOK(Xz_WriteHeader(xz->flags, outStream)); + + { + CSeqCheckInStream checkInStream; + CSeqSizeOutStream seqSizeOutStream; + CXzBlock block; + int filterIndex = 0; + + XzBlock_ClearFlags(&block); + XzBlock_SetNumFilters(&block, 1 + (useSubblock ? 1 : 0)); + + if (useSubblock) + { + CXzFilter *f = &block.filters[filterIndex++]; + f->id = XZ_ID_Subblock; + f->propsSize = 0; + } + + { + CXzFilter *f = &block.filters[filterIndex++]; + f->id = XZ_ID_LZMA2; + f->propsSize = 1; + f->props[0] = Lzma2Enc_WriteProperties(lzmaf->lzma2); + } + + seqSizeOutStream.p.Write = MyWrite; + seqSizeOutStream.realStream = outStream; + seqSizeOutStream.processed = 0; + + RINOK(XzBlock_WriteHeader(&block, &seqSizeOutStream.p)); + + checkInStream.p.Read = SeqCheckInStream_Read; + checkInStream.realStream = inStream; + SeqCheckInStream_Init(&checkInStream, XzFlags_GetCheckType(xz->flags)); + + #ifdef USE_SUBBLOCK + if (useSubblock) + { + lzmaf->sb.sb.inStream = &checkInStream.p; + SubblockEnc_Init(&lzmaf->sb.sb); + } + #endif + + { + UInt64 packPos = seqSizeOutStream.processed; + SRes res = Lzma2Enc_Encode(lzmaf->lzma2, &seqSizeOutStream.p, + #ifdef USE_SUBBLOCK + useSubblock ? &lzmaf->sb.p: + #endif + &checkInStream.p, + progress); + RINOK(res); + block.unpackSize = checkInStream.processed; + block.packSize = seqSizeOutStream.processed - packPos; + } + + { + unsigned padSize = 0; + Byte buf[128]; + while((((unsigned)block.packSize + padSize) & 3) != 0) + buf[padSize++] = 0; + SeqCheckInStream_GetDigest(&checkInStream, buf + padSize); + RINOK(WriteBytes(&seqSizeOutStream.p, buf, padSize + XzFlags_GetCheckSize(xz->flags))); + RINOK(Xz_AddIndexRecord(xz, block.unpackSize, seqSizeOutStream.processed - padSize, &g_Alloc)); + } + } + return Xz_WriteFooter(xz, outStream); +} + +SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream, + const CLzma2EncProps *lzma2Props, Bool useSubblock, + ICompressProgress *progress) +{ + SRes res; + CXzStream xz; + CLzma2WithFilters lzmaf; + Xz_Construct(&xz); + Lzma2WithFilters_Construct(&lzmaf, &g_Alloc, &g_BigAlloc); + res = Lzma2WithFilters_Create(&lzmaf); + if (res == SZ_OK) + res = Xz_Compress(&xz, &lzmaf, outStream, inStream, + lzma2Props, useSubblock, progress); + Lzma2WithFilters_Free(&lzmaf); + Xz_Free(&xz, &g_Alloc); + return res; +} + +SRes Xz_EncodeEmpty(ISeqOutStream *outStream) +{ + SRes res; + CXzStream xz; + Xz_Construct(&xz); + res = Xz_WriteHeader(xz.flags, outStream); + if (res == SZ_OK) + res = Xz_WriteFooter(&xz, outStream); + Xz_Free(&xz, &g_Alloc); + return res; +} diff --git a/C/XzEnc.h b/C/XzEnc.h new file mode 100755 index 0000000..aad9aa4 --- /dev/null +++ b/C/XzEnc.h @@ -0,0 +1,25 @@ +/* XzEnc.h -- Xz Encode +2009-04-15 : Igor Pavlov : Public domain */ + +#ifndef __XZ_ENC_H +#define __XZ_ENC_H + +#include "Lzma2Enc.h" + +#include "Xz.h" + +#ifdef __cplusplus +extern "C" { +#endif + +SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream, + const CLzma2EncProps *lzma2Props, Bool useSubblock, + ICompressProgress *progress); + +SRes Xz_EncodeEmpty(ISeqOutStream *outStream); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/C/XzIn.c b/C/XzIn.c new file mode 100755 index 0000000..356d019 --- /dev/null +++ b/C/XzIn.c @@ -0,0 +1,306 @@ +/* XzIn.c - Xz input +2009-06-19 : Igor Pavlov : Public domain */ + +#include + +#include "7zCrc.h" +#include "CpuArch.h" +#include "Xz.h" + +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] << 2) + 4; + if (headerSize == 0) + { + *headerSizeRes = 1; + *isIndex = True; + return SZ_OK; + } + + *isIndex = False; + *headerSizeRes = headerSize; + RINOK(SeqInStream_Read(inStream, header + 1, headerSize - 1)); + return XzBlock_Parse(p, header); +} + +#define ADD_SIZE_CHECH(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_CHECH(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_CHECH(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, ISzAlloc *alloc) +{ + size_t i, numBlocks, crcStartPos, 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; + } + + crcStartPos = pos; + Xz_Free(p, alloc); + if (numBlocks != 0) + { + p->numBlocks = numBlocks; + p->numBlocksAllocated = numBlocks; + p->blocks = alloc->Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks); + if (p->blocks == 0) + 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, ISzAlloc *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 = alloc->Alloc(alloc, size); + if (buf == 0) + return SZ_ERROR_MEM; + res = LookInStream_Read2(stream, buf, size, SZ_ERROR_UNSUPPORTED); + if (res == SZ_OK) + res = Xz_ReadIndex2(p, buf, size, alloc); + alloc->Free(alloc, buf); + return res; +} + +static SRes SeekFromCur(ILookInStream *inStream, Int64 *res) +{ + return inStream->Seek(inStream, res, SZ_SEEK_CUR); +} + +static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOffset, ISzAlloc *alloc) +{ + UInt64 indexSize; + Byte buf[XZ_STREAM_FOOTER_SIZE]; + + if ((*startOffset & 3) != 0 || *startOffset < XZ_STREAM_FOOTER_SIZE) + return SZ_ERROR_NO_ARCHIVE; + *startOffset = -XZ_STREAM_FOOTER_SIZE; + RINOK(SeekFromCur(stream, startOffset)); + + RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE)); + + if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0) + { + Int64 i = 0; + *startOffset += XZ_STREAM_FOOTER_SIZE; + for (;;) + { + int j; + size_t processedSize; + #define TEMP_BUF_SIZE (1 << 10) + Byte tempBuf[TEMP_BUF_SIZE]; + if (*startOffset < XZ_STREAM_FOOTER_SIZE || i > (1 << 16)) + return SZ_ERROR_NO_ARCHIVE; + processedSize = (*startOffset > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)*startOffset; + i += processedSize; + *startOffset = -(Int64)processedSize; + RINOK(SeekFromCur(stream, startOffset)); + RINOK(LookInStream_Read2(stream, tempBuf, processedSize, SZ_ERROR_NO_ARCHIVE)); + for (j = (int)processedSize; j >= 0; j--) + if (tempBuf[j -1] != 0) + break; + if (j != 0) + { + if ((j & 3) != 0) + return SZ_ERROR_NO_ARCHIVE; + *startOffset += j; + if (*startOffset < XZ_STREAM_FOOTER_SIZE) + return SZ_ERROR_NO_ARCHIVE; + *startOffset -= XZ_STREAM_FOOTER_SIZE; + RINOK(stream->Seek(stream, startOffset, SZ_SEEK_SET)); + RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE)); + if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0) + return SZ_ERROR_NO_ARCHIVE; + break; + } + } + } + + 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; + + *startOffset = -(Int64)(indexSize + XZ_STREAM_FOOTER_SIZE); + RINOK(SeekFromCur(stream, startOffset)); + + RINOK(Xz_ReadIndex(p, stream, indexSize, alloc)); + + { + UInt64 totalSize = Xz_GetPackSize(p); + UInt64 sum = XZ_STREAM_HEADER_SIZE + totalSize + indexSize; + if (totalSize == XZ_SIZE_OVERFLOW || + sum >= ((UInt64)1 << 63) || + totalSize >= ((UInt64)1 << 63)) + return SZ_ERROR_ARCHIVE; + *startOffset = -(Int64)sum; + RINOK(SeekFromCur(stream, startOffset)); + } + { + CXzStreamFlags headerFlags; + CSecToRead secToRead; + SecToRead_CreateVTable(&secToRead); + secToRead.realStream = stream; + + RINOK(Xz_ReadHeader(&headerFlags, &secToRead.s)); + 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, ISzAlloc *alloc) +{ + size_t i; + for (i = 0; i < p->num; i++) + Xz_Free(&p->streams[i], alloc); + alloc->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_CHECH(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_CHECH(size, Xz_GetTotalSize(&p->streams[i])); + return size; +} +*/ + +SRes Xzs_ReadBackward(CXzs *p, ILookInStream *stream, Int64 *startOffset, ICompressProgress *progress, ISzAlloc *alloc) +{ + Int64 endOffset = 0; + RINOK(stream->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 *)alloc->Alloc(alloc, newNum * sizeof(CXzStream)); + if (data == 0) + return SZ_ERROR_MEM; + p->numAllocated = newNum; + memcpy(data, p->streams, p->num * sizeof(CXzStream)); + alloc->Free(alloc, p->streams); + p->streams = (CXzStream *)data; + } + p->streams[p->num++] = st; + if (*startOffset == 0) + break; + RINOK(stream->Seek(stream, startOffset, SZ_SEEK_SET)); + if (progress && progress->Progress(progress, endOffset - *startOffset, (UInt64)(Int64)-1) != SZ_OK) + return SZ_ERROR_PROGRESS; + } + return SZ_OK; +} diff --git a/CPP/7zip/Aes.mak b/CPP/7zip/Aes.mak new file mode 100755 index 0000000..7ce28cf --- /dev/null +++ b/CPP/7zip/Aes.mak @@ -0,0 +1,7 @@ +C_OBJS = $(C_OBJS) \ + $O\Aes.obj + +!IF "$(CPU)" != "IA64" && "$(CPU)" != "MIPS" && "$(CPU)" != "ARM" +ASM_OBJS = $(ASM_OBJS) \ + $O\AesOpt.obj +!ENDIF diff --git a/CPP/7zip/Archive/7z/7z.dsp b/CPP/7zip/Archive/7z/7z.dsp new file mode 100755 index 0000000..46d41b5 --- /dev/null +++ b/CPP/7zip/Archive/7z/7z.dsp @@ -0,0 +1,650 @@ +# 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) Dynamic-Link Library" 0x0102 + +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) Dynamic-Link Library") +!MESSAGE "7z - 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)" == "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 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /YX /FD /c +# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /D "EXTERNAL_CODECS" /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 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-zip\Formats\7z.dll" /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 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /D "EXTERNAL_CODECS" /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 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-zip\Formats\7z.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "7z - Win32 Release" +# Name "7z - Win32 Debug" +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\Archive.def +# End Source File +# Begin Source File + +SOURCE=..\ArchiveExports.cpp +# End Source File +# Begin Source File + +SOURCE=..\DllExports.cpp +# End Source File +# Begin Source File + +SOURCE=.\resource.rc +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"StdAfx.h" +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# End Group +# Begin Group "Engine" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\7zCompressionMode.cpp +# End Source File +# Begin Source File + +SOURCE=.\7zCompressionMode.h +# End Source File +# Begin Source File + +SOURCE=.\7zDecode.cpp +# End Source File +# Begin Source File + +SOURCE=.\7zDecode.h +# End Source File +# Begin Source File + +SOURCE=.\7zEncode.cpp +# End Source File +# Begin Source File + +SOURCE=.\7zEncode.h +# End Source File +# Begin Source File + +SOURCE=.\7zExtract.cpp +# End Source File +# Begin Source File + +SOURCE=.\7zFolderInStream.cpp +# End Source File +# Begin Source File + +SOURCE=.\7zFolderInStream.h +# End Source File +# Begin Source File + +SOURCE=.\7zFolderOutStream.cpp +# End Source File +# Begin Source File + +SOURCE=.\7zFolderOutStream.h +# End Source File +# Begin Source File + +SOURCE=.\7zHandler.cpp +# End Source File +# Begin Source File + +SOURCE=.\7zHandler.h +# End Source File +# Begin Source File + +SOURCE=.\7zHandlerOut.cpp +# End Source File +# Begin Source File + +SOURCE=.\7zHeader.cpp +# End Source File +# Begin Source File + +SOURCE=.\7zHeader.h +# End Source File +# Begin Source File + +SOURCE=.\7zIn.cpp +# End Source File +# Begin Source File + +SOURCE=.\7zIn.h +# End Source File +# Begin Source File + +SOURCE=.\7zItem.h +# End Source File +# Begin Source File + +SOURCE=.\7zOut.cpp +# End Source File +# Begin Source File + +SOURCE=.\7zOut.h +# End Source File +# Begin Source File + +SOURCE=.\7zProperties.cpp +# End Source File +# Begin Source File + +SOURCE=.\7zProperties.h +# End Source File +# Begin Source File + +SOURCE=.\7zRegister.cpp +# End Source File +# Begin Source File + +SOURCE=.\7zSpecStream.cpp +# End Source File +# Begin Source File + +SOURCE=.\7zSpecStream.h +# End Source File +# Begin Source File + +SOURCE=.\7zUpdate.cpp +# End Source File +# Begin Source File + +SOURCE=.\7zUpdate.h +# End Source File +# End Group +# Begin Group "Interface" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\IArchive.h +# End Source File +# 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 "Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Common\Buffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\CRC.cpp +# 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\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\StringToInt.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringToInt.h +# End Source File +# End Group +# Begin Group "Archive Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\Common\CoderMixer2.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\CoderMixer2.h +# End Source File +# Begin Source File + +SOURCE=..\Common\CoderMixer2MT.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\CoderMixer2MT.h +# End Source File +# Begin Source File + +SOURCE=..\Common\CrossThreadProgress.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\CrossThreadProgress.h +# End Source File +# Begin Source File + +SOURCE=..\Common\HandlerOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\HandlerOut.h +# End Source File +# Begin Source File + +SOURCE=..\Common\InStreamWithCRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\InStreamWithCRC.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ItemNameUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ItemNameUtils.h +# End Source File +# Begin Source File + +SOURCE=..\Common\MultiStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\MultiStream.h +# End Source File +# Begin Source File + +SOURCE=..\Common\OutStreamWithCRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\OutStreamWithCRC.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ParseProperties.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ParseProperties.h +# End Source File +# End Group +# Begin Group "7-Zip 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\FilterCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FilterCoder.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\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\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 "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.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Handle.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 "Compress" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\CopyCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\CopyCoder.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\CpuArch.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 +# End Target +# End Project diff --git a/CPP/7zip/Archive/7z/7z.dsw b/CPP/7zip/Archive/7z/7z.dsw new file mode 100755 index 0000000..5b0e36c --- /dev/null +++ b/CPP/7zip/Archive/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/CPP/7zip/Archive/7z/7zCompressionMode.cpp b/CPP/7zip/Archive/7z/7zCompressionMode.cpp new file mode 100755 index 0000000..232c638 --- /dev/null +++ b/CPP/7zip/Archive/7z/7zCompressionMode.cpp @@ -0,0 +1,3 @@ +// CompressionMethod.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.h b/CPP/7zip/Archive/7z/7zCompressionMode.h new file mode 100755 index 0000000..a388e1f --- /dev/null +++ b/CPP/7zip/Archive/7z/7zCompressionMode.h @@ -0,0 +1,50 @@ +// 7zCompressionMode.h + +#ifndef __7Z_COMPRESSION_MODE_H +#define __7Z_COMPRESSION_MODE_H + +#include "../../../Common/MyString.h" + +#include "../../../Windows/PropVariant.h" + +#include "../../Common/MethodProps.h" + +namespace NArchive { +namespace N7z { + +struct CMethodFull: public CMethod +{ + UInt32 NumInStreams; + UInt32 NumOutStreams; + bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } +}; + +struct CBind +{ + UInt32 InCoder; + UInt32 InStream; + UInt32 OutCoder; + UInt32 OutStream; +}; + +struct CCompressionMethodMode +{ + CObjectVector Methods; + CRecordVector Binds; + #ifndef _7ZIP_ST + UInt32 NumThreads; + #endif + bool PasswordIsDefined; + UString Password; + + bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); } + CCompressionMethodMode(): PasswordIsDefined(false) + #ifndef _7ZIP_ST + , NumThreads(1) + #endif + {} +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/7z/7zDecode.cpp b/CPP/7zip/Archive/7z/7zDecode.cpp new file mode 100755 index 0000000..3fcdd5f --- /dev/null +++ b/CPP/7zip/Archive/7z/7zDecode.cpp @@ -0,0 +1,332 @@ +// 7zDecode.cpp + +#include "StdAfx.h" + +#include "../../Common/LimitedStreams.h" +#include "../../Common/LockedStream.h" +#include "../../Common/ProgressUtils.h" +#include "../../Common/StreamObjects.h" + +#include "7zDecode.h" + +namespace NArchive { +namespace N7z { + +static void ConvertFolderItemInfoToBindInfo(const CFolder &folder, + CBindInfoEx &bindInfo) +{ + bindInfo.Clear(); + int i; + for (i = 0; i < folder.BindPairs.Size(); i++) + { + NCoderMixer::CBindPair bindPair; + bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex; + bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex; + bindInfo.BindPairs.Add(bindPair); + } + UInt32 outStreamIndex = 0; + for (i = 0; i < folder.Coders.Size(); i++) + { + NCoderMixer::CCoderStreamsInfo coderStreamsInfo; + const CCoderInfo &coderInfo = folder.Coders[i]; + coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams; + coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams; + bindInfo.Coders.Add(coderStreamsInfo); + bindInfo.CoderMethodIDs.Add(coderInfo.MethodID); + for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++) + if (folder.FindBindPairForOutStream(outStreamIndex) < 0) + bindInfo.OutStreams.Add(outStreamIndex); + } + for (i = 0; i < folder.PackStreams.Size(); i++) + bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]); +} + +static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1, + const NCoderMixer::CCoderStreamsInfo &a2) +{ + return (a1.NumInStreams == a2.NumInStreams) && + (a1.NumOutStreams == a2.NumOutStreams); +} + +static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2) +{ + return (a1.InIndex == a2.InIndex) && + (a1.OutIndex == a2.OutIndex); +} + +static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2) +{ + if (a1.Coders.Size() != a2.Coders.Size()) + return false; + int i; + for (i = 0; i < a1.Coders.Size(); i++) + if (!AreCodersEqual(a1.Coders[i], a2.Coders[i])) + return false; + if (a1.BindPairs.Size() != a2.BindPairs.Size()) + return false; + for (i = 0; i < a1.BindPairs.Size(); i++) + if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i])) + return false; + for (i = 0; i < a1.CoderMethodIDs.Size(); i++) + if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i]) + return false; + if (a1.InStreams.Size() != a2.InStreams.Size()) + return false; + if (a1.OutStreams.Size() != a2.OutStreams.Size()) + return false; + return true; +} + +CDecoder::CDecoder(bool multiThread) +{ + #ifndef _ST_MODE + multiThread = true; + #endif + _multiThread = multiThread; + _bindInfoExPrevIsDefined = false; +} + +HRESULT CDecoder::Decode( + DECL_EXTERNAL_CODECS_LOC_VARS + IInStream *inStream, + UInt64 startPos, + const UInt64 *packSizes, + const CFolder &folderInfo, + ISequentialOutStream *outStream, + ICompressProgressInfo *compressProgress + #ifndef _NO_CRYPTO + , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined + #endif + #if !defined(_7ZIP_ST) && !defined(_SFX) + , bool mtMode, UInt32 numThreads + #endif + ) +{ + if (!folderInfo.CheckStructure()) + return E_NOTIMPL; + #ifndef _NO_CRYPTO + passwordIsDefined = false; + #endif + CObjectVector< CMyComPtr > inStreams; + + CLockedInStream lockedInStream; + lockedInStream.Init(inStream); + + for (int j = 0; j < folderInfo.PackStreams.Size(); j++) + { + CLockedSequentialInStreamImp *lockedStreamImpSpec = new + CLockedSequentialInStreamImp; + CMyComPtr lockedStreamImp = lockedStreamImpSpec; + lockedStreamImpSpec->Init(&lockedInStream, startPos); + startPos += packSizes[j]; + + CLimitedSequentialInStream *streamSpec = new + CLimitedSequentialInStream; + CMyComPtr inStream = streamSpec; + streamSpec->SetStream(lockedStreamImp); + streamSpec->Init(packSizes[j]); + inStreams.Add(inStream); + } + + int numCoders = folderInfo.Coders.Size(); + + CBindInfoEx bindInfo; + ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo); + bool createNewCoders; + if (!_bindInfoExPrevIsDefined) + createNewCoders = true; + else + createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev); + if (createNewCoders) + { + int i; + _decoders.Clear(); + // _decoders2.Clear(); + + _mixerCoder.Release(); + + if (_multiThread) + { + _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT; + _mixerCoder = _mixerCoderMTSpec; + _mixerCoderCommon = _mixerCoderMTSpec; + } + else + { + #ifdef _ST_MODE + _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST; + _mixerCoder = _mixerCoderSTSpec; + _mixerCoderCommon = _mixerCoderSTSpec; + #endif + } + RINOK(_mixerCoderCommon->SetBindInfo(bindInfo)); + + for (i = 0; i < numCoders; i++) + { + const CCoderInfo &coderInfo = folderInfo.Coders[i]; + + + CMyComPtr decoder; + CMyComPtr decoder2; + RINOK(CreateCoder( + EXTERNAL_CODECS_LOC_VARS + coderInfo.MethodID, decoder, decoder2, false)); + CMyComPtr decoderUnknown; + if (coderInfo.IsSimpleCoder()) + { + if (decoder == 0) + return E_NOTIMPL; + + decoderUnknown = (IUnknown *)decoder; + + if (_multiThread) + _mixerCoderMTSpec->AddCoder(decoder); + #ifdef _ST_MODE + else + _mixerCoderSTSpec->AddCoder(decoder, false); + #endif + } + else + { + if (decoder2 == 0) + return E_NOTIMPL; + decoderUnknown = (IUnknown *)decoder2; + if (_multiThread) + _mixerCoderMTSpec->AddCoder2(decoder2); + #ifdef _ST_MODE + else + _mixerCoderSTSpec->AddCoder2(decoder2, false); + #endif + } + _decoders.Add(decoderUnknown); + #ifdef EXTERNAL_CODECS + CMyComPtr setCompressCodecsInfo; + decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); + if (setCompressCodecsInfo) + { + RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); + } + #endif + } + _bindInfoExPrev = bindInfo; + _bindInfoExPrevIsDefined = true; + } + int i; + _mixerCoderCommon->ReInit(); + + UInt32 packStreamIndex = 0, unpackStreamIndex = 0; + UInt32 coderIndex = 0; + // UInt32 coder2Index = 0; + + for (i = 0; i < numCoders; i++) + { + const CCoderInfo &coderInfo = folderInfo.Coders[i]; + CMyComPtr &decoder = _decoders[coderIndex]; + + { + CMyComPtr setDecoderProperties; + decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); + if (setDecoderProperties) + { + const CByteBuffer &props = coderInfo.Props; + size_t size = props.GetCapacity(); + if (size > 0xFFFFFFFF) + return E_NOTIMPL; + // if (size > 0) + { + RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size)); + } + } + } + + #if !defined(_7ZIP_ST) && !defined(_SFX) + if (mtMode) + { + CMyComPtr setCoderMt; + decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); + if (setCoderMt) + { + RINOK(setCoderMt->SetNumberOfThreads(numThreads)); + } + } + #endif + + #ifndef _NO_CRYPTO + { + CMyComPtr cryptoSetPassword; + decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); + if (cryptoSetPassword) + { + if (getTextPassword == 0) + return E_FAIL; + CMyComBSTR passwordBSTR; + RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR)); + CByteBuffer buffer; + passwordIsDefined = true; + const UString password(passwordBSTR); + const UInt32 sizeInBytes = password.Length() * 2; + buffer.SetCapacity(sizeInBytes); + for (int i = 0; i < password.Length(); i++) + { + wchar_t c = password[i]; + ((Byte *)buffer)[i * 2] = (Byte)c; + ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); + } + RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes)); + } + } + #endif + + coderIndex++; + + UInt32 numInStreams = (UInt32)coderInfo.NumInStreams; + UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams; + CRecordVector packSizesPointers; + CRecordVector unpackSizesPointers; + packSizesPointers.Reserve(numInStreams); + unpackSizesPointers.Reserve(numOutStreams); + UInt32 j; + for (j = 0; j < numOutStreams; j++, unpackStreamIndex++) + unpackSizesPointers.Add(&folderInfo.UnpackSizes[unpackStreamIndex]); + + for (j = 0; j < numInStreams; j++, packStreamIndex++) + { + int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex); + if (bindPairIndex >= 0) + packSizesPointers.Add( + &folderInfo.UnpackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]); + else + { + int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex); + if (index < 0) + return E_FAIL; + packSizesPointers.Add(&packSizes[index]); + } + } + + _mixerCoderCommon->SetCoderInfo(i, + &packSizesPointers.Front(), + &unpackSizesPointers.Front()); + } + UInt32 mainCoder, temp; + bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp); + + if (_multiThread) + _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder); + /* + else + _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);; + */ + + if (numCoders == 0) + return 0; + CRecordVector inStreamPointers; + inStreamPointers.Reserve(inStreams.Size()); + for (i = 0; i < inStreams.Size(); i++) + inStreamPointers.Add(inStreams[i]); + ISequentialOutStream *outStreamPointer = outStream; + return _mixerCoder->Code(&inStreamPointers.Front(), NULL, + inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress); +} + +}} diff --git a/CPP/7zip/Archive/7z/7zDecode.h b/CPP/7zip/Archive/7z/7zDecode.h new file mode 100755 index 0000000..da213a1 --- /dev/null +++ b/CPP/7zip/Archive/7z/7zDecode.h @@ -0,0 +1,68 @@ +// 7zDecode.h + +#ifndef __7Z_DECODE_H +#define __7Z_DECODE_H + +#include "../../IStream.h" +#include "../../IPassword.h" + +#include "../Common/CoderMixer2.h" +#include "../Common/CoderMixer2MT.h" +#ifdef _ST_MODE +#include "../Common/CoderMixer2ST.h" +#endif + +#include "../../Common/CreateCoder.h" + +#include "7zItem.h" + +namespace NArchive { +namespace N7z { + +struct CBindInfoEx: public NCoderMixer::CBindInfo +{ + CRecordVector CoderMethodIDs; + void Clear() + { + CBindInfo::Clear(); + CoderMethodIDs.Clear(); + } +}; + +class CDecoder +{ + bool _bindInfoExPrevIsDefined; + CBindInfoEx _bindInfoExPrev; + + bool _multiThread; + #ifdef _ST_MODE + NCoderMixer::CCoderMixer2ST *_mixerCoderSTSpec; + #endif + NCoderMixer::CCoderMixer2MT *_mixerCoderMTSpec; + NCoderMixer::CCoderMixer2 *_mixerCoderCommon; + + CMyComPtr _mixerCoder; + CObjectVector > _decoders; + // CObjectVector > _decoders2; +public: + CDecoder(bool multiThread); + HRESULT Decode( + DECL_EXTERNAL_CODECS_LOC_VARS + IInStream *inStream, + UInt64 startPos, + const UInt64 *packSizes, + const CFolder &folder, + ISequentialOutStream *outStream, + ICompressProgressInfo *compressProgress + #ifndef _NO_CRYPTO + , ICryptoGetTextPassword *getTextPasswordSpec, bool &passwordIsDefined + #endif + #if !defined(_7ZIP_ST) && !defined(_SFX) + , bool mtMode, UInt32 numThreads + #endif + ); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp new file mode 100755 index 0000000..4b93449 --- /dev/null +++ b/CPP/7zip/Archive/7z/7zEncode.cpp @@ -0,0 +1,444 @@ +// 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" + +static const UInt64 k_Delta = 0x03; +static const UInt64 k_BCJ = 0x03030103; +static const UInt64 k_BCJ2 = 0x0303011B; + +namespace NArchive { +namespace N7z { + +static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindInfo, + const CRecordVector decompressionMethods, + CFolder &folder) +{ + folder.Coders.Clear(); + // bindInfo.CoderMethodIDs.Clear(); + // folder.OutStreams.Clear(); + folder.PackStreams.Clear(); + folder.BindPairs.Clear(); + int i; + for (i = 0; i < bindInfo.BindPairs.Size(); i++) + { + CBindPair bindPair; + bindPair.InIndex = bindInfo.BindPairs[i].InIndex; + bindPair.OutIndex = bindInfo.BindPairs[i].OutIndex; + folder.BindPairs.Add(bindPair); + } + for (i = 0; i < bindInfo.Coders.Size(); i++) + { + CCoderInfo coderInfo; + const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i]; + coderInfo.NumInStreams = coderStreamsInfo.NumInStreams; + coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams; + coderInfo.MethodID = decompressionMethods[i]; + folder.Coders.Add(coderInfo); + } + for (i = 0; i < bindInfo.InStreams.Size(); i++) + folder.PackStreams.Add(bindInfo.InStreams[i]); +} + +HRESULT CEncoder::CreateMixerCoder( + DECL_EXTERNAL_CODECS_LOC_VARS + const UInt64 *inSizeForReduce) +{ + _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT; + _mixerCoder = _mixerCoderSpec; + RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo)); + for (int i = 0; i < _options.Methods.Size(); i++) + { + const CMethodFull &methodFull = _options.Methods[i]; + _codersInfo.Add(CCoderInfo()); + CCoderInfo &encodingInfo = _codersInfo.Back(); + encodingInfo.MethodID = methodFull.Id; + CMyComPtr encoder; + CMyComPtr encoder2; + + + RINOK(CreateCoder( + EXTERNAL_CODECS_LOC_VARS + methodFull.Id, encoder, encoder2, true)); + + if (!encoder && !encoder2) + return E_FAIL; + + CMyComPtr encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2; + + #ifndef _7ZIP_ST + { + CMyComPtr setCoderMt; + encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); + if (setCoderMt) + { + RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads)); + } + } + #endif + + + RINOK(SetMethodProperties(methodFull, inSizeForReduce, encoderCommon)); + + /* + CMyComPtr resetSalt; + encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt); + if (resetSalt != NULL) + { + resetSalt->ResetSalt(); + } + */ + + #ifdef EXTERNAL_CODECS + CMyComPtr setCompressCodecsInfo; + encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); + if (setCompressCodecsInfo) + { + RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); + } + #endif + + CMyComPtr cryptoSetPassword; + encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); + + if (cryptoSetPassword) + { + CByteBuffer buffer; + const UInt32 sizeInBytes = _options.Password.Length() * 2; + buffer.SetCapacity(sizeInBytes); + for (int i = 0; i < _options.Password.Length(); 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, sizeInBytes)); + } + + if (encoder) + _mixerCoderSpec->AddCoder(encoder); + else + _mixerCoderSpec->AddCoder2(encoder2); + } + return S_OK; +} + +HRESULT CEncoder::Encode( + DECL_EXTERNAL_CODECS_LOC_VARS + ISequentialInStream *inStream, + const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, + CFolder &folderItem, + ISequentialOutStream *outStream, + CRecordVector &packSizes, + ICompressProgressInfo *compressProgress) +{ + RINOK(EncoderConstr()); + + if (_mixerCoderSpec == NULL) + { + RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce)); + } + _mixerCoderSpec->ReInit(); + // _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress); + + CObjectVector inOutTempBuffers; + CObjectVector tempBufferSpecs; + CObjectVector > tempBuffers; + int numMethods = _bindInfo.Coders.Size(); + int i; + for (i = 1; i < _bindInfo.OutStreams.Size(); i++) + { + inOutTempBuffers.Add(CInOutTempBuffer()); + inOutTempBuffers.Back().Create(); + inOutTempBuffers.Back().InitWriting(); + } + for (i = 1; i < _bindInfo.OutStreams.Size(); i++) + { + CSequentialOutTempBufferImp *tempBufferSpec = new CSequentialOutTempBufferImp; + CMyComPtr tempBuffer = tempBufferSpec; + tempBufferSpec->Init(&inOutTempBuffers[i - 1]); + tempBuffers.Add(tempBuffer); + tempBufferSpecs.Add(tempBufferSpec); + } + + for (i = 0; i < numMethods; i++) + _mixerCoderSpec->SetCoderInfo(i, NULL, NULL); + + if (_bindInfo.InStreams.IsEmpty()) + return E_FAIL; + UInt32 mainCoderIndex, mainStreamIndex; + _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex); + + if (inStreamSize != NULL) + { + CRecordVector sizePointers; + for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++) + if (i == mainStreamIndex) + sizePointers.Add(inStreamSize); + else + sizePointers.Add(NULL); + _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL); + } + + + // UInt64 outStreamStartPos; + // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos)); + + CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2; + CMyComPtr inStreamSizeCount = inStreamSizeCountSpec; + CSequentialOutStreamSizeCount *outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; + CMyComPtr outStreamSizeCount = outStreamSizeCountSpec; + + inStreamSizeCountSpec->Init(inStream); + outStreamSizeCountSpec->SetStream(outStream); + outStreamSizeCountSpec->Init(); + + CRecordVector inStreamPointers; + CRecordVector outStreamPointers; + inStreamPointers.Add(inStreamSizeCount); + outStreamPointers.Add(outStreamSizeCount); + for (i = 1; i < _bindInfo.OutStreams.Size(); i++) + outStreamPointers.Add(tempBuffers[i - 1]); + + for (i = 0; i < _codersInfo.Size(); i++) + { + CCoderInfo &encodingInfo = _codersInfo[i]; + + CMyComPtr resetInitVector; + _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector); + if (resetInitVector != NULL) + { + resetInitVector->ResetInitVector(); + } + + CMyComPtr writeCoderProperties; + _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); + if (writeCoderProperties != NULL) + { + CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream; + CMyComPtr outStream(outStreamSpec); + outStreamSpec->Init(); + writeCoderProperties->WriteCoderProperties(outStream); + outStreamSpec->CopyToBuffer(encodingInfo.Props); + } + } + + UInt32 progressIndex = mainCoderIndex; + + for (i = 0; i + 1 < _codersInfo.Size(); i++) + { + UInt64 m = _codersInfo[i].MethodID; + if (m == k_Delta || m == k_BCJ || m == k_BCJ2) + progressIndex = i + 1; + } + + _mixerCoderSpec->SetProgressCoderIndex(progressIndex); + + RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1, + &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress)); + + ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem); + + packSizes.Add(outStreamSizeCountSpec->GetSize()); + + for (i = 1; i < _bindInfo.OutStreams.Size(); i++) + { + CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1]; + RINOK(inOutTempBuffer.WriteToStream(outStream)); + packSizes.Add(inOutTempBuffer.GetDataSize()); + } + + for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++) + { + int binder = _bindInfo.FindBinderForInStream( + _bindReverseConverter->DestOutToSrcInMap[i]); + UInt64 streamSize; + if (binder < 0) + streamSize = inStreamSizeCountSpec->GetSize(); + else + streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder); + folderItem.UnpackSizes.Add(streamSize); + } + for (i = numMethods - 1; i >= 0; i--) + folderItem.Coders[numMethods - 1 - i].Props = _codersInfo[i].Props; + return S_OK; +} + + +CEncoder::CEncoder(const CCompressionMethodMode &options): + _bindReverseConverter(0), + _constructed(false) +{ + if (options.IsEmpty()) + throw 1; + + _options = options; + _mixerCoderSpec = 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.Binds.IsEmpty()) + throw 1; + NCoderMixer::CCoderStreamsInfo coderStreamsInfo; + CMethodFull method; + + method.NumInStreams = 1; + method.NumOutStreams = 1; + coderStreamsInfo.NumInStreams = 1; + coderStreamsInfo.NumOutStreams = 1; + method.Id = k_AES; + + _options.Methods.Add(method); + _bindInfo.Coders.Add(coderStreamsInfo); + + _bindInfo.InStreams.Add(0); + _bindInfo.OutStreams.Add(0); + } + else + { + + UInt32 numInStreams = 0, numOutStreams = 0; + int i; + for (i = 0; i < _options.Methods.Size(); i++) + { + const CMethodFull &methodFull = _options.Methods[i]; + NCoderMixer::CCoderStreamsInfo coderStreamsInfo; + coderStreamsInfo.NumInStreams = methodFull.NumOutStreams; + coderStreamsInfo.NumOutStreams = methodFull.NumInStreams; + if (_options.Binds.IsEmpty()) + { + if (i < _options.Methods.Size() - 1) + { + NCoderMixer::CBindPair bindPair; + bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams; + bindPair.OutIndex = numOutStreams; + _bindInfo.BindPairs.Add(bindPair); + } + else + _bindInfo.OutStreams.Insert(0, numOutStreams); + for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++) + _bindInfo.OutStreams.Add(numOutStreams + j); + } + + numInStreams += coderStreamsInfo.NumInStreams; + numOutStreams += coderStreamsInfo.NumOutStreams; + + _bindInfo.Coders.Add(coderStreamsInfo); + } + + if (!_options.Binds.IsEmpty()) + { + for (i = 0; i < _options.Binds.Size(); i++) + { + NCoderMixer::CBindPair bindPair; + const CBind &bind = _options.Binds[i]; + bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream; + bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream; + _bindInfo.BindPairs.Add(bindPair); + } + for (i = 0; i < (int)numOutStreams; i++) + if (_bindInfo.FindBinderForOutStream(i) == -1) + _bindInfo.OutStreams.Add(i); + } + + for (i = 0; i < (int)numInStreams; i++) + if (_bindInfo.FindBinderForInStream(i) == -1) + _bindInfo.InStreams.Add(i); + + if (_bindInfo.InStreams.IsEmpty()) + throw 1; // this is error + + // Make main stream first in list + int inIndex = _bindInfo.InStreams[0]; + for (;;) + { + UInt32 coderIndex, coderStreamIndex; + _bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex); + UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex); + int binder = _bindInfo.FindBinderForOutStream(outIndex); + if (binder >= 0) + { + inIndex = _bindInfo.BindPairs[binder].InIndex; + continue; + } + for (i = 0; i < _bindInfo.OutStreams.Size(); i++) + if (_bindInfo.OutStreams[i] == outIndex) + { + _bindInfo.OutStreams.Delete(i); + _bindInfo.OutStreams.Insert(0, outIndex); + break; + } + break; + } + + if (_options.PasswordIsDefined) + { + int numCryptoStreams = _bindInfo.OutStreams.Size(); + + for (i = 0; i < numCryptoStreams; i++) + { + NCoderMixer::CBindPair bindPair; + bindPair.InIndex = numInStreams + i; + bindPair.OutIndex = _bindInfo.OutStreams[i]; + _bindInfo.BindPairs.Add(bindPair); + } + _bindInfo.OutStreams.Clear(); + + /* + if (numCryptoStreams == 0) + numCryptoStreams = 1; + */ + + for (i = 0; i < numCryptoStreams; i++) + { + NCoderMixer::CCoderStreamsInfo coderStreamsInfo; + CMethodFull method; + method.NumInStreams = 1; + method.NumOutStreams = 1; + coderStreamsInfo.NumInStreams = method.NumOutStreams; + coderStreamsInfo.NumOutStreams = method.NumInStreams; + method.Id = k_AES; + + _options.Methods.Add(method); + _bindInfo.Coders.Add(coderStreamsInfo); + _bindInfo.OutStreams.Add(numOutStreams + i); + } + } + + } + + for (int i = _options.Methods.Size() - 1; i >= 0; i--) + { + const CMethodFull &methodFull = _options.Methods[i]; + _decompressionMethods.Add(methodFull.Id); + } + + _bindReverseConverter = new NCoderMixer::CBindReverseConverter(_bindInfo); + _bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo); + _constructed = true; + return S_OK; +} + +CEncoder::~CEncoder() +{ + delete _bindReverseConverter; +} + +}} diff --git a/CPP/7zip/Archive/7z/7zEncode.h b/CPP/7zip/Archive/7z/7zEncode.h new file mode 100755 index 0000000..c75f02f --- /dev/null +++ b/CPP/7zip/Archive/7z/7zEncode.h @@ -0,0 +1,55 @@ +// 7zEncode.h + +#ifndef __7Z_ENCODE_H +#define __7Z_ENCODE_H + +// #include "../../Common/StreamObjects.h" + +#include "7zCompressionMode.h" + +#include "../Common/CoderMixer2.h" +#include "../Common/CoderMixer2MT.h" +#ifdef _ST_MODE +#include "../Common/CoderMixer2ST.h" +#endif +#include "7zItem.h" + +#include "../../Common/CreateCoder.h" + +namespace NArchive { +namespace N7z { + +class CEncoder +{ + NCoderMixer::CCoderMixer2MT *_mixerCoderSpec; + CMyComPtr _mixerCoder; + + CObjectVector _codersInfo; + + CCompressionMethodMode _options; + NCoderMixer::CBindInfo _bindInfo; + NCoderMixer::CBindInfo _decompressBindInfo; + NCoderMixer::CBindReverseConverter *_bindReverseConverter; + CRecordVector _decompressionMethods; + + 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, + ISequentialOutStream *outStream, + CRecordVector &packSizes, + ICompressProgressInfo *compressProgress); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/7z/7zExtract.cpp b/CPP/7zip/Archive/7z/7zExtract.cpp new file mode 100755 index 0000000..6e31943 --- /dev/null +++ b/CPP/7zip/Archive/7z/7zExtract.cpp @@ -0,0 +1,270 @@ +// 7zExtract.cpp + +#include "StdAfx.h" + +#include "../../../Common/ComTry.h" + +#include "../../Common/ProgressUtils.h" + +#include "7zDecode.h" +// #include "7z1Decode.h" +#include "7zFolderOutStream.h" +#include "7zHandler.h" + +namespace NArchive { +namespace N7z { + +struct CExtractFolderInfo +{ + #ifdef _7Z_VOL + int VolumeIndex; + #endif + CNum FileIndex; + CNum FolderIndex; + CBoolVector ExtractStatuses; + UInt64 UnpackSize; + CExtractFolderInfo( + #ifdef _7Z_VOL + int volumeIndex, + #endif + CNum fileIndex, CNum folderIndex): + #ifdef _7Z_VOL + VolumeIndex(volumeIndex), + #endif + FileIndex(fileIndex), + FolderIndex(folderIndex), + UnpackSize(0) + { + if (fileIndex != kNumNoIndex) + { + ExtractStatuses.Reserve(1); + ExtractStatuses.Add(true); + } + }; +}; + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec) +{ + COM_TRY_BEGIN + bool testMode = (testModeSpec != 0); + CMyComPtr extractCallback = extractCallbackSpec; + UInt64 importantTotalUnpacked = 0; + + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = + #ifdef _7Z_VOL + _refs.Size(); + #else + _db.Files.Size(); + #endif + + if(numItems == 0) + return S_OK; + + /* + if(_volumes.Size() != 1) + return E_FAIL; + const CVolume &volume = _volumes.Front(); + const CArchiveDatabaseEx &_db = volume.Database; + IInStream *_inStream = volume.Stream; + */ + + CObjectVector extractFolderInfoVector; + for (UInt32 ii = 0; ii < numItems; ii++) + { + // UInt32 fileIndex = allFilesMode ? indexIndex : indices[indexIndex]; + UInt32 ref2Index = allFilesMode ? ii : indices[ii]; + // const CRef2 &ref2 = _refs[ref2Index]; + + // for (UInt32 ri = 0; ri < ref2.Refs.Size(); ri++) + { + #ifdef _7Z_VOL + // const CRef &ref = ref2.Refs[ri]; + const CRef &ref = _refs[ref2Index]; + + int volumeIndex = ref.VolumeIndex; + const CVolume &volume = _volumes[volumeIndex]; + const CArchiveDatabaseEx &db = volume.Database; + UInt32 fileIndex = ref.ItemIndex; + #else + const CArchiveDatabaseEx &db = _db; + UInt32 fileIndex = ref2Index; + #endif + + CNum folderIndex = db.FileIndexToFolderIndexMap[fileIndex]; + if (folderIndex == kNumNoIndex) + { + extractFolderInfoVector.Add(CExtractFolderInfo( + #ifdef _7Z_VOL + volumeIndex, + #endif + fileIndex, kNumNoIndex)); + continue; + } + if (extractFolderInfoVector.IsEmpty() || + folderIndex != extractFolderInfoVector.Back().FolderIndex + #ifdef _7Z_VOL + || volumeIndex != extractFolderInfoVector.Back().VolumeIndex + #endif + ) + { + extractFolderInfoVector.Add(CExtractFolderInfo( + #ifdef _7Z_VOL + volumeIndex, + #endif + kNumNoIndex, folderIndex)); + const CFolder &folderInfo = db.Folders[folderIndex]; + UInt64 unpackSize = folderInfo.GetUnpackSize(); + importantTotalUnpacked += unpackSize; + extractFolderInfoVector.Back().UnpackSize = unpackSize; + } + + CExtractFolderInfo &efi = extractFolderInfoVector.Back(); + + // const CFolderInfo &folderInfo = m_dam_Folders[folderIndex]; + CNum startIndex = db.FolderStartFileIndex[folderIndex]; + for (CNum index = efi.ExtractStatuses.Size(); + index <= fileIndex - startIndex; index++) + { + // UInt64 unpackSize = _db.Files[startIndex + index].UnpackSize; + // Count partial_folder_size + // efi.UnpackSize += unpackSize; + // importantTotalUnpacked += unpackSize; + efi.ExtractStatuses.Add(index == fileIndex - startIndex); + } + } + } + + RINOK(extractCallback->SetTotal(importantTotalUnpacked)); + + CDecoder decoder( + #ifdef _ST_MODE + false + #else + true + #endif + ); + // CDecoder1 decoder; + + UInt64 totalPacked = 0; + UInt64 totalUnpacked = 0; + UInt64 curPacked, curUnpacked; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + for (int i = 0;; i++, totalUnpacked += curUnpacked, totalPacked += curPacked) + { + lps->OutSize = totalUnpacked; + lps->InSize = totalPacked; + RINOK(lps->SetCur()); + + if (i >= extractFolderInfoVector.Size()) + break; + + const CExtractFolderInfo &efi = extractFolderInfoVector[i]; + curUnpacked = efi.UnpackSize; + curPacked = 0; + + CFolderOutStream *folderOutStream = new CFolderOutStream; + CMyComPtr outStream(folderOutStream); + + #ifdef _7Z_VOL + const CVolume &volume = _volumes[efi.VolumeIndex]; + const CArchiveDatabaseEx &db = volume.Database; + #else + const CArchiveDatabaseEx &db = _db; + #endif + + CNum startIndex; + if (efi.FileIndex != kNumNoIndex) + startIndex = efi.FileIndex; + else + startIndex = db.FolderStartFileIndex[efi.FolderIndex]; + + HRESULT result = folderOutStream->Init(&db, + #ifdef _7Z_VOL + volume.StartRef2Index, + #else + 0, + #endif + startIndex, + &efi.ExtractStatuses, extractCallback, testMode, _crcSize != 0); + + RINOK(result); + + if (efi.FileIndex != kNumNoIndex) + continue; + + CNum folderIndex = efi.FolderIndex; + const CFolder &folderInfo = db.Folders[folderIndex]; + + curPacked = _db.GetFolderFullPackSize(folderIndex); + + CNum packStreamIndex = db.FolderStartPackStreamIndex[folderIndex]; + UInt64 folderStartPackPos = db.GetFolderStreamPos(folderIndex, 0); + + #ifndef _NO_CRYPTO + CMyComPtr getTextPassword; + if (extractCallback) + extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); + #endif + + try + { + #ifndef _NO_CRYPTO + bool passwordIsDefined; + #endif + + HRESULT result = decoder.Decode( + EXTERNAL_CODECS_VARS + #ifdef _7Z_VOL + volume.Stream, + #else + _inStream, + #endif + folderStartPackPos, + &db.PackSizes[packStreamIndex], + folderInfo, + outStream, + progress + #ifndef _NO_CRYPTO + , getTextPassword, passwordIsDefined + #endif + #if !defined(_7ZIP_ST) && !defined(_SFX) + , true, _numThreads + #endif + ); + + if (result == S_FALSE) + { + RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError)); + continue; + } + if (result == E_NOTIMPL) + { + RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kUnSupportedMethod)); + continue; + } + if (result != S_OK) + return result; + if (folderOutStream->WasWritingFinished() != S_OK) + { + RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError)); + continue; + } + } + catch(...) + { + RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError)); + continue; + } + } + return S_OK; + COM_TRY_END +} + +}} diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.cpp b/CPP/7zip/Archive/7z/7zFolderInStream.cpp new file mode 100755 index 0000000..c49d341 --- /dev/null +++ b/CPP/7zip/Archive/7z/7zFolderInStream.cpp @@ -0,0 +1,123 @@ +// 7zFolderInStream.cpp + +#include "StdAfx.h" + +#include "7zFolderInStream.h" + +namespace NArchive { +namespace N7z { + +CFolderInStream::CFolderInStream() +{ + _inStreamWithHashSpec = new CSequentialInStreamWithCRC; + _inStreamWithHash = _inStreamWithHashSpec; +} + +void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback, + const UInt32 *fileIndices, UInt32 numFiles) +{ + _updateCallback = updateCallback; + _numFiles = numFiles; + _fileIndex = 0; + _fileIndices = fileIndices; + Processed.Clear(); + CRCs.Clear(); + Sizes.Clear(); + _fileIsOpen = false; + _currentSizeIsDefined = false; +} + +HRESULT CFolderInStream::OpenStream() +{ + _filePos = 0; + while (_fileIndex < _numFiles) + { + CMyComPtr stream; + HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream); + if (result != S_OK && result != S_FALSE) + return result; + _fileIndex++; + _inStreamWithHashSpec->SetStream(stream); + _inStreamWithHashSpec->Init(); + if (stream) + { + _fileIsOpen = true; + CMyComPtr streamGetSize; + stream.QueryInterface(IID_IStreamGetSize, &streamGetSize); + if (streamGetSize) + { + RINOK(streamGetSize->GetSize(&_currentSize)); + _currentSizeIsDefined = true; + } + return S_OK; + } + RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); + Sizes.Add(0); + Processed.Add(result == S_OK); + AddDigest(); + } + return S_OK; +} + +void CFolderInStream::AddDigest() +{ + CRCs.Add(_inStreamWithHashSpec->GetCRC()); +} + +HRESULT CFolderInStream::CloseStream() +{ + RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); + _inStreamWithHashSpec->ReleaseStream(); + _fileIsOpen = false; + _currentSizeIsDefined = false; + Processed.Add(true); + Sizes.Add(_filePos); + AddDigest(); + return S_OK; +} + +STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != 0) + *processedSize = 0; + while (size > 0) + { + if (_fileIsOpen) + { + UInt32 processed2; + RINOK(_inStreamWithHash->Read(data, size, &processed2)); + if (processed2 == 0) + { + RINOK(CloseStream()); + continue; + } + if (processedSize != 0) + *processedSize = processed2; + _filePos += processed2; + break; + } + if (_fileIndex >= _numFiles) + break; + RINOK(OpenStream()); + } + return S_OK; +} + +STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value) +{ + *value = 0; + int index2 = (int)subStream; + if (index2 < 0 || subStream > Sizes.Size()) + return E_FAIL; + if (index2 < Sizes.Size()) + { + *value = Sizes[index2]; + return S_OK; + } + if (!_currentSizeIsDefined) + return S_FALSE; + *value = _currentSize; + return S_OK; +} + +}} diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.h b/CPP/7zip/Archive/7z/7zFolderInStream.h new file mode 100755 index 0000000..fc27b9b --- /dev/null +++ b/CPP/7zip/Archive/7z/7zFolderInStream.h @@ -0,0 +1,58 @@ +// 7zFolderInStream.h + +#ifndef __7Z_FOLDER_IN_STREAM_H +#define __7Z_FOLDER_IN_STREAM_H + +#include "../../ICoder.h" +#include "../IArchive.h" +#include "../Common/InStreamWithCRC.h" + +#include "7zItem.h" + +namespace NArchive { +namespace N7z { + +class CFolderInStream: + public ISequentialInStream, + public ICompressGetSubStreamSize, + public CMyUnknownImp +{ + CSequentialInStreamWithCRC *_inStreamWithHashSpec; + CMyComPtr _inStreamWithHash; + CMyComPtr _updateCallback; + + bool _currentSizeIsDefined; + bool _fileIsOpen; + UInt64 _currentSize; + UInt64 _filePos; + const UInt32 *_fileIndices; + UInt32 _numFiles; + UInt32 _fileIndex; + + HRESULT OpenStream(); + HRESULT CloseStream(); + void AddDigest(); + +public: + CRecordVector Processed; + CRecordVector CRCs; + CRecordVector Sizes; + + MY_UNKNOWN_IMP1(ICompressGetSubStreamSize) + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); + + CFolderInStream(); + void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles); + UInt64 GetFullSize() const + { + UInt64 size = 0; + for (int i = 0; i < Sizes.Size(); i++) + size += Sizes[i]; + return size; + } +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.cpp b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp new file mode 100755 index 0000000..403ca60 --- /dev/null +++ b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp @@ -0,0 +1,149 @@ +// 7zFolderOutStream.cpp + +#include "StdAfx.h" + +#include "7zFolderOutStream.h" + +namespace NArchive { +namespace N7z { + +CFolderOutStream::CFolderOutStream() +{ + _crcStreamSpec = new COutStreamWithCRC; + _crcStream = _crcStreamSpec; +} + +HRESULT CFolderOutStream::Init( + const CArchiveDatabaseEx *db, + UInt32 ref2Offset, UInt32 startIndex, + const CBoolVector *extractStatuses, + IArchiveExtractCallback *extractCallback, + bool testMode, bool checkCrc) +{ + _db = db; + _ref2Offset = ref2Offset; + _startIndex = startIndex; + + _extractStatuses = extractStatuses; + _extractCallback = extractCallback; + _testMode = testMode; + _checkCrc = checkCrc; + + _currentIndex = 0; + _fileIsOpen = false; + return ProcessEmptyFiles(); +} + +HRESULT CFolderOutStream::OpenFile() +{ + Int32 askMode = ((*_extractStatuses)[_currentIndex]) ? (_testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract) : + NExtract::NAskMode::kSkip; + CMyComPtr realOutStream; + UInt32 index = _startIndex + _currentIndex; + RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode)); + _crcStreamSpec->SetStream(realOutStream); + _crcStreamSpec->Init(_checkCrc); + _fileIsOpen = true; + const CFileItem &fi = _db->Files[index]; + _rem = fi.Size; + if (askMode == NExtract::NAskMode::kExtract && !realOutStream && + !_db->IsItemAnti(index) && !fi.IsDir) + askMode = NExtract::NAskMode::kSkip; + return _extractCallback->PrepareOperation(askMode); +} + +HRESULT CFolderOutStream::CloseFileAndSetResult(Int32 res) +{ + _crcStreamSpec->ReleaseStream(); + _fileIsOpen = false; + _currentIndex++; + return _extractCallback->SetOperationResult(res); +} + +HRESULT CFolderOutStream::CloseFileAndSetResult() +{ + const CFileItem &fi = _db->Files[_startIndex + _currentIndex]; + return CloseFileAndSetResult( + (fi.IsDir || !fi.CrcDefined || !_checkCrc || fi.Crc == _crcStreamSpec->GetCRC()) ? + NExtract::NOperationResult::kOK : + NExtract::NOperationResult::kCRCError); +} + +HRESULT CFolderOutStream::ProcessEmptyFiles() +{ + while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0) + { + RINOK(OpenFile()); + RINOK(CloseFileAndSetResult()); + } + return S_OK; +} + +STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != NULL) + *processedSize = 0; + while (size != 0) + { + if (_fileIsOpen) + { + UInt32 cur = size < _rem ? size : (UInt32)_rem; + RINOK(_crcStream->Write(data, cur, &cur)); + if (cur == 0) + break; + data = (const Byte *)data + cur; + size -= cur; + _rem -= cur; + if (processedSize != NULL) + *processedSize += cur; + if (_rem == 0) + { + RINOK(CloseFileAndSetResult()); + RINOK(ProcessEmptyFiles()); + continue; + } + } + else + { + RINOK(ProcessEmptyFiles()); + if (_currentIndex == _extractStatuses->Size()) + { + // we support partial extracting + if (processedSize != NULL) + *processedSize += size; + break; + } + RINOK(OpenFile()); + } + } + return S_OK; +} + +STDMETHODIMP CFolderOutStream::GetSubStreamSize(UInt64 subStream, UInt64 *value) +{ + *value = 0; + if ((int)subStream >= _extractStatuses->Size()) + return S_FALSE; + *value = _db->Files[_startIndex + (int)subStream].Size; + return S_OK; +} + +HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult) +{ + while (_currentIndex < _extractStatuses->Size()) + { + if (_fileIsOpen) + { + RINOK(CloseFileAndSetResult(resultEOperationResult)); + } + else + { + RINOK(OpenFile()); + } + } + return S_OK; +} + +}} diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.h b/CPP/7zip/Archive/7z/7zFolderOutStream.h new file mode 100755 index 0000000..c964b1d --- /dev/null +++ b/CPP/7zip/Archive/7z/7zFolderOutStream.h @@ -0,0 +1,58 @@ +// 7zFolderOutStream.h + +#ifndef __7Z_FOLDER_OUT_STREAM_H +#define __7Z_FOLDER_OUT_STREAM_H + +#include "../../IStream.h" +#include "../IArchive.h" +#include "../Common/OutStreamWithCRC.h" + +#include "7zIn.h" + +namespace NArchive { +namespace N7z { + +class CFolderOutStream: + public ISequentialOutStream, + public ICompressGetSubStreamSize, + public CMyUnknownImp +{ + COutStreamWithCRC *_crcStreamSpec; + CMyComPtr _crcStream; + const CArchiveDatabaseEx *_db; + const CBoolVector *_extractStatuses; + CMyComPtr _extractCallback; + UInt32 _ref2Offset; + UInt32 _startIndex; + int _currentIndex; + bool _testMode; + bool _checkCrc; + bool _fileIsOpen; + UInt64 _rem; + + HRESULT OpenFile(); + HRESULT CloseFileAndSetResult(Int32 res); + HRESULT CloseFileAndSetResult(); + HRESULT ProcessEmptyFiles(); +public: + MY_UNKNOWN_IMP1(ICompressGetSubStreamSize) + + CFolderOutStream(); + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); + + HRESULT Init( + const CArchiveDatabaseEx *db, + UInt32 ref2Offset, UInt32 startIndex, + const CBoolVector *extractStatuses, + IArchiveExtractCallback *extractCallback, + bool testMode, bool checkCrc); + HRESULT FlushCorrupted(Int32 resultEOperationResult); + HRESULT WasWritingFinished() const + { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; } +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp new file mode 100755 index 0000000..c404b9c --- /dev/null +++ b/CPP/7zip/Archive/7z/7zHandler.cpp @@ -0,0 +1,482 @@ +// 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; + +extern UString ConvertMethodIdToString(UInt64 id); + +namespace NArchive { +namespace N7z { + +CHandler::CHandler() +{ + _crcSize = 4; + + #ifndef _NO_CRYPTO + _passwordIsDefined = false; + #endif + + #ifdef EXTRACT_ONLY + #ifdef __7Z_SET_PROPERTIES + _numThreads = NSystem::GetNumberOfProcessors(); + #endif + #else + Init(); + #endif +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _db.Files.Size(); + return S_OK; +} + +#ifdef _SFX + +IMP_IInArchive_ArcProps_NO + +STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */, + BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */) +{ + return E_NOTIMPL; +} + + +#else + +STATPROPSTG kArcProps[] = +{ + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidSolid, VT_BOOL}, + { NULL, kpidNumBlocks, VT_UI4}, + { NULL, kpidPhySize, VT_UI8}, + { NULL, kpidHeadersSize, VT_UI8}, + { NULL, kpidOffset, VT_UI8} +}; + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NCOM::CPropVariant prop; + switch(propID) + { + case kpidMethod: + { + UString resString; + CRecordVector ids; + int i; + for (i = 0; i < _db.Folders.Size(); i++) + { + const CFolder &f = _db.Folders[i]; + for (int j = f.Coders.Size() - 1; j >= 0; j--) + ids.AddToUniqueSorted(f.Coders[j].MethodID); + } + + for (i = 0; i < ids.Size(); i++) + { + UInt64 id = ids[i]; + UString methodName; + /* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName); + if (methodName.IsEmpty()) + methodName = ConvertMethodIdToString(id); + if (!resString.IsEmpty()) + resString += L' '; + resString += methodName; + } + prop = resString; + break; + } + case kpidSolid: prop = _db.IsSolid(); break; + case kpidNumBlocks: prop = (UInt32)_db.Folders.Size(); break; + case kpidHeadersSize: prop = _db.HeadersSize; break; + case kpidPhySize: prop = _db.PhySize; break; + case kpidOffset: if (_db.ArchiveInfo.StartPosition != 0) prop = _db.ArchiveInfo.StartPosition; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +IMP_IInArchive_ArcProps + +#endif + +static void SetPropFromUInt64Def(CUInt64DefVector &v, int index, NCOM::CPropVariant &prop) +{ + UInt64 value; + if (v.GetItem(index, value)) + { + FILETIME ft; + ft.dwLowDateTime = (DWORD)value; + ft.dwHighDateTime = (DWORD)(value >> 32); + prop = ft; + } +} + +#ifndef _SFX + +static UString ConvertUInt32ToString(UInt32 value) +{ + wchar_t buffer[32]; + ConvertUInt64ToString(value, buffer); + return buffer; +} + +static UString GetStringForSizeValue(UInt32 value) +{ + for (int i = 31; i >= 0; i--) + if ((UInt32(1) << i) == value) + return ConvertUInt32ToString(i); + UString result; + if (value % (1 << 20) == 0) + { + result += ConvertUInt32ToString(value >> 20); + result += L"m"; + } + else if (value % (1 << 10) == 0) + { + result += ConvertUInt32ToString(value >> 10); + result += L"k"; + } + else + { + result += ConvertUInt32ToString(value); + result += L"b"; + } + return result; +} + +static const UInt64 k_Copy = 0x0; +static const UInt64 k_Delta = 3; +static const UInt64 k_LZMA2 = 0x21; +static const UInt64 k_LZMA = 0x030101; +static const UInt64 k_PPMD = 0x030401; + +static wchar_t GetHex(Byte value) +{ + return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10))); +} +static inline void AddHexToString(UString &res, Byte value) +{ + res += GetHex((Byte)(value >> 4)); + res += GetHex((Byte)(value & 0xF)); +} + +#endif + +bool CHandler::IsEncrypted(UInt32 index2) const +{ + CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; + if (folderIndex != kNumNoIndex) + return _db.Folders[folderIndex].IsEncrypted(); + return false; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *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]; + UInt32 index2 = index; + + switch(propID) + { + case kpidPath: + if (!item.Name.IsEmpty()) + prop = NItemName::GetOSName(item.Name); + break; + case kpidIsDir: prop = item.IsDir; break; + case kpidSize: + { + prop = 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) + prop = _db.GetFolderFullPackSize(folderIndex); + /* + else + prop = (UInt64)0; + */ + } + else + prop = (UInt64)0; + } + break; + } + case kpidPosition: { UInt64 v; if (_db.StartPos.GetItem(index2, v)) prop = v; break; } + case kpidCTime: SetPropFromUInt64Def(_db.CTime, index2, prop); break; + case kpidATime: SetPropFromUInt64Def(_db.ATime, index2, prop); break; + case kpidMTime: SetPropFromUInt64Def(_db.MTime, index2, prop); break; + case kpidAttrib: if (item.AttribDefined) prop = item.Attrib; break; + case kpidCRC: if (item.CrcDefined) prop = item.Crc; break; + case kpidEncrypted: prop = IsEncrypted(index2); break; + case kpidIsAnti: prop = _db.IsItemAnti(index2); break; + #ifndef _SFX + case kpidMethod: + { + CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; + if (folderIndex != kNumNoIndex) + { + const CFolder &folderInfo = _db.Folders[folderIndex]; + UString methodsString; + for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) + { + const CCoderInfo &coder = folderInfo.Coders[i]; + if (!methodsString.IsEmpty()) + methodsString += L' '; + + UString methodName, propsString; + bool methodIsKnown = FindMethod( + EXTERNAL_CODECS_VARS + coder.MethodID, methodName); + + if (!methodIsKnown) + methodsString += ConvertMethodIdToString(coder.MethodID); + else + { + methodsString += methodName; + if (coder.MethodID == k_Delta && coder.Props.GetCapacity() == 1) + propsString = ConvertUInt32ToString((UInt32)coder.Props[0] + 1); + else if (coder.MethodID == k_LZMA && coder.Props.GetCapacity() == 5) + { + UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1); + propsString = GetStringForSizeValue(dicSize); + } + else if (coder.MethodID == k_LZMA2 && coder.Props.GetCapacity() == 1) + { + Byte p = coder.Props[0]; + UInt32 dicSize = (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)); + propsString = GetStringForSizeValue(dicSize); + } + else if (coder.MethodID == k_PPMD && coder.Props.GetCapacity() == 5) + { + Byte order = *(const Byte *)coder.Props; + propsString = L'o'; + propsString += ConvertUInt32ToString(order); + propsString += L":mem"; + UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1); + propsString += GetStringForSizeValue(dicSize); + } + else if (coder.MethodID == k_AES && coder.Props.GetCapacity() >= 1) + { + const Byte *data = (const Byte *)coder.Props; + Byte firstByte = *data++; + UInt32 numCyclesPower = firstByte & 0x3F; + propsString = ConvertUInt32ToString(numCyclesPower); + /* + if ((firstByte & 0xC0) != 0) + { + UInt32 saltSize = (firstByte >> 7) & 1; + UInt32 ivSize = (firstByte >> 6) & 1; + if (coder.Props.GetCapacity() >= 2) + { + Byte secondByte = *data++; + saltSize += (secondByte >> 4); + ivSize += (secondByte & 0x0F); + } + } + */ + } + } + if (!propsString.IsEmpty()) + { + methodsString += L':'; + methodsString += propsString; + } + else if (coder.Props.GetCapacity() > 0) + { + methodsString += L":["; + for (size_t bi = 0; bi < coder.Props.GetCapacity(); bi++) + { + if (bi > 5 && bi + 1 < coder.Props.GetCapacity()) + { + methodsString += L".."; + break; + } + else + AddHexToString(methodsString, coder.Props[bi]); + } + methodsString += L']'; + } + } + prop = methodsString; + } + } + break; + case kpidBlock: + { + CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; + if (folderIndex != kNumNoIndex) + prop = (UInt32)folderIndex; + } + break; + case kpidPackedSize0: + case kpidPackedSize1: + case kpidPackedSize2: + case kpidPackedSize3: + case kpidPackedSize4: + { + CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; + if (folderIndex != kNumNoIndex) + { + const CFolder &folderInfo = _db.Folders[folderIndex]; + if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 && + folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0)) + { + prop = _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0); + } + else + prop = (UInt64)0; + } + else + prop = (UInt64)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; + RINOK(archive.Open(stream, maxCheckStartPosition)); + #ifndef _NO_CRYPTO + _passwordIsDefined = false; + UString password; + #endif + HRESULT result = archive.ReadDatabase( + EXTERNAL_CODECS_VARS + _db + #ifndef _NO_CRYPTO + , getTextPassword, _passwordIsDefined + #endif + ); + RINOK(result); + _db.Fill(); + _inStream = stream; + } + catch(...) + { + Close(); + return S_FALSE; + } + // _inStream = stream; + #ifndef _SFX + FillPopIDs(); + #endif + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + COM_TRY_BEGIN + _inStream.Release(); + _db.Clear(); + return S_OK; + COM_TRY_END +} + +#ifdef __7Z_SET_PROPERTIES +#ifdef EXTRACT_ONLY + +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) +{ + COM_TRY_BEGIN + const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); + _numThreads = numProcessors; + + for (int i = 0; i < numProperties; i++) + { + UString name = names[i]; + name.MakeUpper(); + if (name.IsEmpty()) + return E_INVALIDARG; + const PROPVARIANT &value = values[i]; + UInt32 number; + int index = ParseStringToUInt32(name, number); + if (index == 0) + { + if(name.Left(2).CompareNoCase(L"MT") == 0) + { + RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); + continue; + } + else + return E_INVALIDARG; + } + } + return S_OK; + COM_TRY_END +} + +#endif +#endif + +IMPL_ISetCompressCodecsInfo + +}} diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h new file mode 100755 index 0000000..c0fd0e0 --- /dev/null +++ b/CPP/7zip/Archive/7z/7zHandler.h @@ -0,0 +1,119 @@ +// 7z/Handler.h + +#ifndef __7Z_HANDLER_H +#define __7Z_HANDLER_H + +#include "../../ICoder.h" +#include "../IArchive.h" + +#include "../../Common/CreateCoder.h" + +#ifndef EXTRACT_ONLY +#include "../Common/HandlerOut.h" +#endif + +#include "7zCompressionMode.h" +#include "7zIn.h" + +namespace NArchive { +namespace N7z { + +#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 + + +class CHandler: + #ifndef EXTRACT_ONLY + public NArchive::COutHandler, + #endif + public IInArchive, + #ifdef __7Z_SET_PROPERTIES + public ISetProperties, + #endif + #ifndef EXTRACT_ONLY + public IOutArchive, + #endif + PUBLIC_ISetCompressCodecsInfo + public CMyUnknownImp +{ +public: + MY_QUERYINTERFACE_BEGIN2(IInArchive) + #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(;) + + #ifdef __7Z_SET_PROPERTIES + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties); + #endif + + #ifndef EXTRACT_ONLY + INTERFACE_IOutArchive(;) + #endif + + DECL_ISetCompressCodecsInfo + + CHandler(); + +private: + CMyComPtr _inStream; + NArchive::N7z::CArchiveDatabaseEx _db; + #ifndef _NO_CRYPTO + bool _passwordIsDefined; + #endif + + #ifdef EXTRACT_ONLY + + #ifdef __7Z_SET_PROPERTIES + UInt32 _numThreads; + #endif + + UInt32 _crcSize; + + #else + + CRecordVector _binds; + + HRESULT SetCompressionMethod(CCompressionMethodMode &method, + CObjectVector &methodsInfo + #ifndef _7ZIP_ST + , UInt32 numThreads + #endif + ); + + HRESULT SetCompressionMethod( + CCompressionMethodMode &method, + CCompressionMethodMode &headerMethod); + + #endif + + bool IsEncrypted(UInt32 index2) const; + #ifndef _SFX + + CRecordVector _fileInfoPopIDs; + void FillPopIDs(); + + #endif + + DECL_EXTERNAL_CODECS_VARS +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp new file mode 100755 index 0000000..59d6269 --- /dev/null +++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp @@ -0,0 +1,483 @@ +// 7zHandlerOut.cpp + +#include "StdAfx.h" + +#include "../../../Windows/PropVariant.h" + +#include "../../../Common/ComTry.h" +#include "../../../Common/StringToInt.h" + +#include "../../ICoder.h" + +#include "../Common/ItemNameUtils.h" +#include "../Common/ParseProperties.h" + +#include "7zHandler.h" +#include "7zOut.h" +#include "7zUpdate.h" + +using namespace NWindows; + +namespace NArchive { +namespace N7z { + +static const wchar_t *kLZMAMethodName = L"LZMA"; +static const wchar_t *kCopyMethod = L"Copy"; +static const wchar_t *kDefaultMethodName = kLZMAMethodName; + +static const UInt32 kLzmaAlgorithmX5 = 1; +static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; +static const UInt32 kDictionaryForHeaders = + #ifdef UNDER_CE + 1 << 18 + #else + 1 << 20 + #endif +; +static const UInt32 kNumFastBytesForHeaders = 273; +static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5; + +static inline bool IsCopyMethod(const UString &methodName) + { return (methodName.CompareNoCase(kCopyMethod) == 0); } + +STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) +{ + *type = NFileTimeType::kWindows; + return S_OK; +} + +HRESULT CHandler::SetCompressionMethod( + CCompressionMethodMode &methodMode, + CCompressionMethodMode &headerMethod) +{ + HRESULT res = SetCompressionMethod(methodMode, _methods + #ifndef _7ZIP_ST + , _numThreads + #endif + ); + RINOK(res); + methodMode.Binds = _binds; + + if (_compressHeaders) + { + // headerMethod.Methods.Add(methodMode.Methods.Back()); + + CObjectVector headerMethodInfoVector; + COneMethodInfo oneMethodInfo; + oneMethodInfo.MethodName = kLZMAMethodName; + { + CProp prop; + prop.Id = NCoderPropID::kMatchFinder; + prop.Value = kLzmaMatchFinderForHeaders; + oneMethodInfo.Props.Add(prop); + } + { + CProp prop; + prop.Id = NCoderPropID::kAlgorithm; + prop.Value = kAlgorithmForHeaders; + oneMethodInfo.Props.Add(prop); + } + { + CProp prop; + prop.Id = NCoderPropID::kNumFastBytes; + prop.Value = (UInt32)kNumFastBytesForHeaders; + oneMethodInfo.Props.Add(prop); + } + { + CProp prop; + prop.Id = NCoderPropID::kDictionarySize; + prop.Value = (UInt32)kDictionaryForHeaders; + oneMethodInfo.Props.Add(prop); + } + headerMethodInfoVector.Add(oneMethodInfo); + HRESULT res = SetCompressionMethod(headerMethod, headerMethodInfoVector + #ifndef _7ZIP_ST + , 1 + #endif + ); + RINOK(res); + } + return S_OK; +} + +HRESULT CHandler::SetCompressionMethod( + CCompressionMethodMode &methodMode, + CObjectVector &methodsInfo + #ifndef _7ZIP_ST + , UInt32 numThreads + #endif + ) +{ + UInt32 level = _level; + + if (methodsInfo.IsEmpty()) + { + COneMethodInfo oneMethodInfo; + oneMethodInfo.MethodName = ((level == 0) ? kCopyMethod : kDefaultMethodName); + methodsInfo.Add(oneMethodInfo); + } + + bool needSolid = false; + for(int i = 0; i < methodsInfo.Size(); i++) + { + COneMethodInfo &oneMethodInfo = methodsInfo[i]; + SetCompressionMethod2(oneMethodInfo + #ifndef _7ZIP_ST + , numThreads + #endif + ); + + if (!IsCopyMethod(oneMethodInfo.MethodName)) + needSolid = true; + + CMethodFull methodFull; + + if (!FindMethod( + EXTERNAL_CODECS_VARS + oneMethodInfo.MethodName, methodFull.Id, methodFull.NumInStreams, methodFull.NumOutStreams)) + return E_INVALIDARG; + methodFull.Props = oneMethodInfo.Props; + methodMode.Methods.Add(methodFull); + + if (!_numSolidBytesDefined) + { + for (int j = 0; j < methodFull.Props.Size(); j++) + { + const CProp &prop = methodFull.Props[j]; + if ((prop.Id == NCoderPropID::kDictionarySize || + prop.Id == NCoderPropID::kUsedMemorySize) && prop.Value.vt == VT_UI4) + { + _numSolidBytes = ((UInt64)prop.Value.ulVal) << 7; + const UInt64 kMinSize = (1 << 24); + if (_numSolidBytes < kMinSize) + _numSolidBytes = kMinSize; + _numSolidBytesDefined = true; + break; + } + } + } + } + + if (!needSolid && !_numSolidBytesDefined) + { + _numSolidBytesDefined = true; + _numSolidBytes = 0; + } + return S_OK; +} + +static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, bool writeTime, PROPID propID, UInt64 &ft, bool &ftDefined) +{ + ft = 0; + ftDefined = false; + if (!writeTime) + return S_OK; + 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; + return S_OK; +} + +STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, + IArchiveUpdateCallback *updateCallback) +{ + COM_TRY_BEGIN + + const CArchiveDatabaseEx *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 + + CObjectVector updateItems; + + 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; + + if (ui.IndexInArchive != -1) + { + if (db == 0 || ui.IndexInArchive >= db->Files.Size()) + return E_INVALIDARG; + const CFileItem &fi = db->Files[ui.IndexInArchive]; + ui.Name = fi.Name; + ui.IsDir = fi.IsDir; + ui.Size = fi.Size; + ui.IsAnti = db->IsItemAnti(ui.IndexInArchive); + + 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 nameIsDefined; + bool folderStatusIsDefined; + { + 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. + RINOK(GetTime(updateCallback, i, WriteCTime, kpidCTime, ui.CTime, ui.CTimeDefined)); + RINOK(GetTime(updateCallback, i, WriteATime, kpidATime, ui.ATime, ui.ATimeDefined)); + RINOK(GetTime(updateCallback, i, true, kpidMTime, ui.MTime, ui.MTimeDefined)); + + { + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(i, kpidPath, &prop)); + if (prop.vt == VT_EMPTY) + nameIsDefined = false; + else if (prop.vt != VT_BSTR) + return E_INVALIDARG; + else + { + ui.Name = NItemName::MakeLegalName(prop.bstrVal); + nameIsDefined = true; + } + } + { + 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); + } + + if (ui.IsAnti) + { + ui.AttribDefined = false; + + ui.CTimeDefined = false; + ui.ATimeDefined = false; + ui.MTimeDefined = false; + + ui.Size = 0; + } + + if (!folderStatusIsDefined && ui.AttribDefined) + ui.SetDirStatusFromAttrib(); + } + + if (ui.NewData) + { + 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); + } + + CCompressionMethodMode methodMode, headerMethod; + RINOK(SetCompressionMethod(methodMode, headerMethod)); + #ifndef _7ZIP_ST + methodMode.NumThreads = _numThreads; + headerMethod.NumThreads = 1; + #endif + + CMyComPtr getPassword2; + updateCallback->QueryInterface(IID_ICryptoGetTextPassword2, (void **)&getPassword2); + + if (getPassword2) + { + CMyComBSTR password; + Int32 passwordIsDefined; + RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password)); + methodMode.PasswordIsDefined = IntToBool(passwordIsDefined); + if (methodMode.PasswordIsDefined) + methodMode.Password = password; + } + else + methodMode.PasswordIsDefined = false; + + bool compressMainHeader = _compressHeaders; // check it + + bool encryptHeaders = false; + + 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; + + CUpdateOptions options; + options.Method = &methodMode; + options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : 0; + options.UseFilters = _level != 0 && _autoFilter; + options.MaxFilter = _level >= 8; + + options.HeaderOptions.CompressMainHeader = compressMainHeader; + options.HeaderOptions.WriteCTime = WriteCTime; + options.HeaderOptions.WriteATime = WriteATime; + options.HeaderOptions.WriteMTime = WriteMTime; + + options.NumSolidFiles = _numSolidFiles; + options.NumSolidBytes = _numSolidBytes; + options.SolidExtension = _solidExtension; + options.RemoveSfxBlock = _removeSfxBlock; + options.VolumeMode = _volumeMode; + + COutArchive archive; + CArchiveDatabase newDatabase; + + CMyComPtr getPassword; + updateCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getPassword); + + HRESULT res = Update( + EXTERNAL_CODECS_VARS + #ifdef _7Z_VOL + volume ? volume->Stream: 0, + volume ? db : 0, + #else + _inStream, + db, + #endif + updateItems, + 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 GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream) +{ + stream = 0; + int index = ParseStringToUInt32(srcString, coder); + if (index == 0) + return E_INVALIDARG; + srcString.Delete(0, index); + if (srcString[0] == 'S') + { + srcString.Delete(0); + int index = ParseStringToUInt32(srcString, stream); + if (index == 0) + return E_INVALIDARG; + srcString.Delete(0, index); + } + return S_OK; +} + +static HRESULT GetBindInfo(UString &srcString, CBind &bind) +{ + RINOK(GetBindInfoPart(srcString, bind.OutCoder, bind.OutStream)); + if (srcString[0] != ':') + return E_INVALIDARG; + srcString.Delete(0); + RINOK(GetBindInfoPart(srcString, bind.InCoder, bind.InStream)); + if (!srcString.IsEmpty()) + return E_INVALIDARG; + return S_OK; +} + +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) +{ + COM_TRY_BEGIN + _binds.Clear(); + BeforeSetProperty(); + + for (int i = 0; i < numProperties; i++) + { + UString name = names[i]; + name.MakeUpper(); + if (name.IsEmpty()) + return E_INVALIDARG; + + const PROPVARIANT &value = values[i]; + + if (name[0] == 'B') + { + name.Delete(0); + CBind bind; + RINOK(GetBindInfo(name, bind)); + _binds.Add(bind); + continue; + } + + RINOK(SetProperty(name, value)); + } + + return S_OK; + COM_TRY_END +} + +}} diff --git a/CPP/7zip/Archive/7z/7zHeader.cpp b/CPP/7zip/Archive/7z/7zHeader.cpp new file mode 100755 index 0000000..d93670c --- /dev/null +++ b/CPP/7zip/Archive/7z/7zHeader.cpp @@ -0,0 +1,14 @@ +// 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 + +}} diff --git a/CPP/7zip/Archive/7z/7zHeader.h b/CPP/7zip/Archive/7z/7zHeader.h new file mode 100755 index 0000000..57f455b --- /dev/null +++ b/CPP/7zip/Archive/7z/7zHeader.h @@ -0,0 +1,97 @@ +// 7z/7zHeader.h + +#ifndef __7Z_HEADER_H +#define __7Z_HEADER_H + +#include "../../../Common/Types.h" + +namespace NArchive { +namespace N7z { + +const int 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, + kWinAttributes, + kComment, + + kEncodedHeader, + + kStartPos, + kDummy + }; +} + +}} + +#endif diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp new file mode 100755 index 0000000..f418bb1 --- /dev/null +++ b/CPP/7zip/Archive/7z/7zIn.cpp @@ -0,0 +1,1276 @@ +// 7zIn.cpp + +#include "StdAfx.h" + +#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 + +namespace NArchive { +namespace N7z { + +static void BoolVector_Fill_False(CBoolVector &v, int size) +{ + v.Clear(); + v.Reserve(size); + for (int i = 0; i < size; i++) + v.Add(false); +} + +static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index) +{ + if (index >= (UInt32)v.Size()) + return true; + bool res = v[index]; + v[index] = true; + return res; +} + +bool CFolder::CheckStructure() const +{ + const int kNumCodersMax = sizeof(UInt32) * 8; // don't change it + const int kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax + const int kNumBindsMax = 32; + + if (Coders.Size() > kNumCodersMax || BindPairs.Size() > kNumBindsMax) + return false; + + { + CBoolVector v; + BoolVector_Fill_False(v, BindPairs.Size() + PackStreams.Size()); + + int i; + for (i = 0; i < BindPairs.Size(); i++) + if (BoolVector_GetAndSet(v, BindPairs[i].InIndex)) + return false; + for (i = 0; i < PackStreams.Size(); i++) + if (BoolVector_GetAndSet(v, PackStreams[i])) + return false; + + BoolVector_Fill_False(v, UnpackSizes.Size()); + for (i = 0; i < BindPairs.Size(); i++) + if (BoolVector_GetAndSet(v, BindPairs[i].OutIndex)) + return false; + } + + UInt32 mask[kMaskSize]; + int i; + for (i = 0; i < kMaskSize; i++) + mask[i] = 0; + + { + CIntVector inStreamToCoder, outStreamToCoder; + for (i = 0; i < Coders.Size(); i++) + { + CNum j; + const CCoderInfo &coder = Coders[i]; + for (j = 0; j < coder.NumInStreams; j++) + inStreamToCoder.Add(i); + for (j = 0; j < coder.NumOutStreams; j++) + outStreamToCoder.Add(i); + } + + for (i = 0; i < BindPairs.Size(); i++) + { + const CBindPair &bp = BindPairs[i]; + mask[inStreamToCoder[bp.InIndex]] |= (1 << outStreamToCoder[bp.OutIndex]); + } + } + + for (i = 0; i < kMaskSize; i++) + for (int j = 0; j < kMaskSize; j++) + if (((1 << j) & mask[i]) != 0) + mask[i] |= mask[j]; + + for (i = 0; i < kMaskSize; i++) + if (((1 << i) & mask[i]) != 0) + return false; + + return true; +} + +class CInArchiveException {}; + +static void ThrowException() { throw CInArchiveException(); } +static inline void ThrowEndOfData() { ThrowException(); } +static inline void ThrowUnsupported() { ThrowException(); } +static inline void ThrowIncorrect() { ThrowException(); } +static inline void ThrowUnsupportedVersion() { ThrowException(); } + +/* +class CInArchiveException +{ +public: + enum CCauseType + { + kUnsupportedVersion = 0, + kUnsupported, + kIncorrect, + kEndOfData + } Cause; + CInArchiveException(CCauseType cause): Cause(cause) {}; +}; + +static void ThrowException(CInArchiveException::CCauseType c) { throw CInArchiveException(c); } +static void ThrowEndOfData() { ThrowException(CInArchiveException::kEndOfData); } +static void ThrowUnsupported() { ThrowException(CInArchiveException::kUnsupported); } +static void ThrowIncorrect() { ThrowException(CInArchiveException::kIncorrect); } +static void ThrowUnsupportedVersion() { ThrowException(CInArchiveException::kUnsupportedVersion); } +*/ + +class CStreamSwitch +{ + CInArchive *_archive; + bool _needRemove; +public: + CStreamSwitch(): _needRemove(false) {} + ~CStreamSwitch() { Remove(); } + void Remove(); + void Set(CInArchive *archive, const Byte *data, size_t size); + void Set(CInArchive *archive, const CByteBuffer &byteBuffer); + void Set(CInArchive *archive, const CObjectVector *dataVector); +}; + +void CStreamSwitch::Remove() +{ + if (_needRemove) + { + _archive->DeleteByteStream(); + _needRemove = false; + } +} + +void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size) +{ + Remove(); + _archive = archive; + _archive->AddByteStream(data, size); + _needRemove = true; +} + +void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer) +{ + Set(archive, byteBuffer, byteBuffer.GetCapacity()); +} + +void CStreamSwitch::Set(CInArchive *archive, const CObjectVector *dataVector) +{ + Remove(); + Byte external = archive->ReadByte(); + if (external != 0) + { + int dataIndex = (int)archive->ReadNum(); + if (dataIndex < 0 || dataIndex >= dataVector->Size()) + ThrowIncorrect(); + Set(archive, (*dataVector)[dataIndex]); + } +} + +Byte CInByte2::ReadByte() +{ + if (_pos >= _size) + ThrowEndOfData(); + return _buffer[_pos++]; +} + +void CInByte2::ReadBytes(Byte *data, size_t size) +{ + if (size > _size - _pos) + ThrowEndOfData(); + for (size_t i = 0; i < size; i++) + data[i] = _buffer[_pos++]; +} + +void CInByte2::SkipData(UInt64 size) +{ + if (size > _size - _pos) + ThrowEndOfData(); + _pos += (size_t)size; +} + +void CInByte2::SkipData() +{ + SkipData(ReadNumber()); +} + +UInt64 CInByte2::ReadNumber() +{ + if (_pos >= _size) + ThrowEndOfData(); + Byte firstByte = _buffer[_pos++]; + Byte mask = 0x80; + UInt64 value = 0; + for (int i = 0; i < 8; i++) + { + if ((firstByte & mask) == 0) + { + UInt64 highPart = firstByte & (mask - 1); + value += (highPart << (i * 8)); + return value; + } + if (_pos >= _size) + ThrowEndOfData(); + value |= ((UInt64)_buffer[_pos++] << (8 * i)); + mask >>= 1; + } + return value; +} + +CNum CInByte2::ReadNum() +{ + 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; +} + +void CInByte2::ReadString(UString &s) +{ + const Byte *buf = _buffer + _pos; + size_t rem = (_size - _pos) / 2 * 2; + { + size_t i; + for (i = 0; i < rem; i += 2) + if (buf[i] == 0 && buf[i + 1] == 0) + break; + if (i == rem) + ThrowEndOfData(); + rem = i; + } + int len = (int)(rem / 2); + if (len < 0 || (size_t)len * 2 != rem) + ThrowUnsupported(); + wchar_t *p = s.GetBuffer(len); + int i; + for (i = 0; i < len; i++, buf += 2) + p[i] = (wchar_t)Get16(buf); + s.ReleaseBuffer(len); + _pos += rem + 2; +} + +static inline bool TestSignature(const Byte *p) +{ + for (int i = 0; i < kSignatureSize; i++) + if (p[i] != kSignature[i]) + return false; + return CrcCalc(p + 12, 20) == GetUi32(p + 8); +} + +#ifdef FORMAT_7Z_RECOVERY +static inline bool TestSignature2(const Byte *p) +{ + int i; + for (i = 0; i < kSignatureSize; i++) + if (p[i] != kSignature[i]) + return false; + if (CrcCalc(p + 12, 20) == GetUi32(p + 8)) + return true; + for (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; + + CByteBuffer byteBuffer; + const UInt32 kBufferSize = (1 << 16); + byteBuffer.SetCapacity(kBufferSize); + Byte *buffer = byteBuffer; + UInt32 numPrevBytes = kHeaderSize; + memcpy(buffer, _header, kHeaderSize); + UInt64 curTestPos = _arhiveBeginStreamPosition; + for (;;) + { + if (searchHeaderSizeLimit != NULL) + if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit) + break; + do + { + UInt32 numReadBytes = kBufferSize - numPrevBytes; + UInt32 processedSize; + RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize)); + numPrevBytes += processedSize; + if (processedSize == 0) + return S_FALSE; + } + while (numPrevBytes <= kHeaderSize); + UInt32 numTests = numPrevBytes - kHeaderSize; + for (UInt32 pos = 0; pos < numTests; pos++) + { + for (; buffer[pos] != '7' && pos < numTests; pos++); + if (pos == numTests) + break; + if (TestSignature(buffer + pos)) + { + memcpy(_header, buffer + pos, kHeaderSize); + curTestPos += pos; + _arhiveBeginStreamPosition = curTestPos; + return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL); + } + } + curTestPos += numTests; + numPrevBytes -= numTests; + memmove(buffer, buffer + numTests, numPrevBytes); + } + return S_FALSE; +} + +// 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(FindAndReadSignature(stream, searchHeaderSizeLimit)); + _stream = stream; + return S_OK; +} + +void CInArchive::Close() +{ + _stream.Release(); +} + +void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */) +{ + for (;;) + { + if (ReadID() == NID::kEnd) + break; + SkipData(); + } +} + +void CInArchive::GetNextFolderItem(CFolder &folder) +{ + CNum numCoders = ReadNum(); + + folder.Coders.Clear(); + folder.Coders.Reserve((int)numCoders); + CNum numInStreams = 0; + CNum numOutStreams = 0; + CNum i; + for (i = 0; i < numCoders; i++) + { + folder.Coders.Add(CCoderInfo()); + CCoderInfo &coder = folder.Coders.Back(); + + { + Byte mainByte = ReadByte(); + int idSize = (mainByte & 0xF); + Byte longID[15]; + ReadBytes(longID, idSize); + if (idSize > 8) + ThrowUnsupported(); + UInt64 id = 0; + for (int j = 0; j < idSize; j++) + id |= (UInt64)longID[idSize - 1 - j] << (8 * j); + coder.MethodID = id; + + if ((mainByte & 0x10) != 0) + { + coder.NumInStreams = ReadNum(); + coder.NumOutStreams = ReadNum(); + } + else + { + coder.NumInStreams = 1; + coder.NumOutStreams = 1; + } + if ((mainByte & 0x20) != 0) + { + CNum propsSize = ReadNum(); + coder.Props.SetCapacity((size_t)propsSize); + ReadBytes((Byte *)coder.Props, (size_t)propsSize); + } + if ((mainByte & 0x80) != 0) + ThrowUnsupported(); + } + numInStreams += coder.NumInStreams; + numOutStreams += coder.NumOutStreams; + } + + CNum numBindPairs = numOutStreams - 1; + folder.BindPairs.Clear(); + folder.BindPairs.Reserve(numBindPairs); + for (i = 0; i < numBindPairs; i++) + { + CBindPair bp; + bp.InIndex = ReadNum(); + bp.OutIndex = ReadNum(); + folder.BindPairs.Add(bp); + } + + if (numInStreams < numBindPairs) + ThrowUnsupported(); + CNum numPackStreams = numInStreams - numBindPairs; + folder.PackStreams.Reserve(numPackStreams); + if (numPackStreams == 1) + { + for (i = 0; i < numInStreams; i++) + if (folder.FindBindPairForInStream(i) < 0) + { + folder.PackStreams.Add(i); + break; + } + if (folder.PackStreams.Size() != 1) + ThrowUnsupported(); + } + else + for (i = 0; i < numPackStreams; i++) + folder.PackStreams.Add(ReadNum()); +} + +void CInArchive::WaitAttribute(UInt64 attribute) +{ + for (;;) + { + UInt64 type = ReadID(); + if (type == attribute) + return; + if (type == NID::kEnd) + ThrowIncorrect(); + SkipData(); + } +} + +void CInArchive::ReadHashDigests(int numItems, + CBoolVector &digestsDefined, + CRecordVector &digests) +{ + ReadBoolVector2(numItems, digestsDefined); + digests.Clear(); + digests.Reserve(numItems); + for (int i = 0; i < numItems; i++) + { + UInt32 crc = 0; + if (digestsDefined[i]) + crc = ReadUInt32(); + digests.Add(crc); + } +} + +void CInArchive::ReadPackInfo( + UInt64 &dataOffset, + CRecordVector &packSizes, + CBoolVector &packCRCsDefined, + CRecordVector &packCRCs) +{ + dataOffset = ReadNumber(); + CNum numPackStreams = ReadNum(); + + WaitAttribute(NID::kSize); + packSizes.Clear(); + packSizes.Reserve(numPackStreams); + for (CNum i = 0; i < numPackStreams; i++) + packSizes.Add(ReadNumber()); + + UInt64 type; + for (;;) + { + type = ReadID(); + if (type == NID::kEnd) + break; + if (type == NID::kCRC) + { + ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs); + continue; + } + SkipData(); + } + if (packCRCsDefined.IsEmpty()) + { + BoolVector_Fill_False(packCRCsDefined, numPackStreams); + packCRCs.Reserve(numPackStreams); + packCRCs.Clear(); + for (CNum i = 0; i < numPackStreams; i++) + packCRCs.Add(0); + } +} + +void CInArchive::ReadUnpackInfo( + const CObjectVector *dataVector, + CObjectVector &folders) +{ + WaitAttribute(NID::kFolder); + CNum numFolders = ReadNum(); + + { + CStreamSwitch streamSwitch; + streamSwitch.Set(this, dataVector); + folders.Clear(); + folders.Reserve(numFolders); + for (CNum i = 0; i < numFolders; i++) + { + folders.Add(CFolder()); + GetNextFolderItem(folders.Back()); + } + } + + WaitAttribute(NID::kCodersUnpackSize); + + CNum i; + for (i = 0; i < numFolders; i++) + { + CFolder &folder = folders[i]; + CNum numOutStreams = folder.GetNumOutStreams(); + folder.UnpackSizes.Reserve(numOutStreams); + for (CNum j = 0; j < numOutStreams; j++) + folder.UnpackSizes.Add(ReadNumber()); + } + + for (;;) + { + UInt64 type = ReadID(); + if (type == NID::kEnd) + return; + if (type == NID::kCRC) + { + CBoolVector crcsDefined; + CRecordVector crcs; + ReadHashDigests(numFolders, crcsDefined, crcs); + for (i = 0; i < numFolders; i++) + { + CFolder &folder = folders[i]; + folder.UnpackCRCDefined = crcsDefined[i]; + folder.UnpackCRC = crcs[i]; + } + continue; + } + SkipData(); + } +} + +void CInArchive::ReadSubStreamsInfo( + const CObjectVector &folders, + CRecordVector &numUnpackStreamsInFolders, + CRecordVector &unpackSizes, + CBoolVector &digestsDefined, + CRecordVector &digests) +{ + numUnpackStreamsInFolders.Clear(); + numUnpackStreamsInFolders.Reserve(folders.Size()); + UInt64 type; + for (;;) + { + type = ReadID(); + if (type == NID::kNumUnpackStream) + { + for (int i = 0; i < folders.Size(); i++) + numUnpackStreamsInFolders.Add(ReadNum()); + continue; + } + if (type == NID::kCRC || type == NID::kSize) + break; + if (type == NID::kEnd) + break; + SkipData(); + } + + if (numUnpackStreamsInFolders.IsEmpty()) + for (int i = 0; i < folders.Size(); i++) + numUnpackStreamsInFolders.Add(1); + + int i; + for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) + { + // v3.13 incorrectly worked with empty folders + // v4.07: we check that folder is empty + CNum numSubstreams = numUnpackStreamsInFolders[i]; + if (numSubstreams == 0) + continue; + UInt64 sum = 0; + for (CNum j = 1; j < numSubstreams; j++) + if (type == NID::kSize) + { + UInt64 size = ReadNumber(); + unpackSizes.Add(size); + sum += size; + } + unpackSizes.Add(folders[i].GetUnpackSize() - sum); + } + if (type == NID::kSize) + type = ReadID(); + + int numDigests = 0; + int numDigestsTotal = 0; + for (i = 0; i < folders.Size(); i++) + { + CNum numSubstreams = numUnpackStreamsInFolders[i]; + if (numSubstreams != 1 || !folders[i].UnpackCRCDefined) + numDigests += numSubstreams; + numDigestsTotal += numSubstreams; + } + + for (;;) + { + if (type == NID::kCRC) + { + CBoolVector digestsDefined2; + CRecordVector digests2; + ReadHashDigests(numDigests, digestsDefined2, digests2); + int digestIndex = 0; + for (i = 0; i < folders.Size(); i++) + { + CNum numSubstreams = numUnpackStreamsInFolders[i]; + const CFolder &folder = folders[i]; + if (numSubstreams == 1 && folder.UnpackCRCDefined) + { + digestsDefined.Add(true); + digests.Add(folder.UnpackCRC); + } + else + for (CNum j = 0; j < numSubstreams; j++, digestIndex++) + { + digestsDefined.Add(digestsDefined2[digestIndex]); + digests.Add(digests2[digestIndex]); + } + } + } + else if (type == NID::kEnd) + { + if (digestsDefined.IsEmpty()) + { + BoolVector_Fill_False(digestsDefined, numDigestsTotal); + digests.Clear(); + for (int i = 0; i < numDigestsTotal; i++) + digests.Add(0); + } + return; + } + else + SkipData(); + type = ReadID(); + } +} + +void CInArchive::ReadStreamsInfo( + const CObjectVector *dataVector, + UInt64 &dataOffset, + CRecordVector &packSizes, + CBoolVector &packCRCsDefined, + CRecordVector &packCRCs, + CObjectVector &folders, + CRecordVector &numUnpackStreamsInFolders, + CRecordVector &unpackSizes, + CBoolVector &digestsDefined, + CRecordVector &digests) +{ + for (;;) + { + UInt64 type = ReadID(); + if (type > ((UInt32)1 << 30)) + ThrowIncorrect(); + switch((UInt32)type) + { + case NID::kEnd: + return; + case NID::kPackInfo: + { + ReadPackInfo(dataOffset, packSizes, packCRCsDefined, packCRCs); + break; + } + case NID::kUnpackInfo: + { + ReadUnpackInfo(dataVector, folders); + break; + } + case NID::kSubStreamsInfo: + { + ReadSubStreamsInfo(folders, numUnpackStreamsInFolders, + unpackSizes, digestsDefined, digests); + break; + } + default: + ThrowIncorrect(); + } + } +} + +void CInArchive::ReadBoolVector(int numItems, CBoolVector &v) +{ + v.Clear(); + v.Reserve(numItems); + Byte b = 0; + Byte mask = 0; + for (int i = 0; i < numItems; i++) + { + if (mask == 0) + { + b = ReadByte(); + mask = 0x80; + } + v.Add((b & mask) != 0); + mask >>= 1; + } +} + +void CInArchive::ReadBoolVector2(int numItems, CBoolVector &v) +{ + Byte allAreDefined = ReadByte(); + if (allAreDefined == 0) + { + ReadBoolVector(numItems, v); + return; + } + v.Clear(); + v.Reserve(numItems); + for (int i = 0; i < numItems; i++) + v.Add(true); +} + +void CInArchive::ReadUInt64DefVector(const CObjectVector &dataVector, + CUInt64DefVector &v, int numFiles) +{ + ReadBoolVector2(numFiles, v.Defined); + + CStreamSwitch streamSwitch; + streamSwitch.Set(this, &dataVector); + v.Values.Reserve(numFiles); + + for (int i = 0; i < numFiles; i++) + { + UInt64 t = 0; + if (v.Defined[i]) + t = ReadUInt64(); + v.Values.Add(t); + } +} + +HRESULT CInArchive::ReadAndDecodePackedStreams( + DECL_EXTERNAL_CODECS_LOC_VARS + UInt64 baseOffset, + UInt64 &dataOffset, CObjectVector &dataVector + #ifndef _NO_CRYPTO + , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined + #endif + ) +{ + CRecordVector packSizes; + CBoolVector packCRCsDefined; + CRecordVector packCRCs; + CObjectVector folders; + + CRecordVector numUnpackStreamsInFolders; + CRecordVector unpackSizes; + CBoolVector digestsDefined; + CRecordVector digests; + + ReadStreamsInfo(NULL, + dataOffset, + packSizes, + packCRCsDefined, + packCRCs, + folders, + numUnpackStreamsInFolders, + unpackSizes, + digestsDefined, + digests); + + // db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader; + + CNum packIndex = 0; + CDecoder decoder( + #ifdef _ST_MODE + false + #else + true + #endif + ); + UInt64 dataStartPos = baseOffset + dataOffset; + for (int i = 0; i < folders.Size(); i++) + { + const CFolder &folder = folders[i]; + dataVector.Add(CByteBuffer()); + CByteBuffer &data = dataVector.Back(); + UInt64 unpackSize64 = folder.GetUnpackSize(); + size_t unpackSize = (size_t)unpackSize64; + if (unpackSize != unpackSize64) + ThrowUnsupported(); + data.SetCapacity(unpackSize); + + CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream; + CMyComPtr outStream = outStreamSpec; + outStreamSpec->Init(data, unpackSize); + + HRESULT result = decoder.Decode( + EXTERNAL_CODECS_LOC_VARS + _stream, dataStartPos, + &packSizes[packIndex], folder, outStream, NULL + #ifndef _NO_CRYPTO + , getTextPassword, passwordIsDefined + #endif + #if !defined(_7ZIP_ST) && !defined(_SFX) + , false, 1 + #endif + ); + RINOK(result); + + if (folder.UnpackCRCDefined) + if (CrcCalc(data, unpackSize) != folder.UnpackCRC) + ThrowIncorrect(); + for (int j = 0; j < folder.PackStreams.Size(); j++) + { + UInt64 packSize = packSizes[packIndex++]; + dataStartPos += packSize; + HeadersSize += packSize; + } + } + return S_OK; +} + +HRESULT CInArchive::ReadHeader( + DECL_EXTERNAL_CODECS_LOC_VARS + CArchiveDatabaseEx &db + #ifndef _NO_CRYPTO + , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined + #endif + ) +{ + UInt64 type = ReadID(); + + if (type == NID::kArchiveProperties) + { + ReadArchiveProperties(db.ArchiveInfo); + type = ReadID(); + } + + CObjectVector dataVector; + + if (type == NID::kAdditionalStreamsInfo) + { + HRESULT result = ReadAndDecodePackedStreams( + EXTERNAL_CODECS_LOC_VARS + db.ArchiveInfo.StartPositionAfterHeader, + db.ArchiveInfo.DataStartPosition2, + dataVector + #ifndef _NO_CRYPTO + , getTextPassword, passwordIsDefined + #endif + ); + RINOK(result); + db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader; + type = ReadID(); + } + + CRecordVector unpackSizes; + CBoolVector digestsDefined; + CRecordVector digests; + + if (type == NID::kMainStreamsInfo) + { + ReadStreamsInfo(&dataVector, + db.ArchiveInfo.DataStartPosition, + db.PackSizes, + db.PackCRCsDefined, + db.PackCRCs, + db.Folders, + db.NumUnpackStreamsVector, + unpackSizes, + digestsDefined, + digests); + db.ArchiveInfo.DataStartPosition += db.ArchiveInfo.StartPositionAfterHeader; + type = ReadID(); + } + else + { + for (int i = 0; i < db.Folders.Size(); i++) + { + db.NumUnpackStreamsVector.Add(1); + CFolder &folder = db.Folders[i]; + unpackSizes.Add(folder.GetUnpackSize()); + digestsDefined.Add(folder.UnpackCRCDefined); + digests.Add(folder.UnpackCRC); + } + } + + db.Files.Clear(); + + if (type == NID::kEnd) + return S_OK; + if (type != NID::kFilesInfo) + ThrowIncorrect(); + + CNum numFiles = ReadNum(); + db.Files.Reserve(numFiles); + CNum i; + for (i = 0; i < numFiles; i++) + db.Files.Add(CFileItem()); + + db.ArchiveInfo.FileInfoPopIDs.Add(NID::kSize); + if (!db.PackSizes.IsEmpty()) + db.ArchiveInfo.FileInfoPopIDs.Add(NID::kPackInfo); + if (numFiles > 0 && !digests.IsEmpty()) + db.ArchiveInfo.FileInfoPopIDs.Add(NID::kCRC); + + CBoolVector emptyStreamVector; + BoolVector_Fill_False(emptyStreamVector, (int)numFiles); + CBoolVector emptyFileVector; + CBoolVector antiFileVector; + CNum numEmptyStreams = 0; + + for (;;) + { + UInt64 type = ReadID(); + if (type == NID::kEnd) + break; + UInt64 size = ReadNumber(); + size_t ppp = _inByteBack->_pos; + bool addPropIdToList = true; + bool isKnownType = true; + if (type > ((UInt32)1 << 30)) + isKnownType = false; + else switch((UInt32)type) + { + case NID::kName: + { + CStreamSwitch streamSwitch; + streamSwitch.Set(this, &dataVector); + for (int i = 0; i < db.Files.Size(); i++) + _inByteBack->ReadString(db.Files[i].Name); + break; + } + case NID::kWinAttributes: + { + CBoolVector boolVector; + ReadBoolVector2(db.Files.Size(), boolVector); + CStreamSwitch streamSwitch; + streamSwitch.Set(this, &dataVector); + for (i = 0; i < numFiles; i++) + { + CFileItem &file = db.Files[i]; + file.AttribDefined = boolVector[i]; + if (file.AttribDefined) + file.Attrib = ReadUInt32(); + } + break; + } + case NID::kEmptyStream: + { + ReadBoolVector(numFiles, emptyStreamVector); + for (i = 0; i < (CNum)emptyStreamVector.Size(); i++) + if (emptyStreamVector[i]) + numEmptyStreams++; + + BoolVector_Fill_False(emptyFileVector, numEmptyStreams); + BoolVector_Fill_False(antiFileVector, numEmptyStreams); + + break; + } + case NID::kEmptyFile: ReadBoolVector(numEmptyStreams, emptyFileVector); break; + case NID::kAnti: ReadBoolVector(numEmptyStreams, antiFileVector); break; + case NID::kStartPos: ReadUInt64DefVector(dataVector, db.StartPos, (int)numFiles); break; + case NID::kCTime: ReadUInt64DefVector(dataVector, db.CTime, (int)numFiles); break; + case NID::kATime: ReadUInt64DefVector(dataVector, db.ATime, (int)numFiles); break; + case NID::kMTime: ReadUInt64DefVector(dataVector, db.MTime, (int)numFiles); break; + case NID::kDummy: + { + for (UInt64 j = 0; j < size; j++) + if (ReadByte() != 0) + ThrowIncorrect(); + addPropIdToList = false; + break; + } + default: + addPropIdToList = isKnownType = false; + } + if (isKnownType) + { + if(addPropIdToList) + db.ArchiveInfo.FileInfoPopIDs.Add(type); + } + else + SkipData(size); + bool checkRecordsSize = (db.ArchiveInfo.Version.Major > 0 || + db.ArchiveInfo.Version.Minor > 2); + if (checkRecordsSize && _inByteBack->_pos - ppp != size) + ThrowIncorrect(); + } + + CNum emptyFileIndex = 0; + CNum sizeIndex = 0; + + CNum numAntiItems = 0; + for (i = 0; i < numEmptyStreams; i++) + if (antiFileVector[i]) + numAntiItems++; + + for (i = 0; i < numFiles; i++) + { + CFileItem &file = db.Files[i]; + bool isAnti; + file.HasStream = !emptyStreamVector[i]; + if (file.HasStream) + { + file.IsDir = false; + isAnti = false; + file.Size = unpackSizes[sizeIndex]; + file.Crc = digests[sizeIndex]; + file.CrcDefined = digestsDefined[sizeIndex]; + sizeIndex++; + } + else + { + file.IsDir = !emptyFileVector[emptyFileIndex]; + isAnti = antiFileVector[emptyFileIndex]; + emptyFileIndex++; + file.Size = 0; + file.CrcDefined = false; + } + if (numAntiItems != 0) + db.IsAnti.Add(isAnti); + } + return S_OK; +} + + +void CArchiveDatabaseEx::FillFolderStartPackStream() +{ + FolderStartPackStreamIndex.Clear(); + FolderStartPackStreamIndex.Reserve(Folders.Size()); + CNum startPos = 0; + for (int i = 0; i < Folders.Size(); i++) + { + FolderStartPackStreamIndex.Add(startPos); + startPos += (CNum)Folders[i].PackStreams.Size(); + } +} + +void CArchiveDatabaseEx::FillStartPos() +{ + PackStreamStartPositions.Clear(); + PackStreamStartPositions.Reserve(PackSizes.Size()); + UInt64 startPos = 0; + for (int i = 0; i < PackSizes.Size(); i++) + { + PackStreamStartPositions.Add(startPos); + startPos += PackSizes[i]; + } +} + +void CArchiveDatabaseEx::FillFolderStartFileIndex() +{ + FolderStartFileIndex.Clear(); + FolderStartFileIndex.Reserve(Folders.Size()); + FileIndexToFolderIndexMap.Clear(); + FileIndexToFolderIndexMap.Reserve(Files.Size()); + + int folderIndex = 0; + CNum indexInFolder = 0; + for (int i = 0; i < Files.Size(); i++) + { + const CFileItem &file = Files[i]; + bool emptyStream = !file.HasStream; + if (emptyStream && indexInFolder == 0) + { + FileIndexToFolderIndexMap.Add(kNumNoIndex); + continue; + } + if (indexInFolder == 0) + { + // v3.13 incorrectly worked with empty folders + // v4.07: Loop for skipping empty folders + for (;;) + { + if (folderIndex >= Folders.Size()) + ThrowIncorrect(); + FolderStartFileIndex.Add(i); // check it + if (NumUnpackStreamsVector[folderIndex] != 0) + break; + folderIndex++; + } + } + FileIndexToFolderIndexMap.Add(folderIndex); + if (emptyStream) + continue; + indexInFolder++; + if (indexInFolder >= NumUnpackStreamsVector[folderIndex]) + { + folderIndex++; + indexInFolder = 0; + } + } +} + +HRESULT CInArchive::ReadDatabase2( + DECL_EXTERNAL_CODECS_LOC_VARS + CArchiveDatabaseEx &db + #ifndef _NO_CRYPTO + , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined + #endif + ) +{ + db.Clear(); + db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; + + db.ArchiveInfo.Version.Major = _header[6]; + db.ArchiveInfo.Version.Minor = _header[7]; + + if (db.ArchiveInfo.Version.Major != kMajorVersion) + ThrowUnsupportedVersion(); + + UInt32 crcFromArchive = Get32(_header + 8); + UInt64 nextHeaderOffset = Get64(_header + 0xC); + UInt64 nextHeaderSize = Get64(_header + 0x14); + UInt32 nextHeaderCRC = Get32(_header + 0x1C); + UInt32 crc = CrcCalc(_header + 0xC, 20); + + #ifdef FORMAT_7Z_RECOVERY + if (crcFromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0) + { + UInt64 cur, cur2; + RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur)); + const int kCheckSize = 500; + Byte buf[kCheckSize]; + RINOK(_stream->Seek(0, STREAM_SEEK_END, &cur2)); + int checkSize = kCheckSize; + if (cur2 - cur < kCheckSize) + checkSize = (int)(cur2 - cur); + RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2)); + + RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize)); + + int i; + for (i = (int)checkSize - 2; i >= 0; i--) + if (buf[i] == 0x17 && buf[i + 1] == 0x6 || buf[i] == 0x01 && buf[i + 1] == 0x04) + break; + if (i < 0) + return S_FALSE; + nextHeaderSize = checkSize - i; + nextHeaderOffset = cur2 - cur + i; + nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize); + RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL)); + } + else + #endif + { + if (crc != crcFromArchive) + ThrowIncorrect(); + } + + db.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; + + if (nextHeaderSize == 0) + return S_OK; + + if (nextHeaderSize > (UInt64)0xFFFFFFFF) + return S_FALSE; + + if ((Int64)nextHeaderOffset < 0) + return S_FALSE; + + RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL)); + + CByteBuffer buffer2; + buffer2.SetCapacity((size_t)nextHeaderSize); + + RINOK(ReadStream_FALSE(_stream, buffer2, (size_t)nextHeaderSize)); + HeadersSize += kHeaderSize + nextHeaderSize; + db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize; + + if (CrcCalc(buffer2, (UInt32)nextHeaderSize) != nextHeaderCRC) + ThrowIncorrect(); + + 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.ArchiveInfo.StartPositionAfterHeader, + db.ArchiveInfo.DataStartPosition2, + dataVector + #ifndef _NO_CRYPTO + , getTextPassword, passwordIsDefined + #endif + ); + 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.HeadersSize = HeadersSize; + + return ReadHeader( + EXTERNAL_CODECS_LOC_VARS + db + #ifndef _NO_CRYPTO + , getTextPassword, passwordIsDefined + #endif + ); +} + +HRESULT CInArchive::ReadDatabase( + DECL_EXTERNAL_CODECS_LOC_VARS + CArchiveDatabaseEx &db + #ifndef _NO_CRYPTO + , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined + #endif + ) +{ + try + { + return ReadDatabase2( + EXTERNAL_CODECS_LOC_VARS db + #ifndef _NO_CRYPTO + , getTextPassword, passwordIsDefined + #endif + ); + } + catch(CInArchiveException &) { return S_FALSE; } +} + +}} diff --git a/CPP/7zip/Archive/7z/7zIn.h b/CPP/7zip/Archive/7z/7zIn.h new file mode 100755 index 0000000..b82a020 --- /dev/null +++ b/CPP/7zip/Archive/7z/7zIn.h @@ -0,0 +1,245 @@ +// 7zIn.h + +#ifndef __7Z_IN_H +#define __7Z_IN_H + +#include "../../../Common/MyCom.h" + +#include "../../IPassword.h" +#include "../../IStream.h" + +#include "../../Common/CreateCoder.h" +#include "../../Common/InBuffer.h" + +#include "7zItem.h" + +namespace NArchive { +namespace N7z { + +struct CInArchiveInfo +{ + CArchiveVersion Version; + UInt64 StartPosition; + UInt64 StartPositionAfterHeader; + UInt64 DataStartPosition; + UInt64 DataStartPosition2; + CRecordVector FileInfoPopIDs; + void Clear() + { + FileInfoPopIDs.Clear(); + } +}; + +struct CArchiveDatabaseEx: public CArchiveDatabase +{ + CInArchiveInfo ArchiveInfo; + CRecordVector PackStreamStartPositions; + CRecordVector FolderStartPackStreamIndex; + CRecordVector FolderStartFileIndex; + CRecordVector FileIndexToFolderIndexMap; + + UInt64 HeadersSize; + UInt64 PhySize; + + void Clear() + { + CArchiveDatabase::Clear(); + ArchiveInfo.Clear(); + PackStreamStartPositions.Clear(); + FolderStartPackStreamIndex.Clear(); + FolderStartFileIndex.Clear(); + FileIndexToFolderIndexMap.Clear(); + + HeadersSize = 0; + PhySize = 0; + } + + void FillFolderStartPackStream(); + void FillStartPos(); + void FillFolderStartFileIndex(); + + void Fill() + { + FillFolderStartPackStream(); + FillStartPos(); + FillFolderStartFileIndex(); + } + + UInt64 GetFolderStreamPos(int folderIndex, int indexInFolder) const + { + return ArchiveInfo.DataStartPosition + + PackStreamStartPositions[FolderStartPackStreamIndex[folderIndex] + indexInFolder]; + } + + UInt64 GetFolderFullPackSize(int folderIndex) const + { + CNum packStreamIndex = FolderStartPackStreamIndex[folderIndex]; + const CFolder &folder = Folders[folderIndex]; + UInt64 size = 0; + for (int i = 0; i < folder.PackStreams.Size(); i++) + size += PackSizes[packStreamIndex + i]; + return size; + } + + UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const + { + return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; + } + + UInt64 GetFilePackSize(CNum fileIndex) const + { + CNum folderIndex = FileIndexToFolderIndexMap[fileIndex]; + if (folderIndex != kNumNoIndex) + if (FolderStartFileIndex[folderIndex] == fileIndex) + return GetFolderFullPackSize(folderIndex); + return 0; + } +}; + +class CInByte2 +{ + const Byte *_buffer; + size_t _size; +public: + size_t _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 SkipData(UInt64 size); + void SkipData(); + UInt64 ReadNumber(); + CNum ReadNum(); + UInt32 ReadUInt32(); + UInt64 ReadUInt64(); + void ReadString(UString &s); +}; + +class CStreamSwitch; + +const UInt32 kHeaderSize = 32; + +class CInArchive +{ + friend class CStreamSwitch; + + CMyComPtr _stream; + + CObjectVector _inByteVector; + CInByte2 *_inByteBack; + + UInt64 _arhiveBeginStreamPosition; + + Byte _header[kHeaderSize]; + + UInt64 HeadersSize; + + void AddByteStream(const Byte *buffer, size_t size) + { + _inByteVector.Add(CInByte2()); + _inByteBack = &_inByteVector.Back(); + _inByteBack->Init(buffer, size); + } + + void DeleteByteStream() + { + _inByteVector.DeleteBack(); + if (!_inByteVector.IsEmpty()) + _inByteBack = &_inByteVector.Back(); + } + +private: + 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 WaitAttribute(UInt64 attribute); + + void ReadArchiveProperties(CInArchiveInfo &archiveInfo); + void GetNextFolderItem(CFolder &itemInfo); + void ReadHashDigests(int numItems, + CBoolVector &digestsDefined, CRecordVector &digests); + + void ReadPackInfo( + UInt64 &dataOffset, + CRecordVector &packSizes, + CBoolVector &packCRCsDefined, + CRecordVector &packCRCs); + + void ReadUnpackInfo( + const CObjectVector *dataVector, + CObjectVector &folders); + + void ReadSubStreamsInfo( + const CObjectVector &folders, + CRecordVector &numUnpackStreamsInFolders, + CRecordVector &unpackSizes, + CBoolVector &digestsDefined, + CRecordVector &digests); + + void ReadStreamsInfo( + const CObjectVector *dataVector, + UInt64 &dataOffset, + CRecordVector &packSizes, + CBoolVector &packCRCsDefined, + CRecordVector &packCRCs, + CObjectVector &folders, + CRecordVector &numUnpackStreamsInFolders, + CRecordVector &unpackSizes, + CBoolVector &digestsDefined, + CRecordVector &digests); + + + void ReadBoolVector(int numItems, CBoolVector &v); + void ReadBoolVector2(int numItems, CBoolVector &v); + void ReadUInt64DefVector(const CObjectVector &dataVector, + CUInt64DefVector &v, int numFiles); + HRESULT ReadAndDecodePackedStreams( + DECL_EXTERNAL_CODECS_LOC_VARS + UInt64 baseOffset, UInt64 &dataOffset, + CObjectVector &dataVector + #ifndef _NO_CRYPTO + , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined + #endif + ); + HRESULT ReadHeader( + DECL_EXTERNAL_CODECS_LOC_VARS + CArchiveDatabaseEx &db + #ifndef _NO_CRYPTO + ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined + #endif + ); + HRESULT ReadDatabase2( + DECL_EXTERNAL_CODECS_LOC_VARS + CArchiveDatabaseEx &db + #ifndef _NO_CRYPTO + ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined + #endif + ); +public: + HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive + void Close(); + + HRESULT ReadDatabase( + DECL_EXTERNAL_CODECS_LOC_VARS + CArchiveDatabaseEx &db + #ifndef _NO_CRYPTO + ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined + #endif + ); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/7z/7zItem.h b/CPP/7zip/Archive/7z/7zItem.h new file mode 100755 index 0000000..3b01a8d --- /dev/null +++ b/CPP/7zip/Archive/7z/7zItem.h @@ -0,0 +1,268 @@ +// 7zItem.h + +#ifndef __7Z_ITEM_H +#define __7Z_ITEM_H + +#include "../../../Common/Buffer.h" +#include "../../../Common/MyString.h" + +#include "../../Common/MethodId.h" + +#include "7zHeader.h" + +namespace NArchive { +namespace N7z { + +const UInt64 k_AES = 0x06F10701; + +typedef UInt32 CNum; +const CNum kNumMax = 0x7FFFFFFF; +const CNum kNumNoIndex = 0xFFFFFFFF; + +struct CCoderInfo +{ + CMethodId MethodID; + CByteBuffer Props; + CNum NumInStreams; + CNum NumOutStreams; + bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } +}; + +struct CBindPair +{ + CNum InIndex; + CNum OutIndex; +}; + +struct CFolder +{ + CObjectVector Coders; + CRecordVector BindPairs; + CRecordVector PackStreams; + CRecordVector UnpackSizes; + UInt32 UnpackCRC; + bool UnpackCRCDefined; + + CFolder(): UnpackCRCDefined(false) {} + + UInt64 GetUnpackSize() const // test it + { + if (UnpackSizes.IsEmpty()) + return 0; + for (int i = UnpackSizes.Size() - 1; i >= 0; i--) + if (FindBindPairForOutStream(i) < 0) + return UnpackSizes[i]; + throw 1; + } + + CNum GetNumOutStreams() const + { + CNum result = 0; + for (int i = 0; i < Coders.Size(); i++) + result += Coders[i].NumOutStreams; + return result; + } + + int FindBindPairForInStream(CNum inStreamIndex) const + { + for(int i = 0; i < BindPairs.Size(); i++) + if (BindPairs[i].InIndex == inStreamIndex) + return i; + return -1; + } + int FindBindPairForOutStream(CNum outStreamIndex) const + { + for(int i = 0; i < BindPairs.Size(); i++) + if (BindPairs[i].OutIndex == outStreamIndex) + return i; + return -1; + } + int FindPackStreamArrayIndex(CNum inStreamIndex) const + { + for(int i = 0; i < PackStreams.Size(); i++) + if (PackStreams[i] == inStreamIndex) + return i; + return -1; + } + + bool IsEncrypted() const + { + for (int i = Coders.Size() - 1; i >= 0; i--) + if (Coders[i].MethodID == k_AES) + return true; + return false; + } + + bool CheckStructure() const; +}; + +struct CUInt64DefVector +{ + CRecordVector Values; + CRecordVector Defined; + + void Clear() + { + Values.Clear(); + Defined.Clear(); + } + + void ReserveDown() + { + Values.ReserveDown(); + Values.ReserveDown(); + } + + bool GetItem(int index, UInt64 &value) const + { + if (index < Defined.Size() && Defined[index]) + { + value = Values[index]; + return true; + } + value = 0; + return false; + } + + void SetItem(int index, bool defined, UInt64 value) + { + while (index >= Defined.Size()) + Defined.Add(false); + Defined[index] = defined; + if (!defined) + return; + while (index >= Values.Size()) + Values.Add(0); + Values[index] = value; + } + + bool CheckSize(int size) const { return Defined.Size() == size || Defined.Size() == 0; } +}; + +struct CFileItem +{ + UInt64 Size; + UInt32 Attrib; + UInt32 Crc; + UString Name; + + bool HasStream; // Test it !!! it means that there is + // stream in some folder. It can be empty stream + bool IsDir; + bool CrcDefined; + bool AttribDefined; + + CFileItem(): + HasStream(true), + IsDir(false), + CrcDefined(false), + AttribDefined(false) + {} + void SetAttrib(UInt32 attrib) + { + AttribDefined = true; + Attrib = attrib; + } +}; + +struct CFileItem2 +{ + UInt64 CTime; + UInt64 ATime; + UInt64 MTime; + UInt64 StartPos; + bool CTimeDefined; + bool ATimeDefined; + bool MTimeDefined; + bool StartPosDefined; + bool IsAnti; +}; + +struct CArchiveDatabase +{ + CRecordVector PackSizes; + CRecordVector PackCRCsDefined; + CRecordVector PackCRCs; + CObjectVector Folders; + CRecordVector NumUnpackStreamsVector; + CObjectVector Files; + + CUInt64DefVector CTime; + CUInt64DefVector ATime; + CUInt64DefVector MTime; + CUInt64DefVector StartPos; + CRecordVector IsAnti; + + void Clear() + { + PackSizes.Clear(); + PackCRCsDefined.Clear(); + PackCRCs.Clear(); + Folders.Clear(); + NumUnpackStreamsVector.Clear(); + Files.Clear(); + CTime.Clear(); + ATime.Clear(); + MTime.Clear(); + StartPos.Clear(); + IsAnti.Clear(); + } + + void ReserveDown() + { + PackSizes.ReserveDown(); + PackCRCsDefined.ReserveDown(); + PackCRCs.ReserveDown(); + Folders.ReserveDown(); + NumUnpackStreamsVector.ReserveDown(); + Files.ReserveDown(); + CTime.ReserveDown(); + ATime.ReserveDown(); + MTime.ReserveDown(); + StartPos.ReserveDown(); + IsAnti.ReserveDown(); + } + + bool IsEmpty() const + { + return (PackSizes.IsEmpty() && + PackCRCsDefined.IsEmpty() && + PackCRCs.IsEmpty() && + Folders.IsEmpty() && + NumUnpackStreamsVector.IsEmpty() && + Files.IsEmpty()); + } + + bool CheckNumFiles() const + { + int size = Files.Size(); + return ( + CTime.CheckSize(size) && + ATime.CheckSize(size) && + MTime.CheckSize(size) && + StartPos.CheckSize(size) && + (size == IsAnti.Size() || IsAnti.Size() == 0)); + } + + bool IsSolid() const + { + for (int i = 0; i < NumUnpackStreamsVector.Size(); i++) + if (NumUnpackStreamsVector[i] > 1) + return true; + return false; + } + bool IsItemAnti(int index) const { return (index < IsAnti.Size() && IsAnti[index]); } + void SetItemAnti(int index, bool isAnti) + { + while (index >= IsAnti.Size()) + IsAnti.Add(false); + IsAnti[index] = isAnti; + } + + void GetFile(int index, CFileItem &file, CFileItem2 &file2) const; + void AddFile(const CFileItem &file, const CFileItem2 &file2); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/7z/7zOut.cpp b/CPP/7zip/Archive/7z/7zOut.cpp new file mode 100755 index 0000000..b34a2c9 --- /dev/null +++ b/CPP/7zip/Archive/7z/7zOut.cpp @@ -0,0 +1,866 @@ +// 7zOut.cpp + +#include "StdAfx.h" + +#include "../../../../C/7zCrc.h" + +#include "../../../Common/AutoPtr.h" + +#include "../../Common/StreamObjects.h" + +#include "7zOut.h" + +static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size) +{ + while (size > 0) + { + UInt32 curSize = (UInt32)MyMin(size, (size_t)0xFFFFFFFF); + UInt32 processedSize; + RINOK(stream->Write(data, curSize, &processedSize)); + if (processedSize == 0) + return E_FAIL; + data = (const void *)((const Byte *)data + processedSize); + size -= processedSize; + } + return S_OK; +} + +namespace NArchive { +namespace N7z { + +HRESULT COutArchive::WriteDirect(const void *data, UInt32 size) +{ + return ::WriteBytes(SeqStream, data, size); +} + +HRESULT COutArchive::WriteSignature() +{ + Byte buf[8]; + memcpy(buf, kSignature, kSignatureSize); + buf[kSignatureSize] = kMajorVersion; + buf[kSignatureSize + 1] = 3; + 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 + return Stream->Seek(24, STREAM_SEEK_CUR, NULL); +} + +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()); + int i; + for (i = 0; i < folder.Coders.Size(); i++) + { + const CCoderInfo &coder = folder.Coders[i]; + { + size_t propsSize = coder.Props.GetCapacity(); + + UInt64 id = coder.MethodID; + int idSize; + for (idSize = 1; idSize < sizeof(id); idSize++) + if ((id >> (8 * idSize)) == 0) + break; + BYTE longID[15]; + for (int t = idSize - 1; t >= 0 ; t--, id >>= 8) + longID[t] = (Byte)(id & 0xFF); + Byte b; + b = (Byte)(idSize & 0xF); + bool isComplex = !coder.IsSimpleCoder(); + b |= (isComplex ? 0x10 : 0); + b |= ((propsSize != 0) ? 0x20 : 0 ); + WriteByte(b); + WriteBytes(longID, idSize); + if (isComplex) + { + WriteNumber(coder.NumInStreams); + WriteNumber(coder.NumOutStreams); + } + if (propsSize == 0) + continue; + WriteNumber(propsSize); + WriteBytes(coder.Props, propsSize); + } + } + for (i = 0; i < folder.BindPairs.Size(); i++) + { + const CBindPair &bindPair = folder.BindPairs[i]; + WriteNumber(bindPair.InIndex); + WriteNumber(bindPair.OutIndex); + } + 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 (int i = 0; i < boolVector.Size(); i++) + { + if (boolVector[i]) + b |= mask; + mask >>= 1; + if (mask == 0) + { + WriteByte(b); + mask = 0x80; + b = 0; + } + } + if (mask != 0x80) + WriteByte(b); +} + + +void COutArchive::WriteHashDigests( + const CRecordVector &digestsDefined, + const CRecordVector &digests) +{ + int numDefined = 0; + int i; + for (i = 0; i < digestsDefined.Size(); i++) + if (digestsDefined[i]) + numDefined++; + if (numDefined == 0) + return; + + WriteByte(NID::kCRC); + if (numDefined == digestsDefined.Size()) + WriteByte(1); + else + { + WriteByte(0); + WriteBoolVector(digestsDefined); + } + for (i = 0; i < digests.Size(); i++) + if (digestsDefined[i]) + WriteUInt32(digests[i]); +} + +void COutArchive::WritePackInfo( + UInt64 dataOffset, + const CRecordVector &packSizes, + const CRecordVector &packCRCsDefined, + const CRecordVector &packCRCs) +{ + if (packSizes.IsEmpty()) + return; + WriteByte(NID::kPackInfo); + WriteNumber(dataOffset); + WriteNumber(packSizes.Size()); + WriteByte(NID::kSize); + for (int i = 0; i < packSizes.Size(); i++) + WriteNumber(packSizes[i]); + + WriteHashDigests(packCRCsDefined, packCRCs); + + WriteByte(NID::kEnd); +} + +void COutArchive::WriteUnpackInfo(const CObjectVector &folders) +{ + if (folders.IsEmpty()) + return; + + WriteByte(NID::kUnpackInfo); + + WriteByte(NID::kFolder); + WriteNumber(folders.Size()); + { + WriteByte(0); + for (int i = 0; i < folders.Size(); i++) + WriteFolder(folders[i]); + } + + WriteByte(NID::kCodersUnpackSize); + int i; + for (i = 0; i < folders.Size(); i++) + { + const CFolder &folder = folders[i]; + for (int j = 0; j < folder.UnpackSizes.Size(); j++) + WriteNumber(folder.UnpackSizes[j]); + } + + CRecordVector unpackCRCsDefined; + CRecordVector unpackCRCs; + for (i = 0; i < folders.Size(); i++) + { + const CFolder &folder = folders[i]; + unpackCRCsDefined.Add(folder.UnpackCRCDefined); + unpackCRCs.Add(folder.UnpackCRC); + } + WriteHashDigests(unpackCRCsDefined, unpackCRCs); + + WriteByte(NID::kEnd); +} + +void COutArchive::WriteSubStreamsInfo( + const CObjectVector &folders, + const CRecordVector &numUnpackStreamsInFolders, + const CRecordVector &unpackSizes, + const CRecordVector &digestsDefined, + const CRecordVector &digests) +{ + WriteByte(NID::kSubStreamsInfo); + + int 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; + } + } + + + bool needFlag = true; + CNum index = 0; + for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) + for (CNum j = 0; j < numUnpackStreamsInFolders[i]; j++) + { + if (j + 1 != numUnpackStreamsInFolders[i]) + { + if (needFlag) + WriteByte(NID::kSize); + needFlag = false; + WriteNumber(unpackSizes[index]); + } + index++; + } + + CRecordVector digestsDefined2; + CRecordVector digests2; + + int digestIndex = 0; + for (i = 0; i < folders.Size(); i++) + { + int numSubStreams = (int)numUnpackStreamsInFolders[i]; + if (numSubStreams == 1 && folders[i].UnpackCRCDefined) + digestIndex++; + else + for (int j = 0; j < numSubStreams; j++, digestIndex++) + { + digestsDefined2.Add(digestsDefined[digestIndex]); + digests2.Add(digests[digestIndex]); + } + } + WriteHashDigests(digestsDefined2, digests2); + WriteByte(NID::kEnd); +} + +void COutArchive::SkipAlign(unsigned /* pos */, unsigned /* alignSize */) +{ + return; +} + +/* +7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field. + +void COutArchive::SkipAlign(unsigned pos, unsigned alignSize) +{ + 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); +} +*/ + +static inline unsigned Bv_GetSizeInBytes(const CBoolVector &v) { return ((unsigned)v.Size() + 7) / 8; } + +void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize) +{ + const unsigned bvSize = (numDefined == v.Size()) ? 0 : Bv_GetSizeInBytes(v); + const UInt64 dataSize = (UInt64)numDefined * itemSize + bvSize + 2; + SkipAlign(3 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), itemSize); + + WriteByte(type); + WriteNumber(dataSize); + if (numDefined == v.Size()) + WriteByte(1); + else + { + WriteByte(0); + WriteBoolVector(v); + } + WriteByte(0); +} + +void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type) +{ + int numDefined = 0; + + int i; + for (i = 0; i < v.Defined.Size(); i++) + if (v.Defined[i]) + numDefined++; + + if (numDefined == 0) + return; + + WriteAlignedBoolHeader(v.Defined, numDefined, type, 8); + + for (i = 0; i < v.Defined.Size(); i++) + if (v.Defined[i]) + WriteUInt64(v.Values[i]); +} + +HRESULT COutArchive::EncodeStream( + DECL_EXTERNAL_CODECS_LOC_VARS + CEncoder &encoder, const CByteBuffer &data, + CRecordVector &packSizes, CObjectVector &folders) +{ + CBufInStream *streamSpec = new CBufInStream; + CMyComPtr stream = streamSpec; + streamSpec->Init(data, data.GetCapacity()); + CFolder folderItem; + folderItem.UnpackCRCDefined = true; + folderItem.UnpackCRC = CrcCalc(data, data.GetCapacity()); + UInt64 dataSize64 = data.GetCapacity(); + RINOK(encoder.Encode( + EXTERNAL_CODECS_LOC_VARS + stream, NULL, &dataSize64, folderItem, SeqStream, packSizes, NULL)) + folders.Add(folderItem); + return S_OK; +} + +void COutArchive::WriteHeader( + const CArchiveDatabase &db, + const CHeaderOptions &headerOptions, + UInt64 &headerOffset) +{ + int i; + + UInt64 packedSize = 0; + for (i = 0; i < db.PackSizes.Size(); i++) + packedSize += db.PackSizes[i]; + + headerOffset = packedSize; + + WriteByte(NID::kHeader); + + // Archive Properties + + if (db.Folders.Size() > 0) + { + WriteByte(NID::kMainStreamsInfo); + WritePackInfo(0, db.PackSizes, + db.PackCRCsDefined, + db.PackCRCs); + + WriteUnpackInfo(db.Folders); + + CRecordVector unpackSizes; + CRecordVector digestsDefined; + CRecordVector digests; + for (i = 0; i < db.Files.Size(); i++) + { + const CFileItem &file = db.Files[i]; + if (!file.HasStream) + continue; + unpackSizes.Add(file.Size); + digestsDefined.Add(file.CrcDefined); + digests.Add(file.Crc); + } + + WriteSubStreamsInfo( + db.Folders, + db.NumUnpackStreamsVector, + unpackSizes, + digestsDefined, + digests); + WriteByte(NID::kEnd); + } + + if (db.Files.IsEmpty()) + { + WriteByte(NID::kEnd); + return; + } + + WriteByte(NID::kFilesInfo); + WriteNumber(db.Files.Size()); + + { + /* ---------- Empty Streams ---------- */ + CBoolVector emptyStreamVector; + emptyStreamVector.Reserve(db.Files.Size()); + int numEmptyStreams = 0; + for (i = 0; i < db.Files.Size(); i++) + if (db.Files[i].HasStream) + emptyStreamVector.Add(false); + else + { + emptyStreamVector.Add(true); + numEmptyStreams++; + } + if (numEmptyStreams > 0) + { + WriteByte(NID::kEmptyStream); + WriteNumber(Bv_GetSizeInBytes(emptyStreamVector)); + WriteBoolVector(emptyStreamVector); + + CBoolVector emptyFileVector, antiVector; + emptyFileVector.Reserve(numEmptyStreams); + antiVector.Reserve(numEmptyStreams); + CNum numEmptyFiles = 0, numAntiItems = 0; + for (i = 0; i < db.Files.Size(); i++) + { + const CFileItem &file = db.Files[i]; + if (!file.HasStream) + { + emptyFileVector.Add(!file.IsDir); + if (!file.IsDir) + numEmptyFiles++; + bool isAnti = db.IsItemAnti(i); + antiVector.Add(isAnti); + if (isAnti) + numAntiItems++; + } + } + + if (numEmptyFiles > 0) + { + WriteByte(NID::kEmptyFile); + WriteNumber(Bv_GetSizeInBytes(emptyFileVector)); + WriteBoolVector(emptyFileVector); + } + + if (numAntiItems > 0) + { + WriteByte(NID::kAnti); + WriteNumber(Bv_GetSizeInBytes(antiVector)); + WriteBoolVector(antiVector); + } + } + } + + + { + /* ---------- Names ---------- */ + + int numDefined = 0; + size_t namesDataSize = 0; + for (int i = 0; i < db.Files.Size(); i++) + { + const UString &name = db.Files[i].Name; + if (!name.IsEmpty()) + numDefined++; + namesDataSize += (name.Length() + 1) * 2; + } + + if (numDefined > 0) + { + namesDataSize++; + SkipAlign(2 + GetBigNumberSize(namesDataSize), 2); + + WriteByte(NID::kName); + WriteNumber(namesDataSize); + WriteByte(0); + for (int i = 0; i < db.Files.Size(); i++) + { + const UString &name = db.Files[i].Name; + for (int t = 0; t <= name.Length(); 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 ---------- */ + CBoolVector boolVector; + boolVector.Reserve(db.Files.Size()); + int numDefined = 0; + for (i = 0; i < db.Files.Size(); i++) + { + bool defined = db.Files[i].AttribDefined; + boolVector.Add(defined); + if (defined) + numDefined++; + } + if (numDefined > 0) + { + WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttributes, 4); + for (i = 0; i < db.Files.Size(); i++) + { + const CFileItem &file = db.Files[i]; + if (file.AttribDefined) + WriteUInt32(file.Attrib); + } + } + } + + WriteByte(NID::kEnd); // for files + WriteByte(NID::kEnd); // for headers +} + +HRESULT COutArchive::WriteDatabase( + DECL_EXTERNAL_CODECS_LOC_VARS + const CArchiveDatabase &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; + buf.SetCapacity(_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; + RINOK(EncodeStream( + EXTERNAL_CODECS_LOC_VARS + encoder, buf, + packSizes, folders)); + + _writeToStream = true; + + if (folders.Size() == 0) + throw 1; + + WriteID(NID::kEncodedHeader); + WritePackInfo(headerOffset, packSizes, + CRecordVector(), CRecordVector()); + WriteUnpackInfo(folders); + WriteByte(NID::kEnd); + for (int i = 0; i < packSizes.Size(); i++) + 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 CArchiveDatabase::GetFile(int index, CFileItem &file, CFileItem2 &file2) const +{ + file = Files[index]; + file2.CTimeDefined = CTime.GetItem(index, file2.CTime); + file2.ATimeDefined = ATime.GetItem(index, file2.ATime); + file2.MTimeDefined = MTime.GetItem(index, file2.MTime); + file2.StartPosDefined = StartPos.GetItem(index, file2.StartPos); + file2.IsAnti = IsItemAnti(index); +} + +void CArchiveDatabase::AddFile(const CFileItem &file, const CFileItem2 &file2) +{ + int 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); + SetItemAnti(index, file2.IsAnti); + Files.Add(file); +} + +}} diff --git a/CPP/7zip/Archive/7z/7zOut.h b/CPP/7zip/Archive/7z/7zOut.h new file mode 100755 index 0000000..bdd465c --- /dev/null +++ b/CPP/7zip/Archive/7z/7zOut.h @@ -0,0 +1,152 @@ +// 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" + +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 > _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) + {} +}; + +class COutArchive +{ + UInt64 _prefixHeaderPos; + + HRESULT WriteDirect(const void *data, UInt32 size); + + UInt64 GetPos() const; + void WriteBytes(const void *data, size_t size); + void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.GetCapacity()); } + 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 WriteHashDigests( + const CRecordVector &digestsDefined, + const CRecordVector &hashDigests); + + void WritePackInfo( + UInt64 dataOffset, + const CRecordVector &packSizes, + const CRecordVector &packCRCsDefined, + const CRecordVector &packCRCs); + + void WriteUnpackInfo(const CObjectVector &folders); + + void WriteSubStreamsInfo( + const CObjectVector &folders, + const CRecordVector &numUnpackStreamsInFolders, + const CRecordVector &unpackSizes, + const CRecordVector &digestsDefined, + const CRecordVector &hashDigests); + + void SkipAlign(unsigned pos, unsigned alignSize); + void WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize); + void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type); + + HRESULT EncodeStream( + DECL_EXTERNAL_CODECS_LOC_VARS + CEncoder &encoder, const CByteBuffer &data, + CRecordVector &packSizes, CObjectVector &folders); + void WriteHeader( + const CArchiveDatabase &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 + + 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 CArchiveDatabase &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/CPP/7zip/Archive/7z/7zProperties.cpp b/CPP/7zip/Archive/7z/7zProperties.cpp new file mode 100755 index 0000000..432da23 --- /dev/null +++ b/CPP/7zip/Archive/7z/7zProperties.cpp @@ -0,0 +1,164 @@ +// 7zProperties.cpp + +#include "StdAfx.h" + +#include "7zProperties.h" +#include "7zHeader.h" +#include "7zHandler.h" + +// #define _MULTI_PACK + +namespace NArchive { +namespace N7z { + +struct CPropMap +{ + UInt64 FilePropID; + STATPROPSTG StatPROPSTG; +}; + +CPropMap kPropMap[] = +{ + { NID::kName, { NULL, kpidPath, VT_BSTR } }, + { NID::kSize, { NULL, kpidSize, VT_UI8 } }, + { NID::kPackInfo, { NULL, kpidPackSize, VT_UI8 } }, + + #ifdef _MULTI_PACK + { 100, { L"Pack0", kpidPackedSize0, VT_UI8 } }, + { 101, { L"Pack1", kpidPackedSize1, VT_UI8 } }, + { 102, { L"Pack2", kpidPackedSize2, VT_UI8 } }, + { 103, { L"Pack3", kpidPackedSize3, VT_UI8 } }, + { 104, { L"Pack4", kpidPackedSize4, VT_UI8 } }, + #endif + + { NID::kCTime, { NULL, kpidCTime, VT_FILETIME } }, + { NID::kMTime, { NULL, kpidMTime, VT_FILETIME } }, + { NID::kATime, { NULL, kpidATime, VT_FILETIME } }, + { NID::kWinAttributes, { NULL, kpidAttrib, VT_UI4 } }, + { NID::kStartPos, { NULL, kpidPosition, VT_UI4 } }, + + { NID::kCRC, { NULL, kpidCRC, VT_UI4 } }, + + { 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 const int kPropMapSize = sizeof(kPropMap) / sizeof(kPropMap[0]); + +static int FindPropInMap(UInt64 filePropID) +{ + for (int i = 0; i < kPropMapSize; i++) + if (kPropMap[i].FilePropID == filePropID) + return i; + return -1; +} + +static void CopyOneItem(CRecordVector &src, + CRecordVector &dest, UInt32 item) +{ + for (int i = 0; i < src.Size(); i++) + if (src[i] == item) + { + dest.Add(item); + src.Delete(i); + return; + } +} + +static void RemoveOneItem(CRecordVector &src, UInt32 item) +{ + for (int i = 0; i < src.Size(); i++) + if (src[i] == item) + { + src.Delete(i); + return; + } +} + +static void InsertToHead(CRecordVector &dest, UInt32 item) +{ + for (int i = 0; i < dest.Size(); i++) + if (dest[i] == item) + { + dest.Delete(i); + break; + } + dest.Insert(0, item); +} + +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.ArchiveInfo.FileInfoPopIDs; + + RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream); + RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile); + + CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kName); + CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kAnti); + CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kSize); + CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kPackInfo); + CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCTime); + CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kMTime); + CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kATime); + CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kWinAttributes); + CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCRC); + CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::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 *numProperties) +{ + *numProperties = _fileInfoPopIDs.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) +{ + if ((int)index >= _fileInfoPopIDs.Size()) + return E_INVALIDARG; + int indexInMap = FindPropInMap(_fileInfoPopIDs[index]); + if (indexInMap == -1) + return E_INVALIDARG; + const STATPROPSTG &srcItem = kPropMap[indexInMap].StatPROPSTG; + *propID = srcItem.propid; + *varType = srcItem.vt; + *name = 0; + return S_OK; +} + +}} diff --git a/CPP/7zip/Archive/7z/7zProperties.h b/CPP/7zip/Archive/7z/7zProperties.h new file mode 100755 index 0000000..7b78130 --- /dev/null +++ b/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/CPP/7zip/Archive/7z/7zRegister.cpp b/CPP/7zip/Archive/7z/7zRegister.cpp new file mode 100755 index 0000000..ac3d133 --- /dev/null +++ b/CPP/7zip/Archive/7z/7zRegister.cpp @@ -0,0 +1,18 @@ +// 7zRegister.cpp + +#include "StdAfx.h" + +#include "../../Common/RegisterArc.h" + +#include "7zHandler.h" +static IInArchive *CreateArc() { return new NArchive::N7z::CHandler; } +#ifndef EXTRACT_ONLY +static IOutArchive *CreateArcOut() { return new NArchive::N7z::CHandler; } +#else +#define CreateArcOut 0 +#endif + +static CArcInfo g_ArcInfo = + { L"7z", L"7z", 0, 7, {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}, 6, false, CreateArc, CreateArcOut }; + +REGISTER_ARC(7z) diff --git a/CPP/7zip/Archive/7z/7zSpecStream.cpp b/CPP/7zip/Archive/7z/7zSpecStream.cpp new file mode 100755 index 0000000..58f2ec4 --- /dev/null +++ b/CPP/7zip/Archive/7z/7zSpecStream.cpp @@ -0,0 +1,24 @@ +// 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 != 0) + *processedSize = realProcessedSize; + return result; +} + +STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize( + UInt64 subStream, UInt64 *value) +{ + if (_getSubStreamSize == NULL) + return E_NOTIMPL; + return _getSubStreamSize->GetSubStreamSize(subStream, value); +} + diff --git a/CPP/7zip/Archive/7z/7zSpecStream.h b/CPP/7zip/Archive/7z/7zSpecStream.h new file mode 100755 index 0000000..0058ac2 --- /dev/null +++ b/CPP/7zip/Archive/7z/7zSpecStream.h @@ -0,0 +1,35 @@ +// 7zSpecStream.h + +#ifndef __7Z_SPEC_STREAM_H +#define __7Z_SPEC_STREAM_H + +#include "../../IStream.h" +#include "../../ICoder.h" +#include "../../../Common/MyCom.h" + +class CSequentialInStreamSizeCount2: + public ISequentialInStream, + public ICompressGetSubStreamSize, + public CMyUnknownImp +{ + CMyComPtr _stream; + CMyComPtr _getSubStreamSize; + UInt64 _size; +public: + void Init(ISequentialInStream *stream) + { + _stream = stream; + _getSubStreamSize = 0; + _stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize); + _size = 0; + } + UInt64 GetSize() const { return _size; } + + MY_UNKNOWN_IMP1(ICompressGetSubStreamSize) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + + STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); +}; + +#endif diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp new file mode 100755 index 0000000..4b4db06 --- /dev/null +++ b/CPP/7zip/Archive/7z/7zUpdate.cpp @@ -0,0 +1,1177 @@ +// 7zUpdate.cpp + +#include "StdAfx.h" + +#include "../../../../C/CpuArch.h" + +#include "../../Common/LimitedStreams.h" +#include "../../Common/ProgressUtils.h" + +#include "../../Common/CreateCoder.h" + +#include "../../Compress/CopyCoder.h" + +#include "../Common/ItemNameUtils.h" +#include "../Common/OutStreamWithCRC.h" + +#include "7zDecode.h" +#include "7zEncode.h" +#include "7zFolderInStream.h" +#include "7zHandler.h" +#include "7zOut.h" +#include "7zUpdate.h" + +namespace NArchive { +namespace N7z { + +static const UInt64 k_LZMA = 0x030101; +static const UInt64 k_BCJ = 0x03030103; +static const UInt64 k_BCJ2 = 0x0303011B; + +static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2"; +static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20; +static const UInt32 kAlgorithmForBCJ2_LZMA = 1; +static const UInt32 kNumFastBytesForBCJ2_LZMA = 64; + +#ifdef MY_CPU_X86_OR_AMD64 +#define USE_86_FILTER +#endif + +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); +} + +static int GetReverseSlashPos(const UString &name) +{ + int slashPos = name.ReverseFind(L'/'); + #ifdef _WIN32 + int slash1Pos = name.ReverseFind(L'\\'); + slashPos = MyMax(slashPos, slash1Pos); + #endif + return slashPos; +} + +int CUpdateItem::GetExtensionPos() const +{ + int slashPos = GetReverseSlashPos(Name); + int dotPos = Name.ReverseFind(L'.'); + if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0)) + return Name.Length(); + return dotPos + 1; +} + +UString CUpdateItem::GetExtension() const +{ + return Name.Mid(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 CompareBindPairs(const CBindPair &b1, const CBindPair &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.BindPairs.Size(); + s2 = f2.BindPairs.Size(); + RINOZ_COMP(s1, s2); + for (i = 0; i < s1; i++) + RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i])); + return 0; +} + +/* +static int CompareFiles(const CFileItem &f1, const CFileItem &f2) +{ + return MyStringCompareNoCase(f1.Name, f2.Name); +} +*/ + +struct CFolderRepack +{ + int FolderIndex; + int Group; + CNum NumCopyFiles; +}; + +static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void *param) +{ + RINOZ_COMP(p1->Group, p2->Group); + int i1 = p1->FolderIndex; + int i2 = p2->FolderIndex; + const CArchiveDatabaseEx &db = *(const CArchiveDatabaseEx *)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]]); + */ +} + +//////////////////////////////////////////////////////////// + +static int CompareEmptyItems(const int *p1, const int *p2, void *param) +{ + const CObjectVector &updateItems = *(const CObjectVector *)param; + const CUpdateItem &u1 = updateItems[*p1]; + const CUpdateItem &u2 = updateItems[*p2]; + 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 = MyStringCompareNoCase(u1.Name, u2.Name); + return -n; + } + if (u1.IsAnti != u2.IsAnti) + return (u1.IsAnti ? 1 : -1); + return MyStringCompareNoCase(u1.Name, u2.Name); +} + +static const char *g_Exts = + " lzma 7z ace arc arj bz bz2 deb lzo lzx gz pak rpm sit tgz tbz tbz2 tgz cab ha lha lzh rar 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 rc java cs pas bas vb cls ctl frm dlg def" + " f77 f f90 f95" + " asm sql manifest dep " + " mak clw csproj vcproj sln dsp dsw " + " class " + " bat cmd" + " xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml" + " awk sed hta js php php3 php4 php5 phptml pl pm py pyo rb sh tcl 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"; + +int GetExtIndex(const char *ext) +{ + int extIndex = 1; + const char *p = g_Exts; + for (;;) + { + char c = *p++; + if (c == 0) + return extIndex; + if (c == ' ') + continue; + int 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; + UInt32 ExtensionPos; + UInt32 NamePos; + int ExtensionIndex; + CRefItem(UInt32 index, const CUpdateItem &ui, bool sortByType): + UpdateItem(&ui), + Index(index), + ExtensionPos(0), + NamePos(0), + ExtensionIndex(0) + { + if (sortByType) + { + int slashPos = GetReverseSlashPos(ui.Name); + NamePos = ((slashPos >= 0) ? (slashPos + 1) : 0); + int dotPos = ui.Name.ReverseFind(L'.'); + if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0)) + ExtensionPos = ui.Name.Length(); + else + { + ExtensionPos = dotPos + 1; + UString us = ui.Name.Mid(ExtensionPos); + if (!us.IsEmpty()) + { + us.MakeLower(); + int i; + AString s; + for (i = 0; i < us.Length(); i++) + { + wchar_t c = us[i]; + if (c >= 0x80) + break; + s += (char)c; + } + if (i == us.Length()) + ExtensionIndex = GetExtIndex(s); + else + ExtensionIndex = 0; + } + } + } + } +}; + +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; + int n; + if (u1.IsDir != u2.IsDir) + return (u1.IsDir) ? 1 : -1; + if (u1.IsDir) + { + if (u1.IsAnti != u2.IsAnti) + return (u1.IsAnti ? 1 : -1); + n = MyStringCompareNoCase(u1.Name, u2.Name); + return -n; + } + bool sortByType = *(bool *)param; + if (sortByType) + { + RINOZ_COMP(a1.ExtensionIndex, a2.ExtensionIndex); + RINOZ(MyStringCompareNoCase(u1.Name + a1.ExtensionPos, u2.Name + a2.ExtensionPos)); + RINOZ(MyStringCompareNoCase(u1.Name + a1.NamePos, u2.Name + 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); + } + return MyStringCompareNoCase(u1.Name, u2.Name); +} + +struct CSolidGroup +{ + CRecordVector Indices; +}; + +static wchar_t *g_ExeExts[] = +{ + L"dll", + L"exe", + L"ocx", + L"sfx", + L"sys" +}; + +static bool IsExeExt(const UString &ext) +{ + for (int i = 0; i < sizeof(g_ExeExts) / sizeof(g_ExeExts[0]); i++) + if (ext.CompareNoCase(g_ExeExts[i]) == 0) + return true; + return false; +} + +#ifdef USE_86_FILTER + +static inline void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &methodResult) +{ + methodResult.Id = methodID; + methodResult.NumInStreams = numInStreams; + methodResult.NumOutStreams = 1; +} + +static void MakeExeMethod(const CCompressionMethodMode &method, + bool bcj2Filter, CCompressionMethodMode &exeMethod) +{ + exeMethod = method; + if (bcj2Filter) + { + CMethodFull methodFull; + GetMethodFull(k_BCJ2, 4, methodFull); + exeMethod.Methods.Insert(0, methodFull); + GetMethodFull(k_LZMA, 1, methodFull); + { + CProp prop; + prop.Id = NCoderPropID::kAlgorithm; + prop.Value = kAlgorithmForBCJ2_LZMA; + methodFull.Props.Add(prop); + } + { + CProp prop; + prop.Id = NCoderPropID::kMatchFinder; + prop.Value = kMatchFinderForBCJ2_LZMA; + methodFull.Props.Add(prop); + } + { + CProp prop; + prop.Id = NCoderPropID::kDictionarySize; + prop.Value = kDictionaryForBCJ2_LZMA; + methodFull.Props.Add(prop); + } + { + CProp prop; + prop.Id = NCoderPropID::kNumFastBytes; + prop.Value = kNumFastBytesForBCJ2_LZMA; + methodFull.Props.Add(prop); + } + { + CProp prop; + prop.Id = NCoderPropID::kNumThreads; + prop.Value = (UInt32)1; + methodFull.Props.Add(prop); + } + + exeMethod.Methods.Add(methodFull); + exeMethod.Methods.Add(methodFull); + CBind bind; + + bind.OutCoder = 0; + bind.InStream = 0; + + bind.InCoder = 1; + bind.OutStream = 0; + exeMethod.Binds.Add(bind); + + bind.InCoder = 2; + bind.OutStream = 1; + exeMethod.Binds.Add(bind); + + bind.InCoder = 3; + bind.OutStream = 2; + exeMethod.Binds.Add(bind); + } + else + { + CMethodFull methodFull; + GetMethodFull(k_BCJ, 1, methodFull); + exeMethod.Methods.Insert(0, methodFull); + CBind bind; + bind.OutCoder = 0; + bind.InStream = 0; + bind.InCoder = 1; + bind.OutStream = 0; + exeMethod.Binds.Add(bind); + } +} + +#endif + +static void FromUpdateItemToFileItem(const CUpdateItem &ui, + CFileItem &file, CFileItem2 &file2) +{ + file.Name = NItemName::MakeLegalName(ui.Name); + if (ui.AttribDefined) + file.SetAttrib(ui.Attrib); + + 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.StartPosDefined = false; + + file.Size = ui.Size; + file.IsDir = ui.IsDir; + file.HasStream = ui.HasStream(); +} + +class CFolderOutStream2: + public ISequentialOutStream, + public CMyUnknownImp +{ + COutStreamWithCRC *_crcStreamSpec; + CMyComPtr _crcStream; + const CArchiveDatabaseEx *_db; + const CBoolVector *_extractStatuses; + CMyComPtr _outStream; + UInt32 _startIndex; + int _currentIndex; + bool _fileIsOpen; + UInt64 _rem; + + void OpenFile(); + void CloseFile(); + HRESULT CloseFileAndSetResult(); + HRESULT ProcessEmptyFiles(); +public: + MY_UNKNOWN_IMP + + CFolderOutStream2() + { + _crcStreamSpec = new COutStreamWithCRC; + _crcStream = _crcStreamSpec; + } + + HRESULT Init(const CArchiveDatabaseEx *db, UInt32 startIndex, + const CBoolVector *extractStatuses, ISequentialOutStream *outStream); + void ReleaseOutStream(); + HRESULT CheckFinishedState() const { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; } + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + +HRESULT CFolderOutStream2::Init(const CArchiveDatabaseEx *db, UInt32 startIndex, + const CBoolVector *extractStatuses, ISequentialOutStream *outStream) +{ + _db = db; + _startIndex = startIndex; + _extractStatuses = extractStatuses; + _outStream = outStream; + + _currentIndex = 0; + _fileIsOpen = false; + return ProcessEmptyFiles(); +} + +void CFolderOutStream2::ReleaseOutStream() +{ + _outStream.Release(); + _crcStreamSpec->ReleaseStream(); +} + +void CFolderOutStream2::OpenFile() +{ + _crcStreamSpec->SetStream((*_extractStatuses)[_currentIndex] ? _outStream : NULL); + _crcStreamSpec->Init(true); + _fileIsOpen = true; + _rem = _db->Files[_startIndex + _currentIndex].Size; +} + +void CFolderOutStream2::CloseFile() +{ + _crcStreamSpec->ReleaseStream(); + _fileIsOpen = false; + _currentIndex++; +} + +HRESULT CFolderOutStream2::CloseFileAndSetResult() +{ + const CFileItem &file = _db->Files[_startIndex + _currentIndex]; + CloseFile(); + return (file.IsDir || !file.CrcDefined || file.Crc == _crcStreamSpec->GetCRC()) ? S_OK: S_FALSE; +} + +HRESULT CFolderOutStream2::ProcessEmptyFiles() +{ + while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0) + { + OpenFile(); + RINOK(CloseFileAndSetResult()); + } + return S_OK; +} + +STDMETHODIMP CFolderOutStream2::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != NULL) + *processedSize = 0; + while (size != 0) + { + if (_fileIsOpen) + { + UInt32 cur = size < _rem ? size : (UInt32)_rem; + RINOK(_crcStream->Write(data, cur, &cur)); + if (cur == 0) + break; + data = (const Byte *)data + cur; + size -= cur; + _rem -= cur; + if (processedSize != NULL) + *processedSize += cur; + if (_rem == 0) + { + RINOK(CloseFileAndSetResult()); + RINOK(ProcessEmptyFiles()); + continue; + } + } + else + { + RINOK(ProcessEmptyFiles()); + if (_currentIndex == _extractStatuses->Size()) + { + // we don't support partial extracting + return E_FAIL; + } + OpenFile(); + } + } + return S_OK; +} + +class CThreadDecoder: public CVirtThread +{ +public: + HRESULT Result; + CMyComPtr InStream; + + CFolderOutStream2 *FosSpec; + CMyComPtr Fos; + + UInt64 StartPos; + const UInt64 *PackSizes; + const CFolder *Folder; + #ifndef _NO_CRYPTO + CMyComPtr GetTextPassword; + #endif + + DECL_EXTERNAL_CODECS_VARS + CDecoder Decoder; + + #ifndef _7ZIP_ST + bool MtMode; + UInt32 NumThreads; + #endif + + CThreadDecoder(): + Decoder(true) + { + #ifndef _7ZIP_ST + MtMode = false; + NumThreads = 1; + #endif + FosSpec = new CFolderOutStream2; + Fos = FosSpec; + Result = E_FAIL; + } + virtual void Execute(); +}; + +void CThreadDecoder::Execute() +{ + try + { + #ifndef _NO_CRYPTO + bool passwordIsDefined; + #endif + Result = Decoder.Decode( + EXTERNAL_CODECS_VARS + InStream, + StartPos, + PackSizes, + *Folder, + Fos, + NULL + #ifndef _NO_CRYPTO + , GetTextPassword, passwordIsDefined + #endif + #ifndef _7ZIP_ST + , MtMode, NumThreads + #endif + ); + } + catch(...) + { + Result = E_FAIL; + } + if (Result == S_OK) + Result = FosSpec->CheckFinishedState(); + FosSpec->ReleaseOutStream(); +} + +bool static Is86FilteredFolder(const CFolder &f) +{ + for (int i = 0; i < f.Coders.Size(); i++) + { + CMethodId m = f.Coders[i].MethodID; + if (m == k_BCJ || m == k_BCJ2) + return true; + } + return false; +} + +#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 const int kNumGroupsMax = 4; + +#ifdef USE_86_FILTER +static bool Is86Group(int group) { return (group & 1) != 0; } +#endif +static bool IsEncryptedGroup(int group) { return (group & 2) != 0; } +static int GetGroupIndex(bool encrypted, int bcjFiltered) + { return (encrypted ? 2 : 0) + (bcjFiltered ? 1 : 0); } + +HRESULT Update( + DECL_EXTERNAL_CODECS_LOC_VARS + IInStream *inStream, + const CArchiveDatabaseEx *db, + const CObjectVector &updateItems, + COutArchive &archive, + CArchiveDatabase &newDatabase, + ISequentialOutStream *seqOutStream, + IArchiveUpdateCallback *updateCallback, + const CUpdateOptions &options + #ifndef _NO_CRYPTO + , ICryptoGetTextPassword *getDecoderPassword + #endif + ) +{ + UInt64 numSolidFiles = options.NumSolidFiles; + if (numSolidFiles == 0) + numSolidFiles = 1; + /* + CMyComPtr outStream; + RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream)); + if (!outStream) + return E_NOTIMPL; + */ + + UInt64 startBlockSize = db != 0 ? db->ArchiveInfo.StartPosition: 0; + if (startBlockSize > 0 && !options.RemoveSfxBlock) + { + RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL)); + } + + CRecordVector fileIndexToUpdateIndexMap; + CRecordVector folderRefs; + UInt64 complexity = 0; + UInt64 inSizeForReduce2 = 0; + bool needEncryptedRepack = false; + if (db != 0) + { + fileIndexToUpdateIndexMap.Reserve(db->Files.Size()); + int i; + for (i = 0; i < db->Files.Size(); i++) + fileIndexToUpdateIndexMap.Add(-1); + + for (i = 0; i < updateItems.Size(); i++) + { + int index = updateItems[i].IndexInArchive; + if (index != -1) + fileIndexToUpdateIndexMap[index] = i; + } + + for (i = 0; i < db->Folders.Size(); 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; + const CFolder &f = db->Folders[i]; + bool isEncrypted = f.IsEncrypted(); + rep.Group = GetGroupIndex(isEncrypted, Is86FilteredFolder(f)); + folderRefs.Add(rep); + if (numCopyItems == numUnpackStreams) + complexity += db->GetFolderFullPackSize(i); + else + { + complexity += repackSize; + if (repackSize > inSizeForReduce2) + inSizeForReduce2 = repackSize; + if (isEncrypted) + needEncryptedRepack = true; + } + } + folderRefs.Sort(CompareFolderRepacks, (void *)db); + } + + UInt64 inSizeForReduce = 0; + int i; + for (i = 0; i < updateItems.Size(); i++) + { + const CUpdateItem &ui = updateItems[i]; + if (ui.NewData) + { + complexity += ui.Size; + if (numSolidFiles != 1) + inSizeForReduce += ui.Size; + else if (ui.Size > inSizeForReduce) + inSizeForReduce = ui.Size; + } + } + + if (inSizeForReduce2 > inSizeForReduce) + inSizeForReduce = inSizeForReduce2; + + const UInt32 kMinReduceSize = (1 << 16); + if (inSizeForReduce < kMinReduceSize) + inSizeForReduce = kMinReduceSize; + + RINOK(updateCallback->SetTotal(complexity)); + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(updateCallback, true); + + CThreadDecoder threadDecoder; + if (!folderRefs.IsEmpty()) + { + #ifdef EXTERNAL_CODECS + threadDecoder._codecsInfo = codecsInfo; + threadDecoder._externalCodecs = *externalCodecs; + #endif + RINOK(threadDecoder.Create()); + } + + CObjectVector groups; + for (i = 0; i < kNumGroupsMax; i++) + groups.Add(CSolidGroup()); + + { + // ---------- Split files to 2 groups ---------- + + bool useFilters = options.UseFilters; + const CCompressionMethodMode &method = *options.Method; + if (method.Methods.Size() != 1 || method.Binds.Size() != 0) + useFilters = false; + for (i = 0; i < updateItems.Size(); i++) + { + const CUpdateItem &ui = updateItems[i]; + if (!ui.NewData || !ui.HasStream()) + continue; + bool filteredGroup = false; + if (useFilters) + { + int dotPos = ui.Name.ReverseFind(L'.'); + if (dotPos >= 0) + filteredGroup = IsExeExt(ui.Name.Mid(dotPos + 1)); + } + groups[GetGroupIndex(method.PasswordIsDefined, filteredGroup)].Indices.Add(i); + } + } + + #ifndef _NO_CRYPTO + + CCryptoGetTextPassword *getPasswordSpec = NULL; + if (needEncryptedRepack) + { + getPasswordSpec = new CCryptoGetTextPassword; + threadDecoder.GetTextPassword = getPasswordSpec; + + if (options.Method->PasswordIsDefined) + getPasswordSpec->Password = options.Method->Password; + else + { + if (!getDecoderPassword) + return E_NOTIMPL; + CMyComBSTR password; + RINOK(getDecoderPassword->CryptoGetTextPassword(&password)); + getPasswordSpec->Password = password; + } + } + + #endif + + // ---------- Compress ---------- + + RINOK(archive.Create(seqOutStream, false)); + RINOK(archive.SkipPrefixArchiveHeader()); + + int folderRefIndex = 0; + lps->ProgressOffset = 0; + + for (int groupIndex = 0; groupIndex < kNumGroupsMax; groupIndex++) + { + const CSolidGroup &group = groups[groupIndex]; + + CCompressionMethodMode method; + #ifdef USE_86_FILTER + if (Is86Group(groupIndex)) + MakeExeMethod(*options.Method, options.MaxFilter, method); + else + #endif + method = *options.Method; + + if (IsEncryptedGroup(groupIndex)) + { + 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); + + for (; folderRefIndex < folderRefs.Size(); folderRefIndex++) + { + const CFolderRepack &rep = folderRefs[folderRefIndex]; + if (rep.Group != groupIndex) + break; + int folderIndex = rep.FolderIndex; + + if (rep.NumCopyFiles == db->NumUnpackStreamsVector[folderIndex]) + { + UInt64 packSize = db->GetFolderFullPackSize(folderIndex); + RINOK(WriteRange(inStream, archive.SeqStream, + db->GetFolderStreamPos(folderIndex, 0), packSize, progress)); + lps->ProgressOffset += packSize; + + const CFolder &folder = db->Folders[folderIndex]; + CNum startIndex = db->FolderStartPackStreamIndex[folderIndex]; + for (int j = 0; j < folder.PackStreams.Size(); j++) + { + newDatabase.PackSizes.Add(db->PackSizes[startIndex + j]); + // newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]); + // newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]); + } + newDatabase.Folders.Add(folder); + } + else + { + CStreamBinder sb; + RINOK(sb.CreateEvents()); + CMyComPtr sbOutStream; + CMyComPtr sbInStream; + sb.CreateStreams(&sbInStream, &sbOutStream); + CBoolVector extractStatuses; + + CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; + CNum indexInFolder = 0; + + for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) + { + bool needExtract = false; + if (db->Files[fi].HasStream) + { + indexInFolder++; + int updateIndex = fileIndexToUpdateIndexMap[fi]; + if (updateIndex >= 0 && !updateItems[updateIndex].NewData) + needExtract = true; + } + extractStatuses.Add(needExtract); + } + + RINOK(threadDecoder.FosSpec->Init(db, db->FolderStartFileIndex[folderIndex], &extractStatuses, sbOutStream)); + sbOutStream.Release(); + + threadDecoder.InStream = inStream; + threadDecoder.Folder = &db->Folders[folderIndex]; + threadDecoder.StartPos = db->GetFolderStreamPos(folderIndex, 0); + threadDecoder.PackSizes = &db->PackSizes[db->FolderStartPackStreamIndex[folderIndex]]; + + threadDecoder.Start(); + + int startPackIndex = newDatabase.PackSizes.Size(); + CFolder newFolder; + RINOK(encoder.Encode( + EXTERNAL_CODECS_LOC_VARS + sbInStream, NULL, &inSizeForReduce, newFolder, + archive.SeqStream, newDatabase.PackSizes, progress)); + + threadDecoder.WaitFinish(); + + RINOK(threadDecoder.Result); + + for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) + lps->OutSize += newDatabase.PackSizes[startPackIndex]; + lps->InSize += newFolder.GetUnpackSize(); + + newDatabase.Folders.Add(newFolder); + } + + newDatabase.NumUnpackStreamsVector.Add(rep.NumCopyFiles); + + CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; + + CNum indexInFolder = 0; + for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) + { + CFileItem file; + CFileItem2 file2; + db->GetFile(fi, file, file2); + if (file.HasStream) + { + indexInFolder++; + int updateIndex = fileIndexToUpdateIndexMap[fi]; + if (updateIndex >= 0) + { + const CUpdateItem &ui = updateItems[updateIndex]; + if (ui.NewData) + continue; + if (ui.NewProps) + { + CFileItem uf; + FromUpdateItemToFileItem(ui, uf, file2); + uf.Size = file.Size; + uf.Crc = file.Crc; + uf.CrcDefined = file.CrcDefined; + uf.HasStream = file.HasStream; + file = uf; + } + newDatabase.AddFile(file, file2); + } + } + } + } + + int numFiles = group.Indices.Size(); + if (numFiles == 0) + continue; + CRecordVector refItems; + refItems.Reserve(numFiles); + bool sortByType = (numSolidFiles > 1); + for (i = 0; i < numFiles; i++) + refItems.Add(CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType)); + refItems.Sort(CompareUpdateItems, (void *)&sortByType); + + CRecordVector indices; + indices.Reserve(numFiles); + + for (i = 0; i < numFiles; i++) + { + UInt32 index = refItems[i].Index; + indices.Add(index); + /* + const CUpdateItem &ui = updateItems[index]; + CFileItem file; + if (ui.NewProps) + FromUpdateItemToFileItem(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; + int numSubFiles; + UString prevExtension; + 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) + { + UString ext = ui.GetExtension(); + if (numSubFiles == 0) + prevExtension = ext; + else + if (ext.CompareNoCase(prevExtension) != 0) + break; + } + } + if (numSubFiles < 1) + numSubFiles = 1; + + CFolderInStream *inStreamSpec = new CFolderInStream; + CMyComPtr solidInStream(inStreamSpec); + inStreamSpec->Init(updateCallback, &indices[i], numSubFiles); + + CFolder folderItem; + + int startPackIndex = newDatabase.PackSizes.Size(); + RINOK(encoder.Encode( + EXTERNAL_CODECS_LOC_VARS + solidInStream, NULL, &inSizeForReduce, folderItem, + archive.SeqStream, newDatabase.PackSizes, progress)); + + for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) + lps->OutSize += newDatabase.PackSizes[startPackIndex]; + + lps->InSize += folderItem.GetUnpackSize(); + // for () + // newDatabase.PackCRCsDefined.Add(false); + // newDatabase.PackCRCs.Add(0); + + newDatabase.Folders.Add(folderItem); + + CNum numUnpackStreams = 0; + for (int subIndex = 0; subIndex < numSubFiles; subIndex++) + { + const CUpdateItem &ui = updateItems[indices[i + subIndex]]; + CFileItem file; + CFileItem2 file2; + if (ui.NewProps) + FromUpdateItemToFileItem(ui, file, file2); + else + db->GetFile(ui.IndexInArchive, file, file2); + if (file2.IsAnti || file.IsDir) + return E_FAIL; + + /* + CFileItem &file = newDatabase.Files[ + startFileIndexInDatabase + i + subIndex]; + */ + if (!inStreamSpec->Processed[subIndex]) + { + continue; + // file.Name += L".locked"; + } + + file.Crc = inStreamSpec->CRCs[subIndex]; + file.Size = inStreamSpec->Sizes[subIndex]; + if (file.Size != 0) + { + file.CrcDefined = true; + file.HasStream = true; + numUnpackStreams++; + } + else + { + file.CrcDefined = false; + file.HasStream = false; + } + newDatabase.AddFile(file, file2); + } + // numUnpackStreams = 0 is very bad case for locked files + // v3.13 doesn't understand it. + newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams); + i += numSubFiles; + } + } + + if (folderRefIndex != folderRefs.Size()) + return E_FAIL; + + /* + folderRefs.ClearAndFree(); + fileIndexToUpdateIndexMap.ClearAndFree(); + groups.ClearAndFree(); + */ + + { + // ---------- Write Folders & Empty Files ---------- + + CRecordVector emptyRefs; + 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; + 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; + if (ui.NewProps) + FromUpdateItemToFileItem(ui, file, file2); + else + db->GetFile(ui.IndexInArchive, file, file2); + newDatabase.AddFile(file, file2); + } + } + + newDatabase.ReserveDown(); + return S_OK; +} + +}} diff --git a/CPP/7zip/Archive/7z/7zUpdate.h b/CPP/7zip/Archive/7z/7zUpdate.h new file mode 100755 index 0000000..f3dc885 --- /dev/null +++ b/CPP/7zip/Archive/7z/7zUpdate.h @@ -0,0 +1,88 @@ +// 7zUpdate.h + +#ifndef __7Z_UPDATE_H +#define __7Z_UPDATE_H + +#include "7zCompressionMode.h" +#include "7zIn.h" +#include "7zOut.h" + +#include "../IArchive.h" + +namespace NArchive { +namespace N7z { + +struct CUpdateItem +{ + int IndexInArchive; + int IndexInClient; + + UInt64 CTime; + UInt64 ATime; + UInt64 MTime; + + UInt64 Size; + UString Name; + + UInt32 Attrib; + + bool NewData; + bool NewProps; + + bool IsAnti; + bool IsDir; + + bool AttribDefined; + bool CTimeDefined; + bool ATimeDefined; + bool MTimeDefined; + + bool HasStream() const { return !IsDir && !IsAnti && Size != 0; } + + CUpdateItem(): + IsAnti(false), + IsDir(false), + AttribDefined(false), + CTimeDefined(false), + ATimeDefined(false), + MTimeDefined(false) + {} + void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); }; + + int GetExtensionPos() const; + UString GetExtension() const; +}; + +struct CUpdateOptions +{ + const CCompressionMethodMode *Method; + const CCompressionMethodMode *HeaderMethod; + bool UseFilters; + bool MaxFilter; + + CHeaderOptions HeaderOptions; + + UInt64 NumSolidFiles; + UInt64 NumSolidBytes; + bool SolidExtension; + bool RemoveSfxBlock; + bool VolumeMode; +}; + +HRESULT Update( + DECL_EXTERNAL_CODECS_LOC_VARS + IInStream *inStream, + const CArchiveDatabaseEx *db, + const CObjectVector &updateItems, + COutArchive &archive, + CArchiveDatabase &newDatabase, + ISequentialOutStream *seqOutStream, + IArchiveUpdateCallback *updateCallback, + const CUpdateOptions &options + #ifndef _NO_CRYPTO + , ICryptoGetTextPassword *getDecoderPassword + #endif + ); +}} + +#endif diff --git a/CPP/7zip/Archive/7z/StdAfx.cpp b/CPP/7zip/Archive/7z/StdAfx.cpp new file mode 100755 index 0000000..c6d3b1f --- /dev/null +++ b/CPP/7zip/Archive/7z/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/Archive/7z/StdAfx.h b/CPP/7zip/Archive/7z/StdAfx.h new file mode 100755 index 0000000..a4e6173 --- /dev/null +++ b/CPP/7zip/Archive/7z/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" +#include "../../../Common/NewHandler.h" + +#endif diff --git a/CPP/7zip/Archive/7z/makefile b/CPP/7zip/Archive/7z/makefile new file mode 100755 index 0000000..8836989 --- /dev/null +++ b/CPP/7zip/Archive/7z/makefile @@ -0,0 +1,110 @@ +PROG = 7z.dll +DEF_FILE = ../Archive.def +CFLAGS = $(CFLAGS) -I ../../../ \ + -DEXTERNAL_CODECS \ + +AR_OBJS = \ + $O\ArchiveExports.obj \ + $O\DllExports.obj \ + +7Z_OBJS = \ + $O\7zCompressionMode.obj \ + $O\7zDecode.obj \ + $O\7zEncode.obj \ + $O\7zExtract.obj \ + $O\7zFolderInStream.obj \ + $O\7zFolderOutStream.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 \ + +COMMON_OBJS = \ + $O\CRC.obj \ + $O\IntToString.obj \ + $O\NewHandler.obj \ + $O\MyString.obj \ + $O\StringConvert.obj \ + $O\StringToInt.obj \ + $O\MyVector.obj \ + +WIN_OBJS = \ + $O\DLL.obj \ + $O\FileDir.obj \ + $O\FileFind.obj \ + $O\FileIO.obj \ + $O\PropVariant.obj \ + $O\Synchronization.obj \ + $O\System.obj \ + +7ZIP_COMMON_OBJS = \ + $O\CreateCoder.obj \ + $O\InOutTempBuffer.obj \ + $O\FilterCoder.obj \ + $O\LimitedStreams.obj \ + $O\LockedStream.obj \ + $O\MethodId.obj \ + $O\MethodProps.obj \ + $O\OutBuffer.obj \ + $O\ProgressUtils.obj \ + $O\StreamBinder.obj \ + $O\StreamObjects.obj \ + $O\StreamUtils.obj \ + $O\VirtThread.obj \ + +AR_COMMON_OBJS = \ + $O\CoderMixer2.obj \ + $O\CoderMixer2MT.obj \ + $O\CrossThreadProgress.obj \ + $O\HandlerOut.obj \ + $O\InStreamWithCRC.obj \ + $O\ItemNameUtils.obj \ + $O\MultiStream.obj \ + $O\OutStreamWithCRC.obj \ + $O\ParseProperties.obj \ + +C_OBJS = \ + $O\Alloc.obj \ + $O\CpuArch.obj \ + $O\Threads.obj \ + +!include "../../Crc.mak" + +OBJS = \ + $O\StdAfx.obj \ + $(AR_OBJS) \ + $(7Z_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(AR_COMMON_OBJS) \ + $O\CopyCoder.obj \ + $(C_OBJS) \ + $(ASM_OBJS) \ + $O\resource.res + +!include "../../../Build.mak" + +$(AR_OBJS): ../$(*B).cpp + $(COMPL) +$(7Z_OBJS): $(*B).cpp + $(COMPL) +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) +$(AR_COMMON_OBJS): ../Common/$(*B).cpp + $(COMPL) +$O\CopyCoder.obj: ../../Compress/$(*B).cpp + $(COMPL) +$(C_OBJS): ../../../../C/$(*B).c + $(COMPL_O2) + +!include "../../Asm.mak" diff --git a/CPP/7zip/Archive/7z/resource.rc b/CPP/7zip/Archive/7z/resource.rc new file mode 100755 index 0000000..3958af8 --- /dev/null +++ b/CPP/7zip/Archive/7z/resource.rc @@ -0,0 +1,11 @@ +#include "../../MyVersionInfo.rc" + +MY_VERSION_INFO_DLL("7z Plugin", "7z") + +0 ICON "../Icons/7z.ico" + +STRINGTABLE +BEGIN + 100 "7z:0" +END + diff --git a/CPP/7zip/Archive/ApmHandler.cpp b/CPP/7zip/Archive/ApmHandler.cpp new file mode 100755 index 0000000..666f3a4 --- /dev/null +++ b/CPP/7zip/Archive/ApmHandler.cpp @@ -0,0 +1,356 @@ +// ApmHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Common/ComTry.h" +#include "Common/IntToString.h" +#include "Common/MyString.h" + +#include "Windows/PropVariant.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +#define Get16(p) GetBe16(p) +#define Get32(p) GetBe32(p) + +using namespace NWindows; + +namespace NArchive { +namespace NApm { + +struct CItem +{ + UInt32 StartBlock; + UInt32 NumBlocks; + char Name[32]; + char Type[32]; + /* + UInt32 DataStartBlock; + UInt32 NumDataBlocks; + UInt32 Status; + UInt32 BootStartBlock; + UInt32 BootSize; + UInt32 BootAddr; + UInt32 BootEntry; + UInt32 BootChecksum; + char Processor[16]; + */ + + bool Parse(const Byte *p, UInt32 &numBlocksInMap) + { + if (p[0] != 0x50 || p[1] != 0x4D || p[2] != 0 || p[3] != 0) + return false; + numBlocksInMap = Get32(p + 4); + StartBlock = Get32(p + 8); + NumBlocks = Get32(p + 0xC); + memcpy(Name, p + 0x10, 32); + memcpy(Type, p + 0x30, 32); + /* + DataStartBlock = Get32(p + 0x50); + NumDataBlocks = Get32(p + 0x54); + Status = Get32(p + 0x58); + BootStartBlock = Get32(p + 0x5C); + BootSize = Get32(p + 0x60); + BootAddr = Get32(p + 0x64); + if (Get32(p + 0x68) != 0) + return false; + BootEntry = Get32(p + 0x6C); + if (Get32(p + 0x70) != 0) + return false; + BootChecksum = Get32(p + 0x74); + memcpy(Processor, p + 0x78, 16); + */ + return true; + } +}; + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + CRecordVector _items; + + int _blockSizeLog; + UInt32 _numBlocks; + + HRESULT ReadTables(IInStream *stream); + UInt64 BlocksToBytes(UInt32 i) const { return (UInt64)i << _blockSizeLog; } + UInt64 GetItemSize(const CItem &item) { return BlocksToBytes(item.NumBlocks); } +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +static inline int GetLog(UInt32 num) +{ + for (int i = 0; i < 31; i++) + if (((UInt32)1 << i) == num) + return i; + return -1; +} + +HRESULT CHandler::ReadTables(IInStream *stream) +{ + const UInt32 kSectorSize = 512; + Byte buf[kSectorSize]; + { + RINOK(ReadStream_FALSE(stream, buf, kSectorSize)); + if (buf[0] != 0x45 || buf[1] != 0x52) + return S_FALSE; + _blockSizeLog = GetLog(Get16(buf + 2)); + if (_blockSizeLog < 9 || _blockSizeLog > 14) + return S_FALSE; + _numBlocks = Get32(buf + 4); + for (int i = 8; i < 16; i++) + if (buf[i] != 0) + return S_FALSE; + } + + unsigned numSkips = (unsigned)1 << (_blockSizeLog - 9); + for (unsigned j = 1; j < numSkips; j++) + { + RINOK(ReadStream_FALSE(stream, buf, kSectorSize)); + } + + UInt32 numBlocksInMap = 0; + for (unsigned i = 0;;) + { + RINOK(ReadStream_FALSE(stream, buf, kSectorSize)); + + CItem item; + + UInt32 numBlocksInMap2; + if (!item.Parse(buf, numBlocksInMap2)) + return S_FALSE; + if (i == 0) + { + numBlocksInMap = numBlocksInMap2; + if (numBlocksInMap > (1 << 8)) + return S_FALSE; + } + else if (numBlocksInMap2 != numBlocksInMap) + return S_FALSE; + + UInt32 finish = item.StartBlock + item.NumBlocks; + if (finish < item.StartBlock) + return S_FALSE; + _numBlocks = MyMax(_numBlocks, finish); + + _items.Add(item); + for (unsigned j = 1; j < numSkips; j++) + { + RINOK(ReadStream_FALSE(stream, buf, kSectorSize)); + } + if (++i == numBlocksInMap) + break; + } + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *stream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback * /* openArchiveCallback */) +{ + COM_TRY_BEGIN + Close(); + RINOK(ReadTables(stream)); + _stream = stream; + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _items.Clear(); + _stream.Release(); + return S_OK; +} + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidOffset, VT_UI8} +}; + +STATPROPSTG kArcProps[] = +{ + { NULL, kpidClusterSize, VT_UI4}, + { NULL, kpidPhySize, VT_UI8} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +static AString GetString(const char *s) +{ + AString res; + for (int i = 0; i < 32 && s[i] != 0; i++) + res += s[i]; + return res; +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NCOM::CPropVariant prop; + switch(propID) + { + case kpidMainSubfile: + { + int mainIndex = -1; + for (int i = 0; i < _items.Size(); i++) + { + AString s = GetString(_items[i].Type); + if (s != "Apple_Free" && + s != "Apple_partition_map") + { + if (mainIndex >= 0) + { + mainIndex = -1; + break; + } + mainIndex = i; + } + } + if (mainIndex >= 0) + prop = (UInt32)mainIndex; + break; + } + case kpidClusterSize: prop = (UInt32)1 << _blockSizeLog; break; + case kpidPhySize: prop = BlocksToBytes(_numBlocks); break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +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 CItem &item = _items[index]; + switch(propID) + { + case kpidPath: + { + AString s = GetString(item.Name); + if (s.IsEmpty()) + { + char s2[32]; + ConvertUInt32ToString(index, s2); + s = s2; + } + AString type = GetString(item.Type); + if (type == "Apple_HFS") + type = "hfs"; + if (!type.IsEmpty()) + { + s += '.'; + s += type; + } + prop = s; + break; + } + case kpidSize: + case kpidPackSize: + prop = GetItemSize(item); + break; + case kpidOffset: prop = BlocksToBytes(item.StartBlock); break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _items.Size(); + if (numItems == 0) + return S_OK; + UInt64 totalSize = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + totalSize += GetItemSize(_items[allFilesMode ? i : indices[i]]); + extractCallback->SetTotal(totalSize); + + totalSize = 0; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStream(streamSpec); + streamSpec->SetStream(_stream); + + for (i = 0; i < numItems; i++) + { + lps->InSize = totalSize; + lps->OutSize = totalSize; + RINOK(lps->SetCur()); + CMyComPtr outStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + const CItem &item = _items[index]; + + RINOK(extractCallback->GetStream(index, &outStream, askMode)); + UInt64 size = GetItemSize(item); + totalSize += size; + if (!testMode && !outStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + + RINOK(_stream->Seek(BlocksToBytes(item.StartBlock), STREAM_SEEK_SET, NULL)); + streamSpec->Init(size); + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + outStream.Release(); + RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == size ? + NExtract::NOperationResult::kOK: + NExtract::NOperationResult::kDataError)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + const CItem &item = _items[index]; + return CreateLimitedInStream(_stream, BlocksToBytes(item.StartBlock), GetItemSize(item), stream); + COM_TRY_END +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"APM", L"", 0, 0xD4, { 0x50, 0x4D, 0, 0, 0, 0, 0 }, 7, false, CreateArc, 0 }; + +REGISTER_ARC(Apm) + +}} diff --git a/CPP/7zip/Archive/Archive.def b/CPP/7zip/Archive/Archive.def new file mode 100755 index 0000000..839245e --- /dev/null +++ b/CPP/7zip/Archive/Archive.def @@ -0,0 +1,6 @@ +EXPORTS + CreateObject PRIVATE + GetHandlerProperty PRIVATE + GetNumberOfFormats PRIVATE + GetHandlerProperty2 PRIVATE + CreateObject PRIVATE diff --git a/CPP/7zip/Archive/Archive2.def b/CPP/7zip/Archive/Archive2.def new file mode 100755 index 0000000..190fbd8 --- /dev/null +++ b/CPP/7zip/Archive/Archive2.def @@ -0,0 +1,9 @@ +EXPORTS + CreateObject PRIVATE + GetHandlerProperty PRIVATE + GetNumberOfFormats PRIVATE + GetHandlerProperty2 PRIVATE + CreateObject PRIVATE + GetNumberOfMethods PRIVATE + GetMethodProperty PRIVATE + SetLargePageMode PRIVATE diff --git a/CPP/7zip/Archive/ArchiveExports.cpp b/CPP/7zip/Archive/ArchiveExports.cpp new file mode 100755 index 0000000..5d6cf92 --- /dev/null +++ b/CPP/7zip/Archive/ArchiveExports.cpp @@ -0,0 +1,135 @@ +// ArchiveExports.cpp + +#include "StdAfx.h" + +#include "../../Common/ComTry.h" + +#include "../../Windows/PropVariant.h" + +#include "../Common/RegisterArc.h" + +static const unsigned int kNumArcsMax = 48; +static unsigned int g_NumArcs = 0; +static unsigned int g_DefaultArcIndex = 0; +static const CArcInfo *g_Arcs[kNumArcsMax]; +void RegisterArc(const CArcInfo *arcInfo) +{ + if (g_NumArcs < kNumArcsMax) + { + const wchar_t *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, +0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); + +#define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5]) + +static inline HRESULT SetPropString(const char *s, unsigned int 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 SetPropString((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]->ClassId == 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 + if (formatIndex >= g_NumArcs) + return E_INVALIDARG; + const CArcInfo &arc = *g_Arcs[formatIndex]; + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case NArchive::kName: + prop = arc.Name; + break; + case NArchive::kClassID: + { + GUID clsId = CLSID_CArchiveHandler; + CLS_ARC_ID_ITEM(clsId) = arc.ClassId; + return SetPropGUID(clsId, value); + } + case NArchive::kExtension: + if (arc.Ext != 0) + prop = arc.Ext; + break; + case NArchive::kAddExtension: + if (arc.AddExt != 0) + prop = arc.AddExt; + break; + case NArchive::kUpdate: + prop = (bool)(arc.CreateOutArchive != 0); + break; + case NArchive::kKeepName: + prop = arc.KeepName; + break; + case NArchive::kStartSignature: + return SetPropString((const char *)arc.Signature, arc.SignatureSize, value); + } + 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; +} diff --git a/CPP/7zip/Archive/ArjHandler.cpp b/CPP/7zip/Archive/ArjHandler.cpp new file mode 100755 index 0000000..813ef70 --- /dev/null +++ b/CPP/7zip/Archive/ArjHandler.cpp @@ -0,0 +1,798 @@ +// ArjHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Common/ComTry.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamObjects.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/ArjDecoder1.h" +#include "../Compress/ArjDecoder2.h" +#include "../Compress/CopyCoder.h" + +#include "Common/ItemNameUtils.h" +#include "Common/OutStreamWithCRC.h" + +using namespace NWindows; + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) + +namespace NArchive { +namespace NArj { + +const int kBlockSizeMin = 30; +const int kBlockSizeMax = 2600; + +namespace NSignature +{ + const Byte kSig0 = 0x60; + const Byte kSig1 = 0xEA; +} + +namespace NFileHeader +{ + namespace NCompressionMethod + { + enum + { + kStored = 0, + kCompressed1a = 1, + kCompressed1b = 2, + kCompressed1c = 3, + kCompressed2 = 4, + kNoDataNoCRC = 8, + kNoData = 9 + }; + } + + namespace NFileType + { + enum + { + kBinary = 0, + k7BitText = 1, + kArchiveHeader = 2, + kDirectory = 3, + kVolumeLablel = 4, + kChapterLabel = 5 + }; + } + + namespace NFlags + { + const Byte kGarbled = 1; + const Byte kVolume = 4; + const Byte kExtFile = 8; + const Byte kPathSym = 0x10; + const Byte kBackup = 0x20; + } + + namespace NHostOS + { + enum EEnum + { + kMSDOS = 0, // filesystem used by MS-DOS, OS/2, Win32 + // pkarj 2.50 (FAT / VFAT / FAT32 file systems) + kPRIMOS, + kUnix, + kAMIGA, + kMac, + kOS_2, + kAPPLE_GS, + kAtari_ST, + kNext, + kVAX_VMS, + kWIN95 + }; + } +} + +struct CArchiveHeader +{ + // Byte ArchiverVersion; + // Byte ExtractVersion; + Byte HostOS; + // Byte Flags; + // Byte SecuryVersion; + // Byte FileType; + // Byte Reserved; + UInt32 CTime; + UInt32 MTime; + UInt32 ArchiveSize; + // UInt32 SecurityEnvelopeFilePosition; + // UInt16 FilespecPositionInFilename; + // UInt16 LengthOfSecurityEnvelopeSata; + // Byte EncryptionVersion; + // Byte LastChapter; + AString Name; + AString Comment; + + HRESULT Parse(const Byte *p, unsigned size); +}; + +static HRESULT ReadString(const Byte *p, unsigned &size, AString &res) +{ + AString s; + for (unsigned i = 0; i < size;) + { + char c = (char)p[i++]; + if (c == 0) + { + size = i; + res = s; + return S_OK; + } + s += c; + } + return S_FALSE; +} + +HRESULT CArchiveHeader::Parse(const Byte *p, unsigned size) +{ + if (size < kBlockSizeMin) + return S_FALSE; + Byte firstHeaderSize = p[0]; + if (firstHeaderSize > size) + return S_FALSE; + // ArchiverVersion = p[1]; + // ExtractVersion = p[2]; + HostOS = p[3]; + // Flags = p[4]; + // SecuryVersion = p[5]; + if (p[6] != NFileHeader::NFileType::kArchiveHeader) + return S_FALSE; + // Reserved = p[7]; + CTime = Get32(p + 8); + MTime = Get32(p + 12); + ArchiveSize = Get32(p + 16); + // SecurityEnvelopeFilePosition = Get32(p + 20); + // UInt16 filespecPositionInFilename = Get16(p + 24); + // LengthOfSecurityEnvelopeSata = Get16(p + 26); + // EncryptionVersion = p[28]; + // LastChapter = p[29]; + unsigned pos = firstHeaderSize; + unsigned size1 = size - pos; + RINOK(ReadString(p + pos, size1, Name)); + pos += size1; + size1 = size - pos; + RINOK(ReadString(p + pos, size1, Comment)); + pos += size1; + return S_OK; +} + +struct CItem +{ + AString Name; + AString Comment; + + UInt32 MTime; + UInt32 PackSize; + UInt32 Size; + UInt32 FileCRC; + UInt32 SplitPos; + + Byte Version; + Byte ExtractVersion; + Byte HostOS; + Byte Flags; + Byte Method; + Byte FileType; + + // UInt16 FilespecPositionInFilename; + UInt16 FileAccessMode; + // Byte FirstChapter; + // Byte LastChapter; + + UInt64 DataPosition; + + bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kGarbled) != 0; } + bool IsDir() const { return (FileType == NFileHeader::NFileType::kDirectory); } + bool IsSplitAfter() const { return (Flags & NFileHeader::NFlags::kVolume) != 0; } + bool IsSplitBefore() const { return (Flags & NFileHeader::NFlags::kExtFile) != 0; } + UInt32 GetWinAttributes() const + { + UInt32 winAtrributes; + switch(HostOS) + { + case NFileHeader::NHostOS::kMSDOS: + case NFileHeader::NHostOS::kWIN95: + winAtrributes = FileAccessMode; + break; + default: + winAtrributes = 0; + } + if (IsDir()) + winAtrributes |= FILE_ATTRIBUTE_DIRECTORY; + return winAtrributes; + } + + HRESULT Parse(const Byte *p, unsigned size); +}; + +HRESULT CItem::Parse(const Byte *p, unsigned size) +{ + if (size < kBlockSizeMin) + return S_FALSE; + + Byte firstHeaderSize = p[0]; + + Version = p[1]; + ExtractVersion = p[2]; + HostOS = p[3]; + Flags = p[4]; + Method = p[5]; + FileType = p[6]; + // Reserved = p[7]; + MTime = Get32(p + 8); + PackSize = Get32(p + 12); + Size = Get32(p + 16); + FileCRC = Get32(p + 20); + // FilespecPositionInFilename = Get16(p + 24); + FileAccessMode = Get16(p + 26); + // FirstChapter = p[28]; + // FirstChapter = p[29]; + + SplitPos = 0; + if (IsSplitBefore() && firstHeaderSize >= 34) + SplitPos = Get32(p + 30); + + unsigned pos = firstHeaderSize; + unsigned size1 = size - pos; + RINOK(ReadString(p + pos, size1, Name)); + pos += size1; + size1 = size - pos; + RINOK(ReadString(p + pos, size1, Comment)); + pos += size1; + + return S_OK; +} + +struct CInArchiveException +{ + enum CCauseType + { + kUnexpectedEndOfArchive = 0, + kCRCError, + kIncorrectArchive + } + Cause; + CInArchiveException(CCauseType cause): Cause(cause) {}; +}; + +class CInArchive +{ + UInt32 _blockSize; + Byte _block[kBlockSizeMax + 4]; + + HRESULT ReadBlock(bool &filled); + HRESULT ReadSignatureAndBlock(bool &filled); + HRESULT SkipExtendedHeaders(); + + HRESULT SafeReadBytes(void *data, UInt32 size); + +public: + CArchiveHeader Header; + + IInStream *Stream; + IArchiveOpenCallback *Callback; + UInt64 NumFiles; + UInt64 NumBytes; + + HRESULT Open(const UInt64 *searchHeaderSizeLimit); + HRESULT GetNextItem(bool &filled, CItem &item); +}; + +static inline bool TestMarkerCandidate(const Byte *p, unsigned maxSize) +{ + if (p[0] != NSignature::kSig0 || p[1] != NSignature::kSig1) + return false; + UInt32 blockSize = Get16(p + 2); + p += 4; + if (p[6] != NFileHeader::NFileType::kArchiveHeader || + p[0] > blockSize || + maxSize < 2 + 2 + blockSize + 4 || + blockSize < kBlockSizeMin || blockSize > kBlockSizeMax || + p[28] > 8) // EncryptionVersion + return false; + // return (Get32(p + blockSize) == CrcCalc(p, blockSize)); + return true; +} + +static HRESULT FindAndReadMarker(ISequentialInStream *stream, const UInt64 *searchHeaderSizeLimit, UInt64 &position) +{ + position = 0; + + const int kMarkerSizeMin = 2 + 2 + kBlockSizeMin + 4; + const int kMarkerSizeMax = 2 + 2 + kBlockSizeMax + 4; + + CByteBuffer byteBuffer; + const UInt32 kBufSize = 1 << 16; + byteBuffer.SetCapacity(kBufSize); + Byte *buf = byteBuffer; + + size_t processedSize = kMarkerSizeMax; + RINOK(ReadStream(stream, buf, &processedSize)); + if (processedSize < kMarkerSizeMin) + return S_FALSE; + if (TestMarkerCandidate(buf, (unsigned)processedSize)) + return S_OK; + + UInt32 numBytesPrev = (UInt32)processedSize - 1; + memmove(buf, buf + 1, numBytesPrev); + UInt64 curTestPos = 1; + for (;;) + { + if (searchHeaderSizeLimit != NULL) + if (curTestPos > *searchHeaderSizeLimit) + return S_FALSE; + processedSize = kBufSize - numBytesPrev; + RINOK(ReadStream(stream, buf + numBytesPrev, &processedSize)); + UInt32 numBytesInBuffer = numBytesPrev + (UInt32)processedSize; + if (numBytesInBuffer < kMarkerSizeMin) + return S_FALSE; + UInt32 numTests = numBytesInBuffer - kMarkerSizeMin + 1; + UInt32 pos; + for (pos = 0; pos < numTests; pos++) + { + for (; buf[pos] != NSignature::kSig0 && pos < numTests; pos++); + if (pos == numTests) + break; + if (TestMarkerCandidate(buf + pos, numBytesInBuffer - pos)) + { + position = curTestPos + pos; + return S_OK; + } + } + curTestPos += pos; + numBytesPrev = numBytesInBuffer - numTests; + memmove(buf, buf + numTests, numBytesPrev); + } +} + +HRESULT CInArchive::SafeReadBytes(void *data, UInt32 size) +{ + size_t processed = size; + RINOK(ReadStream(Stream, data, &processed)); + if (processed != size) + throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive); + return S_OK; +} + +HRESULT CInArchive::ReadBlock(bool &filled) +{ + filled = false; + Byte buf[2]; + RINOK(SafeReadBytes(buf, 2)); + _blockSize = Get16(buf); + if (_blockSize == 0) + return S_OK; + if (_blockSize > kBlockSizeMax) + throw CInArchiveException(CInArchiveException::kIncorrectArchive); + RINOK(SafeReadBytes(_block, _blockSize + 4)); + NumBytes += _blockSize + 6; + if (Get32(_block + _blockSize) != CrcCalc(_block, _blockSize)) + throw CInArchiveException(CInArchiveException::kCRCError); + filled = true; + return S_OK; +} + +HRESULT CInArchive::ReadSignatureAndBlock(bool &filled) +{ + Byte id[2]; + RINOK(SafeReadBytes(id, 2)); + if (id[0] != NSignature::kSig0 || id[1] != NSignature::kSig1) + throw CInArchiveException(CInArchiveException::kIncorrectArchive); + return ReadBlock(filled); +} + +HRESULT CInArchive::SkipExtendedHeaders() +{ + for (UInt32 i = 0;; i++) + { + bool filled; + RINOK(ReadBlock(filled)); + if (!filled) + return S_OK; + if (Callback && (i & 0xFF) == 0) + RINOK(Callback->SetCompleted(&NumFiles, &NumBytes)); + } +} + +HRESULT CInArchive::Open(const UInt64 *searchHeaderSizeLimit) +{ + UInt64 position = 0; + RINOK(FindAndReadMarker(Stream, searchHeaderSizeLimit, position)); + RINOK(Stream->Seek(position, STREAM_SEEK_SET, NULL)); + bool filled; + RINOK(ReadSignatureAndBlock(filled)); + if (!filled) + return S_FALSE; + RINOK(Header.Parse(_block, _blockSize)); + return SkipExtendedHeaders(); +} + +HRESULT CInArchive::GetNextItem(bool &filled, CItem &item) +{ + RINOK(ReadSignatureAndBlock(filled)); + if (!filled) + return S_OK; + filled = false; + RINOK(item.Parse(_block, _blockSize)); + /* + UInt32 extraData; + if ((header.Flags & NFileHeader::NFlags::kExtFile) != 0) + extraData = GetUi32(_block + pos); + */ + + RINOK(SkipExtendedHeaders()); + filled = true; + return S_OK; +} + +class CHandler: + public IInArchive, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP1(IInArchive) + + INTERFACE_IInArchive(;) + + HRESULT Open2(IInStream *inStream, const UInt64 *maxCheckStartPosition, + IArchiveOpenCallback *callback); +private: + CInArchive _archive; + CObjectVector _items; + CMyComPtr _stream; +}; + +const wchar_t *kHostOS[] = +{ + L"MSDOS", + L"PRIMOS", + L"UNIX", + L"AMIGA", + L"MAC", + L"OS/2", + L"APPLE GS", + L"ATARI ST", + L"NEXT", + L"VAX VMS", + L"WIN95" +}; + +const wchar_t *kUnknownOS = L"Unknown"; + +const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]); + +STATPROPSTG kArcProps[] = +{ + { NULL, kpidName, VT_BSTR}, + { NULL, kpidCTime, VT_BSTR}, + { NULL, kpidMTime, VT_BSTR}, + { NULL, kpidHostOS, VT_BSTR}, + { NULL, kpidComment, VT_BSTR} +}; + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI4}, + { NULL, kpidPosition, VT_UI8}, + { NULL, kpidPackSize, VT_UI4}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidAttrib, VT_UI4}, + { NULL, kpidEncrypted, VT_BOOL}, + { NULL, kpidCRC, VT_UI4}, + { NULL, kpidMethod, VT_UI1}, + { NULL, kpidHostOS, VT_BSTR}, + { NULL, kpidComment, VT_BSTR} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +static void SetTime(UInt32 dosTime, NWindows::NCOM::CPropVariant &prop) +{ + if (dosTime == 0) + return; + FILETIME localFileTime, utc; + if (NTime::DosTimeToFileTime(dosTime, localFileTime)) + { + if (!LocalFileTimeToFileTime(&localFileTime, &utc)) + utc.dwHighDateTime = utc.dwLowDateTime = 0; + } + else + utc.dwHighDateTime = utc.dwLowDateTime = 0; + prop = utc; +} + +static void SetHostOS(Byte hostOS, NWindows::NCOM::CPropVariant &prop) +{ + prop = hostOS < kNumHostOSes ? kHostOS[hostOS] : kUnknownOS; +} + +static void SetUnicodeString(const AString &s, NWindows::NCOM::CPropVariant &prop) +{ + if (!s.IsEmpty()) + prop = MultiByteToUnicodeString(s, CP_OEMCP); +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidName: SetUnicodeString(_archive.Header.Name, prop); break; + case kpidCTime: SetTime(_archive.Header.CTime, prop); break; + case kpidMTime: SetTime(_archive.Header.MTime, prop); break; + case kpidHostOS: SetHostOS(_archive.Header.HostOS, prop); break; + case kpidComment: SetUnicodeString(_archive.Header.Comment, prop); break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _items.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + const CItem &item = _items[index]; + switch(propID) + { + case kpidPath: prop = NItemName::GetOSName(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break; + case kpidIsDir: prop = item.IsDir(); break; + case kpidSize: prop = item.Size; break; + case kpidPackSize: prop = item.PackSize; break; + case kpidPosition: if (item.IsSplitBefore() || item.IsSplitAfter()) prop = (UInt64)item.SplitPos; break; + case kpidAttrib: prop = item.GetWinAttributes(); break; + case kpidEncrypted: prop = item.IsEncrypted(); break; + case kpidCRC: prop = item.FileCRC; break; + case kpidMethod: prop = item.Method; break; + case kpidHostOS: SetHostOS(item.HostOS, prop); break; + case kpidMTime: SetTime(item.MTime, prop); break; + case kpidComment: SetUnicodeString(item.Comment, prop); break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +HRESULT CHandler::Open2(IInStream *inStream, const UInt64 *maxCheckStartPosition, + IArchiveOpenCallback *callback) +{ + Close(); + + UInt64 endPos = 0; + if (callback != NULL) + { + RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos)); + RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); + } + + _archive.Stream = inStream; + _archive.Callback = callback; + _archive.NumFiles = _archive.NumBytes = 0; + + RINOK(_archive.Open(maxCheckStartPosition)); + if (callback != NULL) + RINOK(callback->SetTotal(NULL, &endPos)); + for (;;) + { + CItem item; + bool filled; + + + RINOK(_archive.GetNextItem(filled, item)); + + RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &item.DataPosition)); + + if (!filled) + break; + _items.Add(item); + + if (inStream->Seek(item.PackSize, STREAM_SEEK_CUR, NULL) != S_OK) + throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive); + + _archive.NumFiles = _items.Size(); + _archive.NumBytes = item.DataPosition; + + if (callback != NULL && _items.Size() % 100 == 0) + { + RINOK(callback->SetCompleted(&_archive.NumFiles, &_archive.NumBytes)); + } + } + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *inStream, + const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + HRESULT res; + try + { + res = Open2(inStream, maxCheckStartPosition, callback); + if (res == S_OK) + { + _stream = inStream; + return S_OK; + } + } + catch(const CInArchiveException &) { res = S_FALSE; } + Close(); + return res; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _items.Clear(); + _stream.Release(); + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + UInt64 totalUnpacked = 0, totalPacked = 0; + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _items.Size(); + if (numItems == 0) + return S_OK; + UInt32 i; + for (i = 0; i < numItems; i++) + { + const CItem &item = _items[allFilesMode ? i : indices[i]]; + totalUnpacked += item.Size; + totalPacked += item.PackSize; + } + extractCallback->SetTotal(totalUnpacked); + + totalUnpacked = totalPacked = 0; + UInt64 curUnpacked, curPacked; + + CMyComPtr arj1Decoder; + CMyComPtr arj2Decoder; + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *inStreamSpec = new CLimitedSequentialInStream; + CMyComPtr inStream(inStreamSpec); + inStreamSpec->SetStream(_stream); + + for (i = 0; i < numItems; i++, totalUnpacked += curUnpacked, totalPacked += curPacked) + { + lps->InSize = totalPacked; + lps->OutSize = totalUnpacked; + RINOK(lps->SetCur()); + + curUnpacked = curPacked = 0; + + CMyComPtr realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + const CItem &item = _items[index]; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + if (item.IsDir()) + { + // if (!testMode) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + } + continue; + } + + if (!testMode && !realOutStream) + continue; + + RINOK(extractCallback->PrepareOperation(askMode)); + curUnpacked = item.Size; + curPacked = item.PackSize; + + { + COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; + CMyComPtr outStream(outStreamSpec); + outStreamSpec->SetStream(realOutStream); + realOutStream.Release(); + outStreamSpec->Init(); + + inStreamSpec->Init(item.PackSize); + + UInt64 pos; + _stream->Seek(item.DataPosition, STREAM_SEEK_SET, &pos); + + HRESULT result = S_OK; + Int32 opRes = NExtract::NOperationResult::kOK; + + if (item.IsEncrypted()) + opRes = NExtract::NOperationResult::kUnSupportedMethod; + else + { + switch(item.Method) + { + case NFileHeader::NCompressionMethod::kStored: + { + result = copyCoder->Code(inStream, outStream, NULL, NULL, progress); + if (result == S_OK && copyCoderSpec->TotalSize != item.PackSize) + result = S_FALSE; + break; + } + case NFileHeader::NCompressionMethod::kCompressed1a: + case NFileHeader::NCompressionMethod::kCompressed1b: + case NFileHeader::NCompressionMethod::kCompressed1c: + { + if (!arj1Decoder) + arj1Decoder = new NCompress::NArj::NDecoder1::CCoder; + result = arj1Decoder->Code(inStream, outStream, NULL, &curUnpacked, progress); + break; + } + case NFileHeader::NCompressionMethod::kCompressed2: + { + if (!arj2Decoder) + arj2Decoder = new NCompress::NArj::NDecoder2::CCoder; + result = arj2Decoder->Code(inStream, outStream, NULL, &curUnpacked, progress); + break; + } + default: + opRes = NExtract::NOperationResult::kUnSupportedMethod; + } + } + if (opRes == NExtract::NOperationResult::kOK) + { + if (result == S_FALSE) + opRes = NExtract::NOperationResult::kDataError; + else + { + RINOK(result); + opRes = (outStreamSpec->GetCRC() == item.FileCRC) ? + NExtract::NOperationResult::kOK: + NExtract::NOperationResult::kCRCError; + } + } + outStream.Release(); + RINOK(extractCallback->SetOperationResult(opRes)); + } + } + return S_OK; + COM_TRY_END +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"Arj", L"arj", 0, 4, { 0x60, 0xEA }, 2, false, CreateArc, 0 }; + +REGISTER_ARC(Arj) + +}} diff --git a/CPP/7zip/Archive/Bz2Handler.cpp b/CPP/7zip/Archive/Bz2Handler.cpp new file mode 100755 index 0000000..39cd3b3 --- /dev/null +++ b/CPP/7zip/Archive/Bz2Handler.cpp @@ -0,0 +1,423 @@ +// Bz2Handler.cpp + +#include "StdAfx.h" + +#include "Common/ComTry.h" + +#include "Windows/PropVariant.h" + +#ifndef _7ZIP_ST +#include "../../Windows/System.h" +#endif + +#include "../Common/CreateCoder.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/BZip2Decoder.h" +#include "../Compress/BZip2Encoder.h" +#include "../Compress/CopyCoder.h" + +#include "Common/DummyOutStream.h" +#include "Common/ParseProperties.h" + +using namespace NWindows; + +namespace NArchive { +namespace NBz2 { + +static const UInt32 kNumPassesX1 = 1; +static const UInt32 kNumPassesX7 = 2; +static const UInt32 kNumPassesX9 = 7; + +static const UInt32 kDicSizeX1 = 100000; +static const UInt32 kDicSizeX3 = 500000; +static const UInt32 kDicSizeX5 = 900000; + +class CHandler: + public IInArchive, + public IArchiveOpenSeq, + public IOutArchive, + public ISetProperties, + public CMyUnknownImp +{ + CMyComPtr _stream; + CMyComPtr _seqStream; + UInt64 _packSize; + UInt64 _startPosition; + bool _packSizeDefined; + + UInt32 _level; + UInt32 _dicSize; + UInt32 _numPasses; + #ifndef _7ZIP_ST + UInt32 _numThreads; + #endif + + void InitMethodProperties() + { + _level = 5; + _dicSize = + _numPasses = 0xFFFFFFFF; + #ifndef _7ZIP_ST + _numThreads = NWindows::NSystem::GetNumberOfProcessors();; + #endif + } + +public: + MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties) + + INTERFACE_IInArchive(;) + INTERFACE_IOutArchive(;) + STDMETHOD(OpenSeq)(ISequentialInStream *stream); + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps); + + CHandler() { InitMethodProperties(); } +}; + +STATPROPSTG kProps[] = +{ + { NULL, kpidPackSize, VT_UI8} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO_Table + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidPhySize: if (_packSizeDefined) prop = _packSize; break; + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = 1; + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +{ + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidPackSize: if (_packSizeDefined) prop = _packSize; break; + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *stream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback * /* openArchiveCallback */) +{ + COM_TRY_BEGIN + try + { + Close(); + RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_startPosition)); + const int kSignatureSize = 3; + Byte buf[kSignatureSize]; + RINOK(ReadStream_FALSE(stream, buf, kSignatureSize)); + if (buf[0] != 'B' || buf[1] != 'Z' || buf[2] != 'h') + return S_FALSE; + + UInt64 endPosition; + RINOK(stream->Seek(0, STREAM_SEEK_END, &endPosition)); + _packSize = endPosition - _startPosition; + _packSizeDefined = true; + _stream = stream; + _seqStream = stream; + } + catch(...) { return S_FALSE; } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) +{ + Close(); + _seqStream = stream; + return S_OK; +} + +STDMETHODIMP CHandler::Close() +{ + _packSizeDefined = false; + _seqStream.Release(); + _stream.Release(); + 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)-1 && (numItems != 1 || indices[0] != 0)) + return E_INVALIDARG; + + if (_stream) + extractCallback->SetTotal(_packSize); + 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); + + NCompress::NBZip2::CDecoder *decoderSpec = new NCompress::NBZip2::CDecoder; + CMyComPtr decoder = decoderSpec; + + if (_stream) + { + RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); + } + + decoderSpec->SetInStream(_seqStream); + + #ifndef _7ZIP_ST + RINOK(decoderSpec->SetNumberOfThreads(_numThreads)); + #endif + + 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); + + HRESULT result = S_OK; + + bool firstItem = true; + for (;;) + { + lps->InSize = currentTotalPacked; + lps->OutSize = outStreamSpec->GetSize(); + + RINOK(lps->SetCur()); + + bool isBz2; + result = decoderSpec->CodeResume(outStream, isBz2, progress); + + if (result != S_OK) + break; + if (!isBz2) + { + if (firstItem) + result = S_FALSE; + break; + } + firstItem = false; + + _packSize = currentTotalPacked = decoderSpec->GetInputProcessedSize(); + _packSizeDefined = true; + } + decoderSpec->ReleaseInStream(); + outStream.Release(); + + Int32 retResult; + if (result == S_OK) + retResult = NExtract::NOperationResult::kOK; + else if (result == S_FALSE) + retResult = NExtract::NOperationResult::kDataError; + else + return result; + return extractCallback->SetOperationResult(retResult); + + COM_TRY_END +} + +static HRESULT UpdateArchive( + UInt64 unpackSize, + ISequentialOutStream *outStream, + int indexInClient, + UInt32 dictionary, + UInt32 numPasses, + #ifndef _7ZIP_ST + UInt32 numThreads, + #endif + IArchiveUpdateCallback *updateCallback) +{ + RINOK(updateCallback->SetTotal(unpackSize)); + UInt64 complexity = 0; + RINOK(updateCallback->SetCompleted(&complexity)); + + CMyComPtr fileInStream; + + RINOK(updateCallback->GetStream(indexInClient, &fileInStream)); + + CLocalProgress *localProgressSpec = new CLocalProgress; + CMyComPtr localProgress = localProgressSpec; + localProgressSpec->Init(updateCallback, true); + + NCompress::NBZip2::CEncoder *encoderSpec = new NCompress::NBZip2::CEncoder; + CMyComPtr encoder = encoderSpec; + { + NWindows::NCOM::CPropVariant properties[] = + { + dictionary, + numPasses + #ifndef _7ZIP_ST + , numThreads + #endif + }; + PROPID propIDs[] = + { + NCoderPropID::kDictionarySize, + NCoderPropID::kNumPasses + #ifndef _7ZIP_ST + , NCoderPropID::kNumThreads + #endif + }; + RINOK(encoderSpec->SetCoderProperties(propIDs, properties, sizeof(propIDs) / sizeof(propIDs[0]))); + } + + RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, localProgress)); + + return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); +} + +STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) +{ + *type = NFileTimeType::kUnix; + return S_OK; +} + +STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, + IArchiveUpdateCallback *updateCallback) +{ + 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_BOOL) + { + if (prop.boolVal != VARIANT_FALSE) + return E_INVALIDARG; + } + else if (prop.vt != VT_EMPTY) + 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; + } + + UInt32 dicSize = _dicSize; + if (dicSize == 0xFFFFFFFF) + dicSize = (_level >= 5 ? kDicSizeX5 : + (_level >= 3 ? kDicSizeX3 : + kDicSizeX1)); + + UInt32 numPasses = _numPasses; + if (numPasses == 0xFFFFFFFF) + numPasses = (_level >= 9 ? kNumPassesX9 : + (_level >= 7 ? kNumPassesX7 : + kNumPassesX1)); + + return UpdateArchive( + size, outStream, 0, dicSize, numPasses, + #ifndef _7ZIP_ST + _numThreads, + #endif + updateCallback); + } + if (indexInArchive != 0) + return E_INVALIDARG; + if (_stream) + RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); + return NCompress::CopyStream(_stream, outStream, NULL); +} + +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) +{ + InitMethodProperties(); + #ifndef _7ZIP_ST + const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); + _numThreads = numProcessors; + #endif + + for (int i = 0; i < numProps; i++) + { + UString name = names[i]; + name.MakeUpper(); + if (name.IsEmpty()) + return E_INVALIDARG; + const PROPVARIANT &prop = values[i]; + if (name[0] == L'X') + { + UInt32 level = 9; + RINOK(ParsePropValue(name.Mid(1), prop, level)); + _level = level; + } + else if (name[0] == L'D') + { + UInt32 dicSize = kDicSizeX5; + RINOK(ParsePropDictionaryValue(name.Mid(1), prop, dicSize)); + _dicSize = dicSize; + } + else if (name.Left(4) == L"PASS") + { + UInt32 num = kNumPassesX9; + RINOK(ParsePropValue(name.Mid(4), prop, num)); + _numPasses = num; + } + else if (name.Left(2) == L"MT") + { + #ifndef _7ZIP_ST + RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _numThreads)); + #endif + } + else + return E_INVALIDARG; + } + return S_OK; +} + +static IInArchive *CreateArc() { return new CHandler; } +#ifndef EXTRACT_ONLY +static IOutArchive *CreateArcOut() { return new CHandler; } +#else +#define CreateArcOut 0 +#endif + +static CArcInfo g_ArcInfo = + { L"bzip2", L"bz2 bzip2 tbz2 tbz", L"* * .tar .tar", 2, { 'B', 'Z', 'h' }, 3, true, CreateArc, CreateArcOut }; + +REGISTER_ARC(BZip2) + +}} diff --git a/CPP/7zip/Archive/Cab/CabBlockInStream.cpp b/CPP/7zip/Archive/Cab/CabBlockInStream.cpp new file mode 100755 index 0000000..e34d265 --- /dev/null +++ b/CPP/7zip/Archive/Cab/CabBlockInStream.cpp @@ -0,0 +1,189 @@ +// CabBlockInStream.cpp + +#include "StdAfx.h" + +#include "../../../../C/Alloc.h" + +#include "Common/Defs.h" + +#include "../../Common/StreamUtils.h" + +#include "CabBlockInStream.h" + +namespace NArchive { +namespace NCab { + +static const UInt32 kBlockSize = (1 << 16); + +bool CCabBlockInStream::Create() +{ + if (!_buffer) + _buffer = (Byte *)::MyAlloc(kBlockSize); + return (_buffer != 0); +} + +CCabBlockInStream::~CCabBlockInStream() +{ + MyFree(_buffer); +} + +class CCheckSum2 +{ + UInt32 m_Value; + int m_Pos; + Byte m_Hist[4]; +public: + CCheckSum2(): m_Value(0){}; + void Init() { m_Value = 0; m_Pos = 0; } + void Update(const void *data, UInt32 size); + void FinishDataUpdate() + { + for (int i = 0; i < m_Pos; i++) + m_Value ^= ((UInt32)(m_Hist[i])) << (8 * (m_Pos - i - 1)); + } + void UpdateUInt32(UInt32 v) { m_Value ^= v; } + UInt32 GetResult() const { return m_Value; } +}; + +void CCheckSum2::Update(const void *data, UInt32 size) +{ + UInt32 checkSum = m_Value; + const Byte *dataPointer = (const Byte *)data; + + while (size != 0 && m_Pos != 0) + { + m_Hist[m_Pos] = *dataPointer++; + m_Pos = (m_Pos + 1) & 3; + size--; + if (m_Pos == 0) + for (int i = 0; i < 4; i++) + checkSum ^= ((UInt32)m_Hist[i]) << (8 * i); + } + + int numWords = size / 4; + + while (numWords-- != 0) + { + UInt32 temp = *dataPointer++; + temp |= ((UInt32)(*dataPointer++)) << 8; + temp |= ((UInt32)(*dataPointer++)) << 16; + temp |= ((UInt32)(*dataPointer++)) << 24; + checkSum ^= temp; + } + m_Value = checkSum; + + size &= 3; + + while (size != 0) + { + m_Hist[m_Pos] = *dataPointer++; + m_Pos = (m_Pos + 1) & 3; + size--; + } +} + +static const UInt32 kDataBlockHeaderSize = 8; + +class CTempCabInBuffer2 +{ +public: + Byte Buffer[kDataBlockHeaderSize]; + UInt32 Pos; + Byte ReadByte() + { + return Buffer[Pos++]; + } + UInt32 ReadUInt32() + { + UInt32 value = 0; + for (int i = 0; i < 4; i++) + value |= (((UInt32)ReadByte()) << (8 * i)); + return value; + } + UInt16 ReadUInt16() + { + UInt16 value = 0; + for (int i = 0; i < 2; i++) + value |= (((UInt16)ReadByte()) << (8 * i)); + return value; + } +}; + +HRESULT CCabBlockInStream::PreRead(UInt32 &packSize, UInt32 &unpackSize) +{ + CTempCabInBuffer2 inBuffer; + inBuffer.Pos = 0; + RINOK(ReadStream_FALSE(_stream, inBuffer.Buffer, kDataBlockHeaderSize)) + + UInt32 checkSum = inBuffer.ReadUInt32(); + packSize = inBuffer.ReadUInt16(); + unpackSize = inBuffer.ReadUInt16(); + if (ReservedSize != 0) + { + RINOK(ReadStream_FALSE(_stream, _buffer, ReservedSize)); + } + _pos = 0; + CCheckSum2 checkSumCalc; + checkSumCalc.Init(); + UInt32 packSize2 = packSize; + if (MsZip && _size == 0) + { + if (packSize < 2) + return S_FALSE; // bad block; + Byte sig[2]; + RINOK(ReadStream_FALSE(_stream, sig, 2)); + if (sig[0] != 0x43 || sig[1] != 0x4B) + return S_FALSE; + packSize2 -= 2; + checkSumCalc.Update(sig, 2); + } + + if (kBlockSize - _size < packSize2) + return S_FALSE; + + UInt32 curSize = packSize2; + if (curSize != 0) + { + size_t processedSizeLoc = curSize; + RINOK(ReadStream(_stream, _buffer + _size, &processedSizeLoc)); + checkSumCalc.Update(_buffer + _size, (UInt32)processedSizeLoc); + _size += (UInt32)processedSizeLoc; + if (processedSizeLoc != curSize) + return S_FALSE; + } + TotalPackSize = _size; + + checkSumCalc.FinishDataUpdate(); + + bool dataError; + if (checkSum == 0) + dataError = false; + else + { + checkSumCalc.UpdateUInt32(packSize | (((UInt32)unpackSize) << 16)); + dataError = (checkSumCalc.GetResult() != checkSum); + } + DataError |= dataError; + return dataError ? S_FALSE : S_OK; +} + +STDMETHODIMP CCabBlockInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != 0) + *processedSize = 0; + if (size == 0) + return S_OK; + if (_size != 0) + { + size = MyMin(_size, size); + memmove(data, _buffer + _pos, size); + _pos += size; + _size -= size; + if (processedSize != 0) + *processedSize = size; + return S_OK; + } + return S_OK; // no blocks data +} + +}} diff --git a/CPP/7zip/Archive/Cab/CabBlockInStream.h b/CPP/7zip/Archive/Cab/CabBlockInStream.h new file mode 100755 index 0000000..b01113d --- /dev/null +++ b/CPP/7zip/Archive/Cab/CabBlockInStream.h @@ -0,0 +1,44 @@ +// CabBlockInStream.cpp + +#ifndef __CABBLOCKINSTREAM_H +#define __CABBLOCKINSTREAM_H + +#include "Common/MyCom.h" +#include "../../IStream.h" + +namespace NArchive { +namespace NCab { + +class CCabBlockInStream: + public ISequentialInStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + Byte *_buffer; + UInt32 _pos; + UInt32 _size; + +public: + UInt32 TotalPackSize; + UInt32 ReservedSize; + bool DataError; + bool MsZip; + + CCabBlockInStream(): _buffer(0), ReservedSize(0), MsZip(false), DataError(false), TotalPackSize(0) {} + ~CCabBlockInStream(); + bool Create(); + void SetStream(ISequentialInStream *stream) { _stream = stream; } + + void InitForNewFolder() { TotalPackSize = 0; } + void InitForNewBlock() { _size = 0; } + + MY_UNKNOWN_IMP + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + + HRESULT PreRead(UInt32 &packSize, UInt32 &unpackSize); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Cab/CabHandler.cpp b/CPP/7zip/Archive/Cab/CabHandler.cpp new file mode 100755 index 0000000..084a96b --- /dev/null +++ b/CPP/7zip/Archive/Cab/CabHandler.cpp @@ -0,0 +1,929 @@ +// CabHandler.cpp + +#include "StdAfx.h" + +#include "../../../../C/Alloc.h" + +#include "Common/Buffer.h" +#include "Common/ComTry.h" +#include "Common/Defs.h" +#include "Common/IntToString.h" +#include "Common/StringConvert.h" +#include "Common/UTFConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../../Common/ProgressUtils.h" +#include "../../Common/StreamUtils.h" + +#include "../../Compress/CopyCoder.h" +#include "../../Compress/DeflateDecoder.h" +#include "../../Compress/LzxDecoder.h" +#include "../../Compress/QuantumDecoder.h" + +#include "../Common/ItemNameUtils.h" + +#include "CabBlockInStream.h" +#include "CabHandler.h" + +using namespace NWindows; + +namespace NArchive { +namespace NCab { + +// #define _CAB_DETAILS + +#ifdef _CAB_DETAILS +enum +{ + kpidBlockReal = kpidUserDefined +}; +#endif + +static STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidAttrib, VT_UI4}, + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidBlock, VT_I4} + #ifdef _CAB_DETAILS + , + { L"BlockReal", kpidBlockReal, VT_UI4}, + { NULL, kpidOffset, VT_UI4}, + { NULL, kpidVolume, VT_UI4} + #endif +}; + +static const char *kMethods[] = +{ + "None", + "MSZip", + "Quantum", + "LZX" +}; + +static const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]); +static const char *kUnknownMethod = "Unknown"; + +static STATPROPSTG kArcProps[] = +{ + { NULL, kpidMethod, VT_BSTR}, + // { NULL, kpidSolid, VT_BOOL}, + { NULL, kpidNumBlocks, VT_UI4}, + { NULL, kpidNumVolumes, VT_UI4} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidMethod: + { + AString resString; + CRecordVector ids; + int i; + for (int v = 0; v < m_Database.Volumes.Size(); v++) + { + const CDatabaseEx &de = m_Database.Volumes[v]; + for (i = 0; i < de.Folders.Size(); i++) + ids.AddToUniqueSorted(de.Folders[i].GetCompressionMethod()); + } + for (i = 0; i < ids.Size(); i++) + { + Byte id = ids[i]; + AString method = (id < kNumMethods) ? kMethods[id] : kUnknownMethod; + if (!resString.IsEmpty()) + resString += ' '; + resString += method; + } + prop = resString; + break; + } + // case kpidSolid: prop = _database.IsSolid(); break; + case kpidNumBlocks: + { + UInt32 numFolders = 0; + for (int v = 0; v < m_Database.Volumes.Size(); v++) + numFolders += m_Database.Volumes[v].Folders.Size(); + prop = numFolders; + break; + } + case kpidNumVolumes: + { + prop = (UInt32)m_Database.Volumes.Size(); + break; + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + + const CMvItem &mvItem = m_Database.Items[index]; + const CDatabaseEx &db = m_Database.Volumes[mvItem.VolumeIndex]; + int itemIndex = mvItem.ItemIndex; + const CItem &item = db.Items[itemIndex]; + switch(propID) + { + case kpidPath: + { + UString unicodeName; + if (item.IsNameUTF()) + ConvertUTF8ToUnicode(item.Name, unicodeName); + else + unicodeName = MultiByteToUnicodeString(item.Name, CP_ACP); + prop = (const wchar_t *)NItemName::WinNameToOSName(unicodeName); + break; + } + case kpidIsDir: prop = item.IsDir(); break; + case kpidSize: prop = item.Size; break; + case kpidAttrib: prop = item.GetWinAttributes(); break; + + case kpidMTime: + { + FILETIME localFileTime, utcFileTime; + if (NTime::DosTimeToFileTime(item.Time, localFileTime)) + { + if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime)) + utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0; + } + else + utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0; + prop = utcFileTime; + break; + } + + case kpidMethod: + { + UInt32 realFolderIndex = item.GetFolderIndex(db.Folders.Size()); + const CFolder &folder = db.Folders[realFolderIndex]; + int methodIndex = folder.GetCompressionMethod(); + AString method = (methodIndex < kNumMethods) ? kMethods[methodIndex] : kUnknownMethod; + if (methodIndex == NHeader::NCompressionMethodMajor::kLZX || + methodIndex == NHeader::NCompressionMethodMajor::kQuantum) + { + method += ':'; + char temp[32]; + ConvertUInt64ToString(folder.CompressionTypeMinor, temp); + method += temp; + } + prop = method; + break; + } + case kpidBlock: prop = (Int32)m_Database.GetFolderIndex(&mvItem); break; + + #ifdef _CAB_DETAILS + + case kpidBlockReal: prop = (UInt32)item.FolderIndex; break; + case kpidOffset: prop = (UInt32)item.Offset; break; + case kpidVolume: prop = (UInt32)mvItem.VolumeIndex; break; + + #endif + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +/* +class CProgressImp: public CProgressVirt +{ + CMyComPtr m_OpenArchiveCallback; +public: + STDMETHOD(SetTotal)(const UInt64 *numFiles); + STDMETHOD(SetCompleted)(const UInt64 *numFiles); + void Init(IArchiveOpenCallback *openArchiveCallback) + { m_OpenArchiveCallback = openArchiveCallback; } +}; + +STDMETHODIMP CProgressImp::SetTotal(const UInt64 *numFiles) +{ + if (m_OpenArchiveCallback) + return m_OpenArchiveCallback->SetCompleted(numFiles, NULL); + return S_OK; +} + +STDMETHODIMP CProgressImp::SetCompleted(const UInt64 *numFiles) +{ + if (m_OpenArchiveCallback) + return m_OpenArchiveCallback->SetCompleted(numFiles, NULL); + return S_OK; +} +*/ + +STDMETHODIMP CHandler::Open(IInStream *inStream, + const UInt64 *maxCheckStartPosition, + IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + Close(); + HRESULT res = S_FALSE; + CInArchive archive; + CMyComPtr openVolumeCallback; + callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback); + + CMyComPtr nextStream = inStream; + bool prevChecked = false; + UInt64 numItems = 0; + try + { + while (nextStream != 0) + { + CDatabaseEx db; + db.Stream = nextStream; + res = archive.Open(maxCheckStartPosition, db); + if (res == S_OK) + { + if (!m_Database.Volumes.IsEmpty()) + { + const CDatabaseEx &dbPrev = m_Database.Volumes[prevChecked ? m_Database.Volumes.Size() - 1 : 0]; + if (dbPrev.ArchiveInfo.SetID != db.ArchiveInfo.SetID || + dbPrev.ArchiveInfo.CabinetNumber + (prevChecked ? 1: - 1) != + db.ArchiveInfo.CabinetNumber) + res = S_FALSE; + } + } + if (res == S_OK) + m_Database.Volumes.Insert(prevChecked ? m_Database.Volumes.Size() : 0, db); + else if (res != S_FALSE) + return res; + else + { + if (m_Database.Volumes.IsEmpty()) + return S_FALSE; + if (prevChecked) + break; + prevChecked = true; + } + + numItems += db.Items.Size(); + RINOK(callback->SetCompleted(&numItems, NULL)); + + nextStream = 0; + for (;;) + { + const COtherArchive *otherArchive = 0; + if (!prevChecked) + { + const CInArchiveInfo &ai = m_Database.Volumes.Front().ArchiveInfo; + if (ai.IsTherePrev()) + otherArchive = &ai.PrevArc; + else + prevChecked = true; + } + if (otherArchive == 0) + { + const CInArchiveInfo &ai = m_Database.Volumes.Back().ArchiveInfo; + if (ai.IsThereNext()) + otherArchive = &ai.NextArc; + } + if (!otherArchive) + break; + const UString fullName = MultiByteToUnicodeString(otherArchive->FileName, CP_ACP); + if (!openVolumeCallback) + break; + + HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream); + if (result == S_OK) + break; + if (result != S_FALSE) + return result; + if (prevChecked) + break; + prevChecked = true; + } + } + if (res == S_OK) + { + m_Database.FillSortAndShrink(); + if (!m_Database.Check()) + res = S_FALSE; + } + } + catch(...) + { + res = S_FALSE; + } + if (res != S_OK) + { + Close(); + return res; + } + COM_TRY_END + return S_OK; +} + +STDMETHODIMP CHandler::Close() +{ + m_Database.Clear(); + return S_OK; +} + +class CFolderOutStream: + public ISequentialOutStream, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +private: + const CMvDatabaseEx *m_Database; + const CRecordVector *m_ExtractStatuses; + + Byte *TempBuf; + UInt32 TempBufSize; + int NumIdenticalFiles; + bool TempBufMode; + UInt32 m_BufStartFolderOffset; + + int m_StartIndex; + int m_CurrentIndex; + CMyComPtr m_ExtractCallback; + bool m_TestMode; + + CMyComPtr m_RealOutStream; + + bool m_IsOk; + bool m_FileIsOpen; + UInt32 m_RemainFileSize; + UInt64 m_FolderSize; + UInt64 m_PosInFolder; + + void FreeTempBuf() + { + ::MyFree(TempBuf); + TempBuf = NULL; + } + + HRESULT OpenFile(); + HRESULT CloseFileWithResOp(Int32 resOp); + HRESULT CloseFile(); + HRESULT Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK); +public: + HRESULT WriteEmptyFiles(); + + CFolderOutStream(): TempBuf(NULL) {} + ~CFolderOutStream() { FreeTempBuf(); } + void Init( + const CMvDatabaseEx *database, + const CRecordVector *extractStatuses, + int startIndex, + UInt64 folderSize, + IArchiveExtractCallback *extractCallback, + bool testMode); + HRESULT FlushCorrupted(); + HRESULT Unsupported(); + + UInt64 GetRemain() const { return m_FolderSize - m_PosInFolder; } + UInt64 GetPosInFolder() const { return m_PosInFolder; } +}; + +void CFolderOutStream::Init( + const CMvDatabaseEx *database, + const CRecordVector *extractStatuses, + int startIndex, + UInt64 folderSize, + IArchiveExtractCallback *extractCallback, + bool testMode) +{ + m_Database = database; + m_ExtractStatuses = extractStatuses; + m_StartIndex = startIndex; + m_FolderSize = folderSize; + + m_ExtractCallback = extractCallback; + m_TestMode = testMode; + + m_CurrentIndex = 0; + m_PosInFolder = 0; + m_FileIsOpen = false; + m_IsOk = true; + TempBufMode = false; + NumIdenticalFiles = 0; +} + +HRESULT CFolderOutStream::CloseFileWithResOp(Int32 resOp) +{ + m_RealOutStream.Release(); + m_FileIsOpen = false; + NumIdenticalFiles--; + return m_ExtractCallback->SetOperationResult(resOp); +} + +HRESULT CFolderOutStream::CloseFile() +{ + return CloseFileWithResOp(m_IsOk ? + NExtract::NOperationResult::kOK: + NExtract::NOperationResult::kDataError); +} + +HRESULT CFolderOutStream::OpenFile() +{ + if (NumIdenticalFiles == 0) + { + const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex]; + const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; + int numExtractItems = 0; + int curIndex; + for (curIndex = m_CurrentIndex; curIndex < m_ExtractStatuses->Size(); curIndex++) + { + const CMvItem &mvItem2 = m_Database->Items[m_StartIndex + curIndex]; + const CItem &item2 = m_Database->Volumes[mvItem2.VolumeIndex].Items[mvItem2.ItemIndex]; + if (item.Offset != item2.Offset || + item.Size != item2.Size || + item.Size == 0) + break; + if (!m_TestMode && (*m_ExtractStatuses)[curIndex]) + numExtractItems++; + } + NumIdenticalFiles = (curIndex - m_CurrentIndex); + if (NumIdenticalFiles == 0) + NumIdenticalFiles = 1; + TempBufMode = false; + if (numExtractItems > 1) + { + if (!TempBuf || item.Size > TempBufSize) + { + FreeTempBuf(); + TempBuf = (Byte *)MyAlloc(item.Size); + TempBufSize = item.Size; + if (TempBuf == NULL) + return E_OUTOFMEMORY; + } + TempBufMode = true; + m_BufStartFolderOffset = item.Offset; + } + else if (numExtractItems == 1) + { + while (NumIdenticalFiles && !(*m_ExtractStatuses)[m_CurrentIndex]) + { + CMyComPtr stream; + RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &stream, NExtract::NAskMode::kSkip)); + if (stream) + return E_FAIL; + RINOK(m_ExtractCallback->PrepareOperation(NExtract::NAskMode::kSkip)); + m_CurrentIndex++; + m_FileIsOpen = true; + CloseFile(); + } + } + } + + Int32 askMode = (*m_ExtractStatuses)[m_CurrentIndex] ? (m_TestMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract) : + NExtract::NAskMode::kSkip; + RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &m_RealOutStream, askMode)); + if (!m_RealOutStream && !m_TestMode) + askMode = NExtract::NAskMode::kSkip; + return m_ExtractCallback->PrepareOperation(askMode); +} + +HRESULT CFolderOutStream::WriteEmptyFiles() +{ + if (m_FileIsOpen) + return S_OK; + for (; m_CurrentIndex < m_ExtractStatuses->Size(); m_CurrentIndex++) + { + const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex]; + const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; + UInt64 fileSize = item.Size; + if (fileSize != 0) + return S_OK; + HRESULT result = OpenFile(); + m_RealOutStream.Release(); + RINOK(result); + RINOK(m_ExtractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + } + return S_OK; +} + +// This is Write function +HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK) +{ + COM_TRY_BEGIN + UInt32 realProcessed = 0; + if (processedSize != NULL) + *processedSize = 0; + while (size != 0) + { + if (m_FileIsOpen) + { + UInt32 numBytesToWrite = MyMin(m_RemainFileSize, size); + HRESULT res = S_OK; + if (numBytesToWrite > 0) + { + if (!isOK) + m_IsOk = false; + if (m_RealOutStream) + { + UInt32 processedSizeLocal = 0; + res = m_RealOutStream->Write((const Byte *)data, numBytesToWrite, &processedSizeLocal); + numBytesToWrite = processedSizeLocal; + } + if (TempBufMode && TempBuf) + memcpy(TempBuf + (m_PosInFolder - m_BufStartFolderOffset), data, numBytesToWrite); + } + realProcessed += numBytesToWrite; + if (processedSize != NULL) + *processedSize = realProcessed; + data = (const void *)((const Byte *)data + numBytesToWrite); + size -= numBytesToWrite; + m_RemainFileSize -= numBytesToWrite; + m_PosInFolder += numBytesToWrite; + if (res != S_OK) + return res; + if (m_RemainFileSize == 0) + { + RINOK(CloseFile()); + + while (NumIdenticalFiles) + { + HRESULT result = OpenFile(); + m_FileIsOpen = true; + m_CurrentIndex++; + if (result == S_OK && m_RealOutStream && TempBuf) + result = WriteStream(m_RealOutStream, TempBuf, (size_t)(m_PosInFolder - m_BufStartFolderOffset)); + + if (!TempBuf && TempBufMode && m_RealOutStream) + { + RINOK(CloseFileWithResOp(NExtract::NOperationResult::kUnSupportedMethod)); + } + else + { + RINOK(CloseFile()); + } + RINOK(result); + } + TempBufMode = false; + } + if (realProcessed > 0) + break; // with this break this function works as Write-Part + } + else + { + if (m_CurrentIndex >= m_ExtractStatuses->Size()) + return E_FAIL; + + const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex]; + const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; + + m_RemainFileSize = item.Size; + + UInt32 fileOffset = item.Offset; + if (fileOffset < m_PosInFolder) + return E_FAIL; + if (fileOffset > m_PosInFolder) + { + UInt32 numBytesToWrite = MyMin(fileOffset - (UInt32)m_PosInFolder, size); + realProcessed += numBytesToWrite; + if (processedSize != NULL) + *processedSize = realProcessed; + data = (const void *)((const Byte *)data + numBytesToWrite); + size -= numBytesToWrite; + m_PosInFolder += numBytesToWrite; + } + if (fileOffset == m_PosInFolder) + { + RINOK(OpenFile()); + m_FileIsOpen = true; + m_CurrentIndex++; + m_IsOk = true; + } + } + } + return WriteEmptyFiles(); + COM_TRY_END +} + +STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + return Write2(data, size, processedSize, true); +} + +HRESULT CFolderOutStream::FlushCorrupted() +{ + const UInt32 kBufferSize = (1 << 10); + Byte buffer[kBufferSize]; + for (int i = 0; i < kBufferSize; i++) + buffer[i] = 0; + for (;;) + { + UInt64 remain = GetRemain(); + if (remain == 0) + return S_OK; + UInt32 size = (UInt32)MyMin(remain, (UInt64)kBufferSize); + UInt32 processedSizeLocal = 0; + RINOK(Write2(buffer, size, &processedSizeLocal, false)); + } +} + +HRESULT CFolderOutStream::Unsupported() +{ + while(m_CurrentIndex < m_ExtractStatuses->Size()) + { + HRESULT result = OpenFile(); + if (result != S_FALSE && result != S_OK) + return result; + m_RealOutStream.Release(); + RINOK(m_ExtractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod)); + m_CurrentIndex++; + } + return S_OK; +} + + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testModeSpec, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = m_Database.Items.Size(); + if(numItems == 0) + return S_OK; + bool testMode = (testModeSpec != 0); + UInt64 totalUnPacked = 0; + + UInt32 i; + int lastFolder = -2; + UInt64 lastFolderSize = 0; + for(i = 0; i < numItems; i++) + { + int index = allFilesMode ? i : indices[i]; + const CMvItem &mvItem = m_Database.Items[index]; + const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; + if (item.IsDir()) + continue; + int folderIndex = m_Database.GetFolderIndex(&mvItem); + if (folderIndex != lastFolder) + totalUnPacked += lastFolderSize; + lastFolder = folderIndex; + lastFolderSize = item.GetEndOffset(); + } + totalUnPacked += lastFolderSize; + + extractCallback->SetTotal(totalUnPacked); + + totalUnPacked = 0; + + UInt64 totalPacked = 0; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; + CMyComPtr copyCoder = copyCoderSpec; + + NCompress::NDeflate::NDecoder::CCOMCoder *deflateDecoderSpec = NULL; + CMyComPtr deflateDecoder; + + NCompress::NLzx::CDecoder *lzxDecoderSpec = NULL; + CMyComPtr lzxDecoder; + + NCompress::NQuantum::CDecoder *quantumDecoderSpec = NULL; + CMyComPtr quantumDecoder; + + CCabBlockInStream *cabBlockInStreamSpec = new CCabBlockInStream(); + CMyComPtr cabBlockInStream = cabBlockInStreamSpec; + if (!cabBlockInStreamSpec->Create()) + return E_OUTOFMEMORY; + + CRecordVector extractStatuses; + for(i = 0; i < numItems;) + { + int index = allFilesMode ? i : indices[i]; + + const CMvItem &mvItem = m_Database.Items[index]; + const CDatabaseEx &db = m_Database.Volumes[mvItem.VolumeIndex]; + int itemIndex = mvItem.ItemIndex; + const CItem &item = db.Items[itemIndex]; + + i++; + if (item.IsDir()) + { + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + CMyComPtr realOutStream; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + RINOK(extractCallback->PrepareOperation(askMode)); + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + int folderIndex = m_Database.GetFolderIndex(&mvItem); + if (folderIndex < 0) + { + // If we need previous archive + Int32 askMode= testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + CMyComPtr realOutStream; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + RINOK(extractCallback->PrepareOperation(askMode)); + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kDataError)); + continue; + } + int startIndex2 = m_Database.FolderStartFileIndex[folderIndex]; + int startIndex = startIndex2; + extractStatuses.Clear(); + for (; startIndex < index; startIndex++) + extractStatuses.Add(false); + extractStatuses.Add(true); + startIndex++; + UInt64 curUnpack = item.GetEndOffset(); + for(;i < numItems; i++) + { + int indexNext = allFilesMode ? i : indices[i]; + const CMvItem &mvItem = m_Database.Items[indexNext]; + const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; + if (item.IsDir()) + continue; + int newFolderIndex = m_Database.GetFolderIndex(&mvItem); + + if (newFolderIndex != folderIndex) + break; + for (; startIndex < indexNext; startIndex++) + extractStatuses.Add(false); + extractStatuses.Add(true); + startIndex++; + curUnpack = item.GetEndOffset(); + } + + lps->OutSize = totalUnPacked; + lps->InSize = totalPacked; + RINOK(lps->SetCur()); + + CFolderOutStream *cabFolderOutStream = new CFolderOutStream; + CMyComPtr outStream(cabFolderOutStream); + + const CFolder &folder = db.Folders[item.GetFolderIndex(db.Folders.Size())]; + + cabFolderOutStream->Init(&m_Database, &extractStatuses, startIndex2, + curUnpack, extractCallback, testMode); + + cabBlockInStreamSpec->MsZip = false; + switch(folder.GetCompressionMethod()) + { + case NHeader::NCompressionMethodMajor::kNone: + break; + case NHeader::NCompressionMethodMajor::kMSZip: + if(deflateDecoderSpec == NULL) + { + deflateDecoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder; + deflateDecoder = deflateDecoderSpec; + } + cabBlockInStreamSpec->MsZip = true; + break; + case NHeader::NCompressionMethodMajor::kLZX: + if(lzxDecoderSpec == NULL) + { + lzxDecoderSpec = new NCompress::NLzx::CDecoder; + lzxDecoder = lzxDecoderSpec; + } + RINOK(lzxDecoderSpec->SetParams(folder.CompressionTypeMinor)); + break; + case NHeader::NCompressionMethodMajor::kQuantum: + if(quantumDecoderSpec == NULL) + { + quantumDecoderSpec = new NCompress::NQuantum::CDecoder; + quantumDecoder = quantumDecoderSpec; + } + quantumDecoderSpec->SetParams(folder.CompressionTypeMinor); + break; + default: + { + RINOK(cabFolderOutStream->Unsupported()); + totalUnPacked += curUnpack; + continue; + } + } + + cabBlockInStreamSpec->InitForNewFolder(); + + HRESULT res = S_OK; + + { + int volIndex = mvItem.VolumeIndex; + int locFolderIndex = item.GetFolderIndex(db.Folders.Size()); + bool keepHistory = false; + bool keepInputBuffer = false; + for (UInt32 f = 0; cabFolderOutStream->GetRemain() != 0;) + { + if (volIndex >= m_Database.Volumes.Size()) + { + res = S_FALSE; + break; + } + + const CDatabaseEx &db = m_Database.Volumes[volIndex]; + const CFolder &folder = db.Folders[locFolderIndex]; + if (f == 0) + { + cabBlockInStreamSpec->SetStream(db.Stream); + cabBlockInStreamSpec->ReservedSize = db.ArchiveInfo.GetDataBlockReserveSize(); + RINOK(db.Stream->Seek(db.StartPosition + folder.DataStart, STREAM_SEEK_SET, NULL)); + } + if (f == folder.NumDataBlocks) + { + volIndex++; + locFolderIndex = 0; + f = 0; + continue; + } + f++; + + cabBlockInStreamSpec->DataError = false; + + if (!keepInputBuffer) + cabBlockInStreamSpec->InitForNewBlock(); + + UInt32 packSize, unpackSize; + res = cabBlockInStreamSpec->PreRead(packSize, unpackSize); + if (res == S_FALSE) + break; + RINOK(res); + keepInputBuffer = (unpackSize == 0); + if (keepInputBuffer) + continue; + + UInt64 totalUnPacked2 = totalUnPacked + cabFolderOutStream->GetPosInFolder(); + totalPacked += packSize; + + lps->OutSize = totalUnPacked2; + lps->InSize = totalPacked; + RINOK(lps->SetCur()); + + UInt64 unpackRemain = cabFolderOutStream->GetRemain(); + + const UInt32 kBlockSizeMax = (1 << 15); + if (unpackRemain > kBlockSizeMax) + unpackRemain = kBlockSizeMax; + if (unpackRemain > unpackSize) + unpackRemain = unpackSize; + + switch(folder.GetCompressionMethod()) + { + case NHeader::NCompressionMethodMajor::kNone: + res = copyCoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL); + break; + case NHeader::NCompressionMethodMajor::kMSZip: + deflateDecoderSpec->SetKeepHistory(keepHistory); + res = deflateDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL); + break; + case NHeader::NCompressionMethodMajor::kLZX: + lzxDecoderSpec->SetKeepHistory(keepHistory); + res = lzxDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL); + break; + case NHeader::NCompressionMethodMajor::kQuantum: + quantumDecoderSpec->SetKeepHistory(keepHistory); + res = quantumDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL); + break; + } + if (res != S_OK) + { + if (res != S_FALSE) + RINOK(res); + break; + } + keepHistory = true; + } + if (res == S_OK) + { + RINOK(cabFolderOutStream->WriteEmptyFiles()); + } + } + if (res != S_OK || cabFolderOutStream->GetRemain() != 0) + { + RINOK(cabFolderOutStream->FlushCorrupted()); + } + totalUnPacked += curUnpack; + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = m_Database.Items.Size(); + return S_OK; +} + +}} diff --git a/CPP/7zip/Archive/Cab/CabHandler.h b/CPP/7zip/Archive/Cab/CabHandler.h new file mode 100755 index 0000000..67c0d03 --- /dev/null +++ b/CPP/7zip/Archive/Cab/CabHandler.h @@ -0,0 +1,28 @@ +// CabHandler.h + +#ifndef __CAB_HANDLER_H +#define __CAB_HANDLER_H + +#include "Common/MyCom.h" +#include "../IArchive.h" +#include "CabIn.h" + +namespace NArchive { +namespace NCab { + +class CHandler: + public IInArchive, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP1(IInArchive) + + INTERFACE_IInArchive(;) + +private: + CMvDatabaseEx m_Database; +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Cab/CabHeader.cpp b/CPP/7zip/Archive/Cab/CabHeader.cpp new file mode 100755 index 0000000..4d59ba0 --- /dev/null +++ b/CPP/7zip/Archive/Cab/CabHeader.cpp @@ -0,0 +1,15 @@ +// CabHeader.cpp + +#include "StdAfx.h" + +#include "CabHeader.h" + +namespace NArchive { +namespace NCab { +namespace NHeader { + +Byte kMarker[kMarkerSize] = {'M', 'S', 'C', 'F', 0, 0, 0, 0 }; + +// struct CSignatureInitializer { CSignatureInitializer() { kMarker[0]--; }; } g_SignatureInitializer; + +}}} diff --git a/CPP/7zip/Archive/Cab/CabHeader.h b/CPP/7zip/Archive/Cab/CabHeader.h new file mode 100755 index 0000000..5e68471 --- /dev/null +++ b/CPP/7zip/Archive/Cab/CabHeader.h @@ -0,0 +1,44 @@ +// Archive/Cab/Header.h + +#ifndef __ARCHIVE_CAB_HEADER_H +#define __ARCHIVE_CAB_HEADER_H + +#include "Common/Types.h" + +namespace NArchive { +namespace NCab { +namespace NHeader { + +const unsigned kMarkerSize = 8; +extern Byte kMarker[kMarkerSize]; + +namespace NArchive +{ + namespace NFlags + { + const int kPrevCabinet = 0x0001; + const int kNextCabinet = 0x0002; + const int kReservePresent = 0x0004; + } +} + +namespace NCompressionMethodMajor +{ + const Byte kNone = 0; + const Byte kMSZip = 1; + const Byte kQuantum = 2; + const Byte kLZX = 3; +} + +const int kFileNameIsUTFAttributeMask = 0x80; + +namespace NFolderIndex +{ + const int kContinuedFromPrev = 0xFFFD; + const int kContinuedToNext = 0xFFFE; + const int kContinuedPrevAndNext = 0xFFFF; +} + +}}} + +#endif diff --git a/CPP/7zip/Archive/Cab/CabIn.cpp b/CPP/7zip/Archive/Cab/CabIn.cpp new file mode 100755 index 0000000..a0ff0ad --- /dev/null +++ b/CPP/7zip/Archive/Cab/CabIn.cpp @@ -0,0 +1,272 @@ +// Archive/CabIn.cpp + +#include "StdAfx.h" + +#include "../Common/FindSignature.h" + +#include "CabIn.h" + +namespace NArchive { +namespace NCab { + +Byte CInArchive::Read8() +{ + Byte b; + if (!inBuffer.ReadByte(b)) + throw CInArchiveException(CInArchiveException::kUnsupported); + return b; +} + +UInt16 CInArchive::Read16() +{ + UInt16 value = 0; + for (int i = 0; i < 2; i++) + { + Byte b = Read8(); + value |= (UInt16(b) << (8 * i)); + } + return value; +} + +UInt32 CInArchive::Read32() +{ + UInt32 value = 0; + for (int i = 0; i < 4; i++) + { + Byte b = Read8(); + value |= (UInt32(b) << (8 * i)); + } + return value; +} + +AString CInArchive::SafeReadName() +{ + AString name; + for (;;) + { + Byte b = Read8(); + if (b == 0) + return name; + name += (char)b; + } +} + +void CInArchive::ReadOtherArchive(COtherArchive &oa) +{ + oa.FileName = SafeReadName(); + oa.DiskName = SafeReadName(); +} + +void CInArchive::Skip(UInt32 size) +{ + while (size-- != 0) + Read8(); +} + +HRESULT CInArchive::Open(const UInt64 *searchHeaderSizeLimit, CDatabaseEx &db) +{ + IInStream *stream = db.Stream; + db.Clear(); + RINOK(stream->Seek(0, STREAM_SEEK_SET, &db.StartPosition)); + + RINOK(FindSignatureInStream(stream, NHeader::kMarker, NHeader::kMarkerSize, + searchHeaderSizeLimit, db.StartPosition)); + + RINOK(stream->Seek(db.StartPosition + NHeader::kMarkerSize, STREAM_SEEK_SET, NULL)); + if (!inBuffer.Create(1 << 17)) + return E_OUTOFMEMORY; + inBuffer.SetStream(stream); + inBuffer.Init(); + + CInArchiveInfo &ai = db.ArchiveInfo; + + ai.Size = Read32(); + if (Read32() != 0) + return S_FALSE; + ai.FileHeadersOffset = Read32(); + if (Read32() != 0) + return S_FALSE; + + ai.VersionMinor = Read8(); + ai.VersionMajor = Read8(); + ai.NumFolders = Read16(); + ai.NumFiles = Read16(); + ai.Flags = Read16(); + if (ai.Flags > 7) + return S_FALSE; + ai.SetID = Read16(); + ai.CabinetNumber = Read16(); + + if (ai.ReserveBlockPresent()) + { + ai.PerCabinetAreaSize = Read16(); + ai.PerFolderAreaSize = Read8(); + ai.PerDataBlockAreaSize = Read8(); + + Skip(ai.PerCabinetAreaSize); + } + + { + if (ai.IsTherePrev()) + ReadOtherArchive(ai.PrevArc); + if (ai.IsThereNext()) + ReadOtherArchive(ai.NextArc); + } + + int i; + for (i = 0; i < ai.NumFolders; i++) + { + CFolder folder; + + folder.DataStart = Read32(); + folder.NumDataBlocks = Read16(); + folder.CompressionTypeMajor = Read8(); + folder.CompressionTypeMinor = Read8(); + + Skip(ai.PerFolderAreaSize); + db.Folders.Add(folder); + } + + RINOK(stream->Seek(db.StartPosition + ai.FileHeadersOffset, STREAM_SEEK_SET, NULL)); + + inBuffer.SetStream(stream); + inBuffer.Init(); + for (i = 0; i < ai.NumFiles; i++) + { + CItem item; + item.Size = Read32(); + item.Offset = Read32(); + item.FolderIndex = Read16(); + UInt16 pureDate = Read16(); + UInt16 pureTime = Read16(); + item.Time = ((UInt32(pureDate) << 16)) | pureTime; + item.Attributes = Read16(); + item.Name = SafeReadName(); + int folderIndex = item.GetFolderIndex(db.Folders.Size()); + if (folderIndex >= db.Folders.Size()) + return S_FALSE; + db.Items.Add(item); + } + return S_OK; +} + +#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } + +static int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param) +{ + const CMvDatabaseEx &mvDb = *(const CMvDatabaseEx *)param; + const CDatabaseEx &db1 = mvDb.Volumes[p1->VolumeIndex]; + const CDatabaseEx &db2 = mvDb.Volumes[p2->VolumeIndex]; + const CItem &item1 = db1.Items[p1->ItemIndex]; + const CItem &item2 = db2.Items[p2->ItemIndex];; + bool isDir1 = item1.IsDir(); + bool isDir2 = item2.IsDir(); + if (isDir1 && !isDir2) + return -1; + if (isDir2 && !isDir1) + return 1; + int f1 = mvDb.GetFolderIndex(p1); + int f2 = mvDb.GetFolderIndex(p2); + RINOZ(MyCompare(f1, f2)); + RINOZ(MyCompare(item1.Offset, item2.Offset)); + RINOZ(MyCompare(item1.Size, item2.Size)); + RINOZ(MyCompare(p1->VolumeIndex, p2->VolumeIndex)); + return MyCompare(p1->ItemIndex, p2->ItemIndex); +} + +bool CMvDatabaseEx::AreItemsEqual(int i1, int i2) +{ + const CMvItem *p1 = &Items[i1]; + const CMvItem *p2 = &Items[i2]; + const CDatabaseEx &db1 = Volumes[p1->VolumeIndex]; + const CDatabaseEx &db2 = Volumes[p2->VolumeIndex]; + const CItem &item1 = db1.Items[p1->ItemIndex]; + const CItem &item2 = db2.Items[p2->ItemIndex];; + return GetFolderIndex(p1) == GetFolderIndex(p2) && + item1.Offset == item2.Offset && + item1.Size == item2.Size && + item1.Name == item2.Name; +} + +void CMvDatabaseEx::FillSortAndShrink() +{ + Items.Clear(); + StartFolderOfVol.Clear(); + FolderStartFileIndex.Clear(); + int offset = 0; + for (int v = 0; v < Volumes.Size(); v++) + { + const CDatabaseEx &db = Volumes[v]; + int curOffset = offset; + if (db.IsTherePrevFolder()) + curOffset--; + StartFolderOfVol.Add(curOffset); + offset += db.GetNumberOfNewFolders(); + + CMvItem mvItem; + mvItem.VolumeIndex = v; + for (int i = 0 ; i < db.Items.Size(); i++) + { + mvItem.ItemIndex = i; + Items.Add(mvItem); + } + } + + Items.Sort(CompareMvItems, (void *)this); + int j = 1; + int i; + for (i = 1; i < Items.Size(); i++) + if (!AreItemsEqual(i, i -1)) + Items[j++] = Items[i]; + Items.DeleteFrom(j); + + for (i = 0; i < Items.Size(); i++) + { + int folderIndex = GetFolderIndex(&Items[i]); + if (folderIndex >= FolderStartFileIndex.Size()) + FolderStartFileIndex.Add(i); + } +} + +bool CMvDatabaseEx::Check() +{ + for (int v = 1; v < Volumes.Size(); v++) + { + const CDatabaseEx &db1 = Volumes[v]; + if (db1.IsTherePrevFolder()) + { + const CDatabaseEx &db0 = Volumes[v - 1]; + if (db0.Folders.IsEmpty() || db1.Folders.IsEmpty()) + return false; + const CFolder &f0 = db0.Folders.Back(); + const CFolder &f1 = db1.Folders.Front(); + if (f0.CompressionTypeMajor != f1.CompressionTypeMajor || + f0.CompressionTypeMinor != f1.CompressionTypeMinor) + return false; + } + } + UInt32 beginPos = 0; + UInt64 endPos = 0; + int prevFolder = -2; + for (int i = 0; i < Items.Size(); i++) + { + const CMvItem &mvItem = Items[i]; + int fIndex = GetFolderIndex(&mvItem); + if (fIndex >= FolderStartFileIndex.Size()) + return false; + const CItem &item = Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; + if (item.IsDir()) + continue; + int folderIndex = GetFolderIndex(&mvItem); + if (folderIndex != prevFolder) + prevFolder = folderIndex; + else if (item.Offset < endPos && + (item.Offset != beginPos || item.GetEndOffset() != endPos)) + return false; + beginPos = item.Offset; + endPos = item.GetEndOffset(); + } + return true; +} + +}} diff --git a/CPP/7zip/Archive/Cab/CabIn.h b/CPP/7zip/Archive/Cab/CabIn.h new file mode 100755 index 0000000..a672989 --- /dev/null +++ b/CPP/7zip/Archive/Cab/CabIn.h @@ -0,0 +1,161 @@ +// Archive/CabIn.h + +#ifndef __ARCHIVE_CAB_IN_H +#define __ARCHIVE_CAB_IN_H + +#include "../../IStream.h" +#include "../../Common/InBuffer.h" +#include "CabHeader.h" +#include "CabItem.h" + +namespace NArchive { +namespace NCab { + +class CInArchiveException +{ +public: + enum CCauseType + { + kUnexpectedEndOfArchive = 0, + kIncorrectArchive, + kUnsupported + } Cause; + CInArchiveException(CCauseType cause) : Cause(cause) {} +}; + +struct COtherArchive +{ + AString FileName; + AString DiskName; +}; + +struct CArchiveInfo +{ + Byte VersionMinor; /* cabinet file format version, minor */ + Byte VersionMajor; /* cabinet file format version, major */ + UInt16 NumFolders; /* number of CFFOLDER entries in this cabinet */ + UInt16 NumFiles; /* number of CFFILE entries in this cabinet */ + UInt16 Flags; /* cabinet file option indicators */ + UInt16 SetID; /* must be the same for all cabinets in a set */ + UInt16 CabinetNumber; /* number of this cabinet file in a set */ + + bool ReserveBlockPresent() const { return (Flags & NHeader::NArchive::NFlags::kReservePresent) != 0; } + + bool IsTherePrev() const { return (Flags & NHeader::NArchive::NFlags::kPrevCabinet) != 0; } + bool IsThereNext() const { return (Flags & NHeader::NArchive::NFlags::kNextCabinet) != 0; } + + UInt16 PerCabinetAreaSize; // (optional) size of per-cabinet reserved area + Byte PerFolderAreaSize; // (optional) size of per-folder reserved area + Byte PerDataBlockAreaSize; // (optional) size of per-datablock reserved area + + Byte GetDataBlockReserveSize() const { return (Byte)(ReserveBlockPresent() ? PerDataBlockAreaSize : 0); } + + COtherArchive PrevArc; + COtherArchive NextArc; + + CArchiveInfo() + { + Clear(); + } + + void Clear() + { + PerCabinetAreaSize = 0; + PerFolderAreaSize = 0; + PerDataBlockAreaSize = 0; + } +}; + +struct CInArchiveInfo: public CArchiveInfo +{ + UInt32 Size; /* size of this cabinet file in bytes */ + UInt32 FileHeadersOffset; // offset of the first CFFILE entry +}; + + +struct CDatabase +{ + UInt64 StartPosition; + CInArchiveInfo ArchiveInfo; + CObjectVector Folders; + CObjectVector Items; + + void Clear() + { + ArchiveInfo.Clear(); + Folders.Clear(); + Items.Clear(); + } + bool IsTherePrevFolder() const + { + for (int i = 0; i < Items.Size(); i++) + if (Items[i].ContinuedFromPrev()) + return true; + return false; + } + int GetNumberOfNewFolders() const + { + int res = Folders.Size(); + if (IsTherePrevFolder()) + res--; + return res; + } + UInt32 GetFileOffset(int index) const { return Items[index].Offset; } + UInt32 GetFileSize(int index) const { return Items[index].Size; } +}; + +struct CDatabaseEx: public CDatabase +{ + CMyComPtr Stream; +}; + +struct CMvItem +{ + int VolumeIndex; + int ItemIndex; +}; + +class CMvDatabaseEx +{ + bool AreItemsEqual(int i1, int i2); +public: + CObjectVector Volumes; + CRecordVector Items; + CRecordVector StartFolderOfVol; + CRecordVector FolderStartFileIndex; + + int GetFolderIndex(const CMvItem *mvi) const + { + const CDatabaseEx &db = Volumes[mvi->VolumeIndex]; + return StartFolderOfVol[mvi->VolumeIndex] + + db.Items[mvi->ItemIndex].GetFolderIndex(db.Folders.Size()); + } + void Clear() + { + Volumes.Clear(); + Items.Clear(); + StartFolderOfVol.Clear(); + FolderStartFileIndex.Clear(); + } + void FillSortAndShrink(); + bool Check(); +}; + +class CInArchive +{ + CInBuffer inBuffer; + + Byte Read8(); + UInt16 Read16(); + UInt32 Read32(); + AString SafeReadName(); + void Skip(UInt32 size); + void ReadOtherArchive(COtherArchive &oa); + +public: + HRESULT Open(const UInt64 *searchHeaderSizeLimit, CDatabaseEx &db); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Cab/CabItem.h b/CPP/7zip/Archive/Cab/CabItem.h new file mode 100755 index 0000000..98a0f9b --- /dev/null +++ b/CPP/7zip/Archive/Cab/CabItem.h @@ -0,0 +1,63 @@ +// Archive/CabItem.h + +#ifndef __ARCHIVE_CAB_ITEM_H +#define __ARCHIVE_CAB_ITEM_H + +#include "Common/Types.h" +#include "Common/MyString.h" +#include "CabHeader.h" + +namespace NArchive { +namespace NCab { + +struct CFolder +{ + UInt32 DataStart; // offset of the first CFDATA block in this folder + UInt16 NumDataBlocks; // number of CFDATA blocks in this folder + Byte CompressionTypeMajor; + Byte CompressionTypeMinor; + Byte GetCompressionMethod() const { return (Byte)(CompressionTypeMajor & 0xF); } +}; + +struct CItem +{ + AString Name; + UInt32 Offset; + UInt32 Size; + UInt32 Time; + UInt16 FolderIndex; + UInt16 Flags; + UInt16 Attributes; + + UInt64 GetEndOffset() const { return (UInt64)Offset + Size; } + UInt32 GetWinAttributes() const { return (Attributes & ~NHeader::kFileNameIsUTFAttributeMask); } + bool IsNameUTF() const { return (Attributes & NHeader::kFileNameIsUTFAttributeMask) != 0; } + bool IsDir() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; } + + bool ContinuedFromPrev() const + { + return + (FolderIndex == NHeader::NFolderIndex::kContinuedFromPrev) || + (FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext); + } + + bool ContinuedToNext() const + { + return + (FolderIndex == NHeader::NFolderIndex::kContinuedToNext) || + (FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext); + } + + int GetFolderIndex(int numFolders) const + { + if (ContinuedFromPrev()) + return 0; + if (ContinuedToNext()) + return (numFolders - 1); + return FolderIndex; + } +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Cab/CabRegister.cpp b/CPP/7zip/Archive/Cab/CabRegister.cpp new file mode 100755 index 0000000..eb27d04 --- /dev/null +++ b/CPP/7zip/Archive/Cab/CabRegister.cpp @@ -0,0 +1,13 @@ +// CabRegister.cpp + +#include "StdAfx.h" + +#include "../../Common/RegisterArc.h" + +#include "CabHandler.h" +static IInArchive *CreateArc() { return new NArchive::NCab::CHandler; } + +static CArcInfo g_ArcInfo = + { L"Cab", L"cab", 0, 8, { 0x4D, 0x53, 0x43, 0x46 }, 4, false, CreateArc, 0 }; + +REGISTER_ARC(Cab) diff --git a/CPP/7zip/Archive/Cab/StdAfx.h b/CPP/7zip/Archive/Cab/StdAfx.h new file mode 100755 index 0000000..83fdd22 --- /dev/null +++ b/CPP/7zip/Archive/Cab/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" + +#endif diff --git a/CPP/7zip/Archive/Chm/ChmHandler.cpp b/CPP/7zip/Archive/Chm/ChmHandler.cpp new file mode 100755 index 0000000..24f88b6 --- /dev/null +++ b/CPP/7zip/Archive/Chm/ChmHandler.cpp @@ -0,0 +1,721 @@ +// ChmHandler.cpp + +#include "StdAfx.h" + +#include "Common/ComTry.h" +#include "Common/Defs.h" +#include "Common/StringConvert.h" +#include "Common/UTFConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../../Common/LimitedStreams.h" +#include "../../Common/ProgressUtils.h" +#include "../../Common/StreamUtils.h" + +#include "../../Compress/CopyCoder.h" +#include "../../Compress/LzxDecoder.h" + +#include "../Common/ItemNameUtils.h" + +#include "ChmHandler.h" + +using namespace NWindows; +using namespace NTime; + +namespace NArchive { +namespace NChm { + +// #define _CHM_DETAILS + +#ifdef _CHM_DETAILS + +enum +{ + kpidSection = kpidUserDefined +}; + +#endif + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidBlock, VT_UI4} + + #ifdef _CHM_DETAILS + , + { L"Section", kpidSection, VT_UI4}, + { NULL, kpidOffset, VT_UI4} + #endif +}; + +STATPROPSTG kArcProps[] = +{ + { NULL, kpidNumBlocks, VT_UI8} +}; + +IMP_IInArchive_Props + +IMP_IInArchive_ArcProps_NO +/* +IMP_IInArchive_ArcProps + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidNumBlocks: + { + UInt64 numBlocks = 0; + for (int i = 0; i < m_Database.Sections.Size(); i++) + { + const CSectionInfo &s = m_Database.Sections[i]; + for (int j = 0; j < s.Methods.Size(); j++) + { + const CMethodInfo &m = s.Methods[j]; + if (m.IsLzx()) + numBlocks += m.LzxInfo.ResetTable.GetNumBlocks(); + } + } + prop = numBlocks; + break; + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} +*/ + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + if (m_Database.NewFormat) + { + switch(propID) + { + case kpidSize: + prop = (UInt64)m_Database.NewFormatString.Length(); + break; + } + prop.Detach(value); + return S_OK; + } + int entryIndex; + if (m_Database.LowLevel) + entryIndex = index; + else + entryIndex = m_Database.Indices[index]; + const CItem &item = m_Database.Items[entryIndex]; + switch(propID) + { + case kpidPath: + { + UString us; + if (ConvertUTF8ToUnicode(item.Name, us)) + { + if (!m_Database.LowLevel) + { + if (us.Length() > 1) + if (us[0] == L'/') + us.Delete(0); + } + prop = NItemName::GetOSName2(us); + } + break; + } + case kpidIsDir: prop = item.IsDir(); break; + case kpidSize: prop = item.Size; break; + case kpidMethod: + { + if (!item.IsDir()) + if (item.Section == 0) + prop = L"Copy"; + else if (item.Section < m_Database.Sections.Size()) + prop = m_Database.Sections[(int)item.Section].GetMethodName(); + break; + } + case kpidBlock: + if (m_Database.LowLevel) + prop = item.Section; + else if (item.Section != 0) + prop = m_Database.GetFolder(index); + break; + + #ifdef _CHM_DETAILS + + case kpidSection: prop = (UInt32)item.Section; break; + case kpidOffset: prop = (UInt32)item.Offset; break; + + #endif + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +class CProgressImp: public CProgressVirt +{ + CMyComPtr _callback; +public: + STDMETHOD(SetTotal)(const UInt64 *numFiles); + STDMETHOD(SetCompleted)(const UInt64 *numFiles); + CProgressImp(IArchiveOpenCallback *callback): _callback(callback) {}; +}; + +STDMETHODIMP CProgressImp::SetTotal(const UInt64 *numFiles) +{ + if (_callback) + return _callback->SetCompleted(numFiles, NULL); + return S_OK; +} + +STDMETHODIMP CProgressImp::SetCompleted(const UInt64 *numFiles) +{ + if (_callback) + return _callback->SetCompleted(numFiles, NULL); + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *inStream, + const UInt64 *maxCheckStartPosition, + IArchiveOpenCallback * /* openArchiveCallback */) +{ + COM_TRY_BEGIN + m_Stream.Release(); + try + { + CInArchive archive; + // CProgressImp progressImp(openArchiveCallback); + RINOK(archive.Open(inStream, maxCheckStartPosition, m_Database)); + /* + if (m_Database.LowLevel) + return S_FALSE; + */ + m_Stream = inStream; + } + catch(...) + { + return S_FALSE; + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + m_Database.Clear(); + m_Stream.Release(); + return S_OK; +} + +class CChmFolderOutStream: + public ISequentialOutStream, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP + + HRESULT Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK); + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + + UInt64 m_FolderSize; + UInt64 m_PosInFolder; + UInt64 m_PosInSection; + const CRecordVector *m_ExtractStatuses; + int m_StartIndex; + int m_CurrentIndex; + int m_NumFiles; + +private: + const CFilesDatabase *m_Database; + CMyComPtr m_ExtractCallback; + bool m_TestMode; + + bool m_IsOk; + bool m_FileIsOpen; + UInt64 m_RemainFileSize; + CMyComPtr m_RealOutStream; + + HRESULT OpenFile(); + HRESULT WriteEmptyFiles(); +public: + void Init( + const CFilesDatabase *database, + IArchiveExtractCallback *extractCallback, + bool testMode); + HRESULT FlushCorrupted(UInt64 maxSize); +}; + +void CChmFolderOutStream::Init( + const CFilesDatabase *database, + IArchiveExtractCallback *extractCallback, + bool testMode) +{ + m_Database = database; + m_ExtractCallback = extractCallback; + m_TestMode = testMode; + + m_CurrentIndex = 0; + m_FileIsOpen = false; +} + +HRESULT CChmFolderOutStream::OpenFile() +{ + Int32 askMode = (*m_ExtractStatuses)[m_CurrentIndex] ? (m_TestMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract) : + NExtract::NAskMode::kSkip; + m_RealOutStream.Release(); + RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &m_RealOutStream, askMode)); + if (!m_RealOutStream && !m_TestMode) + askMode = NExtract::NAskMode::kSkip; + return m_ExtractCallback->PrepareOperation(askMode); +} + +HRESULT CChmFolderOutStream::WriteEmptyFiles() +{ + if (m_FileIsOpen) + return S_OK; + for (;m_CurrentIndex < m_NumFiles; m_CurrentIndex++) + { + UInt64 fileSize = m_Database->GetFileSize(m_StartIndex + m_CurrentIndex); + if (fileSize != 0) + return S_OK; + HRESULT result = OpenFile(); + m_RealOutStream.Release(); + RINOK(result); + RINOK(m_ExtractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + } + return S_OK; +} + +// This is WritePart function +HRESULT CChmFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK) +{ + UInt32 realProcessed = 0; + if (processedSize != NULL) + *processedSize = 0; + while(size != 0) + { + if (m_FileIsOpen) + { + UInt32 numBytesToWrite = (UInt32)MyMin(m_RemainFileSize, (UInt64)(size)); + HRESULT res = S_OK; + if (numBytesToWrite > 0) + { + if (!isOK) + m_IsOk = false; + if (m_RealOutStream) + { + UInt32 processedSizeLocal = 0; + res = m_RealOutStream->Write((const Byte *)data, numBytesToWrite, &processedSizeLocal); + numBytesToWrite = processedSizeLocal; + } + } + realProcessed += numBytesToWrite; + if (processedSize != NULL) + *processedSize = realProcessed; + data = (const void *)((const Byte *)data + numBytesToWrite); + size -= numBytesToWrite; + m_RemainFileSize -= numBytesToWrite; + m_PosInSection += numBytesToWrite; + m_PosInFolder += numBytesToWrite; + if (res != S_OK) + return res; + if (m_RemainFileSize == 0) + { + m_RealOutStream.Release(); + RINOK(m_ExtractCallback->SetOperationResult( + m_IsOk ? + NExtract::NOperationResult::kOK: + NExtract::NOperationResult::kDataError)); + m_FileIsOpen = false; + } + if (realProcessed > 0) + break; // with this break this function works as write part + } + else + { + if (m_CurrentIndex >= m_NumFiles) + return E_FAIL; + int fullIndex = m_StartIndex + m_CurrentIndex; + m_RemainFileSize = m_Database->GetFileSize(fullIndex); + UInt64 fileOffset = m_Database->GetFileOffset(fullIndex); + if (fileOffset < m_PosInSection) + return E_FAIL; + if (fileOffset > m_PosInSection) + { + UInt32 numBytesToWrite = (UInt32)MyMin(fileOffset - m_PosInSection, UInt64(size)); + realProcessed += numBytesToWrite; + if (processedSize != NULL) + *processedSize = realProcessed; + data = (const void *)((const Byte *)data + numBytesToWrite); + size -= numBytesToWrite; + m_PosInSection += numBytesToWrite; + m_PosInFolder += numBytesToWrite; + } + if (fileOffset == m_PosInSection) + { + RINOK(OpenFile()); + m_FileIsOpen = true; + m_CurrentIndex++; + m_IsOk = true; + } + } + } + return WriteEmptyFiles(); +} + +STDMETHODIMP CChmFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + return Write2(data, size, processedSize, true); +} + +HRESULT CChmFolderOutStream::FlushCorrupted(UInt64 maxSize) +{ + const UInt32 kBufferSize = (1 << 10); + Byte buffer[kBufferSize]; + for (int i = 0; i < kBufferSize; i++) + buffer[i] = 0; + if (maxSize > m_FolderSize) + maxSize = m_FolderSize; + while (m_PosInFolder < maxSize) + { + UInt32 size = (UInt32)MyMin(maxSize - m_PosInFolder, (UInt64)kBufferSize); + UInt32 processedSizeLocal = 0; + RINOK(Write2(buffer, size, &processedSizeLocal, false)); + if (processedSizeLocal == 0) + return S_OK; + } + return S_OK; +} + + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testModeSpec, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + + if (allFilesMode) + numItems = m_Database.NewFormat ? 1: + (m_Database.LowLevel ? + m_Database.Items.Size(): + m_Database.Indices.Size()); + if (numItems == 0) + return S_OK; + bool testMode = (testModeSpec != 0); + + UInt64 currentTotalSize = 0; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + UInt32 i; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStream(streamSpec); + streamSpec->SetStream(m_Stream); + + if (m_Database.LowLevel) + { + UInt64 currentItemSize = 0; + UInt64 totalSize = 0; + if (m_Database.NewFormat) + totalSize = m_Database.NewFormatString.Length(); + else + for (i = 0; i < numItems; i++) + totalSize += m_Database.Items[allFilesMode ? i : indices[i]].Size; + extractCallback->SetTotal(totalSize); + + for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) + { + currentItemSize = 0; + lps->InSize = currentTotalSize; // Change it + lps->OutSize = currentTotalSize; + + RINOK(lps->SetCur()); + CMyComPtr realOutStream; + Int32 askMode= testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + if (m_Database.NewFormat) + { + if (index != 0) + return E_FAIL; + if (!testMode && !realOutStream) + continue; + if (!testMode) + { + UInt32 size = m_Database.NewFormatString.Length(); + RINOK(WriteStream(realOutStream, (const char *)m_Database.NewFormatString, size)); + } + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + const CItem &item = m_Database.Items[index]; + + currentItemSize = item.Size; + + if (!testMode && !realOutStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + if (item.Section != 0) + { + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod)); + continue; + } + + if (testMode) + { + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + + RINOK(m_Stream->Seek(m_Database.ContentOffset + item.Offset, STREAM_SEEK_SET, NULL)); + streamSpec->Init(item.Size); + + RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ? + NExtract::NOperationResult::kOK: + NExtract::NOperationResult::kDataError)); + } + return S_OK; + } + + UInt64 lastFolderIndex = ((UInt64)0 - 1); + for (i = 0; i < numItems; i++) + { + UInt32 index = allFilesMode ? i : indices[i]; + int entryIndex = m_Database.Indices[index]; + const CItem &item = m_Database.Items[entryIndex]; + UInt64 sectionIndex = item.Section; + if (item.IsDir() || item.Size == 0) + continue; + if (sectionIndex == 0) + { + currentTotalSize += item.Size; + continue; + } + const CSectionInfo §ion = m_Database.Sections[(int)item.Section]; + if (section.IsLzx()) + { + const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo; + UInt64 folderIndex = m_Database.GetFolder(index); + if (lastFolderIndex == folderIndex) + folderIndex++; + lastFolderIndex = m_Database.GetLastFolder(index); + for (; folderIndex <= lastFolderIndex; folderIndex++) + currentTotalSize += lzxInfo.GetFolderSize(); + } + } + + RINOK(extractCallback->SetTotal(currentTotalSize)); + + NCompress::NLzx::CDecoder *lzxDecoderSpec = 0; + CMyComPtr lzxDecoder; + CChmFolderOutStream *chmFolderOutStream = 0; + CMyComPtr outStream; + + currentTotalSize = 0; + + CRecordVector extractStatuses; + for (i = 0; i < numItems;) + { + RINOK(extractCallback->SetCompleted(¤tTotalSize)); + UInt32 index = allFilesMode ? i : indices[i]; + i++; + int entryIndex = m_Database.Indices[index]; + const CItem &item = m_Database.Items[entryIndex]; + UInt64 sectionIndex = item.Section; + Int32 askMode= testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + if (item.IsDir()) + { + CMyComPtr realOutStream; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + RINOK(extractCallback->PrepareOperation(askMode)); + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + + lps->InSize = currentTotalSize; // Change it + lps->OutSize = currentTotalSize; + + if (item.Size == 0 || sectionIndex == 0) + { + CMyComPtr realOutStream; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + if (!testMode && !realOutStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + Int32 opRes = NExtract::NOperationResult::kOK; + if (!testMode && item.Size != 0) + { + RINOK(m_Stream->Seek(m_Database.ContentOffset + item.Offset, STREAM_SEEK_SET, NULL)); + streamSpec->Init(item.Size); + RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); + if (copyCoderSpec->TotalSize != item.Size) + opRes = NExtract::NOperationResult::kDataError; + } + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(opRes)); + currentTotalSize += item.Size; + continue; + } + + const CSectionInfo §ion = m_Database.Sections[(int)sectionIndex]; + + if (!section.IsLzx()) + { + CMyComPtr realOutStream; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + if (!testMode && !realOutStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod)); + continue; + } + + const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo; + + if (chmFolderOutStream == 0) + { + chmFolderOutStream = new CChmFolderOutStream; + outStream = chmFolderOutStream; + } + + chmFolderOutStream->Init(&m_Database, extractCallback, testMode); + + if (lzxDecoderSpec == NULL) + { + lzxDecoderSpec = new NCompress::NLzx::CDecoder; + lzxDecoder = lzxDecoderSpec; + } + + UInt64 folderIndex = m_Database.GetFolder(index); + + UInt64 compressedPos = m_Database.ContentOffset + section.Offset; + UInt32 numDictBits = lzxInfo.GetNumDictBits(); + RINOK(lzxDecoderSpec->SetParams(numDictBits)); + + const CItem *lastItem = &item; + extractStatuses.Clear(); + extractStatuses.Add(true); + + for (;; folderIndex++) + { + RINOK(extractCallback->SetCompleted(¤tTotalSize)); + + UInt64 startPos = lzxInfo.GetFolderPos(folderIndex); + UInt64 finishPos = lastItem->Offset + lastItem->Size; + UInt64 limitFolderIndex = lzxInfo.GetFolder(finishPos); + + lastFolderIndex = m_Database.GetLastFolder(index); + UInt64 folderSize = lzxInfo.GetFolderSize(); + UInt64 unPackSize = folderSize; + if (extractStatuses.IsEmpty()) + chmFolderOutStream->m_StartIndex = index + 1; + else + chmFolderOutStream->m_StartIndex = index; + if (limitFolderIndex == folderIndex) + { + for (; i < numItems; i++) + { + UInt32 nextIndex = allFilesMode ? i : indices[i]; + int entryIndex = m_Database.Indices[nextIndex]; + const CItem &nextItem = m_Database.Items[entryIndex]; + if (nextItem.Section != sectionIndex) + break; + UInt64 nextFolderIndex = m_Database.GetFolder(nextIndex); + if (nextFolderIndex != folderIndex) + break; + for (index++; index < nextIndex; index++) + extractStatuses.Add(false); + extractStatuses.Add(true); + index = nextIndex; + lastItem = &nextItem; + if (nextItem.Size != 0) + finishPos = nextItem.Offset + nextItem.Size; + lastFolderIndex = m_Database.GetLastFolder(index); + } + } + unPackSize = MyMin(finishPos - startPos, unPackSize); + + chmFolderOutStream->m_FolderSize = folderSize; + chmFolderOutStream->m_PosInFolder = 0; + chmFolderOutStream->m_PosInSection = startPos; + chmFolderOutStream->m_ExtractStatuses = &extractStatuses; + chmFolderOutStream->m_NumFiles = extractStatuses.Size(); + chmFolderOutStream->m_CurrentIndex = 0; + try + { + UInt64 startBlock = lzxInfo.GetBlockIndexFromFolderIndex(folderIndex); + const CResetTable &rt = lzxInfo.ResetTable; + UInt32 numBlocks = (UInt32)rt.GetNumBlocks(unPackSize); + for (UInt32 b = 0; b < numBlocks; b++) + { + UInt64 completedSize = currentTotalSize + chmFolderOutStream->m_PosInSection - startPos; + RINOK(extractCallback->SetCompleted(&completedSize)); + UInt64 bCur = startBlock + b; + if (bCur >= rt.ResetOffsets.Size()) + return E_FAIL; + UInt64 offset = rt.ResetOffsets[(int)bCur]; + UInt64 compressedSize; + rt.GetCompressedSizeOfBlock(bCur, compressedSize); + UInt64 rem = finishPos - chmFolderOutStream->m_PosInSection; + if (rem > rt.BlockSize) + rem = rt.BlockSize; + RINOK(m_Stream->Seek(compressedPos + offset, STREAM_SEEK_SET, NULL)); + streamSpec->SetStream(m_Stream); + streamSpec->Init(compressedSize); + lzxDecoderSpec->SetKeepHistory(b > 0); + HRESULT res = lzxDecoder->Code(inStream, outStream, NULL, &rem, NULL); + if (res != S_OK) + { + if (res != S_FALSE) + return res; + throw 1; + } + } + } + catch(...) + { + RINOK(chmFolderOutStream->FlushCorrupted(unPackSize)); + } + currentTotalSize += folderSize; + if (folderIndex == lastFolderIndex) + break; + extractStatuses.Clear(); + } + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = m_Database.NewFormat ? 1: + (m_Database.LowLevel ? + m_Database.Items.Size(): + m_Database.Indices.Size()); + return S_OK; +} + +}} diff --git a/CPP/7zip/Archive/Chm/ChmHandler.h b/CPP/7zip/Archive/Chm/ChmHandler.h new file mode 100755 index 0000000..69075cc --- /dev/null +++ b/CPP/7zip/Archive/Chm/ChmHandler.h @@ -0,0 +1,29 @@ +// ChmHandler.h + +#ifndef __ARCHIVE_CHM_HANDLER_H +#define __ARCHIVE_CHM_HANDLER_H + +#include "Common/MyCom.h" +#include "../IArchive.h" +#include "ChmIn.h" + +namespace NArchive { +namespace NChm { + +class CHandler: + public IInArchive, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP1(IInArchive) + + INTERFACE_IInArchive(;) + +private: + CFilesDatabase m_Database; + CMyComPtr m_Stream; +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Chm/ChmHeader.cpp b/CPP/7zip/Archive/Chm/ChmHeader.cpp new file mode 100755 index 0000000..89b0bfc --- /dev/null +++ b/CPP/7zip/Archive/Chm/ChmHeader.cpp @@ -0,0 +1,24 @@ +// Archive/Chm/Header.h + +#include "StdAfx.h" + +#include "ChmHeader.h" + +namespace NArchive{ +namespace NChm{ +namespace NHeader{ + +UInt32 kItsfSignature = 0x46535449 + 1; +UInt32 kItolSignature = 0x4C4F5449 + 1; +static class CSignatureInitializer +{ +public: + CSignatureInitializer() + { + kItsfSignature--; + kItolSignature--; + } +}g_SignatureInitializer; + + +}}} diff --git a/CPP/7zip/Archive/Chm/ChmHeader.h b/CPP/7zip/Archive/Chm/ChmHeader.h new file mode 100755 index 0000000..ad6e0a9 --- /dev/null +++ b/CPP/7zip/Archive/Chm/ChmHeader.h @@ -0,0 +1,28 @@ +// Archive/Chm/Header.h + +#ifndef __ARCHIVE_CHM_HEADER_H +#define __ARCHIVE_CHM_HEADER_H + +#include "Common/Types.h" + +namespace NArchive { +namespace NChm { +namespace NHeader{ + +const UInt32 kItspSignature = 0x50535449; +const UInt32 kPmglSignature = 0x4C474D50; +const UInt32 kLzxcSignature = 0x43585A4C; + +const UInt32 kIfcmSignature = 0x4D434649; +const UInt32 kAollSignature = 0x4C4C4F41; +const UInt32 kCaolSignature = 0x4C4F4143; + +extern UInt32 kItsfSignature; + +extern UInt32 kItolSignature; +const UInt32 kItlsSignature = 0x534C5449; +UInt64 inline GetHxsSignature() { return ((UInt64)kItlsSignature << 32) | kItolSignature; } + +}}} + +#endif diff --git a/CPP/7zip/Archive/Chm/ChmIn.cpp b/CPP/7zip/Archive/Chm/ChmIn.cpp new file mode 100755 index 0000000..78ea590 --- /dev/null +++ b/CPP/7zip/Archive/Chm/ChmIn.cpp @@ -0,0 +1,937 @@ +// Archive/ChmIn.cpp + +#include "StdAfx.h" + +#include "Common/IntToString.h" +#include "Common/UTFConvert.h" + +#include "../../Common/LimitedStreams.h" + +#include "ChmIn.h" + +namespace NArchive { +namespace NChm { + +// define CHM_LOW, if you want to see low level items +// #define CHM_LOW + +static const GUID kChmLzxGuid = { 0x7FC28940, 0x9D31, 0x11D0, { 0x9B, 0x27, 0x00, 0xA0, 0xC9, 0x1E, 0x9C, 0x7C } }; +static const GUID kHelp2LzxGuid = { 0x0A9007C6, 0x4076, 0x11D3, { 0x87, 0x89, 0x00, 0x00, 0xF8, 0x10, 0x57, 0x54 } }; +static const GUID kDesGuid = { 0x67F6E4A2, 0x60BF, 0x11D3, { 0x85, 0x40, 0x00, 0xC0, 0x4F, 0x58, 0xC3, 0xCF } }; + +static bool AreGuidsEqual(REFGUID g1, REFGUID g2) +{ + if (g1.Data1 != g2.Data1 || + g1.Data2 != g2.Data2 || + g1.Data3 != g2.Data3) + return false; + for (int i = 0; i < 8; i++) + if (g1.Data4[i] != g2.Data4[i]) + return false; + return true; +} + +static char GetHex(Byte value) +{ + return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); +} + +static void PrintByte(Byte b, AString &s) +{ + s += GetHex(b >> 4); + s += GetHex(b & 0xF); +} + +static void PrintUInt16(UInt16 v, AString &s) +{ + PrintByte((Byte)(v >> 8), s); + PrintByte((Byte)v, s); +} + +static void PrintUInt32(UInt32 v, AString &s) +{ + PrintUInt16((UInt16)(v >> 16), s); + PrintUInt16((UInt16)v, s); +} + +AString CMethodInfo::GetGuidString() const +{ + AString s; + s += '{'; + PrintUInt32(Guid.Data1, s); + s += '-'; + PrintUInt16(Guid.Data2, s); + s += '-'; + PrintUInt16(Guid.Data3, s); + s += '-'; + PrintByte(Guid.Data4[0], s); + PrintByte(Guid.Data4[1], s); + s += '-'; + for (int i = 2; i < 8; i++) + PrintByte(Guid.Data4[i], s); + s += '}'; + return s; +} + +bool CMethodInfo::IsLzx() const +{ + if (AreGuidsEqual(Guid, kChmLzxGuid)) + return true; + return AreGuidsEqual(Guid, kHelp2LzxGuid); +} + +bool CMethodInfo::IsDes() const +{ + return AreGuidsEqual(Guid, kDesGuid); +} + +UString CMethodInfo::GetName() const +{ + UString s; + if (IsLzx()) + { + s = L"LZX:"; + wchar_t temp[16]; + ConvertUInt32ToString(LzxInfo.GetNumDictBits(), temp); + s += temp; + } + else + { + AString s2; + if (IsDes()) + s2 = "DES"; + else + { + s2 = GetGuidString(); + if (ControlData.GetCapacity() > 0) + { + s2 += ':'; + for (size_t i = 0; i < ControlData.GetCapacity(); i++) + PrintByte(ControlData[i], s2); + } + } + ConvertUTF8ToUnicode(s2, s); + } + return s; +} + +bool CSectionInfo::IsLzx() const +{ + if (Methods.Size() != 1) + return false; + return Methods[0].IsLzx(); +} + +UString CSectionInfo::GetMethodName() const +{ + UString s; + if (!IsLzx()) + { + UString temp; + if (ConvertUTF8ToUnicode(Name, temp)) + s += temp; + s += L": "; + } + for (int i = 0; i < Methods.Size(); i++) + { + if (i != 0) + s += L' '; + s += Methods[i].GetName(); + } + return s; +} + +Byte CInArchive::ReadByte() +{ + Byte b; + if (!_inBuffer.ReadByte(b)) + throw 1; + return b; +} + +void CInArchive::Skip(size_t size) +{ + while (size-- != 0) + ReadByte(); +} + +void CInArchive::ReadBytes(Byte *data, UInt32 size) +{ + for (UInt32 i = 0; i < size; i++) + data[i] = ReadByte(); +} + +UInt16 CInArchive::ReadUInt16() +{ + UInt16 value = 0; + for (int i = 0; i < 2; i++) + value |= ((UInt16)(ReadByte()) << (8 * i)); + return value; +} + +UInt32 CInArchive::ReadUInt32() +{ + UInt32 value = 0; + for (int i = 0; i < 4; i++) + value |= ((UInt32)(ReadByte()) << (8 * i)); + return value; +} + +UInt64 CInArchive::ReadUInt64() +{ + UInt64 value = 0; + for (int i = 0; i < 8; i++) + value |= ((UInt64)(ReadByte()) << (8 * i)); + return value; +} + +UInt64 CInArchive::ReadEncInt() +{ + UInt64 val = 0;; + for (int i = 0; i < 10; i++) + { + Byte b = ReadByte(); + val |= (b & 0x7F); + if (b < 0x80) + return val; + val <<= 7; + } + throw 1; +} + +void CInArchive::ReadGUID(GUID &g) +{ + g.Data1 = ReadUInt32(); + g.Data2 = ReadUInt16(); + g.Data3 = ReadUInt16(); + ReadBytes(g.Data4, 8); +} + +void CInArchive::ReadString(int size, AString &s) +{ + s.Empty(); + while(size-- != 0) + { + char c = (char)ReadByte(); + if (c == 0) + { + Skip(size); + return; + } + s += c; + } +} + +void CInArchive::ReadUString(int size, UString &s) +{ + s.Empty(); + while(size-- != 0) + { + wchar_t c = ReadUInt16(); + if (c == 0) + { + Skip(2 * size); + return; + } + s += c; + } +} + +HRESULT CInArchive::ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size) +{ + RINOK(inStream->Seek(pos, STREAM_SEEK_SET, NULL)); + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr limitedStream(streamSpec); + streamSpec->SetStream(inStream); + streamSpec->Init(size); + _inBuffer.SetStream(limitedStream); + _inBuffer.Init(); + return S_OK; +} + +HRESULT CInArchive::ReadDirEntry(CDatabase &database) +{ + CItem item; + UInt64 nameLength = ReadEncInt(); + if (nameLength == 0 || nameLength >= 0x10000000) + return S_FALSE; + ReadString((int)nameLength, item.Name); + item.Section = ReadEncInt(); + item.Offset = ReadEncInt(); + item.Size = ReadEncInt(); + database.Items.Add(item); + return S_OK; +} + +HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database) +{ + UInt32 headerSize = ReadUInt32(); + if (headerSize != 0x60) + return S_FALSE; + UInt32 unknown1 = ReadUInt32(); + if (unknown1 != 0 && unknown1 != 1) // it's 0 in one .sll file + return S_FALSE; + /* UInt32 timeStamp = */ ReadUInt32(); + // Considered as a big-endian DWORD, it appears to contain seconds (MSB) and + // fractional seconds (second byte). + // The third and fourth bytes may contain even more fractional bits. + // The 4 least significant bits in the last byte are constant. + /* UInt32 lang = */ ReadUInt32(); + GUID g; + ReadGUID(g); // {7C01FD10-7BAA-11D0-9E0C-00A0-C922-E6EC} + ReadGUID(g); // {7C01FD11-7BAA-11D0-9E0C-00A0-C922-E6EC} + const int kNumSections = 2; + UInt64 sectionOffsets[kNumSections]; + UInt64 sectionSizes[kNumSections]; + int i; + for (i = 0; i < kNumSections; i++) + { + sectionOffsets[i] = ReadUInt64(); + sectionSizes[i] = ReadUInt64(); + } + // if (chmVersion == 3) + database.ContentOffset = ReadUInt64(); + /* + else + database.ContentOffset = _startPosition + 0x58 + */ + + /* + // Section 0 + ReadChunk(inStream, sectionOffsets[0], sectionSizes[0]); + if (sectionSizes[0] != 0x18) + return S_FALSE; + ReadUInt32(); // unknown: 01FE + ReadUInt32(); // unknown: 0 + UInt64 fileSize = ReadUInt64(); + ReadUInt32(); // unknown: 0 + ReadUInt32(); // unknown: 0 + */ + + // Section 1: The Directory Listing + ReadChunk(inStream, sectionOffsets[1], sectionSizes[1]); + if (ReadUInt32() != NHeader::kItspSignature) + return S_FALSE; + if (ReadUInt32() != 1) // version + return S_FALSE; + /* UInt32 dirHeaderSize = */ ReadUInt32(); + ReadUInt32(); // 0x0A (unknown) + UInt32 dirChunkSize = ReadUInt32(); // $1000 + if (dirChunkSize < 32) + return S_FALSE; + /* UInt32 density = */ ReadUInt32(); // "Density" of quickref section, usually 2. + /* UInt32 depth = */ ReadUInt32(); // Depth of the index tree: 1 there is no index, + // 2 if there is one level of PMGI chunks. + + /* UInt32 chunkNumber = */ ReadUInt32(); // Chunk number of root index chunk, -1 if there is none + // (though at least one file has 0 despite there being no + // index chunk, probably a bug.) + /* UInt32 firstPmglChunkNumber = */ ReadUInt32(); // Chunk number of first PMGL (listing) chunk + /* UInt32 lastPmglChunkNumber = */ ReadUInt32(); // Chunk number of last PMGL (listing) chunk + ReadUInt32(); // -1 (unknown) + UInt32 numDirChunks = ReadUInt32(); // Number of directory chunks (total) + /* UInt32 windowsLangId = */ ReadUInt32(); + ReadGUID(g); // {5D02926A-212E-11D0-9DF9-00A0C922E6EC} + ReadUInt32(); // 0x54 (This is the length again) + ReadUInt32(); // -1 (unknown) + ReadUInt32(); // -1 (unknown) + ReadUInt32(); // -1 (unknown) + + for (UInt32 ci = 0; ci < numDirChunks; ci++) + { + UInt64 chunkPos = _inBuffer.GetProcessedSize(); + if (ReadUInt32() == NHeader::kPmglSignature) + { + // The quickref area is written backwards from the end of the chunk. + // One quickref entry exists for every n entries in the file, where n + // is calculated as 1 + (1 << quickref density). So for density = 2, n = 5. + + UInt32 quickrefLength = ReadUInt32(); // Length of free space and/or quickref area at end of directory chunk + if (quickrefLength > dirChunkSize || quickrefLength < 2) + return S_FALSE; + ReadUInt32(); // Always 0 + ReadUInt32(); // Chunk number of previous listing chunk when reading + // directory in sequence (-1 if this is the first listing chunk) + ReadUInt32(); // Chunk number of next listing chunk when reading + // directory in sequence (-1 if this is the last listing chunk) + int numItems = 0; + for (;;) + { + UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos; + UInt32 offsetLimit = dirChunkSize - quickrefLength; + if (offset > offsetLimit) + return S_FALSE; + if (offset == offsetLimit) + break; + RINOK(ReadDirEntry(database)); + numItems++; + } + Skip(quickrefLength - 2); + if (ReadUInt16() != numItems) + return S_FALSE; + } + else + Skip(dirChunkSize - 4); + } + return S_OK; +} + +HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database) +{ + if (ReadUInt32() != 1) // version + return S_FALSE; + if (ReadUInt32() != 0x28) // Location of header section table + return S_FALSE; + UInt32 numHeaderSections = ReadUInt32(); + const int kNumHeaderSectionsMax = 5; + if (numHeaderSections != kNumHeaderSectionsMax) + return S_FALSE; + ReadUInt32(); // Length of post-header table + GUID g; + ReadGUID(g); // {0A9007C1-4076-11D3-8789-0000F8105754} + + // header section table + UInt64 sectionOffsets[kNumHeaderSectionsMax]; + UInt64 sectionSizes[kNumHeaderSectionsMax]; + UInt32 i; + for (i = 0; i < numHeaderSections; i++) + { + sectionOffsets[i] = ReadUInt64(); + sectionSizes[i] = ReadUInt64(); + } + + // Post-Header + ReadUInt32(); // 2 + ReadUInt32(); // 0x98: offset to CAOL from beginning of post-header) + // ----- Directory information + ReadUInt64(); // Chunk number of top-level AOLI chunk in directory, or -1 + ReadUInt64(); // Chunk number of first AOLL chunk in directory + ReadUInt64(); // Chunk number of last AOLL chunk in directory + ReadUInt64(); // 0 (unknown) + ReadUInt32(); // $2000 (Directory chunk size of directory) + ReadUInt32(); // Quickref density for main directory, usually 2 + ReadUInt32(); // 0 (unknown) + ReadUInt32(); // Depth of main directory index tree + // 1 there is no index, 2 if there is one level of AOLI chunks. + ReadUInt64(); // 0 (unknown) + UInt64 numDirEntries = ReadUInt64(); // Number of directory entries + // ----- Directory Index Information + ReadUInt64(); // -1 (unknown, probably chunk number of top-level AOLI in directory index) + ReadUInt64(); // Chunk number of first AOLL chunk in directory index + ReadUInt64(); // Chunk number of last AOLL chunk in directory index + ReadUInt64(); // 0 (unknown) + ReadUInt32(); // $200 (Directory chunk size of directory index) + ReadUInt32(); // Quickref density for directory index, usually 2 + ReadUInt32(); // 0 (unknown) + ReadUInt32(); // Depth of directory index index tree. + ReadUInt64(); // Possibly flags -- sometimes 1, sometimes 0. + ReadUInt64(); // Number of directory index entries (same as number of AOLL + // chunks in main directory) + + // (The obvious guess for the following two fields, which recur in a number + // of places, is they are maximum sizes for the directory and directory index. + // However, I have seen no direct evidence that this is the case.) + + ReadUInt32(); // $100000 (Same as field following chunk size in directory) + ReadUInt32(); // $20000 (Same as field following chunk size in directory index) + + ReadUInt64(); // 0 (unknown) + if (ReadUInt32() != NHeader::kCaolSignature) + return S_FALSE; + if (ReadUInt32() != 2) // (Most likely a version number) + return S_FALSE; + UInt32 caolLength = ReadUInt32(); // $50 (Length of the CAOL section, which includes the ITSF section) + if (caolLength >= 0x2C) + { + /* UInt32 c7 = */ ReadUInt16(); // Unknown. Remains the same when identical files are built. + // Does not appear to be a checksum. Many files have + // 'HH' (HTML Help?) here, indicating this may be a compiler ID + // field. But at least one ITOL/ITLS compiler does not set this + // field to a constant value. + ReadUInt16(); // 0 (Unknown. Possibly part of 00A4 field) + ReadUInt32(); // Unknown. Two values have been seen -- $43ED, and 0. + ReadUInt32(); // $2000 (Directory chunk size of directory) + ReadUInt32(); // $200 (Directory chunk size of directory index) + ReadUInt32(); // $100000 (Same as field following chunk size in directory) + ReadUInt32(); // $20000 (Same as field following chunk size in directory index) + ReadUInt32(); // 0 (unknown) + ReadUInt32(); // 0 (Unknown) + if (caolLength == 0x2C) + { + database.ContentOffset = 0; + database.NewFormat = true; + } + else if (caolLength == 0x50) + { + ReadUInt32(); // 0 (Unknown) + if (ReadUInt32() != NHeader::kItsfSignature) + return S_FALSE; + if (ReadUInt32() != 4) // $4 (Version number -- CHM uses 3) + return S_FALSE; + if (ReadUInt32() != 0x20) // $20 (length of ITSF) + return S_FALSE; + UInt32 unknown = ReadUInt32(); + if (unknown != 0 && unknown != 1) // = 0 for some HxW files, 1 in other cases; + return S_FALSE; + database.ContentOffset = _startPosition + ReadUInt64(); + /* UInt32 timeStamp = */ ReadUInt32(); + // A timestamp of some sort. + // Considered as a big-endian DWORD, it appears to contain + // seconds (MSB) and fractional seconds (second byte). + // The third and fourth bytes may contain even more fractional + // bits. The 4 least significant bits in the last byte are constant. + /* UInt32 lang = */ ReadUInt32(); // BE? + } + else + return S_FALSE; + } + + /* + // Section 0 + ReadChunk(inStream, _startPosition + sectionOffsets[0], sectionSizes[0]); + if (sectionSizes[0] != 0x18) + return S_FALSE; + ReadUInt32(); // unknown: 01FE + ReadUInt32(); // unknown: 0 + UInt64 fileSize = ReadUInt64(); + ReadUInt32(); // unknown: 0 + ReadUInt32(); // unknown: 0 + */ + + // Section 1: The Directory Listing + ReadChunk(inStream, _startPosition + sectionOffsets[1], sectionSizes[1]); + if (ReadUInt32() != NHeader::kIfcmSignature) + return S_FALSE; + if (ReadUInt32() != 1) // (probably a version number) + return S_FALSE; + UInt32 dirChunkSize = ReadUInt32(); // $2000 + if (dirChunkSize < 64) + return S_FALSE; + ReadUInt32(); // $100000 (unknown) + ReadUInt32(); // -1 (unknown) + ReadUInt32(); // -1 (unknown) + UInt32 numDirChunks = ReadUInt32(); + ReadUInt32(); // 0 (unknown, probably high word of above) + + for (UInt32 ci = 0; ci < numDirChunks; ci++) + { + UInt64 chunkPos = _inBuffer.GetProcessedSize(); + if (ReadUInt32() == NHeader::kAollSignature) + { + UInt32 quickrefLength = ReadUInt32(); // Length of quickref area at end of directory chunk + if (quickrefLength > dirChunkSize || quickrefLength < 2) + return S_FALSE; + ReadUInt64(); // Directory chunk number + // This must match physical position in file, that is + // the chunk size times the chunk number must be the + // offset from the end of the directory header. + ReadUInt64(); // Chunk number of previous listing chunk when reading + // directory in sequence (-1 if first listing chunk) + ReadUInt64(); // Chunk number of next listing chunk when reading + // directory in sequence (-1 if last listing chunk) + ReadUInt64(); // Number of first listing entry in this chunk + ReadUInt32(); // 1 (unknown -- other values have also been seen here) + ReadUInt32(); // 0 (unknown) + + int numItems = 0; + for (;;) + { + UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos; + UInt32 offsetLimit = dirChunkSize - quickrefLength; + if (offset > offsetLimit) + return S_FALSE; + if (offset == offsetLimit) + break; + if (database.NewFormat) + { + UInt16 nameLength = ReadUInt16(); + if (nameLength == 0) + return S_FALSE; + UString name; + ReadUString((int)nameLength, name); + AString s; + ConvertUnicodeToUTF8(name, s); + Byte b = ReadByte(); + s += ' '; + PrintByte(b, s); + s += ' '; + UInt64 len = ReadEncInt(); + // then number of items ? + // then length ? + // then some data (binary encoding?) + while (len-- != 0) + { + b = ReadByte(); + PrintByte(b, s); + } + database.NewFormatString += s; + database.NewFormatString += "\r\n"; + } + else + { + RINOK(ReadDirEntry(database)); + } + numItems++; + } + Skip(quickrefLength - 2); + if (ReadUInt16() != numItems) + return S_FALSE; + if (numItems > numDirEntries) + return S_FALSE; + numDirEntries -= numItems; + } + else + Skip(dirChunkSize - 4); + } + return numDirEntries == 0 ? S_OK : S_FALSE; +} + +HRESULT CInArchive::DecompressStream(IInStream *inStream, const CDatabase &database, const AString &name) +{ + int index = database.FindItem(name); + if (index < 0) + return S_FALSE; + const CItem &item = database.Items[index]; + _chunkSize = item.Size; + return ReadChunk(inStream, database.ContentOffset + item.Offset, item.Size); +} + + +#define DATA_SPACE "::DataSpace/" +static const char *kNameList = DATA_SPACE "NameList"; +static const char *kStorage = DATA_SPACE "Storage/"; +static const char *kContent = "Content"; +static const char *kControlData = "ControlData"; +static const char *kSpanInfo = "SpanInfo"; +static const char *kTransform = "Transform/"; +static const char *kResetTable = "/InstanceData/ResetTable"; +static const char *kTransformList = "List"; + +static AString GetSectionPrefix(const AString &name) +{ + return AString(kStorage) + name + AString("/"); +} + +#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } + +static int CompareFiles(const int *p1, const int *p2, void *param) +{ + const CObjectVector &items = *(const CObjectVector *)param; + const CItem &item1 = items[*p1]; + const CItem &item2 = items[*p2]; + bool isDir1 = item1.IsDir(); + bool isDir2 = item2.IsDir(); + if (isDir1 && !isDir2) + return -1; + if (isDir2) + { + if (isDir1) + return MyCompare(*p1, *p2); + return 1; + } + RINOZ(MyCompare(item1.Section, item2.Section)); + RINOZ(MyCompare(item1.Offset, item2.Offset)); + RINOZ(MyCompare(item1.Size, item2.Size)); + return MyCompare(*p1, *p2); +} + +void CFilesDatabase::SetIndices() +{ + for (int i = 0; i < Items.Size(); i++) + { + const CItem &item = Items[i]; + if (item.IsUserItem() && item.Name.Length() != 1) + Indices.Add(i); + } +} + +void CFilesDatabase::Sort() +{ + Indices.Sort(CompareFiles, (void *)&Items); +} + +bool CFilesDatabase::Check() +{ + UInt64 maxPos = 0; + UInt64 prevSection = 0; + for(int i = 0; i < Indices.Size(); i++) + { + const CItem &item = Items[Indices[i]]; + if (item.Section == 0 || item.IsDir()) + continue; + if (item.Section != prevSection) + { + prevSection = item.Section; + maxPos = 0; + continue; + } + if (item.Offset < maxPos) + return false; + maxPos = item.Offset + item.Size; + if (maxPos < item.Offset) + return false; + } + return true; +} + +HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database) +{ + { + // The NameList file + RINOK(DecompressStream(inStream, database, kNameList)); + /* UInt16 length = */ ReadUInt16(); + UInt16 numSections = ReadUInt16(); + for (int i = 0; i < numSections; i++) + { + CSectionInfo section; + UInt16 nameLength = ReadUInt16(); + UString name; + ReadUString(nameLength, name); + if (ReadUInt16() != 0) + return S_FALSE; + if (!ConvertUnicodeToUTF8(name, section.Name)) + return S_FALSE; + database.Sections.Add(section); + } + } + + int i; + for (i = 1; i < database.Sections.Size(); i++) + { + CSectionInfo §ion = database.Sections[i]; + AString sectionPrefix = GetSectionPrefix(section.Name); + { + // Content + int index = database.FindItem(sectionPrefix + kContent); + if (index < 0) + return S_FALSE; + const CItem &item = database.Items[index]; + section.Offset = item.Offset; + section.CompressedSize = item.Size; + } + AString transformPrefix = sectionPrefix + kTransform; + if (database.Help2Format) + { + // Transform List + RINOK(DecompressStream(inStream, database, transformPrefix + kTransformList)); + if ((_chunkSize & 0xF) != 0) + return S_FALSE; + int numGuids = (int)(_chunkSize / 0x10); + if (numGuids < 1) + return S_FALSE; + for (int i = 0; i < numGuids; i++) + { + CMethodInfo method; + ReadGUID(method.Guid); + section.Methods.Add(method); + } + } + else + { + CMethodInfo method; + method.Guid = kChmLzxGuid; + section.Methods.Add(method); + } + + { + // Control Data + RINOK(DecompressStream(inStream, database, sectionPrefix + kControlData)); + for (int mi = 0; mi < section.Methods.Size(); mi++) + { + CMethodInfo &method = section.Methods[mi]; + UInt32 numDWORDS = ReadUInt32(); + if (method.IsLzx()) + { + if (numDWORDS < 5) + return S_FALSE; + if (ReadUInt32() != NHeader::kLzxcSignature) + return S_FALSE; + CLzxInfo &li = method.LzxInfo; + li.Version = ReadUInt32(); + if (li.Version != 2 && li.Version != 3) + return S_FALSE; + li.ResetInterval = ReadUInt32(); + li.WindowSize = ReadUInt32(); + li.CacheSize = ReadUInt32(); + if ( + li.ResetInterval != 1 && + li.ResetInterval != 2 && + li.ResetInterval != 4 && + li.ResetInterval != 8 && + li.ResetInterval != 16 && + li.ResetInterval != 32 && + li.ResetInterval != 64) + return S_FALSE; + if ( + li.WindowSize != 1 && + li.WindowSize != 2 && + li.WindowSize != 4 && + li.WindowSize != 8 && + li.WindowSize != 16 && + li.WindowSize != 32 && + li.WindowSize != 64) + return S_FALSE; + numDWORDS -= 5; + while (numDWORDS-- != 0) + ReadUInt32(); + } + else + { + UInt32 numBytes = numDWORDS * 4; + method.ControlData.SetCapacity(numBytes); + ReadBytes(method.ControlData, numBytes); + } + } + } + + { + // SpanInfo + RINOK(DecompressStream(inStream, database, sectionPrefix + kSpanInfo)); + section.UncompressedSize = ReadUInt64(); + } + + // read ResetTable for LZX + for (int mi = 0; mi < section.Methods.Size(); mi++) + { + CMethodInfo &method = section.Methods[mi]; + if (method.IsLzx()) + { + // ResetTable; + RINOK(DecompressStream(inStream, database, transformPrefix + + method.GetGuidString() + kResetTable)); + CResetTable &rt = method.LzxInfo.ResetTable; + if (_chunkSize < 4) + { + if (_chunkSize != 0) + return S_FALSE; + // ResetTable is empty in .chw files + if (section.UncompressedSize != 0) + return S_FALSE; + rt.UncompressedSize = 0; + rt.CompressedSize = 0; + rt.BlockSize = 0; + } + else + { + UInt32 ver = ReadUInt32(); // 2 unknown (possibly a version number) + if (ver != 2 && ver != 3) + return S_FALSE; + UInt32 numEntries = ReadUInt32(); + if (ReadUInt32() != 8) // Size of table entry (bytes) + return S_FALSE; + if (ReadUInt32() != 0x28) // Length of table header + return S_FALSE; + rt.UncompressedSize = ReadUInt64(); + rt.CompressedSize = ReadUInt64(); + rt.BlockSize = ReadUInt64(); // 0x8000 block size for locations below + if (rt.BlockSize != 0x8000) + return S_FALSE; + rt.ResetOffsets.Reserve(numEntries); + for (UInt32 i = 0; i < numEntries; i++) + rt.ResetOffsets.Add(ReadUInt64()); + } + } + } + } + + database.SetIndices(); + database.Sort(); + return database.Check() ? S_OK : S_FALSE; +} + +HRESULT CInArchive::Open2(IInStream *inStream, + const UInt64 *searchHeaderSizeLimit, + CFilesDatabase &database) +{ + database.Clear(); + + RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &_startPosition)); + + database.Help2Format = false; + const UInt32 chmVersion = 3; + { + if (!_inBuffer.Create(1 << 14)) + return E_OUTOFMEMORY; + _inBuffer.SetStream(inStream); + _inBuffer.Init(); + UInt64 value = 0; + const int kSignatureSize = 8; + UInt64 hxsSignature = NHeader::GetHxsSignature(); + UInt64 chmSignature = ((UInt64)chmVersion << 32)| NHeader::kItsfSignature; + UInt64 limit = 1 << 18; + if (searchHeaderSizeLimit) + if (limit > *searchHeaderSizeLimit) + limit = *searchHeaderSizeLimit; + + for (;;) + { + Byte b; + if (!_inBuffer.ReadByte(b)) + return S_FALSE; + value >>= 8; + value |= ((UInt64)b) << ((kSignatureSize - 1) * 8); + if (_inBuffer.GetProcessedSize() >= kSignatureSize) + { + if (value == chmSignature) + break; + if (value == hxsSignature) + { + database.Help2Format = true; + break; + } + if (_inBuffer.GetProcessedSize() > limit) + return S_FALSE; + } + } + _startPosition += _inBuffer.GetProcessedSize() - kSignatureSize; + } + + if (database.Help2Format) + { + RINOK(OpenHelp2(inStream, database)); + if (database.NewFormat) + return S_OK; + } + else + { + RINOK(OpenChm(inStream, database)); + } + + #ifndef CHM_LOW + try + { + HRESULT res = OpenHighLevel(inStream, database); + if (res == S_FALSE) + { + database.HighLevelClear(); + return S_OK; + } + RINOK(res); + database.LowLevel = false; + } + catch(...) + { + return S_OK; + } + #endif + return S_OK; +} + +HRESULT CInArchive::Open(IInStream *inStream, + const UInt64 *searchHeaderSizeLimit, + CFilesDatabase &database) +{ + try + { + HRESULT res = Open2(inStream, searchHeaderSizeLimit, database); + _inBuffer.ReleaseStream(); + return res; + } + catch(...) + { + _inBuffer.ReleaseStream(); + throw; + } +} + +}} diff --git a/CPP/7zip/Archive/Chm/ChmIn.h b/CPP/7zip/Archive/Chm/ChmIn.h new file mode 100755 index 0000000..8b6eb97 --- /dev/null +++ b/CPP/7zip/Archive/Chm/ChmIn.h @@ -0,0 +1,244 @@ +// Archive/ChmIn.h + +#ifndef __ARCHIVE_CHM_IN_H +#define __ARCHIVE_CHM_IN_H + +#include "Common/Buffer.h" +#include "Common/MyString.h" + +#include "../../IStream.h" +#include "../../Common/InBuffer.h" + +#include "ChmHeader.h" + +namespace NArchive { +namespace NChm { + +struct CItem +{ + UInt64 Section; + UInt64 Offset; + UInt64 Size; + AString Name; + + bool IsFormatRelatedItem() const + { + if (Name.Length() < 2) + return false; + return Name[0] == ':' && Name[1] == ':'; + } + + bool IsUserItem() const + { + if (Name.Length() < 2) + return false; + return Name[0] == '/'; + } + + bool IsDir() const + { + if (Name.Length() == 0) + return false; + return (Name[Name.Length() - 1] == '/'); + } +}; + +struct CDatabase +{ + UInt64 ContentOffset; + CObjectVector Items; + AString NewFormatString; + bool Help2Format; + bool NewFormat; + + int FindItem(const AString &name) const + { + for (int i = 0; i < Items.Size(); i++) + if (Items[i].Name == name) + return i; + return -1; + } + + void Clear() + { + NewFormat = false; + NewFormatString.Empty(); + Help2Format = false; + Items.Clear(); + } +}; + +struct CResetTable +{ + UInt64 UncompressedSize; + UInt64 CompressedSize; + UInt64 BlockSize; + CRecordVector ResetOffsets; + bool GetCompressedSizeOfBlocks(UInt64 blockIndex, UInt32 numBlocks, UInt64 &size) const + { + if (blockIndex >= ResetOffsets.Size()) + return false; + UInt64 startPos = ResetOffsets[(int)blockIndex]; + if (blockIndex + numBlocks >= ResetOffsets.Size()) + size = CompressedSize - startPos; + else + size = ResetOffsets[(int)(blockIndex + numBlocks)] - startPos; + return true; + } + bool GetCompressedSizeOfBlock(UInt64 blockIndex, UInt64 &size) const + { + return GetCompressedSizeOfBlocks(blockIndex, 1, size); + } + UInt64 GetNumBlocks(UInt64 size) const + { + return (size + BlockSize - 1) / BlockSize; + } +}; + +struct CLzxInfo +{ + UInt32 Version; + UInt32 ResetInterval; + UInt32 WindowSize; + UInt32 CacheSize; + CResetTable ResetTable; + + UInt32 GetNumDictBits() const + { + if (Version == 2 || Version == 3) + { + for (int i = 0; i <= 31; i++) + if (((UInt32)1 << i) >= WindowSize) + return 15 + i; + } + return 0; + } + + UInt64 GetFolderSize() const { return ResetTable.BlockSize * ResetInterval; }; + UInt64 GetFolder(UInt64 offset) const { return offset / GetFolderSize(); }; + UInt64 GetFolderPos(UInt64 folderIndex) const { return folderIndex * GetFolderSize(); }; + UInt64 GetBlockIndexFromFolderIndex(UInt64 folderIndex) const { return folderIndex * ResetInterval; }; + bool GetOffsetOfFolder(UInt64 folderIndex, UInt64 &offset) const + { + UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex); + if (blockIndex >= ResetTable.ResetOffsets.Size()) + return false; + offset = ResetTable.ResetOffsets[(int)blockIndex]; + return true; + } + bool GetCompressedSizeOfFolder(UInt64 folderIndex, UInt64 &size) const + { + UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex); + return ResetTable.GetCompressedSizeOfBlocks(blockIndex, ResetInterval, size); + } +}; + +struct CMethodInfo +{ + GUID Guid; + CByteBuffer ControlData; + CLzxInfo LzxInfo; + bool IsLzx() const; + bool IsDes() const; + AString GetGuidString() const; + UString GetName() const; +}; + +struct CSectionInfo +{ + UInt64 Offset; + UInt64 CompressedSize; + UInt64 UncompressedSize; + + AString Name; + CObjectVector Methods; + + bool IsLzx() const; + UString GetMethodName() const; +}; + +class CFilesDatabase: public CDatabase +{ +public: + bool LowLevel; + CRecordVector Indices; + CObjectVector Sections; + + UInt64 GetFileSize(int fileIndex) const { return Items[Indices[fileIndex]].Size; } + UInt64 GetFileOffset(int fileIndex) const { return Items[Indices[fileIndex]].Offset; } + + UInt64 GetFolder(int fileIndex) const + { + const CItem &item = Items[Indices[fileIndex]]; + const CSectionInfo §ion = Sections[(int)item.Section]; + if (section.IsLzx()) + return section.Methods[0].LzxInfo.GetFolder(item.Offset); + return 0; + } + + UInt64 GetLastFolder(int fileIndex) const + { + const CItem &item = Items[Indices[fileIndex]]; + const CSectionInfo §ion = Sections[(int)item.Section]; + if (section.IsLzx()) + return section.Methods[0].LzxInfo.GetFolder(item.Offset + item.Size - 1); + return 0; + } + + void HighLevelClear() + { + LowLevel = true; + Indices.Clear(); + Sections.Clear(); + } + + void Clear() + { + CDatabase::Clear(); + HighLevelClear(); + } + void SetIndices(); + void Sort(); + bool Check(); +}; + +class CProgressVirt +{ +public: + STDMETHOD(SetTotal)(const UInt64 *numFiles) PURE; + STDMETHOD(SetCompleted)(const UInt64 *numFiles) PURE; +}; + +class CInArchive +{ + UInt64 _startPosition; + ::CInBuffer _inBuffer; + UInt64 _chunkSize; + + Byte ReadByte(); + void ReadBytes(Byte *data, UInt32 size); + void Skip(size_t size); + UInt16 ReadUInt16(); + UInt32 ReadUInt32(); + UInt64 ReadUInt64(); + UInt64 ReadEncInt(); + void ReadString(int size, AString &s); + void ReadUString(int size, UString &s); + void ReadGUID(GUID &g); + + HRESULT ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size); + + HRESULT ReadDirEntry(CDatabase &database); + HRESULT DecompressStream(IInStream *inStream, const CDatabase &database, const AString &name); + +public: + HRESULT OpenChm(IInStream *inStream, CDatabase &database); + HRESULT OpenHelp2(IInStream *inStream, CDatabase &database); + HRESULT OpenHighLevel(IInStream *inStream, CFilesDatabase &database); + HRESULT Open2(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, CFilesDatabase &database); + HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, CFilesDatabase &database); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Chm/ChmRegister.cpp b/CPP/7zip/Archive/Chm/ChmRegister.cpp new file mode 100755 index 0000000..8f1f2ec --- /dev/null +++ b/CPP/7zip/Archive/Chm/ChmRegister.cpp @@ -0,0 +1,13 @@ +// ChmRegister.cpp + +#include "StdAfx.h" + +#include "../../Common/RegisterArc.h" + +#include "ChmHandler.h" +static IInArchive *CreateArc() { return new NArchive::NChm::CHandler; } + +static CArcInfo g_ArcInfo = + { L"Chm", L"chm chi chq chw hxs hxi hxr hxq hxw lit", 0, 0xE9, { 'I', 'T', 'S', 'F' }, 4, false, CreateArc, 0 }; + +REGISTER_ARC(Chm) diff --git a/CPP/7zip/Archive/Chm/StdAfx.h b/CPP/7zip/Archive/Chm/StdAfx.h new file mode 100755 index 0000000..83fdd22 --- /dev/null +++ b/CPP/7zip/Archive/Chm/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" + +#endif diff --git a/CPP/7zip/Archive/Com/ComHandler.cpp b/CPP/7zip/Archive/Com/ComHandler.cpp new file mode 100755 index 0000000..8b9437e --- /dev/null +++ b/CPP/7zip/Archive/Com/ComHandler.cpp @@ -0,0 +1,239 @@ +// ComHandler.cpp + +#include "StdAfx.h" + +#include "Common/ComTry.h" + +#include "Windows/PropVariant.h" + +#include "../../Common/LimitedStreams.h" +#include "../../Common/ProgressUtils.h" +#include "../../Common/StreamUtils.h" + +#include "../../Compress/CopyCoder.h" + +#include "ComHandler.h" + +namespace NArchive { +namespace NCom { + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidMTime, VT_FILETIME} +}; + +STATPROPSTG kArcProps[] = +{ + { NULL, kpidClusterSize, VT_UI4}, + { NULL, kpidSectorSize, VT_UI4} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidClusterSize: prop = (UInt32)1 << _db.SectorSizeBits; break; + case kpidSectorSize: prop = (UInt32)1 << _db.MiniSectorSizeBits; break; + case kpidMainSubfile: if (_db.MainSubfile >= 0) prop = (UInt32)_db.MainSubfile; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + const CRef &ref = _db.Refs[index]; + const CItem &item = _db.Items[ref.Did]; + + switch(propID) + { + case kpidPath: prop = _db.GetItemPath(index); break; + case kpidIsDir: prop = item.IsDir(); break; + case kpidCTime: prop = item.CTime; break; + case kpidMTime: prop = item.MTime; break; + case kpidPackSize: if (!item.IsDir()) prop = _db.GetItemPackSize(item.Size); break; + case kpidSize: if (!item.IsDir()) prop = item.Size; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Open(IInStream *inStream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback * /* openArchiveCallback */) +{ + COM_TRY_BEGIN + Close(); + try + { + if (_db.Open(inStream) != S_OK) + return S_FALSE; + _stream = inStream; + } + catch(...) { return S_FALSE; } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _db.Clear(); + _stream.Release(); + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _db.Refs.Size(); + if (numItems == 0) + return S_OK; + UInt32 i; + UInt64 totalSize = 0; + for(i = 0; i < numItems; i++) + { + const CItem &item = _db.Items[_db.Refs[allFilesMode ? i : indices[i]].Did]; + if (!item.IsDir()) + totalSize += item.Size; + } + RINOK(extractCallback->SetTotal(totalSize)); + + UInt64 totalPackSize; + totalSize = totalPackSize = 0; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + for (i = 0; i < numItems; i++) + { + lps->InSize = totalPackSize; + lps->OutSize = totalSize; + RINOK(lps->SetCur()); + Int32 index = allFilesMode ? i : indices[i]; + const CItem &item = _db.Items[_db.Refs[index].Did]; + + CMyComPtr outStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + RINOK(extractCallback->GetStream(index, &outStream, askMode)); + + if (item.IsDir()) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + + totalPackSize += _db.GetItemPackSize(item.Size); + totalSize += item.Size; + + if (!testMode && !outStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + Int32 res = NExtract::NOperationResult::kDataError; + CMyComPtr inStream; + HRESULT hres = GetStream(index, &inStream); + if (hres == S_FALSE) + res = NExtract::NOperationResult::kDataError; + else if (hres == E_NOTIMPL) + res = NExtract::NOperationResult::kUnSupportedMethod; + else + { + RINOK(hres); + if (inStream) + { + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + if (copyCoderSpec->TotalSize == item.Size) + res = NExtract::NOperationResult::kOK; + } + } + outStream.Release(); + RINOK(extractCallback->SetOperationResult(res)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _db.Refs.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + *stream = 0; + const CItem &item = _db.Items[_db.Refs[index].Did]; + CClusterInStream *streamSpec = new CClusterInStream; + CMyComPtr streamTemp = streamSpec; + streamSpec->Stream = _stream; + streamSpec->StartOffset = 0; + + bool isLargeStream = _db.IsLargeStream(item.Size); + int bsLog = isLargeStream ? _db.SectorSizeBits : _db.MiniSectorSizeBits; + streamSpec->BlockSizeLog = bsLog; + streamSpec->Size = item.Size; + + UInt32 clusterSize = (UInt32)1 << bsLog; + UInt64 numClusters64 = (item.Size + clusterSize - 1) >> bsLog; + if (numClusters64 >= ((UInt32)1 << 31)) + return E_NOTIMPL; + streamSpec->Vector.Reserve((int)numClusters64); + UInt32 sid = item.Sid; + UInt64 size = item.Size; + + if (size != 0) + { + for (;; size -= clusterSize) + { + if (isLargeStream) + { + if (sid >= _db.FatSize) + return S_FALSE; + streamSpec->Vector.Add(sid + 1); + sid = _db.Fat[sid]; + } + else + { + UInt64 val; + if (sid >= _db.MatSize || !_db.GetMiniCluster(sid, val) || val >= (UInt64)1 << 32) + return S_FALSE; + streamSpec->Vector.Add((UInt32)val); + sid = _db.Mat[sid]; + } + if (size <= clusterSize) + break; + } + } + if (sid != NFatID::kEndOfChain) + return S_FALSE; + RINOK(streamSpec->InitAndSeek()); + *stream = streamTemp.Detach(); + return S_OK; + COM_TRY_END +} + +}} diff --git a/CPP/7zip/Archive/Com/ComHandler.h b/CPP/7zip/Archive/Com/ComHandler.h new file mode 100755 index 0000000..6b725e7 --- /dev/null +++ b/CPP/7zip/Archive/Com/ComHandler.h @@ -0,0 +1,28 @@ +// ComHandler.h + +#ifndef __ARCHIVE_COM_HANDLER_H +#define __ARCHIVE_COM_HANDLER_H + +#include "Common/MyCom.h" +#include "../IArchive.h" +#include "ComIn.h" + +namespace NArchive { +namespace NCom { + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + CDatabase _db; +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Com/ComIn.cpp b/CPP/7zip/Archive/Com/ComIn.cpp new file mode 100755 index 0000000..f69e134 --- /dev/null +++ b/CPP/7zip/Archive/Com/ComIn.cpp @@ -0,0 +1,389 @@ +// Archive/ComIn.cpp + +#include "StdAfx.h" + +#include "../../../../C/Alloc.h" +#include "../../../../C/CpuArch.h" + +#include "Common/IntToString.h" +#include "Common/MyCom.h" + +#include "../../Common/StreamUtils.h" + +#include "ComIn.h" + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) + +namespace NArchive{ +namespace NCom{ + +static const UInt32 kSignatureSize = 8; +static const Byte kSignature[kSignatureSize] = { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 }; + +void CUInt32Buf::Free() +{ + MyFree(_buf); + _buf = 0; +} + +bool CUInt32Buf::Allocate(UInt32 numItems) +{ + Free(); + if (numItems == 0) + return true; + size_t newSize = (size_t)numItems * sizeof(UInt32); + if (newSize / sizeof(UInt32) != numItems) + return false; + _buf = (UInt32 *)MyAlloc(newSize); + return (_buf != 0); +} + +static HRESULT ReadSector(IInStream *inStream, Byte *buf, int sectorSizeBits, UInt32 sid) +{ + RINOK(inStream->Seek((((UInt64)sid + 1) << sectorSizeBits), STREAM_SEEK_SET, NULL)); + return ReadStream_FALSE(inStream, buf, (UInt32)1 << sectorSizeBits); +} + +static HRESULT ReadIDs(IInStream *inStream, Byte *buf, int sectorSizeBits, UInt32 sid, UInt32 *dest) +{ + RINOK(ReadSector(inStream, buf, sectorSizeBits, sid)); + UInt32 sectorSize = (UInt32)1 << sectorSizeBits; + for (UInt32 t = 0; t < sectorSize; t += 4) + *dest++ = Get32(buf + t); + return S_OK; +} + +static void GetFileTimeFromMem(const Byte *p, FILETIME *ft) +{ + ft->dwLowDateTime = Get32(p); + ft->dwHighDateTime = Get32(p + 4); +} + +void CItem::Parse(const Byte *p, bool mode64bit) +{ + memcpy(Name, p, kNameSizeMax); + // NameSize = Get16(p + 64); + Type = p[66]; + LeftDid = Get32(p + 68); + RightDid = Get32(p + 72); + SonDid = Get32(p + 76); + // Flags = Get32(p + 96); + GetFileTimeFromMem(p + 100, &CTime); + GetFileTimeFromMem(p + 108, &MTime); + Sid = Get32(p + 116); + Size = Get32(p + 120); + if (mode64bit) + Size |= ((UInt64)Get32(p + 124) << 32); +} + +void CDatabase::Clear() +{ + Fat.Free(); + MiniSids.Free(); + Mat.Free(); + Items.Clear(); + Refs.Clear(); +} + +static const UInt32 kNoDid = 0xFFFFFFFF; + +HRESULT CDatabase::AddNode(int parent, UInt32 did) +{ + if (did == kNoDid) + return S_OK; + if (did >= (UInt32)Items.Size()) + return S_FALSE; + const CItem &item = Items[did]; + if (item.IsEmpty()) + return S_FALSE; + CRef ref; + ref.Parent = parent; + ref.Did = did; + int index = Refs.Add(ref); + if (Refs.Size() > Items.Size()) + return S_FALSE; + RINOK(AddNode(parent, item.LeftDid)); + RINOK(AddNode(parent, item.RightDid)); + if (item.IsDir()) + { + RINOK(AddNode(index, item.SonDid)); + } + return S_OK; +} + +static const char kCharOpenBracket = '['; +static const char kCharCloseBracket = ']'; + +static UString CompoundNameToFileName(const UString &s) +{ + UString res; + for (int i = 0; i < s.Length(); i++) + { + wchar_t c = s[i]; + if (c < 0x20) + { + res += kCharOpenBracket; + wchar_t buf[32]; + ConvertUInt32ToString(c, buf); + res += buf; + res += kCharCloseBracket; + } + else + res += c; + } + return res; +} + +static char g_MsiChars[] = +"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._"; + +static const wchar_t *kMsi_ID = L""; // L"{msi}"; + +static const int kMsiNumBits = 6; +static const UInt32 kMsiNumChars = 1 << kMsiNumBits; +static const UInt32 kMsiCharMask = kMsiNumChars - 1; +static const UInt32 kMsiStartUnicodeChar = 0x3800; +static const UInt32 kMsiUnicodeRange = kMsiNumChars * (kMsiNumChars + 1); + +bool CompoundMsiNameToFileName(const UString &name, UString &resultName) +{ + resultName.Empty(); + for (int i = 0; i < name.Length(); i++) + { + wchar_t c = name[i]; + if (c < kMsiStartUnicodeChar || c > kMsiStartUnicodeChar + kMsiUnicodeRange) + return false; + if (i == 0) + resultName += kMsi_ID; + c -= kMsiStartUnicodeChar; + + UInt32 c0 = c & kMsiCharMask; + UInt32 c1 = c >> kMsiNumBits; + + if (c1 <= kMsiNumChars) + { + resultName += (wchar_t)g_MsiChars[c0]; + if (c1 == kMsiNumChars) + break; + resultName += (wchar_t)g_MsiChars[c1]; + } + else + resultName += L'!'; + } + return true; +} + +static UString ConvertName(const Byte *p, bool &isMsi) +{ + isMsi = false; + UString s; + for (int i = 0; i < kNameSizeMax; i += 2) + { + wchar_t c = (p[i] | (wchar_t)p[i + 1] << 8); + if (c == 0) + break; + s += c; + } + UString msiName; + if (CompoundMsiNameToFileName(s, msiName)) + { + isMsi = true; + return msiName; + } + return CompoundNameToFileName(s); +} + +static UString ConvertName(const Byte *p) +{ + bool isMsi; + return ConvertName(p, isMsi); +} + +UString CDatabase::GetItemPath(UInt32 index) const +{ + UString s; + while (index != kNoDid) + { + const CRef &ref = Refs[index]; + const CItem &item = Items[ref.Did]; + if (!s.IsEmpty()) + s = (UString)WCHAR_PATH_SEPARATOR + s; + s = ConvertName(item.Name) + s; + index = ref.Parent; + } + return s; +} + +HRESULT CDatabase::Open(IInStream *inStream) +{ + MainSubfile = -1; + static const UInt32 kHeaderSize = 512; + Byte p[kHeaderSize]; + RINOK(ReadStream_FALSE(inStream, p, kHeaderSize)); + if (memcmp(p, kSignature, kSignatureSize) != 0) + return S_FALSE; + if (Get16(p + 0x1A) > 4) // majorVer + return S_FALSE; + if (Get16(p + 0x1C) != 0xFFFE) + return S_FALSE; + int sectorSizeBits = Get16(p + 0x1E); + bool mode64bit = (sectorSizeBits >= 12); + int miniSectorSizeBits = Get16(p + 0x20); + SectorSizeBits = sectorSizeBits; + MiniSectorSizeBits = miniSectorSizeBits; + + if (sectorSizeBits > 28 || miniSectorSizeBits > 28 || + sectorSizeBits < 7 || miniSectorSizeBits < 2 || miniSectorSizeBits > sectorSizeBits) + return S_FALSE; + UInt32 numSectorsForFAT = Get32(p + 0x2C); + LongStreamMinSize = Get32(p + 0x38); + + UInt32 sectSize = (UInt32)1 << (int)sectorSizeBits; + + CByteBuffer sect; + sect.SetCapacity(sectSize); + + int ssb2 = (int)(sectorSizeBits - 2); + UInt32 numSidsInSec = (UInt32)1 << ssb2; + UInt32 numFatItems = numSectorsForFAT << ssb2; + if ((numFatItems >> ssb2) != numSectorsForFAT) + return S_FALSE; + FatSize = numFatItems; + + { + CUInt32Buf bat; + UInt32 numSectorsForBat = Get32(p + 0x48); + const UInt32 kNumHeaderBatItems = 109; + UInt32 numBatItems = kNumHeaderBatItems + (numSectorsForBat << ssb2); + if (numBatItems < kNumHeaderBatItems || ((numBatItems - kNumHeaderBatItems) >> ssb2) != numSectorsForBat) + return S_FALSE; + if (!bat.Allocate(numBatItems)) + return S_FALSE; + UInt32 i; + for (i = 0; i < kNumHeaderBatItems; i++) + bat[i] = Get32(p + 0x4c + i * 4); + UInt32 sid = Get32(p + 0x44); + for (UInt32 s = 0; s < numSectorsForBat; s++) + { + RINOK(ReadIDs(inStream, sect, sectorSizeBits, sid, bat + i)); + i += numSidsInSec - 1; + sid = bat[i]; + } + numBatItems = i; + + if (!Fat.Allocate(numFatItems)) + return S_FALSE; + UInt32 j = 0; + + for (i = 0; i < numFatItems; j++, i += numSidsInSec) + { + if (j >= numBatItems) + return S_FALSE; + RINOK(ReadIDs(inStream, sect, sectorSizeBits, bat[j], Fat + i)); + } + } + + UInt32 numMatItems; + { + UInt32 numSectorsForMat = Get32(p + 0x40); + numMatItems = (UInt32)numSectorsForMat << ssb2; + if ((numMatItems >> ssb2) != numSectorsForMat) + return S_FALSE; + if (!Mat.Allocate(numMatItems)) + return S_FALSE; + UInt32 i; + UInt32 sid = Get32(p + 0x3C); + for (i = 0; i < numMatItems; i += numSidsInSec) + { + RINOK(ReadIDs(inStream, sect, sectorSizeBits, sid, Mat + i)); + if (sid >= numFatItems) + return S_FALSE; + sid = Fat[sid]; + } + if (sid != NFatID::kEndOfChain) + return S_FALSE; + } + + { + UInt32 sid = Get32(p + 0x30); + for (;;) + { + if (sid >= numFatItems) + return S_FALSE; + RINOK(ReadSector(inStream, sect, sectorSizeBits, sid)); + for (UInt32 i = 0; i < sectSize; i += 128) + { + CItem item; + item.Parse(sect + i, mode64bit); + Items.Add(item); + } + sid = Fat[sid]; + if (sid == NFatID::kEndOfChain) + break; + } + } + + CItem root = Items[0]; + + { + UInt32 numSectorsInMiniStream; + { + UInt64 numSatSects64 = (root.Size + sectSize - 1) >> sectorSizeBits; + if (numSatSects64 > NFatID::kMaxValue) + return S_FALSE; + numSectorsInMiniStream = (UInt32)numSatSects64; + } + NumSectorsInMiniStream = numSectorsInMiniStream; + if (!MiniSids.Allocate(numSectorsInMiniStream)) + return S_FALSE; + { + UInt64 matSize64 = (root.Size + ((UInt64)1 << miniSectorSizeBits) - 1) >> miniSectorSizeBits; + if (matSize64 > NFatID::kMaxValue) + return S_FALSE; + MatSize = (UInt32)matSize64; + if (numMatItems < MatSize) + return S_FALSE; + } + + UInt32 sid = root.Sid; + for (UInt32 i = 0; ; i++) + { + if (sid == NFatID::kEndOfChain) + { + if (i != numSectorsInMiniStream) + return S_FALSE; + break; + } + if (i >= numSectorsInMiniStream) + return S_FALSE; + MiniSids[i] = sid; + if (sid >= numFatItems) + return S_FALSE; + sid = Fat[sid]; + } + } + + RINOK(AddNode(-1, root.SonDid)); + + unsigned numCabs = 0; + for (int i = 0; i < Refs.Size(); i++) + { + const CItem &item = Items[Refs[i].Did]; + if (item.IsDir() || numCabs > 1) + continue; + bool isMsiName; + UString msiName = ConvertName(item.Name, isMsiName); + if (isMsiName && msiName.Right(4).CompareNoCase(L".cab") == 0) + { + numCabs++; + MainSubfile = i; + } + } + if (numCabs > 1) + MainSubfile = -1; + + return S_OK; +} + +}} diff --git a/CPP/7zip/Archive/Com/ComIn.h b/CPP/7zip/Archive/Com/ComIn.h new file mode 100755 index 0000000..1439d2f --- /dev/null +++ b/CPP/7zip/Archive/Com/ComIn.h @@ -0,0 +1,119 @@ +// Archive/ComIn.h + +#ifndef __ARCHIVE_COM_IN_H +#define __ARCHIVE_COM_IN_H + +#include "Common/MyString.h" +#include "Common/Buffer.h" + +namespace NArchive { +namespace NCom { + +struct CUInt32Buf +{ + UInt32 *_buf; +public: + CUInt32Buf(): _buf(0) {} + ~CUInt32Buf() { Free(); } + void Free(); + bool Allocate(UInt32 numItems); + operator UInt32 *() const { return _buf; }; +}; + +namespace NFatID +{ + const UInt32 kFree = 0xFFFFFFFF; + const UInt32 kEndOfChain = 0xFFFFFFFE; + const UInt32 kFatSector = 0xFFFFFFFD; + const UInt32 kMatSector = 0xFFFFFFFC; + const UInt32 kMaxValue = 0xFFFFFFFA; +} + +namespace NItemType +{ + const Byte kEmpty = 0; + const Byte kStorage = 1; + const Byte kStream = 2; + const Byte kLockBytes = 3; + const Byte kProperty = 4; + const Byte kRootStorage = 5; +} + +const UInt32 kNameSizeMax = 64; + +struct CItem +{ + Byte Name[kNameSizeMax]; + // UInt16 NameSize; + // UInt32 Flags; + FILETIME CTime; + FILETIME MTime; + UInt64 Size; + UInt32 LeftDid; + UInt32 RightDid; + UInt32 SonDid; + UInt32 Sid; + Byte Type; + + bool IsEmpty() const { return Type == NItemType::kEmpty; } + bool IsDir() const { return Type == NItemType::kStorage || Type == NItemType::kRootStorage; } + + void Parse(const Byte *p, bool mode64bit); +}; + +struct CRef +{ + int Parent; + UInt32 Did; +}; + +class CDatabase +{ + UInt32 NumSectorsInMiniStream; + CUInt32Buf MiniSids; + + HRESULT AddNode(int parent, UInt32 did); +public: + + CUInt32Buf Fat; + UInt32 FatSize; + + CUInt32Buf Mat; + UInt32 MatSize; + + CObjectVector Items; + CRecordVector Refs; + + UInt32 LongStreamMinSize; + int SectorSizeBits; + int MiniSectorSizeBits; + + Int32 MainSubfile; + + void Clear(); + bool IsLargeStream(UInt64 size) const { return size >= LongStreamMinSize; } + UString GetItemPath(UInt32 index) const; + + UInt64 GetItemPackSize(UInt64 size) const + { + UInt64 mask = ((UInt64)1 << (IsLargeStream(size) ? SectorSizeBits : MiniSectorSizeBits)) - 1; + return (size + mask) & ~mask; + } + + bool GetMiniCluster(UInt32 sid, UInt64 &res) const + { + int subBits = SectorSizeBits - MiniSectorSizeBits; + UInt32 fid = sid >> subBits; + if (fid >= NumSectorsInMiniStream) + return false; + res = (((UInt64)MiniSids[fid] + 1) << subBits) + (sid & ((1 << subBits) - 1)); + return true; + } + + HRESULT Open(IInStream *inStream); +}; + + +}} + +#endif diff --git a/CPP/7zip/Archive/Com/ComRegister.cpp b/CPP/7zip/Archive/Com/ComRegister.cpp new file mode 100755 index 0000000..46a6810 --- /dev/null +++ b/CPP/7zip/Archive/Com/ComRegister.cpp @@ -0,0 +1,13 @@ +// ComRegister.cpp + +#include "StdAfx.h" + +#include "../../Common/RegisterArc.h" + +#include "ComHandler.h" +static IInArchive *CreateArc() { return new NArchive::NCom::CHandler; } + +static CArcInfo g_ArcInfo = + { L"Compound", L"msi msp doc xls ppt", 0, 0xE5, { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 }, 8, false, CreateArc, 0 }; + +REGISTER_ARC(Com) diff --git a/CPP/7zip/Archive/Common/CoderMixer.cpp b/CPP/7zip/Archive/Common/CoderMixer.cpp new file mode 100755 index 0000000..8a4b038 --- /dev/null +++ b/CPP/7zip/Archive/Common/CoderMixer.cpp @@ -0,0 +1,19 @@ +// CoderMixer.cpp + +#include "StdAfx.h" + +#include "CoderMixer.h" + +namespace NCoderMixer { + +void CCoderInfo::SetCoderInfo(const UInt64 *inSize, const UInt64 *outSize) +{ + InSizeAssigned = (inSize != 0); + if (InSizeAssigned) + InSizeValue = *inSize; + OutSizeAssigned = (outSize != 0); + if (OutSizeAssigned) + OutSizeValue = *outSize; +} + +} diff --git a/CPP/7zip/Archive/Common/CoderMixer.h b/CPP/7zip/Archive/Common/CoderMixer.h new file mode 100755 index 0000000..aefe702 --- /dev/null +++ b/CPP/7zip/Archive/Common/CoderMixer.h @@ -0,0 +1,32 @@ +// CoderMixer.h + +#ifndef __CODER_MIXER_H +#define __CODER_MIXER_H + +#include "../../../Common/MyCom.h" +#include "../../ICoder.h" + +namespace NCoderMixer { + +struct CCoderInfo +{ + CMyComPtr Coder; + CMyComPtr InStream; + CMyComPtr OutStream; + CMyComPtr Progress; + + UInt64 InSizeValue; + UInt64 OutSizeValue; + bool InSizeAssigned; + bool OutSizeAssigned; + + void ReInit() + { + InSizeAssigned = OutSizeAssigned = false; + } + + void SetCoderInfo(const UInt64 *inSize, const UInt64 *outSize); +}; + +} +#endif diff --git a/CPP/7zip/Archive/Common/CoderMixer2.cpp b/CPP/7zip/Archive/Common/CoderMixer2.cpp new file mode 100755 index 0000000..417e8a7 --- /dev/null +++ b/CPP/7zip/Archive/Common/CoderMixer2.cpp @@ -0,0 +1,121 @@ +// CoderMixer2.cpp + +#include "StdAfx.h" + +#include "CoderMixer2.h" + +namespace NCoderMixer { + +CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo): + _srcBindInfo(srcBindInfo) +{ + srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams); + + UInt32 j; + for (j = 0; j < NumSrcInStreams; j++) + { + _srcInToDestOutMap.Add(0); + DestOutToSrcInMap.Add(0); + } + for (j = 0; j < _numSrcOutStreams; j++) + { + _srcOutToDestInMap.Add(0); + _destInToSrcOutMap.Add(0); + } + + UInt32 destInOffset = 0; + UInt32 destOutOffset = 0; + UInt32 srcInOffset = NumSrcInStreams; + UInt32 srcOutOffset = _numSrcOutStreams; + + for (int i = srcBindInfo.Coders.Size() - 1; i >= 0; i--) + { + const CCoderStreamsInfo &srcCoderInfo = srcBindInfo.Coders[i]; + + srcInOffset -= srcCoderInfo.NumInStreams; + srcOutOffset -= srcCoderInfo.NumOutStreams; + + UInt32 j; + for (j = 0; j < srcCoderInfo.NumInStreams; j++, destOutOffset++) + { + UInt32 index = srcInOffset + j; + _srcInToDestOutMap[index] = destOutOffset; + DestOutToSrcInMap[destOutOffset] = index; + } + for (j = 0; j < srcCoderInfo.NumOutStreams; j++, destInOffset++) + { + UInt32 index = srcOutOffset + j; + _srcOutToDestInMap[index] = destInOffset; + _destInToSrcOutMap[destInOffset] = index; + } + } +} + +void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo) +{ + destBindInfo.Coders.Clear(); + destBindInfo.BindPairs.Clear(); + destBindInfo.InStreams.Clear(); + destBindInfo.OutStreams.Clear(); + + int i; + for (i = _srcBindInfo.Coders.Size() - 1; i >= 0; i--) + { + const CCoderStreamsInfo &srcCoderInfo = _srcBindInfo.Coders[i]; + CCoderStreamsInfo destCoderInfo; + destCoderInfo.NumInStreams = srcCoderInfo.NumOutStreams; + destCoderInfo.NumOutStreams = srcCoderInfo.NumInStreams; + destBindInfo.Coders.Add(destCoderInfo); + } + for (i = _srcBindInfo.BindPairs.Size() - 1; i >= 0; i--) + { + const CBindPair &srcBindPair = _srcBindInfo.BindPairs[i]; + CBindPair destBindPair; + destBindPair.InIndex = _srcOutToDestInMap[srcBindPair.OutIndex]; + destBindPair.OutIndex = _srcInToDestOutMap[srcBindPair.InIndex]; + destBindInfo.BindPairs.Add(destBindPair); + } + for (i = 0; i < _srcBindInfo.InStreams.Size(); i++) + destBindInfo.OutStreams.Add(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]); + for (i = 0; i < _srcBindInfo.OutStreams.Size(); i++) + destBindInfo.InStreams.Add(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]); +} + +CCoderInfo2::CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams): + NumInStreams(numInStreams), + NumOutStreams(numOutStreams) +{ + InSizes.Reserve(NumInStreams); + InSizePointers.Reserve(NumInStreams); + OutSizes.Reserve(NumOutStreams); + OutSizePointers.Reserve(NumOutStreams); +} + +static void SetSizes(const UInt64 **srcSizes, CRecordVector &sizes, + CRecordVector &sizePointers, UInt32 numItems) +{ + sizes.Clear(); + sizePointers.Clear(); + for(UInt32 i = 0; i < numItems; i++) + { + if (srcSizes == 0 || srcSizes[i] == NULL) + { + sizes.Add(0); + sizePointers.Add(NULL); + } + else + { + sizes.Add(*srcSizes[i]); + sizePointers.Add(&sizes.Back()); + } + } +} + +void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes, + const UInt64 **outSizes) +{ + SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); + SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); +} + +} diff --git a/CPP/7zip/Archive/Common/CoderMixer2.h b/CPP/7zip/Archive/Common/CoderMixer2.h new file mode 100755 index 0000000..b1893b2 --- /dev/null +++ b/CPP/7zip/Archive/Common/CoderMixer2.h @@ -0,0 +1,174 @@ +// CoderMixer2.h + +#ifndef __CODER_MIXER2_H +#define __CODER_MIXER2_H + +#include "../../../Common/MyVector.h" +#include "../../../Common/Types.h" +#include "../../../Common/MyCom.h" +#include "../../ICoder.h" + +namespace NCoderMixer { + +struct CBindPair +{ + UInt32 InIndex; + UInt32 OutIndex; +}; + +struct CCoderStreamsInfo +{ + UInt32 NumInStreams; + UInt32 NumOutStreams; +}; + +struct CBindInfo +{ + CRecordVector Coders; + CRecordVector BindPairs; + CRecordVector InStreams; + CRecordVector OutStreams; + + void Clear() + { + Coders.Clear(); + BindPairs.Clear(); + InStreams.Clear(); + OutStreams.Clear(); + } + + /* + UInt32 GetCoderStartOutStream(UInt32 coderIndex) const + { + UInt32 numOutStreams = 0; + for (UInt32 i = 0; i < coderIndex; i++) + numOutStreams += Coders[i].NumOutStreams; + return numOutStreams; + } + */ + + + void GetNumStreams(UInt32 &numInStreams, UInt32 &numOutStreams) const + { + numInStreams = 0; + numOutStreams = 0; + for (int i = 0; i < Coders.Size(); i++) + { + const CCoderStreamsInfo &coderStreamsInfo = Coders[i]; + numInStreams += coderStreamsInfo.NumInStreams; + numOutStreams += coderStreamsInfo.NumOutStreams; + } + } + + int FindBinderForInStream(UInt32 inStream) const + { + for (int i = 0; i < BindPairs.Size(); i++) + if (BindPairs[i].InIndex == inStream) + return i; + return -1; + } + int FindBinderForOutStream(UInt32 outStream) const + { + for (int i = 0; i < BindPairs.Size(); i++) + if (BindPairs[i].OutIndex == outStream) + return i; + return -1; + } + + UInt32 GetCoderInStreamIndex(UInt32 coderIndex) const + { + UInt32 streamIndex = 0; + for (UInt32 i = 0; i < coderIndex; i++) + streamIndex += Coders[i].NumInStreams; + return streamIndex; + } + + UInt32 GetCoderOutStreamIndex(UInt32 coderIndex) const + { + UInt32 streamIndex = 0; + for (UInt32 i = 0; i < coderIndex; i++) + streamIndex += Coders[i].NumOutStreams; + return streamIndex; + } + + + void FindInStream(UInt32 streamIndex, UInt32 &coderIndex, + UInt32 &coderStreamIndex) const + { + for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++) + { + UInt32 curSize = Coders[coderIndex].NumInStreams; + if (streamIndex < curSize) + { + coderStreamIndex = streamIndex; + return; + } + streamIndex -= curSize; + } + throw 1; + } + void FindOutStream(UInt32 streamIndex, UInt32 &coderIndex, + UInt32 &coderStreamIndex) const + { + for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++) + { + UInt32 curSize = Coders[coderIndex].NumOutStreams; + if (streamIndex < curSize) + { + coderStreamIndex = streamIndex; + return; + } + streamIndex -= curSize; + } + throw 1; + } +}; + +class CBindReverseConverter +{ + UInt32 _numSrcOutStreams; + NCoderMixer::CBindInfo _srcBindInfo; + CRecordVector _srcInToDestOutMap; + CRecordVector _srcOutToDestInMap; + CRecordVector _destInToSrcOutMap; +public: + UInt32 NumSrcInStreams; + CRecordVector DestOutToSrcInMap; + + CBindReverseConverter(const NCoderMixer::CBindInfo &srcBindInfo); + void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo); +}; + +struct CCoderInfo2 +{ + CMyComPtr Coder; + CMyComPtr Coder2; + UInt32 NumInStreams; + UInt32 NumOutStreams; + + CRecordVector InSizes; + CRecordVector OutSizes; + CRecordVector InSizePointers; + CRecordVector OutSizePointers; + + CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams); + void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); + + HRESULT QueryInterface(REFGUID iid, void** pp) const + { + IUnknown *p = Coder ? (IUnknown *)Coder : (IUnknown *)Coder2; + return p->QueryInterface(iid, pp); + } +}; + +class CCoderMixer2 +{ +public: + virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) = 0; + virtual void ReInit() = 0; + virtual void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) = 0; +}; + +} +#endif + diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp new file mode 100755 index 0000000..3047b13 --- /dev/null +++ b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp @@ -0,0 +1,240 @@ +// CoderMixer2MT.cpp + +#include "StdAfx.h" + +#include "CoderMixer2MT.h" + +namespace NCoderMixer { + +CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams): + CCoderInfo2(numInStreams, numOutStreams) +{ + InStreams.Reserve(NumInStreams); + InStreamPointers.Reserve(NumInStreams); + OutStreams.Reserve(NumOutStreams); + OutStreamPointers.Reserve(NumOutStreams); +} + +void CCoder2::Execute() { Code(NULL); } + +void CCoder2::Code(ICompressProgressInfo *progress) +{ + InStreamPointers.Clear(); + OutStreamPointers.Clear(); + UInt32 i; + for (i = 0; i < NumInStreams; i++) + { + if (InSizePointers[i] != NULL) + InSizePointers[i] = &InSizes[i]; + InStreamPointers.Add((ISequentialInStream *)InStreams[i]); + } + for (i = 0; i < NumOutStreams; i++) + { + if (OutSizePointers[i] != NULL) + OutSizePointers[i] = &OutSizes[i]; + OutStreamPointers.Add((ISequentialOutStream *)OutStreams[i]); + } + if (Coder) + Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0], + InSizePointers[0], OutSizePointers[0], progress); + else + Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams, + &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress); + { + int i; + for (i = 0; i < InStreams.Size(); i++) + InStreams[i].Release(); + for (i = 0; i < OutStreams.Size(); i++) + OutStreams[i].Release(); + } +} + +static void SetSizes(const UInt64 **srcSizes, CRecordVector &sizes, + CRecordVector &sizePointers, UInt32 numItems) +{ + sizes.Clear(); + sizePointers.Clear(); + for (UInt32 i = 0; i < numItems; i++) + { + if (srcSizes == 0 || srcSizes[i] == NULL) + { + sizes.Add(0); + sizePointers.Add(NULL); + } + else + { + sizes.Add(*srcSizes[i]); + sizePointers.Add(&sizes.Back()); + } + } +} + + +void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) +{ + SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); + SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); +} + +////////////////////////////////////// +// CCoderMixer2MT + +HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo) +{ + _bindInfo = bindInfo; + _streamBinders.Clear(); + for (int i = 0; i < _bindInfo.BindPairs.Size(); i++) + { + _streamBinders.Add(CStreamBinder()); + RINOK(_streamBinders.Back().CreateEvents()); + } + return S_OK; +} + +void CCoderMixer2MT::AddCoderCommon() +{ + const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()]; + CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams); + _coders.Add(threadCoderInfo); +} + +void CCoderMixer2MT::AddCoder(ICompressCoder *coder) +{ + AddCoderCommon(); + _coders.Back().Coder = coder; +} + +void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder) +{ + AddCoderCommon(); + _coders.Back().Coder2 = coder; +} + + +void CCoderMixer2MT::ReInit() +{ + for (int i = 0; i < _streamBinders.Size(); i++) + _streamBinders[i].ReInit(); +} + + +HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams) +{ + /* + if (_coders.Size() != _bindInfo.Coders.Size()) + throw 0; + */ + int i; + for (i = 0; i < _coders.Size(); i++) + { + CCoder2 &coderInfo = _coders[i]; + const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i]; + coderInfo.InStreams.Clear(); + UInt32 j; + for (j = 0; j < coderStreamsInfo.NumInStreams; j++) + coderInfo.InStreams.Add(NULL); + coderInfo.OutStreams.Clear(); + for (j = 0; j < coderStreamsInfo.NumOutStreams; j++) + coderInfo.OutStreams.Add(NULL); + } + + for (i = 0; i < _bindInfo.BindPairs.Size(); i++) + { + const CBindPair &bindPair = _bindInfo.BindPairs[i]; + UInt32 inCoderIndex, inCoderStreamIndex; + UInt32 outCoderIndex, outCoderStreamIndex; + _bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex); + _bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex); + + _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); + } + } + + for (i = 0; i < _bindInfo.InStreams.Size(); i++) + { + UInt32 inCoderIndex, inCoderStreamIndex; + _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex); + _coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i]; + } + + for (i = 0; i < _bindInfo.OutStreams.Size(); i++) + { + UInt32 outCoderIndex, outCoderStreamIndex; + _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex); + _coders[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i]; + } + return S_OK; +} + +HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code) +{ + for (int i = 0; i < _coders.Size(); i++) + if (_coders[i].Result == code) + return code; + return S_OK; +} + +STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams, + const UInt64 ** /* inSizes */, + UInt32 numInStreams, + ISequentialOutStream **outStreams, + const UInt64 ** /* outSizes */, + UInt32 numOutStreams, + ICompressProgressInfo *progress) +{ + if (numInStreams != (UInt32)_bindInfo.InStreams.Size() || + numOutStreams != (UInt32)_bindInfo.OutStreams.Size()) + return E_INVALIDARG; + + Init(inStreams, outStreams); + + int i; + for (i = 0; i < _coders.Size(); i++) + if (i != _progressCoderIndex) + { + RINOK(_coders[i].Create()); + } + + for (i = 0; i < _coders.Size(); i++) + if (i != _progressCoderIndex) + _coders[i].Start(); + + _coders[_progressCoderIndex].Code(progress); + + for (i = 0; i < _coders.Size(); i++) + if (i != _progressCoderIndex) + _coders[i].WaitFinish(); + + 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 != E_FAIL && result != S_FALSE) + return result; + } + + RINOK(ReturnIfError(S_FALSE)); + + for (i = 0; i < _coders.Size(); i++) + { + HRESULT result = _coders[i].Result; + if (result != S_OK) + return result; + } + return S_OK; +} + +} diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.h b/CPP/7zip/Archive/Common/CoderMixer2MT.h new file mode 100755 index 0000000..acecc39 --- /dev/null +++ b/CPP/7zip/Archive/Common/CoderMixer2MT.h @@ -0,0 +1,80 @@ +// CoderMixer2MT.h + +#ifndef __CODER_MIXER2_MT_H +#define __CODER_MIXER2_MT_H + +#include "CoderMixer2.h" +#include "../../../Common/MyCom.h" +#include "../../Common/StreamBinder.h" +#include "../../Common/VirtThread.h" + +namespace NCoderMixer { + +struct CCoder2: public CCoderInfo2, public CVirtThread +{ + HRESULT Result; + CObjectVector< CMyComPtr > InStreams; + CObjectVector< CMyComPtr > OutStreams; + CRecordVector InStreamPointers; + CRecordVector OutStreamPointers; + + CCoder2(UInt32 numInStreams, UInt32 numOutStreams); + void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); + virtual void Execute(); + void Code(ICompressProgressInfo *progress); +}; + + +/* + SetBindInfo() + for each coder + AddCoder[2]() + SetProgressIndex(UInt32 coderIndex); + + for each file + { + ReInit() + for each coder + SetCoderInfo + Code + } +*/ + +class CCoderMixer2MT: + public ICompressCoder2, + public CCoderMixer2, + public CMyUnknownImp +{ + CBindInfo _bindInfo; + CObjectVector _streamBinders; + int _progressCoderIndex; + + void AddCoderCommon(); + HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams); + HRESULT ReturnIfError(HRESULT code); +public: + CObjectVector _coders; + MY_UNKNOWN_IMP + + STDMETHOD(Code)(ISequentialInStream **inStreams, + const UInt64 **inSizes, + UInt32 numInStreams, + ISequentialOutStream **outStreams, + const UInt64 **outSizes, + UInt32 numOutStreams, + ICompressProgressInfo *progress); + + HRESULT SetBindInfo(const CBindInfo &bindInfo); + void AddCoder(ICompressCoder *coder); + void AddCoder2(ICompressCoder2 *coder); + void SetProgressCoderIndex(int coderIndex) { _progressCoderIndex = coderIndex; } + + void ReInit(); + void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) + { _coders[coderIndex].SetCoderInfo(inSizes, outSizes); } + UInt64 GetWriteProcessedSize(UInt32 binderIndex) const + { return _streamBinders[binderIndex].ProcessedSize; } +}; + +} +#endif diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.cpp b/CPP/7zip/Archive/Common/CoderMixer2ST.cpp new file mode 100755 index 0000000..4d9916e --- /dev/null +++ b/CPP/7zip/Archive/Common/CoderMixer2ST.cpp @@ -0,0 +1,239 @@ +// CoderMixer2ST.cpp + +#include "StdAfx.h" + +#include "CoderMixer2ST.h" + +namespace NCoderMixer2 { + +CCoderMixer2ST::CCoderMixer2ST() {} + +CCoderMixer2ST::~CCoderMixer2ST(){ } + +HRESULT CCoderMixer2ST::SetBindInfo(const CBindInfo &bindInfo) +{ + _bindInfo = bindInfo; + return S_OK; +} + +void CCoderMixer2ST::AddCoderCommon(bool isMain) +{ + const CCoderStreamsInfo &csi = _bindInfo.Coders[_coders.Size()]; + _coders.Add(CSTCoderInfo(csi.NumInStreams, csi.NumOutStreams, isMain)); +} + +void CCoderMixer2ST::AddCoder(ICompressCoder *coder, bool isMain) +{ + AddCoderCommon(isMain); + _coders.Back().Coder = coder; +} + +void CCoderMixer2ST::AddCoder2(ICompressCoder2 *coder, bool isMain) +{ + AddCoderCommon(isMain); + _coders.Back().Coder2 = coder; +} + +void CCoderMixer2ST::ReInit() { } + +HRESULT CCoderMixer2ST::GetInStream( + ISequentialInStream **inStreams, const UInt64 **inSizes, + UInt32 streamIndex, ISequentialInStream **inStreamRes) +{ + CMyComPtr seqInStream; + int i; + for(i = 0; i < _bindInfo.InStreams.Size(); i++) + if (_bindInfo.InStreams[i] == streamIndex) + { + seqInStream = inStreams[i]; + *inStreamRes = seqInStream.Detach(); + return S_OK; + } + int binderIndex = _bindInfo.FindBinderForInStream(streamIndex); + if (binderIndex < 0) + return E_INVALIDARG; + + UInt32 coderIndex, coderStreamIndex; + _bindInfo.FindOutStream(_bindInfo.BindPairs[binderIndex].OutIndex, + coderIndex, coderStreamIndex); + + CCoderInfo &coder = _coders[coderIndex]; + if (!coder.Coder) + return E_NOTIMPL; + coder.Coder.QueryInterface(IID_ISequentialInStream, &seqInStream); + if (!seqInStream) + return E_NOTIMPL; + + UInt32 startIndex = _bindInfo.GetCoderInStreamIndex(coderIndex); + + CMyComPtr setInStream; + if (!coder.Coder) + return E_NOTIMPL; + coder.Coder.QueryInterface(IID_ICompressSetInStream, &setInStream); + if (!setInStream) + return E_NOTIMPL; + + if (coder.NumInStreams > 1) + return E_NOTIMPL; + for (i = 0; i < (int)coder.NumInStreams; i++) + { + CMyComPtr seqInStream2; + RINOK(GetInStream(inStreams, inSizes, startIndex + i, &seqInStream2)); + RINOK(setInStream->SetInStream(seqInStream2)); + } + *inStreamRes = seqInStream.Detach(); + return S_OK; +} + +HRESULT CCoderMixer2ST::GetOutStream( + ISequentialOutStream **outStreams, const UInt64 **outSizes, + UInt32 streamIndex, ISequentialOutStream **outStreamRes) +{ + CMyComPtr seqOutStream; + int i; + for(i = 0; i < _bindInfo.OutStreams.Size(); i++) + if (_bindInfo.OutStreams[i] == streamIndex) + { + seqOutStream = outStreams[i]; + *outStreamRes = seqOutStream.Detach(); + return S_OK; + } + int binderIndex = _bindInfo.FindBinderForOutStream(streamIndex); + if (binderIndex < 0) + return E_INVALIDARG; + + UInt32 coderIndex, coderStreamIndex; + _bindInfo.FindInStream(_bindInfo.BindPairs[binderIndex].InIndex, + coderIndex, coderStreamIndex); + + CCoderInfo &coder = _coders[coderIndex]; + if (!coder.Coder) + return E_NOTIMPL; + coder.Coder.QueryInterface(IID_ISequentialOutStream, &seqOutStream); + if (!seqOutStream) + return E_NOTIMPL; + + UInt32 startIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex); + + CMyComPtr setOutStream; + if (!coder.Coder) + return E_NOTIMPL; + coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream); + if (!setOutStream) + return E_NOTIMPL; + + if (coder.NumOutStreams > 1) + return E_NOTIMPL; + for (i = 0; i < (int)coder.NumOutStreams; i++) + { + CMyComPtr seqOutStream2; + RINOK(GetOutStream(outStreams, outSizes, startIndex + i, &seqOutStream2)); + RINOK(setOutStream->SetOutStream(seqOutStream2)); + } + *outStreamRes = seqOutStream.Detach(); + return S_OK; +} + + +STDMETHODIMP CCoderMixer2ST::Code(ISequentialInStream **inStreams, + const UInt64 **inSizes, + UInt32 numInStreams, + ISequentialOutStream **outStreams, + const UInt64 **outSizes, + UInt32 numOutStreams, + ICompressProgressInfo *progress) +{ + if (numInStreams != (UInt32)_bindInfo.InStreams.Size() || + numOutStreams != (UInt32)_bindInfo.OutStreams.Size()) + return E_INVALIDARG; + + // Find main coder + int _mainCoderIndex = -1; + int i; + for (i = 0; i < _coders.Size(); i++) + if (_coders[i].IsMain) + { + _mainCoderIndex = i; + break; + } + if (_mainCoderIndex < 0) + for (i = 0; i < _coders.Size(); i++) + if (_coders[i].NumInStreams > 1) + { + if (_mainCoderIndex >= 0) + return E_NOTIMPL; + _mainCoderIndex = i; + } + if (_mainCoderIndex < 0) + _mainCoderIndex = 0; + + // _mainCoderIndex = 0; + // _mainCoderIndex = _coders.Size() - 1; + CCoderInfo &mainCoder = _coders[_mainCoderIndex]; + + CObjectVector< CMyComPtr > seqInStreams; + CObjectVector< CMyComPtr > seqOutStreams; + UInt32 startInIndex = _bindInfo.GetCoderInStreamIndex(_mainCoderIndex); + UInt32 startOutIndex = _bindInfo.GetCoderOutStreamIndex(_mainCoderIndex); + for (i = 0; i < (int)mainCoder.NumInStreams; i++) + { + CMyComPtr seqInStream; + RINOK(GetInStream(inStreams, inSizes, startInIndex + i, &seqInStream)); + seqInStreams.Add(seqInStream); + } + for (i = 0; i < (int)mainCoder.NumOutStreams; i++) + { + CMyComPtr seqOutStream; + RINOK(GetOutStream(outStreams, outSizes, startOutIndex + i, &seqOutStream)); + seqOutStreams.Add(seqOutStream); + } + CRecordVector< ISequentialInStream * > seqInStreamsSpec; + CRecordVector< ISequentialOutStream * > seqOutStreamsSpec; + for (i = 0; i < (int)mainCoder.NumInStreams; i++) + seqInStreamsSpec.Add(seqInStreams[i]); + for (i = 0; i < (int)mainCoder.NumOutStreams; i++) + seqOutStreamsSpec.Add(seqOutStreams[i]); + + for (i = 0; i < _coders.Size(); i++) + { + if (i == _mainCoderIndex) + continue; + CCoderInfo &coder = _coders[i]; + CMyComPtr setOutStreamSize; + coder.Coder.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize); + if (setOutStreamSize) + { + RINOK(setOutStreamSize->SetOutStreamSize(coder.OutSizePointers[0])); + } + } + if (mainCoder.Coder) + { + RINOK(mainCoder.Coder->Code( + seqInStreamsSpec[0], seqOutStreamsSpec[0], + mainCoder.InSizePointers[0], mainCoder.OutSizePointers[0], + progress)); + } + else + { + RINOK(mainCoder.Coder2->Code( + &seqInStreamsSpec.Front(), + &mainCoder.InSizePointers.Front(), mainCoder.NumInStreams, + &seqOutStreamsSpec.Front(), + &mainCoder.OutSizePointers.Front(), mainCoder.NumOutStreams, + progress)); + } + CMyComPtr flush; + seqOutStreams.Front().QueryInterface(IID_IOutStreamFlush, &flush); + if (flush) + return flush->Flush(); + return S_OK; +} + +/* +UInt64 CCoderMixer2ST::GetWriteProcessedSize(UInt32 binderIndex) const +{ + return _streamBinders[binderIndex].ProcessedSize; +} +*/ + +} diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.h b/CPP/7zip/Archive/Common/CoderMixer2ST.h new file mode 100755 index 0000000..fee21d5 --- /dev/null +++ b/CPP/7zip/Archive/Common/CoderMixer2ST.h @@ -0,0 +1,88 @@ +// CoderMixer2ST.h + +#ifndef __CODER_MIXER2_ST_H +#define __CODER_MIXER2_ST_H + +#include "CoderMixer2.h" +#include "../../../Common/MyCom.h" +#include "../../ICoder.h" + +namespace NCoderMixer2 { + +// SetBindInfo() +// for each coder +// { +// AddCoder[2]() +// } +// +// for each file +// { +// ReInit() +// for each coder +// { +// SetCoderInfo +// } +// SetProgressIndex(UInt32 coderIndex); +// Code +// } + +struct CSTCoderInfo: public CCoderInfo +{ + bool IsMain; + CSTCoderInfo(UInt32 numInStreams, UInt32 numOutStreams, bool isMain): + CCoderInfo(numInStreams, numOutStreams),IsMain(isMain) {} +}; + +class CCoderMixer2ST: + public ICompressCoder2, + public CCoderMixer2, + public CMyUnknownImp +{ + MY_UNKNOWN_IMP + + HRESULT GetInStream( + ISequentialInStream **inStreams, const UInt64 **inSizes, + UInt32 streamIndex, ISequentialInStream **inStreamRes); + HRESULT GetOutStream( + ISequentialOutStream **outStreams, const UInt64 **outSizes, + UInt32 streamIndex, ISequentialOutStream **outStreamRes); +public: + STDMETHOD(Code)(ISequentialInStream **inStreams, + const UInt64 **inSizes, + UInt32 numInStreams, + ISequentialOutStream **outStreams, + const UInt64 **outSizes, + UInt32 numOutStreams, + ICompressProgressInfo *progress); + + CCoderMixer2ST(); + ~CCoderMixer2ST(); + void AddCoderCommon(bool isMain); + void AddCoder(ICompressCoder *coder, bool isMain); + void AddCoder2(ICompressCoder2 *coder, bool isMain); + + void ReInit(); + void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) + { + { _coders[coderIndex].SetCoderInfo(inSizes, outSizes); } + } + + void SetProgressCoderIndex(UInt32 /*coderIndex*/) + { + // _progressCoderIndex = coderIndex; + } + + // UInt64 GetWriteProcessedSize(UInt32 binderIndex) const; + +private: + CBindInfo _bindInfo; + CObjectVector _coders; + int _mainCoderIndex; +public: + HRESULT SetBindInfo(const CBindInfo &bindInfo); + +}; + +} +#endif + diff --git a/CPP/7zip/Archive/Common/CoderMixerMT.cpp b/CPP/7zip/Archive/Common/CoderMixerMT.cpp new file mode 100755 index 0000000..79a6299 --- /dev/null +++ b/CPP/7zip/Archive/Common/CoderMixerMT.cpp @@ -0,0 +1,99 @@ +// CoderMixerMT.cpp + +#include "StdAfx.h" + +#include "CoderMixerMT.h" + +namespace NCoderMixer { + +void CCoder::Execute() { Code(NULL); } + +void CCoder::Code(ICompressProgressInfo *progress) +{ + Result = Coder->Code(InStream, OutStream, + InSizeAssigned ? &InSizeValue : NULL, + OutSizeAssigned ? &OutSizeValue : NULL, + progress); + InStream.Release(); + OutStream.Release(); +} + +void CCoderMixerMT::AddCoder(ICompressCoder *coder) +{ + _coders.Add(CCoder()); + _coders.Back().Coder = coder; +} + +void CCoderMixerMT::ReInit() +{ + for(int i = 0; i < _coders.Size(); i++) + _coders[i].ReInit(); +} + +HRESULT CCoderMixerMT::ReturnIfError(HRESULT code) +{ + for (int i = 0; i < _coders.Size(); i++) + if (_coders[i].Result == code) + return code; + return S_OK; +} + +STDMETHODIMP CCoderMixerMT::Code(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 * /* outSize */, + ICompressProgressInfo *progress) +{ + _coders.Front().InStream = inStream; + int i; + _coders.Back().OutStream = outStream; + + for (i = 0; i < _coders.Size(); i++) + if (i != _progressCoderIndex) + { + RINOK(_coders[i].Create()); + } + + _streamBinders.Clear(); + for (i = 0; i + 1 < _coders.Size(); i++) + { + _streamBinders.Add(CStreamBinder()); + CStreamBinder &sb = _streamBinders[i]; + RINOK(sb.CreateEvents()); + sb.CreateStreams(&_coders[i + 1].InStream, &_coders[i].OutStream); + } + + for(i = 0; i < _streamBinders.Size(); i++) + _streamBinders[i].ReInit(); + + for (i = 0; i < _coders.Size(); i++) + if (i != _progressCoderIndex) + _coders[i].Start(); + + _coders[_progressCoderIndex].Code(progress); + + for (i = 0; i < _coders.Size(); i++) + if (i != _progressCoderIndex) + _coders[i].WaitFinish(); + + 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 != E_FAIL && result != S_FALSE) + return result; + } + + RINOK(ReturnIfError(S_FALSE)); + + for (i = 0; i < _coders.Size(); i++) + { + HRESULT result = _coders[i].Result; + if (result != S_OK) + return result; + } + return S_OK; +} + +} diff --git a/CPP/7zip/Archive/Common/CoderMixerMT.h b/CPP/7zip/Archive/Common/CoderMixerMT.h new file mode 100755 index 0000000..346ed1e --- /dev/null +++ b/CPP/7zip/Archive/Common/CoderMixerMT.h @@ -0,0 +1,69 @@ +// CoderMixerMT.h + +#ifndef __CODER_MIXER_MT_H +#define __CODER_MIXER_MT_H + +#include "../../../Common/MyVector.h" +#include "../../../Common/MyCom.h" +#include "../../ICoder.h" +#include "../../Common/StreamBinder.h" +#include "../../Common/VirtThread.h" +#include "CoderMixer.h" + +namespace NCoderMixer { + +struct CCoder: public CCoderInfo, public CVirtThread +{ + HRESULT Result; + + virtual void Execute(); + void Code(ICompressProgressInfo *progress); +}; + +/* + for each coder + AddCoder() + SetProgressIndex(UInt32 coderIndex); + + for each file + { + ReInit() + for each coder + SetCoderInfo + Code + } +*/ + + +class CCoderMixerMT: + public ICompressCoder, + public CMyUnknownImp +{ + CObjectVector _streamBinders; + int _progressCoderIndex; + + HRESULT ReturnIfError(HRESULT code); +public: + CObjectVector _coders; + MY_UNKNOWN_IMP + + STDMETHOD(Code)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); + + void AddCoder(ICompressCoder *coder); + void SetProgressCoderIndex(int coderIndex) { _progressCoderIndex = coderIndex; } + + void ReInit(); + void SetCoderInfo(UInt32 coderIndex, const UInt64 *inSize, const UInt64 *outSize) + { _coders[coderIndex].SetCoderInfo(inSize, outSize); } + + /* + UInt64 GetWriteProcessedSize(UInt32 binderIndex) const + { return _streamBinders[binderIndex].ProcessedSize; } + */ +}; + +} +#endif diff --git a/CPP/7zip/Archive/Common/CrossThreadProgress.cpp b/CPP/7zip/Archive/Common/CrossThreadProgress.cpp new file mode 100755 index 0000000..62d05af --- /dev/null +++ b/CPP/7zip/Archive/Common/CrossThreadProgress.cpp @@ -0,0 +1,15 @@ +// CrossThreadProgress.cpp + +#include "StdAfx.h" + +#include "CrossThreadProgress.h" + +STDMETHODIMP CCrossThreadProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) +{ + InSize = inSize; + OutSize = outSize; + ProgressEvent.Set(); + WaitEvent.Lock(); + return Result; +} + diff --git a/CPP/7zip/Archive/Common/CrossThreadProgress.h b/CPP/7zip/Archive/Common/CrossThreadProgress.h new file mode 100755 index 0000000..d414958 --- /dev/null +++ b/CPP/7zip/Archive/Common/CrossThreadProgress.h @@ -0,0 +1,37 @@ +// CrossThreadProgress.h + +#ifndef __CROSSTHREADPROGRESS_H +#define __CROSSTHREADPROGRESS_H + +#include "../../ICoder.h" +#include "../../../Windows/Synchronization.h" +#include "../../../Common/MyCom.h" + +class CCrossThreadProgress: + public ICompressProgressInfo, + public CMyUnknownImp +{ +public: + const UInt64 *InSize; + const UInt64 *OutSize; + HRESULT Result; + NWindows::NSynchronization::CAutoResetEvent ProgressEvent; + NWindows::NSynchronization::CAutoResetEvent WaitEvent; + + HRes Create() + { + RINOK(ProgressEvent.CreateIfNotCreated()); + return WaitEvent.CreateIfNotCreated(); + } + void Init() + { + ProgressEvent.Reset(); + WaitEvent.Reset(); + } + + MY_UNKNOWN_IMP + + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); +}; + +#endif diff --git a/CPP/7zip/Archive/Common/DummyOutStream.cpp b/CPP/7zip/Archive/Common/DummyOutStream.cpp new file mode 100755 index 0000000..237e01e --- /dev/null +++ b/CPP/7zip/Archive/Common/DummyOutStream.cpp @@ -0,0 +1,22 @@ +// DummyOutStream.cpp + +#include "StdAfx.h" + +#include "DummyOutStream.h" + +STDMETHODIMP CDummyOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessedSize; + HRESULT result; + if(!_stream) + { + realProcessedSize = size; + result = S_OK; + } + else + result = _stream->Write(data, size, &realProcessedSize); + _size += realProcessedSize; + if(processedSize != NULL) + *processedSize = realProcessedSize; + return result; +} diff --git a/CPP/7zip/Archive/Common/DummyOutStream.h b/CPP/7zip/Archive/Common/DummyOutStream.h new file mode 100755 index 0000000..c993bb3 --- /dev/null +++ b/CPP/7zip/Archive/Common/DummyOutStream.h @@ -0,0 +1,24 @@ +// DummyOutStream.h + +#ifndef __DUMMYOUTSTREAM_H +#define __DUMMYOUTSTREAM_H + +#include "../../IStream.h" +#include "Common/MyCom.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/CPP/7zip/Archive/Common/FindSignature.cpp b/CPP/7zip/Archive/Common/FindSignature.cpp new file mode 100755 index 0000000..ad04bfc --- /dev/null +++ b/CPP/7zip/Archive/Common/FindSignature.cpp @@ -0,0 +1,62 @@ +// FindSignature.cpp + +#include "StdAfx.h" + +#include "Common/Buffer.h" + +#include "FindSignature.h" + +#include "../../Common/StreamUtils.h" + +HRESULT FindSignatureInStream(ISequentialInStream *stream, + const Byte *signature, unsigned signatureSize, + const UInt64 *limit, UInt64 &resPos) +{ + resPos = 0; + CByteBuffer byteBuffer2; + byteBuffer2.SetCapacity(signatureSize); + RINOK(ReadStream_FALSE(stream, byteBuffer2, signatureSize)); + + if (memcmp(byteBuffer2, signature, signatureSize) == 0) + return S_OK; + + const UInt32 kBufferSize = (1 << 16); + CByteBuffer byteBuffer; + byteBuffer.SetCapacity(kBufferSize); + Byte *buffer = byteBuffer; + UInt32 numPrevBytes = signatureSize - 1; + memcpy(buffer, (const Byte *)byteBuffer2 + 1, numPrevBytes); + resPos = 1; + for (;;) + { + if (limit != NULL) + if (resPos > *limit) + return S_FALSE; + do + { + UInt32 numReadBytes = kBufferSize - numPrevBytes; + UInt32 processedSize; + RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize)); + numPrevBytes += processedSize; + if (processedSize == 0) + return S_FALSE; + } + while (numPrevBytes < signatureSize); + UInt32 numTests = numPrevBytes - signatureSize + 1; + for (UInt32 pos = 0; pos < numTests; pos++) + { + Byte b = signature[0]; + for (; buffer[pos] != b && pos < numTests; pos++); + if (pos == numTests) + break; + if (memcmp(buffer + pos, signature, signatureSize) == 0) + { + resPos += pos; + return S_OK; + } + } + resPos += numTests; + numPrevBytes -= numTests; + memmove(buffer, buffer + numTests, numPrevBytes); + } +} diff --git a/CPP/7zip/Archive/Common/FindSignature.h b/CPP/7zip/Archive/Common/FindSignature.h new file mode 100755 index 0000000..f801d98 --- /dev/null +++ b/CPP/7zip/Archive/Common/FindSignature.h @@ -0,0 +1,12 @@ +// FindSignature.h + +#ifndef __FINDSIGNATURE_H +#define __FINDSIGNATURE_H + +#include "../../IStream.h" + +HRESULT FindSignatureInStream(ISequentialInStream *stream, + const Byte *signature, unsigned signatureSize, + const UInt64 *limit, UInt64 &resPos); + +#endif diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp new file mode 100755 index 0000000..c2254a7 --- /dev/null +++ b/CPP/7zip/Archive/Common/HandlerOut.cpp @@ -0,0 +1,623 @@ +// HandlerOut.cpp + +#include "StdAfx.h" + +#include "../../../Common/StringToInt.h" + +#include "../../../Windows/PropVariant.h" + +#ifndef _7ZIP_ST +#include "../../../Windows/System.h" +#endif + +#include "../../ICoder.h" + +#include "../Common/ParseProperties.h" + +#include "HandlerOut.h" + +using namespace NWindows; + +namespace NArchive { + +static const wchar_t *kCopyMethod = L"Copy"; +static const wchar_t *kLZMAMethodName = L"LZMA"; +static const wchar_t *kLZMA2MethodName = L"LZMA2"; +static const wchar_t *kBZip2MethodName = L"BZip2"; +static const wchar_t *kPpmdMethodName = L"PPMd"; +static const wchar_t *kDeflateMethodName = L"Deflate"; +static const wchar_t *kDeflate64MethodName = L"Deflate64"; + +static const wchar_t *kLzmaMatchFinderX1 = L"HC4"; +static const wchar_t *kLzmaMatchFinderX5 = L"BT4"; + +static const UInt32 kLzmaAlgoX1 = 0; +static const UInt32 kLzmaAlgoX5 = 1; + +static const UInt32 kLzmaDicSizeX1 = 1 << 16; +static const UInt32 kLzmaDicSizeX3 = 1 << 20; +static const UInt32 kLzmaDicSizeX5 = 1 << 24; +static const UInt32 kLzmaDicSizeX7 = 1 << 25; +static const UInt32 kLzmaDicSizeX9 = 1 << 26; + +static const UInt32 kLzmaFastBytesX1 = 32; +static const UInt32 kLzmaFastBytesX7 = 64; + +static const UInt32 kPpmdMemSizeX1 = (1 << 22); +static const UInt32 kPpmdMemSizeX5 = (1 << 24); +static const UInt32 kPpmdMemSizeX7 = (1 << 26); +static const UInt32 kPpmdMemSizeX9 = (192 << 20); + +static const UInt32 kPpmdOrderX1 = 4; +static const UInt32 kPpmdOrderX5 = 6; +static const UInt32 kPpmdOrderX7 = 16; +static const UInt32 kPpmdOrderX9 = 32; + +static const UInt32 kDeflateAlgoX1 = 0; +static const UInt32 kDeflateAlgoX5 = 1; + +static const UInt32 kDeflateFastBytesX1 = 32; +static const UInt32 kDeflateFastBytesX7 = 64; +static const UInt32 kDeflateFastBytesX9 = 128; + +static const UInt32 kDeflatePassesX1 = 1; +static const UInt32 kDeflatePassesX7 = 3; +static const UInt32 kDeflatePassesX9 = 10; + +static const UInt32 kBZip2NumPassesX1 = 1; +static const UInt32 kBZip2NumPassesX7 = 2; +static const UInt32 kBZip2NumPassesX9 = 7; + +static const UInt32 kBZip2DicSizeX1 = 100000; +static const UInt32 kBZip2DicSizeX3 = 500000; +static const UInt32 kBZip2DicSizeX5 = 900000; + +static const wchar_t *kDefaultMethodName = kLZMAMethodName; + +static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; +static const UInt32 kDictionaryForHeaders = 1 << 20; +static const UInt32 kNumFastBytesForHeaders = 273; +static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5; + +static bool AreEqual(const UString &methodName, const wchar_t *s) + { return (methodName.CompareNoCase(s) == 0); } + +bool COneMethodInfo::IsLzma() const +{ + return + AreEqual(MethodName, kLZMAMethodName) || + AreEqual(MethodName, kLZMA2MethodName); +} + +static inline bool IsBZip2Method(const UString &methodName) + { return AreEqual(methodName, kBZip2MethodName); } + +static inline bool IsPpmdMethod(const UString &methodName) + { return AreEqual(methodName, kPpmdMethodName); } + +static inline bool IsDeflateMethod(const UString &methodName) +{ + return + AreEqual(methodName, kDeflateMethodName) || + AreEqual(methodName, kDeflate64MethodName); +} + +struct CNameToPropID +{ + PROPID PropID; + VARTYPE VarType; + const wchar_t *Name; +}; + +static CNameToPropID g_NameToPropID[] = +{ + { NCoderPropID::kBlockSize, VT_UI4, L"C" }, + { NCoderPropID::kDictionarySize, VT_UI4, L"D" }, + { NCoderPropID::kUsedMemorySize, VT_UI4, L"MEM" }, + + { NCoderPropID::kOrder, VT_UI4, L"O" }, + { NCoderPropID::kPosStateBits, VT_UI4, L"PB" }, + { NCoderPropID::kLitContextBits, VT_UI4, L"LC" }, + { NCoderPropID::kLitPosBits, VT_UI4, L"LP" }, + { NCoderPropID::kEndMarker, VT_BOOL, L"eos" }, + + { NCoderPropID::kNumPasses, VT_UI4, L"Pass" }, + { NCoderPropID::kNumFastBytes, VT_UI4, L"fb" }, + { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" }, + { NCoderPropID::kAlgorithm, VT_UI4, L"a" }, + { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" }, + { NCoderPropID::kNumThreads, VT_UI4, L"mt" }, + { NCoderPropID::kDefaultProp, VT_UI4, L"" } +}; + +static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp) +{ + if (varType == srcProp.vt) + { + destProp = srcProp; + return true; + } + if (varType == VT_UI1) + { + if (srcProp.vt == VT_UI4) + { + UInt32 value = srcProp.ulVal; + if (value > 0xFF) + return false; + destProp = (Byte)value; + return true; + } + } + else if (varType == VT_BOOL) + { + bool res; + if (SetBoolProperty(res, srcProp) != S_OK) + return false; + destProp = res; + return true; + } + return false; +} + +static int FindPropIdExact(const UString &name) +{ + for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++) + if (name.CompareNoCase(g_NameToPropID[i].Name) == 0) + return i; + return -1; +} + +static int FindPropIdStart(const UString &name) +{ + for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++) + { + UString t = g_NameToPropID[i].Name; + if (t.CompareNoCase(name.Left(t.Length())) == 0) + return i; + } + return -1; +} + +static void SetMethodProp(COneMethodInfo &m, PROPID propID, const NCOM::CPropVariant &value) +{ + for (int j = 0; j < m.Props.Size(); j++) + if (m.Props[j].Id == propID) + return; + CProp prop; + prop.Id = propID; + prop.Value = value; + m.Props.Add(prop); +} + +void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo + #ifndef _7ZIP_ST + , UInt32 numThreads + #endif + ) +{ + UInt32 level = _level; + if (oneMethodInfo.MethodName.IsEmpty()) + oneMethodInfo.MethodName = kDefaultMethodName; + + if (oneMethodInfo.IsLzma()) + { + UInt32 dicSize = + (level >= 9 ? kLzmaDicSizeX9 : + (level >= 7 ? kLzmaDicSizeX7 : + (level >= 5 ? kLzmaDicSizeX5 : + (level >= 3 ? kLzmaDicSizeX3 : + kLzmaDicSizeX1)))); + + UInt32 algo = + (level >= 5 ? kLzmaAlgoX5 : + kLzmaAlgoX1); + + UInt32 fastBytes = + (level >= 7 ? kLzmaFastBytesX7 : + kLzmaFastBytesX1); + + const wchar_t *matchFinder = + (level >= 5 ? kLzmaMatchFinderX5 : + kLzmaMatchFinderX1); + + SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); + SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); + SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); + SetMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder); + #ifndef _7ZIP_ST + SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); + #endif + } + else if (IsDeflateMethod(oneMethodInfo.MethodName)) + { + UInt32 fastBytes = + (level >= 9 ? kDeflateFastBytesX9 : + (level >= 7 ? kDeflateFastBytesX7 : + kDeflateFastBytesX1)); + + UInt32 numPasses = + (level >= 9 ? kDeflatePassesX9 : + (level >= 7 ? kDeflatePassesX7 : + kDeflatePassesX1)); + + UInt32 algo = + (level >= 5 ? kDeflateAlgoX5 : + kDeflateAlgoX1); + + SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); + SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); + SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); + } + else if (IsBZip2Method(oneMethodInfo.MethodName)) + { + UInt32 numPasses = + (level >= 9 ? kBZip2NumPassesX9 : + (level >= 7 ? kBZip2NumPassesX7 : + kBZip2NumPassesX1)); + + UInt32 dicSize = + (level >= 5 ? kBZip2DicSizeX5 : + (level >= 3 ? kBZip2DicSizeX3 : + kBZip2DicSizeX1)); + + SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); + SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); + #ifndef _7ZIP_ST + SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); + #endif + } + else if (IsPpmdMethod(oneMethodInfo.MethodName)) + { + UInt32 useMemSize = + (level >= 9 ? kPpmdMemSizeX9 : + (level >= 7 ? kPpmdMemSizeX7 : + (level >= 5 ? kPpmdMemSizeX5 : + kPpmdMemSizeX1))); + + UInt32 order = + (level >= 9 ? kPpmdOrderX9 : + (level >= 7 ? kPpmdOrderX7 : + (level >= 5 ? kPpmdOrderX5 : + kPpmdOrderX1))); + + SetMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize); + SetMethodProp(oneMethodInfo, NCoderPropID::kOrder, order); + } +} + +static void SplitParams(const UString &srcString, UStringVector &subStrings) +{ + subStrings.Clear(); + UString name; + int len = srcString.Length(); + if (len == 0) + return; + for (int i = 0; i < len; i++) + { + wchar_t c = srcString[i]; + if (c == L':') + { + subStrings.Add(name); + name.Empty(); + } + else + name += c; + } + subStrings.Add(name); +} + +static void SplitParam(const UString ¶m, UString &name, UString &value) +{ + int eqPos = param.Find(L'='); + if (eqPos >= 0) + { + name = param.Left(eqPos); + value = param.Mid(eqPos + 1); + return; + } + for(int i = 0; i < param.Length(); i++) + { + wchar_t c = param[i]; + if (c >= L'0' && c <= L'9') + { + name = param.Left(i); + value = param.Mid(i); + return; + } + } + name = param; +} + +HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value) +{ + CProp prop; + int index = FindPropIdExact(name); + if (index < 0) + return E_INVALIDARG; + const CNameToPropID &nameToPropID = g_NameToPropID[index]; + prop.Id = nameToPropID.PropID; + + if (prop.Id == NCoderPropID::kBlockSize || + prop.Id == NCoderPropID::kDictionarySize || + prop.Id == NCoderPropID::kUsedMemorySize) + { + UInt32 dicSize; + RINOK(ParsePropDictionaryValue(value, dicSize)); + prop.Value = dicSize; + } + 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 + { + UInt32 number; + if (ParseStringToUInt32(value, number) == value.Length()) + propValue = number; + else + propValue = value; + } + + if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value)) + return E_INVALIDARG; + } + oneMethodInfo.Props.Add(prop); + return S_OK; +} + +HRESULT COutHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString) +{ + UStringVector params; + SplitParams(srcString, params); + if (params.Size() > 0) + oneMethodInfo.MethodName = params[0]; + for (int i = 1; i < params.Size(); i++) + { + const UString ¶m = params[i]; + UString name, value; + SplitParam(param, name, value); + RINOK(SetParam(oneMethodInfo, name, value)); + } + return S_OK; +} + +HRESULT COutHandler::SetSolidSettings(const UString &s) +{ + UString s2 = s; + s2.MakeUpper(); + for (int i = 0; i < s2.Length();) + { + 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.Length()) + return E_INVALIDARG; + wchar_t c = s2[i++]; + switch(c) + { + case 'F': + if (v < 1) + v = 1; + _numSolidFiles = v; + break; + case 'B': + _numSolidBytes = v; + _numSolidBytesDefined = true; + break; + case 'K': + _numSolidBytes = (v << 10); + _numSolidBytesDefined = true; + break; + case 'M': + _numSolidBytes = (v << 20); + _numSolidBytesDefined = true; + break; + case 'G': + _numSolidBytes = (v << 30); + _numSolidBytesDefined = true; + break; + default: + return E_INVALIDARG; + } + } + return S_OK; +} + +HRESULT COutHandler::SetSolidSettings(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 SetSolidSettings(value.bstrVal); + default: + return E_INVALIDARG; + } + if (isSolid) + InitSolid(); + else + _numSolidFiles = 1; + return S_OK; +} + +void COutHandler::Init() +{ + _removeSfxBlock = false; + _compressHeaders = true; + _encryptHeadersSpecified = false; + _encryptHeaders = false; + + WriteCTime = false; + WriteATime = false; + WriteMTime = true; + + #ifndef _7ZIP_ST + _numThreads = NSystem::GetNumberOfProcessors(); + #endif + + _level = 5; + _autoFilter = true; + _volumeMode = false; + _crcSize = 4; + InitSolid(); +} + +void COutHandler::BeforeSetProperty() +{ + Init(); + #ifndef _7ZIP_ST + numProcessors = NSystem::GetNumberOfProcessors(); + #endif + + mainDicSize = 0xFFFFFFFF; + mainDicMethodIndex = 0xFFFFFFFF; + minNumber = 0; + _crcSize = 4; +} + +HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) +{ + UString name = nameSpec; + name.MakeUpper(); + if (name.IsEmpty()) + return E_INVALIDARG; + + if (name[0] == 'X') + { + name.Delete(0); + _level = 9; + return ParsePropValue(name, value, _level); + } + + if (name[0] == L'S') + { + name.Delete(0); + if (name.IsEmpty()) + return SetSolidSettings(value); + if (value.vt != VT_EMPTY) + return E_INVALIDARG; + return SetSolidSettings(name); + } + + if (name == L"CRC") + { + _crcSize = 4; + name.Delete(0, 3); + return ParsePropValue(name, value, _crcSize); + } + + UInt32 number; + int index = ParseStringToUInt32(name, number); + UString realName = name.Mid(index); + if (index == 0) + { + if(name.Left(2).CompareNoCase(L"MT") == 0) + { + #ifndef _7ZIP_ST + RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); + #endif + return S_OK; + } + if (name.CompareNoCase(L"RSFX") == 0) return SetBoolProperty(_removeSfxBlock, value); + if (name.CompareNoCase(L"F") == 0) return SetBoolProperty(_autoFilter, value); + if (name.CompareNoCase(L"HC") == 0) return SetBoolProperty(_compressHeaders, value); + if (name.CompareNoCase(L"HCF") == 0) + { + bool compressHeadersFull = true; + RINOK(SetBoolProperty(compressHeadersFull, value)); + if (!compressHeadersFull) + return E_INVALIDARG; + return S_OK; + } + if (name.CompareNoCase(L"HE") == 0) + { + RINOK(SetBoolProperty(_encryptHeaders, value)); + _encryptHeadersSpecified = true; + return S_OK; + } + if (name.CompareNoCase(L"TC") == 0) return SetBoolProperty(WriteCTime, value); + if (name.CompareNoCase(L"TA") == 0) return SetBoolProperty(WriteATime, value); + if (name.CompareNoCase(L"TM") == 0) return SetBoolProperty(WriteMTime, value); + if (name.CompareNoCase(L"V") == 0) return SetBoolProperty(_volumeMode, value); + number = 0; + } + if (number > 10000) + return E_FAIL; + if (number < minNumber) + return E_INVALIDARG; + number -= minNumber; + for(int j = _methods.Size(); j <= (int)number; j++) + { + COneMethodInfo oneMethodInfo; + _methods.Add(oneMethodInfo); + } + + COneMethodInfo &oneMethodInfo = _methods[number]; + + if (realName.Length() == 0) + { + if (value.vt != VT_BSTR) + return E_INVALIDARG; + + RINOK(SetParams(oneMethodInfo, value.bstrVal)); + } + else + { + int index = FindPropIdStart(realName); + if (index < 0) + return E_INVALIDARG; + const CNameToPropID &nameToPropID = g_NameToPropID[index]; + CProp prop; + prop.Id = nameToPropID.PropID; + + if (prop.Id == NCoderPropID::kBlockSize || + prop.Id == NCoderPropID::kDictionarySize || + prop.Id == NCoderPropID::kUsedMemorySize) + { + UInt32 dicSize; + RINOK(ParsePropDictionaryValue(realName.Mid(MyStringLen(nameToPropID.Name)), value, dicSize)); + prop.Value = dicSize; + if (number <= mainDicMethodIndex) + mainDicSize = dicSize; + } + else + { + int index = FindPropIdExact(realName); + if (index < 0) + return E_INVALIDARG; + const CNameToPropID &nameToPropID = g_NameToPropID[index]; + prop.Id = nameToPropID.PropID; + if (!ConvertProperty(value, nameToPropID.VarType, prop.Value)) + return E_INVALIDARG; + } + oneMethodInfo.Props.Add(prop); + } + return S_OK; +} + +} diff --git a/CPP/7zip/Archive/Common/HandlerOut.h b/CPP/7zip/Archive/Common/HandlerOut.h new file mode 100755 index 0000000..c4ccf37 --- /dev/null +++ b/CPP/7zip/Archive/Common/HandlerOut.h @@ -0,0 +1,87 @@ +// HandlerOut.h + +#ifndef __HANDLER_OUT_H +#define __HANDLER_OUT_H + +#include "../../../Common/MyString.h" +#include "../../Common/MethodProps.h" + +namespace NArchive { + +struct COneMethodInfo +{ + CObjectVector Props; + UString MethodName; + + bool IsLzma() const; +}; + +class COutHandler +{ +public: + HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); + + HRESULT SetSolidSettings(const UString &s); + HRESULT SetSolidSettings(const PROPVARIANT &value); + + #ifndef _7ZIP_ST + UInt32 _numThreads; + #endif + + UInt32 _crcSize; + + CObjectVector _methods; + bool _removeSfxBlock; + + UInt64 _numSolidFiles; + UInt64 _numSolidBytes; + bool _numSolidBytesDefined; + bool _solidExtension; + + bool _compressHeaders; + bool _encryptHeadersSpecified; + bool _encryptHeaders; + + bool WriteCTime; + bool WriteATime; + bool WriteMTime; + + bool _autoFilter; + UInt32 _level; + + bool _volumeMode; + + HRESULT SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value); + HRESULT SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString); + + void SetCompressionMethod2(COneMethodInfo &oneMethodInfo + #ifndef _7ZIP_ST + , UInt32 numThreads + #endif + ); + + void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); } + void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); } + void InitSolid() + { + InitSolidFiles(); + InitSolidSize(); + _solidExtension = false; + _numSolidBytesDefined = false; + } + + void Init(); + + COutHandler() { Init(); } + + void BeforeSetProperty(); + + UInt32 minNumber; + UInt32 numProcessors; + UInt32 mainDicSize; + UInt32 mainDicMethodIndex; +}; + +} + +#endif diff --git a/CPP/7zip/Archive/Common/InStreamWithCRC.cpp b/CPP/7zip/Archive/Common/InStreamWithCRC.cpp new file mode 100755 index 0000000..6338d0a --- /dev/null +++ b/CPP/7zip/Archive/Common/InStreamWithCRC.cpp @@ -0,0 +1,42 @@ +// InStreamWithCRC.cpp + +#include "StdAfx.h" + +#include "InStreamWithCRC.h" + +STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessedSize; + HRESULT result = _stream->Read(data, size, &realProcessedSize); + _size += realProcessedSize; + if (size > 0 && realProcessedSize == 0) + _wasFinished = true; + _crc = CrcUpdate(_crc, data, realProcessedSize); + if(processedSize != NULL) + *processedSize = realProcessedSize; + return result; +} + +STDMETHODIMP CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessedSize; + HRESULT result = _stream->Read(data, size, &realProcessedSize); + /* + if (size > 0 && realProcessedSize == 0) + _wasFinished = true; + */ + _size += realProcessedSize; + _crc = CrcUpdate(_crc, data, realProcessedSize); + if(processedSize != NULL) + *processedSize = realProcessedSize; + 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/CPP/7zip/Archive/Common/InStreamWithCRC.h b/CPP/7zip/Archive/Common/InStreamWithCRC.h new file mode 100755 index 0000000..1a4b2c9 --- /dev/null +++ b/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/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/CPP/7zip/Archive/Common/ItemNameUtils.cpp new file mode 100755 index 0000000..287ddce --- /dev/null +++ b/CPP/7zip/Archive/Common/ItemNameUtils.cpp @@ -0,0 +1,61 @@ +// Archive/Common/ItemNameUtils.cpp + +#include "StdAfx.h" + +#include "../../../../C/Types.h" + +#include "ItemNameUtils.h" + +namespace NArchive { +namespace NItemName { + +static const wchar_t kOSDirDelimiter = WCHAR_PATH_SEPARATOR; +static const wchar_t kDirDelimiter = L'/'; + +UString MakeLegalName(const UString &name) +{ + UString zipName = name; + zipName.Replace(kOSDirDelimiter, kDirDelimiter); + return zipName; +} + +UString GetOSName(const UString &name) +{ + UString newName = name; + newName.Replace(kDirDelimiter, kOSDirDelimiter); + return newName; +} + +UString GetOSName2(const UString &name) +{ + if (name.IsEmpty()) + return UString(); + UString newName = GetOSName(name); + if (newName[newName.Length() - 1] == kOSDirDelimiter) + newName.Delete(newName.Length() - 1); + return newName; +} + +bool HasTailSlash(const AString &name, UINT codePage) +{ + if (name.IsEmpty()) + return false; + LPCSTR prev = + #if defined(_WIN32) && !defined(UNDER_CE) + CharPrevExA((WORD)codePage, name, &name[name.Length()], 0); + #else + (LPCSTR)(name) + (name.Length() - 1); + #endif + return (*prev == '/'); +} + +#ifndef _WIN32 +UString WinNameToOSName(const UString &name) +{ + UString newName = name; + newName.Replace(L'\\', kOSDirDelimiter); + return newName; +} +#endif + +}} diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.h b/CPP/7zip/Archive/Common/ItemNameUtils.h new file mode 100755 index 0000000..8b91d1c --- /dev/null +++ b/CPP/7zip/Archive/Common/ItemNameUtils.h @@ -0,0 +1,24 @@ +// Archive/Common/ItemNameUtils.h + +#ifndef __ARCHIVE_ITEMNAMEUTILS_H +#define __ARCHIVE_ITEMNAMEUTILS_H + +#include "../../../Common/MyString.h" + +namespace NArchive { +namespace NItemName { + + UString MakeLegalName(const UString &name); + UString GetOSName(const UString &name); + UString GetOSName2(const UString &name); + bool HasTailSlash(const AString &name, UINT codePage); + + #ifdef _WIN32 + inline UString WinNameToOSName(const UString &name) { return name; } + #else + UString WinNameToOSName(const UString &name); + #endif + +}} + +#endif diff --git a/CPP/7zip/Archive/Common/MultiStream.cpp b/CPP/7zip/Archive/Common/MultiStream.cpp new file mode 100755 index 0000000..83b3da1 --- /dev/null +++ b/CPP/7zip/Archive/Common/MultiStream.cpp @@ -0,0 +1,190 @@ +// 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 (_pos == _totalLength) ? S_OK : E_FAIL; + + { + int 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: _pos = offset; break; + case STREAM_SEEK_CUR: _pos = _pos + offset; break; + case STREAM_SEEK_END: _pos = _totalLength + offset; break; + default: return STG_E_INVALIDFUNCTION; + } + if (newPosition != 0) + *newPosition = _pos; + return S_OK; +} + + +/* +class COutVolumeStream: + public ISequentialOutStream, + public CMyUnknownImp +{ + int _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 != NULL) + *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 != NULL) + *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) +{ + 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; + _streamIndex = 0; + return S_OK; +} +*/ diff --git a/CPP/7zip/Archive/Common/MultiStream.h b/CPP/7zip/Archive/Common/MultiStream.h new file mode 100755 index 0000000..74ec6ad --- /dev/null +++ b/CPP/7zip/Archive/Common/MultiStream.h @@ -0,0 +1,84 @@ +// 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; + int _streamIndex; +public: + struct CSubStreamInfo + { + CMyComPtr Stream; + UInt64 Size; + UInt64 GlobalOffset; + UInt64 LocalPos; + }; + CObjectVector Streams; + + HRESULT Init() + { + UInt64 total = 0; + for (int i = 0; i < Streams.Size(); i++) + { + 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 +{ + int _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/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp b/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp new file mode 100755 index 0000000..e0d3894 --- /dev/null +++ b/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/CPP/7zip/Archive/Common/OutStreamWithCRC.h b/CPP/7zip/Archive/Common/OutStreamWithCRC.h new file mode 100755 index 0000000..d9eb646 --- /dev/null +++ b/CPP/7zip/Archive/Common/OutStreamWithCRC.h @@ -0,0 +1,36 @@ +// 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 InitCRC() { _crc = CRC_INIT_VAL; } + UInt64 GetSize() const { return _size; } + UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } +}; + +#endif diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp new file mode 100755 index 0000000..ba10802 --- /dev/null +++ b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp @@ -0,0 +1,18 @@ +// OutStreamWithSha1.cpp + +#include "StdAfx.h" + +#include "OutStreamWithSha1.h" + +STDMETHODIMP COutStreamWithSha1::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + HRESULT result = S_OK; + if (_stream) + result = _stream->Write(data, size, &size); + if (_calculate) + _sha.Update((const Byte *)data, size); + _size += size; + if (processedSize != NULL) + *processedSize = size; + return result; +} diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.h b/CPP/7zip/Archive/Common/OutStreamWithSha1.h new file mode 100755 index 0000000..9e13244 --- /dev/null +++ b/CPP/7zip/Archive/Common/OutStreamWithSha1.h @@ -0,0 +1,36 @@ +// OutStreamWithSha1.h + +#ifndef __OUT_STREAM_WITH_SHA1_H +#define __OUT_STREAM_WITH_SHA1_H + +#include "../../Crypto/Sha1.h" + +#include "../../../Common/MyCom.h" + +#include "../../IStream.h" + +class COutStreamWithSha1: + public ISequentialOutStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + UInt64 _size; + NCrypto::NSha1::CContext _sha; + 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; + _sha.Init(); + } + void InitSha1() { _sha.Init(); } + UInt64 GetSize() const { return _size; } + void Final(Byte *digest) { _sha.Final(digest); } +}; + +#endif diff --git a/CPP/7zip/Archive/Common/ParseProperties.cpp b/CPP/7zip/Archive/Common/ParseProperties.cpp new file mode 100755 index 0000000..5550a23 --- /dev/null +++ b/CPP/7zip/Archive/Common/ParseProperties.cpp @@ -0,0 +1,177 @@ +// ParseProperties.cpp + +#include "StdAfx.h" + +#include "ParseProperties.h" + +#include "Common/StringToInt.h" +#include "Common/MyCom.h" + +HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) +{ + if (prop.vt == VT_UI4) + { + if (!name.IsEmpty()) + return E_INVALIDARG; + resValue = prop.ulVal; + } + else if (prop.vt == VT_EMPTY) + { + if(!name.IsEmpty()) + { + const wchar_t *start = name; + const wchar_t *end; + UInt64 v = ConvertStringToUInt64(start, &end); + if (end - start != name.Length()) + return E_INVALIDARG; + resValue = (UInt32)v; + } + } + else + return E_INVALIDARG; + return S_OK; +} + +static const int kLogarithmicSizeLimit = 32; +static const wchar_t kByteSymbol = L'B'; +static const wchar_t kKiloByteSymbol = L'K'; +static const wchar_t kMegaByteSymbol = L'M'; + +HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize) +{ + UString srcString = srcStringSpec; + srcString.MakeUpper(); + + const wchar_t *start = srcString; + const wchar_t *end; + UInt64 number = ConvertStringToUInt64(start, &end); + int numDigits = (int)(end - start); + if (numDigits == 0 || srcString.Length() > numDigits + 1) + return E_INVALIDARG; + if (srcString.Length() == numDigits) + { + if (number >= kLogarithmicSizeLimit) + return E_INVALIDARG; + dicSize = (UInt32)1 << (int)number; + return S_OK; + } + switch (srcString[numDigits]) + { + case kByteSymbol: + if (number >= ((UInt64)1 << kLogarithmicSizeLimit)) + return E_INVALIDARG; + dicSize = (UInt32)number; + break; + case kKiloByteSymbol: + if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 10))) + return E_INVALIDARG; + dicSize = (UInt32)(number << 10); + break; + case kMegaByteSymbol: + if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 20))) + return E_INVALIDARG; + dicSize = (UInt32)(number << 20); + break; + default: + return E_INVALIDARG; + } + return S_OK; +} + +HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) +{ + if (name.IsEmpty()) + { + if (prop.vt == VT_UI4) + { + UInt32 logDicSize = prop.ulVal; + if (logDicSize >= 32) + return E_INVALIDARG; + resValue = (UInt32)1 << logDicSize; + return S_OK; + } + if (prop.vt == VT_BSTR) + return ParsePropDictionaryValue(prop.bstrVal, resValue); + return E_INVALIDARG; + } + return ParsePropDictionaryValue(name, resValue); +} + +bool StringToBool(const UString &s, bool &res) +{ + if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0 || s.Compare(L"+") == 0) + { + res = true; + return true; + } + if (s.CompareNoCase(L"OFF") == 0 || s.Compare(L"-") == 0) + { + res = false; + return true; + } + return false; +} + +HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value) +{ + switch(value.vt) + { + case VT_EMPTY: + dest = true; + return S_OK; + case VT_BOOL: + dest = (value.boolVal != VARIANT_FALSE); + return S_OK; + /* + case VT_UI4: + dest = (value.ulVal != 0); + break; + */ + case VT_BSTR: + return StringToBool(value.bstrVal, dest) ? S_OK : E_INVALIDARG; + } + return E_INVALIDARG; +} + +int ParseStringToUInt32(const UString &srcString, UInt32 &number) +{ + const wchar_t *start = srcString; + const wchar_t *end; + UInt64 number64 = ConvertStringToUInt64(start, &end); + if (number64 > 0xFFFFFFFF) + { + number = 0; + return 0; + } + number = (UInt32)number64; + return (int)(end - start); +} + +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(SetBoolProperty(val, prop)); + numThreads = (val ? defaultNumThreads : 1); + break; + } + } + } + else + { + UInt32 number; + int index = ParseStringToUInt32(name, number); + if (index != name.Length()) + return E_INVALIDARG; + numThreads = number; + } + return S_OK; +} diff --git a/CPP/7zip/Archive/Common/ParseProperties.h b/CPP/7zip/Archive/Common/ParseProperties.h new file mode 100755 index 0000000..c64fc1e --- /dev/null +++ b/CPP/7zip/Archive/Common/ParseProperties.h @@ -0,0 +1,18 @@ +// ParseProperties.h + +#ifndef __PARSEPROPERTIES_H +#define __PARSEPROPERTIES_H + +#include "Common/MyString.h" +#include "Common/Types.h" + +HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); +HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize); +HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); + +bool StringToBool(const UString &s, bool &res); +HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value); +int ParseStringToUInt32(const UString &srcString, UInt32 &number); +HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads); + +#endif diff --git a/CPP/7zip/Archive/Common/StdAfx.h b/CPP/7zip/Archive/Common/StdAfx.h new file mode 100755 index 0000000..a4e6173 --- /dev/null +++ b/CPP/7zip/Archive/Common/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" +#include "../../../Common/NewHandler.h" + +#endif diff --git a/CPP/7zip/Archive/CpioHandler.cpp b/CPP/7zip/Archive/CpioHandler.cpp new file mode 100755 index 0000000..44633f2 --- /dev/null +++ b/CPP/7zip/Archive/CpioHandler.cpp @@ -0,0 +1,624 @@ +// CpioHandler.cpp + +#include "StdAfx.h" + +#include "Common/ComTry.h" +#include "Common/StringConvert.h" +#include "Common/StringToInt.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +#include "Common/ItemNameUtils.h" + +namespace NArchive { +namespace NCpio { + +namespace NFileHeader +{ + namespace NMagic + { + const char *kMagic1 = "070701"; + const char *kMagic2 = "070702"; + const char *kMagic3 = "070707"; + const char *kEndName = "TRAILER!!!"; + + const Byte kMagicForRecord2[2] = { 0xC7, 0x71 }; + } + + const UInt32 kRecord2Size = 26; + /* + struct CRecord2 + { + unsigned short c_magic; + short c_dev; + unsigned short c_ino; + unsigned short c_mode; + unsigned short c_uid; + unsigned short c_gid; + unsigned short c_nlink; + short c_rdev; + unsigned short c_mtimes[2]; + unsigned short c_namesize; + unsigned short c_filesizes[2]; + }; + */ + + const UInt32 kRecordSize = 110; + /* + struct CRecord + { + char Magic[6]; // "070701" for "new" portable format, "070702" for CRC format + char inode[8]; + char Mode[8]; + char UID[8]; + char GID[8]; + char nlink[8]; + char mtime[8]; + char Size[8]; // must be 0 for FIFOs and directories + char DevMajor[8]; + char DevMinor[8]; + char RDevMajor[8]; //only valid for chr and blk special files + char RDevMinor[8]; //only valid for chr and blk special files + char NameSize[8]; // count includes terminating NUL in pathname + char ChkSum[8]; // 0 for "new" portable format; for CRC format the sum of all the bytes in the file + bool CheckMagic() const + { return memcmp(Magic, NMagic::kMagic1, 6) == 0 || + memcmp(Magic, NMagic::kMagic2, 6) == 0; }; + }; + */ + + const UInt32 kOctRecordSize = 76; + +} + +struct CItem +{ + AString Name; + UInt32 inode; + UInt32 Mode; + UInt32 UID; + UInt32 GID; + UInt32 Size; + UInt32 MTime; + + // char LinkFlag; + // AString LinkName; ????? + char Magic[8]; + UInt32 NumLinks; + UInt32 DevMajor; + UInt32 DevMinor; + UInt32 RDevMajor; + UInt32 RDevMinor; + UInt32 ChkSum; + + UInt32 Align; + + bool IsDir() const { return (Mode & 0170000) == 0040000; } +}; + +class CItemEx: public CItem +{ +public: + UInt64 HeaderPosition; + UInt32 HeaderSize; + UInt64 GetDataPosition() const { return HeaderPosition + HeaderSize; }; +}; + +const UInt32 kMaxBlockSize = NFileHeader::kRecordSize; + +class CInArchive +{ + CMyComPtr m_Stream; + UInt64 m_Position; + + UInt16 _blockSize; + Byte _block[kMaxBlockSize]; + UInt32 _blockPos; + Byte ReadByte(); + UInt16 ReadUInt16(); + UInt32 ReadUInt32(); + + bool ReadNumber(UInt32 &resultValue); + bool ReadOctNumber(int size, UInt32 &resultValue); + + HRESULT ReadBytes(void *data, UInt32 size, UInt32 &processedSize); +public: + HRESULT Open(IInStream *inStream); + HRESULT GetNextItem(bool &filled, CItemEx &itemInfo); + HRESULT Skip(UInt64 numBytes); + HRESULT SkipDataRecords(UInt64 dataSize, UInt32 align); +}; + +HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize) +{ + size_t realProcessedSize = size; + RINOK(ReadStream(m_Stream, data, &realProcessedSize)); + processedSize = (UInt32)realProcessedSize; + m_Position += processedSize; + return S_OK; +} + +Byte CInArchive::ReadByte() +{ + if (_blockPos >= _blockSize) + throw "Incorrect cpio archive"; + return _block[_blockPos++]; +} + +UInt16 CInArchive::ReadUInt16() +{ + UInt16 value = 0; + for (int i = 0; i < 2; i++) + { + Byte b = ReadByte(); + value |= (UInt16(b) << (8 * i)); + } + return value; +} + +UInt32 CInArchive::ReadUInt32() +{ + UInt32 value = 0; + for (int i = 0; i < 4; i++) + { + Byte b = ReadByte(); + value |= (UInt32(b) << (8 * i)); + } + return value; +} + +HRESULT CInArchive::Open(IInStream *inStream) +{ + RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position)); + m_Stream = inStream; + return S_OK; +} + +bool CInArchive::ReadNumber(UInt32 &resultValue) +{ + resultValue = 0; + for (int i = 0; i < 8; i++) + { + char c = char(ReadByte()); + int d; + if (c >= '0' && c <= '9') + d = c - '0'; + else if (c >= 'A' && c <= 'F') + d = 10 + c - 'A'; + else if (c >= 'a' && c <= 'f') + d = 10 + c - 'a'; + else + return false; + resultValue *= 0x10; + resultValue += d; + } + return true; +} + +static bool OctalToNumber(const char *s, UInt64 &res) +{ + const char *end; + res = ConvertOctStringToUInt64(s, &end); + return (*end == ' ' || *end == 0); +} + +static bool OctalToNumber32(const char *s, UInt32 &res) +{ + UInt64 res64; + if (!OctalToNumber(s, res64)) + return false; + res = (UInt32)res64; + return (res64 <= 0xFFFFFFFF); +} + +bool CInArchive::ReadOctNumber(int size, UInt32 &resultValue) +{ + char sz[32 + 4]; + int i; + for (i = 0; i < size && i < 32; i++) + sz[i] = (char)ReadByte(); + sz[i] = 0; + return OctalToNumber32(sz, resultValue); +} + +#define GetFromHex(y) { if (!ReadNumber(y)) return S_FALSE; } +#define GetFromOct6(y) { if (!ReadOctNumber(6, y)) return S_FALSE; } +#define GetFromOct11(y) { if (!ReadOctNumber(11, y)) return S_FALSE; } + +static unsigned short ConvertValue(unsigned short value, bool convert) +{ + if (!convert) + return value; + return (unsigned short)((((unsigned short)(value & 0xFF)) << 8) | (value >> 8)); +} + +static UInt32 GetAlignedSize(UInt32 size, UInt32 align) +{ + while ((size & (align - 1)) != 0) + size++; + return size; +} + + +HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) +{ + filled = false; + + UInt32 processedSize; + item.HeaderPosition = m_Position; + + _blockSize = kMaxBlockSize; + RINOK(ReadBytes(_block, 2, processedSize)); + if (processedSize != 2) + return S_FALSE; + _blockPos = 0; + + UInt32 nameSize; + + bool oldBE = + _block[0] == NFileHeader::NMagic::kMagicForRecord2[1] && + _block[1] == NFileHeader::NMagic::kMagicForRecord2[0]; + + bool binMode = (_block[0] == NFileHeader::NMagic::kMagicForRecord2[0] && + _block[1] == NFileHeader::NMagic::kMagicForRecord2[1]) || + oldBE; + + if (binMode) + { + RINOK(ReadBytes(_block + 2, NFileHeader::kRecord2Size - 2, processedSize)); + if (processedSize != NFileHeader::kRecord2Size - 2) + return S_FALSE; + item.Align = 2; + _blockPos = 2; + item.DevMajor = 0; + item.DevMinor = ConvertValue(ReadUInt16(), oldBE); + item.inode = ConvertValue(ReadUInt16(), oldBE); + item.Mode = ConvertValue(ReadUInt16(), oldBE); + item.UID = ConvertValue(ReadUInt16(), oldBE); + item.GID = ConvertValue(ReadUInt16(), oldBE); + item.NumLinks = ConvertValue(ReadUInt16(), oldBE); + item.RDevMajor =0; + item.RDevMinor = ConvertValue(ReadUInt16(), oldBE); + UInt16 timeHigh = ConvertValue(ReadUInt16(), oldBE); + UInt16 timeLow = ConvertValue(ReadUInt16(), oldBE); + item.MTime = (UInt32(timeHigh) << 16) + timeLow; + nameSize = ConvertValue(ReadUInt16(), oldBE); + UInt16 sizeHigh = ConvertValue(ReadUInt16(), oldBE); + UInt16 sizeLow = ConvertValue(ReadUInt16(), oldBE); + item.Size = (UInt32(sizeHigh) << 16) + sizeLow; + + item.ChkSum = 0; + item.HeaderSize = GetAlignedSize( + nameSize + NFileHeader::kRecord2Size, item.Align); + nameSize = item.HeaderSize - NFileHeader::kRecord2Size; + } + else + { + RINOK(ReadBytes(_block + 2, 4, processedSize)); + if (processedSize != 4) + return S_FALSE; + + bool magicOK = + memcmp(_block, NFileHeader::NMagic::kMagic1, 6) == 0 || + memcmp(_block, NFileHeader::NMagic::kMagic2, 6) == 0; + _blockPos = 6; + if (magicOK) + { + RINOK(ReadBytes(_block + 6, NFileHeader::kRecordSize - 6, processedSize)); + if (processedSize != NFileHeader::kRecordSize - 6) + return S_FALSE; + item.Align = 4; + + GetFromHex(item.inode); + GetFromHex(item.Mode); + GetFromHex(item.UID); + GetFromHex(item.GID); + GetFromHex(item.NumLinks); + UInt32 mTime; + GetFromHex(mTime); + item.MTime = mTime; + GetFromHex(item.Size); + GetFromHex(item.DevMajor); + GetFromHex(item.DevMinor); + GetFromHex(item.RDevMajor); + GetFromHex(item.RDevMinor); + GetFromHex(nameSize); + GetFromHex(item.ChkSum); + item.HeaderSize = GetAlignedSize( + nameSize + NFileHeader::kRecordSize, item.Align); + nameSize = item.HeaderSize - NFileHeader::kRecordSize; + } + else + { + if (!memcmp(_block, NFileHeader::NMagic::kMagic3, 6) == 0) + return S_FALSE; + RINOK(ReadBytes(_block + 6, NFileHeader::kOctRecordSize - 6, processedSize)); + if (processedSize != NFileHeader::kOctRecordSize - 6) + return S_FALSE; + item.Align = 1; + item.DevMajor = 0; + GetFromOct6(item.DevMinor); + GetFromOct6(item.inode); + GetFromOct6(item.Mode); + GetFromOct6(item.UID); + GetFromOct6(item.GID); + GetFromOct6(item.NumLinks); + item.RDevMajor = 0; + GetFromOct6(item.RDevMinor); + UInt32 mTime; + GetFromOct11(mTime); + item.MTime = mTime; + GetFromOct6(nameSize); + GetFromOct11(item.Size); // ????? + item.HeaderSize = GetAlignedSize( + nameSize + NFileHeader::kOctRecordSize, item.Align); + nameSize = item.HeaderSize - NFileHeader::kOctRecordSize; + } + } + if (nameSize == 0 || nameSize >= (1 << 27)) + return E_FAIL; + RINOK(ReadBytes(item.Name.GetBuffer(nameSize), nameSize, processedSize)); + if (processedSize != nameSize) + return E_FAIL; + item.Name.ReleaseBuffer(); + if (strcmp(item.Name, NFileHeader::NMagic::kEndName) == 0) + return S_OK; + filled = true; + return S_OK; +} + +HRESULT CInArchive::Skip(UInt64 numBytes) +{ + UInt64 newPostion; + RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion)); + m_Position += numBytes; + if (m_Position != newPostion) + return E_FAIL; + return S_OK; +} + +HRESULT CInArchive::SkipDataRecords(UInt64 dataSize, UInt32 align) +{ + while ((dataSize & (align - 1)) != 0) + dataSize++; + return Skip(dataSize); +} + + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + CObjectVector _items; + CMyComPtr _stream; +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +/* +enum +{ + kpidinode = kpidUserDefined, + kpidiChkSum +}; +*/ + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidPosixAttrib, VT_UI4}, + // { L"inode", kpidinode, VT_UI4} + // { L"CheckSum", kpidiChkSum, VT_UI4} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + // try + { + CInArchive archive; + + UInt64 endPos = 0; + bool needSetTotal = true; + + if (callback != NULL) + { + RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos)); + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + } + + RINOK(archive.Open(stream)); + + _items.Clear(); + + for (;;) + { + CItemEx item; + bool filled; + HRESULT result = archive.GetNextItem(filled, item); + if (result == S_FALSE) + return S_FALSE; + if (result != S_OK) + return S_FALSE; + if (!filled) + break; + _items.Add(item); + archive.SkipDataRecords(item.Size, item.Align); + if (callback != NULL) + { + if (needSetTotal) + { + RINOK(callback->SetTotal(NULL, &endPos)); + needSetTotal = false; + } + if (_items.Size() % 100 == 0) + { + UInt64 numFiles = _items.Size(); + UInt64 numBytes = item.HeaderPosition; + RINOK(callback->SetCompleted(&numFiles, &numBytes)); + } + } + } + if (_items.Size() == 0) + return S_FALSE; + + _stream = stream; + } + /* + catch(...) + { + return S_FALSE; + } + */ + 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 + NWindows::NCOM::CPropVariant prop; + const CItemEx &item = _items[index]; + + switch(propID) + { + case kpidPath: prop = NItemName::GetOSName(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break; + case kpidIsDir: prop = item.IsDir(); break; + case kpidSize: + case kpidPackSize: + prop = (UInt64)item.Size; + break; + case kpidMTime: + { + if (item.MTime != 0) + { + FILETIME utc; + NWindows::NTime::UnixTimeToFileTime(item.MTime, utc); + prop = utc; + } + break; + } + case kpidPosixAttrib: prop = item.Mode; break; + /* + case kpidinode: prop = item.inode; break; + case kpidiChkSum: prop = item.ChkSum; break; + */ + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _items.Size(); + if (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); + + UInt64 currentTotalSize = 0; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStream(streamSpec); + streamSpec->SetStream(_stream); + + for (i = 0; i < numItems; i++) + { + lps->InSize = lps->OutSize = currentTotalSize; + RINOK(lps->SetCur()); + CMyComPtr outStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + const CItemEx &item = _items[index]; + RINOK(extractCallback->GetStream(index, &outStream, askMode)); + currentTotalSize += item.Size; + if (item.IsDir()) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + if (!testMode && !outStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + if (testMode) + { + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + RINOK(_stream->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL)); + streamSpec->Init(item.Size); + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + outStream.Release(); + RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ? + NExtract::NOperationResult::kOK: + NExtract::NOperationResult::kDataError)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + const CItemEx &item = _items[index]; + return CreateLimitedInStream(_stream, item.GetDataPosition(), item.Size, stream); + COM_TRY_END +} + +static IInArchive *CreateArc() { return new NArchive::NCpio::CHandler; } + +static CArcInfo g_ArcInfo = + { L"Cpio", L"cpio", 0, 0xED, { 0 }, 0, false, CreateArc, 0 }; + +REGISTER_ARC(Cpio) + +}} diff --git a/CPP/7zip/Archive/CramfsHandler.cpp b/CPP/7zip/Archive/CramfsHandler.cpp new file mode 100755 index 0000000..a574cdf --- /dev/null +++ b/CPP/7zip/Archive/CramfsHandler.cpp @@ -0,0 +1,644 @@ +// CramfsHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/7zCrc.h" +#include "../../../C/CpuArch.h" +#include "../../../C/Alloc.h" + +#include "Common/ComTry.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariantUtils.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamObjects.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" +#include "../Compress/ZlibDecoder.h" + +namespace NArchive { +namespace NCramfs { + +#define SIGNATURE { 'C','o','m','p','r','e','s','s','e','d',' ','R','O','M','F','S' } + +static const UInt32 kSignatureSize = 16; +static const char kSignature[kSignatureSize] = SIGNATURE; + +static const UInt32 kArcSizeMax = (256 + 16) << 20; +static const UInt32 kNumFilesMax = (1 << 19); +static const unsigned kNumDirLevelsMax = (1 << 8); + +static const UInt32 kHeaderSize = 0x40; +static const unsigned kHeaderNameSize = 16; +static const UInt32 kNodeSize = 12; + +static const UInt32 kFlag_FsVer2 = (1 << 0); + +static const CUInt32PCharPair k_Flags[] = +{ + { 0, "Ver2" }, + { 1, "SortedDirs" }, + { 8, "Holes" }, + { 9, "WrongSignature" }, + { 10, "ShiftedRootOffset" } +}; + +static const unsigned kBlockSizeLog = 12; +static const UInt32 kBlockSize = 1 << kBlockSizeLog; + +/* +struct CNode +{ + UInt16 Mode; + UInt16 Uid; + UInt32 Size; + Byte Gid; + UInt32 NameLen; + UInt32 Offset; + + void Parse(const Byte *p) + { + Mode = GetUi16(p); + Uid = GetUi16(p + 2); + Size = Get32(p + 4) & 0xFFFFFF; + Gid = p[7]; + NameLen = p[8] & 0x3F; + Offset = Get32(p + 8) >> 6; + } +}; +*/ + +#define Get32(p) (be ? GetBe32(p) : GetUi32(p)) + +static UInt32 GetMode(const Byte *p, bool be) { return be ? GetBe16(p) : GetUi16(p); } +static bool IsDir(const Byte *p, bool be) { return (GetMode(p, be) & 0xF000) == 0x4000; } + +static UInt32 GetSize(const Byte *p, bool be) +{ + if (be) + return GetBe32(p + 4) >> 8; + else + return GetUi32(p + 4) & 0xFFFFFF; +} + +static UInt32 GetNameLen(const Byte *p, bool be) +{ + if (be) + return (p[8] & 0xFC); + else + return (p[8] & 0x3F) << 2; +} + +static UInt32 GetOffset(const Byte *p, bool be) +{ + if (be) + return (GetBe32(p + 8) & 0x03FFFFFF) << 2; + else + return GetUi32(p + 8) >> 6 << 2; +} + +struct CItem +{ + UInt32 Offset; + int Parent; +}; + +struct CHeader +{ + bool be; + UInt32 Size; + UInt32 Flags; + // UInt32 Future; + UInt32 Crc; + // UInt32 Edition; + UInt32 NumBlocks; + UInt32 NumFiles; + char Name[kHeaderNameSize]; + + bool Parse(const Byte *p) + { + if (memcmp(p + 16, kSignature, kSignatureSize) != 0) + return false; + switch(GetUi32(p)) + { + case 0x28CD3D45: be = false; break; + case 0x453DCD28: be = true; break; + default: return false; + } + Size = Get32(p + 4); + Flags = Get32(p + 8); + // Future = Get32(p + 0xC); + Crc = Get32(p + 0x20); + // Edition = Get32(p + 0x24); + NumBlocks = Get32(p + 0x28); + NumFiles = Get32(p + 0x2C); + memcpy(Name, p + 0x30, kHeaderNameSize); + return true; + } + + bool IsVer2() const { return (Flags & kFlag_FsVer2) != 0; } +}; + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + CRecordVector _items; + CMyComPtr _stream; + Byte *_data; + UInt32 _size; + UInt32 _headersSize; + AString _errorMessage; + CHeader _h; + + // Current file + + NCompress::NZlib::CDecoder *_zlibDecoderSpec; + CMyComPtr _zlibDecoder; + + CBufInStream *_inStreamSpec; + CMyComPtr _inStream; + + CBufPtrSeqOutStream *_outStreamSpec; + CMyComPtr _outStream; + + UInt32 _curBlocksOffset; + UInt32 _curNumBlocks; + + HRESULT OpenDir(int parent, UInt32 baseOffsetBase, unsigned level); + HRESULT Open2(IInStream *inStream); + AString GetPath(int index) const; + bool GetPackSize(int index, UInt32 &res) const; + void Free(); +public: + CHandler(): _data(0) {} + ~CHandler() { Free(); } + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); + HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize); +}; + +static const STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI4}, + { NULL, kpidPackSize, VT_UI4}, + { NULL, kpidPosixAttrib, VT_UI4} + // { NULL, kpidOffset, VT_UI4} +}; + +static const STATPROPSTG kArcProps[] = +{ + { NULL, kpidName, VT_BSTR}, + { NULL, kpidBigEndian, VT_BOOL}, + { NULL, kpidCharacts, VT_BSTR}, + { NULL, kpidPhySize, VT_UI4}, + { NULL, kpidHeadersSize, VT_UI4}, + { NULL, kpidNumSubFiles, VT_UI4}, + { NULL, kpidNumBlocks, VT_UI4} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +HRESULT CHandler::OpenDir(int parent, UInt32 baseOffset, unsigned level) +{ + const Byte *p = _data + baseOffset; + bool be = _h.be; + if (!IsDir(p, be)) + return S_OK; + UInt32 offset = GetOffset(p, be); + UInt32 size = GetSize(p, be); + if (offset == 0 && size == 0) + return S_OK; + UInt32 end = offset + size; + if (offset < kHeaderSize || end > _size || level > kNumDirLevelsMax) + return S_FALSE; + if (end > _headersSize) + _headersSize = end; + + int startIndex = _items.Size(); + + while (size != 0) + { + if (size < kNodeSize || (UInt32)_items.Size() >= kNumFilesMax) + return S_FALSE; + CItem item; + item.Parent = parent; + item.Offset = offset; + _items.Add(item); + UInt32 nodeLen = kNodeSize + GetNameLen(_data + offset, be); + if (size < nodeLen) + return S_FALSE; + offset += nodeLen; + size -= nodeLen; + } + + int endIndex = _items.Size(); + for (int i = startIndex; i < endIndex; i++) + { + RINOK(OpenDir(i, _items[i].Offset, level + 1)); + } + return S_OK; +} + +HRESULT CHandler::Open2(IInStream *inStream) +{ + Byte buf[kHeaderSize]; + RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize)); + if (!_h.Parse(buf)) + return S_FALSE; + if (_h.IsVer2()) + { + if (_h.Size < kHeaderSize || _h.Size > kArcSizeMax || _h.NumFiles > kNumFilesMax) + return S_FALSE; + } + else + { + UInt64 size; + RINOK(inStream->Seek(0, STREAM_SEEK_END, &size)); + if (size > kArcSizeMax) + return S_FALSE; + _h.Size = (UInt32)size; + RINOK(inStream->Seek(kHeaderSize, STREAM_SEEK_SET, NULL)); + } + _data = (Byte *)MidAlloc(_h.Size); + if (_data == 0) + return E_OUTOFMEMORY; + memcpy(_data, buf, kHeaderSize); + size_t processed = _h.Size - kHeaderSize; + RINOK(ReadStream(inStream, _data + kHeaderSize, &processed)); + if (processed < kNodeSize) + return S_FALSE; + _size = kHeaderSize + (UInt32)processed; + if (_size != _h.Size) + _errorMessage = "Unexpected end of archive"; + else + { + SetUi32(_data + 0x20, 0); + if (_h.IsVer2()) + if (CrcCalc(_data, _h.Size) != _h.Crc) + _errorMessage = "CRC error"; + } + if (_h.IsVer2()) + _items.Reserve(_h.NumFiles - 1); + return OpenDir(-1, kHeaderSize, 0); +} + +AString CHandler::GetPath(int index) const +{ + unsigned len = 0; + int indexMem = index; + do + { + const CItem &item = _items[index]; + index = item.Parent; + const Byte *p = _data + item.Offset; + unsigned size = GetNameLen(p, _h.be); + p += kNodeSize; + unsigned i; + for (i = 0; i < size && p[i]; i++); + len += i + 1; + } + while (index >= 0); + len--; + + AString path; + char *dest = path.GetBuffer(len) + len; + index = indexMem; + for (;;) + { + const CItem &item = _items[index]; + index = item.Parent; + const Byte *p = _data + item.Offset; + unsigned size = GetNameLen(p, _h.be); + p += kNodeSize; + unsigned i; + for (i = 0; i < size && p[i]; i++); + dest -= i; + memcpy(dest, p, i); + if (index < 0) + break; + *(--dest) = CHAR_PATH_SEPARATOR; + } + path.ReleaseBuffer(len); + return path; +} + +bool CHandler::GetPackSize(int index, UInt32 &res) const +{ + const CItem &item = _items[index]; + const Byte *p = _data + item.Offset; + bool be = _h.be; + UInt32 offset = GetOffset(p, be); + if (offset < kHeaderSize) + return false; + UInt32 numBlocks = (GetSize(p, be) + kBlockSize - 1) >> kBlockSizeLog; + UInt32 start = offset + numBlocks * 4; + if (start > _size) + return false; + UInt32 end = Get32(_data + start - 4); + if (end < start) + return false; + res = end - start; + return true; +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* callback */) +{ + COM_TRY_BEGIN + { + Close(); + RINOK(Open2(stream)); + _stream = stream; + } + return S_OK; + COM_TRY_END +} + +void CHandler::Free() +{ + MidFree(_data); + _data = 0; +} + +STDMETHODIMP CHandler::Close() +{ + _headersSize = 0; + _items.Clear(); + _stream.Release(); + _errorMessage.Empty(); + Free(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _items.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidName: + { + char dest[kHeaderNameSize + 4]; + memcpy(dest, _h.Name, kHeaderNameSize); + dest[kHeaderNameSize] = 0; + prop = dest; + break; + } + case kpidBigEndian: prop = _h.be; break; + case kpidCharacts: FLAGS_TO_PROP(k_Flags, _h.Flags, prop); break; + case kpidNumBlocks: if (_h.IsVer2()) prop = _h.NumBlocks; break; + case kpidNumSubFiles: if (_h.IsVer2()) prop = _h.NumFiles; break; + case kpidPhySize: if (_h.IsVer2()) prop = _h.Size; break; + case kpidHeadersSize: prop = _headersSize; break; + case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + const CItem &item = _items[index]; + const Byte *p = _data + item.Offset; + bool be = _h.be; + bool isDir = IsDir(p, be); + switch(propID) + { + case kpidPath: prop = MultiByteToUnicodeString(GetPath(index), CP_OEMCP); break; + case kpidIsDir: prop = isDir; break; + // case kpidOffset: prop = (UInt32)GetOffset(p, be); break; + case kpidSize: if (!isDir) prop = GetSize(p, be); break; + case kpidPackSize: + if (!isDir) + { + UInt32 size; + if (GetPackSize(index, size)) + prop = size; + } + break; + case kpidPosixAttrib: prop = (UInt32)GetMode(p, be); break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +class CCramfsInStream: public CCachedInStream +{ + HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize); +public: + CHandler *Handler; +}; + +HRESULT CCramfsInStream::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) +{ + return Handler->ReadBlock(blockIndex, dest, blockSize); +} + +HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) +{ + if (!_zlibDecoder) + { + _zlibDecoderSpec = new NCompress::NZlib::CDecoder(); + _zlibDecoder = _zlibDecoderSpec; + } + if (!_inStream) + { + _inStreamSpec = new CBufInStream(); + _inStream = _inStreamSpec; + } + if (!_outStream) + { + _outStreamSpec = new CBufPtrSeqOutStream(); + _outStream = _outStreamSpec; + } + bool be = _h.be; + const Byte *p = _data + (_curBlocksOffset + (UInt32)blockIndex * 4); + UInt32 start = (blockIndex == 0 ? _curBlocksOffset + _curNumBlocks * 4: Get32(p - 4)); + UInt32 end = Get32(p); + if (end < start || end > _size) + return S_FALSE; + UInt32 inSize = end - start; + _inStreamSpec->Init(_data + start, inSize); + _outStreamSpec->Init(dest, blockSize); + RINOK(_zlibDecoder->Code(_inStream, _outStream, NULL, NULL, NULL)); + return (_zlibDecoderSpec->GetInputProcessedSize() == inSize && + _outStreamSpec->GetPos() == blockSize) ? S_OK : S_FALSE; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _items.Size(); + if (numItems == 0) + return S_OK; + bool be = _h.be; + UInt64 totalSize = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + { + const Byte *p = _data + _items[allFilesMode ? i : indices[i]].Offset; + if (!IsDir(p, be)) + totalSize += GetSize(p, be); + } + extractCallback->SetTotal(totalSize); + + UInt64 totalPackSize; + totalSize = totalPackSize = 0; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStream(streamSpec); + streamSpec->SetStream(_stream); + + for (i = 0; i < numItems; i++) + { + lps->InSize = totalPackSize; + lps->OutSize = totalSize; + RINOK(lps->SetCur()); + CMyComPtr outStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + UInt32 index = allFilesMode ? i : indices[i]; + const CItem &item = _items[index]; + RINOK(extractCallback->GetStream(index, &outStream, askMode)); + const Byte *p = _data + item.Offset; + + if (IsDir(p, be)) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + UInt32 curSize = GetSize(p, be); + totalSize += curSize; + UInt32 packSize; + if (GetPackSize(index, packSize)) + totalPackSize += packSize; + + if (!testMode && !outStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + + UInt32 offset = GetOffset(p, be); + if (offset < kHeaderSize) + curSize = 0; + + int res = NExtract::NOperationResult::kDataError; + { + CMyComPtr inSeqStream; + CMyComPtr inStream; + HRESULT hres = GetStream(index, &inSeqStream); + if (inSeqStream) + inSeqStream.QueryInterface(IID_IInStream, &inStream); + if (hres == E_OUTOFMEMORY) + return E_OUTOFMEMORY; + if (hres == S_FALSE || !inStream) + res = NExtract::NOperationResult::kUnSupportedMethod; + else + { + RINOK(hres); + if (inStream) + { + HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress); + if (hres != S_OK && hres != S_FALSE) + { + RINOK(hres); + } + if (copyCoderSpec->TotalSize == curSize && hres == S_OK) + res = NExtract::NOperationResult::kOK; + } + } + } + RINOK(extractCallback->SetOperationResult(res)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + + const CItem &item = _items[index]; + const Byte *p = _data + item.Offset; + + bool be = _h.be; + if (IsDir(p, be)) + return E_FAIL; + + UInt32 size = GetSize(p, be); + UInt32 numBlocks = (size + kBlockSize - 1) >> kBlockSizeLog; + UInt32 offset = GetOffset(p, be); + if (offset < kHeaderSize) + { + if (offset != 0) + return S_FALSE; + CBufInStream *streamSpec = new CBufInStream; + CMyComPtr streamTemp = streamSpec; + streamSpec->Init(NULL, 0); + *stream = streamTemp.Detach(); + return S_OK; + } + + if (offset + numBlocks * 4 > _size) + return S_FALSE; + UInt32 prev = offset; + for (UInt32 i = 0; i < numBlocks; i++) + { + UInt32 next = Get32(_data + offset + i * 4); + if (next < prev || next > _size) + return S_FALSE; + prev = next; + } + + CCramfsInStream *streamSpec = new CCramfsInStream; + CMyComPtr streamTemp = streamSpec; + _curNumBlocks = numBlocks; + _curBlocksOffset = offset; + streamSpec->Handler = this; + if (!streamSpec->Alloc(kBlockSizeLog, 21 - kBlockSizeLog)) + return E_OUTOFMEMORY; + streamSpec->Init(size); + *stream = streamTemp.Detach(); + + return S_OK; + COM_TRY_END +} + +static IInArchive *CreateArc() { return new NArchive::NCramfs::CHandler; } + +static CArcInfo g_ArcInfo = + { L"CramFS", L"cramfs", 0, 0xD3, SIGNATURE, kSignatureSize, false, CreateArc, 0 }; + +REGISTER_ARC(Cramfs) + +}} diff --git a/CPP/7zip/Archive/DebHandler.cpp b/CPP/7zip/Archive/DebHandler.cpp new file mode 100755 index 0000000..1699b17 --- /dev/null +++ b/CPP/7zip/Archive/DebHandler.cpp @@ -0,0 +1,413 @@ +// DebHandler.cpp + +#include "StdAfx.h" + +#include "Common/ComTry.h" +#include "Common/StringConvert.h" +#include "Common/StringToInt.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +#include "Common/ItemNameUtils.h" + +using namespace NWindows; +using namespace NTime; + +namespace NArchive { +namespace NDeb { + +namespace NHeader +{ + const int kSignatureLen = 8; + + const char *kSignature = "!\n"; + + const int kNameSize = 16; + const int kTimeSize = 12; + const int kModeSize = 8; + const int kSizeSize = 10; + + /* + struct CHeader + { + char Name[kNameSize]; + char MTime[kTimeSize]; + char Number0[6]; + char Number1[6]; + char Mode[kModeSize]; + char Size[kSizeSize]; + char Quote; + char NewLine; + }; + */ + const int kHeaderSize = kNameSize + kTimeSize + 6 + 6 + kModeSize + kSizeSize + 1 + 1; +} + +struct CItem +{ + AString Name; + UInt64 Size; + UInt32 MTime; + UInt32 Mode; + + UInt64 HeaderPos; + UInt64 GetDataPos() const { return HeaderPos + NHeader::kHeaderSize; }; + // UInt64 GetFullSize() const { return NFileHeader::kRecordSize + Size; }; +}; + +class CInArchive +{ + CMyComPtr m_Stream; + + HRESULT GetNextItemReal(bool &filled, CItem &itemInfo); +public: + UInt64 m_Position; + HRESULT Open(IInStream *inStream); + HRESULT GetNextItem(bool &filled, CItem &itemInfo); + HRESULT SkipData(UInt64 dataSize); +}; + +HRESULT CInArchive::Open(IInStream *inStream) +{ + RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position)); + char signature[NHeader::kSignatureLen]; + RINOK(ReadStream_FALSE(inStream, signature, NHeader::kSignatureLen)); + m_Position += NHeader::kSignatureLen; + if (memcmp(signature, NHeader::kSignature, NHeader::kSignatureLen) != 0) + return S_FALSE; + m_Stream = inStream; + return S_OK; +} + +static void MyStrNCpy(char *dest, const char *src, int size) +{ + for (int i = 0; i < size; i++) + { + char c = src[i]; + dest[i] = c; + if (c == 0) + break; + } +} + +static bool OctalToNumber(const char *s, int size, UInt64 &res) +{ + char sz[32]; + MyStrNCpy(sz, s, size); + sz[size] = 0; + const char *end; + int i; + for (i = 0; sz[i] == ' '; i++); + res = ConvertOctStringToUInt64(sz + i, &end); + return (*end == ' ' || *end == 0); +} + +static bool OctalToNumber32(const char *s, int size, UInt32 &res) +{ + UInt64 res64; + if (!OctalToNumber(s, size, res64)) + return false; + res = (UInt32)res64; + return (res64 <= 0xFFFFFFFF); +} + +static bool DecimalToNumber(const char *s, int size, UInt64 &res) +{ + char sz[32]; + MyStrNCpy(sz, s, size); + sz[size] = 0; + const char *end; + int i; + for (i = 0; sz[i] == ' '; i++); + res = ConvertStringToUInt64(sz + i, &end); + return (*end == ' ' || *end == 0); +} + +static bool DecimalToNumber32(const char *s, int size, UInt32 &res) +{ + UInt64 res64; + if (!DecimalToNumber(s, size, res64)) + return false; + res = (UInt32)res64; + return (res64 <= 0xFFFFFFFF); +} + +#define RIF(x) { if (!(x)) return S_FALSE; } + + +HRESULT CInArchive::GetNextItemReal(bool &filled, CItem &item) +{ + filled = false; + + char header[NHeader::kHeaderSize]; + const char *cur = header; + + size_t processedSize = sizeof(header); + item.HeaderPos = m_Position; + RINOK(ReadStream(m_Stream, header, &processedSize)); + if (processedSize != sizeof(header)) + return S_OK; + m_Position += processedSize; + + char tempString[NHeader::kNameSize + 1]; + MyStrNCpy(tempString, cur, NHeader::kNameSize); + cur += NHeader::kNameSize; + tempString[NHeader::kNameSize] = '\0'; + item.Name = tempString; + item.Name.Trim(); + + for (int i = 0; i < item.Name.Length(); i++) + if (((Byte)item.Name[i]) < 0x20) + return S_FALSE; + + RIF(DecimalToNumber32(cur, NHeader::kTimeSize, item.MTime)); + cur += NHeader::kTimeSize; + + cur += 6 + 6; + + RIF(OctalToNumber32(cur, NHeader::kModeSize, item.Mode)); + cur += NHeader::kModeSize; + + RIF(DecimalToNumber(cur, NHeader::kSizeSize, item.Size)); + cur += NHeader::kSizeSize; + + filled = true; + return S_OK; +} + +HRESULT CInArchive::GetNextItem(bool &filled, CItem &item) +{ + for (;;) + { + RINOK(GetNextItemReal(filled, item)); + if (!filled) + return S_OK; + if (item.Name.Compare("debian-binary") != 0) + return S_OK; + if (item.Size != 4) + return S_OK; + SkipData(item.Size); + } +} + +HRESULT CInArchive::SkipData(UInt64 dataSize) +{ + return m_Stream->Seek((dataSize + 1) & (~((UInt64)0x1)), STREAM_SEEK_CUR, &m_Position); +} + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + CObjectVector _items; + CMyComPtr _stream; + Int32 _mainSubfile; + UInt64 _phySize; +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +static STATPROPSTG kArcProps[] = +{ + { NULL, kpidPhySize, VT_UI8} +}; + +static STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +STDMETHODIMP CHandler::Open(IInStream *stream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback *openArchiveCallback) +{ + COM_TRY_BEGIN + { + _mainSubfile = -1; + CInArchive archive; + if (archive.Open(stream) != S_OK) + return S_FALSE; + _items.Clear(); + + if (openArchiveCallback != NULL) + { + RINOK(openArchiveCallback->SetTotal(NULL, NULL)); + UInt64 numFiles = _items.Size(); + RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); + } + + for (;;) + { + CItem item; + bool filled; + HRESULT result = archive.GetNextItem(filled, item); + if (result == S_FALSE) + return S_FALSE; + if (result != S_OK) + return S_FALSE; + if (!filled) + break; + if (item.Name.Left(5) == "data.") + _mainSubfile = _items.Size(); + _items.Add(item); + archive.SkipData(item.Size); + if (openArchiveCallback != NULL) + { + UInt64 numFiles = _items.Size(); + RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); + } + } + _stream = stream; + _phySize = archive.m_Position; + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _stream.Release(); + _items.Clear(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _items.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidPhySize: prop = _phySize; break; + case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break; + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + const CItem &item = _items[index]; + + switch(propID) + { + case kpidPath: prop = (const wchar_t *)NItemName::GetOSName2(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break; + case kpidSize: + case kpidPackSize: + prop = item.Size; + break; + case kpidMTime: + { + if (item.MTime != 0) + { + FILETIME fileTime; + NTime::UnixTimeToFileTime(item.MTime, fileTime); + prop = fileTime; + } + break; + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _items.Size(); + if (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); + + UInt64 currentTotalSize = 0; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStream(streamSpec); + streamSpec->SetStream(_stream); + + for (i = 0; i < numItems; i++) + { + lps->InSize = lps->OutSize = currentTotalSize; + RINOK(lps->SetCur()); + CMyComPtr realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + const CItem &item = _items[index]; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + currentTotalSize += item.Size; + + if (!testMode && !realOutStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + if (testMode) + { + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + RINOK(_stream->Seek(item.GetDataPos(), STREAM_SEEK_SET, NULL)); + streamSpec->Init(item.Size); + RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ? + NExtract::NOperationResult::kOK: + NExtract::NOperationResult::kDataError)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + const CItem &item = _items[index]; + return CreateLimitedInStream(_stream, item.GetDataPos(), item.Size, stream); + COM_TRY_END +} + +static IInArchive *CreateArc() { return new NArchive::NDeb::CHandler; } + +static CArcInfo g_ArcInfo = + { L"Deb", L"deb", 0, 0xEC, { '!', '<', 'a', 'r', 'c', 'h', '>', '\n' }, 8, false, CreateArc, 0 }; + +REGISTER_ARC(Deb) + +}} diff --git a/CPP/7zip/Archive/DeflateProps.cpp b/CPP/7zip/Archive/DeflateProps.cpp new file mode 100755 index 0000000..41d7f0e --- /dev/null +++ b/CPP/7zip/Archive/DeflateProps.cpp @@ -0,0 +1,118 @@ +// DeflateProps.cpp + +#include "StdAfx.h" + +#include "Windows/PropVariant.h" + +#include "Common/ParseProperties.h" + +#include "DeflateProps.h" + +namespace NArchive { + +static const UInt32 kAlgo1 = 0; +static const UInt32 kAlgo5 = 1; + +static const UInt32 kPasses1 = 1; +static const UInt32 kPasses7 = 3; +static const UInt32 kPasses9 = 10; + +static const UInt32 kFb1 = 32; +static const UInt32 kFb7 = 64; +static const UInt32 kFb9 = 128; + +void CDeflateProps::Normalize() +{ + UInt32 level = Level; + if (level == 0xFFFFFFFF) + level = 5; + + if (Algo == 0xFFFFFFFF) + Algo = (level >= 5 ? + kAlgo5 : + kAlgo1); + + if (NumPasses == 0xFFFFFFFF) + NumPasses = + (level >= 9 ? kPasses9 : + (level >= 7 ? kPasses7 : + kPasses1)); + if (Fb == 0xFFFFFFFF) + Fb = + (level >= 9 ? kFb9 : + (level >= 7 ? kFb7 : + kFb1)); +} + +HRESULT CDeflateProps::SetCoderProperties(ICompressSetCoderProperties *setCoderProperties) +{ + Normalize(); + + NWindows::NCOM::CPropVariant props[] = + { + Algo, + NumPasses, + Fb, + Mc + }; + PROPID propIDs[] = + { + NCoderPropID::kAlgorithm, + NCoderPropID::kNumPasses, + NCoderPropID::kNumFastBytes, + NCoderPropID::kMatchFinderCycles + }; + int numProps = sizeof(propIDs) / sizeof(propIDs[0]); + if (!McDefined) + numProps--; + return setCoderProperties->SetCoderProperties(propIDs, props, numProps); +} + +HRESULT CDeflateProps::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) +{ + Init(); + for (int i = 0; i < numProps; i++) + { + UString name = names[i]; + name.MakeUpper(); + if (name.IsEmpty()) + return E_INVALIDARG; + const PROPVARIANT &prop = values[i]; + if (name[0] == L'X') + { + UInt32 a = 9; + RINOK(ParsePropValue(name.Mid(1), prop, a)); + Level = a; + } + else if (name.Left(1) == L"A") + { + UInt32 a = kAlgo5; + RINOK(ParsePropValue(name.Mid(1), prop, a)); + Algo = a; + } + else if (name.Left(4) == L"PASS") + { + UInt32 a = kPasses9; + RINOK(ParsePropValue(name.Mid(4), prop, a)); + NumPasses = a; + } + else if (name.Left(2) == L"FB") + { + UInt32 a = kFb9; + RINOK(ParsePropValue(name.Mid(2), prop, a)); + Fb = a; + } + else if (name.Left(2) == L"MC") + { + UInt32 a = 0xFFFFFFFF; + RINOK(ParsePropValue(name.Mid(2), prop, a)); + Mc = a; + McDefined = true; + } + else + return E_INVALIDARG; + } + return S_OK; +} + +} diff --git a/CPP/7zip/Archive/DeflateProps.h b/CPP/7zip/Archive/DeflateProps.h new file mode 100755 index 0000000..454da8d --- /dev/null +++ b/CPP/7zip/Archive/DeflateProps.h @@ -0,0 +1,35 @@ +// DeflateProps.h + +#ifndef __DEFLATE_PROPS_H +#define __DEFLATE_PROPS_H + +#include "../ICoder.h" + +namespace NArchive { + +class CDeflateProps +{ + UInt32 Level; + UInt32 NumPasses; + UInt32 Fb; + UInt32 Algo; + UInt32 Mc; + bool McDefined; + + void Init() + { + Level = NumPasses = Fb = Algo = Mc = 0xFFFFFFFF; + McDefined = false; + } + void Normalize(); +public: + CDeflateProps() { Init(); } + bool IsMaximum() const { return Algo > 0; } + + HRESULT SetCoderProperties(ICompressSetCoderProperties *setCoderProperties); + HRESULT SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps); +}; + +} + +#endif diff --git a/CPP/7zip/Archive/DllExports.cpp b/CPP/7zip/Archive/DllExports.cpp new file mode 100755 index 0000000..9b72d04 --- /dev/null +++ b/CPP/7zip/Archive/DllExports.cpp @@ -0,0 +1,47 @@ +// DLLExports.cpp + +#include "StdAfx.h" + +#include "../../Common/MyInitGuid.h" +#include "../../Common/ComTry.h" +#include "../../Common/Types.h" + +#include "../../Windows/NtCheck.h" +#include "../../Windows/PropVariant.h" + +#include "IArchive.h" +#include "../ICoder.h" +#include "../IPassword.h" + +HINSTANCE g_hInstance; + +#define NT_CHECK_FAIL_ACTION return FALSE; + +extern "C" +BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) +{ + if (dwReason == DLL_PROCESS_ATTACH) + { + g_hInstance = hInstance; + NT_CHECK; + } + return TRUE; +} + +DEFINE_GUID(CLSID_CArchiveHandler, +0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); + +STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject); + +STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) +{ + return CreateArchiver(clsid, iid, outObject); +} + +STDAPI SetLargePageMode() +{ + #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) + SetLargePageSize(); + #endif + return S_OK; +} diff --git a/CPP/7zip/Archive/DllExports2.cpp b/CPP/7zip/Archive/DllExports2.cpp new file mode 100755 index 0000000..a45b5c9 --- /dev/null +++ b/CPP/7zip/Archive/DllExports2.cpp @@ -0,0 +1,74 @@ +// DLLExports.cpp + +#include "StdAfx.h" + +#include "../../Common/MyInitGuid.h" + +#if defined(_WIN32) && 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 "IArchive.h" + +HINSTANCE g_hInstance; + +#define NT_CHECK_FAIL_ACTION return FALSE; + +extern "C" +BOOL WINAPI DllMain( + #ifdef UNDER_CE + HANDLE + #else + HINSTANCE + #endif + hInstance, DWORD dwReason, LPVOID /*lpReserved*/) +{ + if (dwReason == DLL_PROCESS_ATTACH) + { + g_hInstance = (HINSTANCE)hInstance; + NT_CHECK; + } + return TRUE; +} + +DEFINE_GUID(CLSID_CArchiveHandler, +0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); + +static const UInt16 kDecodeId = 0x2790; + +DEFINE_GUID(CLSID_CCodec, +0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + +STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject); +STDAPI CreateArchiver(const GUID *classID, 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); + } + else + { + return CreateArchiver(clsid, iid, outObject); + } + // COM_TRY_END +} + +STDAPI SetLargePageMode() +{ + #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) + SetLargePageSize(); + #endif + return S_OK; +} diff --git a/CPP/7zip/Archive/DmgHandler.cpp b/CPP/7zip/Archive/DmgHandler.cpp new file mode 100755 index 0000000..8e812d8 --- /dev/null +++ b/CPP/7zip/Archive/DmgHandler.cpp @@ -0,0 +1,918 @@ +// DmgHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Common/Buffer.h" +#include "Common/ComTry.h" +#include "Common/IntToString.h" +#include "Common/MyXml.h" +#include "Common/UTFConvert.h" + +#include "Windows/PropVariant.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/BZip2Decoder.h" +#include "../Compress/CopyCoder.h" +#include "../Compress/ZlibDecoder.h" + +// #define DMG_SHOW_RAW + +// #include +#define PRF(x) // x + +#define Get32(p) GetBe32(p) +#define Get64(p) GetBe64(p) + +static int Base64ToByte(char c) +{ + if (c >= 'A' && c <= 'Z') return c - 'A'; + if (c >= 'a' && c <= 'z') return c - 'a' + 26; + if (c >= '0' && c <= '9') return c - '0' + 52; + if (c == '+') return 62; + if (c == '/') return 63; + if (c == '=') return 0; + return -1; +} + +static int Base64ToBin(Byte *dest, const char *src, int srcLen) +{ + int srcPos = 0; + int destPos = 0; + while (srcPos < srcLen) + { + Byte buf[4]; + int filled = 0; + while (srcPos < srcLen) + { + int n = Base64ToByte(src[srcPos++]); + if (n >= 0) + { + buf[filled++] = (Byte)n; + if (filled == 4) + break; + } + } + if (filled >= 2) { if (dest) dest[destPos] = (buf[0] << 2) | (buf[1] >> 4); destPos++; } + if (filled >= 3) { if (dest) dest[destPos] = (buf[1] << 4) | (buf[2] >> 2); destPos++; } + if (filled >= 4) { if (dest) dest[destPos] = (buf[2] << 6) | (buf[3] ); destPos++; } + } + return destPos; +} + +static UString GetSizeString(UInt64 value) +{ + wchar_t s[32]; + wchar_t c; + if (value < (UInt64)20000) c = 0; + else if (value < ((UInt64)20000 << 10)) { value >>= 10; c = L'K'; } + else if (value < ((UInt64)20000 << 20)) { value >>= 20; c = L'M'; } + else { value >>= 30; c = L'G'; } + ConvertUInt64ToString(value, s); + int p = MyStringLen(s); + s[p++] = c; + s[p++] = L'\0'; + return s; +} + +namespace NArchive { +namespace NDmg { + +struct CBlock +{ + UInt32 Type; + UInt64 UnpPos; + UInt64 UnpSize; + UInt64 PackPos; + UInt64 PackSize; + + UInt64 GetNextPackOffset() const { return PackPos + PackSize; } +}; + +struct CFile +{ + CByteBuffer Raw; + UInt64 StartPos; + CRecordVector Blocks; + UInt64 GetUnpackSize() const + { + UInt64 size = 0; + for (int i = 0; i < Blocks.Size(); i++) + size += Blocks[i].UnpSize; + return size; + }; + UInt64 GetPackSize() const + { + UInt64 size = 0; + for (int i = 0; i < Blocks.Size(); i++) + size += Blocks[i].PackSize; + return size; + }; + + AString Name; +}; + +class CHandler: + public IInArchive, + public CMyUnknownImp +{ + CMyComPtr _inStream; + + AString _xml; + CObjectVector _files; + CRecordVector _fileIndices; + + HRESULT Open2(IInStream *stream); + HRESULT Extract(IInStream *stream); +public: + MY_UNKNOWN_IMP1(IInArchive) + INTERFACE_IInArchive(;) +}; + +const UInt32 kXmlSizeMax = ((UInt32)1 << 31) - (1 << 14); + +enum +{ + METHOD_ZERO_0 = 0, + METHOD_COPY = 1, + METHOD_ZERO_2 = 2, + METHOD_ADC = 0x80000004, + METHOD_ZLIB = 0x80000005, + METHOD_BZIP2 = 0x80000006, + METHOD_DUMMY = 0x7FFFFFFE, + METHOD_END = 0xFFFFFFFF +}; + +struct CMethodStat +{ + UInt32 NumBlocks; + UInt64 PackSize; + UInt64 UnpSize; + CMethodStat(): NumBlocks(0), PackSize(0), UnpSize(0) {} +}; + +struct CMethods +{ + CRecordVector Stats; + CRecordVector Types; + void Update(const CFile &file); + UString GetString() const; +}; + +void CMethods::Update(const CFile &file) +{ + for (int i = 0; i < file.Blocks.Size(); i++) + { + const CBlock &b = file.Blocks[i]; + int index = Types.FindInSorted(b.Type); + if (index < 0) + { + index = Types.AddToUniqueSorted(b.Type); + Stats.Insert(index, CMethodStat()); + } + CMethodStat &m = Stats[index]; + m.PackSize += b.PackSize; + m.UnpSize += b.UnpSize; + m.NumBlocks++; + } +} + +UString CMethods::GetString() const +{ + UString res; + for (int i = 0; i < Types.Size(); i++) + { + if (i != 0) + res += L' '; + wchar_t buf[32]; + const wchar_t *s; + const CMethodStat &m = Stats[i]; + bool showPack = true; + UInt32 type = Types[i]; + switch(type) + { + case METHOD_ZERO_0: s = L"zero0"; showPack = (m.PackSize != 0); break; + case METHOD_ZERO_2: s = L"zero2"; showPack = (m.PackSize != 0); break; + case METHOD_COPY: s = L"copy"; showPack = (m.UnpSize != m.PackSize); break; + case METHOD_ADC: s = L"adc"; break; + case METHOD_ZLIB: s = L"zlib"; break; + case METHOD_BZIP2: s = L"bzip2"; break; + default: ConvertUInt64ToString(type, buf); s = buf; + } + res += s; + if (m.NumBlocks != 1) + { + res += L'['; + ConvertUInt64ToString(m.NumBlocks, buf); + res += buf; + res += L']'; + } + res += L'-'; + res += GetSizeString(m.UnpSize); + if (showPack) + { + res += L'-'; + res += GetSizeString(m.PackSize); + } + } + return res; +} + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidComment, VT_BSTR}, + { NULL, kpidMethod, VT_BSTR} +}; + +IMP_IInArchive_Props + +STATPROPSTG kArcProps[] = +{ + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidNumBlocks, VT_UI4} +}; + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidMethod: + { + CMethods m; + for (int i = 0; i < _files.Size(); i++) + m.Update(_files[i]); + prop = m.GetString(); + break; + } + case kpidNumBlocks: + { + UInt64 numBlocks = 0; + for (int i = 0; i < _files.Size(); i++) + numBlocks += _files[i].Blocks.Size(); + prop = numBlocks; + break; + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +IMP_IInArchive_ArcProps + +static int FindKeyPair(const CXmlItem &item, const AString &key, const AString &nextTag) +{ + for (int i = 0; i + 1 < item.SubItems.Size(); i++) + { + const CXmlItem &si = item.SubItems[i]; + if (si.IsTagged("key") && si.GetSubString() == key && item.SubItems[i + 1].IsTagged(nextTag)) + return i + 1; + } + return -1; +} + +static AString GetStringFromKeyPair(const CXmlItem &item, const AString &key, const AString &nextTag) +{ + int index = FindKeyPair(item, key, nextTag); + if (index >= 0) + return item.SubItems[index].GetSubString(); + return AString(); +} + +HRESULT CHandler::Open2(IInStream *stream) +{ + const int HEADER_SIZE = 0x1E0; + + UInt64 headerPos; + RINOK(stream->Seek(-HEADER_SIZE, STREAM_SEEK_END, &headerPos)); + Byte buf[HEADER_SIZE]; + RINOK(ReadStream_FALSE(stream, buf, HEADER_SIZE)); + UInt64 address1 = Get64(buf + 0); + UInt64 address2 = Get64(buf + 0xB8); + UInt64 size64 = Get64(buf + 0xC0); + if (address1 != address2 || size64 >= kXmlSizeMax || size64 == 0 || + address1 >= headerPos || address1 + size64 > headerPos) + return S_FALSE; + RINOK(stream->Seek(address1, STREAM_SEEK_SET, NULL)); + size_t size = (size_t)size64; + + char *ss = _xml.GetBuffer((int)size + 1); + RINOK(ReadStream_FALSE(stream, ss, size)); + ss[size] = 0; + _xml.ReleaseBuffer(); + + CXml xml; + if (!xml.Parse(_xml)) + return S_FALSE; + if (xml.Root.Name != "plist") + return S_FALSE; + + int dictIndex = xml.Root.FindSubTag("dict"); + if (dictIndex < 0) + return S_FALSE; + + const CXmlItem &dictItem = xml.Root.SubItems[dictIndex]; + int rfDictIndex = FindKeyPair(dictItem, "resource-fork", "dict"); + if (rfDictIndex < 0) + return S_FALSE; + + const CXmlItem &rfDictItem = dictItem.SubItems[rfDictIndex]; + int arrIndex = FindKeyPair(rfDictItem, "blkx", "array"); + if (arrIndex < 0) + return S_FALSE; + + const CXmlItem &arrItem = rfDictItem.SubItems[arrIndex]; + + int i; + for (i = 0; i < arrItem.SubItems.Size(); i++) + { + const CXmlItem &item = arrItem.SubItems[i]; + if (!item.IsTagged("dict")) + continue; + + CFile file; + file.StartPos = 0; + + int destLen; + { + AString dataString; + AString name = GetStringFromKeyPair(item, "Name", "string"); + if (name.IsEmpty()) + name = GetStringFromKeyPair(item, "CFName", "string"); + file.Name = name; + dataString = GetStringFromKeyPair(item, "Data", "data"); + + destLen = Base64ToBin(NULL, dataString, dataString.Length()); + file.Raw.SetCapacity(destLen); + Base64ToBin(file.Raw, dataString, dataString.Length()); + } + + if (destLen > 0xCC && Get32(file.Raw) == 0x6D697368) + { + PRF(printf("\n\n index = %d", _files.Size())); + const int kRecordSize = 40; + for (int offset = 0xCC; offset + kRecordSize <= destLen; offset += kRecordSize) + { + const Byte *p = (const Byte *)file.Raw + offset; + CBlock b; + b.Type = Get32(p); + if (b.Type == METHOD_END) + break; + if (b.Type == METHOD_DUMMY) + continue; + + b.UnpPos = Get64(p + 0x08) << 9; + b.UnpSize = Get64(p + 0x10) << 9; + b.PackPos = Get64(p + 0x18); + b.PackSize = Get64(p + 0x20); + + file.Blocks.Add(b); + + PRF(printf("\nType=%8x m[1]=%8x uPos=%8x uSize=%7x pPos=%8x pSize=%7x", + b.Type, Get32(p + 4), (UInt32)b.UnpPos, (UInt32)b.UnpSize, (UInt32)b.PackPos, (UInt32)b.PackSize)); + } + } + int itemIndex = _files.Add(file); + if (file.Blocks.Size() > 0) + { + // if (file.Name.Find("HFS") >= 0) + _fileIndices.Add(itemIndex); + } + } + + // PackPos for each new file is 0 in some DMG files. So we use additional StartPos + + bool allStartAreZeros = true; + for (i = 0; i < _files.Size(); i++) + { + const CFile &file = _files[i]; + if (!file.Blocks.IsEmpty() && file.Blocks[0].PackPos != 0) + allStartAreZeros = false; + } + UInt64 startPos = 0; + if (allStartAreZeros) + { + for (i = 0; i < _files.Size(); i++) + { + CFile &file = _files[i]; + file.StartPos = startPos; + if (!file.Blocks.IsEmpty()) + startPos += file.Blocks.Back().GetNextPackOffset(); + } + } + + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *stream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback * /* openArchiveCallback */) +{ + COM_TRY_BEGIN + { + Close(); + if (Open2(stream) != S_OK) + return S_FALSE; + _inStream = stream; + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _inStream.Release(); + _fileIndices.Clear(); + _files.Clear(); + _xml.Empty(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _fileIndices.Size() + #ifdef DMG_SHOW_RAW + + _files.Size() + 1; + #endif + ; + return S_OK; +} + +#define RAW_PREFIX L"raw" WSTRING_PATH_SEPARATOR + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + + #ifdef DMG_SHOW_RAW + if ((int)index == _fileIndices.Size()) + { + switch(propID) + { + case kpidPath: + prop = RAW_PREFIX L"a.xml"; + break; + case kpidSize: + case kpidPackSize: + prop = (UInt64)_xml.Length(); + break; + } + } + else if ((int)index > _fileIndices.Size()) + { + int rawIndex = (int)index - (_fileIndices.Size() + 1); + switch(propID) + { + case kpidPath: + { + wchar_t s[32] = RAW_PREFIX; + ConvertUInt64ToString(rawIndex, s + MyStringLen(s)); + prop = s; + break; + } + case kpidSize: + case kpidPackSize: + prop = (UInt64)_files[rawIndex].Raw.GetCapacity(); + break; + } + } + else + #endif + { + int itemIndex = _fileIndices[index]; + const CFile &item = _files[itemIndex]; + switch(propID) + { + case kpidMethod: + { + CMethods m; + m.Update(item); + UString resString = m.GetString(); + if (!resString.IsEmpty()) + prop = resString; + break; + } + + // case kpidExtension: prop = L"hfs"; break; + + case kpidPath: + { + // break; + UString name; + wchar_t s[32]; + ConvertUInt64ToString(index, s); + name = s; + int num = 10; + int numDigits; + for (numDigits = 1; num < _fileIndices.Size(); numDigits++) + num *= 10; + while (name.Length() < numDigits) + name = L'0' + name; + + AString subName; + int pos1 = item.Name.Find('('); + if (pos1 >= 0) + { + pos1++; + int pos2 = item.Name.Find(')', pos1); + if (pos2 >= 0) + { + subName = item.Name.Mid(pos1, pos2 - pos1); + pos1 = subName.Find(':'); + if (pos1 >= 0) + subName = subName.Left(pos1); + } + } + subName.Trim(); + if (!subName.IsEmpty()) + { + if (subName == "Apple_HFS") + subName = "hfs"; + else if (subName == "Apple_HFSX") + subName = "hfsx"; + else if (subName == "Apple_Free") + subName = "free"; + else if (subName == "DDM") + subName = "ddm"; + UString name2; + ConvertUTF8ToUnicode(subName, name2); + name += L'.'; + name += name2; + } + else + { + UString name2; + ConvertUTF8ToUnicode(item.Name, name2); + if (!name2.IsEmpty()) + name += L" - "; + name += name2; + } + prop = name; + break; + } + case kpidComment: + { + UString name; + ConvertUTF8ToUnicode(item.Name, name); + prop = name; + break; + } + + case kpidSize: prop = item.GetUnpackSize(); break; + case kpidPackSize: prop = item.GetPackSize(); break; + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +class CAdcDecoder: + public ICompressCoder, + public CMyUnknownImp +{ + CLzOutWindow m_OutWindowStream; + CInBuffer m_InStream; + + void ReleaseStreams() + { + m_OutWindowStream.ReleaseStream(); + m_InStream.ReleaseStream(); + } + + class CCoderReleaser + { + CAdcDecoder *m_Coder; + public: + bool NeedFlush; + CCoderReleaser(CAdcDecoder *coder): m_Coder(coder), NeedFlush(true) {} + ~CCoderReleaser() + { + if (NeedFlush) + m_Coder->m_OutWindowStream.Flush(); + m_Coder->ReleaseStreams(); + } + }; + friend class CCoderReleaser; + +public: + MY_UNKNOWN_IMP + + STDMETHOD(CodeReal)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); + + STDMETHOD(Code)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); +}; + +STDMETHODIMP CAdcDecoder::CodeReal(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress) +{ + if (!m_OutWindowStream.Create(1 << 18)) + return E_OUTOFMEMORY; + if (!m_InStream.Create(1 << 18)) + return E_OUTOFMEMORY; + + m_OutWindowStream.SetStream(outStream); + m_OutWindowStream.Init(false); + m_InStream.SetStream(inStream); + m_InStream.Init(); + + CCoderReleaser coderReleaser(this); + + const UInt32 kStep = (1 << 20); + UInt64 nextLimit = kStep; + + UInt64 pos = 0; + while (pos < *outSize) + { + if (pos > nextLimit && progress) + { + UInt64 packSize = m_InStream.GetProcessedSize(); + RINOK(progress->SetRatioInfo(&packSize, &pos)); + nextLimit += kStep; + } + Byte b; + if (!m_InStream.ReadByte(b)) + return S_FALSE; + UInt64 rem = *outSize - pos; + if (b & 0x80) + { + unsigned num = (b & 0x7F) + 1; + if (num > rem) + return S_FALSE; + for (unsigned i = 0; i < num; i++) + { + if (!m_InStream.ReadByte(b)) + return S_FALSE; + m_OutWindowStream.PutByte(b); + } + pos += num; + continue; + } + Byte b1; + if (!m_InStream.ReadByte(b1)) + return S_FALSE; + + UInt32 len, distance; + + if (b & 0x40) + { + len = ((UInt32)b & 0x3F) + 4; + Byte b2; + if (!m_InStream.ReadByte(b2)) + return S_FALSE; + distance = ((UInt32)b1 << 8) + b2; + } + else + { + b &= 0x3F; + len = ((UInt32)b >> 2) + 3; + distance = (((UInt32)b & 3) << 8) + b1; + } + + if (distance >= pos || len > rem) + return S_FALSE; + m_OutWindowStream.CopyBlock(distance, len); + pos += len; + } + if (*inSize != m_InStream.GetProcessedSize()) + return S_FALSE; + coderReleaser.NeedFlush = false; + return m_OutWindowStream.Flush(); +} + +STDMETHODIMP CAdcDecoder::Code(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress) +{ + try { return CodeReal(inStream, outStream, inSize, outSize, progress);} + catch(const CInBufferException &e) { return e.ErrorCode; } + catch(const CLzOutWindowException &e) { return e.ErrorCode; } + catch(...) { return S_FALSE; } +} + + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _files.Size(); + if (numItems == 0) + return S_OK; + UInt64 totalSize = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + { + int index = (int)(allFilesMode ? i : indices[i]); + #ifdef DMG_SHOW_RAW + if (index == _fileIndices.Size()) + totalSize += _xml.Length(); + else if (index > _fileIndices.Size()) + totalSize += _files[index - (_fileIndices.Size() + 1)].Raw.GetCapacity(); + else + #endif + totalSize += _files[_fileIndices[index]].GetUnpackSize(); + } + extractCallback->SetTotal(totalSize); + + UInt64 currentPackTotal = 0; + UInt64 currentUnpTotal = 0; + UInt64 currentPackSize = 0; + UInt64 currentUnpSize = 0; + + const UInt32 kZeroBufSize = (1 << 14); + CByteBuffer zeroBuf; + zeroBuf.SetCapacity(kZeroBufSize); + memset(zeroBuf, 0, kZeroBufSize); + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + + NCompress::NBZip2::CDecoder *bzip2CoderSpec = new NCompress::NBZip2::CDecoder(); + CMyComPtr bzip2Coder = bzip2CoderSpec; + + NCompress::NZlib::CDecoder *zlibCoderSpec = new NCompress::NZlib::CDecoder(); + CMyComPtr zlibCoder = zlibCoderSpec; + + CAdcDecoder *adcCoderSpec = new CAdcDecoder(); + CMyComPtr adcCoder = adcCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStream(streamSpec); + streamSpec->SetStream(_inStream); + + for (i = 0; i < numItems; i++, currentPackTotal += currentPackSize, currentUnpTotal += currentUnpSize) + { + lps->InSize = currentPackTotal; + lps->OutSize = currentUnpTotal; + currentPackSize = 0; + currentUnpSize = 0; + RINOK(lps->SetCur()); + CMyComPtr realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + // const CItemEx &item = _files[index]; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + + if (!testMode && !realOutStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + + CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream; + CMyComPtr outStream(outStreamSpec); + outStreamSpec->SetStream(realOutStream); + + realOutStream.Release(); + + Int32 opRes = NExtract::NOperationResult::kOK; + #ifdef DMG_SHOW_RAW + if (index > _fileIndices.Size()) + { + const CByteBuffer &buf = _files[index - (_fileIndices.Size() + 1)].Raw; + outStreamSpec->Init(buf.GetCapacity()); + RINOK(WriteStream(outStream, buf, buf.GetCapacity())); + currentPackSize = currentUnpSize = buf.GetCapacity(); + } + else if (index == _fileIndices.Size()) + { + outStreamSpec->Init(_xml.Length()); + RINOK(WriteStream(outStream, (const char *)_xml, _xml.Length())); + currentPackSize = currentUnpSize = _xml.Length(); + } + else + #endif + { + const CFile &item = _files[_fileIndices[index]]; + currentPackSize = item.GetPackSize(); + currentUnpSize = item.GetUnpackSize(); + + UInt64 unpPos = 0; + UInt64 packPos = 0; + { + for (int j = 0; j < item.Blocks.Size(); j++) + { + lps->InSize = currentPackTotal + packPos; + lps->OutSize = currentUnpTotal + unpPos; + RINOK(lps->SetCur()); + + const CBlock &block = item.Blocks[j]; + + packPos += block.PackSize; + if (block.UnpPos != unpPos) + { + opRes = NExtract::NOperationResult::kDataError; + break; + } + + RINOK(_inStream->Seek(item.StartPos + block.PackPos, STREAM_SEEK_SET, NULL)); + streamSpec->Init(block.PackSize); + // UInt64 startSize = outStreamSpec->GetSize(); + bool realMethod = true; + outStreamSpec->Init(block.UnpSize); + HRESULT res = S_OK; + + switch(block.Type) + { + case METHOD_ZERO_0: + case METHOD_ZERO_2: + realMethod = false; + if (block.PackSize != 0) + opRes = NExtract::NOperationResult::kUnSupportedMethod; + break; + + case METHOD_COPY: + if (block.UnpSize != block.PackSize) + { + opRes = NExtract::NOperationResult::kUnSupportedMethod; + break; + } + res = copyCoder->Code(inStream, outStream, NULL, NULL, progress); + break; + + case METHOD_ADC: + { + res = adcCoder->Code(inStream, outStream, &block.PackSize, &block.UnpSize, progress); + break; + } + + case METHOD_ZLIB: + { + res = zlibCoder->Code(inStream, outStream, NULL, NULL, progress); + break; + } + + case METHOD_BZIP2: + { + res = bzip2Coder->Code(inStream, outStream, NULL, NULL, progress); + if (res == S_OK) + if (streamSpec->GetSize() != block.PackSize) + opRes = NExtract::NOperationResult::kDataError; + break; + } + + default: + opRes = NExtract::NOperationResult::kUnSupportedMethod; + break; + } + if (res != S_OK) + { + if (res != S_FALSE) + return res; + if (opRes == NExtract::NOperationResult::kOK) + opRes = NExtract::NOperationResult::kDataError; + } + unpPos += block.UnpSize; + if (!outStreamSpec->IsFinishedOK()) + { + if (realMethod && opRes == NExtract::NOperationResult::kOK) + opRes = NExtract::NOperationResult::kDataError; + + while (outStreamSpec->GetRem() != 0) + { + UInt64 rem = outStreamSpec->GetRem(); + UInt32 size = (UInt32)MyMin(rem, (UInt64)kZeroBufSize); + RINOK(WriteStream(outStream, zeroBuf, size)); + } + } + } + } + } + outStream.Release(); + RINOK(extractCallback->SetOperationResult(opRes)); + } + return S_OK; + COM_TRY_END +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"Dmg", L"dmg", 0, 0xE4, { 0 }, 0, false, CreateArc, 0 }; + +REGISTER_ARC(Dmg) + +}} diff --git a/CPP/7zip/Archive/ElfHandler.cpp b/CPP/7zip/Archive/ElfHandler.cpp new file mode 100755 index 0000000..171f049 --- /dev/null +++ b/CPP/7zip/Archive/ElfHandler.cpp @@ -0,0 +1,534 @@ +// ElfHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Common/Buffer.h" +#include "Common/ComTry.h" +#include "Common/IntToString.h" + +#include "Windows/PropVariantUtils.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +static UInt16 Get16(const Byte *p, int be) { if (be) return GetBe16(p); return GetUi16(p); } +static UInt32 Get32(const Byte *p, int be) { if (be) return GetBe32(p); return GetUi32(p); } +static UInt64 Get64(const Byte *p, int be) { if (be) return GetBe64(p); return GetUi64(p); } + +using namespace NWindows; + +namespace NArchive { +namespace NElf { + +#define ELF_CLASS_32 1 +#define ELF_CLASS_64 2 + +#define ELF_DATA_2LSB 1 +#define ELF_DATA_2MSB 2 + +#define NUM_SCAN_SECTIONS_MAX (1 << 6) + +struct CHeader +{ + bool Mode64; + bool Be; + Byte Os; + Byte AbiVer; + + UInt16 Type; + UInt16 Machine; + // UInt32 Version; + + // UInt64 EntryVa; + UInt64 ProgOffset; + UInt64 SectOffset; + UInt32 Flags; + UInt16 ElfHeaderSize; + UInt16 SegmentEntrySize; + UInt16 NumSegments; + UInt16 SectEntrySize; + UInt16 NumSections; + // UInt16 SectNameStringTableIndex; + + bool Parse(const Byte *buf); + + bool CheckSegmentEntrySize() const + { + return (Mode64 && SegmentEntrySize == 0x38) || (!Mode64 && SegmentEntrySize == 0x20); + }; + + UInt64 GetHeadersSize() const + { return ElfHeaderSize + + (UInt64)SegmentEntrySize * NumSegments + + (UInt64)SectEntrySize * NumSections; } + +}; + +bool CHeader::Parse(const Byte *p) +{ + switch(p[4]) + { + case ELF_CLASS_32: Mode64 = false; break; + case ELF_CLASS_64: Mode64 = true; break; + default: return false; + } + bool be; + switch(p[5]) + { + case ELF_DATA_2LSB: be = false; break; + case ELF_DATA_2MSB: be = true; break; + default: return false; + } + Be = be; + if (p[6] != 1) // Version + return false; + Os = p[7]; + AbiVer = p[8]; + for (int i = 9; i < 16; i++) + if (p[i] != 0) + return false; + + Type = Get16(p + 0x10, be); + Machine = Get16(p + 0x12, be); + if (Get32(p + 0x14, be) != 1) // Version + return false; + + if (Mode64) + { + // EntryVa = Get64(p + 0x18, be); + ProgOffset = Get64(p + 0x20, be); + SectOffset = Get64(p + 0x28, be); + p += 0x30; + } + else + { + // EntryVa = Get32(p + 0x18, be); + ProgOffset = Get32(p + 0x1C, be); + SectOffset = Get32(p + 0x20, be); + p += 0x24; + } + + Flags = Get32(p + 0, be); + ElfHeaderSize = Get16(p + 4, be); + SegmentEntrySize = Get16(p + 6, be); + NumSegments = Get16(p + 8, be); + SectEntrySize = Get16(p + 10, be); + NumSections = Get16(p + 12, be); + // SectNameStringTableIndex = Get16(p + 14, be); + return CheckSegmentEntrySize(); +} + +struct CSegment +{ + UInt32 Type; + UInt32 Flags; + UInt64 Offset; + UInt64 Va; + // UInt64 Pa; + UInt64 PSize; + UInt64 VSize; + // UInt64 Align; + + void UpdateTotalSize(UInt64 &totalSize) + { + UInt64 t = Offset + PSize; + if (t > totalSize) + totalSize = t; + } + void Parse(const Byte *p, bool mode64, bool be); +}; + +void CSegment::Parse(const Byte *p, bool mode64, bool be) +{ + Type = Get32(p, be); + if (mode64) + { + Flags = Get32(p + 4, be); + Offset = Get64(p + 8, be); + Va = Get64(p + 0x10, be); + // Pa = Get64(p + 0x18, be); + PSize = Get64(p + 0x20, be); + VSize = Get64(p + 0x28, be); + // Align = Get64(p + 0x30, be); + } + else + { + Offset = Get32(p + 4, be); + Va = Get32(p + 8, be); + // Pa = Get32(p + 12, be); + PSize = Get32(p + 16, be); + VSize = Get32(p + 20, be); + Flags = Get32(p + 24, be); + // Align = Get32(p + 28, be); + } +} + +static const CUInt32PCharPair g_MachinePairs[] = +{ + { 0, "None" }, + { 1, "AT&T WE 32100" }, + { 2, "SPARC" }, + { 3, "Intel 386" }, + { 4, "Motorola 68000" }, + { 5, "Motorola 88000" }, + { 6, "Intel 486" }, + { 7, "Intel i860" }, + { 8, "MIPS" }, + { 9, "IBM S/370" }, + { 10, "MIPS RS3000 LE" }, + { 11, "RS6000" }, + + { 15, "PA-RISC" }, + { 16, "nCUBE" }, + { 17, "Fujitsu VPP500" }, + { 18, "SPARC 32+" }, + { 19, "Intel i960" }, + { 20, "PowerPC" }, + { 21, "PowerPC 64-bit" }, + { 22, "IBM S/390" }, + + { 36, "NEX v800" }, + { 37, "Fujitsu FR20" }, + { 38, "TRW RH-32" }, + { 39, "Motorola RCE" }, + { 40, "ARM" }, + { 41, "Alpha" }, + { 42, "Hitachi SH" }, + { 43, "SPARC-V9" }, + { 44, "Siemens Tricore" }, + { 45, "ARC" }, + { 46, "H8/300" }, + { 47, "H8/300H" }, + { 48, "H8S" }, + { 49, "H8/500" }, + { 50, "IA-64" }, + { 51, "Stanford MIPS-X" }, + { 52, "Motorola ColdFire" }, + { 53, "M68HC12" }, + { 54, "Fujitsu MMA" }, + { 55, "Siemens PCP" }, + { 56, "Sony nCPU" }, + { 57, "Denso NDR1" }, + { 58, "Motorola StarCore" }, + { 59, "Toyota ME16" }, + { 60, "ST100" }, + { 61, "Advanced Logic TinyJ" }, + { 62, "AMD64" }, + { 63, "Sony DSP" }, + + { 66, "Siemens FX66" }, + { 67, "ST9+" }, + { 68, "ST7" }, + { 69, "MC68HC16" }, + { 70, "MC68HC11" }, + { 71, "MC68HC08" }, + { 72, "MC68HC05" }, + { 73, "Silicon Graphics SVx" }, + { 74, "ST19" }, + { 75, "Digital VAX" }, + { 76, "Axis CRIS" }, + { 77, "Infineon JAVELIN" }, + { 78, "Element 14 FirePath" }, + { 79, "LSI ZSP" }, + { 80, "MMIX" }, + { 81, "HUANY" }, + { 82, "SiTera Prism" }, + { 83, "Atmel AVR" }, + { 84, "Fujitsu FR30" }, + { 85, "Mitsubishi D10V" }, + { 86, "Mitsubishi D30V" }, + { 87, "NEC v850" }, + { 88, "Mitsubishi M32R" }, + { 89, "Matsushita MN10300" }, + { 90, "Matsushita MN10200" }, + { 91, "picoJava" }, + { 92, "OpenRISC" }, + { 93, "ARC Tangent-A5" }, + { 94, "Tensilica Xtensa" }, + { 0x9026, "Alpha" } +}; + +static const CUInt32PCharPair g_AbiOS[] = +{ + { 0, "None" }, + { 1, "HP-UX" }, + { 2, "NetBSD" }, + { 3, "Linux" }, + + { 6, "Solaris" }, + { 7, "AIX" }, + { 8, "IRIX" }, + { 9, "FreeBSD" }, + { 10, "TRU64" }, + { 11, "Novell Modesto" }, + { 12, "OpenBSD" }, + { 13, "OpenVMS" }, + { 14, "HP NSK" }, + { 15, "AROS" }, + { 97, "ARM" }, + { 255, "Standalone" } +}; + +static const CUInt32PCharPair g_SegmentFlags[] = +{ + { 0, "Execute" }, + { 1, "Write" }, + { 2, "Read" } +}; + +static const char *g_Types[] = +{ + "None", + "Relocatable file", + "Executable file", + "Shared object file", + "Core file" +}; + +static const char *g_SegnmentTypes[] = +{ + "Unused", + "Loadable segment", + "Dynamic linking tables", + "Program interpreter path name", + "Note section", + "SHLIB", + "Program header table", + "TLS" +}; + +class CHandler: + public IInArchive, + public CMyUnknownImp +{ + CMyComPtr _inStream; + CObjectVector _sections; + UInt32 _peOffset; + CHeader _header; + UInt64 _totalSize; + HRESULT Open2(IInStream *stream); + bool Parse(const Byte *buf, UInt32 size); +public: + MY_UNKNOWN_IMP1(IInArchive) + INTERFACE_IInArchive(;) +}; + +#define ELF_PT_PHDR 6 + +bool CHandler::Parse(const Byte *buf, UInt32 size) +{ + if (size < 64) + return false; + if (!_header.Parse(buf)) + return false; + if (_header.ProgOffset > size || + _header.ProgOffset + (UInt64)_header.SegmentEntrySize * _header.NumSegments > size || + _header.NumSegments > NUM_SCAN_SECTIONS_MAX) + return false; + const Byte *p = buf + _header.ProgOffset; + _totalSize = _header.ProgOffset; + + for (int i = 0; i < _header.NumSegments; i++, p += _header.SegmentEntrySize) + { + CSegment sect; + sect.Parse(p, _header.Mode64, _header.Be); + sect.UpdateTotalSize(_totalSize); + if (sect.Type != ELF_PT_PHDR) + _sections.Add(sect); + } + UInt64 total2 = _header.SectOffset + (UInt64)_header.SectEntrySize * _header.NumSections; + if (total2 > _totalSize) + _totalSize = total2; + return true; +} + +STATPROPSTG kArcProps[] = +{ + { NULL, kpidCpu, VT_BSTR}, + { NULL, kpidBit64, VT_BOOL}, + { NULL, kpidBigEndian, VT_BOOL}, + { NULL, kpidHostOS, VT_BSTR}, + { NULL, kpidCharacts, VT_BSTR}, + { NULL, kpidPhySize, VT_UI8}, + { NULL, kpidHeadersSize, VT_UI8} + }; + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidType, VT_BSTR}, + { NULL, kpidCharacts, VT_BSTR}, + { NULL, kpidOffset, VT_UI8}, + { NULL, kpidVa, VT_UI8} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NCOM::CPropVariant prop; + switch(propID) + { + case kpidPhySize: prop = _totalSize; break; + case kpidHeadersSize: prop = _header.GetHeadersSize(); break; + case kpidBit64: if (_header.Mode64) prop = _header.Mode64; break; + case kpidBigEndian: if (_header.Be) prop = _header.Be; break; + case kpidCpu: PAIR_TO_PROP(g_MachinePairs, _header.Machine, prop); break; + case kpidHostOS: PAIR_TO_PROP(g_AbiOS, _header.Os, prop); break; + case kpidCharacts: TYPE_TO_PROP(g_Types, _header.Type, prop); break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NCOM::CPropVariant prop; + const CSegment &item = _sections[index]; + switch(propID) + { + case kpidPath: + { + wchar_t sz[32]; + ConvertUInt64ToString(index, sz); + prop = sz; + break; + } + case kpidSize: prop = (UInt64)item.VSize; break; + case kpidPackSize: prop = (UInt64)item.PSize; break; + case kpidOffset: prop = item.Offset; break; + case kpidVa: prop = item.Va; break; + case kpidType: TYPE_TO_PROP(g_SegnmentTypes, item.Type, prop); break; + case kpidCharacts: FLAGS_TO_PROP(g_SegmentFlags, item.Flags, prop); break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +HRESULT CHandler::Open2(IInStream *stream) +{ + const UInt32 kBufSize = 1 << 18; + const UInt32 kSigSize = 4; + + CByteBuffer buffer; + buffer.SetCapacity(kBufSize); + Byte *buf = buffer; + + size_t processed = kSigSize; + RINOK(ReadStream_FALSE(stream, buf, processed)); + if (buf[0] != 0x7F || buf[1] != 'E' || buf[2] != 'L' || buf[3] != 'F') + return S_FALSE; + processed = kBufSize - kSigSize; + RINOK(ReadStream(stream, buf + kSigSize, &processed)); + processed += kSigSize; + if (!Parse(buf, (UInt32)processed)) + return S_FALSE; + UInt64 fileSize; + RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize)); + return (fileSize == _totalSize) ? S_OK : S_FALSE; +} + +STDMETHODIMP CHandler::Open(IInStream *inStream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback * /* openArchiveCallback */) +{ + COM_TRY_BEGIN + Close(); + RINOK(Open2(inStream)); + _inStream = inStream; + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _inStream.Release(); + _sections.Clear(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _sections.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _sections.Size(); + if (numItems == 0) + return S_OK; + UInt64 totalSize = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + totalSize += _sections[allFilesMode ? i : indices[i]].PSize; + extractCallback->SetTotal(totalSize); + + UInt64 currentTotalSize = 0; + UInt64 currentItemSize; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStream(streamSpec); + streamSpec->SetStream(_inStream); + + for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) + { + lps->InSize = lps->OutSize = currentTotalSize; + RINOK(lps->SetCur()); + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + UInt32 index = allFilesMode ? i : indices[i]; + const CSegment &item = _sections[index]; + currentItemSize = item.PSize; + + CMyComPtr outStream; + RINOK(extractCallback->GetStream(index, &outStream, askMode)); + if (!testMode && !outStream) + continue; + + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(_inStream->Seek(item.Offset, STREAM_SEEK_SET, NULL)); + streamSpec->Init(currentItemSize); + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + outStream.Release(); + RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == currentItemSize ? + NExtract::NOperationResult::kOK: + NExtract::NOperationResult::kDataError)); + } + return S_OK; + COM_TRY_END +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"ELF", L"", 0, 0xDE, { 0 }, 0, false, CreateArc, 0 }; + +REGISTER_ARC(Elf) + +}} diff --git a/CPP/7zip/Archive/FatHandler.cpp b/CPP/7zip/Archive/FatHandler.cpp new file mode 100755 index 0000000..1886906 --- /dev/null +++ b/CPP/7zip/Archive/FatHandler.cpp @@ -0,0 +1,996 @@ +// FatHandler.cpp + +#include "StdAfx.h" + +// #include + +#include "../../../C/CpuArch.h" + +#include "Common/Buffer.h" +#include "Common/ComTry.h" +#include "Common/IntToString.h" +#include "Common/MyCom.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +#include "Common/DummyOutStream.h" + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) + +#define PRF(x) /* x */ + +namespace NArchive { +namespace NFat { + +static const UInt32 kFatItemUsedByDirMask = (UInt32)1 << 31; + +struct CHeader +{ + UInt32 NumSectors; + UInt16 NumReservedSectors; + Byte NumFats; + UInt32 NumFatSectors; + UInt32 RootDirSector; + UInt32 NumRootDirSectors; + UInt32 DataSector; + + UInt32 FatSize; + UInt32 BadCluster; + + Byte NumFatBits; + Byte SectorSizeLog; + Byte SectorsPerClusterLog; + Byte ClusterSizeLog; + + UInt16 SectorsPerTrack; + UInt16 NumHeads; + UInt32 NumHiddenSectors; + + bool VolFieldsDefined; + + UInt32 VolId; + // Byte VolName[11]; + // Byte FileSys[8]; + + // Byte OemName[5]; + Byte MediaType; + + // 32-bit FAT + UInt16 Flags; + UInt16 FsInfoSector; + UInt32 RootCluster; + + bool IsFat32() const { return NumFatBits == 32; } + UInt64 GetPhySize() const { return (UInt64)NumSectors << SectorSizeLog; } + UInt32 SectorSize() const { return (UInt32)1 << SectorSizeLog; } + UInt32 ClusterSize() const { return (UInt32)1 << ClusterSizeLog; } + UInt32 ClusterToSector(UInt32 c) const { return DataSector + ((c - 2) << SectorsPerClusterLog); } + UInt32 IsEoc(UInt32 c) const { return c > BadCluster; } + UInt32 IsEocAndUnused(UInt32 c) const { return c > BadCluster && (c & kFatItemUsedByDirMask) == 0; } + UInt32 IsValidCluster(UInt32 c) const { return c >= 2 && c < FatSize; } + UInt32 SizeToSectors(UInt32 size) const { return (size + SectorSize() - 1) >> SectorSizeLog; } + UInt32 CalcFatSizeInSectors() const { return SizeToSectors((FatSize * (NumFatBits / 4) + 1) / 2); } + + UInt32 GetFatSector() const + { + UInt32 index = (IsFat32() && (Flags & 0x80) != 0) ? (Flags & 0xF) : 0; + if (index > NumFats) + index = 0; + return NumReservedSectors + index * NumFatSectors; + } + + UInt64 GetFilePackSize(UInt32 unpackSize) const + { + UInt64 mask = ClusterSize() - 1; + return (unpackSize + mask) & ~mask; + } + + UInt32 GetNumClusters(UInt32 size) const + { return (UInt32)(((UInt64)size + ClusterSize() - 1) >> ClusterSizeLog); } + + bool Parse(const Byte *p); +}; + +static int GetLog(UInt32 num) +{ + for (int i = 0; i < 31; i++) + if (((UInt32)1 << i) == num) + return i; + return -1; +} + +bool CHeader::Parse(const Byte *p) +{ + if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA) + return false; + + int codeOffset = 0; + switch (p[0]) + { + case 0xE9: codeOffset = 3 + (Int16)Get16(p + 1); break; + case 0xEB: if (p[2] != 0x90) return false; codeOffset = 2 + (signed char)p[1]; break; + default: return false; + } + { + int s = GetLog(Get16(p + 11)); + if (s < 9 || s > 12) + return false; + SectorSizeLog = (Byte)s; + s = GetLog(p[13]); + if (s < 0) + return false; + SectorsPerClusterLog = (Byte)s; + ClusterSizeLog = SectorSizeLog + SectorsPerClusterLog; + } + + NumReservedSectors = Get16(p + 14); + if (NumReservedSectors == 0) + return false; + + NumFats = p[16]; + if (NumFats < 1 || NumFats > 4) + return false; + + UInt16 numRootDirEntries = Get16(p + 17); + if (numRootDirEntries == 0) + { + if (codeOffset < 90) + return false; + NumFatBits = 32; + NumRootDirSectors = 0; + } + else + { + if (codeOffset < 62) + return false; + NumFatBits = 0; + UInt32 mask = (1 << (SectorSizeLog - 5)) - 1; + if ((numRootDirEntries & mask) != 0) + return false; + NumRootDirSectors = (numRootDirEntries + mask) >> (SectorSizeLog - 5); + } + + NumSectors = Get16(p + 19); + if (NumSectors == 0) + NumSectors = Get32(p + 32); + else if (IsFat32()) + return false; + + MediaType = p[21]; + NumFatSectors = Get16(p + 22); + SectorsPerTrack = Get16(p + 24); + NumHeads = Get16(p + 26); + NumHiddenSectors = Get32(p + 28); + + // memcpy(OemName, p + 3, 5); + + p += 36; + if (IsFat32()) + { + if (NumFatSectors != 0) + return false; + NumFatSectors = Get32(p); + if (NumFatSectors >= (1 << 24)) + return false; + + Flags = Get16(p + 4); + if (Get16(p + 6) != 0) + return false; + RootCluster = Get32(p + 8); + FsInfoSector = Get16(p + 12); + for (int i = 16; i < 28; i++) + if (p[i] != 0) + return false; + p += 28; + } + + // DriveNumber = p[0]; + VolFieldsDefined = (p[2] == 0x29); // ExtendedBootSig + VolId = Get32(p + 3); + // memcpy(VolName, p + 7, 11); + // memcpy(FileSys, p + 18, 8); + + if (NumFatSectors == 0) + return false; + RootDirSector = NumReservedSectors + NumFatSectors * NumFats; + DataSector = RootDirSector + NumRootDirSectors; + if (NumSectors < DataSector) + return false; + UInt32 numDataSectors = NumSectors - DataSector; + UInt32 numClusters = numDataSectors >> SectorsPerClusterLog; + + BadCluster = 0x0FFFFFF7; + if (numClusters < 0xFFF5) + { + if (NumFatBits == 32) + return false; + NumFatBits = (numClusters < 0xFF5) ? 12: 16; + BadCluster &= ((1 << NumFatBits) - 1); + } + else if (NumFatBits != 32) + return false; + + FatSize = numClusters + 2; + if (FatSize > BadCluster || CalcFatSizeInSectors() > NumFatSectors) + return false; + return true; +} + +struct CItem +{ + UString UName; + char DosName[11]; + Byte CTime2; + UInt32 CTime; + UInt32 MTime; + UInt16 ADate; + Byte Attrib; + Byte Flags; + UInt32 Size; + UInt32 Cluster; + Int32 Parent; + + // NT uses Flags to store Low Case status + bool NameIsLow() const { return (Flags & 0x8) != 0; } + bool ExtIsLow() const { return (Flags & 0x10) != 0; } + bool IsDir() const { return (Attrib & 0x10) != 0; } + UString GetShortName() const; + UString GetName() const; + UString GetVolName() const; +}; + +static int CopyAndTrim(char *dest, const char *src, int size, bool toLower) +{ + int i; + memcpy(dest, src, size); + if (toLower) + for (i = 0; i < size; i++) + { + char c = dest[i]; + if (c >= 'A' && c <= 'Z') + dest[i] = c + 0x20; + } + for (i = size - 1; i >= 0 && dest[i] == ' '; i--); + return i + 1; +} + +static UString FatStringToUnicode(const char *s) +{ + return MultiByteToUnicodeString(s, CP_OEMCP); +} + +UString CItem::GetShortName() const +{ + char s[16]; + int i = CopyAndTrim(s, DosName, 8, NameIsLow()); + s[i++] = '.'; + int j = CopyAndTrim(s + i, DosName + 8, 3, ExtIsLow()); + if (j == 0) + j--; + s[i + j] = 0; + return FatStringToUnicode(s); +} + +UString CItem::GetName() const +{ + if (!UName.IsEmpty()) + return UName; + return GetShortName(); +} + +UString CItem::GetVolName() const +{ + if (!UName.IsEmpty()) + return UName; + char s[12]; + int i = CopyAndTrim(s, DosName, 11, false); + s[i] = 0; + return FatStringToUnicode(s); +} + +struct CDatabase +{ + CHeader Header; + CObjectVector Items; + UInt32 *Fat; + CMyComPtr InStream; + IArchiveOpenCallback *OpenCallback; + + UInt32 NumFreeClusters; + bool VolItemDefined; + CItem VolItem; + UInt32 NumDirClusters; + CByteBuffer ByteBuf; + UInt64 NumCurUsedBytes; + + CDatabase(): Fat(0) {} + ~CDatabase() { ClearAndClose(); } + + void Clear(); + void ClearAndClose(); + HRESULT OpenProgressFat(bool changeTotal = true); + HRESULT OpenProgress(); + + UString GetItemPath(Int32 index) const; + HRESULT Open(); + HRESULT ReadDir(Int32 parent, UInt32 cluster, int level); + + UInt64 GetHeadersSize() const + { + return (UInt64)(Header.DataSector + (NumDirClusters << Header.SectorsPerClusterLog)) << Header.SectorSizeLog; + } + HRESULT SeekToSector(UInt32 sector); + HRESULT SeekToCluster(UInt32 cluster) { return SeekToSector(Header.ClusterToSector(cluster)); } +}; + +HRESULT CDatabase::SeekToSector(UInt32 sector) +{ + return InStream->Seek((UInt64)sector << Header.SectorSizeLog, STREAM_SEEK_SET, NULL); +} + +void CDatabase::Clear() +{ + VolItemDefined = false; + NumDirClusters = 0; + NumCurUsedBytes = 0; + + Items.Clear(); + delete []Fat; + Fat = 0; +} + +void CDatabase::ClearAndClose() +{ + Clear(); + InStream.Release(); +} + +HRESULT CDatabase::OpenProgressFat(bool changeTotal) +{ + if (!OpenCallback) + return S_OK; + if (changeTotal) + { + UInt64 numTotalBytes = (Header.CalcFatSizeInSectors() << Header.SectorSizeLog) + + ((UInt64)(Header.FatSize - NumFreeClusters) << Header.ClusterSizeLog); + RINOK(OpenCallback->SetTotal(NULL, &numTotalBytes)); + } + return OpenCallback->SetCompleted(NULL, &NumCurUsedBytes); +} + +HRESULT CDatabase::OpenProgress() +{ + if (!OpenCallback) + return S_OK; + UInt64 numItems = Items.Size(); + return OpenCallback->SetCompleted(&numItems, &NumCurUsedBytes); +} + +UString CDatabase::GetItemPath(Int32 index) const +{ + const CItem *item = &Items[index]; + UString name = item->GetName(); + for (;;) + { + index = item->Parent; + if (index < 0) + return name; + item = &Items[index]; + name = item->GetName() + WCHAR_PATH_SEPARATOR + name; + } +} + +static wchar_t *AddSubStringToName(wchar_t *dest, const Byte *p, int numChars) +{ + for (int i = 0; i < numChars; i++) + { + wchar_t c = Get16(p + i * 2); + if (c != 0 && c != 0xFFFF) + *dest++ = c; + } + *dest = 0; + return dest; +} + +HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level) +{ + int startIndex = Items.Size(); + if (startIndex >= (1 << 30) || level > 256) + return S_FALSE; + + UInt32 sectorIndex = 0; + UInt32 blockSize = Header.ClusterSize(); + bool clusterMode = (Header.IsFat32() || parent >= 0); + if (!clusterMode) + { + blockSize = Header.SectorSize(); + RINOK(SeekToSector(Header.RootDirSector)); + } + + ByteBuf.SetCapacity(blockSize); + UString curName; + int checkSum = -1; + int numLongRecords = -1; + for (UInt32 pos = blockSize;; pos += 32) + { + if (pos == blockSize) + { + pos = 0; + + if ((NumDirClusters & 0xFF) == 0) + { + RINOK(OpenProgress()); + } + + if (clusterMode) + { + if (Header.IsEoc(cluster)) + break; + if (!Header.IsValidCluster(cluster)) + return S_FALSE; + PRF(printf("\nCluster = %4X", cluster)); + RINOK(SeekToCluster(cluster)); + UInt32 newCluster = Fat[cluster]; + if ((newCluster & kFatItemUsedByDirMask) != 0) + return S_FALSE; + Fat[cluster] |= kFatItemUsedByDirMask; + cluster = newCluster; + NumDirClusters++; + NumCurUsedBytes += Header.ClusterSize(); + } + else if (sectorIndex++ >= Header.NumRootDirSectors) + break; + + RINOK(ReadStream_FALSE(InStream, ByteBuf, blockSize)); + } + const Byte *p = ByteBuf + pos; + if (p[0] == 0) + { + /* + // FreeDOS formats FAT partition with cluster chain longer than required. + if (clusterMode && !Header.IsEoc(cluster)) + return S_FALSE; + */ + break; + } + if (p[0] == 0xE5) + { + if (numLongRecords > 0) + return S_FALSE; + continue; + } + + Byte attrib = p[11]; + if ((attrib & 0x3F) == 0xF) + { + if (p[0] > 0x7F || Get16(p + 26) != 0) + return S_FALSE; + int longIndex = p[0] & 0x3F; + if (longIndex == 0) + return S_FALSE; + bool isLast = (p[0] & 0x40) != 0; + if (numLongRecords < 0) + { + if (!isLast) + return S_FALSE; + numLongRecords = longIndex; + } + else if (isLast || numLongRecords != longIndex) + return S_FALSE; + + numLongRecords--; + + if (p[12] == 0) + { + wchar_t nameBuf[14]; + wchar_t *dest; + + dest = AddSubStringToName(nameBuf, p + 1, 5); + dest = AddSubStringToName(dest, p + 14, 6); + AddSubStringToName(dest, p + 28, 2); + curName = nameBuf + curName; + if (isLast) + checkSum = p[13]; + if (checkSum != p[13]) + return S_FALSE; + } + } + else + { + if (numLongRecords > 0) + return S_FALSE; + CItem item; + memcpy(item.DosName, p, 11); + + if (checkSum >= 0) + { + Byte sum = 0; + for (int i = 0; i < 11; i++) + sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + (Byte)item.DosName[i]; + if (sum == checkSum) + item.UName = curName; + } + + if (item.DosName[0] == 5) + item.DosName[0] = (char)(Byte)0xE5; + item.Attrib = attrib; + item.Flags = p[12]; + item.Size = Get32(p + 28); + item.Cluster = Get16(p + 26); + if (Header.NumFatBits > 16) + item.Cluster |= ((UInt32)Get16(p + 20) << 16); + else + { + // OS/2 and WinNT probably can store EA (extended atributes) in that field. + } + + item.CTime = Get32(p + 14); + item.CTime2 = p[13]; + item.ADate = Get16(p + 18); + item.MTime = Get32(p + 22); + item.Parent = parent; + + if (attrib == 8) + { + VolItem = item; + VolItemDefined = true; + } + else + if (memcmp(item.DosName, ". ", 11) != 0 && + memcmp(item.DosName, ".. ", 11) != 0) + { + if (!item.IsDir()) + NumCurUsedBytes += Header.GetFilePackSize(item.Size); + Items.Add(item); + PRF(printf("\n%7d: %S", Items.Size(), GetItemPath(Items.Size() - 1))); + } + numLongRecords = -1; + curName.Empty(); + checkSum = -1; + } + } + + int finishIndex = Items.Size(); + for (int i = startIndex; i < finishIndex; i++) + { + const CItem &item = Items[i]; + if (item.IsDir()) + { + PRF(printf("\n%S", GetItemPath(i))); + RINOK(CDatabase::ReadDir(i, item.Cluster, level + 1)); + } + } + return S_OK; +} + +HRESULT CDatabase::Open() +{ + Clear(); + bool numFreeClustersDefined = false; + { + static const UInt32 kHeaderSize = 512; + Byte buf[kHeaderSize]; + RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize)); + if (!Header.Parse(buf)) + return S_FALSE; + UInt64 fileSize; + RINOK(InStream->Seek(0, STREAM_SEEK_END, &fileSize)); + + /* we comment that check to support truncated images */ + /* + if (fileSize < Header.GetPhySize()) + return S_FALSE; + */ + + if (Header.IsFat32()) + { + SeekToSector(Header.FsInfoSector); + RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize)); + if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA) + return S_FALSE; + if (Get32(buf) == 0x41615252 && Get32(buf + 484) == 0x61417272) + { + NumFreeClusters = Get32(buf + 488); + numFreeClustersDefined = (NumFreeClusters <= Header.FatSize); + } + } + } + + // numFreeClustersDefined = false; // to recalculate NumFreeClusters + if (!numFreeClustersDefined) + NumFreeClusters = 0; + + CByteBuffer byteBuf; + Fat = new UInt32[Header.FatSize]; + + RINOK(OpenProgressFat()); + RINOK(SeekToSector(Header.GetFatSector())); + if (Header.NumFatBits == 32) + { + const UInt32 kBufSize = (1 << 15); + byteBuf.SetCapacity(kBufSize); + for (UInt32 i = 0; i < Header.FatSize;) + { + UInt32 size = Header.FatSize - i; + const UInt32 kBufSize32 = kBufSize / 4; + if (size > kBufSize32) + size = kBufSize32; + UInt32 readSize = Header.SizeToSectors(size * 4) << Header.SectorSizeLog; + RINOK(ReadStream_FALSE(InStream, byteBuf, readSize)); + NumCurUsedBytes += readSize; + + const UInt32 *src = (const UInt32 *)(const Byte *)byteBuf; + UInt32 *dest = Fat + i; + if (numFreeClustersDefined) + for (UInt32 j = 0; j < size; j++) + dest[j] = Get32(src + j) & 0x0FFFFFFF; + else + { + UInt32 numFreeClusters = 0; + for (UInt32 j = 0; j < size; j++) + { + UInt32 v = Get32(src + j) & 0x0FFFFFFF; + numFreeClusters += (UInt32)(v - 1) >> 31; + dest[j] = v; + } + NumFreeClusters += numFreeClusters; + } + i += size; + if ((i & 0xFFFFF) == 0) + { + RINOK(OpenProgressFat(!numFreeClustersDefined)); + } + } + } + else + { + const UInt32 kBufSize = (UInt32)Header.CalcFatSizeInSectors() << Header.SectorSizeLog; + NumCurUsedBytes += kBufSize; + byteBuf.SetCapacity(kBufSize); + Byte *p = byteBuf; + RINOK(ReadStream_FALSE(InStream, p, kBufSize)); + UInt32 fatSize = Header.FatSize; + UInt32 *fat = &Fat[0]; + if (Header.NumFatBits == 16) + for (UInt32 j = 0; j < fatSize; j++) + fat[j] = Get16(p + j * 2); + else + for (UInt32 j = 0; j < fatSize; j++) + fat[j] = (Get16(p + j * 3 / 2) >> ((j & 1) << 2)) & 0xFFF; + + if (!numFreeClustersDefined) + { + UInt32 numFreeClusters = 0; + for (UInt32 i = 0; i < fatSize; i++) + numFreeClusters += (UInt32)(fat[i] - 1) >> 31; + NumFreeClusters = numFreeClusters; + } + } + + RINOK(OpenProgressFat()); + + if ((Fat[0] & 0xFF) != Header.MediaType) + return S_FALSE; + + return ReadDir(-1, Header.RootCluster, 0); +} + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp, + CDatabase +{ +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + *stream = 0; + const CItem &item = Items[index]; + CClusterInStream *streamSpec = new CClusterInStream; + CMyComPtr streamTemp = streamSpec; + streamSpec->Stream = InStream; + streamSpec->StartOffset = Header.DataSector << Header.SectorSizeLog; + streamSpec->BlockSizeLog = Header.ClusterSizeLog; + streamSpec->Size = item.Size; + + UInt32 numClusters = Header.GetNumClusters(item.Size); + streamSpec->Vector.Reserve(numClusters); + UInt32 cluster = item.Cluster; + UInt32 size = item.Size; + + if (size == 0) + { + if (cluster != 0) + return S_FALSE; + } + else + { + UInt32 clusterSize = Header.ClusterSize(); + for (;; size -= clusterSize) + { + if (!Header.IsValidCluster(cluster)) + return S_FALSE; + streamSpec->Vector.Add(cluster - 2); + cluster = Fat[cluster]; + if (size <= clusterSize) + break; + } + if (!Header.IsEocAndUnused(cluster)) + return S_FALSE; + } + RINOK(streamSpec->InitAndSeek()); + *stream = streamTemp.Detach(); + return S_OK; + COM_TRY_END +} + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidATime, VT_FILETIME}, + { NULL, kpidAttrib, VT_UI8}, + { NULL, kpidShortName, VT_BSTR} +}; + +enum +{ + kpidNumFats = kpidUserDefined + // kpidOemName, + // kpidVolName, + // kpidFileSysType +}; + +STATPROPSTG kArcProps[] = +{ + { NULL, kpidFileSystem, VT_BSTR}, + { NULL, kpidClusterSize, VT_UI4}, + { NULL, kpidPhySize, VT_UI8}, + { NULL, kpidFreeSpace, VT_UI8}, + { NULL, kpidHeadersSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidVolumeName, VT_BSTR}, + + { L"FATs", kpidNumFats, VT_UI4}, + { NULL, kpidSectorSize, VT_UI4}, + { NULL, kpidId, VT_UI4}, + // { L"OEM Name", kpidOemName, VT_BSTR}, + // { L"Volume Name", kpidVolName, VT_BSTR}, + // { L"File System Type", kpidFileSysType, VT_BSTR} + // { NULL, kpidSectorsPerTrack, VT_UI4}, + // { NULL, kpidNumHeads, VT_UI4}, + // { NULL, kpidHiddenSectors, VT_UI4} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_WITH_NAME + +static void FatTimeToProp(UInt32 dosTime, UInt32 ms10, NWindows::NCOM::CPropVariant &prop) +{ + FILETIME localFileTime, utc; + if (NWindows::NTime::DosTimeToFileTime(dosTime, localFileTime)) + if (LocalFileTimeToFileTime(&localFileTime, &utc)) + { + UInt64 t64 = (((UInt64)utc.dwHighDateTime) << 32) + utc.dwLowDateTime; + t64 += ms10 * 100000; + utc.dwLowDateTime = (DWORD)t64; + utc.dwHighDateTime = (DWORD)(t64 >> 32); + prop = utc; + } +} + +/* +static void StringToProp(const Byte *src, int size, NWindows::NCOM::CPropVariant &prop) +{ + char dest[32]; + memcpy(dest, src, size); + dest[size] = 0; + prop = FatStringToUnicode(dest); +} + +#define STRING_TO_PROP(s, p) StringToProp(s, sizeof(s), prop) +*/ + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidFileSystem: + { + wchar_t s[32] = { L'F', L'A', L'T' }; + ConvertUInt32ToString(Header.NumFatBits, s + 3); + prop = s; + break; + } + case kpidClusterSize: prop = Header.ClusterSize(); break; + case kpidPhySize: prop = Header.GetPhySize(); break; + case kpidFreeSpace: prop = (UInt64)NumFreeClusters << Header.ClusterSizeLog; break; + case kpidHeadersSize: prop = GetHeadersSize(); break; + case kpidMTime: if (VolItemDefined) FatTimeToProp(VolItem.MTime, 0, prop); break; + case kpidVolumeName: if (VolItemDefined) prop = VolItem.GetVolName(); break; + case kpidNumFats: if (Header.NumFats != 2) prop = Header.NumFats; break; + case kpidSectorSize: prop = (UInt32)1 << Header.SectorSizeLog; break; + // case kpidSectorsPerTrack: prop = Header.SectorsPerTrack; break; + // case kpidNumHeads: prop = Header.NumHeads; break; + // case kpidOemName: STRING_TO_PROP(Header.OemName, prop); break; + case kpidId: if (Header.VolFieldsDefined) prop = Header.VolId; break; + // case kpidVolName: if (Header.VolFieldsDefined) STRING_TO_PROP(Header.VolName, prop); break; + // case kpidFileSysType: if (Header.VolFieldsDefined) STRING_TO_PROP(Header.FileSys, prop); break; + // case kpidHiddenSectors: prop = Header.NumHiddenSectors; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + const CItem &item = Items[index]; + switch(propID) + { + case kpidPath: prop = GetItemPath(index); break; + case kpidShortName: prop = item.GetShortName(); break; + case kpidIsDir: prop = item.IsDir(); break; + case kpidMTime: FatTimeToProp(item.MTime, 0, prop); break; + case kpidCTime: FatTimeToProp(item.CTime, item.CTime2, prop); break; + case kpidATime: FatTimeToProp(((UInt32)item.ADate << 16), 0, prop); break; + case kpidAttrib: prop = (UInt32)item.Attrib; break; + case kpidSize: if (!item.IsDir()) prop = item.Size; break; + case kpidPackSize: if (!item.IsDir()) prop = Header.GetFilePackSize(item.Size); break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + { + OpenCallback = callback; + InStream = stream; + HRESULT res; + try + { + res = CDatabase::Open(); + if (res == S_OK) + return S_OK; + } + catch(...) + { + Close(); + throw; + } + Close(); + return res; + } + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + ClearAndClose(); + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = Items.Size(); + if (numItems == 0) + return S_OK; + UInt32 i; + UInt64 totalSize = 0; + for (i = 0; i < numItems; i++) + { + const CItem &item = Items[allFilesMode ? i : indices[i]]; + if (!item.IsDir()) + totalSize += item.Size; + } + RINOK(extractCallback->SetTotal(totalSize)); + + UInt64 totalPackSize; + totalSize = totalPackSize = 0; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + CDummyOutStream *outStreamSpec = new CDummyOutStream; + CMyComPtr outStream(outStreamSpec); + + for (i = 0; i < numItems; i++) + { + lps->InSize = totalPackSize; + lps->OutSize = totalSize; + RINOK(lps->SetCur()); + CMyComPtr realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + const CItem &item = Items[index]; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + if (item.IsDir()) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + + totalPackSize += Header.GetFilePackSize(item.Size); + totalSize += item.Size; + + if (!testMode && !realOutStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + + outStreamSpec->SetStream(realOutStream); + realOutStream.Release(); + outStreamSpec->Init(); + + int res = NExtract::NOperationResult::kDataError; + CMyComPtr inStream; + HRESULT hres = GetStream(index, &inStream); + if (hres != S_FALSE) + { + RINOK(hres); + if (inStream) + { + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + if (copyCoderSpec->TotalSize == item.Size) + res = NExtract::NOperationResult::kOK; + } + } + outStreamSpec->ReleaseStream(); + RINOK(extractCallback->SetOperationResult(res)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = Items.Size(); + return S_OK; +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"FAT", L"fat img", 0, 0xDA, { 0x55, 0xAA }, 2, false, CreateArc, 0 }; + +REGISTER_ARC(Fat) + +}} diff --git a/CPP/7zip/Archive/FlvHandler.cpp b/CPP/7zip/Archive/FlvHandler.cpp new file mode 100755 index 0000000..f64b8bb --- /dev/null +++ b/CPP/7zip/Archive/FlvHandler.cpp @@ -0,0 +1,544 @@ +// FlvHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Common/Buffer.h" +#include "Common/ComTry.h" +// #include "Common/Defs.h" +#include "Common/MyString.h" + +#include "Windows/PropVariant.h" + +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamObjects.h" +#include "../Common/StreamUtils.h" + +#define GetBe24(p) ( \ + ((UInt32)((const Byte *)(p))[0] << 16) | \ + ((UInt32)((const Byte *)(p))[1] << 8) | \ + ((const Byte *)(p))[2] ) + +#define Get16(p) GetBe16(p) +#define Get24(p) GetBe24(p) +#define Get32(p) GetBe32(p) + +namespace NArchive { +namespace NFlv { + +static const UInt32 kFileSizeMax = (UInt32)1 << 30; +static const int kNumChunksMax = (UInt32)1 << 23; + +const UInt32 kTagHeaderSize = 11; + +static const Byte kFlag_Video = 1; +static const Byte kFlag_Audio = 4; + +static const Byte kType_Audio = 8; +static const Byte kType_Video = 9; +static const Byte kType_Meta = 18; +static const int kNumTypes = 19; + +struct CItem +{ + UInt32 Offset; + UInt32 Size; + // UInt32 Time; + Byte Type; +}; + +struct CItem2 +{ + Byte Type; + Byte SubType; + Byte Props; + bool SameSubTypes; + int NumChunks; + size_t Size; + + CReferenceBuf *BufSpec; + CMyComPtr RefBuf; + + bool IsAudio() const { return Type == kType_Audio; } +}; + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + int _isRaw; + CMyComPtr _stream; + CObjectVector _items2; + // CByteBuffer _metadata; + HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); + AString GetComment(); +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +STATPROPSTG kProps[] = +{ + { NULL, kpidSize, VT_UI8}, + { NULL, kpidNumBlocks, VT_UI4}, + { NULL, kpidComment, VT_BSTR} +}; + +/* +STATPROPSTG kArcProps[] = +{ + { NULL, kpidComment, VT_BSTR} +}; +*/ + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO + +static const char *g_AudioTypes[16] = +{ + "pcm", + "adpcm", + "mp3", + "pcm_le", + "nellymoser16", + "nellymoser8", + "nellymoser", + "g711a", + "g711m", + "audio9", + "aac", + "speex", + "audio12", + "audio13", + "mp3", + "audio15" +}; + +static const char *g_VideoTypes[16] = +{ + "video0", + "jpeg", + "h263", + "screen", + "vp6", + "vp6alpha", + "screen2", + "avc", + "video8", + "video9", + "video10", + "video11", + "video12", + "video13", + "video14", + "video15" +}; + +static const char *g_Rates[4] = +{ + "5.5 kHz", + "11 kHz", + "22 kHz", + "44 kHz" +}; + +static void MyStrCat(char *d, const char *s) +{ + MyStringCopy(d + MyStringLen(d), s); +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + NWindows::NCOM::CPropVariant prop; + const CItem2 &item = _items2[index]; + switch(propID) + { + case kpidExtension: + prop = _isRaw ? + (item.IsAudio() ? g_AudioTypes[item.SubType] : g_VideoTypes[item.SubType]) : + (item.IsAudio() ? "audio.flv" : "video.flv"); + break; + case kpidSize: + case kpidPackSize: + prop = (UInt64)item.Size; + break; + case kpidNumBlocks: prop = (UInt32)item.NumChunks; break; + case kpidComment: + { + char sz[64]; + MyStringCopy(sz, (item.IsAudio() ? g_AudioTypes[item.SubType] : g_VideoTypes[item.SubType]) ); + if (item.IsAudio()) + { + MyStrCat(sz, " "); + MyStrCat(sz, g_Rates[(item.Props >> 2) & 3]); + MyStrCat(sz, (item.Props & 2) ? " 16-bit" : " 8-bit"); + MyStrCat(sz, (item.Props & 1) ? " stereo" : " mono"); + } + prop = sz; + break; + } + } + prop.Detach(value); + return S_OK; +} + +/* +AString CHandler::GetComment() +{ + const Byte *p = _metadata; + size_t size = _metadata.GetCapacity(); + AString res; + if (size > 0) + { + p++; + size--; + for (;;) + { + if (size < 2) + break; + int len = Get16(p); + p += 2; + size -= 2; + if (len == 0 || (size_t)len > size) + break; + { + AString temp; + char *sz = temp.GetBuffer(len); + memcpy(sz, p, len); + sz[len] = 0; + temp.ReleaseBuffer(); + if (!res.IsEmpty()) + res += '\n'; + res += temp; + } + p += len; + size -= len; + if (size < 1) + break; + Byte type = *p++; + size--; + bool ok = false; + switch(type) + { + case 0: + { + if (size < 8) + break; + ok = true; + Byte reverse[8]; + for (int i = 0; i < 8; i++) + { + bool little_endian = 1; + if (little_endian) + reverse[i] = p[7 - i]; + else + reverse[i] = p[i]; + } + double d = *(double *)reverse; + char temp[32]; + sprintf(temp, " = %.3f", d); + res += temp; + p += 8; + size -= 8; + break; + } + case 8: + { + if (size < 4) + break; + ok = true; + // UInt32 numItems = Get32(p); + p += 4; + size -= 4; + break; + } + } + if (!ok) + break; + } + } + return res; +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidComment: prop = GetComment(); break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} +*/ + +HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) +{ + CRecordVector items; + + const UInt32 kHeaderSize = 13; + Byte header[kHeaderSize]; + RINOK(ReadStream_FALSE(stream, header, kHeaderSize)); + if (header[0] != 'F' || + header[1] != 'L' || + header[2] != 'V' || + header[3] != 1 || + (header[4] & 0xFA) != 0) + return S_FALSE; + UInt32 offset = Get32(header + 5); + if (offset != 9 || Get32(header + 9) != 0) + return S_FALSE; + offset += 4; + + CByteBuffer inBuf; + size_t fileSize; + { + UInt64 fileSize64; + RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize64)); + if (fileSize64 > kFileSizeMax) + return S_FALSE; + + if (callback) + RINOK(callback->SetTotal(NULL, &fileSize64)) + + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + fileSize = (size_t)fileSize64; + inBuf.SetCapacity(fileSize); + for (size_t pos = 0; pos < fileSize;) + { + UInt64 offset64 = pos; + if (callback) + RINOK(callback->SetCompleted(NULL, &offset64)) + size_t rem = MyMin(fileSize - pos, (size_t)(1 << 20)); + RINOK(ReadStream_FALSE(stream, inBuf + pos, rem)); + pos += rem; + } + } + + int lasts[kNumTypes]; + int i; + for (i = 0; i < kNumTypes; i++) + lasts[i] = -1; + + while (offset < fileSize) + { + CItem item; + item.Offset = offset; + const Byte *buf = inBuf + offset; + offset += kTagHeaderSize; + if (offset > fileSize) + return S_FALSE; + + item.Type = buf[0]; + UInt32 size = Get24(buf + 1); + if (size < 1) + return S_FALSE; + // item.Time = Get24(buf + 4); + // item.Time |= (UInt32)buf[7] << 24; + if (Get24(buf + 8) != 0) // streamID + return S_FALSE; + + UInt32 curSize = kTagHeaderSize + size + 4; + item.Size = curSize; + + offset += curSize - kTagHeaderSize; + if (offset > fileSize) + return S_FALSE; + + if (Get32(buf + kTagHeaderSize + size) != kTagHeaderSize + size) + return S_FALSE; + + // printf("\noffset = %6X type = %2d time = %6d size = %6d", (UInt32)offset, item.Type, item.Time, item.Size); + + if (item.Type == kType_Meta) + { + // _metadata = item.Buf; + } + else + { + if (item.Type != kType_Audio && item.Type != kType_Video) + return S_FALSE; + if (items.Size() >= kNumChunksMax) + return S_FALSE; + Byte firstByte = buf[kTagHeaderSize]; + Byte subType, props; + if (item.Type == kType_Audio) + { + subType = firstByte >> 4; + props = firstByte & 0xF; + } + else + { + subType = firstByte & 0xF; + props = firstByte >> 4; + } + int last = lasts[item.Type]; + if (last < 0) + { + CItem2 item2; + item2.RefBuf = item2.BufSpec = new CReferenceBuf; + item2.Size = curSize; + item2.Type = item.Type; + item2.SubType = subType; + item2.Props = props; + item2.NumChunks = 1; + item2.SameSubTypes = true; + lasts[item.Type] = _items2.Add(item2); + } + else + { + CItem2 &item2 = _items2[last]; + if (subType != item2.SubType) + item2.SameSubTypes = false; + item2.Size += curSize; + item2.NumChunks++; + } + items.Add(item); + } + } + + _isRaw = (_items2.Size() == 1); + for (i = 0; i < _items2.Size(); i++) + { + CItem2 &item2 = _items2[i]; + CByteBuffer &itemBuf = item2.BufSpec->Buf; + if (_isRaw) + { + if (!item2.SameSubTypes) + return S_FALSE; + itemBuf.SetCapacity((size_t)item2.Size - (kTagHeaderSize + 4 + 1) * item2.NumChunks); + item2.Size = 0; + } + else + { + itemBuf.SetCapacity(kHeaderSize + (size_t)item2.Size); + memcpy(itemBuf, header, kHeaderSize); + itemBuf[4] = item2.IsAudio() ? kFlag_Audio : kFlag_Video; + item2.Size = kHeaderSize; + } + } + + for (i = 0; i < items.Size(); i++) + { + const CItem &item = items[i]; + CItem2 &item2 = _items2[lasts[item.Type]]; + size_t size = item.Size; + const Byte *src = inBuf + item.Offset; + if (_isRaw) + { + src += kTagHeaderSize + 1; + size -= (kTagHeaderSize + 4 + 1); + } + memcpy(item2.BufSpec->Buf + item2.Size, src, size); + item2.Size += size; + } + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + Close(); + HRESULT res; + try + { + res = Open2(inStream, callback); + if (res == S_OK) + _stream = inStream; + } + catch(...) { res = S_FALSE; } + if (res != S_OK) + { + Close(); + return S_FALSE; + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _stream.Release(); + _items2.Clear(); + // _metadata.SetCapacity(0); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _items2.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _items2.Size(); + if (numItems == 0) + return S_OK; + UInt64 totalSize = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + totalSize += _items2[allFilesMode ? i : indices[i]].Size; + extractCallback->SetTotal(totalSize); + + totalSize = 0; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + for (i = 0; i < numItems; i++) + { + lps->InSize = lps->OutSize = totalSize; + RINOK(lps->SetCur()); + CMyComPtr outStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + UInt32 index = allFilesMode ? i : indices[i]; + const CItem2 &item = _items2[index]; + RINOK(extractCallback->GetStream(index, &outStream, askMode)); + totalSize += item.Size; + if (!testMode && !outStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + if (outStream) + { + RINOK(WriteStream(outStream, item.BufSpec->Buf, item.BufSpec->Buf.GetCapacity())); + } + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + *stream = 0; + CBufInStream *streamSpec = new CBufInStream; + CMyComPtr streamTemp = streamSpec; + streamSpec->Init(_items2[index].BufSpec); + *stream = streamTemp.Detach(); + return S_OK; + COM_TRY_END +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"FLV", L"flv", 0, 0xD6, { 'F', 'L', 'V' }, 3, false, CreateArc, 0 }; + +REGISTER_ARC(Flv) + +}} diff --git a/CPP/7zip/Archive/GzHandler.cpp b/CPP/7zip/Archive/GzHandler.cpp new file mode 100755 index 0000000..4c8c692 --- /dev/null +++ b/CPP/7zip/Archive/GzHandler.cpp @@ -0,0 +1,698 @@ +// GzHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Common/ComTry.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" +#include "../Compress/DeflateDecoder.h" +#include "../Compress/DeflateEncoder.h" + +#include "Common/InStreamWithCRC.h" +#include "Common/OutStreamWithCRC.h" + +#include "DeflateProps.h" + +#define Get32(p) GetUi32(p) + +using namespace NWindows; + +namespace NArchive { +namespace NGz { + +static const UInt16 kSignature = 0x8B1F; + +namespace NHeader +{ + namespace NFlags + { + const Byte kIsText = 1 << 0; + const Byte kCrc = 1 << 1; + const Byte kExtra = 1 << 2; + const Byte kName = 1 << 3; + const Byte kComment = 1 << 4; + } + + namespace NExtraFlags + { + const Byte kMaximum = 2; + const Byte kFastest = 4; + } + + namespace NCompressionMethod + { + const Byte kDeflate = 8; + } + + namespace NHostOS + { + enum EEnum + { + kFAT = 0, + kAMIGA, + kVMS, + kUnix, + kVM_CMS, + kAtari, + kHPFS, + kMac, + kZ_System, + kCPM, + kTOPS20, + kNTFS, + kQDOS, + kAcorn, + kVFAT, + kMVS, + kBeOS, + kTandem, + + kUnknown = 255 + }; + } +} + +static const char *kHostOSes[] = +{ + "FAT", + "AMIGA", + "VMS", + "Unix", + "VM/CMS", + "Atari", + "HPFS", + "Macintosh", + "Z-System", + "CP/M", + "TOPS-20", + "NTFS", + "SMS/QDOS", + "Acorn", + "VFAT", + "MVS", + "BeOS", + "Tandem", + "OS/400", + "OS/X" +}; + +static const char *kUnknownOS = "Unknown"; + +class CItem +{ + bool TestFlag(Byte flag) const { return (Flags & flag) != 0; } +public: + Byte Method; + Byte Flags; + Byte ExtraFlags; + Byte HostOS; + UInt32 Time; + UInt32 Crc; + UInt32 Size32; + + AString Name; + AString Comment; + // CByteBuffer Extra; + + // bool IsText() const { return TestFlag(NHeader::NFlags::kIsText); } + bool HeaderCrcIsPresent() const { return TestFlag(NHeader::NFlags::kCrc); } + bool ExtraFieldIsPresent() const { return TestFlag(NHeader::NFlags::kExtra); } + bool NameIsPresent() const { return TestFlag(NHeader::NFlags::kName); } + bool CommentIsPresent() const { return TestFlag(NHeader::NFlags::kComment); } + + void Clear() + { + Name.Empty(); + Comment.Empty(); + // Extra.SetCapacity(0); + } + + HRESULT ReadHeader(NCompress::NDeflate::NDecoder::CCOMCoder *stream); + HRESULT ReadFooter1(NCompress::NDeflate::NDecoder::CCOMCoder *stream); + HRESULT ReadFooter2(ISequentialInStream *stream); + + HRESULT WriteHeader(ISequentialOutStream *stream); + HRESULT WriteFooter(ISequentialOutStream *stream); +}; + +static HRESULT ReadBytes(NCompress::NDeflate::NDecoder::CCOMCoder *stream, Byte *data, UInt32 size) +{ + for (UInt32 i = 0; i < size; i++) + data[i] = stream->ReadByte(); + return stream->InputEofError() ? S_FALSE : S_OK; +} + +static HRESULT SkipBytes(NCompress::NDeflate::NDecoder::CCOMCoder *stream, UInt32 size) +{ + for (UInt32 i = 0; i < size; i++) + stream->ReadByte(); + return stream->InputEofError() ? S_FALSE : S_OK; +} + +static HRESULT ReadUInt16(NCompress::NDeflate::NDecoder::CCOMCoder *stream, UInt16 &value /* , UInt32 &crc */) +{ + value = 0; + for (int i = 0; i < 2; i++) + { + Byte b = stream->ReadByte(); + if (stream->InputEofError()) + return S_FALSE; + // crc = CRC_UPDATE_BYTE(crc, b); + value |= (UInt16(b) << (8 * i)); + } + return S_OK; +} + +static HRESULT ReadString(NCompress::NDeflate::NDecoder::CCOMCoder *stream, AString &s, UInt32 limit /* , UInt32 &crc */) +{ + s.Empty(); + for (UInt32 i = 0; i < limit; i++) + { + Byte b = stream->ReadByte(); + if (stream->InputEofError()) + return S_FALSE; + // crc = CRC_UPDATE_BYTE(crc, b); + if (b == 0) + return S_OK; + s += (char)b; + } + return S_FALSE; +} + +HRESULT CItem::ReadHeader(NCompress::NDeflate::NDecoder::CCOMCoder *stream) +{ + Clear(); + + // Header-CRC field had another meaning in old version of gzip! + // UInt32 crc = CRC_INIT_VAL; + Byte buf[10]; + + RINOK(ReadBytes(stream, buf, 10)); + + if (GetUi16(buf) != kSignature) + return S_FALSE; + + Method = buf[2]; + + if (Method != NHeader::NCompressionMethod::kDeflate) + return S_FALSE; + + Flags = buf[3]; + Time = Get32(buf + 4); + ExtraFlags = buf[8]; + HostOS = buf[9]; + + // crc = CrcUpdate(crc, buf, 10); + + if (ExtraFieldIsPresent()) + { + UInt16 extraSize; + RINOK(ReadUInt16(stream, extraSize /* , crc */)); + RINOK(SkipBytes(stream, extraSize)); + // Extra.SetCapacity(extraSize); + // RINOK(ReadStream_FALSE(stream, Extra, extraSize)); + // crc = CrcUpdate(crc, Extra, extraSize); + } + if (NameIsPresent()) + RINOK(ReadString(stream, Name, (1 << 10) /* , crc */)); + if (CommentIsPresent()) + RINOK(ReadString(stream, Comment, (1 << 16) /* , crc */)); + + if (HeaderCrcIsPresent()) + { + UInt16 headerCRC; + // UInt32 dummy = 0; + RINOK(ReadUInt16(stream, headerCRC /* , dummy */)); + /* + if ((UInt16)CRC_GET_DIGEST(crc) != headerCRC) + return S_FALSE; + */ + } + return stream->InputEofError() ? S_FALSE : S_OK; +} + +HRESULT CItem::ReadFooter1(NCompress::NDeflate::NDecoder::CCOMCoder *stream) +{ + Byte buf[8]; + RINOK(ReadBytes(stream, buf, 8)); + Crc = Get32(buf); + Size32 = Get32(buf + 4); + return stream->InputEofError() ? S_FALSE : S_OK; +} + +HRESULT CItem::ReadFooter2(ISequentialInStream *stream) +{ + Byte buf[8]; + RINOK(ReadStream_FALSE(stream, buf, 8)); + Crc = Get32(buf); + Size32 = Get32(buf + 4); + return S_OK; +} + +HRESULT CItem::WriteHeader(ISequentialOutStream *stream) +{ + Byte buf[10]; + SetUi16(buf, kSignature); + buf[2] = Method; + buf[3] = Flags & NHeader::NFlags::kName; + // buf[3] |= NHeader::NFlags::kCrc; + SetUi32(buf + 4, Time); + buf[8] = ExtraFlags; + buf[9] = HostOS; + RINOK(WriteStream(stream, buf, 10)); + // crc = CrcUpdate(CRC_INIT_VAL, buf, 10); + if (NameIsPresent()) + { + // crc = CrcUpdate(crc, (const char *)Name, Name.Length() + 1); + RINOK(WriteStream(stream, (const char *)Name, Name.Length() + 1)); + } + // SetUi16(buf, (UInt16)CRC_GET_DIGEST(crc)); + // RINOK(WriteStream(stream, buf, 2)); + return S_OK; +} + +HRESULT CItem::WriteFooter(ISequentialOutStream *stream) +{ + Byte buf[8]; + SetUi32(buf, Crc); + SetUi32(buf + 4, Size32); + return WriteStream(stream, buf, 8); +} + +class CHandler: + public IInArchive, + public IArchiveOpenSeq, + public IOutArchive, + public ISetProperties, + public CMyUnknownImp +{ + CItem _item; + UInt64 _startPosition; + UInt64 _headerSize; + UInt64 _packSize; + bool _packSizeDefined; + CMyComPtr _stream; + CMyComPtr _decoder; + NCompress::NDeflate::NDecoder::CCOMCoder *_decoderSpec; + + CDeflateProps _method; + +public: + MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties) + INTERFACE_IInArchive(;) + INTERFACE_IOutArchive(;) + STDMETHOD(OpenSeq)(ISequentialInStream *stream); + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps); + + CHandler() + { + _decoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder; + _decoder = _decoderSpec; + } +}; + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidHostOS, VT_BSTR}, + { NULL, kpidCRC, VT_UI4} + // { NULL, kpidComment, VT_BSTR} +} +; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO_Table + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidPhySize: if (_packSizeDefined) prop = _packSize; break; + } + prop.Detach(value); + return S_OK; +} + + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = 1; + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidPath: + if (_item.NameIsPresent()) + prop = MultiByteToUnicodeString(_item.Name, CP_ACP); + break; + // case kpidComment: if (_item.CommentIsPresent()) prop = MultiByteToUnicodeString(_item.Comment, CP_ACP); break; + case kpidMTime: + { + if (_item.Time != 0) + { + FILETIME utc; + NTime::UnixTimeToFileTime(_item.Time, utc); + prop = utc; + } + break; + } + case kpidSize: if (_stream) prop = (UInt64)_item.Size32; break; + case kpidPackSize: if (_packSizeDefined) prop = _packSize; break; + case kpidHostOS: prop = (_item.HostOS < sizeof(kHostOSes) / sizeof(kHostOSes[0])) ? + kHostOSes[_item.HostOS] : kUnknownOS; break; + case kpidCRC: if (_stream) prop = _item.Crc; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *) +{ + COM_TRY_BEGIN + HRESULT res; + try + { + RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_startPosition)); + res = OpenSeq(stream); + if (res == S_OK) + { + UInt64 endPos; + res = stream->Seek(-8, STREAM_SEEK_END, &endPos); + _packSize = endPos + 8 - _startPosition; + _packSizeDefined = true; + if (res == S_OK) + { + res = _item.ReadFooter2(stream); + _stream = stream; + } + } + } + catch(...) { res = S_FALSE; } + if (res != S_OK) + Close(); + return res; + COM_TRY_END +} + +STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) +{ + COM_TRY_BEGIN + HRESULT res; + try + { + Close(); + _decoderSpec->SetInStream(stream); + _decoderSpec->InitInStream(true); + res = _item.ReadHeader(_decoderSpec); + _headerSize = _decoderSpec->GetInputProcessedSize(); + } + catch(...) { res = S_FALSE; } + if (res != S_OK) + Close(); + return res; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _packSizeDefined = false; + _stream.Release(); + _decoderSpec->ReleaseInStream(); + 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)-1 && (numItems != 1 || indices[0] != 0)) + return E_INVALIDARG; + + if (_stream) + extractCallback->SetTotal(_packSize); + 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); + + COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; + CMyComPtr outStream(outStreamSpec); + outStreamSpec->SetStream(realOutStream); + outStreamSpec->Init(); + realOutStream.Release(); + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, true); + + if (_stream) + { + RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); + _decoderSpec->InitInStream(true); + } + bool firstItem = true; + Int32 opRes; + for (;;) + { + lps->InSize = _packSize = _decoderSpec->GetInputProcessedSize(); + _packSizeDefined = true; + lps->OutSize = outStreamSpec->GetSize(); + RINOK(lps->SetCur()); + + CItem item; + if (!firstItem || _stream) + { + HRESULT result = item.ReadHeader(_decoderSpec); + if (result != S_OK) + { + if (result != S_FALSE) + return result; + opRes = firstItem ? + NExtract::NOperationResult::kDataError : + NExtract::NOperationResult::kOK; + break; + } + } + firstItem = false; + + UInt64 startOffset = outStreamSpec->GetSize(); + outStreamSpec->InitCRC(); + + HRESULT result = _decoderSpec->CodeResume(outStream, NULL, progress); + if (result != S_OK) + { + if (result != S_FALSE) + return result; + opRes = NExtract::NOperationResult::kDataError; + break; + } + + _decoderSpec->AlignToByte(); + if (item.ReadFooter1(_decoderSpec) != S_OK) + { + opRes = NExtract::NOperationResult::kDataError; + break; + } + if (item.Crc != outStreamSpec->GetCRC() || + item.Size32 != (UInt32)(outStreamSpec->GetSize() - startOffset)) + { + opRes = NExtract::NOperationResult::kCRCError; + break; + } + } + outStream.Release(); + return extractCallback->SetOperationResult(opRes); + COM_TRY_END +} + +static const Byte kHostOS = + #ifdef _WIN32 + NHeader::NHostOS::kFAT; + #else + NHeader::NHostOS::kUnix; + #endif + +static HRESULT UpdateArchive( + ISequentialOutStream *outStream, + UInt64 unpackSize, + const CItem &newItem, + CDeflateProps &deflateProps, + IArchiveUpdateCallback *updateCallback) +{ + UInt64 complexity = 0; + RINOK(updateCallback->SetTotal(unpackSize)); + RINOK(updateCallback->SetCompleted(&complexity)); + + CMyComPtr fileInStream; + + RINOK(updateCallback->GetStream(0, &fileInStream)); + + CSequentialInStreamWithCRC *inStreamSpec = new CSequentialInStreamWithCRC; + CMyComPtr crcStream(inStreamSpec); + inStreamSpec->SetStream(fileInStream); + inStreamSpec->Init(); + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(updateCallback, true); + + CItem item = newItem; + item.Method = NHeader::NCompressionMethod::kDeflate; + item.ExtraFlags = deflateProps.IsMaximum() ? + NHeader::NExtraFlags::kMaximum : + NHeader::NExtraFlags::kFastest; + + item.HostOS = kHostOS; + + RINOK(item.WriteHeader(outStream)); + + NCompress::NDeflate::NEncoder::CCOMCoder *deflateEncoderSpec = new NCompress::NDeflate::NEncoder::CCOMCoder; + CMyComPtr deflateEncoder = deflateEncoderSpec; + RINOK(deflateProps.SetCoderProperties(deflateEncoderSpec)); + RINOK(deflateEncoder->Code(crcStream, outStream, NULL, NULL, progress)); + + item.Crc = inStreamSpec->GetCRC(); + item.Size32 = (UInt32)inStreamSpec->GetSize(); + RINOK(item.WriteFooter(outStream)); + return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); +} + +STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) +{ + *timeType = NFileTimeType::kUnix; + return S_OK; +} + +STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, + IArchiveUpdateCallback *updateCallback) +{ + if (numItems != 1) + return E_INVALIDARG; + + Int32 newData, newProps; + UInt32 indexInArchive; + if (!updateCallback) + return E_FAIL; + RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive)); + + CItem newItem = _item; + newItem.ExtraFlags = 0; + newItem.Flags = 0; + if (IntToBool(newProps)) + { + { + FILETIME utcTime; + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(0, kpidMTime, &prop)); + if (prop.vt != VT_FILETIME) + return E_INVALIDARG; + utcTime = prop.filetime; + if (!NTime::FileTimeToUnixTime(utcTime, newItem.Time)) + return E_INVALIDARG; + } + { + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(0, kpidPath, &prop)); + if (prop.vt == VT_BSTR) + { + UString name = prop.bstrVal; + int dirDelimiterPos = name.ReverseFind(CHAR_PATH_SEPARATOR); + if (dirDelimiterPos >= 0) + name = name.Mid(dirDelimiterPos + 1); + newItem.Name = UnicodeStringToMultiByte(name, CP_ACP); + if (!newItem.Name.IsEmpty()) + newItem.Flags |= NHeader::NFlags::kName; + } + else if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + } + { + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop)); + if (prop.vt == VT_BOOL) + { + if (prop.boolVal != VARIANT_FALSE) + return E_INVALIDARG; + } + else if (prop.vt != VT_EMPTY) + 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; + } + + return UpdateArchive(outStream, size, newItem, _method, updateCallback); + } + + if (indexInArchive != 0) + return E_INVALIDARG; + + if (!_stream) + return E_NOTIMPL; + + UInt64 offset = _startPosition; + if (IntToBool(newProps)) + { + newItem.WriteHeader(outStream); + offset += _headerSize; + } + RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL)); + return NCompress::CopyStream(_stream, outStream, NULL); +} + +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) +{ + return _method.SetProperties(names, values, numProps); +} + +static IInArchive *CreateArc() { return new CHandler; } +#ifndef EXTRACT_ONLY +static IOutArchive *CreateArcOut() { return new CHandler; } +#else +#define CreateArcOut 0 +#endif + +static CArcInfo g_ArcInfo = + { L"gzip", L"gz gzip tgz tpz", L"* * .tar .tar", 0xEF, { 0x1F, 0x8B, 8 }, 3, true, CreateArc, CreateArcOut }; + +REGISTER_ARC(GZip) + +}} diff --git a/CPP/7zip/Archive/Hfs/HfsHandler.cpp b/CPP/7zip/Archive/Hfs/HfsHandler.cpp new file mode 100755 index 0000000..756da17 --- /dev/null +++ b/CPP/7zip/Archive/Hfs/HfsHandler.cpp @@ -0,0 +1,243 @@ +// HfsHandler.cpp + +#include "StdAfx.h" + +#include "Common/ComTry.h" +#include "Windows/PropVariant.h" +#include "../../Common/StreamUtils.h" +#include "HfsHandler.h" + +namespace NArchive { +namespace NHfs { + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidATime, VT_FILETIME} +}; + +STATPROPSTG kArcProps[] = +{ + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidClusterSize, VT_UI4}, + { NULL, kpidFreeSpace, VT_UI8}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidMTime, VT_FILETIME} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +static void HfsTimeToProp(UInt32 hfsTime, NWindows::NCOM::CPropVariant &prop) +{ + FILETIME ft; + HfsTimeToFileTime(hfsTime, ft); + prop = ft; +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidMethod: prop = _db.Header.IsHfsX() ? L"HFSX" : L"HFS+"; break; + case kpidClusterSize: prop = (UInt32)1 << _db.Header.BlockSizeLog; break; + case kpidFreeSpace: prop = (UInt64)_db.Header.NumFreeBlocks << _db.Header.BlockSizeLog; break; + case kpidMTime: HfsTimeToProp(_db.Header.MTime, prop); break; + case kpidCTime: + { + FILETIME localFt, ft; + HfsTimeToFileTime(_db.Header.CTime, localFt); + if (LocalFileTimeToFileTime(&localFt, &ft)) + prop = ft; + break; + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + const CItem &item = _db.Items[index]; + switch(propID) + { + case kpidPath: prop = _db.GetItemPath(index); break; + case kpidIsDir: prop = item.IsDir(); break; + + case kpidCTime: HfsTimeToProp(item.CTime, prop); break; + case kpidMTime: HfsTimeToProp(item.MTime, prop); break; + case kpidATime: HfsTimeToProp(item.ATime, prop); break; + + case kpidPackSize: if (!item.IsDir()) prop = (UInt64)item.NumBlocks << _db.Header.BlockSizeLog; break; + case kpidSize: if (!item.IsDir()) prop = item.Size; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +class CProgressImp: public CProgressVirt +{ + CMyComPtr _callback; +public: + HRESULT SetTotal(UInt64 numFiles); + HRESULT SetCompleted(UInt64 numFiles); + CProgressImp(IArchiveOpenCallback *callback): _callback(callback) {} +}; + +HRESULT CProgressImp::SetTotal(UInt64 numFiles) +{ + if (_callback) + return _callback->SetTotal(&numFiles, NULL); + return S_OK; +} + +HRESULT CProgressImp::SetCompleted(UInt64 numFiles) +{ + if (_callback) + return _callback->SetCompleted(&numFiles, NULL); + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *inStream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + Close(); + try + { + CProgressImp progressImp(callback); + HRESULT res = _db.Open(inStream, &progressImp); + if (res == E_ABORT) + return res; + if (res != S_OK) + return S_FALSE; + _stream = inStream; + } + catch(...) { return S_FALSE; } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _stream.Release(); + _db.Clear(); + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _db.Items.Size(); + if (numItems == 0) + return S_OK; + UInt32 i; + UInt64 totalSize = 0; + for (i = 0; i < numItems; i++) + { + const CItem &item = _db.Items[allFilesMode ? i : indices[i]]; + if (!item.IsDir()) + totalSize += item.Size; + } + RINOK(extractCallback->SetTotal(totalSize)); + + UInt64 currentTotalSize = 0, currentItemSize = 0; + + CByteBuffer buf; + const UInt32 kBufSize = (1 << 16); + buf.SetCapacity(kBufSize); + + for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) + { + RINOK(extractCallback->SetCompleted(¤tTotalSize)); + Int32 index = allFilesMode ? i : indices[i]; + const CItem &item = _db.Items[index]; + currentItemSize = 0; + if (!item.IsDir()) + currentItemSize = item.Size; + + CMyComPtr realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + if (item.IsDir()) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + if (!testMode && !realOutStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + UInt64 pos = 0; + int res = NExtract::NOperationResult::kOK; + int i; + for (i = 0; i < item.Extents.Size(); i++) + { + if (item.Size == pos) + break; + if (res != NExtract::NOperationResult::kOK) + break; + const CExtent &e = item.Extents[i]; + RINOK(_stream->Seek((UInt64)e.Pos << _db.Header.BlockSizeLog, STREAM_SEEK_SET, NULL)); + UInt64 extentSize = (UInt64)e.NumBlocks << _db.Header.BlockSizeLog; + for (;;) + { + if (extentSize == 0) + break; + UInt64 rem = item.Size - pos; + if (rem == 0) + { + if (extentSize >= (UInt64)((UInt32)1 << _db.Header.BlockSizeLog)) + res = NExtract::NOperationResult::kDataError; + break; + } + UInt32 curSize = kBufSize; + if (curSize > rem) + curSize = (UInt32)rem; + if (curSize > extentSize) + curSize = (UInt32)extentSize; + RINOK(ReadStream_FALSE(_stream, buf, curSize)); + if (realOutStream) + { + RINOK(WriteStream(realOutStream, buf, curSize)); + } + pos += curSize; + extentSize -= curSize; + UInt64 processed = currentTotalSize + pos; + RINOK(extractCallback->SetCompleted(&processed)); + } + } + if (i != item.Extents.Size() || item.Size != pos) + res = NExtract::NOperationResult::kDataError; + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(res)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _db.Items.Size(); + return S_OK; +} + +}} diff --git a/CPP/7zip/Archive/Hfs/HfsHandler.h b/CPP/7zip/Archive/Hfs/HfsHandler.h new file mode 100755 index 0000000..8cfa9f6 --- /dev/null +++ b/CPP/7zip/Archive/Hfs/HfsHandler.h @@ -0,0 +1,26 @@ +// HfsHandler.h + +#ifndef __ARCHIVE_HFS_HANDLER_H +#define __ARCHIVE_HFS_HANDLER_H + +#include "Common/MyCom.h" +#include "../IArchive.h" +#include "HfsIn.h" + +namespace NArchive { +namespace NHfs { + +class CHandler: + public IInArchive, + public CMyUnknownImp +{ + CMyComPtr _stream; + CDatabase _db; +public: + MY_UNKNOWN_IMP1(IInArchive) + INTERFACE_IInArchive(;) +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Hfs/HfsIn.cpp b/CPP/7zip/Archive/Hfs/HfsIn.cpp new file mode 100755 index 0000000..0e84898 --- /dev/null +++ b/CPP/7zip/Archive/Hfs/HfsIn.cpp @@ -0,0 +1,480 @@ +// HfsIn.cpp + +#include "StdAfx.h" + +#include "../../Common/StreamUtils.h" +#include "Common/IntToString.h" + +#include "HfsIn.h" + +#include "../../../../C/CpuArch.h" + +#define Get16(p) GetBe16(p) +#define Get32(p) GetBe32(p) +#define Get64(p) GetBe64(p) + +namespace NArchive { +namespace NHfs { + +#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } + +static int CompareIdToIndex(const CIdIndexPair *p1, const CIdIndexPair *p2, void * /* param */) +{ + RINOZ(MyCompare(p1->ID, p2->ID)); + return MyCompare(p1->Index, p2->Index); +} + +bool operator< (const CIdIndexPair &a1, const CIdIndexPair &a2) { return (a1.ID < a2.ID); } +bool operator> (const CIdIndexPair &a1, const CIdIndexPair &a2) { return (a1.ID > a2.ID); } +bool operator==(const CIdIndexPair &a1, const CIdIndexPair &a2) { return (a1.ID == a2.ID); } +bool operator!=(const CIdIndexPair &a1, const CIdIndexPair &a2) { return (a1.ID != a2.ID); } + +static UString GetSpecName(const UString &name, UInt32 /* id */) +{ + UString name2 = name; + name2.Trim(); + if (name2.IsEmpty()) + { + /* + wchar_t s[32]; + ConvertUInt64ToString(id, s); + return L"[" + (UString)s + L"]"; + */ + return L"[]"; + } + return name; +} + +UString CDatabase::GetItemPath(int index) const +{ + const CItem *item = &Items[index]; + UString name = GetSpecName(item->Name, item->ID); + + for (int i = 0; i < 1000; i++) + { + if (item->ParentID < 16 && item->ParentID != 2) + { + if (item->ParentID != 1) + break; + return name; + } + CIdIndexPair pair; + pair.ID = item->ParentID; + pair.Index = 0; + int indexInMap = IdToIndexMap.FindInSorted(pair); + if (indexInMap < 0) + break; + item = &Items[IdToIndexMap[indexInMap].Index]; + name = GetSpecName(item->Name, item->ID) + WCHAR_PATH_SEPARATOR + name; + } + return (UString)L"Unknown" + WCHAR_PATH_SEPARATOR + name; +} + +void CFork::Parse(const Byte *p) +{ + Size = Get64(p); + // ClumpSize = Get32(p + 8); + NumBlocks = Get32(p + 0xC); + for (int i = 0; i < 8; i++) + { + CExtent &e = Extents[i]; + e.Pos = Get32(p + 0x10 + i * 8); + e.NumBlocks = Get32(p + 0x10 + i * 8 + 4); + } +} + +static HRESULT ReadExtent(int blockSizeLog, IInStream *inStream, Byte *buf, const CExtent &e) +{ + RINOK(inStream->Seek((UInt64)e.Pos << blockSizeLog, STREAM_SEEK_SET, NULL)); + return ReadStream_FALSE(inStream, buf, (size_t)e.NumBlocks << blockSizeLog); +} + +HRESULT CDatabase::ReadFile(const CFork &fork, CByteBuffer &buf, IInStream *inStream) +{ + if (fork.NumBlocks >= Header.NumBlocks) + return S_FALSE; + size_t totalSize = (size_t)fork.NumBlocks << Header.BlockSizeLog; + if ((totalSize >> Header.BlockSizeLog) != fork.NumBlocks) + return S_FALSE; + buf.SetCapacity(totalSize); + UInt32 curBlock = 0; + for (int i = 0; i < 8; i++) + { + if (curBlock >= fork.NumBlocks) + break; + const CExtent &e = fork.Extents[i]; + if (fork.NumBlocks - curBlock < e.NumBlocks || e.Pos >= Header.NumBlocks) + return S_FALSE; + RINOK(ReadExtent(Header.BlockSizeLog, inStream, + (Byte *)buf + ((size_t)curBlock << Header.BlockSizeLog), e)); + curBlock += e.NumBlocks; + } + return S_OK; +} + +struct CNodeDescriptor +{ + UInt32 fLink; + UInt32 bLink; + Byte Kind; + Byte Height; + UInt16 NumRecords; + // UInt16 Reserved; + void Parse(const Byte *p); +}; + +void CNodeDescriptor::Parse(const Byte *p) +{ + fLink = Get32(p); + bLink = Get32(p + 4); + Kind = p[8]; + Height = p[9]; + NumRecords = Get16(p + 10); +} + +struct CHeaderRec +{ + // UInt16 TreeDepth; + // UInt32 RootNode; + // UInt32 LeafRecords; + UInt32 FirstLeafNode; + // UInt32 LastLeafNode; + int NodeSizeLog; + // UInt16 MaxKeyLength; + UInt32 TotalNodes; + // UInt32 FreeNodes; + // UInt16 Reserved1; + // UInt32 ClumpSize; + // Byte BtreeType; + // Byte KeyCompareType; + // UInt32 Attributes; + // UInt32 Reserved3[16]; + + HRESULT Parse(const Byte *p); +}; + +HRESULT CHeaderRec::Parse(const Byte *p) +{ + // TreeDepth = Get16(p); + // RootNode = Get32(p + 2); + // LeafRecords = Get32(p + 6); + FirstLeafNode = Get32(p + 0xA); + // LastLeafNode = Get32(p + 0xE); + UInt32 nodeSize = Get16(p + 0x12); + + int i; + for (i = 9; ((UInt32)1 << i) != nodeSize; i++) + if (i == 16) + return S_FALSE; + NodeSizeLog = i; + + // MaxKeyLength = Get16(p + 0x14); + TotalNodes = Get32(p + 0x16); + // FreeNodes = Get32(p + 0x1A); + // Reserved1 = Get16(p + 0x1E); + // ClumpSize = Get32(p + 0x20); + // BtreeType = p[0x24]; + // KeyCompareType = p[0x25]; + // Attributes = Get32(p + 0x26); + /* + for (int i = 0; i < 16; i++) + Reserved3[i] = Get32(p + 0x2A + i * 4); + */ + return S_OK; +} + + +enum ENodeType +{ + NODE_TYPE_LEAF = 0xFF, + NODE_TYPE_INDEX = 0, + NODE_TYPE_HEADER = 1, + NODE_TYPE_MODE = 2 +}; + +HRESULT CDatabase::LoadExtentFile(IInStream *inStream) +{ + // FileExtents.Clear(); + // ResExtents.Clear(); + + CByteBuffer extents; + RINOK(ReadFile(Header.ExtentsFile, extents, inStream)); + + const Byte *p = (const Byte *)extents; + + // CNodeDescriptor nodeDesc; + // nodeDesc.Parse(p); + CHeaderRec hr; + RINOK(hr.Parse(p + 14)); + + UInt32 node = hr.FirstLeafNode; + if (node != 0) + return S_FALSE; + /* + while (node != 0) + { + size_t nodeOffset = node * hr.NodeSize; + if ((node + 1)* hr.NodeSize > CatalogBuf.GetCapacity()) + return S_FALSE; + CNodeDescriptor desc; + desc.Parse(p + nodeOffset); + if (desc.Kind != NODE_TYPE_LEAF) + return S_FALSE; + UInt32 ptr = hr.NodeSize; + for (int i = 0; i < desc.NumRecords; i++) + { + UInt32 offs = Get16(p + nodeOffset + hr.NodeSize - (i + 1) * 2); + UInt32 offsNext = Get16(p + nodeOffset + hr.NodeSize - (i + 2) * 2); + + const Byte *r = p + nodeOffset + offs; + int keyLength = Get16(r); + Byte forkType = r[2]; + UInt32 id = Get16(r + 4); + UInt32 startBlock = Get16(r + 4); + CObjectVector *extents = (forkType == 0) ? &FileExtents : &ResExtents; + if (extents->Size() == 0) + extents->Add(CIdExtents()); + else + { + CIdExtents &e = extents->Back(); + if (e.ID != id) + { + if (e.ID > id) + return S_FALSE; + extents->Add(CIdExtents()); + } + } + CIdExtents &e = extents->Back(); + for (UInt32 k = offs + 10 + 2; k + 8 <= offsNext; k += 8) + { + CExtent ee; + ee.Pos = Get32(p + nodeOffset + k); + ee.NumBlocks = Get32(p + nodeOffset + k * 4); + e.Extents.Add(ee); + } + } + node = desc.fLink; + } + */ + return S_OK; +} + + +HRESULT CDatabase::LoadCatalog(IInStream *inStream, CProgressVirt *progress) +{ + Items.Clear(); + IdToIndexMap.ClearAndFree(); + + CByteBuffer catalogBuf; + RINOK(ReadFile(Header.CatalogFile, catalogBuf, inStream)); + const Byte *p = (const Byte *)catalogBuf; + + // CNodeDescriptor nodeDesc; + // nodeDesc.Parse(p); + CHeaderRec hr; + hr.Parse(p + 14); + + // CaseSensetive = (Header.IsHfsX() && hr.KeyCompareType == 0xBC); + + if ((catalogBuf.GetCapacity() >> hr.NodeSizeLog) < hr.TotalNodes) + return S_FALSE; + + CByteBuffer usedBuf; + usedBuf.SetCapacity(hr.TotalNodes); + for (UInt32 i = 0; i < hr.TotalNodes; i++) + usedBuf[i] = 0; + + UInt32 node = hr.FirstLeafNode; + while (node != 0) + { + if (node >= hr.TotalNodes) + return S_FALSE; + if (usedBuf[node]) + return S_FALSE; + usedBuf[node] = 1; + size_t nodeOffset = (size_t)node << hr.NodeSizeLog; + CNodeDescriptor desc; + desc.Parse(p + nodeOffset); + if (desc.Kind != NODE_TYPE_LEAF) + return S_FALSE; + for (int i = 0; i < desc.NumRecords; i++) + { + UInt32 nodeSize = (1 << hr.NodeSizeLog); + UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2); + UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2); + UInt32 recSize = offsNext - offs; + if (offsNext >= nodeSize || offsNext < offs || recSize < 6) + return S_FALSE; + + CItem item; + + const Byte *r = p + nodeOffset + offs; + UInt32 keyLength = Get16(r); + item.ParentID = Get32(r + 2); + UString name; + if (keyLength < 6 || (keyLength & 1) != 0 || keyLength + 2 > recSize) + return S_FALSE; + r += 6; + recSize -= 6; + keyLength -= 6; + + int nameLength = Get16(r); + if (nameLength * 2 != (int)keyLength) + return S_FALSE; + r += 2; + recSize -= 2; + + wchar_t *pp = name.GetBuffer(nameLength + 1); + + int j; + for (j = 0; j < nameLength; j++) + pp[j] = ((wchar_t)r[j * 2] << 8) | r[j * 2 + 1]; + pp[j] = 0; + name.ReleaseBuffer(); + r += j * 2; + recSize -= j * 2; + + if (recSize < 2) + return S_FALSE; + item.Type = Get16(r); + + if (item.Type != RECORD_TYPE_FOLDER && item.Type != RECORD_TYPE_FILE) + continue; + if (recSize < 0x58) + return S_FALSE; + + // item.Flags = Get16(r + 2); + // item.Valence = Get32(r + 4); + item.ID = Get32(r + 8); + item.CTime = Get32(r + 0xC); + item.MTime = Get32(r + 0x10); + // item.AttrMTime = Get32(r + 0x14); + item.ATime = Get32(r + 0x18); + // item.BackupDate = Get32(r + 0x1C); + + /* + item.OwnerID = Get32(r + 0x20); + item.GroupID = Get32(r + 0x24); + item.AdminFlags = r[0x28]; + item.OwnerFlags = r[0x29]; + item.FileMode = Get16(r + 0x2A); + item.special.iNodeNum = Get16(r + 0x2C); + */ + + item.Name = name; + + if (item.IsDir()) + { + CIdIndexPair pair; + pair.ID = item.ID; + pair.Index = Items.Size(); + IdToIndexMap.Add(pair); + } + else + { + CFork fd; + recSize -= 0x58; + r += 0x58; + if (recSize < 0x50 * 2) + return S_FALSE; + fd.Parse(r); + item.Size = fd.Size; + item.NumBlocks = fd.NumBlocks; + UInt32 curBlock = 0; + for (int j = 0; j < 8; j++) + { + if (curBlock >= fd.NumBlocks) + break; + const CExtent &e = fd.Extents[j]; + item.Extents.Add(e); + curBlock += e.NumBlocks; + } + } + Items.Add(item); + if (progress && Items.Size() % 100 == 0) + { + RINOK(progress->SetCompleted(Items.Size())); + } + } + node = desc.fLink; + } + IdToIndexMap.Sort(CompareIdToIndex, NULL); + return S_OK; +} + +HRESULT CDatabase::Open(IInStream *inStream, CProgressVirt *progress) +{ + static const UInt32 kHeaderSize = 1024 + 512; + Byte buf[kHeaderSize]; + RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize)); + int i; + for (i = 0; i < 1024; i++) + if (buf[i] != 0) + return S_FALSE; + const Byte *p = buf + 1024; + CVolHeader &h = Header; + + h.Header[0] = p[0]; + h.Header[1] = p[1]; + if (p[0] != 'H' || (p[1] != '+' && p[1] != 'X')) + return S_FALSE; + h.Version = Get16(p + 2); + if (h.Version < 4 || h.Version > 5) + return S_FALSE; + + // h.Attr = Get32(p + 4); + // h.LastMountedVersion = Get32(p + 8); + // h.JournalInfoBlock = Get32(p + 0xC); + + h.CTime = Get32(p + 0x10); + h.MTime = Get32(p + 0x14); + // h.BackupTime = Get32(p + 0x18); + // h.CheckedTime = Get32(p + 0x1C); + + // h.NumFiles = Get32(p + 0x20); + // h.NumFolders = Get32(p + 0x24); + + UInt32 numFiles = Get32(p + 0x20); + UInt32 numFolders = Get32(p + 0x24);; + if (progress) + { + RINOK(progress->SetTotal(numFolders + numFiles)); + } + + UInt32 blockSize = Get32(p + 0x28); + + for (i = 9; ((UInt32)1 << i) != blockSize; i++) + if (i == 31) + return S_FALSE; + h.BlockSizeLog = i; + + h.NumBlocks = Get32(p + 0x2C); + h.NumFreeBlocks = Get32(p + 0x30); + + /* + h.WriteCount = Get32(p + 0x44); + for (i = 0; i < 6; i++) + h.FinderInfo[i] = Get32(p + 0x50 + i * 4); + h.VolID = Get64(p + 0x68); + */ + + UInt64 endPos; + RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos)); + if ((endPos >> h.BlockSizeLog) < h.NumBlocks) + return S_FALSE; + + // h.AllocationFile.Parse(p + 0x70 + 0x50 * 0); + h.ExtentsFile.Parse( p + 0x70 + 0x50 * 1); + h.CatalogFile.Parse( p + 0x70 + 0x50 * 2); + // h.AttributesFile.Parse(p + 0x70 + 0x50 * 3); + // h.StartupFile.Parse( p + 0x70 + 0x50 * 4); + + RINOK(LoadExtentFile(inStream)); + RINOK(LoadCatalog(inStream, progress)); + + // if (Header.NumFiles + Header.NumFolders != (UInt32)Items.Size()) return S_OK; + + return S_OK; +} + +}} diff --git a/CPP/7zip/Archive/Hfs/HfsIn.h b/CPP/7zip/Archive/Hfs/HfsIn.h new file mode 100755 index 0000000..c7993e5 --- /dev/null +++ b/CPP/7zip/Archive/Hfs/HfsIn.h @@ -0,0 +1,154 @@ +// HfsIn.h + +#ifndef __ARCHIVE_HFS_IN_H +#define __ARCHIVE_HFS_IN_H + +#include "Common/MyString.h" +#include "Common/Buffer.h" + +namespace NArchive { +namespace NHfs { + +struct CExtent +{ + UInt32 Pos; + UInt32 NumBlocks; +}; + +struct CFork +{ + UInt64 Size; + // UInt32 ClumpSize; + UInt32 NumBlocks; + CExtent Extents[8]; + void Parse(const Byte *p); +}; + +struct CVolHeader +{ + Byte Header[2]; + UInt16 Version; + // UInt32 Attr; + // UInt32 LastMountedVersion; + // UInt32 JournalInfoBlock; + + UInt32 CTime; + UInt32 MTime; + // UInt32 BackupTime; + // UInt32 CheckedTime; + + // UInt32 NumFiles; + // UInt32 NumFolders; + int BlockSizeLog; + UInt32 NumBlocks; + UInt32 NumFreeBlocks; + + // UInt32 WriteCount; + // UInt32 FinderInfo[8]; + // UInt64 VolID; + + // CFork AllocationFile; + CFork ExtentsFile; + CFork CatalogFile; + // CFork AttributesFile; + // CFork StartupFile; + + bool IsHfsX() const { return Version > 4; } +}; + +inline void HfsTimeToFileTime(UInt32 hfsTime, FILETIME &ft) +{ + UInt64 v = ((UInt64)3600 * 24 * (365 * 303 + 24 * 3) + hfsTime) * 10000000; + ft.dwLowDateTime = (DWORD)v; + ft.dwHighDateTime = (DWORD)(v >> 32); +} + +enum ERecordType +{ + RECORD_TYPE_FOLDER = 1, + RECORD_TYPE_FILE = 2, + RECORD_TYPE_FOLDER_THREAD = 3, + RECORD_TYPE_FILE_THREAD = 4 +}; + +struct CItem +{ + UString Name; + + UInt32 ParentID; + + UInt16 Type; + // UInt16 Flags; + // UInt32 Valence; + UInt32 ID; + UInt32 CTime; + UInt32 MTime; + // UInt32 AttrMTime; + UInt32 ATime; + // UInt32 BackupDate; + + /* + UInt32 OwnerID; + UInt32 GroupID; + Byte AdminFlags; + Byte OwnerFlags; + UInt16 FileMode; + union + { + UInt32 iNodeNum; + UInt32 LinkCount; + UInt32 RawDevice; + } special; + */ + + UInt64 Size; + UInt32 NumBlocks; + CRecordVector Extents; + + bool IsDir() const { return Type == RECORD_TYPE_FOLDER; } + CItem(): Size(0), NumBlocks(0) {} +}; + +struct CIdIndexPair +{ + UInt32 ID; + int Index; +}; + +struct CProgressVirt +{ + virtual HRESULT SetTotal(UInt64 numFiles) PURE; + virtual HRESULT SetCompleted(UInt64 numFiles) PURE; +}; + +class CDatabase +{ + // CObjectVector FileExtents; + // CObjectVector ResExtents; + CRecordVector IdToIndexMap; + + HRESULT LoadExtentFile(IInStream *inStream); + HRESULT LoadCatalog(IInStream *inStream, CProgressVirt *progress); + + HRESULT ReadFile(const CFork &fork, CByteBuffer &buf, IInStream *inStream); +public: + CVolHeader Header; + CObjectVector Items; + // bool CaseSensetive; + + void Clear() + { + // CaseSensetive = false; + Items.Clear(); + // FileExtents.Clear(); + // ResExtents.Clear(); + IdToIndexMap.Clear(); + } + + UString GetItemPath(int index) const; + HRESULT Open(IInStream *inStream, CProgressVirt *progress); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Hfs/HfsRegister.cpp b/CPP/7zip/Archive/Hfs/HfsRegister.cpp new file mode 100755 index 0000000..d877f9e --- /dev/null +++ b/CPP/7zip/Archive/Hfs/HfsRegister.cpp @@ -0,0 +1,13 @@ +// HfsRegister.cpp + +#include "StdAfx.h" + +#include "../../Common/RegisterArc.h" + +#include "HfsHandler.h" +static IInArchive *CreateArc() { return new NArchive::NHfs::CHandler; } + +static CArcInfo g_ArcInfo = + { L"HFS", L"hfs", 0, 0xE3, { 'H', '+', 0, 4 }, 4, false, CreateArc, 0 }; + +REGISTER_ARC(Hfs) diff --git a/CPP/7zip/Archive/IArchive.h b/CPP/7zip/Archive/IArchive.h new file mode 100755 index 0000000..e4101cc --- /dev/null +++ b/CPP/7zip/Archive/IArchive.h @@ -0,0 +1,234 @@ +// 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 NArchive +{ + enum + { + kName = 0, + kClassID, + kExtension, + kAddExtension, + kUpdate, + kKeepName, + kStartSignature, + kFinishSignature, + kAssociate + }; + + namespace NExtract + { + namespace NAskMode + { + enum + { + kExtract = 0, + kTest, + kSkip + }; + } + namespace NOperationResult + { + enum + { + kOK = 0, + kUnSupportedMethod, + kDataError, + kCRCError + }; + } + } + 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); +}; + + +#define INTERFACE_IArchiveExtractCallback(x) \ + INTERFACE_IProgress(x) \ + STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) x; \ + STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \ + STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) x; \ + +ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20) +{ + INTERFACE_IArchiveExtractCallback(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::Extract: + indices must be sorted + numItems = 0xFFFFFFFF means "all files" + testMode != 0 means "test files without writing to outStream" +*/ + +#define INTERFACE_IInArchive(x) \ + STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) x; \ + STDMETHOD(Close)() x; \ + STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \ + STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \ + STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) x; \ + STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) x; \ + STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \ + STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \ + STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties) x; \ + STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; + +ARCHIVE_INTERFACE(IInArchive, 0x60) +{ + INTERFACE_IInArchive(PURE) +}; + +ARCHIVE_INTERFACE(IArchiveOpenSeq, 0x61) +{ + STDMETHOD(OpenSeq)(ISequentialInStream *stream) PURE; +}; + +#define INTERFACE_IArchiveUpdateCallback(x) \ + INTERFACE_IProgress(x); \ + STDMETHOD(GetUpdateItemInfo)(UInt32 index, \ + Int32 *newData, /*1 - new data, 0 - old data */ \ + Int32 *newProperties, /* 1 - new properties, 0 - old properties */ \ + UInt32 *indexInArchive /* -1 if there is no in archive, or if doesn't matter */ \ + ) 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); +}; + + +#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) +}; + + +ARCHIVE_INTERFACE(ISetProperties, 0x03) +{ + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) PURE; +}; + + +#define IMP_IInArchive_GetProp(k) \ + (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ + { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ + const STATPROPSTG &srcItem = k[index]; \ + *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } \ + +#define IMP_IInArchive_GetProp_WITH_NAME(k) \ + (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ + { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ + const STATPROPSTG &srcItem = k[index]; \ + *propID = srcItem.propid; *varType = srcItem.vt; \ + if (srcItem.lpwstrName == 0) *name = 0; else *name = ::SysAllocString(srcItem.lpwstrName); return S_OK; } \ + +#define IMP_IInArchive_Props \ + STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \ + { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ + STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp(kProps) + +#define IMP_IInArchive_Props_WITH_NAME \ + STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \ + { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ + STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kProps) + + +#define IMP_IInArchive_ArcProps \ + STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ + { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \ + STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp(kArcProps) + +#define IMP_IInArchive_ArcProps_WITH_NAME \ + STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ + { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \ + STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kArcProps) + +#define IMP_IInArchive_ArcProps_NO_Table \ + STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ + { *numProperties = 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; } + +#endif diff --git a/CPP/7zip/Archive/Icons/7z.ico b/CPP/7zip/Archive/Icons/7z.ico new file mode 100755 index 0000000000000000000000000000000000000000..319753a1772db054fd0c04de24a105769a5a0da2 GIT binary patch literal 4710 zcmeH~ziT5$6vv-)3K$_0yK&`0adqw%rZQ=aS<;!i#@D(V@*fyO2wS-h1PtR!MG}%C z5PW4CfgwdawcVWIz{Ld($hIOI5;>sI5-$3 zI5;>sI5;>sI2cVhI5;>sI5;>s7sI5;@Cgbf}J9!`0rWEH@|sGmTKH0*lG zaPcJfB=UfIxL6r*dL|w&9xhfEczAetczAetcvz|6;o;!n;NhU9^YHL+@NkIaO7vDj z^5hS?l~=0+D{=>-tkmQVa0(<1BnWT{2DNN`ASh;RUgMm!u6 z91)rtrEG6+%g)Y@?CtHz{{Frk zA0Nx%;h~(Kp32$TnVg@W%f-coTwPts_4Tz}{+i^A!GPa!MRoNzpaXcODXywXy8pGX zf!rhAV)tHIDbm3}Ke?-?W;&qX#XqQh8j~G5VTPz5yM?H?S)aYx-x#NG6o>^iz9E=J zK@^8hXXekbwcA3ov(BFv>yqrNA$0km#WzeWHJAoZtj|juBx3YSYu78heYDHT2x$Ec z0{i@wSp8by!ITrF^=H^lho@>Rll}~HpI@nEKfs1DYyDgM55~ZjU>1H#IfMGAWz63K z@ZWem)sM?WXWinLrg}OSxBT6xIpP;o{fkUh-?dZrKO6y8a^qG%82l!tQ) zXNiY%%8hdao9I#f{g>j~>0r0kC*E%6ABB z3s*-+if>*3I8AIqjEYvv0!q2BA{#v$rMQ?&zs8gMz0^>0xXqMEa16}bskLTiu_Q5 R(A?DK`tq{2um0t8*YEBV)$afR literal 0 HcmV?d00001 diff --git a/CPP/7zip/Archive/Icons/arj.ico b/CPP/7zip/Archive/Icons/arj.ico new file mode 100755 index 0000000000000000000000000000000000000000..c0f8b14189c62734cc4b5f14d32a7614a3011ca6 GIT binary patch literal 3638 zcmeH}F>4e-6vtmQLRhXaO{x?zg_v$(s&tY*V3RuC;5P^Xi>*=%LSRx|p`wLNKEXl2 z!VH#4V?anD1i_?{fD6yxd$X6loEj^!$=uEC%>T{2_q(@yvm-JicVuZvyu6tcc}Va6 z{W5-fPvj%oBZf=V$J7}?pft07`AyScL~fdLp`|OM(MU$0Msoh)wam`W%G}(X3zz|>vFa#Ka zqQMd12*#o689?D`pG3`6boW#nS>ugd@Tc;fQc}s^Ew) zL>M9rmbwT>gdxI^iKVojLgJJUV^6PT2P$GGW_hZKonT4?O$10VC1NLx2`7oziP(NS zJT^M<6Y&%A?G`2CCvuZuNH8SwV7HB|_^(IdN^7@~9Ax5U*fJcMcz$b*gB)ZyvT^Xk z{C2Y_!;)diKx6{?BLGWgVP;ZB$guFG;)i>ZVab*cXR)Wj?gAPN3WLI+FenTPgFj9% zWEd0%g(1U$8!Gc*P#6>jg#p)8bQlx{g+T#O;%A&G3zbO`ACYl{L*2K{iSj^R$>!#! zY;A4H&d!eP?(WLr;i2sB@5}M=v7DTo$m!{+oSmJ?#l?kOUS7)i50#h0A^+os?Am|8 zF8K42`L&@+^}h=n$PJ~cw{I-VweAh=Q<|>p(jM(L_F-qUImKWddK9yx`xLW|*B5KC zkHu?#%n=JZ|L(yRb7FpItmpPJw=?_HV(j9V#kQo_Iv2Kl*!y>%D4jE#Jh8qk9eZMq zeX0F=bMGH(N-!q$_OXX{s(Ai-$HOUe+uMuVw&kh1D(!^5IJwDgXl5^SO0W0dum8Kf zP@1Qy^?SayxQ6l|NFdq-AqSIhX772=7xTK1#(8h|Zf9m^zMH$-Tag)gAWKW)@@`J#DQAx# zm+|vQBA?McW4J_Hqs<5kq@MM|9bJtPbzPSOJ*P4p4rTadD3_n!%Ixf{%+1Y7uh*0L z`FUAbSdhiVMOj{6mX(zi+1lEYjg1XiUtgEi)m5oqsBCVkypj{q?^!;c{E(Ax-{j@{ z4p0@Bl?IwqL1ipT0)=DCk6?9LeD`m`iwrK&nPl_Wvq-f zd*(nN$R7w4m=r|C)6)eQ0t^9$0D~jJ5MT%}1Q-GgjtN76A;1t|2rxK03;~7!Lx3T` z5ELC80ghlCs$Ky!9PO8AnTFmj8J0-$NTNv42#c2iW8@^l5@GSOz!Bkya6~vF99}9o zA`B6R2!oX_!VzJJFl2Hmy_b+Y<;U2|Yt?~@+zBr)HMtW^iKK}H38qBugfS5$kvoyw zZ-?hbPyR&yM1H$PiTsJ$Bp4D5i8|PAqbh#&XgJc_ZKMX7d>OV3M<$=&TH~Mw8IEim zT$tZ(CS_PMEE$MQLVpBc$xO^RWfU0}{xsrnPckgo>ftQ*G}v802ZO?(FenTPgTmmC z6AT#!g+XD+Fc5}@KMV?k!k{n^nuZ<*g+XCZ0F?ZhV9G?rDH0esdJs9vF*HqWu z0Xq=SM;6zHD%JlM7LX}Y^>?Sra$gSy_A6a`>Z$|!UF?I_WNAE6X9nCM+ zVjn4Q#j!w4XybbX*H{pXLuY4hFTSnWU5l~JUnbj>VrxU#^g$QjW1?w;ne*8EGIbOQ zAN$j~`4--P)|F&9boNn%Wm-AFTLFF~f+4bALr4x-#Wzr-k> zUH&fq6#GG$Wq{M>J3*V@d^`DL{>0-sX|MV}N7b`qzu3F@RW*JE{hrx7X&PS7&Y|C{ z?yy(=k@PC;w`KD6zHPl7&GNEZ%&f|@-F zj;v{Zpy%{{pTakZPZaHbpK`xXVJ~sNPnp;^u!tVD-#`Cs+L+b2RUPcM4z!6o6lX3&wazmP{Gk45ir)G-WH<16eX>6a5FF(7{vYLLs0`9@^3lUGfVI zh7OJBm@EwxG6X`Q@lp&us($b3Y+vjoTj*lhPba-6z4zVIolYW4vMimBSozo#c}8nx zCHG%G5&4GhIo%HO0$CCiS{nH>Uw1|LOShXZ)HJ2v?@RxCUv9pBkVc~+&1O^D?Y6A0 zuFBflnyjy{%f`lrY;JDK-rk<Sqxa}NdXHYG1@r-ZpcBvs^jsvOkLV-%h$5m-^b`FQ zEwZC_#CJGyOmdRM!c#dI91IQy2ZJHO;9zhtI2arZh6#g%!NK5Qa4;A;3=RedgM-1r z;1W7G92`zLQnC!7;i|uYL+$l)x-`k1%d_w1egM`1IB=pKJf- z{{Frk9305u;h`KI9m(nGshpgg$ocuXTwGkp<>jSZUth~`IF!+7BsYJOyzBLNkGo`7 z-vPbg&wA=tyGdIAyRd;gP+G;S2g^p0j(hscRn;`rG4(6#y~?IzvOycPC~8MEW6Ifzx{a5@wbZKcH>oLc5YjX-CwI!&v23LlaOV}>p2}zwC}RFig9VT zvgcYo^Lp1Txj6|{HP|hd*diXKbn)6pejqo?>_30=IYo~y9b|G&xtE~J8HIuDX?CHe zxj3irP2v-UEY2y5a|&mP#W`i>+`uL}uajY~QZ&Ac1&I5OOg2X7-)$?u>RJjr(r)$IR@^_x8Qpw<2@$NLE(F%lmneXY>{p z%J{_-kuT_;Gh9K|kvTy@saoFrrK&KZuBy^d)0M$sAcL<1x%&K0TCJAM&(BMz(~-r+ zMOj)}lI7)P>2|xay1FXc+uO3axhWeP8?v^xCe=%otu2+;aw_^G%cs+ya{B$dy!!Bw zL;;CNLUI`fbOBvJ7fh$cC8Ce$Bl?IwqPJ-YeL|lYB=iYAjb!v0eMX;AWc12d8Ef{; zfjW>s5GXJyh>EAD3NQp10t^8LM}i^15MT%}1Q;9>h5$o=A;1t|aC8^~3;~7!Lx3SD zIyeFx!8lZX1<=sim5_{}w_AoKl01?q5;Vf%%YZS`iLgXid|BX#a6~vF91#v*DmWqx z5rznZEnS2o!VqD|gN6L1D-+5C*{?28BUkP#6e}poc+WP#6>dC4VNEGEs4g#E6U|9O|*nC(2WKD?2+o zvb(!0`}_NHaBv_eCns`rbR=hIXL5diE*BRUa(Q_v!{Jb_udn6mx5}G-pZ{^i>e_$6 z8shoL;@VK9{l5zv$UUXq+q<`PdwSTnt5kK@Rfp7j*!#83e2T$3^eARW?=EH?&o9JT=)-^BNrXzF0*JTbpa9Y?~) zen>Ol!uw@aNrppXA4eF?6koq4aDT=;YV0NKXvAA}Q$`c^5@c*I?X=y{?z3A2v%_HG zy(a%nd^cHTUNiPXSHf4?TXu`jZ_<8qGv2vnpLsoJ?d{&L0#@pt+w00wwcC?~y$&X{ z&HeHBY#e%>w%MCv^KlrLP8<7lnf-fDTc@L0Ty~2&wupaHDxwaMZ)CW7?Awu_Q|#!n zf{f28>vs}VoKbLOPxFSF?!!5SZxWv<&E2gxDQSWheH6jkVp7Zy-X7t*iq9VXUr5LQ={GGuC$f5 zW{(^w1Mvewfk8o3JUm5!A;1t|2rxJj3;~7!Lx3T`;FvH37y=9dh5&=3!w_HyFa#I^ z3_-EM5#R{Mq3Sb$g}YseoXObjkzt7hj|7T{Mp%3ra7HQ-mI#Ya3mg%S2uFk?!r@Z| zM}#555Mi*Xi*Q63A`F>WO6gNboO03j>9yH`ir9%>KGnodFeQQ}0wkCcu@laONFsJ3 zw!aRKjh*<3_=))TiW2b?bCY05FeK)|UK_LGPmhH=rM*VxAQLacmf^_6^H*ye%t3}D z8wU^OubV*`mJCYa;Fk~2zA=4iQg+XCZ7?37ohe2Ub7!&{{enw0gsC0^GMA{J!b#3bt<*B@t zot+)o-QAV_{e3w&IFRGxV>voHlGD>uIXgR(^Ye4Lyu6gbU?A7m*K+ksLWz@5BOfPil4c?oBHlJ?z?5in{8iL&`n;-P&h;io+_@Nan}xUCcWg zU%bUXGTzWJAqLd?uHY6EF&zr4xxe(S-QKl0>-c4`4Jp1_!iIMneb>ZNi&^K1@nz^p zi9YrtH{(s-FDptgIyC-~!f-12{58VeDfh7P7un&EuWFoz6aFG{pWo2TU&lb@_VKP! z7ft*|{~rHg(Rb;;)E_^LSN<43^?8o`&H#U_^K&$NcJCBFPgtw9T9Z%EY1fWADB~wP zblR<3{H@L?wOjaars==;P47)L3(9IS!xHgNQiW=d{EY}#k9|4vbBY~ZmdT@Y%KDuI z6=xJWvZncslIp`bg*}Naiu`a+c{rzVmUuX)Or0B8MEmvr=i8>WS&eJc;a=UI*xlUU z9dBmCaoZM9Hm0Uc6a5cDpu3x$9@d1y;Jbje>} zFmz}{$7E@skRcEXjh7OrLH*v-*=M_np+o6n+0yC#(0iZXoplmfkw?;MiM982k!Q?S zSF`-$iO3gp&k$0)2A?k2&0t^9$Kpph9Q5F03Xt*-!ZKMW~d=a(?MU`R07 z;{-#5A;FMfh%gX_jz0_uh6F=`fzWjHFeDff3<-cl{z$OI!i1A2hDY{rB#W&+UY^QZ zIXF0w!^1;4K0cO{lM^{RJCoDXQ@Oafkju+Uxw^WNo0}UM4u^7gcPF>MlDz5l_#YQk zSN{WgA)ZMZSH&ca|J~R?7PLm^Xklx2Qn#m{Jd{&Ybs3Ma_ez`kWP?ta(bSIKT+}*V zpRL(GR?fuHKrATZTLjZ+5RJp2GqY#k(rm8TSmw`*bxF3BA#{1Kif=K|l)=<_YJFZh zj)aeX>D77-Zyz0UG8`)VIKpVIS^cWOy*cx!vgfd)5l_{mji&55$RfLXP^EYPZhkHMTz88>c(sL#@Ej Ir;q5r0p2+il>h($ literal 0 HcmV?d00001 diff --git a/CPP/7zip/Archive/Icons/fat.ico b/CPP/7zip/Archive/Icons/fat.ico new file mode 100755 index 0000000000000000000000000000000000000000..882753acd48c09f1db5e9d663d5dd47990d88cd1 GIT binary patch literal 3638 zcmeH}v1%JZ5J1O90U=b_jVl+5ix78$t=t*+1~;zVE%^fzNO6_xK)|rBR3srO()bGm zffVtQ(r#i1xGTi zuCB`3+M2Adugk{9hHP$b%KrYo?C$Q$&d!c(ZEZ>MEXm$pk{5C=>1&h^=ilV~`dXg9 zeMcgPcqAY(4;?y(&Y^RvOWDPv_vk%(kKUu#X#sse9~cDm0X-*)=p*`wKB9=|6XV1< zMa%5y9r+!B9Fv?RvGjBf1_y(K!NFiiFgO?-3=RedgJHtpU~n)v7#s|S4ugZi!QfzU zFt~&c4hM%*j+CqdXgKQ;kcgnyTZYAx+>^)?)Wc$B!05T~uy|OkEO2-@JRBYl4~LZs z4iAHe!NZ`X^Kf_=JPeUsiQY;`o_sL2@@jRUB6q;cN=@znQy^&|L4YZcJ75e13FHps zw#Q+)(UU)rKagJ^Q6PVyHUWkJL!b`&*r;5d2|CFeDff41`9|!;oM|FeCsH`6Iy+6BACJ7@o0*BUxC>xT2{Yy}78h znxC!NUMZ*IXdot(@hyUBG>FEb(<`%Q-_mTZ*;wY!lXXhAl_7L`ZxY{PqA7!^b8UW} zT1CP~f5>FMhUXZ~HmlD#d2iM{s_Z4(Xv9l1X``Cm80Oe5Lbi{+>hq0ouAK;fYv(?c zayou({-5mSE$aNKR)w9|r(e&?u64v`G-`Ff+l`mq@Ag)`!rg2ir(}Ms=Fn~5Wp8z> z)^2IusW$WXp0ep+oT|KFwOC?__$RF(Y9IN6+%B{J{LK3l-MVy;YM-)wFG0Z`1xMC2 zJJEBw*r)JK;uD1|_9=^f3VVsgK4oU#z#{tIzJK}+6~%5P(M)2h2l|xN+sery|6iU@LcrQybE_cDLL=FoqPba(xgmtg2Te;jXyG zzd&F}5ieKT%^40137CVkn_!4w?wi^7Buh@*g*0Ai_wCH=%zT>nv~NXv@{_Eui?`pG zMV>Kx`n1TuJ{I{4-E+is`Y-gJps==7E_cUTgs;?fxiB)7@pvrbzsGX*;hiikEy?oo zvh@3XSy@?;)zwv5TU(RCU?3YC8?v*rBiq~CvbD7(o12?bzfyVmQsuRrivFAB{po*l z`stJW_Q#(j3iL=%^jyS%E}#qOg6Xs@iRdHxh(4l^=*=ymPv{duLZ8rck&Hg0&*(FX zj9!ryS+i#jjDh@tKmn&9DxRJpzz|>vFa#JJ35EbefFZyTU~o(r0t^9$07HPm(P0QM z1Q-Gg0fwOH;0SO8<52Yqpy6ttM9*~e_LE_WB#$JD1dXtG88AjB5tayxmj#XpM}#B7 z5#jJs!4YAIFhm%vbPquoYokja-}%W!1!`K>h$ zYLMZ`#=#Hs+l^C(CBu?|$RzYf0G5nnW>H3wVc|^@#bL0S+soS4>`RNW&0n0&rP$gK=HATWdrUNKFk5`f zzqodhSYu!M%-_QM$A*%O1v7gWVY1M?ezU;Mf_XBtm#~uwPt~+dZrMwa`|O71_L77s zU-$1AzHK)Ei*(0-RJ3NH-L-rEvZk|7e~eE$|Dq-S!s9vhHFx4y!_Qsy>^d}UNnR#Z zHLD=zzT2lM@xQ%b*ss1~uZCUgSJ>y<;@^ATIv>r_vRm}nBECzji8`kLLx!tIz8(2F z#f~oP^yxX}n*=py6c)0l`Gt|`!#Ra_60a!w!#U;QoWfb+;heH?ZeSBVZr^|Y+BBKn zxK)kzTlv=8&Fzit(cUIAnH`iJd@B1kJ}27(?AB~$>+kQ0nOqI8kB>dR?a0bLZ<}~o yjEC*}G_#ea`lL}k?bW@HJ?S+gdLzA2BQhF^><>hc#bmo;XI^6)BTwYTqyGW?)+1;D literal 0 HcmV?d00001 diff --git a/CPP/7zip/Archive/Icons/hfs.ico b/CPP/7zip/Archive/Icons/hfs.ico new file mode 100755 index 0000000000000000000000000000000000000000..92a46b8135154d1a42d20b7214434c1561b8e01f GIT binary patch literal 3638 zcmeH}F-sgl6o8*%;5e?(#>&E65n{J6m0hqGY^?2u`~wkEY-Jq?2xE0c5|Sc~zu+K{ zA`U6Fi4d?5BoMC&LY7Rv_h!#s@AR4w(l~c-cILgA_r86zJ3AtCGB2yEV&z>&1oNT<`0Uau!h zOG~o6yeum#E7I@xWo>Ouwzs!sb8}NRHa28^eO<~INw&6(DuL4xLk7%0oPQkKUvA=skL!7SIRuflfdl&~uT9KBAB4BZ`PV(NFYK zw8)Oy5#Qm+G09013s2=>a4y&C6JQ811oEKEMpo?Z(Qu{KWh4iYcoDV;MjI;A`>HnB8mtLe*{0QNrWY8K8!`523-YoFeDff3<-t=LxRB` zCm13O35EnigaJ1Q<6%fJBp4D5xJJ;!kYGqKBmffeBhC^N6N5ZHJbe#GGT%DJ%VT*X zJ3BkFySpp<`}=Zma3IIW$8vOZB&VmRa&~qm=jZ2gd3h@oD{uKxM@*>wn+MaV6ZJ!-Ewksbwb_PdV;w(F)+yOmyU^)_#=rSQQ#;eat@(NC z*b`&)k2LeuJ-=$QSblDT4<^mk*j}?$6%S2Qs+QdtX4uVx+1pjyzwzPxK06-TCL7tF z-`MRo{=(is6f|39I{xj)bIRT=e%g)K)wI3azJtQ-O}wh&^=t+dy}Rt)VqALNsr8$9 zy{GI=tlVO^m}86hC#A&e5c!5&&9ndf&gT?8x~wAObIP-O2};f=3}jEU3pLG$a|+)i zK2gZSIpyJ;!dc?soHB84U=#gl-#`5Z^4ZotJ94eM>9=-Avo{~RYTVZi7@5&mCu*nU pv3b0HCtCe(F}h`ks3=3` literal 0 HcmV?d00001 diff --git a/CPP/7zip/Archive/Icons/iso.ico b/CPP/7zip/Archive/Icons/iso.ico new file mode 100755 index 0000000000000000000000000000000000000000..2538e40894a2aa25932aae7b070b9ec365d3a4a7 GIT binary patch literal 3638 zcmeH}u}d9G6o-$A0a+L0*Z3D) z5K_b;r8W@)76A!Fn}_fgPQG(y*S+4TsUB&ZduL|ncV^D{?%BPwBQhgTWNAsfyq^$-HbT*`PnmhtDYTz>pZW@l$*Zf;Hn zgMrM?&&$HXf-EjB%JTBEtgNia*4CD6Y;4H-`ns&Hu1ftzWph*Iot%h%%ktsmyPSOe zDsTV(hd_ZEsfn7)FrWprfEG;CG9{u%^oSnOBf2e1=m|YBNazWjPBMB%&*&K;qbp-& ztl1+6+Ccn(qrjpdDjuFDzz|>vFa#JJ35EbefFZyTU~o(r0t^9$07HPm(P0QM1Q-Gg z0fwMxa0EDlaj1F*Q0VQGsF{jxKN*%t@JOJD(+G>F0b}GM!V+Qew7?PJh;T$WA{?G7 zI3f%Yh6sbDF2WIEh%jVgDXpiFIOW6G(`(s*ir9%+o@!zzm=Zw~0TN7!*a>68Ng{S4 zw%-nqjZXYT{6u`aMTz){+$0zh42eA0Z6hoG>rv=w?KYBwOuP(Rh9eWtZ>@2VgA7MD z4t|*5ZWd)&GAtR0OhA7GV96}ZOv(ru7QR&ca8EKU+4A8m_B7aCK!ZVHP#6>jg+XEP z#|efEgTkONWEgNmWj+iFgTkON;F^jKgTkONC;&?Qj5B4SGAZICGLCSl`?fhzUdW%a zy}d0vJ3F$sw{3A1up5Js8=iH0`BJ2eiA`N3G4~6oXxGMKL?NPcdt^ zzF3RB6L0x3M=WUly9ZayiTRif!&7xrnhASx@{rxoiru1^ll#{H z%FaS(_-XyYjp1&48-H@WPrPYy$jbg{5|^# z!$Eb2y&869P+`AarvKizt+%~dRCbFQwut|w)Oa0JzYyW_sc%PqPO+oQ616+0tldjc zb4FnzdzyE&Tt1#tcqj3SqCTEe9?vP9B_7WyQ|AUY(WCbL=dVp0vm3Y4!EQUAc)PiM zbn`N6`Y}5wFQ$I1HtCM>5yjURyT2#;aW%X;I&%NT9|RP)+cs?bKBeES%Xy8h&-TX2 N%J9BYV;EB#>JK}~6Q=+G literal 0 HcmV?d00001 diff --git a/CPP/7zip/Archive/Icons/lzh.ico b/CPP/7zip/Archive/Icons/lzh.ico new file mode 100755 index 0000000000000000000000000000000000000000..84dab49c3bd019b0502cabeb61fdfe942d81fa1b GIT binary patch literal 3638 zcmeH}ziS&Y6vtoM6wKivSu$mCJ(OlMXv!9{2eM?&Ci)+QK!=+$7YYG+^3axc=#sy{ z5a`f|j>*zMAwwY)8ZRZ#1NHNs&OXQa(W!K?Z0V%;r0@Iq-B~A*1$iW$j#zo$5_v{% zX(^9iJQ4YV?K#5^b%VMf7%1hUUG8W~oS4fpUufyda5$9V*P&c}ekY5Ii_&Vfq}^`I z^768*tgOiD>Z)|RU0GXOlbxL%+1lEY&CN|&UtgEdfB(LRE(vK*gPJhbj_wVxR z!$$%+s;35O%tMFGVRP7=+ESk4v3u+uyT|Ua>#~47U=Iue_JEy>MC=iJ#2zt3?1^z= zoT5c`w2t@=A;%&oNh~~#gTcYzU~n)P5)2Lo2ZMvb!C;s$I2arZ4h9E#$)n*JdpMG5>l`mn z<*n@Q?#kZYo*Wz;$l>9koSdA<(b18dot??~`MF$NT*&3+rHn=+xxT)ZtKUi93NZcIZ*mkKLxI zcf3A(vwv*7p`$`9sP#?3EGnWpG}<$No?E+ZYIfG~^I~0+eYJ!xA2j-=iKQ0P$y4j| z(yOtJhm!h;!i)%de)Rq<3!N;T!rA`kf$&HOnCD)+4a zyT2y5wZ32L-{&94pYqq;iG|MON1#9Rc+Tn9u#uUo;uS-JVEWysF~w*-YrQ zi#z;9Z(Q01{+ng??|svIQ%ys%TP(0e{F73mI;4Ih!qsEjj_jPGN0$zDd`{W8m!RZ~ z!bJ8oyU@~|pHp}z@rt6(&nfeB3TKJ=Ic4VDz$SWJzyIvDsbhBI+SK2#$5U@N^A9F3 zv#J@hgYpKL8tb-s$M~3{>rJD6Pc-AAH#$C^(uaUzb4@Sr+s$sB&ueUbx;IW&hWC{c J$BEBbi`S`mmE-uQ_(vplu zBUxElk=4~zSzB9^jg1Z2+}xDi-Cfz)*^%w-ZQ0t|lKPFx>(?s3%DL#jSw5WqC+D9& z$=g5vq)?zodZOnd26O>kKo?A>#U-MT=p*`wKBBjf~a_Th5$o=A;1t|a3mN43;~7!Lx90CVF)k;7y=9d21kb>zz|>v zFa#KaqJtyA5sX9CX8;XnI}$z9(c3M<5-A=j6iFIk@oB&qxrnetSbSRGh;T$WA{-G8 zpDH*a3=xJ1gH2t8Bf=12$kb9spF--C1KFq7W(O*2C%k;Bshwa-6ipOJFePdyjEN+P z+KJl!IJ`D`>L=f0kq)KAP!f+4|>m=^0&d$!{t-lL`Oh zn%TAgfSt(alI1l~rTX5D1>}iVjSrq|8)H45*inY|(pATd2iPaA&3uZ%F1VtZ9lg7l zwTmy-V(*mq@>n7Q+WeluHI~HkFxZvbi*IXo*J5nzmtYGiwl;-@Px}0x6HS}UoConG zw9AB#{pfwXrT4>zQVfUQ-eqX!n$KUKcrs^hdV5LRG`v-Jtr^%$lBev3X7JnvK3OFZvW=JpM&vZw9$&p(?cvl_Rm@HW9@|4x`(;;ZrO^pyN&Hx~$Kt>m(;-2G}@_G>JC Qwl)qs;$yAGFr_#2uhlsdi~s-t literal 0 HcmV?d00001 diff --git a/CPP/7zip/Archive/Icons/ntfs.ico b/CPP/7zip/Archive/Icons/ntfs.ico new file mode 100755 index 0000000000000000000000000000000000000000..6b2aeb00ae7aa90e3c1ab94149ee1d0b9bdf8a03 GIT binary patch literal 3638 zcmeH}F-u%Q5XVO`AjcKjSXmg05W9n|?8IKMv9??C4J44_Rn~!kuvS+jAt}=M2@Zr5 zaY?C7gn)%0fp|?2a%A$G+4sEXq1S~p?%nR&{m;(K@9n$Ww<0q#D=RDF<-@$lGkOaP zW&Gla$XB%I3|FWd)EPmbRC9j0r>QU^S5>*t(v`trAcJoMx&HEA=H}*PeturM-L5Py zF3QrvFa$+| zBft@iL)BLRg{yrMHB-^;mSKq`k0go&jj;GKV2pGkED;u87C0gt5snB)gu|B#jtE19 zA;Mrw7vYF7L>Mx;l-8G!JmtgKm)BMYDsm@g`BIZR!IVgvNRVJkJFK_*{@EyIz?=a1GnSc42lHV$sg zA2&`JmJCYx6b6MsVIVXW9R`I#VNd{+{Fz{iqcSNHBQlO~sK>TBQJ%^>+1=fh zy}doz-`|&mg9AA^Igz8IBRM-elk@X)xwyEHtE(#+4u^7cb0gQkRo?dd{EsVE*Zu=` zA)b#ct_@W>|GTh(Oevk-%c*6xr-yy}l&0>wbV&OWd%w2XoMNyJJ&M`UeTrEd|6(on zM!XZp0^v}{_Xw_75Q{@&J-3&+wb`c@W1YV^n@h3PAR>jx zb?k59`HUuuug`7r{-k--*lV`Yh#$?kj9PYQm}2(`ZZDIpZTmanR67yIc1S1v+jhH= zDR#flhwbLv_>b?Fo{2QY=Kgnoo{hbpIvRC)zx>AQrnXzm5~I^;uW--pW-SH(_Jm&d zK6|Ivly1lGtKCfez1t@5H<_9%yTuG!#6Kw&Q3urT)azOHpFicCVn>%1YI9E6c#xpt zjKW0rG{4Z&eLSb|PU00seLSZ;o>MqWJf2e~&JAp$$Nv7acOb8A8?z(V((SmlJG$LA z`%*^D*!O=n@7CBi^6{8Ahue>jkFDb$=G%M1#;z&vg<);CIgD)=r_4z!6o6lX3&wazmP{F352e`-G-WH<16eX>6a5Dv(7{vYLLs0`9@^3lUGfVI zfewx6m@EwxG6X`Q@lp&us($b3?7O;6I+ZS#{dCfMPw#yv-RUH&v zR&xL81CfvD9@Fh1Pmm=+p{12Czt;m1{xTTk3pGs{jYcy1G?Lp7ucg&$NxR*aZnrC| ztE;lMwkGTA>(cM{Wn*JQc6WDWdwW~9wzgz*b5jP-lI-jxc_HVLzC?L{{#DMeujTpM zcO-I%M*3%>F~~_0OHbusa4p3lmz@iSki_-2W#s$tilW!dR8@1QVyGaavI z?ND_8WbYKy((PE{W;OSEH%->AbLAGh#S&Y@KPdyEj*!pD?K1n%k9jecgbOd-?>yr8uQz-|Vl)m`1--j4ONgho~s9SB38arNNWWYixbGH#UXtU1fk_ HgiMg18XzXJ literal 0 HcmV?d00001 diff --git a/CPP/7zip/Archive/Icons/rpm.ico b/CPP/7zip/Archive/Icons/rpm.ico new file mode 100755 index 0000000000000000000000000000000000000000..cdeb8d1b47aeb82163934b78620b5f49a2c8269d GIT binary patch literal 3638 zcmeH}u}dUL6o;RC9!N96niv_l2FsZ>RAjc83ns>9#r_8(T+os6!h%pn6Wkql!6p6$ z1HuJsv7sg_EEp`v!fA2{*YNgxueztlK~0Y35^JWatA4NQy>DLkRF}wtypXju@$&nU z$ZL8pUzYLPA4NW*{lsvM`i8n72$W{gFAp>gM&za`7h1Y9nM`EzX(Bftev`$;MOj)} zlF?`+%gf8Mva%wptE;lUzAhUZ8?w8*E8E-KvbD7(o12@`{H(IGqw-$PMZaeG>-=vy z|MErN{qZM(0yR<-HJ4#P3upl?n5Jb)M33kZJ)%c+Tb9rhdSZ~!6FL{k=ovkuXM~Kd zjFquwj~r+N@dJ(mi-M?lc$xr1fFZyTU~nWD0t^9$07HPmF<}TW1Q-Gg0R~5hA;1t| z2rvW~f}+6@;0VT{>KQ=cYM(^SRCN2vutb7K0!5rgSUe3FBb^9KgvHYWM}#B75#fk% zc&gxtFhm$443@eGM}#55kcp+Vo=)*gmD{x-K2l9$+7LHk(rn)}co+JGxIX zYrno&i@g```7uW<=={3}SImj|p|PIZ%iPZFQ;V^SUl!YvV(VPk^6}u`eWG;EZ1T+d zvb6Wa9Q#s-_2%9`)|6mO80@`=cCL8-2FK$$b353J+qUJYnwECPUYtB-H#F?iuhJd- zPuKq!`>`*k!L@gv@^2{h^tY7GG`MxlKKFRe+pGGYK6`ep-A>cTuc}#sdSs@dv@L(n zVM0Bs9 zw~wcraodl5*Jt;BbnIKZ*{zh>!+T;FSM}}bDgMi=K-uSQ6CdK0eS6rg%Xy8h&-TXI N%J8w$V3<%_>Nl*26D9xv literal 0 HcmV?d00001 diff --git a/CPP/7zip/Archive/Icons/split.ico b/CPP/7zip/Archive/Icons/split.ico new file mode 100755 index 0000000000000000000000000000000000000000..79cb089bac9b1a6ef30c1f09383a1c7faa111539 GIT binary patch literal 3638 zcmeH}ze^lJ6vv;5fn&Ks8!L;;6(M#9Q`w2VU}J4JDFd?SmCi_&Vfq}^`I z^768*tgOiD>Z)|RU0GXOlbxL%+1lEY&CN|&UtgEWgmE#)a5-J^SSkM7ZRSwIiyfk8kI=yVd%BYH%S2oXIoPK;Bu z$d1+#-{Huy$Vn0lPvc;4FgO?-42A@QgTcYzU~n)PCJYV+2ZMvb!C>exI2arZ4h9E< zOK5O7IGl2%WEnuA*H55ED!Tq;SUkZ!fjmw-N~ zc35n5;s@df;_EF6#1G^qzz|>vvoHlGD>uIXgR(^Ye4LxVVtJRjjoBGnEKJ7mCL2c7H*`OC(QPhrZQ`Fk5 z&(>^j#2G*8hy}HO^I(cPQ9m?#W%fL`Hrv!}tmEg!x+L3b7rJ~f@ozp+YG*omYJFbX zcw&xzsgw2U-agvoU`&|U8xPf7vHVRO59Z9(#Gc(&6;IW5siy4N$z66uYwWqdef?kB z`+x5L`p4Ks6SwK-pU>JqY0~LcRrG!|+0(vP+p*O4Vv<43?Z$4wbbT>3q1P^Muou0i zvWv)87M*^O(dzh951-fm_eT))h!sj-T` zF&E1Y98QxY(3`1%~{ROIH B6Tbie literal 0 HcmV?d00001 diff --git a/CPP/7zip/Archive/Icons/squashfs.ico b/CPP/7zip/Archive/Icons/squashfs.ico new file mode 100755 index 0000000000000000000000000000000000000000..551a7439855dabf997d416053b025f33e03aae37 GIT binary patch literal 3638 zcmeH}F-s*$5P-{F4`g`3niv_l2FsZ}=*Vm_7fg)Jn)?SLY%r1W!hz666YL##!6p8J z2f_tsbD<_D92f|)u$nBw4%B{CJ>$IhP_yF_dtUc+RdrW=Q$4SzMHb|htgVTc- z(P$*g%geH|vLdUitFpenE*l#gvb(!0+uPf+wY4Rio10R9P}$j0`B~0IKWF*#{EM7l zU(3he{~%DHMrxwwA_jB;T|gI1r)5Y)AJIqj5q(5&(-QiGJ|QIZ2|YK-=rj6^KBLI! z6x3`-<nS8oxsW}*mK~^wofze*CU$};5i}7X!IX%dFeaQN zVkctza(Ha?#81Re#J43%#82cV!H{4`i;fmAkUO)eDG{pAM0^rS82MgtBz?8us5B}#uS5f=uym$-iMgA zpI@xS-YaMPm?I{1{@sIX%!&D-v7Xz@*v{-ji?NGeCfk%^>s;9MX7KMm(R9vi@YMV= zwfDpr`%#Da=H4%BN-zct_TED~S3G}%<7Up>4))@H@~+No&kQ%$3O1;KV^T!|HH$0$0iPs2>;ycId8AVU(17+c5IUizqxDMsv0ub zG~>~f^UgjsU_7cGu~*~1j4JH2W&ZCyYn}CGMC=v|Y!UxSsqs3Y{!4`0*S;P3ImM1H zYt;Un^8QJJnllOm+0*<+OZVlR!Z(Re6!qnt@^Vh$Eb($qnL9VI%bs@MKmTl+%!b^l zjt@F{>g(qA=3%FAXJozsz07{iVX%qZ#2Q3xeG4Q zFIW&bI5iHX!~%l?gE%-TF#<1?zp9>n`YaBExkNqNud3>*Z)#?HTBIjG$>yeb`F&O7 z38Tl4%lyS7k$1?RGTo#;qxJ-Wm6g(c-8Lfpq-jb=%TPw6k&NDtzvZ%gx1<@s}!*K#iUcb2#3|H%2r zkMin|KM545k(#KvOarojEFcRe(_#{lN8}NCL>`gbvV=S#PfQZ>gq%(?@{Bwq&j>Pd zWvRx#81Re#J5M3h@Z$!f+4|>$b&sLvf_7-gr3$OBRR;#%dllQGV%P;8V5PZ zaAf1)#{6-!D8rIr$v|WR`YQlSW?{xCBgnAuqvD5Wl3~e~4`;Er!JYy#7!(GDL19oB z6b65tV8}2i3<^Vr0XJ0aVNe(p2899FROB!y3<`q+pv2EOQx+;l5g(CxghSo8*+lt8 zev|$EeK|NdkfWm`IX*s?v$HcfIXRJwiwn8Dyp*e}E4jYDmfPD~xx2fQo6jo0wk`kT zhV0sZz&iZ-%>3F^rTV`M8^}GSst@ligIb5JU8U)UE*jDvqHjB$*%XBh7*R}*+)Ye7 zSzok8KM^kYF-I)u{JRI2m=p6uV!{iw6`=H4%BN-zv&`iY0}Qt|xF9JfpA@l0Rbj>o)J(=wjZ7bo}W4Xx8pyP5xm z_1~)>P8T}kH~FS!_4HoKV5*p`UwS=FKgp4es`}F;d)C)q>8trWtoxn+E-LG*IfJ@i z{foY;C#7GZUo6Xi??vsRHw(&c(PNAFA*I3Vi28vDH$VG!}G@MZ| zWKZ*smf^!Wg>Mp{DC)yG<>8#dS>oZGvUF}>6Fu#|fBxCDIlFNu8Xk7@xv!h++v&$_ zJU2Jtf0&=+2w$dB6 ZBEzA`;Xs7Lp4i-aY#2A_M$E_PzX1HCB~JhV literal 0 HcmV?d00001 diff --git a/CPP/7zip/Archive/Icons/vhd.ico b/CPP/7zip/Archive/Icons/vhd.ico new file mode 100755 index 0000000000000000000000000000000000000000..33bed3c9805af14100e123015694ddddb1af82b8 GIT binary patch literal 3638 zcmeH}F-u%Q5XZ;FfE-t7V`X71LhKHY7VXdx6LQp3$41 zFZPQkB45y+V=hzIsWXB=sb>9hOH<)QuBvjOr7MHMKn7n2a`pM0%+Air+}xaWyIomW zSdhiVMOj)}l9iPeSzTR~?d@&Z+}xCnjSX2_Ta)Ug%GQ?3YdIDDk>%6rPdWYmU0!|o zNTNWE)I`n23}^u@pas*k42kFwJ)%eSh;GvodO}Ya2|b~6k&K?vGkQkI=!&h_nmu!% z4df353QP*3;^}Du3;~7!Lx91NUvFa#JJ9fklyfFZyTUT9pL^vWG5e{D}I3f%Y zh6sZ#U4$dT5MjvVQd(a^@{|v@FR!f*ROC*K@}(wsf+>+Sks!g8$enN|f+TV$a{KM@ z-00*_jg@MpibQlx{g+T#O@@Il66O}=c7!fKN(E-x?T`ubXKZf@l2x5}G-pZ{^i>e_$6 zF2r-o;+m<_`QL>Njcx--|I*h~^ z`%>Ha7T!PBlw=HO{lf_LRPps|1NW!gb?Yx->zb!(RO&H*338v`&>H{f(#9X3Zxoi~ zj`#)gHvgf|v!?0X8h^q+`Z3-axjX>*rykE~f2a3rxO#T&{pIhB6ZE>~Z%bYC_iP9B zx}976o!+o?JNPHd^xu2ZI~mRLvRllsMf{Ue5p_WQMuw}$z8(2F#f~n^)Zsa0{Z4|4 zGYSLQ)BHk9_u-tvJBe2m_2HcIa8BVY@o-L=IybP19yjkle{Gu0Zrn(RdyPHzc5{D! zv>Df9wuxhQt@bt<`Q2-_74z6=Y=2L*cBglJd~ER>KLivryx6`^X?N>#USsRCy>Yx^ M-c>3b18PnE1D5|2i~s-t literal 0 HcmV?d00001 diff --git a/CPP/7zip/Archive/Icons/wim.ico b/CPP/7zip/Archive/Icons/wim.ico new file mode 100755 index 0000000000000000000000000000000000000000..887975e661e7035a25bb32c7f33336fc7ed1883e GIT binary patch literal 3638 zcmeH}ze^lJ6o8+J0a>ol#>(Pi5n^{Rm7UlNHr94S{sR$GY-Jq?2y@jHNl1z`{sjj@ zia4ayCPKhMkU+d92sxO1@6GP*{qXEU8fR~2_q{joy>H*{&5p=|Jdt)=tbJS(dBN54 za+Y5`6ZwYjC1RVtMPCpUv~tl-_Y5UQ)Mc4Zj9f~;-^fStr^Ivj)eJyW3 zeI}8kdwQV9EIM=!okQnTm+};k-lO;EJ$jE`-2(c6J|G120X-*)=p*`wKB9=|6LLaM z(K0(mM}9{jhm(^emY%`E;9zhtI2a5G1_y(K!NK5QFiaR63=RedgM-1)VQ?@w7#s`^ z2A9ym;oxw}k&;ya4QD+9J<`$ZEyLnT?n&ec>S3`mVDwygSUfCN7C1Z{9u5zOhr>z* zhljz#;9=0xc{n@_9)?J+#AqcXPd<>XyjmTo$Q_tvr6zZPDUdXfAixyJ9WVxh1ab#* z+vBj@=*b_*AIPtdD3Cu;n*c+AAy5Z>Y*fYW9t~$keT>u~k}tv*;fUn3N2?svAi@!q zgB!EQjZ=gr!V-aqB(zrmmWX3yQbZA9;YTM9&m_VUwI0TzZ-YJsbTA|s5)2831Ve(s zUMCnL3<-t=Lxh1abmqg5U`Q||7zj;A4?}_>!H@t*M9av~QO7jk)dDOXola&vPdgTX-V?(XFFPm*`N9{=N# z>gs<$PsB4xG*vL2Jm#NW z>qyMeAHDI{@OJ2slQE&O*Aa$O&Fa?#?oFA8jXj4Q4tc9aZ8&DnK_0Rzn%Q#_qTKIa zGt9T+sJ~hNZr0AVTmI}^`;TtME@u3vUeC&I?3%ym{I08~=gy41Xex-grS_)bUyM!Y zw2FJ|MW=490{di}{(DbaC!=XzR*MCeh=0;bqW0-O$Z-4AmLuDz=+>o8ulFfia|ufJ zC`@EcvlAnikNXt9NqnN{kNcFzeF}St$9>AwzJW#bwEF(pXH#WX<4V;%tmLt;o7sD# z#dz4rte`CHBbg749<%Z(O=nhi`%W}+(HWecYJ7e=0|J@~)^y#cHLG>rud(#$+Bn`3 M=d}_;pFX7j1!G|oPyhe` literal 0 HcmV?d00001 diff --git a/CPP/7zip/Archive/Icons/xar.ico b/CPP/7zip/Archive/Icons/xar.ico new file mode 100755 index 0000000000000000000000000000000000000000..281aa7dc1c9de06d58f713eeb69c357a689a6423 GIT binary patch literal 3638 zcmeH}ze`*}5P-+TfE-t7V`X71LhKH|NFdq-ArB_s%)aNlyQp1AAl;iK;<<*Ce z1PbIxPUKv=0a-v6kOh-zF^R|{@`yYlkH~FULY|N(Ith6~P9+(6MxK#p1R1%~SNfVg za-a;v4>$@83ZmlSDFO@uh5$o=!I5AHFa#I^3;_nmgdxBXUv ziVThbM=%amp8+J)_9Sv9Bez$EB@#RmDB?82;?saK(ulA`SbSRGh;T$WA{-G8pDH*a z3=xJ1gH2t8Bf=12$iz}gpF-l4hrUm*%??z=PFVR=6Fb3_2$~3xU`oVJC=*T+u@kX< zIXpIU;wR!K;@c7>;wR=N!H{4`%!4f(v*K@$gqqTpkvYi3%dllQGVy$Aje|MJaAf1) z#eBILlwrxRWFRsD{S$yCGcaS65oB2Sk@3TtWLUDzhqKt%V5@)(28BUkP#6>jg~2~3 z7%~hBgTjzuzzrFD7!(GDL1Dl(8959JgTkNyDDgASl!1y-#7Cqb;ZXN&Hc=kSTiM#$ zlI`tn+1=fhy}dm-Iy#brg9AA^Ig!)TQ#m_3lk@X)xxBoTtE(%y_^tA0IOKm^F}wC3 zunK?PGr!hV>HY7-269L04R-EKD+Aph+Ea?A>7sqg9rVLSXEsG)4O%4ABX<+iw&RPo z=v(20A9KWj#=m=Ti8(Pp6xMQmv2E0DT9i%vGT4R`UE{)r4?F+v6G`LDjK{{8p{*xu z>__g#n|pt(D8Vr3^sR?_D*60%j)zm~y3-f8b#pDM4zG*yyRX6)@^yb9kPo~Cm^OoqRK2IOiMW}m&U+wH!J@`xC8-K$=-~4x} zuK9a*27`X@27PbPrhX6oWSahaPiiNE4zq6eDs?{sY}O6Jh`W literal 0 HcmV?d00001 diff --git a/CPP/7zip/Archive/Icons/xz.ico b/CPP/7zip/Archive/Icons/xz.ico new file mode 100755 index 0000000000000000000000000000000000000000..02707351b95da13405d4a48b14683077add16b7e GIT binary patch literal 3638 zcmeH}F-sgl6vv;*1&-qiZLBOV79n;EQ`w2VU}J4J`~(L= zia4ayCPKhMkU+EvLKY^!_h$F@?xLm&X`H*6o%z3c@BMCeZ+1lHpSEYQJWOFmgYdMkhJ<6w(A98YWA+J7s zB$1JCNIM zhvh~me;|J#zuuxi{=nJ<7y=A|b$_igWd%+7!nK#h6F=`A;Dme z6ATfC1Ve%$!ax`*^I=FZBp4D5gr=gykYGqKBmffmBf%1miAkOqp0S4`S!|u-<*B@t z?d@&Z+1Zi3y*=6A-vuLl+)8wIXgR(^Ye4Lyu6g_>ub5Wxsj`1N!|>H{Etgk zSN{WgA)bvit`3v*{&!&mxu^7s-FwS&kq(CX$xYog>40_@`>?j@oNUkzJ&M}VZHihO z|7^|nMx2VHfpDnfTLe=yh{mDOp4s!<+H6y^vCf~J)g{~N5b8c`<6BIWI+#wL@XxMI zB0L5vrMD>(>Sz&X}v#p2JoZPt~|o6ZRbBKD(lsU7Nbo#-H&2 zn;mC!=Q`tmko6p0lg!w2{yKZMkAIAHnz+q%_W3kjo4V60em1M8*WwR*Z<3(sn|++J zs`z`h6N-NC7JIK~O23DFy3GE)r>)b`G%dTu99zUcDJ4-y)Nf?CdTiT~om2GaGN3l+ zl(jnvO3o-uWKXjTE!~H63hyLdQPhWX%ELK@v&6$WW#-(#CVEuA|LnD?V|L?OI@qnp z6K^-O563UFYCP7ho$sCFdgCvSw5WgH@$-A4c1G+K*GEShzy3l%(fL+%->0;@bw01L S_37R?SsC6{N(>`vMg0xs)Dx8e literal 0 HcmV?d00001 diff --git a/CPP/7zip/Archive/Icons/z.ico b/CPP/7zip/Archive/Icons/z.ico new file mode 100755 index 0000000000000000000000000000000000000000..2db53583ee4e1ff1c74d4ecb89ccf502fcd8b13a GIT binary patch literal 3638 zcmeH}y-Qp{5WvU8fIP0y#>&E2gxDQyWheH6jkVp9|3HKkud)sVgtfXN2}zO0zu-Vf z5to$OLw0E~OHA=*FT{>EZ((m`B|FtidpWn&!^t8;(%t)uxk-51! znV+ARg@pxKT3V9j`ex_LE_W1djxYIE}D)8c;?C5tayxrv;7(M}#B75#jJu!4YAI zFhm$EbrFsTLxdp{OKClY#3>)CN$!ITJ^2#{b(#7-y^P7<*bvHfv) zY~;jG#81SxN0f-4$W4MF!H~#H3vVc|=~56>jSk}V(3VsC>z1!OQN3<`t7pfD&5{yM>s zVNe(ph71F4sH}%UVNe(p23%8-!=NxI3<`h}KjTa>R2D^iMCK6=b>Fro%2RnOTU%SQ zy}d2FySuWtw*gF z>d@ZY`^TCRj0Hn|>tQfaJby#Sy$SVTs4s2@1Kz5eG8oYpC->-llrRrv(29M-8Oz3q^d>K1*~ZA+&@KVByP-s9SFZ^p!KF~t_~PfCr~KJ^|A35Dz-@7@? z2JPIACw9%7IcI=vnvCUX>$AOa Ov@*S`)F}GY0rfXt5fgv_ literal 0 HcmV?d00001 diff --git a/CPP/7zip/Archive/Icons/zip.ico b/CPP/7zip/Archive/Icons/zip.ico new file mode 100755 index 0000000000000000000000000000000000000000..2af46066b97ef29a732ae999c303acc7f8a20c63 GIT binary patch literal 3638 zcmeH}F>72$5P;`m8N_iAt5Kywz9LxN!B*;wdVw3&>X!TiA#m|3)q#LuuX;rsk|K?M z!GXYqwYZcT3j%@|L?BWV1bHy|X7)Y3yHg@pA&vHK_wCH=%zQWR-M$qW$XBwtDc*is z75RqQix)-y_PNMMbgvLM>96SnL1AsBTpo^<2w$nHa$#gDv)N2$pJsCN;YV3nS&`M% zRT+&&vbMG+>+9>Xv9TfJ@mRLDwq$Q_Pj+{AWoKtcwzs#XdaLs0jmr0OF8X_x_ve4e z`RC8_-Os;}D9|H4(Q^?4x_~aA3#QYuB%+V#Bl?IwqBpmMKA}$t34KD(MKbz~KBLbl zGI~W;WX+yAFb47m0tK9csCasY07HNwzz|??Bp3n=0fqoWfWa|g2rvW~0t^8LM~5N6 z5MT%}1Q>#%gCoEZj6>BcfQGAm5+Sks!g8$el1I zf+TV$a{KM@+~~=l$e+k>wFem^@{!B2%QCSp;5s@Pt>alH2 zl$Y{O_V@SY;NU=xj*jH`_*l-)&gA6eL@q8afBgl4IE{rbT5lDX;aC2Z61RNc2`&R&8%W;ZmmcR6g< z$M5~WWVZkX;er3OSh@ud?4BRrc7fR!TOZj{U|)JXm-&a2KfCJLb@ISIod1QBQ5U~t zZ5sZb{esD8_z(8sq-&!g_QkgR_g=IvMzfsk76Z13|D;t!ozZ_K!_70_j{KZrN0&|d z{W;}d2`bJgEM!mf3nSB~a|-VyUQzU?bIQ{>g|o!dIc4eGz$SXyzW@BSX)?QUtC}9R z^4#0a?e+c3thtwc1J!xiw#{DVolxXcn){ogeNU8lD4OBq_Vm=^xA7pL6}$PDeY@YS pRllxP&j;1uw}A}mDZQ4#v=*68MGnUz$YQcxu`{o*&5#@He*;V>BftOv literal 0 HcmV?d00001 diff --git a/CPP/7zip/Archive/Iso/IsoHandler.cpp b/CPP/7zip/Archive/Iso/IsoHandler.cpp new file mode 100755 index 0000000..9f78605 --- /dev/null +++ b/CPP/7zip/Archive/Iso/IsoHandler.cpp @@ -0,0 +1,326 @@ +// IsoHandler.cpp + +#include "StdAfx.h" + +#include "Common/ComTry.h" +#include "Common/IntToString.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../../Common/LimitedStreams.h" +#include "../../Common/ProgressUtils.h" + +#include "../../Compress/CopyCoder.h" + +#include "../Common/ItemNameUtils.h" + +#include "IsoHandler.h" + +using namespace NWindows; +using namespace NTime; + +namespace NArchive { +namespace NIso { + +static const STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME} +}; + +static const STATPROPSTG kArcProps[] = +{ + { NULL, kpidComment, VT_BSTR}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidMTime, VT_FILETIME} + // { NULL, kpidPhySize, VT_UI8}, + // { NULL, kpidHeadersSize, VT_UI8} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +STDMETHODIMP CHandler::Open(IInStream *stream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback * /* openArchiveCallback */) +{ + COM_TRY_BEGIN + Close(); + // try + { + if (_archive.Open(stream) != S_OK) + return S_FALSE; + _stream = stream; + } + // catch(...) { return S_FALSE; } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _archive.Clear(); + _stream.Release(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _archive.Refs.Size() + _archive.BootEntries.Size(); + return S_OK; +} + +static void AddString(AString &s, const char *name, const Byte *p, int size) +{ + int i; + for (i = 0; i < size && p[i]; i++); + for (; i > 0 && p[i - 1] == ' '; i--); + if (i != 0) + { + AString d; + memcpy(d.GetBuffer(i), p, i); + d.ReleaseBuffer(i); + s += '\n'; + s += name; + s += ": "; + s += d; + } +} + +#define ADD_STRING(n, v) AddString(s, n, vol. ## v, sizeof(vol. ## v)) + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + const CVolumeDescriptor &vol = _archive.VolDescs[_archive.MainVolDescIndex]; + switch(propID) + { + case kpidComment: + { + AString s; + ADD_STRING("System", SystemId); + ADD_STRING("Volume", VolumeId); + ADD_STRING("VolumeSet", VolumeSetId); + ADD_STRING("Publisher", PublisherId); + ADD_STRING("Preparer", DataPreparerId); + ADD_STRING("Application", ApplicationId); + ADD_STRING("Copyright", CopyrightFileId); + ADD_STRING("Abstract", AbstractFileId); + ADD_STRING("Bib", BibFileId); + prop = s; + break; + } + case kpidCTime: { FILETIME utc; if (vol.CTime.GetFileTime(utc)) prop = utc; break; } + case kpidMTime: { FILETIME utc; if (vol.MTime.GetFileTime(utc)) prop = utc; break; } + // case kpidPhySize: break; + // case kpidHeadersSize: break; + case kpidError: if (_archive.IncorrectBigEndian) prop = "Incorrect big-endian headers"; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + if (index >= (UInt32)_archive.Refs.Size()) + { + index -= _archive.Refs.Size(); + const CBootInitialEntry &be = _archive.BootEntries[index]; + switch(propID) + { + case kpidPath: + { + // wchar_t name[32]; + // ConvertUInt64ToString(index + 1, name); + UString s = L"[BOOT]" WSTRING_PATH_SEPARATOR; + // s += name; + // s += L"-"; + s += be.GetName(); + prop = (const wchar_t *)s; + break; + } + case kpidIsDir: prop = false; break; + case kpidSize: + case kpidPackSize: + prop = (UInt64)_archive.GetBootItemSize(index); + break; + } + } + else + { + const CRef &ref = _archive.Refs[index]; + const CDir &item = ref.Dir->_subItems[ref.Index]; + switch(propID) + { + case kpidPath: + // if (item.FileId.GetCapacity() >= 0) + { + UString s; + if (_archive.IsJoliet()) + s = item.GetPathU(); + else + s = MultiByteToUnicodeString(item.GetPath(_archive.IsSusp, _archive.SuspSkipSize), CP_OEMCP); + + int pos = s.ReverseFind(L';'); + if (pos >= 0 && pos == s.Length() - 2) + if (s[s.Length() - 1] == L'1') + s = s.Left(pos); + if (!s.IsEmpty()) + if (s[s.Length() - 1] == L'.') + s = s.Left(s.Length() - 1); + prop = (const wchar_t *)NItemName::GetOSName2(s); + } + break; + case kpidIsDir: prop = item.IsDir(); break; + case kpidSize: + case kpidPackSize: + if (!item.IsDir()) + prop = (UInt64)item.DataLength; + break; + case kpidMTime: + { + FILETIME utc; + if (item.DateTime.GetFileTime(utc)) + prop = utc; + break; + } + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _archive.Refs.Size(); + if (numItems == 0) + return S_OK; + UInt64 totalSize = 0; + UInt32 i; + for(i = 0; i < numItems; i++) + { + UInt32 index = (allFilesMode ? i : indices[i]); + if (index < (UInt32)_archive.Refs.Size()) + { + const CRef &ref = _archive.Refs[index]; + const CDir &item = ref.Dir->_subItems[ref.Index]; + totalSize += item.DataLength; + } + else + { + totalSize += _archive.GetBootItemSize(index - _archive.Refs.Size()); + } + } + extractCallback->SetTotal(totalSize); + + UInt64 currentTotalSize = 0; + UInt64 currentItemSize; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + + 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); + + for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) + { + lps->InSize = lps->OutSize = currentTotalSize; + RINOK(lps->SetCur()); + currentItemSize = 0; + CMyComPtr realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + UInt32 index = allFilesMode ? i : indices[i]; + + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + UInt64 blockIndex; + if (index < (UInt32)_archive.Refs.Size()) + { + const CRef &ref = _archive.Refs[index]; + const CDir &item = ref.Dir->_subItems[ref.Index]; + if (item.IsDir()) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + currentItemSize = item.DataLength; + blockIndex = item.ExtentLocation; + } + else + { + int bootIndex = index - _archive.Refs.Size(); + const CBootInitialEntry &be = _archive.BootEntries[bootIndex]; + currentItemSize = _archive.GetBootItemSize(bootIndex); + blockIndex = be.LoadRBA; + } + + if (!testMode && !realOutStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + outStreamSpec->SetStream(realOutStream); + realOutStream.Release(); + outStreamSpec->Init(currentItemSize); + RINOK(_stream->Seek(blockIndex * _archive.BlockSize, STREAM_SEEK_SET, NULL)); + streamSpec->Init(currentItemSize); + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + outStreamSpec->ReleaseStream(); + RINOK(extractCallback->SetOperationResult(outStreamSpec->IsFinishedOK() ? + NExtract::NOperationResult::kOK: + NExtract::NOperationResult::kDataError)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + *stream = 0; + UInt64 blockIndex; + UInt64 currentItemSize; + if (index < (UInt32)_archive.Refs.Size()) + { + const CRef &ref = _archive.Refs[index]; + const CDir &item = ref.Dir->_subItems[ref.Index]; + if (item.IsDir()) + return S_FALSE; + currentItemSize = item.DataLength; + blockIndex = item.ExtentLocation; + } + else + { + int bootIndex = index - _archive.Refs.Size(); + const CBootInitialEntry &be = _archive.BootEntries[bootIndex]; + currentItemSize = _archive.GetBootItemSize(bootIndex); + blockIndex = be.LoadRBA; + } + return CreateLimitedInStream(_stream, blockIndex * _archive.BlockSize, currentItemSize, stream); + COM_TRY_END +} + +}} diff --git a/CPP/7zip/Archive/Iso/IsoHandler.h b/CPP/7zip/Archive/Iso/IsoHandler.h new file mode 100755 index 0000000..29b6472 --- /dev/null +++ b/CPP/7zip/Archive/Iso/IsoHandler.h @@ -0,0 +1,30 @@ +// IsoHandler.h + +#ifndef __ISO_HANDLER_H +#define __ISO_HANDLER_H + +#include "Common/MyCom.h" +#include "../IArchive.h" + +#include "IsoIn.h" +#include "IsoItem.h" + +namespace NArchive { +namespace NIso { + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + CInArchive _archive; +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Iso/IsoHeader.cpp b/CPP/7zip/Archive/Iso/IsoHeader.cpp new file mode 100755 index 0000000..fa4c8e7 --- /dev/null +++ b/CPP/7zip/Archive/Iso/IsoHeader.cpp @@ -0,0 +1,21 @@ +// Archive/Iso/Header.h + +#include "StdAfx.h" + +#include "IsoHeader.h" + +namespace NArchive { +namespace NIso { + +const char *kElToritoSpec = "EL TORITO SPECIFICATION\0\0\0\0\0\0\0\0\0"; + +const wchar_t *kMediaTypes[5] = +{ + L"NoEmulation", + L"1.2M", + L"1.44M", + L"2.88M", + L"HardDisk" +}; + +}} diff --git a/CPP/7zip/Archive/Iso/IsoHeader.h b/CPP/7zip/Archive/Iso/IsoHeader.h new file mode 100755 index 0000000..bd50666 --- /dev/null +++ b/CPP/7zip/Archive/Iso/IsoHeader.h @@ -0,0 +1,61 @@ +// Archive/IsoHeader.h + +#ifndef __ARCHIVE_ISO_HEADER_H +#define __ARCHIVE_ISO_HEADER_H + +#include "Common/Types.h" + +namespace NArchive { +namespace NIso { + +namespace NVolDescType +{ + const Byte kBootRecord = 0; + const Byte kPrimaryVol = 1; + const Byte kSupplementaryVol = 2; + const Byte kVolParttition = 3; + const Byte kTerminator = 255; +} + +const Byte kVersion = 1; + +namespace NFileFlags +{ + const Byte kDirectory = 1 << 1; +} + +extern const char *kElToritoSpec; + +const UInt32 kStartPos = 0x8000; + +namespace NBootEntryId +{ + const Byte kValidationEntry = 1; + const Byte kInitialEntryNotBootable = 0; + const Byte kInitialEntryBootable = 0x88; +} + +namespace NBootPlatformId +{ + const Byte kX86 = 0; + const Byte kPowerPC = 1; + const Byte kMac = 2; +} + +const BYTE kBootMediaTypeMask = 0xF; + +namespace NBootMediaType +{ + const Byte kNoEmulation = 0; + const Byte k1d2Floppy = 1; + const Byte k1d44Floppy = 2; + const Byte k2d88Floppy = 3; + const Byte kHardDisk = 4; +} + +const int kNumBootMediaTypes = 5; +extern const wchar_t *kMediaTypes[]; + +}} + +#endif diff --git a/CPP/7zip/Archive/Iso/IsoIn.cpp b/CPP/7zip/Archive/Iso/IsoIn.cpp new file mode 100755 index 0000000..400d6ca --- /dev/null +++ b/CPP/7zip/Archive/Iso/IsoIn.cpp @@ -0,0 +1,453 @@ +// Archive/IsoIn.cpp + +#include "StdAfx.h" + +#include "IsoIn.h" + +#include "../../Common/StreamUtils.h" + +namespace NArchive { +namespace NIso { + +Byte CInArchive::ReadByte() +{ + if (m_BufferPos >= BlockSize) + m_BufferPos = 0; + if (m_BufferPos == 0) + { + size_t processedSize = BlockSize; + if (ReadStream(_stream, m_Buffer, &processedSize) != S_OK) + throw 1; + if (processedSize != BlockSize) + throw 1; + } + Byte b = m_Buffer[m_BufferPos++]; + _position++; + return b; +} + +void CInArchive::ReadBytes(Byte *data, UInt32 size) +{ + for (UInt32 i = 0; i < size; i++) + data[i] = ReadByte(); +} + +void CInArchive::Skip(size_t size) +{ + while (size-- != 0) + ReadByte(); +} + +void CInArchive::SkipZeros(size_t size) +{ + while (size-- != 0) + { + Byte b = ReadByte(); + if (b != 0) + throw 1; + } +} + +UInt16 CInArchive::ReadUInt16Spec() +{ + UInt16 value = 0; + for (int i = 0; i < 2; i++) + value |= ((UInt16)(ReadByte()) << (8 * i)); + return value; +} + + +UInt16 CInArchive::ReadUInt16() +{ + Byte b[4]; + ReadBytes(b, 4); + UInt32 value = 0; + for (int i = 0; i < 2; i++) + { + if (b[i] != b[3 - i]) + IncorrectBigEndian = true; + value |= ((UInt16)(b[i]) << (8 * i)); + } + return (UInt16)value; +} + +UInt32 CInArchive::ReadUInt32Le() +{ + UInt32 value = 0; + for (int i = 0; i < 4; i++) + value |= ((UInt32)(ReadByte()) << (8 * i)); + return value; +} + +UInt32 CInArchive::ReadUInt32Be() +{ + UInt32 value = 0; + for (int i = 0; i < 4; i++) + { + value <<= 8; + value |= ReadByte(); + } + return value; +} + +UInt32 CInArchive::ReadUInt32() +{ + Byte b[8]; + ReadBytes(b, 8); + UInt32 value = 0; + for (int i = 0; i < 4; i++) + { + if (b[i] != b[7 - i]) + throw 1; + value |= ((UInt32)(b[i]) << (8 * i)); + } + return value; +} + +UInt32 CInArchive::ReadDigits(int numDigits) +{ + UInt32 res = 0; + for (int i = 0; i < numDigits; i++) + { + Byte b = ReadByte(); + if (b < '0' || b > '9') + { + if (b == 0) // it's bug in some CD's + b = '0'; + else + throw 1; + } + UInt32 d = (UInt32)(b - '0'); + res *= 10; + res += d; + } + return res; +} + +void CInArchive::ReadDateTime(CDateTime &d) +{ + d.Year = (UInt16)ReadDigits(4); + d.Month = (Byte)ReadDigits(2); + d.Day = (Byte)ReadDigits(2); + d.Hour = (Byte)ReadDigits(2); + d.Minute = (Byte)ReadDigits(2); + d.Second = (Byte)ReadDigits(2); + d.Hundredths = (Byte)ReadDigits(2); + d.GmtOffset = (signed char)ReadByte(); +} + +void CInArchive::ReadBootRecordDescriptor(CBootRecordDescriptor &d) +{ + ReadBytes(d.BootSystemId, sizeof(d.BootSystemId)); + ReadBytes(d.BootId, sizeof(d.BootId)); + ReadBytes(d.BootSystemUse, sizeof(d.BootSystemUse)); +} + +void CInArchive::ReadRecordingDateTime(CRecordingDateTime &t) +{ + t.Year = ReadByte(); + t.Month = ReadByte(); + t.Day = ReadByte(); + t.Hour = ReadByte(); + t.Minute = ReadByte(); + t.Second = ReadByte(); + t.GmtOffset = (signed char)ReadByte(); +} + +void CInArchive::ReadDirRecord2(CDirRecord &r, Byte len) +{ + r.ExtendedAttributeRecordLen = ReadByte(); + if (r.ExtendedAttributeRecordLen != 0) + throw 1; + r.ExtentLocation = ReadUInt32(); + r.DataLength = ReadUInt32(); + ReadRecordingDateTime(r.DateTime); + r.FileFlags = ReadByte(); + r.FileUnitSize = ReadByte(); + r.InterleaveGapSize = ReadByte(); + r.VolSequenceNumber = ReadUInt16(); + Byte idLen = ReadByte(); + r.FileId.SetCapacity(idLen); + ReadBytes((Byte *)r.FileId, idLen); + int padSize = 1 - (idLen & 1); + + // SkipZeros(1 - (idLen & 1)); + Skip(1 - (idLen & 1)); // it's bug in some cd's. Must be zeros + + int curPos = 33 + idLen + padSize; + if (curPos > len) + throw 1; + int rem = len - curPos; + r.SystemUse.SetCapacity(rem); + ReadBytes((Byte *)r.SystemUse, rem); +} + +void CInArchive::ReadDirRecord(CDirRecord &r) +{ + Byte len = ReadByte(); + // Some CDs can have incorrect value len = 48 ('0') in VolumeDescriptor. + // But maybe we must use real "len" for other records. + len = 34; + ReadDirRecord2(r, len); +} + +void CInArchive::ReadVolumeDescriptor(CVolumeDescriptor &d) +{ + d.VolFlags = ReadByte(); + ReadBytes(d.SystemId, sizeof(d.SystemId)); + ReadBytes(d.VolumeId, sizeof(d.VolumeId)); + SkipZeros(8); + d.VolumeSpaceSize = ReadUInt32(); + ReadBytes(d.EscapeSequence, sizeof(d.EscapeSequence)); + d.VolumeSetSize = ReadUInt16(); + d.VolumeSequenceNumber = ReadUInt16(); + d.LogicalBlockSize = ReadUInt16(); + d.PathTableSize = ReadUInt32(); + d.LPathTableLocation = ReadUInt32Le(); + d.LOptionalPathTableLocation = ReadUInt32Le(); + d.MPathTableLocation = ReadUInt32Be(); + d.MOptionalPathTableLocation = ReadUInt32Be(); + ReadDirRecord(d.RootDirRecord); + ReadBytes(d.VolumeSetId, sizeof(d.VolumeSetId)); + ReadBytes(d.PublisherId, sizeof(d.PublisherId)); + ReadBytes(d.DataPreparerId, sizeof(d.DataPreparerId)); + ReadBytes(d.ApplicationId, sizeof(d.ApplicationId)); + ReadBytes(d.CopyrightFileId, sizeof(d.CopyrightFileId)); + ReadBytes(d.AbstractFileId, sizeof(d.AbstractFileId)); + ReadBytes(d.BibFileId, sizeof(d.BibFileId)); + ReadDateTime(d.CTime); + ReadDateTime(d.MTime); + ReadDateTime(d.ExpirationTime); + ReadDateTime(d.EffectiveTime); + d.FileStructureVersion = ReadByte(); // = 1 + SkipZeros(1); + ReadBytes(d.ApplicationUse, sizeof(d.ApplicationUse)); + SkipZeros(653); +} + +static const Byte kSig_CD001[5] = { 'C', 'D', '0', '0', '1' }; + +static const Byte kSig_NSR02[5] = { 'N', 'S', 'R', '0', '2' }; +static const Byte kSig_NSR03[5] = { 'N', 'S', 'R', '0', '3' }; +static const Byte kSig_BEA01[5] = { 'B', 'E', 'A', '0', '1' }; +static const Byte kSig_TEA01[5] = { 'T', 'E', 'A', '0', '1' }; + +static inline bool CheckSignature(const Byte *sig, const Byte *data) +{ + for (int i = 0; i < 5; i++) + if (sig[i] != data[i]) + return false; + return true; +} + +void CInArchive::SeekToBlock(UInt32 blockIndex) +{ + if (_stream->Seek((UInt64)blockIndex * VolDescs[MainVolDescIndex].LogicalBlockSize, STREAM_SEEK_SET, &_position) != S_OK) + throw 1; + m_BufferPos = 0; +} + +void CInArchive::ReadDir(CDir &d, int level) +{ + if (!d.IsDir()) + return; + SeekToBlock(d.ExtentLocation); + UInt64 startPos = _position; + + bool firstItem = true; + for (;;) + { + UInt64 offset = _position - startPos; + if (offset >= d.DataLength) + break; + Byte len = ReadByte(); + if (len == 0) + continue; + CDir subItem; + ReadDirRecord2(subItem, len); + if (firstItem && level == 0) + IsSusp = subItem.CheckSusp(SuspSkipSize); + + if (!subItem.IsSystemItem()) + d._subItems.Add(subItem); + + firstItem = false; + } + for (int i = 0; i < d._subItems.Size(); i++) + ReadDir(d._subItems[i], level + 1); +} + +void CInArchive::CreateRefs(CDir &d) +{ + if (!d.IsDir()) + return; + for (int i = 0; i < d._subItems.Size(); i++) + { + CRef ref; + CDir &subItem = d._subItems[i]; + subItem.Parent = &d; + ref.Dir = &d; + ref.Index = i; + Refs.Add(ref); + CreateRefs(subItem); + } +} + +void CInArchive::ReadBootInfo() +{ + if (!_bootIsDefined) + return; + if (memcmp(_bootDesc.BootSystemId, kElToritoSpec, sizeof(_bootDesc.BootSystemId)) != 0) + return; + + const Byte *p = (const Byte *)_bootDesc.BootSystemUse; + UInt32 blockIndex = p[0] | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16) | ((UInt32)p[3] << 24); + SeekToBlock(blockIndex); + Byte b = ReadByte(); + if (b != NBootEntryId::kValidationEntry) + return; + { + CBootValidationEntry e; + e.PlatformId = ReadByte(); + if (ReadUInt16Spec() != 0) + throw 1; + ReadBytes(e.Id, sizeof(e.Id)); + /* UInt16 checkSum = */ ReadUInt16Spec(); + if (ReadByte() != 0x55) + throw 1; + if (ReadByte() != 0xAA) + throw 1; + } + b = ReadByte(); + if (b == NBootEntryId::kInitialEntryBootable || b == NBootEntryId::kInitialEntryNotBootable) + { + CBootInitialEntry e; + e.Bootable = (b == NBootEntryId::kInitialEntryBootable); + e.BootMediaType = ReadByte(); + e.LoadSegment = ReadUInt16Spec(); + e.SystemType = ReadByte(); + if (ReadByte() != 0) + throw 1; + e.SectorCount = ReadUInt16Spec(); + e.LoadRBA = ReadUInt32Le(); + if (ReadByte() != 0) + throw 1; + BootEntries.Add(e); + } + else + return; +} + +HRESULT CInArchive::Open2() +{ + Clear(); + RINOK(_stream->Seek(kStartPos, STREAM_SEEK_CUR, &_position)); + + m_BufferPos = 0; + BlockSize = kBlockSize; + for (;;) + { + Byte sig[7]; + ReadBytes(sig, 7); + Byte ver = sig[6]; + if (!CheckSignature(kSig_CD001, sig + 1)) + { + return S_FALSE; + /* + if (sig[0] != 0 || ver != 1) + break; + if (CheckSignature(kSig_BEA01, sig + 1)) + { + } + else if (CheckSignature(kSig_TEA01, sig + 1)) + { + break; + } + else if (CheckSignature(kSig_NSR02, sig + 1)) + { + } + else + break; + SkipZeros(0x800 - 7); + continue; + */ + } + // version = 2 for ISO 9660:1999? + if (ver > 2) + throw S_FALSE; + + if (sig[0] == NVolDescType::kTerminator) + { + break; + // Skip(0x800 - 7); + // continue; + } + switch(sig[0]) + { + case NVolDescType::kBootRecord: + { + _bootIsDefined = true; + ReadBootRecordDescriptor(_bootDesc); + break; + } + case NVolDescType::kPrimaryVol: + case NVolDescType::kSupplementaryVol: + { + // some ISOs have two PrimaryVols. + CVolumeDescriptor vd; + ReadVolumeDescriptor(vd); + if (sig[0] == NVolDescType::kPrimaryVol) + { + // some burners write "Joliet" Escape Sequence to primary volume + memset(vd.EscapeSequence, 0, sizeof(vd.EscapeSequence)); + } + VolDescs.Add(vd); + break; + } + default: + break; + } + } + if (VolDescs.IsEmpty()) + return S_FALSE; + for (MainVolDescIndex = VolDescs.Size() - 1; MainVolDescIndex > 0; MainVolDescIndex--) + if (VolDescs[MainVolDescIndex].IsJoliet()) + break; + // MainVolDescIndex = 0; // to read primary volume + const CVolumeDescriptor &vd = VolDescs[MainVolDescIndex]; + if (vd.LogicalBlockSize != kBlockSize) + return S_FALSE; + (CDirRecord &)_rootDir = vd.RootDirRecord; + ReadDir(_rootDir, 0); + CreateRefs(_rootDir); + ReadBootInfo(); + return S_OK; +} + +HRESULT CInArchive::Open(IInStream *inStream) +{ + _stream = inStream; + UInt64 pos; + RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &pos)); + RINOK(_stream->Seek(0, STREAM_SEEK_END, &_archiveSize)); + RINOK(_stream->Seek(pos, STREAM_SEEK_SET, &_position)); + HRESULT res = S_FALSE; + try { res = Open2(); } + catch(...) { Clear(); res = S_FALSE; } + _stream.Release(); + return res; +} + +void CInArchive::Clear() +{ + IncorrectBigEndian = false; + Refs.Clear(); + _rootDir.Clear(); + VolDescs.Clear(); + _bootIsDefined = false; + BootEntries.Clear(); + SuspSkipSize = 0; + IsSusp = false; +} + +}} diff --git a/CPP/7zip/Archive/Iso/IsoIn.h b/CPP/7zip/Archive/Iso/IsoIn.h new file mode 100755 index 0000000..38908ca --- /dev/null +++ b/CPP/7zip/Archive/Iso/IsoIn.h @@ -0,0 +1,315 @@ +// Archive/IsoIn.h + +#ifndef __ARCHIVE_ISO_IN_H +#define __ARCHIVE_ISO_IN_H + +#include "Common/IntToString.h" +#include "Common/MyCom.h" + +#include "../../IStream.h" + +#include "IsoHeader.h" +#include "IsoItem.h" + +namespace NArchive { +namespace NIso { + +struct CDir: public CDirRecord +{ + CDir *Parent; + CObjectVector _subItems; + + void Clear() + { + Parent = 0; + _subItems.Clear(); + } + + int GetLength(bool checkSusp, int skipSize) const + { + int len = GetLengthCur(checkSusp, skipSize); + if (Parent != 0) + if (Parent->Parent != 0) + len += 1 + Parent->GetLength(checkSusp, skipSize); + return len; + } + + int GetLengthU() const + { + int len = (int)(FileId.GetCapacity() / 2); + if (Parent != 0) + if (Parent->Parent != 0) + len += 1 + Parent->GetLengthU(); + return len; + } + + AString GetPath(bool checkSusp, int skipSize) const + { + AString s; + int len = GetLength(checkSusp, skipSize); + char *p = s.GetBuffer(len + 1); + p += len; + *p = 0; + const CDir *cur = this; + for (;;) + { + int curLen = cur->GetLengthCur(checkSusp, skipSize); + p -= curLen; + memmove(p, (const char *)(const Byte *)cur->GetNameCur(checkSusp, skipSize), curLen); + cur = cur->Parent; + if (cur == 0) + break; + if (cur->Parent == 0) + break; + p--; + *p = CHAR_PATH_SEPARATOR; + } + s.ReleaseBuffer(); + return s; + } + + UString GetPathU() const + { + UString s; + int len = GetLengthU(); + wchar_t *p = s.GetBuffer(len + 1); + p += len; + *p = 0; + const CDir *cur = this; + for (;;) + { + int curLen = (int)(cur->FileId.GetCapacity() / 2); + p -= curLen; + for (int i = 0; i < curLen; i++) + { + Byte b0 = ((const Byte *)cur->FileId)[i * 2]; + Byte b1 = ((const Byte *)cur->FileId)[i * 2 + 1]; + p[i] = (wchar_t)(((wchar_t)b0 << 8) | b1); + } + cur = cur->Parent; + if (cur == 0) + break; + if (cur->Parent == 0) + break; + p--; + *p = WCHAR_PATH_SEPARATOR; + } + s.ReleaseBuffer(); + return s; + } +}; + +struct CDateTime +{ + UInt16 Year; + Byte Month; + Byte Day; + Byte Hour; + Byte Minute; + Byte Second; + Byte Hundredths; + signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded. + bool NotSpecified() const { return Year == 0 && Month == 0 && Day == 0 && + Hour == 0 && Minute == 0 && Second == 0 && GmtOffset == 0; } + + bool GetFileTime(FILETIME &ft) const + { + UInt64 value; + bool res = NWindows::NTime::GetSecondsSince1601(Year, Month, Day, Hour, Minute, Second, value); + if (res) + { + value -= (UInt64)((Int64)GmtOffset * 15 * 60); + value *= 10000000; + } + ft.dwLowDateTime = (DWORD)value; + ft.dwHighDateTime = (DWORD)(value >> 32); + return res; + } +}; + +struct CBootRecordDescriptor +{ + Byte BootSystemId[32]; // a-characters + Byte BootId[32]; // a-characters + Byte BootSystemUse[1977]; +}; + +struct CBootValidationEntry +{ + Byte PlatformId; + Byte Id[24]; // to identify the manufacturer/developer of the CD-ROM. +}; + +struct CBootInitialEntry +{ + bool Bootable; + Byte BootMediaType; + UInt16 LoadSegment; + /* This is the load segment for the initial boot image. If this + value is 0 the system will use the traditional segment of 7C0. If this value + is non-zero the system will use the specified segment. This applies to x86 + architectures only. For "flat" model architectures (such as Motorola) this + is the address divided by 10. */ + Byte SystemType; // This must be a copy of byte 5 (System Type) from the + // Partition Table found in the boot image. + UInt16 SectorCount; // This is the number of virtual/emulated sectors the system + // will store at Load Segment during the initial boot procedure. + UInt32 LoadRBA; // This is the start address of the virtual disk. CDÂ’s use + // Relative/Logical block addressing. + + UInt64 GetSize() const + { + // if (BootMediaType == NBootMediaType::k1d44Floppy) (1440 << 10); + return SectorCount * 512; + } + + UString GetName() const + { + UString s; + if (Bootable) + s += L"Bootable"; + else + s += L"NotBootable"; + s += L"_"; + if (BootMediaType >= kNumBootMediaTypes) + { + wchar_t name[16]; + ConvertUInt32ToString(BootMediaType, name); + s += name; + } + else + s += kMediaTypes[BootMediaType]; + s += L".img"; + return s; + } +}; + +struct CVolumeDescriptor +{ + Byte VolFlags; + Byte SystemId[32]; // a-characters. An identification of a system + // which can recognize and act upon the content of the Logical + // Sectors with logical Sector Numbers 0 to 15 of the volume. + Byte VolumeId[32]; // d-characters. An identification of the volume. + UInt32 VolumeSpaceSize; // the number of Logical Blocks in which the Volume Space of the volume is recorded + Byte EscapeSequence[32]; + UInt16 VolumeSetSize; + UInt16 VolumeSequenceNumber; // the ordinal number of the volume in the Volume Set of which the volume is a member. + UInt16 LogicalBlockSize; + UInt32 PathTableSize; + UInt32 LPathTableLocation; + UInt32 LOptionalPathTableLocation; + UInt32 MPathTableLocation; + UInt32 MOptionalPathTableLocation; + CDirRecord RootDirRecord; + Byte VolumeSetId[128]; + Byte PublisherId[128]; + Byte DataPreparerId[128]; + Byte ApplicationId[128]; + Byte CopyrightFileId[37]; + Byte AbstractFileId[37]; + Byte BibFileId[37]; + CDateTime CTime; + CDateTime MTime; + CDateTime ExpirationTime; + CDateTime EffectiveTime; + Byte FileStructureVersion; // = 1; + Byte ApplicationUse[512]; + + bool IsJoliet() const + { + if ((VolFlags & 1) != 0) + return false; + Byte b = EscapeSequence[2]; + return (EscapeSequence[0] == 0x25 && EscapeSequence[1] == 0x2F && + (b == 0x40 || b == 0x43 || b == 0x45)); + } +}; + +struct CRef +{ + CDir *Dir; + UInt32 Index; +}; + +const UInt32 kBlockSize = 1 << 11; + +class CInArchive +{ + CMyComPtr _stream; + UInt64 _position; + + Byte m_Buffer[kBlockSize]; + UInt32 m_BufferPos; + + CDir _rootDir; + bool _bootIsDefined; + CBootRecordDescriptor _bootDesc; + + void Skip(size_t size); + void SkipZeros(size_t size); + Byte ReadByte(); + void ReadBytes(Byte *data, UInt32 size); + UInt16 ReadUInt16Spec(); + UInt16 ReadUInt16(); + UInt32 ReadUInt32Le(); + UInt32 ReadUInt32Be(); + UInt32 ReadUInt32(); + UInt64 ReadUInt64(); + UInt32 ReadDigits(int numDigits); + void ReadDateTime(CDateTime &d); + void ReadRecordingDateTime(CRecordingDateTime &t); + void ReadDirRecord2(CDirRecord &r, Byte len); + void ReadDirRecord(CDirRecord &r); + + void ReadBootRecordDescriptor(CBootRecordDescriptor &d); + void ReadVolumeDescriptor(CVolumeDescriptor &d); + + void SeekToBlock(UInt32 blockIndex); + void ReadDir(CDir &d, int level); + void CreateRefs(CDir &d); + + void ReadBootInfo(); + HRESULT Open2(); +public: + HRESULT Open(IInStream *inStream); + void Clear(); + + UInt64 _archiveSize; + + CRecordVector Refs; + CObjectVector VolDescs; + int MainVolDescIndex; + UInt32 BlockSize; + CObjectVector BootEntries; + bool IncorrectBigEndian; + + + bool IsJoliet() const { return VolDescs[MainVolDescIndex].IsJoliet(); } + + UInt64 GetBootItemSize(int index) const + { + const CBootInitialEntry &be = BootEntries[index]; + UInt64 size = be.GetSize(); + if (be.BootMediaType == NBootMediaType::k1d2Floppy) + size = (1200 << 10); + else if (be.BootMediaType == NBootMediaType::k1d44Floppy) + size = (1440 << 10); + else if (be.BootMediaType == NBootMediaType::k2d88Floppy) + size = (2880 << 10); + UInt64 startPos = be.LoadRBA * BlockSize; + if (startPos < _archiveSize) + { + if (_archiveSize - startPos < size) + size = _archiveSize - startPos; + } + return size; + } + + bool IsSusp; + int SuspSkipSize; +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Iso/IsoItem.h b/CPP/7zip/Archive/Iso/IsoItem.h new file mode 100755 index 0000000..7788974 --- /dev/null +++ b/CPP/7zip/Archive/Iso/IsoItem.h @@ -0,0 +1,141 @@ +// Archive/IsoItem.h + +#ifndef __ARCHIVE_ISO_ITEM_H +#define __ARCHIVE_ISO_ITEM_H + +#include "Common/Types.h" +#include "Common/MyString.h" +#include "Common/Buffer.h" + +#include "Windows/Time.h" + +#include "IsoHeader.h" + +namespace NArchive { +namespace NIso { + +struct CRecordingDateTime +{ + Byte Year; + Byte Month; + Byte Day; + Byte Hour; + Byte Minute; + Byte Second; + signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded. + + bool GetFileTime(FILETIME &ft) const + { + UInt64 value; + bool res = NWindows::NTime::GetSecondsSince1601(Year + 1900, Month, Day, Hour, Minute, Second, value); + if (res) + { + value -= (UInt64)((Int64)GmtOffset * 15 * 60); + value *= 10000000; + } + ft.dwLowDateTime = (DWORD)value; + ft.dwHighDateTime = (DWORD)(value >> 32); + return res; + } +}; + +struct CDirRecord +{ + Byte ExtendedAttributeRecordLen; + UInt32 ExtentLocation; + UInt32 DataLength; + CRecordingDateTime DateTime; + Byte FileFlags; + Byte FileUnitSize; + Byte InterleaveGapSize; + UInt16 VolSequenceNumber; + CByteBuffer FileId; + CByteBuffer SystemUse; + + bool IsDir() const { return (FileFlags & NFileFlags::kDirectory) != 0; } + bool IsSystemItem() const + { + if (FileId.GetCapacity() != 1) + return false; + Byte b = *(const Byte *)FileId; + return (b == 0 || b == 1); + } + + const Byte* FindSuspName(int skipSize, int &lenRes) const + { + lenRes = 0; + const Byte *p = (const Byte *)SystemUse + skipSize; + int length = (int)(SystemUse.GetCapacity() - skipSize); + while (length >= 5) + { + int len = p[2]; + if (p[0] == 'N' && p[1] == 'M' && p[3] == 1) + { + lenRes = len - 5; + return p + 5; + } + p += len; + length -= len; + } + return 0; + } + + int GetLengthCur(bool checkSusp, int skipSize) const + { + if (checkSusp) + { + int len; + const Byte *res = FindSuspName(skipSize, len); + if (res != 0) + return len; + } + return (int)FileId.GetCapacity(); + } + + const Byte* GetNameCur(bool checkSusp, int skipSize) const + { + if (checkSusp) + { + int len; + const Byte *res = FindSuspName(skipSize, len); + if (res != 0) + return res; + } + return (const Byte *)FileId; + } + + + bool CheckSusp(const Byte *p, int &startPos) const + { + if (p[0] == 'S' && + p[1] == 'P' && + p[2] == 0x7 && + p[3] == 0x1 && + p[4] == 0xBE && + p[5] == 0xEF) + { + startPos = p[6]; + return true; + } + return false; + } + + bool CheckSusp(int &startPos) const + { + const Byte *p = (const Byte *)SystemUse; + int length = (int)SystemUse.GetCapacity(); + const int kMinLen = 7; + if (length < kMinLen) + return false; + if (CheckSusp(p, startPos)) + return true; + const int kOffset2 = 14; + if (length < kOffset2 + kMinLen) + return false; + return CheckSusp(p + kOffset2, startPos); + } +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Iso/IsoRegister.cpp b/CPP/7zip/Archive/Iso/IsoRegister.cpp new file mode 100755 index 0000000..e6e8ade --- /dev/null +++ b/CPP/7zip/Archive/Iso/IsoRegister.cpp @@ -0,0 +1,13 @@ +// IsoRegister.cpp + +#include "StdAfx.h" + +#include "../../Common/RegisterArc.h" + +#include "IsoHandler.h" +static IInArchive *CreateArc() { return new NArchive::NIso::CHandler; } + +static CArcInfo g_ArcInfo = + { L"Iso", L"iso img", 0, 0xE7, { 'C', 'D', '0', '0', '1', 0x1 }, 7, false, CreateArc, 0 }; + +REGISTER_ARC(Iso) diff --git a/CPP/7zip/Archive/Iso/StdAfx.h b/CPP/7zip/Archive/Iso/StdAfx.h new file mode 100755 index 0000000..a4e6173 --- /dev/null +++ b/CPP/7zip/Archive/Iso/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" +#include "../../../Common/NewHandler.h" + +#endif diff --git a/CPP/7zip/Archive/LzhHandler.cpp b/CPP/7zip/Archive/LzhHandler.cpp new file mode 100755 index 0000000..ce09b6a --- /dev/null +++ b/CPP/7zip/Archive/LzhHandler.cpp @@ -0,0 +1,775 @@ +// LzhHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Common/Buffer.h" +#include "Common/ComTry.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../ICoder.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" +#include "../Compress/LzhDecoder.h" + +#include "IArchive.h" + +#include "Common/ItemNameUtils.h" + +using namespace NWindows; +using namespace NTime; + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) + +namespace NArchive { +namespace NLzh{ + +const int kMethodIdSize = 5; + +const Byte kExtIdFileName = 0x01; +const Byte kExtIdDirName = 0x02; +const Byte kExtIdUnixTime = 0x54; + +struct CExtension +{ + Byte Type; + CByteBuffer Data; + AString GetString() const + { + AString s; + for (size_t i = 0; i < Data.GetCapacity(); i++) + { + char c = (char)Data[i]; + if (c == 0) + break; + s += c; + } + return s; + } +}; + +struct CItem +{ + AString Name; + Byte Method[kMethodIdSize]; + Byte Attributes; + Byte Level; + Byte OsId; + UInt32 PackSize; + UInt32 Size; + UInt32 ModifiedTime; + UInt16 CRC; + CObjectVector Extensions; + + bool IsValidMethod() const { return (Method[0] == '-' && Method[1] == 'l' && Method[4] == '-'); } + bool IsLhMethod() const {return (IsValidMethod() && Method[2] == 'h'); } + bool IsDir() const {return (IsLhMethod() && Method[3] == 'd'); } + + bool IsCopyMethod() const + { + return (IsLhMethod() && Method[3] == '0') || + (IsValidMethod() && Method[2] == 'z' && Method[3] == '4'); + } + + bool IsLh1GroupMethod() const + { + if (!IsLhMethod()) + return false; + switch(Method[3]) + { + case '1': + return true; + } + return false; + } + + bool IsLh4GroupMethod() const + { + if (!IsLhMethod()) + return false; + switch(Method[3]) + { + case '4': + case '5': + case '6': + case '7': + return true; + } + return false; + } + + int GetNumDictBits() const + { + if (!IsLhMethod()) + return 0; + switch(Method[3]) + { + case '1': return 12; + case '2': return 13; + case '3': return 13; + case '4': return 12; + case '5': return 13; + case '6': return 15; + case '7': return 16; + } + return 0; + } + + int FindExt(Byte type) const + { + for (int i = 0; i < Extensions.Size(); i++) + if (Extensions[i].Type == type) + return i; + return -1; + } + bool GetUnixTime(UInt32 &value) const + { + int index = FindExt(kExtIdUnixTime); + if (index < 0) + { + if (Level == 2) + { + value = ModifiedTime; + return true; + } + return false; + } + const Byte *data = (const Byte *)(Extensions[index].Data); + value = GetUi32(data); + return true; + } + + AString GetDirName() const + { + int index = FindExt(kExtIdDirName); + if (index < 0) + return AString(); + return Extensions[index].GetString(); + } + + AString GetFileName() const + { + int index = FindExt(kExtIdFileName); + if (index < 0) + return Name; + return Extensions[index].GetString(); + } + + AString GetName() const + { + AString dirName = GetDirName(); + const char kDirSeparator = '\\'; + // check kDirSeparator in Linux + dirName.Replace((char)(unsigned char)0xFF, kDirSeparator); + if (!dirName.IsEmpty() && dirName.Back() != kDirSeparator) + dirName += kDirSeparator; + return dirName + GetFileName(); + } +}; + +struct CItemEx: public CItem +{ + UInt64 DataPosition; +}; + +class CInArchive +{ + CMyComPtr m_Stream; + UInt64 m_Position; + + HRESULT ReadBytes(void *data, UInt32 size, UInt32 &processedSize); + HRESULT CheckReadBytes(void *data, UInt32 size); +public: + HRESULT Open(IInStream *inStream); + HRESULT GetNextItem(bool &filled, CItemEx &itemInfo); + HRESULT Skip(UInt64 numBytes); +}; + +HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize) +{ + size_t realProcessedSize = size; + RINOK(ReadStream(m_Stream, data, &realProcessedSize)); + processedSize = (UInt32)realProcessedSize; + m_Position += processedSize; + return S_OK; +} + +HRESULT CInArchive::CheckReadBytes(void *data, UInt32 size) +{ + UInt32 processedSize; + RINOK(ReadBytes(data, size, processedSize)); + return (processedSize == size) ? S_OK: S_FALSE; +} + +HRESULT CInArchive::Open(IInStream *inStream) +{ + RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position)); + m_Stream = inStream; + return S_OK; +} + +static const Byte *ReadUInt16(const Byte *p, UInt16 &v) +{ + v = Get16(p); + return p + 2; +} + +static const Byte *ReadString(const Byte *p, size_t size, AString &s) +{ + s.Empty(); + for (size_t i = 0; i < size; i++) + { + char c = p[i]; + if (c == 0) + break; + s += c; + } + return p + size; +} + +static Byte CalcSum(const Byte *data, size_t size) +{ + Byte sum = 0; + for (size_t i = 0; i < size; i++) + sum = (Byte)(sum + data[i]); + return sum; +} + +HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) +{ + filled = false; + + UInt32 processedSize; + Byte startHeader[2]; + RINOK(ReadBytes(startHeader, 2, processedSize)) + if (processedSize == 0) + return S_OK; + if (processedSize == 1) + return (startHeader[0] == 0) ? S_OK: S_FALSE; + if (startHeader[0] == 0 && startHeader[1] == 0) + return S_OK; + + Byte header[256]; + const UInt32 kBasicPartSize = 22; + RINOK(ReadBytes(header, kBasicPartSize, processedSize)); + if (processedSize != kBasicPartSize) + return (startHeader[0] == 0) ? S_OK: S_FALSE; + + const Byte *p = header; + memcpy(item.Method, p, kMethodIdSize); + if (!item.IsValidMethod()) + return S_OK; + p += kMethodIdSize; + item.PackSize = Get32(p); + item.Size = Get32(p + 4); + item.ModifiedTime = Get32(p + 8); + item.Attributes = p[12]; + item.Level = p[13]; + p += 14; + if (item.Level > 2) + return S_FALSE; + UInt32 headerSize; + if (item.Level < 2) + { + headerSize = startHeader[0]; + if (headerSize < kBasicPartSize) + return S_FALSE; + UInt32 remain = headerSize - kBasicPartSize; + RINOK(CheckReadBytes(header + kBasicPartSize, remain)); + if (startHeader[1] != CalcSum(header, headerSize)) + return S_FALSE; + size_t nameLength = *p++; + if ((p - header) + nameLength + 2 > headerSize) + return S_FALSE; + p = ReadString(p, nameLength, item.Name); + } + else + headerSize = startHeader[0] | ((UInt32)startHeader[1] << 8); + p = ReadUInt16(p, item.CRC); + if (item.Level != 0) + { + if (item.Level == 2) + { + RINOK(CheckReadBytes(header + kBasicPartSize, 2)); + } + if ((size_t)(p - header) + 3 > headerSize) + return S_FALSE; + item.OsId = *p++; + UInt16 nextSize; + p = ReadUInt16(p, nextSize); + while (nextSize != 0) + { + if (nextSize < 3) + return S_FALSE; + if (item.Level == 1) + { + if (item.PackSize < nextSize) + return S_FALSE; + item.PackSize -= nextSize; + } + CExtension ext; + RINOK(CheckReadBytes(&ext.Type, 1)) + nextSize -= 3; + ext.Data.SetCapacity(nextSize); + RINOK(CheckReadBytes((Byte *)ext.Data, nextSize)) + item.Extensions.Add(ext); + Byte hdr2[2]; + RINOK(CheckReadBytes(hdr2, 2)); + ReadUInt16(hdr2, nextSize); + } + } + item.DataPosition = m_Position; + filled = true; + return S_OK; +} + +HRESULT CInArchive::Skip(UInt64 numBytes) +{ + UInt64 newPostion; + RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion)); + m_Position += numBytes; + if (m_Position != newPostion) + return E_FAIL; + return S_OK; +} + +struct COsPair +{ + Byte Id; + const char *Name; +}; + +static COsPair g_OsPairs[] = +{ + { 0, "MS-DOS" }, + { 'M', "MS-DOS" }, + { '2', "OS/2" }, + { '9', "OS9" }, + { 'K', "OS/68K" }, + { '3', "OS/386" }, + { 'H', "HUMAN" }, + { 'U', "UNIX" }, + { 'C', "CP/M" }, + { 'F', "FLEX" }, + { 'm', "Mac" }, + { 'R', "Runser" }, + { 'T', "TownsOS" }, + { 'X', "XOSK" }, + { 'w', "Windows 95" }, + { 'W', "Windows NT" }, + { 'J', "Java VM" } +}; + +static const char *kUnknownOS = "Unknown"; + +static const char *GetOS(Byte osId) +{ + for (int i = 0; i < sizeof(g_OsPairs) / sizeof(g_OsPairs[0]); i++) + if (g_OsPairs[i].Id == osId) + return g_OsPairs[i].Name; + return kUnknownOS; +} + +static STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + // { NULL, kpidAttrib, VT_UI4}, + { NULL, kpidCRC, VT_UI4}, + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidHostOS, VT_BSTR} +}; + +class CCRC +{ + UInt16 _value; +public: + static UInt16 Table[256]; + static void InitTable(); + + CCRC(): _value(0) {} + void Init() { _value = 0; } + void Update(const void *data, size_t size); + UInt16 GetDigest() const { return _value; } +}; + +static const UInt16 kCRCPoly = 0xA001; + +UInt16 CCRC::Table[256]; + +void CCRC::InitTable() +{ + for (UInt32 i = 0; i < 256; i++) + { + UInt32 r = i; + for (int j = 0; j < 8; j++) + if (r & 1) + r = (r >> 1) ^ kCRCPoly; + else + r >>= 1; + CCRC::Table[i] = (UInt16)r; + } +} + +class CCRCTableInit +{ +public: + CCRCTableInit() { CCRC::InitTable(); } +} g_CRCTableInit; + +void CCRC::Update(const void *data, size_t size) +{ + UInt16 v = _value; + const Byte *p = (const Byte *)data; + for (; size > 0; size--, p++) + v = (UInt16)(Table[((Byte)(v)) ^ *p] ^ (v >> 8)); + _value = v; +} + + +class COutStreamWithCRC: + public ISequentialOutStream, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +private: + CCRC _crc; + CMyComPtr _stream; +public: + void Init(ISequentialOutStream *stream) + { + _stream = stream; + _crc.Init(); + } + void ReleaseStream() { _stream.Release(); } + UInt32 GetCRC() const { return _crc.GetDigest(); } + void InitCRC() { _crc.Init(); } +}; + +STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessedSize; + HRESULT result; + if (!_stream) + { + realProcessedSize = size; + result = S_OK; + } + else + result = _stream->Write(data, size, &realProcessedSize); + _crc.Update(data, realProcessedSize); + if (processedSize != NULL) + *processedSize = realProcessedSize; + return result; +} + +class CHandler: + public IInArchive, + public CMyUnknownImp +{ + CObjectVector _items; + CMyComPtr _stream; +public: + MY_UNKNOWN_IMP1(IInArchive) + INTERFACE_IInArchive(;) + CHandler(); +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO + +CHandler::CHandler() {} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _items.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + const CItemEx &item = _items[index]; + switch(propID) + { + case kpidPath: + { + UString s = NItemName::WinNameToOSName(MultiByteToUnicodeString(item.GetName(), CP_OEMCP)); + if (!s.IsEmpty()) + { + if (s[s.Length() - 1] == WCHAR_PATH_SEPARATOR) + s.Delete(s.Length() - 1); + prop = s; + } + break; + } + case kpidIsDir: prop = item.IsDir(); break; + case kpidSize: prop = item.Size; break; + case kpidPackSize: prop = item.PackSize; break; + case kpidCRC: prop = (UInt32)item.CRC; break; + case kpidHostOS: prop = GetOS(item.OsId); break; + case kpidMTime: + { + FILETIME utc; + UInt32 unixTime; + if (item.GetUnixTime(unixTime)) + NTime::UnixTimeToFileTime(unixTime, utc); + else + { + FILETIME localFileTime; + if (DosTimeToFileTime(item.ModifiedTime, localFileTime)) + { + if (!LocalFileTimeToFileTime(&localFileTime, &utc)) + utc.dwHighDateTime = utc.dwLowDateTime = 0; + } + else + utc.dwHighDateTime = utc.dwLowDateTime = 0; + } + prop = utc; + break; + } + // case kpidAttrib: prop = (UInt32)item.Attributes; break; + case kpidMethod: + { + char method2[kMethodIdSize + 1]; + method2[kMethodIdSize] = 0; + memcpy(method2, item.Method, kMethodIdSize); + prop = method2; + break; + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Open(IInStream *stream, + const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + try + { + _items.Clear(); + CInArchive archive; + + UInt64 endPos = 0; + bool needSetTotal = true; + + if (callback != NULL) + { + RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos)); + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + } + + RINOK(archive.Open(stream)); + for (;;) + { + CItemEx item; + bool filled; + HRESULT result = archive.GetNextItem(filled, item); + if (result == S_FALSE) + return S_FALSE; + if (result != S_OK) + return S_FALSE; + if (!filled) + break; + _items.Add(item); + archive.Skip(item.PackSize); + if (callback != NULL) + { + if (needSetTotal) + { + RINOK(callback->SetTotal(NULL, &endPos)); + needSetTotal = false; + } + if (_items.Size() % 100 == 0) + { + UInt64 numFiles = _items.Size(); + UInt64 numBytes = item.DataPosition; + RINOK(callback->SetCompleted(&numFiles, &numBytes)); + } + } + } + if (_items.IsEmpty()) + return S_FALSE; + + _stream = stream; + } + catch(...) + { + return S_FALSE; + } + COM_TRY_END + return S_OK; +} + +STDMETHODIMP CHandler::Close() +{ + _items.Clear(); + _stream.Release(); + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testModeSpec, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool testMode = (testModeSpec != 0); + UInt64 totalUnPacked = 0, totalPacked = 0; + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _items.Size(); + if (numItems == 0) + return S_OK; + UInt32 i; + for (i = 0; i < numItems; i++) + { + const CItemEx &item = _items[allFilesMode ? i : indices[i]]; + totalUnPacked += item.Size; + totalPacked += item.PackSize; + } + RINOK(extractCallback->SetTotal(totalUnPacked)); + + UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0; + UInt64 currentItemUnPacked, currentItemPacked; + + NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = 0; + CMyComPtr lzhDecoder; + CMyComPtr lzh1Decoder; + CMyComPtr arj2Decoder; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStream(streamSpec); + streamSpec->SetStream(_stream); + + for (i = 0; i < numItems; i++, currentTotalUnPacked += currentItemUnPacked, + currentTotalPacked += currentItemPacked) + { + currentItemUnPacked = 0; + currentItemPacked = 0; + + lps->InSize = currentTotalPacked; + lps->OutSize = currentTotalUnPacked; + RINOK(lps->SetCur()); + + CMyComPtr realOutStream; + Int32 askMode; + askMode = testMode ? NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + const CItemEx &item = _items[index]; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + if (item.IsDir()) + { + // if (!testMode) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + } + continue; + } + + if (!testMode && !realOutStream) + continue; + + RINOK(extractCallback->PrepareOperation(askMode)); + currentItemUnPacked = item.Size; + currentItemPacked = item.PackSize; + + { + COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; + CMyComPtr outStream(outStreamSpec); + outStreamSpec->Init(realOutStream); + realOutStream.Release(); + + UInt64 pos; + _stream->Seek(item.DataPosition, STREAM_SEEK_SET, &pos); + + streamSpec->Init(item.PackSize); + + HRESULT result = S_OK; + Int32 opRes = NExtract::NOperationResult::kOK; + + if (item.IsCopyMethod()) + { + result = copyCoder->Code(inStream, outStream, NULL, NULL, progress); + if (result == S_OK && copyCoderSpec->TotalSize != item.PackSize) + result = S_FALSE; + } + else if (item.IsLh4GroupMethod()) + { + if (!lzhDecoder) + { + lzhDecoderSpec = new NCompress::NLzh::NDecoder::CCoder; + lzhDecoder = lzhDecoderSpec; + } + lzhDecoderSpec->SetDictionary(item.GetNumDictBits()); + result = lzhDecoder->Code(inStream, outStream, NULL, ¤tItemUnPacked, progress); + } + /* + else if (item.IsLh1GroupMethod()) + { + if (!lzh1Decoder) + { + lzh1DecoderSpec = new NCompress::NLzh1::NDecoder::CCoder; + lzh1Decoder = lzh1DecoderSpec; + } + lzh1DecoderSpec->SetDictionary(item.GetNumDictBits()); + result = lzh1Decoder->Code(inStream, outStream, NULL, ¤tItemUnPacked, progress); + } + */ + else + opRes = NExtract::NOperationResult::kUnSupportedMethod; + + if (opRes == NExtract::NOperationResult::kOK) + { + if (result == S_FALSE) + opRes = NExtract::NOperationResult::kDataError; + else + { + RINOK(result); + if (outStreamSpec->GetCRC() != item.CRC) + opRes = NExtract::NOperationResult::kCRCError; + } + } + outStream.Release(); + RINOK(extractCallback->SetOperationResult(opRes)); + } + } + return S_OK; + COM_TRY_END +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"Lzh", L"lzh lha", 0, 6, { '-', 'l' }, 2, false, CreateArc, 0 }; + +REGISTER_ARC(Lzh) + +}} diff --git a/CPP/7zip/Archive/LzmaHandler.cpp b/CPP/7zip/Archive/LzmaHandler.cpp new file mode 100755 index 0000000..9b8db45 --- /dev/null +++ b/CPP/7zip/Archive/LzmaHandler.cpp @@ -0,0 +1,430 @@ +// LzmaHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Common/ComTry.h" +#include "Common/IntToString.h" + +#include "Windows/PropVariant.h" + +#include "../Common/CreateCoder.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.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); + for (int i = 1; i <= 30; i++) + if (dicSize == ((UInt32)2 << i) || dicSize == ((UInt32)3 << i)) + return true; + return (dicSize == 0xFFFFFFFF); +} + +STATPROPSTG kProps[] = +{ + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMethod, VT_BSTR} +}; + +struct CHeader +{ + UInt64 Size; + Byte FilterID; + Byte LzmaProps[5]; + + 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 +{ + NCompress::NLzma::CDecoder *_lzmaDecoderSpec; + CMyComPtr _lzmaDecoder; + CMyComPtr _bcjStream; +public: + ~CDecoder(); + HRESULT Create(DECL_EXTERNAL_CODECS_LOC_VARS + 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); } +}; + +static const UInt64 k_BCJ = 0x03030103; + +HRESULT CDecoder::Create( + DECL_EXTERNAL_CODECS_LOC_VARS + bool filteredMode, ISequentialInStream *inStream) +{ + if (!_lzmaDecoder) + { + _lzmaDecoderSpec = new NCompress::NLzma::CDecoder; + _lzmaDecoder = _lzmaDecoderSpec; + } + + if (filteredMode) + { + if (!_bcjStream) + { + CMyComPtr coder; + RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_BCJ, coder, false)); + if (!coder) + return E_NOTIMPL; + coder.QueryInterface(IID_ISequentialOutStream, &_bcjStream); + if (!_bcjStream) + return E_NOTIMPL; + } + } + + 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)); + } + + CMyComPtr setOutStream; + + bool filteredMode = (header.FilterID == 1); + + if (filteredMode) + { + _bcjStream.QueryInterface(IID_ICompressSetOutStream, &setOutStream); + if (!setOutStream) + return E_NOTIMPL; + RINOK(setOutStream->SetOutStream(outStream)); + outStream = _bcjStream; + } + + const UInt64 *Size = header.HasSize() ? &header.Size : NULL; + HRESULT res = _lzmaDecoderSpec->CodeResume(outStream, Size, progress); + + if (filteredMode) + { + CMyComPtr flush; + _bcjStream.QueryInterface(IID_IOutStreamFlush, &flush); + if (flush) + { + HRESULT res2 = flush->Flush(); + if (res == S_OK) + res = res2; + } + HRESULT res2 = setOutStream->ReleaseOutStream(); + if (res == S_OK) + res = res2; + } + RINOK(res); + + return S_OK; +} + + +class CHandler: + public IInArchive, + public IArchiveOpenSeq, + PUBLIC_ISetCompressCodecsInfo + public CMyUnknownImp +{ + CHeader _header; + bool _lzma86; + UInt64 _startPosition; + UInt64 _packSize; + bool _packSizeDefined; + CMyComPtr _stream; + CMyComPtr _seqStream; + + DECL_EXTERNAL_CODECS_VARS + DECL_ISetCompressCodecsInfo + +public: + MY_QUERYINTERFACE_BEGIN2(IInArchive) + MY_QUERYINTERFACE_ENTRY(IArchiveOpenSeq) + QUERY_ENTRY_ISetCompressCodecsInfo + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + 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_NO_Table + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidPhySize: if (_packSizeDefined) prop = _packSize; break; + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = 1; + return S_OK; +} + +static void DictSizeToString(UInt32 value, char *s) +{ + for (int i = 0; i <= 31; i++) + if ((UInt32(1) << i) == value) + { + ::ConvertUInt32ToString(i, s); + return; + } + char c = 'b'; + if ((value & ((1 << 20) - 1)) == 0) + { + value >>= 20; + c = 'm'; + } + else if ((value & ((1 << 10) - 1)) == 0) + { + value >>= 10; + c = 'k'; + } + ::ConvertUInt32ToString(value, s); + int p = MyStringLen(s); + s[p++] = c; + s[p++] = '\0'; +} + +static void MyStrCat(char *d, const char *s) +{ + MyStringCopy(d + MyStringLen(d), s); +} + +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 (_packSizeDefined) prop = _packSize; break; + case kpidMethod: + if (_stream) + { + char s[64]; + s[0] = '\0'; + if (_header.FilterID != 0) + MyStrCat(s, "BCJ "); + MyStrCat(s, "LZMA:"); + DictSizeToString(_header.GetDicSize(), s + MyStringLen(s)); + prop = s; + } + break; + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *) +{ + RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &_startPosition)); + + const UInt32 kBufSize = 1 + 5 + 8 + 1; + 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) + return S_FALSE; + + UInt64 endPos; + RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos)); + _packSize = endPos - _startPosition; + _packSizeDefined = true; + + _stream = inStream; + _seqStream = inStream; + return S_OK; +} + +STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) +{ + Close(); + _seqStream = stream; + return S_OK; +} + +STDMETHODIMP CHandler::Close() +{ + _packSizeDefined = false; + _stream.Release(); + _seqStream.Release(); + 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)-1 && (numItems != 1 || indices[0] != 0)) + return E_INVALIDARG; + + if (_stream) + 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 (_stream) + { + RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); + } + + CDecoder decoder; + HRESULT result = decoder.Create( + EXTERNAL_CODECS_VARS + _lzma86, _seqStream); + RINOK(result); + + Int32 opRes = NExtract::NOperationResult::kOK; + bool firstItem = true; + + for (;;) + { + lps->OutSize = outStreamSpec->GetSize(); + lps->InSize = _packSize = decoder.GetInputProcessedSize(); + _packSizeDefined = true; + RINOK(lps->SetCur()); + + CHeader st; + + const UInt32 kBufSize = 1 + 5 + 8; + Byte buf[kBufSize]; + const UInt32 headerSize = GetHeaderSize(); + UInt32 processed; + RINOK(decoder.ReadInput(buf, headerSize, &processed)); + if (processed != headerSize) + break; + + if (!st.Parse(buf, _lzma86)) + break; + firstItem = false; + + result = decoder.Code(st, outStream, progress); + if (result == E_NOTIMPL) + { + opRes = NExtract::NOperationResult::kUnSupportedMethod; + break; + } + if (result == S_FALSE) + { + opRes = NExtract::NOperationResult::kDataError; + break; + } + RINOK(result); + } + if (firstItem) + return E_FAIL; + outStream.Release(); + return extractCallback->SetOperationResult(opRes); + COM_TRY_END +} + +IMPL_ISetCompressCodecsInfo + +static IInArchive *CreateArc() { return new CHandler(false); } +static IInArchive *CreateArc86() { return new CHandler(true); } + +namespace NLzmaAr { + +static CArcInfo g_ArcInfo = + { L"lzma", L"lzma", 0, 0xA, { 0 }, 0, true, CreateArc, NULL }; +REGISTER_ARC(Lzma) + +} + +namespace NLzma86Ar { + +static CArcInfo g_ArcInfo = + { L"lzma86", L"lzma86", 0, 0xB, { 0 }, 0, true, CreateArc86, NULL }; +REGISTER_ARC(Lzma86) + +} + +}} diff --git a/CPP/7zip/Archive/MachoHandler.cpp b/CPP/7zip/Archive/MachoHandler.cpp new file mode 100755 index 0000000..4f3e37f --- /dev/null +++ b/CPP/7zip/Archive/MachoHandler.cpp @@ -0,0 +1,500 @@ +// MachoHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Common/Buffer.h" +#include "Common/ComTry.h" + +#include "Windows/PropVariantUtils.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +static UInt32 Get32(const Byte *p, int be) { if (be) return GetBe32(p); return GetUi32(p); } +static UInt64 Get64(const Byte *p, int be) { if (be) return GetBe64(p); return GetUi64(p); } + +using namespace NWindows; + +namespace NArchive { +namespace NMacho { + +#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) + +#define MACH_CMD_SEGMENT_32 1 +#define MACH_CMD_SEGMENT_64 0x19 + +#define MACH_SECT_TYPE_MASK 0x000000FF +#define MACH_SECT_ATTR_MASK 0xFFFFFF00 + +#define MACH_SECT_ATTR_ZEROFILL 1 + +static const char *g_SectTypes[] = +{ + "REGULAR", + "ZEROFILL", + "CSTRINGS", + "4BYTE_LITERALS", + "8BYTE_LITERALS", + "LITERAL_POINTERS", + "NON_LAZY_SYMBOL_POINTERS", + "LAZY_SYMBOL_POINTERS", + "SYMBOL_STUBS", + "MOD_INIT_FUNC_POINTERS", + "MOD_TERM_FUNC_POINTERS", + "COALESCED", + "GB_ZEROFILL", + "INTERPOSING", + "16BYTE_LITERALS" +}; + +static const char *g_FileTypes[] = +{ + "0", + "OBJECT", + "EXECUTE", + "FVMLIB", + "CORE", + "PRELOAD", + "DYLIB", + "DYLINKER", + "BUNDLE", + "DYLIB_STUB", + "DSYM" +}; + +static const CUInt32PCharPair g_Flags[] = +{ + { 31, "PURE_INSTRUCTIONS" }, + { 30, "NO_TOC" }, + { 29, "STRIP_STATIC_SYMS" }, + { 28, "NO_DEAD_STRIP" }, + { 27, "LIVE_SUPPORT" }, + { 26, "SELF_MODIFYING_CODE" }, + { 25, "DEBUG" }, + { 10, "SOME_INSTRUCTIONS" }, + { 9, "EXT_RELOC" }, + { 8, "LOC_RELOC" } +}; + +static const CUInt32PCharPair g_MachinePairs[] = +{ + { MACH_MACHINE_386, "x86" }, + { MACH_MACHINE_ARM, "ARM" }, + { MACH_MACHINE_SPARC, "SPARC" }, + { MACH_MACHINE_PPC, "PowerPC" }, + { MACH_MACHINE_PPC64, "PowerPC 64-bit" }, + { MACH_MACHINE_AMD64, "x64" } +}; + +static const int kNameSize = 16; + +struct CSegment +{ + char Name[kNameSize]; +}; + +struct CSection +{ + char Name[kNameSize]; + char SegName[kNameSize]; + UInt64 Va; + UInt64 Pa; + UInt64 VSize; + UInt64 PSize; + + UInt32 Flags; + int SegmentIndex; + + bool IsDummy; + + CSection(): IsDummy(false) {} + // UInt64 GetPackSize() const { return Flags == MACH_SECT_ATTR_ZEROFILL ? 0 : Size; } + UInt64 GetPackSize() const { return PSize; } +}; + + +class CHandler: + public IInArchive, + public CMyUnknownImp +{ + CMyComPtr _inStream; + CObjectVector _segments; + CObjectVector _sections; + bool _mode64; + bool _be; + UInt32 _machine; + UInt32 _type; + UInt32 _headersSize; + UInt64 _totalSize; + HRESULT Open2(ISequentialInStream *stream); + bool Parse(const Byte *buf, UInt32 size); +public: + MY_UNKNOWN_IMP1(IInArchive) + INTERFACE_IInArchive(;) +}; + +bool CHandler::Parse(const Byte *buf, UInt32 size) +{ + bool mode64 = _mode64; + bool be = _be; + + const Byte *bufStart = buf; + bool reduceCommands = false; + if (size < 512) + return false; + + _machine = Get32(buf + 4, be); + _type = Get32(buf + 0xC, be); + + UInt32 numCommands = Get32(buf + 0x10, be); + UInt32 commandsSize = Get32(buf + 0x14, be); + if (commandsSize > size) + return false; + + if (commandsSize > (1 << 24) || numCommands > (1 << 18)) + return false; + + if (numCommands > 16) + { + reduceCommands = true; + numCommands = 16; + } + + _headersSize = 0; + + buf += 0x1C; + size -= 0x1C; + + if (mode64) + { + buf += 4; + size -= 4; + } + + _totalSize = (UInt32)(buf - bufStart); + if (commandsSize < size) + size = commandsSize; + + for (UInt32 cmdIndex = 0; cmdIndex < numCommands; cmdIndex++) + { + if (size < 8) + return false; + UInt32 cmd = Get32(buf, be); + UInt32 cmdSize = Get32(buf + 4, be); + if (size < cmdSize) + return false; + if (cmd == MACH_CMD_SEGMENT_32 || cmd == MACH_CMD_SEGMENT_64) + { + UInt32 offs = (cmd == MACH_CMD_SEGMENT_64) ? 0x48 : 0x38; + if (cmdSize < offs) + break; + + UInt64 vmAddr, vmSize, phAddr, phSize; + + { + if (cmd == MACH_CMD_SEGMENT_64) + { + vmAddr = Get64(buf + 0x18, be); + vmSize = Get64(buf + 0x20, be); + phAddr = Get64(buf + 0x28, be); + phSize = Get64(buf + 0x30, be); + } + else + { + vmAddr = Get32(buf + 0x18, be); + vmSize = Get32(buf + 0x1C, be); + phAddr = Get32(buf + 0x20, be); + phSize = Get32(buf + 0x24, be); + } + { + UInt64 totalSize = phAddr + phSize; + if (totalSize > _totalSize) + _totalSize = totalSize; + } + } + + CSegment seg; + memcpy(seg.Name, buf + 8, kNameSize); + _segments.Add(seg); + + UInt32 numSections = Get32(buf + offs - 8, be); + if (numSections > (1 << 8)) + return false; + + if (numSections == 0) + { + CSection section; + section.IsDummy = true; + section.SegmentIndex = _segments.Size() - 1; + section.Va = vmAddr; + section.PSize = phSize; + section.VSize = vmSize; + section.Pa = phAddr; + section.Flags = 0; + _sections.Add(section); + } + else do + { + CSection section; + UInt32 headerSize = (cmd == MACH_CMD_SEGMENT_64) ? 0x50 : 0x44; + const Byte *p = buf + offs; + if (cmdSize - offs < headerSize) + break; + if (cmd == MACH_CMD_SEGMENT_64) + { + section.Va = Get64(p + 0x20, be); + section.VSize = Get64(p + 0x28, be); + section.Pa = Get32(p + 0x30, be); + section.Flags = Get32(p + 0x40, be); + } + else + { + section.Va = Get32(p + 0x20, be); + section.VSize = Get32(p + 0x24, be); + section.Pa = Get32(p + 0x28, be); + section.Flags = Get32(p + 0x38, be); + } + if (section.Flags == MACH_SECT_ATTR_ZEROFILL) + section.PSize = 0; + else + section.PSize = section.VSize; + memcpy(section.Name, p, kNameSize); + memcpy(section.SegName, p + kNameSize, kNameSize); + section.SegmentIndex = _segments.Size() - 1; + _sections.Add(section); + offs += headerSize; + } + while (--numSections); + + if (offs != cmdSize) + return false; + } + buf += cmdSize; + size -= cmdSize; + } + _headersSize = (UInt32)(buf - bufStart); + return reduceCommands || (size == 0); +} + +static STATPROPSTG kArcProps[] = +{ + { NULL, kpidCpu, VT_BSTR}, + { NULL, kpidBit64, VT_BOOL}, + { NULL, kpidBigEndian, VT_BOOL}, + { NULL, kpidCharacts, VT_BSTR}, + { NULL, kpidPhySize, VT_UI8}, + { NULL, kpidHeadersSize, VT_UI4} +}; + +static STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidCharacts, VT_BSTR}, + { NULL, kpidOffset, VT_UI8}, + { NULL, kpidVa, VT_UI8} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NCOM::CPropVariant prop; + switch(propID) + { + case kpidCpu: PAIR_TO_PROP(g_MachinePairs, _machine, prop); break; + case kpidCharacts: TYPE_TO_PROP(g_FileTypes, _type, prop); break; + case kpidPhySize: prop = _totalSize; break; + case kpidHeadersSize: prop = _headersSize; break; + case kpidBit64: if (_mode64) prop = _mode64; break; + case kpidBigEndian: if (_be) prop = _be; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +static AString GetName(const char *name) +{ + char res[kNameSize + 1]; + memcpy(res, name, kNameSize); + res[kNameSize] = 0; + return res; +} + +static AString SectFlagsToString(UInt32 flags) +{ + AString res = TypeToString(g_SectTypes, sizeof(g_SectTypes) / sizeof(g_SectTypes[0]), + flags & MACH_SECT_TYPE_MASK); + AString s = FlagsToString(g_Flags, sizeof(g_Flags) / sizeof(g_Flags[0]), + flags & MACH_SECT_ATTR_MASK); + if (!s.IsEmpty()) + { + res += ' '; + res += s; + } + return res; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NCOM::CPropVariant prop; + const CSection &item = _sections[index]; + switch(propID) + { + case kpidPath: + { + AString s = GetName(_segments[item.SegmentIndex].Name); + if (!item.IsDummy) + s += GetName(item.Name); + StringToProp(s, prop); + break; + } + case kpidSize: /* prop = (UInt64)item.VSize; break; */ + case kpidPackSize: prop = (UInt64)item.GetPackSize(); break; + case kpidCharacts: if (!item.IsDummy) StringToProp(SectFlagsToString(item.Flags), prop); break; + case kpidOffset: prop = item.Pa; break; + case kpidVa: prop = item.Va; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +HRESULT CHandler::Open2(ISequentialInStream *stream) +{ + const UInt32 kBufSize = 1 << 18; + const UInt32 kSigSize = 4; + + CByteBuffer buffer; + buffer.SetCapacity(kBufSize); + Byte *buf = buffer; + + size_t processed = kSigSize; + RINOK(ReadStream_FALSE(stream, buf, processed)); + UInt32 sig = GetUi32(buf); + bool be, mode64; + switch(sig) + { + case 0xCEFAEDFE: be = true; mode64 = false; break; + case 0xCFFAEDFE: be = true; mode64 = true; break; + case 0xFEEDFACE: be = false; mode64 = false; break; + case 0xFEEDFACF: be = false; mode64 = true; break; + default: return S_FALSE; + } + processed = kBufSize - kSigSize; + RINOK(ReadStream(stream, buf + kSigSize, &processed)); + _mode64 = mode64; + _be = be; + return Parse(buf, (UInt32)processed + kSigSize) ? S_OK : S_FALSE; +} + +STDMETHODIMP CHandler::Open(IInStream *inStream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback * /* openArchiveCallback */) +{ + COM_TRY_BEGIN + Close(); + RINOK(Open2(inStream)); + _inStream = inStream; + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _inStream.Release(); + _sections.Clear(); + _segments.Clear(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _sections.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _sections.Size(); + if (numItems == 0) + return S_OK; + UInt64 totalSize = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + totalSize += _sections[allFilesMode ? i : indices[i]].GetPackSize(); + extractCallback->SetTotal(totalSize); + + UInt64 currentTotalSize = 0; + UInt64 currentItemSize; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStream(streamSpec); + streamSpec->SetStream(_inStream); + + for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) + { + lps->InSize = lps->OutSize = currentTotalSize; + RINOK(lps->SetCur()); + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + UInt32 index = allFilesMode ? i : indices[i]; + const CSection &item = _sections[index]; + currentItemSize = item.GetPackSize(); + + CMyComPtr outStream; + RINOK(extractCallback->GetStream(index, &outStream, askMode)); + if (!testMode && !outStream) + continue; + + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(_inStream->Seek(item.Pa, STREAM_SEEK_SET, NULL)); + streamSpec->Init(currentItemSize); + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + outStream.Release(); + RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == currentItemSize ? + NExtract::NOperationResult::kOK: + NExtract::NOperationResult::kDataError)); + } + return S_OK; + COM_TRY_END +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"MachO", L"", 0, 0xDF, { 0 }, 0, false, CreateArc, 0 }; + +REGISTER_ARC(Macho) + +}} diff --git a/CPP/7zip/Archive/MbrHandler.cpp b/CPP/7zip/Archive/MbrHandler.cpp new file mode 100755 index 0000000..8fb9a8e --- /dev/null +++ b/CPP/7zip/Archive/MbrHandler.cpp @@ -0,0 +1,507 @@ +// MbrHandler.cpp + +#include "StdAfx.h" + +// #define SHOW_DEBUG_INFO + +#ifdef SHOW_DEBUG_INFO +#include +#endif + +#include "../../../C/CpuArch.h" + +#include "Common/Buffer.h" +#include "Common/ComTry.h" +#include "Common/IntToString.h" +#include "Common/MyString.h" + +#include "Windows/PropVariant.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif + +using namespace NWindows; + +namespace NArchive { +namespace NMbr { + +struct CChs +{ + Byte Head; + Byte SectCyl; + Byte Cyl8; + + UInt32 GetSector() const { return SectCyl & 0x3F; } + UInt32 GetCyl() const { return ((UInt32)SectCyl >> 6 << 8) | Cyl8; } + void ToString(NCOM::CPropVariant &prop) const; + + void Parse(const Byte *p) + { + Head = p[0]; + SectCyl = p[1]; + Cyl8 = p[2]; + } + bool Check() const { return GetSector() > 0; } +}; + +#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } + +static int CompareChs(const CChs &c1, const CChs &c2) +{ + RINOZ(MyCompare(c1.GetCyl(), c2.GetCyl())); + RINOZ(MyCompare(c1.Head, c2.Head)); + return MyCompare(c1.GetSector(), c2.GetSector()); +} + +static void AddUIntToString(UInt32 val, AString &res) +{ + char s[16]; + ConvertUInt32ToString(val, s); + res += s; +} + +void CChs::ToString(NCOM::CPropVariant &prop) const +{ + AString s; + AddUIntToString(GetCyl(), s); + s += '-'; + AddUIntToString(Head, s); + s += '-'; + AddUIntToString(GetSector(), s); + prop = s; +} + +struct CPartition +{ + Byte Status; + CChs BeginChs; + Byte Type; + CChs EndChs; + UInt32 Lba; + UInt32 NumBlocks; + + CPartition() { memset (this, 0, sizeof(*this)); } + + bool IsEmpty() const { return Type == 0; } + bool IsExtended() const { return Type == 5 || Type == 0xF; } + UInt32 GetLimit() const { return Lba + NumBlocks; } + // bool IsActive() const { return Status == 0x80; } + UInt64 GetPos() const { return (UInt64)Lba * 512; } + UInt64 GetSize() const { return (UInt64)NumBlocks * 512; } + + bool CheckLbaLimits() const { return (UInt32)0xFFFFFFFF - Lba >= NumBlocks; } + bool Parse(const Byte *p) + { + Status = p[0]; + BeginChs.Parse(p + 1); + Type = p[4]; + EndChs.Parse(p + 5); + Lba = GetUi32(p + 8); + NumBlocks = GetUi32(p + 12); + if (Type == 0) + return true; + if (Status != 0 && Status != 0x80) + return false; + return + BeginChs.Check() && + EndChs.Check() && + CompareChs(BeginChs, EndChs) <= 0 && + NumBlocks > 0 && + CheckLbaLimits(); + } + + #ifdef SHOW_DEBUG_INFO + void Print() const + { + NCOM::CPropVariant prop, prop2; + BeginChs.ToString(prop); + EndChs.ToString(prop2); + printf(" %2x %2x %8X %8X %12S %12S", (int)Status, (int)Type, Lba, NumBlocks, prop.bstrVal, prop2.bstrVal); + } + #endif +}; + +struct CPartType +{ + UInt32 Id; + const char *Ext; + const char *Name; +}; + +static const char *kFat = "fat"; + +static const CPartType kPartTypes[] = +{ + { 0x01, kFat, "FAT12" }, + { 0x04, kFat, "FAT16 DOS 3.0+" }, + { 0x05, 0, "Extended" }, + { 0x06, kFat, "FAT16 DOS 3.31+" }, + { 0x07, "ntfs", "NTFS" }, + { 0x0B, kFat, "FAT32" }, + { 0x0C, kFat, "FAT32-LBA" }, + { 0x0E, kFat, "FAT16-LBA" }, + { 0x0F, 0, "Extended-LBA" }, + { 0x11, kFat, "FAT12-Hidden" }, + { 0x14, kFat, "FAT16-Hidden < 32 MB" }, + { 0x16, kFat, "FAT16-Hidden >= 32 MB" }, + { 0x1B, kFat, "FAT32-Hidden" }, + { 0x1C, kFat, "FAT32-LBA-Hidden" }, + { 0x1E, kFat, "FAT16-LBA-WIN95-Hidden" }, + { 0x82, 0, "Solaris x86 / Linux swap" }, + { 0x83, 0, "Linux" }, + { 0xBE, 0, "Solaris 8 boot" }, + { 0xBF, 0, "New Solaris x86" }, + { 0xC2, 0, "Linux-Hidden" }, + { 0xC3, 0, "Linux swap-Hidden" }, + { 0xEE, 0, "EFI-MBR" }, + { 0xEE, 0, "EFI" } +}; + +static int FindPartType(UInt32 type) +{ + for (int i = 0; i < sizeof(kPartTypes) / sizeof(kPartTypes[0]); i++) + if (kPartTypes[i].Id == type) + return i; + return -1; +} + +struct CItem +{ + bool IsReal; + bool IsPrim; + UInt64 Size; + CPartition Part; +}; + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + CObjectVector _items; + UInt64 _totalSize; + CByteBuffer _buffer; + + HRESULT ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int level); +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int level) +{ + if (level >= 128 || _items.Size() >= 128) + return S_FALSE; + + const int kNumHeaderParts = 4; + CPartition parts[kNumHeaderParts]; + + { + const UInt32 kSectorSize = 512; + _buffer.SetCapacity(kSectorSize); + Byte *buf = _buffer; + UInt64 newPos = (UInt64)lba << 9; + if (newPos + 512 > _totalSize) + return S_FALSE; + RINOK(stream->Seek(newPos, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream_FALSE(stream, buf, kSectorSize)); + + if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA) + return S_FALSE; + + for (int i = 0; i < kNumHeaderParts; i++) + if (!parts[i].Parse(buf + 0x1BE + 16 * i)) + return S_FALSE; + } + + PRF(printf("\n# %8X", lba)); + + UInt32 limLba = lba + 1; + if (limLba == 0) + return S_FALSE; + + for (int i = 0; i < kNumHeaderParts; i++) + { + CPartition &part = parts[i]; + + if (part.IsEmpty()) + continue; + PRF(printf("\n %2d ", (int)level)); + #ifdef SHOW_DEBUG_INFO + part.Print(); + #endif + + int numItems = _items.Size(); + UInt32 newLba = lba + part.Lba; + + if (part.IsExtended()) + { + // if (part.Type == 5) // Check it! + newLba = baseLba + part.Lba; + if (newLba < limLba) + return S_FALSE; + HRESULT res = ReadTables(stream, level < 1 ? newLba : baseLba, newLba, level + 1); + if (res != S_FALSE && res != S_OK) + return res; + } + if (newLba < limLba) + return S_FALSE; + part.Lba = newLba; + if (!part.CheckLbaLimits()) + return S_FALSE; + + CItem n; + n.Part = part; + bool addItem = false; + if (numItems == _items.Size()) + { + n.IsPrim = (level == 0); + n.IsReal = true; + addItem = true; + } + else + { + const CItem &back = _items.Back(); + UInt32 backLimit = back.Part.GetLimit(); + UInt32 partLimit = part.GetLimit(); + if (backLimit < partLimit) + { + n.IsReal = false; + n.Part.Lba = backLimit; + n.Part.NumBlocks = partLimit - backLimit; + addItem = true; + } + } + if (addItem) + { + if (n.Part.GetLimit() < limLba) + return S_FALSE; + limLba = n.Part.GetLimit(); + n.Size = n.Part.GetSize(); + _items.Add(n); + } + } + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *stream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback * /* openArchiveCallback */) +{ + COM_TRY_BEGIN + Close(); + RINOK(stream->Seek(0, STREAM_SEEK_END, &_totalSize)); + RINOK(ReadTables(stream, 0, 0, 0)); + if (_items.IsEmpty()) + return S_FALSE; + UInt32 lbaLimit = _items.Back().Part.GetLimit(); + UInt64 lim = (UInt64)lbaLimit << 9; + if (lim < _totalSize) + { + CItem n; + n.Part.Lba = lbaLimit; + n.Size = _totalSize - lim; + n.IsReal = false; + _items.Add(n); + } + _stream = stream; + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _items.Clear(); + _stream.Release(); + return S_OK; +} + +enum +{ + kpidPrimary = kpidUserDefined, + kpidBegChs, + kpidEndChs +}; + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidFileSystem, VT_BSTR}, + { NULL, kpidOffset, VT_UI8}, + { L"Primary", kpidPrimary, VT_BOOL}, + { L"Begin CHS", kpidBegChs, VT_BSTR}, + { L"End CHS", kpidEndChs, VT_BSTR} +}; + +IMP_IInArchive_Props_WITH_NAME +IMP_IInArchive_ArcProps_NO_Table + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidMainSubfile: + { + int mainIndex = -1; + for (int i = 0; i < _items.Size(); i++) + if (_items[i].IsReal) + { + if (mainIndex >= 0) + { + mainIndex = -1; + break; + } + mainIndex = i; + } + if (mainIndex >= 0) + prop = (UInt32)mainIndex; + break; + } + } + prop.Detach(value); + 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 CItem &item = _items[index]; + const CPartition &part = item.Part; + switch(propID) + { + case kpidPath: + { + AString s; + AddUIntToString(index, s); + if (item.IsReal) + { + int typeIndex = FindPartType(part.Type); + s += '.'; + const char *ext = "img"; + if (typeIndex >= 0 && kPartTypes[typeIndex].Ext != 0) + ext = kPartTypes[typeIndex].Ext; + s += ext; + } + prop = s; + break; + } + case kpidFileSystem: + if (item.IsReal) + { + char s[32]; + ConvertUInt32ToString(part.Type, s); + const char *res = s; + int typeIndex = FindPartType(part.Type); + if (typeIndex >= 0 && kPartTypes[typeIndex].Name) + res = kPartTypes[typeIndex].Name; + prop = res; + } + break; + case kpidSize: prop = item.Size; break;; + case kpidPackSize: prop = item.Size; break; + case kpidOffset: prop = part.GetPos(); break; + case kpidPrimary: if (item.IsReal) prop = item.IsPrim; break; + case kpidBegChs: if (item.IsReal) part.BeginChs.ToString(prop); break; + case kpidEndChs: if (item.IsReal) part.EndChs.ToString(prop); break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _items.Size(); + if (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; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStream(streamSpec); + streamSpec->SetStream(_stream); + + for (i = 0; i < numItems; i++) + { + lps->InSize = totalSize; + lps->OutSize = totalSize; + RINOK(lps->SetCur()); + CMyComPtr outStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + const CItem &item = _items[index]; + const CPartition &part = item.Part; + RINOK(extractCallback->GetStream(index, &outStream, askMode)); + totalSize += item.Size; + if (!testMode && !outStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + + RINOK(_stream->Seek(part.GetPos(), STREAM_SEEK_SET, NULL)); + streamSpec->Init(item.Size); + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + outStream.Release(); + RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == item.Size ? + NExtract::NOperationResult::kOK: + NExtract::NOperationResult::kDataError)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + const CItem &item = _items[index]; + return CreateLimitedInStream(_stream, item.Part.GetPos(), item.Size, stream); + COM_TRY_END +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"MBR", L"mbr", 0, 0xDB, { 1, 1, 0 }, 3, false, CreateArc, 0 }; + +REGISTER_ARC(Mbr) + +}} diff --git a/CPP/7zip/Archive/MslzHandler.cpp b/CPP/7zip/Archive/MslzHandler.cpp new file mode 100755 index 0000000..8515cdd --- /dev/null +++ b/CPP/7zip/Archive/MslzHandler.cpp @@ -0,0 +1,257 @@ +// MslzHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Common/ComTry.h" +#include "Common/MyString.h" + +#include "Windows/PropVariant.h" + +#include "../Common/InBuffer.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "Common/DummyOutStream.h" + +namespace NArchive { +namespace NMslz { + +class CHandler: + public IInArchive, + public CMyUnknownImp +{ + CMyComPtr _stream; + UInt32 _size; + UInt64 _packSize; + UString _name; +public: + MY_UNKNOWN_IMP1(IInArchive) + INTERFACE_IInArchive(;) +}; + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = 1; + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidPath: if (!_name.IsEmpty()) prop = _name; break; + case kpidSize: prop = _size; break; + case kpidPackSize: prop = _packSize; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +static const unsigned kSignatureSize = 9; +static const unsigned kHeaderSize = kSignatureSize + 1 + 4; +#define MSLZ_SIGNATURE { 0x53, 0x5A, 0x44, 0x44, 0x88, 0xF0, 0x27, 0x33, 0x41 } +// old signature: 53 5A 20 88 F0 27 33 +static const Byte signature[kSignatureSize] = MSLZ_SIGNATURE; + +static const wchar_t *g_Exts[] = +{ + L"dll", + L"exe", + L"kmd", + L"sys" +}; + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + { + Close(); + Byte buffer[kHeaderSize]; + RINOK(ReadStream_FALSE(stream, buffer, kHeaderSize)); + if (memcmp(buffer, signature, kSignatureSize) != 0) + return S_FALSE; + _size = GetUi32(buffer + 10); + if (_size > 0xFFFFFFE0) + return S_FALSE; + RINOK(stream->Seek(0, STREAM_SEEK_END, &_packSize)); + + if (callback) + { + CMyComPtr openVolumeCallback; + callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback); + if (openVolumeCallback) + { + NWindows::NCOM::CPropVariant prop; + if (openVolumeCallback->GetProperty(kpidName, &prop) == S_OK && prop.vt == VT_BSTR) + { + UString baseName = prop.bstrVal; + if (!baseName.IsEmpty() && baseName.Back() == L'_') + { + baseName.DeleteBack(); + Byte replaceByte = buffer[kSignatureSize]; + if (replaceByte == 0) + { + for (int i = 0; i < sizeof(g_Exts) / sizeof(g_Exts[0]); i++) + { + UString s = g_Exts[i]; + int len = s.Length(); + Byte b = (Byte)s.Back(); + s.DeleteBack(); + if (baseName.Length() >= len && + baseName[baseName.Length() - len] == '.' && + s.CompareNoCase(baseName.Right(len - 1)) == 0) + { + replaceByte = b; + break; + } + } + } + if (replaceByte >= 0x20 && replaceByte < 0x80) + _name = baseName + (wchar_t)replaceByte; + } + } + } + } + _stream = stream; + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _stream.Release(); + _name.Empty(); + return S_OK; +} + +// MslzDec is modified LZSS algorithm of Haruhiko Okumura: +// maxLen = 18; Okumura +// maxLen = 16; MS + +#define PROGRESS_AND_WRITE \ + if ((dest & kMask) == 0) { RINOK(WriteStream(outStream, buf, kBufSize)); \ + if ((dest & ((1 << 20) - 1)) == 0) \ + { UInt64 inSize = inStream.GetProcessedSize(); UInt64 outSize = dest; \ + RINOK(progress->SetRatioInfo(&inSize, &outSize)); }} + +static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UInt32 unpackSize, ICompressProgressInfo *progress) +{ + const unsigned kBufSize = (1 << 12); + const unsigned kMask = kBufSize - 1; + Byte buf[kBufSize]; + UInt32 dest = 0; + memset(buf, ' ', kBufSize); + while (dest < unpackSize) + { + Byte b; + if (!inStream.ReadByte(b)) + return S_FALSE; + for (unsigned mask = (unsigned)b | 0x100; mask > 1 && dest < unpackSize; mask >>= 1) + { + if (!inStream.ReadByte(b)) + return S_FALSE; + if (mask & 1) + { + buf[dest++ & kMask] = b; + PROGRESS_AND_WRITE + } + else + { + Byte b1; + if (!inStream.ReadByte(b1)) + return S_FALSE; + const unsigned kMaxLen = 16; // 18 in Okumura's code. + unsigned src = (((((unsigned)b1 & 0xF0) << 4) | b) + kMaxLen) & kMask; + unsigned len = (b1 & 0xF) + 3; + if (len > kMaxLen || dest + len > unpackSize) + return S_FALSE; + do + { + buf[dest++ & kMask] = buf[src++ & kMask]; + PROGRESS_AND_WRITE + } + while (--len != 0); + } + } + } + return WriteStream(outStream, buf, dest & kMask); +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + if (numItems == 0) + return S_OK; + if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0)) + return E_INVALIDARG; + + extractCallback->SetTotal(_size); + + 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, false); + + RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL)); + CInBuffer s; + if (!s.Create(1 << 20)) + return E_OUTOFMEMORY; + s.SetStream(_stream); + s.Init(); + Byte buffer[kHeaderSize]; + Int32 opRes = NExtract::NOperationResult::kDataError; + if (s.ReadBytes(buffer, kHeaderSize) == kHeaderSize) + { + HRESULT result = MslzDec(s, outStream, _size, progress); + if (result == S_OK) + opRes = NExtract::NOperationResult::kOK; + else if (result != S_FALSE) + return result; + } + outStream.Release(); + return extractCallback->SetOperationResult(opRes); + COM_TRY_END +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"MsLZ", L"", 0, 0xD5, MSLZ_SIGNATURE, kSignatureSize, false, CreateArc, 0 }; + +REGISTER_ARC(Mslz) + +}} diff --git a/CPP/7zip/Archive/MubHandler.cpp b/CPP/7zip/Archive/MubHandler.cpp new file mode 100755 index 0000000..0445eda --- /dev/null +++ b/CPP/7zip/Archive/MubHandler.cpp @@ -0,0 +1,266 @@ +// MubHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Common/ComTry.h" + +#include "Windows/PropVariant.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +#define Get32(p) GetBe32(p) + +namespace NArchive { +namespace NMub { + +struct CItem +{ + UInt32 Type; + UInt32 SubType; + UInt64 Offset; + UInt64 Size; + UInt32 Align; + bool IsTail; +}; + +const UInt32 kNumFilesMax = 10; + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + UInt64 _startPos; + CMyComPtr _stream; + UInt32 _numItems; + CItem _items[kNumFilesMax + 1]; + HRESULT Open2(IInStream *stream); +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +STATPROPSTG kProps[] = +{ + { NULL, kpidSize, VT_UI8} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO + +#define MACH_ARCH_ABI64 0x1000000 +#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_MACHINE_PPC | MACH_ARCH_ABI64) +#define MACH_MACHINE_AMD64 (MACH_MACHINE_386 | MACH_ARCH_ABI64) + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + NWindows::NCOM::CPropVariant prop; + const CItem &item = _items[index]; + switch(propID) + { + case kpidExtension: + { + const wchar_t *ext; + if (item.IsTail) + ext = L"tail"; + else + { + switch(item.Type) + { + case MACH_MACHINE_386: ext = L"86"; break; + case MACH_MACHINE_ARM: ext = L"arm"; break; + case MACH_MACHINE_SPARC: ext = L"sparc"; break; + case MACH_MACHINE_PPC: ext = L"ppc"; break; + case MACH_MACHINE_PPC64: ext = L"ppc64"; break; + case MACH_MACHINE_AMD64: ext = L"x64"; break; + default: ext = L"unknown"; break; + } + } + prop = ext; + break; + } + case kpidSize: + case kpidPackSize: + prop = (UInt64)item.Size; + break; + } + prop.Detach(value); + return S_OK; +} + +#define MACH_TYPE_ABI64 (1 << 24) +#define MACH_SUBTYPE_ABI64 (1 << 31) + +HRESULT CHandler::Open2(IInStream *stream) +{ + RINOK(stream->Seek(0, STREAM_SEEK_SET, &_startPos)); + + const UInt32 kHeaderSize = 8; + const UInt32 kRecordSize = 5 * 4; + const UInt32 kBufSize = kHeaderSize + kNumFilesMax * kRecordSize; + Byte buf[kBufSize]; + size_t processed = kBufSize; + RINOK(ReadStream(stream, buf, &processed)); + if (processed < kHeaderSize) + return S_FALSE; + UInt32 num = Get32(buf + 4); + if (Get32(buf) != 0xCAFEBABE || num > kNumFilesMax || processed < kHeaderSize + num * kRecordSize) + return S_FALSE; + UInt64 endPosMax = kHeaderSize; + for (UInt32 i = 0; i < num; i++) + { + const Byte *p = buf + kHeaderSize + i * kRecordSize; + CItem &sb = _items[i]; + sb.IsTail = false; + sb.Type = Get32(p); + sb.SubType = Get32(p + 4); + sb.Offset = Get32(p + 8); + sb.Size = Get32(p + 12); + sb.Align = Get32(p + 16); + + if ((sb.Type & ~MACH_TYPE_ABI64) >= 0x100 || + (sb.SubType & ~MACH_SUBTYPE_ABI64) >= 0x100 || + sb.Align > 31) + return S_FALSE; + + UInt64 endPos = (UInt64)sb.Offset + sb.Size; + if (endPos > endPosMax) + endPosMax = endPos; + } + UInt64 fileSize; + RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize)); + fileSize -= _startPos; + _numItems = num; + if (fileSize > endPosMax) + { + CItem &sb = _items[_numItems++]; + sb.IsTail = true; + sb.Type = 0; + sb.SubType = 0; + sb.Offset = endPosMax; + sb.Size = fileSize - endPosMax; + sb.Align = 0; + } + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *inStream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback * /* openArchiveCallback */) +{ + COM_TRY_BEGIN + Close(); + try + { + if (Open2(inStream) != S_OK) + return S_FALSE; + _stream = inStream; + } + catch(...) { return S_FALSE; } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _stream.Release(); + _numItems = 0; + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _numItems; + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _numItems; + if (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); + + UInt64 currentTotalSize = 0; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStream(streamSpec); + streamSpec->SetStream(_stream); + + for (i = 0; i < numItems; i++) + { + lps->InSize = lps->OutSize = currentTotalSize; + RINOK(lps->SetCur()); + CMyComPtr realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + UInt32 index = allFilesMode ? i : indices[i]; + const CItem &item = _items[index]; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + currentTotalSize += item.Size; + + if (!testMode && !realOutStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + if (testMode) + { + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + RINOK(_stream->Seek(_startPos + item.Offset, STREAM_SEEK_SET, NULL)); + streamSpec->Init(item.Size); + RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ? + NExtract::NOperationResult::kOK: + NExtract::NOperationResult::kDataError)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + const CItem &item = _items[index]; + return CreateLimitedInStream(_stream, _startPos + item.Offset, item.Size, stream); + COM_TRY_END +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"Mub", L"", 0, 0xE2, { 0xCA, 0xFE, 0xBA, 0xBE, 0, 0, 0 }, 7, false, CreateArc, 0 }; + +REGISTER_ARC(Mub) + +}} diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.cpp b/CPP/7zip/Archive/Nsis/NsisDecode.cpp new file mode 100755 index 0000000..f7cf2f0 --- /dev/null +++ b/CPP/7zip/Archive/Nsis/NsisDecode.cpp @@ -0,0 +1,130 @@ +// NsisDecode.cpp + +#include "StdAfx.h" + +#include "NsisDecode.h" + +#include "../../Common/StreamUtils.h" + +#include "../../Common/MethodId.h" + +#include "../../Compress/BZip2Decoder.h" +#include "../../Compress/DeflateDecoder.h" +#include "../../Compress/LzmaDecoder.h" + +namespace NArchive { +namespace NNsis { + +static const CMethodId k_BCJ_X86 = 0x03030103; + +HRESULT CDecoder::Init( + DECL_EXTERNAL_CODECS_LOC_VARS + IInStream *inStream, NMethodType::EEnum method, bool thereIsFilterFlag, bool &useFilter) +{ + useFilter = false; + CObjectVector< CMyComPtr > inStreams; + + if (_decoderInStream) + if (method != _method) + Release(); + _method = method; + if (!_codecInStream) + { + switch (method) + { + // case NMethodType::kCopy: return E_NOTIMPL; + case NMethodType::kDeflate: _codecInStream = new NCompress::NDeflate::NDecoder::CNsisCOMCoder(); break; + case NMethodType::kBZip2: _codecInStream = new NCompress::NBZip2::CNsisDecoder(); break; + case NMethodType::kLZMA: _codecInStream = new NCompress::NLzma::CDecoder(); break; + default: return E_NOTIMPL; + } + } + + if (thereIsFilterFlag) + { + UInt32 processedSize; + BYTE flag; + RINOK(inStream->Read(&flag, 1, &processedSize)); + if (processedSize != 1) + return E_FAIL; + if (flag > 1) + return E_NOTIMPL; + useFilter = (flag != 0); + } + + if (useFilter) + { + if (!_filterInStream) + { + CMyComPtr coder; + RINOK(CreateCoder( + EXTERNAL_CODECS_LOC_VARS + k_BCJ_X86, coder, false)); + if (!coder) + return E_NOTIMPL; + coder.QueryInterface(IID_ISequentialInStream, &_filterInStream); + if (!_filterInStream) + return E_NOTIMPL; + } + CMyComPtr setInStream; + _filterInStream.QueryInterface(IID_ICompressSetInStream, &setInStream); + if (!setInStream) + return E_NOTIMPL; + RINOK(setInStream->SetInStream(_codecInStream)); + _decoderInStream = _filterInStream; + } + else + _decoderInStream = _codecInStream; + + if (method == NMethodType::kLZMA) + { + CMyComPtr setDecoderProperties; + _codecInStream.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); + if (setDecoderProperties) + { + static const UInt32 kPropertiesSize = 5; + BYTE properties[kPropertiesSize]; + UInt32 processedSize; + RINOK(inStream->Read(properties, kPropertiesSize, &processedSize)); + if (processedSize != kPropertiesSize) + return E_FAIL; + RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)properties, kPropertiesSize)); + } + } + + { + CMyComPtr setInStream; + _codecInStream.QueryInterface(IID_ICompressSetInStream, &setInStream); + if (!setInStream) + return E_NOTIMPL; + RINOK(setInStream->SetInStream(inStream)); + } + + { + CMyComPtr setOutStreamSize; + _codecInStream.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize); + if (!setOutStreamSize) + return E_NOTIMPL; + RINOK(setOutStreamSize->SetOutStreamSize(NULL)); + } + + if (useFilter) + { + /* + CMyComPtr setOutStreamSize; + _filterInStream.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize); + if (!setOutStreamSize) + return E_NOTIMPL; + RINOK(setOutStreamSize->SetOutStreamSize(NULL)); + */ + } + + return S_OK; +} + +HRESULT CDecoder::Read(void *data, size_t *processedSize) +{ + return ReadStream(_decoderInStream, data, processedSize);; +} + +}} diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.h b/CPP/7zip/Archive/Nsis/NsisDecode.h new file mode 100755 index 0000000..fcdf4ea --- /dev/null +++ b/CPP/7zip/Archive/Nsis/NsisDecode.h @@ -0,0 +1,47 @@ +// NsisDecode.h + +#ifndef __NSIS_DECODE_H +#define __NSIS_DECODE_H + +#include "../../IStream.h" + +#include "../../Common/CreateCoder.h" + +namespace NArchive { +namespace NNsis { + +namespace NMethodType +{ + enum EEnum + { + kCopy, + kDeflate, + kBZip2, + kLZMA + }; +} + +class CDecoder +{ + NMethodType::EEnum _method; + + CMyComPtr _filterInStream; + CMyComPtr _codecInStream; + CMyComPtr _decoderInStream; + +public: + void Release() + { + _filterInStream.Release(); + _codecInStream.Release(); + _decoderInStream.Release(); + } + HRESULT Init( + DECL_EXTERNAL_CODECS_LOC_VARS + IInStream *inStream, NMethodType::EEnum method, bool thereIsFilterFlag, bool &useFilter); + HRESULT Read(void *data, size_t *processedSize); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Nsis/NsisHandler.cpp b/CPP/7zip/Archive/Nsis/NsisHandler.cpp new file mode 100755 index 0000000..2bdd2c8 --- /dev/null +++ b/CPP/7zip/Archive/Nsis/NsisHandler.cpp @@ -0,0 +1,510 @@ +// NSisHandler.cpp + +#include "StdAfx.h" + +#include "../../../../C/CpuArch.h" + +#include "Common/ComTry.h" +#include "Common/IntToString.h" + +#include "Windows/PropVariant.h" + +#include "../../Common/StreamUtils.h" + +#include "../Common/ItemNameUtils.h" + +#include "NsisHandler.h" + +#define Get32(p) GetUi32(p) + +using namespace NWindows; + +namespace NArchive { +namespace NNsis { + +static const char *kBcjMethod = "BCJ"; +static const char *kUnknownMethod = "Unknown"; + +static const char *kMethods[] = +{ + "Copy", + "Deflate", + "BZip2", + "LZMA" +}; + +static const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]); + +static STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidSolid, VT_BOOL} +}; + +static STATPROPSTG kArcProps[] = +{ + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidSolid, VT_BOOL} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidMethod: + { + UInt32 dict = 1; + bool filter = false; + for (int i = 0; i < _archive.Items.Size(); i++) + { + const CItem &item = _archive.Items[i]; + filter |= item.UseFilter; + if (item.DictionarySize > dict) + dict = item.DictionarySize; + } + prop = GetMethod(filter, dict); + break; + } + case kpidSolid: prop = _archive.IsSolid; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * maxCheckStartPosition, IArchiveOpenCallback * /* openArchiveCallback */) +{ + COM_TRY_BEGIN + Close(); + { + if (_archive.Open( + EXTERNAL_CODECS_VARS + stream, maxCheckStartPosition) != S_OK) + return S_FALSE; + _inStream = stream; + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _archive.Clear(); + _archive.Release(); + _inStream.Release(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _archive.Items.Size() + #ifdef NSIS_SCRIPT + + 1 + #endif + ; + return S_OK; +} + +static AString UInt32ToString(UInt32 value) +{ + char buffer[16]; + ConvertUInt32ToString(value, buffer); + return buffer; +} + +static AString GetStringForSizeValue(UInt32 value) +{ + for (int i = 31; i >= 0; i--) + if (((UInt32)1 << i) == value) + return UInt32ToString(i); + char c = 'b'; + if (value % (1 << 20) == 0) + { + value >>= 20; + c = 'm'; + } + else if (value % (1 << 10) == 0) + { + value >>= 10; + c = 'k'; + } + return UInt32ToString(value) + c; +} + +AString CHandler::GetMethod(bool useItemFilter, UInt32 dictionary) const +{ + NMethodType::EEnum methodIndex = _archive.Method; + AString method; + if (_archive.IsSolid && _archive.UseFilter || !_archive.IsSolid && useItemFilter) + { + method += kBcjMethod; + method += ' '; + } + method += (methodIndex < kNumMethods) ? kMethods[methodIndex] : kUnknownMethod; + if (methodIndex == NMethodType::kLZMA) + { + method += ':'; + method += GetStringForSizeValue(_archive.IsSolid ? _archive.DictionarySize: dictionary); + } + return method; +} + +bool CHandler::GetUncompressedSize(int index, UInt32 &size) +{ + size = 0; + const CItem &item = _archive.Items[index]; + if (item.SizeIsDefined) + size = item.Size; + else if (_archive.IsSolid && item.EstimatedSizeIsDefined) + size = item.EstimatedSize; + else + return false; + return true; +} + +bool CHandler::GetCompressedSize(int index, UInt32 &size) +{ + size = 0; + const CItem &item = _archive.Items[index]; + if (item.CompressedSizeIsDefined) + size = item.CompressedSize; + else + { + if (_archive.IsSolid) + { + if (index == 0) + size = _archive.FirstHeader.GetDataSize(); + else + return false; + } + else + { + if (!item.IsCompressed) + size = item.Size; + else + return false; + } + } + return true; +} + + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + #ifdef NSIS_SCRIPT + if (index >= (UInt32)_archive.Items.Size()) + { + switch(propID) + { + case kpidPath: prop = L"[NSIS].nsi"; break; + case kpidSize: + case kpidPackSize: prop = (UInt64)_archive.Script.Length(); break; + case kpidSolid: prop = false; break; + } + } + else + #endif + { + const CItem &item = _archive.Items[index]; + switch(propID) + { + case kpidPath: + { + UString s = NItemName::WinNameToOSName(item.GetReducedName(_archive.IsUnicode)); + if (!s.IsEmpty()) + prop = (const wchar_t *)s; + break; + } + case kpidSize: + { + UInt32 size; + if (GetUncompressedSize(index, size)) + prop = (UInt64)size; + break; + } + case kpidPackSize: + { + UInt32 size; + if (GetCompressedSize(index, size)) + prop = (UInt64)size; + break; + } + case kpidMTime: + { + if (item.MTime.dwHighDateTime > 0x01000000 && + item.MTime.dwHighDateTime < 0xFF000000) + prop = item.MTime; + break; + } + case kpidMethod: prop = GetMethod(item.UseFilter, item.DictionarySize); break; + case kpidSolid: prop = _archive.IsSolid; break; + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + GetNumberOfItems(&numItems); + if (numItems == 0) + return S_OK; + UInt64 totalSize = 0; + + UInt32 i; + for (i = 0; i < numItems; i++) + { + UInt32 index = (allFilesMode ? i : indices[i]); + #ifdef NSIS_SCRIPT + if (index >= (UInt32)_archive.Items.Size()) + totalSize += _archive.Script.Length(); + else + #endif + { + UInt32 size; + if (_archive.IsSolid) + { + GetUncompressedSize(index, size); + UInt64 pos = _archive.GetPosOfSolidItem(index); + if (pos > totalSize) + totalSize = pos + size; + } + else + { + GetCompressedSize(index, size); + totalSize += size; + } + } + } + extractCallback->SetTotal(totalSize); + + UInt64 currentTotalSize = 0; + UInt32 currentItemSize = 0; + + UInt64 streamPos = 0; + if (_archive.IsSolid) + { + RINOK(_inStream->Seek(_archive.StreamOffset, STREAM_SEEK_SET, NULL)); + bool useFilter; + RINOK(_archive.Decoder.Init( + EXTERNAL_CODECS_VARS + _inStream, _archive.Method, _archive.FilterFlag, useFilter)); + } + + CByteBuffer byteBuf; + const UInt32 kBufferLength = 1 << 16; + byteBuf.SetCapacity(kBufferLength); + Byte *buffer = byteBuf; + + CByteBuffer tempBuf; + + bool dataError = false; + for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) + { + currentItemSize = 0; + RINOK(extractCallback->SetCompleted(¤tTotalSize)); + CMyComPtr realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + UInt32 index = allFilesMode ? i : indices[i]; + + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + #ifdef NSIS_SCRIPT + if (index >= (UInt32)_archive.Items.Size()) + { + currentItemSize = _archive.Script.Length(); + if (!testMode && !realOutStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + if (!testMode) + RINOK(WriteStream(realOutStream, (const char *)_archive.Script, (UInt32)_archive.Script.Length())); + } + else + #endif + { + const CItem &item = _archive.Items[index]; + + if (_archive.IsSolid) + GetUncompressedSize(index, currentItemSize); + else + GetCompressedSize(index, currentItemSize); + + if (!testMode && !realOutStream) + continue; + + RINOK(extractCallback->PrepareOperation(askMode)); + + if (!dataError) + { + bool needDecompress = false; + bool sizeIsKnown = false; + UInt32 fullSize = 0; + + bool writeToTemp = false; + bool readFromTemp = false; + + if (_archive.IsSolid) + { + UInt64 pos = _archive.GetPosOfSolidItem(index); + while (streamPos < pos) + { + size_t processedSize = (UInt32)MyMin(pos - streamPos, (UInt64)kBufferLength); + HRESULT res = _archive.Decoder.Read(buffer, &processedSize); + if (res != S_OK) + { + if (res != S_FALSE) + return res; + dataError = true; + break; + } + if (processedSize == 0) + { + dataError = true; + break; + } + streamPos += processedSize; + } + if (streamPos == pos) + { + Byte buffer2[4]; + size_t processedSize = 4; + RINOK(_archive.Decoder.Read(buffer2, &processedSize)); + if (processedSize != 4) + return E_FAIL; + streamPos += processedSize; + fullSize = Get32(buffer2); + sizeIsKnown = true; + needDecompress = true; + + if (!testMode && i + 1 < numItems) + { + UInt64 nextPos = _archive.GetPosOfSolidItem(allFilesMode ? i : indices[i + 1]); + if (nextPos < streamPos + fullSize) + { + tempBuf.Free(); + tempBuf.SetCapacity(fullSize); + writeToTemp = true; + } + } + } + else + readFromTemp = true; + } + else + { + RINOK(_inStream->Seek(_archive.GetPosOfNonSolidItem(index) + 4, STREAM_SEEK_SET, NULL)); + if (item.IsCompressed) + { + needDecompress = true; + bool useFilter; + RINOK(_archive.Decoder.Init( + EXTERNAL_CODECS_VARS + _inStream, _archive.Method, _archive.FilterFlag, useFilter)); + // fullSize = Get32(buffer); // It's bug !!! + // Test it: what is exact fullSize? + fullSize = 0xFFFFFFFF; + } + else + fullSize = item.Size; + } + if (!dataError) + { + if (needDecompress) + { + UInt64 offset = 0; + while (!sizeIsKnown || fullSize > 0) + { + UInt32 curSize = kBufferLength; + if (sizeIsKnown && curSize > fullSize) + curSize = fullSize; + size_t processedSize = curSize; + HRESULT res = _archive.Decoder.Read(buffer, &processedSize); + if (res != S_OK) + { + if (res != S_FALSE) + return res; + dataError = true; + break; + } + if (processedSize == 0) + { + if (sizeIsKnown) + dataError = true; + break; + } + + if (writeToTemp) + memcpy((Byte *)tempBuf + (size_t)offset, buffer, processedSize); + + fullSize -= (UInt32)processedSize; + streamPos += processedSize; + offset += processedSize; + + UInt64 completed; + if (_archive.IsSolid) + completed = currentTotalSize + offset; + else + completed = streamPos; + RINOK(extractCallback->SetCompleted(&completed)); + if (!testMode) + RINOK(WriteStream(realOutStream, buffer, processedSize)); + } + } + else + { + if (readFromTemp) + { + if (!testMode) + RINOK(WriteStream(realOutStream, tempBuf, tempBuf.GetCapacity())); + } + else + while (fullSize > 0) + { + UInt32 curSize = MyMin(fullSize, kBufferLength); + UInt32 processedSize; + RINOK(_inStream->Read(buffer, curSize, &processedSize)); + if (processedSize == 0) + { + dataError = true; + break; + } + fullSize -= processedSize; + streamPos += processedSize; + if (!testMode) + RINOK(WriteStream(realOutStream, buffer, processedSize)); + } + } + } + } + } + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(dataError ? + NExtract::NOperationResult::kDataError : + NExtract::NOperationResult::kOK)); + } + return S_OK; + COM_TRY_END +} + +IMPL_ISetCompressCodecsInfo + +}} diff --git a/CPP/7zip/Archive/Nsis/NsisHandler.h b/CPP/7zip/Archive/Nsis/NsisHandler.h new file mode 100755 index 0000000..c3db089 --- /dev/null +++ b/CPP/7zip/Archive/Nsis/NsisHandler.h @@ -0,0 +1,43 @@ +// NSisHandler.h + +#ifndef __NSIS_HANDLER_H +#define __NSIS_HANDLER_H + +#include "Common/MyCom.h" +#include "../IArchive.h" + +#include "NsisIn.h" + +#include "../../Common/CreateCoder.h" + +namespace NArchive { +namespace NNsis { + +class CHandler: + public IInArchive, + PUBLIC_ISetCompressCodecsInfo + public CMyUnknownImp +{ + CMyComPtr _inStream; + CInArchive _archive; + + DECL_EXTERNAL_CODECS_VARS + + bool GetUncompressedSize(int index, UInt32 &size); + bool GetCompressedSize(int index, UInt32 &size); + + AString GetMethod(bool useItemFilter, UInt32 dictionary) const; +public: + MY_QUERYINTERFACE_BEGIN2(IInArchive) + QUERY_ENTRY_ISetCompressCodecsInfo + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + INTERFACE_IInArchive(;) + + DECL_ISetCompressCodecsInfo +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Nsis/NsisIn.cpp b/CPP/7zip/Archive/Nsis/NsisIn.cpp new file mode 100755 index 0000000..18bdff0 --- /dev/null +++ b/CPP/7zip/Archive/Nsis/NsisIn.cpp @@ -0,0 +1,1461 @@ +// NsisIn.cpp + +#include "StdAfx.h" + +#include "../../../../C/CpuArch.h" + +#include "Common/IntToString.h" + +#include "../../Common/StreamUtils.h" + +#include "NsisIn.h" + +#define Get32(p) GetUi32(p) + +namespace NArchive { +namespace NNsis { + +Byte kSignature[kSignatureSize] = NSIS_SIGNATURE; + +#ifdef NSIS_SCRIPT +static const char *kCrLf = "\x0D\x0A"; +#endif + +#define NS_UN_SKIP_CODE 0xE000 +#define NS_UN_VAR_CODE 0xE001 +#define NS_UN_SHELL_CODE 0xE002 +#define NS_UN_LANG_CODE 0xE003 +#define NS_UN_CODES_START NS_UN_SKIP_CODE +#define NS_UN_CODES_END NS_UN_LANG_CODE + +Byte CInArchive::ReadByte() +{ + if (_posInData >= _size) + throw 1; + return _data[_posInData++]; +} + +UInt32 CInArchive::ReadUInt32() +{ + UInt32 value = 0; + for (int i = 0; i < 4; i++) + value |= ((UInt32)(ReadByte()) << (8 * i)); + return value; +} + +void CInArchive::ReadBlockHeader(CBlockHeader &bh) +{ + bh.Offset = ReadUInt32(); + bh.Num = ReadUInt32(); +} + +#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } + +static int CompareItems(void *const *p1, void *const *p2, void * /* param */) +{ + const CItem &i1 = **(CItem **)p1; + const CItem &i2 = **(CItem **)p2; + RINOZ(MyCompare(i1.Pos, i2.Pos)); + if (i1.IsUnicode) + { + RINOZ(i1.PrefixU.Compare(i2.PrefixU)); + RINOZ(i1.NameU.Compare(i2.NameU)); + } + else + { + RINOZ(i1.PrefixA.Compare(i2.PrefixA)); + RINOZ(i1.NameA.Compare(i2.NameA)); + } + return 0; +} + +static AString UIntToString(UInt32 v) +{ + char sz[32]; + ConvertUInt64ToString(v, sz); + return sz; +} + +static AString IntToString(Int32 v) +{ + char sz[32]; + ConvertInt64ToString(v, sz); + return sz; +} + +AString CInArchive::ReadStringA(UInt32 pos) const +{ + AString s; + if (pos >= _size) + return IntToString((Int32)pos); + UInt32 offset = GetOffset() + _stringsPos + pos; + for (;;) + { + if (offset >= _size) + break; // throw 1; + char c = _data[offset++]; + if (c == 0) + break; + s += c; + } + return s; +} + +UString CInArchive::ReadStringU(UInt32 pos) const +{ + UString s; + UInt32 offset = GetOffset() + _stringsPos + (pos * 2); + for (;;) + { + if (offset >= _size || offset + 1 >= _size) + return s; // throw 1; + char c0 = _data[offset++]; + char c1 = _data[offset++]; + wchar_t c = (c0 | ((wchar_t)c1 << 8)); + if (c == 0) + break; + s += c; + } + return s; +} + +/* +static AString ParsePrefix(const AString &prefix) +{ + AString res = prefix; + if (prefix.Length() >= 3) + { + if ((Byte)prefix[0] == 0xFD && (Byte)prefix[1] == 0x95 && (Byte)prefix[2] == 0x80) + res = "$INSTDIR" + prefix.Mid(3); + else if ((Byte)prefix[0] == 0xFD && (Byte)prefix[1] == 0x96 && (Byte)prefix[2] == 0x80) + res = "$OUTDIR" + prefix.Mid(3); + } + return res; +} +*/ + +#define SYSREGKEY "Software\\Microsoft\\Windows\\CurrentVersion" + +/* +# define CSIDL_PROGRAMS 0x2 +# define CSIDL_PRINTERS 0x4 +# define CSIDL_PERSONAL 0x5 +# define CSIDL_FAVORITES 0x6 +# define CSIDL_STARTUP 0x7 +# define CSIDL_RECENT 0x8 +# define CSIDL_SENDTO 0x9 +# define CSIDL_STARTMENU 0xB +# define CSIDL_MYMUSIC 0xD +# define CSIDL_MYVIDEO 0xE + +# define CSIDL_DESKTOPDIRECTORY 0x10 +# define CSIDL_NETHOOD 0x13 +# define CSIDL_FONTS 0x14 +# define CSIDL_TEMPLATES 0x15 +# define CSIDL_COMMON_STARTMENU 0x16 +# define CSIDL_COMMON_PROGRAMS 0x17 +# define CSIDL_COMMON_STARTUP 0x18 +# define CSIDL_COMMON_DESKTOPDIRECTORY 0x19 +# define CSIDL_APPDATA 0x1A +# define CSIDL_PRINTHOOD 0x1B +# define CSIDL_LOCAL_APPDATA 0x1C +# define CSIDL_ALTSTARTUP 0x1D +# define CSIDL_COMMON_ALTSTARTUP 0x1E +# define CSIDL_COMMON_FAVORITES 0x1F + +# define CSIDL_INTERNET_CACHE 0x20 +# define CSIDL_COOKIES 0x21 +# define CSIDL_HISTORY 0x22 +# define CSIDL_COMMON_APPDATA 0x23 +# define CSIDL_WINDOWS 0x24 +# define CSIDL_SYSTEM 0x25 +# define CSIDL_PROGRAM_FILES 0x26 +# define CSIDL_MYPICTURES 0x27 +# define CSIDL_PROFILE 0x28 +# define CSIDL_PROGRAM_FILES_COMMON 0x2B +# define CSIDL_COMMON_TEMPLATES 0x2D +# define CSIDL_COMMON_DOCUMENTS 0x2E +# define CSIDL_COMMON_ADMINTOOLS 0x2F + +# define CSIDL_ADMINTOOLS 0x30 +# define CSIDL_COMMON_MUSIC 0x35 +# define CSIDL_COMMON_PICTURES 0x36 +# define CSIDL_COMMON_VIDEO 0x37 +# define CSIDL_RESOURCES 0x38 +# define CSIDL_RESOURCES_LOCALIZED 0x39 +# define CSIDL_CDBURN_AREA 0x3B +*/ + +struct CCommandPair +{ + int NumParams; + const char *Name; +}; + +enum +{ + // 0 + EW_INVALID_OPCODE, // zero is invalid. useful for catching errors. (otherwise an all zeroes instruction + // does nothing, which is easily ignored but means something is wrong. + EW_RET, // return from function call + EW_NOP, // Nop/Jump, do nothing: 1, [?new address+1:advance one] + EW_ABORT, // Abort: 1 [status] + EW_QUIT, // Quit: 0 + EW_CALL, // Call: 1 [new address+1] + EW_UPDATETEXT, // Update status text: 2 [update str, ui_st_updateflag=?ui_st_updateflag:this] + EW_SLEEP, // Sleep: 1 [sleep time in milliseconds] + EW_BRINGTOFRONT, // BringToFront: 0 + EW_CHDETAILSVIEW, // SetDetailsView: 2 [listaction,buttonaction] + + // 10 + EW_SETFILEATTRIBUTES, // SetFileAttributes: 2 [filename, attributes] + EW_CREATEDIR, // Create directory: 2, [path, ?update$INSTDIR] + EW_IFFILEEXISTS, // IfFileExists: 3, [file name, jump amount if exists, jump amount if not exists] + EW_SETFLAG, // Sets a flag: 2 [id, data] + EW_IFFLAG, // If a flag: 4 [on, off, id, new value mask] + EW_GETFLAG, // Gets a flag: 2 [output, id] + EW_RENAME, // Rename: 3 [old, new, rebootok] + EW_GETFULLPATHNAME, // GetFullPathName: 2 [output, input, ?lfn:sfn] + EW_SEARCHPATH, // SearchPath: 2 [output, filename] + EW_GETTEMPFILENAME, // GetTempFileName: 2 [output, base_dir] + + // 20 + EW_EXTRACTFILE, // File to extract: 6 [overwriteflag, output filename, compressed filedata, filedatetimelow, filedatetimehigh, allow ignore] + // overwriteflag: 0x1 = no. 0x0=force, 0x2=try, 0x3=if date is newer + EW_DELETEFILE, // Delete File: 2, [filename, rebootok] + EW_MESSAGEBOX, // MessageBox: 5,[MB_flags,text,retv1:retv2,moveonretv1:moveonretv2] + EW_RMDIR, // RMDir: 2 [path, recursiveflag] + EW_STRLEN, // StrLen: 2 [output, input] + EW_ASSIGNVAR, // Assign: 4 [variable (0-9) to assign, string to assign, maxlen, startpos] + EW_STRCMP, // StrCmp: 5 [str1, str2, jump_if_equal, jump_if_not_equal, case-sensitive?] + EW_READENVSTR, // ReadEnvStr/ExpandEnvStrings: 3 [output, string_with_env_variables, IsRead] + EW_INTCMP, // IntCmp: 6 [val1, val2, equal, val1val2, unsigned?] + EW_INTOP, // IntOp: 4 [output, input1, input2, op] where op: 0=add, 1=sub, 2=mul, 3=div, 4=bor, 5=band, 6=bxor, 7=bnot input1, 8=lnot input1, 9=lor, 10=land], 11=1%2 + + // 30 + EW_INTFMT, // IntFmt: [output, format, input] + EW_PUSHPOP, // Push/Pop/Exchange: 3 [variable/string, ?pop:push, ?exch] + EW_FINDWINDOW, // FindWindow: 5, [outputvar, window class,window name, window_parent, window_after] + EW_SENDMESSAGE, // SendMessage: 6 [output, hwnd, msg, wparam, lparam, [wparamstring?1:0 | lparamstring?2:0 | timeout<<2] + EW_ISWINDOW, // IsWindow: 3 [hwnd, jump_if_window, jump_if_notwindow] + EW_GETDLGITEM, // GetDlgItem: 3: [outputvar, dialog, item_id] + EW_SETCTLCOLORS, // SerCtlColors: 3: [hwnd, pointer to struct colors] + EW_SETBRANDINGIMAGE, // SetBrandingImage: 1: [Bitmap file] + EW_CREATEFONT, // CreateFont: 5: [handle output, face name, height, weight, flags] + EW_SHOWWINDOW, // ShowWindow: 2: [hwnd, show state] + + // 40 + EW_SHELLEXEC, // ShellExecute program: 4, [shell action, complete commandline, parameters, showwindow] + EW_EXECUTE, // Execute program: 3,[complete command line,waitflag,>=0?output errorcode] + EW_GETFILETIME, // GetFileTime; 3 [file highout lowout] + EW_GETDLLVERSION, // GetDLLVersion: 3 [file highout lowout] + EW_REGISTERDLL, // Register DLL: 3,[DLL file name, string ptr of function to call, text to put in display (<0 if none/pass parms), 1 - no unload, 0 - unload] + EW_CREATESHORTCUT, // Make Shortcut: 5, [link file, target file, parameters, icon file, iconindex|show mode<<8|hotkey<<16] + EW_COPYFILES, // CopyFiles: 3 [source mask, destination location, flags] + EW_REBOOT, // Reboot: 0 + EW_WRITEINI, // Write INI String: 4, [Section, Name, Value, INI File] + EW_READINISTR, // ReadINIStr: 4 [output, section, name, ini_file] + + // 50 + EW_DELREG, // DeleteRegValue/DeleteRegKey: 4, [root key(int), KeyName, ValueName, delkeyonlyifempty]. ValueName is -1 if delete key + EW_WRITEREG, // Write Registry value: 5, [RootKey(int),KeyName,ItemName,ItemData,typelen] + // typelen=1 for str, 2 for dword, 3 for binary, 0 for expanded str + EW_READREGSTR, // ReadRegStr: 5 [output, rootkey(int), keyname, itemname, ==1?int::str] + EW_REGENUM, // RegEnum: 5 [output, rootkey, keyname, index, ?key:value] + EW_FCLOSE, // FileClose: 1 [handle] + EW_FOPEN, // FileOpen: 4 [name, openmode, createmode, outputhandle] + EW_FPUTS, // FileWrite: 3 [handle, string, ?int:string] + EW_FGETS, // FileRead: 4 [handle, output, maxlen, ?getchar:gets] + EW_FSEEK, // FileSeek: 4 [handle, offset, mode, >=0?positionoutput] + EW_FINDCLOSE, // FindClose: 1 [handle] + + // 60 + EW_FINDNEXT, // FindNext: 2 [output, handle] + EW_FINDFIRST, // FindFirst: 2 [filespec, output, handleoutput] + EW_WRITEUNINSTALLER, // WriteUninstaller: 3 [name, offset, icon_size] + EW_LOG, // LogText: 2 [0, text] / LogSet: [1, logstate] + EW_SECTIONSET, // SectionSetText: 3: [idx, 0, text] + // SectionGetText: 3: [idx, 1, output] + // SectionSetFlags: 3: [idx, 2, flags] + // SectionGetFlags: 3: [idx, 3, output] + EW_INSTTYPESET, // InstTypeSetFlags: 3: [idx, 0, flags] + // InstTypeGetFlags: 3: [idx, 1, output] + // instructions not actually implemented in exehead, but used in compiler. + EW_GETLABELADDR, // both of these get converted to EW_ASSIGNVAR + EW_GETFUNCTIONADDR, + + EW_LOCKWINDOW +}; + +#ifdef NSIS_SCRIPT +static CCommandPair kCommandPairs[] = +{ + { 0, "Invalid" }, + { 0, "Return" }, + { 1, "Goto" }, + { 0, "Abort" }, + { 0, "Quit" }, + { 1, "Call" }, + { 2, "UpdateSatusText" }, + { 1, "Sleep" }, + { 0, "BringToFront" }, + { 2, "SetDetailsView" }, + + { 2, "SetFileAttributes" }, + { 2, "SetOutPath" }, + { 3, "IfFileExists" }, + { 2, "SetFlag" }, + { 4, "IfFlag" }, + { 2, "GetFlag" }, + { 3, "Rename" }, + { 2, "GetFullPathName" }, + { 2, "SearchPath" }, + { 2, "GetTempFileName" }, + + { 6, "File" }, + { 2, "Delete" }, + { 5, "MessageBox" }, + { 2, "RMDir" }, + { 2, "StrLen" }, + { 4, "StrCpy" }, + { 5, "StrCmp" }, + { 3, "ReadEnvStr" }, + { 6, "IntCmp" }, + { 4, "IntOp" }, + + { 3, "IntFmt" }, + { 3, "PushPop" }, + { 5, "FindWindow" }, + { 6, "SendMessage" }, + { 3, "IsWindow" }, + { 3, "GetDlgItem" }, + { 3, "SerCtlColors" }, + { 1, "SetBrandingImage" }, + { 5, "CreateFont" }, + { 2, "ShowWindow" }, + + { 4, "ShellExecute" }, + { 3, "Execute" }, + { 3, "GetFileTime" }, + { 3, "GetDLLVersion" }, + { 3, "RegisterDLL" }, + { 5, "CreateShortCut" }, + { 3, "CopyFiles" }, + { 0, "Reboot" }, + { 4, "WriteINIStr" }, + { 4, "ReadINIStr" }, + + { 4, "DelReg" }, + { 5, "WriteReg" }, + { 5, "ReadRegStr" }, + { 5, "RegEnum" }, + { 1, "FileClose" }, + { 4, "FileOpen" }, + { 3, "FileWrite" }, + { 4, "FileRead" }, + { 4, "FileSeek" }, + { 1, "FindClose" }, + + { 2, "FindNext" }, + { 2, "FindFirst" }, + { 3, "WriteUninstaller" }, + { 2, "LogText" }, + { 3, "Section?etText" }, + { 3, "InstType?etFlags" }, + { 6, "GetLabelAddr" }, + { 2, "GetFunctionAddress" }, + { 6, "LockWindow" } +}; + +#endif + +static const char *kShellStrings[] = +{ + "", + "", + + "SMPROGRAMS", + "", + "PRINTERS", + "DOCUMENTS", + "FAVORITES", + "SMSTARTUP", + "RECENT", + "SENDTO", + "", + "STARTMENU", + "", + "MUSIC", + "VIDEO", + "", + + "DESKTOP", + "", + "", + "NETHOOD", + "FONTS", + "TEMPLATES", + "COMMONSTARTMENU", + "COMMONFILES", + "COMMON_STARTUP", + "COMMON_DESKTOPDIRECTORY", + "QUICKLAUNCH", + "PRINTHOOD", + "LOCALAPPDATA", + "ALTSTARTUP", + "ALTSTARTUP", + "FAVORITES", + + "INTERNET_CACHE", + "COOKIES", + "HISTORY", + "APPDATA", + "WINDIR", + "SYSDIR", + "PROGRAMFILES", + "PICTURES", + "PROFILE", + "", + "", + "COMMONFILES", + "", + "TEMPLATES", + "DOCUMENTS", + "ADMINTOOLS", + + "ADMINTOOLS", + "", + "", + "", + "", + "MUSIC", + "PICTURES", + "VIDEO", + "RESOURCES", + "RESOURCES_LOCALIZED", + "", + "CDBURN_AREA" +}; + +static const int kNumShellStrings = sizeof(kShellStrings) / sizeof(kShellStrings[0]); + +/* +# define CMDLINE 20 // everything before here doesn't have trailing slash removal +# define INSTDIR 21 +# define OUTDIR 22 +# define EXEDIR 23 +# define LANGUAGE 24 +# define TEMP 25 +# define PLUGINSDIR 26 +# define HWNDPARENT 27 +# define _CLICK 28 +# define _OUTDIR 29 +*/ + +static const char *kVarStrings[] = +{ + "CMDLINE", + "INSTDIR", + "OUTDIR", + "EXEDIR", + "LANGUAGE", + "TEMP", + "PLUGINSDIR", + "EXEPATH", // test it + "EXEFILE", // test it + "HWNDPARENT", + "_CLICK", + "_OUTDIR" +}; + +static const int kNumVarStrings = sizeof(kVarStrings) / sizeof(kVarStrings[0]); + + +static AString GetVar(UInt32 index) +{ + AString res = "$"; + if (index < 10) + res += UIntToString(index); + else if (index < 20) + { + res += "R"; + res += UIntToString(index - 10); + } + else if (index < 20 + kNumVarStrings) + res += kVarStrings[index - 20]; + else + { + res += "["; + res += UIntToString(index); + res += "]"; + } + return res; +} + +#define NS_SKIP_CODE 252 +#define NS_VAR_CODE 253 +#define NS_SHELL_CODE 254 +#define NS_LANG_CODE 255 +#define NS_CODES_START NS_SKIP_CODE + +static AString GetShellString(int index) +{ + AString res = "$"; + if (index < kNumShellStrings) + { + const char *sz = kShellStrings[index]; + if (sz[0] != 0) + return res + sz; + } + res += "SHELL["; + res += UIntToString(index); + res += "]"; + return res; +} + +// Based on Dave Laundon's simplified process_string +AString GetNsisString(const AString &s) +{ + AString res; + for (int i = 0; i < s.Length();) + { + unsigned char nVarIdx = s[i++]; + if (nVarIdx > NS_CODES_START && i + 2 <= s.Length()) + { + int nData = s[i++] & 0x7F; + unsigned char c1 = s[i++]; + nData |= (((int)(c1 & 0x7F)) << 7); + + if (nVarIdx == NS_SHELL_CODE) + res += GetShellString(c1); + else if (nVarIdx == NS_VAR_CODE) + res += GetVar(nData); + else if (nVarIdx == NS_LANG_CODE) + res += "NS_LANG_CODE"; + } + else if (nVarIdx == NS_SKIP_CODE) + { + if (i < s.Length()) + res += s[i++]; + } + else // Normal char + res += (char)nVarIdx; + } + return res; +} + +UString GetNsisString(const UString &s) +{ + UString res; + for (int i = 0; i < s.Length();) + { + wchar_t nVarIdx = s[i++]; + if (nVarIdx > NS_UN_CODES_START && nVarIdx <= NS_UN_CODES_END) + { + if (i == s.Length()) + break; + int nData = s[i++] & 0x7FFF; + + if (nVarIdx == NS_UN_SHELL_CODE) + res += GetUnicodeString(GetShellString(nData >> 8)); + else if (nVarIdx == NS_UN_VAR_CODE) + res += GetUnicodeString(GetVar(nData)); + else if (nVarIdx == NS_UN_LANG_CODE) + res += L"NS_LANG_CODE"; + } + else if (nVarIdx == NS_UN_SKIP_CODE) + { + if (i == s.Length()) + break; + res += s[i++]; + } + else // Normal char + res += (char)nVarIdx; + } + return res; +} + +AString CInArchive::ReadString2A(UInt32 pos) const +{ + return GetNsisString(ReadStringA(pos)); +} + +UString CInArchive::ReadString2U(UInt32 pos) const +{ + return GetNsisString(ReadStringU(pos)); +} + +AString CInArchive::ReadString2(UInt32 pos) const +{ + if (IsUnicode) + return UnicodeStringToMultiByte(ReadString2U(pos)); + else + return ReadString2A(pos); +} + +AString CInArchive::ReadString2Qw(UInt32 pos) const +{ + return "\"" + ReadString2(pos) + "\""; +} + +#define DEL_DIR 1 +#define DEL_RECURSE 2 +#define DEL_REBOOT 4 +// #define DEL_SIMPLE 8 + +static const int kNumEntryParams = 6; + +struct CEntry +{ + UInt32 Which; + UInt32 Params[kNumEntryParams]; + AString GetParamsString(int numParams); + CEntry() + { + Which = 0; + for (UInt32 j = 0; j < kNumEntryParams; j++) + Params[j] = 0; + } +}; + +AString CEntry::GetParamsString(int numParams) +{ + AString s; + for (int i = 0; i < numParams; i++) + { + s += " "; + UInt32 v = Params[i]; + if (v > 0xFFF00000) + s += IntToString((Int32)Params[i]); + else + s += UIntToString(Params[i]); + } + return s; +} + +#ifdef NSIS_SCRIPT + +static AString GetRegRootID(UInt32 val) +{ + const char *s; + switch(val) + { + case 0: s = "SHCTX"; break; + case 0x80000000: s = "HKCR"; break; + case 0x80000001: s = "HKCU"; break; + case 0x80000002: s = "HKLM"; break; + case 0x80000003: s = "HKU"; break; + case 0x80000004: s = "HKPD"; break; + case 0x80000005: s = "HKCC"; break; + case 0x80000006: s = "HKDD"; break; + case 0x80000050: s = "HKPT"; break; + case 0x80000060: s = "HKPN"; break; + default: + return UIntToString(val); break; + } + return s; +} + +#endif + +HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) +{ + _posInData = bh.Offset + GetOffset(); + AString prefixA; + UString prefixU; + for (UInt32 i = 0; i < bh.Num; i++) + { + CEntry e; + e.Which = ReadUInt32(); + for (UInt32 j = 0; j < kNumEntryParams; j++) + e.Params[j] = ReadUInt32(); + #ifdef NSIS_SCRIPT + if (e.Which != EW_PUSHPOP && e.Which < sizeof(kCommandPairs) / sizeof(kCommandPairs[0])) + { + const CCommandPair &pair = kCommandPairs[e.Which]; + Script += pair.Name; + } + #endif + + switch (e.Which) + { + case EW_CREATEDIR: + { + if (IsUnicode) + { + prefixU.Empty(); + prefixU = ReadString2U(e.Params[0]); + } + else + { + prefixA.Empty(); + prefixA = ReadString2A(e.Params[0]); + } + #ifdef NSIS_SCRIPT + Script += " "; + if (IsUnicode) + Script += UnicodeStringToMultiByte(prefixU); + else + Script += prefixA; + #endif + break; + } + + case EW_EXTRACTFILE: + { + CItem item; + item.IsUnicode = IsUnicode; + if (IsUnicode) + { + item.PrefixU = prefixU; + item.NameU = ReadString2U(e.Params[1]); + } + else + { + item.PrefixA = prefixA; + item.NameA = ReadString2A(e.Params[1]); + } + /* UInt32 overwriteFlag = e.Params[0]; */ + item.Pos = e.Params[2]; + item.MTime.dwLowDateTime = e.Params[3]; + item.MTime.dwHighDateTime = e.Params[4]; + /* UInt32 allowIgnore = e.Params[5]; */ + if (Items.Size() > 0) + { + /* + if (item.Pos == Items.Back().Pos) + continue; + */ + } + Items.Add(item); + #ifdef NSIS_SCRIPT + Script += " "; + + if (IsUnicode) + Script += UnicodeStringToMultiByte(item.NameU); + else + Script += item.NameA; + #endif + break; + } + + + #ifdef NSIS_SCRIPT + case EW_UPDATETEXT: + { + Script += " "; + Script += ReadString2(e.Params[0]); + Script += " "; + Script += UIntToString(e.Params[1]); + break; + } + case EW_SETFILEATTRIBUTES: + { + Script += " "; + Script += ReadString2(e.Params[0]); + Script += " "; + Script += UIntToString(e.Params[1]); + break; + } + case EW_IFFILEEXISTS: + { + Script += " "; + Script += ReadString2(e.Params[0]); + Script += " "; + Script += UIntToString(e.Params[1]); + Script += " "; + Script += UIntToString(e.Params[2]); + break; + } + case EW_RENAME: + { + Script += " "; + Script += ReadString2(e.Params[0]); + Script += " "; + Script += ReadString2(e.Params[1]); + Script += " "; + Script += UIntToString(e.Params[2]); + break; + } + case EW_GETFULLPATHNAME: + { + Script += " "; + Script += ReadString2(e.Params[0]); + Script += " "; + Script += ReadString2(e.Params[1]); + Script += " "; + Script += UIntToString(e.Params[2]); + break; + } + case EW_SEARCHPATH: + { + Script += " "; + Script += ReadString2(e.Params[0]); + Script += " "; + Script += ReadString2(e.Params[1]); + break; + } + case EW_GETTEMPFILENAME: + { + AString s; + Script += " "; + Script += ReadString2(e.Params[0]); + Script += " "; + Script += ReadString2(e.Params[1]); + break; + } + + case EW_DELETEFILE: + { + UInt64 flag = e.Params[1]; + if (flag != 0) + { + Script += " "; + if (flag == DEL_REBOOT) + Script += "/REBOOTOK"; + else + Script += UIntToString(e.Params[1]); + } + Script += " "; + Script += ReadString2(e.Params[0]); + break; + } + case EW_RMDIR: + { + UInt64 flag = e.Params[1]; + if (flag != 0) + { + if ((flag & DEL_REBOOT) != 0) + Script += " /REBOOTOK"; + if ((flag & DEL_RECURSE) != 0) + Script += " /r"; + } + Script += " "; + Script += ReadString2(e.Params[0]); + break; + } + case EW_STRLEN: + { + Script += " "; + Script += GetVar(e.Params[0]);; + Script += " "; + Script += ReadString2Qw(e.Params[1]); + break; + } + case EW_ASSIGNVAR: + { + Script += " "; + Script += GetVar(e.Params[0]);; + Script += " "; + Script += ReadString2Qw(e.Params[1]); + AString maxLen, startOffset; + if (e.Params[2] != 0) + maxLen = ReadString2(e.Params[2]); + if (e.Params[3] != 0) + startOffset = ReadString2(e.Params[3]); + if (!maxLen.IsEmpty() || !startOffset.IsEmpty()) + { + Script += " "; + if (maxLen.IsEmpty()) + Script += "\"\""; + else + Script += maxLen; + if (!startOffset.IsEmpty()) + { + Script += " "; + Script += startOffset; + } + } + break; + } + case EW_STRCMP: + { + Script += " "; + + Script += " "; + Script += ReadString2Qw(e.Params[0]); + + Script += " "; + Script += ReadString2Qw(e.Params[1]); + + for (int j = 2; j < 5; j++) + { + Script += " "; + Script += UIntToString(e.Params[j]); + } + break; + } + case EW_INTCMP: + { + if (e.Params[5] != 0) + Script += "U"; + + Script += " "; + Script += ReadString2(e.Params[0]); + Script += " "; + Script += ReadString2(e.Params[1]); + + for (int i = 2; i < 5; i++) + { + Script += " "; + Script += UIntToString(e.Params[i]); + } + break; + } + case EW_INTOP: + { + Script += " "; + Script += GetVar(e.Params[0]); + Script += " "; + int numOps = 2; + AString op; + switch (e.Params[3]) + { + case 0: op = '+'; break; + case 1: op = '-'; break; + case 2: op = '*'; break; + case 3: op = '/'; break; + case 4: op = '|'; break; + case 5: op = '&'; break; + case 6: op = '^'; break; + case 7: op = '~'; numOps = 1; break; + case 8: op = '!'; numOps = 1; break; + case 9: op = "||"; break; + case 10: op = "&&"; break; + case 11: op = '%'; break; + default: op = UIntToString(e.Params[3]); + } + AString p1 = ReadString2(e.Params[1]); + if (numOps == 1) + { + Script += op; + Script += p1; + } + else + { + Script += p1; + Script += " "; + Script += op; + Script += " "; + Script += ReadString2(e.Params[2]); + } + break; + } + + case EW_PUSHPOP: + { + int isPop = (e.Params[1] != 0); + if (isPop) + { + Script += "Pop"; + Script += " "; + Script += GetVar(e.Params[0]);; + } + else + { + int isExch = (e.Params[2] != 0); + if (isExch) + { + Script += "Exch"; + } + else + { + Script += "Push"; + Script += " "; + Script += ReadString2(e.Params[0]); + } + } + break; + } + + case EW_SENDMESSAGE: + { + // SendMessage: 6 [output, hwnd, msg, wparam, lparam, [wparamstring?1:0 | lparamstring?2:0 | timeout<<2] + Script += " "; + // Script += ReadString2(e.Params[0]); + // Script += " "; + Script += ReadString2(e.Params[1]); + Script += " "; + Script += ReadString2(e.Params[2]); + + Script += " "; + UInt32 spec = e.Params[5]; + // if (spec & 1) + Script += IntToString(e.Params[3]); + // else + // Script += ReadString2(e.Params[3]); + + Script += " "; + // if (spec & 2) + Script += IntToString(e.Params[4]); + // else + // Script += ReadString2(e.Params[4]); + + if ((Int32)e.Params[0] >= 0) + { + Script += " "; + Script += GetVar(e.Params[1]); + } + + spec >>= 2; + if (spec != 0) + { + Script += " /TIMEOUT="; + Script += IntToString(spec); + } + break; + } + + case EW_GETDLGITEM: + { + Script += " "; + Script += GetVar(e.Params[0]);; + Script += " "; + Script += ReadString2(e.Params[1]); + Script += " "; + Script += ReadString2(e.Params[2]); + break; + } + + + case EW_REGISTERDLL: + { + Script += " "; + Script += ReadString2(e.Params[0]); + Script += " "; + Script += ReadString2(e.Params[1]); + Script += " "; + Script += UIntToString(e.Params[2]); + break; + } + + case EW_CREATESHORTCUT: + { + AString s; + + Script += " "; + Script += ReadString2Qw(e.Params[0]); + + Script += " "; + Script += ReadString2Qw(e.Params[1]); + + for (int j = 2; j < 5; j++) + { + Script += " "; + Script += UIntToString(e.Params[j]); + } + break; + } + + /* + case EW_DELREG: + { + AString keyName, valueName; + keyName = ReadString2(e.Params[1]); + bool isValue = (e.Params[2] != -1); + if (isValue) + { + valueName = ReadString2(e.Params[2]); + Script += "Key"; + } + else + Script += "Value"; + Script += " "; + Script += UIntToString(e.Params[0]); + Script += " "; + Script += keyName; + if (isValue) + { + Script += " "; + Script += valueName; + } + Script += " "; + Script += UIntToString(e.Params[3]); + break; + } + */ + + case EW_WRITEREG: + { + AString s; + switch(e.Params[4]) + { + case 1: s = "Str"; break; + case 2: s = "ExpandStr"; break; + case 3: s = "Bin"; break; + case 4: s = "DWORD"; break; + default: s = "?" + UIntToString(e.Params[4]); break; + } + Script += s; + Script += " "; + Script += GetRegRootID(e.Params[0]); + Script += " "; + + AString keyName, valueName; + keyName = ReadString2Qw(e.Params[1]); + Script += keyName; + Script += " "; + + valueName = ReadString2Qw(e.Params[2]); + Script += valueName; + Script += " "; + + valueName = ReadString2Qw(e.Params[3]); + Script += valueName; + Script += " "; + + break; + } + + case EW_WRITEUNINSTALLER: + { + Script += " "; + Script += ReadString2(e.Params[0]); + for (int j = 1; j < 3; j++) + { + Script += " "; + Script += UIntToString(e.Params[j]); + } + break; + } + + default: + { + int numParams = kNumEntryParams; + if (e.Which < sizeof(kCommandPairs) / sizeof(kCommandPairs[0])) + { + const CCommandPair &pair = kCommandPairs[e.Which]; + // Script += pair.Name; + numParams = pair.NumParams; + } + else + { + Script += "Unknown"; + Script += UIntToString(e.Which); + } + Script += e.GetParamsString(numParams); + } + #endif + } + #ifdef NSIS_SCRIPT + Script += kCrLf; + #endif + } + + { + Items.Sort(CompareItems, 0); + int i; + // if (IsSolid) + for (i = 0; i + 1 < Items.Size();) + { + bool sameName = IsUnicode ? + (Items[i].NameU == Items[i + 1].NameU) : + (Items[i].NameA == Items[i + 1].NameA); + if (Items[i].Pos == Items[i + 1].Pos && sameName) + Items.Delete(i + 1); + else + i++; + } + for (i = 0; i < Items.Size(); i++) + { + CItem &item = Items[i]; + UInt32 curPos = item.Pos + 4; + for (int nextIndex = i + 1; nextIndex < Items.Size(); nextIndex++) + { + UInt32 nextPos = Items[nextIndex].Pos; + if (curPos <= nextPos) + { + item.EstimatedSizeIsDefined = true; + item.EstimatedSize = nextPos - curPos; + break; + } + } + } + if (!IsSolid) + { + for (i = 0; i < Items.Size(); i++) + { + CItem &item = Items[i]; + RINOK(_stream->Seek(GetPosOfNonSolidItem(i), STREAM_SEEK_SET, NULL)); + const UInt32 kSigSize = 4 + 1 + 5; + BYTE sig[kSigSize]; + size_t processedSize = kSigSize; + RINOK(ReadStream(_stream, sig, &processedSize)); + if (processedSize < 4) + return S_FALSE; + UInt32 size = Get32(sig); + if ((size & 0x80000000) != 0) + { + item.IsCompressed = true; + // is compressed; + size &= ~0x80000000; + if (Method == NMethodType::kLZMA) + { + if (processedSize < 9) + return S_FALSE; + if (FilterFlag) + item.UseFilter = (sig[4] != 0); + item.DictionarySize = Get32(sig + 5 + (FilterFlag ? 1 : 0)); + } + } + else + { + item.IsCompressed = false; + item.Size = size; + item.SizeIsDefined = true; + } + item.CompressedSize = size; + item.CompressedSizeIsDefined = true; + } + } + } + return S_OK; +} + +HRESULT CInArchive::Parse() +{ + // UInt32 offset = ReadUInt32(); + // ???? offset == FirstHeader.HeaderLength + /* UInt32 ehFlags = */ ReadUInt32(); + CBlockHeader bhPages, bhSections, bhEntries, bhStrings, bhLangTables, bhCtlColors, bhData; + // CBlockHeader bgFont; + ReadBlockHeader(bhPages); + ReadBlockHeader(bhSections); + ReadBlockHeader(bhEntries); + ReadBlockHeader(bhStrings); + ReadBlockHeader(bhLangTables); + ReadBlockHeader(bhCtlColors); + // ReadBlockHeader(bgFont); + ReadBlockHeader(bhData); + + _stringsPos = bhStrings.Offset; + UInt32 pos = GetOffset() + _stringsPos; + int numZeros0 = 0; + int numZeros1 = 0; + int i; + const int kBlockSize = 256; + for (i = 0; i < kBlockSize; i++) + { + if (pos >= _size || pos + 1 >= _size) + break; + char c0 = _data[pos++]; + char c1 = _data[pos++]; + wchar_t c = (c0 | ((wchar_t)c1 << 8)); + + if (c >= NS_UN_CODES_START && c < NS_UN_CODES_END) + { + if (pos >= _size || pos + 1 >= _size) + break; + pos += 2; + numZeros1++; + } + else + { + if (c0 == 0 && c1 != 0) + numZeros0++; + if (c1 == 0) + numZeros1++; + } + // printf("\nnumZeros0 = %2x %2x", _data[pos + 0], _data[pos + 1]); + } + IsUnicode = (numZeros1 > numZeros0 * 3 + kBlockSize / 16); + // printf("\nnumZeros0 = %3d numZeros1 = %3d", numZeros0, numZeros1); + return ReadEntries(bhEntries); +} + +static bool IsLZMA(const Byte *p, UInt32 &dictionary) +{ + dictionary = Get32(p + 1); + return (p[0] == 0x5D && p[1] == 0x00 && p[2] == 0x00 && p[5] == 0x00); +} + +static bool IsLZMA(const Byte *p, UInt32 &dictionary, bool &thereIsFlag) +{ + if (IsLZMA(p, dictionary)) + { + thereIsFlag = false; + return true; + } + if (IsLZMA(p + 1, dictionary)) + { + thereIsFlag = true; + return true; + } + return false; +} + +static bool IsBZip2(const Byte *p) +{ + return (p[0] == 0x31 && p[1] < 14); +} + +HRESULT CInArchive::Open2( + DECL_EXTERNAL_CODECS_LOC_VARS2 + ) +{ + RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &StreamOffset)); + + const UInt32 kSigSize = 4 + 1 + 5 + 1; // size, flag, lzma props, lzma first byte + BYTE sig[kSigSize]; + RINOK(ReadStream_FALSE(_stream, sig, kSigSize)); + UInt64 position; + RINOK(_stream->Seek(StreamOffset, STREAM_SEEK_SET, &position)); + + _headerIsCompressed = true; + IsSolid = true; + FilterFlag = false; + DictionarySize = 1; + + UInt32 compressedHeaderSize = Get32(sig); + + if (compressedHeaderSize == FirstHeader.HeaderLength) + { + _headerIsCompressed = false; + IsSolid = false; + Method = NMethodType::kCopy; + } + else if (IsLZMA(sig, DictionarySize, FilterFlag)) + { + Method = NMethodType::kLZMA; + } + else if (IsLZMA(sig + 4, DictionarySize, FilterFlag)) + { + IsSolid = false; + Method = NMethodType::kLZMA; + } + else if (sig[3] == 0x80) + { + IsSolid = false; + if (IsBZip2(sig + 4)) + Method = NMethodType::kBZip2; + else + Method = NMethodType::kDeflate; + } + else if (IsBZip2(sig)) + { + Method = NMethodType::kBZip2; + } + else + { + Method = NMethodType::kDeflate; + } + + _posInData = 0; + if (!IsSolid) + { + _headerIsCompressed = ((compressedHeaderSize & 0x80000000) != 0); + if (_headerIsCompressed) + compressedHeaderSize &= ~0x80000000; + _nonSolidStartOffset = compressedHeaderSize; + RINOK(_stream->Seek(StreamOffset + 4, STREAM_SEEK_SET, NULL)); + } + UInt32 unpackSize = FirstHeader.HeaderLength; + if (_headerIsCompressed) + { + // unpackSize = (1 << 23); + _data.SetCapacity(unpackSize); + RINOK(Decoder.Init( + EXTERNAL_CODECS_LOC_VARS + _stream, Method, FilterFlag, UseFilter)); + size_t processedSize = unpackSize; + RINOK(Decoder.Read(_data, &processedSize)); + if (processedSize != unpackSize) + return S_FALSE; + _size = processedSize; + if (IsSolid) + { + UInt32 size2 = ReadUInt32(); + if (size2 < _size) + _size = size2; + } + } + else + { + _data.SetCapacity(unpackSize); + _size = (size_t)unpackSize; + RINOK(ReadStream_FALSE(_stream, (Byte *)_data, unpackSize)); + } + return Parse(); +} + +/* +NsisExe = +{ + ExeStub + Archive // must start from 512 * N + #ifndef NSIS_CONFIG_CRC_ANAL + { + Some additional data + } +} + +Archive +{ + FirstHeader + Data + #ifdef NSIS_CONFIG_CRC_SUPPORT && FirstHeader.ThereIsCrc() + { + CRC + } +} + +FirstHeader +{ + UInt32 Flags; + Byte Signature[16]; + // points to the header+sections+entries+stringtable in the datablock + UInt32 HeaderLength; + UInt32 ArchiveSize; +} +*/ + +HRESULT CInArchive::Open( + DECL_EXTERNAL_CODECS_LOC_VARS + IInStream *inStream, const UInt64 *maxCheckStartPosition) +{ + Clear(); + RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); + UInt64 maxSize = ((maxCheckStartPosition != 0) ? *maxCheckStartPosition : 0); + const UInt32 kStep = 512; + Byte buffer[kStep]; + + UInt64 position = 0; + for (; position <= maxSize; position += kStep) + { + RINOK(ReadStream_FALSE(inStream, buffer, kStep)); + if (memcmp(buffer + 4, kSignature, kSignatureSize) == 0) + break; + } + if (position > maxSize) + return S_FALSE; + const UInt32 kStartHeaderSize = 4 * 7; + RINOK(inStream->Seek(0, STREAM_SEEK_END, &_archiveSize)); + RINOK(inStream->Seek(position + kStartHeaderSize, STREAM_SEEK_SET, 0)); + FirstHeader.Flags = Get32(buffer); + FirstHeader.HeaderLength = Get32(buffer + kSignatureSize + 4); + FirstHeader.ArchiveSize = Get32(buffer + kSignatureSize + 8); + if (_archiveSize - position < FirstHeader.ArchiveSize) + return S_FALSE; + + try + { + _stream = inStream; + HRESULT res = Open2(EXTERNAL_CODECS_LOC_VARS2); + if (res != S_OK) + Clear(); + _stream.Release(); + return res; + } + catch(...) { Clear(); return S_FALSE; } +} + +void CInArchive::Clear() +{ + #ifdef NSIS_SCRIPT + Script.Empty(); + #endif + Items.Clear(); + _stream.Release(); +} + +}} diff --git a/CPP/7zip/Archive/Nsis/NsisIn.h b/CPP/7zip/Archive/Nsis/NsisIn.h new file mode 100755 index 0000000..1c36d09 --- /dev/null +++ b/CPP/7zip/Archive/Nsis/NsisIn.h @@ -0,0 +1,181 @@ +// NsisIn.h + +#ifndef __ARCHIVE_NSIS_IN_H +#define __ARCHIVE_NSIS_IN_H + +#include "Common/Buffer.h" +#include "Common/MyCom.h" +#include "Common/StringConvert.h" + +#include "NsisDecode.h" + +// #define NSIS_SCRIPT + +namespace NArchive { +namespace NNsis { + +const int kSignatureSize = 16; +#define NSIS_SIGNATURE { 0xEF, 0xBE, 0xAD, 0xDE, 0x4E, 0x75, 0x6C, 0x6C, 0x73, 0x6F, 0x66, 0x74, 0x49, 0x6E, 0x73, 0x74} + +extern Byte kSignature[kSignatureSize]; + +const UInt32 kFlagsMask = 0xF; +namespace NFlags +{ + const UInt32 kUninstall = 1; + const UInt32 kSilent = 2; + const UInt32 kNoCrc = 4; + const UInt32 kForceCrc = 8; +} + +struct CFirstHeader +{ + UInt32 Flags; + UInt32 HeaderLength; + + UInt32 ArchiveSize; + + bool ThereIsCrc() const + { + if ((Flags & NFlags::kForceCrc ) != 0) + return true; + return ((Flags & NFlags::kNoCrc) == 0); + } + + UInt32 GetDataSize() const { return ArchiveSize - (ThereIsCrc() ? 4 : 0); } +}; + + +struct CBlockHeader +{ + UInt32 Offset; + UInt32 Num; +}; + +struct CItem +{ + AString PrefixA; + UString PrefixU; + AString NameA; + UString NameU; + FILETIME MTime; + bool IsUnicode; + bool UseFilter; + bool IsCompressed; + bool SizeIsDefined; + bool CompressedSizeIsDefined; + bool EstimatedSizeIsDefined; + UInt32 Pos; + UInt32 Size; + UInt32 CompressedSize; + UInt32 EstimatedSize; + UInt32 DictionarySize; + + CItem(): IsUnicode(false), UseFilter(false), IsCompressed(true), SizeIsDefined(false), + CompressedSizeIsDefined(false), EstimatedSizeIsDefined(false), Size(0), DictionarySize(1) {} + + bool IsINSTDIR() const + { + return (PrefixA.Length() >= 3 || PrefixU.Length() >= 3); + } + + UString GetReducedName(bool unicode) const + { + UString s; + if (unicode) + s = PrefixU; + else + s = MultiByteToUnicodeString(PrefixA); + if (s.Length() > 0) + if (s[s.Length() - 1] != L'\\') + s += L'\\'; + if (unicode) + s += NameU; + else + s += MultiByteToUnicodeString(NameA); + const int len = 9; + if (s.Left(len).CompareNoCase(L"$INSTDIR\\") == 0) + s = s.Mid(len); + return s; + } +}; + +class CInArchive +{ + UInt64 _archiveSize; + CMyComPtr _stream; + + Byte ReadByte(); + UInt32 ReadUInt32(); + HRESULT Open2( + DECL_EXTERNAL_CODECS_LOC_VARS2 + ); + void ReadBlockHeader(CBlockHeader &bh); + AString ReadStringA(UInt32 pos) const; + UString ReadStringU(UInt32 pos) const; + AString ReadString2A(UInt32 pos) const; + UString ReadString2U(UInt32 pos) const; + AString ReadString2(UInt32 pos) const; + AString ReadString2Qw(UInt32 pos) const; + HRESULT ReadEntries(const CBlockHeader &bh); + HRESULT Parse(); + + CByteBuffer _data; + UInt64 _size; + + size_t _posInData; + + UInt32 _stringsPos; + + + bool _headerIsCompressed; + UInt32 _nonSolidStartOffset; +public: + HRESULT Open( + DECL_EXTERNAL_CODECS_LOC_VARS + IInStream *inStream, const UInt64 *maxCheckStartPosition); + void Clear(); + + UInt64 StreamOffset; + CDecoder Decoder; + CObjectVector Items; + CFirstHeader FirstHeader; + NMethodType::EEnum Method; + UInt32 DictionarySize; + bool IsSolid; + bool UseFilter; + bool FilterFlag; + bool IsUnicode; + + #ifdef NSIS_SCRIPT + AString Script; + #endif + UInt32 GetOffset() const { return IsSolid ? 4 : 0; } + UInt64 GetDataPos(int index) + { + const CItem &item = Items[index]; + return GetOffset() + FirstHeader.HeaderLength + item.Pos; + } + + UInt64 GetPosOfSolidItem(int index) const + { + const CItem &item = Items[index]; + return 4 + FirstHeader.HeaderLength + item.Pos; + } + + UInt64 GetPosOfNonSolidItem(int index) const + { + const CItem &item = Items[index]; + return StreamOffset + _nonSolidStartOffset + 4 + item.Pos; + } + + void Release() + { + Decoder.Release(); + } + +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Nsis/NsisRegister.cpp b/CPP/7zip/Archive/Nsis/NsisRegister.cpp new file mode 100755 index 0000000..66cf10f --- /dev/null +++ b/CPP/7zip/Archive/Nsis/NsisRegister.cpp @@ -0,0 +1,13 @@ +// NsisRegister.cpp + +#include "StdAfx.h" + +#include "../../Common/RegisterArc.h" + +#include "NsisHandler.h" +static IInArchive *CreateArc() { return new NArchive::NNsis::CHandler; } + +static CArcInfo g_ArcInfo = + { L"Nsis", L"", 0, 0x9, NSIS_SIGNATURE, NArchive::NNsis::kSignatureSize, false, CreateArc, 0 }; + +REGISTER_ARC(Nsis) diff --git a/CPP/7zip/Archive/Nsis/StdAfx.h b/CPP/7zip/Archive/Nsis/StdAfx.h new file mode 100755 index 0000000..a4e6173 --- /dev/null +++ b/CPP/7zip/Archive/Nsis/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" +#include "../../../Common/NewHandler.h" + +#endif diff --git a/CPP/7zip/Archive/NtfsHandler.cpp b/CPP/7zip/Archive/NtfsHandler.cpp new file mode 100755 index 0000000..f1df803 --- /dev/null +++ b/CPP/7zip/Archive/NtfsHandler.cpp @@ -0,0 +1,1764 @@ +// NtfsHandler.cpp + +#include "StdAfx.h" + +// #define SHOW_DEBUG_INFO +// #define SHOW_DEBUG_INFO2 + +#if defined(SHOW_DEBUG_INFO) || defined(SHOW_DEBUG_INFO2) +#include +#endif + +#include "../../../C/CpuArch.h" + +#include "Common/Buffer.h" +#include "Common/ComTry.h" +#include "Common/IntToString.h" +#include "Common/MyCom.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +#include "Common/DummyOutStream.h" + +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif + +#ifdef SHOW_DEBUG_INFO2 +#define PRF2(x) x +#else +#define PRF2(x) +#endif + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) +#define Get64(p) GetUi64(p) + +#define G16(p, dest) dest = Get16(p); +#define G32(p, dest) dest = Get32(p); +#define G64(p, dest) dest = Get64(p); + +namespace NArchive { +namespace Ntfs { + +static const UInt32 kNumSysRecs = 16; +static const UInt32 kRecIndex_Volume = 3; +static const UInt32 kRecIndex_BadClus = 8; + +struct CHeader +{ + Byte SectorSizeLog; + Byte ClusterSizeLog; + // Byte MediaType; + UInt32 NumHiddenSectors; + UInt64 NumClusters; + UInt64 MftCluster; + UInt64 SerialNumber; + UInt16 SectorsPerTrack; + UInt16 NumHeads; + + UInt64 GetPhySize() const { return NumClusters << ClusterSizeLog; } + UInt32 ClusterSize() const { return (UInt32)1 << ClusterSizeLog; } + bool Parse(const Byte *p); +}; + +static int GetLog(UInt32 num) +{ + for (int i = 0; i < 31; i++) + if (((UInt32)1 << i) == num) + return i; + return -1; +} + +bool CHeader::Parse(const Byte *p) +{ + if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA) + return false; + + int codeOffset = 0; + switch (p[0]) + { + case 0xE9: codeOffset = 3 + (Int16)Get16(p + 1); break; + case 0xEB: if (p[2] != 0x90) return false; codeOffset = 2 + (signed char)p[1]; break; + default: return false; + } + Byte sectorsPerClusterLog; + + if (memcmp(p + 3, "NTFS ", 8) != 0) + return false; + { + int s = GetLog(Get16(p + 11)); + if (s < 9 || s > 12) + return false; + SectorSizeLog = (Byte)s; + s = GetLog(p[13]); + if (s < 0) + return false; + sectorsPerClusterLog = (Byte)s; + ClusterSizeLog = SectorSizeLog + sectorsPerClusterLog; + } + + for (int i = 14; i < 21; i++) + if (p[i] != 0) + return false; + + // MediaType = p[21]; + if (Get16(p + 22) != 0) // NumFatSectors + return false; + G16(p + 24, SectorsPerTrack); + G16(p + 26, NumHeads); + G32(p + 28, NumHiddenSectors); + if (Get32(p + 32) != 0) // NumSectors32 + return false; + + // DriveNumber = p[0x24]; + if (p[0x25] != 0) // CurrentHead + return false; + /* + NTFS-HDD: p[0x26] = 0x80 + NTFS-FLASH: p[0x26] = 0 + */ + if (p[0x26] != 0x80 && p[0x26] != 0) // ExtendedBootSig + return false; + if (p[0x27] != 0) // reserved + return false; + UInt64 numSectors = Get64(p + 0x28); + NumClusters = numSectors >> sectorsPerClusterLog; + + G64(p + 0x30, MftCluster); + // G64(p + 0x38, Mft2Cluster); + G64(p + 0x48, SerialNumber); + UInt32 numClustersInMftRec; + UInt32 numClustersInIndexBlock; + G32(p + 0x40, numClustersInMftRec); + G32(p + 0x44, numClustersInIndexBlock); + return (numClustersInMftRec < 256 && numClustersInIndexBlock < 256); +} + +struct CMftRef +{ + UInt64 Val; + UInt64 GetIndex() const { return Val & (((UInt64)1 << 48) - 1); } + UInt16 GetNumber() const { return (UInt16)(Val >> 48); } + bool IsBaseItself() const { return Val == 0; } +}; + +#define ATNAME(n) ATTR_TYPE_ ## n +#define DEF_ATTR_TYPE(v, n) ATNAME(n) = v + +enum +{ + DEF_ATTR_TYPE(0x00, UNUSED), + DEF_ATTR_TYPE(0x10, STANDARD_INFO), + DEF_ATTR_TYPE(0x20, ATTRIBUTE_LIST), + DEF_ATTR_TYPE(0x30, FILE_NAME), + DEF_ATTR_TYPE(0x40, OBJECT_ID), + DEF_ATTR_TYPE(0x50, SECURITY_DESCRIPTOR), + DEF_ATTR_TYPE(0x60, VOLUME_NAME), + DEF_ATTR_TYPE(0x70, VOLUME_INFO), + DEF_ATTR_TYPE(0x80, DATA), + DEF_ATTR_TYPE(0x90, INDEX_ROOT), + DEF_ATTR_TYPE(0xA0, INDEX_ALLOCATION), + DEF_ATTR_TYPE(0xB0, BITMAP), + DEF_ATTR_TYPE(0xC0, REPARSE_POINT), + DEF_ATTR_TYPE(0xD0, EA_INFO), + DEF_ATTR_TYPE(0xE0, EA), + DEF_ATTR_TYPE(0xF0, PROPERTY_SET), + DEF_ATTR_TYPE(0x100, LOGGED_UTILITY_STREAM), + DEF_ATTR_TYPE(0x1000, FIRST_USER_DEFINED_ATTRIBUTE) +}; + +static const Byte kFileNameType_Posix = 0; +static const Byte kFileNameType_Win32 = 1; +static const Byte kFileNameType_Dos = 2; +static const Byte kFileNameType_Win32Dos = 3; + +struct CFileNameAttr +{ + CMftRef ParentDirRef; + // UInt64 CTime; + // UInt64 MTime; + // UInt64 ThisRecMTime; + // UInt64 ATime; + // UInt64 AllocatedSize; + // UInt64 DataSize; + // UInt16 PackedEaSize; + UString Name; + UInt32 Attrib; + Byte NameType; + + bool IsDos() const { return NameType == kFileNameType_Dos; } + bool Parse(const Byte *p, unsigned size); +}; + +static void GetString(const Byte *p, unsigned length, UString &res) +{ + wchar_t *s = res.GetBuffer(length); + for (unsigned i = 0; i < length; i++) + s[i] = Get16(p + i * 2); + s[length] = 0; + res.ReleaseBuffer(); +} + +bool CFileNameAttr::Parse(const Byte *p, unsigned size) +{ + if (size < 0x42) + return false; + G64(p + 0x00, ParentDirRef.Val); + // G64(p + 0x08, CTime); + // G64(p + 0x10, MTime); + // G64(p + 0x18, ThisRecMTime); + // G64(p + 0x20, ATime); + // G64(p + 0x28, AllocatedSize); + // G64(p + 0x30, DataSize); + G32(p + 0x38, Attrib); + // G16(p + 0x3C, PackedEaSize); + NameType = p[0x41]; + unsigned length = p[0x40]; + if (0x42 + length > size) + return false; + GetString(p + 0x42, length, Name); + return true; +} + +struct CSiAttr +{ + UInt64 CTime; + UInt64 MTime; + // UInt64 ThisRecMTime; + UInt64 ATime; + UInt32 Attrib; + + /* + UInt32 MaxVersions; + UInt32 Version; + UInt32 ClassId; + UInt32 OwnerId; + UInt32 SecurityId; + UInt64 QuotaCharged; + */ + + bool Parse(const Byte *p, unsigned size); +}; + +bool CSiAttr::Parse(const Byte *p, unsigned size) +{ + if (size < 0x24) + return false; + G64(p + 0x00, CTime); + G64(p + 0x08, MTime); + // G64(p + 0x10, ThisRecMTime); + G64(p + 0x18, ATime); + G32(p + 0x20, Attrib); + return true; +} + +static const UInt64 kEmptyExtent = (UInt64)(Int64)-1; + +struct CExtent +{ + UInt64 Virt; + UInt64 Phy; + + bool IsEmpty() const { return Phy == kEmptyExtent; } +}; + +struct CVolInfo +{ + Byte MajorVer; + Byte MinorVer; + // UInt16 Flags; + + bool Parse(const Byte *p, unsigned size); +}; + +bool CVolInfo::Parse(const Byte *p, unsigned size) +{ + if (size < 12) + return false; + MajorVer = p[8]; + MinorVer = p[9]; + // Flags = Get16(p + 10); + return true; +} + +struct CAttr +{ + UInt32 Type; + // UInt32 Length; + UString Name; + // UInt16 Flags; + // UInt16 Instance; + CByteBuffer Data; + Byte NonResident; + + // Non-Resident + Byte CompressionUnit; + UInt64 LowVcn; + UInt64 HighVcn; + UInt64 AllocatedSize; + UInt64 Size; + UInt64 PackSize; + UInt64 InitializedSize; + + // Resident + // UInt16 ResidentFlags; + + bool IsCompressionUnitSupported() const { return CompressionUnit == 0 || CompressionUnit == 4; } + + UInt32 Parse(const Byte *p, unsigned size); + bool ParseFileName(CFileNameAttr &a) const { return a.Parse(Data, (unsigned)Data.GetCapacity()); } + bool ParseSi(CSiAttr &a) const { return a.Parse(Data, (unsigned)Data.GetCapacity()); } + bool ParseVolInfo(CVolInfo &a) const { return a.Parse(Data, (unsigned)Data.GetCapacity()); } + bool ParseExtents(CRecordVector &extents, UInt64 numClustersMax, int compressionUnit) const; + UInt64 GetSize() const { return NonResident ? Size : Data.GetCapacity(); } + UInt64 GetPackSize() const + { + if (!NonResident) + return Data.GetCapacity(); + if (CompressionUnit != 0) + return PackSize; + return AllocatedSize; + } +}; + +#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } + +static int CompareAttr(void *const *elem1, void *const *elem2, void *) +{ + const CAttr &a1 = *(*((const CAttr **)elem1)); + const CAttr &a2 = *(*((const CAttr **)elem2)); + RINOZ(MyCompare(a1.Type, a2.Type)); + RINOZ(MyCompare(a1.Name, a2.Name)); + return MyCompare(a1.LowVcn, a2.LowVcn); +} + +UInt32 CAttr::Parse(const Byte *p, unsigned size) +{ + if (size < 4) + return 0; + G32(p, Type); + if (Type == 0xFFFFFFFF) + return 4; + if (size < 0x18) + return 0; + PRF(printf(" T=%2X", Type)); + + UInt32 length = Get32(p + 0x04); + PRF(printf(" L=%3d", length)); + if (length > size) + return 0; + NonResident = p[0x08]; + { + int nameLength = p[9]; + UInt32 nameOffset = Get16(p + 0x0A); + if (nameLength != 0) + { + if (nameOffset + nameLength * 2 > length) + return 0; + GetString(p + nameOffset, nameLength, Name); + PRF(printf(" N=%S", Name)); + } + } + + // G16(p + 0x0C, Flags); + // G16(p + 0x0E, Instance); + // PRF(printf(" F=%4X", Flags)); + // PRF(printf(" Inst=%d", Instance)); + + UInt32 dataSize; + UInt32 offs; + if (NonResident) + { + if (length < 0x40) + return 0; + PRF(printf(" NR")); + G64(p + 0x10, LowVcn); + G64(p + 0x18, HighVcn); + G64(p + 0x28, AllocatedSize); + G64(p + 0x30, Size); + G64(p + 0x38, InitializedSize); + G16(p + 0x20, offs); + CompressionUnit = p[0x22]; + + PackSize = Size; + if (CompressionUnit != 0) + { + if (length < 0x48) + return 0; + G64(p + 0x40, PackSize); + PRF(printf(" PS=%I64x", PackSize)); + } + + // PRF(printf("\n")); + PRF(printf(" ASize=%4I64d", AllocatedSize)); + PRF(printf(" Size=%I64d", Size)); + PRF(printf(" IS=%I64d", InitializedSize)); + PRF(printf(" Low=%I64d", LowVcn)); + PRF(printf(" High=%I64d", HighVcn)); + PRF(printf(" CU=%d", (int)CompressionUnit)); + dataSize = length - offs; + } + else + { + if (length < 0x18) + return 0; + PRF(printf(" RES")); + dataSize = Get32(p + 0x10); + PRF(printf(" dataSize=%3d", dataSize)); + offs = Get16(p + 0x14); + // G16(p + 0x16, ResidentFlags); + // PRF(printf(" ResFlags=%4X", ResidentFlags)); + } + if (offs > length || dataSize > length || length - dataSize < offs) + return 0; + Data.SetCapacity(dataSize); + memcpy(Data, p + offs, dataSize); + #ifdef SHOW_DEBUG_INFO + PRF(printf(" : ")); + for (unsigned i = 0; i < Data.GetCapacity(); i++) + { + PRF(printf(" %02X", (int)Data[i])); + } + #endif + return length; +} + +bool CAttr::ParseExtents(CRecordVector &extents, UInt64 numClustersMax, int compressionUnit) const +{ + const Byte *p = Data; + unsigned size = (unsigned)Data.GetCapacity(); + UInt64 vcn = LowVcn; + UInt64 lcn = 0; + UInt64 highVcn1 = HighVcn + 1; + if (LowVcn != extents.Back().Virt || highVcn1 > (UInt64)1 << 63) + return false; + + extents.DeleteBack(); + + PRF2(printf("\n# ParseExtents # LowVcn = %4I64X # HighVcn = %4I64X", LowVcn, HighVcn)); + + while (size > 0) + { + Byte b = *p++; + size--; + if (b == 0) + break; + UInt32 num = b & 0xF; + if (num == 0 || num > 8 || num > size) + return false; + + int i; + UInt64 vSize = p[num - 1]; + for (i = (int)num - 2; i >= 0; i--) + vSize = (vSize << 8) | p[i]; + if (vSize == 0) + return false; + p += num; + size -= num; + if ((highVcn1 - vcn) < vSize) + return false; + + num = (b >> 4) & 0xF; + if (num > 8 || num > size) + return false; + CExtent e; + e.Virt = vcn; + if (num == 0) + { + if (compressionUnit == 0) + return false; + e.Phy = kEmptyExtent; + } + else + { + Int64 v = (signed char)p[num - 1]; + for (i = (int)num - 2; i >= 0; i--) + v = (v << 8) | p[i]; + p += num; + size -= num; + lcn += v; + if (lcn > numClustersMax) + return false; + e.Phy = lcn; + } + extents.Add(e); + vcn += vSize; + } + CExtent e; + e.Phy = kEmptyExtent; + e.Virt = vcn; + extents.Add(e); + return (highVcn1 == vcn); +} + +static const UInt64 kEmptyTag = (UInt64)(Int64)-1; + +static const int kNumCacheChunksLog = 1; +static const UInt32 kNumCacheChunks = (1 << kNumCacheChunksLog); + +class CInStream: + public IInStream, + public CMyUnknownImp +{ + UInt64 _virtPos; + UInt64 _physPos; + UInt64 _curRem; + bool _sparseMode; + size_t _compressedPos; + + UInt64 _tags[kNumCacheChunks]; + int _chunkSizeLog; + CByteBuffer _inBuf; + CByteBuffer _outBuf; +public: + CMyComPtr Stream; + UInt64 Size; + UInt64 InitializedSize; + int BlockSizeLog; + int CompressionUnit; + bool InUse; + CRecordVector Extents; + + HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); } + + UInt32 GetCuSize() const { return (UInt32)1 << (BlockSizeLog + CompressionUnit); } + HRESULT InitAndSeek(int compressionUnit) + { + CompressionUnit = compressionUnit; + if (compressionUnit != 0) + { + UInt32 cuSize = GetCuSize(); + _inBuf.SetCapacity(cuSize); + _chunkSizeLog = BlockSizeLog + CompressionUnit; + _outBuf.SetCapacity(kNumCacheChunks << _chunkSizeLog); + } + for (int i = 0; i < kNumCacheChunks; i++) + _tags[i] = kEmptyTag; + + _sparseMode = false; + _curRem = 0; + _virtPos = 0; + _physPos = 0; + const CExtent &e = Extents[0]; + if (!e.IsEmpty()) + _physPos = e.Phy << BlockSizeLog; + return SeekToPhys(); + } + + MY_UNKNOWN_IMP1(IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + +static size_t Lznt1Dec(Byte *dest, size_t outBufLim, size_t destLen, const Byte *src, size_t srcLen) +{ + size_t destSize = 0; + while (destSize < destLen) + { + if (srcLen < 2 || (destSize & 0xFFF) != 0) + break; + UInt32 v = Get16(src); + if (v == 0) + break; + src += 2; + srcLen -= 2; + UInt32 comprSize = (v & 0xFFF) + 1; + if (comprSize > srcLen) + break; + srcLen -= comprSize; + if ((v & 0x8000) == 0) + { + if (comprSize != (1 << 12)) + break; + memcpy(dest + destSize, src, comprSize); + src += comprSize; + destSize += comprSize; + } + else + { + if (destSize + (1 << 12) > outBufLim || (src[0] & 1) != 0) + return 0; + int numDistBits = 4; + UInt32 sbOffset = 0; + UInt32 pos = 0; + + do + { + comprSize--; + for (UInt32 mask = src[pos++] | 0x100; mask > 1 && comprSize > 0; mask >>= 1) + { + if ((mask & 1) == 0) + { + if (sbOffset >= (1 << 12)) + return 0; + dest[destSize++] = src[pos++]; + sbOffset++; + comprSize--; + } + else + { + if (comprSize < 2) + return 0; + UInt32 v = Get16(src + pos); + pos += 2; + comprSize -= 2; + + while (((sbOffset - 1) >> numDistBits) != 0) + numDistBits++; + + UInt32 len = (v & (0xFFFF >> numDistBits)) + 3; + if (sbOffset + len > (1 << 12)) + return 0; + UInt32 dist = (v >> (16 - numDistBits)); + if (dist >= sbOffset) + return 0; + Int32 offs = -1 - dist; + Byte *p = dest + destSize; + for (UInt32 t = 0; t < len; t++) + p[t] = p[t + offs]; + destSize += len; + sbOffset += len; + } + } + } + while (comprSize > 0); + src += pos; + } + } + return destSize; +} + +STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != NULL) + *processedSize = 0; + if (_virtPos >= Size) + return (Size == _virtPos) ? S_OK: E_FAIL; + if (size == 0) + return S_OK; + UInt64 rem = Size - _virtPos; + if (size > rem) + size = (UInt32)rem; + if (_virtPos >= InitializedSize) + { + memset((Byte *)data, 0, size); + _virtPos += size; + *processedSize = size; + return S_OK; + } + rem = InitializedSize - _virtPos; + if (size > rem) + size = (UInt32)rem; + + while (_curRem == 0) + { + UInt64 cacheTag = _virtPos >> _chunkSizeLog; + UInt32 cacheIndex = (UInt32)cacheTag & (kNumCacheChunks - 1); + if (_tags[cacheIndex] == cacheTag) + { + UInt32 chunkSize = (UInt32)1 << _chunkSizeLog; + UInt32 offset = (UInt32)_virtPos & (chunkSize - 1); + UInt32 cur = MyMin(chunkSize - offset, size); + memcpy(data, _outBuf + (cacheIndex << _chunkSizeLog) + offset, cur); + *processedSize = cur; + _virtPos += cur; + return S_OK; + } + + PRF2(printf("\nVirtPos = %6d", _virtPos)); + + UInt32 comprUnitSize = (UInt32)1 << CompressionUnit; + UInt64 virtBlock = _virtPos >> BlockSizeLog; + UInt64 virtBlock2 = virtBlock & ~((UInt64)comprUnitSize - 1); + + int left = 0, right = Extents.Size(); + for (;;) + { + int mid = (left + right) / 2; + if (mid == left) + break; + if (virtBlock2 < Extents[mid].Virt) + right = mid; + else + left = mid; + } + + bool isCompressed = false; + UInt64 virtBlock2End = virtBlock2 + comprUnitSize; + if (CompressionUnit != 0) + for (int i = left; i < Extents.Size(); i++) + { + const CExtent &e = Extents[i]; + if (e.Virt >= virtBlock2End) + break; + if (e.IsEmpty()) + { + isCompressed = true; + break; + } + } + + int i; + for (i = left; Extents[i + 1].Virt <= virtBlock; i++); + + _sparseMode = false; + if (!isCompressed) + { + const CExtent &e = Extents[i]; + UInt64 newPos = (e.Phy << BlockSizeLog) + _virtPos - (e.Virt << BlockSizeLog); + if (newPos != _physPos) + { + _physPos = newPos; + RINOK(SeekToPhys()); + } + UInt64 next = Extents[i + 1].Virt; + if (next > virtBlock2End) + next &= ~((UInt64)comprUnitSize - 1); + next <<= BlockSizeLog; + if (next > Size) + next = Size; + _curRem = next - _virtPos; + break; + } + bool thereArePhy = false; + for (int i2 = left; i2 < Extents.Size(); i2++) + { + const CExtent &e = Extents[i2]; + if (e.Virt >= virtBlock2End) + break; + if (!e.IsEmpty()) + { + thereArePhy = true; + break; + } + } + if (!thereArePhy) + { + _curRem = (Extents[i + 1].Virt << BlockSizeLog) - _virtPos; + _sparseMode = true; + break; + } + + size_t offs = 0; + UInt64 curVirt = virtBlock2; + for (i = left; i < Extents.Size(); i++) + { + const CExtent &e = Extents[i]; + if (e.IsEmpty()) + break; + if (e.Virt >= virtBlock2End) + return S_FALSE; + UInt64 newPos = (e.Phy + (curVirt - e.Virt)) << BlockSizeLog; + if (newPos != _physPos) + { + _physPos = newPos; + RINOK(SeekToPhys()); + } + UInt64 numChunks = Extents[i + 1].Virt - curVirt; + if (curVirt + numChunks > virtBlock2End) + numChunks = virtBlock2End - curVirt; + size_t compressed = (size_t)numChunks << BlockSizeLog; + RINOK(ReadStream_FALSE(Stream, _inBuf + offs, compressed)); + curVirt += numChunks; + _physPos += compressed; + offs += compressed; + } + size_t destLenMax = GetCuSize(); + size_t destLen = destLenMax; + UInt64 rem = Size - (virtBlock2 << BlockSizeLog); + if (destLen > rem) + destLen = (size_t)rem; + + Byte *dest = _outBuf + (cacheIndex << _chunkSizeLog); + size_t destSizeRes = Lznt1Dec(dest, destLenMax, destLen, _inBuf, offs); + _tags[cacheIndex] = cacheTag; + + // some files in Vista have destSize > destLen + if (destSizeRes < destLen) + { + memset(dest, 0, destLenMax); + if (InUse) + return S_FALSE; + } + } + if (size > _curRem) + size = (UInt32)_curRem; + HRESULT res = S_OK; + if (_sparseMode) + memset(data, 0, size); + else + { + res = Stream->Read(data, size, &size); + _physPos += size; + } + if (processedSize != NULL) + *processedSize = size; + _virtPos += size; + _curRem -= size; + return res; +} + +STDMETHODIMP CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + UInt64 newVirtPos = offset; + switch(seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: newVirtPos += _virtPos; break; + case STREAM_SEEK_END: newVirtPos += Size; break; + default: return STG_E_INVALIDFUNCTION; + } + if (_virtPos != newVirtPos) + _curRem = 0; + _virtPos = newVirtPos; + if (newPosition) + *newPosition = newVirtPos; + return S_OK; +} + +class CByteBufStream: + public IInStream, + public CMyUnknownImp +{ + UInt64 _virtPos; +public: + CByteBuffer Buf; + void Init() { _virtPos = 0; } + + MY_UNKNOWN_IMP1(IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + +STDMETHODIMP CByteBufStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != NULL) + *processedSize = 0; + if (_virtPos >= Buf.GetCapacity()) + return (_virtPos == Buf.GetCapacity()) ? S_OK: E_FAIL; + UInt64 rem = Buf.GetCapacity() - _virtPos; + if (rem < size) + size = (UInt32)rem; + memcpy(data, Buf + (size_t)_virtPos, size); + if (processedSize != NULL) + *processedSize = size; + _virtPos += size; + return S_OK; +} + +STDMETHODIMP CByteBufStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch(seekOrigin) + { + case STREAM_SEEK_SET: _virtPos = offset; break; + case STREAM_SEEK_CUR: _virtPos += offset; break; + case STREAM_SEEK_END: _virtPos = Buf.GetCapacity() + offset; break; + default: return STG_E_INVALIDFUNCTION; + } + if (newPosition) + *newPosition = _virtPos; + return S_OK; +} + +static HRESULT DataParseExtents(int clusterSizeLog, const CObjectVector &attrs, + int attrIndex, int attrIndexLim, UInt64 numPhysClusters, CRecordVector &Extents) +{ + CExtent e; + e.Virt = 0; + e.Phy = kEmptyExtent; + Extents.Add(e); + const CAttr &attr0 = attrs[attrIndex]; + + if (attr0.AllocatedSize < attr0.Size || + (attrs[attrIndexLim - 1].HighVcn + 1) != (attr0.AllocatedSize >> clusterSizeLog) || + (attr0.AllocatedSize & ((1 << clusterSizeLog) - 1)) != 0) + return S_FALSE; + + for (int i = attrIndex; i < attrIndexLim; i++) + if (!attrs[i].ParseExtents(Extents, numPhysClusters, attr0.CompressionUnit)) + return S_FALSE; + + UInt64 packSizeCalc = 0; + for (int k = 0; k < Extents.Size(); k++) + { + CExtent &e = Extents[k]; + if (!e.IsEmpty()) + packSizeCalc += (Extents[k + 1].Virt - e.Virt) << clusterSizeLog; + PRF2(printf("\nSize = %4I64X", Extents[k + 1].Virt - e.Virt)); + PRF2(printf(" Pos = %4I64X", e.Phy)); + } + + if (attr0.CompressionUnit != 0) + { + if (packSizeCalc != attr0.PackSize) + return S_FALSE; + } + else + { + if (packSizeCalc != attr0.AllocatedSize) + return S_FALSE; + } + return S_OK; +} + +struct CDataRef +{ + int Start; + int Num; +}; + +static const UInt32 kMagic_FILE = 0x454c4946; +static const UInt32 kMagic_BAAD = 0x44414142; + +struct CMftRec +{ + UInt32 Magic; + // UInt64 Lsn; + UInt16 SeqNumber; + UInt16 Flags; + // UInt16 LinkCount; + // UInt16 NextAttrInstance; + CMftRef BaseMftRef; + // UInt32 ThisRecNumber; + UInt32 MyNumNameLinks; + + CObjectVector DataAttrs; + CObjectVector FileNames; + CRecordVector DataRefs; + + CSiAttr SiAttr; + + void MoveAttrsFrom(CMftRec &src) + { + DataAttrs += src.DataAttrs; + FileNames += src.FileNames; + src.DataAttrs.ClearAndFree(); + src.FileNames.ClearAndFree(); + } + + UInt64 GetPackSize() const + { + UInt64 res = 0; + for (int i = 0; i < DataRefs.Size(); i++) + res += DataAttrs[DataRefs[i].Start].GetPackSize(); + return res; + } + + bool Parse(Byte *p, int sectorSizeLog, UInt32 numSectors, UInt32 recNumber, CObjectVector *attrs); + + bool IsEmpty() const { return (Magic <= 2); } + bool IsFILE() const { return (Magic == kMagic_FILE); } + bool IsBAAD() const { return (Magic == kMagic_BAAD); } + + bool InUse() const { return (Flags & 1) != 0; } + bool IsDir() const { return (Flags & 2) != 0; } + + void ParseDataNames(); + HRESULT GetStream(IInStream *mainStream, int dataIndex, + int clusterSizeLog, UInt64 numPhysClusters, IInStream **stream) const; + int GetNumExtents(int dataIndex, int clusterSizeLog, UInt64 numPhysClusters) const; + + UInt64 GetSize(int dataIndex) const { return DataAttrs[DataRefs[dataIndex].Start].GetSize(); } + + CMftRec(): MyNumNameLinks(0) {} +}; + +void CMftRec::ParseDataNames() +{ + DataRefs.Clear(); + DataAttrs.Sort(CompareAttr, 0); + + for (int i = 0; i < DataAttrs.Size();) + { + CDataRef ref; + ref.Start = i; + for (i++; i < DataAttrs.Size(); i++) + if (DataAttrs[ref.Start].Name != DataAttrs[i].Name) + break; + ref.Num = i - ref.Start; + DataRefs.Add(ref); + } +} + +HRESULT CMftRec::GetStream(IInStream *mainStream, int dataIndex, + int clusterSizeLog, UInt64 numPhysClusters, IInStream **destStream) const +{ + *destStream = 0; + CByteBufStream *streamSpec = new CByteBufStream; + CMyComPtr streamTemp = streamSpec; + + if (dataIndex < 0) + return E_FAIL; + + if (dataIndex < DataRefs.Size()) + { + const CDataRef &ref = DataRefs[dataIndex]; + int numNonResident = 0; + int i; + for (i = ref.Start; i < ref.Start + ref.Num; i++) + if (DataAttrs[i].NonResident) + numNonResident++; + + const CAttr &attr0 = DataAttrs[ref.Start]; + + if (numNonResident != 0 || ref.Num != 1) + { + if (numNonResident != ref.Num || !attr0.IsCompressionUnitSupported()) + return S_FALSE; + CInStream *streamSpec = new CInStream; + CMyComPtr streamTemp = streamSpec; + RINOK(DataParseExtents(clusterSizeLog, DataAttrs, ref.Start, ref.Start + ref.Num, numPhysClusters, streamSpec->Extents)); + streamSpec->Size = attr0.Size; + streamSpec->InitializedSize = attr0.InitializedSize; + streamSpec->Stream = mainStream; + streamSpec->BlockSizeLog = clusterSizeLog; + streamSpec->InUse = InUse(); + RINOK(streamSpec->InitAndSeek(attr0.CompressionUnit)); + *destStream = streamTemp.Detach(); + return S_OK; + } + streamSpec->Buf = attr0.Data; + } + streamSpec->Init(); + *destStream = streamTemp.Detach(); + return S_OK; +} + +int CMftRec::GetNumExtents(int dataIndex, int clusterSizeLog, UInt64 numPhysClusters) const +{ + if (dataIndex < 0) + return 0; + { + const CDataRef &ref = DataRefs[dataIndex]; + int numNonResident = 0; + int i; + for (i = ref.Start; i < ref.Start + ref.Num; i++) + if (DataAttrs[i].NonResident) + numNonResident++; + + const CAttr &attr0 = DataAttrs[ref.Start]; + + if (numNonResident != 0 || ref.Num != 1) + { + if (numNonResident != ref.Num || !attr0.IsCompressionUnitSupported()) + return 0; // error; + CRecordVector extents; + if (DataParseExtents(clusterSizeLog, DataAttrs, ref.Start, ref.Start + ref.Num, numPhysClusters, extents) != S_OK) + return 0; // error; + return extents.Size() - 1; + } + // if (attr0.Data.GetCapacity() != 0) + // return 1; + return 0; + } +} + +bool CMftRec::Parse(Byte *p, int sectorSizeLog, UInt32 numSectors, UInt32 recNumber, + CObjectVector *attrs) +{ + G32(p, Magic); + if (!IsFILE()) + return IsEmpty() || IsBAAD(); + + UInt32 usaOffset; + UInt32 numUsaItems; + G16(p + 0x04, usaOffset); + G16(p + 0x06, numUsaItems); + + if ((usaOffset & 1) != 0 || usaOffset + numUsaItems * 2 > ((UInt32)1 << sectorSizeLog) - 2 || + numUsaItems == 0 || numUsaItems - 1 != numSectors) + return false; + + UInt16 usn = Get16(p + usaOffset); + // PRF(printf("\nusn = %d", usn)); + for (UInt32 i = 1; i < numUsaItems; i++) + { + void *pp = p + (i << sectorSizeLog) - 2; + if (Get16(pp) != usn) + return false; + SetUi16(pp, Get16(p + usaOffset + i * 2)); + } + + // G64(p + 0x08, Lsn); + G16(p + 0x10, SeqNumber); + // G16(p + 0x12, LinkCount); + // PRF(printf(" L=%d", LinkCount)); + UInt32 attrOffs = Get16(p + 0x14); + G16(p + 0x16, Flags); + PRF(printf(" F=%4X", Flags)); + + UInt32 bytesInUse = Get32(p + 0x18); + UInt32 bytesAlloc = Get32(p + 0x1C); + G64(p + 0x20, BaseMftRef.Val); + if (BaseMftRef.Val != 0) + { + PRF(printf(" BaseRef=%d", (int)BaseMftRef.Val)); + // return false; // Check it; + } + // G16(p + 0x28, NextAttrInstance); + if (usaOffset >= 0x30) + if (Get32(p + 0x2C) != recNumber) // NTFS 3.1+ + return false; + + UInt32 limit = numSectors << sectorSizeLog; + if (attrOffs >= limit || (attrOffs & 7) != 0 || bytesInUse > limit + || bytesAlloc != limit) + return false; + + + for (UInt32 t = attrOffs; t < limit;) + { + CAttr attr; + // PRF(printf("\n %2d:", Attrs.Size())); + PRF(printf("\n")); + UInt32 length = attr.Parse(p + t, limit - t); + if (length == 0 || limit - t < length) + return false; + t += length; + if (attr.Type == 0xFFFFFFFF) + break; + switch(attr.Type) + { + case ATTR_TYPE_FILE_NAME: + { + CFileNameAttr fna; + if (!attr.ParseFileName(fna)) + return false; + FileNames.Add(fna); + PRF(printf(" flags = %4x", (int)fna.NameType)); + PRF(printf("\n %S", fna.Name)); + break; + } + case ATTR_TYPE_STANDARD_INFO: + if (!attr.ParseSi(SiAttr)) + return false; + break; + case ATTR_TYPE_DATA: + DataAttrs.Add(attr); + break; + default: + if (attrs) + attrs->Add(attr); + break; + } + } + + return true; +} + +struct CItem +{ + int RecIndex; + int DataIndex; + CMftRef ParentRef; + UString Name; + UInt32 Attrib; + + bool IsDir() const { return (DataIndex < 0); } +}; + +struct CDatabase +{ + CHeader Header; + CObjectVector Items; + CObjectVector Recs; + CMyComPtr InStream; + IArchiveOpenCallback *OpenCallback; + + CByteBuffer ByteBuf; + + CObjectVector VolAttrs; + + ~CDatabase() { ClearAndClose(); } + + void Clear(); + void ClearAndClose(); + + UString GetItemPath(Int32 index) const; + HRESULT Open(); + HRESULT ReadDir(Int32 parent, UInt32 cluster, int level); + + HRESULT SeekToCluster(UInt64 cluster); + + int FindMtfRec(const CMftRef &ref) const + { + UInt64 val = ref.GetIndex(); + int left = 0, right = Items.Size(); + while (left != right) + { + int mid = (left + right) / 2; + UInt64 midValue = Items[mid].RecIndex; + if (val == midValue) + return mid; + if (val < midValue) + right = mid; + else + left = mid + 1; + } + return -1; + } + +}; + +HRESULT CDatabase::SeekToCluster(UInt64 cluster) +{ + return InStream->Seek(cluster << Header.ClusterSizeLog, STREAM_SEEK_SET, NULL); +} + +void CDatabase::Clear() +{ + Items.Clear(); + Recs.Clear(); +} + +void CDatabase::ClearAndClose() +{ + Clear(); + InStream.Release(); +} + +#define MY_DIR_PREFIX(x) L"[" x L"]" WSTRING_PATH_SEPARATOR + +UString CDatabase::GetItemPath(Int32 index) const +{ + const CItem *item = &Items[index]; + UString name = item->Name; + for (int j = 0; j < 256; j++) + { + CMftRef ref = item->ParentRef; + index = FindMtfRec(ref); + if (ref.GetIndex() == 5) + return name; + if (index < 0 || Recs[Items[index].RecIndex].SeqNumber != ref.GetNumber()) + return MY_DIR_PREFIX(L"UNKNOWN") + name; + item = &Items[index]; + name = item->Name + WCHAR_PATH_SEPARATOR + name; + } + return MY_DIR_PREFIX(L"BAD") + name; +} + +HRESULT CDatabase::Open() +{ + Clear(); + + static const UInt32 kHeaderSize = 512; + Byte buf[kHeaderSize]; + RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize)); + if (!Header.Parse(buf)) + return S_FALSE; + UInt64 fileSize; + RINOK(InStream->Seek(0, STREAM_SEEK_END, &fileSize)); + if (fileSize < Header.GetPhySize()) + return S_FALSE; + + SeekToCluster(Header.MftCluster); + + CMftRec mftRec; + UInt32 numSectorsInRec; + int recSizeLog; + CMyComPtr mftStream; + { + UInt32 blockSize = 1 << 12; + ByteBuf.SetCapacity(blockSize); + RINOK(ReadStream_FALSE(InStream, ByteBuf, blockSize)); + + UInt32 allocSize = Get32(ByteBuf + 0x1C); + recSizeLog = GetLog(allocSize); + if (recSizeLog < Header.SectorSizeLog) + return false; + numSectorsInRec = 1 << (recSizeLog - Header.SectorSizeLog); + if (!mftRec.Parse(ByteBuf, Header.SectorSizeLog, numSectorsInRec, NULL, 0)) + return S_FALSE; + if (!mftRec.IsFILE()) + return S_FALSE; + mftRec.ParseDataNames(); + if (mftRec.DataRefs.IsEmpty()) + return S_FALSE; + RINOK(mftRec.GetStream(InStream, 0, Header.ClusterSizeLog, Header.NumClusters, &mftStream)); + if (!mftStream) + return S_FALSE; + } + + UInt64 mftSize = mftRec.DataAttrs[0].Size; + if ((mftSize >> 4) > Header.GetPhySize()) + return S_FALSE; + + UInt64 numFiles = mftSize >> recSizeLog; + if (numFiles > (1 << 30)) + return S_FALSE; + if (OpenCallback) + { + RINOK(OpenCallback->SetTotal(&numFiles, &mftSize)); + } + const UInt32 kBufSize = (1 << 15); + if (kBufSize < (1 << recSizeLog)) + return S_FALSE; + + ByteBuf.SetCapacity((size_t)kBufSize); + Recs.Reserve((int)numFiles); + for (UInt64 pos64 = 0;;) + { + if (OpenCallback) + { + UInt64 numFiles = Recs.Size(); + if ((numFiles & 0x3FF) == 0) + { + RINOK(OpenCallback->SetCompleted(&numFiles, &pos64)); + } + } + UInt32 readSize = kBufSize; + UInt64 rem = mftSize - pos64; + if (readSize > rem) + readSize = (UInt32)rem; + if (readSize < ((UInt32)1 << recSizeLog)) + break; + RINOK(ReadStream_FALSE(mftStream, ByteBuf, (size_t)readSize)); + pos64 += readSize; + for (int i = 0; ((UInt32)(i + 1) << recSizeLog) <= readSize; i++) + { + PRF(printf("\n---------------------")); + PRF(printf("\n%5d:", Recs.Size())); + Byte *p = ByteBuf + ((UInt32)i << recSizeLog); + CMftRec rec; + if (!rec.Parse(p, Header.SectorSizeLog, numSectorsInRec, (UInt32)Recs.Size(), + (Recs.Size() == kRecIndex_Volume) ? &VolAttrs: NULL)) + return S_FALSE; + Recs.Add(rec); + } + } + + int i; + for (i = 0; i < Recs.Size(); i++) + { + CMftRec &rec = Recs[i]; + if (!rec.BaseMftRef.IsBaseItself()) + { + UInt64 refIndex = rec.BaseMftRef.GetIndex(); + if (refIndex > (UInt32)Recs.Size()) + return S_FALSE; + CMftRec &refRec = Recs[(int)refIndex]; + bool moveAttrs = (refRec.SeqNumber == rec.BaseMftRef.GetNumber() && refRec.BaseMftRef.IsBaseItself()); + if (rec.InUse() && refRec.InUse()) + { + if (!moveAttrs) + return S_FALSE; + } + else if (rec.InUse() || refRec.InUse()) + moveAttrs = false; + if (moveAttrs) + refRec.MoveAttrsFrom(rec); + } + } + + for (i = 0; i < Recs.Size(); i++) + Recs[i].ParseDataNames(); + + for (i = 0; i < Recs.Size(); i++) + { + CMftRec &rec = Recs[i]; + if (!rec.IsFILE() || !rec.BaseMftRef.IsBaseItself()) + continue; + int numNames = 0; + // printf("\n%4d: ", i); + for (int t = 0; t < rec.FileNames.Size(); t++) + { + const CFileNameAttr &fna = rec.FileNames[t]; + // printf("%4d %S | ", (int)fna.NameType, fna.Name); + if (fna.IsDos()) + continue; + int numDatas = rec.DataRefs.Size(); + + // For hard linked files we show substreams only for first Name. + if (numDatas > 1 && numNames > 0) + numDatas = 1; + numNames++; + + if (rec.IsDir()) + { + CItem item; + item.Name = fna.Name; + item.RecIndex = i; + item.DataIndex = -1; + item.ParentRef = fna.ParentDirRef; + item.Attrib = rec.SiAttr.Attrib | 0x10; + // item.Attrib = fna.Attrib; + Items.Add(item); + } + for (int di = 0; di < numDatas; di++) + { + CItem item; + item.Name = fna.Name; + item.Attrib = rec.SiAttr.Attrib; + const UString &subName = rec.DataAttrs[rec.DataRefs[di].Start].Name; + if (!subName.IsEmpty()) + { + // $BadClus:$Bad is sparse file for all clusters. So we skip it. + if (i == kRecIndex_BadClus && subName == L"$Bad") + continue; + item.Name += L":"; + item.Name += subName; + item.Attrib = fna.Attrib; + } + + PRF(printf("\n%3d", i)); + PRF(printf(" attrib=%2x", rec.SiAttr.Attrib)); + PRF(printf(" %S", item.Name)); + + item.RecIndex = i; + item.DataIndex = di; + item.ParentRef = fna.ParentDirRef; + + Items.Add(item); + rec.MyNumNameLinks++; + } + } + rec.FileNames.ClearAndFree(); + } + + return S_OK; +} + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp, + CDatabase +{ +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + IInStream *stream2; + const CItem &item = Items[index]; + const CMftRec &rec = Recs[item.RecIndex]; + HRESULT res = rec.GetStream(InStream, item.DataIndex, Header.ClusterSizeLog, Header.NumClusters, &stream2); + *stream = (ISequentialInStream *)stream2; + return res; + COM_TRY_END +} + +static const STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidATime, VT_FILETIME}, + { NULL, kpidAttrib, VT_UI4}, + { NULL, kpidLinks, VT_UI4}, + { NULL, kpidNumBlocks, VT_UI4} +}; + +static const STATPROPSTG kArcProps[] = +{ + { NULL, kpidVolumeName, VT_BSTR}, + { NULL, kpidFileSystem, VT_BSTR}, + { NULL, kpidClusterSize, VT_UI4}, + { NULL, kpidPhySize, VT_UI8}, + { NULL, kpidHeadersSize, VT_UI8}, + { NULL, kpidCTime, VT_FILETIME}, + + { NULL, kpidSectorSize, VT_UI4}, + { NULL, kpidId, VT_UI8} + // { NULL, kpidSectorsPerTrack, VT_UI4}, + // { NULL, kpidNumHeads, VT_UI4}, + // { NULL, kpidHiddenSectors, VT_UI4} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +static void NtfsTimeToProp(UInt64 t, NWindows::NCOM::CPropVariant &prop) +{ + FILETIME ft; + ft.dwLowDateTime = (DWORD)t; + ft.dwHighDateTime = (DWORD)(t >> 32); + prop = ft; +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + + const CMftRec *volRec = (Recs.Size() > kRecIndex_Volume ? &Recs[kRecIndex_Volume] : NULL); + + switch(propID) + { + case kpidClusterSize: prop = Header.ClusterSize(); break; + case kpidPhySize: prop = Header.GetPhySize(); break; + /* + case kpidHeadersSize: + { + UInt64 val = 0; + for (int i = 0; i < kNumSysRecs; i++) + { + printf("\n%2d: %8I64d ", i, Recs[i].GetPackSize()); + if (i == 8) + i = i + val += Recs[i].GetPackSize(); + } + prop = val; + break; + } + */ + case kpidCTime: if (volRec) NtfsTimeToProp(volRec->SiAttr.CTime, prop); break;break; + case kpidVolumeName: + { + for (int i = 0; i < VolAttrs.Size(); i++) + { + const CAttr &attr = VolAttrs[i]; + if (attr.Type == ATTR_TYPE_VOLUME_NAME) + { + UString name; + GetString(attr.Data, (int)attr.Data.GetCapacity() / 2, name); + prop = name; + break; + } + } + break; + } + case kpidFileSystem: + { + AString s = "NTFS"; + for (int i = 0; i < VolAttrs.Size(); i++) + { + const CAttr &attr = VolAttrs[i]; + if (attr.Type == ATTR_TYPE_VOLUME_INFO) + { + CVolInfo vi; + if (attr.ParseVolInfo(vi)) + { + s += ' '; + char temp[16]; + ConvertUInt32ToString(vi.MajorVer, temp); + s += temp; + s += '.'; + ConvertUInt32ToString(vi.MinorVer, temp); + s += temp; + } + break; + } + } + prop = s; + break; + } + case kpidSectorSize: prop = (UInt32)1 << Header.SectorSizeLog; break; + case kpidId: prop = Header.SerialNumber; break; + // case kpidMediaType: prop = Header.MediaType; break; + // case kpidSectorsPerTrack: prop = Header.SectorsPerTrack; break; + // case kpidNumHeads: prop = Header.NumHeads; break; + // case kpidHiddenSectors: prop = Header.NumHiddenSectors; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + const CItem &item = Items[index]; + const CMftRec &rec = Recs[item.RecIndex]; + + const CAttr *data= NULL; + if (item.DataIndex >= 0) + data = &rec.DataAttrs[rec.DataRefs[item.DataIndex].Start]; + + switch(propID) + { + case kpidPath: + { + UString name = GetItemPath(index); + const wchar_t *prefix = NULL; + if (!rec.InUse()) + prefix = MY_DIR_PREFIX(L"DELETED"); + else if (item.RecIndex < kNumSysRecs) + prefix = MY_DIR_PREFIX(L"SYSTEM"); + if (prefix) + name = prefix + name; + prop = name; + break; + } + + case kpidIsDir: prop = item.IsDir(); break; + case kpidMTime: NtfsTimeToProp(rec.SiAttr.MTime, prop); break; + + case kpidCTime: NtfsTimeToProp(rec.SiAttr.CTime, prop); break; + case kpidATime: NtfsTimeToProp(rec.SiAttr.ATime, prop); break; + case kpidAttrib: + prop = item.Attrib; + break; + case kpidLinks: prop = rec.MyNumNameLinks; break; + case kpidSize: if (data) prop = data->GetSize(); break; + case kpidPackSize: if (data) prop = data->GetPackSize(); break; + case kpidNumBlocks: if (data) prop = (UInt32)rec.GetNumExtents(item.DataIndex, Header.ClusterSizeLog, Header.NumClusters); break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + { + OpenCallback = callback; + InStream = stream; + HRESULT res; + try + { + res = CDatabase::Open(); + if (res == S_OK) + return S_OK; + } + catch(...) + { + Close(); + throw; + } + Close(); + return res; + } + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + ClearAndClose(); + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = Items.Size(); + if (numItems == 0) + return S_OK; + UInt32 i; + UInt64 totalSize = 0; + for (i = 0; i < numItems; i++) + { + const CItem &item = Items[allFilesMode ? i : indices[i]]; + const CMftRec &rec = Recs[item.RecIndex]; + if (!rec.IsDir()) + totalSize += rec.GetSize(item.DataIndex); + } + RINOK(extractCallback->SetTotal(totalSize)); + + UInt64 totalPackSize; + totalSize = totalPackSize = 0; + + CByteBuffer buf; + UInt32 clusterSize = Header.ClusterSize(); + buf.SetCapacity(clusterSize); + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + CDummyOutStream *outStreamSpec = new CDummyOutStream; + CMyComPtr outStream(outStreamSpec); + + for (i = 0; i < numItems; i++) + { + lps->InSize = totalPackSize; + lps->OutSize = totalSize; + RINOK(lps->SetCur()); + CMyComPtr realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + const CItem &item = Items[index]; + if (item.IsDir()) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + + if (!testMode && !realOutStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + + outStreamSpec->SetStream(realOutStream); + realOutStream.Release(); + outStreamSpec->Init(); + + const CMftRec &rec = Recs[item.RecIndex]; + const CAttr &data = rec.DataAttrs[rec.DataRefs[item.DataIndex].Start]; + + int res = NExtract::NOperationResult::kDataError; + { + CMyComPtr inStream; + HRESULT hres = rec.GetStream(InStream, item.DataIndex, Header.ClusterSizeLog, Header.NumClusters, &inStream); + if (hres == S_FALSE) + res = NExtract::NOperationResult::kUnSupportedMethod; + else + { + RINOK(hres); + if (inStream) + { + HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress); + if (hres != S_OK && hres != S_FALSE) + { + RINOK(hres); + } + if (/* copyCoderSpec->TotalSize == item.GetSize() && */ hres == S_OK) + res = NExtract::NOperationResult::kOK; + } + } + } + totalPackSize += data.GetPackSize(); + totalSize += data.GetSize(); + outStreamSpec->ReleaseStream(); + RINOK(extractCallback->SetOperationResult(res)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = Items.Size(); + return S_OK; +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"NTFS", L"ntfs img", 0, 0xD9, { 'N', 'T', 'F', 'S', ' ', ' ', ' ', ' ', 0 }, 9, false, CreateArc, 0 }; + +REGISTER_ARC(Fat) + +}} diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp new file mode 100755 index 0000000..111eb08 --- /dev/null +++ b/CPP/7zip/Archive/PeHandler.cpp @@ -0,0 +1,1752 @@ +// PeHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Common/DynamicBuffer.h" +#include "Common/ComTry.h" +#include "Common/IntToString.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariantUtils.h" +#include "Windows/Time.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamObjects.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) +#define Get64(p) GetUi64(p) + +using namespace NWindows; + +namespace NArchive { +namespace NPe { + +#define NUM_SCAN_SECTIONS_MAX (1 << 6) + +#define PE_SIG 0x00004550 +#define PE_OptHeader_Magic_32 0x10B +#define PE_OptHeader_Magic_64 0x20B + +static AString GetDecString(UInt32 v) +{ + char sz[32]; + ConvertUInt64ToString(v, sz); + return sz; +} + +struct CVersion +{ + UInt16 Major; + UInt16 Minor; + + void Parse(const Byte *buf); + AString GetString() const { return GetDecString(Major) + '.' + GetDecString(Minor); } +}; + +void CVersion::Parse(const Byte *p) +{ + Major = Get16(p); + Minor = Get16(p + 2); +} + +static const UInt32 kHeaderSize = 4 + 20; + +struct CHeader +{ + UInt16 NumSections; + UInt32 Time; + UInt32 PointerToSymbolTable; + UInt32 NumSymbols; + UInt16 OptHeaderSize; + UInt16 Flags; + UInt16 Machine; + + bool Parse(const Byte *buf); +}; + +bool CHeader::Parse(const Byte *p) +{ + if (Get32(p) != PE_SIG) + return false; + p += 4; + Machine = Get16(p + 0); + NumSections = Get16(p + 2); + Time = Get32(p + 4); + PointerToSymbolTable = Get32(p + 8); + NumSymbols = Get32(p + 12); + OptHeaderSize = Get16(p + 16); + Flags = Get16(p + 18); + return true; +} + +struct CDirLink +{ + UInt32 Va; + UInt32 Size; + void Parse(const Byte *p); +}; + +void CDirLink::Parse(const Byte *p) +{ + Va = Get32(p); + Size = Get32(p + 4); +} + +enum +{ + kDirLink_Certificate = 4, + kDirLink_Debug = 6 +}; + +struct CDebugEntry +{ + UInt32 Flags; + UInt32 Time; + CVersion Ver; + UInt32 Type; + UInt32 Size; + UInt32 Va; + UInt32 Pa; + + void Parse(const Byte *p); +}; + +void CDebugEntry::Parse(const Byte *p) +{ + Flags = Get32(p); + Time = Get32(p + 4); + Ver.Parse(p + 8); + Type = Get32(p + 12); + Size = Get32(p + 16); + Va = Get32(p + 20); + Pa = Get32(p + 24); +} + +static const UInt32 kNumDirItemsMax = 16; + +struct COptHeader +{ + UInt16 Magic; + Byte LinkerVerMajor; + Byte LinkerVerMinor; + + UInt32 CodeSize; + UInt32 InitDataSize; + UInt32 UninitDataSize; + + // UInt32 AddressOfEntryPoint; + // UInt32 BaseOfCode; + // UInt32 BaseOfData32; + UInt64 ImageBase; + + UInt32 SectAlign; + UInt32 FileAlign; + + CVersion OsVer; + CVersion ImageVer; + CVersion SubsysVer; + + UInt32 ImageSize; + UInt32 HeadersSize; + UInt32 CheckSum; + UInt16 SubSystem; + UInt16 DllCharacts; + + UInt64 StackReserve; + UInt64 StackCommit; + UInt64 HeapReserve; + UInt64 HeapCommit; + + UInt32 NumDirItems; + CDirLink DirItems[kNumDirItemsMax]; + + bool Is64Bit() const { return Magic == PE_OptHeader_Magic_64; } + bool Parse(const Byte *p, UInt32 size); + + int GetNumFileAlignBits() const + { + for (int i = 9; i <= 16; i++) + if (((UInt32)1 << i) == FileAlign) + return i; + return -1; + } +}; + +bool COptHeader::Parse(const Byte *p, UInt32 size) +{ + Magic = Get16(p); + switch (Magic) + { + case PE_OptHeader_Magic_32: + case PE_OptHeader_Magic_64: + break; + default: + return false; + } + LinkerVerMajor = p[2]; + LinkerVerMinor = p[3]; + + bool hdr64 = Is64Bit(); + + CodeSize = Get32(p + 4); + InitDataSize = Get32(p + 8); + UninitDataSize = Get32(p + 12); + + // AddressOfEntryPoint = Get32(p + 16); + // BaseOfCode = Get32(p + 20); + // BaseOfData32 = hdr64 ? 0: Get32(p + 24); + ImageBase = hdr64 ? GetUi64(p + 24) : Get32(p + 28); + + SectAlign = Get32(p + 32); + FileAlign = Get32(p + 36); + + OsVer.Parse(p + 40); + ImageVer.Parse(p + 44); + SubsysVer.Parse(p + 48); + + // reserved = Get32(p + 52); + + ImageSize = Get32(p + 56); + HeadersSize = Get32(p + 60); + CheckSum = Get32(p + 64); + SubSystem = Get16(p + 68); + DllCharacts = Get16(p + 70); + + if (hdr64) + { + StackReserve = Get64(p + 72); + StackCommit = Get64(p + 80); + HeapReserve = Get64(p + 88); + HeapCommit = Get64(p + 96); + } + else + { + StackReserve = Get32(p + 72); + StackCommit = Get32(p + 76); + HeapReserve = Get32(p + 80); + HeapCommit = Get32(p + 84); + } + UInt32 pos = (hdr64 ? 108 : 92); + NumDirItems = Get32(p + pos); + pos += 4; + if (pos + 8 * NumDirItems != size) + return false; + for (UInt32 i = 0; i < NumDirItems && i < kNumDirItemsMax; i++) + DirItems[i].Parse(p + pos + i * 8); + return true; +} + +static const UInt32 kSectionSize = 40; + +struct CSection +{ + AString Name; + + UInt32 VSize; + UInt32 Va; + UInt32 PSize; + UInt32 Pa; + UInt32 Flags; + UInt32 Time; + // UInt16 NumRelocs; + bool IsDebug; + bool IsRealSect; + bool IsAdditionalSection; + + CSection(): IsRealSect(false), IsDebug(false), IsAdditionalSection(false) {} + UInt64 GetPackSize() const { return PSize; } + + void UpdateTotalSize(UInt32 &totalSize) + { + UInt32 t = Pa + PSize; + if (t > totalSize) + totalSize = t; + } + void Parse(const Byte *p); +}; + +static bool operator <(const CSection &a1, const CSection &a2) { return (a1.Pa < a2.Pa) || ((a1.Pa == a2.Pa) && (a1.PSize < a2.PSize)) ; } +static bool operator ==(const CSection &a1, const CSection &a2) { return (a1.Pa == a2.Pa) && (a1.PSize == a2.PSize); } + +static AString GetName(const Byte *name) +{ + const int kNameSize = 8; + AString res; + char *p = res.GetBuffer(kNameSize); + memcpy(p, name, kNameSize); + p[kNameSize] = 0; + res.ReleaseBuffer(); + return res; +} + +void CSection::Parse(const Byte *p) +{ + Name = GetName(p); + VSize = Get32(p + 8); + Va = Get32(p + 12); + PSize = Get32(p + 16); + Pa = Get32(p + 20); + // NumRelocs = Get16(p + 32); + Flags = Get32(p + 36); +} + +static const CUInt32PCharPair g_HeaderCharacts[] = +{ + { 1, "Executable" }, + { 13, "DLL" }, + { 8, "32-bit" }, + { 5, "LargeAddress" }, + { 0, "NoRelocs" }, + { 2, "NoLineNums" }, + { 3, "NoLocalSyms" }, + { 4, "AggressiveWsTrim" }, + { 9, "NoDebugInfo" }, + { 10, "RemovableRun" }, + { 11, "NetRun" }, + { 12, "System" }, + { 14, "UniCPU" }, + { 7, "Little-Endian" }, + { 15, "Big-Endian" } +}; + +static const CUInt32PCharPair g_DllCharacts[] = +{ + { 6, "Relocated" }, + { 7, "Integrity" }, + { 8, "NX-Compatible" }, + { 9, "NoIsolation" }, + { 10, "NoSEH" }, + { 11, "NoBind" }, + { 13, "WDM" }, + { 15, "TerminalServerAware" } +}; + +static const CUInt32PCharPair g_SectFlags[] = +{ + { 3, "NoPad" }, + { 5, "Code" }, + { 6, "InitializedData" }, + { 7, "UninitializedData" }, + { 9, "Comments" }, + { 11, "Remove" }, + { 12, "COMDAT" }, + { 15, "GP" }, + { 24, "ExtendedRelocations" }, + { 25, "Discardable" }, + { 26, "NotCached" }, + { 27, "NotPaged" }, + { 28, "Shared" }, + { 29, "Execute" }, + { 30, "Read" }, + { 31, "Write" } +}; + +static const CUInt32PCharPair g_MachinePairs[] = +{ + { 0x014C, "x86" }, + { 0x0162, "MIPS-R3000" }, + { 0x0166, "MIPS-R4000" }, + { 0x0168, "MIPS-R10000" }, + { 0x0169, "MIPS-V2" }, + { 0x0184, "Alpha" }, + { 0x01A2, "SH3" }, + { 0x01A3, "SH3-DSP" }, + { 0x01A4, "SH3E" }, + { 0x01A6, "SH4" }, + { 0x01A8, "SH5" }, + { 0x01C0, "ARM" }, + { 0x01C2, "ARM-Thumb" }, + { 0x01F0, "PPC" }, + { 0x01F1, "PPC-FP" }, + { 0x0200, "IA-64" }, + { 0x0284, "Alpha-64" }, + { 0x0200, "IA-64" }, + { 0x0366, "MIPSFPU" }, + { 0x8664, "x64" }, + { 0x0EBC, "EFI" } +}; + +static const CUInt32PCharPair g_SubSystems[] = +{ + { 0, "Unknown" }, + { 1, "Native" }, + { 2, "Windows GUI" }, + { 3, "Windows CUI" }, + { 7, "Posix" }, + { 9, "Windows CE" }, + { 10, "EFI" }, + { 11, "EFI Boot" }, + { 12, "EFI Runtime" }, + { 13, "EFI ROM" }, + { 14, "XBOX" } +}; + +static const wchar_t *g_ResTypes[] = +{ + NULL, + L"CURSOR", + L"BITMAP", + L"ICON", + L"MENU", + L"DIALOG", + L"STRING", + L"FONTDIR", + L"FONT", + L"ACCELERATOR", + L"RCDATA", + L"MESSAGETABLE", + L"GROUP_CURSOR", + NULL, + L"GROUP_ICON", + NULL, + L"VERSION", + L"DLGINCLUDE", + NULL, + L"PLUGPLAY", + L"VXD", + L"ANICURSOR", + L"ANIICON", + L"HTML", + L"MANIFEST" +}; + +const UInt32 kFlag = (UInt32)1 << 31; +const UInt32 kMask = ~kFlag; + +struct CTableItem +{ + UInt32 Offset; + UInt32 ID; +}; + + +const UInt32 kBmpHeaderSize = 14; +const UInt32 kIconHeaderSize = 22; + +struct CResItem +{ + UInt32 Type; + UInt32 ID; + UInt32 Lang; + + UInt32 Size; + UInt32 Offset; + + UInt32 HeaderSize; + Byte Header[kIconHeaderSize]; // it must be enough for max size header. + bool Enabled; + + bool IsNameEqual(const CResItem &item) const { return Lang == item.Lang; } + UInt32 GetSize() const { return Size + HeaderSize; } + bool IsBmp() const { return Type == 2; } + bool IsIcon() const { return Type == 3; } + bool IsString() const { return Type == 6; } + bool IsRcData() const { return Type == 10; } + bool IsRcDataOrUnknown() const { return IsRcData() || Type > 64; } +}; + +struct CStringItem +{ + UInt32 Lang; + UInt32 Size; + CByteDynamicBuffer Buf; + + void AddChar(Byte c); + void AddWChar(UInt16 c); +}; + +void CStringItem::AddChar(Byte c) +{ + Buf.EnsureCapacity(Size + 2); + Buf[Size++] = c; + Buf[Size++] = 0; +} + +void CStringItem::AddWChar(UInt16 c) +{ + if (c == '\n') + { + AddChar('\\'); + c = 'n'; + } + Buf.EnsureCapacity(Size + 2); + SetUi16(Buf + Size, c); + Size += 2; +} + +struct CMixItem +{ + int SectionIndex; + int ResourceIndex; + int StringIndex; + + bool IsSectionItem() const { return ResourceIndex < 0 && StringIndex < 0; }; +}; + +struct CUsedBitmap +{ + CByteBuffer Buf; +public: + void Alloc(size_t size) + { + size = (size + 7) / 8; + Buf.SetCapacity(size); + memset(Buf, 0, size); + } + void Free() + { + Buf.SetCapacity(0); + } + bool SetRange(size_t from, int size) + { + for (int i = 0; i < size; i++) + { + size_t pos = (from + i) >> 3; + Byte mask = (Byte)(1 << ((from + i) & 7)); + Byte b = Buf[pos]; + if ((b & mask) != 0) + return false; + Buf[pos] = b | mask; + } + return true; + } +}; + + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + CObjectVector _sections; + UInt32 _peOffset; + CHeader _header; + COptHeader _optHeader; + UInt32 _totalSize; + UInt32 _totalSizeLimited; + Int32 _mainSubfile; + + CRecordVector _items; + CObjectVector _strings; + + CByteBuffer _buf; + bool _oneLang; + UString _resourceFileName; + CUsedBitmap _usedRes; + bool _parseResources; + + CRecordVector _mixItems; + + HRESULT LoadDebugSections(IInStream *stream, bool &thereIsSection); + HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); + bool Parse(const Byte *buf, UInt32 size); + + void AddResNameToString(UString &s, UInt32 id) const; + UString GetLangPrefix(UInt32 lang); + HRESULT ReadString(UInt32 offset, UString &dest) const; + HRESULT ReadTable(UInt32 offset, CRecordVector &items); + bool ParseStringRes(UInt32 id, UInt32 lang, const Byte *src, UInt32 size); + HRESULT OpenResources(int sectIndex, IInStream *stream, IArchiveOpenCallback *callback); + void CloseResources(); + + + bool CheckItem(const CSection §, const CResItem &item, size_t offset) const + { + return item.Offset >= sect.Va && offset <= _buf.GetCapacity() && _buf.GetCapacity() - offset >= item.Size; + } + +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +bool CHandler::Parse(const Byte *buf, UInt32 size) +{ + UInt32 i; + if (size < 512) + return false; + _peOffset = Get32(buf + 0x3C); + if (_peOffset >= 0x1000 || _peOffset + 512 > size || (_peOffset & 7) != 0) + return false; + + UInt32 pos = _peOffset; + if (!_header.Parse(buf + pos)) + return false; + if (_header.OptHeaderSize > 512 || _header.NumSections > NUM_SCAN_SECTIONS_MAX) + return false; + pos += kHeaderSize; + + if (!_optHeader.Parse(buf + pos, _header.OptHeaderSize)) + return false; + + pos += _header.OptHeaderSize; + _totalSize = pos; + + for (i = 0; i < _header.NumSections; i++, pos += kSectionSize) + { + CSection sect; + if (pos + kSectionSize > size) + return false; + sect.Parse(buf + pos); + sect.IsRealSect = true; + sect.UpdateTotalSize(_totalSize); + _sections.Add(sect); + } + + return true; +} + +enum +{ + kpidSectAlign = kpidUserDefined, + kpidFileAlign, + kpidLinkerVer, + kpidOsVer, + kpidImageVer, + kpidSubsysVer, + kpidCodeSize, + kpidImageSize, + kpidInitDataSize, + kpidUnInitDataSize, + kpidHeadersSizeUnInitDataSize, + kpidSubSystem, + kpidDllCharacts, + kpidStackReserve, + kpidStackCommit, + kpidHeapReserve, + kpidHeapCommit, + kpidImageBase + // kpidAddressOfEntryPoint, + // kpidBaseOfCode, + // kpidBaseOfData32, +}; + +STATPROPSTG kArcProps[] = +{ + { NULL, kpidCpu, VT_BSTR}, + { NULL, kpidBit64, VT_BOOL}, + { NULL, kpidCharacts, VT_BSTR}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidPhySize, VT_UI4}, + { NULL, kpidHeadersSize, VT_UI4}, + { NULL, kpidChecksum, VT_UI4}, + { L"Image Size", kpidImageSize, VT_UI4}, + { L"Section Alignment", kpidSectAlign, VT_UI4}, + { L"File Alignment", kpidFileAlign, VT_UI4}, + { L"Code Size", kpidCodeSize, VT_UI4}, + { L"Initialized Data Size", kpidInitDataSize, VT_UI4}, + { L"Uninitialized Data Size", kpidUnInitDataSize, VT_UI4}, + { L"Linker Version", kpidLinkerVer, VT_BSTR}, + { L"OS Version", kpidOsVer, VT_BSTR}, + { L"Image Version", kpidImageVer, VT_BSTR}, + { L"Subsystem Version", kpidSubsysVer, VT_BSTR}, + { L"Subsystem", kpidSubSystem, VT_BSTR}, + { L"DLL Characteristics", kpidDllCharacts, VT_BSTR}, + { L"Stack Reserve", kpidStackReserve, VT_UI8}, + { L"Stack Commit", kpidStackCommit, VT_UI8}, + { L"Heap Reserve", kpidHeapReserve, VT_UI8}, + { L"Heap Commit", kpidHeapCommit, VT_UI8}, + { L"Image Base", kpidImageBase, VT_UI8} + // { L"Address Of Entry Point", kpidAddressOfEntryPoint, VT_UI8}, + // { L"Base Of Code", kpidBaseOfCode, VT_UI8}, + // { L"Base Of Data", kpidBaseOfData32, VT_UI8}, +}; + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidCharacts, VT_BSTR}, + { NULL, kpidOffset, VT_UI8}, + { NULL, kpidVa, VT_UI8} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_WITH_NAME + +static void VerToProp(const CVersion &v, NCOM::CPropVariant &prop) +{ + StringToProp(v.GetString(), prop); +} + +void TimeToProp(UInt32 unixTime, NCOM::CPropVariant &prop) +{ + if (unixTime != 0) + { + FILETIME ft; + NTime::UnixTimeToFileTime(unixTime, ft); + prop = ft; + } +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NCOM::CPropVariant prop; + switch(propID) + { + case kpidSectAlign: prop = _optHeader.SectAlign; break; + case kpidFileAlign: prop = _optHeader.FileAlign; break; + case kpidLinkerVer: + { + CVersion v = { _optHeader.LinkerVerMajor, _optHeader.LinkerVerMinor }; + VerToProp(v, prop); + break; + } + + case kpidOsVer: VerToProp(_optHeader.OsVer, prop); break; + case kpidImageVer: VerToProp(_optHeader.ImageVer, prop); break; + case kpidSubsysVer: VerToProp(_optHeader.SubsysVer, prop); break; + case kpidCodeSize: prop = _optHeader.CodeSize; break; + case kpidInitDataSize: prop = _optHeader.InitDataSize; break; + case kpidUnInitDataSize: prop = _optHeader.UninitDataSize; break; + case kpidImageSize: prop = _optHeader.ImageSize; break; + case kpidPhySize: prop = _totalSize; break; + case kpidHeadersSize: prop = _optHeader.HeadersSize; break; + case kpidChecksum: prop = _optHeader.CheckSum; break; + + case kpidCpu: PAIR_TO_PROP(g_MachinePairs, _header.Machine, prop); break; + case kpidBit64: if (_optHeader.Is64Bit()) prop = true; break; + case kpidSubSystem: PAIR_TO_PROP(g_SubSystems, _optHeader.SubSystem, prop); break; + + case kpidMTime: + case kpidCTime: TimeToProp(_header.Time, prop); break; + case kpidCharacts: FLAGS_TO_PROP(g_HeaderCharacts, _header.Flags, prop); break; + case kpidDllCharacts: FLAGS_TO_PROP(g_DllCharacts, _optHeader.DllCharacts, prop); break; + case kpidStackReserve: prop = _optHeader.StackReserve; break; + case kpidStackCommit: prop = _optHeader.StackCommit; break; + case kpidHeapReserve: prop = _optHeader.HeapReserve; break; + case kpidHeapCommit: prop = _optHeader.HeapCommit; break; + + case kpidImageBase: prop = _optHeader.ImageBase; break; + // case kpidAddressOfEntryPoint: prop = _optHeader.AddressOfEntryPoint; break; + // case kpidBaseOfCode: prop = _optHeader.BaseOfCode; break; + // case kpidBaseOfData32: if (!_optHeader.Is64Bit()) prop = _optHeader.BaseOfData32; break; + + case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +void CHandler::AddResNameToString(UString &s, UInt32 id) const +{ + if ((id & kFlag) != 0) + { + UString name; + if (ReadString(id & kMask, name) == S_OK) + { + if (name.IsEmpty()) + s += L"[]"; + else + { + if (name.Length() > 1 && name[0] == '"' && name.Back() == '"') + name = name.Mid(1, name.Length() - 2); + s += name; + } + return; + } + } + wchar_t sz[32]; + ConvertUInt32ToString(id, sz); + s += sz; +} + +UString CHandler::GetLangPrefix(UInt32 lang) +{ + UString s = _resourceFileName; + s += WCHAR_PATH_SEPARATOR; + if (!_oneLang) + { + AddResNameToString(s, lang); + s += WCHAR_PATH_SEPARATOR; + } + return s; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NCOM::CPropVariant prop; + const CMixItem &mixItem = _mixItems[index]; + if (mixItem.StringIndex >= 0) + { + const CStringItem &item = _strings[mixItem.StringIndex]; + switch(propID) + { + case kpidPath: prop = GetLangPrefix(item.Lang) + L"string.txt"; break; + case kpidSize: + case kpidPackSize: + prop = (UInt64)item.Size; break; + } + } + else if (mixItem.ResourceIndex < 0) + { + const CSection &item = _sections[mixItem.SectionIndex]; + switch(propID) + { + case kpidPath: StringToProp(item.Name, prop); break; + case kpidSize: prop = (UInt64)item.VSize; break; + case kpidPackSize: prop = (UInt64)item.GetPackSize(); break; + case kpidOffset: prop = item.Pa; break; + case kpidVa: if (item.IsRealSect) prop = item.Va; break; + case kpidMTime: + case kpidCTime: + TimeToProp(item.IsDebug ? item.Time : _header.Time, prop); break; + case kpidCharacts: if (item.IsRealSect) FLAGS_TO_PROP(g_SectFlags, item.Flags, prop); break; + } + } + else + { + const CResItem &item = _items[mixItem.ResourceIndex]; + switch(propID) + { + case kpidPath: + { + UString s = GetLangPrefix(item.Lang); + { + const wchar_t *p = NULL; + if (item.Type < sizeof(g_ResTypes) / sizeof(g_ResTypes[0])) + p = g_ResTypes[item.Type]; + if (p != 0) + s += p; + else + AddResNameToString(s, item.Type); + } + s += WCHAR_PATH_SEPARATOR; + AddResNameToString(s, item.ID); + if (item.HeaderSize != 0) + { + if (item.IsBmp()) + s += L".bmp"; + else if (item.IsIcon()) + s += L".ico"; + } + prop = s; + break; + } + case kpidSize: prop = (UInt64)item.GetSize(); break; + case kpidPackSize: prop = (UInt64)item.Size; break; + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +HRESULT CHandler::LoadDebugSections(IInStream *stream, bool &thereIsSection) +{ + thereIsSection = false; + const CDirLink &debugLink = _optHeader.DirItems[kDirLink_Debug]; + if (debugLink.Size == 0) + return S_OK; + const unsigned kEntrySize = 28; + UInt32 numItems = debugLink.Size / kEntrySize; + if (numItems * kEntrySize != debugLink.Size || numItems > 16) + return S_FALSE; + + UInt64 pa = 0; + int i; + for (i = 0; i < _sections.Size(); i++) + { + const CSection § = _sections[i]; + if (sect.Va < debugLink.Va && debugLink.Va + debugLink.Size <= sect.Va + sect.PSize) + { + pa = sect.Pa + (debugLink.Va - sect.Va); + break; + } + } + if (i == _sections.Size()) + { + return S_OK; + // Exe for ARM requires S_OK + // return S_FALSE; + } + + CByteBuffer buffer; + buffer.SetCapacity(debugLink.Size); + Byte *buf = buffer; + + RINOK(stream->Seek(pa, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream_FALSE(stream, buf, debugLink.Size)); + + for (i = 0; i < (int)numItems; i++) + { + CDebugEntry de; + de.Parse(buf); + + if (de.Size == 0) + continue; + + CSection sect; + sect.Name = ".debug" + GetDecString(i); + + sect.IsDebug = true; + sect.Time = de.Time; + sect.Va = de.Va; + sect.Pa = de.Pa; + sect.PSize = sect.VSize = de.Size; + UInt32 totalSize = sect.Pa + sect.PSize; + if (totalSize > _totalSize) + { + _totalSize = totalSize; + _sections.Add(sect); + thereIsSection = true; + } + buf += kEntrySize; + } + + return S_OK; +} + +HRESULT CHandler::ReadString(UInt32 offset, UString &dest) const +{ + if ((offset & 1) != 0 || offset >= _buf.GetCapacity()) + return S_FALSE; + size_t rem = _buf.GetCapacity() - offset; + if (rem < 2) + return S_FALSE; + unsigned length = Get16(_buf + offset); + if ((rem - 2) / 2 < length) + return S_FALSE; + dest.Empty(); + offset += 2; + for (unsigned i = 0; i < length; i++) + dest += (wchar_t)Get16(_buf + offset + i * 2); + return S_OK; +} + +HRESULT CHandler::ReadTable(UInt32 offset, CRecordVector &items) +{ + if ((offset & 3) != 0 || offset >= _buf.GetCapacity()) + return S_FALSE; + size_t rem = _buf.GetCapacity() - offset; + if (rem < 16) + return S_FALSE; + items.Clear(); + unsigned numNameItems = Get16(_buf + offset + 12); + unsigned numIdItems = Get16(_buf + offset + 14); + unsigned numItems = numNameItems + numIdItems; + if ((rem - 16) / 8 < numItems) + return S_FALSE; + if (!_usedRes.SetRange(offset, 16 + numItems * 8)) + return S_FALSE; + offset += 16; + _oneLang = true; + unsigned i; + for (i = 0; i < numItems; i++) + { + CTableItem item; + const Byte *buf = _buf + offset; + offset += 8; + item.ID = Get32(buf + 0); + if (((item.ID & kFlag) != 0) != (i < numNameItems)) + return S_FALSE; + item.Offset = Get32(buf + 4); + items.Add(item); + } + return S_OK; +} + +static const UInt32 kFileSizeMax = (UInt32)1 << 30; +static const int kNumResItemsMax = (UInt32)1 << 23; +static const int kNumStringLangsMax = 128; + +// BITMAPINFOHEADER +struct CBitmapInfoHeader +{ + // UInt32 HeaderSize; + UInt32 XSize; + Int32 YSize; + UInt16 Planes; + UInt16 BitCount; + UInt32 Compression; + UInt32 SizeImage; + + bool Parse(const Byte *p, size_t size); +}; + +static const UInt32 kBitmapInfoHeader_Size = 0x28; + +bool CBitmapInfoHeader::Parse(const Byte *p, size_t size) +{ + if (size < kBitmapInfoHeader_Size || Get32(p) != kBitmapInfoHeader_Size) + return false; + XSize = Get32(p + 4); + YSize = (Int32)Get32(p + 8); + Planes = Get16(p + 12); + BitCount = Get16(p + 14); + Compression = Get32(p + 16); + SizeImage = Get32(p + 20); + return true; +} + +static UInt32 GetImageSize(UInt32 xSize, UInt32 ySize, UInt32 bitCount) +{ + return ((xSize * bitCount + 7) / 8 + 3) / 4 * 4 * ySize; +} + +static UInt32 SetBitmapHeader(Byte *dest, const Byte *src, UInt32 size) +{ + CBitmapInfoHeader h; + if (!h.Parse(src, size)) + return 0; + if (h.YSize < 0) + h.YSize = -h.YSize; + if (h.XSize > (1 << 26) || h.YSize > (1 << 26) || h.Planes != 1 || h.BitCount > 32 || + h.Compression != 0) // BI_RGB + return 0; + if (h.SizeImage == 0) + h.SizeImage = GetImageSize(h.XSize, h.YSize, h.BitCount); + UInt32 totalSize = kBmpHeaderSize + size; + UInt32 offBits = totalSize - h.SizeImage; + // BITMAPFILEHEADER + SetUi16(dest, 0x4D42); + SetUi32(dest + 2, totalSize); + SetUi32(dest + 6, 0); + SetUi32(dest + 10, offBits); + return kBmpHeaderSize; +} + +static UInt32 SetIconHeader(Byte *dest, const Byte *src, UInt32 size) +{ + CBitmapInfoHeader h; + if (!h.Parse(src, size)) + return 0; + if (h.YSize < 0) + h.YSize = -h.YSize; + if (h.XSize > (1 << 26) || h.YSize > (1 << 26) || h.Planes != 1 || + h.Compression != 0) // BI_RGB + return 0; + + UInt32 numBitCount = h.BitCount; + if (numBitCount != 1 && + numBitCount != 4 && + numBitCount != 8 && + numBitCount != 24 && + numBitCount != 32) + return 0; + + if ((h.YSize & 1) != 0) + return 0; + h.YSize /= 2; + if (h.XSize > 0x100 || h.YSize > 0x100) + return 0; + + UInt32 imageSize; + // imageSize is not correct if AND mask array contains zeros + // in this case it is equal image1Size + + // UInt32 imageSize = h.SizeImage; + // if (imageSize == 0) + // { + UInt32 image1Size = GetImageSize(h.XSize, h.YSize, h.BitCount); + UInt32 image2Size = GetImageSize(h.XSize, h.YSize, 1); + imageSize = image1Size + image2Size; + // } + UInt32 numColors = 0; + if (numBitCount < 16) + numColors = 1 << numBitCount; + + SetUi16(dest, 0); // Reserved + SetUi16(dest + 2, 1); // RES_ICON + SetUi16(dest + 4, 1); // ResCount + + dest[6] = (Byte)h.XSize; // Width + dest[7] = (Byte)h.YSize; // Height + dest[8] = (Byte)numColors; // ColorCount + dest[9] = 0; // Reserved + + SetUi32(dest + 10, 0); // Reserved1 / Reserved2 + + UInt32 numQuadsBytes = numColors * 4; + UInt32 BytesInRes = kBitmapInfoHeader_Size + numQuadsBytes + imageSize; + SetUi32(dest + 14, BytesInRes); + SetUi32(dest + 18, kIconHeaderSize); + + /* + Description = DWORDToString(xSize) + + kDelimiterChar + DWORDToString(ySize) + + kDelimiterChar + DWORDToString(numBitCount); + */ + return kIconHeaderSize; +} + +bool CHandler::ParseStringRes(UInt32 id, UInt32 lang, const Byte *src, UInt32 size) +{ + if ((size & 1) != 0) + return false; + + int i; + for (i = 0; i < _strings.Size(); i++) + if (_strings[i].Lang == lang) + break; + if (i == _strings.Size()) + { + if (_strings.Size() >= kNumStringLangsMax) + return false; + CStringItem item; + item.Size = 0; + item.Lang = lang; + i = _strings.Add(item); + } + + CStringItem &item = _strings[i]; + id = (id - 1) << 4; + UInt32 pos = 0; + for (i = 0; i < 16; i++) + { + if (size - pos < 2) + return false; + UInt32 len = Get16(src + pos); + pos += 2; + if (len != 0) + { + if (size - pos < len * 2) + return false; + char temp[32]; + ConvertUInt32ToString(id + i, temp); + size_t tempLen = strlen(temp); + size_t j; + for (j = 0; j < tempLen; j++) + item.AddChar(temp[j]); + item.AddChar('\t'); + for (j = 0; j < len; j++, pos += 2) + item.AddWChar(Get16(src + pos)); + item.AddChar(0x0D); + item.AddChar(0x0A); + } + } + return (size == pos); +} + +HRESULT CHandler::OpenResources(int sectionIndex, IInStream *stream, IArchiveOpenCallback *callback) +{ + const CSection § = _sections[sectionIndex]; + size_t fileSize = sect.PSize; // Maybe we need sect.VSize here !!! + if (fileSize > kFileSizeMax) + return S_FALSE; + { + UInt64 fileSize64 = fileSize; + if (callback) + RINOK(callback->SetTotal(NULL, &fileSize64)); + RINOK(stream->Seek(sect.Pa, STREAM_SEEK_SET, NULL)); + _buf.SetCapacity(fileSize); + for (size_t pos = 0; pos < fileSize;) + { + UInt64 offset64 = pos; + if (callback) + RINOK(callback->SetCompleted(NULL, &offset64)) + size_t rem = MyMin(fileSize - pos, (size_t)(1 << 20)); + RINOK(ReadStream_FALSE(stream, _buf + pos, rem)); + pos += rem; + } + } + + _usedRes.Alloc(fileSize); + CRecordVector specItems; + RINOK(ReadTable(0, specItems)); + + _oneLang = true; + bool stringsOk = true; + size_t maxOffset = 0; + for (int i = 0; i < specItems.Size(); i++) + { + const CTableItem &item1 = specItems[i]; + if ((item1.Offset & kFlag) == 0) + return S_FALSE; + + CRecordVector specItems2; + RINOK(ReadTable(item1.Offset & kMask, specItems2)); + + for (int j = 0; j < specItems2.Size(); j++) + { + const CTableItem &item2 = specItems2[j]; + if ((item2.Offset & kFlag) == 0) + return S_FALSE; + + CRecordVector specItems3; + RINOK(ReadTable(item2.Offset & kMask, specItems3)); + + CResItem item; + item.Type = item1.ID; + item.ID = item2.ID; + + for (int k = 0; k < specItems3.Size(); k++) + { + if (_items.Size() >= kNumResItemsMax) + return S_FALSE; + const CTableItem &item3 = specItems3[k]; + if ((item3.Offset & kFlag) != 0) + return S_FALSE; + if (item3.Offset >= _buf.GetCapacity() || _buf.GetCapacity() - item3.Offset < 16) + return S_FALSE; + const Byte *buf = _buf + item3.Offset; + item.Lang = item3.ID; + item.Offset = Get32(buf + 0); + item.Size = Get32(buf + 4); + // UInt32 codePage = Get32(buf + 8); + if (Get32(buf + 12) != 0) + return S_FALSE; + if (!_items.IsEmpty() && _oneLang && !item.IsNameEqual(_items.Back())) + _oneLang = false; + + item.HeaderSize = 0; + + size_t offset = item.Offset - sect.Va; + if (offset > maxOffset) + maxOffset = offset; + if (offset + item.Size > maxOffset) + maxOffset = offset + item.Size; + + if (CheckItem(sect, item, offset)) + { + const Byte *data = _buf + offset; + if (item.IsBmp()) + item.HeaderSize = SetBitmapHeader(item.Header, data, item.Size); + else if (item.IsIcon()) + item.HeaderSize = SetIconHeader(item.Header, data, item.Size); + else if (item.IsString()) + { + if (stringsOk) + stringsOk = ParseStringRes(item.ID, item.Lang, data, item.Size); + } + } + + item.Enabled = true; + _items.Add(item); + } + } + } + + if (stringsOk && !_strings.IsEmpty()) + { + int i; + for (i = 0; i < _items.Size(); i++) + { + CResItem &item = _items[i]; + if (item.IsString()) + item.Enabled = false; + } + for (i = 0; i < _strings.Size(); i++) + { + if (_strings[i].Size == 0) + continue; + CMixItem mixItem; + mixItem.ResourceIndex = -1; + mixItem.StringIndex = i; + mixItem.SectionIndex = sectionIndex; + _mixItems.Add(mixItem); + } + } + + _usedRes.Free(); + + int numBits = _optHeader.GetNumFileAlignBits(); + if (numBits >= 0) + { + UInt32 mask = (1 << numBits) - 1; + size_t end = ((maxOffset + mask) & ~mask); + if (end < sect.VSize && end <= sect.PSize) + { + CSection sect2; + sect2.Flags = 0; + + // we skip Zeros to start of aligned block + size_t i; + for (i = maxOffset; i < end; i++) + if (_buf[i] != 0) + break; + if (i == end) + maxOffset = end; + + sect2.Pa = sect.Pa + (UInt32)maxOffset; + sect2.Va = sect.Va + (UInt32)maxOffset; + sect2.PSize = sect.VSize - (UInt32)maxOffset; + sect2.VSize = sect2.PSize; + sect2.Name = ".rsrc_1"; + sect2.Time = 0; + sect2.IsAdditionalSection = true; + _sections.Add(sect2); + } + } + + return S_OK; +} + +HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) +{ + const UInt32 kBufSize = 1 << 18; + const UInt32 kSigSize = 2; + + _mainSubfile = -1; + + CByteBuffer buffer; + buffer.SetCapacity(kBufSize); + Byte *buf = buffer; + + size_t processed = kSigSize; + RINOK(ReadStream_FALSE(stream, buf, processed)); + if (buf[0] != 'M' || buf[1] != 'Z') + return S_FALSE; + processed = kBufSize - kSigSize; + RINOK(ReadStream(stream, buf + kSigSize, &processed)); + processed += kSigSize; + if (!Parse(buf, (UInt32)processed)) + return S_FALSE; + bool thereISDebug; + RINOK(LoadDebugSections(stream, thereISDebug)); + + const CDirLink &certLink = _optHeader.DirItems[kDirLink_Certificate]; + if (certLink.Size != 0) + { + CSection sect; + sect.Name = "CERTIFICATE"; + sect.Va = 0; + sect.Pa = certLink.Va; + sect.PSize = sect.VSize = certLink.Size; + sect.UpdateTotalSize(_totalSize); + _sections.Add(sect); + } + + if (thereISDebug) + { + const UInt32 kAlign = 1 << 12; + UInt32 alignPos = _totalSize & (kAlign - 1); + if (alignPos != 0) + { + UInt32 size = kAlign - alignPos; + RINOK(stream->Seek(_totalSize, STREAM_SEEK_SET, NULL)); + buffer.Free(); + buffer.SetCapacity(kAlign); + Byte *buf = buffer; + size_t processed = size; + RINOK(ReadStream(stream, buf, &processed)); + size_t i; + for (i = 0; i < processed; i++) + { + if (buf[i] != 0) + break; + } + if (processed < size && processed < 100) + _totalSize += (UInt32)processed; + else if (((_totalSize + i) & 0x1FF) == 0 || processed < size) + _totalSize += (UInt32)i; + } + } + + if (_header.NumSymbols > 0 && _header.PointerToSymbolTable >= 512) + { + if (_header.NumSymbols >= (1 << 24)) + return S_FALSE; + CSection sect; + sect.Name = "COFF_SYMBOLS"; + UInt32 size = _header.NumSymbols * 18; + RINOK(stream->Seek((UInt64)_header.PointerToSymbolTable + size, STREAM_SEEK_SET, NULL)); + Byte buf[4]; + RINOK(ReadStream_FALSE(stream, buf, 4)); + UInt32 size2 = Get32(buf); + if (size2 >= (1 << 28)) + return S_FALSE; + size += size2; + + sect.Va = 0; + sect.Pa = _header.PointerToSymbolTable; + sect.PSize = sect.VSize = size; + sect.UpdateTotalSize(_totalSize); + _sections.Add(sect); + } + + UInt64 fileSize; + RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize)); + if (fileSize > _totalSize) + return S_FALSE; + _totalSizeLimited = (_totalSize < fileSize) ? _totalSize : (UInt32)fileSize; + + { + CObjectVector sections = _sections; + sections.Sort(); + UInt32 limit = (1 << 12); + int num = 0; + int numSections = sections.Size(); + for (int i = 0; i < numSections; i++) + { + const CSection &s = sections[i]; + if (s.Pa > limit) + { + CSection s2; + s2.Pa = s2.Va = limit; + s2.PSize = s2.VSize = s.Pa - limit; + s2.IsAdditionalSection = true; + s2.Name = '['; + s2.Name += GetDecString(num++); + s2.Name += ']'; + _sections.Add(s2); + limit = s.Pa; + } + UInt32 next = s.Pa + s.PSize; + if (next < s.Pa) + break; + if (next >= limit) + limit = next; + } + } + + _parseResources = true; + + UInt64 mainSize = 0, mainSize2 = 0; + int i; + for (i = 0; i < _sections.Size(); i++) + { + const CSection § = _sections[i]; + CMixItem mixItem; + mixItem.SectionIndex = i; + if (_parseResources && sect.Name == ".rsrc" && _items.IsEmpty()) + { + HRESULT res = OpenResources(i, stream, callback); + if (res == S_OK) + { + _resourceFileName = GetUnicodeString(sect.Name); + for (int j = 0; j < _items.Size(); j++) + { + const CResItem &item = _items[j]; + if (item.Enabled) + { + mixItem.ResourceIndex = j; + mixItem.StringIndex = -1; + if (item.IsRcDataOrUnknown()) + { + if (item.Size >= mainSize) + { + mainSize2 = mainSize; + mainSize = item.Size; + _mainSubfile = _mixItems.Size(); + } + else if (item.Size >= mainSize2) + mainSize2 = item.Size; + } + _mixItems.Add(mixItem); + } + } + if (sect.PSize > sect.VSize) + { + int numBits = _optHeader.GetNumFileAlignBits(); + if (numBits >= 0) + { + UInt32 mask = (1 << numBits) - 1; + UInt32 end = ((sect.VSize + mask) & ~mask); + + if (sect.PSize > end) + { + CSection sect2; + sect2.Flags = 0; + sect2.Pa = sect.Pa + end; + sect2.Va = sect.Va + end; + sect2.PSize = sect.PSize - end; + sect2.VSize = sect2.PSize; + sect2.Name = ".rsrc_2"; + sect2.Time = 0; + sect2.IsAdditionalSection = true; + _sections.Add(sect2); + } + } + } + continue; + } + if (res != S_FALSE) + return res; + CloseResources(); + } + mixItem.StringIndex = -1; + mixItem.ResourceIndex = -1; + if (sect.IsAdditionalSection) + { + if (sect.PSize >= mainSize) + { + mainSize2 = mainSize; + mainSize = sect.PSize; + _mainSubfile = _mixItems.Size(); + } + else + mainSize2 = sect.PSize; + } + _mixItems.Add(mixItem); + } + + if (mainSize2 >= (1 << 20) && mainSize < mainSize2 * 2) + _mainSubfile = -1; + + for (i = 0; i < _mixItems.Size(); i++) + { + const CMixItem &mixItem = _mixItems[i]; + if (mixItem.StringIndex < 0 && mixItem.ResourceIndex < 0 && _sections[mixItem.SectionIndex].Name == "_winzip_") + { + _mainSubfile = i; + break; + } + } + + return S_OK; +} + +HRESULT CalcCheckSum(ISequentialInStream *stream, UInt32 size, UInt32 excludePos, UInt32 &res) +{ + // size &= ~1; + const UInt32 kBufSize = 1 << 23; + CByteBuffer buffer; + buffer.SetCapacity(kBufSize); + Byte *buf = buffer; + + UInt32 sum = 0; + UInt32 pos = 0; + for (;;) + { + UInt32 rem = size - pos; + if (rem > kBufSize) + rem = kBufSize; + if (rem == 0) + break; + size_t processed = rem; + RINOK(ReadStream(stream, buf, &processed)); + + /* + for (; processed < rem; processed++) + buf[processed] = 0; + */ + + if ((processed & 1) != 0) + buf[processed] = 0; + + for (int j = 0; j < 4; j++) + { + UInt32 p = excludePos + j; + if (pos <= p && p < pos + processed) + buf[p - pos] = 0; + } + + for (size_t i = 0; i < processed; i += 2) + { + sum += Get16(buf + i); + sum = (sum + (sum >> 16)) & 0xFFFF; + } + pos += (UInt32)processed; + if (rem != processed) + break; + } + sum += pos; + res = sum; + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + Close(); + RINOK(Open2(inStream, callback)); + _stream = inStream; + return S_OK; + COM_TRY_END +} + +void CHandler::CloseResources() +{ + _usedRes.Free(); + _items.Clear(); + _strings.Clear(); + _buf.SetCapacity(0); +} + +STDMETHODIMP CHandler::Close() +{ + _stream.Release(); + _sections.Clear(); + _mixItems.Clear(); + CloseResources(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _mixItems.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _mixItems.Size(); + if (numItems == 0) + return S_OK; + UInt64 totalSize = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + { + const CMixItem &mixItem = _mixItems[allFilesMode ? i : indices[i]]; + if (mixItem.StringIndex >= 0) + totalSize += _strings[mixItem.StringIndex].Size; + else if (mixItem.ResourceIndex < 0) + totalSize += _sections[mixItem.SectionIndex].GetPackSize(); + else + totalSize += _items[mixItem.ResourceIndex].GetSize(); + } + extractCallback->SetTotal(totalSize); + + UInt64 currentTotalSize = 0; + UInt64 currentItemSize; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + bool checkSumOK = true; + if (_optHeader.CheckSum != 0 && (int)numItems == _mixItems.Size()) + { + UInt32 checkSum = 0; + RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL)); + CalcCheckSum(_stream, _totalSizeLimited, _peOffset + kHeaderSize + 64, checkSum); + checkSumOK = (checkSum == _optHeader.CheckSum); + } + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStream(streamSpec); + streamSpec->SetStream(_stream); + + for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) + { + lps->InSize = lps->OutSize = currentTotalSize; + RINOK(lps->SetCur()); + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + UInt32 index = allFilesMode ? i : indices[i]; + + CMyComPtr outStream; + RINOK(extractCallback->GetStream(index, &outStream, askMode)); + const CMixItem &mixItem = _mixItems[index]; + + const CSection § = _sections[mixItem.SectionIndex]; + bool isOk = true; + if (mixItem.StringIndex >= 0) + { + const CStringItem &item = _strings[mixItem.StringIndex]; + currentItemSize = item.Size; + if (!testMode && !outStream) + continue; + + RINOK(extractCallback->PrepareOperation(askMode)); + if (outStream) + RINOK(WriteStream(outStream, item.Buf, item.Size)); + } + else if (mixItem.ResourceIndex < 0) + { + currentItemSize = sect.GetPackSize(); + if (!testMode && !outStream) + continue; + + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(_stream->Seek(sect.Pa, STREAM_SEEK_SET, NULL)); + streamSpec->Init(currentItemSize); + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + isOk = (copyCoderSpec->TotalSize == currentItemSize); + } + else + { + const CResItem &item = _items[mixItem.ResourceIndex]; + currentItemSize = item.GetSize(); + if (!testMode && !outStream) + continue; + + RINOK(extractCallback->PrepareOperation(askMode)); + size_t offset = item.Offset - sect.Va; + if (!CheckItem(sect, item, offset)) + isOk = false; + else if (outStream) + { + if (item.HeaderSize != 0) + RINOK(WriteStream(outStream, item.Header, item.HeaderSize)); + RINOK(WriteStream(outStream, _buf + offset, item.Size)); + } + } + + outStream.Release(); + RINOK(extractCallback->SetOperationResult(isOk ? + checkSumOK ? + NExtract::NOperationResult::kOK: + NExtract::NOperationResult::kCRCError: + NExtract::NOperationResult::kDataError)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + *stream = 0; + + const CMixItem &mixItem = _mixItems[index]; + const CSection § = _sections[mixItem.SectionIndex]; + if (mixItem.IsSectionItem()) + return CreateLimitedInStream(_stream, sect.Pa, sect.PSize, stream); + + CBufInStream *inStreamSpec = new CBufInStream; + CMyComPtr streamTemp = inStreamSpec; + CReferenceBuf *referenceBuf = new CReferenceBuf; + CMyComPtr ref = referenceBuf; + if (mixItem.StringIndex >= 0) + { + const CStringItem &item = _strings[mixItem.StringIndex]; + referenceBuf->Buf.SetCapacity(item.Size); + memcpy(referenceBuf->Buf, item.Buf, item.Size); + } + else + { + const CResItem &item = _items[mixItem.ResourceIndex]; + size_t offset = item.Offset - sect.Va; + if (!CheckItem(sect, item, offset)) + return S_FALSE; + if (item.HeaderSize == 0) + { + CBufInStream *streamSpec = new CBufInStream; + CMyComPtr streamTemp2 = streamSpec; + streamSpec->Init(_buf + offset, item.Size, (IInArchive *)this); + *stream = streamTemp2.Detach(); + return S_OK; + } + referenceBuf->Buf.SetCapacity(item.HeaderSize + item.Size); + memcpy(referenceBuf->Buf, item.Header, item.HeaderSize); + memcpy(referenceBuf->Buf + item.HeaderSize, _buf + offset, item.Size); + } + inStreamSpec->Init(referenceBuf); + + *stream = streamTemp.Detach(); + return S_OK; + COM_TRY_END +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"PE", L"exe dll sys", 0, 0xDD, { 'P', 'E', 0, 0 }, 4, false, CreateArc, 0 }; + +REGISTER_ARC(Pe) + +}} diff --git a/CPP/7zip/Archive/PpmdHandler.cpp b/CPP/7zip/Archive/PpmdHandler.cpp new file mode 100755 index 0000000..e9ee2b1 --- /dev/null +++ b/CPP/7zip/Archive/PpmdHandler.cpp @@ -0,0 +1,456 @@ +/* PpmdHandler.c -- PPMd format handler +2010-03-10 : Igor Pavlov : Public domain +This code is based on: + PPMd var.H (2001) / var.I (2002): Dmitry Shkarin : Public domain + Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" +#include "../../../C/Alloc.h" +#include "../../../C/Ppmd7.h" +#include "../../../C/Ppmd8.h" + +#include "Common/ComTry.h" +#include "Common/IntToString.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../Common/CWrappers.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +using namespace NWindows; + +namespace NArchive { +namespace NPpmd { + +static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } +static void SzBigFree(void *, void *address) { BigFree(address); } +static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; + +static const UInt32 kBufSize = (1 << 20); + +struct CBuf +{ + Byte *Buf; + + CBuf(): Buf(0) {} + ~CBuf() { ::MidFree(Buf); } + bool Alloc() + { + if (!Buf) + Buf = (Byte *)::MidAlloc(kBufSize); + return (Buf != 0); + } +}; + +static const UInt32 kHeaderSize = 16; +static const UInt32 kSignature = 0x84ACAF8F; +static const unsigned kNewHeaderVer = 8; + +struct CItem +{ + UInt32 Attrib; + UInt32 Time; + AString Name; + + unsigned Order; + unsigned MemInMB; + unsigned Ver; + unsigned Restor; + + HRESULT ReadHeader(ISequentialInStream *s, UInt32 &headerSize); + bool IsSupported() const { return Ver == 7 || (Ver == 8 && Restor <= 1); } +}; + +HRESULT CItem::ReadHeader(ISequentialInStream *s, UInt32 &headerSize) +{ + Byte h[kHeaderSize]; + RINOK(ReadStream_FALSE(s, h, kHeaderSize)); + if (GetUi32(h) != kSignature) + return S_FALSE; + Attrib = GetUi32(h + 4); + Time = GetUi32(h + 12); + + unsigned info = GetUi16(h + 8); + Order = (info & 0xF) + 1; + MemInMB = ((info >> 4) & 0xFF) + 1; + Ver = info >> 12; + + UInt32 nameLen = GetUi16(h + 10); + Restor = nameLen >> 14; + if (Restor > 2) + return S_FALSE; + if (Ver >= kNewHeaderVer) + nameLen &= 0x3FFF; + if (nameLen > (1 << 9)) + return S_FALSE; + char *name = Name.GetBuffer(nameLen + 1); + HRESULT res = ReadStream_FALSE(s, name, nameLen); + name[nameLen] = 0; + headerSize = kHeaderSize + nameLen; + Name.ReleaseBuffer(); + return res; +} + +class CHandler: + public IInArchive, + public IArchiveOpenSeq, + public CMyUnknownImp +{ + CItem _item; + UInt32 _headerSize; + UInt64 _packSize; + bool _packSizeDefined; + CMyComPtr _stream; + +public: + MY_UNKNOWN_IMP2(IInArchive, IArchiveOpenSeq) + INTERFACE_IInArchive(;) + STDMETHOD(OpenSeq)(ISequentialInStream *stream); +}; + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidAttrib, VT_UI4}, + { NULL, kpidMethod, VT_BSTR} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO_Table + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidPhySize: if (_packSizeDefined) prop = _packSize; break; + } + prop.Detach(value); + return S_OK; +} + + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = 1; + return S_OK; +} + +static void UIntToString(AString &s, const char *prefix, unsigned value) +{ + s += prefix; + char temp[16]; + ::ConvertUInt32ToString((UInt32)value, temp); + s += temp; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidPath: prop = MultiByteToUnicodeString(_item.Name, CP_ACP); break; + case kpidMTime: + { + FILETIME utc; + if (NTime::DosTimeToFileTime(_item.Time, utc)) + prop = utc; + break; + } + case kpidAttrib: prop = _item.Attrib; break; + case kpidPackSize: if (_packSizeDefined) prop = _packSize; break; + case kpidMethod: + { + AString s = "PPMd"; + s += (char)('A' + _item.Ver); + UIntToString(s, ":o", _item.Order); + UIntToString(s, ":mem", _item.MemInMB); + s += 'm'; + if (_item.Ver >= kNewHeaderVer && _item.Restor != 0) + UIntToString(s, ":r", _item.Restor); + prop = s; + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *) +{ + return OpenSeq(stream); +} + +STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) +{ + COM_TRY_BEGIN + HRESULT res; + try + { + Close(); + res = _item.ReadHeader(stream, _headerSize); + } + catch(...) { res = S_FALSE; } + if (res == S_OK) + _stream = stream; + else + Close(); + return res; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _packSizeDefined = false; + _stream.Release(); + return S_OK; +} + +static const UInt32 kTopValue = (1 << 24); +static const UInt32 kBot = (1 << 15); + +struct CRangeDecoder +{ + IPpmd7_RangeDec s; + UInt32 Range; + UInt32 Code; + UInt32 Low; + CByteInBufWrap *Stream; + +public: + bool Init() + { + Code = 0; + Low = 0; + Range = 0xFFFFFFFF; + for (int i = 0; i < 4; i++) + Code = (Code << 8) | Stream->ReadByte(); + return Code < 0xFFFFFFFF; + } + + void Normalize() + { + while ((Low ^ (Low + Range)) < kTopValue || + Range < kBot && ((Range = (0 - Low) & (kBot - 1)), 1)) + { + Code = (Code << 8) | Stream->ReadByte(); + Range <<= 8; + Low <<= 8; + } + } + + CRangeDecoder(); +}; + + +extern "C" { + +static UInt32 Range_GetThreshold(void *pp, UInt32 total) +{ + CRangeDecoder *p = (CRangeDecoder *)pp; + return p->Code / (p->Range /= total); +} + +static void Range_Decode(void *pp, UInt32 start, UInt32 size) +{ + CRangeDecoder *p = (CRangeDecoder *)pp; + start *= p->Range; + p->Low += start; + p->Code -= start; + p->Range *= size; + p->Normalize(); +} + +static UInt32 Range_DecodeBit(void *pp, UInt32 size0) +{ + CRangeDecoder *p = (CRangeDecoder *)pp; + if (p->Code / (p->Range >>= 14) < size0) + { + Range_Decode(p, 0, size0); + return 0; + } + else + { + Range_Decode(p, size0, (1 << 14) - size0); + return 1; + } +} + +} + +CRangeDecoder::CRangeDecoder() +{ + s.GetThreshold = Range_GetThreshold; + s.Decode = Range_Decode; + s.DecodeBit = Range_DecodeBit; +} + +struct CPpmdCpp +{ + unsigned Ver; + CRangeDecoder _rc; + CPpmd7 _ppmd7; + CPpmd8 _ppmd8; + + CPpmdCpp(unsigned version) + { + Ver = version; + Ppmd7_Construct(&_ppmd7); + Ppmd8_Construct(&_ppmd8); + } + + ~CPpmdCpp() + { + Ppmd7_Free(&_ppmd7, &g_BigAlloc); + Ppmd8_Free(&_ppmd8, &g_BigAlloc); + } + + bool Alloc(UInt32 memInMB) + { + memInMB <<= 20; + if (Ver == 7) + return Ppmd7_Alloc(&_ppmd7, memInMB, &g_BigAlloc) != 0; + return Ppmd8_Alloc(&_ppmd8, memInMB, &g_BigAlloc) != 0; + } + + void Init(unsigned order, unsigned restor) + { + if (Ver == 7) + Ppmd7_Init(&_ppmd7, order); + else + Ppmd8_Init(&_ppmd8, order, restor);; + } + + bool InitRc(CByteInBufWrap *inStream) + { + if (Ver == 7) + { + _rc.Stream = inStream; + return _rc.Init(); + } + else + { + _ppmd8.Stream.In = &inStream->p; + return Ppmd8_RangeDec_Init(&_ppmd8) != 0; + } + } + + bool IsFinishedOK() + { + if (Ver == 7) + return Ppmd7z_RangeDec_IsFinishedOK(&_rc); + return Ppmd8_RangeDec_IsFinishedOK(&_ppmd8); + } +}; + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + if (numItems == 0) + return S_OK; + if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0)) + return E_INVALIDARG; + + // extractCallback->SetTotal(_packSize); + 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); + + CByteInBufWrap inBuf; + if (!inBuf.Alloc(1 << 20)) + return E_OUTOFMEMORY; + inBuf.Stream = _stream; + + CBuf outBuf; + if (!outBuf.Alloc()) + return E_OUTOFMEMORY; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, true); + + CPpmdCpp ppmd(_item.Ver); + if (!ppmd.Alloc(_item.MemInMB)) + return E_OUTOFMEMORY; + Int32 opRes = NExtract::NOperationResult::kUnSupportedMethod; + if (_item.IsSupported()) + { + opRes = NExtract::NOperationResult::kDataError; + ppmd.Init(_item.Order, _item.Restor); + inBuf.Init(); + UInt64 outSize = 0; + if (ppmd.InitRc(&inBuf) && !inBuf.Extra && inBuf.Res == S_OK) + for (;;) + { + lps->InSize = _packSize = inBuf.GetProcessed(); + lps->OutSize = outSize; + RINOK(lps->SetCur()); + + size_t i; + int sym = 0; + + if (ppmd.Ver == 7) + { + for (i = 0; i < kBufSize; i++) + { + sym = Ppmd7_DecodeSymbol(&ppmd._ppmd7, &ppmd._rc.s); + if (inBuf.Extra || sym < 0) + break; + outBuf.Buf[i] = (Byte)sym; + } + } + else + { + for (i = 0; i < kBufSize; i++) + { + sym = Ppmd8_DecodeSymbol(&ppmd._ppmd8); + if (inBuf.Extra || sym < 0) + break; + outBuf.Buf[i] = (Byte)sym; + } + } + + outSize += i; + _packSize = _headerSize + inBuf.GetProcessed(); + _packSizeDefined = true; + if (realOutStream) + { + RINOK(WriteStream(realOutStream, outBuf.Buf, i)); + } + if (sym < 0) + { + if (sym == -1 && ppmd.IsFinishedOK()) + opRes = NExtract::NOperationResult::kOK; + break; + } + } + RINOK(inBuf.Res); + } + realOutStream.Release(); + return extractCallback->SetOperationResult(opRes); +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"Ppmd", L"pmd", 0, 0xD, { 0x8F, 0xAF, 0xAC, 0x84 }, 4, false, CreateArc, 0 }; + +REGISTER_ARC(Ppmd) + +}} diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp new file mode 100755 index 0000000..15abec6 --- /dev/null +++ b/CPP/7zip/Archive/Rar/RarHandler.cpp @@ -0,0 +1,869 @@ +// RarHandler.cpp + +#include "StdAfx.h" + +#include "Common/ComTry.h" +#include "Common/IntToString.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/PropVariantUtils.h" +#include "Windows/Time.h" + +#include "../../IPassword.h" + +#include "../../Common/CreateCoder.h" +#include "../../Common/FilterCoder.h" +#include "../../Common/MethodId.h" +#include "../../Common/ProgressUtils.h" + +#include "../../Compress/CopyCoder.h" + +#include "../../Crypto/Rar20Crypto.h" +#include "../../Crypto/RarAes.h" + +#include "../Common/ItemNameUtils.h" +#include "../Common/OutStreamWithCRC.h" + +#include "RarHandler.h" + +using namespace NWindows; +using namespace NTime; + +namespace NArchive { +namespace NRar { + +static const wchar_t *kHostOS[] = +{ + L"MS DOS", + L"OS/2", + L"Win32", + L"Unix", + L"Mac OS", + L"BeOS" +}; + +static const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]); + +static const wchar_t *kUnknownOS = L"Unknown"; + +static const CUInt32PCharPair k_Flags[] = +{ + { 0, "Volume" }, + { 1, "Comment" }, + { 2, "Lock" }, + { 3, "Solid" }, + { 4, "NewVolName" }, // pack_comment in old versuons + { 5, "Authenticity" }, + { 6, "Recovery" }, + { 7, "BlockEncryption" }, + { 8, "FirstVolume" }, + { 9, "EncryptVer" } +}; + +static const STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidATime, VT_FILETIME}, + { NULL, kpidAttrib, VT_UI4}, + + { NULL, kpidEncrypted, VT_BOOL}, + { NULL, kpidSolid, VT_BOOL}, + { NULL, kpidCommented, VT_BOOL}, + { NULL, kpidSplitBefore, VT_BOOL}, + { NULL, kpidSplitAfter, VT_BOOL}, + { NULL, kpidCRC, VT_UI4}, + { NULL, kpidHostOS, VT_BSTR}, + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidUnpackVer, VT_UI1} +}; + +static const STATPROPSTG kArcProps[] = +{ + { NULL, kpidCharacts, VT_BSTR}, + { NULL, kpidSolid, VT_BOOL}, + { NULL, kpidNumBlocks, VT_UI4}, + // { NULL, kpidEncrypted, VT_BOOL}, + { NULL, kpidIsVolume, VT_BOOL}, + { NULL, kpidNumVolumes, VT_UI4}, + { NULL, kpidPhySize, VT_UI8} + // { NULL, kpidCommented, VT_BOOL} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +UInt64 CHandler::GetPackSize(int refIndex) const +{ + const CRefItem &refItem = _refItems[refIndex]; + UInt64 totalPackSize = 0; + for (int i = 0; i < refItem.NumItems; i++) + totalPackSize += _items[refItem.ItemIndex + i].PackSize; + return totalPackSize; +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidSolid: prop = _archiveInfo.IsSolid(); break; + case kpidCharacts: FLAGS_TO_PROP(k_Flags, _archiveInfo.Flags, prop); break; + // case kpidEncrypted: prop = _archiveInfo.IsEncrypted(); break; // it's for encrypted names. + case kpidIsVolume: prop = _archiveInfo.IsVolume(); break; + case kpidNumVolumes: prop = (UInt32)_archives.Size(); break; + case kpidOffset: if (_archiveInfo.StartPosition != 0) prop = _archiveInfo.StartPosition; break; + // case kpidCommented: prop = _archiveInfo.IsCommented(); break; + case kpidNumBlocks: + { + UInt32 numBlocks = 0; + for (int i = 0; i < _refItems.Size(); i++) + if (!IsSolid(i)) + numBlocks++; + prop = (UInt32)numBlocks; + break; + } + case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _refItems.Size(); + return S_OK; +} + +static bool RarTimeToFileTime(const CRarTime &rarTime, FILETIME &result) +{ + if (!DosTimeToFileTime(rarTime.DosTime, result)) + return false; + UInt64 value = (((UInt64)result.dwHighDateTime) << 32) + result.dwLowDateTime; + value += (UInt64)rarTime.LowSecond * 10000000; + value += ((UInt64)rarTime.SubTime[2] << 16) + + ((UInt64)rarTime.SubTime[1] << 8) + + ((UInt64)rarTime.SubTime[0]); + result.dwLowDateTime = (DWORD)value; + result.dwHighDateTime = DWORD(value >> 32); + return true; +} + +static void RarTimeToProp(const CRarTime &rarTime, NWindows::NCOM::CPropVariant &prop) +{ + FILETIME localFileTime, utcFileTime; + if (RarTimeToFileTime(rarTime, localFileTime)) + { + if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime)) + utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0; + } + else + utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0; + prop = utcFileTime; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + const CRefItem &refItem = _refItems[index]; + const CItemEx &item = _items[refItem.ItemIndex]; + switch(propID) + { + case kpidPath: + { + UString u; + if (item.HasUnicodeName() && !item.UnicodeName.IsEmpty()) + u = item.UnicodeName; + else + u = MultiByteToUnicodeString(item.Name, CP_OEMCP); + prop = (const wchar_t *)NItemName::WinNameToOSName(u); + break; + } + case kpidIsDir: prop = item.IsDir(); break; + case kpidSize: prop = item.Size; break; + case kpidPackSize: prop = GetPackSize(index); break; + case kpidMTime: RarTimeToProp(item.MTime, prop); break; + case kpidCTime: if (item.CTimeDefined) RarTimeToProp(item.CTime, prop); break; + case kpidATime: if (item.ATimeDefined) RarTimeToProp(item.ATime, prop); break; + case kpidAttrib: prop = item.GetWinAttributes(); break; + case kpidEncrypted: prop = item.IsEncrypted(); break; + case kpidSolid: prop = IsSolid(index); break; + case kpidCommented: prop = item.IsCommented(); break; + case kpidSplitBefore: prop = item.IsSplitBefore(); break; + case kpidSplitAfter: prop = _items[refItem.ItemIndex + refItem.NumItems - 1].IsSplitAfter(); break; + case kpidCRC: + { + const CItemEx &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1]; + prop = ((lastItem.IsSplitAfter()) ? item.FileCRC : lastItem.FileCRC); + break; + } + case kpidUnpackVer: prop = item.UnPackVersion; break; + case kpidMethod: + { + UString method; + if (item.Method >= Byte('0') && item.Method <= Byte('5')) + { + method = L"m"; + wchar_t temp[32]; + ConvertUInt64ToString(item.Method - Byte('0'), temp); + method += temp; + if (!item.IsDir()) + { + method += L":"; + ConvertUInt64ToString(16 + item.GetDictSize(), temp); + method += temp; + } + } + else + { + wchar_t temp[32]; + ConvertUInt64ToString(item.Method, temp); + method += temp; + } + prop = method; + break; + } + case kpidHostOS: prop = (item.HostOS < kNumHostOSes) ? (kHostOS[item.HostOS]) : kUnknownOS; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +class CVolumeName +{ + bool _first; + bool _newStyle; + UString _unchangedPart; + UString _changedPart; + UString _afterPart; +public: + CVolumeName(): _newStyle(true) {}; + + bool InitName(const UString &name, bool newStyle) + { + _first = true; + _newStyle = newStyle; + int dotPos = name.ReverseFind('.'); + UString basePart = name; + if (dotPos >= 0) + { + UString ext = name.Mid(dotPos + 1); + if (ext.CompareNoCase(L"rar") == 0) + { + _afterPart = name.Mid(dotPos); + basePart = name.Left(dotPos); + } + else if (ext.CompareNoCase(L"exe") == 0) + { + _afterPart = L".rar"; + basePart = name.Left(dotPos); + } + else if (!_newStyle) + { + if (ext.CompareNoCase(L"000") == 0 || + ext.CompareNoCase(L"001") == 0 || + ext.CompareNoCase(L"r00") == 0 || + ext.CompareNoCase(L"r01") == 0) + { + _afterPart.Empty(); + _first = false; + _changedPart = ext; + _unchangedPart = name.Left(dotPos + 1); + return true; + } + } + } + + if (!_newStyle) + { + _afterPart.Empty(); + _unchangedPart = basePart + UString(L"."); + _changedPart = L"r00"; + return true; + } + + int numLetters = 1; + if (basePart.Right(numLetters) == L"1" || basePart.Right(numLetters) == L"0") + { + while (numLetters < basePart.Length()) + { + if (basePart[basePart.Length() - numLetters - 1] != '0') + break; + numLetters++; + } + } + else + return false; + _unchangedPart = basePart.Left(basePart.Length() - numLetters); + _changedPart = basePart.Right(numLetters); + return true; + } + + UString GetNextName() + { + UString newName; + if (_newStyle || !_first) + { + int i; + int numLetters = _changedPart.Length(); + for (i = numLetters - 1; i >= 0; i--) + { + wchar_t c = _changedPart[i]; + if (c == L'9') + { + c = L'0'; + newName = c + newName; + if (i == 0) + newName = UString(L'1') + newName; + continue; + } + c++; + newName = UString(c) + newName; + i--; + for (; i >= 0; i--) + newName = _changedPart[i] + newName; + break; + } + _changedPart = newName; + } + _first = false; + return _unchangedPart + _changedPart + _afterPart; + } +}; + +HRESULT CHandler::Open2(IInStream *stream, + const UInt64 *maxCheckStartPosition, + IArchiveOpenCallback *openCallback) +{ + { + CMyComPtr openVolumeCallback; + CMyComPtr getTextPassword; + CMyComPtr openArchiveCallbackWrap = openCallback; + + CVolumeName seqName; + + UInt64 totalBytes = 0; + UInt64 curBytes = 0; + + if (openCallback) + { + openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback); + openArchiveCallbackWrap.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); + } + + for (;;) + { + CMyComPtr inStream; + if (!_archives.IsEmpty()) + { + if (!openVolumeCallback) + break; + + if (_archives.Size() == 1) + { + if (!_archiveInfo.IsVolume()) + break; + UString baseName; + { + NCOM::CPropVariant prop; + RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); + if (prop.vt != VT_BSTR) + break; + baseName = prop.bstrVal; + } + seqName.InitName(baseName, _archiveInfo.HaveNewVolumeName()); + } + + UString fullName = seqName.GetNextName(); + HRESULT result = openVolumeCallback->GetStream(fullName, &inStream); + if (result == S_FALSE) + break; + if (result != S_OK) + return result; + if (!stream) + break; + } + else + inStream = stream; + + UInt64 endPos = 0; + RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos)); + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + if (openCallback) + { + totalBytes += endPos; + RINOK(openCallback->SetTotal(NULL, &totalBytes)); + } + + NArchive::NRar::CInArchive archive; + RINOK(archive.Open(inStream, maxCheckStartPosition)); + + if (_archives.IsEmpty()) + archive.GetArchiveInfo(_archiveInfo); + + CItemEx item; + for (;;) + { + if (archive.m_Position > endPos) + { + AddErrorMessage("Unexpected end of archive"); + break; + } + bool decryptionError; + AString errorMessageLoc; + HRESULT result = archive.GetNextItem(item, getTextPassword, decryptionError, errorMessageLoc); + if (errorMessageLoc) + AddErrorMessage(errorMessageLoc); + if (result == S_FALSE) + { + if (decryptionError && _items.IsEmpty()) + return S_FALSE; + break; + } + RINOK(result); + if (item.IgnoreItem()) + continue; + + bool needAdd = true; + if (item.IsSplitBefore()) + { + if (!_refItems.IsEmpty()) + { + CRefItem &refItem = _refItems.Back(); + refItem.NumItems++; + needAdd = false; + } + } + if (needAdd) + { + CRefItem refItem; + refItem.ItemIndex = _items.Size(); + refItem.NumItems = 1; + refItem.VolumeIndex = _archives.Size(); + _refItems.Add(refItem); + } + _items.Add(item); + if (openCallback && _items.Size() % 100 == 0) + { + UInt64 numFiles = _items.Size(); + UInt64 numBytes = curBytes + item.Position; + RINOK(openCallback->SetCompleted(&numFiles, &numBytes)); + } + } + curBytes += endPos; + _archives.Add(archive); + } + } + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *stream, + const UInt64 *maxCheckStartPosition, + IArchiveOpenCallback *openCallback) +{ + COM_TRY_BEGIN + Close(); + try + { + HRESULT res = Open2(stream, maxCheckStartPosition, openCallback); + if (res != S_OK) + Close(); + return res; + } + catch(const CInArchiveException &) { Close(); return S_FALSE; } + catch(...) { Close(); throw; } + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + COM_TRY_BEGIN + _errorMessage.Empty(); + _refItems.Clear(); + _items.Clear(); + _archives.Clear(); + return S_OK; + COM_TRY_END +} + +struct CMethodItem +{ + Byte RarUnPackVersion; + CMyComPtr Coder; +}; + + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + CMyComPtr getTextPassword; + UInt64 censoredTotalUnPacked = 0, + // censoredTotalPacked = 0, + importantTotalUnPacked = 0; + // importantTotalPacked = 0; + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _refItems.Size(); + if (numItems == 0) + return S_OK; + int lastIndex = 0; + CRecordVector importantIndexes; + CRecordVector extractStatuses; + + for (UInt32 t = 0; t < numItems; t++) + { + int index = allFilesMode ? t : indices[t]; + const CRefItem &refItem = _refItems[index]; + const CItemEx &item = _items[refItem.ItemIndex]; + censoredTotalUnPacked += item.Size; + // censoredTotalPacked += item.PackSize; + int j; + for (j = lastIndex; j <= index; j++) + // if (!_items[_refItems[j].ItemIndex].IsSolid()) + if (!IsSolid(j)) + lastIndex = j; + for (j = lastIndex; j <= index; j++) + { + const CRefItem &refItem = _refItems[j]; + const CItemEx &item = _items[refItem.ItemIndex]; + + // const CItemEx &item = _items[j]; + + importantTotalUnPacked += item.Size; + // importantTotalPacked += item.PackSize; + importantIndexes.Add(j); + extractStatuses.Add(j == index); + } + lastIndex = index + 1; + } + + RINOK(extractCallback->SetTotal(importantTotalUnPacked)); + UInt64 currentImportantTotalUnPacked = 0; + UInt64 currentImportantTotalPacked = 0; + UInt64 currentUnPackSize, currentPackSize; + + CObjectVector methodItems; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; + CMyComPtr copyCoder = copyCoderSpec; + + CFilterCoder *filterStreamSpec = new CFilterCoder; + CMyComPtr filterStream = filterStreamSpec; + + NCrypto::NRar20::CDecoder *rar20CryptoDecoderSpec = NULL; + CMyComPtr rar20CryptoDecoder; + NCrypto::NRar29::CDecoder *rar29CryptoDecoderSpec = NULL; + CMyComPtr rar29CryptoDecoder; + + CFolderInStream *folderInStreamSpec = NULL; + CMyComPtr folderInStream; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + bool solidStart = true; + for (int i = 0; i < importantIndexes.Size(); i++, + currentImportantTotalUnPacked += currentUnPackSize, + currentImportantTotalPacked += currentPackSize) + { + lps->InSize = currentImportantTotalPacked; + lps->OutSize = currentImportantTotalUnPacked; + RINOK(lps->SetCur()); + CMyComPtr realOutStream; + + Int32 askMode; + if (extractStatuses[i]) + askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + else + askMode = NExtract::NAskMode::kSkip; + + UInt32 index = importantIndexes[i]; + + const CRefItem &refItem = _refItems[index]; + const CItemEx &item = _items[refItem.ItemIndex]; + + currentUnPackSize = item.Size; + + currentPackSize = GetPackSize(index); + + if (item.IgnoreItem()) + continue; + + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + if (!IsSolid(index)) + solidStart = true; + if (item.IsDir()) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + + bool mustBeProcessedAnywhere = false; + if (i < importantIndexes.Size() - 1) + { + // const CRefItem &nextRefItem = _refItems[importantIndexes[i + 1]]; + // const CItemEx &nextItemInfo = _items[nextRefItem.ItemIndex]; + // mustBeProcessedAnywhere = nextItemInfo.IsSolid(); + mustBeProcessedAnywhere = IsSolid(importantIndexes[i + 1]); + } + + if (!mustBeProcessedAnywhere && !testMode && !realOutStream) + continue; + + if (!realOutStream && !testMode) + askMode = NExtract::NAskMode::kSkip; + + RINOK(extractCallback->PrepareOperation(askMode)); + + COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; + CMyComPtr outStream(outStreamSpec); + outStreamSpec->SetStream(realOutStream); + outStreamSpec->Init(); + realOutStream.Release(); + + /* + for (int partIndex = 0; partIndex < 1; partIndex++) + { + CMyComPtr inStream; + + // item redefinition + const CItemEx &item = _items[refItem.ItemIndex + partIndex]; + + NArchive::NRar::CInArchive &archive = _archives[refItem.VolumeIndex + partIndex]; + + inStream.Attach(archive.CreateLimitedStream(item.GetDataPosition(), + item.PackSize)); + */ + if (!folderInStream) + { + folderInStreamSpec = new CFolderInStream; + folderInStream = folderInStreamSpec; + } + + folderInStreamSpec->Init(&_archives, &_items, refItem); + + UInt64 packSize = currentPackSize; + + // packedPos += item.PackSize; + // unpackedPos += 0; + + CMyComPtr inStream; + if (item.IsEncrypted()) + { + CMyComPtr cryptoSetPassword; + if (item.UnPackVersion >= 29) + { + if (!rar29CryptoDecoder) + { + rar29CryptoDecoderSpec = new NCrypto::NRar29::CDecoder; + rar29CryptoDecoder = rar29CryptoDecoderSpec; + // RINOK(rar29CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar29Decoder)); + } + rar29CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36); + CMyComPtr cryptoProperties; + RINOK(rar29CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, + &cryptoProperties)); + RINOK(cryptoProperties->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0)); + filterStreamSpec->Filter = rar29CryptoDecoder; + } + else if (item.UnPackVersion >= 20) + { + if (!rar20CryptoDecoder) + { + rar20CryptoDecoderSpec = new NCrypto::NRar20::CDecoder; + rar20CryptoDecoder = rar20CryptoDecoderSpec; + // RINOK(rar20CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar20Decoder)); + } + filterStreamSpec->Filter = rar20CryptoDecoder; + } + else + { + outStream.Release(); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod)); + continue; + } + RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, + &cryptoSetPassword)); + + if (!getTextPassword) + extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword); + if (getTextPassword) + { + CMyComBSTR password; + RINOK(getTextPassword->CryptoGetTextPassword(&password)); + if (item.UnPackVersion >= 29) + { + CByteBuffer buffer; + UString unicodePassword(password); + const UInt32 sizeInBytes = unicodePassword.Length() * 2; + buffer.SetCapacity(sizeInBytes); + for (int i = 0; i < unicodePassword.Length(); i++) + { + wchar_t c = unicodePassword[i]; + ((Byte *)buffer)[i * 2] = (Byte)c; + ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); + } + RINOK(cryptoSetPassword->CryptoSetPassword( + (const Byte *)buffer, sizeInBytes)); + } + else + { + AString oemPassword = UnicodeStringToMultiByte( + (const wchar_t *)password, CP_OEMCP); + RINOK(cryptoSetPassword->CryptoSetPassword( + (const Byte *)(const char *)oemPassword, oemPassword.Length())); + } + } + else + { + RINOK(cryptoSetPassword->CryptoSetPassword(0, 0)); + } + filterStreamSpec->SetInStream(folderInStream); + inStream = filterStream; + } + else + { + inStream = folderInStream; + } + CMyComPtr commonCoder; + switch(item.Method) + { + case '0': + { + commonCoder = copyCoder; + break; + } + case '1': + case '2': + case '3': + case '4': + case '5': + { + /* + if (item.UnPackVersion >= 29) + { + outStream.Release(); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod)); + continue; + } + */ + int m; + for (m = 0; m < methodItems.Size(); m++) + if (methodItems[m].RarUnPackVersion == item.UnPackVersion) + break; + if (m == methodItems.Size()) + { + CMethodItem mi; + mi.RarUnPackVersion = item.UnPackVersion; + + mi.Coder.Release(); + if (item.UnPackVersion <= 30) + { + UInt32 methodID = 0x040300; + if (item.UnPackVersion < 20) + methodID += 1; + else if (item.UnPackVersion < 29) + methodID += 2; + else + methodID += 3; + RINOK(CreateCoder(EXTERNAL_CODECS_VARS methodID, mi.Coder, false)); + } + + if (mi.Coder == 0) + { + outStream.Release(); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod)); + continue; + } + + m = methodItems.Add(mi); + } + CMyComPtr decoder = methodItems[m].Coder; + + CMyComPtr compressSetDecoderProperties; + RINOK(decoder.QueryInterface(IID_ICompressSetDecoderProperties2, + &compressSetDecoderProperties)); + + Byte isSolid = (Byte)((IsSolid(index) || item.IsSplitBefore()) ? 1: 0); + if (solidStart) + { + isSolid = false; + solidStart = false; + } + + + RINOK(compressSetDecoderProperties->SetDecoderProperties2(&isSolid, 1)); + + commonCoder = decoder; + break; + } + default: + outStream.Release(); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod)); + continue; + } + HRESULT result = commonCoder->Code(inStream, outStream, &packSize, &item.Size, progress); + if (item.IsEncrypted()) + filterStreamSpec->ReleaseInStream(); + if (result == S_FALSE) + { + outStream.Release(); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kDataError)); + continue; + } + if (result != S_OK) + return result; + + /* + if (refItem.NumItems == 1 && + !item.IsSplitBefore() && !item.IsSplitAfter()) + */ + { + const CItemEx &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1]; + bool crcOK = outStreamSpec->GetCRC() == lastItem.FileCRC; + outStream.Release(); + RINOK(extractCallback->SetOperationResult(crcOK ? + NExtract::NOperationResult::kOK: + NExtract::NOperationResult::kCRCError)); + } + /* + else + { + bool crcOK = true; + for (int partIndex = 0; partIndex < refItem.NumItems; partIndex++) + { + const CItemEx &item = _items[refItem.ItemIndex + partIndex]; + if (item.FileCRC != folderInStreamSpec->CRCs[partIndex]) + { + crcOK = false; + break; + } + } + RINOK(extractCallback->SetOperationResult(crcOK ? + NExtract::NOperationResult::kOK: + NExtract::NOperationResult::kCRCError)); + } + */ + } + return S_OK; + COM_TRY_END +} + +IMPL_ISetCompressCodecsInfo + +}} diff --git a/CPP/7zip/Archive/Rar/RarHandler.h b/CPP/7zip/Archive/Rar/RarHandler.h new file mode 100755 index 0000000..3d43874 --- /dev/null +++ b/CPP/7zip/Archive/Rar/RarHandler.h @@ -0,0 +1,66 @@ +// Rar/Handler.h + +#ifndef __RAR_HANDLER_H +#define __RAR_HANDLER_H + +#include "../IArchive.h" + +#include "../../Common/CreateCoder.h" + +#include "RarIn.h" +#include "RarVolumeInStream.h" + +namespace NArchive { +namespace NRar { + +class CHandler: + public IInArchive, + PUBLIC_ISetCompressCodecsInfo + public CMyUnknownImp +{ + CRecordVector _refItems; + CObjectVector _items; + CObjectVector _archives; + NArchive::NRar::CInArchiveInfo _archiveInfo; + AString _errorMessage; + + DECL_EXTERNAL_CODECS_VARS + + UInt64 GetPackSize(int refIndex) const; + + bool IsSolid(int refIndex) + { + const CItemEx &item = _items[_refItems[refIndex].ItemIndex]; + if (item.UnPackVersion < 20) + { + if (_archiveInfo.IsSolid()) + return (refIndex > 0); + return false; + } + return item.IsSolid(); + } + void AddErrorMessage(const AString &s) + { + if (!_errorMessage.IsEmpty()) + _errorMessage += '\n'; + _errorMessage += s; + } + + HRESULT Open2(IInStream *stream, + const UInt64 *maxCheckStartPosition, + IArchiveOpenCallback *openCallback); + +public: + MY_QUERYINTERFACE_BEGIN2(IInArchive) + QUERY_ENTRY_ISetCompressCodecsInfo + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + INTERFACE_IInArchive(;) + + DECL_ISetCompressCodecsInfo +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Rar/RarHeader.cpp b/CPP/7zip/Archive/Rar/RarHeader.cpp new file mode 100755 index 0000000..7c34875 --- /dev/null +++ b/CPP/7zip/Archive/Rar/RarHeader.cpp @@ -0,0 +1,21 @@ +// Archive/Rar/Headers.cpp + +#include "StdAfx.h" + +#include "RarHeader.h" + +namespace NArchive{ +namespace NRar{ +namespace NHeader{ + +Byte kMarker[kMarkerSize] = {0x52 + 1, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00}; + +class CMarkerInitializer +{ +public: + CMarkerInitializer() { kMarker[0]--; }; +}; + +static CMarkerInitializer markerInitializer; + +}}} diff --git a/CPP/7zip/Archive/Rar/RarHeader.h b/CPP/7zip/Archive/Rar/RarHeader.h new file mode 100755 index 0000000..6624d84 --- /dev/null +++ b/CPP/7zip/Archive/Rar/RarHeader.h @@ -0,0 +1,205 @@ +// Archive/RarHeader.h + +#ifndef __ARCHIVE_RAR_HEADER_H +#define __ARCHIVE_RAR_HEADER_H + +#include "Common/Types.h" + +namespace NArchive { +namespace NRar { +namespace NHeader { + +const int kMarkerSize = 7; +extern Byte kMarker[kMarkerSize]; + +const int kArchiveSolid = 0x1; + +namespace NBlockType +{ + enum EBlockType + { + kMarker = 0x72, + kArchiveHeader, + kFileHeader, + kCommentHeader, + kOldAuthenticity, + kOldSubBlock, + kRecoveryRecord, + kAuthenticity, + kSubBlock, + kEndOfArchive + }; +} + +namespace NArchive +{ + const UInt16 kVolume = 1; + const UInt16 kComment = 2; + const UInt16 kLock = 4; + const UInt16 kSolid = 8; + const UInt16 kNewVolName = 0x10; // ('volname.partN.rar') + const UInt16 kAuthenticity = 0x20; + const UInt16 kRecovery = 0x40; + const UInt16 kBlockEncryption = 0x80; + const UInt16 kFirstVolume = 0x100; // (set only by RAR 3.0 and later) + const UInt16 kEncryptVer = 0x200; // RAR 3.6 there is EncryptVer Byte in End of MainHeader + + const int kHeaderSizeMin = 7; + + const int kArchiveHeaderSize = 13; + + const int kBlockHeadersAreEncrypted = 0x80; + +} + +namespace NFile +{ + const int kSplitBefore = 1 << 0; + const int kSplitAfter = 1 << 1; + const int kEncrypted = 1 << 2; + const int kComment = 1 << 3; + const int kSolid = 1 << 4; + + const int kDictBitStart = 5; + const int kNumDictBits = 3; + const int kDictMask = (1 << kNumDictBits) - 1; + const int kDictDirectoryValue = 0x7; + + const int kSize64Bits = 1 << 8; + const int kUnicodeName = 1 << 9; + const int kSalt = 1 << 10; + const int kOldVersion = 1 << 11; + const int kExtTime = 1 << 12; + // const int kExtFlags = 1 << 13; + // const int kSkipIfUnknown = 1 << 14; + + const int kLongBlock = 1 << 15; + + /* + struct CBlock + { + // UInt16 HeadCRC; + // Byte Type; + // UInt16 Flags; + // UInt16 HeadSize; + UInt32 PackSize; + UInt32 UnPackSize; + Byte HostOS; + UInt32 FileCRC; + UInt32 Time; + Byte UnPackVersion; + Byte Method; + UInt16 NameSize; + UInt32 Attributes; + }; + */ + + /* + struct CBlock32 + { + UInt16 HeadCRC; + Byte Type; + UInt16 Flags; + UInt16 HeadSize; + UInt32 PackSize; + UInt32 UnPackSize; + Byte HostOS; + UInt32 FileCRC; + UInt32 Time; + Byte UnPackVersion; + Byte Method; + UInt16 NameSize; + UInt32 Attributes; + UInt16 GetRealCRC(const void *aName, UInt32 aNameSize, + bool anExtraDataDefined = false, Byte *anExtraData = 0) const; + }; + struct CBlock64 + { + UInt16 HeadCRC; + Byte Type; + UInt16 Flags; + UInt16 HeadSize; + UInt32 PackSizeLow; + UInt32 UnPackSizeLow; + Byte HostOS; + UInt32 FileCRC; + UInt32 Time; + Byte UnPackVersion; + Byte Method; + UInt16 NameSize; + UInt32 Attributes; + UInt32 PackSizeHigh; + UInt32 UnPackSizeHigh; + UInt16 GetRealCRC(const void *aName, UInt32 aNameSize) const; + }; + */ + + const int kLabelFileAttribute = 0x08; + const int kWinFileDirectoryAttributeMask = 0x10; + + enum CHostOS + { + kHostMSDOS = 0, + kHostOS2 = 1, + kHostWin32 = 2, + kHostUnix = 3, + kHostMacOS = 4, + kHostBeOS = 5 + }; +} + +namespace NBlock +{ + const UInt16 kLongBlock = 1 << 15; + struct CBlock + { + UInt16 CRC; + Byte Type; + UInt16 Flags; + UInt16 HeadSize; + // UInt32 DataSize; + }; +} + +/* +struct CSubBlock +{ + UInt16 HeadCRC; + Byte HeadType; + UInt16 Flags; + UInt16 HeadSize; + UInt32 DataSize; + UInt16 SubType; + Byte Level; // Reserved : Must be 0 +}; + +struct CCommentBlock +{ + UInt16 HeadCRC; + Byte HeadType; + UInt16 Flags; + UInt16 HeadSize; + UInt16 UnpSize; + Byte UnpVer; + Byte Method; + UInt16 CommCRC; +}; + + +struct CProtectHeader +{ + UInt16 HeadCRC; + Byte HeadType; + UInt16 Flags; + UInt16 HeadSize; + UInt32 DataSize; + Byte Version; + UInt16 RecSectors; + UInt32 TotalBlocks; + Byte Mark[8]; +}; +*/ + +}}} + +#endif diff --git a/CPP/7zip/Archive/Rar/RarIn.cpp b/CPP/7zip/Archive/Rar/RarIn.cpp new file mode 100755 index 0000000..c277fe2 --- /dev/null +++ b/CPP/7zip/Archive/Rar/RarIn.cpp @@ -0,0 +1,478 @@ +// Archive/RarIn.cpp + +#include "StdAfx.h" + +#include "../../../../C/7zCrc.h" +#include "../../../../C/CpuArch.h" + +#include "Common/StringConvert.h" +#include "Common/UTFConvert.h" + +#include "../../Common/LimitedStreams.h" +#include "../../Common/StreamUtils.h" + +#include "../Common/FindSignature.h" + +#include "RarIn.h" + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) +#define Get64(p) GetUi64(p) + +namespace NArchive { +namespace NRar { + +static const char *k_UnexpectedEnd = "Unexpected end of archive"; +static const char *k_DecryptionError = "Decryption Error"; + +void CInArchive::ThrowExceptionWithCode( + CInArchiveException::CCauseType cause) +{ + throw CInArchiveException(cause); +} + +HRESULT CInArchive::Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit) +{ + try + { + Close(); + HRESULT res = Open2(inStream, searchHeaderSizeLimit); + if (res == S_OK) + return res; + Close(); + return res; + } + catch(...) { Close(); throw; } +} + +void CInArchive::Close() +{ + m_Stream.Release(); +} + +HRESULT CInArchive::ReadBytesSpec(void *data, size_t *resSize) +{ + if (m_CryptoMode) + { + size_t size = *resSize; + *resSize = 0; + const Byte *bufData = m_DecryptedDataAligned; + UInt32 bufSize = m_DecryptedDataSize; + size_t i; + for (i = 0; i < size && m_CryptoPos < bufSize; i++) + ((Byte *)data)[i] = bufData[m_CryptoPos++]; + *resSize = i; + return S_OK; + } + return ReadStream(m_Stream, data, resSize); +} + +bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size) +{ + size_t processed = size; + if (ReadBytesSpec(data, &processed) != S_OK) + return false; + return processed == size; +} + +HRESULT CInArchive::Open2(IInStream *stream, const UInt64 *searchHeaderSizeLimit) +{ + m_CryptoMode = false; + RINOK(stream->Seek(0, STREAM_SEEK_SET, &m_StreamStartPosition)); + m_Position = m_StreamStartPosition; + + UInt64 arcStartPos; + RINOK(FindSignatureInStream(stream, NHeader::kMarker, NHeader::kMarkerSize, + searchHeaderSizeLimit, arcStartPos)); + m_Position = arcStartPos + NHeader::kMarkerSize; + RINOK(stream->Seek(m_Position, STREAM_SEEK_SET, NULL)); + Byte buf[NHeader::NArchive::kArchiveHeaderSize + 1]; + + RINOK(ReadStream_FALSE(stream, buf, NHeader::NArchive::kArchiveHeaderSize)); + AddToSeekValue(NHeader::NArchive::kArchiveHeaderSize); + + + UInt32 blockSize = Get16(buf + 5); + + _header.EncryptVersion = 0; + _header.Flags = Get16(buf + 3); + + UInt32 headerSize = NHeader::NArchive::kArchiveHeaderSize; + if (_header.IsThereEncryptVer()) + { + if (blockSize <= headerSize) + return S_FALSE; + RINOK(ReadStream_FALSE(stream, buf + NHeader::NArchive::kArchiveHeaderSize, 1)); + AddToSeekValue(1); + _header.EncryptVersion = buf[NHeader::NArchive::kArchiveHeaderSize]; + headerSize += 1; + } + if (blockSize < headerSize || + buf[2] != NHeader::NBlockType::kArchiveHeader || + (UInt32)Get16(buf) != (CrcCalc(buf + 2, headerSize - 2) & 0xFFFF)) + return S_FALSE; + + size_t commentSize = blockSize - headerSize; + _comment.SetCapacity(commentSize); + RINOK(ReadStream_FALSE(stream, _comment, commentSize)); + AddToSeekValue(commentSize); + m_Stream = stream; + _header.StartPosition = arcStartPos; + return S_OK; +} + +void CInArchive::GetArchiveInfo(CInArchiveInfo &archiveInfo) const +{ + archiveInfo = _header; +} + +static void DecodeUnicodeFileName(const char *name, const Byte *encName, + int encSize, wchar_t *unicodeName, int maxDecSize) +{ + int encPos = 0; + int decPos = 0; + int flagBits = 0; + Byte flags = 0; + Byte highByte = encName[encPos++]; + while (encPos < encSize && decPos < maxDecSize) + { + if (flagBits == 0) + { + flags = encName[encPos++]; + flagBits = 8; + } + switch(flags >> 6) + { + case 0: + unicodeName[decPos++] = encName[encPos++]; + break; + case 1: + unicodeName[decPos++] = (wchar_t)(encName[encPos++] + (highByte << 8)); + break; + case 2: + unicodeName[decPos++] = (wchar_t)(encName[encPos] + (encName[encPos + 1] << 8)); + encPos += 2; + break; + case 3: + { + int length = encName[encPos++]; + if (length & 0x80) + { + Byte correction = encName[encPos++]; + for (length = (length & 0x7f) + 2; + length > 0 && decPos < maxDecSize; length--, decPos++) + unicodeName[decPos] = (wchar_t)(((name[decPos] + correction) & 0xff) + (highByte << 8)); + } + else + for (length += 2; length > 0 && decPos < maxDecSize; length--, decPos++) + unicodeName[decPos] = name[decPos]; + } + break; + } + flags <<= 2; + flagBits -= 2; + } + unicodeName[decPos < maxDecSize ? decPos : maxDecSize - 1] = 0; +} + +void CInArchive::ReadName(CItemEx &item, int nameSize) +{ + item.UnicodeName.Empty(); + if (nameSize > 0) + { + m_NameBuffer.EnsureCapacity(nameSize + 1); + char *buffer = (char *)m_NameBuffer; + + for (int i = 0; i < nameSize; i++) + buffer[i] = ReadByte(); + + int mainLen; + for (mainLen = 0; mainLen < nameSize; mainLen++) + if (buffer[mainLen] == '\0') + break; + buffer[mainLen] = '\0'; + item.Name = buffer; + + if(item.HasUnicodeName()) + { + if(mainLen < nameSize) + { + int unicodeNameSizeMax = MyMin(nameSize, (0x400)); + _unicodeNameBuffer.EnsureCapacity(unicodeNameSizeMax + 1); + DecodeUnicodeFileName(buffer, (const Byte *)buffer + mainLen + 1, + nameSize - (mainLen + 1), _unicodeNameBuffer, unicodeNameSizeMax); + item.UnicodeName = _unicodeNameBuffer; + } + else if (!ConvertUTF8ToUnicode(item.Name, item.UnicodeName)) + item.UnicodeName.Empty(); + } + } + else + item.Name.Empty(); +} + +Byte CInArchive::ReadByte() +{ + if (m_CurPos >= m_PosLimit) + throw CInArchiveException(CInArchiveException::kIncorrectArchive); + return m_CurData[m_CurPos++]; +} + +UInt16 CInArchive::ReadUInt16() +{ + UInt16 value = 0; + for (int i = 0; i < 2; i++) + { + Byte b = ReadByte(); + value |= (UInt16(b) << (8 * i)); + } + return value; +} + +UInt32 CInArchive::ReadUInt32() +{ + UInt32 value = 0; + for (int i = 0; i < 4; i++) + { + Byte b = ReadByte(); + value |= (UInt32(b) << (8 * i)); + } + return value; +} + +void CInArchive::ReadTime(Byte mask, CRarTime &rarTime) +{ + rarTime.LowSecond = (Byte)(((mask & 4) != 0) ? 1 : 0); + int numDigits = (mask & 3); + rarTime.SubTime[0] = rarTime.SubTime[1] = rarTime.SubTime[2] = 0; + for (int i = 0; i < numDigits; i++) + rarTime.SubTime[3 - numDigits + i] = ReadByte(); +} + +void CInArchive::ReadHeaderReal(CItemEx &item) +{ + item.Flags = m_BlockHeader.Flags; + item.PackSize = ReadUInt32(); + item.Size = ReadUInt32(); + item.HostOS = ReadByte(); + item.FileCRC = ReadUInt32(); + item.MTime.DosTime = ReadUInt32(); + item.UnPackVersion = ReadByte(); + item.Method = ReadByte(); + int nameSize = ReadUInt16(); + item.Attrib = ReadUInt32(); + + item.MTime.LowSecond = 0; + item.MTime.SubTime[0] = + item.MTime.SubTime[1] = + item.MTime.SubTime[2] = 0; + + if((item.Flags & NHeader::NFile::kSize64Bits) != 0) + { + item.PackSize |= ((UInt64)ReadUInt32() << 32); + item.Size |= ((UInt64)ReadUInt32() << 32); + } + + ReadName(item, nameSize); + + if (item.HasSalt()) + for (int i = 0; i < sizeof(item.Salt); i++) + item.Salt[i] = ReadByte(); + + // some rar archives have HasExtTime flag without field. + if (m_CurPos < m_PosLimit && item.HasExtTime()) + { + Byte accessMask = (Byte)(ReadByte() >> 4); + Byte b = ReadByte(); + Byte modifMask = (Byte)(b >> 4); + Byte createMask = (Byte)(b & 0xF); + if ((modifMask & 8) != 0) + ReadTime(modifMask, item.MTime); + item.CTimeDefined = ((createMask & 8) != 0); + if (item.CTimeDefined) + { + item.CTime.DosTime = ReadUInt32(); + ReadTime(createMask, item.CTime); + } + item.ATimeDefined = ((accessMask & 8) != 0); + if (item.ATimeDefined) + { + item.ATime.DosTime = ReadUInt32(); + ReadTime(accessMask, item.ATime); + } + } + + UInt16 fileHeaderWithNameSize = (UInt16)m_CurPos; + + item.Position = m_Position; + item.MainPartSize = fileHeaderWithNameSize; + item.CommentSize = (UInt16)(m_BlockHeader.HeadSize - fileHeaderWithNameSize); + + if (m_CryptoMode) + item.AlignSize = (UInt16)((16 - ((m_BlockHeader.HeadSize) & 0xF)) & 0xF); + else + item.AlignSize = 0; + AddToSeekValue(m_BlockHeader.HeadSize); +} + +void CInArchive::AddToSeekValue(UInt64 addValue) +{ + m_Position += addValue; +} + +HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError, AString &errorMessage) +{ + decryptionError = false; + for (;;) + { + SeekInArchive(m_Position); + if (!m_CryptoMode && (_header.Flags & + NHeader::NArchive::kBlockHeadersAreEncrypted) != 0) + { + m_CryptoMode = false; + if (getTextPassword == 0) + return S_FALSE; + if (!m_RarAES) + { + m_RarAESSpec = new NCrypto::NRar29::CDecoder; + m_RarAES = m_RarAESSpec; + } + m_RarAESSpec->SetRar350Mode(_header.IsEncryptOld()); + + // Salt + const UInt32 kSaltSize = 8; + Byte salt[kSaltSize]; + if(!ReadBytesAndTestSize(salt, kSaltSize)) + return S_FALSE; + m_Position += kSaltSize; + RINOK(m_RarAESSpec->SetDecoderProperties2(salt, kSaltSize)) + // Password + CMyComBSTR password; + RINOK(getTextPassword->CryptoGetTextPassword(&password)) + UString unicodePassword(password); + + CByteBuffer buffer; + const UInt32 sizeInBytes = unicodePassword.Length() * 2; + buffer.SetCapacity(sizeInBytes); + for (int i = 0; i < unicodePassword.Length(); i++) + { + wchar_t c = unicodePassword[i]; + ((Byte *)buffer)[i * 2] = (Byte)c; + ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); + } + + RINOK(m_RarAESSpec->CryptoSetPassword((const Byte *)buffer, sizeInBytes)); + + const UInt32 kDecryptedBufferSize = (1 << 12); + if (m_DecryptedData.GetCapacity() == 0) + { + const UInt32 kAlign = 16; + m_DecryptedData.SetCapacity(kDecryptedBufferSize + kAlign); + m_DecryptedDataAligned = (Byte *)((ptrdiff_t)((Byte *)m_DecryptedData + kAlign - 1) & ~(ptrdiff_t)(kAlign - 1)); + } + RINOK(m_RarAES->Init()); + size_t decryptedDataSizeT = kDecryptedBufferSize; + RINOK(ReadStream(m_Stream, m_DecryptedDataAligned, &decryptedDataSizeT)); + m_DecryptedDataSize = (UInt32)decryptedDataSizeT; + m_DecryptedDataSize = m_RarAES->Filter(m_DecryptedDataAligned, m_DecryptedDataSize); + + m_CryptoMode = true; + m_CryptoPos = 0; + } + + m_FileHeaderData.EnsureCapacity(7); + size_t processed = 7; + RINOK(ReadBytesSpec((Byte *)m_FileHeaderData, &processed)); + if (processed != 7) + { + if (processed != 0) + errorMessage = k_UnexpectedEnd; + return S_FALSE; + } + + m_CurData = (Byte *)m_FileHeaderData; + m_CurPos = 0; + m_PosLimit = 7; + m_BlockHeader.CRC = ReadUInt16(); + m_BlockHeader.Type = ReadByte(); + m_BlockHeader.Flags = ReadUInt16(); + m_BlockHeader.HeadSize = ReadUInt16(); + + if (m_BlockHeader.HeadSize < 7) + ThrowExceptionWithCode(CInArchiveException::kIncorrectArchive); + + if (m_BlockHeader.Type == NHeader::NBlockType::kEndOfArchive) + return S_FALSE; + + if (m_BlockHeader.Type == NHeader::NBlockType::kFileHeader) + { + m_FileHeaderData.EnsureCapacity(m_BlockHeader.HeadSize); + m_CurData = (Byte *)m_FileHeaderData; + m_PosLimit = m_BlockHeader.HeadSize; + if (!ReadBytesAndTestSize(m_CurData + m_CurPos, m_BlockHeader.HeadSize - 7)) + { + errorMessage = k_UnexpectedEnd; + return S_FALSE; + } + + ReadHeaderReal(item); + if ((CrcCalc(m_CurData + 2, + m_BlockHeader.HeadSize - item.CommentSize - 2) & 0xFFFF) != m_BlockHeader.CRC) + ThrowExceptionWithCode(CInArchiveException::kFileHeaderCRCError); + + FinishCryptoBlock(); + m_CryptoMode = false; + SeekInArchive(m_Position); // Move Position to compressed Data; + AddToSeekValue(item.PackSize); // m_Position points to next header; + return S_OK; + } + if (m_CryptoMode && m_BlockHeader.HeadSize > (1 << 10)) + { + decryptionError = true; + errorMessage = k_DecryptionError; + return S_FALSE; + } + if ((m_BlockHeader.Flags & NHeader::NBlock::kLongBlock) != 0) + { + m_FileHeaderData.EnsureCapacity(7 + 4); + m_CurData = (Byte *)m_FileHeaderData; + if (!ReadBytesAndTestSize(m_CurData + m_CurPos, 4)) + { + errorMessage = k_UnexpectedEnd; + return S_FALSE; + } + m_PosLimit = 7 + 4; + UInt32 dataSize = ReadUInt32(); + AddToSeekValue(dataSize); + if (m_CryptoMode && dataSize > (1 << 27)) + { + decryptionError = true; + errorMessage = k_DecryptionError; + return S_FALSE; + } + m_CryptoPos = m_BlockHeader.HeadSize; + } + else + m_CryptoPos = 0; + AddToSeekValue(m_BlockHeader.HeadSize); + FinishCryptoBlock(); + m_CryptoMode = false; + } +} + +void CInArchive::SeekInArchive(UInt64 position) +{ + m_Stream->Seek(position, STREAM_SEEK_SET, NULL); +} + +ISequentialInStream* CInArchive::CreateLimitedStream(UInt64 position, UInt64 size) +{ + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStream(streamSpec); + SeekInArchive(position); + streamSpec->SetStream(m_Stream); + streamSpec->Init(size); + return inStream.Detach(); +} + +}} diff --git a/CPP/7zip/Archive/Rar/RarIn.h b/CPP/7zip/Archive/Rar/RarIn.h new file mode 100755 index 0000000..4ab3269 --- /dev/null +++ b/CPP/7zip/Archive/Rar/RarIn.h @@ -0,0 +1,123 @@ +// RarIn.h + +#ifndef __ARCHIVE_RAR_IN_H +#define __ARCHIVE_RAR_IN_H + +#include "Common/DynamicBuffer.h" +#include "Common/MyCom.h" + +#include "../../ICoder.h" +#include "../../IStream.h" + +#include "../../Common/StreamObjects.h" + +#include "../../Crypto/RarAes.h" + +#include "RarHeader.h" +#include "RarItem.h" + +namespace NArchive { +namespace NRar { + +class CInArchiveException +{ +public: + enum CCauseType + { + kUnexpectedEndOfArchive = 0, + kArchiveHeaderCRCError, + kFileHeaderCRCError, + kIncorrectArchive + } + Cause; + CInArchiveException(CCauseType cause) : Cause(cause) {} +}; + + +struct CInArchiveInfo +{ + UInt32 Flags; + Byte EncryptVersion; + UInt64 StartPosition; + + bool IsSolid() const { return (Flags & NHeader::NArchive::kSolid) != 0; } + bool IsCommented() const { return (Flags & NHeader::NArchive::kComment) != 0; } + bool IsVolume() const { return (Flags & NHeader::NArchive::kVolume) != 0; } + bool HaveNewVolumeName() const { return (Flags & NHeader::NArchive::kNewVolName) != 0; } + bool IsEncrypted() const { return (Flags & NHeader::NArchive::kBlockEncryption) != 0; } + bool IsThereEncryptVer() const { return (Flags & NHeader::NArchive::kEncryptVer) != 0; } + bool IsEncryptOld() const { return (!IsThereEncryptVer() || EncryptVersion < 36); } +}; + +class CInArchive +{ + CMyComPtr m_Stream; + + UInt64 m_StreamStartPosition; + + CInArchiveInfo _header; + CDynamicBuffer m_NameBuffer; + CDynamicBuffer _unicodeNameBuffer; + + CByteBuffer _comment; + + void ReadName(CItemEx &item, int nameSize); + void ReadHeaderReal(CItemEx &item); + + HRESULT ReadBytesSpec(void *data, size_t *size); + bool ReadBytesAndTestSize(void *data, UInt32 size); + + HRESULT Open2(IInStream *stream, const UInt64 *searchHeaderSizeLimit); + + void ThrowExceptionWithCode(CInArchiveException::CCauseType cause); + void ThrowUnexpectedEndOfArchiveException(); + + void AddToSeekValue(UInt64 addValue); + + CDynamicBuffer m_FileHeaderData; + + NHeader::NBlock::CBlock m_BlockHeader; + + NCrypto::NRar29::CDecoder *m_RarAESSpec; + CMyComPtr m_RarAES; + + Byte *m_CurData; // it must point to start of Rar::Block + UInt32 m_CurPos; + UInt32 m_PosLimit; + Byte ReadByte(); + UInt16 ReadUInt16(); + UInt32 ReadUInt32(); + void ReadTime(Byte mask, CRarTime &rarTime); + + CBuffer m_DecryptedData; + Byte *m_DecryptedDataAligned; + UInt32 m_DecryptedDataSize; + + bool m_CryptoMode; + UInt32 m_CryptoPos; + void FinishCryptoBlock() + { + if (m_CryptoMode) + while ((m_CryptoPos & 0xF) != 0) + { + m_CryptoPos++; + m_Position++; + } + } + +public: + UInt64 m_Position; + + HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit); + void Close(); + HRESULT GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError, AString &errorMessage); + + void GetArchiveInfo(CInArchiveInfo &archiveInfo) const; + + void SeekInArchive(UInt64 position); + ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Rar/RarItem.cpp b/CPP/7zip/Archive/Rar/RarItem.cpp new file mode 100755 index 0000000..b096377 --- /dev/null +++ b/CPP/7zip/Archive/Rar/RarItem.cpp @@ -0,0 +1,55 @@ +// RarItem.cpp + +#include "StdAfx.h" + +#include "RarItem.h" + +namespace NArchive{ +namespace NRar{ + +bool CItem::IgnoreItem() const +{ + switch(HostOS) + { + case NHeader::NFile::kHostMSDOS: + case NHeader::NFile::kHostOS2: + case NHeader::NFile::kHostWin32: + return ((Attrib & NHeader::NFile::kLabelFileAttribute) != 0); + } + return false; +} + +bool CItem::IsDir() const +{ + if (GetDictSize() == NHeader::NFile::kDictDirectoryValue) + return true; + switch(HostOS) + { + case NHeader::NFile::kHostMSDOS: + case NHeader::NFile::kHostOS2: + case NHeader::NFile::kHostWin32: + if ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0) + return true; + } + return false; +} + +UInt32 CItem::GetWinAttributes() const +{ + UInt32 winAttributes; + switch(HostOS) + { + case NHeader::NFile::kHostMSDOS: + case NHeader::NFile::kHostOS2: + case NHeader::NFile::kHostWin32: + winAttributes = Attrib; + break; + default: + winAttributes = 0; // must be converted from unix value; + } + if (IsDir()) + winAttributes |= NHeader::NFile::kWinFileDirectoryAttributeMask; + return winAttributes; +} + +}} diff --git a/CPP/7zip/Archive/Rar/RarItem.h b/CPP/7zip/Archive/Rar/RarItem.h new file mode 100755 index 0000000..515ecd4 --- /dev/null +++ b/CPP/7zip/Archive/Rar/RarItem.h @@ -0,0 +1,79 @@ +// RarItem.h + +#ifndef __ARCHIVE_RAR_ITEM_H +#define __ARCHIVE_RAR_ITEM_H + +#include "Common/Types.h" +#include "Common/MyString.h" + +#include "RarHeader.h" + +namespace NArchive{ +namespace NRar{ + +struct CRarTime +{ + UInt32 DosTime; + Byte LowSecond; + Byte SubTime[3]; +}; + +struct CItem +{ + UInt64 Size; + UInt64 PackSize; + + CRarTime CTime; + CRarTime ATime; + CRarTime MTime; + + UInt32 FileCRC; + UInt32 Attrib; + + UInt16 Flags; + Byte HostOS; + Byte UnPackVersion; + Byte Method; + + bool CTimeDefined; + bool ATimeDefined; + + AString Name; + UString UnicodeName; + + Byte Salt[8]; + + bool IsEncrypted() const { return (Flags & NHeader::NFile::kEncrypted) != 0; } + bool IsSolid() const { return (Flags & NHeader::NFile::kSolid) != 0; } + bool IsCommented() const { return (Flags & NHeader::NFile::kComment) != 0; } + bool IsSplitBefore() const { return (Flags & NHeader::NFile::kSplitBefore) != 0; } + bool IsSplitAfter() const { return (Flags & NHeader::NFile::kSplitAfter) != 0; } + bool HasSalt() const { return (Flags & NHeader::NFile::kSalt) != 0; } + bool HasExtTime() const { return (Flags & NHeader::NFile::kExtTime) != 0; } + bool HasUnicodeName()const { return (Flags & NHeader::NFile::kUnicodeName) != 0; } + bool IsOldVersion() const { return (Flags & NHeader::NFile::kOldVersion) != 0; } + + UInt32 GetDictSize() const { return (Flags >> NHeader::NFile::kDictBitStart) & NHeader::NFile::kDictMask; } + bool IsDir() const; + bool IgnoreItem() const; + UInt32 GetWinAttributes() const; + + CItem(): CTimeDefined(false), ATimeDefined(false) {} +}; + +class CItemEx: public CItem +{ +public: + UInt64 Position; + UInt16 MainPartSize; + UInt16 CommentSize; + UInt16 AlignSize; + UInt64 GetFullSize() const { return MainPartSize + CommentSize + AlignSize + PackSize; }; + // DWORD GetHeaderWithCommentSize() const { return MainPartSize + CommentSize; }; + UInt64 GetCommentPosition() const { return Position + MainPartSize; }; + UInt64 GetDataPosition() const { return GetCommentPosition() + CommentSize + AlignSize; }; +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Rar/RarRegister.cpp b/CPP/7zip/Archive/Rar/RarRegister.cpp new file mode 100755 index 0000000..1db21e0 --- /dev/null +++ b/CPP/7zip/Archive/Rar/RarRegister.cpp @@ -0,0 +1,13 @@ +// RarRegister.cpp + +#include "StdAfx.h" + +#include "../../Common/RegisterArc.h" + +#include "RarHandler.h" +static IInArchive *CreateArc() { return new NArchive::NRar::CHandler; } + +static CArcInfo g_ArcInfo = + { L"Rar", L"rar r00", 0, 3, {0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00}, 7, false, CreateArc, 0, }; + +REGISTER_ARC(Rar) diff --git a/CPP/7zip/Archive/Rar/RarVolumeInStream.cpp b/CPP/7zip/Archive/Rar/RarVolumeInStream.cpp new file mode 100755 index 0000000..cc0333b --- /dev/null +++ b/CPP/7zip/Archive/Rar/RarVolumeInStream.cpp @@ -0,0 +1,78 @@ +// RarVolumeInStream.cpp + +#include "StdAfx.h" + +#include "../../../../C/7zCrc.h" + +#include "RarVolumeInStream.h" + +namespace NArchive { +namespace NRar { + +void CFolderInStream::Init( + CObjectVector *archives, + const CObjectVector *items, + const CRefItem &refItem) +{ + _archives = archives; + _items = items; + _refItem = refItem; + _curIndex = 0; + CRCs.Clear(); + _fileIsOpen = false; +} + +HRESULT CFolderInStream::OpenStream() +{ + while (_curIndex < _refItem.NumItems) + { + const CItemEx &item = (*_items)[_refItem.ItemIndex + _curIndex]; + _stream.Attach((*_archives)[_refItem.VolumeIndex + _curIndex]. + CreateLimitedStream(item.GetDataPosition(), item.PackSize)); + _curIndex++; + _fileIsOpen = true; + _crc = CRC_INIT_VAL; + return S_OK; + } + return S_OK; +} + +HRESULT CFolderInStream::CloseStream() +{ + CRCs.Add(CRC_GET_DIGEST(_crc)); + _stream.Release(); + _fileIsOpen = false; + return S_OK; +} + +STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessedSize = 0; + while ((_curIndex < _refItem.NumItems || _fileIsOpen) && size > 0) + { + if (_fileIsOpen) + { + UInt32 localProcessedSize; + RINOK(_stream->Read( + ((Byte *)data) + realProcessedSize, size, &localProcessedSize)); + _crc = CrcUpdate(_crc, ((Byte *)data) + realProcessedSize, localProcessedSize); + if (localProcessedSize == 0) + { + RINOK(CloseStream()); + continue; + } + realProcessedSize += localProcessedSize; + size -= localProcessedSize; + break; + } + else + { + RINOK(OpenStream()); + } + } + if (processedSize != 0) + *processedSize = realProcessedSize; + return S_OK; +} + +}} diff --git a/CPP/7zip/Archive/Rar/RarVolumeInStream.h b/CPP/7zip/Archive/Rar/RarVolumeInStream.h new file mode 100755 index 0000000..d175a2c --- /dev/null +++ b/CPP/7zip/Archive/Rar/RarVolumeInStream.h @@ -0,0 +1,49 @@ +// RarVolumeInStream.h + +#ifndef __RAR_VOLUME_IN_STREAM_H +#define __RAR_VOLUME_IN_STREAM_H + +#include "../../IStream.h" +#include "RarIn.h" + +namespace NArchive { +namespace NRar { + +struct CRefItem +{ + int VolumeIndex; + int ItemIndex; + int NumItems; +}; + +class CFolderInStream: + public ISequentialInStream, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + +private: + CObjectVector *_archives; + const CObjectVector *_items; + CRefItem _refItem; + int _curIndex; + UInt32 _crc; + bool _fileIsOpen; + CMyComPtr _stream; + + HRESULT OpenStream(); + HRESULT CloseStream(); +public: + void Init(CObjectVector *archives, + const CObjectVector *items, + const CRefItem &refItem); + + CRecordVector CRCs; +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Rar/StdAfx.cpp b/CPP/7zip/Archive/Rar/StdAfx.cpp new file mode 100755 index 0000000..c6d3b1f --- /dev/null +++ b/CPP/7zip/Archive/Rar/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/Archive/Rar/StdAfx.h b/CPP/7zip/Archive/Rar/StdAfx.h new file mode 100755 index 0000000..83fdd22 --- /dev/null +++ b/CPP/7zip/Archive/Rar/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" + +#endif diff --git a/CPP/7zip/Archive/RpmHandler.cpp b/CPP/7zip/Archive/RpmHandler.cpp new file mode 100755 index 0000000..536c968 --- /dev/null +++ b/CPP/7zip/Archive/RpmHandler.cpp @@ -0,0 +1,292 @@ +// RpmHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Common/ComTry.h" +#include "Common/MyString.h" + +#include "Windows/PropVariant.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +using namespace NWindows; + +#define Get16(p) GetBe16(p) +#define Get32(p) GetBe32(p) + +namespace NArchive { +namespace NRpm { + +/* Reference: lib/signature.h of rpm package */ +#define RPMSIG_NONE 0 /* Do not change! */ +/* The following types are no longer generated */ +#define RPMSIG_PGP262_1024 1 /* No longer generated */ /* 256 byte */ +/* These are the new-style signatures. They are Header structures. */ +/* Inside them we can put any number of any type of signature we like. */ + +#define RPMSIG_HEADERSIG 5 /* New Header style signature */ + +const UInt32 kLeadSize = 96; +struct CLead +{ + unsigned char Magic[4]; + unsigned char Major; // not supported ver1, only support 2,3 and lator + unsigned char Minor; + UInt16 Type; + UInt16 ArchNum; + char Name[66]; + UInt16 OSNum; + UInt16 SignatureType; + char Reserved[16]; // pad to 96 bytes -- 8 byte aligned + bool MagicCheck() const + { return Magic[0] == 0xed && Magic[1] == 0xab && Magic[2] == 0xee && Magic[3] == 0xdb; }; +}; + +const UInt32 kEntryInfoSize = 16; +/* +struct CEntryInfo +{ + int Tag; + int Type; + int Offset; // Offset from beginning of data segment, only defined on disk + int Count; +}; +*/ + +// case: SignatureType == RPMSIG_HEADERSIG +const UInt32 kCSigHeaderSigSize = 16; +struct CSigHeaderSig +{ + unsigned char Magic[4]; + UInt32 Reserved; + UInt32 IndexLen; // count of index entries + UInt32 DataLen; // number of bytes + bool MagicCheck() + { return Magic[0] == 0x8e && Magic[1] == 0xad && Magic[2] == 0xe8 && Magic[3] == 0x01; }; + UInt32 GetLostHeaderLen() + { return IndexLen * kEntryInfoSize + DataLen; }; +}; + +static HRESULT RedSigHeaderSig(IInStream *inStream, CSigHeaderSig &h) +{ + char dat[kCSigHeaderSigSize]; + char *cur = dat; + RINOK(ReadStream_FALSE(inStream, dat, kCSigHeaderSigSize)); + memcpy(h.Magic, cur, 4); + cur += 4; + cur += 4; + h.IndexLen = Get32(cur); + cur += 4; + h.DataLen = Get32(cur); + return S_OK; +} + +HRESULT OpenArchive(IInStream *inStream) +{ + UInt64 pos; + char leadData[kLeadSize]; + char *cur = leadData; + CLead lead; + RINOK(ReadStream_FALSE(inStream, leadData, kLeadSize)); + memcpy(lead.Magic, cur, 4); + cur += 4; + lead.Major = *cur++; + lead.Minor = *cur++; + lead.Type = Get16(cur); + cur += 2; + lead.ArchNum = Get16(cur); + cur += 2; + memcpy(lead.Name, cur, sizeof(lead.Name)); + cur += sizeof(lead.Name); + lead.OSNum = Get16(cur); + cur += 2; + lead.SignatureType = Get16(cur); + cur += 2; + + if (!lead.MagicCheck() || lead.Major < 3) + return S_FALSE; + + CSigHeaderSig sigHeader, header; + if (lead.SignatureType == RPMSIG_NONE) + { + ; + } + else if (lead.SignatureType == RPMSIG_PGP262_1024) + { + UInt64 pos; + RINOK(inStream->Seek(256, STREAM_SEEK_CUR, &pos)); + } + else if (lead.SignatureType == RPMSIG_HEADERSIG) + { + RINOK(RedSigHeaderSig(inStream, sigHeader)); + if (!sigHeader.MagicCheck()) + return S_FALSE; + UInt32 len = sigHeader.GetLostHeaderLen(); + RINOK(inStream->Seek(len, STREAM_SEEK_CUR, &pos)); + if ((pos % 8) != 0) + { + RINOK(inStream->Seek((pos / 8 + 1) * 8 - pos, + STREAM_SEEK_CUR, &pos)); + } + } + else + return S_FALSE; + + RINOK(RedSigHeaderSig(inStream, header)); + if (!header.MagicCheck()) + return S_FALSE; + int headerLen = header.GetLostHeaderLen(); + if (headerLen == -1) + return S_FALSE; + RINOK(inStream->Seek(headerLen, STREAM_SEEK_CUR, &pos)); + return S_OK; +} + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + UInt64 _pos; + UInt64 _size; + Byte _sig[4]; +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +STATPROPSTG kProps[] = +{ + { NULL, kpidSize, VT_UI8} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO_Table + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) { case kpidMainSubfile: prop = (UInt32)0; break; } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *inStream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback * /* openArchiveCallback */) +{ + COM_TRY_BEGIN + try + { + Close(); + if (OpenArchive(inStream) != S_OK) + return S_FALSE; + RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &_pos)); + RINOK(ReadStream_FALSE(inStream, _sig, sizeof(_sig) / sizeof(_sig[0]))); + UInt64 endPosition; + RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPosition)); + _size = endPosition - _pos; + _stream = inStream; + return S_OK; + } + catch(...) { return S_FALSE; } + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _stream.Release(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = 1; + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +{ + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidSize: + case kpidPackSize: + prop = _size; + break; + case kpidExtension: + { + char s[32]; + MyStringCopy(s, "cpio."); + const char *ext; + if (_sig[0] == 0x1F && _sig[1] == 0x8B) + ext = "gz"; + else if (_sig[0] == 'B' && _sig[1] == 'Z' && _sig[2] == 'h') + ext = "bz2"; + else + ext = "lzma"; + MyStringCopy(s + MyStringLen(s), ext); + prop = s; + 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)-1 && (numItems != 1 || indices[0] != 0)) + return E_INVALIDARG; + + RINOK(extractCallback->SetTotal(_size)); + 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)); + + CMyComPtr copyCoder = new NCompress::CCopyCoder; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + RINOK(_stream->Seek(_pos, STREAM_SEEK_SET, NULL)); + RINOK(copyCoder->Code(_stream, outStream, NULL, NULL, progress)); + outStream.Release(); + return extractCallback->SetOperationResult(NExtract::NOperationResult::kOK); + COM_TRY_END +} + +STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + return CreateLimitedInStream(_stream, _pos, _size, stream); + COM_TRY_END +} + +static IInArchive *CreateArc() { return new NArchive::NRpm::CHandler; } + +static CArcInfo g_ArcInfo = + { L"Rpm", L"rpm", 0, 0xEB, { 0xED, 0xAB, 0xEE, 0xDB}, 4, false, CreateArc, 0 }; + +REGISTER_ARC(Rpm) + +}} diff --git a/CPP/7zip/Archive/SplitHandler.cpp b/CPP/7zip/Archive/SplitHandler.cpp new file mode 100755 index 0000000..cb98a77 --- /dev/null +++ b/CPP/7zip/Archive/SplitHandler.cpp @@ -0,0 +1,366 @@ +// 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 { + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidSize, VT_UI8} +}; + +STATPROPSTG kArcProps[] = +{ + { NULL, kpidNumVolumes, VT_UI4} +}; + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + UString _subName; + CObjectVector > _streams; + CRecordVector _sizes; + UInt64 _totalSize; +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 kpidNumVolumes: prop = (UInt32)_streams.Size(); break; + } + prop.Detach(value); + return S_OK; +} + +struct CSeqName +{ + UString _unchangedPart; + UString _changedPart; + bool _splitStyle; + + UString GetNextName() + { + UString newName; + if (_splitStyle) + { + int i; + int numLetters = _changedPart.Length(); + for (i = numLetters - 1; i >= 0; i--) + { + wchar_t c = _changedPart[i]; + if (c == 'z') + { + c = 'a'; + newName = c + newName; + continue; + } + else if (c == 'Z') + { + c = 'A'; + newName = c + newName; + continue; + } + c++; + if ((c == 'z' || c == 'Z') && i == 0) + { + _unchangedPart += c; + wchar_t newChar = (c == 'z') ? L'a' : L'A'; + newName.Empty(); + numLetters++; + for (int k = 0; k < numLetters; k++) + newName += newChar; + break; + } + newName = c + newName; + i--; + for (; i >= 0; i--) + newName = _changedPart[i] + newName; + break; + } + } + else + { + int i; + int numLetters = _changedPart.Length(); + for (i = numLetters - 1; i >= 0; i--) + { + wchar_t c = _changedPart[i]; + if (c == L'9') + { + c = L'0'; + newName = c + newName; + if (i == 0) + newName = UString(L'1') + newName; + continue; + } + c++; + newName = c + newName; + i--; + for (; i >= 0; i--) + newName = _changedPart[i] + newName; + break; + } + } + _changedPart = newName; + return _unchangedPart + _changedPart; + } +}; + +STDMETHODIMP CHandler::Open(IInStream *stream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback *openArchiveCallback) +{ + COM_TRY_BEGIN + Close(); + if (openArchiveCallback == 0) + return S_FALSE; + // try + { + CMyComPtr openVolumeCallback; + CMyComPtr openArchiveCallbackWrap = openArchiveCallback; + if (openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, + &openVolumeCallback) != S_OK) + return S_FALSE; + + UString name; + { + NCOM::CPropVariant prop; + RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); + if (prop.vt != VT_BSTR) + return S_FALSE; + name = prop.bstrVal; + } + + int dotPos = name.ReverseFind('.'); + UString prefix, ext; + if (dotPos >= 0) + { + prefix = name.Left(dotPos + 1); + ext = name.Mid(dotPos + 1); + } + else + ext = name; + UString extBig = ext; + extBig.MakeUpper(); + + CSeqName seqName; + + int numLetters = 2; + bool splitStyle = false; + if (extBig.Right(2) == L"AA") + { + splitStyle = true; + while (numLetters < extBig.Length()) + { + if (extBig[extBig.Length() - numLetters - 1] != 'A') + break; + numLetters++; + } + } + else if (ext.Right(2) == L"01") + { + while (numLetters < extBig.Length()) + { + if (extBig[extBig.Length() - numLetters - 1] != '0') + break; + numLetters++; + } + if (numLetters != ext.Length()) + return S_FALSE; + } + else + return S_FALSE; + + _streams.Add(stream); + + seqName._unchangedPart = prefix + ext.Left(extBig.Length() - numLetters); + seqName._changedPart = ext.Right(numLetters); + seqName._splitStyle = splitStyle; + + if (prefix.Length() < 1) + _subName = L"file"; + else + _subName = prefix.Left(prefix.Length() - 1); + + _totalSize = 0; + UInt64 size; + { + NCOM::CPropVariant prop; + RINOK(openVolumeCallback->GetProperty(kpidSize, &prop)); + if (prop.vt != VT_UI8) + return E_INVALIDARG; + size = prop.uhVal.QuadPart; + } + _totalSize += size; + _sizes.Add(size); + + if (openArchiveCallback != NULL) + { + UInt64 numFiles = _streams.Size(); + RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); + } + + for (;;) + { + UString fullName = seqName.GetNextName(); + CMyComPtr nextStream; + HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream); + if (result == S_FALSE) + break; + if (result != S_OK) + return result; + if (!stream) + break; + { + NCOM::CPropVariant prop; + RINOK(openVolumeCallback->GetProperty(kpidSize, &prop)); + if (prop.vt != VT_UI8) + return E_INVALIDARG; + size = prop.uhVal.QuadPart; + } + _totalSize += size; + _sizes.Add(size); + _streams.Add(nextStream); + if (openArchiveCallback != NULL) + { + UInt64 numFiles = _streams.Size(); + RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); + } + } + } + /* + catch(...) + { + return S_FALSE; + } + */ + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _sizes.Clear(); + _streams.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) +{ + NWindows::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)-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 (int i = 0; i < _streams.Size(); i++) + { + 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 (int i = 0; i < _streams.Size(); i++) + { + 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 +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = +{ L"Split", L"001", 0, 0xEA, { 0 }, 0, false, CreateArc, 0 }; + +REGISTER_ARC(Split) + +}} diff --git a/CPP/7zip/Archive/SquashfsHandler.cpp b/CPP/7zip/Archive/SquashfsHandler.cpp new file mode 100755 index 0000000..acc0362 --- /dev/null +++ b/CPP/7zip/Archive/SquashfsHandler.cpp @@ -0,0 +1,2155 @@ +// SquashfsHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/7zCrc.h" +#include "../../../C/Alloc.h" +#include "../../../C/CpuArch.h" + +#include "Common/ComTry.h" +#include "Common/IntToString.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariantUtils.h" +#include "Windows/Time.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamObjects.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" +#include "../Compress/ZlibDecoder.h" +#include "../Compress/LzmaDecoder.h" + +namespace NArchive { +namespace NSquashfs { + +static const UInt32 kNumFilesMax = (1 << 28); +static const unsigned kNumDirLevelsMax = (1 << 10); + +// Layout: Header, Data, inodes, Directories, Fragments, UIDs, GIDs + +/* +#define Get16(p) (be ? GetBe16(p) : GetUi16(p)) +#define Get32(p) (be ? GetBe32(p) : GetUi32(p)) +#define Get64(p) (be ? GetBe64(p) : GetUi64(p)) +*/ + +UInt16 Get16b(const Byte *p, bool be) { return be ? GetBe16(p) : GetUi16(p); } +UInt32 Get32b(const Byte *p, bool be) { return be ? GetBe32(p) : GetUi32(p); } +UInt64 Get64b(const Byte *p, bool be) { return be ? GetBe64(p) : GetUi64(p); } + +#define Get16(p) Get16b(p, be) +#define Get32(p) Get32b(p, be) +#define Get64(p) Get64b(p, be) + +#define LE_16(offs, dest) dest = GetUi16(p + (offs)); +#define LE_32(offs, dest) dest = GetUi32(p + (offs)); +#define LE_64(offs, dest) dest = GetUi64(p + (offs)); + +#define GET_16(offs, dest) dest = Get16(p + (offs)); +#define GET_32(offs, dest) dest = Get32(p + (offs)); +#define GET_64(offs, dest) dest = Get64(p + (offs)); + +static const UInt32 kSignatureSize = 4; +#define SIGNATURE { 'h', 's', 'q', 's' } +static const UInt32 kSignature32_LE = 0x73717368; +static const UInt32 kSignature32_BE = 0x68737173; +static const UInt32 kSignature32_LZ = 0x71736873; + +#define kMethod_ZLIB 1 +#define kMethod_LZMA 2 +#define kMethod_LZO 3 + +static const char *k_Methods[] = +{ + "Unknown", + "ZLIB", + "LZMA", + "LZO" +}; + +static const UInt32 kMetadataBlockSizeLog = 13; +static const UInt32 kMetadataBlockSize = (1 << kMetadataBlockSizeLog); + +#define MY_S_IFIFO 0x1000 +#define MY_S_IFCHR 0x2000 +#define MY_S_IFDIR 0x4000 +#define MY_S_IFBLK 0x6000 +#define MY_S_IFREG 0x8000 +#define MY_S_IFLNK 0xA000 +#define MY_S_IFSOCK 0xC000 + +enum +{ + kType_IPC, + kType_DIR, + kType_FILE, + kType_LNK, + kType_BLK, + kType_CHR, + kType_FIFO, + kType_SOCK +}; + +static const UInt32 k_TypeToMode[] = +{ + 0, + MY_S_IFDIR, MY_S_IFREG, MY_S_IFLNK, MY_S_IFBLK, MY_S_IFCHR, MY_S_IFIFO, MY_S_IFSOCK, + MY_S_IFDIR, MY_S_IFREG, MY_S_IFLNK, MY_S_IFBLK, MY_S_IFCHR, MY_S_IFIFO, MY_S_IFSOCK +}; + + +enum +{ + kFlag_UNC_INODES, + kFlag_UNC_DATA, + kFlag_CHECK, + kFlag_UNC_FRAGS, + kFlag_NO_FRAGS, + kFlag_ALWAYS_FRAG, + kFlag_DUPLICATE, + kFlag_EXPORT +}; + +static const CUInt32PCharPair k_Flags[] = +{ + { kFlag_UNC_INODES, "UNCOMPRESSED_INODES" }, + { kFlag_UNC_DATA, "UNCOMPRESSED_DATA" }, + { kFlag_CHECK, "CHECK" }, + { kFlag_UNC_FRAGS, "UNCOMPRESSED_FRAGMENTS" }, + { kFlag_NO_FRAGS, "NO_FRAGMENTS" }, + { kFlag_ALWAYS_FRAG, "ALWAYS_FRAGMENTS" }, + { kFlag_DUPLICATE, "DUPLICATES_REMOVED" }, + { kFlag_EXPORT, "EXPORTABLE" } +}; + +static const UInt32 kNotCompressedBit16 = (1 << 15); +static const UInt32 kNotCompressedBit32 = (1 << 24); + +#define GET_COMPRESSED_BLOCK_SIZE(size) ((size) & ~kNotCompressedBit32) +#define IS_COMPRESSED_BLOCK(size) (((size) & kNotCompressedBit32) == 0) + +static const UInt32 kHeaderSize1 = 0x33; +static const UInt32 kHeaderSize2 = 0x3F; +static const UInt32 kHeaderSize3 = 0x77; +static const UInt32 kHeaderSize4 = 0x60; + +struct CHeader +{ + bool be; + bool SeveralMethods; + Byte NumUids; + Byte NumGids; + + UInt32 NumInodes; + UInt32 CTime; + UInt32 BlockSize; + UInt32 NumFrags; + UInt16 Method; + UInt16 BlockSizeLog; + UInt16 Flags; + UInt16 NumIDs; + UInt16 Major; + UInt16 Minor; + UInt64 RootInode; + UInt64 Size; + UInt64 UidTable; + UInt64 GidTable; + UInt64 XattrIdTable; + UInt64 InodeTable; + UInt64 DirTable; + UInt64 FragTable; + UInt64 LookupTable; + + void Parse3(const Byte *p) + { + Method = kMethod_ZLIB; + GET_32 (0x08, Size); + GET_32 (0x0C, UidTable); + GET_32 (0x10, GidTable); + GET_32 (0x14, InodeTable); + GET_32 (0x18, DirTable); + GET_16 (0x20, BlockSize); + GET_16 (0x22, BlockSizeLog); + Flags = p[0x24]; + NumUids = p[0x25]; + NumGids = p[0x26]; + GET_32 (0x27, CTime); + GET_64 (0x2B, RootInode); + NumFrags = 0; + FragTable = UidTable; + + if (Major >= 2) + { + GET_32 (0x33, BlockSize); + GET_32 (0x37, NumFrags); + GET_32 (0x3B, FragTable); + if (Major == 3) + { + GET_64 (0x3F, Size); + GET_64 (0x47, UidTable); + GET_64 (0x4F, GidTable); + GET_64 (0x57, InodeTable); + GET_64 (0x5F, DirTable); + GET_64 (0x67, FragTable); + GET_64 (0x6F, LookupTable); + } + } + } + + void Parse4(const Byte *p) + { + LE_32 (0x08, CTime); + LE_32 (0x0C, BlockSize); + LE_32 (0x10, NumFrags); + LE_16 (0x14, Method); + LE_16 (0x16, BlockSizeLog); + LE_16 (0x18, Flags); + LE_16 (0x1A, NumIDs); + LE_64 (0x20, RootInode); + LE_64 (0x28, Size); + LE_64 (0x30, UidTable); + LE_64 (0x38, XattrIdTable); + LE_64 (0x40, InodeTable); + LE_64 (0x48, DirTable); + LE_64 (0x50, FragTable); + LE_64 (0x58, LookupTable); + GidTable = 0; + } + + bool Parse(const Byte *p) + { + be = false; + SeveralMethods = false; + switch (GetUi32(p)) + { + case kSignature32_LE: break; + case kSignature32_BE: be = true; break; + case kSignature32_LZ: SeveralMethods = true; break; + default: return false; + } + GET_32 (4, NumInodes); + GET_16 (0x1C, Major); + GET_16 (0x1E, Minor); + if (Major <= 3) + Parse3(p); + else + { + if (be) + return false; + Parse4(p); + } + return + InodeTable < DirTable && + DirTable <= FragTable && + FragTable <= Size && + UidTable <= Size && + BlockSizeLog >= 12 && + BlockSizeLog < 31 && + BlockSize == ((UInt32)1 << BlockSizeLog); + } + + bool IsSupported() const { return Major > 0 && Major <= 4 && BlockSizeLog <= 23; } + bool IsOldVersion() const { return Major < 4; } + bool NeedCheckData() const { return (Flags & (1 << kFlag_CHECK)) != 0; } + unsigned GetFileNameOffset() const { return Major <= 2 ? 3 : (Major == 3 ? 5 : 8); } + unsigned GetSymLinkOffset() const { return Major <= 1 ? 5: (Major <= 2 ? 6: (Major == 3 ? 18 : 24)); } + unsigned GetSpecGuidIndex() const { return Major <= 1 ? 0xF: 0xFF; } +}; + +static const UInt32 kFrag_Empty = (UInt32)(Int32)-1; +// static const UInt32 kXattr_Empty = (UInt32)(Int32)-1; + +struct CNode +{ + UInt16 Type; + UInt16 Mode; + UInt16 Uid; + UInt16 Gid; + UInt32 Frag; + UInt32 Offset; + // UInt32 MTime; + // UInt32 Number; + // UInt32 NumLinks; + // UInt32 RDev; + // UInt32 Xattr; + // UInt32 Parent; + + UInt64 FileSize; + UInt64 StartBlock; + // UInt64 Sparse; + + UInt32 Parse1(const Byte *p, UInt32 size, const CHeader &_h); + UInt32 Parse2(const Byte *p, UInt32 size, const CHeader &_h); + UInt32 Parse3(const Byte *p, UInt32 size, const CHeader &_h); + UInt32 Parse4(const Byte *p, UInt32 size, const CHeader &_h); + + bool IsDir() const { return (Type == kType_DIR || Type == kType_DIR + 7); } + bool IsLink() const { return (Type == kType_LNK || Type == kType_LNK + 7); } + UInt64 GetSize() const { return IsDir() ? 0 : FileSize; } + + bool ThereAreFrags() const { return Frag != kFrag_Empty; } + UInt64 GetNumBlocks(const CHeader &_h) const + { + return (FileSize >> _h.BlockSizeLog) + + (!ThereAreFrags() && (FileSize & (_h.BlockSize - 1)) != 0); + } +}; + +UInt32 CNode::Parse1(const Byte *p, UInt32 size, const CHeader &_h) +{ + bool be = _h.be; + if (size < 4) + return 0; + UInt16 t = Get16(p); + if (be) + { + Type = t >> 12; + Mode = t & 0xFFF; + Uid = p[2] >> 4; + Gid = p[2] & 0xF; + } + else + { + Type = t & 0xF; + Mode = t >> 4; + Uid = p[2] & 0xF; + Gid = p[2] >> 4; + } + + // Xattr = kXattr_Empty; + // MTime = 0; + FileSize = 0; + StartBlock = 0; + Frag = kFrag_Empty; + + if (Type == 0) + { + Byte t = p[3]; + if (be) + { + Type = t >> 4; + Offset = t & 0xF; + } + else + { + Type = t & 0xF; + Offset = t >> 4; + } + return (Type == kType_FIFO || Type == kType_SOCK) ? 4 : 0; + } + + Type--; + Uid += (Type / 5) * 16; + Type = (Type % 5) + 1; + + if (Type == kType_FILE) + { + if (size < 15) + return 0; + // GET_32 (3, MTime); + GET_32 (7, StartBlock); + UInt32 t; + GET_32 (11, t); + FileSize = t; + UInt32 numBlocks = t >> _h.BlockSizeLog; + if ((t & (_h.BlockSize - 1)) != 0) + numBlocks++; + UInt32 pos = numBlocks * 2 + 15; + return (pos <= size) ? pos : 0; + } + + if (Type == kType_DIR) + { + if (size < 14) + return 0; + UInt32 t = Get32(p + 3); + if (be) + { + FileSize = t >> 13; + Offset = t & 0x1FFF; + } + else + { + FileSize = t & 0x7FFFF; + Offset = t >> 19; + } + // GET_32 (7, MTime); + GET_32 (10, StartBlock); + if (be) + StartBlock &= 0xFFFFFF; + else + StartBlock >>= 8; + return 14; + } + + if (size < 5) + return 0; + + if (Type == kType_LNK) + { + UInt32 len; + GET_16 (3, len); + FileSize = len; + len += 5; + return (len <= size) ? len : 0; + } + + // GET_32 (3, RDev); + return 5; +} + +UInt32 CNode::Parse2(const Byte *p, UInt32 size, const CHeader &_h) +{ + bool be = _h.be; + if (size < 4) + return 0; + UInt16 t = Get16(p); + if (be) + { + Type = t >> 12; + Mode = t & 0xFFF; + } + else + { + Type = t & 0xF; + Mode = t >> 4; + } + Uid = p[2]; + Gid = p[3]; + + // Xattr = kXattr_Empty; + + if (Type == kType_FILE) + { + if (size < 24) + return 0; + // GET_32 (4, MTime); + GET_32 (8, StartBlock); + GET_32 (12, Frag); + GET_32 (16, Offset); + UInt32 t; + GET_32 (20, t); + FileSize = t; + UInt32 numBlocks = t >> _h.BlockSizeLog; + if (!ThereAreFrags() && (t & (_h.BlockSize - 1)) != 0) + numBlocks++; + UInt32 pos = numBlocks * 4 + 24; + return (pos <= size) ? (UInt32)pos : 0; + } + + FileSize = 0; + // MTime = 0; + StartBlock = 0; + Frag = kFrag_Empty; + + if (Type == kType_DIR) + { + if (size < 15) + return 0; + UInt32 t = Get32(p + 4); + if (be) + { + FileSize = t >> 13; + Offset = t & 0x1FFF; + } + else + { + FileSize = t & 0x7FFFF; + Offset = t >> 19; + } + // GET_32 (8, MTime); + GET_32 (11, StartBlock); + if (be) + StartBlock &= 0xFFFFFF; + else + StartBlock >>= 8; + return 15; + } + + if (Type == kType_DIR + 7) + { + if (size < 18) + return 0; + UInt32 t = Get32(p + 4); + UInt32 t2 = Get16(p + 7); + if (be) + { + FileSize = t >> 5; + Offset = t2 & 0x1FFF; + } + else + { + FileSize = t & 0x7FFFFFF; + Offset = t2 >> 3; + } + // GET_32 (9, MTime); + GET_32 (12, StartBlock); + if (be) + StartBlock &= 0xFFFFFF; + else + StartBlock >>= 8; + UInt32 iCount; + GET_16 (16, iCount); + UInt32 pos = 18; + for (UInt32 i = 0; i < iCount; i++) + { + // 27 bits: index + // 29 bits: startBlock + if (pos + 8 > size) + return 0; + pos += 8 + (UInt32)p[pos + 7] + 1; // nameSize + if (pos > size) + return 0; + } + return pos; + } + + if (Type == kType_FIFO || Type == kType_SOCK) + return 4; + + if (size < 6) + return 0; + + if (Type == kType_LNK) + { + UInt32 len; + GET_16 (4, len); + FileSize = len; + len += 6; + return (len <= size) ? len : 0; + } + + if (Type == kType_BLK || Type == kType_CHR) + { + // GET_16 (4, RDev); + return 6; + } + + return 0; +} + +UInt32 CNode::Parse3(const Byte *p, UInt32 size, const CHeader &_h) +{ + bool be = _h.be; + if (size < 12) + return 0; + UInt16 t = Get16(p); + if (be) + { + Type = t >> 12; + Mode = t & 0xFFF; + } + else + { + Type = t & 0xF; + Mode = t >> 4; + } + Uid = p[2]; + Gid = p[3]; + // GET_32 (4, MTime); + // GET_32 (8, Number); + // Xattr = kXattr_Empty; + FileSize = 0; + StartBlock = 0; + + if (Type == kType_FILE || Type == kType_FILE + 7) + { + UInt32 offset; + if (Type == kType_FILE) + { + if (size < 32) + return 0; + GET_64 (12, StartBlock); + GET_32 (20, Frag); + GET_32 (24, Offset); + GET_32 (28, FileSize); + offset = 32; + } + else + { + if (size < 40) + return 0; + // GET_32 (12, NumLinks); + GET_64 (16, StartBlock); + GET_32 (24, Frag); + GET_32 (28, Offset); + GET_64 (32, FileSize); + offset = 40; + } + UInt64 pos = GetNumBlocks(_h) * 4 + offset; + return (pos <= size) ? (UInt32)pos : 0; + } + + if (size < 16) + return 0; + // GET_32 (12, NumLinks); + + if (Type == kType_DIR) + { + if (size < 28) + return 0; + UInt32 t = Get32(p + 16); + if (be) + { + FileSize = t >> 13; + Offset = t & 0x1FFF; + } + else + { + FileSize = t & 0x7FFFF; + Offset = t >> 19; + } + GET_32 (20, StartBlock); + // GET_32 (24, Parent); + return 28; + } + + if (Type == kType_DIR + 7) + { + if (size < 31) + return 0; + UInt32 t = Get32(p + 16); + UInt32 t2 = Get16(p + 19); + if (be) + { + FileSize = t >> 5; + Offset = t2 & 0x1FFF; + } + else + { + FileSize = t & 0x7FFFFFF; + Offset = t2 >> 3; + } + GET_32 (21, StartBlock); + UInt32 iCount; + GET_16 (25, iCount); + // GET_32 (27, Parent); + UInt32 pos = 31; + for (UInt32 i = 0; i < iCount; i++) + { + // UInt32 index + // UInt32 startBlock + if (pos + 9 > size) + return 0; + pos += 9 + (unsigned)p[pos + 8] + 1; // nameSize + if (pos > size) + return 0; + } + return pos; + } + + if (Type == kType_FIFO || Type == kType_SOCK) + return 16; + + if (size < 18) + return 0; + if (Type == kType_LNK) + { + UInt32 len; + GET_16 (16, len); + FileSize = len; + len += 18; + return (len <= size) ? len : 0; + } + + if (Type == kType_BLK || Type == kType_CHR) + { + // GET_16 (16, RDev); + return 18; + } + + return 0; +} + +UInt32 CNode::Parse4(const Byte *p, UInt32 size, const CHeader &_h) +{ + if (size < 20) + return 0; + LE_16 (0, Type); + LE_16 (2, Mode); + LE_16 (4, Uid); + LE_16 (6, Gid); + // LE_32 (8, MTime); + // LE_32 (12, Number); + + // Xattr = kXattr_Empty; + FileSize = 0; + StartBlock = 0; + + if (Type == kType_FILE || Type == kType_FILE + 7) + { + UInt32 offset; + if (Type == kType_FILE) + { + if (size < 32) + return 0; + LE_32 (16, StartBlock); + LE_32 (20, Frag); + LE_32 (24, Offset); + LE_32 (28, FileSize); + offset = 32; + } + else + { + if (size < 56) + return 0; + LE_64 (16, StartBlock); + LE_64 (24, FileSize); + // LE_64 (32, Sparse); + // LE_32 (40, NumLinks); + LE_32 (44, Frag); + LE_32 (48, Offset); + // LE_32 (52, Xattr); + offset = 56; + } + UInt64 pos = GetNumBlocks(_h) * 4 + offset; + return (pos <= size) ? (UInt32)pos : 0; + } + + if (Type == kType_DIR) + { + if (size < 32) + return 0; + LE_32 (16, StartBlock); + // LE_32 (20, NumLinks); + LE_16 (24, FileSize); + LE_16 (26, Offset); + // LE_32 (28, Parent); + return 32; + } + + // LE_32 (16, NumLinks); + + if (Type == kType_DIR + 7) + { + if (size < 40) + return 0; + LE_32 (20, FileSize); + LE_32 (24, StartBlock); + // LE_32 (28, Parent); + UInt32 iCount; + LE_16 (32, iCount); + LE_16 (34, Offset); + // LE_32 (36, Xattr); + + UInt32 pos = 40; + for (UInt32 i = 0; i < iCount; i++) + { + // UInt32 index + // UInt32 startBlock + if (pos + 12 > size) + return 0; + UInt32 nameLen = GetUi32(p + pos + 8); + pos += 12 + nameLen + 1; + if (pos > size || nameLen > (1 << 10)) + return 0; + } + return pos; + } + + unsigned offset = 20; + switch(Type) + { + case kType_FIFO: case kType_FIFO + 7: + case kType_SOCK: case kType_SOCK + 7: + break; + case kType_LNK: case kType_LNK + 7: + { + if (size < 24) + return 0; + UInt32 len; + LE_32 (20, len); + FileSize = len; + offset = len + 24; + if (size < offset || len > (1 << 30)) + return 0; + break; + } + case kType_BLK: case kType_BLK + 7: + case kType_CHR: case kType_CHR + 7: + if (size < 24) + return 0; + // LE_32 (20, RDev); + offset = 24; + break; + default: + return 0; + } + + if (Type >= 8) + { + if (size < offset + 4) + return 0; + // LE_32 (offset, Xattr); + offset += 4; + } + return offset; +} + +struct CItem +{ + int Node; + int Parent; + UInt32 Ptr; +}; + +struct CData +{ + CByteBuffer Data; + CRecordVector PackPos; + CRecordVector UnpackPos; // additional item at the end contains TotalUnpackSize + + UInt32 GetNumBlocks() const { return PackPos.Size(); } + void Clear() + { + Data.Free(); + PackPos.Clear(); + UnpackPos.Clear(); + } +}; + +struct CFrag +{ + UInt64 StartBlock; + UInt32 Size; +}; + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + CRecordVector _items; + CRecordVector _nodes; + CRecordVector _nodesPos; + CRecordVector _blockToNode; + CData _inodesData; + CData _dirs; + CRecordVector _frags; + // CByteBuffer _uids; + // CByteBuffer _gids; + CHeader _h; + + CMyComPtr _stream; + UInt64 _sizeCalculated; + + IArchiveOpenCallback *_openCallback; + + int _nodeIndex; + CRecordVector _blockCompressed; + CRecordVector _blockOffsets; + + CByteBuffer _cachedBlock; + UInt64 _cachedBlockStartPos; + UInt32 _cachedPackBlockSize; + UInt32 _cachedUnpackBlockSize; + + CLimitedSequentialInStream *_limitedInStreamSpec; + CMyComPtr _limitedInStream; + + CBufPtrSeqOutStream *_outStreamSpec; + CMyComPtr _outStream; + + NCompress::NLzma::CDecoder *_lzmaDecoderSpec; + CMyComPtr _lzmaDecoder; + + NCompress::NZlib::CDecoder *_zlibDecoderSpec; + CMyComPtr _zlibDecoder; + + CByteBuffer _inputBuffer; + + CDynBufSeqOutStream *_dynOutStreamSpec; + CMyComPtr _dynOutStream; + + void ClearCache() + { + _cachedBlockStartPos = 0; + _cachedPackBlockSize = 0; + _cachedUnpackBlockSize = 0; + } + + HRESULT Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool *outBufWasWritten, UInt32 *outBufWasWrittenSize, + UInt32 inSize, UInt32 outSizeMax); + HRESULT ReadMetadataBlock(UInt32 &packSize); + HRESULT ReadData(CData &data, UInt64 start, UInt64 end); + + HRESULT OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned level, int &nodeIndex); + HRESULT ScanInodes(UInt64 ptr); + // HRESULT ReadUids(UInt64 start, UInt32 num, CByteBuffer &ids); + HRESULT Open2(IInStream *inStream); + AString GetPath(int index) const; + bool GetPackSize(int index, UInt64 &res, bool fillOffsets); + +public: + CHandler(); + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); + + HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize); +}; + +CHandler::CHandler() +{ + _limitedInStreamSpec = new CLimitedSequentialInStream; + _limitedInStream = _limitedInStreamSpec; + + _outStreamSpec = new CBufPtrSeqOutStream(); + _outStream = _outStreamSpec; + + _dynOutStreamSpec = new CDynBufSeqOutStream; + _dynOutStream = _dynOutStreamSpec; +} + +static const STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidPosixAttrib, VT_UI4} + // { NULL, kpidUser, VT_BSTR}, + // { NULL, kpidGroup, VT_BSTR}, + // { NULL, kpidLinks, VT_UI4}, + // { NULL, kpidOffset, VT_UI4} +}; + +static const STATPROPSTG kArcProps[] = +{ + { NULL, kpidFileSystem, VT_BSTR}, + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidBlock, VT_UI4}, + { NULL, kpidPhySize, VT_UI8}, + { NULL, kpidHeadersSize, VT_UI8}, + { NULL, kpidBigEndian, VT_BOOL}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidCharacts, VT_BSTR} + // { NULL, kpidNumBlocks, VT_UI4} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +static HRESULT LzoDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen) +{ + SizeT destRem = *destLen; + SizeT srcRem = *srcLen; + *destLen = 0; + *srcLen = 0; + const Byte *destStart = dest; + const Byte *srcStart = src; + unsigned mode = 2; + + { + if (srcRem == 0) + return S_FALSE; + UInt32 b = *src; + if (b > 17) + { + src++; + srcRem--; + b -= 17; + mode = (b < 4 ? 0 : 1); + if (b > srcRem || b > destRem) + return S_FALSE; + srcRem -= b; + destRem -= b; + do + *dest++ = *src++; + while (--b); + } + } + + for (;;) + { + if (srcRem < 3) + return S_FALSE; + UInt32 b = *src++; + srcRem--; + UInt32 len, back; + if (b >= 64) + { + srcRem--; + back = ((b >> 2) & 7) + ((UInt32)*src++ << 3); + len = (b >> 5) + 1; + } + else if (b < 16) + { + if (mode == 2) + { + if (b == 0) + { + for (b = 15;; b += 255) + { + if (srcRem == 0) + return S_FALSE; + UInt32 b2 = *src++; + srcRem--; + if (b2 != 0) + { + b += b2; + break; + } + } + } + b += 3; + if (b > srcRem || b > destRem) + return S_FALSE; + srcRem -= b; + destRem -= b; + mode = 1; + do + *dest++ = *src++; + while (--b); + continue; + } + srcRem--; + back = (b >> 2) + (*src++ << 2); + len = 2; + if (mode == 1) + { + back += (1 << 11); + len = 3; + } + } + else + { + UInt32 bOld = b; + b = (b < 32 ? 7 : 31); + len = bOld & b; + if (len == 0) + { + for (len = b;; len += 255) + { + if (srcRem == 0) + return S_FALSE; + UInt32 b2 = *src++; + srcRem--; + if (b2 != 0) + { + len += b2; + break; + } + } + } + len += 2; + if (srcRem < 2) + return S_FALSE; + b = *src; + back = (b >> 2) + ((UInt32)src[1] << 6); + src += 2; + srcRem -= 2; + if (bOld < 32) + { + if (back == 0) + { + *destLen = dest - destStart; + *srcLen = src - srcStart; + return S_OK; + } + back += ((bOld & 8) << 11) + (1 << 14) - 1; + } + } + back++; + if (len > destRem || (size_t)(dest - destStart) < back) + return S_FALSE; + destRem -= len; + Byte *destTemp = dest - back; + dest += len; + do + { + *(destTemp + back) = *destTemp; + destTemp++; + } + while (--len); + b &= 3; + if (b == 0) + { + mode = 2; + continue; + } + if (b > srcRem || b > destRem) + return S_FALSE; + srcRem -= b; + destRem -= b; + mode = 0; + *dest++ = *src++; + if (b > 1) + { + *dest++ = *src++; + if (b > 2) + *dest++ = *src++; + } + } +} + +HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool *outBufWasWritten, UInt32 *outBufWasWrittenSize, UInt32 inSize, UInt32 outSizeMax) +{ + if (outBuf) + { + *outBufWasWritten = false; + *outBufWasWrittenSize = 0; + } + UInt32 method = _h.Method; + if (_h.SeveralMethods) + { + Byte props[1]; + RINOK(ReadStream_FALSE(_stream, props, 1)); + method = (props[0] == 0x5D ? kMethod_LZMA : kMethod_ZLIB); + RINOK(_stream->Seek(-1, STREAM_SEEK_CUR, NULL)); + } + + if (method == kMethod_LZO) + { + if (_inputBuffer.GetCapacity() < inSize) + { + _inputBuffer.Free(); + _inputBuffer.SetCapacity(inSize); + } + RINOK(ReadStream_FALSE(_stream, _inputBuffer, inSize)); + + Byte *dest = outBuf; + if (!outBuf) + { + dest = _dynOutStreamSpec->GetBufPtrForWriting(outSizeMax); + if (!dest) + return E_OUTOFMEMORY; + } + SizeT destLen = outSizeMax, srcLen = inSize; + RINOK(LzoDecode(dest, &destLen, _inputBuffer, &srcLen)); + if (inSize != srcLen) + return S_FALSE; + if (outBuf) + { + *outBufWasWritten = true; + *outBufWasWrittenSize = (UInt32)destLen; + } + else + _dynOutStreamSpec->UpdateSize(destLen); + } + else if (method == kMethod_LZMA) + { + if (!_lzmaDecoder) + { + _lzmaDecoderSpec = new NCompress::NLzma::CDecoder(); + _lzmaDecoderSpec->FinishStream = true; + _lzmaDecoder = _lzmaDecoderSpec; + } + const UInt32 kPropsSize = 5 + 8; + Byte props[kPropsSize]; + ReadStream_FALSE(_limitedInStream, props, kPropsSize); + RINOK(_lzmaDecoderSpec->SetDecoderProperties2(props, 5)); + UInt64 outSize = GetUi64(props + 5); + if (outSize > outSizeMax) + return S_FALSE; + RINOK(_lzmaDecoder->Code(_limitedInStream, outStream, NULL, &outSize, NULL)); + if (inSize != kPropsSize + _lzmaDecoderSpec->GetInputProcessedSize()) + return S_FALSE; + } + else + { + if (!_zlibDecoder) + { + _zlibDecoderSpec = new NCompress::NZlib::CDecoder(); + _zlibDecoder = _zlibDecoderSpec; + } + RINOK(_zlibDecoder->Code(_limitedInStream, outStream, NULL, NULL, NULL)); + if (inSize != _zlibDecoderSpec->GetInputProcessedSize()) + return S_FALSE; + } + return S_OK; +} + +HRESULT CHandler::ReadMetadataBlock(UInt32 &packSize) +{ + Byte temp[3]; + unsigned offset = _h.NeedCheckData() ? 3 : 2; + if (offset > packSize) + return S_FALSE; + RINOK(ReadStream_FALSE(_stream, temp, offset)); + // if (NeedCheckData && Major < 4) checkByte must be = 0xFF + bool be = _h.be; + UInt32 size = Get16(temp); + bool isCompressed = ((size & kNotCompressedBit16) == 0); + if (size != kNotCompressedBit16) + size &= ~kNotCompressedBit16; + + if (size > kMetadataBlockSize || offset + size > packSize) + return S_FALSE; + packSize = offset + size; + if (isCompressed) + { + _limitedInStreamSpec->Init(size); + RINOK(Decompress(_dynOutStream, NULL, NULL, NULL, size, kMetadataBlockSize)); + } + else + { + // size != 0 here + Byte *buf = _dynOutStreamSpec->GetBufPtrForWriting(size); + if (!buf) + return E_OUTOFMEMORY; + RINOK(ReadStream_FALSE(_stream, buf, size)); + _dynOutStreamSpec->UpdateSize(size); + } + return S_OK; +} + +HRESULT CHandler::ReadData(CData &data, UInt64 start, UInt64 end) +{ + if (end < start || end - start >= ((UInt64)1 << 32)) + return S_FALSE; + UInt32 size = (UInt32)(end - start); + RINOK(_stream->Seek(start, STREAM_SEEK_SET, NULL)); + _dynOutStreamSpec->Init(); + UInt32 packPos = 0; + while (packPos != size) + { + data.PackPos.Add(packPos); + data.UnpackPos.Add((UInt32)_dynOutStreamSpec->GetSize()); + if (packPos > size) + return S_FALSE; + UInt32 packSize = size - packPos; + RINOK(ReadMetadataBlock(packSize)); + if (_dynOutStreamSpec->GetSize() >= ((UInt64)1 << 32)) + return S_FALSE; + packPos += packSize; + } + data.UnpackPos.Add((UInt32)_dynOutStreamSpec->GetSize()); + _dynOutStreamSpec->CopyToBuffer(data.Data); + return S_OK; +} + +struct CTempItem +{ + UInt32 StartBlock; + // UInt32 iNodeNumber1; + UInt32 Offset; + // UInt16 iNodeNumber2; + UInt16 Type; +}; + +HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned level, int &nodeIndex) +{ + if (level > kNumDirLevelsMax) + return S_FALSE; + + int blockIndex = _inodesData.PackPos.FindInSorted(startBlock); + if (blockIndex < 0) + return S_FALSE; + UInt32 unpackPos = _inodesData.UnpackPos[blockIndex] + offset; + if (unpackPos < offset) + return S_FALSE; + + nodeIndex = _nodesPos.FindInSorted(unpackPos, _blockToNode[blockIndex], _blockToNode[blockIndex + 1]); + // nodeIndex = _nodesPos.FindInSorted(unpackPos); + if (nodeIndex < 0) + return S_FALSE; + + const CNode &n = _nodes[nodeIndex]; + if (!n.IsDir()) + return S_OK; + blockIndex = _dirs.PackPos.FindInSorted((UInt32)n.StartBlock); + if (blockIndex < 0) + return S_FALSE; + unpackPos = _dirs.UnpackPos[blockIndex] + n.Offset; + if (unpackPos < n.Offset || unpackPos > _dirs.Data.GetCapacity()) + return S_FALSE; + + UInt32 rem = (UInt32)_dirs.Data.GetCapacity() - unpackPos; + const Byte *p = _dirs.Data + unpackPos; + UInt32 fileSize = (UInt32)n.FileSize; + + if (fileSize > rem) + return S_FALSE; + rem = fileSize; + if (_h.Major >= 3) + { + if (rem < 3) + return S_FALSE; + rem -= 3; + } + + CRecordVector tempItems; + while (rem != 0) + { + bool be = _h.be; + UInt32 count; + CTempItem tempItem; + if (_h.Major <= 2) + { + if (rem < 4) + return S_FALSE; + count = p[0]; + tempItem.StartBlock = Get32(p); + if (be) + tempItem.StartBlock &= 0xFFFFFF; + else + tempItem.StartBlock >>= 8; + p += 4; + rem -= 4; + } + else + { + if (_h.Major == 3) + { + if (rem < 9) + return S_FALSE; + count = p[0]; + p += 1; + rem -= 1; + } + else + { + if (rem < 12) + return S_FALSE; + count = GetUi32(p); + p += 4; + rem -= 4; + } + GET_32 (0, tempItem.StartBlock); + // GET_32 (4, tempItem.iNodeNumber1); + p += 8; + rem -= 8; + } + count++; + + for (UInt32 i = 0; i < count; i++) + { + if (rem == 0) + return S_FALSE; + + UInt32 nameOffset = _h.GetFileNameOffset(); + if (rem < nameOffset) + return S_FALSE; + + if ((UInt32)_items.Size() >= kNumFilesMax) + return S_FALSE; + if (_openCallback) + { + UInt64 numFiles = _items.Size(); + if ((numFiles & 0xFFFF) == 0) + { + RINOK(_openCallback->SetCompleted(&numFiles, NULL)); + } + } + + CItem item; + item.Ptr = (UInt32)(p - _dirs.Data); + + UInt32 size; + if (_h.IsOldVersion()) + { + UInt32 t = Get16(p); + if (be) + { + tempItem.Offset = t >> 3; + tempItem.Type = (UInt16)(t & 0x7); + } + else + { + tempItem.Offset = t & 0x1FFF; + tempItem.Type = (UInt16)(t >> 13); + } + size = (UInt32)p[2]; + /* + if (_h.Major > 2) + tempItem.iNodeNumber2 = Get16(p + 3); + */ + } + else + { + GET_16 (0, tempItem.Offset); + // GET_16 (2, tempItem.iNodeNumber2); + GET_16 (4, tempItem.Type); + GET_16 (6, size); + } + p += nameOffset; + rem -= nameOffset; + size++; + if (rem < size) + return S_FALSE; + p += size; + rem -= size; + item.Parent = parent; + _items.Add(item); + tempItems.Add(tempItem); + } + } + + int startItemIndex = _items.Size() - tempItems.Size(); + for (int i = 0; i < tempItems.Size(); i++) + { + const CTempItem &tempItem = tempItems[i]; + int index = startItemIndex + i; + CItem &item = _items[index]; + RINOK(OpenDir(index, tempItem.StartBlock, tempItem.Offset, level + 1, item.Node)); + } + + return S_OK; +} + +/* +HRESULT CHandler::ReadUids(UInt64 start, UInt32 num, CByteBuffer &ids) +{ + size_t size = num * 4; + ids.SetCapacity(size); + RINOK(_stream->Seek(start, STREAM_SEEK_SET, NULL)); + return ReadStream_FALSE(_stream, ids, size); +} +*/ + +HRESULT CHandler::Open2(IInStream *inStream) +{ + { + Byte buf[kHeaderSize3]; + RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize3)); + if (!_h.Parse(buf)) + return S_FALSE; + if (!_h.IsSupported()) + return E_NOTIMPL; + + switch (_h.Method) + { + case kMethod_ZLIB: + case kMethod_LZMA: + case kMethod_LZO: + break; + default: + return E_NOTIMPL; + } + } + + _stream = inStream; + + if (_h.NumFrags != 0) + { + if (_h.NumFrags > kNumFilesMax) + return S_FALSE; + _frags.Reserve(_h.NumFrags); + CByteBuffer data; + unsigned bigFrag = (_h.Major > 2); + + unsigned fragPtrsInBlockLog = kMetadataBlockSizeLog - (3 + bigFrag); + UInt32 numBlocks = (_h.NumFrags + (1 << fragPtrsInBlockLog) - 1) >> fragPtrsInBlockLog; + size_t numBlocksBytes = (size_t)numBlocks << (2 + bigFrag); + data.SetCapacity(numBlocksBytes); + RINOK(inStream->Seek(_h.FragTable, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream_FALSE(inStream, data, numBlocksBytes)); + bool be = _h.be; + + for (UInt32 i = 0; i < numBlocks; i++) + { + UInt64 offset = bigFrag ? Get64(data + i * 8) : Get32(data + i * 4); + RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL)); + _dynOutStreamSpec->Init(); + UInt32 packSize = kMetadataBlockSize + 3; + RINOK(ReadMetadataBlock(packSize)); + UInt32 unpackSize = (UInt32)_dynOutStreamSpec->GetSize(); + if (unpackSize != kMetadataBlockSize) + if (i != numBlocks - 1 || unpackSize != ((_h.NumFrags << (3 + bigFrag)) & (kMetadataBlockSize - 1))) + return S_FALSE; + const Byte *buf = _dynOutStreamSpec->GetBuffer(); + for (UInt32 j = 0; j < kMetadataBlockSize && j < unpackSize;) + { + CFrag frag; + if (bigFrag) + { + frag.StartBlock = Get64(buf + j); + frag.Size = Get32(buf + j + 8); + // some archives contain nonzero in unused (buf + j + 12) + j += 16; + } + else + { + frag.StartBlock = Get32(buf + j); + frag.Size = Get32(buf + j + 4); + j += 8; + } + _frags.Add(frag); + } + } + if ((UInt32)_frags.Size() != _h.NumFrags) + return S_FALSE; + } + + // RINOK(inStream->Seek(_h.InodeTable, STREAM_SEEK_SET, NULL)); + + RINOK(ReadData(_inodesData, _h.InodeTable, _h.DirTable)); + RINOK(ReadData(_dirs, _h.DirTable, _h.FragTable)); + + UInt64 absOffset = _h.RootInode >> 16; + if (absOffset >= ((UInt64)1 << 32)) + return S_FALSE; + { + UInt32 pos = 0; + UInt32 totalSize = (UInt32)_inodesData.Data.GetCapacity(); + _nodesPos.Reserve(_h.NumInodes); + _nodes.Reserve(_h.NumInodes); + // we use _blockToNode for binary search seed optimizations + _blockToNode.Reserve(_inodesData.GetNumBlocks() + 1); + int curBlock = 0; + for (UInt32 i = 0; i < _h.NumInodes; i++) + { + CNode n; + const Byte *p = _inodesData.Data + pos; + UInt32 size = totalSize - pos; + + switch(_h.Major) + { + case 1: size = n.Parse1(p, size, _h); break; + case 2: size = n.Parse2(p, size, _h); break; + case 3: size = n.Parse3(p, size, _h); break; + default: size = n.Parse4(p, size, _h); break; + } + if (size == 0) + return S_FALSE; + while (pos >= _inodesData.UnpackPos[curBlock]) + { + _blockToNode.Add(_nodesPos.Size()); + curBlock++; + } + _nodesPos.Add(pos); + _nodes.Add(n); + pos += size; + } + _blockToNode.Add(_nodesPos.Size()); + if (pos != totalSize) + return S_FALSE; + } + int rootNodeIndex; + RINOK(OpenDir(-1, (UInt32)absOffset, (UInt32)_h.RootInode & 0xFFFF, 0, rootNodeIndex)); + + /* + if (_h.Major < 4) + { + RINOK(ReadUids(_h.UidTable, _h.NumUids, _uids)); + RINOK(ReadUids(_h.GidTable, _h.NumGids, _gids)); + } + else + { + UInt32 size = _h.NumIDs * 4; + _uids.SetCapacity(size); + + UInt32 numBlocks = (size + kMetadataBlockSize - 1) / kMetadataBlockSize; + UInt32 numBlocksBytes = numBlocks << 3; + CByteBuffer data; + data.SetCapacity(numBlocksBytes); + RINOK(inStream->Seek(_h.UidTable, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream_FALSE(inStream, data, numBlocksBytes)); + + for (UInt32 i = 0; i < numBlocks; i++) + { + UInt64 offset = GetUi64(data + i * 8); + UInt32 unpackSize, packSize; + RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL)); + RINOK(ReadMetadataBlock(NULL, _uids + kMetadataBlockSize * i, packSize, unpackSize)); + if (unpackSize != kMetadataBlockSize) + if (i != numBlocks - 1 || unpackSize != (size & (kMetadataBlockSize - 1))) + return S_FALSE; + } + } + */ + + { + const UInt32 alignSize = 1 << 12; + Byte buf[alignSize]; + RINOK(inStream->Seek(_h.Size, STREAM_SEEK_SET, NULL)); + UInt32 rem = (UInt32)(0 - _h.Size) & (alignSize - 1); + _sizeCalculated = _h.Size; + if (rem != 0) + { + if (ReadStream_FALSE(_stream, buf, rem) == S_OK) + { + size_t i; + for (i = 0; i < rem && buf[i] == 0; i++); + if (i == rem) + _sizeCalculated = _h.Size + rem; + } + } + } + return S_OK; +} + +AString CHandler::GetPath(int index) const +{ + unsigned len = 0; + int indexMem = index; + bool be = _h.be; + do + { + const CItem &item = _items[index]; + index = item.Parent; + const Byte *p = _dirs.Data + item.Ptr; + unsigned size = (_h.IsOldVersion() ? (unsigned)p[2] : (unsigned)Get16(p + 6)) + 1; + p += _h.GetFileNameOffset(); + unsigned i; + for (i = 0; i < size && p[i]; i++); + len += i + 1; + } + while (index >= 0); + len--; + + AString path; + char *dest = path.GetBuffer(len) + len; + index = indexMem; + for (;;) + { + const CItem &item = _items[index]; + index = item.Parent; + + const Byte *p = _dirs.Data + item.Ptr; + unsigned size = (_h.IsOldVersion() ? (unsigned)p[2] : (unsigned)Get16(p + 6)) + 1; + p += _h.GetFileNameOffset(); + unsigned i; + for (i = 0; i < size && p[i]; i++); + dest -= i; + memcpy(dest, p, i); + if (index < 0) + break; + *(--dest) = CHAR_PATH_SEPARATOR; + } + path.ReleaseBuffer(len); + return path; +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + { + Close(); + _limitedInStreamSpec->SetStream(stream); + HRESULT res; + try + { + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + _openCallback = callback; + res = Open2(stream); + } + catch(...) + { + Close(); + throw; + } + if (res != S_OK) + { + Close(); + return res; + } + _stream = stream; + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _limitedInStreamSpec->ReleaseStream(); + _stream.Release(); + + _items.Clear(); + _nodes.Clear(); + _nodesPos.Clear(); + _blockToNode.Clear(); + _frags.Clear(); + _inodesData.Clear(); + _dirs.Clear(); + + // _uids.Free(); + // _gids.Free();; + + _cachedBlock.Free(); + ClearCache(); + + return S_OK; +} + +bool CHandler::GetPackSize(int index, UInt64 &totalPack, bool fillOffsets) +{ + totalPack = 0; + const CItem &item = _items[index]; + const CNode &node = _nodes[item.Node]; + UInt32 ptr = _nodesPos[item.Node]; + const Byte *p = _inodesData.Data + ptr; + bool be = _h.be; + + UInt32 type = node.Type; + UInt32 offset; + if (node.IsLink() || node.FileSize == 0) + { + totalPack = node.FileSize; + return true; + } + + UInt32 numBlocks = (UInt32)node.GetNumBlocks(_h); + + if (fillOffsets) + { + _blockOffsets.Clear(); + _blockCompressed.Clear(); + _blockOffsets.Add(totalPack); + } + + if (_h.Major <= 1) + { + offset = 15; + p += offset; + + for (UInt32 i = 0; i < numBlocks; i++) + { + UInt32 t = Get16(p + i * 2); + if (fillOffsets) + _blockCompressed.Add((t & kNotCompressedBit16) == 0); + if (t != kNotCompressedBit16) + t &= ~kNotCompressedBit16; + totalPack += t; + if (fillOffsets) + _blockOffsets.Add(totalPack); + } + } + else + { + if (_h.Major <= 2) + offset = 24; + else if (type == kType_FILE) + offset = 32; + else if (type == kType_FILE + 7) + offset = (_h.Major <= 3 ? 40 : 56); + else + return false; + + p += offset; + + for (UInt64 i = 0; i < numBlocks; i++) + { + UInt32 t = Get32(p + i * 4); + if (fillOffsets) + _blockCompressed.Add(IS_COMPRESSED_BLOCK(t)); + UInt32 size = GET_COMPRESSED_BLOCK_SIZE(t); + if (size > _h.BlockSize) + return false; + totalPack += size; + if (fillOffsets) + _blockOffsets.Add(totalPack); + } + + if (node.ThereAreFrags()) + { + if (node.Frag >= (UInt32)_frags.Size()) + return false; + const CFrag &frag = _frags[node.Frag]; + if (node.Offset == 0) + { + UInt32 size = GET_COMPRESSED_BLOCK_SIZE(frag.Size); + if (size > _h.BlockSize) + return false; + totalPack += size; + } + } + } + return true; +} + + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _items.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidMethod: + { + const char *s; + if (_h.SeveralMethods) + s = "LZMA ZLIB"; + else + { + s = k_Methods[0]; + if (_h.Method < sizeof(k_Methods) / sizeof(k_Methods[0])) + s = k_Methods[_h.Method]; + } + prop = s; + break; + } + case kpidFileSystem: + { + AString res = "SquashFS"; + if (_h.SeveralMethods) + res += "-LZMA"; + res += ' '; + char s[16]; + ConvertUInt32ToString(_h.Major, s); + res += s; + res += '.'; + ConvertUInt32ToString(_h.Minor, s); + res += s; + prop = res; + break; + } + case kpidBlock: prop = _h.BlockSize; break; + case kpidBigEndian: prop = _h.be; break; + case kpidCTime: + if (_h.CTime != 0) + { + FILETIME ft; + NWindows::NTime::UnixTimeToFileTime(_h.CTime, ft); + prop = ft; + } + break; + case kpidCharacts: FLAGS_TO_PROP(k_Flags, _h.Flags, prop); break; + // case kpidNumBlocks: prop = _h.NumFrags; break; + case kpidPhySize: prop = _sizeCalculated; break; + case kpidHeadersSize: + if (_sizeCalculated >= _h.InodeTable) + prop = _sizeCalculated - _h.InodeTable; + break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + const CItem &item = _items[index]; + const CNode &node = _nodes[item.Node]; + bool isDir = node.IsDir(); + bool be = _h.be; + + switch(propID) + { + case kpidPath: prop = MultiByteToUnicodeString(GetPath(index), CP_OEMCP); break; + case kpidIsDir: prop = isDir; break; + // case kpidOffset: if (!node.IsLink()) prop = (UInt64)node.StartBlock; break; + case kpidSize: if (!isDir) prop = node.GetSize(); break; + case kpidPackSize: + if (!isDir) + { + UInt64 size; + if (GetPackSize(index, size, false)) + prop = size; + } + break; + case kpidMTime: + { + UInt32 offset = 0; + switch(_h.Major) + { + case 1: + if (node.Type == kType_FILE) + offset = 3; + else if (node.Type == kType_DIR) + offset = 7; + break; + case 2: + if (node.Type == kType_FILE) + offset = 4; + else if (node.Type == kType_DIR) + offset = 8; + else if (node.Type == kType_DIR + 7) + offset = 9; + break; + case 3: offset = 4; break; + case 4: offset = 8; break; + } + if (offset != 0) + { + const Byte *p = _inodesData.Data + _nodesPos[item.Node] + offset; + FILETIME ft; + NWindows::NTime::UnixTimeToFileTime(Get32(p), ft); + prop = ft; + } + break; + } + case kpidPosixAttrib: + { + if (node.Type != 0 && node.Type < sizeof(k_TypeToMode) / sizeof(k_TypeToMode[0])) + prop = (UInt32)(node.Mode & 0xFFF) | k_TypeToMode[node.Type]; + break; + } + /* + case kpidUser: + { + UInt32 offset = node.Uid * 4; + if (offset < _uids.GetCapacity()) + prop = (UInt32)Get32(_uids + offset); + break; + } + case kpidGroup: + { + if (_h.Major == 4 || node.Gid == _h.GetSpecGuidIndex()) + { + UInt32 offset = node.Uid * 4; + if (offset < _uids.GetCapacity()) + prop = (UInt32)Get32(_uids + offset); + } + else + { + UInt32 offset = node.Gid * 4; + if (offset < _gids.GetCapacity()) + prop = (UInt32)Get32(_gids + offset); + } + break; + } + */ + /* + case kpidLinks: + if (_h.Major >= 3 && node.Type != kType_FILE) + prop = node.NumLinks; + break; + */ + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +class CSquashfsInStream: public CCachedInStream +{ + HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize); +public: + CHandler *Handler; +}; + +HRESULT CSquashfsInStream::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) +{ + return Handler->ReadBlock(blockIndex, dest, blockSize); +} + +HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) +{ + const CNode &node = _nodes[_nodeIndex]; + UInt64 blockOffset; + UInt32 packBlockSize; + UInt32 offsetInBlock = 0; + bool compressed; + if (blockIndex < _blockCompressed.Size()) + { + compressed = _blockCompressed[(int)blockIndex]; + blockOffset = _blockOffsets[(int)blockIndex]; + packBlockSize = (UInt32)(_blockOffsets[(int)blockIndex + 1] - blockOffset); + blockOffset += node.StartBlock; + } + else + { + if (!node.ThereAreFrags()) + return S_FALSE; + const CFrag &frag = _frags[node.Frag]; + offsetInBlock = node.Offset; + blockOffset = frag.StartBlock; + packBlockSize = GET_COMPRESSED_BLOCK_SIZE(frag.Size); + compressed = IS_COMPRESSED_BLOCK(frag.Size); + } + + if (packBlockSize == 0) + { + // sparse file ??? + memset(dest, 0, blockSize); + return S_OK; + } + + if (blockOffset != _cachedBlockStartPos || + packBlockSize != _cachedPackBlockSize) + { + ClearCache(); + RINOK(_stream->Seek(blockOffset, STREAM_SEEK_SET, NULL)); + _limitedInStreamSpec->Init(packBlockSize); + + if (compressed) + { + _outStreamSpec->Init((Byte *)_cachedBlock, _h.BlockSize); + bool outBufWasWritten; + UInt32 outBufWasWrittenSize; + HRESULT res = Decompress(_outStream, _cachedBlock, &outBufWasWritten, &outBufWasWrittenSize, packBlockSize, _h.BlockSize); + if (outBufWasWritten) + _cachedUnpackBlockSize = outBufWasWrittenSize; + else + _cachedUnpackBlockSize = (UInt32)_outStreamSpec->GetPos(); + RINOK(res); + } + else + { + RINOK(ReadStream_FALSE(_limitedInStream, _cachedBlock, packBlockSize)); + _cachedUnpackBlockSize = packBlockSize; + } + _cachedBlockStartPos = blockOffset; + _cachedPackBlockSize = packBlockSize; + } + if (offsetInBlock + blockSize > _cachedUnpackBlockSize) + return S_FALSE; + memcpy(dest, _cachedBlock + offsetInBlock, blockSize); + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _items.Size(); + if (numItems == 0) + return S_OK; + UInt64 totalSize = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + { + const CItem &item = _items[allFilesMode ? i : indices[i]]; + const CNode &node = _nodes[item.Node]; + totalSize += node.GetSize(); + } + extractCallback->SetTotal(totalSize); + + UInt64 totalPackSize; + totalSize = totalPackSize = 0; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + for (i = 0; i < numItems; i++) + { + lps->InSize = totalPackSize; + lps->OutSize = totalSize; + RINOK(lps->SetCur()); + CMyComPtr outStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + UInt32 index = allFilesMode ? i : indices[i]; + const CItem &item = _items[index]; + const CNode &node = _nodes[item.Node]; + RINOK(extractCallback->GetStream(index, &outStream, askMode)); + // const Byte *p = _data + item.Offset; + + if (node.IsDir()) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + UInt64 unpackSize = node.GetSize(); + totalSize += unpackSize; + UInt64 packSize; + if (GetPackSize(index, packSize, false)) + totalPackSize += packSize; + + if (!testMode && !outStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + + int res = NExtract::NOperationResult::kDataError; + { + CMyComPtr inSeqStream; + CMyComPtr inStream; + HRESULT hres = GetStream(index, &inSeqStream); + if (inSeqStream) + inSeqStream.QueryInterface(IID_IInStream, &inStream); + if (hres == S_FALSE || !inStream) + { + if (hres == E_OUTOFMEMORY) + return hres; + res = NExtract::NOperationResult::kUnSupportedMethod; + } + else + { + RINOK(hres); + if (inStream) + { + HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress); + if (hres != S_OK && hres != S_FALSE) + { + RINOK(hres); + } + if (copyCoderSpec->TotalSize == unpackSize && hres == S_OK) + res = NExtract::NOperationResult::kOK; + else + { + res = res; + } + } + } + } + RINOK(extractCallback->SetOperationResult(res)); + } + return S_OK; + COM_TRY_END +} + + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + + const CItem &item = _items[index]; + const CNode &node = _nodes[item.Node]; + + if (node.IsDir()) + return E_FAIL; + + const Byte *p = _inodesData.Data + _nodesPos[item.Node]; + + if (node.FileSize == 0 || node.IsLink()) + { + CBufInStream *streamSpec = new CBufInStream; + CMyComPtr streamTemp = streamSpec; + if (node.IsLink()) + streamSpec->Init(p + _h.GetSymLinkOffset(), (size_t)node.FileSize); + else + streamSpec->Init(NULL, 0); + *stream = streamTemp.Detach(); + return S_OK; + } + + UInt64 packSize; + if (!GetPackSize(index, packSize, true)) + return S_FALSE; + + _nodeIndex = item.Node; + + size_t cacheSize = _h.BlockSize; + if (_cachedBlock.GetCapacity() != cacheSize) + { + ClearCache(); + _cachedBlock.SetCapacity(cacheSize); + } + + CSquashfsInStream *streamSpec = new CSquashfsInStream; + CMyComPtr streamTemp = streamSpec; + streamSpec->Handler = this; + unsigned cacheSizeLog = 22; + if (cacheSizeLog <= _h.BlockSizeLog) + cacheSizeLog = _h.BlockSizeLog + 1; + if (!streamSpec->Alloc(_h.BlockSizeLog, cacheSizeLog - _h.BlockSizeLog)) + return E_OUTOFMEMORY; + streamSpec->Init(node.FileSize); + *stream = streamTemp.Detach(); + + return S_OK; + + COM_TRY_END +} + +static IInArchive *CreateArc() { return new NArchive::NSquashfs::CHandler; } + +static CArcInfo g_ArcInfo = + { L"SquashFS", L"squashfs", 0, 0xD2, SIGNATURE, kSignatureSize, false, CreateArc, 0 }; + +REGISTER_ARC(Cramfs) + +}} diff --git a/CPP/7zip/Archive/StdAfx.h b/CPP/7zip/Archive/StdAfx.h new file mode 100755 index 0000000..f56e92f --- /dev/null +++ b/CPP/7zip/Archive/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../Common/MyWindows.h" +#include "../../Common/NewHandler.h" + +#endif diff --git a/CPP/7zip/Archive/SwfHandler.cpp b/CPP/7zip/Archive/SwfHandler.cpp new file mode 100755 index 0000000..398aa0f --- /dev/null +++ b/CPP/7zip/Archive/SwfHandler.cpp @@ -0,0 +1,706 @@ +// SwfHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Common/Buffer.h" +#include "Common/ComTry.h" +#include "Common/IntToString.h" +#include "Common/MyString.h" + +#include "Windows/PropVariant.h" + +#include "../Common/InBuffer.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" +#include "../Compress/ZlibDecoder.h" +#include "../Compress/ZlibEncoder.h" + +#include "Common/DummyOutStream.h" + +#include "DeflateProps.h" + +using namespace NWindows; + +namespace NArchive { +namespace NSwfc { + +static const UInt32 kHeaderSize = 8; + +static const Byte SWF_UNCOMPRESSED = 'F'; +static const Byte SWF_COMPRESSED = 'C'; +static const Byte SWF_MIN_COMPRESSED_VER = 6; + +struct CItem +{ + Byte Buf[kHeaderSize]; + + UInt32 GetSize() const { return GetUi32(Buf + 4); } + bool IsSwf(Byte c) const { return (Buf[0] == c && Buf[1] == 'W' && Buf[2] == 'S' && Buf[3] < 32); } + bool IsUncompressed() const { return IsSwf(SWF_UNCOMPRESSED); } + bool IsCompressed() const { return IsSwf(SWF_COMPRESSED); } + + void MakeUncompressed() { Buf[0] = SWF_UNCOMPRESSED; } + void MakeCompressed() + { + Buf[0] = SWF_COMPRESSED; + if (Buf[3] < SWF_MIN_COMPRESSED_VER) + Buf[3] = SWF_MIN_COMPRESSED_VER; + } + + HRESULT ReadHeader(ISequentialInStream *stream) { return ReadStream_FALSE(stream, Buf, kHeaderSize); } + HRESULT WriteHeader(ISequentialOutStream *stream) { return WriteStream(stream, Buf, kHeaderSize); } +}; + +class CHandler: + public IInArchive, + public IArchiveOpenSeq, + public IOutArchive, + public ISetProperties, + public CMyUnknownImp +{ + CItem _item; + UInt64 _packSize; + bool _packSizeDefined; + CMyComPtr _seqStream; + CMyComPtr _stream; + + CDeflateProps _method; + +public: + MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties) + INTERFACE_IInArchive(;) + INTERFACE_IOutArchive(;) + STDMETHOD(OpenSeq)(ISequentialInStream *stream); + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps); +}; + +STATPROPSTG kProps[] = +{ + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO_Table + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidPhySize: if (_packSizeDefined) prop = _packSize; break; + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = 1; + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +{ + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidSize: prop = (UInt64)_item.GetSize(); break; + case kpidPackSize: if (_packSizeDefined) prop = _packSize; break; + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *) +{ + RINOK(OpenSeq(stream)); + _stream = stream; + return S_OK; +} + +STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) +{ + Close(); + HRESULT res = _item.ReadHeader(stream); + if (res == S_OK) + if (_item.IsCompressed()) + _seqStream = stream; + else + res = S_FALSE; + return res; +} + +STDMETHODIMP CHandler::Close() +{ + _packSizeDefined = false; + _seqStream.Release(); + _stream.Release(); + 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)-1 && (numItems != 1 || indices[0] != 0)) + return E_INVALIDARG; + + extractCallback->SetTotal(_item.GetSize()); + 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); + + NCompress::NZlib::CDecoder *_decoderSpec = new NCompress::NZlib::CDecoder; + CMyComPtr _decoder = _decoderSpec; + + CDummyOutStream *outStreamSpec = new CDummyOutStream; + CMyComPtr outStream(outStreamSpec); + outStreamSpec->SetStream(realOutStream); + outStreamSpec->Init(); + realOutStream.Release(); + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + lps->InSize = kHeaderSize; + lps->OutSize = outStreamSpec->GetSize(); + RINOK(lps->SetCur()); + + CItem item = _item; + item.MakeUncompressed(); + RINOK(item.WriteHeader(outStream)); + if (_stream) + RINOK(_stream->Seek(kHeaderSize, STREAM_SEEK_SET, NULL)); + HRESULT result = _decoderSpec->Code(_seqStream, outStream, NULL, NULL, progress); + Int32 opRes = NExtract::NOperationResult::kDataError; + if (result == S_OK) + { + if (_item.GetSize() == outStreamSpec->GetSize()) + { + _packSizeDefined = true; + _packSize = _decoderSpec->GetInputProcessedSize() + kHeaderSize; + opRes = NExtract::NOperationResult::kOK; + } + } + else if (result != S_FALSE) + return result; + + outStream.Release(); + return extractCallback->SetOperationResult(opRes); + COM_TRY_END +} + +static HRESULT UpdateArchive(ISequentialOutStream *outStream, + UInt64 size, CDeflateProps &deflateProps, + IArchiveUpdateCallback *updateCallback) +{ + UInt64 complexity = 0; + RINOK(updateCallback->SetTotal(size)); + RINOK(updateCallback->SetCompleted(&complexity)); + + CMyComPtr fileInStream; + RINOK(updateCallback->GetStream(0, &fileInStream)); + + CItem item; + HRESULT res = item.ReadHeader(fileInStream); + if (res == S_FALSE) + return E_INVALIDARG; + RINOK(res); + if (!item.IsUncompressed() || size != item.GetSize()) + return E_INVALIDARG; + + item.MakeCompressed(); + item.WriteHeader(outStream); + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(updateCallback, true); + + NCompress::NZlib::CEncoder *encoderSpec = new NCompress::NZlib::CEncoder; + CMyComPtr encoder = encoderSpec; + encoderSpec->Create(); + RINOK(deflateProps.SetCoderProperties(encoderSpec->DeflateEncoderSpec)); + RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, progress)); + if (encoderSpec->GetInputProcessedSize() + kHeaderSize != size) + return E_INVALIDARG; + return updateCallback->SetOperationResult(NUpdate::NOperationResult::kOK); +} + +STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) +{ + *timeType = NFileTimeType::kUnix; + return S_OK; +} + +STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, + IArchiveUpdateCallback *updateCallback) +{ + 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_BOOL) + { + if (prop.boolVal != VARIANT_FALSE) + return E_INVALIDARG; + } + else if (prop.vt != VT_EMPTY) + 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; + } + return UpdateArchive(outStream, size, _method, updateCallback); + } + + if (indexInArchive != 0) + return E_INVALIDARG; + + if (!_seqStream) + return E_NOTIMPL; + + if (_stream) + { + RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL)); + } + else + _item.WriteHeader(outStream); + return NCompress::CopyStream(_seqStream, outStream, NULL); +} + +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) +{ + return _method.SetProperties(names, values, numProps); +} + +static IInArchive *CreateArc() { return new CHandler; } +#ifndef EXTRACT_ONLY +static IOutArchive *CreateArcOut() { return new CHandler; } +#else +#define CreateArcOut 0 +#endif + +static CArcInfo g_ArcInfo = + { L"SWFc", L"swf", L"~.swf", 0xD8, { 'C', 'W', 'S' }, 3, true, CreateArc, CreateArcOut }; + +REGISTER_ARC(Swfc) + +} + +namespace NSwf { + +static const UInt32 kFileSizeMax = (UInt32)1 << 30; +static const int kNumTagsMax = (UInt32)1 << 23; + +struct CTag +{ + UInt32 Type; + CByteBuffer Buf; +}; + +class CHandler: + public IInArchive, + public IArchiveOpenSeq, + public CMyUnknownImp +{ + CObjectVector _tags; + NSwfc::CItem _item; + UInt64 _packSize; + + HRESULT OpenSeq3(ISequentialInStream *stream, IArchiveOpenCallback *callback); + HRESULT OpenSeq2(ISequentialInStream *stream, IArchiveOpenCallback *callback); +public: + MY_UNKNOWN_IMP2(IInArchive, IArchiveOpenSeq) + INTERFACE_IInArchive(;) + + STDMETHOD(OpenSeq)(ISequentialInStream *stream); +}; + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidComment, VT_BSTR} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO_Table + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidPhySize: prop = _packSize; break; + } + prop.Detach(value); + return S_OK; +} + + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _tags.Size(); + return S_OK; +} + +static const char *g_TagDesc[92] = +{ + "End", + "ShowFrame", + "DefineShape", + NULL, + "PlaceObject", + "RemoveObject", + "DefineBits", + "DefineButton", + "JPEGTables", + "SetBackgroundColor", + "DefineFont", + "DefineText", + "DoAction", + "DefineFontInfo", + "DefineSound", + "StartSound", + NULL, + "DefineButtonSound", + "SoundStreamHead", + "SoundStreamBlock", + "DefineBitsLossless", + "DefineBitsJPEG2", + "DefineShape2", + "DefineButtonCxform", + "Protect", + NULL, + "PlaceObject2", + NULL, + "RemoveObject2", + NULL, + NULL, + NULL, + "DefineShape3", + "DefineText2", + "DefineButton2", + "DefineBitsJPEG3", + "DefineBitsLossless2", + "DefineEditText", + NULL, + "DefineSprite", + NULL, + "41", + NULL, + "FrameLabel", + NULL, + "SoundStreamHead2", + "DefineMorphShape", + NULL, + "DefineFont2", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "ExportAssets", + "ImportAssets", + "EnableDebugger", + "DoInitAction", + "DefineVideoStream", + "VideoFrame", + "DefineFontInfo2", + NULL, + "EnableDebugger2", + "ScriptLimits", + "SetTabIndex", + NULL, + NULL, + "FileAttributes", + "PlaceObject3", + "ImportAssets2", + NULL, + "DefineFontAlignZones", + "CSMTextSettings", + "DefineFont3", + "SymbolClass", + "Metadata", + "DefineScalingGrid", + NULL, + NULL, + NULL, + "DoABC", + "DefineShape4", + "DefineMorphShape2", + NULL, + "DefineSceneAndFrameLabelData", + "DefineBinaryData", + "DefineFontName", + "StartSound2", + "DefineBitsJPEG4", + "DefineFont4" +}; + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + NWindows::NCOM::CPropVariant prop; + const CTag &tag = _tags[index]; + switch(propID) + { + case kpidPath: + { + char s[32]; + ConvertUInt32ToString(index, s); + size_t i = strlen(s); + s[i++] = '.'; + ConvertUInt32ToString(tag.Type, s + i); + prop = s; + break; + } + case kpidSize: + case kpidPackSize: + prop = (UInt64)tag.Buf.GetCapacity(); break; + case kpidComment: + if (tag.Type < sizeof(g_TagDesc) / sizeof(g_TagDesc[0])) + { + const char *s = g_TagDesc[tag.Type]; + if (s != NULL) + prop = s; + } + break; + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback) +{ + return OpenSeq2(stream, callback); +} + +static UInt16 Read16(CInBuffer &stream) +{ + UInt16 res = 0; + for (int i = 0; i < 2; i++) + { + Byte b; + if (!stream.ReadByte(b)) + throw 1; + res |= (UInt16)b << (i * 8); + } + return res; +} + +static UInt32 Read32(CInBuffer &stream) +{ + UInt32 res = 0; + for (int i = 0; i < 4; i++) + { + Byte b; + if (!stream.ReadByte(b)) + throw 1; + res |= (UInt32)b << (i * 8); + } + return res; +} + +struct CBitReader +{ + CInBuffer *stream; + unsigned NumBits; + Byte Val; + + CBitReader(): NumBits(0), Val(0) {} + + UInt32 ReadBits(unsigned numBits); +}; + +UInt32 CBitReader::ReadBits(unsigned numBits) +{ + UInt32 res = 0; + while (numBits > 0) + { + if (NumBits == 0) + { + Val = stream->ReadByte(); + NumBits = 8; + } + if (numBits <= NumBits) + { + res <<= numBits; + NumBits -= numBits; + res |= (Val >> NumBits); + Val &= (1 << NumBits) - 1; + break; + } + else + { + res <<= NumBits; + res |= Val; + numBits -= NumBits; + NumBits = 0; + } + } + return res; +} + +HRESULT CHandler::OpenSeq3(ISequentialInStream *stream, IArchiveOpenCallback *callback) +{ + RINOK(_item.ReadHeader(stream)) + if (!_item.IsUncompressed()) + return S_FALSE; + + CInBuffer s; + if (!s.Create(1 << 20)) + return E_OUTOFMEMORY; + s.SetStream(stream); + s.Init(); + { + CBitReader br; + br.stream = &s; + unsigned numBits = br.ReadBits(5); + /* UInt32 xMin = */ br.ReadBits(numBits); + /* UInt32 xMax = */ br.ReadBits(numBits); + /* UInt32 yMin = */ br.ReadBits(numBits); + /* UInt32 yMax = */ br.ReadBits(numBits); + } + /* UInt32 frameDelay = */ Read16(s); + /* UInt32 numFrames = */ Read16(s); + + _tags.Clear(); + UInt64 offsetPrev = 0; + for (;;) + { + UInt32 pair = Read16(s); + UInt32 type = pair >> 6; + UInt32 length = pair & 0x3F; + if (length == 0x3F) + length = Read32(s); + if (type == 0) + break; + UInt64 offset = s.GetProcessedSize() + NSwfc::kHeaderSize + length; + if (offset > kFileSizeMax || _tags.Size() >= kNumTagsMax) + return S_FALSE; + _tags.Add(CTag()); + CTag &tag = _tags.Back(); + tag.Type = type; + tag.Buf.SetCapacity(length); + if (s.ReadBytes(tag.Buf, length) != length) + return S_FALSE; + if (callback && offset >= offsetPrev + (1 << 20)) + { + UInt64 numItems = _tags.Size(); + RINOK(callback->SetCompleted(&numItems, &offset)); + offsetPrev = offset; + } + } + _packSize = s.GetProcessedSize() + NSwfc::kHeaderSize; + return S_OK; +} + +HRESULT CHandler::OpenSeq2(ISequentialInStream *stream, IArchiveOpenCallback *callback) +{ + HRESULT res; + try { res = OpenSeq3(stream, callback); } + catch(...) { res = S_FALSE; } + return res; +} + +STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) +{ + return OpenSeq2(stream, NULL); +} + +STDMETHODIMP CHandler::Close() +{ + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _tags.Size(); + if (numItems == 0) + return S_OK; + UInt64 totalSize = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + totalSize += _tags[allFilesMode ? i : indices[i]].Buf.GetCapacity(); + extractCallback->SetTotal(totalSize); + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + totalSize = 0; + + for (i = 0; i < numItems; i++) + { + lps->InSize = lps->OutSize = totalSize; + RINOK(lps->SetCur()); + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + UInt32 index = allFilesMode ? i : indices[i]; + const CByteBuffer &buf = _tags[index].Buf; + totalSize += buf.GetCapacity(); + + CMyComPtr outStream; + RINOK(extractCallback->GetStream(index, &outStream, askMode)); + if (!testMode && !outStream) + continue; + + RINOK(extractCallback->PrepareOperation(askMode)); + if (outStream) + RINOK(WriteStream(outStream, buf, buf.GetCapacity())); + outStream.Release(); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + } + return S_OK; + COM_TRY_END +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"SWF", L"swf", 0, 0xD7, { 'F', 'W', 'S' }, 3, true, CreateArc, 0 }; + +REGISTER_ARC(Swf) + +}} diff --git a/CPP/7zip/Archive/Tar/StdAfx.h b/CPP/7zip/Archive/Tar/StdAfx.h new file mode 100755 index 0000000..a4e6173 --- /dev/null +++ b/CPP/7zip/Archive/Tar/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" +#include "../../../Common/NewHandler.h" + +#endif diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp new file mode 100755 index 0000000..a0a19a3 --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarHandler.cpp @@ -0,0 +1,386 @@ +// TarHandler.cpp + +#include "StdAfx.h" + +#include "Common/ComTry.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../../Common/LimitedStreams.h" +#include "../../Common/ProgressUtils.h" +#include "../../Common/StreamObjects.h" +#include "../../Common/StreamUtils.h" + +#include "../Common/ItemNameUtils.h" + +#include "TarHandler.h" +#include "TarIn.h" + +using namespace NWindows; + +namespace NArchive { +namespace NTar { + +static const char *kUnexpectedEnd = "Unexpected end of archive"; + +static const STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidPosixAttrib, VT_UI4}, + { NULL, kpidUser, VT_BSTR}, + { NULL, kpidGroup, VT_BSTR}, + { NULL, kpidLink, VT_BSTR} +}; + +static const STATPROPSTG kArcProps[] = +{ + { NULL, kpidPhySize, VT_UI8}, + { NULL, kpidHeadersSize, VT_UI8} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidPhySize: if (_phySizeDefined) prop = _phySize; break; + case kpidHeadersSize: if (_phySizeDefined) prop = _headersSize; break; + case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break; + } + prop.Detach(value); + return S_OK; +} + +HRESULT CHandler::ReadItem2(ISequentialInStream *stream, bool &filled, CItemEx &item) +{ + item.HeaderPos = _phySize; + RINOK(ReadItem(stream, filled, item, _errorMessage)); + _phySize += item.HeaderSize; + _headersSize += item.HeaderSize; + return S_OK; +} + +HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) +{ + UInt64 endPos = 0; + { + RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos)); + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + } + + _phySizeDefined = true; + for (;;) + { + CItemEx item; + bool filled; + RINOK(ReadItem2(stream, filled, item)); + if (!filled) + break; + _items.Add(item); + + RINOK(stream->Seek(item.GetPackSize(), STREAM_SEEK_CUR, &_phySize)); + if (_phySize > endPos) + { + _errorMessage = kUnexpectedEnd; + break; + } + /* + if (_phySize == endPos) + { + _errorMessage = "There are no trailing zero-filled records"; + break; + } + */ + if (callback != NULL) + { + if (_items.Size() == 1) + { + RINOK(callback->SetTotal(NULL, &endPos)); + } + if (_items.Size() % 100 == 0) + { + UInt64 numFiles = _items.Size(); + RINOK(callback->SetCompleted(&numFiles, &_phySize)); + } + } + } + + if (_items.Size() == 0) + { + CMyComPtr openVolumeCallback; + if (!callback) + return S_FALSE; + callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback); + if (!openVolumeCallback) + return S_FALSE; + NCOM::CPropVariant prop; + if (openVolumeCallback->GetProperty(kpidName, &prop) != S_OK) + return S_FALSE; + if (prop.vt != VT_BSTR) + return S_FALSE; + UString baseName = prop.bstrVal; + baseName = baseName.Right(4); + if (baseName.CompareNoCase(L".tar") != 0) + return S_FALSE; + } + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openArchiveCallback) +{ + COM_TRY_BEGIN + { + Close(); + RINOK(Open2(stream, openArchiveCallback)); + _stream = stream; + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) +{ + Close(); + _seqStream = stream; + return S_OK; +} + +STDMETHODIMP CHandler::Close() +{ + _errorMessage.Empty(); + _phySizeDefined = false; + _phySize = 0; + _headersSize = 0; + _curIndex = 0; + _latestIsRead = false; + _items.Clear(); + _seqStream.Release(); + _stream.Release(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = (_stream ? _items.Size() : (UInt32)(Int32)-1); + return S_OK; +} + +CHandler::CHandler() +{ + copyCoderSpec = new NCompress::CCopyCoder(); + copyCoder = copyCoderSpec; +} + +HRESULT CHandler::SkipTo(UInt32 index) +{ + while (_curIndex < index || !_latestIsRead) + { + if (_latestIsRead) + { + UInt64 packSize = _latestItem.GetPackSize(); + RINOK(copyCoderSpec->Code(_seqStream, NULL, &packSize, &packSize, NULL)); + _phySize += copyCoderSpec->TotalSize; + if (copyCoderSpec->TotalSize != packSize) + { + _errorMessage = kUnexpectedEnd; + return S_FALSE; + } + _latestIsRead = false; + _curIndex++; + } + else + { + bool filled; + RINOK(ReadItem2(_seqStream, filled, _latestItem)); + if (!filled) + { + _phySizeDefined = true; + return E_INVALIDARG; + } + _latestIsRead = true; + } + } + return S_OK; +} + +static UString TarStringToUnicode(const AString &s) +{ + return MultiByteToUnicodeString(s, CP_OEMCP); +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + + const CItemEx *item; + if (_stream) + item = &_items[index]; + else + { + if (index < _curIndex) + return E_INVALIDARG; + else + { + RINOK(SkipTo(index)); + item = &_latestItem; + } + } + + switch(propID) + { + case kpidPath: prop = NItemName::GetOSName2(TarStringToUnicode(item->Name)); break; + case kpidIsDir: prop = item->IsDir(); break; + case kpidSize: prop = item->GetUnpackSize(); break; + case kpidPackSize: prop = item->GetPackSize(); break; + case kpidMTime: + if (item->MTime != 0) + { + FILETIME ft; + NTime::UnixTimeToFileTime(item->MTime, ft); + prop = ft; + } + break; + case kpidPosixAttrib: prop = item->Mode; break; + case kpidUser: prop = TarStringToUnicode(item->User); break; + case kpidGroup: prop = TarStringToUnicode(item->Group); break; + case kpidLink: prop = TarStringToUnicode(item->LinkName); 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 + ISequentialInStream *stream = _seqStream; + bool seqMode = (_stream == NULL); + if (!seqMode) + stream = _stream; + + bool allFilesMode = (numItems == (UInt32)-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]].GetUnpackSize(); + extractCallback->SetTotal(totalSize); + + UInt64 totalPackSize; + totalSize = totalPackSize = 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); + + for (i = 0; i < numItems || seqMode; i++) + { + lps->InSize = totalPackSize; + lps->OutSize = totalSize; + RINOK(lps->SetCur()); + CMyComPtr realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + const CItemEx *item; + if (seqMode) + { + HRESULT res = SkipTo(index); + if (res == E_INVALIDARG) + break; + RINOK(res); + item = &_latestItem; + } + else + item = &_items[index]; + + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + UInt64 unpackSize = item->GetUnpackSize(); + totalSize += unpackSize; + totalPackSize += item->GetPackSize(); + if (item->IsDir()) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + bool skipMode = false; + if (!testMode && !realOutStream) + { + if (!seqMode) + continue; + skipMode = true; + askMode = NExtract::NAskMode::kSkip; + } + RINOK(extractCallback->PrepareOperation(askMode)); + + outStreamSpec->SetStream(realOutStream); + realOutStream.Release(); + outStreamSpec->Init(skipMode ? 0 : unpackSize, true); + + if (item->IsLink()) + { + RINOK(WriteStream(outStreamSpec, (const char *)item->LinkName, item->LinkName.Length())); + } + else + { + if (!seqMode) + { + RINOK(_stream->Seek(item->GetDataPosition(), STREAM_SEEK_SET, NULL)); + } + streamSpec->Init(item->GetPackSize()); + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + } + if (seqMode) + { + _latestIsRead = false; + _curIndex++; + } + outStreamSpec->ReleaseStream(); + RINOK(extractCallback->SetOperationResult(outStreamSpec->GetRem() == 0 ? + NExtract::NOperationResult::kOK: + NExtract::NOperationResult::kDataError)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + const CItemEx &item = _items[index]; + if (item.IsLink()) + { + CBufInStream *streamSpec = new CBufInStream; + CMyComPtr streamTemp = streamSpec; + streamSpec->Init((const Byte *)(const char *)item.LinkName, item.LinkName.Length(), (IInArchive *)this); + *stream = streamTemp.Detach(); + return S_OK; + } + return CreateLimitedInStream(_stream, item.GetDataPosition(), item.Size, stream); + COM_TRY_END +} + +}} diff --git a/CPP/7zip/Archive/Tar/TarHandler.h b/CPP/7zip/Archive/Tar/TarHandler.h new file mode 100755 index 0000000..10593da --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarHandler.h @@ -0,0 +1,61 @@ +// TarHandler.h + +#ifndef __TAR_HANDLER_H +#define __TAR_HANDLER_H + +#include "Common/MyCom.h" +#include "../IArchive.h" + +#include "../../Compress/CopyCoder.h" + +#include "TarItem.h" + +namespace NArchive { +namespace NTar { + +class CHandler: + public IInArchive, + public IArchiveOpenSeq, + public IInArchiveGetStream, + public IOutArchive, + public CMyUnknownImp +{ + CObjectVector _items; + CMyComPtr _stream; + CMyComPtr _seqStream; + + UInt32 _curIndex; + bool _latestIsRead; + CItemEx _latestItem; + + UInt64 _phySize; + UInt64 _headersSize; + bool _phySizeDefined; + AString _errorMessage; + + NCompress::CCopyCoder *copyCoderSpec; + CMyComPtr copyCoder; + + HRESULT ReadItem2(ISequentialInStream *stream, bool &filled, CItemEx &itemInfo); + HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); + HRESULT SkipTo(UInt32 index); + +public: + MY_UNKNOWN_IMP4( + IInArchive, + IArchiveOpenSeq, + IInArchiveGetStream, + IOutArchive + ) + + INTERFACE_IInArchive(;) + INTERFACE_IOutArchive(;) + STDMETHOD(OpenSeq)(ISequentialInStream *stream); + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); + + CHandler(); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp new file mode 100755 index 0000000..dfdea31 --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp @@ -0,0 +1,122 @@ +// TarHandlerOut.cpp + +#include "StdAfx.h" + +#include "Common/ComTry.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "TarHandler.h" +#include "TarUpdate.h" + +using namespace NWindows; + +namespace NArchive { +namespace NTar { + +STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) +{ + *type = NFileTimeType::kUnix; + return S_OK; +} + +static HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, AString &res) +{ + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(index, propId, &prop)); + if (prop.vt == VT_BSTR) + res = UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP); + else if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + return S_OK; +} + +STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, + IArchiveUpdateCallback *callback) +{ + COM_TRY_BEGIN + if ((_stream && !_errorMessage.IsEmpty()) || _seqStream) + return E_NOTIMPL; + CObjectVector updateItems; + for (UInt32 i = 0; i < numItems; i++) + { + CUpdateItem ui; + Int32 newData; + Int32 newProps; + UInt32 indexInArchive; + if (!callback) + return E_FAIL; + RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive)); + ui.NewProps = IntToBool(newProps); + ui.NewData = IntToBool(newData); + ui.IndexInArchive = indexInArchive; + ui.IndexInClient = i; + + if (IntToBool(newProps)) + { + { + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(i, kpidIsDir, &prop)); + if (prop.vt == VT_EMPTY) + ui.IsDir = false; + else if (prop.vt != VT_BOOL) + return E_INVALIDARG; + else + ui.IsDir = (prop.boolVal != VARIANT_FALSE); + } + + { + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(i, kpidPosixAttrib, &prop)); + if (prop.vt == VT_EMPTY) + ui.Mode = 0777 | (ui.IsDir ? 0040000 : 0100000); + else if (prop.vt != VT_UI4) + return E_INVALIDARG; + else + ui.Mode = prop.ulVal; + } + { + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(i, kpidMTime, &prop)); + if (prop.vt == VT_EMPTY) + ui.Time = 0; + else if (prop.vt != VT_FILETIME) + return E_INVALIDARG; + else if (!NTime::FileTimeToUnixTime(prop.filetime, ui.Time)) + ui.Time = 0; + } + { + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(i, kpidPath, &prop)); + if (prop.vt == VT_BSTR) + ui.Name = UnicodeStringToMultiByte(NItemName::MakeLegalName(prop.bstrVal), CP_OEMCP); + else if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + if (ui.IsDir) + ui.Name += '/'; + } + RINOK(GetPropString(callback, i, kpidUser, ui.User)); + RINOK(GetPropString(callback, i, kpidGroup, ui.Group)); + } + if (IntToBool(newData)) + { + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(i, kpidSize, &prop)); + if (prop.vt != VT_UI8) + return E_INVALIDARG; + ui.Size = prop.uhVal.QuadPart; + /* + // now we support GNU extension for big files + if (ui.Size >= ((UInt64)1 << 33)) + return E_INVALIDARG; + */ + } + updateItems.Add(ui); + } + return UpdateArchive(_stream, outStream, _items, updateItems, callback); + COM_TRY_END +} + +}} diff --git a/CPP/7zip/Archive/Tar/TarHeader.cpp b/CPP/7zip/Archive/Tar/TarHeader.cpp new file mode 100755 index 0000000..9304388 --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarHeader.cpp @@ -0,0 +1,25 @@ +// Archive/Tar/Header.h + +#include "StdAfx.h" + +#include "TarHeader.h" + +namespace NArchive { +namespace NTar { +namespace NFileHeader { + + // The checksum field is filled with this while the checksum is computed. + const char *kCheckSumBlanks = " "; // 8 blanks, no null + + const char *kLongLink = "././@LongLink"; + const char *kLongLink2 = "@LongLink"; + + // The magic field is filled with this if uname and gname are valid. + namespace NMagic + { + const char *kUsTar = "ustar"; // 5 chars + const char *kGNUTar = "GNUtar "; // 7 chars and a null + const char *kEmpty = "\0\0\0\0\0\0\0\0"; // 7 chars and a null + } + +}}} diff --git a/CPP/7zip/Archive/Tar/TarHeader.h b/CPP/7zip/Archive/Tar/TarHeader.h new file mode 100755 index 0000000..dece1f7 --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarHeader.h @@ -0,0 +1,108 @@ +// Archive/Tar/Header.h + +#ifndef __ARCHIVE_TAR_HEADER_H +#define __ARCHIVE_TAR_HEADER_H + +#include "Common/Types.h" + +namespace NArchive { +namespace NTar { + +namespace NFileHeader +{ + const int kRecordSize = 512; + const int kNameSize = 100; + const int kUserNameSize = 32; + const int kGroupNameSize = 32; + const int kPrefixSize = 155; + + /* + struct CHeader + { + char Name[kNameSize]; + char Mode[8]; + char UID[8]; + char GID[8]; + char Size[12]; + char ModificationTime[12]; + char CheckSum[8]; + char LinkFlag; + char LinkName[kNameSize]; + char Magic[8]; + char UserName[kUserNameSize]; + char GroupName[kGroupNameSize]; + char DeviceMajor[8]; + char DeviceMinor[8]; + char Prefix[155]; + }; + union CRecord + { + CHeader Header; + Byte Padding[kRecordSize]; + }; + */ + + namespace NMode + { + const int kSetUID = 04000; // Set UID on execution + const int kSetGID = 02000; // Set GID on execution + const int kSaveText = 01000; // Save text (sticky bit) + } + + namespace NFilePermissions + { + const int kUserRead = 00400; // read by owner + const int kUserWrite = 00200; // write by owner + const int kUserExecute = 00100; // execute/search by owner + const int kGroupRead = 00040; // read by group + const int kGroupWrite = 00020; // write by group + const int kGroupExecute = 00010; // execute/search by group + const int kOtherRead = 00004; // read by other + const int kOtherWrite = 00002; // write by other + const int kOtherExecute = 00001; // execute/search by other + } + + + // The linkflag defines the type of file + namespace NLinkFlag + { + const char kOldNormal = '\0'; // Normal disk file, Unix compatible + const char kNormal = '0'; // Normal disk file + const char kLink = '1'; // Link to previously dumped file + const char kSymbolicLink = '2'; // Symbolic link + const char kCharacter = '3'; // Character special file + const char kBlock = '4'; // Block special file + const char kDirectory = '5'; // Directory + const char kFIFO = '6'; // FIFO special file + const char kContiguous = '7'; // Contiguous file + + const char kDumpDir = 'D'; /* GNUTYPE_DUMPDIR. + data: list of files created by the --incremental (-G) option + Each file name is preceded by either + - 'Y' (file should be in this archive) + - 'N' (file is a directory, or is not stored in the archive.) + Each file name is terminated by a null + an additional null after + the last file name. */ + + } + // Further link types may be defined later. + + // The checksum field is filled with this while the checksum is computed. + extern const char *kCheckSumBlanks;// = " "; // 8 blanks, no null + + extern const char *kLongLink; // = "././@LongLink"; + extern const char *kLongLink2; // = "@LongLink"; + + // The magic field is filled with this if uname and gname are valid. + namespace NMagic + { + extern const char *kUsTar; // = "ustar"; // 5 chars + extern const char *kGNUTar; // = "GNUtar "; // 7 chars and a null + extern const char *kEmpty; // = "GNUtar "; // 7 chars and a null + } + +} + +}} + +#endif diff --git a/CPP/7zip/Archive/Tar/TarIn.cpp b/CPP/7zip/Archive/Tar/TarIn.cpp new file mode 100755 index 0000000..97d4f7e --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarIn.cpp @@ -0,0 +1,207 @@ +// TarIn.cpp + +#include "StdAfx.h" + +#include "../../../../C/CpuArch.h" + +#include "Common/StringToInt.h" + +#include "../../Common/StreamUtils.h" + +#include "TarIn.h" + +namespace NArchive { +namespace NTar { + +static void MyStrNCpy(char *dest, const char *src, int size) +{ + for (int i = 0; i < size; i++) + { + char c = src[i]; + dest[i] = c; + if (c == 0) + break; + } +} + +static bool OctalToNumber(const char *srcString, int size, UInt64 &res) +{ + char sz[32]; + MyStrNCpy(sz, srcString, size); + sz[size] = 0; + const char *end; + int i; + for (i = 0; sz[i] == ' '; i++); + res = ConvertOctStringToUInt64(sz + i, &end); + return (*end == ' ' || *end == 0); +} + +static bool OctalToNumber32(const char *srcString, int size, UInt32 &res) +{ + UInt64 res64; + if (!OctalToNumber(srcString, size, res64)) + return false; + res = (UInt32)res64; + return (res64 <= 0xFFFFFFFF); +} + +#define RIF(x) { if (!(x)) return S_FALSE; } + +static bool IsRecordLast(const char *buf) +{ + for (int i = 0; i < NFileHeader::kRecordSize; i++) + if (buf[i] != 0) + return false; + return true; +} + +static void ReadString(const char *s, int size, AString &result) +{ + char temp[NFileHeader::kRecordSize + 1]; + MyStrNCpy(temp, s, size); + temp[size] = '\0'; + result = temp; +} + +static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemEx &item, AString &error) +{ + char buf[NFileHeader::kRecordSize]; + char *p = buf; + + error.Empty(); + filled = false; + + bool thereAreEmptyRecords = false; + for (;;) + { + size_t processedSize = NFileHeader::kRecordSize; + RINOK(ReadStream(stream, buf, &processedSize)); + if (processedSize == 0) + { + if (!thereAreEmptyRecords ) + error = "There are no trailing zero-filled records"; + return S_OK; + } + if (processedSize != NFileHeader::kRecordSize) + { + error = "There is no correct record at the end of archive"; + return S_OK; + } + item.HeaderSize += NFileHeader::kRecordSize; + if (!IsRecordLast(buf)) + break; + thereAreEmptyRecords = true; + } + if (thereAreEmptyRecords) + { + error = "There are data after end of archive"; + return S_OK; + } + + ReadString(p, NFileHeader::kNameSize, item.Name); p += NFileHeader::kNameSize; + + RIF(OctalToNumber32(p, 8, item.Mode)); p += 8; + + if (!OctalToNumber32(p, 8, item.UID)) item.UID = 0; p += 8; + if (!OctalToNumber32(p, 8, item.GID)) item.GID = 0; p += 8; + + if (GetBe32(p) == (UInt32)1 << 31) + { + // GNU extension + item.Size = GetBe64(p + 4); + } + else + { + RIF(OctalToNumber(p, 12, item.Size)); + } + p += 12; + RIF(OctalToNumber32(p, 12, item.MTime)); p += 12; + + UInt32 checkSum; + RIF(OctalToNumber32(p, 8, checkSum)); + memcpy(p, NFileHeader::kCheckSumBlanks, 8); p += 8; + + item.LinkFlag = *p++; + + ReadString(p, NFileHeader::kNameSize, item.LinkName); p += NFileHeader::kNameSize; + + memcpy(item.Magic, p, 8); p += 8; + + ReadString(p, NFileHeader::kUserNameSize, item.User); p += NFileHeader::kUserNameSize; + ReadString(p, NFileHeader::kGroupNameSize, item.Group); p += NFileHeader::kGroupNameSize; + + item.DeviceMajorDefined = (p[0] != 0); RIF(OctalToNumber32(p, 8, item.DeviceMajor)); p += 8; + item.DeviceMinorDefined = (p[0] != 0); RIF(OctalToNumber32(p, 8, item.DeviceMinor)); p += 8; + + AString prefix; + ReadString(p, NFileHeader::kPrefixSize, prefix); + p += NFileHeader::kPrefixSize; + if (!prefix.IsEmpty() && item.IsMagic() && + (item.LinkFlag != 'L' /* || prefix != "00000000000" */ )) + item.Name = prefix + AString('/') + item.Name; + + if (item.LinkFlag == NFileHeader::NLinkFlag::kLink) + item.Size = 0; + + UInt32 checkSumReal = 0; + for (int i = 0; i < NFileHeader::kRecordSize; i++) + checkSumReal += (Byte)buf[i]; + + if (checkSumReal != checkSum) + return S_FALSE; + + filled = true; + return S_OK; +} + +HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, AString &error) +{ + item.HeaderSize = 0; + bool flagL = false; + bool flagK = false; + AString nameL; + AString nameK; + for (;;) + { + RINOK(GetNextItemReal(stream, filled, item, error)); + if (!filled) + return S_OK; + if (item.LinkFlag == 'L' || // NEXT file has a long name + item.LinkFlag == 'K') // NEXT file has a long linkname + { + AString *name; + if (item.LinkFlag == 'L') + { if (flagL) return S_FALSE; flagL = true; name = &nameL; } + else + { if (flagK) return S_FALSE; flagK = true; name = &nameK; } + + if (item.Name.Compare(NFileHeader::kLongLink) != 0 && + item.Name.Compare(NFileHeader::kLongLink2) != 0) + return S_FALSE; + if (item.Size > (1 << 14)) + return S_FALSE; + int packSize = (int)item.GetPackSize(); + char *buf = name->GetBuffer(packSize); + RINOK(ReadStream_FALSE(stream, buf, packSize)); + item.HeaderSize += packSize; + buf[(size_t)item.Size] = '\0'; + name->ReleaseBuffer(); + continue; + } + if (item.LinkFlag == 'g' || item.LinkFlag == 'x' || item.LinkFlag == 'X') + { + // pax Extended Header + } + else if (item.LinkFlag == NFileHeader::NLinkFlag::kDumpDir) + { + // GNU Extensions to the Archive Format + } + else if (item.LinkFlag > '7' || (item.LinkFlag < '0' && item.LinkFlag != 0)) + return S_FALSE; + if (flagL) item.Name = nameL; + if (flagK) item.LinkName = nameK; + return S_OK; + } +} + +}} diff --git a/CPP/7zip/Archive/Tar/TarIn.h b/CPP/7zip/Archive/Tar/TarIn.h new file mode 100755 index 0000000..33bf6f6 --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarIn.h @@ -0,0 +1,17 @@ +// TarIn.h + +#ifndef __ARCHIVE_TAR_IN_H +#define __ARCHIVE_TAR_IN_H + +#include "../../IStream.h" + +#include "TarItem.h" + +namespace NArchive { +namespace NTar { + +HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &itemInfo, AString &error); + +}} + +#endif diff --git a/CPP/7zip/Archive/Tar/TarItem.h b/CPP/7zip/Archive/Tar/TarItem.h new file mode 100755 index 0000000..5bcad47 --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarItem.h @@ -0,0 +1,72 @@ +// TarItem.h + +#ifndef __ARCHIVE_TAR_ITEM_H +#define __ARCHIVE_TAR_ITEM_H + +#include "../Common/ItemNameUtils.h" + +#include "TarHeader.h" + +namespace NArchive { +namespace NTar { + +struct CItem +{ + AString Name; + UInt64 Size; + + UInt32 Mode; + UInt32 UID; + UInt32 GID; + UInt32 MTime; + UInt32 DeviceMajor; + UInt32 DeviceMinor; + + AString LinkName; + AString User; + AString Group; + + char Magic[8]; + char LinkFlag; + bool DeviceMajorDefined; + bool DeviceMinorDefined; + + bool IsLink() const { return LinkFlag == NFileHeader::NLinkFlag::kSymbolicLink && (Size == 0); } + UInt64 GetUnpackSize() const { return IsLink() ? LinkName.Length() : Size; } + + bool IsDir() const + { + switch(LinkFlag) + { + case NFileHeader::NLinkFlag::kDirectory: + case NFileHeader::NLinkFlag::kDumpDir: + return true; + case NFileHeader::NLinkFlag::kOldNormal: + case NFileHeader::NLinkFlag::kNormal: + return NItemName::HasTailSlash(Name, CP_OEMCP); + } + return false; + } + + bool IsMagic() const + { + for (int i = 0; i < 5; i++) + if (Magic[i] != NFileHeader::NMagic::kUsTar[i]) + return false; + return true; + } + + UInt64 GetPackSize() const { return (Size + 0x1FF) & (~((UInt64)0x1FF)); } +}; + +struct CItemEx: public CItem +{ + UInt64 HeaderPos; + unsigned HeaderSize; + UInt64 GetDataPosition() const { return HeaderPos + HeaderSize; } + UInt64 GetFullSize() const { return HeaderSize + Size; } +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Tar/TarOut.cpp b/CPP/7zip/Archive/Tar/TarOut.cpp new file mode 100755 index 0000000..d0cb360 --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarOut.cpp @@ -0,0 +1,187 @@ +// TarOut.cpp + +#include "StdAfx.h" + +#include "Common/IntToString.h" + +#include "../../Common/StreamUtils.h" + +#include "TarOut.h" + +namespace NArchive { +namespace NTar { + +HRESULT COutArchive::WriteBytes(const void *buffer, UInt32 size) +{ + return WriteStream(m_Stream, buffer, size); +} + +void COutArchive::Create(ISequentialOutStream *outStream) +{ + m_Stream = outStream; +} + +static AString MakeOctalString(UInt64 value) +{ + char s[32]; + ConvertUInt64ToString(value, s, 8); + return AString(s) + ' '; +} + +static void MyStrNCpy(char *dest, const char *src, int size) +{ + for (int i = 0; i < size; i++) + { + char c = src[i]; + dest[i] = c; + if (c == 0) + break; + } +} + +static bool MakeOctalString8(char *s, UInt32 value) +{ + AString tempString = MakeOctalString(value); + + const int kMaxSize = 8; + if (tempString.Length() >= kMaxSize) + return false; + int numSpaces = kMaxSize - (tempString.Length() + 1); + for(int i = 0; i < numSpaces; i++) + s[i] = ' '; + MyStringCopy(s + numSpaces, (const char *)tempString); + return true; +} + +static void MakeOctalString12(char *s, UInt64 value) +{ + AString tempString = MakeOctalString(value); + const int kMaxSize = 12; + if (tempString.Length() > kMaxSize) + { + // GNU extension; + s[0] = (char)(Byte)0x80; + s[1] = s[2] = s[3] = 0; + for (int i = 0; i < 8; i++, value <<= 8) + s[4 + i] = (char)(value >> 56); + return; + } + int numSpaces = kMaxSize - tempString.Length(); + for(int i = 0; i < numSpaces; i++) + s[i] = ' '; + memmove(s + numSpaces, (const char *)tempString, tempString.Length()); +} + +static bool CopyString(char *dest, const AString &src, int maxSize) +{ + if (src.Length() >= maxSize) + return false; + MyStringCopy(dest, (const char *)src); + return true; +} + +#define RETURN_IF_NOT_TRUE(x) { if (!(x)) return E_FAIL; } + +HRESULT COutArchive::WriteHeaderReal(const CItem &item) +{ + char record[NFileHeader::kRecordSize]; + char *cur = record; + int i; + for (i = 0; i < NFileHeader::kRecordSize; i++) + record[i] = 0; + + // RETURN_IF_NOT_TRUE(CopyString(header.Name, item.Name, NFileHeader::kNameSize)); + if (item.Name.Length() > NFileHeader::kNameSize) + return E_FAIL; + MyStrNCpy(cur, item.Name, NFileHeader::kNameSize); + cur += NFileHeader::kNameSize; + + RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.Mode)); cur += 8; + RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.UID)); cur += 8; + RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.GID)); cur += 8; + + MakeOctalString12(cur, item.Size); cur += 12; + MakeOctalString12(cur, item.MTime); cur += 12; + + memmove(cur, NFileHeader::kCheckSumBlanks, 8); + cur += 8; + + *cur++ = item.LinkFlag; + + RETURN_IF_NOT_TRUE(CopyString(cur, item.LinkName, NFileHeader::kNameSize)); + cur += NFileHeader::kNameSize; + + memmove(cur, item.Magic, 8); + cur += 8; + + RETURN_IF_NOT_TRUE(CopyString(cur, item.User, NFileHeader::kUserNameSize)); + cur += NFileHeader::kUserNameSize; + RETURN_IF_NOT_TRUE(CopyString(cur, item.Group, NFileHeader::kGroupNameSize)); + cur += NFileHeader::kGroupNameSize; + + + if (item.DeviceMajorDefined) + RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.DeviceMajor)); + cur += 8; + + if (item.DeviceMinorDefined) + RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.DeviceMinor)); + cur += 8; + + + UInt32 checkSumReal = 0; + for(i = 0; i < NFileHeader::kRecordSize; i++) + checkSumReal += Byte(record[i]); + + RETURN_IF_NOT_TRUE(MakeOctalString8(record + 148, checkSumReal)); + + return WriteBytes(record, NFileHeader::kRecordSize); +} + +HRESULT COutArchive::WriteHeader(const CItem &item) +{ + int nameSize = item.Name.Length(); + if (nameSize < NFileHeader::kNameSize) + return WriteHeaderReal(item); + + CItem modifiedItem = item; + int nameStreamSize = nameSize + 1; + modifiedItem.Size = nameStreamSize; + modifiedItem.LinkFlag = 'L'; + modifiedItem.Name = NFileHeader::kLongLink; + modifiedItem.LinkName.Empty(); + RINOK(WriteHeaderReal(modifiedItem)); + RINOK(WriteBytes(item.Name, nameStreamSize)); + RINOK(FillDataResidual(nameStreamSize)); + + modifiedItem = item; + modifiedItem.Name = item.Name.Left(NFileHeader::kNameSize - 1); + return WriteHeaderReal(modifiedItem); +} + +HRESULT COutArchive::FillDataResidual(UInt64 dataSize) +{ + UInt32 lastRecordSize = UInt32(dataSize & (NFileHeader::kRecordSize - 1)); + if (lastRecordSize == 0) + return S_OK; + UInt32 residualSize = NFileHeader::kRecordSize - lastRecordSize; + Byte residualBytes[NFileHeader::kRecordSize]; + for (UInt32 i = 0; i < residualSize; i++) + residualBytes[i] = 0; + return WriteBytes(residualBytes, residualSize); +} + +HRESULT COutArchive::WriteFinishHeader() +{ + Byte record[NFileHeader::kRecordSize]; + int i; + for (i = 0; i < NFileHeader::kRecordSize; i++) + record[i] = 0; + for (i = 0; i < 2; i++) + { + RINOK(WriteBytes(record, NFileHeader::kRecordSize)); + } + return S_OK; +} + +}} diff --git a/CPP/7zip/Archive/Tar/TarOut.h b/CPP/7zip/Archive/Tar/TarOut.h new file mode 100755 index 0000000..7430904 --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarOut.h @@ -0,0 +1,28 @@ +// Archive/TarOut.h + +#ifndef __ARCHIVE_TAR_OUT_H +#define __ARCHIVE_TAR_OUT_H + +#include "TarItem.h" + +#include "Common/MyCom.h" +#include "../../IStream.h" + +namespace NArchive { +namespace NTar { + +class COutArchive +{ + CMyComPtr m_Stream; + HRESULT WriteBytes(const void *buffer, UInt32 size); +public: + void Create(ISequentialOutStream *outStream); + HRESULT WriteHeaderReal(const CItem &item); + HRESULT WriteHeader(const CItem &item); + HRESULT FillDataResidual(UInt64 dataSize); + HRESULT WriteFinishHeader(); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Tar/TarRegister.cpp b/CPP/7zip/Archive/Tar/TarRegister.cpp new file mode 100755 index 0000000..1ed9c20 --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarRegister.cpp @@ -0,0 +1,18 @@ +// TarRegister.cpp + +#include "StdAfx.h" + +#include "../../Common/RegisterArc.h" + +#include "TarHandler.h" +static IInArchive *CreateArc() { return new NArchive::NTar::CHandler; } +#ifndef EXTRACT_ONLY +static IOutArchive *CreateArcOut() { return new NArchive::NTar::CHandler; } +#else +#define CreateArcOut 0 +#endif + +static CArcInfo g_ArcInfo = +{ L"tar", L"tar", 0, 0xEE, { 'u', 's', 't', 'a', 'r' }, 5, false, CreateArc, CreateArcOut }; + +REGISTER_ARC(Tar) diff --git a/CPP/7zip/Archive/Tar/TarUpdate.cpp b/CPP/7zip/Archive/Tar/TarUpdate.cpp new file mode 100755 index 0000000..996fd0f --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarUpdate.cpp @@ -0,0 +1,139 @@ +// TarUpdate.cpp + +#include "StdAfx.h" + +#include "../../Common/LimitedStreams.h" +#include "../../Common/ProgressUtils.h" + +#include "../../Compress/CopyCoder.h" + +#include "TarOut.h" +#include "TarUpdate.h" + +namespace NArchive { +namespace NTar { + +HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, + const CObjectVector &inputItems, + const CObjectVector &updateItems, + IArchiveUpdateCallback *updateCallback) +{ + COutArchive outArchive; + outArchive.Create(outStream); + + UInt64 complexity = 0; + + int i; + for(i = 0; i < updateItems.Size(); i++) + { + const CUpdateItem &ui = updateItems[i]; + if (ui.NewData) + complexity += ui.Size; + else + complexity += inputItems[ui.IndexInArchive].GetFullSize(); + } + + RINOK(updateCallback->SetTotal(complexity)); + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; + CMyComPtr copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(updateCallback, true); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStreamLimited(streamSpec); + streamSpec->SetStream(inStream); + + complexity = 0; + + for(i = 0; i < updateItems.Size(); i++) + { + lps->InSize = lps->OutSize = complexity; + RINOK(lps->SetCur()); + + const CUpdateItem &ui = updateItems[i]; + CItem item; + if (ui.NewProps) + { + item.Mode = ui.Mode; + item.Name = ui.Name; + item.User = ui.User; + item.Group = ui.Group; + if (ui.IsDir) + { + item.LinkFlag = NFileHeader::NLinkFlag::kDirectory; + item.Size = 0; + } + else + { + item.LinkFlag = NFileHeader::NLinkFlag::kNormal; + item.Size = ui.Size; + } + item.MTime = ui.Time; + item.DeviceMajorDefined = false; + item.DeviceMinorDefined = false; + item.UID = 0; + item.GID = 0; + memmove(item.Magic, NFileHeader::NMagic::kEmpty, 8); + } + else + item = inputItems[ui.IndexInArchive]; + + if (ui.NewData) + { + item.Size = ui.Size; + if (item.Size == (UInt64)(Int64)-1) + return E_INVALIDARG; + } + else + item.Size = inputItems[ui.IndexInArchive].Size; + + if (ui.NewData) + { + CMyComPtr fileInStream; + HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream); + if (res != S_FALSE) + { + RINOK(res); + RINOK(outArchive.WriteHeader(item)); + if (!ui.IsDir) + { + RINOK(copyCoder->Code(fileInStream, outStream, NULL, NULL, progress)); + if (copyCoderSpec->TotalSize != item.Size) + return E_FAIL; + RINOK(outArchive.FillDataResidual(item.Size)); + } + } + complexity += ui.Size; + RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); + } + else + { + const CItemEx &existItem = inputItems[ui.IndexInArchive]; + UInt64 size; + if (ui.NewProps) + { + RINOK(outArchive.WriteHeader(item)); + RINOK(inStream->Seek(existItem.GetDataPosition(), STREAM_SEEK_SET, NULL)); + size = existItem.Size; + } + else + { + RINOK(inStream->Seek(existItem.HeaderPos, STREAM_SEEK_SET, NULL)); + size = existItem.GetFullSize(); + } + streamSpec->Init(size); + + RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)); + if (copyCoderSpec->TotalSize != size) + return E_FAIL; + RINOK(outArchive.FillDataResidual(existItem.Size)); + complexity += size; + } + } + return outArchive.WriteFinishHeader(); +} + +}} diff --git a/CPP/7zip/Archive/Tar/TarUpdate.h b/CPP/7zip/Archive/Tar/TarUpdate.h new file mode 100755 index 0000000..78461c9 --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarUpdate.h @@ -0,0 +1,34 @@ +// TarUpdate.h + +#ifndef __TAR_UPDATE_H +#define __TAR_UPDATE_H + +#include "../IArchive.h" +#include "TarItem.h" + +namespace NArchive { +namespace NTar { + +struct CUpdateItem +{ + int IndexInArchive; + int IndexInClient; + UInt32 Time; + UInt32 Mode; + UInt64 Size; + AString Name; + AString User; + AString Group; + bool NewData; + bool NewProps; + bool IsDir; +}; + +HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, + const CObjectVector &inputItems, + const CObjectVector &updateItems, + IArchiveUpdateCallback *updateCallback); + +}} + +#endif diff --git a/CPP/7zip/Archive/Udf/StdAfx.h b/CPP/7zip/Archive/Udf/StdAfx.h new file mode 100755 index 0000000..a4e6173 --- /dev/null +++ b/CPP/7zip/Archive/Udf/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" +#include "../../../Common/NewHandler.h" + +#endif diff --git a/CPP/7zip/Archive/Udf/UdfHandler.cpp b/CPP/7zip/Archive/Udf/UdfHandler.cpp new file mode 100755 index 0000000..a1df87f --- /dev/null +++ b/CPP/7zip/Archive/Udf/UdfHandler.cpp @@ -0,0 +1,451 @@ +// UdfHandler.cpp + +#include "StdAfx.h" + +#include "Common/ComTry.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../../Common/LimitedStreams.h" +#include "../../Common/ProgressUtils.h" +#include "../../Common/StreamObjects.h" + +#include "../../Compress/CopyCoder.h" + +#include "UdfHandler.h" + +namespace NArchive { +namespace NUdf { + +void UdfTimeToFileTime(const CTime &t, NWindows::NCOM::CPropVariant &prop) +{ + UInt64 numSecs; + const Byte *d = t.Data; + if (!NWindows::NTime::GetSecondsSince1601(t.GetYear(), d[4], d[5], d[6], d[7], d[8], numSecs)) + return; + if (t.IsLocal()) + numSecs -= t.GetMinutesOffset() * 60; + FILETIME ft; + UInt64 v = (((numSecs * 100 + d[9]) * 100 + d[10]) * 100 + d[11]) * 10; + ft.dwLowDateTime = (UInt32)v; + ft.dwHighDateTime = (UInt32)(v >> 32); + prop = ft; +} + +static STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidATime, VT_FILETIME} +}; + +static STATPROPSTG kArcProps[] = +{ + { NULL, kpidComment, VT_BSTR}, + { NULL, kpidClusterSize, VT_UI4}, + { NULL, kpidCTime, VT_FILETIME} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidComment: + { + UString comment = _archive.GetComment(); + if (!comment.IsEmpty()) + prop = comment; + break; + } + + case kpidClusterSize: + if (_archive.LogVols.Size() > 0) + { + UInt32 blockSize = _archive.LogVols[0].BlockSize; + int i; + for (i = 1; i < _archive.LogVols.Size(); i++) + if (_archive.LogVols[i].BlockSize != blockSize) + break; + if (i == _archive.LogVols.Size()) + prop = blockSize; + } + break; + + case kpidCTime: + if (_archive.LogVols.Size() == 1) + { + const CLogVol &vol = _archive.LogVols[0]; + if (vol.FileSets.Size() >= 1) + UdfTimeToFileTime(vol.FileSets[0].RecodringTime, prop); + } + break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +class CProgressImp: public CProgressVirt +{ + CMyComPtr _callback; + UInt64 _numFiles; + UInt64 _numBytes; +public: + HRESULT SetTotal(UInt64 numBytes); + HRESULT SetCompleted(UInt64 numFiles, UInt64 numBytes); + HRESULT SetCompleted(); + CProgressImp(IArchiveOpenCallback *callback): _callback(callback), _numFiles(0), _numBytes(0) {} +}; + +HRESULT CProgressImp::SetTotal(UInt64 numBytes) +{ + if (_callback) + return _callback->SetTotal(NULL, &numBytes); + return S_OK; +} + +HRESULT CProgressImp::SetCompleted(UInt64 numFiles, UInt64 numBytes) +{ + _numFiles = numFiles; + _numBytes = numBytes; + return SetCompleted(); +} + +HRESULT CProgressImp::SetCompleted() +{ + if (_callback) + return _callback->SetCompleted(&_numFiles, &_numBytes); + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *stream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + { + Close(); + CProgressImp progressImp(callback); + RINOK(_archive.Open(stream, &progressImp)); + bool showVolName = (_archive.LogVols.Size() > 1); + for (int volIndex = 0; volIndex < _archive.LogVols.Size(); volIndex++) + { + const CLogVol &vol = _archive.LogVols[volIndex]; + bool showFileSetName = (vol.FileSets.Size() > 1); + for (int fsIndex = 0; fsIndex < vol.FileSets.Size(); fsIndex++) + { + const CFileSet &fs = vol.FileSets[fsIndex]; + for (int i = ((showVolName || showFileSetName) ? 0 : 1); i < fs.Refs.Size(); i++) + { + CRef2 ref2; + ref2.Vol = volIndex; + ref2.Fs = fsIndex; + ref2.Ref = i; + _refs2.Add(ref2); + } + } + } + _inStream = stream; + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _inStream.Release(); + _archive.Clear(); + _refs2.Clear(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _refs2.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + { + const CRef2 &ref2 = _refs2[index]; + const CLogVol &vol = _archive.LogVols[ref2.Vol]; + const CRef &ref = vol.FileSets[ref2.Fs].Refs[ref2.Ref]; + const CFile &file = _archive.Files[ref.FileIndex]; + const CItem &item = _archive.Items[file.ItemIndex]; + switch(propID) + { + case kpidPath: prop = _archive.GetItemPath(ref2.Vol, ref2.Fs, ref2.Ref, + _archive.LogVols.Size() > 1, vol.FileSets.Size() > 1); break; + case kpidIsDir: prop = item.IsDir(); break; + case kpidSize: if (!item.IsDir()) prop = (UInt64)item.Size; break; + case kpidPackSize: if (!item.IsDir()) prop = (UInt64)item.NumLogBlockRecorded * vol.BlockSize; break; + case kpidMTime: UdfTimeToFileTime(item.MTime, prop); break; + case kpidATime: UdfTimeToFileTime(item.ATime, prop); break; + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +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_IMP1(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; + } + +}; + + +STDMETHODIMP CExtentsStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (size > 0) + { + UInt64 totalSize = Extents.Back().Virt; + if (_virtPos >= totalSize) + return (_virtPos == totalSize) ? S_OK : E_FAIL; + int left = 0, right = Extents.Size() - 1; + for (;;) + { + int 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; + } + return S_OK; +} + +STDMETHODIMP CExtentsStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch(seekOrigin) + { + case STREAM_SEEK_SET: _virtPos = offset; break; + case STREAM_SEEK_CUR: _virtPos += offset; break; + case STREAM_SEEK_END: _virtPos = Extents.Back().Virt + offset; break; + default: return STG_E_INVALIDFUNCTION; + } + if (newPosition) + *newPosition = _virtPos; + return S_OK; +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + *stream = 0; + + const CRef2 &ref2 = _refs2[index]; + const CLogVol &vol = _archive.LogVols[ref2.Vol]; + const CRef &ref = vol.FileSets[ref2.Fs].Refs[ref2.Ref]; + const CFile &file = _archive.Files[ref.FileIndex]; + const CItem &item = _archive.Items[file.ItemIndex]; + UInt64 size = item.Size; + + if (!item.IsRecAndAlloc() || !item.CheckChunkSizes() || ! _archive.CheckItemExtents(ref2.Vol, item)) + return E_NOTIMPL; + + if (item.IsInline) + { + CBufInStream *inStreamSpec = new CBufInStream; + CMyComPtr inStream = inStreamSpec; + CReferenceBuf *referenceBuf = new CReferenceBuf; + CMyComPtr ref = referenceBuf; + referenceBuf->Buf = item.InlineData; + inStreamSpec->Init(referenceBuf); + *stream = inStream.Detach(); + return S_OK; + } + + CExtentsStream *extentStreamSpec = new CExtentsStream(); + CMyComPtr extentStream = extentStreamSpec; + + extentStreamSpec->Stream = _inStream; + + UInt64 virtOffset = 0; + for (int extentIndex = 0; extentIndex < item.Extents.Size(); extentIndex++) + { + const CMyExtent &extent = item.Extents[extentIndex]; + UInt32 len = extent.GetLen(); + if (len == 0) + continue; + if (size < len) + return S_FALSE; + + int partitionIndex = vol.PartitionMaps[extent.PartitionRef].PartitionIndex; + UInt32 logBlockNumber = extent.Pos; + const CPartition &partition = _archive.Partitions[partitionIndex]; + UInt64 offset = ((UInt64)partition.Pos << _archive.SecLogSize) + + (UInt64)logBlockNumber * vol.BlockSize; + + CSeekExtent se; + se.Phy = offset; + se.Virt = virtOffset; + virtOffset += len; + extentStreamSpec->Extents.Add(se); + + size -= len; + } + if (size != 0) + return S_FALSE; + CSeekExtent se; + se.Phy = 0; + se.Virt = virtOffset; + extentStreamSpec->Extents.Add(se); + extentStreamSpec->Init(); + *stream = extentStream.Detach(); + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _refs2.Size(); + if (numItems == 0) + return S_OK; + UInt64 totalSize = 0; + UInt32 i; + + for (i = 0; i < numItems; i++) + { + UInt32 index = (allFilesMode ? i : indices[i]); + const CRef2 &ref2 = _refs2[index]; + const CRef &ref = _archive.LogVols[ref2.Vol].FileSets[ref2.Fs].Refs[ref2.Ref]; + const CFile &file = _archive.Files[ref.FileIndex]; + const CItem &item = _archive.Items[file.ItemIndex]; + if (!item.IsDir()) + totalSize += item.Size; + } + extractCallback->SetTotal(totalSize); + + UInt64 currentTotalSize = 0; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream; + CMyComPtr outStream(outStreamSpec); + + for (i = 0; i < numItems; i++) + { + lps->InSize = lps->OutSize = currentTotalSize; + RINOK(lps->SetCur()); + CMyComPtr realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + UInt32 index = allFilesMode ? i : indices[i]; + + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + const CRef2 &ref2 = _refs2[index]; + const CRef &ref = _archive.LogVols[ref2.Vol].FileSets[ref2.Fs].Refs[ref2.Ref]; + const CFile &file = _archive.Files[ref.FileIndex]; + const CItem &item = _archive.Items[file.ItemIndex]; + + if (item.IsDir()) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + currentTotalSize += item.Size; + + if (!testMode && !realOutStream) + continue; + + RINOK(extractCallback->PrepareOperation(askMode)); + outStreamSpec->SetStream(realOutStream); + realOutStream.Release(); + outStreamSpec->Init(item.Size); + Int32 opRes; + CMyComPtr udfInStream; + HRESULT res = GetStream(index, &udfInStream); + if (res == E_NOTIMPL) + opRes = NExtract::NOperationResult::kUnSupportedMethod; + else if (res != S_OK) + opRes = NExtract::NOperationResult::kDataError; + else + { + RINOK(copyCoder->Code(udfInStream, outStream, NULL, NULL, progress)); + opRes = outStreamSpec->IsFinishedOK() ? + NExtract::NOperationResult::kOK: + NExtract::NOperationResult::kDataError; + } + outStreamSpec->ReleaseStream(); + RINOK(extractCallback->SetOperationResult(opRes)); + } + return S_OK; + COM_TRY_END +} + +}} diff --git a/CPP/7zip/Archive/Udf/UdfHandler.h b/CPP/7zip/Archive/Udf/UdfHandler.h new file mode 100755 index 0000000..20af208 --- /dev/null +++ b/CPP/7zip/Archive/Udf/UdfHandler.h @@ -0,0 +1,37 @@ +// Udf/Handler.h + +#ifndef __UDF_HANDLER_H +#define __UDF_HANDLER_H + +#include "Common/MyCom.h" +#include "../IArchive.h" + +#include "UdfIn.h" + +namespace NArchive { +namespace NUdf { + +struct CRef2 +{ + int Vol; + int Fs; + int Ref; +}; + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + CMyComPtr _inStream; + CInArchive _archive; + CRecordVector _refs2; +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp new file mode 100755 index 0000000..d9b987f --- /dev/null +++ b/CPP/7zip/Archive/Udf/UdfIn.cpp @@ -0,0 +1,876 @@ +// Archive/UdfIn.cpp + +#include "StdAfx.h" + +#include "../../../../C/CpuArch.h" + +#include "../../Common/StreamUtils.h" + +#include "UdfIn.h" + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) +#define Get64(p) GetUi64(p) + +namespace NArchive { +namespace NUdf { + +const int kNumPartitionsMax = 64; +const int kNumLogVolumesMax = 64; +const int kNumRecureseLevelsMax = 1 << 10; +const int kNumItemsMax = 1 << 27; +const int kNumFilesMax = 1 << 28; +const int kNumRefsMax = 1 << 28; +const UInt32 kNumExtentsMax = (UInt32)1 << 30; +const UInt64 kFileNameLengthTotalMax = (UInt64)1 << 33; +const UInt64 kInlineExtentsSizeMax = (UInt64)1 << 33; + +void MY_FAST_CALL Crc16GenerateTable(void); + +#define CRC16_INIT_VAL 0 +#define CRC16_GET_DIGEST(crc) (crc) +#define CRC16_UPDATE_BYTE(crc, b) (g_Crc16Table[(((crc) >> 8) ^ (b)) & 0xFF] ^ ((crc) << 8)) + +#define kCrc16Poly 0x1021 +UInt16 g_Crc16Table[256]; + +void MY_FAST_CALL Crc16GenerateTable(void) +{ + UInt32 i; + for (i = 0; i < 256; i++) + { + UInt32 r = (i << 8); + for (int j = 8; j > 0; j--) + r = ((r & 0x8000) ? ((r << 1) ^ kCrc16Poly) : (r << 1)) & 0xFFFF; + g_Crc16Table[i] = (UInt16)r; + } +} + +UInt16 MY_FAST_CALL Crc16_Update(UInt16 v, const void *data, size_t size) +{ + const Byte *p = (const Byte *)data; + for (; size > 0 ; size--, p++) + v = CRC16_UPDATE_BYTE(v, *p); + return v; +} + +UInt16 MY_FAST_CALL Crc16Calc(const void *data, size_t size) +{ + return Crc16_Update(CRC16_INIT_VAL, data, size); +} + +struct CCrc16TableInit { CCrc16TableInit() { Crc16GenerateTable(); } } g_Crc16TableInit; + +void CDString128::Parse(const Byte *buf) { memcpy(Data, buf, sizeof(Data)); } + +void CDString::Parse(const Byte *p, unsigned size) +{ + Data.SetCapacity(size); + memcpy(Data, p, size); +} + +static UString ParseDString(const Byte *data, int size) +{ + UString res; + wchar_t *p; + if (size > 0) + { + Byte type = data[0]; + if (type == 8) + { + p = res.GetBuffer((int)size + 1); + for (int i = 1; i < size; i++) + { + wchar_t c = data[i]; + if (c == 0) + break; + *p++ = c; + } + } + else if (type == 16) + { + p = res.GetBuffer((int)size / 2 + 1); + for (int i = 1; i + 2 <= size; i += 2) + { + wchar_t c = ((wchar_t)data[i] << 8) | data[i + 1]; + if (c == 0) + break; + *p++ = c; + } + } + else + return L"[unknow]"; + *p++ = 0; + res.ReleaseBuffer(); + } + return res; +} + +UString CDString:: GetString() const { return ParseDString(Data, (int)Data.GetCapacity()); } +UString CDString128::GetString() const +{ + int size = Data[sizeof(Data) - 1]; + return ParseDString(Data, MyMin(size, (int)(sizeof(Data) - 1))); +} + +void CTime::Parse(const Byte *buf) { memcpy(Data, buf, sizeof(Data)); } + +/* +void CRegId::Parse(const Byte *buf) +{ + Flags = buf[0]; + memcpy(Id, buf + 1, sizeof(Id)); + memcpy(Suffix, buf + 24, sizeof(Suffix)); +} +*/ + +// ECMA 3/7.1 + +struct CExtent +{ + UInt32 Len; + UInt32 Pos; + + void Parse(const Byte *buf); +}; + +void CExtent::Parse(const Byte *buf) +{ + Len = Get32(buf); + Pos = Get32(buf + 4); +} + +// ECMA 3/7.2 + +struct CTag +{ + UInt16 Id; + UInt16 Version; + // Byte Checksum; + // UInt16 SerialNumber; + // UInt16 Crc; + // UInt16 CrcLen; + // UInt32 TagLocation; + + HRESULT Parse(const Byte *buf, size_t size); +}; + +HRESULT CTag::Parse(const Byte *buf, size_t size) +{ + if (size < 16) + return S_FALSE; + Byte sum = 0; + int i; + for (i = 0; i < 4; i++) sum = sum + buf[i]; + for (i = 5; i < 16; i++) sum = sum + buf[i]; + if (sum != buf[4] || buf[5] != 0) return S_FALSE; + + Id = Get16(buf); + Version = Get16(buf + 2); + // SerialNumber = Get16(buf + 6); + UInt16 crc = Get16(buf + 8); + UInt16 crcLen = Get16(buf + 10); + // TagLocation = Get32(buf + 12); + + if (size >= 16 + (size_t)crcLen) + if (crc == Crc16Calc(buf + 16, crcLen)) + return S_OK; + return S_FALSE; +} + +// ECMA 3/7.2.1 + +enum EDescriptorType +{ + DESC_TYPE_SpoaringTable = 0, // UDF + DESC_TYPE_PrimVol = 1, + DESC_TYPE_AnchorVolPtr = 2, + DESC_TYPE_VolPtr = 3, + DESC_TYPE_ImplUseVol = 4, + DESC_TYPE_Partition = 5, + DESC_TYPE_LogicalVol = 6, + DESC_TYPE_UnallocSpace = 7, + DESC_TYPE_Terminating = 8, + DESC_TYPE_LogicalVolIntegrity = 9, + DESC_TYPE_FileSet = 256, + DESC_TYPE_FileId = 257, + DESC_TYPE_AllocationExtent = 258, + DESC_TYPE_Indirect = 259, + DESC_TYPE_Terminal = 260, + DESC_TYPE_File = 261, + DESC_TYPE_ExtendedAttrHeader = 262, + DESC_TYPE_UnallocatedSpace = 263, + DESC_TYPE_SpaceBitmap = 264, + DESC_TYPE_PartitionIntegrity = 265, + DESC_TYPE_ExtendedFile = 266 +}; + + +void CLogBlockAddr::Parse(const Byte *buf) +{ + Pos = Get32(buf); + PartitionRef = Get16(buf + 4); +} + +void CShortAllocDesc::Parse(const Byte *buf) +{ + Len = Get32(buf); + Pos = Get32(buf + 4); +} + +/* +void CADImpUse::Parse(const Byte *buf) +{ + Flags = Get16(buf); + UdfUniqueId = Get32(buf + 2); +} +*/ + +void CLongAllocDesc::Parse(const Byte *buf) +{ + Len = Get32(buf); + Location.Parse(buf + 4); + // memcpy(ImplUse, buf + 10, sizeof(ImplUse)); + // adImpUse.Parse(ImplUse); +} + +bool CInArchive::CheckExtent(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len) const +{ + const CLogVol &vol = LogVols[volIndex]; + const CPartition &partition = Partitions[vol.PartitionMaps[partitionRef].PartitionIndex]; + UInt64 offset = ((UInt64)partition.Pos << SecLogSize) + (UInt64)blockPos * vol.BlockSize; + return (offset + len) <= (((UInt64)partition.Pos + partition.Len) << SecLogSize); +} + +bool CInArchive::CheckItemExtents(int volIndex, const CItem &item) const +{ + for (int i = 0; i < item.Extents.Size(); i++) + { + const CMyExtent &e = item.Extents[i]; + if (!CheckExtent(volIndex, e.PartitionRef, e.Pos, e.GetLen())) + return false; + } + return true; +} + +HRESULT CInArchive::Read(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len, Byte *buf) +{ + if (!CheckExtent(volIndex, partitionRef, blockPos, len)) + return S_FALSE; + const CLogVol &vol = LogVols[volIndex]; + const CPartition &partition = Partitions[vol.PartitionMaps[partitionRef].PartitionIndex]; + RINOK(_stream->Seek(((UInt64)partition.Pos << SecLogSize) + + (UInt64)blockPos * vol.BlockSize, STREAM_SEEK_SET, NULL)); + return ReadStream_FALSE(_stream, buf, len); +} + +HRESULT CInArchive::Read(int volIndex, const CLongAllocDesc &lad, Byte *buf) +{ + return Read(volIndex, lad.Location.PartitionRef, lad.Location.Pos, lad.GetLen(), (Byte *)buf); +} + +HRESULT CInArchive::ReadFromFile(int volIndex, const CItem &item, CByteBuffer &buf) +{ + if (item.Size >= (UInt32)1 << 30) + return S_FALSE; + if (item.IsInline) + { + buf = item.InlineData; + return S_OK; + } + buf.SetCapacity((size_t)item.Size); + size_t pos = 0; + for (int i = 0; i < item.Extents.Size(); i++) + { + const CMyExtent &e = item.Extents[i]; + UInt32 len = e.GetLen(); + RINOK(Read(volIndex, e.PartitionRef, e.Pos, len, (Byte *)buf + pos)); + pos += len; + } + return S_OK; +} + + +void CIcbTag::Parse(const Byte *p) +{ + // PriorDirectNum = Get32(p); + // StrategyType = Get16(p + 4); + // StrategyParam = Get16(p + 6); + // MaxNumOfEntries = Get16(p + 8); + FileType = p[11]; + // ParentIcb.Parse(p + 12); + Flags = Get16(p + 18); +} + +void CItem::Parse(const Byte *p) +{ + // Uid = Get32(p + 36); + // Gid = Get32(p + 40); + // Permissions = Get32(p + 44); + // FileLinkCount = Get16(p + 48); + // RecordFormat = p[50]; + // RecordDisplayAttr = p[51]; + // RecordLen = Get32(p + 52); + Size = Get64(p + 56); + NumLogBlockRecorded = Get64(p + 64); + ATime.Parse(p + 72); + MTime.Parse(p + 84); + // AttrtTime.Parse(p + 96); + // CheckPoint = Get32(p + 108); + // ExtendedAttrIcb.Parse(p + 112); + // ImplId.Parse(p + 128); + // UniqueId = Get64(p + 160); +} + +// 4/14.4 +struct CFileId +{ + // UInt16 FileVersion; + Byte FileCharacteristics; + // CByteBuffer ImplUse; + CDString Id; + CLongAllocDesc Icb; + + bool IsItLinkParent() const { return (FileCharacteristics & FILEID_CHARACS_Parent) != 0; } + HRESULT Parse(const Byte *p, size_t size, size_t &processed); +}; + +HRESULT CFileId::Parse(const Byte *p, size_t size, size_t &processed) +{ + processed = 0; + if (size < 38) + return S_FALSE; + CTag tag; + RINOK(tag.Parse(p, size)); + if (tag.Id != DESC_TYPE_FileId) + return S_FALSE; + // FileVersion = Get16(p + 16); + FileCharacteristics = p[18]; + unsigned idLen = p[19]; + Icb.Parse(p + 20); + unsigned impLen = Get16(p + 36); + if (size < 38 + idLen + impLen) + return S_FALSE; + // ImplUse.SetCapacity(impLen); + processed = 38; + // memcpy(ImplUse, p + processed, impLen); + processed += impLen; + Id.Parse(p + processed, idLen); + processed += idLen; + for (;(processed & 3) != 0; processed++) + if (p[processed] != 0) + return S_FALSE; + return (processed <= size) ? S_OK : S_FALSE; +} + +HRESULT CInArchive::ReadFileItem(int volIndex, int fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed) +{ + if (Files.Size() % 100 == 0) + RINOK(_progress->SetCompleted(Files.Size(), _processedProgressBytes)); + if (numRecurseAllowed-- == 0) + return S_FALSE; + CFile &file = Files.Back(); + const CLogVol &vol = LogVols[volIndex]; + CPartition &partition = Partitions[vol.PartitionMaps[lad.Location.PartitionRef].PartitionIndex]; + + UInt32 key = lad.Location.Pos; + UInt32 value; + const UInt32 kRecursedErrorValue = (UInt32)(Int32)-1; + if (partition.Map.Find(key, value)) + { + if (value == kRecursedErrorValue) + return S_FALSE; + file.ItemIndex = value; + } + else + { + value = Items.Size(); + file.ItemIndex = (int)value; + if (partition.Map.Set(key, kRecursedErrorValue)) + return S_FALSE; + RINOK(ReadItem(volIndex, fsIndex, lad, numRecurseAllowed)); + if (!partition.Map.Set(key, value)) + return S_FALSE; + } + return S_OK; +} + +HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed) +{ + if (Items.Size() > kNumItemsMax) + return S_FALSE; + Items.Add(CItem()); + CItem &item = Items.Back(); + + const CLogVol &vol = LogVols[volIndex]; + + if (lad.GetLen() != vol.BlockSize) + return S_FALSE; + + CByteBuffer buf; + size_t size = lad.GetLen(); + buf.SetCapacity(size); + RINOK(Read(volIndex, lad, buf)); + + CTag tag; + const Byte *p = buf; + RINOK(tag.Parse(p, size)); + if (tag.Id != DESC_TYPE_File) + return S_FALSE; + + item.IcbTag.Parse(p + 16); + if (item.IcbTag.FileType != ICB_FILE_TYPE_DIR && + item.IcbTag.FileType != ICB_FILE_TYPE_FILE) + return S_FALSE; + + item.Parse(p); + + _processedProgressBytes += (UInt64)item.NumLogBlockRecorded * vol.BlockSize + size; + + UInt32 extendedAttrLen = Get32(p + 168); + UInt32 allocDescriptorsLen = Get32(p + 172); + + if ((extendedAttrLen & 3) != 0) + return S_FALSE; + int pos = 176; + if (extendedAttrLen > size - pos) + return S_FALSE; + /* + if (extendedAttrLen != 16) + { + if (extendedAttrLen < 24) + return S_FALSE; + CTag attrTag; + RINOK(attrTag.Parse(p + pos, size)); + if (attrTag.Id != DESC_TYPE_ExtendedAttrHeader) + return S_FALSE; + // UInt32 implAttrLocation = Get32(p + pos + 16); + // UInt32 applicationlAttrLocation = Get32(p + pos + 20); + } + */ + pos += extendedAttrLen; + + int desctType = item.IcbTag.GetDescriptorType(); + if (allocDescriptorsLen > size - pos) + return S_FALSE; + if (desctType == ICB_DESC_TYPE_INLINE) + { + item.IsInline = true; + item.InlineData.SetCapacity(allocDescriptorsLen); + memcpy(item.InlineData, p + pos, allocDescriptorsLen); + } + else + { + item.IsInline = false; + if (desctType != ICB_DESC_TYPE_SHORT && desctType != ICB_DESC_TYPE_LONG) + return S_FALSE; + for (UInt32 i = 0; i < allocDescriptorsLen;) + { + CMyExtent e; + if (desctType == ICB_DESC_TYPE_SHORT) + { + if (i + 8 > allocDescriptorsLen) + return S_FALSE; + CShortAllocDesc sad; + sad.Parse(p + pos + i); + e.Pos = sad.Pos; + e.Len = sad.Len; + e.PartitionRef = lad.Location.PartitionRef; + i += 8; + } + else + { + if (i + 16 > allocDescriptorsLen) + return S_FALSE; + CLongAllocDesc ladNew; + ladNew.Parse(p + pos + i); + e.Pos = ladNew.Location.Pos; + e.PartitionRef = ladNew.Location.PartitionRef; + e.Len = ladNew.Len; + i += 16; + } + item.Extents.Add(e); + } + } + + if (item.IcbTag.IsDir()) + { + if (!item.CheckChunkSizes() || !CheckItemExtents(volIndex, item)) + return S_FALSE; + CByteBuffer buf; + RINOK(ReadFromFile(volIndex, item, buf)); + item.Size = 0; + item.Extents.ClearAndFree(); + item.InlineData.Free(); + + const Byte *p = buf; + size = buf.GetCapacity(); + size_t processedTotal = 0; + for (; processedTotal < size;) + { + size_t processedCur; + CFileId fileId; + RINOK(fileId.Parse(p + processedTotal, size - processedTotal, processedCur)); + if (!fileId.IsItLinkParent()) + { + CFile file; + // file.FileVersion = fileId.FileVersion; + // file.FileCharacteristics = fileId.FileCharacteristics; + // file.ImplUse = fileId.ImplUse; + file.Id = fileId.Id; + + _fileNameLengthTotal += file.Id.Data.GetCapacity(); + if (_fileNameLengthTotal > kFileNameLengthTotalMax) + return S_FALSE; + + item.SubFiles.Add(Files.Size()); + if (Files.Size() > kNumFilesMax) + return S_FALSE; + Files.Add(file); + RINOK(ReadFileItem(volIndex, fsIndex, fileId.Icb, numRecurseAllowed)); + } + processedTotal += processedCur; + } + } + else + { + if ((UInt32)item.Extents.Size() > kNumExtentsMax - _numExtents) + return S_FALSE; + _numExtents += item.Extents.Size(); + + if (item.InlineData.GetCapacity() > kInlineExtentsSizeMax - _inlineExtentsSize) + return S_FALSE; + _inlineExtentsSize += item.InlineData.GetCapacity(); + } + + return S_OK; +} + +HRESULT CInArchive::FillRefs(CFileSet &fs, int fileIndex, int parent, int numRecurseAllowed) +{ + if (_numRefs % 10000 == 0) + { + RINOK(_progress->SetCompleted()); + } + if (numRecurseAllowed-- == 0) + return S_FALSE; + if (_numRefs >= kNumRefsMax) + return S_FALSE; + _numRefs++; + CRef ref; + ref.FileIndex = fileIndex; + ref.Parent = parent; + parent = fs.Refs.Size(); + fs.Refs.Add(ref); + const CItem &item = Items[Files[fileIndex].ItemIndex]; + for (int i = 0; i < item.SubFiles.Size(); i++) + { + RINOK(FillRefs(fs, item.SubFiles[i], parent, numRecurseAllowed)); + } + return S_OK; +} + +HRESULT CInArchive::Open2() +{ + Clear(); + + UInt64 fileSize; + RINOK(_stream->Seek(0, STREAM_SEEK_END, &fileSize)); + + // Some UDFs contain additional 2 KB of zeros, so we also check 12, corrected to 11. + const int kSecLogSizeMax = 12; + Byte buf[1 << kSecLogSizeMax]; + Byte kSizesLog[] = { 11, 8, 12 }; + + for (int i = 0;; i++) + { + if (i == sizeof(kSizesLog) / sizeof(kSizesLog[0])) + return S_FALSE; + SecLogSize = kSizesLog[i]; + Int32 bufSize = 1 << SecLogSize; + if (bufSize > fileSize) + return S_FALSE; + RINOK(_stream->Seek(-bufSize, STREAM_SEEK_END, NULL)); + RINOK(ReadStream_FALSE(_stream, buf, bufSize)); + CTag tag; + if (tag.Parse(buf, bufSize) == S_OK) + if (tag.Id == DESC_TYPE_AnchorVolPtr) + break; + } + if (SecLogSize == 12) + SecLogSize = 11; + + CExtent extentVDS; + extentVDS.Parse(buf + 16); + + for (UInt32 location = extentVDS.Pos; ; location++) + { + size_t bufSize = 1 << SecLogSize; + size_t pos = 0; + RINOK(_stream->Seek((UInt64)location << SecLogSize, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream_FALSE(_stream, buf, bufSize)); + CTag tag; + RINOK(tag.Parse(buf + pos, bufSize - pos)); + if (tag.Id == DESC_TYPE_Terminating) + break; + if (tag.Id == DESC_TYPE_Partition) + { + if (Partitions.Size() >= kNumPartitionsMax) + return S_FALSE; + CPartition partition; + // UInt32 volDescSeqNumer = Get32(buf + 16); + // partition.Flags = Get16(buf + 20); + partition.Number = Get16(buf + 22); + // partition.ContentsId.Parse(buf + 24); + + // memcpy(partition.ContentsUse, buf + 56, sizeof(partition.ContentsUse)); + // ContentsUse is Partition Header Description. + + // partition.AccessType = Get32(buf + 184); + partition.Pos = Get32(buf + 188); + partition.Len = Get32(buf + 192); + // partition.ImplId.Parse(buf + 196); + // memcpy(partition.ImplUse, buf + 228, sizeof(partition.ImplUse)); + + Partitions.Add(partition); + } + else if (tag.Id == DESC_TYPE_LogicalVol) + { + if (LogVols.Size() >= kNumLogVolumesMax) + return S_FALSE; + CLogVol vol; + vol.Id.Parse(buf + 84); + vol.BlockSize = Get32(buf + 212); + // vol.DomainId.Parse(buf + 216); + + if (vol.BlockSize < 512 || vol.BlockSize > ((UInt32)1 << 30)) + return S_FALSE; + + // memcpy(vol.ContentsUse, buf + 248, sizeof(vol.ContentsUse)); + vol.FileSetLocation.Parse(buf + 248); + + // UInt32 mapTableLength = Get32(buf + 264); + UInt32 numPartitionMaps = Get32(buf + 268); + if (numPartitionMaps > kNumPartitionsMax) + return S_FALSE; + // vol.ImplId.Parse(buf + 272); + // memcpy(vol.ImplUse, buf + 128, sizeof(vol.ImplUse)); + size_t pos = 440; + for (UInt32 i = 0; i < numPartitionMaps; i++) + { + if (pos + 2 > bufSize) + return S_FALSE; + CPartitionMap pm; + pm.Type = buf[pos]; + // pm.Length = buf[pos + 1]; + Byte len = buf[pos + 1]; + + if (pos + len > bufSize) + return S_FALSE; + + // memcpy(pm.Data, buf + pos + 2, pm.Length - 2); + if (pm.Type == 1) + { + if (pos + 6 > bufSize) + return S_FALSE; + // pm.VolSeqNumber = Get16(buf + pos + 2); + pm.PartitionNumber = Get16(buf + pos + 4); + } + else + return S_FALSE; + pos += len; + vol.PartitionMaps.Add(pm); + } + LogVols.Add(vol); + } + } + + UInt64 totalSize = 0; + + int volIndex; + for (volIndex = 0; volIndex < LogVols.Size(); volIndex++) + { + CLogVol &vol = LogVols[volIndex]; + for (int pmIndex = 0; pmIndex < vol.PartitionMaps.Size(); pmIndex++) + { + CPartitionMap &pm = vol.PartitionMaps[pmIndex]; + int i; + for (i = 0; i < Partitions.Size(); i++) + { + CPartition &part = Partitions[i]; + if (part.Number == pm.PartitionNumber) + { + if (part.VolIndex >= 0) + return S_FALSE; + pm.PartitionIndex = i; + part.VolIndex = volIndex; + + totalSize += (UInt64)part.Len << SecLogSize; + break; + } + } + if (i == Partitions.Size()) + return S_FALSE; + } + } + + RINOK(_progress->SetTotal(totalSize)); + + for (volIndex = 0; volIndex < LogVols.Size(); volIndex++) + { + CLogVol &vol = LogVols[volIndex]; + + CLongAllocDesc nextExtent = vol.FileSetLocation; + // while (nextExtent.ExtentLen != 0) + // for (int i = 0; i < 1; i++) + { + if (nextExtent.GetLen() < 512) + return S_FALSE; + CByteBuffer buf; + buf.SetCapacity(nextExtent.GetLen()); + RINOK(Read(volIndex, nextExtent, buf)); + const Byte *p = buf; + size_t size = nextExtent.GetLen(); + + CTag tag; + RINOK(tag.Parse(p, size)); + if (tag.Id != DESC_TYPE_FileSet) + return S_FALSE; + + CFileSet fs; + fs.RecodringTime.Parse(p + 16); + // fs.InterchangeLevel = Get16(p + 18); + // fs.MaxInterchangeLevel = Get16(p + 20); + // fs.FileSetNumber = Get32(p + 40); + // fs.FileSetDescNumber = Get32(p + 44); + + // fs.Id.Parse(p + 304); + // fs.CopyrightId.Parse(p + 336); + // fs.AbstractId.Parse(p + 368); + + fs.RootDirICB.Parse(p + 400); + // fs.DomainId.Parse(p + 416); + + // fs.SystemStreamDirICB.Parse(p + 464); + + vol.FileSets.Add(fs); + + // nextExtent.Parse(p + 448); + } + + for (int fsIndex = 0; fsIndex < vol.FileSets.Size(); fsIndex++) + { + CFileSet &fs = vol.FileSets[fsIndex]; + int fileIndex = Files.Size(); + Files.Add(CFile()); + RINOK(ReadFileItem(volIndex, fsIndex, fs.RootDirICB, kNumRecureseLevelsMax)); + RINOK(FillRefs(fs, fileIndex, -1, kNumRecureseLevelsMax)); + } + } + + return S_OK; +} + +HRESULT CInArchive::Open(IInStream *inStream, CProgressVirt *progress) +{ + _progress = progress; + _stream = inStream; + HRESULT res; + try { res = Open2(); } + catch(...) { Clear(); res = S_FALSE; } + _stream.Release(); + return res; +} + +void CInArchive::Clear() +{ + Partitions.Clear(); + LogVols.Clear(); + Items.Clear(); + Files.Clear(); + _fileNameLengthTotal = 0; + _numRefs = 0; + _numExtents = 0; + _inlineExtentsSize = 0; + _processedProgressBytes = 0; +} + +UString CInArchive::GetComment() const +{ + UString res; + for (int i = 0; i < LogVols.Size(); i++) + { + if (i > 0) + res += L" "; + res += LogVols[i].GetName(); + } + return res; +} + +static UString GetSpecName(const UString &name) +{ + UString name2 = name; + name2.Trim(); + if (name2.IsEmpty()) + { + /* + wchar_t s[32]; + ConvertUInt64ToString(id, s); + return L"[" + (UString)s + L"]"; + */ + return L"[]"; + } + return name; +} + +static void UpdateWithName(UString &res, const UString &addString) +{ + if (res.IsEmpty()) + res = addString; + else + res = addString + WCHAR_PATH_SEPARATOR + res; +} + +UString CInArchive::GetItemPath(int volIndex, int fsIndex, int refIndex, + bool showVolName, bool showFsName) const +{ + // showVolName = true; + const CLogVol &vol = LogVols[volIndex]; + const CFileSet &fs = vol.FileSets[fsIndex]; + + UString name; + + for (;;) + { + const CRef &ref = fs.Refs[refIndex]; + refIndex = ref.Parent; + if (refIndex < 0) + break; + UpdateWithName(name, GetSpecName(Files[ref.FileIndex].GetName())); + } + + if (showFsName) + { + wchar_t s[32]; + ConvertUInt64ToString(fsIndex, s); + UString newName = L"File Set "; + newName += s; + UpdateWithName(name, newName); + } + + if (showVolName) + { + wchar_t s[32]; + ConvertUInt64ToString(volIndex, s); + UString newName = s; + UString newName2 = vol.GetName(); + if (newName2.IsEmpty()) + newName2 = L"Volume"; + newName += L'-'; + newName += newName2; + UpdateWithName(name, newName); + } + return name; +} + +}} diff --git a/CPP/7zip/Archive/Udf/UdfIn.h b/CPP/7zip/Archive/Udf/UdfIn.h new file mode 100755 index 0000000..c9a3c02 --- /dev/null +++ b/CPP/7zip/Archive/Udf/UdfIn.h @@ -0,0 +1,375 @@ +// Archive/UdfIn.h -- UDF / ECMA-167 + +#ifndef __ARCHIVE_UDF_IN_H +#define __ARCHIVE_UDF_IN_H + +#include "Common/MyCom.h" +#include "Common/IntToString.h" +#include "Common/Buffer.h" +#include "Common/MyString.h" +#include "Common/MyMap.h" + +#include "../../IStream.h" + +namespace NArchive { +namespace NUdf { + +// ---------- ECMA Part 1 ---------- + +// ECMA 1/7.2.12 + +/* +struct CDString32 +{ + Byte Data[32]; + void Parse(const Byte *buf); + // UString GetString() const; +}; +*/ + +struct CDString128 +{ + Byte Data[128]; + void Parse(const Byte *buf); + UString GetString() const; +}; + +struct CDString +{ + CByteBuffer Data; + void Parse(const Byte *p, unsigned size); + UString GetString() const; +}; + + +// ECMA 1/7.3 + +struct CTime +{ + Byte Data[12]; + + unsigned GetType() const { return Data[1] >> 4; } + bool IsLocal() const { return GetType() == 1; } + int GetMinutesOffset() const + { + int t = (Data[0] | ((UInt16)Data[1] << 8)) & 0xFFF; + if ((t >> 11) != 0) + t -= (1 << 12); + return (t > (60 * 24) || t < -(60 * 24)) ? 0 : t; + } + unsigned GetYear() const { return (Data[2] | ((UInt16)Data[3] << 8)); } + void Parse(const Byte *buf); +}; + + +// ECMA 1/7.4 + +/* +struct CRegId +{ + Byte Flags; + char Id[23]; + char Suffix[8]; + + void Parse(const Byte *buf); +}; +*/ + +// ---------- ECMA Part 3: Volume Structure ---------- + +// ECMA 3/10.5 + +struct CPartition +{ + // UInt16 Flags; + UInt16 Number; + // CRegId ContentsId; + // Byte ContentsUse[128]; + // UInt32 AccessType; + + UInt32 Pos; + UInt32 Len; + + // CRegId ImplId; + // Byte ImplUse[128]; + + int VolIndex; + CMap32 Map; + + CPartition(): VolIndex(-1) {} + + // bool IsNsr() const { return (strncmp(ContentsId.Id, "+NSR0", 5) == 0); } + // bool IsAllocated() const { return ((Flags & 1) != 0); } +}; + +struct CLogBlockAddr +{ + UInt32 Pos; + UInt16 PartitionRef; + + void Parse(const Byte *buf); +}; + +enum EShortAllocDescType +{ + SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated = 0, + SHORT_ALLOC_DESC_TYPE_NotRecordedButAllocated = 1, + SHORT_ALLOC_DESC_TYPE_NotRecordedAndNotAllocated = 2, + SHORT_ALLOC_DESC_TYPE_NextExtent = 3 +}; + +struct CShortAllocDesc +{ + UInt32 Len; + UInt32 Pos; + + // 4/14.14.1 + // UInt32 GetLen() const { return Len & 0x3FFFFFFF; } + // UInt32 GetType() const { return Len >> 30; } + // bool IsRecAndAlloc() const { return GetType() == SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated; } + void Parse(const Byte *buf); +}; + +/* +struct CADImpUse +{ + UInt16 Flags; + UInt32 UdfUniqueId; + void Parse(const Byte *buf); +}; +*/ + +struct CLongAllocDesc +{ + UInt32 Len; + CLogBlockAddr Location; + + // Byte ImplUse[6]; + // CADImpUse adImpUse; // UDF + + UInt32 GetLen() const { return Len & 0x3FFFFFFF; } + UInt32 GetType() const { return Len >> 30; } + bool IsRecAndAlloc() const { return GetType() == SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated; } + void Parse(const Byte *buf); +}; + +struct CPartitionMap +{ + Byte Type; + // Byte Len; + + // Type - 1 + // UInt16 VolSeqNumber; + UInt16 PartitionNumber; + + // Byte Data[256]; + + int PartitionIndex; +}; + +// ECMA 4/14.6 + +enum EIcbFileType +{ + ICB_FILE_TYPE_DIR = 4, + ICB_FILE_TYPE_FILE = 5 +}; + +enum EIcbDescriptorType +{ + ICB_DESC_TYPE_SHORT = 0, + ICB_DESC_TYPE_LONG = 1, + ICB_DESC_TYPE_EXTENDED = 2, + ICB_DESC_TYPE_INLINE = 3 +}; + +struct CIcbTag +{ + // UInt32 PriorDirectNum; + // UInt16 StrategyType; + // UInt16 StrategyParam; + // UInt16 MaxNumOfEntries; + Byte FileType; + // CLogBlockAddr ParentIcb; + UInt16 Flags; + + bool IsDir() const { return FileType == ICB_FILE_TYPE_DIR; } + int GetDescriptorType() const { return Flags & 3; } + void Parse(const Byte *p); +}; + +// const Byte FILEID_CHARACS_Existance = (1 << 0); +const Byte FILEID_CHARACS_Parent = (1 << 3); + +struct CFile +{ + // UInt16 FileVersion; + // Byte FileCharacteristics; + // CByteBuffer ImplUse; + CDString Id; + + CFile(): /* FileVersion(0), FileCharacteristics(0), */ ItemIndex(-1) {} + int ItemIndex; + UString GetName() const { return Id.GetString(); } +}; + +struct CMyExtent +{ + UInt32 Pos; + UInt32 Len; + int PartitionRef; + + UInt32 GetLen() const { return Len & 0x3FFFFFFF; } + UInt32 GetType() const { return Len >> 30; } + bool IsRecAndAlloc() const { return GetType() == SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated; } +}; + +struct CItem +{ + CIcbTag IcbTag; + + // UInt32 Uid; + // UInt32 Gid; + // UInt32 Permissions; + // UInt16 FileLinkCount; + // Byte RecordFormat; + // Byte RecordDisplayAttr; + // UInt32 RecordLen; + UInt64 Size; + UInt64 NumLogBlockRecorded; + CTime ATime; + CTime MTime; + // CTime AttrtTime; + // UInt32 CheckPoint; + // CLongAllocDesc ExtendedAttrIcb; + // CRegId ImplId; + // UInt64 UniqueId; + + bool IsInline; + CByteBuffer InlineData; + CRecordVector Extents; + CRecordVector SubFiles; + + void Parse(const Byte *buf); + + bool IsRecAndAlloc() const + { + for (int i = 0; i < Extents.Size(); i++) + if (!Extents[i].IsRecAndAlloc()) + return false; + return true; + } + + UInt64 GetChunksSumSize() const + { + if (IsInline) + return InlineData.GetCapacity(); + UInt64 size = 0; + for (int i = 0; i < Extents.Size(); i++) + size += Extents[i].GetLen(); + return size; + } + + bool CheckChunkSizes() const { return GetChunksSumSize() == Size; } + + bool IsDir() const { return IcbTag.IsDir(); } +}; + +struct CRef +{ + int Parent; + int FileIndex; +}; + + +// ECMA 4 / 14.1 +struct CFileSet +{ + CTime RecodringTime; + // UInt16 InterchangeLevel; + // UInt16 MaxInterchangeLevel; + // UInt32 FileSetNumber; + // UInt32 FileSetDescNumber; + // CDString32 Id; + // CDString32 CopyrightId; + // CDString32 AbstractId; + + CLongAllocDesc RootDirICB; + // CRegId DomainId; + // CLongAllocDesc SystemStreamDirICB; + + CRecordVector Refs; +}; + + +// ECMA 3/10.6 + +struct CLogVol +{ + CDString128 Id; + UInt32 BlockSize; + // CRegId DomainId; + + // Byte ContentsUse[16]; + CLongAllocDesc FileSetLocation; // UDF + + // CRegId ImplId; + // Byte ImplUse[128]; + + CObjectVector PartitionMaps; + CObjectVector FileSets; + + UString GetName() const { return Id.GetString(); } +}; + +struct CProgressVirt +{ + virtual HRESULT SetTotal(UInt64 numBytes) PURE; + virtual HRESULT SetCompleted(UInt64 numFiles, UInt64 numBytes) PURE; + virtual HRESULT SetCompleted() PURE; +}; + +class CInArchive +{ + CMyComPtr _stream; + CProgressVirt *_progress; + + HRESULT Read(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len, Byte *buf); + HRESULT Read(int volIndex, const CLongAllocDesc &lad, Byte *buf); + HRESULT ReadFromFile(int volIndex, const CItem &item, CByteBuffer &buf); + + HRESULT ReadFileItem(int volIndex, int fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed); + HRESULT ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed); + + HRESULT Open2(); + HRESULT FillRefs(CFileSet &fs, int fileIndex, int parent, int numRecurseAllowed); + + UInt64 _processedProgressBytes; + + UInt64 _fileNameLengthTotal; + int _numRefs; + UInt32 _numExtents; + UInt64 _inlineExtentsSize; + bool CheckExtent(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len) const; +public: + HRESULT Open(IInStream *inStream, CProgressVirt *progress); + void Clear(); + + CObjectVector Partitions; + CObjectVector LogVols; + + CObjectVector Items; + CObjectVector Files; + + int SecLogSize; + + UString GetComment() const; + UString GetItemPath(int volIndex, int fsIndex, int refIndex, + bool showVolName, bool showFsName) const; + + bool CheckItemExtents(int volIndex, const CItem &item) const; +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Udf/UdfRegister.cpp b/CPP/7zip/Archive/Udf/UdfRegister.cpp new file mode 100755 index 0000000..483614a --- /dev/null +++ b/CPP/7zip/Archive/Udf/UdfRegister.cpp @@ -0,0 +1,13 @@ +// UdfRegister.cpp + +#include "StdAfx.h" + +#include "../../Common/RegisterArc.h" + +#include "UdfHandler.h" +static IInArchive *CreateArc() { return new NArchive::NUdf::CHandler; } + +static CArcInfo g_ArcInfo = + { L"Udf", L"iso img", 0, 0xE0, { 0, 'N', 'S', 'R', '0' }, 5, false, CreateArc, 0 }; + +REGISTER_ARC(Udf) diff --git a/CPP/7zip/Archive/VhdHandler.cpp b/CPP/7zip/Archive/VhdHandler.cpp new file mode 100755 index 0000000..26d1c69 --- /dev/null +++ b/CPP/7zip/Archive/VhdHandler.cpp @@ -0,0 +1,734 @@ +// VhdHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Common/Buffer.h" +#include "Common/ComTry.h" +#include "Common/IntToString.h" +#include "Common/MyString.h" + +#include "Windows/PropVariant.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +#define Get16(p) GetBe16(p) +#define Get32(p) GetBe32(p) +#define Get64(p) GetBe64(p) + +#define G32(p, dest) dest = Get32(p); +#define G64(p, dest) dest = Get64(p); + +using namespace NWindows; + +namespace NArchive { +namespace NVhd { + +static const UInt32 kUnusedBlock = 0xFFFFFFFF; + +static const UInt32 kDiskType_Fixed = 2; +static const UInt32 kDiskType_Dynamic = 3; +static const UInt32 kDiskType_Diff = 4; + +static const char *kDiskTypes[] = +{ + "0", + "1", + "Fixed", + "Dynamic", + "Differencing" +}; + +struct CFooter +{ + // UInt32 Features; + // UInt32 FormatVersion; + UInt64 DataOffset; + UInt32 CTime; + UInt32 CreatorApp; + UInt32 CreatorVersion; + UInt32 CreatorHostOS; + // UInt64 OriginalSize; + UInt64 CurrentSize; + UInt32 DiskGeometry; + UInt32 Type; + Byte Id[16]; + Byte SavedState; + + bool IsFixed() const { return Type == kDiskType_Fixed; } + bool ThereIsDynamic() const { return Type == kDiskType_Dynamic || Type == kDiskType_Diff; } + // bool IsSupported() const { return Type == kDiskType_Fixed || Type == kDiskType_Dynamic || Type == kDiskType_Diff; } + UInt32 NumCyls() const { return DiskGeometry >> 16; } + UInt32 NumHeads() const { return (DiskGeometry >> 8) & 0xFF; } + UInt32 NumSectorsPerTrack() const { return DiskGeometry & 0xFF; } + AString GetTypeString() const; + bool Parse(const Byte *p); +}; + +AString CFooter::GetTypeString() const +{ + if (Type < sizeof(kDiskTypes) / sizeof(kDiskTypes[0])) + return kDiskTypes[Type]; + char s[16]; + ConvertUInt32ToString(Type, s); + return s; +} + +static bool CheckBlock(const Byte *p, unsigned size, unsigned checkSumOffset, unsigned zeroOffset) +{ + UInt32 sum = 0; + unsigned i; + for (i = 0; i < checkSumOffset; i++) + sum += p[i]; + for (i = checkSumOffset + 4; i < size; i++) + sum += p[i]; + if (~sum != Get32(p + checkSumOffset)) + return false; + for (i = zeroOffset; i < size; i++) + if (p[i] != 0) + return false; + return true; +} + +bool CFooter::Parse(const Byte *p) +{ + if (memcmp(p, "conectix", 8) != 0) + return false; + // G32(p + 0x08, Features); + // G32(p + 0x0C, FormatVersion); + G64(p + 0x10, DataOffset); + G32(p + 0x18, CTime); + G32(p + 0x1C, CreatorApp); + G32(p + 0x20, CreatorVersion); + G32(p + 0x24, CreatorHostOS); + // G64(p + 0x28, OriginalSize); + G64(p + 0x30, CurrentSize); + G32(p + 0x38, DiskGeometry); + G32(p + 0x3C, Type); + memcpy(Id, p + 0x44, 16); + SavedState = p[0x54]; + return CheckBlock(p, 512, 0x40, 0x55); +} + +/* +struct CParentLocatorEntry +{ + UInt32 Code; + UInt32 DataSpace; + UInt32 DataLen; + UInt64 DataOffset; + + bool Parse(const Byte *p); +}; +bool CParentLocatorEntry::Parse(const Byte *p) +{ + G32(p + 0x00, Code); + G32(p + 0x04, DataSpace); + G32(p + 0x08, DataLen); + G32(p + 0x10, DataOffset); + return (Get32(p + 0x0C) == 0); // Resrved +} +*/ + +struct CDynHeader +{ + // UInt64 DataOffset; + UInt64 TableOffset; + // UInt32 HeaderVersion; + UInt32 NumBlocks; + int BlockSizeLog; + UInt32 ParentTime; + Byte ParentId[16]; + UString ParentName; + // CParentLocatorEntry ParentLocators[8]; + + bool Parse(const Byte *p); + UInt32 NumBitMapSectors() const + { + UInt32 numSectorsInBlock = (1 << (BlockSizeLog - 9)); + return (numSectorsInBlock + 512 * 8 - 1) / (512 * 8); + } +}; + +static int GetLog(UInt32 num) +{ + for (int i = 0; i < 31; i++) + if (((UInt32)1 << i) == num) + return i; + return -1; +} + +bool CDynHeader::Parse(const Byte *p) +{ + if (memcmp(p, "cxsparse", 8) != 0) + return false; + // G64(p + 0x08, DataOffset); + G64(p + 0x10, TableOffset); + // G32(p + 0x18, HeaderVersion); + G32(p + 0x1C, NumBlocks); + BlockSizeLog = GetLog(Get32(p + 0x20)); + if (BlockSizeLog < 9 || BlockSizeLog > 30) + return false; + G32(p + 0x38, ParentTime); + if (Get32(p + 0x3C) != 0) // reserved + return false; + memcpy(ParentId, p + 0x28, 16); + { + const int kNameLength = 256; + wchar_t *s = ParentName.GetBuffer(kNameLength); + for (unsigned i = 0; i < kNameLength; i++) + s[i] = Get16(p + 0x40 + i * 2); + s[kNameLength] = 0; + ParentName.ReleaseBuffer(); + } + /* + for (int i = 0; i < 8; i++) + if (!ParentLocators[i].Parse(p + 0x240 + i * 24)) + return false; + */ + return CheckBlock(p, 1024, 0x24, 0x240 + 8 * 24); +} + +class CHandler: + public IInStream, + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + UInt64 _virtPos; + UInt64 _phyPos; + UInt64 _phyLimit; + + CFooter Footer; + CDynHeader Dyn; + CRecordVector Bat; + CByteBuffer BitMap; + UInt32 BitMapTag; + UInt32 NumUsedBlocks; + CMyComPtr Stream; + CMyComPtr ParentStream; + CHandler *Parent; + + HRESULT Seek(UInt64 offset); + HRESULT InitAndSeek(); + HRESULT ReadPhy(UInt64 offset, void *data, UInt32 size); + + bool NeedParent() const { return Footer.Type == kDiskType_Diff; } + UInt64 GetPackSize() const + { return Footer.ThereIsDynamic() ? ((UInt64)NumUsedBlocks << Dyn.BlockSizeLog) : Footer.CurrentSize; } + + UString GetParentName() const + { + const CHandler *p = this; + UString res; + while (p && p->NeedParent()) + { + if (!res.IsEmpty()) + res += L" -> "; + res += p->Dyn.ParentName; + p = p->Parent; + } + return res; + } + + bool IsOK() const + { + const CHandler *p = this; + while (p->NeedParent()) + { + p = p->Parent; + if (p == 0) + return false; + } + return true; + } + + HRESULT Open3(); + HRESULT Open2(IInStream *stream, CHandler *child, IArchiveOpenCallback *openArchiveCallback, int level); + +public: + MY_UNKNOWN_IMP3(IInArchive, IInArchiveGetStream, IInStream) + + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + +HRESULT CHandler::Seek(UInt64 offset) { return Stream->Seek(offset, STREAM_SEEK_SET, NULL); } + +HRESULT CHandler::InitAndSeek() +{ + if (ParentStream) + { + RINOK(Parent->InitAndSeek()); + } + _virtPos = _phyPos = 0; + BitMapTag = kUnusedBlock; + BitMap.SetCapacity(Dyn.NumBitMapSectors() << 9); + return Seek(0); +} + +HRESULT CHandler::ReadPhy(UInt64 offset, void *data, UInt32 size) +{ + if (offset + size > _phyLimit) + return S_FALSE; + if (offset != _phyPos) + { + _phyPos = offset; + RINOK(Seek(offset)); + } + HRESULT res = ReadStream_FALSE(Stream, data, size); + _phyPos += size; + return res; +} + +HRESULT CHandler::Open3() +{ + RINOK(Stream->Seek(0, STREAM_SEEK_END, &_phyPos)); + if (_phyPos < 512) + return S_FALSE; + const UInt32 kDynSize = 1024; + Byte buf[kDynSize]; + + _phyLimit = _phyPos; + RINOK(ReadPhy(_phyLimit - 512, buf, 512)); + if (!Footer.Parse(buf)) + return S_FALSE; + _phyLimit -= 512; + + if (!Footer.ThereIsDynamic()) + return S_OK; + + RINOK(ReadPhy(0, buf + 512, 512)); + if (memcmp(buf, buf + 512, 512) != 0) + return S_FALSE; + + RINOK(ReadPhy(Footer.DataOffset, buf, kDynSize)); + if (!Dyn.Parse(buf)) + return S_FALSE; + + if (Dyn.NumBlocks >= (UInt32)1 << 31) + return S_FALSE; + if (Footer.CurrentSize == 0) + { + if (Dyn.NumBlocks != 0) + return S_FALSE; + } + else if (((Footer.CurrentSize - 1) >> Dyn.BlockSizeLog) + 1 != Dyn.NumBlocks) + return S_FALSE; + + Bat.Reserve(Dyn.NumBlocks); + while ((UInt32)Bat.Size() < Dyn.NumBlocks) + { + RINOK(ReadPhy(Dyn.TableOffset + (UInt64)Bat.Size() * 4, buf, 512)); + for (UInt32 j = 0; j < 512; j += 4) + { + UInt32 v = Get32(buf + j); + if (v != kUnusedBlock) + NumUsedBlocks++; + Bat.Add(v); + if ((UInt32)Bat.Size() >= Dyn.NumBlocks) + break; + } + } + return S_OK; +} + +STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != NULL) + *processedSize = 0; + if (_virtPos >= Footer.CurrentSize) + return (Footer.CurrentSize == _virtPos) ? S_OK: E_FAIL; + UInt64 rem = Footer.CurrentSize - _virtPos; + if (size > rem) + size = (UInt32)rem; + if (size == 0) + return S_OK; + UInt32 blockIndex = (UInt32)(_virtPos >> Dyn.BlockSizeLog); + UInt32 blockSectIndex = Bat[blockIndex]; + UInt32 blockSize = (UInt32)1 << Dyn.BlockSizeLog; + UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1); + size = MyMin(blockSize - offsetInBlock, size); + + HRESULT res = S_OK; + if (blockSectIndex == kUnusedBlock) + { + if (ParentStream) + { + RINOK(ParentStream->Seek(_virtPos, STREAM_SEEK_SET, NULL)); + res = ParentStream->Read(data, size, &size); + } + else + memset(data, 0, size); + } + else + { + UInt64 newPos = (UInt64)blockSectIndex << 9; + if (BitMapTag != blockIndex) + { + RINOK(ReadPhy(newPos, BitMap, (UInt32)BitMap.GetCapacity())); + BitMapTag = blockIndex; + } + RINOK(ReadPhy(newPos + BitMap.GetCapacity() + offsetInBlock, data, size)); + for (UInt32 cur = 0; cur < size;) + { + UInt32 rem = MyMin(0x200 - (offsetInBlock & 0x1FF), size - cur); + UInt32 bmi = offsetInBlock >> 9; + if (((BitMap[bmi >> 3] >> (7 - (bmi & 7))) & 1) == 0) + { + if (ParentStream) + { + RINOK(ParentStream->Seek(_virtPos + cur, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream_FALSE(ParentStream, (Byte *)data + cur, rem)); + } + else + { + const Byte *p = (const Byte *)data + cur; + for (UInt32 i = 0; i < rem; i++) + if (p[i] != 0) + return S_FALSE; + } + } + offsetInBlock += rem; + cur += rem; + } + } + if (processedSize != NULL) + *processedSize = size; + _virtPos += size; + return res; +} + +STDMETHODIMP CHandler::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch(seekOrigin) + { + case STREAM_SEEK_SET: _virtPos = offset; break; + case STREAM_SEEK_CUR: _virtPos += offset; break; + case STREAM_SEEK_END: _virtPos = Footer.CurrentSize + offset; break; + default: return STG_E_INVALIDFUNCTION; + } + if (newPosition) + *newPosition = _virtPos; + return S_OK; +} + +enum +{ + kpidParent = kpidUserDefined, + kpidSavedState +}; + +STATPROPSTG kArcProps[] = +{ + { NULL, kpidSize, VT_UI8}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidClusterSize, VT_UI8}, + { NULL, kpidMethod, VT_BSTR}, + { L"Parent", kpidParent, VT_BSTR}, + { NULL, kpidCreatorApp, VT_BSTR}, + { NULL, kpidHostOS, VT_BSTR}, + { L"Saved State", kpidSavedState, VT_BOOL}, + { NULL, kpidId, VT_BSTR} + }; + +STATPROPSTG kProps[] = +{ + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidCTime, VT_FILETIME} + + /* + { NULL, kpidNumCyls, VT_UI4}, + { NULL, kpidNumHeads, VT_UI4}, + { NULL, kpidSectorsPerTrack, VT_UI4} + */ +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_WITH_NAME + +// VHD start time: 2000-01-01 +static const UInt64 kVhdTimeStartValue = (UInt64)3600 * 24 * (399 * 365 + 24 * 4); + +static void VhdTimeToFileTime(UInt32 vhdTime, NCOM::CPropVariant &prop) +{ + FILETIME ft, utc; + UInt64 v = (kVhdTimeStartValue + vhdTime) * 10000000; + ft.dwLowDateTime = (DWORD)v; + ft.dwHighDateTime = (DWORD)(v >> 32); + // specification says that it's UTC time, but Virtual PC 6 writes local time. Why? + LocalFileTimeToFileTime(&ft, &utc); + prop = utc; +} + +static void StringToAString(char *dest, UInt32 s) +{ + for (int i = 24; i >= 0; i -= 8) + { + Byte b = (Byte)((s >> i) & 0xFF); + if (b < 0x20 || b > 0x7F) + break; + *dest++ = b; + } + *dest = 0; +} + +static void ConvertByteToHex(unsigned value, char *s) +{ + for (int i = 0; i < 2; i++) + { + unsigned t = value & 0xF; + value >>= 4; + s[1 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + } +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NCOM::CPropVariant prop; + switch(propID) + { + case kpidMainSubfile: prop = (UInt32)0; break; + case kpidCTime: VhdTimeToFileTime(Footer.CTime, prop); break; + case kpidClusterSize: if (Footer.ThereIsDynamic()) prop = (UInt32)1 << Dyn.BlockSizeLog; break; + case kpidMethod: + { + AString s = Footer.GetTypeString(); + if (NeedParent()) + { + s += " -> "; + const CHandler *p = this; + while (p != 0 && p->NeedParent()) + p = p->Parent; + if (p == 0) + s += '?'; + else + s += p->Footer.GetTypeString(); + } + prop = s; + break; + } + case kpidCreatorApp: + { + char s[16]; + StringToAString(s, Footer.CreatorApp); + AString res = s; + res.Trim(); + ConvertUInt32ToString(Footer.CreatorVersion >> 16, s); + res += ' '; + res += s; + res += '.'; + ConvertUInt32ToString(Footer.CreatorVersion & 0xFFFF, s); + res += s; + prop = res; + break; + } + case kpidHostOS: + { + if (Footer.CreatorHostOS == 0x5769326b) + prop = "Windows"; + else + { + char s[16]; + StringToAString(s, Footer.CreatorHostOS); + prop = s; + } + break; + } + case kpidId: + { + char s[32 + 4]; + for (int i = 0; i < 16; i++) + ConvertByteToHex(Footer.Id[i], s + i * 2); + s[32] = 0; + prop = s; + break; + } + case kpidSavedState: prop = Footer.SavedState ? true : false; break; + case kpidParent: if (NeedParent()) prop = GetParentName(); break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +HRESULT CHandler::Open2(IInStream *stream, CHandler *child, IArchiveOpenCallback *openArchiveCallback, int level) +{ + Close(); + Stream = stream; + if (level > 32) + return S_FALSE; + RINOK(Open3()); + if (child && memcmp(child->Dyn.ParentId, Footer.Id, 16) != 0) + return S_FALSE; + if (Footer.Type != kDiskType_Diff) + return S_OK; + CMyComPtr openVolumeCallback; + if (openArchiveCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback) != S_OK) + return S_FALSE; + CMyComPtr nextStream; + HRESULT res = openVolumeCallback->GetStream(Dyn.ParentName, &nextStream); + if (res == S_FALSE) + return S_OK; + RINOK(res); + + Parent = new CHandler; + ParentStream = Parent; + return Parent->Open2(nextStream, this, openArchiveCallback, level + 1); +} + +STDMETHODIMP CHandler::Open(IInStream *stream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback * openArchiveCallback) +{ + COM_TRY_BEGIN + { + HRESULT res; + try + { + res = Open2(stream, NULL, openArchiveCallback, 0); + if (res == S_OK) + return S_OK; + } + catch(...) + { + Close(); + throw; + } + Close(); + return res; + } + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + Bat.Clear(); + NumUsedBlocks = 0; + Parent = 0; + Stream.Release(); + ParentStream.Release(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = 1; + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + + switch(propID) + { + case kpidSize: prop = Footer.CurrentSize; break; + case kpidPackSize: prop = GetPackSize(); break; + case kpidCTime: VhdTimeToFileTime(Footer.CTime, prop); break; + /* + case kpidNumCyls: prop = Footer.NumCyls(); break; + case kpidNumHeads: prop = Footer.NumHeads(); break; + case kpidSectorsPerTrack: prop = Footer.NumSectorsPerTrack(); break; + */ + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + if (numItems == 0) + return S_OK; + if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0)) + return E_INVALIDARG; + + RINOK(extractCallback->SetTotal(Footer.CurrentSize)); + 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); + + int res = NExtract::NOperationResult::kDataError; + CMyComPtr inStream; + HRESULT hres = GetStream(0, &inStream); + if (hres == S_FALSE) + res = NExtract::NOperationResult::kUnSupportedMethod; + else + { + RINOK(hres); + HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress); + if (hres == S_OK) + { + if (copyCoderSpec->TotalSize == Footer.CurrentSize) + res = NExtract::NOperationResult::kOK; + } + else + { + if (hres != S_FALSE) + { + RINOK(hres); + } + } + } + outStream.Release(); + return extractCallback->SetOperationResult(res); + COM_TRY_END +} + +STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + *stream = 0; + if (Footer.IsFixed()) + { + CLimitedInStream *streamSpec = new CLimitedInStream; + CMyComPtr streamTemp = streamSpec; + streamSpec->SetStream(Stream); + streamSpec->InitAndSeek(0, Footer.CurrentSize); + RINOK(streamSpec->SeekToStart()); + *stream = streamTemp.Detach(); + return S_OK; + } + if (!Footer.ThereIsDynamic() || !IsOK()) + return S_FALSE; + CMyComPtr streamTemp = this; + RINOK(InitAndSeek()); + *stream = streamTemp.Detach(); + return S_OK; + COM_TRY_END +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"VHD", L"vhd", L".mbr", 0xDC, { 'c', 'o', 'n', 'e', 'c', 't', 'i', 'x', 0, 0 }, 10, false, CreateArc, 0 }; + +REGISTER_ARC(Vhd) + +}} diff --git a/CPP/7zip/Archive/Wim/StdAfx.h b/CPP/7zip/Archive/Wim/StdAfx.h new file mode 100755 index 0000000..83fdd22 --- /dev/null +++ b/CPP/7zip/Archive/Wim/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" + +#endif diff --git a/CPP/7zip/Archive/Wim/WimHandler.cpp b/CPP/7zip/Archive/Wim/WimHandler.cpp new file mode 100755 index 0000000..a1fddff --- /dev/null +++ b/CPP/7zip/Archive/Wim/WimHandler.cpp @@ -0,0 +1,660 @@ +// WimHandler.cpp + +#include "StdAfx.h" + +#include "../../../../C/CpuArch.h" + +#include "Common/ComTry.h" +#include "Common/IntToString.h" +#include "Common/StringToInt.h" +#include "Common/UTFConvert.h" + +#include "Windows/PropVariant.h" + +#include "../../Common/ProgressUtils.h" +#include "../../Common/StreamUtils.h" + +#include "WimHandler.h" + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) +#define Get64(p) GetUi64(p) + +using namespace NWindows; + +namespace NArchive { +namespace NWim { + +#define WIM_DETAILS + +static STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidATime, VT_FILETIME}, + { NULL, kpidAttrib, VT_UI4}, + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidShortName, VT_BSTR} + + #ifdef WIM_DETAILS + , { NULL, kpidVolume, VT_UI4} + , { NULL, kpidOffset, VT_UI8} + , { NULL, kpidLinks, VT_UI4} + #endif +}; + +static STATPROPSTG kArcProps[] = +{ + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidComment, VT_BSTR}, + { NULL, kpidUnpackVer, VT_BSTR}, + { NULL, kpidIsVolume, VT_BOOL}, + { NULL, kpidVolume, VT_UI4}, + { NULL, kpidNumVolumes, VT_UI4} +}; + +static bool ParseNumber64(const AString &s, UInt64 &res) +{ + const char *end; + if (s.Left(2) == "0x") + { + if (s.Length() == 2) + return false; + res = ConvertHexStringToUInt64((const char *)s + 2, &end); + } + else + { + if (s.IsEmpty()) + return false; + res = ConvertStringToUInt64(s, &end); + } + return *end == 0; +} + +static bool ParseNumber32(const AString &s, UInt32 &res) +{ + UInt64 res64; + if (!ParseNumber64(s, res64) || res64 >= ((UInt64)1 << 32)) + return false; + res = (UInt32)res64; + return true; +} + +bool ParseTime(const CXmlItem &item, FILETIME &ft, const char *tag) +{ + int index = item.FindSubTag(tag); + if (index >= 0) + { + const CXmlItem &timeItem = item.SubItems[index]; + UInt32 low = 0, high = 0; + if (ParseNumber32(timeItem.GetSubStringForTag("LOWPART"), low) && + ParseNumber32(timeItem.GetSubStringForTag("HIGHPART"), high)) + { + ft.dwLowDateTime = low; + ft.dwHighDateTime = high; + return true; + } + } + return false; +} + +void CImageInfo::Parse(const CXmlItem &item) +{ + CTimeDefined = ParseTime(item, CTime, "CREATIONTIME"); + MTimeDefined = ParseTime(item, MTime, "LASTMODIFICATIONTIME"); + NameDefined = ConvertUTF8ToUnicode(item.GetSubStringForTag("NAME"), Name); + // IndexDefined = ParseNumber32(item.GetPropertyValue("INDEX"), Index); +} + +void CXml::ToUnicode(UString &s) +{ + size_t size = Data.GetCapacity(); + if (size < 2 || (size & 1) != 0 || size > (1 << 24)) + return; + const Byte *p = Data; + if (Get16(p) != 0xFEFF) + return; + wchar_t *chars = s.GetBuffer((int)size / 2); + for (size_t i = 2; i < size; i += 2) + *chars++ = (wchar_t)Get16(p + i); + *chars = 0; + s.ReleaseBuffer(); +} + +void CXml::Parse() +{ + UString s; + ToUnicode(s); + AString utf; + if (!ConvertUnicodeToUTF8(s, utf)) + return; + ::CXml xml; + if (!xml.Parse(utf)) + return; + if (xml.Root.Name != "WIM") + return; + + for (int i = 0; i < xml.Root.SubItems.Size(); i++) + { + const CXmlItem &item = xml.Root.SubItems[i]; + if (item.IsTagged("IMAGE")) + { + CImageInfo imageInfo; + imageInfo.Parse(item); + Images.Add(imageInfo); + } + } +} + +static const char *kMethodLZX = "LZX"; +static const char *kMethodXpress = "XPress"; +static const char *kMethodCopy = "Copy"; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + + const CImageInfo *image = NULL; + if (_xmls.Size() == 1) + { + const CXml &xml = _xmls[0]; + if (xml.Images.Size() == 1) + image = &xml.Images[0]; + } + + switch(propID) + { + case kpidSize: prop = _db.GetUnpackSize(); break; + case kpidPackSize: prop = _db.GetPackSize(); break; + + case kpidCTime: + if (_xmls.Size() == 1) + { + const CXml &xml = _xmls[0]; + int index = -1; + for (int i = 0; i < xml.Images.Size(); i++) + { + const CImageInfo &image = xml.Images[i]; + if (image.CTimeDefined) + if (index < 0 || ::CompareFileTime(&image.CTime, &xml.Images[index].CTime) < 0) + index = i; + } + if (index >= 0) + prop = xml.Images[index].CTime; + } + break; + + case kpidMTime: + if (_xmls.Size() == 1) + { + const CXml &xml = _xmls[0]; + int index = -1; + for (int i = 0; i < xml.Images.Size(); i++) + { + const CImageInfo &image = xml.Images[i]; + if (image.MTimeDefined) + if (index < 0 || ::CompareFileTime(&image.MTime, &xml.Images[index].MTime) > 0) + index = i; + } + if (index >= 0) + prop = xml.Images[index].MTime; + } + break; + + case kpidComment: + if (image != NULL) + { + if (_xmlInComments) + { + UString s; + _xmls[0].ToUnicode(s); + prop = s; + } + else if (image->NameDefined) + prop = image->Name; + } + break; + + case kpidUnpackVer: + { + UInt32 ver1 = _version >> 16; + UInt32 ver2 = (_version >> 8) & 0xFF; + UInt32 ver3 = (_version) & 0xFF; + + char s[16]; + ConvertUInt32ToString(ver1, s); + AString res = s; + res += '.'; + ConvertUInt32ToString(ver2, s); + res += s; + if (ver3 != 0) + { + res += '.'; + ConvertUInt32ToString(ver3, s); + res += s; + } + prop = res; + break; + } + + case kpidIsVolume: + if (_xmls.Size() > 0) + { + UInt16 volIndex = _xmls[0].VolIndex; + if (volIndex < _volumes.Size()) + prop = (_volumes[volIndex].Header.NumParts > 1); + } + break; + case kpidVolume: + if (_xmls.Size() > 0) + { + UInt16 volIndex = _xmls[0].VolIndex; + if (volIndex < _volumes.Size()) + prop = (UInt32)_volumes[volIndex].Header.PartNumber; + } + break; + case kpidNumVolumes: if (_volumes.Size() > 0) prop = (UInt32)(_volumes.Size() - 1); break; + case kpidMethod: + { + bool lzx = false, xpress = false, copy = false; + for (int i = 0; i < _xmls.Size(); i++) + { + const CHeader &header = _volumes[_xmls[i].VolIndex].Header; + if (header.IsCompressed()) + if (header.IsLzxMode()) + lzx = true; + else + xpress = true; + else + copy = true; + } + AString res; + if (lzx) + res = kMethodLZX; + if (xpress) + { + if (!res.IsEmpty()) + res += ' '; + res += kMethodXpress; + } + if (copy) + { + if (!res.IsEmpty()) + res += ' '; + res += kMethodCopy; + } + prop = res; + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + if (index < (UInt32)_db.SortedItems.Size()) + { + int realIndex = _db.SortedItems[index]; + const CItem &item = _db.Items[realIndex]; + const CStreamInfo *si = NULL; + const CVolume *vol = NULL; + if (item.StreamIndex >= 0) + { + si = &_db.Streams[item.StreamIndex]; + vol = &_volumes[si->PartNumber]; + } + + switch(propID) + { + case kpidPath: + if (item.HasMetadata) + prop = _db.GetItemPath(realIndex); + else + { + char sz[16]; + ConvertUInt32ToString(item.StreamIndex, sz); + AString s = sz; + while (s.Length() < _nameLenForStreams) + s = '0' + s; + /* + if (si->Resource.IsFree()) + prefix = "[Free]"; + */ + s = "[Files]" STRING_PATH_SEPARATOR + s; + prop = s; + } + break; + case kpidShortName: if (item.HasMetadata) prop = item.ShortName; break; + + case kpidIsDir: prop = item.IsDir(); break; + case kpidAttrib: if (item.HasMetadata) prop = item.Attrib; break; + case kpidCTime: if (item.HasMetadata) prop = item.CTime; break; + case kpidATime: if (item.HasMetadata) prop = item.ATime; break; + case kpidMTime: if (item.HasMetadata) prop = item.MTime; break; + case kpidPackSize: prop = si ? si->Resource.PackSize : (UInt64)0; break; + case kpidSize: prop = si ? si->Resource.UnpackSize : (UInt64)0; break; + case kpidMethod: if (si) prop = si->Resource.IsCompressed() ? + (vol->Header.IsLzxMode() ? kMethodLZX : kMethodXpress) : kMethodCopy; break; + #ifdef WIM_DETAILS + case kpidVolume: if (si) prop = (UInt32)si->PartNumber; break; + case kpidOffset: if (si) prop = (UInt64)si->Resource.Offset; break; + case kpidLinks: prop = si ? (UInt32)si->RefCount : (UInt32)0; break; + #endif + } + } + else + { + index -= _db.SortedItems.Size(); + { + switch(propID) + { + case kpidPath: + { + char sz[16]; + ConvertUInt32ToString(_xmls[index].VolIndex, sz); + prop = (AString)"[" + (AString)sz + "].xml"; + break; + } + case kpidIsDir: prop = false; break; + case kpidPackSize: + case kpidSize: prop = (UInt64)_xmls[index].Data.GetCapacity(); break; + case kpidMethod: prop = kMethodCopy; break; + } + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +class CVolumeName +{ + // UInt32 _volIndex; + UString _before; + UString _after; +public: + CVolumeName() {}; + + void InitName(const UString &name) + { + // _volIndex = 1; + int dotPos = name.ReverseFind('.'); + if (dotPos < 0) + dotPos = name.Length(); + _before = name.Left(dotPos); + _after = name.Mid(dotPos); + } + + UString GetNextName(UInt32 index) + { + wchar_t s[16]; + ConvertUInt32ToString(index, s); + return _before + (UString)s + _after; + } +}; + +STDMETHODIMP CHandler::Open(IInStream *inStream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback *openArchiveCallback) +{ + COM_TRY_BEGIN + Close(); + { + CMyComPtr openVolumeCallback; + + CVolumeName seqName; + if (openArchiveCallback != NULL) + openArchiveCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback); + + UInt32 numVolumes = 1; + int firstVolumeIndex = -1; + for (UInt32 i = 1; i <= numVolumes; i++) + { + CMyComPtr curStream; + if (i != 1) + { + UString fullName = seqName.GetNextName(i); + HRESULT result = openVolumeCallback->GetStream(fullName, &curStream); + if (result == S_FALSE) + continue; + if (result != S_OK) + return result; + if (!curStream) + break; + } + else + curStream = inStream; + CHeader header; + HRESULT res = NWim::ReadHeader(curStream, header); + if (res != S_OK) + { + if (i == 1) + return res; + if (res == S_FALSE) + continue; + return res; + } + _version = header.Version; + _isOldVersion = header.IsOldVersion(); + if (firstVolumeIndex >= 0) + if (!header.AreFromOnArchive(_volumes[firstVolumeIndex].Header)) + break; + if (_volumes.Size() > header.PartNumber && _volumes[header.PartNumber].Stream) + break; + CXml xml; + xml.VolIndex = header.PartNumber; + res = _db.Open(curStream, header, xml.Data, openArchiveCallback); + if (res != S_OK) + { + if (i == 1) + return res; + if (res == S_FALSE) + continue; + return res; + } + + while (_volumes.Size() <= header.PartNumber) + _volumes.Add(CVolume()); + CVolume &volume = _volumes[header.PartNumber]; + volume.Header = header; + volume.Stream = curStream; + + firstVolumeIndex = header.PartNumber; + + bool needAddXml = true; + if (_xmls.Size() != 0) + if (xml.Data == _xmls[0].Data) + needAddXml = false; + if (needAddXml) + { + xml.Parse(); + _xmls.Add(xml); + } + + if (i == 1) + { + if (header.PartNumber != 1) + break; + if (!openVolumeCallback) + break; + numVolumes = header.NumParts; + { + NCOM::CPropVariant prop; + RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); + if (prop.vt != VT_BSTR) + break; + seqName.InitName(prop.bstrVal); + } + } + } + + _db.DetectPathMode(); + RINOK(_db.Sort(_db.SkipRoot)); + + wchar_t sz[16]; + ConvertUInt32ToString(_db.Streams.Size(), sz); + _nameLenForStreams = MyStringLen(sz); + + _xmlInComments = (_xmls.Size() == 1 && !_db.ShowImageNumber); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _db.Clear(); + _volumes.Clear(); + _xmls.Clear(); + _nameLenForStreams = 0; + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + + if (allFilesMode) + numItems = _db.SortedItems.Size() + _xmls.Size(); + if (numItems == 0) + return S_OK; + + UInt32 i; + UInt64 totalSize = 0; + for (i = 0; i < numItems; i++) + { + UInt32 index = allFilesMode ? i : indices[i]; + if (index < (UInt32)_db.SortedItems.Size()) + { + int streamIndex = _db.Items[_db.SortedItems[index]].StreamIndex; + if (streamIndex >= 0) + { + const CStreamInfo &si = _db.Streams[streamIndex]; + totalSize += si.Resource.UnpackSize; + } + } + else + totalSize += _xmls[index - (UInt32)_db.SortedItems.Size()].Data.GetCapacity(); + } + + RINOK(extractCallback->SetTotal(totalSize)); + + UInt64 currentTotalPacked = 0; + UInt64 currentTotalUnPacked = 0; + UInt64 currentItemUnPacked, currentItemPacked; + + int prevSuccessStreamIndex = -1; + + CUnpacker unpacker; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + for (i = 0; i < numItems; currentTotalUnPacked += currentItemUnPacked, + currentTotalPacked += currentItemPacked) + { + currentItemUnPacked = 0; + currentItemPacked = 0; + + lps->InSize = currentTotalPacked; + lps->OutSize = currentTotalUnPacked; + + RINOK(lps->SetCur()); + UInt32 index = allFilesMode ? i : indices[i]; + i++; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + + CMyComPtr realOutStream; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + if (index >= (UInt32)_db.SortedItems.Size()) + { + if (!testMode && !realOutStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + const CByteBuffer &data = _xmls[index - (UInt32)_db.SortedItems.Size()].Data; + currentItemUnPacked = data.GetCapacity(); + if (realOutStream) + { + RINOK(WriteStream(realOutStream, (const Byte *)data, data.GetCapacity())); + realOutStream.Release(); + } + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + + const CItem &item = _db.Items[_db.SortedItems[index]]; + int streamIndex = item.StreamIndex; + if (streamIndex < 0) + { + if (!testMode && !realOutStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(item.HasStream() ? + NExtract::NOperationResult::kDataError : + NExtract::NOperationResult::kOK)); + continue; + } + + const CStreamInfo &si = _db.Streams[streamIndex]; + currentItemUnPacked = si.Resource.UnpackSize; + currentItemPacked = si.Resource.PackSize; + + if (!testMode && !realOutStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + Int32 opRes = NExtract::NOperationResult::kOK; + if (streamIndex != prevSuccessStreamIndex || realOutStream) + { + Byte digest[20]; + const CVolume &vol = _volumes[si.PartNumber]; + HRESULT res = unpacker.Unpack(vol.Stream, si.Resource, vol.Header.IsLzxMode(), + realOutStream, progress, digest); + if (res == S_OK) + { + if (memcmp(digest, si.Hash, kHashSize) == 0) + prevSuccessStreamIndex = streamIndex; + else + opRes = NExtract::NOperationResult::kCRCError; + } + else if (res == S_FALSE) + opRes = NExtract::NOperationResult::kDataError; + else + return res; + } + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(opRes)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _db.SortedItems.Size(); + if (!_xmlInComments) + *numItems += _xmls.Size(); + return S_OK; +} + +}} diff --git a/CPP/7zip/Archive/Wim/WimHandler.h b/CPP/7zip/Archive/Wim/WimHandler.h new file mode 100755 index 0000000..5f5ab98 --- /dev/null +++ b/CPP/7zip/Archive/Wim/WimHandler.h @@ -0,0 +1,77 @@ +// WimHandler.h + +#ifndef __ARCHIVE_WIM_HANDLER_H +#define __ARCHIVE_WIM_HANDLER_H + +#include "Common/MyCom.h" +#include "Common/MyXml.h" + +#include "WimIn.h" + +namespace NArchive { +namespace NWim { + +struct CVolume +{ + CHeader Header; + CMyComPtr Stream; +}; + +struct CImageInfo +{ + bool CTimeDefined; + bool MTimeDefined; + bool NameDefined; + // bool IndexDefined; + + FILETIME CTime; + FILETIME MTime; + UString Name; + // UInt32 Index; + + CImageInfo(): CTimeDefined(false), MTimeDefined(false), NameDefined(false) + // , IndexDefined(false) + {} + void Parse(const CXmlItem &item); +}; + +struct CXml +{ + CByteBuffer Data; + UInt16 VolIndex; + CObjectVector Images; + + void ToUnicode(UString &s); + void Parse(); +}; + + +class CHandler: + public IInArchive, + public CMyUnknownImp +{ + CDatabase _db; + UInt32 _version; + bool _isOldVersion; + CObjectVector _volumes; + CObjectVector _xmls; + int _nameLenForStreams; + bool _xmlInComments; + +public: + MY_UNKNOWN_IMP1(IInArchive) + INTERFACE_IInArchive(;) +}; + +class COutHandler: + public IOutArchive, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP1(IOutArchive) + INTERFACE_IOutArchive(;) +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp new file mode 100755 index 0000000..5ee1b73 --- /dev/null +++ b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp @@ -0,0 +1,639 @@ +// WimHandlerOut.cpp + +#include "StdAfx.h" + +#include "../../../../C/CpuArch.h" + +#include "Common/ComTry.h" +#include "Common/IntToString.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../../Common/LimitedStreams.h" +#include "../../Common/ProgressUtils.h" +#include "../../Common/StreamUtils.h" + +#include "../../Crypto/RandGen.h" +#include "../../Crypto/Sha1.h" + +#include "WimHandler.h" + +using namespace NWindows; + +namespace NArchive { +namespace NWim { + +struct CSha1Hash +{ + Byte Hash[kHashSize]; +}; + +struct CHashList +{ + CRecordVector Digests; + CIntVector Sorted; + + int AddUnique(const CSha1Hash &h); +}; + +int CHashList::AddUnique(const CSha1Hash &h) +{ + int left = 0, right = Sorted.Size(); + while (left != right) + { + int mid = (left + right) / 2; + int index = Sorted[mid]; + UInt32 i; + const Byte *hash2 = Digests[index].Hash; + for (i = 0; i < kHashSize; i++) + if (h.Hash[i] != hash2[i]) + break; + if (i == kHashSize) + return index; + if (h.Hash[i] < hash2[i]) + right = mid; + else + left = mid + 1; + } + Sorted.Insert(left, Digests.Add(h)); + return -1; +} + +struct CUpdateItem +{ + UString Name; + UInt64 Size; + FILETIME CTime; + FILETIME ATime; + FILETIME MTime; + UInt32 Attrib; + bool IsDir; + int HashIndex; + + CUpdateItem(): HashIndex(-1) {} +}; + +struct CDir +{ + int Index; + UString Name; + CObjectVector Dirs; + CIntVector Files; + + CDir(): Index(-1) {} + bool IsLeaf() const { return Index >= 0; } + UInt64 GetNumDirs() const; + UInt64 GetNumFiles() const; + CDir* AddDir(CObjectVector &items, const UString &name, int index); +}; + +UInt64 CDir::GetNumDirs() const +{ + UInt64 num = Dirs.Size(); + for (int i = 0; i < Dirs.Size(); i++) + num += Dirs[i].GetNumDirs(); + return num; +} + +UInt64 CDir::GetNumFiles() const +{ + UInt64 num = Files.Size(); + for (int i = 0; i < Dirs.Size(); i++) + num += Dirs[i].GetNumFiles(); + return num; +} + +CDir* CDir::AddDir(CObjectVector &items, const UString &name, int index) +{ + int left = 0, right = Dirs.Size(); + while (left != right) + { + int mid = (left + right) / 2; + CDir &d = Dirs[mid]; + int compare = name.CompareNoCase(d.IsLeaf() ? items[Dirs[mid].Index].Name : d.Name); + if (compare == 0) + { + if (index >= 0) + d.Index = index; + return &d; + } + if (compare < 0) + right = mid; + else + left = mid + 1; + } + Dirs.Insert(left, CDir()); + CDir &d = Dirs[left]; + d.Index = index; + if (index < 0) + d.Name = name; + return &d; +} + + +STDMETHODIMP COutHandler::GetFileTimeType(UInt32 *type) +{ + *type = NFileTimeType::kWindows; + return S_OK; +} + +static HRESULT GetTime(IArchiveUpdateCallback *callback, int index, PROPID propID, FILETIME &ft) +{ + ft.dwLowDateTime = ft.dwHighDateTime = 0; + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(index, propID, &prop)); + if (prop.vt == VT_FILETIME) + ft = prop.filetime; + else if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + return S_OK; +} + +#define Set16(p, d) SetUi16(p, d) +#define Set32(p, d) SetUi32(p, d) +#define Set64(p, d) SetUi64(p, d) + +void CResource::WriteTo(Byte *p) const +{ + Set64(p, PackSize); + p[7] = Flags; + Set64(p + 8, Offset); + Set64(p + 16, UnpackSize); +} + +void CHeader::WriteTo(Byte *p) const +{ + memcpy(p, kSignature, kSignatureSize); + Set32(p + 8, kHeaderSizeMax); + Set32(p + 0xC, Version); + Set32(p + 0x10, Flags); + Set32(p + 0x14, ChunkSize); + memcpy(p + 0x18, Guid, 16); + Set16(p + 0x28, PartNumber); + Set16(p + 0x2A, NumParts); + Set32(p + 0x2C, NumImages); + OffsetResource.WriteTo(p + 0x30); + XmlResource.WriteTo(p + 0x48); + MetadataResource.WriteTo(p + 0x60); + IntegrityResource.WriteTo(p + 0x7C); + Set32(p + 0x78, BootIndex); + memset(p + 0x94, 0, 60); +} + +void CStreamInfo::WriteTo(Byte *p) const +{ + Resource.WriteTo(p); + Set16(p + 0x18, PartNumber); + Set32(p + 0x1A, RefCount); + memcpy(p + 0x1E, Hash, kHashSize); +} + +class CInStreamWithSha1: + public ISequentialInStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + UInt64 _size; + NCrypto::NSha1::CContext _sha; +public: + MY_UNKNOWN_IMP1(IInStream) + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + + void SetStream(ISequentialInStream *stream) { _stream = stream; } + void Init() + { + _size = 0; + _sha.Init(); + } + void ReleaseStream() { _stream.Release(); } + UInt64 GetSize() const { return _size; } + void Final(Byte *digest) { _sha.Final(digest); } +}; + +STDMETHODIMP CInStreamWithSha1::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessedSize; + HRESULT result = _stream->Read(data, size, &realProcessedSize); + _size += realProcessedSize; + _sha.Update((const Byte *)data, realProcessedSize); + if (processedSize != NULL) + *processedSize = realProcessedSize; + return result; +} + +static void SetFileTimeToMem(Byte *p, const FILETIME &ft) +{ + Set32(p, ft.dwLowDateTime); + Set32(p + 4, ft.dwHighDateTime); +} + +static size_t WriteItem(const CUpdateItem &item, Byte *p, const Byte *hash) +{ + int fileNameLen = item.Name.Length() * 2; + int fileNameLen2 = (fileNameLen == 0 ? fileNameLen : fileNameLen + 2); + + size_t totalLen = ((kDirRecordSize + fileNameLen2 + 6) & ~7); + if (p) + { + memset(p, 0, totalLen); + Set64(p, totalLen); + Set64(p + 8, item.Attrib); + Set32(p + 0xC, (UInt32)(Int32)-1); // item.SecurityId + // Set64(p + 0x10, 0); // subdirOffset + SetFileTimeToMem(p + 0x28, item.CTime); + SetFileTimeToMem(p + 0x30, item.ATime); + SetFileTimeToMem(p + 0x38, item.MTime); + if (hash) + memcpy(p + 0x40, hash, kHashSize); + /* + else + memset(p + 0x40, 0, kHashSize); + */ + // Set16(p + 98, 0); // shortNameLen + Set16(p + 100, (UInt16)fileNameLen); + for (int i = 0; i * 2 < fileNameLen; i++) + Set16(p + kDirRecordSize + i * 2, item.Name[i]); + } + return totalLen; +} + +static void WriteTree(const CDir &tree, CRecordVector &digests, + CUpdateItem &defaultDirItem, + CObjectVector &updateItems, Byte *dest, size_t &pos) +{ + int i; + for (i = 0; i < tree.Files.Size(); i++) + { + const CUpdateItem &ui = updateItems[tree.Files[i]]; + pos += WriteItem(ui, dest ? dest + pos : NULL, + ui.HashIndex >= 0 ? digests[ui.HashIndex].Hash : NULL); + } + + size_t posStart = pos; + for (i = 0; i < tree.Dirs.Size(); i++) + { + const CDir &subfolder = tree.Dirs[i]; + CUpdateItem *item = &defaultDirItem; + if (subfolder.IsLeaf()) + item = &updateItems[subfolder.Index]; + else + defaultDirItem.Name = subfolder.Name; + pos += WriteItem(*item, NULL, NULL); + } + + if (dest) + Set64(dest + pos, 0); + + pos += 8; + + for (i = 0; i < tree.Dirs.Size(); i++) + { + const CDir &subfolder = tree.Dirs[i]; + if (dest) + { + CUpdateItem *item = &defaultDirItem; + if (subfolder.IsLeaf()) + item = &updateItems[subfolder.Index]; + else + defaultDirItem.Name = subfolder.Name; + size_t len = WriteItem(*item, dest + posStart, NULL); + Set64(dest + posStart + 0x10, pos); + posStart += len; + } + WriteTree(subfolder, digests, defaultDirItem, updateItems, dest, pos); + } +} + +static void AddTag(AString &s, const char *name, const AString &value) +{ + s += "<"; + s += name; + s += ">"; + s += value; + s += ""; +} + +static void AddTagUInt64(AString &s, const char *name, UInt64 value) +{ + char temp[32]; + ConvertUInt64ToString(value, temp); + AddTag(s, name, temp); +} + +static AString TimeToXml(FILETIME &ft) +{ + AString res; + char temp[16] = { '0', 'x' }; + ConvertUInt32ToHexWithZeros(ft.dwHighDateTime, temp + 2); + AddTag(res, "HIGHPART", temp); + ConvertUInt32ToHexWithZeros(ft.dwLowDateTime, temp + 2); + AddTag(res, "LOWPART", temp); + return res; +} + +void CHeader::SetDefaultFields(bool useLZX) +{ + Version = kWimVersion; + Flags = NHeaderFlags::kRpFix; + ChunkSize = 0; + if (useLZX) + { + Flags |= NHeaderFlags::kCompression | NHeaderFlags::kLZX; + ChunkSize = kChunkSize; + } + g_RandomGenerator.Generate(Guid, 16); + PartNumber = 1; + NumParts = 1; + NumImages = 1; + BootIndex = 0; + OffsetResource.Clear(); + XmlResource.Clear(); + MetadataResource.Clear(); + IntegrityResource.Clear(); +} + +static HRESULT UpdateArchive(ISequentialOutStream *seqOutStream, + CDir &rootFolder, + CObjectVector &updateItems, + IArchiveUpdateCallback *callback) +{ + CMyComPtr outStream; + RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream)); + if (!outStream) + return E_NOTIMPL; + + UInt64 complexity = 0; + + int i; + for (i = 0; i < updateItems.Size(); i++) + complexity += updateItems[i].Size; + + RINOK(callback->SetTotal(complexity)); + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; + CMyComPtr copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(callback, true); + + complexity = 0; + + bool useCompression = false; + + CHeader header; + header.SetDefaultFields(useCompression); + Byte buf[kHeaderSizeMax]; + header.WriteTo(buf); + RINOK(WriteStream(outStream, buf, kHeaderSizeMax)); + + CHashList hashes; + CObjectVector streams; + + UInt64 curPos = kHeaderSizeMax; + UInt64 unpackTotalSize = 0; + for (i = 0; i < updateItems.Size(); i++) + { + lps->InSize = lps->OutSize = complexity; + RINOK(lps->SetCur()); + + CUpdateItem &ui = updateItems[i]; + if (ui.IsDir || ui.Size == 0) + continue; + + CInStreamWithSha1 *inShaStreamSpec = new CInStreamWithSha1; + CMyComPtr inShaStream = inShaStreamSpec; + + { + CMyComPtr fileInStream; + HRESULT res = callback->GetStream(i, &fileInStream); + if (res != S_FALSE) + { + RINOK(res); + inShaStreamSpec->SetStream(fileInStream); + fileInStream.Release(); + inShaStreamSpec->Init(); + UInt64 offsetBlockSize = 0; + if (useCompression) + { + for (UInt64 t = kChunkSize; t < ui.Size; t += kChunkSize) + { + Byte buf[8]; + SetUi32(buf, (UInt32)t); + RINOK(WriteStream(outStream, buf, 4)); + offsetBlockSize += 4; + } + } + + RINOK(copyCoder->Code(inShaStream, outStream, NULL, NULL, progress)); + ui.Size = copyCoderSpec->TotalSize; + + CSha1Hash hash; + unpackTotalSize += ui.Size; + UInt64 packSize = offsetBlockSize + ui.Size; + inShaStreamSpec->Final(hash.Hash); + int index = hashes.AddUnique(hash); + if (index >= 0) + { + ui.HashIndex = index; + streams[index].RefCount++; + outStream->Seek(-(Int64)packSize, STREAM_SEEK_CUR, &curPos); + outStream->SetSize(curPos); + } + else + { + ui.HashIndex = hashes.Digests.Size() - 1; + CStreamInfo s; + s.Resource.PackSize = packSize; + s.Resource.Offset = curPos; + s.Resource.UnpackSize = ui.Size; + s.Resource.Flags = 0; + if (useCompression) + s.Resource.Flags = NResourceFlags::Compressed; + s.PartNumber = 1; + s.RefCount = 1; + memcpy(s.Hash, hash.Hash, kHashSize); + streams.Add(s); + curPos += packSize; + } + } + fileInStream.Release(); + complexity += ui.Size; + RINOK(callback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); + } + } + + + CUpdateItem ri; + FILETIME ft; + NTime::GetCurUtcFileTime(ft); + ri.MTime = ri.ATime = ri.CTime = ft; + ri.Attrib = FILE_ATTRIBUTE_DIRECTORY; + + const UInt32 kSecuritySize = 8; + size_t pos = kSecuritySize; + WriteTree(rootFolder, hashes.Digests, ri, updateItems, NULL, pos); + + CByteBuffer meta; + meta.SetCapacity(pos); + + // we can write 0 here only if there is no security data, imageX does it, + // but some programs expect size = 8 + Set32((Byte *)meta, 8); // size of security data + Set32((Byte *)meta + 4, 0); // num security entries + + pos = kSecuritySize; + WriteTree(rootFolder, hashes.Digests, ri, updateItems, (Byte *)meta, pos); + + { + NCrypto::NSha1::CContext sha; + sha.Init(); + sha.Update((const Byte *)meta, pos); + CSha1Hash digest; + sha.Final(digest.Hash); + + CStreamInfo s; + s.Resource.PackSize = pos; + s.Resource.Offset = curPos; + s.Resource.UnpackSize = pos; + s.Resource.Flags = NResourceFlags::kMetadata; + s.PartNumber = 1; + s.RefCount = 1; + memcpy(s.Hash, digest.Hash, kHashSize); + streams.Add(s); + RINOK(WriteStream(outStream, (const Byte *)meta, pos)); + meta.Free(); + curPos += pos; + } + + + header.OffsetResource.UnpackSize = header.OffsetResource.PackSize = (UInt64)streams.Size() * kStreamInfoSize; + header.OffsetResource.Offset = curPos; + header.OffsetResource.Flags = NResourceFlags::kMetadata; + + for (i = 0; i < streams.Size(); i++) + { + Byte buf[kStreamInfoSize]; + streams[i].WriteTo(buf); + RINOK(WriteStream(outStream, buf, kStreamInfoSize)); + curPos += kStreamInfoSize; + } + + AString xml = ""; + AddTagUInt64(xml, "TOTALBYTES", curPos); + xml += "1"; + AddTagUInt64(xml, "DIRCOUNT", rootFolder.GetNumDirs()); + AddTagUInt64(xml, "FILECOUNT", rootFolder.GetNumFiles()); + AddTagUInt64(xml, "TOTALBYTES", unpackTotalSize); + NTime::GetCurUtcFileTime(ft); + AddTag(xml, "CREATIONTIME", TimeToXml(ft)); + AddTag(xml, "LASTMODIFICATIONTIME", TimeToXml(ft)); + xml += ""; + + size_t xmlSize = (xml.Length() + 1) * 2; + meta.SetCapacity(xmlSize); + Set16((Byte *)meta, 0xFEFF); + for (i = 0; i < xml.Length(); i++) + Set16((Byte *)meta + 2 + i * 2, xml[i]); + RINOK(WriteStream(outStream, (const Byte *)meta, xmlSize)); + meta.Free(); + + header.XmlResource.UnpackSize = header.XmlResource.PackSize = xmlSize; + header.XmlResource.Offset = curPos; + header.XmlResource.Flags = NResourceFlags::kMetadata; + + outStream->Seek(0, STREAM_SEEK_SET, NULL); + header.WriteTo(buf); + return WriteStream(outStream, buf, kHeaderSizeMax); +} + +STDMETHODIMP COutHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, + IArchiveUpdateCallback *callback) +{ + COM_TRY_BEGIN + CObjectVector updateItems; + CDir tree; + tree.Dirs.Add(CDir()); + CDir &rootFolder = tree.Dirs.Back(); + + for (UInt32 i = 0; i < numItems; i++) + { + CUpdateItem ui; + Int32 newData, newProps; + UInt32 indexInArchive; + if (!callback) + return E_FAIL; + RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive)); + + { + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(i, kpidIsDir, &prop)); + if (prop.vt == VT_EMPTY) + ui.IsDir = false; + else if (prop.vt != VT_BOOL) + return E_INVALIDARG; + else + ui.IsDir = (prop.boolVal != VARIANT_FALSE); + } + + { + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(i, kpidAttrib, &prop)); + if (prop.vt == VT_EMPTY) + ui.Attrib = (ui.IsDir ? FILE_ATTRIBUTE_DIRECTORY : 0); + else if (prop.vt != VT_UI4) + return E_INVALIDARG; + else + ui.Attrib = prop.ulVal; + } + + RINOK(GetTime(callback, i, kpidCTime, ui.CTime)); + RINOK(GetTime(callback, i, kpidATime, ui.ATime)); + RINOK(GetTime(callback, i, kpidMTime, ui.MTime)); + + { + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(i, kpidSize, &prop)); + if (prop.vt != VT_UI8) + return E_INVALIDARG; + ui.Size = prop.uhVal.QuadPart; + } + + UString path; + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(i, kpidPath, &prop)); + if (prop.vt == VT_BSTR) + path = prop.bstrVal; + else if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + + CDir *curItem = &rootFolder; + int len = path.Length(); + UString fileName; + for (int j = 0; j < len; j++) + { + wchar_t c = path[j]; + if (c == WCHAR_PATH_SEPARATOR || c == L'/') + { + curItem = curItem->AddDir(updateItems, fileName, -1); + fileName.Empty(); + } + else + fileName += c; + } + + ui.Name = fileName; + updateItems.Add(ui); + if (ui.IsDir) + curItem->AddDir(updateItems, fileName, (int)i); + else + curItem->Files.Add(i); + } + return UpdateArchive(outStream, tree, updateItems, callback); + COM_TRY_END +} + +}} diff --git a/CPP/7zip/Archive/Wim/WimIn.cpp b/CPP/7zip/Archive/Wim/WimIn.cpp new file mode 100755 index 0000000..48d8321 --- /dev/null +++ b/CPP/7zip/Archive/Wim/WimIn.cpp @@ -0,0 +1,855 @@ +// Archive/WimIn.cpp + +#include "StdAfx.h" + +#include "../../../../C/CpuArch.h" + +#include "Common/IntToString.h" + +#include "../../Common/StreamUtils.h" +#include "../../Common/StreamObjects.h" +#include "../../Common/LimitedStreams.h" + +#include "../Common/OutStreamWithSha1.h" + +#include "WimIn.h" + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) +#define Get64(p) GetUi64(p) + +namespace NArchive { +namespace NWim { + +namespace NXpress { + +class CDecoderFlusher +{ + CDecoder *m_Decoder; +public: + bool NeedFlush; + CDecoderFlusher(CDecoder *decoder): m_Decoder(decoder), NeedFlush(true) {} + ~CDecoderFlusher() + { + if (NeedFlush) + m_Decoder->Flush(); + m_Decoder->ReleaseStreams(); + } +}; + +HRESULT CDecoder::CodeSpec(UInt32 outSize) +{ + { + Byte levels[kMainTableSize]; + for (unsigned i = 0; i < kMainTableSize; i += 2) + { + Byte b = m_InBitStream.DirectReadByte(); + levels[i] = b & 0xF; + levels[i + 1] = b >> 4; + } + if (!m_MainDecoder.SetCodeLengths(levels)) + return S_FALSE; + } + + while (outSize > 0) + { + UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream); + if (number < 256) + { + m_OutWindowStream.PutByte((Byte)number); + outSize--; + } + else + { + if (number >= kMainTableSize) + return S_FALSE; + UInt32 posLenSlot = number - 256; + UInt32 posSlot = posLenSlot / kNumLenSlots; + UInt32 len = posLenSlot % kNumLenSlots; + UInt32 distance = (1 << posSlot) - 1 + m_InBitStream.ReadBits(posSlot); + + if (len == kNumLenSlots - 1) + { + len = m_InBitStream.DirectReadByte(); + if (len == 0xFF) + { + len = m_InBitStream.DirectReadByte(); + len |= (UInt32)m_InBitStream.DirectReadByte() << 8; + } + else + len += kNumLenSlots - 1; + } + + len += kMatchMinLen; + UInt32 locLen = (len <= outSize ? len : outSize); + + if (!m_OutWindowStream.CopyBlock(distance, locLen)) + return S_FALSE; + + len -= locLen; + outSize -= locLen; + if (len != 0) + return S_FALSE; + } + } + return S_OK; +} + +const UInt32 kDictSize = (1 << kNumPosSlots); + +HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt32 outSize) +{ + if (!m_OutWindowStream.Create(kDictSize) || !m_InBitStream.Create(1 << 16)) + return E_OUTOFMEMORY; + + CDecoderFlusher flusher(this); + + m_InBitStream.SetStream(inStream); + m_OutWindowStream.SetStream(outStream); + m_InBitStream.Init(); + m_OutWindowStream.Init(false); + + RINOK(CodeSpec(outSize)); + + flusher.NeedFlush = false; + return Flush(); +} + +HRESULT CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt32 outSize) +{ + try { return CodeReal(inStream, outStream, outSize); } + catch(const CInBufferException &e) { return e.ErrorCode; } \ + catch(const CLzOutWindowException &e) { return e.ErrorCode; } + catch(...) { return S_FALSE; } +} + +} + +HRESULT CUnpacker::Unpack(IInStream *inStream, const CResource &resource, bool lzxMode, + ISequentialOutStream *outStream, ICompressProgressInfo *progress) +{ + RINOK(inStream->Seek(resource.Offset, STREAM_SEEK_SET, NULL)); + + CLimitedSequentialInStream *limitedStreamSpec = new CLimitedSequentialInStream(); + CMyComPtr limitedStream = limitedStreamSpec; + limitedStreamSpec->SetStream(inStream); + + if (!copyCoder) + { + copyCoderSpec = new NCompress::CCopyCoder; + copyCoder = copyCoderSpec; + } + if (!resource.IsCompressed()) + { + if (resource.PackSize != resource.UnpackSize) + return S_FALSE; + limitedStreamSpec->Init(resource.PackSize); + return copyCoder->Code(limitedStreamSpec, outStream, NULL, NULL, progress); + } + if (resource.UnpackSize == 0) + return S_OK; + UInt64 numChunks = (resource.UnpackSize + kChunkSize - 1) >> kChunkSizeBits; + unsigned entrySize = ((resource.UnpackSize > (UInt64)1 << 32) ? 8 : 4); + UInt64 sizesBufSize64 = entrySize * (numChunks - 1); + size_t sizesBufSize = (size_t)sizesBufSize64; + if (sizesBufSize != sizesBufSize64) + return E_OUTOFMEMORY; + if (sizesBufSize > sizesBuf.GetCapacity()) + { + sizesBuf.Free(); + sizesBuf.SetCapacity(sizesBufSize); + } + RINOK(ReadStream_FALSE(inStream, (Byte *)sizesBuf, sizesBufSize)); + const Byte *p = (const Byte *)sizesBuf; + + if (lzxMode && !lzxDecoder) + { + lzxDecoderSpec = new NCompress::NLzx::CDecoder(true); + lzxDecoder = lzxDecoderSpec; + RINOK(lzxDecoderSpec->SetParams(kChunkSizeBits)); + } + + UInt64 baseOffset = resource.Offset + sizesBufSize64; + UInt64 outProcessed = 0; + for (UInt32 i = 0; i < (UInt32)numChunks; i++) + { + UInt64 offset = 0; + if (i > 0) + { + offset = (entrySize == 4) ? Get32(p): Get64(p); + p += entrySize; + } + UInt64 nextOffset = resource.PackSize - sizesBufSize64; + if (i + 1 < (UInt32)numChunks) + nextOffset = (entrySize == 4) ? Get32(p): Get64(p); + if (nextOffset < offset) + return S_FALSE; + + RINOK(inStream->Seek(baseOffset + offset, STREAM_SEEK_SET, NULL)); + UInt64 inSize = nextOffset - offset; + limitedStreamSpec->Init(inSize); + + if (progress) + { + RINOK(progress->SetRatioInfo(&offset, &outProcessed)); + } + + UInt32 outSize = kChunkSize; + if (outProcessed + outSize > resource.UnpackSize) + outSize = (UInt32)(resource.UnpackSize - outProcessed); + UInt64 outSize64 = outSize; + if (inSize == outSize) + { + RINOK(copyCoder->Code(limitedStreamSpec, outStream, NULL, &outSize64, NULL)); + } + else + { + if (lzxMode) + { + lzxDecoderSpec->SetKeepHistory(false); + RINOK(lzxDecoder->Code(limitedStreamSpec, outStream, NULL, &outSize64, NULL)); + } + else + { + RINOK(xpressDecoder.Code(limitedStreamSpec, outStream, outSize)); + } + } + outProcessed += outSize; + } + return S_OK; +} + +HRESULT CUnpacker::Unpack(IInStream *inStream, const CResource &resource, bool lzxMode, + ISequentialOutStream *outStream, ICompressProgressInfo *progress, Byte *digest) +{ + COutStreamWithSha1 *shaStreamSpec = new COutStreamWithSha1(); + CMyComPtr shaStream = shaStreamSpec; + shaStreamSpec->SetStream(outStream); + shaStreamSpec->Init(digest != NULL); + HRESULT result = Unpack(inStream, resource, lzxMode, shaStream, progress); + if (digest) + shaStreamSpec->Final(digest); + return result; +} + +static HRESULT UnpackData(IInStream *inStream, const CResource &resource, bool lzxMode, CByteBuffer &buf, Byte *digest) +{ + size_t size = (size_t)resource.UnpackSize; + if (size != resource.UnpackSize) + return E_OUTOFMEMORY; + buf.Free(); + buf.SetCapacity(size); + + CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream(); + CMyComPtr outStream = outStreamSpec; + outStreamSpec->Init((Byte *)buf, size); + + CUnpacker unpacker; + return unpacker.Unpack(inStream, resource, lzxMode, outStream, NULL, digest); +} + +void CResource::Parse(const Byte *p) +{ + Flags = p[7]; + PackSize = Get64(p) & (((UInt64)1 << 56) - 1); + Offset = Get64(p + 8); + UnpackSize = Get64(p + 16); +} + +#define GetResource(p, res) res.Parse(p) + +static void GetStream(bool oldVersion, const Byte *p, CStreamInfo &s) +{ + s.Resource.Parse(p); + if (oldVersion) + { + s.PartNumber = 1; + s.Id = Get32(p + 24); + s.RefCount = Get32(p + 28); + memcpy(s.Hash, p + 32, kHashSize); + } + else + { + s.PartNumber = Get16(p + 24); + s.RefCount = Get32(p + 26); + memcpy(s.Hash, p + 30, kHashSize); + } +} + +static const wchar_t *kLongPath = L"[LongPath]"; + +UString CDatabase::GetItemPath(const int index1) const +{ + int size = 0; + int index = index1; + int newLevel; + for (newLevel = 0;; newLevel = 1) + { + const CItem &item = Items[index]; + index = item.Parent; + if (index >= 0 || !SkipRoot) + size += item.Name.Length() + newLevel; + if (index < 0) + break; + if ((UInt32)size >= ((UInt32)1 << 16)) + return kLongPath; + } + + wchar_t temp[16]; + int imageLen = 0; + if (ShowImageNumber) + { + ConvertUInt32ToString(-1 - index, temp); + imageLen = MyStringLen(temp); + size += imageLen + 1; + } + if ((UInt32)size >= ((UInt32)1 << 16)) + return kLongPath; + + UString path; + wchar_t *s = path.GetBuffer(size); + s[size] = 0; + if (ShowImageNumber) + { + memcpy(s, temp, imageLen * sizeof(wchar_t)); + s[imageLen] = WCHAR_PATH_SEPARATOR; + } + + index = index1; + + for (newLevel = 0;; newLevel = 1) + { + const CItem &item = Items[index]; + index = item.Parent; + if (index >= 0 || !SkipRoot) + { + if (newLevel) + s[--size] = WCHAR_PATH_SEPARATOR; + size -= item.Name.Length(); + memcpy(s + size, item.Name, sizeof(wchar_t) * item.Name.Length()); + } + if (index < 0) + { + path.ReleaseBuffer(); + return path; + } + } +} + +static void GetFileTimeFromMem(const Byte *p, FILETIME *ft) +{ + ft->dwLowDateTime = Get32(p); + ft->dwHighDateTime = Get32(p + 4); +} + +static HRESULT ReadName(const Byte *p, int size, UString &dest) +{ + if (size == 0) + return S_OK; + if (Get16(p + size) != 0) + return S_FALSE; + wchar_t *s = dest.GetBuffer(size / 2); + for (int i = 0; i <= size; i += 2) + *s++ = Get16(p + i); + dest.ReleaseBuffer(); + return S_OK; +} + +HRESULT CDatabase::ParseDirItem(size_t pos, int parent) +{ + if ((pos & 7) != 0) + return S_FALSE; + + int prevIndex = -1; + for (int numItems = 0;; numItems++) + { + if (OpenCallback) + { + UInt64 numFiles = Items.Size(); + if ((numFiles & 0x3FF) == 0) + { + RINOK(OpenCallback->SetCompleted(&numFiles, NULL)); + } + } + size_t rem = DirSize - pos; + if (pos < DirStartOffset || pos > DirSize || rem < 8) + return S_FALSE; + const Byte *p = DirData + pos; + UInt64 len = Get64(p); + if (len == 0) + { + if (parent < 0 && numItems != 1) + SkipRoot = false; + DirProcessed += 8; + return S_OK; + } + if ((len & 7) != 0 || rem < len) + return S_FALSE; + if (!IsOldVersion) + if (len < 0x28) + return S_FALSE; + DirProcessed += (size_t)len; + if (DirProcessed > DirSize) + return S_FALSE; + int extraOffset = 0; + if (IsOldVersion) + { + if (len < 0x40 || (/* Get32(p + 12) == 0 && */ Get32(p + 0x14) != 0)) + { + extraOffset = 0x10; + } + } + else if (Get64(p + 8) == 0) + extraOffset = 0x24; + if (extraOffset) + { + if (prevIndex == -1) + return S_FALSE; + UInt32 fileNameLen = Get16(p + extraOffset); + if ((fileNameLen & 1) != 0) + return S_FALSE; + /* Probably different versions of ImageX can use different number of + additional ZEROs. So we don't use exact check. */ + UInt32 fileNameLen2 = (fileNameLen == 0 ? fileNameLen : fileNameLen + 2); + if (((extraOffset + 2 + fileNameLen2 + 6) & ~7) > len) + return S_FALSE; + + UString name; + RINOK(ReadName(p + extraOffset + 2, fileNameLen, name)); + + CItem &prevItem = Items[prevIndex]; + if (name.IsEmpty() && !prevItem.HasStream()) + { + if (IsOldVersion) + prevItem.Id = Get32(p + 8); + else + memcpy(prevItem.Hash, p + 0x10, kHashSize); + } + else + { + CItem item; + item.Name = prevItem.Name + L':' + name; + item.CTime = prevItem.CTime; + item.ATime = prevItem.ATime; + item.MTime = prevItem.MTime; + if (IsOldVersion) + { + item.Id = Get32(p + 8); + memset(item.Hash, 0, kHashSize); + } + else + memcpy(item.Hash, p + 0x10, kHashSize); + item.Attrib = 0; + item.Order = Order++; + item.Parent = parent; + Items.Add(item); + } + pos += (size_t)len; + continue; + } + + UInt32 dirRecordSize = IsOldVersion ? kDirRecordSizeOld : kDirRecordSize; + if (len < dirRecordSize) + return S_FALSE; + + CItem item; + item.Attrib = Get32(p + 8); + // item.SecurityId = Get32(p + 0xC); + UInt64 subdirOffset = Get64(p + 0x10); + UInt32 timeOffset = IsOldVersion ? 0x18: 0x28; + GetFileTimeFromMem(p + timeOffset, &item.CTime); + GetFileTimeFromMem(p + timeOffset + 8, &item.ATime); + GetFileTimeFromMem(p + timeOffset + 16, &item.MTime); + if (IsOldVersion) + { + item.Id = Get32(p + 0x10); + memset(item.Hash, 0, kHashSize); + } + else + { + memcpy(item.Hash, p + 0x40, kHashSize); + } + // UInt32 numStreams = Get16(p + dirRecordSize - 6); + UInt32 shortNameLen = Get16(p + dirRecordSize - 4); + UInt32 fileNameLen = Get16(p + dirRecordSize - 2); + + if ((shortNameLen & 1) != 0 || (fileNameLen & 1) != 0) + return S_FALSE; + + UInt32 shortNameLen2 = (shortNameLen == 0 ? shortNameLen : shortNameLen + 2); + UInt32 fileNameLen2 = (fileNameLen == 0 ? fileNameLen : fileNameLen + 2); + + if (((dirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7) > len) + return S_FALSE; + p += dirRecordSize; + + RINOK(ReadName(p, fileNameLen, item.Name)); + RINOK(ReadName(p + fileNameLen2, shortNameLen, item.ShortName)); + + if (parent < 0 && (shortNameLen || fileNameLen || !item.IsDir())) + SkipRoot = false; + + /* + // there are some extra data for some files. + p -= dirRecordSize; + p += ((dirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7); + if (((dirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7) != len) + p = p; + */ + + /* + if (parent >= 0) + { + UString s = GetItemPath(parent) + L"\\" + item.Name; + printf("\n%s %8x %S", item.IsDir() ? "D" : " ", (int)subdirOffset, (const wchar_t *)s); + } + */ + + if (fileNameLen == 0 && item.IsDir() && !item.HasStream()) + item.Attrib = 0x10; // some swm archives have system/hidden attributes for root + + item.Parent = parent; + prevIndex = Items.Add(item); + if (item.IsDir() && subdirOffset != 0) + { + RINOK(ParseDirItem((size_t)subdirOffset, prevIndex)); + } + Items[prevIndex].Order = Order++; + pos += (size_t)len; + } +} + +HRESULT CDatabase::ParseImageDirs(const CByteBuffer &buf, int parent) +{ + DirData = buf; + DirSize = buf.GetCapacity(); + + size_t pos = 0; + if (DirSize < 8) + return S_FALSE; + const Byte *p = DirData; + UInt32 totalLength = Get32(p); + if (IsOldVersion) + { + for (pos = 4;; pos += 8) + { + if (pos + 4 > DirSize) + return S_FALSE; + UInt32 n = Get32(p + pos); + if (n == 0) + break; + if (pos + 8 > DirSize) + return S_FALSE; + totalLength += Get32(p + pos + 4); + if (totalLength > DirSize) + return S_FALSE; + } + pos += totalLength + 4; + pos = (pos + 7) & ~(size_t)7; + if (pos > DirSize) + return S_FALSE; + } + else + { + + // UInt32 numEntries = Get32(p + 4); + pos += 8; + { + /* + CRecordVector entryLens; + UInt64 sum = 0; + for (UInt32 i = 0; i < numEntries; i++) + { + if (pos + 8 > DirSize) + return S_FALSE; + UInt64 len = Get64(p + pos); + entryLens.Add(len); + sum += len; + pos += 8; + } + pos += (size_t)sum; // skip security descriptors + while ((pos & 7) != 0) + pos++; + if (pos != totalLength) + return S_FALSE; + */ + if (totalLength == 0) + pos = 8; + else if (totalLength < 8) + return S_FALSE; + else + pos = totalLength; + } + } + DirStartOffset = DirProcessed = pos; + RINOK(ParseDirItem(pos, parent)); + if (DirProcessed == DirSize) + return S_OK; + /* Original program writes additional 8 bytes (END_OF_ROOT_FOLDER), but + reference to that folder is empty */ + if (DirProcessed == DirSize - 8 && DirProcessed - DirStartOffset == 112 && + Get64(p + DirSize - 8) == 0) + return S_OK; + return S_FALSE; +} + +HRESULT CHeader::Parse(const Byte *p) +{ + UInt32 headerSize = Get32(p + 8); + Version = Get32(p + 0x0C); + Flags = Get32(p + 0x10); + if (!IsSupported()) + return S_FALSE; + ChunkSize = Get32(p + 0x14); + if (ChunkSize != kChunkSize && ChunkSize != 0) + return S_FALSE; + int offset; + if (IsOldVersion()) + { + if (headerSize != 0x60) + return S_FALSE; + memset(Guid, 0, 16); + offset = 0x18; + PartNumber = 1; + NumParts = 1; + } + else + { + if (headerSize < 0x74) + return S_FALSE; + memcpy(Guid, p + 0x18, 16); + PartNumber = Get16(p + 0x28); + NumParts = Get16(p + 0x2A); + offset = 0x2C; + if (IsNewVersion()) + { + NumImages = Get32(p + offset); + offset += 4; + } + } + GetResource(p + offset, OffsetResource); + GetResource(p + offset + 0x18, XmlResource); + GetResource(p + offset + 0x30, MetadataResource); + if (IsNewVersion()) + { + if (headerSize < 0xD0) + return S_FALSE; + BootIndex = Get32(p + 0x48); + IntegrityResource.Parse(p + offset + 0x4C); + } + return S_OK; +} + +const Byte kSignature[kSignatureSize] = { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 }; + +HRESULT ReadHeader(IInStream *inStream, CHeader &h) +{ + Byte p[kHeaderSizeMax]; + RINOK(ReadStream_FALSE(inStream, p, kHeaderSizeMax)); + if (memcmp(p, kSignature, kSignatureSize) != 0) + return S_FALSE; + return h.Parse(p); +} + +static HRESULT ReadStreams(bool oldVersion, IInStream *inStream, const CHeader &h, CDatabase &db) +{ + CByteBuffer offsetBuf; + RINOK(UnpackData(inStream, h.OffsetResource, h.IsLzxMode(), offsetBuf, NULL)); + size_t i; + size_t streamInfoSize = oldVersion ? kStreamInfoSize + 2 : kStreamInfoSize; + for (i = 0; offsetBuf.GetCapacity() - i >= streamInfoSize; i += streamInfoSize) + { + CStreamInfo s; + GetStream(oldVersion, (const Byte *)offsetBuf + i, s); + if (s.PartNumber == h.PartNumber) + db.Streams.Add(s); + } + return (i == offsetBuf.GetCapacity()) ? S_OK : S_FALSE; +} + +static bool IsEmptySha(const Byte *data) +{ + for (int i = 0; i < kHashSize; i++) + if (data[i] != 0) + return false; + return true; +} + +HRESULT CDatabase::Open(IInStream *inStream, const CHeader &h, CByteBuffer &xml, IArchiveOpenCallback *openCallback) +{ + OpenCallback = openCallback; + IsOldVersion = h.IsOldVersion(); + RINOK(UnpackData(inStream, h.XmlResource, h.IsLzxMode(), xml, NULL)); + RINOK(ReadStreams(h.IsOldVersion(), inStream, h, *this)); + bool needBootMetadata = !h.MetadataResource.IsEmpty(); + Order = 0; + if (h.PartNumber == 1) + { + int imageIndex = 1; + for (int i = 0; i < Streams.Size(); i++) + { + // if (imageIndex > 1) break; + const CStreamInfo &si = Streams[i]; + if (!si.Resource.IsMetadata() || si.PartNumber != h.PartNumber) + continue; + Byte hash[kHashSize]; + CByteBuffer metadata; + RINOK(UnpackData(inStream, si.Resource, h.IsLzxMode(), metadata, hash)); + if (memcmp(hash, si.Hash, kHashSize) != 0 && + !(h.IsOldVersion() && IsEmptySha(si.Hash))) + return S_FALSE; + NumImages++; + RINOK(ParseImageDirs(metadata, -(int)(++imageIndex))); + if (needBootMetadata) + if (h.MetadataResource.Offset == si.Resource.Offset) + needBootMetadata = false; + } + } + + if (needBootMetadata) + { + CByteBuffer metadata; + RINOK(UnpackData(inStream, h.MetadataResource, h.IsLzxMode(), metadata, NULL)); + RINOK(ParseImageDirs(metadata, -1)); + NumImages++; + } + return S_OK; +} + + +static int CompareStreamsByPos(const CStreamInfo *p1, const CStreamInfo *p2, void * /* param */) +{ + int res = MyCompare(p1->PartNumber, p2->PartNumber); + if (res != 0) + return res; + return MyCompare(p1->Resource.Offset, p2->Resource.Offset); +} + +static int CompareIDs(const int *p1, const int *p2, void *param) +{ + const CRecordVector &streams = *(const CRecordVector *)param; + return MyCompare(streams[*p1].Id, streams[*p2].Id); +} + +static int CompareHashRefs(const int *p1, const int *p2, void *param) +{ + const CRecordVector &streams = *(const CRecordVector *)param; + return memcmp(streams[*p1].Hash, streams[*p2].Hash, kHashSize); +} + +static int FindId(const CRecordVector &streams, + const CIntVector &sortedByHash, UInt32 id) +{ + int left = 0, right = streams.Size(); + while (left != right) + { + int mid = (left + right) / 2; + int streamIndex = sortedByHash[mid]; + UInt32 id2 = streams[streamIndex].Id; + if (id == id2) + return streamIndex; + if (id < id2) + right = mid; + else + left = mid + 1; + } + return -1; +} + +static int FindHash(const CRecordVector &streams, + const CIntVector &sortedByHash, const Byte *hash) +{ + int left = 0, right = streams.Size(); + while (left != right) + { + int mid = (left + right) / 2; + int streamIndex = sortedByHash[mid]; + UInt32 i; + const Byte *hash2 = streams[streamIndex].Hash; + for (i = 0; i < kHashSize; i++) + if (hash[i] != hash2[i]) + break; + if (i == kHashSize) + return streamIndex; + if (hash[i] < hash2[i]) + right = mid; + else + left = mid + 1; + } + return -1; +} + +static int CompareItems(const int *a1, const int *a2, void *param) +{ + const CObjectVector &items = ((CDatabase *)param)->Items; + const CItem &i1 = items[*a1]; + const CItem &i2 = items[*a2]; + + if (i1.IsDir() != i2.IsDir()) + return i1.IsDir() ? 1 : -1; + int res = MyCompare(i1.StreamIndex, i2.StreamIndex); + if (res != 0) + return res; + return MyCompare(i1.Order, i2.Order); +} + +HRESULT CDatabase::Sort(bool skipRootDir) +{ + Streams.Sort(CompareStreamsByPos, NULL); + + { + CIntVector sortedByHash; + { + for (int i = 0; i < Streams.Size(); i++) + sortedByHash.Add(i); + if (IsOldVersion) + sortedByHash.Sort(CompareIDs, &Streams); + else + sortedByHash.Sort(CompareHashRefs, &Streams); + } + + for (int i = 0; i < Items.Size(); i++) + { + CItem &item = Items[i]; + item.StreamIndex = -1; + if (item.HasStream()) + if (IsOldVersion) + item.StreamIndex = FindId(Streams, sortedByHash, item.Id); + else + item.StreamIndex = FindHash(Streams, sortedByHash, item.Hash); + } + } + + { + CRecordVector used; + int i; + for (i = 0; i < Streams.Size(); i++) + { + const CStreamInfo &s = Streams[i]; + used.Add(s.Resource.IsMetadata() && s.PartNumber == 1); + // used.Add(false); + } + for (i = 0; i < Items.Size(); i++) + { + CItem &item = Items[i]; + if (item.StreamIndex >= 0) + used[item.StreamIndex] = true; + } + for (i = 0; i < Streams.Size(); i++) + if (!used[i]) + { + CItem item; + item.StreamIndex = i; + item.HasMetadata = false; + Items.Add(item); + } + } + + SortedItems.Reserve(Items.Size()); + for (int i = (skipRootDir ? 1 : 0); i < Items.Size(); i++) + SortedItems.Add(i); + SortedItems.Sort(CompareItems, this); + return S_OK; +} + +}} diff --git a/CPP/7zip/Archive/Wim/WimIn.h b/CPP/7zip/Archive/Wim/WimIn.h new file mode 100755 index 0000000..0d9be3e --- /dev/null +++ b/CPP/7zip/Archive/Wim/WimIn.h @@ -0,0 +1,297 @@ +// Archive/WimIn.h + +#ifndef __ARCHIVE_WIM_IN_H +#define __ARCHIVE_WIM_IN_H + +#include "Common/Buffer.h" +#include "Common/MyString.h" + +#include "../../Compress/CopyCoder.h" +#include "../../Compress/LzxDecoder.h" + +#include "../IArchive.h" + +namespace NArchive { +namespace NWim { + +namespace NXpress { + +class CBitStream +{ + CInBuffer m_Stream; + UInt32 m_Value; + unsigned m_BitPos; +public: + bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); } + void SetStream(ISequentialInStream *s) { m_Stream.SetStream(s); } + void ReleaseStream() { m_Stream.ReleaseStream(); } + + void Init() { m_Stream.Init(); m_BitPos = 0; } + // UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() - m_BitPos / 8; } + Byte DirectReadByte() { return m_Stream.ReadByte(); } + + void Normalize() + { + if (m_BitPos < 16) + { + Byte b0 = m_Stream.ReadByte(); + Byte b1 = m_Stream.ReadByte(); + m_Value = (m_Value << 8) | b1; + m_Value = (m_Value << 8) | b0; + m_BitPos += 16; + } + } + + UInt32 GetValue(unsigned numBits) + { + Normalize(); + return (m_Value >> (m_BitPos - numBits)) & ((1 << numBits) - 1); + } + + void MovePos(unsigned numBits) { m_BitPos -= numBits; } + + UInt32 ReadBits(unsigned numBits) + { + UInt32 res = GetValue(numBits); + m_BitPos -= numBits; + return res; + } +}; + +const unsigned kNumHuffmanBits = 16; +const UInt32 kMatchMinLen = 3; +const UInt32 kNumLenSlots = 16; +const UInt32 kNumPosSlots = 16; +const UInt32 kNumPosLenSlots = kNumPosSlots * kNumLenSlots; +const UInt32 kMainTableSize = 256 + kNumPosLenSlots; + +class CDecoder +{ + CBitStream m_InBitStream; + CLzOutWindow m_OutWindowStream; + NCompress::NHuffman::CDecoder m_MainDecoder; + + HRESULT CodeSpec(UInt32 size); + HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt32 outSize); +public: + void ReleaseStreams() + { + m_OutWindowStream.ReleaseStream(); + m_InBitStream.ReleaseStream(); + } + HRESULT Flush() { return m_OutWindowStream.Flush(); } + HRESULT Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt32 outSize); +}; + +} + +namespace NResourceFlags +{ + const Byte kFree = 1; + const Byte kMetadata = 2; + const Byte Compressed = 4; + const Byte Spanned = 4; +} + +struct CResource +{ + UInt64 PackSize; + UInt64 Offset; + UInt64 UnpackSize; + Byte Flags; + + void Clear() + { + PackSize = 0; + Offset = 0; + UnpackSize = 0; + Flags = 0; + } + void Parse(const Byte *p); + void WriteTo(Byte *p) const; + bool IsFree() const { return (Flags & NResourceFlags::kFree) != 0; } + bool IsMetadata() const { return (Flags & NResourceFlags::kMetadata) != 0; } + bool IsCompressed() const { return (Flags & NResourceFlags::Compressed) != 0; } + bool IsEmpty() const { return (UnpackSize == 0); } +}; + +namespace NHeaderFlags +{ + const UInt32 kCompression = 2; + const UInt32 kSpanned = 8; + const UInt32 kRpFix = 0x80; + const UInt32 kXPRESS = 0x20000; + const UInt32 kLZX = 0x40000; +} + +const UInt32 kWimVersion = 0x010D00; +const UInt32 kHeaderSizeMax = 0xD0; +const UInt32 kSignatureSize = 8; +extern const Byte kSignature[kSignatureSize]; +const unsigned kChunkSizeBits = 15; +const UInt32 kChunkSize = (1 << kChunkSizeBits); + +struct CHeader +{ + UInt32 Version; + UInt32 Flags; + UInt32 ChunkSize; + Byte Guid[16]; + UInt16 PartNumber; + UInt16 NumParts; + UInt32 NumImages; + + CResource OffsetResource; + CResource XmlResource; + CResource MetadataResource; + CResource IntegrityResource; + UInt32 BootIndex; + + void SetDefaultFields(bool useLZX); + + void WriteTo(Byte *p) const; + HRESULT Parse(const Byte *p); + bool IsCompressed() const { return (Flags & NHeaderFlags::kCompression) != 0; } + bool IsSupported() const { return (!IsCompressed() || (Flags & NHeaderFlags::kLZX) != 0 || (Flags & NHeaderFlags::kXPRESS) != 0 ) ; } + bool IsLzxMode() const { return (Flags & NHeaderFlags::kLZX) != 0; } + bool IsSpanned() const { return (!IsCompressed() || (Flags & NHeaderFlags::kSpanned) != 0); } + bool IsOldVersion() const { return (Version <= 0x010A00); } + bool IsNewVersion() const { return (Version > 0x010C00); } + + bool AreFromOnArchive(const CHeader &h) + { + return (memcmp(Guid, h.Guid, sizeof(Guid)) == 0) && (h.NumParts == NumParts); + } +}; + +const UInt32 kHashSize = 20; +const UInt32 kStreamInfoSize = 24 + 2 + 4 + kHashSize; + +struct CStreamInfo +{ + CResource Resource; + UInt16 PartNumber; + UInt32 RefCount; + UInt32 Id; + BYTE Hash[kHashSize]; + + void WriteTo(Byte *p) const; +}; + +const UInt32 kDirRecordSizeOld = 62; +const UInt32 kDirRecordSize = 102; + +struct CItem +{ + UString Name; + UString ShortName; + UInt32 Attrib; + // UInt32 SecurityId; + BYTE Hash[kHashSize]; + UInt32 Id; + FILETIME CTime; + FILETIME ATime; + FILETIME MTime; + // UInt32 ReparseTag; + // UInt64 HardLink; + // UInt16 NumStreams; + int StreamIndex; + int Parent; + unsigned Order; + bool HasMetadata; + CItem(): HasMetadata(true), StreamIndex(-1), Id(0) {} + bool IsDir() const { return HasMetadata && ((Attrib & 0x10) != 0); } + bool HasStream() const + { + for (unsigned i = 0; i < kHashSize; i++) + if (Hash[i] != 0) + return true; + return Id != 0; + } +}; + +class CDatabase +{ + const Byte *DirData; + size_t DirSize; + size_t DirProcessed; + size_t DirStartOffset; + int Order; + IArchiveOpenCallback *OpenCallback; + + HRESULT ParseDirItem(size_t pos, int parent); + HRESULT ParseImageDirs(const CByteBuffer &buf, int parent); + +public: + CRecordVector Streams; + CObjectVector Items; + CIntVector SortedItems; + int NumImages; + bool SkipRoot; + bool ShowImageNumber; + + bool IsOldVersion; + + UInt64 GetUnpackSize() const + { + UInt64 res = 0; + for (int i = 0; i < Streams.Size(); i++) + res += Streams[i].Resource.UnpackSize; + return res; + } + + UInt64 GetPackSize() const + { + UInt64 res = 0; + for (int i = 0; i < Streams.Size(); i++) + res += Streams[i].Resource.PackSize; + return res; + } + + void Clear() + { + Streams.Clear(); + Items.Clear(); + SortedItems.Clear(); + NumImages = 0; + + SkipRoot = true; + ShowImageNumber = true; + IsOldVersion = false; + } + + UString GetItemPath(int index) const; + + HRESULT Open(IInStream *inStream, const CHeader &h, CByteBuffer &xml, IArchiveOpenCallback *openCallback); + + void DetectPathMode() + { + ShowImageNumber = (NumImages != 1); + } + + HRESULT Sort(bool skipRootDir); +}; + +HRESULT ReadHeader(IInStream *inStream, CHeader &header); + +class CUnpacker +{ + NCompress::CCopyCoder *copyCoderSpec; + CMyComPtr copyCoder; + + NCompress::NLzx::CDecoder *lzxDecoderSpec; + CMyComPtr lzxDecoder; + + NXpress::CDecoder xpressDecoder; + + CByteBuffer sizesBuf; + HRESULT Unpack(IInStream *inStream, const CResource &res, bool lzxMode, + ISequentialOutStream *outStream, ICompressProgressInfo *progress); +public: + HRESULT Unpack(IInStream *inStream, const CResource &res, bool lzxMode, + ISequentialOutStream *outStream, ICompressProgressInfo *progress, Byte *digest); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Wim/WimRegister.cpp b/CPP/7zip/Archive/Wim/WimRegister.cpp new file mode 100755 index 0000000..e91ac53 --- /dev/null +++ b/CPP/7zip/Archive/Wim/WimRegister.cpp @@ -0,0 +1,18 @@ +// WimRegister.cpp + +#include "StdAfx.h" + +#include "../../Common/RegisterArc.h" + +#include "WimHandler.h" +static IInArchive *CreateArc() { return new NArchive::NWim::CHandler; } +#ifndef EXTRACT_ONLY +static IOutArchive *CreateArcOut() { return new NArchive::NWim::COutHandler; } +#else +#define CreateArcOut 0 +#endif + +static CArcInfo g_ArcInfo = + { L"wim", L"wim swm", 0, 0xE6, { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 }, 8, false, CreateArc, CreateArcOut }; + +REGISTER_ARC(Wim) diff --git a/CPP/7zip/Archive/XarHandler.cpp b/CPP/7zip/Archive/XarHandler.cpp new file mode 100755 index 0000000..b2d67d8 --- /dev/null +++ b/CPP/7zip/Archive/XarHandler.cpp @@ -0,0 +1,588 @@ +// XarHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Common/ComTry.h" +#include "Common/MyXml.h" +#include "Common/StringToInt.h" +#include "Common/UTFConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../Common/LimitedStreams.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamObjects.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/BZip2Decoder.h" +#include "../Compress/CopyCoder.h" +#include "../Compress/ZlibDecoder.h" + +#include "Common/OutStreamWithSha1.h" + +#define XAR_SHOW_RAW + +#define Get16(p) GetBe16(p) +#define Get32(p) GetBe32(p) +#define Get64(p) GetBe64(p) + +namespace NArchive { +namespace NXar { + +struct CFile +{ + AString Name; + AString Method; + UInt64 Size; + UInt64 PackSize; + UInt64 Offset; + + // UInt32 mode; + UInt64 CTime; + UInt64 MTime; + UInt64 ATime; + + bool IsDir; + bool HasData; + + bool Sha1IsDefined; + Byte Sha1[20]; + // bool packSha1IsDefined; + // Byte packSha1[20]; + + int Parent; + + CFile(): IsDir(false), HasData(false), Sha1IsDefined(false), + /* packSha1IsDefined(false), */ + Parent(-1), Size(0), PackSize(0), CTime(0), MTime(0), ATime(0) {} +}; + +class CHandler: + public IInArchive, + public CMyUnknownImp +{ + UInt64 _dataStartPos; + CMyComPtr _inStream; + AString _xml; + CObjectVector _files; + + HRESULT Open2(IInStream *stream); + HRESULT Extract(IInStream *stream); +public: + MY_UNKNOWN_IMP1(IInArchive) + INTERFACE_IInArchive(;) +}; + +const UInt32 kXmlSizeMax = ((UInt32)1 << 30) - (1 << 14); + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidATime, VT_FILETIME}, + { NULL, kpidMethod, VT_BSTR} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO + +static bool ParseNumber(const char *s, int size, UInt32 &res) +{ + const char *end; + res = (UInt32)ConvertStringToUInt64(s, &end); + return (end - s == size); +} + +static bool ParseUInt64(const CXmlItem &item, const char *name, UInt64 &res) +{ + AString s = item.GetSubStringForTag(name); + const char *end; + res = ConvertStringToUInt64(s, &end); + return (end - (const char *)s == s.Length()); +} + +static UInt64 ParseTime(const CXmlItem &item, const char *name) +{ + AString s = item.GetSubStringForTag(name); + if (s.Length() < 20) + return 0; + const char *p = s; + if (p[ 4] != '-' || p[ 7] != '-' || p[10] != 'T' || + p[13] != ':' || p[16] != ':' || p[19] != 'Z') + return 0; + UInt32 year, month, day, hour, min, sec; + if (!ParseNumber(p, 4, year )) return 0; + if (!ParseNumber(p + 5, 2, month)) return 0; + if (!ParseNumber(p + 8, 2, day )) return 0; + if (!ParseNumber(p + 11, 2, hour )) return 0; + if (!ParseNumber(p + 14, 2, min )) return 0; + if (!ParseNumber(p + 17, 2, sec )) return 0; + + UInt64 numSecs; + if (!NWindows::NTime::GetSecondsSince1601(year, month, day, hour, min, sec, numSecs)) + return 0; + return numSecs * 10000000; +} + +static bool HexToByte(char c, Byte &res) +{ + if (c >= '0' && c <= '9') res = c - '0'; + else if (c >= 'A' && c <= 'F') res = c - 'A' + 10; + else if (c >= 'a' && c <= 'f') res = c - 'a' + 10; + else return false; + return true; +} + +#define METHOD_NAME_ZLIB "zlib" + +static bool ParseSha1(const CXmlItem &item, const char *name, Byte *digest) +{ + int index = item.FindSubTag(name); + if (index < 0) + return false; + const CXmlItem &checkItem = item.SubItems[index]; + AString style = checkItem.GetPropertyValue("style"); + if (style == "SHA1") + { + AString s = checkItem.GetSubString(); + if (s.Length() != 40) + return false; + for (int i = 0; i < s.Length(); i += 2) + { + Byte b0, b1; + if (!HexToByte(s[i], b0) || !HexToByte(s[i + 1], b1)) + return false; + digest[i / 2] = (b0 << 4) | b1; + } + return true; + } + return false; +} + +static bool AddItem(const CXmlItem &item, CObjectVector &files, int parent) +{ + if (!item.IsTag) + return true; + if (item.Name == "file") + { + CFile file; + file.Parent = parent; + parent = files.Size(); + file.Name = item.GetSubStringForTag("name"); + AString type = item.GetSubStringForTag("type"); + if (type == "directory") + file.IsDir = true; + else if (type == "file") + file.IsDir = false; + else + return false; + + int dataIndex = item.FindSubTag("data"); + if (dataIndex >= 0 && !file.IsDir) + { + file.HasData = true; + const CXmlItem &dataItem = item.SubItems[dataIndex]; + if (!ParseUInt64(dataItem, "size", file.Size)) + return false; + if (!ParseUInt64(dataItem, "length", file.PackSize)) + return false; + if (!ParseUInt64(dataItem, "offset", file.Offset)) + return false; + file.Sha1IsDefined = ParseSha1(dataItem, "extracted-checksum", file.Sha1); + // file.packSha1IsDefined = ParseSha1(dataItem, "archived-checksum", file.packSha1); + int encodingIndex = dataItem.FindSubTag("encoding"); + if (encodingIndex >= 0) + { + const CXmlItem &encodingItem = dataItem.SubItems[encodingIndex]; + if (encodingItem.IsTag) + { + AString s = encodingItem.GetPropertyValue("style"); + if (s.Length() >= 0) + { + AString appl = "application/"; + if (s.Left(appl.Length()) == appl) + { + s = s.Mid(appl.Length()); + AString xx = "x-"; + if (s.Left(xx.Length()) == xx) + { + s = s.Mid(xx.Length()); + if (s == "gzip") + s = METHOD_NAME_ZLIB; + } + } + file.Method = s; + } + } + } + } + + file.CTime = ParseTime(item, "ctime"); + file.MTime = ParseTime(item, "mtime"); + file.ATime = ParseTime(item, "atime"); + files.Add(file); + } + for (int i = 0; i < item.SubItems.Size(); i++) + if (!AddItem(item.SubItems[i], files, parent)) + return false; + return true; +} + +HRESULT CHandler::Open2(IInStream *stream) +{ + UInt64 archiveStartPos; + RINOK(stream->Seek(0, STREAM_SEEK_SET, &archiveStartPos)); + + const UInt32 kHeaderSize = 0x1C; + Byte buf[kHeaderSize]; + RINOK(ReadStream_FALSE(stream, buf, kHeaderSize)); + + UInt32 size = Get16(buf + 4); + // UInt32 ver = Get16(buf + 6); // == 0 + if (Get32(buf) != 0x78617221 || size != kHeaderSize) + return S_FALSE; + + UInt64 packSize = Get64(buf + 8); + UInt64 unpackSize = Get64(buf + 0x10); + // UInt32 checkSumAlogo = Get32(buf + 0x18); + + if (unpackSize >= kXmlSizeMax) + return S_FALSE; + + _dataStartPos = archiveStartPos + kHeaderSize + packSize; + + char *ss = _xml.GetBuffer((int)unpackSize + 1); + + NCompress::NZlib::CDecoder *zlibCoderSpec = new NCompress::NZlib::CDecoder(); + CMyComPtr zlibCoder = zlibCoderSpec; + + CLimitedSequentialInStream *inStreamLimSpec = new CLimitedSequentialInStream; + CMyComPtr inStreamLim(inStreamLimSpec); + inStreamLimSpec->SetStream(stream); + inStreamLimSpec->Init(packSize); + + CBufPtrSeqOutStream *outStreamLimSpec = new CBufPtrSeqOutStream; + CMyComPtr outStreamLim(outStreamLimSpec); + outStreamLimSpec->Init((Byte *)ss, (size_t)unpackSize); + + RINOK(zlibCoder->Code(inStreamLim, outStreamLim, NULL, NULL, NULL)); + + if (outStreamLimSpec->GetPos() != (size_t)unpackSize) + return S_FALSE; + + ss[(size_t)unpackSize] = 0; + _xml.ReleaseBuffer(); + + CXml xml; + if (!xml.Parse(_xml)) + return S_FALSE; + + if (!xml.Root.IsTagged("xar") || xml.Root.SubItems.Size() != 1) + return S_FALSE; + const CXmlItem &toc = xml.Root.SubItems[0]; + if (!toc.IsTagged("toc")) + return S_FALSE; + if (!AddItem(toc, _files, -1)) + return S_FALSE; + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *stream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback * /* openArchiveCallback */) +{ + COM_TRY_BEGIN + { + Close(); + if (Open2(stream) != S_OK) + return S_FALSE; + _inStream = stream; + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _inStream.Release(); + _files.Clear(); + _xml.Empty(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _files.Size() + #ifdef XAR_SHOW_RAW + + 1 + #endif + ; + return S_OK; +} + +static void TimeToProp(UInt64 t, NWindows::NCOM::CPropVariant &prop) +{ + if (t != 0) + { + FILETIME ft; + ft.dwLowDateTime = (UInt32)(t); + ft.dwHighDateTime = (UInt32)(t >> 32); + prop = ft; + } +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + + #ifdef XAR_SHOW_RAW + if ((int)index == _files.Size()) + { + switch(propID) + { + case kpidPath: prop = L"[TOC].xml"; break; + case kpidSize: + case kpidPackSize: prop = (UInt64)_xml.Length(); break; + } + } + else + #endif + { + const CFile &item = _files[index]; + switch(propID) + { + case kpidMethod: + { + UString name; + if (!item.Method.IsEmpty() && ConvertUTF8ToUnicode(item.Method, name)) + prop = name; + break; + } + case kpidPath: + { + AString path; + int cur = index; + do + { + const CFile &item = _files[cur]; + AString s = item.Name; + if (s.IsEmpty()) + s = "unknown"; + if (path.IsEmpty()) + path = s; + else + path = s + CHAR_PATH_SEPARATOR + path; + cur = item.Parent; + } + while (cur >= 0); + + UString name; + if (ConvertUTF8ToUnicode(path, name)) + prop = name; + break; + } + + case kpidIsDir: prop = item.IsDir; break; + case kpidSize: if (!item.IsDir) prop = item.Size; break; + case kpidPackSize: if (!item.IsDir) prop = item.PackSize; break; + + case kpidMTime: TimeToProp(item.MTime, prop); break; + case kpidCTime: TimeToProp(item.CTime, prop); break; + case kpidATime: TimeToProp(item.ATime, prop); break; + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _files.Size(); + if (numItems == 0) + return S_OK; + UInt64 totalSize = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + { + int index = (int)(allFilesMode ? i : indices[i]); + #ifdef XAR_SHOW_RAW + if (index == _files.Size()) + totalSize += _xml.Length(); + else + #endif + totalSize += _files[index].Size; + } + extractCallback->SetTotal(totalSize); + + UInt64 currentPackTotal = 0; + UInt64 currentUnpTotal = 0; + UInt64 currentPackSize = 0; + UInt64 currentUnpSize = 0; + + const UInt32 kZeroBufSize = (1 << 14); + CByteBuffer zeroBuf; + zeroBuf.SetCapacity(kZeroBufSize); + memset(zeroBuf, 0, kZeroBufSize); + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + + NCompress::NZlib::CDecoder *zlibCoderSpec = new NCompress::NZlib::CDecoder(); + CMyComPtr zlibCoder = zlibCoderSpec; + + NCompress::NBZip2::CDecoder *bzip2CoderSpec = new NCompress::NBZip2::CDecoder(); + CMyComPtr bzip2Coder = bzip2CoderSpec; + + NCompress::NDeflate::NDecoder::CCOMCoder *deflateCoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder(); + CMyComPtr deflateCoder = deflateCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *inStreamSpec = new CLimitedSequentialInStream; + CMyComPtr inStream(inStreamSpec); + inStreamSpec->SetStream(_inStream); + + + CLimitedSequentialOutStream *outStreamLimSpec = new CLimitedSequentialOutStream; + CMyComPtr outStream(outStreamLimSpec); + + COutStreamWithSha1 *outStreamSha1Spec = new COutStreamWithSha1; + { + CMyComPtr outStreamSha1(outStreamSha1Spec); + outStreamLimSpec->SetStream(outStreamSha1); + } + + for (i = 0; i < numItems; i++, currentPackTotal += currentPackSize, currentUnpTotal += currentUnpSize) + { + lps->InSize = currentPackTotal; + lps->OutSize = currentUnpTotal; + currentPackSize = 0; + currentUnpSize = 0; + RINOK(lps->SetCur()); + CMyComPtr realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + if (index < _files.Size()) + { + const CFile &item = _files[index]; + if (item.IsDir) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + } + + if (!testMode && !realOutStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + + outStreamSha1Spec->SetStream(realOutStream); + realOutStream.Release(); + + Int32 opRes = NExtract::NOperationResult::kOK; + #ifdef XAR_SHOW_RAW + if (index == _files.Size()) + { + outStreamSha1Spec->Init(false); + outStreamLimSpec->Init(_xml.Length()); + RINOK(WriteStream(outStream, (const char *)_xml, _xml.Length())); + currentPackSize = currentUnpSize = _xml.Length(); + } + else + #endif + { + const CFile &item = _files[index]; + if (item.HasData) + { + currentPackSize = item.PackSize; + currentUnpSize = item.Size; + + RINOK(_inStream->Seek(_dataStartPos + item.Offset, STREAM_SEEK_SET, NULL)); + inStreamSpec->Init(item.PackSize); + outStreamSha1Spec->Init(item.Sha1IsDefined); + outStreamLimSpec->Init(item.Size); + HRESULT res = S_OK; + + ICompressCoder *coder = NULL; + if (item.Method.IsEmpty() || item.Method == "octet-stream") + if (item.PackSize == item.Size) + coder = copyCoder; + else + opRes = NExtract::NOperationResult::kUnSupportedMethod; + else if (item.Method == METHOD_NAME_ZLIB) + coder = zlibCoder; + else if (item.Method == "bzip2") + coder = bzip2Coder; + else + opRes = NExtract::NOperationResult::kUnSupportedMethod; + + if (coder) + res = coder->Code(inStream, outStream, NULL, NULL, progress); + + if (res != S_OK) + { + if (!outStreamLimSpec->IsFinishedOK()) + opRes = NExtract::NOperationResult::kDataError; + else if (res != S_FALSE) + return res; + if (opRes == NExtract::NOperationResult::kOK) + opRes = NExtract::NOperationResult::kDataError; + } + + if (opRes == NExtract::NOperationResult::kOK) + { + if (outStreamLimSpec->IsFinishedOK() && + outStreamSha1Spec->GetSize() == item.Size) + { + if (!outStreamLimSpec->IsFinishedOK()) + { + opRes = NExtract::NOperationResult::kDataError; + } + else if (item.Sha1IsDefined) + { + Byte digest[NCrypto::NSha1::kDigestSize]; + outStreamSha1Spec->Final(digest); + if (memcmp(digest, item.Sha1, NCrypto::NSha1::kDigestSize) != 0) + opRes = NExtract::NOperationResult::kCRCError; + } + } + else + opRes = NExtract::NOperationResult::kDataError; + } + } + } + outStreamSha1Spec->ReleaseStream(); + RINOK(extractCallback->SetOperationResult(opRes)); + } + return S_OK; + COM_TRY_END +} + +static IInArchive *CreateArc() { return new NArchive::NXar::CHandler; } + +static CArcInfo g_ArcInfo = + { L"Xar", L"xar", 0, 0xE1, { 'x', 'a', 'r', '!', 0, 0x1C }, 6, false, CreateArc, 0 }; + +REGISTER_ARC(Xar) + +}} diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp new file mode 100755 index 0000000..e4029e0 --- /dev/null +++ b/CPP/7zip/Archive/XzHandler.cpp @@ -0,0 +1,707 @@ +// XzHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" +#include "../../../C/XzCrc64.h" +#include "../../../C/XzEnc.h" + +#include "../../Common/ComTry.h" +#include "../../Common/IntToString.h" + +#include "../ICoder.h" + +#include "../Common/CWrappers.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +#include "IArchive.h" + +#include "Common/HandlerOut.h" + +using namespace NWindows; + +namespace NCompress { +namespace NLzma2 { + +HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props); + +}} + +static void *SzAlloc(void *, size_t size) { return MyAlloc(size); } +static void SzFree(void *, void *address) { MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +namespace NArchive { +namespace NXz { + +struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit; + +class CHandler: + public IInArchive, + public IArchiveOpenSeq, + #ifndef EXTRACT_ONLY + public IOutArchive, + public ISetProperties, + public COutHandler, + #endif + public CMyUnknownImp +{ + Int64 _startPosition; + UInt64 _packSize; + UInt64 _unpackSize; + UInt64 _numBlocks; + AString _methodsString; + bool _useSeq; + UInt64 _unpackSizeDefined; + UInt64 _packSizeDefined; + + CMyComPtr _stream; + CMyComPtr _seqStream; + + UInt32 _crcSize; + + void Init() + { + _crcSize = 4; + COutHandler::Init(); + } + + HRESULT Open2(IInStream *inStream, IArchiveOpenCallback *callback); + +public: + MY_QUERYINTERFACE_BEGIN2(IInArchive) + MY_QUERYINTERFACE_ENTRY(IArchiveOpenSeq) + #ifndef EXTRACT_ONLY + MY_QUERYINTERFACE_ENTRY(IOutArchive) + MY_QUERYINTERFACE_ENTRY(ISetProperties) + #endif + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + INTERFACE_IInArchive(;) + STDMETHOD(OpenSeq)(ISequentialInStream *stream); + + #ifndef EXTRACT_ONLY + INTERFACE_IOutArchive(;) + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps); + #endif + + CHandler(); +}; + +CHandler::CHandler() +{ + Init(); +} + +STATPROPSTG kProps[] = +{ + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMethod, VT_BSTR} +}; + +STATPROPSTG kArcProps[] = +{ + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidNumBlocks, VT_UI4} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +static char GetHex(Byte value) +{ + return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); +} + +static inline void AddHexToString(AString &res, Byte value) +{ + res += GetHex((Byte)(value >> 4)); + res += GetHex((Byte)(value & 0xF)); +} + +static AString ConvertUInt32ToString(UInt32 value) +{ + char temp[32]; + ::ConvertUInt32ToString(value, temp); + return temp; +} + +static AString Lzma2PropToString(int prop) +{ + if ((prop & 1) == 0) + return ConvertUInt32ToString(prop / 2 + 12); + AString res; + char c; + + UInt32 size = (2 | ((prop) & 1)) << ((prop) / 2 + 1); + + if (prop > 17) + { + res = ConvertUInt32ToString(size >> 10); + c = 'm'; + } + else + { + res = ConvertUInt32ToString(size); + c = 'k'; + } + return res + c; +} + +struct CMethodNamePair +{ + UInt32 Id; + const char *Name; +}; + +static CMethodNamePair g_NamePairs[] = +{ + { XZ_ID_Subblock, "SB" }, + { XZ_ID_Delta, "Delta" }, + { XZ_ID_X86, "x86" }, + { 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 AString GetMethodString(const CXzFilter &f) +{ + AString s; + + for (int i = 0; i < sizeof(g_NamePairs) / sizeof(g_NamePairs[i]); i++) + if (g_NamePairs[i].Id == f.id) + s = g_NamePairs[i].Name; + if (s.IsEmpty()) + { + char temp[32]; + ::ConvertUInt64ToString(f.id, temp); + s = temp; + } + + if (f.propsSize > 0) + { + s += ':'; + if (f.id == XZ_ID_LZMA2 && f.propsSize == 1) + s += Lzma2PropToString(f.props[0]); + else if (f.id == XZ_ID_Delta && f.propsSize == 1) + s += ConvertUInt32ToString((UInt32)f.props[0] + 1); + else + { + s += '['; + for (UInt32 bi = 0; bi < f.propsSize; bi++) + AddHexToString(s, f.props[bi]); + s += ']'; + } + } + return s; +} + +static void AddString(AString &dest, const AString &src) +{ + if (!dest.IsEmpty()) + dest += ' '; + dest += src; +} + +static const char *kChecks[] = +{ + "NoCheck", + "CRC32", + NULL, + NULL, + "CRC64", + NULL, + NULL, + NULL, + NULL, + NULL, + "SHA256", + NULL, + NULL, + NULL, + NULL, + NULL +}; + +static AString GetCheckString(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)); + AString s; + for (i = 0; i <= XZ_CHECK_MASK; i++) + if (((mask >> i) & 1) != 0) + { + AString s2; + if (kChecks[i]) + s2 = kChecks[i]; + else + s2 = "Check-" + ConvertUInt32ToString((UInt32)i); + AddString(s, s2); + } + return s; +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidNumBlocks: if (!_useSeq) prop = _numBlocks; break; + case kpidPhySize: if (_packSizeDefined) prop = _packSize; break; + case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; 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 + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidSize: if (_unpackSizeDefined) prop = _unpackSize; break; + case kpidPackSize: if (_packSizeDefined) prop = _packSize; break; + case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + + +struct COpenCallbackWrap +{ + ICompressProgress p; + IArchiveOpenCallback *OpenCallback; + HRESULT Res; + COpenCallbackWrap(IArchiveOpenCallback *progress); +}; + +static SRes OpenCallbackProgress(void *pp, UInt64 inSize, UInt64 /* outSize */) +{ + COpenCallbackWrap *p = (COpenCallbackWrap *)pp; + p->Res = p->OpenCallback->SetCompleted(NULL, &inSize); + return (SRes)p->Res; +} + +COpenCallbackWrap::COpenCallbackWrap(IArchiveOpenCallback *callback) +{ + p.Progress = OpenCallbackProgress; + OpenCallback = callback; + Res = SZ_OK; +} + +struct CXzsCPP +{ + CXzs p; + CXzsCPP() { Xzs_Construct(&p); } + ~CXzsCPP() { Xzs_Free(&p, &g_Alloc); } +}; + +HRESULT CHandler::Open2(IInStream *inStream, IArchiveOpenCallback *callback) +{ + CSeekInStreamWrap inStreamImp(inStream); + + CLookToRead lookStream; + LookToRead_CreateVTable(&lookStream, True); + lookStream.realStream = &inStreamImp.p; + LookToRead_Init(&lookStream); + + COpenCallbackWrap openWrap(callback); + RINOK(inStream->Seek(0, STREAM_SEEK_END, &_packSize)); + RINOK(callback->SetTotal(NULL, &_packSize)); + + CXzsCPP xzs; + SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.s, &_startPosition, &openWrap.p, &g_Alloc); + if (res == SZ_ERROR_NO_ARCHIVE && xzs.p.num > 0) + res = SZ_OK; + if (res == SZ_OK) + { + _packSize -= _startPosition; + _unpackSize = Xzs_GetUnpackSize(&xzs.p); + _unpackSizeDefined = _packSizeDefined = true; + _numBlocks = (UInt64)Xzs_GetNumBlocks(&xzs.p); + + RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); + CXzStreamFlags st; + CSeqInStreamWrap inStreamWrap(inStream); + SRes res2 = Xz_ReadHeader(&st, &inStreamWrap.p); + + if (res2 == SZ_OK) + { + CXzBlock block; + Bool isIndex; + UInt32 headerSizeRes; + res2 = XzBlock_ReadHeader(&block, &inStreamWrap.p, &isIndex, &headerSizeRes); + if (res2 == SZ_OK && !isIndex) + { + int numFilters = XzBlock_GetNumFilters(&block); + for (int i = 0; i < numFilters; i++) + AddString(_methodsString, GetMethodString(block.filters[i])); + } + } + AddString(_methodsString, GetCheckString(xzs.p)); + } + + if (res != SZ_OK || _startPosition != 0) + { + RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); + CXzStreamFlags st; + CSeqInStreamWrap inStreamWrap(inStream); + SRes res2 = Xz_ReadHeader(&st, &inStreamWrap.p); + if (res2 == SZ_OK) + { + res = res2; + _startPosition = 0; + _useSeq = True; + _unpackSizeDefined = _packSizeDefined = false; + } + } + if (res == SZ_ERROR_NO_ARCHIVE) + return S_FALSE; + RINOK(SResToHRESULT(res)); + _stream = inStream; + _seqStream = inStream; + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + try + { + Close(); + return Open2(inStream, callback); + } + catch(...) { return S_FALSE; } + COM_TRY_END +} + +STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) +{ + Close(); + _seqStream = stream; + return S_OK; +} + +STDMETHODIMP CHandler::Close() +{ + _numBlocks = 0; + _useSeq = true; + _unpackSizeDefined = _packSizeDefined = false; + _methodsString.Empty(); + _stream.Release(); + _seqStream.Release(); + return S_OK; +} + +class CSeekToSeqStream: + public IInStream, + public CMyUnknownImp +{ +public: + CMyComPtr Stream; + MY_UNKNOWN_IMP1(IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + +STDMETHODIMP CSeekToSeqStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + return Stream->Read(data, size, processedSize); +} + +STDMETHODIMP CSeekToSeqStream::Seek(Int64, UInt32, UInt64 *) { return E_NOTIMPL; } + +struct CXzUnpackerCPP +{ + Byte *InBuf; + Byte *OutBuf; + CXzUnpacker p; + CXzUnpackerCPP(): InBuf(0), OutBuf(0) {} + ~CXzUnpackerCPP() + { + XzUnpacker_Free(&p); + MyFree(InBuf); + MyFree(OutBuf); + } +}; + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + if (numItems == 0) + return S_OK; + if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0)) + return E_INVALIDARG; + + extractCallback->SetTotal(_packSize); + 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); + + if (_stream) + { + RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); + } + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, true); + + CCompressProgressWrap progressWrap(progress); + + SRes res; + + const UInt32 kInBufSize = 1 << 15; + const UInt32 kOutBufSize = 1 << 21; + + UInt32 inPos = 0; + UInt32 inSize = 0; + UInt32 outPos = 0; + CXzUnpackerCPP xzu; + res = XzUnpacker_Create(&xzu.p, &g_Alloc); + if (res == SZ_OK) + { + xzu.InBuf = (Byte *)MyAlloc(kInBufSize); + xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize); + if (xzu.InBuf == 0 || xzu.OutBuf == 0) + res = SZ_ERROR_MEM; + } + if (res == SZ_OK) + for (;;) + { + if (inPos == inSize) + { + inPos = inSize = 0; + RINOK(_seqStream->Read(xzu.InBuf, kInBufSize, &inSize)); + } + + SizeT inLen = inSize - inPos; + SizeT outLen = kOutBufSize - outPos; + ECoderStatus status; + res = XzUnpacker_Code(&xzu.p, + xzu.OutBuf + outPos, &outLen, + xzu.InBuf + inPos, &inLen, + (inSize == 0 ? CODER_FINISH_END : CODER_FINISH_ANY), &status); + + // printf("\n_inPos = %6d inLen = %5d, outLen = %5d", inPos, inLen, outLen); + + inPos += (UInt32)inLen; + outPos += (UInt32)outLen; + lps->InSize += inLen; + lps->OutSize += outLen; + + bool finished = (((inLen == 0) && (outLen == 0)) || res != SZ_OK); + + if (outPos == kOutBufSize || finished) + { + if (realOutStream && outPos > 0) + { + RINOK(WriteStream(realOutStream, xzu.OutBuf, outPos)); + } + outPos = 0; + } + if (finished) + { + _packSize = lps->InSize; + _unpackSize = lps->OutSize; + _packSizeDefined = _unpackSizeDefined = true; + if (res == SZ_OK) + { + if (status == CODER_STATUS_NEEDS_MORE_INPUT) + { + if (XzUnpacker_IsStreamWasFinished(&xzu.p)) + _packSize -= xzu.p.padSize; + else + res = SZ_ERROR_DATA; + } + else + res = SZ_ERROR_DATA; + } + break; + } + RINOK(lps->SetCur()); + } + + Int32 opRes; + switch(res) + { + case SZ_OK: + opRes = NExtract::NOperationResult::kOK; break; + case SZ_ERROR_UNSUPPORTED: + opRes = NExtract::NOperationResult::kUnSupportedMethod; break; + case SZ_ERROR_CRC: + opRes = NExtract::NOperationResult::kCRCError; break; + case SZ_ERROR_DATA: + case SZ_ERROR_ARCHIVE: + case SZ_ERROR_NO_ARCHIVE: + opRes = NExtract::NOperationResult::kDataError; break; + default: + return SResToHRESULT(res); + } + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(opRes)); + return S_OK; + 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) +{ + CSeqOutStreamWrap seqOutStream(outStream); + + if (numItems == 0) + { + SRes res = Xz_EncodeEmpty(&seqOutStream.p); + 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)); + } + + CLzma2EncProps lzma2Props; + Lzma2EncProps_Init(&lzma2Props); + + lzma2Props.lzmaProps.level = _level; + + CMyComPtr fileInStream; + RINOK(updateCallback->GetStream(0, &fileInStream)); + + CSeqInStreamWrap seqInStream(fileInStream); + + for (int i = 0; i < _methods.Size(); i++) + { + COneMethodInfo &m = _methods[i]; + SetCompressionMethod2(m + #ifndef _7ZIP_ST + , _numThreads + #endif + ); + if (m.IsLzma()) + { + for (int j = 0; j < m.Props.Size(); j++) + { + const CProp &prop = m.Props[j]; + RINOK(NCompress::NLzma2::SetLzma2Prop(prop.Id, prop.Value, lzma2Props)); + } + } + } + + #ifndef _7ZIP_ST + lzma2Props.numTotalThreads = _numThreads; + #endif + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(updateCallback, true); + + CCompressProgressWrap progressWrap(progress); + SRes res = Xz_Encode(&seqOutStream.p, &seqInStream.p, &lzma2Props, False, &progressWrap.p); + if (res == SZ_OK) + return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); + return SResToHRESULT(res); + } + if (indexInArchive != 0) + return E_INVALIDARG; + if (_stream) + RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); + return NCompress::CopyStream(_stream, outStream, 0); +} + +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) +{ + COM_TRY_BEGIN + BeforeSetProperty(); + for (int i = 0; i < numProps; i++) + { + RINOK(SetProperty(names[i], values[i])); + } + return S_OK; + COM_TRY_END +} + +#endif + +static IInArchive *CreateArc() { return new NArchive::NXz::CHandler; } +#ifndef EXTRACT_ONLY +static IOutArchive *CreateArcOut() { return new NArchive::NXz::CHandler; } +#else +#define CreateArcOut 0 +#endif + +static CArcInfo g_ArcInfo = + { L"xz", L"xz txz", L"* .tar", 0xC, {0xFD, '7' , 'z', 'X', 'Z', '\0'}, 6, true, CreateArc, CreateArcOut }; + +REGISTER_ARC(xz) + +}} diff --git a/CPP/7zip/Archive/ZHandler.cpp b/CPP/7zip/Archive/ZHandler.cpp new file mode 100755 index 0000000..1307197 --- /dev/null +++ b/CPP/7zip/Archive/ZHandler.cpp @@ -0,0 +1,161 @@ +// ZHandler.cpp + +#include "StdAfx.h" + +#include "Common/ComTry.h" + +#include "Windows/PropVariant.h" + +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/ZDecoder.h" + +#include "Common/DummyOutStream.h" + +namespace NArchive { +namespace NZ { + +class CHandler: + public IInArchive, + public CMyUnknownImp +{ + CMyComPtr _stream; + UInt64 _streamStartPosition; + UInt64 _packSize; + Byte _properties; +public: + MY_UNKNOWN_IMP1(IInArchive) + INTERFACE_IInArchive(;) +}; + +STATPROPSTG kProps[] = +{ + { NULL, kpidPackSize, VT_UI8} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = 1; + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +{ + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidPackSize: prop = _packSize; break; + } + prop.Detach(value); + return S_OK; +} + +static const int kSignatureSize = 3; + +STDMETHODIMP CHandler::Open(IInStream *stream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback * /* openArchiveCallback */) +{ + COM_TRY_BEGIN + { + RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_streamStartPosition)); + Byte buffer[kSignatureSize]; + RINOK(ReadStream_FALSE(stream, buffer, kSignatureSize)); + if (buffer[0] != 0x1F || buffer[1] != 0x9D) + return S_FALSE; + _properties = buffer[2]; + + UInt64 endPosition; + RINOK(stream->Seek(0, STREAM_SEEK_END, &endPosition)); + _packSize = endPosition - _streamStartPosition - kSignatureSize; + + _stream = stream; + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _stream.Release(); + 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)-1 && (numItems != 1 || indices[0] != 0)) + return E_INVALIDARG; + + extractCallback->SetTotal(_packSize); + + 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); + + 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); + + RINOK(_stream->Seek(_streamStartPosition + kSignatureSize, STREAM_SEEK_SET, NULL)); + + CMyComPtr decoder; + NCompress::NZ::CDecoder *decoderSpec = new NCompress::NZ::CDecoder; + decoder = decoderSpec; + + HRESULT result = decoderSpec->SetDecoderProperties2(&_properties, 1); + + int opResult; + if (result != S_OK) + opResult = NExtract::NOperationResult::kUnSupportedMethod; + else + { + result = decoder->Code(_stream, outStream, NULL, NULL, progress); + if (result == S_FALSE) + opResult = NExtract::NOperationResult::kDataError; + else + { + RINOK(result); + opResult = NExtract::NOperationResult::kOK; + } + } + outStream.Release(); + return extractCallback->SetOperationResult(opResult); + COM_TRY_END +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"Z", L"z taz", L"* .tar", 5, { 0x1F, 0x9D }, 2, false, CreateArc, 0 }; + +REGISTER_ARC(Z) + +}} diff --git a/CPP/7zip/Archive/Zip/StdAfx.h b/CPP/7zip/Archive/Zip/StdAfx.h new file mode 100755 index 0000000..83fdd22 --- /dev/null +++ b/CPP/7zip/Archive/Zip/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" + +#endif diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp new file mode 100755 index 0000000..f86391e --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp @@ -0,0 +1,379 @@ +// ZipAddCommon.cpp + +#include "StdAfx.h" + +#include "../../../../C/7zCrc.h" + +#include "Windows/PropVariant.h" + +#include "../../ICoder.h" +#include "../../IPassword.h" +#include "../../MyVersion.h" + +#include "../../Common/CreateCoder.h" +#include "../../Common/StreamObjects.h" +#include "../../Common/StreamUtils.h" + +#include "../../Compress/LzmaEncoder.h" +#include "../../Compress/PpmdZip.h" + +#include "../Common/InStreamWithCRC.h" + +#include "ZipAddCommon.h" +#include "ZipHeader.h" + +namespace NArchive { +namespace NZip { + +static const CMethodId kMethodId_ZipBase = 0x040100; +static const CMethodId kMethodId_BZip2 = 0x040202; + +static const UInt32 kLzmaPropsSize = 5; +static const UInt32 kLzmaHeaderSize = 4 + kLzmaPropsSize; + +class CLzmaEncoder: + public ICompressCoder, + public CMyUnknownImp +{ + NCompress::NLzma::CEncoder *EncoderSpec; + CMyComPtr Encoder; + Byte Header[kLzmaHeaderSize]; +public: + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + HRESULT SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); + + MY_UNKNOWN_IMP +}; + +HRESULT CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) +{ + if (!Encoder) + { + EncoderSpec = new NCompress::NLzma::CEncoder; + Encoder = EncoderSpec; + } + CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream; + CMyComPtr outStream(outStreamSpec); + outStreamSpec->Init(Header + 4, kLzmaPropsSize); + RINOK(EncoderSpec->SetCoderProperties(propIDs, props, numProps)); + RINOK(EncoderSpec->WriteCoderProperties(outStream)); + if (outStreamSpec->GetPos() != kLzmaPropsSize) + return E_FAIL; + Header[0] = MY_VER_MAJOR; + Header[1] = MY_VER_MINOR; + Header[2] = kLzmaPropsSize; + Header[3] = 0; + return S_OK; +} + +HRESULT CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + RINOK(WriteStream(outStream, Header, kLzmaHeaderSize)); + return Encoder->Code(inStream, outStream, inSize, outSize, progress); +} + + +CAddCommon::CAddCommon(const CCompressionMethodMode &options): + _options(options), + _copyCoderSpec(NULL), + _cryptoStreamSpec(0) + {} + +static HRESULT GetStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC) +{ + UInt32 crc = CRC_INIT_VAL; + const UInt32 kBufferSize = (1 << 14); + Byte buffer[kBufferSize]; + for (;;) + { + UInt32 realProcessedSize; + RINOK(inStream->Read(buffer, kBufferSize, &realProcessedSize)); + if (realProcessedSize == 0) + { + resultCRC = CRC_GET_DIGEST(crc); + return S_OK; + } + crc = CrcUpdate(crc, buffer, (size_t)realProcessedSize); + } +} + +HRESULT CAddCommon::Compress( + DECL_EXTERNAL_CODECS_LOC_VARS + ISequentialInStream *inStream, IOutStream *outStream, + ICompressProgressInfo *progress, CCompressingResult &opRes) +{ + CSequentialInStreamWithCRC *inSecCrcStreamSpec = 0; + CInStreamWithCRC *inCrcStreamSpec = 0; + CMyComPtr inCrcStream; + { + CMyComPtr inStream2; + // we don't support stdin, since stream from stdin can require 64-bit size header + RINOK(inStream->QueryInterface(IID_IInStream, (void **)&inStream2)); + if (inStream2) + { + inCrcStreamSpec = new CInStreamWithCRC; + inCrcStream = inCrcStreamSpec; + inCrcStreamSpec->SetStream(inStream2); + inCrcStreamSpec->Init(); + } + else + { + inSecCrcStreamSpec = new CSequentialInStreamWithCRC; + inCrcStream = inSecCrcStreamSpec; + inSecCrcStreamSpec->SetStream(inStream); + inSecCrcStreamSpec->Init(); + } + } + + int numTestMethods = _options.MethodSequence.Size(); + if (numTestMethods > 1 || _options.PasswordIsDefined) + { + if (inCrcStreamSpec == 0) + { + if (_options.PasswordIsDefined) + return E_NOTIMPL; + numTestMethods = 1; + } + } + Byte method = 0; + COutStreamReleaser outStreamReleaser; + opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Default; + for (int i = 0; i < numTestMethods; i++) + { + opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Default; + if (inCrcStreamSpec != 0) + RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL)); + RINOK(outStream->SetSize(0)); + RINOK(outStream->Seek(0, STREAM_SEEK_SET, NULL)); + if (_options.PasswordIsDefined) + { + opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_ZipCrypto; + + if (!_cryptoStream) + { + _cryptoStreamSpec = new CFilterCoder; + _cryptoStream = _cryptoStreamSpec; + } + if (_options.IsAesMode) + { + opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Aes; + if (!_cryptoStreamSpec->Filter) + { + _cryptoStreamSpec->Filter = _filterAesSpec = new NCrypto::NWzAes::CEncoder; + _filterAesSpec->SetKeyMode(_options.AesKeyMode); + RINOK(_filterAesSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Length())); + } + RINOK(_filterAesSpec->WriteHeader(outStream)); + } + else + { + if (!_cryptoStreamSpec->Filter) + { + _cryptoStreamSpec->Filter = _filterSpec = new NCrypto::NZip::CEncoder; + _filterSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Length()); + } + UInt32 crc = 0; + RINOK(GetStreamCRC(inStream, crc)); + RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL)); + RINOK(_filterSpec->WriteHeader(outStream, crc)); + } + RINOK(_cryptoStreamSpec->SetOutStream(outStream)); + outStreamReleaser.FilterCoder = _cryptoStreamSpec; + } + + method = _options.MethodSequence[i]; + switch(method) + { + case NFileHeader::NCompressionMethod::kStored: + { + if (_copyCoderSpec == NULL) + { + _copyCoderSpec = new NCompress::CCopyCoder; + _copyCoder = _copyCoderSpec; + } + CMyComPtr outStreamNew; + if (_options.PasswordIsDefined) + outStreamNew = _cryptoStream; + else + outStreamNew = outStream; + RINOK(_copyCoder->Code(inCrcStream, outStreamNew, NULL, NULL, progress)); + break; + } + default: + { + if (!_compressEncoder) + { + if (method == NFileHeader::NCompressionMethod::kLZMA) + { + _compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_LZMA; + CLzmaEncoder *_lzmaEncoder = new CLzmaEncoder(); + _compressEncoder = _lzmaEncoder; + NWindows::NCOM::CPropVariant props[] = + { + #ifndef _7ZIP_ST + _options.NumThreads, + #endif + _options.Algo, + _options.DicSize, + _options.NumFastBytes, + const_cast((const wchar_t *)_options.MatchFinder), + _options.NumMatchFinderCycles + }; + PROPID propIDs[] = + { + #ifndef _7ZIP_ST + NCoderPropID::kNumThreads, + #endif + NCoderPropID::kAlgorithm, + NCoderPropID::kDictionarySize, + NCoderPropID::kNumFastBytes, + NCoderPropID::kMatchFinder, + NCoderPropID::kMatchFinderCycles + }; + int numProps = sizeof(propIDs) / sizeof(propIDs[0]); + if (!_options.NumMatchFinderCyclesDefined) + numProps--; + RINOK(_lzmaEncoder->SetCoderProperties(propIDs, props, numProps)); + } + else if (method == NFileHeader::NCompressionMethod::kPPMd) + { + _compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_PPMd; + NCompress::NPpmdZip::CEncoder *encoder = new NCompress::NPpmdZip::CEncoder(); + _compressEncoder = encoder; + NWindows::NCOM::CPropVariant props[] = + { + _options.Algo, + _options.MemSize, + _options.Order + + }; + PROPID propIDs[] = + { + NCoderPropID::kAlgorithm, + NCoderPropID::kUsedMemorySize, + NCoderPropID::kOrder + }; + RINOK(encoder->SetCoderProperties(propIDs, props, sizeof(propIDs) / sizeof(propIDs[0]))); + } + else + { + CMethodId methodId; + switch(method) + { + case NFileHeader::NCompressionMethod::kBZip2: + methodId = kMethodId_BZip2; + _compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_BZip2; + break; + default: + _compressExtractVersion = ((method == NFileHeader::NCompressionMethod::kDeflated64) ? + NFileHeader::NCompressionMethod::kExtractVersion_Deflate64 : + NFileHeader::NCompressionMethod::kExtractVersion_Deflate); + methodId = kMethodId_ZipBase + method; + break; + } + RINOK(CreateCoder( + EXTERNAL_CODECS_LOC_VARS + methodId, _compressEncoder, true)); + if (!_compressEncoder) + return E_NOTIMPL; + + if (method == NFileHeader::NCompressionMethod::kDeflated || + method == NFileHeader::NCompressionMethod::kDeflated64) + { + NWindows::NCOM::CPropVariant props[] = + { + _options.Algo, + _options.NumPasses, + _options.NumFastBytes, + _options.NumMatchFinderCycles + }; + PROPID propIDs[] = + { + NCoderPropID::kAlgorithm, + NCoderPropID::kNumPasses, + NCoderPropID::kNumFastBytes, + NCoderPropID::kMatchFinderCycles + }; + int numProps = sizeof(propIDs) / sizeof(propIDs[0]); + if (!_options.NumMatchFinderCyclesDefined) + numProps--; + CMyComPtr setCoderProperties; + _compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties); + if (setCoderProperties) + { + RINOK(setCoderProperties->SetCoderProperties(propIDs, props, numProps)); + } + } + else if (method == NFileHeader::NCompressionMethod::kBZip2) + { + NWindows::NCOM::CPropVariant props[] = + { + _options.DicSize, + _options.NumPasses + #ifndef _7ZIP_ST + , _options.NumThreads + #endif + }; + PROPID propIDs[] = + { + NCoderPropID::kDictionarySize, + NCoderPropID::kNumPasses + #ifndef _7ZIP_ST + , NCoderPropID::kNumThreads + #endif + }; + CMyComPtr setCoderProperties; + _compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties); + if (setCoderProperties) + { + RINOK(setCoderProperties->SetCoderProperties(propIDs, props, sizeof(propIDs) / sizeof(propIDs[0]))); + } + } + } + } + CMyComPtr outStreamNew; + if (_options.PasswordIsDefined) + outStreamNew = _cryptoStream; + else + outStreamNew = outStream; + if (_compressExtractVersion > opRes.ExtractVersion) + opRes.ExtractVersion = _compressExtractVersion; + RINOK(_compressEncoder->Code(inCrcStream, outStreamNew, NULL, NULL, progress)); + break; + } + } + + RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &opRes.PackSize)); + + if (inCrcStreamSpec != 0) + { + opRes.CRC = inCrcStreamSpec->GetCRC(); + opRes.UnpackSize = inCrcStreamSpec->GetSize(); + } + else + { + opRes.CRC = inSecCrcStreamSpec->GetCRC(); + opRes.UnpackSize = inSecCrcStreamSpec->GetSize(); + } + + if (_options.PasswordIsDefined) + { + if (opRes.PackSize < opRes.UnpackSize + + (_options.IsAesMode ? _filterAesSpec->GetHeaderSize() : NCrypto::NZip::kHeaderSize)) + break; + } + else if (opRes.PackSize < opRes.UnpackSize) + break; + } + if (_options.IsAesMode) + { + RINOK(_filterAesSpec->WriteFooter(outStream)); + RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &opRes.PackSize)); + } + opRes.Method = method; + return S_OK; +} + +}} diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.h b/CPP/7zip/Archive/Zip/ZipAddCommon.h new file mode 100755 index 0000000..7c379cc --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipAddCommon.h @@ -0,0 +1,56 @@ +// ZipAddCommon.h + +#ifndef __ZIP_ADD_COMMON_H +#define __ZIP_ADD_COMMON_H + +#include "../../ICoder.h" +#include "../../IProgress.h" + +#include "../../Common/CreateCoder.h" +#include "../../Common/FilterCoder.h" + +#include "../../Compress/CopyCoder.h" + +#include "../../Crypto/ZipCrypto.h" +#include "../../Crypto/WzAes.h" + +#include "ZipCompressionMode.h" + +namespace NArchive { +namespace NZip { + +struct CCompressingResult +{ + UInt64 UnpackSize; + UInt64 PackSize; + UInt32 CRC; + UInt16 Method; + Byte ExtractVersion; +}; + +class CAddCommon +{ + CCompressionMethodMode _options; + NCompress::CCopyCoder *_copyCoderSpec; + CMyComPtr _copyCoder; + + CMyComPtr _compressEncoder; + Byte _compressExtractVersion; + + CFilterCoder *_cryptoStreamSpec; + CMyComPtr _cryptoStream; + + NCrypto::NZip::CEncoder *_filterSpec; + NCrypto::NWzAes::CEncoder *_filterAesSpec; + +public: + CAddCommon(const CCompressionMethodMode &options); + HRESULT Compress( + DECL_EXTERNAL_CODECS_LOC_VARS + ISequentialInStream *inStream, IOutStream *outStream, + ICompressProgressInfo *progress, CCompressingResult &operationResult); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Zip/ZipCompressionMode.h b/CPP/7zip/Archive/Zip/ZipCompressionMode.h new file mode 100755 index 0000000..6713473 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipCompressionMode.h @@ -0,0 +1,42 @@ +// CompressionMode.h + +#ifndef __ZIP_COMPRESSION_MODE_H +#define __ZIP_COMPRESSION_MODE_H + +#include "Common/MyString.h" + +namespace NArchive { +namespace NZip { + +struct CCompressionMethodMode +{ + CRecordVector MethodSequence; + UString MatchFinder; + UInt32 Algo; + UInt32 NumPasses; + UInt32 NumFastBytes; + bool NumMatchFinderCyclesDefined; + UInt32 NumMatchFinderCycles; + UInt32 DicSize; + UInt32 MemSize; + UInt32 Order; + + #ifndef _7ZIP_ST + UInt32 NumThreads; + #endif + bool PasswordIsDefined; + AString Password; + bool IsAesMode; + Byte AesKeyMode; + + CCompressionMethodMode(): + NumMatchFinderCyclesDefined(false), + PasswordIsDefined(false), + IsAesMode(false), + AesKeyMode(3) + {} +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp new file mode 100755 index 0000000..4b257f1 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp @@ -0,0 +1,822 @@ +// ZipHandler.cpp + +#include "StdAfx.h" + +#include "Common/ComTry.h" +#include "Common/IntToString.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../../IPassword.h" + +#include "../../Common/FilterCoder.h" +#include "../../Common/ProgressUtils.h" +#include "../../Common/StreamObjects.h" +#include "../../Common/StreamUtils.h" + +#include "../../Compress/CopyCoder.h" +#include "../../Compress/LzmaDecoder.h" +#include "../../Compress/ImplodeDecoder.h" +#include "../../Compress/PpmdZip.h" +#include "../../Compress/ShrinkDecoder.h" + +#include "../../Crypto/WzAes.h" +#include "../../Crypto/ZipCrypto.h" +#include "../../Crypto/ZipStrong.h" + +#include "../Common/ItemNameUtils.h" +#include "../Common/OutStreamWithCRC.h" + +#include "ZipHandler.h" + +using namespace NWindows; + +namespace NArchive { +namespace NZip { + +static const CMethodId kMethodId_ZipBase = 0x040100; +static const CMethodId kMethodId_BZip2 = 0x040202; + +static const char *kHostOS[] = +{ + "FAT", + "AMIGA", + "VMS", + "Unix", + "VM/CMS", + "Atari", + "HPFS", + "Macintosh", + "Z-System", + "CP/M", + "TOPS-20", + "NTFS", + "SMS/QDOS", + "Acorn", + "VFAT", + "MVS", + "BeOS", + "Tandem", + "OS/400", + "OS/X" +}; + +static const char *kUnknownOS = "Unknown"; + +static const char *kMethods[] = +{ + "Store", + "Shrink", + "Reduced1", + "Reduced2", + "Reduced3", + "Reduced4", + "Implode", + "Tokenizing", + "Deflate", + "Deflate64", + "PKImploding" +}; + +static const char *kBZip2Method = "BZip2"; +static const char *kLZMAMethod = "LZMA"; +static const char *kJpegMethod = "Jpeg"; +static const char *kWavPackMethod = "WavPack"; +static const char *kPPMdMethod = "PPMd"; +static const char *kAESMethod = "AES"; +static const char *kZipCryptoMethod = "ZipCrypto"; +static const char *kStrongCryptoMethod = "StrongCrypto"; + +static struct CStrongCryptoPair +{ + UInt16 Id; + const char *Name; +} g_StrongCryptoPairs[] = +{ + { NStrongCryptoFlags::kDES, "DES" }, + { NStrongCryptoFlags::kRC2old, "RC2a" }, + { NStrongCryptoFlags::k3DES168, "3DES-168" }, + { NStrongCryptoFlags::k3DES112, "3DES-112" }, + { NStrongCryptoFlags::kAES128, "pkAES-128" }, + { NStrongCryptoFlags::kAES192, "pkAES-192" }, + { NStrongCryptoFlags::kAES256, "pkAES-256" }, + { NStrongCryptoFlags::kRC2, "RC2" }, + { NStrongCryptoFlags::kBlowfish, "Blowfish" }, + { NStrongCryptoFlags::kTwofish, "Twofish" }, + { NStrongCryptoFlags::kRC4, "RC4" } +}; + +static STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidATime, VT_FILETIME}, + { NULL, kpidAttrib, VT_UI4}, + { NULL, kpidEncrypted, VT_BOOL}, + { NULL, kpidComment, VT_BSTR}, + { NULL, kpidCRC, VT_UI4}, + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidHostOS, VT_BSTR}, + { NULL, kpidUnpackVer, VT_UI4} +}; + +static STATPROPSTG kArcProps[] = +{ + { NULL, kpidBit64, VT_BOOL}, + { NULL, kpidComment, VT_BSTR}, + { NULL, kpidPhySize, VT_UI8}, + { NULL, kpidOffset, VT_UI8} +}; + +CHandler::CHandler() +{ + InitMethodProperties(); +} + +static AString BytesToString(const CByteBuffer &data) +{ + AString s; + int size = (int)data.GetCapacity(); + if (size > 0) + { + char *p = s.GetBuffer(size + 1); + memcpy(p, (const Byte *)data, size); + p[size] = '\0'; + s.ReleaseBuffer(); + } + return s; +} + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidBit64: if (m_Archive.IsZip64) prop = m_Archive.IsZip64; break; + case kpidComment: prop = MultiByteToUnicodeString(BytesToString(m_Archive.ArcInfo.Comment), CP_ACP); break; + case kpidPhySize: prop = m_Archive.ArcInfo.GetPhySize(); break; + case kpidOffset: if (m_Archive.ArcInfo.StartPosition != 0) prop = m_Archive.ArcInfo.StartPosition; break; + } + prop.Detach(value); + COM_TRY_END + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = m_Items.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + const CItemEx &item = m_Items[index]; + switch(propID) + { + case kpidPath: prop = NItemName::GetOSName2(item.GetUnicodeString(item.Name)); break; + case kpidIsDir: prop = item.IsDir(); break; + case kpidSize: prop = item.UnPackSize; break; + case kpidPackSize: prop = item.PackSize; break; + case kpidTimeType: + { + FILETIME ft; + UInt32 unixTime; + if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, ft)) + prop = (UInt32)NFileTimeType::kWindows; + else if (item.CentralExtra.GetUnixTime(NFileHeader::NUnixTime::kMTime, unixTime)) + prop = (UInt32)NFileTimeType::kUnix; + else + prop = (UInt32)NFileTimeType::kDOS; + break; + } + case kpidCTime: + { + FILETIME ft; + if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kCTime, ft)) + prop = ft; + break; + } + case kpidATime: + { + FILETIME ft; + if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kATime, ft)) + prop = ft; + break; + } + case kpidMTime: + { + FILETIME utc; + if (!item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, utc)) + { + UInt32 unixTime; + if (item.CentralExtra.GetUnixTime(NFileHeader::NUnixTime::kMTime, unixTime)) + NTime::UnixTimeToFileTime(unixTime, utc); + else + { + FILETIME localFileTime; + if (!NTime::DosTimeToFileTime(item.Time, localFileTime) || + !LocalFileTimeToFileTime(&localFileTime, &utc)) + utc.dwHighDateTime = utc.dwLowDateTime = 0; + } + } + prop = utc; + break; + } + case kpidAttrib: prop = item.GetWinAttributes(); break; + case kpidEncrypted: prop = item.IsEncrypted(); break; + case kpidComment: prop = item.GetUnicodeString(BytesToString(item.Comment)); break; + case kpidCRC: if (item.IsThereCrc()) prop = item.FileCRC; break; + case kpidMethod: + { + UInt16 methodId = item.CompressionMethod; + AString method; + if (item.IsEncrypted()) + { + if (methodId == NFileHeader::NCompressionMethod::kWzAES) + { + method = kAESMethod; + CWzAesExtraField aesField; + if (item.CentralExtra.GetWzAesField(aesField)) + { + method += '-'; + char s[32]; + ConvertUInt64ToString((aesField.Strength + 1) * 64 , s); + method += s; + method += ' '; + methodId = aesField.Method; + } + } + else + { + if (item.IsStrongEncrypted()) + { + CStrongCryptoField f; + bool finded = false; + if (item.CentralExtra.GetStrongCryptoField(f)) + { + for (int i = 0; i < sizeof(g_StrongCryptoPairs) / sizeof(g_StrongCryptoPairs[0]); i++) + { + const CStrongCryptoPair &pair = g_StrongCryptoPairs[i]; + if (f.AlgId == pair.Id) + { + method += pair.Name; + finded = true; + break; + } + } + } + if (!finded) + method += kStrongCryptoMethod; + } + else + method += kZipCryptoMethod; + method += ' '; + } + } + if (methodId < sizeof(kMethods) / sizeof(kMethods[0])) + method += kMethods[methodId]; + else switch (methodId) + { + case NFileHeader::NCompressionMethod::kLZMA: + method += kLZMAMethod; + if (item.IsLzmaEOS()) + method += ":EOS"; + break; + case NFileHeader::NCompressionMethod::kBZip2: method += kBZip2Method; break; + case NFileHeader::NCompressionMethod::kJpeg: method += kJpegMethod; break; + case NFileHeader::NCompressionMethod::kWavPack: method += kWavPackMethod; break; + case NFileHeader::NCompressionMethod::kPPMd: method += kPPMdMethod; break; + default: + { + char s[32]; + ConvertUInt64ToString(methodId, s); + method += s; + } + } + prop = method; + break; + } + case kpidHostOS: + prop = (item.MadeByVersion.HostOS < sizeof(kHostOS) / sizeof(kHostOS[0])) ? + (kHostOS[item.MadeByVersion.HostOS]) : kUnknownOS; + break; + case kpidUnpackVer: + prop = (UInt32)item.ExtractVersion.Version; + break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +class CProgressImp: public CProgressVirt +{ + CMyComPtr _callback; +public: + STDMETHOD(SetTotal)(UInt64 numFiles); + STDMETHOD(SetCompleted)(UInt64 numFiles); + CProgressImp(IArchiveOpenCallback *callback): _callback(callback) {} +}; + +STDMETHODIMP CProgressImp::SetTotal(UInt64 numFiles) +{ + if (_callback) + return _callback->SetTotal(&numFiles, NULL); + return S_OK; +} + +STDMETHODIMP CProgressImp::SetCompleted(UInt64 numFiles) +{ + if (_callback) + return _callback->SetCompleted(&numFiles, NULL); + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *inStream, + const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + try + { + Close(); + RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); + RINOK(m_Archive.Open(inStream, maxCheckStartPosition)); + CProgressImp progressImp(callback); + return m_Archive.ReadHeaders(m_Items, &progressImp); + } + catch(const CInArchiveException &) { Close(); return S_FALSE; } + catch(...) { Close(); throw; } + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + m_Items.Clear(); + m_Archive.Close(); + return S_OK; +} + +////////////////////////////////////// +// CHandler::DecompressItems + +class CLzmaDecoder: + public ICompressCoder, + public CMyUnknownImp +{ + NCompress::NLzma::CDecoder *DecoderSpec; + CMyComPtr Decoder; +public: + CLzmaDecoder(); + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + + MY_UNKNOWN_IMP +}; + +CLzmaDecoder::CLzmaDecoder() +{ + DecoderSpec = new NCompress::NLzma::CDecoder; + Decoder = DecoderSpec; +} + +HRESULT CLzmaDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + Byte buf[9]; + RINOK(ReadStream_FALSE(inStream, buf, 9)); + if (buf[2] != 5 || buf[3] != 0) + return E_NOTIMPL; + RINOK(DecoderSpec->SetDecoderProperties2(buf + 4, 5)); + return Decoder->Code(inStream, outStream, NULL, outSize, progress); +} + +struct CMethodItem +{ + UInt16 ZipMethod; + CMyComPtr Coder; +}; + +class CZipDecoder +{ + NCrypto::NZip::CDecoder *_zipCryptoDecoderSpec; + NCrypto::NZipStrong::CDecoder *_pkAesDecoderSpec; + NCrypto::NWzAes::CDecoder *_wzAesDecoderSpec; + + CMyComPtr _zipCryptoDecoder; + CMyComPtr _pkAesDecoder; + CMyComPtr _wzAesDecoder; + + CFilterCoder *filterStreamSpec; + CMyComPtr filterStream; + CMyComPtr getTextPassword; + CObjectVector methodItems; + +public: + CZipDecoder(): + _zipCryptoDecoderSpec(0), + _pkAesDecoderSpec(0), + _wzAesDecoderSpec(0), + filterStreamSpec(0) {} + + HRESULT Decode( + DECL_EXTERNAL_CODECS_LOC_VARS + CInArchive &archive, const CItemEx &item, + ISequentialOutStream *realOutStream, + IArchiveExtractCallback *extractCallback, + ICompressProgressInfo *compressProgress, + UInt32 numThreads, Int32 &res); +}; + +HRESULT CZipDecoder::Decode( + DECL_EXTERNAL_CODECS_LOC_VARS + CInArchive &archive, const CItemEx &item, + ISequentialOutStream *realOutStream, + IArchiveExtractCallback *extractCallback, + ICompressProgressInfo *compressProgress, + UInt32 numThreads, Int32 &res) +{ + res = NExtract::NOperationResult::kDataError; + CInStreamReleaser inStreamReleaser; + + bool needCRC = true; + bool wzAesMode = false; + bool pkAesMode = false; + UInt16 methodId = item.CompressionMethod; + if (item.IsEncrypted()) + { + if (item.IsStrongEncrypted()) + { + CStrongCryptoField f; + if (item.CentralExtra.GetStrongCryptoField(f)) + { + pkAesMode = true; + } + if (!pkAesMode) + { + res = NExtract::NOperationResult::kUnSupportedMethod; + return S_OK; + } + } + if (methodId == NFileHeader::NCompressionMethod::kWzAES) + { + CWzAesExtraField aesField; + if (item.CentralExtra.GetWzAesField(aesField)) + { + wzAesMode = true; + needCRC = aesField.NeedCrc(); + } + } + } + + COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; + CMyComPtr outStream = outStreamSpec; + outStreamSpec->SetStream(realOutStream); + outStreamSpec->Init(needCRC); + + UInt64 authenticationPos; + + CMyComPtr inStream; + { + UInt64 packSize = item.PackSize; + if (wzAesMode) + { + if (packSize < NCrypto::NWzAes::kMacSize) + return S_OK; + packSize -= NCrypto::NWzAes::kMacSize; + } + UInt64 dataPos = item.GetDataPosition(); + inStream.Attach(archive.CreateLimitedStream(dataPos, packSize)); + authenticationPos = dataPos + packSize; + } + + CMyComPtr cryptoFilter; + if (item.IsEncrypted()) + { + if (wzAesMode) + { + CWzAesExtraField aesField; + if (!item.CentralExtra.GetWzAesField(aesField)) + return S_OK; + methodId = aesField.Method; + if (!_wzAesDecoder) + { + _wzAesDecoderSpec = new NCrypto::NWzAes::CDecoder; + _wzAesDecoder = _wzAesDecoderSpec; + } + cryptoFilter = _wzAesDecoder; + Byte properties = aesField.Strength; + RINOK(_wzAesDecoderSpec->SetDecoderProperties2(&properties, 1)); + } + else if (pkAesMode) + { + if (!_pkAesDecoder) + { + _pkAesDecoderSpec = new NCrypto::NZipStrong::CDecoder; + _pkAesDecoder = _pkAesDecoderSpec; + } + cryptoFilter = _pkAesDecoder; + } + else + { + if (!_zipCryptoDecoder) + { + _zipCryptoDecoderSpec = new NCrypto::NZip::CDecoder; + _zipCryptoDecoder = _zipCryptoDecoderSpec; + } + cryptoFilter = _zipCryptoDecoder; + } + CMyComPtr cryptoSetPassword; + RINOK(cryptoFilter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword)); + + if (!getTextPassword) + extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword); + + if (getTextPassword) + { + CMyComBSTR password; + RINOK(getTextPassword->CryptoGetTextPassword(&password)); + AString charPassword; + if (wzAesMode || pkAesMode) + { + charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_ACP); + /* + for (int i = 0;; i++) + { + wchar_t c = password[i]; + if (c == 0) + break; + if (c >= 0x80) + { + res = NExtract::NOperationResult::kDataError; + return S_OK; + } + charPassword += (char)c; + } + */ + } + else + { + // we use OEM. WinZip/Windows probably use ANSI for some files + charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP); + } + HRESULT result = cryptoSetPassword->CryptoSetPassword( + (const Byte *)(const char *)charPassword, charPassword.Length()); + if (result != S_OK) + return S_OK; + } + else + { + RINOK(cryptoSetPassword->CryptoSetPassword(0, 0)); + } + } + + int m; + for (m = 0; m < methodItems.Size(); m++) + if (methodItems[m].ZipMethod == methodId) + break; + + if (m == methodItems.Size()) + { + CMethodItem mi; + mi.ZipMethod = methodId; + if (methodId == NFileHeader::NCompressionMethod::kStored) + mi.Coder = new NCompress::CCopyCoder; + else if (methodId == NFileHeader::NCompressionMethod::kShrunk) + mi.Coder = new NCompress::NShrink::CDecoder; + else if (methodId == NFileHeader::NCompressionMethod::kImploded) + mi.Coder = new NCompress::NImplode::NDecoder::CCoder; + else if (methodId == NFileHeader::NCompressionMethod::kLZMA) + mi.Coder = new CLzmaDecoder; + else if (methodId == NFileHeader::NCompressionMethod::kPPMd) + mi.Coder = new NCompress::NPpmdZip::CDecoder(true); + else + { + CMethodId szMethodID; + if (methodId == NFileHeader::NCompressionMethod::kBZip2) + szMethodID = kMethodId_BZip2; + else + { + if (methodId > 0xFF) + { + res = NExtract::NOperationResult::kUnSupportedMethod; + return S_OK; + } + szMethodID = kMethodId_ZipBase + (Byte)methodId; + } + + RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS szMethodID, mi.Coder, false)); + + if (mi.Coder == 0) + { + res = NExtract::NOperationResult::kUnSupportedMethod; + return S_OK; + } + } + m = methodItems.Add(mi); + } + ICompressCoder *coder = methodItems[m].Coder; + + { + CMyComPtr setDecoderProperties; + coder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties); + if (setDecoderProperties) + { + Byte properties = (Byte)item.Flags; + RINOK(setDecoderProperties->SetDecoderProperties2(&properties, 1)); + } + } + + #ifndef _7ZIP_ST + { + CMyComPtr setCoderMt; + coder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt); + if (setCoderMt) + { + RINOK(setCoderMt->SetNumberOfThreads(numThreads)); + } + } + #endif + + { + HRESULT result = S_OK; + CMyComPtr inStreamNew; + if (item.IsEncrypted()) + { + if (!filterStream) + { + filterStreamSpec = new CFilterCoder; + filterStream = filterStreamSpec; + } + filterStreamSpec->Filter = cryptoFilter; + if (wzAesMode) + { + result = _wzAesDecoderSpec->ReadHeader(inStream); + } + else if (pkAesMode) + { + result =_pkAesDecoderSpec->ReadHeader(inStream, item.FileCRC, item.UnPackSize); + if (result == S_OK) + { + bool passwOK; + result = _pkAesDecoderSpec->CheckPassword(passwOK); + if (result == S_OK && !passwOK) + result = S_FALSE; + } + } + else + { + result = _zipCryptoDecoderSpec->ReadHeader(inStream); + } + + if (result == S_OK) + { + RINOK(filterStreamSpec->SetInStream(inStream)); + inStreamReleaser.FilterCoder = filterStreamSpec; + inStreamNew = filterStream; + if (wzAesMode) + { + if (!_wzAesDecoderSpec->CheckPasswordVerifyCode()) + result = S_FALSE; + } + } + } + else + inStreamNew = inStream; + if (result == S_OK) + result = coder->Code(inStreamNew, outStream, NULL, &item.UnPackSize, compressProgress); + if (result == S_FALSE) + return S_OK; + if (result == E_NOTIMPL) + { + res = NExtract::NOperationResult::kUnSupportedMethod; + return S_OK; + } + + RINOK(result); + } + bool crcOK = true; + bool authOk = true; + if (needCRC) + crcOK = (outStreamSpec->GetCRC() == item.FileCRC); + if (wzAesMode) + { + inStream.Attach(archive.CreateLimitedStream(authenticationPos, NCrypto::NWzAes::kMacSize)); + if (_wzAesDecoderSpec->CheckMac(inStream, authOk) != S_OK) + authOk = false; + } + + res = ((crcOK && authOk) ? + NExtract::NOperationResult::kOK : + NExtract::NOperationResult::kCRCError); + return S_OK; +} + + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + CZipDecoder myDecoder; + UInt64 totalUnPacked = 0, totalPacked = 0; + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = m_Items.Size(); + if(numItems == 0) + return S_OK; + UInt32 i; + for (i = 0; i < numItems; i++) + { + const CItemEx &item = m_Items[allFilesMode ? i : indices[i]]; + totalUnPacked += item.UnPackSize; + totalPacked += item.PackSize; + } + RINOK(extractCallback->SetTotal(totalUnPacked)); + + UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0; + UInt64 currentItemUnPacked, currentItemPacked; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + for (i = 0; i < numItems; i++, currentTotalUnPacked += currentItemUnPacked, + currentTotalPacked += currentItemPacked) + { + currentItemUnPacked = 0; + currentItemPacked = 0; + + lps->InSize = currentTotalPacked; + lps->OutSize = currentTotalUnPacked; + RINOK(lps->SetCur()); + + CMyComPtr realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + CItemEx item = m_Items[index]; + if (!item.FromLocal) + { + HRESULT res = m_Archive.ReadLocalItemAfterCdItem(item); + if (res == S_FALSE) + { + if (item.IsDir() || realOutStream || testMode) + { + RINOK(extractCallback->PrepareOperation(askMode)); + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod)); + } + continue; + } + RINOK(res); + } + + if (item.IsDir() || item.IgnoreItem()) + { + // if (!testMode) + { + RINOK(extractCallback->PrepareOperation(askMode)); + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + } + continue; + } + + currentItemUnPacked = item.UnPackSize; + currentItemPacked = item.PackSize; + + if (!testMode && !realOutStream) + continue; + + RINOK(extractCallback->PrepareOperation(askMode)); + + Int32 res; + RINOK(myDecoder.Decode( + EXTERNAL_CODECS_VARS + m_Archive, item, realOutStream, extractCallback, + progress, _numThreads, res)); + realOutStream.Release(); + + RINOK(extractCallback->SetOperationResult(res)) + } + return S_OK; + COM_TRY_END +} + +IMPL_ISetCompressCodecsInfo + +}} diff --git a/CPP/7zip/Archive/Zip/ZipHandler.h b/CPP/7zip/Archive/Zip/ZipHandler.h new file mode 100755 index 0000000..48f07a0 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipHandler.h @@ -0,0 +1,101 @@ +// Zip/Handler.h + +#ifndef __ZIP_HANDLER_H +#define __ZIP_HANDLER_H + +#include "Common/DynamicBuffer.h" +#include "../../ICoder.h" +#include "../IArchive.h" + +#include "../../Common/CreateCoder.h" + +#include "ZipIn.h" +#include "ZipCompressionMode.h" + +#ifndef _7ZIP_ST +#include "../../../Windows/System.h" +#endif + +namespace NArchive { +namespace NZip { + +class CHandler: + public IInArchive, + public IOutArchive, + public ISetProperties, + PUBLIC_ISetCompressCodecsInfo + public CMyUnknownImp +{ +public: + MY_QUERYINTERFACE_BEGIN2(IInArchive) + MY_QUERYINTERFACE_ENTRY(IOutArchive) + MY_QUERYINTERFACE_ENTRY(ISetProperties) + QUERY_ENTRY_ISetCompressCodecsInfo + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + INTERFACE_IInArchive(;) + INTERFACE_IOutArchive(;) + + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties); + + DECL_ISetCompressCodecsInfo + + CHandler(); +private: + CObjectVector m_Items; + CInArchive m_Archive; + + int m_Level; + int m_MainMethod; + UInt32 m_DicSize; + UInt32 m_Algo; + UInt32 m_NumPasses; + UInt32 m_NumFastBytes; + UInt32 m_NumMatchFinderCycles; + UInt32 m_MemSize; + UInt32 m_Order; + + bool m_NumMatchFinderCyclesDefined; + + bool m_ForceAesMode; + bool m_IsAesMode; + Byte m_AesKeyMode; + + bool m_WriteNtfsTimeExtra; + bool m_ForceLocal; + bool m_ForceUtf8; + + #ifndef _7ZIP_ST + UInt32 _numThreads; + #endif + + DECL_EXTERNAL_CODECS_VARS + + void InitMethodProperties() + { + m_Level = -1; + m_MainMethod = -1; + m_Algo = + m_DicSize = + m_NumPasses = + m_NumFastBytes = + m_Order = + m_MemSize = + m_NumMatchFinderCycles = 0xFFFFFFFF; + m_NumMatchFinderCyclesDefined = false; + m_ForceAesMode = false; + m_IsAesMode = false; + m_AesKeyMode = 3; // aes-256 + m_WriteNtfsTimeExtra = true; + m_ForceLocal = false; + m_ForceUtf8 = false; + #ifndef _7ZIP_ST + _numThreads = NWindows::NSystem::GetNumberOfProcessors();; + #endif + } +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp new file mode 100755 index 0000000..ceb03cd --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp @@ -0,0 +1,531 @@ +// ZipHandlerOut.cpp + +#include "StdAfx.h" + +#include "Common/ComTry.h" +#include "Common/StringConvert.h" +#include "Common/StringToInt.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../../IPassword.h" + +#include "../../Common/OutBuffer.h" + +#include "../../Crypto/WzAes.h" + +#include "../Common/ItemNameUtils.h" +#include "../Common/ParseProperties.h" + +#include "ZipHandler.h" +#include "ZipUpdate.h" + +using namespace NWindows; +using namespace NCOM; +using namespace NTime; + +namespace NArchive { +namespace NZip { + +static const UInt32 kLzAlgoX1 = 0; +static const UInt32 kLzAlgoX5 = 1; + +static const UInt32 kDeflateNumPassesX1 = 1; +static const UInt32 kDeflateNumPassesX7 = 3; +static const UInt32 kDeflateNumPassesX9 = 10; + +static const UInt32 kDeflateNumFastBytesX1 = 32; +static const UInt32 kDeflateNumFastBytesX7 = 64; +static const UInt32 kDeflateNumFastBytesX9 = 128; + +static const wchar_t *kLzmaMatchFinderX1 = L"HC4"; +static const wchar_t *kLzmaMatchFinderX5 = L"BT4"; + +static const UInt32 kLzmaNumFastBytesX1 = 32; +static const UInt32 kLzmaNumFastBytesX7 = 64; + +static const UInt32 kLzmaDicSizeX1 = 1 << 16; +static const UInt32 kLzmaDicSizeX3 = 1 << 20; +static const UInt32 kLzmaDicSizeX5 = 1 << 24; +static const UInt32 kLzmaDicSizeX7 = 1 << 25; +static const UInt32 kLzmaDicSizeX9 = 1 << 26; + +static const UInt32 kBZip2NumPassesX1 = 1; +static const UInt32 kBZip2NumPassesX7 = 2; +static const UInt32 kBZip2NumPassesX9 = 7; + +static const UInt32 kBZip2DicSizeX1 = 100000; +static const UInt32 kBZip2DicSizeX3 = 500000; +static const UInt32 kBZip2DicSizeX5 = 900000; + +STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) +{ + *timeType = NFileTimeType::kDOS; + return S_OK; +} + +static bool IsAsciiString(const UString &s) +{ + for (int i = 0; i < s.Length(); i++) + { + wchar_t c = s[i]; + if (c < 0x20 || c > 0x7F) + return false; + } + return true; +} + +#define COM_TRY_BEGIN2 try { +#define COM_TRY_END2 } \ +catch(const CSystemException &e) { return e.ErrorCode; } \ +catch(...) { return E_OUTOFMEMORY; } + +static HRESULT GetTime(IArchiveUpdateCallback *callback, int index, PROPID propID, FILETIME &filetime) +{ + filetime.dwHighDateTime = filetime.dwLowDateTime = 0; + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(index, propID, &prop)); + if (prop.vt == VT_FILETIME) + filetime = prop.filetime; + else if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + return S_OK; +} + +STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, + IArchiveUpdateCallback *callback) +{ + COM_TRY_BEGIN2 + CObjectVector updateItems; + bool thereAreAesUpdates = false; + for (UInt32 i = 0; i < numItems; i++) + { + CUpdateItem ui; + Int32 newData; + Int32 newProperties; + UInt32 indexInArchive; + if (!callback) + return E_FAIL; + RINOK(callback->GetUpdateItemInfo(i, &newData, &newProperties, &indexInArchive)); + ui.NewProperties = IntToBool(newProperties); + ui.NewData = IntToBool(newData); + ui.IndexInArchive = indexInArchive; + ui.IndexInClient = i; + bool existInArchive = (indexInArchive != (UInt32)-1); + if (existInArchive && newData) + if (m_Items[indexInArchive].IsAesEncrypted()) + thereAreAesUpdates = true; + + if (IntToBool(newProperties)) + { + UString name; + { + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(i, kpidAttrib, &prop)); + if (prop.vt == VT_EMPTY) + ui.Attributes = 0; + else if (prop.vt != VT_UI4) + return E_INVALIDARG; + else + ui.Attributes = prop.ulVal; + } + + { + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(i, kpidPath, &prop)); + if (prop.vt == VT_EMPTY) + name.Empty(); + else if (prop.vt != VT_BSTR) + return E_INVALIDARG; + else + name = prop.bstrVal; + } + { + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(i, kpidIsDir, &prop)); + if (prop.vt == VT_EMPTY) + ui.IsDir = false; + else if (prop.vt != VT_BOOL) + return E_INVALIDARG; + else + ui.IsDir = (prop.boolVal != VARIANT_FALSE); + } + + { + CPropVariant prop; + RINOK(callback->GetProperty(i, kpidTimeType, &prop)); + if (prop.vt == VT_UI4) + ui.NtfsTimeIsDefined = (prop.ulVal == NFileTimeType::kWindows); + else + ui.NtfsTimeIsDefined = m_WriteNtfsTimeExtra; + } + RINOK(GetTime(callback, i, kpidMTime, ui.NtfsMTime)); + RINOK(GetTime(callback, i, kpidATime, ui.NtfsATime)); + RINOK(GetTime(callback, i, kpidCTime, ui.NtfsCTime)); + + { + FILETIME localFileTime = { 0, 0 }; + if (ui.NtfsMTime.dwHighDateTime != 0 || + ui.NtfsMTime.dwLowDateTime != 0) + if (!FileTimeToLocalFileTime(&ui.NtfsMTime, &localFileTime)) + return E_INVALIDARG; + FileTimeToDosTime(localFileTime, ui.Time); + } + + name = NItemName::MakeLegalName(name); + bool needSlash = ui.IsDir; + const wchar_t kSlash = L'/'; + if (!name.IsEmpty()) + { + if (name[name.Length() - 1] == kSlash) + { + if (!ui.IsDir) + return E_INVALIDARG; + needSlash = false; + } + } + if (needSlash) + name += kSlash; + + bool tryUtf8 = true; + if (m_ForceLocal || !m_ForceUtf8) + { + bool defaultCharWasUsed; + ui.Name = UnicodeStringToMultiByte(name, CP_OEMCP, '_', defaultCharWasUsed); + tryUtf8 = (!m_ForceLocal && (defaultCharWasUsed || + MultiByteToUnicodeString(ui.Name, CP_OEMCP) != name)); + } + + if (tryUtf8) + { + int i; + for (i = 0; i < name.Length() && (unsigned)name[i] < 0x80; i++); + ui.IsUtf8 = (i != name.Length()); + if (!ConvertUnicodeToUTF8(name, ui.Name)) + return E_INVALIDARG; + } + + if (ui.Name.Length() >= (1 << 16)) + return E_INVALIDARG; + + ui.IndexInClient = i; + /* + if (existInArchive) + { + const CItemEx &itemInfo = m_Items[indexInArchive]; + // ui.Commented = itemInfo.IsCommented(); + ui.Commented = false; + if (ui.Commented) + { + ui.CommentRange.Position = itemInfo.GetCommentPosition(); + ui.CommentRange.Size = itemInfo.CommentSize; + } + } + else + ui.Commented = false; + */ + } + if (IntToBool(newData)) + { + UInt64 size; + { + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(i, kpidSize, &prop)); + if (prop.vt != VT_UI8) + return E_INVALIDARG; + size = prop.uhVal.QuadPart; + } + ui.Size = size; + } + updateItems.Add(ui); + } + + CMyComPtr getTextPassword; + { + CMyComPtr udateCallBack2(callback); + udateCallBack2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword); + } + CCompressionMethodMode options; + + if (getTextPassword) + { + CMyComBSTR password; + Int32 passwordIsDefined; + RINOK(getTextPassword->CryptoGetTextPassword2(&passwordIsDefined, &password)); + options.PasswordIsDefined = IntToBool(passwordIsDefined); + if (options.PasswordIsDefined) + { + options.IsAesMode = (m_ForceAesMode ? m_IsAesMode : thereAreAesUpdates); + options.AesKeyMode = m_AesKeyMode; + + if (!IsAsciiString((const wchar_t *)password)) + return E_INVALIDARG; + if (options.IsAesMode) + { + if (options.Password.Length() > NCrypto::NWzAes::kPasswordSizeMax) + return E_INVALIDARG; + } + options.Password = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP); + } + } + else + options.PasswordIsDefined = false; + + int level = m_Level; + if (level < 0) + level = 5; + + Byte mainMethod; + if (m_MainMethod < 0) + mainMethod = (Byte)(((level == 0) ? + NFileHeader::NCompressionMethod::kStored : + NFileHeader::NCompressionMethod::kDeflated)); + else + mainMethod = (Byte)m_MainMethod; + options.MethodSequence.Add(mainMethod); + if (mainMethod != NFileHeader::NCompressionMethod::kStored) + options.MethodSequence.Add(NFileHeader::NCompressionMethod::kStored); + bool isDeflate = (mainMethod == NFileHeader::NCompressionMethod::kDeflated) || + (mainMethod == NFileHeader::NCompressionMethod::kDeflated64); + bool isLZMA = (mainMethod == NFileHeader::NCompressionMethod::kLZMA); + bool isLz = (isLZMA || isDeflate); + options.NumPasses = m_NumPasses; + options.DicSize = m_DicSize; + options.NumFastBytes = m_NumFastBytes; + options.NumMatchFinderCycles = m_NumMatchFinderCycles; + options.NumMatchFinderCyclesDefined = m_NumMatchFinderCyclesDefined; + options.Algo = m_Algo; + options.MemSize = m_MemSize; + options.Order = m_Order; + #ifndef _7ZIP_ST + options.NumThreads = _numThreads; + #endif + if (isLz) + { + if (isDeflate) + { + if (options.NumPasses == 0xFFFFFFFF) + options.NumPasses = (level >= 9 ? kDeflateNumPassesX9 : + (level >= 7 ? kDeflateNumPassesX7 : + kDeflateNumPassesX1)); + if (options.NumFastBytes == 0xFFFFFFFF) + options.NumFastBytes = (level >= 9 ? kDeflateNumFastBytesX9 : + (level >= 7 ? kDeflateNumFastBytesX7 : + kDeflateNumFastBytesX1)); + } + else if (isLZMA) + { + if (options.DicSize == 0xFFFFFFFF) + options.DicSize = + (level >= 9 ? kLzmaDicSizeX9 : + (level >= 7 ? kLzmaDicSizeX7 : + (level >= 5 ? kLzmaDicSizeX5 : + (level >= 3 ? kLzmaDicSizeX3 : + kLzmaDicSizeX1)))); + + if (options.NumFastBytes == 0xFFFFFFFF) + options.NumFastBytes = (level >= 7 ? kLzmaNumFastBytesX7 : + kLzmaNumFastBytesX1); + + options.MatchFinder = + (level >= 5 ? kLzmaMatchFinderX5 : + kLzmaMatchFinderX1); + } + + if (options.Algo == 0xFFFFFFFF) + options.Algo = (level >= 5 ? kLzAlgoX5 : + kLzAlgoX1); + } + if (mainMethod == NFileHeader::NCompressionMethod::kBZip2) + { + if (options.NumPasses == 0xFFFFFFFF) + options.NumPasses = (level >= 9 ? kBZip2NumPassesX9 : + (level >= 7 ? kBZip2NumPassesX7 : + kBZip2NumPassesX1)); + if (options.DicSize == 0xFFFFFFFF) + options.DicSize = (level >= 5 ? kBZip2DicSizeX5 : + (level >= 3 ? kBZip2DicSizeX3 : + kBZip2DicSizeX1)); + } + if (mainMethod == NFileHeader::NCompressionMethod::kPPMd) + { + int level2 = level; + if (level2 < 1) level2 = 1; + if (level2 > 9) level2 = 9; + + if (options.MemSize == 0xFFFFFFFF) + options.MemSize = (1 << (19 + (level2 > 8 ? 8 : level2))); + + if (options.Order == 0xFFFFFFFF) + options.Order = 3 + level2; + + if (options.Algo == 0xFFFFFFFF) + options.Algo = (level2 >= 7 ? 1 : 0); + } + + return Update( + EXTERNAL_CODECS_VARS + m_Items, updateItems, outStream, + m_Archive.IsOpen() ? &m_Archive : NULL, &options, callback); + COM_TRY_END2 +} + +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) +{ + #ifndef _7ZIP_ST + const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); + _numThreads = numProcessors; + #endif + InitMethodProperties(); + for (int i = 0; i < numProperties; i++) + { + UString name = UString(names[i]); + name.MakeUpper(); + if (name.IsEmpty()) + return E_INVALIDARG; + + const PROPVARIANT &prop = values[i]; + + if (name[0] == L'X') + { + UInt32 level = 9; + RINOK(ParsePropValue(name.Mid(1), prop, level)); + m_Level = level; + continue; + } + else if (name == L"M") + { + if (prop.vt == VT_BSTR) + { + UString m = prop.bstrVal; + m.MakeUpper(); + if (m == L"COPY") m_MainMethod = NFileHeader::NCompressionMethod::kStored; + else if (m == L"DEFLATE") m_MainMethod = NFileHeader::NCompressionMethod::kDeflated; + else if (m == L"DEFLATE64") m_MainMethod = NFileHeader::NCompressionMethod::kDeflated64; + else if (m == L"BZIP2") m_MainMethod = NFileHeader::NCompressionMethod::kBZip2; + else if (m == L"LZMA") m_MainMethod = NFileHeader::NCompressionMethod::kLZMA; + else if (m == L"PPMD") m_MainMethod = NFileHeader::NCompressionMethod::kPPMd; + else return E_INVALIDARG; + } + else if (prop.vt == VT_UI4) + { + switch(prop.ulVal) + { + case NFileHeader::NCompressionMethod::kStored: + case NFileHeader::NCompressionMethod::kDeflated: + case NFileHeader::NCompressionMethod::kDeflated64: + case NFileHeader::NCompressionMethod::kBZip2: + case NFileHeader::NCompressionMethod::kLZMA: + m_MainMethod = (Byte)prop.ulVal; + break; + default: + return E_INVALIDARG; + } + } + else + return E_INVALIDARG; + } + else if (name.Left(2) == L"EM") + { + if (prop.vt == VT_BSTR) + { + UString valueString = prop.bstrVal; + valueString.MakeUpper(); + if (valueString.Left(3) == L"AES") + { + valueString = valueString.Mid(3); + if (valueString == L"128") + m_AesKeyMode = 1; + else if (valueString == L"192") + m_AesKeyMode = 2; + else if (valueString == L"256" || valueString.IsEmpty()) + m_AesKeyMode = 3; + else + return E_INVALIDARG; + m_IsAesMode = true; + m_ForceAesMode = true; + } + else if (valueString == L"ZIPCRYPTO") + { + m_IsAesMode = false; + m_ForceAesMode = true; + } + else + return E_INVALIDARG; + } + else + return E_INVALIDARG; + } + else if (name[0] == L'D') + { + UInt32 dicSize = kBZip2DicSizeX5; + RINOK(ParsePropDictionaryValue(name.Mid(1), prop, dicSize)); + m_DicSize = dicSize; + } + else if (name.Left(3) == L"MEM") + { + UInt32 memSize = 1 << 24; + RINOK(ParsePropDictionaryValue(name.Mid(3), prop, memSize)); + m_MemSize = memSize; + } + else if (name[0] == L'O') + { + UInt32 order = 8; + RINOK(ParsePropValue(name.Mid(1), prop, order)); + m_Order = order; + } + else if (name.Left(4) == L"PASS") + { + UInt32 num = kDeflateNumPassesX9; + RINOK(ParsePropValue(name.Mid(4), prop, num)); + m_NumPasses = num; + } + else if (name.Left(2) == L"FB") + { + UInt32 num = kDeflateNumFastBytesX9; + RINOK(ParsePropValue(name.Mid(2), prop, num)); + m_NumFastBytes = num; + } + else if (name.Left(2) == L"MC") + { + UInt32 num = 0xFFFFFFFF; + RINOK(ParsePropValue(name.Mid(2), prop, num)); + m_NumMatchFinderCycles = num; + m_NumMatchFinderCyclesDefined = true; + } + else if (name.Left(2) == L"MT") + { + #ifndef _7ZIP_ST + RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _numThreads)); + #endif + } + else if (name.Left(1) == L"A") + { + UInt32 num = kLzAlgoX5; + RINOK(ParsePropValue(name.Mid(1), prop, num)); + m_Algo = num; + } + else if (name.CompareNoCase(L"TC") == 0) + { + RINOK(SetBoolProperty(m_WriteNtfsTimeExtra, prop)); + } + else if (name.CompareNoCase(L"CL") == 0) + { + RINOK(SetBoolProperty(m_ForceLocal, prop)); + if (m_ForceLocal) + m_ForceUtf8 = false; + } + else if (name.CompareNoCase(L"CU") == 0) + { + RINOK(SetBoolProperty(m_ForceUtf8, prop)); + if (m_ForceUtf8) + m_ForceLocal = false; + } + else + return E_INVALIDARG; + } + return S_OK; +} + +}} diff --git a/CPP/7zip/Archive/Zip/ZipHeader.cpp b/CPP/7zip/Archive/Zip/ZipHeader.cpp new file mode 100755 index 0000000..27fe244 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipHeader.cpp @@ -0,0 +1,36 @@ +// Archive/Zip/Header.h + +#include "StdAfx.h" + +#include "ZipHeader.h" + +namespace NArchive { +namespace NZip { + +namespace NSignature +{ + UInt32 kLocalFileHeader = 0x04034B50 + 1; + UInt32 kDataDescriptor = 0x08074B50 + 1; + UInt32 kCentralFileHeader = 0x02014B50 + 1; + UInt32 kEndOfCentralDir = 0x06054B50 + 1; + UInt32 kZip64EndOfCentralDir = 0x06064B50 + 1; + UInt32 kZip64EndOfCentralDirLocator = 0x07064B50 + 1; + + class CMarkersInitializer + { + public: + CMarkersInitializer() + { + kLocalFileHeader--; + kDataDescriptor--; + kCentralFileHeader--; + kEndOfCentralDir--; + kZip64EndOfCentralDir--; + kZip64EndOfCentralDirLocator--; + } + }; + static CMarkersInitializer g_MarkerInitializer; +} + +}} + diff --git a/CPP/7zip/Archive/Zip/ZipHeader.h b/CPP/7zip/Archive/Zip/ZipHeader.h new file mode 100755 index 0000000..4989daf --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipHeader.h @@ -0,0 +1,284 @@ +// Archive/Zip/Header.h + +#ifndef __ARCHIVE_ZIP_HEADER_H +#define __ARCHIVE_ZIP_HEADER_H + +#include "Common/Types.h" + +namespace NArchive { +namespace NZip { + +namespace NSignature +{ + extern UInt32 kLocalFileHeader; + extern UInt32 kDataDescriptor; + extern UInt32 kCentralFileHeader; + extern UInt32 kEndOfCentralDir; + extern UInt32 kZip64EndOfCentralDir; + extern UInt32 kZip64EndOfCentralDirLocator; + + static const UInt32 kMarkerSize = 4; +} + +const UInt32 kEcdSize = 22; +const UInt32 kZip64EcdSize = 44; +const UInt32 kZip64EcdLocatorSize = 20; +/* +struct CEndOfCentralDirectoryRecord +{ + UInt16 ThisDiskNumber; + UInt16 StartCentralDirectoryDiskNumber; + UInt16 NumEntriesInCentaralDirectoryOnThisDisk; + UInt16 NumEntriesInCentaralDirectory; + UInt32 CentralDirectorySize; + UInt32 CentralDirectoryStartOffset; + UInt16 CommentSize; +}; + +struct CEndOfCentralDirectoryRecordFull +{ + UInt32 Signature; + CEndOfCentralDirectoryRecord Header; +}; +*/ + +namespace NFileHeader +{ + /* + struct CVersion + { + Byte Version; + Byte HostOS; + }; + */ + + namespace NCompressionMethod + { + enum EType + { + kStored = 0, + kShrunk = 1, + kReduced1 = 2, + kReduced2 = 3, + kReduced3 = 4, + kReduced4 = 5, + kImploded = 6, + kReservedTokenizing = 7, // reserved for tokenizing + kDeflated = 8, + kDeflated64 = 9, + kPKImploding = 10, + + kBZip2 = 12, + kLZMA = 14, + kTerse = 18, + kLz77 = 19, + kJpeg = 0x60, + kWavPack = 0x61, + kPPMd = 0x62, + kWzAES = 0x63 + }; + const int kNumCompressionMethods = 11; + const Byte kMadeByProgramVersion = 63; + + const Byte kExtractVersion_Default = 10; + const Byte kExtractVersion_Dir = 20; + const Byte kExtractVersion_ZipCrypto = 20; + const Byte kExtractVersion_Deflate = 20; + const Byte kExtractVersion_Deflate64 = 21; + const Byte kExtractVersion_Zip64 = 45; + const Byte kExtractVersion_BZip2 = 46; + const Byte kExtractVersion_Aes = 51; + const Byte kExtractVersion_LZMA = 63; + const Byte kExtractVersion_PPMd = 63; + + // const Byte kSupportedVersion = 20; + } + + namespace NExtraID + { + enum + { + kZip64 = 0x01, + kNTFS = 0x0A, + kStrongEncrypt = 0x17, + kUnixTime = 0x5455, + kWzAES = 0x9901 + }; + } + + namespace NNtfsExtra + { + const UInt16 kTagTime = 1; + enum + { + kMTime = 0, + kATime, + kCTime + }; + } + + namespace NUnixTime + { + enum + { + kMTime = 0, + kATime, + kCTime + }; + } + + const UInt32 kLocalBlockSize = 26; + /* + struct CLocalBlock + { + CVersion ExtractVersion; + + UInt16 Flags; + UInt16 CompressionMethod; + UInt32 Time; + UInt32 FileCRC; + UInt32 PackSize; + UInt32 UnPackSize; + UInt16 NameSize; + UInt16 ExtraSize; + }; + */ + + const UInt32 kDataDescriptorSize = 16; + // const UInt32 kDataDescriptor64Size = 16 + 8; + /* + struct CDataDescriptor + { + UInt32 Signature; + UInt32 FileCRC; + UInt32 PackSize; + UInt32 UnPackSize; + }; + + struct CLocalBlockFull + { + UInt32 Signature; + CLocalBlock Header; + }; + */ + + const UInt32 kCentralBlockSize = 42; + /* + struct CBlock + { + CVersion MadeByVersion; + CVersion ExtractVersion; + UInt16 Flags; + UInt16 CompressionMethod; + UInt32 Time; + UInt32 FileCRC; + UInt32 PackSize; + UInt32 UnPackSize; + UInt16 NameSize; + UInt16 ExtraSize; + UInt16 CommentSize; + UInt16 DiskNumberStart; + UInt16 InternalAttributes; + UInt32 ExternalAttributes; + UInt32 LocalHeaderOffset; + }; + + struct CBlockFull + { + UInt32 Signature; + CBlock Header; + }; + */ + + namespace NFlags + { + const int kEncrypted = 1 << 0; + const int kLzmaEOS = 1 << 1; + const int kDescriptorUsedMask = 1 << 3; + const int kStrongEncrypted = 1 << 6; + const int kUtf8 = 1 << 11; + + const int kImplodeDictionarySizeMask = 1 << 1; + const int kImplodeLiteralsOnMask = 1 << 2; + + const int kDeflateTypeBitStart = 1; + const int kNumDeflateTypeBits = 2; + const int kNumDeflateTypes = (1 << kNumDeflateTypeBits); + const int kDeflateTypeMask = (1 << kNumDeflateTypeBits) - 1; + } + + namespace NHostOS + { + enum EEnum + { + kFAT = 0, + kAMIGA = 1, + kVMS = 2, // VAX/VMS + kUnix = 3, + kVM_CMS = 4, + kAtari = 5, // what if it's a minix filesystem? [cjh] + kHPFS = 6, // filesystem used by OS/2 (and NT 3.x) + kMac = 7, + kZ_System = 8, + kCPM = 9, + kTOPS20 = 10, // pkzip 2.50 NTFS + kNTFS = 11, // filesystem used by Windows NT + kQDOS = 12, // SMS/QDOS + kAcorn = 13, // Archimedes Acorn RISC OS + kVFAT = 14, // filesystem used by Windows 95, NT + kMVS = 15, + kBeOS = 16, // hybrid POSIX/database filesystem + kTandem = 17, + kOS400 = 18, + kOSX = 19 + }; + } + namespace NUnixAttribute + { + const UInt32 kIFMT = 0170000; /* Unix file type mask */ + + const UInt32 kIFDIR = 0040000; /* Unix directory */ + const UInt32 kIFREG = 0100000; /* Unix regular file */ + const UInt32 kIFSOCK = 0140000; /* Unix socket (BSD, not SysV or Amiga) */ + const UInt32 kIFLNK = 0120000; /* Unix symbolic link (not SysV, Amiga) */ + const UInt32 kIFBLK = 0060000; /* Unix block special (not Amiga) */ + const UInt32 kIFCHR = 0020000; /* Unix character special (not Amiga) */ + const UInt32 kIFIFO = 0010000; /* Unix fifo (BCC, not MSC or Amiga) */ + + const UInt32 kISUID = 04000; /* Unix set user id on execution */ + const UInt32 kISGID = 02000; /* Unix set group id on execution */ + const UInt32 kISVTX = 01000; /* Unix directory permissions control */ + const UInt32 kENFMT = kISGID; /* Unix record locking enforcement flag */ + const UInt32 kIRWXU = 00700; /* Unix read, write, execute: owner */ + const UInt32 kIRUSR = 00400; /* Unix read permission: owner */ + const UInt32 kIWUSR = 00200; /* Unix write permission: owner */ + const UInt32 kIXUSR = 00100; /* Unix execute permission: owner */ + const UInt32 kIRWXG = 00070; /* Unix read, write, execute: group */ + const UInt32 kIRGRP = 00040; /* Unix read permission: group */ + const UInt32 kIWGRP = 00020; /* Unix write permission: group */ + const UInt32 kIXGRP = 00010; /* Unix execute permission: group */ + const UInt32 kIRWXO = 00007; /* Unix read, write, execute: other */ + const UInt32 kIROTH = 00004; /* Unix read permission: other */ + const UInt32 kIWOTH = 00002; /* Unix write permission: other */ + const UInt32 kIXOTH = 00001; /* Unix execute permission: other */ + } + + namespace NAmigaAttribute + { + const UInt32 kIFMT = 06000; /* Amiga file type mask */ + const UInt32 kIFDIR = 04000; /* Amiga directory */ + const UInt32 kIFREG = 02000; /* Amiga regular file */ + const UInt32 kIHIDDEN = 00200; /* to be supported in AmigaDOS 3.x */ + const UInt32 kISCRIPT = 00100; /* executable script (text command file) */ + const UInt32 kIPURE = 00040; /* allow loading into resident memory */ + const UInt32 kIARCHIVE = 00020; /* not modified since bit was last set */ + const UInt32 kIREAD = 00010; /* can be opened for reading */ + const UInt32 kIWRITE = 00004; /* can be opened for writing */ + const UInt32 kIEXECUTE = 00002; /* executable image, a loadable runfile */ + const UInt32 kIDELETE = 00001; /* can be deleted */ + } +} + +}} + +#endif diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp new file mode 100755 index 0000000..639efd0 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipIn.cpp @@ -0,0 +1,893 @@ +// Archive/ZipIn.cpp + +#include "StdAfx.h" + +#include "../../../../C/CpuArch.h" + +#include "Common/DynamicBuffer.h" + +#include "../../Common/LimitedStreams.h" +#include "../../Common/StreamUtils.h" + +#include "ZipIn.h" + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) +#define Get64(p) GetUi64(p) + +namespace NArchive { +namespace NZip { + +HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) +{ + _inBufMode = false; + Close(); + RINOK(stream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition)); + m_Position = m_StreamStartPosition; + RINOK(FindAndReadMarker(stream, searchHeaderSizeLimit)); + RINOK(stream->Seek(m_Position, STREAM_SEEK_SET, NULL)); + m_Stream = stream; + return S_OK; +} + +void CInArchive::Close() +{ + _inBuffer.ReleaseStream(); + m_Stream.Release(); +} + +HRESULT CInArchive::Seek(UInt64 offset) +{ + return m_Stream->Seek(offset, STREAM_SEEK_SET, NULL); +} + +////////////////////////////////////// +// Markers + +static inline bool TestMarkerCandidate(const Byte *p, UInt32 &value) +{ + value = Get32(p); + return + (value == NSignature::kLocalFileHeader) || + (value == NSignature::kEndOfCentralDir); +} + +static const UInt32 kNumMarkerAddtionalBytes = 2; +static inline bool TestMarkerCandidate2(const Byte *p, UInt32 &value) +{ + value = Get32(p); + if (value == NSignature::kEndOfCentralDir) + return (Get16(p + 4) == 0); + return (value == NSignature::kLocalFileHeader && p[4] < 128); +} + +HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit) +{ + ArcInfo.Clear(); + m_Position = m_StreamStartPosition; + + Byte marker[NSignature::kMarkerSize]; + RINOK(ReadStream_FALSE(stream, marker, NSignature::kMarkerSize)); + m_Position += NSignature::kMarkerSize; + if (TestMarkerCandidate(marker, m_Signature)) + return S_OK; + + CByteDynamicBuffer dynamicBuffer; + const UInt32 kSearchMarkerBufferSize = 0x10000; + dynamicBuffer.EnsureCapacity(kSearchMarkerBufferSize); + Byte *buffer = dynamicBuffer; + UInt32 numBytesPrev = NSignature::kMarkerSize - 1; + memcpy(buffer, marker + 1, numBytesPrev); + UInt64 curTestPos = m_StreamStartPosition + 1; + for (;;) + { + if (searchHeaderSizeLimit != NULL) + if (curTestPos - m_StreamStartPosition > *searchHeaderSizeLimit) + break; + size_t numReadBytes = kSearchMarkerBufferSize - numBytesPrev; + RINOK(ReadStream(stream, buffer + numBytesPrev, &numReadBytes)); + m_Position += numReadBytes; + UInt32 numBytesInBuffer = numBytesPrev + (UInt32)numReadBytes; + const UInt32 kMarker2Size = NSignature::kMarkerSize + kNumMarkerAddtionalBytes; + if (numBytesInBuffer < kMarker2Size) + break; + UInt32 numTests = numBytesInBuffer - kMarker2Size + 1; + for (UInt32 pos = 0; pos < numTests; pos++) + { + if (buffer[pos] != 0x50) + continue; + if (TestMarkerCandidate2(buffer + pos, m_Signature)) + { + curTestPos += pos; + ArcInfo.StartPosition = curTestPos; + m_Position = curTestPos + NSignature::kMarkerSize; + return S_OK; + } + } + curTestPos += numTests; + numBytesPrev = numBytesInBuffer - numTests; + memmove(buffer, buffer + numTests, numBytesPrev); + } + return S_FALSE; +} + +HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize) +{ + size_t realProcessedSize = size; + HRESULT result = S_OK; + if (_inBufMode) + { + try { realProcessedSize = _inBuffer.ReadBytes((Byte *)data, size); } + catch (const CInBufferException &e) { return e.ErrorCode; } + } + else + result = ReadStream(m_Stream, data, &realProcessedSize); + if (processedSize != NULL) + *processedSize = (UInt32)realProcessedSize; + m_Position += realProcessedSize; + return result; +} + +void CInArchive::Skip(UInt64 num) +{ + for (UInt64 i = 0; i < num; i++) + ReadByte(); +} + +void CInArchive::IncreaseRealPosition(UInt64 addValue) +{ + if (m_Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position) != S_OK) + throw CInArchiveException(CInArchiveException::kSeekStreamError); +} + +bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size) +{ + UInt32 realProcessedSize; + if (ReadBytes(data, size, &realProcessedSize) != S_OK) + throw CInArchiveException(CInArchiveException::kReadStreamError); + return (realProcessedSize == size); +} + +void CInArchive::SafeReadBytes(void *data, UInt32 size) +{ + if (!ReadBytesAndTestSize(data, size)) + throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive); +} + +void CInArchive::ReadBuffer(CByteBuffer &buffer, UInt32 size) +{ + buffer.SetCapacity(size); + if (size > 0) + SafeReadBytes(buffer, size); +} + +Byte CInArchive::ReadByte() +{ + Byte b; + SafeReadBytes(&b, 1); + return b; +} + +UInt16 CInArchive::ReadUInt16() +{ + Byte buf[2]; + SafeReadBytes(buf, 2); + return Get16(buf); +} + +UInt32 CInArchive::ReadUInt32() +{ + Byte buf[4]; + SafeReadBytes(buf, 4); + return Get32(buf); +} + +UInt64 CInArchive::ReadUInt64() +{ + Byte buf[8]; + SafeReadBytes(buf, 8); + return Get64(buf); +} + +bool CInArchive::ReadUInt32(UInt32 &value) +{ + Byte buf[4]; + if (!ReadBytesAndTestSize(buf, 4)) + return false; + value = Get32(buf); + return true; +} + +void CInArchive::ReadFileName(UInt32 nameSize, AString &dest) +{ + if (nameSize == 0) + dest.Empty(); + char *p = dest.GetBuffer((int)nameSize); + SafeReadBytes(p, nameSize); + p[nameSize] = 0; + dest.ReleaseBuffer(); +} + +void CInArchive::ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock, + UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber) +{ + extraBlock.Clear(); + UInt32 remain = extraSize; + while(remain >= 4) + { + CExtraSubBlock subBlock; + subBlock.ID = ReadUInt16(); + UInt32 dataSize = ReadUInt16(); + remain -= 4; + if (dataSize > remain) // it's bug + dataSize = remain; + if (subBlock.ID == NFileHeader::NExtraID::kZip64) + { + if (unpackSize == 0xFFFFFFFF) + { + if (dataSize < 8) + break; + unpackSize = ReadUInt64(); + remain -= 8; + dataSize -= 8; + } + if (packSize == 0xFFFFFFFF) + { + if (dataSize < 8) + break; + packSize = ReadUInt64(); + remain -= 8; + dataSize -= 8; + } + if (localHeaderOffset == 0xFFFFFFFF) + { + if (dataSize < 8) + break; + localHeaderOffset = ReadUInt64(); + remain -= 8; + dataSize -= 8; + } + if (diskStartNumber == 0xFFFF) + { + if (dataSize < 4) + break; + diskStartNumber = ReadUInt32(); + remain -= 4; + dataSize -= 4; + } + for (UInt32 i = 0; i < dataSize; i++) + ReadByte(); + } + else + { + ReadBuffer(subBlock.Data, dataSize); + extraBlock.SubBlocks.Add(subBlock); + } + remain -= dataSize; + } + Skip(remain); +} + +HRESULT CInArchive::ReadLocalItem(CItemEx &item) +{ + const int kBufSize = 26; + Byte p[kBufSize]; + SafeReadBytes(p, kBufSize); + + item.ExtractVersion.Version = p[0]; + item.ExtractVersion.HostOS = p[1]; + item.Flags = Get16(p + 2); + item.CompressionMethod = Get16(p + 4); + item.Time = Get32(p + 6); + item.FileCRC = Get32(p + 10); + item.PackSize = Get32(p + 14); + item.UnPackSize = Get32(p + 18); + UInt32 fileNameSize = Get16(p + 22); + item.LocalExtraSize = Get16(p + 24); + ReadFileName(fileNameSize, item.Name); + item.FileHeaderWithNameSize = 4 + NFileHeader::kLocalBlockSize + fileNameSize; + if (item.LocalExtraSize > 0) + { + UInt64 localHeaderOffset = 0; + UInt32 diskStartNumber = 0; + ReadExtra(item.LocalExtraSize, item.LocalExtra, item.UnPackSize, item.PackSize, + localHeaderOffset, diskStartNumber); + } + /* + if (item.IsDir()) + item.UnPackSize = 0; // check It + */ + return S_OK; +} + +static bool FlagsAreSame(CItem &i1, CItem &i2) +{ + if (i1.CompressionMethod != i2.CompressionMethod) + return false; + // i1.Time + + if (i1.Flags == i2.Flags) + return true; + UInt32 mask = 0xFFFF; + switch(i1.CompressionMethod) + { + case NFileHeader::NCompressionMethod::kDeflated: + mask = 0x7FF9; + break; + default: + if (i1.CompressionMethod <= NFileHeader::NCompressionMethod::kImploded) + mask = 0x7FFF; + } + return ((i1.Flags & mask) == (i2.Flags & mask)); +} + +HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item) +{ + if (item.FromLocal) + return S_OK; + try + { + RINOK(Seek(ArcInfo.Base + item.LocalHeaderPosition)); + CItemEx localItem; + if (ReadUInt32() != NSignature::kLocalFileHeader) + return S_FALSE; + RINOK(ReadLocalItem(localItem)); + if (!FlagsAreSame(item, localItem)) + return S_FALSE; + + if ((!localItem.HasDescriptor() && + ( + item.FileCRC != localItem.FileCRC || + item.PackSize != localItem.PackSize || + item.UnPackSize != localItem.UnPackSize + ) + ) || + item.Name.Length() != localItem.Name.Length() + ) + return S_FALSE; + item.FileHeaderWithNameSize = localItem.FileHeaderWithNameSize; + item.LocalExtraSize = localItem.LocalExtraSize; + item.LocalExtra = localItem.LocalExtra; + item.FromLocal = true; + } + catch(...) { return S_FALSE; } + return S_OK; +} + +HRESULT CInArchive::ReadLocalItemDescriptor(CItemEx &item) +{ + if (item.HasDescriptor()) + { + const int kBufferSize = (1 << 12); + Byte buffer[kBufferSize]; + + UInt32 numBytesInBuffer = 0; + UInt32 packedSize = 0; + + bool descriptorWasFound = false; + for (;;) + { + UInt32 processedSize; + RINOK(ReadBytes(buffer + numBytesInBuffer, kBufferSize - numBytesInBuffer, &processedSize)); + numBytesInBuffer += processedSize; + if (numBytesInBuffer < NFileHeader::kDataDescriptorSize) + return S_FALSE; + UInt32 i; + for (i = 0; i <= numBytesInBuffer - NFileHeader::kDataDescriptorSize; i++) + { + // descriptorSignature field is Info-ZIP's extension + // to Zip specification. + UInt32 descriptorSignature = Get32(buffer + i); + + // !!!! It must be fixed for Zip64 archives + UInt32 descriptorPackSize = Get32(buffer + i + 8); + if (descriptorSignature== NSignature::kDataDescriptor && descriptorPackSize == packedSize + i) + { + descriptorWasFound = true; + item.FileCRC = Get32(buffer + i + 4); + item.PackSize = descriptorPackSize; + item.UnPackSize = Get32(buffer + i + 12); + IncreaseRealPosition(Int64(Int32(0 - (numBytesInBuffer - i - NFileHeader::kDataDescriptorSize)))); + break; + } + } + if (descriptorWasFound) + break; + packedSize += i; + int j; + for (j = 0; i < numBytesInBuffer; i++, j++) + buffer[j] = buffer[i]; + numBytesInBuffer = j; + } + } + else + IncreaseRealPosition(item.PackSize); + return S_OK; +} + +HRESULT CInArchive::ReadLocalItemAfterCdItemFull(CItemEx &item) +{ + if (item.FromLocal) + return S_OK; + try + { + RINOK(ReadLocalItemAfterCdItem(item)); + if (item.HasDescriptor()) + { + RINOK(Seek(ArcInfo.Base + item.GetDataPosition() + item.PackSize)); + if (ReadUInt32() != NSignature::kDataDescriptor) + return S_FALSE; + UInt32 crc = ReadUInt32(); + UInt64 packSize, unpackSize; + + /* + if (IsZip64) + { + packSize = ReadUInt64(); + unpackSize = ReadUInt64(); + } + else + */ + { + packSize = ReadUInt32(); + unpackSize = ReadUInt32(); + } + + if (crc != item.FileCRC || item.PackSize != packSize || item.UnPackSize != unpackSize) + return S_FALSE; + } + } + catch(...) { return S_FALSE; } + return S_OK; +} + +HRESULT CInArchive::ReadCdItem(CItemEx &item) +{ + item.FromCentral = true; + const int kBufSize = 42; + Byte p[kBufSize]; + SafeReadBytes(p, kBufSize); + item.MadeByVersion.Version = p[0]; + item.MadeByVersion.HostOS = p[1]; + item.ExtractVersion.Version = p[2]; + item.ExtractVersion.HostOS = p[3]; + item.Flags = Get16(p + 4); + item.CompressionMethod = Get16(p + 6); + item.Time = Get32(p + 8); + item.FileCRC = Get32(p + 12); + item.PackSize = Get32(p + 16); + item.UnPackSize = Get32(p + 20); + UInt16 headerNameSize = Get16(p + 24); + UInt16 headerExtraSize = Get16(p + 26); + UInt16 headerCommentSize = Get16(p + 28); + UInt32 headerDiskNumberStart = Get16(p + 30); + item.InternalAttributes = Get16(p + 32); + item.ExternalAttributes = Get32(p + 34); + item.LocalHeaderPosition = Get32(p + 38); + ReadFileName(headerNameSize, item.Name); + + if (headerExtraSize > 0) + { + ReadExtra(headerExtraSize, item.CentralExtra, item.UnPackSize, item.PackSize, + item.LocalHeaderPosition, headerDiskNumberStart); + } + + if (headerDiskNumberStart != 0) + throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported); + + // May be these strings must be deleted + /* + if (item.IsDir()) + item.UnPackSize = 0; + */ + + ReadBuffer(item.Comment, headerCommentSize); + return S_OK; +} + +HRESULT CInArchive::TryEcd64(UInt64 offset, CCdInfo &cdInfo) +{ + RINOK(Seek(offset)); + const UInt32 kEcd64Size = 56; + Byte buf[kEcd64Size]; + if (!ReadBytesAndTestSize(buf, kEcd64Size)) + return S_FALSE; + if (Get32(buf) != NSignature::kZip64EndOfCentralDir) + return S_FALSE; + // cdInfo.NumEntries = Get64(buf + 24); + cdInfo.Size = Get64(buf + 40); + cdInfo.Offset = Get64(buf + 48); + return S_OK; +} + +HRESULT CInArchive::FindCd(CCdInfo &cdInfo) +{ + UInt64 endPosition; + RINOK(m_Stream->Seek(0, STREAM_SEEK_END, &endPosition)); + const UInt32 kBufSizeMax = (1 << 16) + kEcdSize + kZip64EcdLocatorSize; + CByteBuffer byteBuffer; + byteBuffer.SetCapacity(kBufSizeMax); + Byte *buf = byteBuffer; + UInt32 bufSize = (endPosition < kBufSizeMax) ? (UInt32)endPosition : kBufSizeMax; + if (bufSize < kEcdSize) + return S_FALSE; + UInt64 startPosition = endPosition - bufSize; + RINOK(m_Stream->Seek(startPosition, STREAM_SEEK_SET, &m_Position)); + if (m_Position != startPosition) + return S_FALSE; + if (!ReadBytesAndTestSize(buf, bufSize)) + return S_FALSE; + for (int i = (int)(bufSize - kEcdSize); i >= 0; i--) + { + if (Get32(buf + i) == NSignature::kEndOfCentralDir) + { + if (i >= kZip64EcdLocatorSize) + { + const Byte *locator = buf + i - kZip64EcdLocatorSize; + if (Get32(locator) == NSignature::kZip64EndOfCentralDirLocator) + { + UInt64 ecd64Offset = Get64(locator + 8); + if (TryEcd64(ecd64Offset, cdInfo) == S_OK) + return S_OK; + if (TryEcd64(ArcInfo.StartPosition + ecd64Offset, cdInfo) == S_OK) + { + ArcInfo.Base = ArcInfo.StartPosition; + return S_OK; + } + } + } + if (Get32(buf + i + 4) == 0) + { + // cdInfo.NumEntries = GetUInt16(buf + i + 10); + cdInfo.Size = Get32(buf + i + 12); + cdInfo.Offset = Get32(buf + i + 16); + UInt64 curPos = endPosition - bufSize + i; + UInt64 cdEnd = cdInfo.Size + cdInfo.Offset; + if (curPos != cdEnd) + { + /* + if (cdInfo.Offset <= 16 && cdInfo.Size != 0) + { + // here we support some rare ZIP files with Central directory at the start + ArcInfo.Base = 0; + } + else + */ + ArcInfo.Base = curPos - cdEnd; + } + return S_OK; + } + } + } + return S_FALSE; +} + +HRESULT CInArchive::TryReadCd(CObjectVector &items, UInt64 cdOffset, UInt64 cdSize, CProgressVirt *progress) +{ + items.Clear(); + RINOK(m_Stream->Seek(cdOffset, STREAM_SEEK_SET, &m_Position)); + if (m_Position != cdOffset) + return S_FALSE; + + if (!_inBuffer.Create(1 << 15)) + return E_OUTOFMEMORY; + _inBuffer.SetStream(m_Stream); + _inBuffer.Init(); + _inBufMode = true; + + while(m_Position - cdOffset < cdSize) + { + if (ReadUInt32() != NSignature::kCentralFileHeader) + return S_FALSE; + CItemEx cdItem; + RINOK(ReadCdItem(cdItem)); + items.Add(cdItem); + if (progress && items.Size() % 1000 == 0) + RINOK(progress->SetCompleted(items.Size())); + } + return (m_Position - cdOffset == cdSize) ? S_OK : S_FALSE; +} + +HRESULT CInArchive::ReadCd(CObjectVector &items, UInt64 &cdOffset, UInt64 &cdSize, CProgressVirt *progress) +{ + ArcInfo.Base = 0; + CCdInfo cdInfo; + RINOK(FindCd(cdInfo)); + HRESULT res = S_FALSE; + cdSize = cdInfo.Size; + cdOffset = cdInfo.Offset; + res = TryReadCd(items, ArcInfo.Base + cdOffset, cdSize, progress); + if (res == S_FALSE && ArcInfo.Base == 0) + { + res = TryReadCd(items, cdInfo.Offset + ArcInfo.StartPosition, cdSize, progress); + if (res == S_OK) + ArcInfo.Base = ArcInfo.StartPosition; + } + if (!ReadUInt32(m_Signature)) + return S_FALSE; + return res; +} + +HRESULT CInArchive::ReadLocalsAndCd(CObjectVector &items, CProgressVirt *progress, UInt64 &cdOffset, int &numCdItems) +{ + items.Clear(); + numCdItems = 0; + while (m_Signature == NSignature::kLocalFileHeader) + { + // FSeek points to next byte after signature + // NFileHeader::CLocalBlock localHeader; + CItemEx item; + item.LocalHeaderPosition = m_Position - m_StreamStartPosition - 4; // points to signature; + RINOK(ReadLocalItem(item)); + item.FromLocal = true; + ReadLocalItemDescriptor(item); + items.Add(item); + if (progress && items.Size() % 100 == 0) + RINOK(progress->SetCompleted(items.Size())); + if (!ReadUInt32(m_Signature)) + break; + } + cdOffset = m_Position - 4; + int i; + for (i = 0; i < items.Size(); i++, numCdItems++) + { + if (progress && i % 1000 == 0) + RINOK(progress->SetCompleted(items.Size())); + if (m_Signature == NSignature::kEndOfCentralDir) + break; + + if (m_Signature != NSignature::kCentralFileHeader) + return S_FALSE; + + CItemEx cdItem; + RINOK(ReadCdItem(cdItem)); + + if (i == 0) + { + int j; + for (j = 0; j < items.Size(); j++) + { + CItemEx &item = items[j]; + if (item.Name == cdItem.Name) + { + ArcInfo.Base = item.LocalHeaderPosition - cdItem.LocalHeaderPosition; + break; + } + } + if (j == items.Size()) + return S_FALSE; + } + + int index; + int left = 0, right = items.Size(); + for (;;) + { + if (left >= right) + return S_FALSE; + index = (left + right) / 2; + UInt64 position = items[index].LocalHeaderPosition - ArcInfo.Base; + if (cdItem.LocalHeaderPosition == position) + break; + if (cdItem.LocalHeaderPosition < position) + right = index; + else + left = index + 1; + } + CItemEx &item = items[index]; + // item.LocalHeaderPosition = cdItem.LocalHeaderPosition; + item.MadeByVersion = cdItem.MadeByVersion; + item.CentralExtra = cdItem.CentralExtra; + + if ( + // item.ExtractVersion != cdItem.ExtractVersion || + !FlagsAreSame(item, cdItem) || + item.FileCRC != cdItem.FileCRC) + return S_FALSE; + + if (item.Name.Length() != cdItem.Name.Length() || + item.PackSize != cdItem.PackSize || + item.UnPackSize != cdItem.UnPackSize + ) + return S_FALSE; + item.Name = cdItem.Name; + item.InternalAttributes = cdItem.InternalAttributes; + item.ExternalAttributes = cdItem.ExternalAttributes; + item.Comment = cdItem.Comment; + item.FromCentral = cdItem.FromCentral; + if (!ReadUInt32(m_Signature)) + return S_FALSE; + } + for (i = 0; i < items.Size(); i++) + items[i].LocalHeaderPosition -= ArcInfo.Base; + return S_OK; +} + +struct CEcd +{ + UInt16 thisDiskNumber; + UInt16 startCDDiskNumber; + UInt16 numEntriesInCDOnThisDisk; + UInt16 numEntriesInCD; + UInt32 cdSize; + UInt32 cdStartOffset; + UInt16 commentSize; + void Parse(const Byte *p); +}; + +void CEcd::Parse(const Byte *p) +{ + thisDiskNumber = Get16(p); + startCDDiskNumber = Get16(p + 2); + numEntriesInCDOnThisDisk = Get16(p + 4); + numEntriesInCD = Get16(p + 6); + cdSize = Get32(p + 8); + cdStartOffset = Get32(p + 12); + commentSize = Get16(p + 16); +} + +struct CEcd64 +{ + UInt16 versionMade; + UInt16 versionNeedExtract; + UInt32 thisDiskNumber; + UInt32 startCDDiskNumber; + UInt64 numEntriesInCDOnThisDisk; + UInt64 numEntriesInCD; + UInt64 cdSize; + UInt64 cdStartOffset; + void Parse(const Byte *p); + CEcd64() { memset(this, 0, sizeof(*this)); } +}; + +void CEcd64::Parse(const Byte *p) +{ + versionMade = Get16(p); + versionNeedExtract = Get16(p + 2); + thisDiskNumber = Get32(p + 4); + startCDDiskNumber = Get32(p + 8); + numEntriesInCDOnThisDisk = Get64(p + 12); + numEntriesInCD = Get64(p + 20); + cdSize = Get64(p + 28); + cdStartOffset = Get64(p + 36); +} + +#define COPY_ECD_ITEM_16(n) if (!isZip64 || ecd. n != 0xFFFF) ecd64. n = ecd. n; +#define COPY_ECD_ITEM_32(n) if (!isZip64 || ecd. n != 0xFFFFFFFF) ecd64. n = ecd. n; + +HRESULT CInArchive::ReadHeaders(CObjectVector &items, CProgressVirt *progress) +{ + // m_Signature must be kLocalFileHeaderSignature or + // kEndOfCentralDirSignature + // m_Position points to next byte after signature + + IsZip64 = false; + items.Clear(); + + UInt64 cdSize, cdStartOffset; + HRESULT res; + try + { + res = ReadCd(items, cdStartOffset, cdSize, progress); + } + catch(CInArchiveException &) + { + res = S_FALSE; + } + if (res != S_FALSE && res != S_OK) + return res; + + /* + if (res != S_OK) + return res; + res = S_FALSE; + */ + + int numCdItems = items.Size(); + if (res == S_FALSE) + { + _inBufMode = false; + ArcInfo.Base = 0; + RINOK(m_Stream->Seek(ArcInfo.StartPosition, STREAM_SEEK_SET, &m_Position)); + if (m_Position != ArcInfo.StartPosition) + return S_FALSE; + if (!ReadUInt32(m_Signature)) + return S_FALSE; + RINOK(ReadLocalsAndCd(items, progress, cdStartOffset, numCdItems)); + cdSize = (m_Position - 4) - cdStartOffset; + cdStartOffset -= ArcInfo.Base; + } + + CEcd64 ecd64; + bool isZip64 = false; + UInt64 zip64EcdStartOffset = m_Position - 4 - ArcInfo.Base; + if (m_Signature == NSignature::kZip64EndOfCentralDir) + { + IsZip64 = isZip64 = true; + UInt64 recordSize = ReadUInt64(); + + const int kBufSize = kZip64EcdSize; + Byte buf[kBufSize]; + SafeReadBytes(buf, kBufSize); + ecd64.Parse(buf); + + Skip(recordSize - kZip64EcdSize); + if (!ReadUInt32(m_Signature)) + return S_FALSE; + if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0) + throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported); + if (ecd64.numEntriesInCDOnThisDisk != numCdItems || + ecd64.numEntriesInCD != numCdItems || + ecd64.cdSize != cdSize || + (ecd64.cdStartOffset != cdStartOffset && + (!items.IsEmpty()))) + return S_FALSE; + } + if (m_Signature == NSignature::kZip64EndOfCentralDirLocator) + { + /* UInt32 startEndCDDiskNumber = */ ReadUInt32(); + UInt64 endCDStartOffset = ReadUInt64(); + /* UInt32 numberOfDisks = */ ReadUInt32(); + if (zip64EcdStartOffset != endCDStartOffset) + return S_FALSE; + if (!ReadUInt32(m_Signature)) + return S_FALSE; + } + if (m_Signature != NSignature::kEndOfCentralDir) + return S_FALSE; + + const int kBufSize = kEcdSize - 4; + Byte buf[kBufSize]; + SafeReadBytes(buf, kBufSize); + CEcd ecd; + ecd.Parse(buf); + + COPY_ECD_ITEM_16(thisDiskNumber); + COPY_ECD_ITEM_16(startCDDiskNumber); + COPY_ECD_ITEM_16(numEntriesInCDOnThisDisk); + COPY_ECD_ITEM_16(numEntriesInCD); + COPY_ECD_ITEM_32(cdSize); + COPY_ECD_ITEM_32(cdStartOffset); + + ReadBuffer(ArcInfo.Comment, ecd.commentSize); + + if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0) + throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported); + if ((UInt16)ecd64.numEntriesInCDOnThisDisk != ((UInt16)numCdItems) || + (UInt16)ecd64.numEntriesInCD != ((UInt16)numCdItems) || + (UInt32)ecd64.cdSize != (UInt32)cdSize || + ((UInt32)(ecd64.cdStartOffset) != (UInt32)cdStartOffset && + (!items.IsEmpty()))) + return S_FALSE; + + _inBufMode = false; + _inBuffer.Free(); + IsOkHeaders = (numCdItems == items.Size()); + ArcInfo.FinishPosition = m_Position; + return S_OK; +} + +ISequentialInStream* CInArchive::CreateLimitedStream(UInt64 position, UInt64 size) +{ + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr stream(streamSpec); + SeekInArchive(ArcInfo.Base + position); + streamSpec->SetStream(m_Stream); + streamSpec->Init(size); + return stream.Detach(); +} + +IInStream* CInArchive::CreateStream() +{ + CMyComPtr stream = m_Stream; + return stream.Detach(); +} + +bool CInArchive::SeekInArchive(UInt64 position) +{ + UInt64 newPosition; + if (m_Stream->Seek(position, STREAM_SEEK_SET, &newPosition) != S_OK) + return false; + return (newPosition == position); +} + +}} diff --git a/CPP/7zip/Archive/Zip/ZipIn.h b/CPP/7zip/Archive/Zip/ZipIn.h new file mode 100755 index 0000000..86fe6b8 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipIn.h @@ -0,0 +1,125 @@ +// Archive/ZipIn.h + +#ifndef __ZIP_IN_H +#define __ZIP_IN_H + +#include "Common/MyCom.h" + +#include "../../IStream.h" + +#include "../../Common/InBuffer.h" + +#include "ZipHeader.h" +#include "ZipItemEx.h" + +namespace NArchive { +namespace NZip { + +class CInArchiveException +{ +public: + enum ECauseType + { + kUnexpectedEndOfArchive = 0, + kArchiceHeaderCRCError, + kFileHeaderCRCError, + kIncorrectArchive, + kDataDescroptorsAreNotSupported, + kMultiVolumeArchiveAreNotSupported, + kReadStreamError, + kSeekStreamError + } + Cause; + CInArchiveException(ECauseType cause): Cause(cause) {} +}; + +class CInArchiveInfo +{ +public: + UInt64 Base; + UInt64 StartPosition; + UInt64 FinishPosition; + CByteBuffer Comment; + + CInArchiveInfo(): Base(0), StartPosition(0) {} + UInt64 GetPhySize() const { return FinishPosition - StartPosition; } + void Clear() + { + Base = 0; + StartPosition = 0; + Comment.SetCapacity(0); + } +}; + +class CProgressVirt +{ +public: + STDMETHOD(SetTotal)(UInt64 numFiles) PURE; + STDMETHOD(SetCompleted)(UInt64 numFiles) PURE; +}; + +struct CCdInfo +{ + // UInt64 NumEntries; + UInt64 Size; + UInt64 Offset; +}; + +class CInArchive +{ + CMyComPtr m_Stream; + UInt32 m_Signature; + UInt64 m_StreamStartPosition; + UInt64 m_Position; + + bool _inBufMode; + CInBuffer _inBuffer; + + HRESULT Seek(UInt64 offset); + + HRESULT FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit); + void ReadFileName(UInt32 nameSize, AString &dest); + + HRESULT ReadBytes(void *data, UInt32 size, UInt32 *processedSize); + bool ReadBytesAndTestSize(void *data, UInt32 size); + void SafeReadBytes(void *data, UInt32 size); + void ReadBuffer(CByteBuffer &buffer, UInt32 size); + Byte ReadByte(); + UInt16 ReadUInt16(); + UInt32 ReadUInt32(); + UInt64 ReadUInt64(); + bool ReadUInt32(UInt32 &signature); + + void Skip(UInt64 num); + void IncreaseRealPosition(UInt64 addValue); + + void ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock, + UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber); + HRESULT ReadLocalItem(CItemEx &item); + HRESULT ReadLocalItemDescriptor(CItemEx &item); + HRESULT ReadCdItem(CItemEx &item); + HRESULT TryEcd64(UInt64 offset, CCdInfo &cdInfo); + HRESULT FindCd(CCdInfo &cdInfo); + HRESULT TryReadCd(CObjectVector &items, UInt64 cdOffset, UInt64 cdSize, CProgressVirt *progress); + HRESULT ReadCd(CObjectVector &items, UInt64 &cdOffset, UInt64 &cdSize, CProgressVirt *progress); + HRESULT ReadLocalsAndCd(CObjectVector &items, CProgressVirt *progress, UInt64 &cdOffset, int &numCdItems); +public: + CInArchiveInfo ArcInfo; + bool IsZip64; + bool IsOkHeaders; + + HRESULT ReadHeaders(CObjectVector &items, CProgressVirt *progress); + HRESULT ReadLocalItemAfterCdItem(CItemEx &item); + HRESULT ReadLocalItemAfterCdItemFull(CItemEx &item); + HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); + void Close(); + bool SeekInArchive(UInt64 position); + ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size); + IInStream* CreateStream(); + + bool IsOpen() const { return m_Stream != NULL; } +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Zip/ZipItem.cpp b/CPP/7zip/Archive/Zip/ZipItem.cpp new file mode 100755 index 0000000..df4a379 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipItem.cpp @@ -0,0 +1,172 @@ +// Archive/ZipItem.cpp + +#include "StdAfx.h" + +#include "ZipHeader.h" +#include "ZipItem.h" +#include "../Common/ItemNameUtils.h" +#include "../../../../C/CpuArch.h" + +namespace NArchive { +namespace NZip { + +bool operator==(const CVersion &v1, const CVersion &v2) +{ + return (v1.Version == v2.Version) && (v1.HostOS == v2.HostOS); +} + +bool operator!=(const CVersion &v1, const CVersion &v2) +{ + return !(v1 == v2); +} + +bool CExtraSubBlock::ExtractNtfsTime(int index, FILETIME &ft) const +{ + ft.dwHighDateTime = ft.dwLowDateTime = 0; + UInt32 size = (UInt32)Data.GetCapacity(); + if (ID != NFileHeader::NExtraID::kNTFS || size < 32) + return false; + const Byte *p = (const Byte *)Data; + p += 4; // for reserved + size -= 4; + while (size > 4) + { + UInt16 tag = GetUi16(p); + UInt32 attrSize = GetUi16(p + 2); + p += 4; + size -= 4; + if (attrSize > size) + attrSize = size; + + if (tag == NFileHeader::NNtfsExtra::kTagTime && attrSize >= 24) + { + p += 8 * index; + ft.dwLowDateTime = GetUi32(p); + ft.dwHighDateTime = GetUi32(p + 4); + return true; + } + p += attrSize; + size -= attrSize; + } + return false; +} + +bool CExtraSubBlock::ExtractUnixTime(int index, UInt32 &res) const +{ + res = 0; + UInt32 size = (UInt32)Data.GetCapacity(); + if (ID != NFileHeader::NExtraID::kUnixTime || size < 5) + return false; + const Byte *p = (const Byte *)Data; + Byte flags = *p++; + size--; + for (int i = 0; i < 3; i++) + if ((flags & (1 << i)) != 0) + { + if (size < 4) + return false; + if (index == i) + { + res = GetUi32(p); + return true; + } + p += 4; + size -= 4; + } + return false; +} + +bool CLocalItem::IsDir() const +{ + return NItemName::HasTailSlash(Name, GetCodePage()); +} + +bool CItem::IsDir() const +{ + if (NItemName::HasTailSlash(Name, GetCodePage())) + return true; + if (!FromCentral) + return false; + WORD highAttributes = WORD((ExternalAttributes >> 16 ) & 0xFFFF); + switch(MadeByVersion.HostOS) + { + case NFileHeader::NHostOS::kAMIGA: + switch (highAttributes & NFileHeader::NAmigaAttribute::kIFMT) + { + case NFileHeader::NAmigaAttribute::kIFDIR: return true; + case NFileHeader::NAmigaAttribute::kIFREG: return false; + default: return false; // change it throw kUnknownAttributes; + } + case NFileHeader::NHostOS::kFAT: + case NFileHeader::NHostOS::kNTFS: + case NFileHeader::NHostOS::kHPFS: + case NFileHeader::NHostOS::kVFAT: + return ((ExternalAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0); + case NFileHeader::NHostOS::kAtari: + case NFileHeader::NHostOS::kMac: + case NFileHeader::NHostOS::kVMS: + case NFileHeader::NHostOS::kVM_CMS: + case NFileHeader::NHostOS::kAcorn: + case NFileHeader::NHostOS::kMVS: + return false; // change it throw kUnknownAttributes; + default: + /* + switch (highAttributes & NFileHeader::NUnixAttribute::kIFMT) + { + case NFileHeader::NUnixAttribute::kIFDIR: + return true; + default: + return false; + } + */ + return false; + } +} + +UInt32 CLocalItem::GetWinAttributes() const +{ + DWORD winAttributes = 0; + if (IsDir()) + winAttributes |= FILE_ATTRIBUTE_DIRECTORY; + return winAttributes; +} + +UInt32 CItem::GetWinAttributes() const +{ + DWORD winAttributes = 0; + switch(MadeByVersion.HostOS) + { + case NFileHeader::NHostOS::kFAT: + case NFileHeader::NHostOS::kNTFS: + if (FromCentral) + winAttributes = ExternalAttributes; + break; + default: + winAttributes = 0; // must be converted from unix value; + } + if (IsDir()) // test it; + winAttributes |= FILE_ATTRIBUTE_DIRECTORY; + return winAttributes; +} + +void CLocalItem::SetFlagBits(int startBitNumber, int numBits, int value) +{ + UInt16 mask = (UInt16)(((1 << numBits) - 1) << startBitNumber); + Flags &= ~mask; + Flags |= value << startBitNumber; +} + +void CLocalItem::SetBitMask(int bitMask, bool enable) +{ + if(enable) + Flags |= bitMask; + else + Flags &= ~bitMask; +} + +void CLocalItem::SetEncrypted(bool encrypted) + { SetBitMask(NFileHeader::NFlags::kEncrypted, encrypted); } +void CLocalItem::SetUtf8(bool isUtf8) + { SetBitMask(NFileHeader::NFlags::kUtf8, isUtf8); } + +}} diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h new file mode 100755 index 0000000..b9cc524 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipItem.h @@ -0,0 +1,281 @@ +// Archive/ZipItem.h + +#ifndef __ARCHIVE_ZIP_ITEM_H +#define __ARCHIVE_ZIP_ITEM_H + +#include "Common/Types.h" +#include "Common/MyString.h" +#include "Common/Buffer.h" +#include "Common/UTFConvert.h" +#include "Common/StringConvert.h" + +#include "ZipHeader.h" + +namespace NArchive { +namespace NZip { + +struct CVersion +{ + Byte Version; + Byte HostOS; +}; + +bool operator==(const CVersion &v1, const CVersion &v2); +bool operator!=(const CVersion &v1, const CVersion &v2); + +struct CExtraSubBlock +{ + UInt16 ID; + CByteBuffer Data; + bool ExtractNtfsTime(int index, FILETIME &ft) const; + bool ExtractUnixTime(int index, UInt32 &res) const; +}; + +struct CWzAesExtraField +{ + UInt16 VendorVersion; // 0x0001 - AE-1, 0x0002 - AE-2, + // UInt16 VendorId; // "AE" + Byte Strength; // 1 - 128-bit , 2 - 192-bit , 3 - 256-bit + UInt16 Method; + + CWzAesExtraField(): VendorVersion(2), Strength(3), Method(0) {} + + bool NeedCrc() const { return (VendorVersion == 1); } + + bool ParseFromSubBlock(const CExtraSubBlock &sb) + { + if (sb.ID != NFileHeader::NExtraID::kWzAES) + return false; + if (sb.Data.GetCapacity() < 7) + return false; + const Byte *p = (const Byte *)sb.Data; + VendorVersion = (((UInt16)p[1]) << 8) | p[0]; + if (p[2] != 'A' || p[3] != 'E') + return false; + Strength = p[4]; + Method = (((UInt16)p[6]) << 16) | p[5]; + return true; + } + void SetSubBlock(CExtraSubBlock &sb) const + { + sb.Data.SetCapacity(7); + sb.ID = NFileHeader::NExtraID::kWzAES; + Byte *p = (Byte *)sb.Data; + p[0] = (Byte)VendorVersion; + p[1] = (Byte)(VendorVersion >> 8); + p[2] = 'A'; + p[3] = 'E'; + p[4] = Strength; + p[5] = (Byte)Method; + p[6] = (Byte)(Method >> 8); + } +}; + +namespace NStrongCryptoFlags +{ + const UInt16 kDES = 0x6601; + const UInt16 kRC2old = 0x6602; + const UInt16 k3DES168 = 0x6603; + const UInt16 k3DES112 = 0x6609; + const UInt16 kAES128 = 0x660E; + const UInt16 kAES192 = 0x660F; + const UInt16 kAES256 = 0x6610; + const UInt16 kRC2 = 0x6702; + const UInt16 kBlowfish = 0x6720; + const UInt16 kTwofish = 0x6721; + const UInt16 kRC4 = 0x6801; +} + +struct CStrongCryptoField +{ + UInt16 Format; + UInt16 AlgId; + UInt16 BitLen; + UInt16 Flags; + + bool ParseFromSubBlock(const CExtraSubBlock &sb) + { + if (sb.ID != NFileHeader::NExtraID::kStrongEncrypt) + return false; + const Byte *p = (const Byte *)sb.Data; + if (sb.Data.GetCapacity() < 8) + return false; + Format = (((UInt16)p[1]) << 8) | p[0]; + AlgId = (((UInt16)p[3]) << 8) | p[2]; + BitLen = (((UInt16)p[5]) << 8) | p[4]; + Flags = (((UInt16)p[7]) << 8) | p[6]; + return (Format == 2); + } +}; + +struct CExtraBlock +{ + CObjectVector SubBlocks; + void Clear() { SubBlocks.Clear(); } + size_t GetSize() const + { + size_t res = 0; + for (int i = 0; i < SubBlocks.Size(); i++) + res += SubBlocks[i].Data.GetCapacity() + 2 + 2; + return res; + } + bool GetWzAesField(CWzAesExtraField &aesField) const + { + for (int i = 0; i < SubBlocks.Size(); i++) + if (aesField.ParseFromSubBlock(SubBlocks[i])) + return true; + return false; + } + + bool GetStrongCryptoField(CStrongCryptoField &f) const + { + for (int i = 0; i < SubBlocks.Size(); i++) + if (f.ParseFromSubBlock(SubBlocks[i])) + return true; + return false; + } + + bool HasWzAesField() const + { + CWzAesExtraField aesField; + return GetWzAesField(aesField); + } + + bool GetNtfsTime(int index, FILETIME &ft) const + { + for (int i = 0; i < SubBlocks.Size(); i++) + { + const CExtraSubBlock &sb = SubBlocks[i]; + if (sb.ID == NFileHeader::NExtraID::kNTFS) + return sb.ExtractNtfsTime(index, ft); + } + return false; + } + + bool GetUnixTime(int index, UInt32 &res) const + { + for (int i = 0; i < SubBlocks.Size(); i++) + { + const CExtraSubBlock &sb = SubBlocks[i]; + if (sb.ID == NFileHeader::NExtraID::kUnixTime) + return sb.ExtractUnixTime(index, res); + } + return false; + } + + /* + bool HasStrongCryptoField() const + { + CStrongCryptoField f; + return GetStrongCryptoField(f); + } + */ + + void RemoveUnknownSubBlocks() + { + for (int i = SubBlocks.Size() - 1; i >= 0; i--) + if (SubBlocks[i].ID != NFileHeader::NExtraID::kWzAES) + SubBlocks.Delete(i); + } +}; + + +class CLocalItem +{ +public: + CVersion ExtractVersion; + UInt16 Flags; + UInt16 CompressionMethod; + UInt32 Time; + UInt32 FileCRC; + UInt64 PackSize; + UInt64 UnPackSize; + + AString Name; + + CExtraBlock LocalExtra; + + bool IsUtf8() const { return (Flags & NFileHeader::NFlags::kUtf8) != 0; } + + bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kEncrypted) != 0; } + bool IsStrongEncrypted() const { return IsEncrypted() && (Flags & NFileHeader::NFlags::kStrongEncrypted) != 0; }; + bool IsAesEncrypted() const { return IsEncrypted() && (IsStrongEncrypted() || CompressionMethod == NFileHeader::NCompressionMethod::kWzAES); }; + + bool IsLzmaEOS() const { return (Flags & NFileHeader::NFlags::kLzmaEOS) != 0; } + + bool IsDir() const; + bool IgnoreItem() const { return false; } + UInt32 GetWinAttributes() const; + + bool HasDescriptor() const { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; } + + UString GetUnicodeString(const AString &s) const + { + UString res; + if (IsUtf8()) + if (!ConvertUTF8ToUnicode(s, res)) + res.Empty(); + if (res.IsEmpty()) + res = MultiByteToUnicodeString(s, GetCodePage()); + return res; + } + +private: + void SetFlagBits(int startBitNumber, int numBits, int value); + void SetBitMask(int bitMask, bool enable); +public: + void ClearFlags() { Flags = 0; } + void SetEncrypted(bool encrypted); + void SetUtf8(bool isUtf8); + + WORD GetCodePage() const { return CP_OEMCP; } +}; + +class CItem: public CLocalItem +{ +public: + CVersion MadeByVersion; + UInt16 InternalAttributes; + UInt32 ExternalAttributes; + + UInt64 LocalHeaderPosition; + + FILETIME NtfsMTime; + FILETIME NtfsATime; + FILETIME NtfsCTime; + + CExtraBlock CentralExtra; + CByteBuffer Comment; + + bool FromLocal; + bool FromCentral; + bool NtfsTimeIsDefined; + + bool IsDir() const; + UInt32 GetWinAttributes() const; + + bool IsThereCrc() const + { + if (CompressionMethod == NFileHeader::NCompressionMethod::kWzAES) + { + CWzAesExtraField aesField; + if (CentralExtra.GetWzAesField(aesField)) + return aesField.NeedCrc(); + } + return (FileCRC != 0 || !IsDir()); + } + + WORD GetCodePage() const + { + return (WORD)((MadeByVersion.HostOS == NFileHeader::NHostOS::kFAT + || MadeByVersion.HostOS == NFileHeader::NHostOS::kNTFS + ) ? CP_OEMCP : CP_ACP); + } + CItem() : FromLocal(false), FromCentral(false), NtfsTimeIsDefined(false) {} +}; + +}} + +#endif + + diff --git a/CPP/7zip/Archive/Zip/ZipItemEx.h b/CPP/7zip/Archive/Zip/ZipItemEx.h new file mode 100755 index 0000000..0d74edd --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipItemEx.h @@ -0,0 +1,34 @@ +// Archive/ZipItemEx.h + +#ifndef __ARCHIVE_ZIP_ITEMEX_H +#define __ARCHIVE_ZIP_ITEMEX_H + +#include "ZipHeader.h" +#include "ZipItem.h" + +namespace NArchive { +namespace NZip { + +class CItemEx: public CItem +{ +public: + UInt32 FileHeaderWithNameSize; + UInt16 LocalExtraSize; + + UInt64 GetLocalFullSize() const + { return FileHeaderWithNameSize + LocalExtraSize + PackSize + + (HasDescriptor() ? NFileHeader::kDataDescriptorSize : 0); }; + /* + UInt64 GetLocalFullSize(bool isZip64) const + { return FileHeaderWithNameSize + LocalExtraSize + PackSize + + (HasDescriptor() ? (isZip64 ? NFileHeader::kDataDescriptor64Size : NFileHeader::kDataDescriptorSize) : 0); }; + */ + UInt64 GetLocalExtraPosition() const + { return LocalHeaderPosition + FileHeaderWithNameSize; }; + UInt64 GetDataPosition() const + { return GetLocalExtraPosition() + LocalExtraSize; }; +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Zip/ZipOut.cpp b/CPP/7zip/Archive/Zip/ZipOut.cpp new file mode 100755 index 0000000..c8157b9 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipOut.cpp @@ -0,0 +1,289 @@ +// ZipOut.cpp + +#include "StdAfx.h" + +#include "../../Common/OffsetStream.h" + +#include "ZipOut.h" + +namespace NArchive { +namespace NZip { + +void COutArchive::Create(IOutStream *outStream) +{ + if (!m_OutBuffer.Create(1 << 16)) + throw CSystemException(E_OUTOFMEMORY); + m_Stream = outStream; + m_OutBuffer.SetStream(outStream); + m_OutBuffer.Init(); + m_BasePosition = 0; +} + +void COutArchive::MoveBasePosition(UInt64 distanceToMove) +{ + m_BasePosition += distanceToMove; // test overflow +} + +void COutArchive::PrepareWriteCompressedDataZip64(UInt16 fileNameLength, bool isZip64, bool aesEncryption) +{ + m_IsZip64 = isZip64; + m_ExtraSize = isZip64 ? (4 + 8 + 8) : 0; + if (aesEncryption) + m_ExtraSize += 4 + 7; + m_LocalFileHeaderSize = 4 + NFileHeader::kLocalBlockSize + fileNameLength + m_ExtraSize; +} + +void COutArchive::PrepareWriteCompressedData(UInt16 fileNameLength, UInt64 unPackSize, bool aesEncryption) +{ + // We test it to 0xF8000000 to support case when compressed size + // can be larger than uncompressed size. + PrepareWriteCompressedDataZip64(fileNameLength, unPackSize >= 0xF8000000, aesEncryption); +} + +void COutArchive::PrepareWriteCompressedData2(UInt16 fileNameLength, UInt64 unPackSize, UInt64 packSize, bool aesEncryption) +{ + bool isUnPack64 = unPackSize >= 0xFFFFFFFF; + bool isPack64 = packSize >= 0xFFFFFFFF; + bool isZip64 = isPack64 || isUnPack64; + PrepareWriteCompressedDataZip64(fileNameLength, isZip64, aesEncryption); +} + +void COutArchive::WriteBytes(const void *buffer, UInt32 size) +{ + m_OutBuffer.WriteBytes(buffer, size); + m_BasePosition += size; +} + +void COutArchive::WriteByte(Byte b) +{ + WriteBytes(&b, 1); +} + +void COutArchive::WriteUInt16(UInt16 value) +{ + for (int i = 0; i < 2; i++) + { + WriteByte((Byte)value); + value >>= 8; + } +} + +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::WriteExtra(const CExtraBlock &extra) +{ + if (extra.SubBlocks.Size() != 0) + { + for (int i = 0; i < extra.SubBlocks.Size(); i++) + { + const CExtraSubBlock &subBlock = extra.SubBlocks[i]; + WriteUInt16(subBlock.ID); + WriteUInt16((UInt16)subBlock.Data.GetCapacity()); + WriteBytes(subBlock.Data, (UInt32)subBlock.Data.GetCapacity()); + } + } +} + +void COutArchive::SeekTo(UInt64 offset) +{ + HRESULT res = m_Stream->Seek(offset, STREAM_SEEK_SET, NULL); + if (res != S_OK) + throw CSystemException(res); +} + +void COutArchive::WriteLocalHeader(const CLocalItem &item) +{ + SeekTo(m_BasePosition); + + bool isZip64 = m_IsZip64 || item.PackSize >= 0xFFFFFFFF || item.UnPackSize >= 0xFFFFFFFF; + + WriteUInt32(NSignature::kLocalFileHeader); + { + Byte ver = item.ExtractVersion.Version; + if (isZip64 && ver < NFileHeader::NCompressionMethod::kExtractVersion_Zip64) + ver = NFileHeader::NCompressionMethod::kExtractVersion_Zip64; + WriteByte(ver); + } + WriteByte(item.ExtractVersion.HostOS); + WriteUInt16(item.Flags); + WriteUInt16(item.CompressionMethod); + WriteUInt32(item.Time); + WriteUInt32(item.FileCRC); + WriteUInt32(isZip64 ? 0xFFFFFFFF: (UInt32)item.PackSize); + WriteUInt32(isZip64 ? 0xFFFFFFFF: (UInt32)item.UnPackSize); + WriteUInt16((UInt16)item.Name.Length()); + { + UInt16 localExtraSize = (UInt16)((isZip64 ? (4 + 16): 0) + item.LocalExtra.GetSize()); + if (localExtraSize > m_ExtraSize) + throw CSystemException(E_FAIL); + } + WriteUInt16((UInt16)m_ExtraSize); // test it; + WriteBytes((const char *)item.Name, item.Name.Length()); + + UInt32 extraPos = 0; + if (isZip64) + { + extraPos += 4 + 16; + WriteUInt16(NFileHeader::NExtraID::kZip64); + WriteUInt16(16); + WriteUInt64(item.UnPackSize); + WriteUInt64(item.PackSize); + } + + WriteExtra(item.LocalExtra); + extraPos += (UInt32)item.LocalExtra.GetSize(); + for (; extraPos < m_ExtraSize; extraPos++) + WriteByte(0); + + m_OutBuffer.FlushWithCheck(); + MoveBasePosition(item.PackSize); + SeekTo(m_BasePosition); +} + +void COutArchive::WriteCentralHeader(const CItem &item) +{ + bool isUnPack64 = item.UnPackSize >= 0xFFFFFFFF; + bool isPack64 = item.PackSize >= 0xFFFFFFFF; + bool isPosition64 = item.LocalHeaderPosition >= 0xFFFFFFFF; + bool isZip64 = isPack64 || isUnPack64 || isPosition64; + + WriteUInt32(NSignature::kCentralFileHeader); + WriteByte(item.MadeByVersion.Version); + WriteByte(item.MadeByVersion.HostOS); + { + Byte ver = item.ExtractVersion.Version; + if (isZip64 && ver < NFileHeader::NCompressionMethod::kExtractVersion_Zip64) + ver = NFileHeader::NCompressionMethod::kExtractVersion_Zip64; + WriteByte(ver); + } + WriteByte(item.ExtractVersion.HostOS); + WriteUInt16(item.Flags); + WriteUInt16(item.CompressionMethod); + WriteUInt32(item.Time); + WriteUInt32(item.FileCRC); + WriteUInt32(isPack64 ? 0xFFFFFFFF: (UInt32)item.PackSize); + WriteUInt32(isUnPack64 ? 0xFFFFFFFF: (UInt32)item.UnPackSize); + WriteUInt16((UInt16)item.Name.Length()); + UInt16 zip64ExtraSize = (UInt16)((isUnPack64 ? 8: 0) + (isPack64 ? 8: 0) + (isPosition64 ? 8: 0)); + const UInt16 kNtfsExtraSize = 4 + 2 + 2 + (3 * 8); + UInt16 centralExtraSize = (UInt16)(isZip64 ? (4 + zip64ExtraSize) : 0) + (item.NtfsTimeIsDefined ? (4 + kNtfsExtraSize) : 0); + centralExtraSize = (UInt16)(centralExtraSize + item.CentralExtra.GetSize()); + WriteUInt16(centralExtraSize); // test it; + WriteUInt16((UInt16)item.Comment.GetCapacity()); + WriteUInt16(0); // DiskNumberStart; + WriteUInt16(item.InternalAttributes); + WriteUInt32(item.ExternalAttributes); + WriteUInt32(isPosition64 ? 0xFFFFFFFF: (UInt32)item.LocalHeaderPosition); + WriteBytes((const char *)item.Name, item.Name.Length()); + if (isZip64) + { + WriteUInt16(NFileHeader::NExtraID::kZip64); + WriteUInt16(zip64ExtraSize); + if(isUnPack64) + WriteUInt64(item.UnPackSize); + if(isPack64) + WriteUInt64(item.PackSize); + if(isPosition64) + WriteUInt64(item.LocalHeaderPosition); + } + if (item.NtfsTimeIsDefined) + { + WriteUInt16(NFileHeader::NExtraID::kNTFS); + WriteUInt16(kNtfsExtraSize); + WriteUInt32(0); // reserved + WriteUInt16(NFileHeader::NNtfsExtra::kTagTime); + WriteUInt16(8 * 3); + WriteUInt32(item.NtfsMTime.dwLowDateTime); + WriteUInt32(item.NtfsMTime.dwHighDateTime); + WriteUInt32(item.NtfsATime.dwLowDateTime); + WriteUInt32(item.NtfsATime.dwHighDateTime); + WriteUInt32(item.NtfsCTime.dwLowDateTime); + WriteUInt32(item.NtfsCTime.dwHighDateTime); + } + WriteExtra(item.CentralExtra); + if (item.Comment.GetCapacity() > 0) + WriteBytes(item.Comment, (UInt32)item.Comment.GetCapacity()); +} + +void COutArchive::WriteCentralDir(const CObjectVector &items, const CByteBuffer *comment) +{ + SeekTo(m_BasePosition); + + UInt64 cdOffset = GetCurrentPosition(); + for(int i = 0; i < items.Size(); i++) + WriteCentralHeader(items[i]); + UInt64 cd64EndOffset = GetCurrentPosition(); + UInt64 cdSize = cd64EndOffset - cdOffset; + bool cdOffset64 = cdOffset >= 0xFFFFFFFF; + bool cdSize64 = cdSize >= 0xFFFFFFFF; + bool items64 = items.Size() >= 0xFFFF; + bool isZip64 = (cdOffset64 || cdSize64 || items64); + + if (isZip64) + { + WriteUInt32(NSignature::kZip64EndOfCentralDir); + WriteUInt64(kZip64EcdSize); // ThisDiskNumber = 0; + WriteUInt16(45); // version + WriteUInt16(45); // version + WriteUInt32(0); // ThisDiskNumber = 0; + WriteUInt32(0); // StartCentralDirectoryDiskNumber;; + WriteUInt64((UInt64)items.Size()); + WriteUInt64((UInt64)items.Size()); + WriteUInt64((UInt64)cdSize); + WriteUInt64((UInt64)cdOffset); + + WriteUInt32(NSignature::kZip64EndOfCentralDirLocator); + WriteUInt32(0); // number of the disk with the start of the zip64 end of central directory + WriteUInt64(cd64EndOffset); + WriteUInt32(1); // total number of disks + } + WriteUInt32(NSignature::kEndOfCentralDir); + WriteUInt16(0); // ThisDiskNumber = 0; + WriteUInt16(0); // StartCentralDirectoryDiskNumber; + WriteUInt16((UInt16)(items64 ? 0xFFFF: items.Size())); + WriteUInt16((UInt16)(items64 ? 0xFFFF: items.Size())); + WriteUInt32(cdSize64 ? 0xFFFFFFFF: (UInt32)cdSize); + WriteUInt32(cdOffset64 ? 0xFFFFFFFF: (UInt32)cdOffset); + UInt32 commentSize = (UInt32)(comment ? comment->GetCapacity() : 0); + WriteUInt16((UInt16)commentSize); + if (commentSize > 0) + WriteBytes((const Byte *)*comment, commentSize); + m_OutBuffer.FlushWithCheck(); +} + +void COutArchive::CreateStreamForCompressing(IOutStream **outStream) +{ + COffsetOutStream *streamSpec = new COffsetOutStream; + CMyComPtr tempStream(streamSpec); + streamSpec->Init(m_Stream, m_BasePosition + m_LocalFileHeaderSize); + *outStream = tempStream.Detach(); +} + +void COutArchive::SeekToPackedDataPosition() +{ + SeekTo(m_BasePosition + m_LocalFileHeaderSize); +} + +void COutArchive::CreateStreamForCopying(ISequentialOutStream **outStream) +{ + CMyComPtr tempStream(m_Stream); + *outStream = tempStream.Detach(); +} + +}} diff --git a/CPP/7zip/Archive/Zip/ZipOut.h b/CPP/7zip/Archive/Zip/ZipOut.h new file mode 100755 index 0000000..327eef2 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipOut.h @@ -0,0 +1,56 @@ +// ZipOut.h + +#ifndef __ZIP_OUT_H +#define __ZIP_OUT_H + +#include "Common/MyCom.h" + +#include "../../IStream.h" +#include "../../Common/OutBuffer.h" + +#include "ZipItem.h" + +namespace NArchive { +namespace NZip { + +// can throw CSystemException and COutBufferException + +class COutArchive +{ + CMyComPtr m_Stream; + COutBuffer m_OutBuffer; + + UInt64 m_BasePosition; + UInt32 m_LocalFileHeaderSize; + UInt32 m_ExtraSize; + bool m_IsZip64; + + void WriteBytes(const void *buffer, UInt32 size); + void WriteByte(Byte b); + void WriteUInt16(UInt16 value); + void WriteUInt32(UInt32 value); + void WriteUInt64(UInt64 value); + + void WriteExtraHeader(const CItem &item); + void WriteCentralHeader(const CItem &item); + void WriteExtra(const CExtraBlock &extra); + void SeekTo(UInt64 offset); +public: + void Create(IOutStream *outStream); + void MoveBasePosition(UInt64 distanceToMove); + UInt64 GetCurrentPosition() const { return m_BasePosition; }; + void PrepareWriteCompressedDataZip64(UInt16 fileNameLength, bool isZip64, bool aesEncryption); + void PrepareWriteCompressedData(UInt16 fileNameLength, UInt64 unPackSize, bool aesEncryption); + void PrepareWriteCompressedData2(UInt16 fileNameLength, UInt64 unPackSize, UInt64 packSize, bool aesEncryption); + void WriteLocalHeader(const CLocalItem &item); + + void WriteCentralDir(const CObjectVector &items, const CByteBuffer *comment); + + void CreateStreamForCompressing(IOutStream **outStream); + void CreateStreamForCopying(ISequentialOutStream **outStream); + void SeekToPackedDataPosition(); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Zip/ZipRegister.cpp b/CPP/7zip/Archive/Zip/ZipRegister.cpp new file mode 100755 index 0000000..e97a679 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipRegister.cpp @@ -0,0 +1,18 @@ +// ZipRegister.cpp + +#include "StdAfx.h" + +#include "../../Common/RegisterArc.h" + +#include "ZipHandler.h" +static IInArchive *CreateArc() { return new NArchive::NZip::CHandler; } +#ifndef EXTRACT_ONLY +static IOutArchive *CreateArcOut() { return new NArchive::NZip::CHandler; } +#else +#define CreateArcOut 0 +#endif + +static CArcInfo g_ArcInfo = + { L"zip", L"zip jar xpi odt ods docx xlsx", 0, 1, { 0x50, 0x4B, 0x03, 0x04 }, 4, false, CreateArc, CreateArcOut }; + +REGISTER_ARC(Zip) diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp new file mode 100755 index 0000000..9327158 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp @@ -0,0 +1,1068 @@ +// ZipUpdate.cpp + +#include "StdAfx.h" + +#include "../../../../C/Alloc.h" + +#include "Common/AutoPtr.h" +#include "Common/Defs.h" +#include "Common/StringConvert.h" + +#include "Windows/Defs.h" +#include "Windows/Thread.h" + +#include "../../Common/CreateCoder.h" +#include "../../Common/LimitedStreams.h" +#include "../../Common/OutMemStream.h" +#include "../../Common/ProgressUtils.h" +#ifndef _7ZIP_ST +#include "../../Common/ProgressMt.h" +#endif +#include "../../Common/StreamUtils.h" + +#include "../../Compress/CopyCoder.h" + +#include "ZipAddCommon.h" +#include "ZipOut.h" +#include "ZipUpdate.h" + +using namespace NWindows; +using namespace NSynchronization; + +namespace NArchive { +namespace NZip { + +static const Byte kHostOS = + #ifdef _WIN32 + NFileHeader::NHostOS::kFAT; + #else + NFileHeader::NHostOS::kUnix; + #endif + +static const Byte kMadeByHostOS = kHostOS; +static const Byte kExtractHostOS = kHostOS; + +static const Byte kMethodForDirectory = NFileHeader::NCompressionMethod::kStored; + +static HRESULT CopyBlockToArchive(ISequentialInStream *inStream, + COutArchive &outArchive, ICompressProgressInfo *progress) +{ + CMyComPtr outStream; + outArchive.CreateStreamForCopying(&outStream); + return NCompress::CopyStream(inStream, outStream, progress); +} + +static HRESULT WriteRange(IInStream *inStream, COutArchive &outArchive, + const CUpdateRange &range, ICompressProgressInfo *progress) +{ + UInt64 position; + RINOK(inStream->Seek(range.Position, STREAM_SEEK_SET, &position)); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStreamLimited(streamSpec); + streamSpec->SetStream(inStream); + streamSpec->Init(range.Size); + + RINOK(CopyBlockToArchive(inStreamLimited, outArchive, progress)); + return progress->SetRatioInfo(&range.Size, &range.Size); +} + +static void SetFileHeader( + COutArchive &archive, + const CCompressionMethodMode &options, + const CUpdateItem &ui, + CItem &item) +{ + item.UnPackSize = ui.Size; + bool isDir; + + item.ClearFlags(); + + if (ui.NewProperties) + { + isDir = ui.IsDir; + item.Name = ui.Name; + item.SetUtf8(ui.IsUtf8); + item.ExternalAttributes = ui.Attributes; + item.Time = ui.Time; + item.NtfsMTime = ui.NtfsMTime; + item.NtfsATime = ui.NtfsATime; + item.NtfsCTime = ui.NtfsCTime; + item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined; + } + else + isDir = item.IsDir(); + + item.LocalHeaderPosition = archive.GetCurrentPosition(); + item.MadeByVersion.HostOS = kMadeByHostOS; + item.MadeByVersion.Version = NFileHeader::NCompressionMethod::kMadeByProgramVersion; + + item.ExtractVersion.HostOS = kExtractHostOS; + + item.InternalAttributes = 0; // test it + item.SetEncrypted(!isDir && options.PasswordIsDefined); + if (isDir) + { + item.ExtractVersion.Version = NFileHeader::NCompressionMethod::kExtractVersion_Dir; + item.CompressionMethod = kMethodForDirectory; + item.PackSize = 0; + item.FileCRC = 0; // test it + } +} + +static void SetItemInfoFromCompressingResult(const CCompressingResult &compressingResult, + bool isAesMode, Byte aesKeyMode, CItem &item) +{ + item.ExtractVersion.Version = compressingResult.ExtractVersion; + item.CompressionMethod = compressingResult.Method; + item.FileCRC = compressingResult.CRC; + item.UnPackSize = compressingResult.UnpackSize; + item.PackSize = compressingResult.PackSize; + + item.LocalExtra.Clear(); + item.CentralExtra.Clear(); + + if (isAesMode) + { + CWzAesExtraField wzAesField; + wzAesField.Strength = aesKeyMode; + wzAesField.Method = compressingResult.Method; + item.CompressionMethod = NFileHeader::NCompressionMethod::kWzAES; + item.FileCRC = 0; + CExtraSubBlock sb; + wzAesField.SetSubBlock(sb); + item.LocalExtra.SubBlocks.Add(sb); + item.CentralExtra.SubBlocks.Add(sb); + } +} + +#ifndef _7ZIP_ST + +static THREAD_FUNC_DECL CoderThread(void *threadCoderInfo); + +struct CThreadInfo +{ + #ifdef EXTERNAL_CODECS + CMyComPtr _codecsInfo; + const CObjectVector *_externalCodecs; + #endif + + NWindows::CThread Thread; + NWindows::NSynchronization::CAutoResetEvent CompressEvent; + NWindows::NSynchronization::CAutoResetEvent CompressionCompletedEvent; + bool ExitThread; + + CMtCompressProgress *ProgressSpec; + CMyComPtr Progress; + + COutMemStream *OutStreamSpec; + CMyComPtr OutStream; + CMyComPtr InStream; + + CAddCommon Coder; + HRESULT Result; + CCompressingResult CompressingResult; + + bool IsFree; + UInt32 UpdateIndex; + + CThreadInfo(const CCompressionMethodMode &options): + ExitThread(false), + ProgressSpec(0), + OutStreamSpec(0), + Coder(options) + {} + + HRESULT CreateEvents() + { + RINOK(CompressEvent.CreateIfNotCreated()); + return CompressionCompletedEvent.CreateIfNotCreated(); + } + HRes CreateThread() { return Thread.Create(CoderThread, this); } + + void WaitAndCode(); + void StopWaitClose() + { + ExitThread = true; + if (OutStreamSpec != 0) + OutStreamSpec->StopWriting(E_ABORT); + if (CompressEvent.IsCreated()) + CompressEvent.Set(); + Thread.Wait(); + Thread.Close(); + } + +}; + +void CThreadInfo::WaitAndCode() +{ + for (;;) + { + CompressEvent.Lock(); + if (ExitThread) + return; + Result = Coder.Compress( + #ifdef EXTERNAL_CODECS + _codecsInfo, _externalCodecs, + #endif + InStream, OutStream, Progress, CompressingResult); + if (Result == S_OK && Progress) + Result = Progress->SetRatioInfo(&CompressingResult.UnpackSize, &CompressingResult.PackSize); + CompressionCompletedEvent.Set(); + } +} + +static THREAD_FUNC_DECL CoderThread(void *threadCoderInfo) +{ + ((CThreadInfo *)threadCoderInfo)->WaitAndCode(); + return 0; +} + +class CThreads +{ +public: + CObjectVector Threads; + ~CThreads() + { + for (int i = 0; i < Threads.Size(); i++) + Threads[i].StopWaitClose(); + } +}; + +struct CMemBlocks2: public CMemLockBlocks +{ + CCompressingResult CompressingResult; + bool Defined; + bool Skip; + CMemBlocks2(): Defined(false), Skip(false) {} +}; + +class CMemRefs +{ +public: + CMemBlockManagerMt *Manager; + CObjectVector Refs; + CMemRefs(CMemBlockManagerMt *manager): Manager(manager) {} ; + ~CMemRefs() + { + for (int i = 0; i < Refs.Size(); i++) + Refs[i].FreeOpt(Manager); + } +}; + +class CMtProgressMixer2: + public ICompressProgressInfo, + public CMyUnknownImp +{ + UInt64 ProgressOffset; + UInt64 InSizes[2]; + UInt64 OutSizes[2]; + CMyComPtr Progress; + CMyComPtr RatioProgress; + bool _inSizeIsMain; +public: + NWindows::NSynchronization::CCriticalSection CriticalSection; + MY_UNKNOWN_IMP + void Create(IProgress *progress, bool inSizeIsMain); + void SetProgressOffset(UInt64 progressOffset); + HRESULT SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize); + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); +}; + +void CMtProgressMixer2::Create(IProgress *progress, bool inSizeIsMain) +{ + Progress = progress; + Progress.QueryInterface(IID_ICompressProgressInfo, &RatioProgress); + _inSizeIsMain = inSizeIsMain; + ProgressOffset = InSizes[0] = InSizes[1] = OutSizes[0] = OutSizes[1] = 0; +} + +void CMtProgressMixer2::SetProgressOffset(UInt64 progressOffset) +{ + CriticalSection.Enter(); + InSizes[1] = OutSizes[1] = 0; + ProgressOffset = progressOffset; + CriticalSection.Leave(); +} + +HRESULT CMtProgressMixer2::SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize) +{ + NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection); + if (index == 0 && RatioProgress) + { + RINOK(RatioProgress->SetRatioInfo(inSize, outSize)); + } + if (inSize != 0) + InSizes[index] = *inSize; + if (outSize != 0) + OutSizes[index] = *outSize; + UInt64 v = ProgressOffset + (_inSizeIsMain ? + (InSizes[0] + InSizes[1]) : + (OutSizes[0] + OutSizes[1])); + return Progress->SetCompleted(&v); +} + +STDMETHODIMP CMtProgressMixer2::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) +{ + return SetRatioInfo(0, inSize, outSize); +} + +class CMtProgressMixer: + public ICompressProgressInfo, + public CMyUnknownImp +{ +public: + CMtProgressMixer2 *Mixer2; + CMyComPtr RatioProgress; + void Create(IProgress *progress, bool inSizeIsMain); + MY_UNKNOWN_IMP + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); +}; + +void CMtProgressMixer::Create(IProgress *progress, bool inSizeIsMain) +{ + Mixer2 = new CMtProgressMixer2; + RatioProgress = Mixer2; + Mixer2->Create(progress, inSizeIsMain); +} + +STDMETHODIMP CMtProgressMixer::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) +{ + return Mixer2->SetRatioInfo(1, inSize, outSize); +} + + +#endif + + +static HRESULT UpdateItemOldData(COutArchive &archive, + IInStream *inStream, + const CUpdateItem &ui, CItemEx &item, + /* bool izZip64, */ + ICompressProgressInfo *progress, + UInt64 &complexity) +{ + if (ui.NewProperties) + { + if (item.HasDescriptor()) + return E_NOTIMPL; + + // use old name size. + // CUpdateRange range(item.GetLocalExtraPosition(), item.LocalExtraSize + item.PackSize); + CUpdateRange range(item.GetDataPosition(), item.PackSize); + + // item.ExternalAttributes = ui.Attributes; + // Test it + item.Name = ui.Name; + item.SetUtf8(ui.IsUtf8); + item.Time = ui.Time; + item.NtfsMTime = ui.NtfsMTime; + item.NtfsATime = ui.NtfsATime; + item.NtfsCTime = ui.NtfsCTime; + item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined; + + item.CentralExtra.RemoveUnknownSubBlocks(); + item.LocalExtra.RemoveUnknownSubBlocks(); + + archive.PrepareWriteCompressedData2((UInt16)item.Name.Length(), item.UnPackSize, item.PackSize, item.LocalExtra.HasWzAesField()); + item.LocalHeaderPosition = archive.GetCurrentPosition(); + archive.SeekToPackedDataPosition(); + RINOK(WriteRange(inStream, archive, range, progress)); + complexity += range.Size; + archive.WriteLocalHeader(item); + } + else + { + CUpdateRange range(item.LocalHeaderPosition, item.GetLocalFullSize()); + + // set new header position + item.LocalHeaderPosition = archive.GetCurrentPosition(); + + RINOK(WriteRange(inStream, archive, range, progress)); + complexity += range.Size; + archive.MoveBasePosition(range.Size); + } + return S_OK; +} + +static void WriteDirHeader(COutArchive &archive, const CCompressionMethodMode *options, + const CUpdateItem &ui, CItemEx &item) +{ + SetFileHeader(archive, *options, ui, item); + archive.PrepareWriteCompressedData((UInt16)item.Name.Length(), ui.Size, options->IsAesMode); + archive.WriteLocalHeader(item); +} + +static HRESULT Update2St( + DECL_EXTERNAL_CODECS_LOC_VARS + COutArchive &archive, + CInArchive *inArchive, + IInStream *inStream, + const CObjectVector &inputItems, + const CObjectVector &updateItems, + const CCompressionMethodMode *options, + const CByteBuffer *comment, + IArchiveUpdateCallback *updateCallback) +{ + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(updateCallback, true); + + CAddCommon compressor(*options); + + CObjectVector items; + UInt64 unpackSizeTotal = 0, packSizeTotal = 0; + + for (int itemIndex = 0; itemIndex < updateItems.Size(); itemIndex++) + { + lps->InSize = unpackSizeTotal; + lps->OutSize = packSizeTotal; + RINOK(lps->SetCur()); + const CUpdateItem &ui = updateItems[itemIndex]; + CItemEx item; + if (!ui.NewProperties || !ui.NewData) + { + item = inputItems[ui.IndexInArchive]; + if (inArchive->ReadLocalItemAfterCdItemFull(item) != S_OK) + return E_NOTIMPL; + } + + if (ui.NewData) + { + bool isDir = ((ui.NewProperties) ? ui.IsDir : item.IsDir()); + if (isDir) + { + WriteDirHeader(archive, options, ui, item); + } + else + { + CMyComPtr fileInStream; + HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream); + if (res == S_FALSE) + { + lps->ProgressOffset += ui.Size; + RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); + continue; + } + RINOK(res); + + // file Size can be 64-bit !!! + SetFileHeader(archive, *options, ui, item); + archive.PrepareWriteCompressedData((UInt16)item.Name.Length(), ui.Size, options->IsAesMode); + CCompressingResult compressingResult; + CMyComPtr outStream; + archive.CreateStreamForCompressing(&outStream); + RINOK(compressor.Compress( + EXTERNAL_CODECS_LOC_VARS + fileInStream, outStream, progress, compressingResult)); + SetItemInfoFromCompressingResult(compressingResult, options->IsAesMode, options->AesKeyMode, item); + archive.WriteLocalHeader(item); + RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); + unpackSizeTotal += item.UnPackSize; + packSizeTotal += item.PackSize; + } + } + else + { + UInt64 complexity = 0; + lps->SendRatio = false; + RINOK(UpdateItemOldData(archive, inStream, ui, item, progress, complexity)); + lps->SendRatio = true; + lps->ProgressOffset += complexity; + } + items.Add(item); + lps->ProgressOffset += NFileHeader::kLocalBlockSize; + } + archive.WriteCentralDir(items, comment); + return S_OK; +} + +static HRESULT Update2( + DECL_EXTERNAL_CODECS_LOC_VARS + COutArchive &archive, + CInArchive *inArchive, + IInStream *inStream, + const CObjectVector &inputItems, + const CObjectVector &updateItems, + const CCompressionMethodMode *options, + const CByteBuffer *comment, + IArchiveUpdateCallback *updateCallback) +{ + UInt64 complexity = 0; + UInt64 numFilesToCompress = 0; + UInt64 numBytesToCompress = 0; + + int i; + for(i = 0; i < updateItems.Size(); i++) + { + const CUpdateItem &ui = updateItems[i]; + if (ui.NewData) + { + complexity += ui.Size; + numBytesToCompress += ui.Size; + numFilesToCompress++; + /* + if (ui.Commented) + complexity += ui.CommentRange.Size; + */ + } + else + { + CItemEx inputItem = inputItems[ui.IndexInArchive]; + if (inArchive->ReadLocalItemAfterCdItemFull(inputItem) != S_OK) + return E_NOTIMPL; + complexity += inputItem.GetLocalFullSize(); + // complexity += inputItem.GetCentralExtraPlusCommentSize(); + } + complexity += NFileHeader::kLocalBlockSize; + complexity += NFileHeader::kCentralBlockSize; + } + + if (comment) + complexity += comment->GetCapacity(); + complexity++; // end of central + updateCallback->SetTotal(complexity); + + CAddCommon compressor(*options); + + complexity = 0; + + #ifndef _7ZIP_ST + + const size_t kNumMaxThreads = (1 << 10); + UInt32 numThreads = options->NumThreads; + if (numThreads > kNumMaxThreads) + numThreads = kNumMaxThreads; + + const size_t kMemPerThread = (1 << 25); + const size_t kBlockSize = 1 << 16; + + CCompressionMethodMode options2; + if (options != 0) + options2 = *options; + + bool mtMode = ((options != 0) && (numThreads > 1)); + + if (numFilesToCompress <= 1) + mtMode = false; + + if (mtMode) + { + Byte method = options->MethodSequence.Front(); + if (method == NFileHeader::NCompressionMethod::kStored && !options->PasswordIsDefined) + mtMode = false; + if (method == NFileHeader::NCompressionMethod::kBZip2) + { + UInt64 averageSize = numBytesToCompress / numFilesToCompress; + UInt32 blockSize = options->DicSize; + if (blockSize == 0) + blockSize = 1; + UInt64 averageNumberOfBlocks = averageSize / blockSize; + UInt32 numBZip2Threads = 32; + if (averageNumberOfBlocks < numBZip2Threads) + numBZip2Threads = (UInt32)averageNumberOfBlocks; + if (numBZip2Threads < 1) + numBZip2Threads = 1; + numThreads = numThreads / numBZip2Threads; + options2.NumThreads = numBZip2Threads; + if (numThreads <= 1) + mtMode = false; + } + if (method == NFileHeader::NCompressionMethod::kLZMA) + { + UInt32 numLZMAThreads = (options->Algo > 0 ? 2 : 1); + numThreads /= numLZMAThreads; + options2.NumThreads = numLZMAThreads; + if (numThreads <= 1) + mtMode = false; + } + } + + if (!mtMode) + #endif + return Update2St( + EXTERNAL_CODECS_LOC_VARS + archive, inArchive,inStream, + inputItems, updateItems, options, comment, updateCallback); + + + #ifndef _7ZIP_ST + + CObjectVector items; + + CMtProgressMixer *mtProgressMixerSpec = new CMtProgressMixer; + CMyComPtr progress = mtProgressMixerSpec; + mtProgressMixerSpec->Create(updateCallback, true); + + CMtCompressProgressMixer mtCompressProgressMixer; + mtCompressProgressMixer.Init(numThreads, mtProgressMixerSpec->RatioProgress); + + CMemBlockManagerMt memManager(kBlockSize); + CMemRefs refs(&memManager); + + CThreads threads; + CRecordVector compressingCompletedEvents; + CRecordVector threadIndices; // list threads in order of updateItems + + { + RINOK(memManager.AllocateSpaceAlways((size_t)numThreads * (kMemPerThread / kBlockSize))); + for(i = 0; i < updateItems.Size(); i++) + refs.Refs.Add(CMemBlocks2()); + + UInt32 i; + for (i = 0; i < numThreads; i++) + threads.Threads.Add(CThreadInfo(options2)); + + for (i = 0; i < numThreads; i++) + { + CThreadInfo &threadInfo = threads.Threads[i]; + #ifdef EXTERNAL_CODECS + threadInfo._codecsInfo = codecsInfo; + threadInfo._externalCodecs = externalCodecs; + #endif + RINOK(threadInfo.CreateEvents()); + threadInfo.OutStreamSpec = new COutMemStream(&memManager); + RINOK(threadInfo.OutStreamSpec->CreateEvents()); + threadInfo.OutStream = threadInfo.OutStreamSpec; + threadInfo.IsFree = true; + threadInfo.ProgressSpec = new CMtCompressProgress(); + threadInfo.Progress = threadInfo.ProgressSpec; + threadInfo.ProgressSpec->Init(&mtCompressProgressMixer, (int)i); + RINOK(threadInfo.CreateThread()); + } + } + int mtItemIndex = 0; + + int itemIndex = 0; + int lastRealStreamItemIndex = -1; + + while (itemIndex < updateItems.Size()) + { + if ((UInt32)threadIndices.Size() < numThreads && mtItemIndex < updateItems.Size()) + { + const CUpdateItem &ui = updateItems[mtItemIndex++]; + if (!ui.NewData) + continue; + CItemEx item; + if (ui.NewProperties) + { + if (ui.IsDir) + continue; + } + else + { + item = inputItems[ui.IndexInArchive]; + if (inArchive->ReadLocalItemAfterCdItemFull(item) != S_OK) + return E_NOTIMPL; + if (item.IsDir()) + continue; + } + CMyComPtr fileInStream; + { + NWindows::NSynchronization::CCriticalSectionLock lock(mtProgressMixerSpec->Mixer2->CriticalSection); + HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream); + if (res == S_FALSE) + { + complexity += ui.Size; + complexity += NFileHeader::kLocalBlockSize; + mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity); + RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); + refs.Refs[mtItemIndex - 1].Skip = true; + continue; + } + RINOK(res); + RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); + } + + for (UInt32 i = 0; i < numThreads; i++) + { + CThreadInfo &threadInfo = threads.Threads[i]; + if (threadInfo.IsFree) + { + threadInfo.IsFree = false; + threadInfo.InStream = fileInStream; + + // !!!!! we must release ref before sending event + // BUG was here in v4.43 and v4.44. It could change ref counter in two threads in same time + fileInStream.Release(); + + threadInfo.OutStreamSpec->Init(); + threadInfo.ProgressSpec->Reinit(); + threadInfo.CompressEvent.Set(); + threadInfo.UpdateIndex = mtItemIndex - 1; + + compressingCompletedEvents.Add(threadInfo.CompressionCompletedEvent); + threadIndices.Add(i); + break; + } + } + continue; + } + + if (refs.Refs[itemIndex].Skip) + { + itemIndex++; + continue; + } + + const CUpdateItem &ui = updateItems[itemIndex]; + + CItemEx item; + if (!ui.NewProperties || !ui.NewData) + { + item = inputItems[ui.IndexInArchive]; + if (inArchive->ReadLocalItemAfterCdItemFull(item) != S_OK) + return E_NOTIMPL; + } + + if (ui.NewData) + { + bool isDir = ((ui.NewProperties) ? ui.IsDir : item.IsDir()); + if (isDir) + { + WriteDirHeader(archive, options, ui, item); + } + else + { + if (lastRealStreamItemIndex < itemIndex) + { + lastRealStreamItemIndex = itemIndex; + SetFileHeader(archive, *options, ui, item); + // file Size can be 64-bit !!! + archive.PrepareWriteCompressedData((UInt16)item.Name.Length(), ui.Size, options->IsAesMode); + } + + CMemBlocks2 &memRef = refs.Refs[itemIndex]; + if (memRef.Defined) + { + CMyComPtr outStream; + archive.CreateStreamForCompressing(&outStream); + memRef.WriteToStream(memManager.GetBlockSize(), outStream); + SetItemInfoFromCompressingResult(memRef.CompressingResult, + options->IsAesMode, options->AesKeyMode, item); + SetFileHeader(archive, *options, ui, item); + archive.WriteLocalHeader(item); + // RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); + memRef.FreeOpt(&memManager); + } + else + { + { + CThreadInfo &thread = threads.Threads[threadIndices.Front()]; + if (!thread.OutStreamSpec->WasUnlockEventSent()) + { + CMyComPtr outStream; + archive.CreateStreamForCompressing(&outStream); + thread.OutStreamSpec->SetOutStream(outStream); + thread.OutStreamSpec->SetRealStreamMode(); + } + } + + DWORD result = ::WaitForMultipleObjects(compressingCompletedEvents.Size(), + &compressingCompletedEvents.Front(), FALSE, INFINITE); + int t = (int)(result - WAIT_OBJECT_0); + CThreadInfo &threadInfo = threads.Threads[threadIndices[t]]; + threadInfo.InStream.Release(); + threadInfo.IsFree = true; + RINOK(threadInfo.Result); + threadIndices.Delete(t); + compressingCompletedEvents.Delete(t); + if (t == 0) + { + RINOK(threadInfo.OutStreamSpec->WriteToRealStream()); + threadInfo.OutStreamSpec->ReleaseOutStream(); + SetItemInfoFromCompressingResult(threadInfo.CompressingResult, + options->IsAesMode, options->AesKeyMode, item); + SetFileHeader(archive, *options, ui, item); + archive.WriteLocalHeader(item); + } + else + { + CMemBlocks2 &memRef = refs.Refs[threadInfo.UpdateIndex]; + threadInfo.OutStreamSpec->DetachData(memRef); + memRef.CompressingResult = threadInfo.CompressingResult; + memRef.Defined = true; + continue; + } + } + } + } + else + { + RINOK(UpdateItemOldData(archive, inStream, ui, item, progress, complexity)); + } + items.Add(item); + complexity += NFileHeader::kLocalBlockSize; + mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity); + itemIndex++; + } + archive.WriteCentralDir(items, comment); + return S_OK; + #endif +} + +static const size_t kCacheBlockSize = (1 << 20); +static const size_t kCacheSize = (kCacheBlockSize << 2); +static const size_t kCacheMask = (kCacheSize - 1); + +class CCacheOutStream: + public IOutStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + Byte *_cache; + UInt64 _virtPos; + UInt64 _virtSize; + UInt64 _phyPos; + UInt64 _phySize; // <= _virtSize + UInt64 _cachedPos; // (_cachedPos + _cachedSize) <= _virtSize + size_t _cachedSize; + + HRESULT MyWrite(size_t size); + HRESULT MyWriteBlock() + { + return MyWrite(kCacheBlockSize - ((size_t)_cachedPos & (kCacheBlockSize - 1))); + } + HRESULT FlushCache(); +public: + CCacheOutStream(): _cache(0) {} + ~CCacheOutStream(); + bool Allocate(); + HRESULT Init(IOutStream *stream); + + MY_UNKNOWN_IMP + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + STDMETHOD(SetSize)(UInt64 newSize); +}; + +bool CCacheOutStream::Allocate() +{ + if (!_cache) + _cache = (Byte *)::MidAlloc(kCacheSize); + return (_cache != NULL); +} + +HRESULT CCacheOutStream::Init(IOutStream *stream) +{ + _virtPos = _phyPos = 0; + _stream = stream; + RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &_virtPos)); + RINOK(_stream->Seek(0, STREAM_SEEK_END, &_virtSize)); + RINOK(_stream->Seek(_virtPos, STREAM_SEEK_SET, &_virtPos)); + _phyPos = _virtPos; + _phySize = _virtSize; + _cachedPos = 0; + _cachedSize = 0; + return S_OK; +} + +HRESULT CCacheOutStream::MyWrite(size_t size) +{ + while (size != 0 && _cachedSize != 0) + { + if (_phyPos != _cachedPos) + { + RINOK(_stream->Seek(_cachedPos, STREAM_SEEK_SET, &_phyPos)); + } + size_t pos = (size_t)_cachedPos & kCacheMask; + size_t curSize = MyMin(kCacheSize - pos, _cachedSize); + curSize = MyMin(curSize, size); + RINOK(WriteStream(_stream, _cache + pos, curSize)); + _phyPos += curSize; + if (_phySize < _phyPos) + _phySize = _phyPos; + _cachedPos += curSize; + _cachedSize -= curSize; + size -= curSize; + } + return S_OK; +} + +HRESULT CCacheOutStream::FlushCache() +{ + return MyWrite(_cachedSize); +} + +CCacheOutStream::~CCacheOutStream() +{ + FlushCache(); + if (_virtSize != _phySize) + _stream->SetSize(_virtSize); + if (_virtPos != _phyPos) + _stream->Seek(_virtPos, STREAM_SEEK_SET, NULL); + ::MidFree(_cache); +} + +STDMETHODIMP CCacheOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (size == 0) + return S_OK; + + UInt64 zerosStart = _virtPos; + if (_cachedSize != 0) + { + if (_virtPos < _cachedPos) + { + RINOK(FlushCache()); + } + else + { + UInt64 cachedEnd = _cachedPos + _cachedSize; + if (cachedEnd < _virtPos) + { + if (cachedEnd < _phySize) + { + RINOK(FlushCache()); + } + else + zerosStart = cachedEnd; + } + } + } + + if (_cachedSize == 0 && _phySize < _virtPos) + _cachedPos = zerosStart = _phySize; + + if (zerosStart != _virtPos) + { + // write zeros to [cachedEnd ... _virtPos) + + for (;;) + { + UInt64 cachedEnd = _cachedPos + _cachedSize; + size_t endPos = (size_t)cachedEnd & kCacheMask; + size_t curSize = kCacheSize - endPos; + if (curSize > _virtPos - cachedEnd) + curSize = (size_t)(_virtPos - cachedEnd); + if (curSize == 0) + break; + while (curSize > (kCacheSize - _cachedSize)) + { + RINOK(MyWriteBlock()); + } + memset(_cache + endPos, 0, curSize); + _cachedSize += curSize; + } + } + + if (_cachedSize == 0) + _cachedPos = _virtPos; + + size_t pos = (size_t)_virtPos & kCacheMask; + size = (UInt32)MyMin((size_t)size, kCacheSize - pos); + UInt64 cachedEnd = _cachedPos + _cachedSize; + if (_virtPos != cachedEnd) // _virtPos < cachedEnd + size = (UInt32)MyMin((size_t)size, (size_t)(cachedEnd - _virtPos)); + else + { + // _virtPos == cachedEnd + if (_cachedSize == kCacheSize) + { + RINOK(MyWriteBlock()); + } + size_t startPos = (size_t)_cachedPos & kCacheMask; + if (startPos > pos) + size = (UInt32)MyMin((size_t)size, (size_t)(startPos - pos)); + _cachedSize += size; + } + memcpy(_cache + pos, data, size); + if (processedSize) + *processedSize = size; + _virtPos += size; + if (_virtSize < _virtPos) + _virtSize = _virtPos; + return S_OK; +} + +STDMETHODIMP CCacheOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch(seekOrigin) + { + case STREAM_SEEK_SET: _virtPos = offset; break; + case STREAM_SEEK_CUR: _virtPos += offset; break; + case STREAM_SEEK_END: _virtPos = _virtSize + offset; break; + default: return STG_E_INVALIDFUNCTION; + } + if (newPosition) + *newPosition = _virtPos; + return S_OK; +} + +STDMETHODIMP CCacheOutStream::SetSize(UInt64 newSize) +{ + _virtSize = newSize; + if (newSize < _phySize) + { + RINOK(_stream->SetSize(newSize)); + _phySize = newSize; + } + if (newSize <= _cachedPos) + { + _cachedSize = 0; + _cachedPos = newSize; + } + if (newSize < _cachedPos + _cachedSize) + _cachedSize = (size_t)(newSize - _cachedPos); + return S_OK; +} + + +HRESULT Update( + DECL_EXTERNAL_CODECS_LOC_VARS + const CObjectVector &inputItems, + const CObjectVector &updateItems, + ISequentialOutStream *seqOutStream, + CInArchive *inArchive, + CCompressionMethodMode *compressionMethodMode, + IArchiveUpdateCallback *updateCallback) +{ + CMyComPtr outStream; + { + CMyComPtr outStreamReal; + seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStreamReal); + if (!outStreamReal) + return E_NOTIMPL; + CCacheOutStream *cacheStream = new CCacheOutStream(); + outStream = cacheStream; + if (!cacheStream->Allocate()) + return E_OUTOFMEMORY; + RINOK(cacheStream->Init(outStreamReal)); + } + + if (inArchive) + { + if (inArchive->ArcInfo.Base != 0 || + inArchive->ArcInfo.StartPosition != 0 || + !inArchive->IsOkHeaders) + return E_NOTIMPL; + } + + COutArchive outArchive; + outArchive.Create(outStream); + /* + if (inArchive && inArchive->ArcInfo.StartPosition > 0) + { + CMyComPtr inStream; + inStream.Attach(inArchive->CreateLimitedStream(0, inArchive->ArcInfo.StartPosition)); + RINOK(CopyBlockToArchive(inStream, outArchive, NULL)); + outArchive.MoveBasePosition(inArchive->ArcInfo.StartPosition); + } + */ + CMyComPtr inStream; + if (inArchive) + inStream.Attach(inArchive->CreateStream()); + + return Update2( + EXTERNAL_CODECS_LOC_VARS + outArchive, inArchive, inStream, + inputItems, updateItems, + compressionMethodMode, + inArchive ? &inArchive->ArcInfo.Comment : NULL, + updateCallback); +} + +}} diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.h b/CPP/7zip/Archive/Zip/ZipUpdate.h new file mode 100755 index 0000000..75b4781 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipUpdate.h @@ -0,0 +1,58 @@ +// Zip/Update.h + +#ifndef __ZIP_UPDATE_H +#define __ZIP_UPDATE_H + +#include "../../ICoder.h" +#include "../IArchive.h" + +#include "../../Common/CreateCoder.h" + +#include "ZipCompressionMode.h" +#include "ZipIn.h" + +namespace NArchive { +namespace NZip { + +struct CUpdateRange +{ + UInt64 Position; + UInt64 Size; + CUpdateRange() {}; + CUpdateRange(UInt64 position, UInt64 size): Position(position), Size(size) {}; +}; + +struct CUpdateItem +{ + bool NewData; + bool NewProperties; + bool IsDir; + bool NtfsTimeIsDefined; + bool IsUtf8; + int IndexInArchive; + int IndexInClient; + UInt32 Attributes; + UInt32 Time; + UInt64 Size; + AString Name; + // bool Commented; + // CUpdateRange CommentRange; + FILETIME NtfsMTime; + FILETIME NtfsATime; + FILETIME NtfsCTime; + + CUpdateItem(): NtfsTimeIsDefined(false), IsUtf8(false), Size(0) {} +}; + +HRESULT Update( + DECL_EXTERNAL_CODECS_LOC_VARS + const CObjectVector &inputItems, + const CObjectVector &updateItems, + ISequentialOutStream *seqOutStream, + CInArchive *inArchive, + CCompressionMethodMode *compressionMethodMode, + IArchiveUpdateCallback *updateCallback); + +}} + +#endif diff --git a/CPP/7zip/Archive/makefile b/CPP/7zip/Archive/makefile new file mode 100755 index 0000000..96d8d78 --- /dev/null +++ b/CPP/7zip/Archive/makefile @@ -0,0 +1,23 @@ +DIRS = \ + 7z\~ \ + Arj\~ \ + BZip2\~ \ + Cab\~ \ + Chm\~ \ + Cpio\~ \ + Deb\~ \ + GZip\~ \ + Iso\~ \ + Lzh\~ \ + Nsis\~ \ + Rar\~ \ + RPM\~ \ + Split\~ \ + Tar\~ \ + Z\~ \ + Zip\~ \ + +all: $(DIRS) + +$(DIRS): +!include "../SubBuild.mak" diff --git a/CPP/7zip/Asm.mak b/CPP/7zip/Asm.mak new file mode 100755 index 0000000..0284903 --- /dev/null +++ b/CPP/7zip/Asm.mak @@ -0,0 +1,7 @@ +!IF "$(CPU)" == "ARM" +$(ASM_OBJS): ../../../../Asm/Arm/$(*B).asm + $(COMPL_ASM) +!ELSEIF "$(CPU)" != "IA64" && "$(CPU)" != "MIPS" +$(ASM_OBJS): ../../../../Asm/x86/$(*B).asm + $(COMPL_ASM) +!ENDIF diff --git a/CPP/7zip/Bundles/Alone/Alone.dsp b/CPP/7zip/Bundles/Alone/Alone.dsp new file mode 100755 index 0000000..5a4e097 --- /dev/null +++ b/CPP/7zip/Bundles/Alone/Alone.dsp @@ -0,0 +1,2928 @@ +# 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 /Gz /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /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 +# 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\7za.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 /Gz /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 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 + +!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 /Gz /MD /W3 /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 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\7zan.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 /Gz /MDd /W3 /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 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\7zan.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\List.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\List.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\Main.cpp +# 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\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\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 +# 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\Error.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Error.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\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\PropVariantConversions.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariantConversions.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\Time.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Time.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=..\..\Archive\Common\CrossThreadProgress.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\CrossThreadProgress.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\MemBlocks.cpp +# 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\OutMemStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OutMemStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressMt.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressMt.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\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 "Compress" + +# PROP Default_Filter "" +# Begin Group "BZip2" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\BZip2Crc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BZip2Crc.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BZip2Decoder.cpp + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BZip2Decoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BZip2Encoder.cpp + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BZip2Encoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BZip2Register.cpp +# End Source File +# End Group +# Begin Group "Copy" + +# PROP Default_Filter "" +# 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 +# End Group +# Begin Group "Deflate" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\Deflate64Register.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\DeflateConst.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\DeflateDecoder.cpp + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\DeflateDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\DeflateEncoder.cpp + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\DeflateEncoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\DeflateExtConst.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\DeflateRegister.cpp +# End Source File +# End Group +# Begin Group "Huffman" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\HuffmanDecoder.h +# End Source File +# End Group +# Begin Group "Implode" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\ImplodeDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\ImplodeDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\ImplodeHuffmanDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\ImplodeHuffmanDecoder.h +# End Source File +# End Group +# Begin Group "LZMA" + +# PROP Default_Filter "" +# 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 + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzmaDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzmaEncoder.cpp + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +!ENDIF + +# 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 "PPMd" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\PpmdContext.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\PpmdDecode.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\PpmdDecoder.cpp + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\PpmdDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\PpmdEncode.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\PpmdEncoder.cpp + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\PpmdEncoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\PpmdRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\PpmdSubAlloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\PpmdType.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\PpmdZip.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\PpmdZip.h +# End Source File +# End Group +# Begin Group "RangeCoder" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\RangeCoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\RangeCoderBit.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\RangeCoderBitTree.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\RangeCoderOpt.h +# End Source File +# End Group +# Begin Group "Shrink" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\ShrinkDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\ShrinkDecoder.h +# End Source File +# End Group +# Begin Group "Z" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\ZDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\ZDecoder.h +# End Source File +# End Group +# Begin Group "BWT" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\Mtf8.h +# End Source File +# End Group +# Begin Group "LZX" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\Lzx.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzx86Converter.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzx86Converter.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzxDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzxDecoder.h +# End Source File +# End Group +# Begin Group "Quantum" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\QuantumDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\QuantumDecoder.h +# End Source File +# End Group +# 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\BitlDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BitlDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BitlEncoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BitmDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BitmEncoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BranchCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BranchCoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BranchMisc.cpp +# End Source File +# Begin Source File + +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\DeltaFilter.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzOutWindow.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzOutWindow.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\7zFolderOutStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zFolderOutStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHandlerOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHeader.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHeader.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zIn.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zIn.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zItem.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zOut.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zProperties.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zProperties.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zSpecStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zSpecStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zUpdate.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zUpdate.h +# End Source File +# End Group +# Begin Group "tar" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarHandlerOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarHeader.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarHeader.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarIn.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarIn.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarItem.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarOut.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarUpdate.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarUpdate.h +# End Source File +# End Group +# Begin Group "zip" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipAddCommon.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipAddCommon.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipCompressionMode.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipHandlerOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipHeader.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipHeader.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipIn.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipIn.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipItem.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipItem.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipItemEx.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipOut.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipUpdate.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipUpdate.h +# End Source File +# End Group +# Begin Group "Archive Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Common\CoderLoader.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\CoderMixer2.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\CoderMixer2.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\CoderMixer2MT.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\DummyOutStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\DummyOutStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\FindSignature.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\FindSignature.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\HandlerOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\HandlerOut.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\InStreamWithCRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\InStreamWithCRC.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\ItemNameUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\ItemNameUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\MultiStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\MultiStream.h +# End Source File +# Begin Source File + +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 Group "cab" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Cab\CabBlockInStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Cab\CabBlockInStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Cab\CabHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Cab\CabHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Cab\CabHeader.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Cab\CabHeader.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Cab\CabIn.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Cab\CabIn.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Cab\CabItem.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Cab\CabRegister.cpp +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\Archive\Bz2Handler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\DeflateProps.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\DeflateProps.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\GzHandler.cpp +# 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 +# Begin Source File + +SOURCE=..\..\Archive\ZHandler.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\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 +# 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 +# Begin Source File + +SOURCE=..\..\UI\Common\WorkDir.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\WorkDir.h +# End Source File +# End Group +# Begin Group "Crypto" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Crypto\7zAes.cpp + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +!ENDIF + +# 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\HmacSha1.cpp + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\HmacSha1.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\MyAes.cpp + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\MyAes.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Pbkdf2HmacSha1.cpp + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Pbkdf2HmacSha1.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\RandGen.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\RandGen.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Sha1.cpp + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Sha1.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\WzAes.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\WzAes.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\ZipCrypto.cpp + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O1 + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# ADD CPP /O1 + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\ZipCrypto.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\ZipStrong.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\ZipStrong.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\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\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 + +!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\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" + +# 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 + +!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.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 + +!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.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\Bra.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.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bra86.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\BraIA64.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\BwtSort.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\BwtSort.h +# 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" + +# 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\HuffEnc.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\HuffEnc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\IStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzFind.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\LzFind.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzFindMt.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\LzFindMt.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\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 + +!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\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\Ppmd.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Ppmd7.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\Ppmd7.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Ppmd7Dec.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\Ppmd7Enc.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\Ppmd8.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\Ppmd8.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Ppmd8Dec.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\Ppmd8Enc.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\RotateDefs.h +# End Source File +# 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\Sort.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\Sort.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Threads.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\Threads.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Types.h +# End Source File +# End Group +# End Target +# End Project diff --git a/CPP/7zip/Bundles/Alone/Alone.dsw b/CPP/7zip/Bundles/Alone/Alone.dsw new file mode 100755 index 0000000..036aab4 --- /dev/null +++ b/CPP/7zip/Bundles/Alone/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/CPP/7zip/Bundles/Alone/StdAfx.cpp b/CPP/7zip/Bundles/Alone/StdAfx.cpp new file mode 100755 index 0000000..c6d3b1f --- /dev/null +++ b/CPP/7zip/Bundles/Alone/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/Bundles/Alone/StdAfx.h b/CPP/7zip/Bundles/Alone/StdAfx.h new file mode 100755 index 0000000..a4e6173 --- /dev/null +++ b/CPP/7zip/Bundles/Alone/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" +#include "../../../Common/NewHandler.h" + +#endif diff --git a/CPP/7zip/Bundles/Alone/afxres.h b/CPP/7zip/Bundles/Alone/afxres.h new file mode 100755 index 0000000..f646cce --- /dev/null +++ b/CPP/7zip/Bundles/Alone/afxres.h @@ -0,0 +1 @@ +#include diff --git a/CPP/7zip/Bundles/Alone/makefile b/CPP/7zip/Bundles/Alone/makefile new file mode 100755 index 0000000..ce1c8f7 --- /dev/null +++ b/CPP/7zip/Bundles/Alone/makefile @@ -0,0 +1,308 @@ +PROG = 7za.exe +MY_CONSOLE = 1 +CFLAGS = $(CFLAGS) -I ../../../ + +!IFNDEF UNDER_CE +CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -D_7ZIP_LARGE_PAGES -DSUPPORT_DEVICE_FILE +!ENDIF + +CONSOLE_OBJS = \ + $O\BenchCon.obj \ + $O\ConsoleClose.obj \ + $O\ExtractCallbackConsole.obj \ + $O\List.obj \ + $O\Main.obj \ + $O\MainAr.obj \ + $O\OpenCallbackConsole.obj \ + $O\PercentPrinter.obj \ + $O\UpdateCallbackConsole.obj \ + $O\UserInputUtils.obj \ + +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\Error.obj \ + $O\FileDir.obj \ + $O\FileFind.obj \ + $O\FileIO.obj \ + $O\FileName.obj \ + $O\MemoryLock.obj \ + $O\PropVariant.obj \ + $O\PropVariantConversions.obj \ + $O\Synchronization.obj \ + $O\System.obj \ + $O\Time.obj \ + +7ZIP_COMMON_OBJS = \ + $O\CreateCoder.obj \ + $O\CWrappers.obj \ + $O\FilePathAutoRename.obj \ + $O\FileStreams.obj \ + $O\FilterCoder.obj \ + $O\InBuffer.obj \ + $O\InOutTempBuffer.obj \ + $O\LimitedStreams.obj \ + $O\LockedStream.obj \ + $O\MemBlocks.obj \ + $O\MethodId.obj \ + $O\MethodProps.obj \ + $O\OffsetStream.obj \ + $O\OutBuffer.obj \ + $O\OutMemStream.obj \ + $O\ProgressMt.obj \ + $O\ProgressUtils.obj \ + $O\StreamBinder.obj \ + $O\StreamObjects.obj \ + $O\StreamUtils.obj \ + $O\VirtThread.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\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 \ + $O\WorkDir.obj \ + +AR_OBJS = \ + $O\Bz2Handler.obj \ + $O\DeflateProps.obj \ + $O\GzHandler.obj \ + $O\LzmaHandler.obj \ + $O\SplitHandler.obj \ + $O\XzHandler.obj \ + $O\ZHandler.obj \ + +AR_COMMON_OBJS = \ + $O\CoderMixer2.obj \ + $O\CoderMixer2MT.obj \ + $O\CrossThreadProgress.obj \ + $O\DummyOutStream.obj \ + $O\FindSignature.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\7zFolderOutStream.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 \ + +CAB_OBJS = \ + $O\CabBlockInStream.obj \ + $O\CabHandler.obj \ + $O\CabHeader.obj \ + $O\CabIn.obj \ + $O\CabRegister.obj \ + +TAR_OBJS = \ + $O\TarHandler.obj \ + $O\TarHandlerOut.obj \ + $O\TarHeader.obj \ + $O\TarIn.obj \ + $O\TarOut.obj \ + $O\TarUpdate.obj \ + $O\TarRegister.obj \ + +ZIP_OBJS = \ + $O\ZipAddCommon.obj \ + $O\ZipHandler.obj \ + $O\ZipHandlerOut.obj \ + $O\ZipHeader.obj \ + $O\ZipIn.obj \ + $O\ZipItem.obj \ + $O\ZipOut.obj \ + $O\ZipUpdate.obj \ + $O\ZipRegister.obj \ + + +COMPRESS_OBJS = \ + $O\Bcj2Coder.obj \ + $O\Bcj2Register.obj \ + $O\BcjCoder.obj \ + $O\BcjRegister.obj \ + $O\BitlDecoder.obj \ + $O\BranchCoder.obj \ + $O\BranchMisc.obj \ + $O\BranchRegister.obj \ + $O\ByteSwap.obj \ + $O\BZip2CRC.obj \ + $O\BZip2Decoder.obj \ + $O\BZip2Encoder.obj \ + $O\BZip2Register.obj \ + $O\CopyCoder.obj \ + $O\CopyRegister.obj \ + $O\Deflate64Register.obj \ + $O\DeflateDecoder.obj \ + $O\DeflateEncoder.obj \ + $O\DeflateRegister.obj \ + $O\DeltaFilter.obj \ + $O\ImplodeDecoder.obj \ + $O\ImplodeHuffmanDecoder.obj \ + $O\Lzma2Decoder.obj \ + $O\Lzma2Encoder.obj \ + $O\Lzma2Register.obj \ + $O\LzmaDecoder.obj \ + $O\LzmaEncoder.obj \ + $O\LzmaRegister.obj \ + $O\LzOutWindow.obj \ + $O\Lzx86Converter.obj \ + $O\LzxDecoder.obj \ + $O\PpmdDecoder.obj \ + $O\PpmdEncoder.obj \ + $O\PpmdRegister.obj \ + $O\PpmdZip.obj \ + $O\QuantumDecoder.obj \ + $O\ShrinkDecoder.obj \ + $O\ZDecoder.obj \ + +CRYPTO_OBJS = \ + $O\7zAes.obj \ + $O\7zAesRegister.obj \ + $O\HmacSha1.obj \ + $O\MyAes.obj \ + $O\Pbkdf2HmacSha1.obj \ + $O\RandGen.obj \ + $O\Sha1.obj \ + $O\WzAes.obj \ + $O\ZipCrypto.obj \ + $O\ZipStrong.obj \ + +C_OBJS = \ + $O\7zStream.obj \ + $O\Alloc.obj \ + $O\Bra.obj \ + $O\Bra86.obj \ + $O\BraIA64.obj \ + $O\BwtSort.obj \ + $O\CpuArch.obj \ + $O\Delta.obj \ + $O\HuffEnc.obj \ + $O\LzFind.obj \ + $O\LzFindMt.obj \ + $O\Lzma2Dec.obj \ + $O\Lzma2Enc.obj \ + $O\LzmaDec.obj \ + $O\LzmaEnc.obj \ + $O\MtCoder.obj \ + $O\Ppmd7.obj \ + $O\Ppmd7Dec.obj \ + $O\Ppmd7Enc.obj \ + $O\Ppmd8.obj \ + $O\Ppmd8Dec.obj \ + $O\Ppmd8Enc.obj \ + $O\Sha256.obj \ + $O\Sort.obj \ + $O\Threads.obj \ + $O\Xz.obj \ + $O\XzCrc64.obj \ + $O\XzDec.obj \ + $O\XzEnc.obj \ + $O\XzIn.obj \ + +!include "../../Aes.mak" +!include "../../Crc.mak" + +OBJS = \ + $O\StdAfx.obj \ + $(CONSOLE_OBJS) \ + $(COMMON_OBJS) \ + $(COMMON_OBJS_O2) \ + $(WIN_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(UI_COMMON_OBJS) \ + $(AR_OBJS) \ + $(AR_COMMON_OBJS) \ + $(7Z_OBJS) \ + $(CAB_OBJS) \ + $(TAR_OBJS) \ + $(ZIP_OBJS) \ + $(COMPRESS_OBJS) \ + $(LZMA_BENCH_OBJS) \ + $(CRYPTO_OBJS) \ + $(C_OBJS) \ + $(ASM_OBJS) \ + $O\resource.res + + +!include "../../../Build.mak" + +$(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp + $(COMPL) + +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) +$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp + $(COMPL) +$(AR_OBJS): ../../Archive/$(*B).cpp + $(COMPL) +$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp + $(COMPL) + +$(7Z_OBJS): ../../Archive/7z/$(*B).cpp + $(COMPL) +$(CAB_OBJS): ../../Archive/Cab/$(*B).cpp + $(COMPL) +$(TAR_OBJS): ../../Archive/Tar/$(*B).cpp + $(COMPL) +$(ZIP_OBJS): ../../Archive/Zip/$(*B).cpp + $(COMPL) + +$(COMPRESS_OBJS): ../../Compress/$(*B).cpp + $(COMPL_O2) + +$(CRYPTO_OBJS): ../../Crypto/$(*B).cpp + $(COMPL_O2) + +$(C_OBJS): ../../../../C/$(*B).c + $(COMPL_O2) + +!include "../../Asm.mak" diff --git a/CPP/7zip/Bundles/Alone/resource.rc b/CPP/7zip/Bundles/Alone/resource.rc new file mode 100755 index 0000000..9b81707 --- /dev/null +++ b/CPP/7zip/Bundles/Alone/resource.rc @@ -0,0 +1,3 @@ +#include "../../MyVersionInfo.rc" + +MY_VERSION_INFO_APP("7-Zip Standalone Console", "7za") diff --git a/CPP/7zip/Bundles/Alone7z/StdAfx.cpp b/CPP/7zip/Bundles/Alone7z/StdAfx.cpp new file mode 100755 index 0000000..c6d3b1f --- /dev/null +++ b/CPP/7zip/Bundles/Alone7z/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/Bundles/Alone7z/StdAfx.h b/CPP/7zip/Bundles/Alone7z/StdAfx.h new file mode 100755 index 0000000..a4e6173 --- /dev/null +++ b/CPP/7zip/Bundles/Alone7z/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" +#include "../../../Common/NewHandler.h" + +#endif diff --git a/CPP/7zip/Bundles/Alone7z/makefile b/CPP/7zip/Bundles/Alone7z/makefile new file mode 100755 index 0000000..3132895 --- /dev/null +++ b/CPP/7zip/Bundles/Alone7z/makefile @@ -0,0 +1,213 @@ +PROG = 7zr.exe +MY_CONSOLE = 1 +CFLAGS = $(CFLAGS) -I ../../../ \ + -D_NO_CRYPTO \ + +!IFNDEF UNDER_CE +CFLAGS = $(CFLAGS) -DWIN_LONG_PATH +!ENDIF + +CONSOLE_OBJS = \ + $O\BenchCon.obj \ + $O\ConsoleClose.obj \ + $O\ExtractCallbackConsole.obj \ + $O\List.obj \ + $O\Main.obj \ + $O\MainAr.obj \ + $O\OpenCallbackConsole.obj \ + $O\PercentPrinter.obj \ + $O\UpdateCallbackConsole.obj \ + $O\UserInputUtils.obj \ + +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\Error.obj \ + $O\FileDir.obj \ + $O\FileFind.obj \ + $O\FileIO.obj \ + $O\FileName.obj \ + $O\MemoryLock.obj \ + $O\PropVariant.obj \ + $O\PropVariantConversions.obj \ + $O\Synchronization.obj \ + $O\System.obj \ + $O\Time.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\LockedStream.obj \ + $O\MethodId.obj \ + $O\MethodProps.obj \ + $O\OffsetStream.obj \ + $O\OutBuffer.obj \ + $O\ProgressUtils.obj \ + $O\StreamBinder.obj \ + $O\StreamObjects.obj \ + $O\StreamUtils.obj \ + $O\VirtThread.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\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 \ + $O\WorkDir.obj \ + +AR_OBJS = \ + $O\LzmaHandler.obj \ + $O\SplitHandler.obj \ + $O\XzHandler.obj \ + +AR_COMMON_OBJS = \ + $O\CoderMixer2.obj \ + $O\CoderMixer2MT.obj \ + $O\CrossThreadProgress.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\7zFolderOutStream.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\BranchCoder.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\7zStream.obj \ + $O\Alloc.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\Lzma2Enc.obj \ + $O\LzmaDec.obj \ + $O\LzmaEnc.obj \ + $O\MtCoder.obj \ + $O\Sha256.obj \ + $O\Threads.obj \ + $O\Xz.obj \ + $O\XzCrc64.obj \ + $O\XzDec.obj \ + $O\XzEnc.obj \ + $O\XzIn.obj \ + +!include "../../Crc.mak" + +OBJS = \ + $O\StdAfx.obj \ + $(CONSOLE_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(UI_COMMON_OBJS) \ + $(AR_OBJS) \ + $(AR_COMMON_OBJS) \ + $(7Z_OBJS) \ + $(COMPRESS_OBJS) \ + $(C_OBJS) \ + $(ASM_OBJS) \ + $O\resource.res + + +!include "../../../Build.mak" + +$(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp + $(COMPL) + +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) +$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp + $(COMPL) +$(AR_OBJS): ../../Archive/$(*B).cpp + $(COMPL) +$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp + $(COMPL) + +$(7Z_OBJS): ../../Archive/7z/$(*B).cpp + $(COMPL) +$(COMPRESS_OBJS): ../../Compress/$(*B).cpp + $(COMPL_O2) +$(C_OBJS): ../../../../C/$(*B).c + $(COMPL_O2) + +!include "../../Asm.mak" diff --git a/CPP/7zip/Bundles/Alone7z/resource.rc b/CPP/7zip/Bundles/Alone7z/resource.rc new file mode 100755 index 0000000..0f90dfb --- /dev/null +++ b/CPP/7zip/Bundles/Alone7z/resource.rc @@ -0,0 +1,3 @@ +#include "../../MyVersionInfo.rc" + +MY_VERSION_INFO_APP("7-Zip Standalone Console", "7zr") diff --git a/CPP/7zip/Bundles/Fm/FM.dsp b/CPP/7zip/Bundles/Fm/FM.dsp new file mode 100755 index 0000000..8564f4c --- /dev/null +++ b/CPP/7zip/Bundles/Fm/FM.dsp @@ -0,0 +1,1726 @@ +# Microsoft Developer Studio Project File - Name="FM" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=FM - 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 "FM.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 "FM.mak" CFG="FM - Win32 DebugU" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "FM - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "FM - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE "FM - Win32 ReleaseU" (based on "Win32 (x86) Application") +!MESSAGE "FM - Win32 DebugU" (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)" == "FM - 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 /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x409 /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 comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Program Files\7-ZIP\7zFM.exe" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "FM - 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 /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x409 /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 comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Program Files\7-ZIP\7zFM.exe" /pdbtype:sept + +!ELSEIF "$(CFG)" == "FM - 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 "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x409 /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 comctl32.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 comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Program Files\7-ZIP\7zFM.exe" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "FM - 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 "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x409 /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 comctl32.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 comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Program Files\7-ZIP\7zFM.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "FM - Win32 Release" +# Name "FM - Win32 Debug" +# Name "FM - Win32 ReleaseU" +# Name "FM - Win32 DebugU" +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\UI\FileManager\7zipLogo.ico +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\add.bmp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\ClassDefs.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\Copy.bmp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\Delete.bmp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\Extract.bmp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\FM.ico +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\Move.bmp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\Parent.bmp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\Properties.bmp +# End Source File +# Begin Source File + +SOURCE=.\resource.rc +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\StdAfx.cpp +# ADD CPP /Yc"StdAfx.h" +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\StdAfx.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\Test.bmp +# End Source File +# End Group +# Begin Group "Archive" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\IArchive.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 "Folders" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\UI\FileManager\FSDrives.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\FSDrives.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\FSFolder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\FSFolder.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\FSFolderCopy.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\IFolder.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\NetFolder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\NetFolder.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\RootFolder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\RootFolder.h +# End Source File +# End Group +# Begin Group "Registry" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\UI\FileManager\RegistryAssociations.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\RegistryAssociations.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\RegistryPlugins.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\RegistryPlugins.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\RegistryUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\RegistryUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\ViewSettings.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\ViewSettings.h +# End Source File +# End Group +# Begin Group "Panel" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\UI\FileManager\App.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\App.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\AppState.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\EnumFormatEtc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\EnumFormatEtc.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\FileFolderPluginOpen.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\FileFolderPluginOpen.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\Panel.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\Panel.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\PanelCopy.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\PanelCrc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\PanelDrag.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\PanelFolderChange.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\PanelItemOpen.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\PanelItems.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\PanelKey.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\PanelListNotify.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\PanelMenu.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\PanelOperations.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\PanelSelect.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\PanelSort.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\PanelSplitFile.cpp +# End Source File +# End Group +# Begin Group "Dialog" + +# PROP Default_Filter "" +# Begin Group "Options" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\UI\FileManager\EditPage.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\EditPage.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\FoldersPage.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\FoldersPage.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\LangPage.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\LangPage.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\MenuPage.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\MenuPage.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\OptionsDialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\SettingsPage.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\SettingsPage.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\SystemPage.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\SystemPage.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\UI\FileManager\AboutDialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\AboutDialog.h +# End Source File +# 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\CopyDialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\CopyDialog.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\DialogSize.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\ListViewDialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\ListViewDialog.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\MessagesDialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\MessagesDialog.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 +# Begin Source File + +SOURCE=..\..\UI\FileManager\SplitDialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\SplitDialog.h +# End Source File +# End Group +# Begin Group "FM Common" + +# 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\HelpUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\HelpUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\LangUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\LangUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\ProgramLocation.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\ProgramLocation.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\UpdateCallback100.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\UpdateCallback100.h +# End Source File +# End Group +# Begin Group "7-Zip Common" + +# PROP Default_Filter "" +# 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\ProgressUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressUtils.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 +# 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 + +!IF "$(CFG)" == "FM - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "FM - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "FM - Win32 ReleaseU" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "FM - 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\CpuArch.c + +!IF "$(CFG)" == "FM - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "FM - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "FM - Win32 ReleaseU" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "FM - 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\Sha256.c + +!IF "$(CFG)" == "FM - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "FM - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "FM - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "FM - 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\Sort.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Sort.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 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\CommandBar.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\Edit.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\ImageList.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 +# Begin Source File + +SOURCE=..\..\..\Windows\Control\ProgressBar.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\PropertyPage.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\PropertyPage.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\ReBar.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\Static.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\StatusBar.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\ToolBar.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\Trackbar.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\Window2.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\Window2.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\..\Windows\Clipboard.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Clipboard.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\COM.h +# End Source File +# 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\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\Error.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Error.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\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\Memory.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Memory.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\Menu.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Menu.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Net.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Net.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Process.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Process.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\PropVariantConversions.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariantConversions.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Registry.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Registry.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\ResourceString.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\ResourceString.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Security.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Security.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\Thread.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Time.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Time.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Timer.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\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\Defs.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\DynamicBuffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Exception.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\Lang.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Lang.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\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\Random.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Random.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\TextConfig.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\TextConfig.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 +# End Group +# Begin Group "UI" + +# PROP Default_Filter "" +# 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\ArchiveName.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\ArchiveName.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\CompressCall.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\CompressCall2.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CreateCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CreateCoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\DefaultName.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\DefaultName.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\DirItem.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\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=..\..\Common\FilterCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FilterCoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\IFileExtractCallback.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\StdAfx.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 +# Begin Source File + +SOURCE=..\..\UI\Common\WorkDir.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\WorkDir.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\ZipRegistry.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\ZipRegistry.h +# End Source File +# End Group +# Begin Group "Agent" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\UI\Agent\Agent.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Agent\Agent.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Agent\AgentOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Agent\AgentProxy.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Agent\AgentProxy.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Agent\ArchiveFolder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Agent\ArchiveFolderOpen.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Agent\ArchiveFolderOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Agent\IFolderArchive.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Agent\UpdateCallbackAgent.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Agent\UpdateCallbackAgent.h +# End Source File +# End Group +# Begin Group "Explorer" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\UI\Explorer\ContextMenu.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Explorer\ContextMenu.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Explorer\MyMessages.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Explorer\MyMessages.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Explorer\RegistryContextMenu.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Explorer\RegistryContextMenu.h +# End Source File +# End Group +# Begin Group "GUI" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\UI\GUI\BenchmarkDialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\GUI\BenchmarkDialog.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\GUI\BenchmarkDialogRes.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\GUI\CompressDialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\GUI\CompressDialog.h +# End Source File +# 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 +# Begin Source File + +SOURCE=..\..\UI\GUI\UpdateCallbackGUI.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\GUI\UpdateCallbackGUI.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\GUI\UpdateGUI.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\GUI\UpdateGUI.h +# End Source File +# End Group +# End Group +# Begin Group "Compress" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\CopyCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\CopyCoder.h +# End Source File +# End Group +# Begin Group "Interface" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\ICoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\IDecl.h +# End Source File +# Begin Source File + +SOURCE=..\..\IPassword.h +# End Source File +# Begin Source File + +SOURCE=..\..\IProgress.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\UI\FileManager\7zFM.exe.manifest +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\7zipLogo.ico +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\Add2.bmp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\Copy2.bmp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\Delete2.bmp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\Extract2.bmp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\FilePlugins.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\FilePlugins.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\FM.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\Info.bmp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\Info2.bmp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\Move2.bmp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\MyCom2.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\MyLoadMenu.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\MyLoadMenu.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\OpenCallback.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\OpenCallback.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\PluginInterface.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\PluginLoader.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\resource.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\SplitUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\SplitUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\StringUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\StringUtils.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 +# Begin Source File + +SOURCE=..\..\UI\FileManager\Test2.bmp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\TextPairs.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\TextPairs.h +# End Source File +# End Target +# End Project diff --git a/CPP/7zip/Bundles/Fm/FM.dsw b/CPP/7zip/Bundles/Fm/FM.dsw new file mode 100755 index 0000000..38f65d2 --- /dev/null +++ b/CPP/7zip/Bundles/Fm/FM.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "FM"=.\FM.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/CPP/7zip/Bundles/Fm/StdAfx.cpp b/CPP/7zip/Bundles/Fm/StdAfx.cpp new file mode 100755 index 0000000..c6d3b1f --- /dev/null +++ b/CPP/7zip/Bundles/Fm/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/Bundles/Fm/StdAfx.h b/CPP/7zip/Bundles/Fm/StdAfx.h new file mode 100755 index 0000000..a9ae92e --- /dev/null +++ b/CPP/7zip/Bundles/Fm/StdAfx.h @@ -0,0 +1,23 @@ +// stdafx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#define _WIN32_WINNT 0x0400 + +// it's for Windows NT supporting (MENUITEMINFOW) +#define WINVER 0x0400 + +#include +#include +#include +#include +#include +#include +#include + +// #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#include "Common/NewHandler.h" + +#endif diff --git a/CPP/7zip/Bundles/Fm/makefile b/CPP/7zip/Bundles/Fm/makefile new file mode 100755 index 0000000..2c55e27 --- /dev/null +++ b/CPP/7zip/Bundles/Fm/makefile @@ -0,0 +1,535 @@ +PROG = 7zFM.exe +CFLAGS = $(CFLAGS) -I ../../../ \ + -DLANG \ + -DNEW_FOLDER_INTERFACE \ + -DEXTERNAL_CODECS \ + +!IFDEF UNDER_CE +LIBS = $(LIBS) ceshell.lib Commctrl.lib +!ELSE +LIBS = $(LIBS) comctl32.lib htmlhelp.lib comdlg32.lib Mpr.lib Gdi32.lib +CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -DSUPPORT_DEVICE_FILE +!ENDIF + +FM_OBJS = \ + $O\App.obj \ + $O\BrowseDialog.obj \ + $O\ClassDefs.obj \ + $O\EnumFormatEtc.obj \ + $O\ExtractCallback.obj \ + $O\FileFolderPluginOpen.obj \ + $O\FilePlugins.obj \ + $O\FM.obj \ + $O\FoldersPage.obj \ + $O\FormatUtils.obj \ + $O\FSFolder.obj \ + $O\FSFolderCopy.obj \ + $O\HelpUtils.obj \ + $O\LangUtils.obj \ + $O\MenuPage.obj \ + $O\MyLoadMenu.obj \ + $O\OpenCallback.obj \ + $O\OptionsDialog.obj \ + $O\Panel.obj \ + $O\PanelCopy.obj \ + $O\PanelCrc.obj \ + $O\PanelDrag.obj \ + $O\PanelFolderChange.obj \ + $O\PanelItemOpen.obj \ + $O\PanelItems.obj \ + $O\PanelKey.obj \ + $O\PanelListNotify.obj \ + $O\PanelMenu.obj \ + $O\PanelOperations.obj \ + $O\PanelSelect.obj \ + $O\PanelSort.obj \ + $O\PanelSplitFile.obj \ + $O\ProgramLocation.obj \ + $O\PropertyName.obj \ + $O\RegistryAssociations.obj \ + $O\RegistryPlugins.obj \ + $O\RegistryUtils.obj \ + $O\RootFolder.obj \ + $O\SplitUtils.obj \ + $O\StringUtils.obj \ + $O\SysIconUtils.obj \ + $O\TextPairs.obj \ + $O\UpdateCallback100.obj \ + $O\ViewSettings.obj \ + $O\AboutDialog.obj \ + $O\ComboDialog.obj \ + $O\CopyDialog.obj \ + $O\EditPage.obj \ + $O\LangPage.obj \ + $O\ListViewDialog.obj \ + $O\MessagesDialog.obj \ + $O\OverwriteDialog.obj \ + $O\PasswordDialog.obj \ + $O\ProgressDialog2.obj \ + $O\SettingsPage.obj \ + $O\SplitDialog.obj \ + $O\SystemPage.obj \ + +COMMON_OBJS = \ + $O\CommandLineParser.obj \ + $O\CRC.obj \ + $O\IntToString.obj \ + $O\Lang.obj \ + $O\ListFileUtils.obj \ + $O\MyMap.obj \ + $O\MyString.obj \ + $O\MyVector.obj \ + $O\MyXml.obj \ + $O\NewHandler.obj \ + $O\Random.obj \ + $O\StringConvert.obj \ + $O\StringToInt.obj \ + $O\TextConfig.obj \ + $O\UTFConvert.obj \ + $O\Wildcard.obj \ + +WIN_OBJS = \ + $O\Clipboard.obj \ + $O\DLL.obj \ + $O\Error.obj \ + $O\FileDir.obj \ + $O\FileFind.obj \ + $O\FileIO.obj \ + $O\FileName.obj \ + $O\Memory.obj \ + $O\MemoryLock.obj \ + $O\Menu.obj \ + $O\Process.obj \ + $O\PropVariant.obj \ + $O\PropVariantConversions.obj \ + $O\PropVariantUtils.obj \ + $O\Registry.obj \ + $O\ResourceString.obj \ + $O\Shell.obj \ + $O\Synchronization.obj \ + $O\System.obj \ + $O\Time.obj \ + $O\Window.obj \ + +!IFNDEF UNDER_CE + +FM_OBJS = $(FM_OBJS) \ + $O\FSDrives.obj \ + $O\NetFolder.obj \ + +WIN_OBJS = $(WIN_OBJS) \ + $O\CommonDialog.obj \ + $O\FileSystem.obj \ + $O\Net.obj \ + $O\Security.obj \ + +!ENDIF + + +WIN_CTRL_OBJS = \ + $O\ComboBox.obj \ + $O\Dialog.obj \ + $O\ListView.obj \ + $O\PropertyPage.obj \ + $O\Window2.obj \ + +7ZIP_COMMON_OBJS = \ + $O\CreateCoder.obj \ + $O\CWrappers.obj \ + $O\FilePathAutoRename.obj \ + $O\FileStreams.obj \ + $O\FilterCoder.obj \ + $O\InBuffer.obj \ + $O\InOutTempBuffer.obj \ + $O\LimitedStreams.obj \ + $O\LockedStream.obj \ + $O\MemBlocks.obj \ + $O\MethodId.obj \ + $O\MethodProps.obj \ + $O\OffsetStream.obj \ + $O\OutBuffer.obj \ + $O\OutMemStream.obj \ + $O\ProgressMt.obj \ + $O\ProgressUtils.obj \ + $O\StreamBinder.obj \ + $O\StreamObjects.obj \ + $O\StreamUtils.obj \ + $O\VirtThread.obj \ + +AR_OBJS = \ + $O\ArjHandler.obj \ + $O\Bz2Handler.obj \ + $O\CpioHandler.obj \ + $O\CramfsHandler.obj \ + $O\DebHandler.obj \ + $O\DeflateProps.obj \ + $O\DmgHandler.obj \ + $O\ElfHandler.obj \ + $O\FatHandler.obj \ + $O\FlvHandler.obj \ + $O\GzHandler.obj \ + $O\LzhHandler.obj \ + $O\LzmaHandler.obj \ + $O\MachoHandler.obj \ + $O\MbrHandler.obj \ + $O\MslzHandler.obj \ + $O\MubHandler.obj \ + $O\NtfsHandler.obj \ + $O\PeHandler.obj \ + $O\PpmdHandler.obj \ + $O\RpmHandler.obj \ + $O\SplitHandler.obj \ + $O\SquashfsHandler.obj \ + $O\SwfHandler.obj \ + $O\VhdHandler.obj \ + $O\XarHandler.obj \ + $O\XzHandler.obj \ + $O\ZHandler.obj \ + +AR_COMMON_OBJS = \ + $O\CoderMixer2.obj \ + $O\CoderMixer2MT.obj \ + $O\CrossThreadProgress.obj \ + $O\DummyOutStream.obj \ + $O\FindSignature.obj \ + $O\InStreamWithCRC.obj \ + $O\ItemNameUtils.obj \ + $O\MultiStream.obj \ + $O\OutStreamWithCRC.obj \ + $O\OutStreamWithSha1.obj \ + $O\HandlerOut.obj \ + $O\ParseProperties.obj \ + +UI_COMMON_OBJS = \ + $O\ArchiveCommandLine.obj \ + $O\ArchiveExtractCallback.obj \ + $O\ArchiveName.obj \ + $O\ArchiveOpenCallback.obj \ + $O\Bench.obj \ + $O\CompressCall2.obj \ + $O\DefaultName.obj \ + $O\EnumDirItems.obj \ + $O\Extract.obj \ + $O\ExtractingFilePath.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 \ + $O\WorkDir.obj \ + $O\ZipRegistry.obj \ + +AGENT_OBJS = \ + $O\Agent.obj \ + $O\AgentOut.obj \ + $O\AgentProxy.obj \ + $O\ArchiveFolder.obj \ + $O\ArchiveFolderOpen.obj \ + $O\ArchiveFolderOut.obj \ + $O\UpdateCallbackAgent.obj \ + +EXPLORER_OBJS = \ + $O\ContextMenu.obj \ + $O\MyMessages.obj \ + $O\RegistryContextMenu.obj \ + +GUI_OBJS = \ + $O\BenchmarkDialog.obj \ + $O\CompressDialog.obj \ + $O\ExtractDialog.obj \ + $O\ExtractGUI.obj \ + $O\UpdateCallbackGUI.obj \ + $O\UpdateGUI.obj \ + + +7Z_OBJS = \ + $O\7zCompressionMode.obj \ + $O\7zDecode.obj \ + $O\7zEncode.obj \ + $O\7zExtract.obj \ + $O\7zFolderInStream.obj \ + $O\7zFolderOutStream.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 \ + +CAB_OBJS = \ + $O\CabBlockInStream.obj \ + $O\CabHandler.obj \ + $O\CabHeader.obj \ + $O\CabIn.obj \ + $O\CabRegister.obj \ + +CHM_OBJS = \ + $O\ChmHandler.obj \ + $O\ChmHeader.obj \ + $O\ChmIn.obj \ + $O\ChmRegister.obj \ + +COM_OBJS = \ + $O\ComHandler.obj \ + $O\ComIn.obj \ + $O\ComRegister.obj \ + +HFS_OBJS = \ + $O\HfsHandler.obj \ + $O\HfsIn.obj \ + $O\HfsRegister.obj \ + +ISO_OBJS = \ + $O\IsoHandler.obj \ + $O\IsoHeader.obj \ + $O\IsoIn.obj \ + $O\IsoRegister.obj \ + +NSIS_OBJS = \ + $O\NsisDecode.obj \ + $O\NsisHandler.obj \ + $O\NsisIn.obj \ + $O\NsisRegister.obj \ + +RAR_OBJS = \ + $O\RarHandler.obj \ + $O\RarHeader.obj \ + $O\RarIn.obj \ + $O\RarItem.obj \ + $O\RarVolumeInStream.obj \ + $O\RarRegister.obj \ + +TAR_OBJS = \ + $O\TarHandler.obj \ + $O\TarHandlerOut.obj \ + $O\TarHeader.obj \ + $O\TarIn.obj \ + $O\TarOut.obj \ + $O\TarUpdate.obj \ + $O\TarRegister.obj \ + +UDF_OBJS = \ + $O\UdfHandler.obj \ + $O\UdfIn.obj \ + $O\UdfRegister.obj \ + +WIM_OBJS = \ + $O\WimHandler.obj \ + $O\WimHandlerOut.obj \ + $O\WimIn.obj \ + $O\WimRegister.obj \ + +ZIP_OBJS = \ + $O\ZipAddCommon.obj \ + $O\ZipHandler.obj \ + $O\ZipHandlerOut.obj \ + $O\ZipHeader.obj \ + $O\ZipIn.obj \ + $O\ZipItem.obj \ + $O\ZipOut.obj \ + $O\ZipUpdate.obj \ + $O\ZipRegister.obj \ + +COMPRESS_OBJS = \ + $O\ArjDecoder1.obj \ + $O\ArjDecoder2.obj \ + $O\Bcj2Coder.obj \ + $O\Bcj2Register.obj \ + $O\BcjCoder.obj \ + $O\BcjRegister.obj \ + $O\BitlDecoder.obj \ + $O\BranchCoder.obj \ + $O\BranchMisc.obj \ + $O\BranchRegister.obj \ + $O\ByteSwap.obj \ + $O\BZip2Crc.obj \ + $O\BZip2Decoder.obj \ + $O\BZip2Encoder.obj \ + $O\BZip2Register.obj \ + $O\CopyCoder.obj \ + $O\CopyRegister.obj \ + $O\Deflate64Register.obj \ + $O\DeflateDecoder.obj \ + $O\DeflateEncoder.obj \ + $O\DeflateRegister.obj \ + $O\DeltaFilter.obj \ + $O\ImplodeDecoder.obj \ + $O\ImplodeHuffmanDecoder.obj \ + $O\LzhDecoder.obj \ + $O\Lzma2Decoder.obj \ + $O\Lzma2Encoder.obj \ + $O\Lzma2Register.obj \ + $O\LzmaDecoder.obj \ + $O\LzmaEncoder.obj \ + $O\LzmaRegister.obj \ + $O\LzOutWindow.obj \ + $O\Lzx86Converter.obj \ + $O\LzxDecoder.obj \ + $O\PpmdDecoder.obj \ + $O\PpmdEncoder.obj \ + $O\PpmdRegister.obj \ + $O\PpmdZip.obj \ + $O\QuantumDecoder.obj \ + $O\Rar1Decoder.obj \ + $O\Rar2Decoder.obj \ + $O\Rar3Decoder.obj \ + $O\Rar3Vm.obj \ + $O\RarCodecsRegister.obj \ + $O\ShrinkDecoder.obj \ + $O\ZlibDecoder.obj \ + $O\ZlibEncoder.obj \ + $O\ZDecoder.obj \ + +CRYPTO_OBJS = \ + $O\7zAes.obj \ + $O\7zAesRegister.obj \ + $O\HmacSha1.obj \ + $O\MyAes.obj \ + $O\Pbkdf2HmacSha1.obj \ + $O\RandGen.obj \ + $O\Rar20Crypto.obj \ + $O\RarAes.obj \ + $O\Sha1.obj \ + $O\WzAes.obj \ + $O\ZipCrypto.obj \ + $O\ZipStrong.obj \ + + +C_OBJS = \ + $O\7zBuf2.obj \ + $O\7zStream.obj \ + $O\Alloc.obj \ + $O\Bra.obj \ + $O\Bra86.obj \ + $O\BraIA64.obj \ + $O\BwtSort.obj \ + $O\CpuArch.obj \ + $O\Delta.obj \ + $O\HuffEnc.obj \ + $O\LzFind.obj \ + $O\LzFindMt.obj \ + $O\Lzma2Dec.obj \ + $O\Lzma2Enc.obj \ + $O\LzmaDec.obj \ + $O\LzmaEnc.obj \ + $O\MtCoder.obj \ + $O\Ppmd7.obj \ + $O\Ppmd7Dec.obj \ + $O\Ppmd7Enc.obj \ + $O\Ppmd8.obj \ + $O\Ppmd8Dec.obj \ + $O\Ppmd8Enc.obj \ + $O\Sha256.obj \ + $O\Sort.obj \ + $O\Threads.obj \ + $O\Xz.obj \ + $O\XzCrc64.obj \ + $O\XzDec.obj \ + $O\XzEnc.obj \ + $O\XzIn.obj \ + +!include "../../Aes.mak" +!include "../../Crc.mak" + +OBJS = \ + $O\StdAfx.obj \ + $(FM_OBJS)\ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(WIN_CTRL_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(AR_OBJS) \ + $(AR_COMMON_OBJS) \ + $(UI_COMMON_OBJS) \ + $(AGENT_OBJS) \ + $(EXPLORER_OBJS) \ + $(GUI_OBJS) \ + $(7Z_OBJS) \ + $(CAB_OBJS) \ + $(CHM_OBJS) \ + $(COM_OBJS) \ + $(HFS_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" + +$(FM_OBJS): ../../UI/FileManager/$(*B).cpp + $(COMPL) +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +$(WIN_CTRL_OBJS): ../../../Windows/Control/$(*B).cpp + $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) + +$(AR_OBJS): ../../Archive/$(*B).cpp + $(COMPL) +$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp + $(COMPL) + +$(7Z_OBJS): ../../Archive/7z/$(*B).cpp + $(COMPL) +$(CAB_OBJS): ../../Archive/Cab/$(*B).cpp + $(COMPL) +$(CHM_OBJS): ../../Archive/Chm/$(*B).cpp + $(COMPL) +$(COM_OBJS): ../../Archive/Com/$(*B).cpp + $(COMPL) +$(HFS_OBJS): ../../Archive/Hfs/$(*B).cpp + $(COMPL) +$(ISO_OBJS): ../../Archive/Iso/$(*B).cpp + $(COMPL) +$(NSIS_OBJS): ../../Archive/Nsis/$(*B).cpp + $(COMPL) +$(RAR_OBJS): ../../Archive/Rar/$(*B).cpp + $(COMPL) +$(TAR_OBJS): ../../Archive/Tar/$(*B).cpp + $(COMPL) +$(UDF_OBJS): ../../Archive/Udf/$(*B).cpp + $(COMPL) +$(WIM_OBJS): ../../Archive/Wim/$(*B).cpp + $(COMPL) +$(ZIP_OBJS): ../../Archive/Zip/$(*B).cpp + $(COMPL) + +$(COMPRESS_OBJS): ../../Compress/$(*B).cpp + $(COMPL_O2) + +$(CRYPTO_OBJS): ../../Crypto/$(*B).cpp + $(COMPL_O2) + +$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp + $(COMPL) +$(AGENT_OBJS): ../../UI/Agent/$(*B).cpp + $(COMPL) +$(EXPLORER_OBJS): ../../UI/Explorer/$(*B).cpp + $(COMPL) +$(GUI_OBJS): ../../UI/GUI/$(*B).cpp + $(COMPL) + +$(C_OBJS): ../../../../C/$(*B).c + $(COMPL_O2) + +!include "../../Asm.mak" diff --git a/CPP/7zip/Bundles/Fm/resource.rc b/CPP/7zip/Bundles/Fm/resource.rc new file mode 100755 index 0000000..218e6d0 --- /dev/null +++ b/CPP/7zip/Bundles/Fm/resource.rc @@ -0,0 +1,7 @@ +#include "../../UI/FileManager/resource.rc" +#include "../../UI/GUI/resource2.rc" + +STRINGTABLE +BEGIN + 100 "7z zip bz2 bzip2 tbz2 tbz rar arj z taz lzh lha cab iso 001 rpm deb cpio tar gz gzip tgz tpz4 wim swm lzma dmg hfs xar vhd fat ntfs xz" +END diff --git a/CPP/7zip/Bundles/Format7z/StdAfx.cpp b/CPP/7zip/Bundles/Format7z/StdAfx.cpp new file mode 100755 index 0000000..c6d3b1f --- /dev/null +++ b/CPP/7zip/Bundles/Format7z/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/Bundles/Format7z/StdAfx.h b/CPP/7zip/Bundles/Format7z/StdAfx.h new file mode 100755 index 0000000..a4e6173 --- /dev/null +++ b/CPP/7zip/Bundles/Format7z/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" +#include "../../../Common/NewHandler.h" + +#endif diff --git a/CPP/7zip/Bundles/Format7z/makefile b/CPP/7zip/Bundles/Format7z/makefile new file mode 100755 index 0000000..14293e4 --- /dev/null +++ b/CPP/7zip/Bundles/Format7z/makefile @@ -0,0 +1,181 @@ +PROG = 7za.dll +DEF_FILE = ../../Archive/Archive2.def +CFLAGS = $(CFLAGS) -I ../../../ \ + -DDEFLATE_EXTRACT_ONLY \ + -DBZIP2_EXTRACT_ONLY \ + +COMMON_OBJS = \ + $O\CRC.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\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\LockedStream.obj \ + $O\MethodId.obj \ + $O\MethodProps.obj \ + $O\OutBuffer.obj \ + $O\ProgressUtils.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\CoderMixer2MT.obj \ + $O\CrossThreadProgress.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\7zFolderOutStream.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\BitlDecoder.obj \ + $O\BranchCoder.obj \ + $O\BranchMisc.obj \ + $O\BranchRegister.obj \ + $O\ByteSwap.obj \ + $O\BZip2Crc.obj \ + $O\BZip2Decoder.obj \ + $O\BZip2Encoder.obj \ + $O\BZip2Register.obj \ + $O\CopyCoder.obj \ + $O\CopyRegister.obj \ + $O\DeflateDecoder.obj \ + $O\DeflateEncoder.obj \ + $O\DeflateRegister.obj \ + $O\DeltaFilter.obj \ + $O\Lzma2Decoder.obj \ + $O\Lzma2Encoder.obj \ + $O\Lzma2Register.obj \ + $O\LzmaDecoder.obj \ + $O\LzmaEncoder.obj \ + $O\LzmaRegister.obj \ + $O\LzOutWindow.obj \ + $O\PpmdDecoder.obj \ + $O\PpmdEncoder.obj \ + $O\PpmdRegister.obj \ + +CRYPTO_OBJS = \ + $O\7zAes.obj \ + $O\7zAesRegister.obj \ + $O\MyAes.obj \ + $O\RandGen.obj \ + $O\Sha1.obj \ + +C_OBJS = \ + $O\Alloc.obj \ + $O\Bra.obj \ + $O\Bra86.obj \ + $O\BraIA64.obj \ + $O\BwtSort.obj \ + $O\CpuArch.obj \ + $O\Delta.obj \ + $O\HuffEnc.obj \ + $O\LzFind.obj \ + $O\LzFindMt.obj \ + $O\Lzma2Dec.obj \ + $O\Lzma2Enc.obj \ + $O\LzmaDec.obj \ + $O\LzmaEnc.obj \ + $O\MtCoder.obj \ + $O\Ppmd7.obj \ + $O\Ppmd7Dec.obj \ + $O\Ppmd7Enc.obj \ + $O\Sha256.obj \ + $O\Sort.obj \ + $O\Threads.obj \ + +!include "../../Aes.mak" +!include "../../Crc.mak" + +OBJS = \ + $O\StdAfx.obj \ + $(CONSOLE_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(AR_OBJS) \ + $(AR_COMMON_OBJS) \ + $(7Z_OBJS) \ + $(COMPRESS_OBJS) \ + $(CRYPTO_OBJS) \ + $(C_OBJS) \ + $(ASM_OBJS) \ + $O\resource.res + + +!include "../../../Build.mak" + +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) +$(AR_OBJS): ../../Archive/$(*B).cpp + $(COMPL) +$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp + $(COMPL) + +$(7Z_OBJS): ../../Archive/7z/$(*B).cpp + $(COMPL) + +$(COMPRESS_OBJS): ../../Compress/$(*B).cpp + $(COMPL_O2) + +$(CRYPTO_OBJS): ../../Crypto/$(*B).cpp + $(COMPL_O2) + +$(C_OBJS): ../../../../C/$(*B).c + $(COMPL_O2) + +!include "../../Asm.mak" diff --git a/CPP/7zip/Bundles/Format7z/resource.rc b/CPP/7zip/Bundles/Format7z/resource.rc new file mode 100755 index 0000000..53d6be0 --- /dev/null +++ b/CPP/7zip/Bundles/Format7z/resource.rc @@ -0,0 +1,5 @@ +#include "../../MyVersionInfo.rc" + +MY_VERSION_INFO_DLL("7z Standalone Plugin", "7za") + +101 ICON "../../Archive/Icons/7z.ico" diff --git a/CPP/7zip/Bundles/Format7zExtract/StdAfx.cpp b/CPP/7zip/Bundles/Format7zExtract/StdAfx.cpp new file mode 100755 index 0000000..c6d3b1f --- /dev/null +++ b/CPP/7zip/Bundles/Format7zExtract/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/Bundles/Format7zExtract/StdAfx.h b/CPP/7zip/Bundles/Format7zExtract/StdAfx.h new file mode 100755 index 0000000..a4e6173 --- /dev/null +++ b/CPP/7zip/Bundles/Format7zExtract/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" +#include "../../../Common/NewHandler.h" + +#endif diff --git a/CPP/7zip/Bundles/Format7zExtract/makefile b/CPP/7zip/Bundles/Format7zExtract/makefile new file mode 100755 index 0000000..ee883ca --- /dev/null +++ b/CPP/7zip/Bundles/Format7zExtract/makefile @@ -0,0 +1,150 @@ +PROG = 7zxa.dll +DEF_FILE = ../../Archive/Archive2.def +CFLAGS = $(CFLAGS) -I ../../../ \ + -DEXTRACT_ONLY \ + +COMMON_OBJS = \ + $O\CRC.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\LockedStream.obj \ + $O\MethodId.obj \ + $O\OutBuffer.obj \ + $O\ProgressUtils.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\CoderMixer2MT.obj \ + $O\CrossThreadProgress.obj \ + $O\ItemNameUtils.obj \ + $O\OutStreamWithCRC.obj \ + $O\ParseProperties.obj \ + +7Z_OBJS = \ + $O\7zCompressionMode.obj \ + $O\7zDecode.obj \ + $O\7zExtract.obj \ + $O\7zFolderOutStream.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\BitlDecoder.obj \ + $O\BranchCoder.obj \ + $O\BranchMisc.obj \ + $O\BranchRegister.obj \ + $O\ByteSwap.obj \ + $O\BZip2Crc.obj \ + $O\BZip2Decoder.obj \ + $O\BZip2Register.obj \ + $O\CopyCoder.obj \ + $O\CopyRegister.obj \ + $O\DeflateDecoder.obj \ + $O\DeflateRegister.obj \ + $O\DeltaFilter.obj \ + $O\Lzma2Decoder.obj \ + $O\Lzma2Register.obj \ + $O\LzmaDecoder.obj \ + $O\LzmaRegister.obj \ + $O\LzOutWindow.obj \ + $O\PpmdDecoder.obj \ + $O\PpmdRegister.obj \ + +CRYPTO_OBJS = \ + $O\7zAes.obj \ + $O\7zAesRegister.obj \ + $O\MyAes.obj \ + +C_OBJS = \ + $O\Alloc.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 \ + $O\Sha256.obj \ + $O\Threads.obj \ + +!include "../../Aes.mak" +!include "../../Crc.mak" + +OBJS = \ + $O\StdAfx.obj \ + $(CONSOLE_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(AR_OBJS) \ + $(AR_COMMON_OBJS) \ + $(7Z_OBJS) \ + $(COMPRESS_OBJS) \ + $(CRYPTO_OBJS) \ + $(C_OBJS) \ + $(ASM_OBJS) \ + $O\resource.res + + +!include "../../../Build.mak" + +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) +$(AR_OBJS): ../../Archive/$(*B).cpp + $(COMPL) +$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp + $(COMPL) + +$(7Z_OBJS): ../../Archive/7z/$(*B).cpp + $(COMPL) + +$(COMPRESS_OBJS): ../../Compress/$(*B).cpp + $(COMPL_O2) + +$(CRYPTO_OBJS): ../../Crypto/$(*B).cpp + $(COMPL_O2) + +$(C_OBJS): ../../../../C/$(*B).c + $(COMPL_O2) + +!include "../../Asm.mak" diff --git a/CPP/7zip/Bundles/Format7zExtract/resource.rc b/CPP/7zip/Bundles/Format7zExtract/resource.rc new file mode 100755 index 0000000..e85e7e9 --- /dev/null +++ b/CPP/7zip/Bundles/Format7zExtract/resource.rc @@ -0,0 +1,5 @@ +#include "../../MyVersionInfo.rc" + +MY_VERSION_INFO_DLL("7z Standalone Extracting Plugin", "7zxa") + +101 ICON "../../Archive/Icons/7z.ico" diff --git a/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp b/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp new file mode 100755 index 0000000..c6d3b1f --- /dev/null +++ b/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h b/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h new file mode 100755 index 0000000..a4e6173 --- /dev/null +++ b/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" +#include "../../../Common/NewHandler.h" + +#endif diff --git a/CPP/7zip/Bundles/Format7zExtractR/makefile b/CPP/7zip/Bundles/Format7zExtractR/makefile new file mode 100755 index 0000000..34a9bb3 --- /dev/null +++ b/CPP/7zip/Bundles/Format7zExtractR/makefile @@ -0,0 +1,132 @@ +PROG = 7zxr.dll +DEF_FILE = ../../Archive/Archive2.def +CFLAGS = $(CFLAGS) -I ../../../ \ + -DEXTRACT_ONLY \ + -D_NO_CRYPTO + +COMMON_OBJS = \ + $O\CRC.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\LockedStream.obj \ + $O\MethodId.obj \ + $O\MethodProps.obj \ + $O\OutBuffer.obj \ + $O\ProgressUtils.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\CoderMixer2MT.obj \ + $O\CrossThreadProgress.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\7zFolderOutStream.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\BranchCoder.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\Bra.obj \ + $O\Bra86.obj \ + $O\BraIA64.obj \ + $O\CpuArch.obj \ + $O\Delta.obj \ + $O\Lzma2Dec.obj \ + $O\LzmaDec.obj \ + $O\Threads.obj \ + +!include "../../Crc.mak" + +OBJS = \ + $O\StdAfx.obj \ + $(CONSOLE_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(AR_OBJS) \ + $(AR_COMMON_OBJS) \ + $(7Z_OBJS) \ + $(COMPRESS_OBJS) \ + $(C_OBJS) \ + $(ASM_OBJS) \ + $O\resource.res + + +!include "../../../Build.mak" + +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) +$(AR_OBJS): ../../Archive/$(*B).cpp + $(COMPL) +$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp + $(COMPL) + +$(7Z_OBJS): ../../Archive/7z/$(*B).cpp + $(COMPL) + +$(COMPRESS_OBJS): ../../Compress/$(*B).cpp + $(COMPL_O2) + +$(C_OBJS): ../../../../C/$(*B).c + $(COMPL_O2) + +!include "../../Asm.mak" diff --git a/CPP/7zip/Bundles/Format7zExtractR/resource.rc b/CPP/7zip/Bundles/Format7zExtractR/resource.rc new file mode 100755 index 0000000..652c4a1 --- /dev/null +++ b/CPP/7zip/Bundles/Format7zExtractR/resource.rc @@ -0,0 +1,5 @@ +#include "../../MyVersionInfo.rc" + +MY_VERSION_INFO_DLL("7z Standalone Extracting Plugin", "7zxr") + +101 ICON "../../Archive/Icons/7z.ico" diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsp b/CPP/7zip/Bundles/Format7zF/Format7z.dsp new file mode 100755 index 0000000..92c9a30 --- /dev/null +++ b/CPP/7zip/Bundles/Format7zF/Format7z.dsp @@ -0,0 +1,2627 @@ +# 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) Dynamic-Link Library" 0x0102 + +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 "Format7z.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 "Format7z.mak" CFG="7z - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "7z - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "7z - 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)" == "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 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /YX /FD /c +# ADD CPP /nologo /Gr /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /D "NO_REGISTRY" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /FAs /Yu"StdAfx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-Zip\7z.dll" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none /debug + +!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 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /Gr /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\SDK" /I "..\..\..\\" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /D "NO_REGISTRY" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /Yu"StdAfx.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-Zip\7z.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "7z - Win32 Release" +# Name "7z - Win32 Debug" +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Group "Icons" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Icons\7z.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Icons\arj.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Icons\bz2.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Icons\cab.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Icons\cpio.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Icons\deb.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Icons\dmg.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Icons\fat.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Icons\gz.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Icons\hfs.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Icons\iso.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Icons\lzh.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Icons\lzma.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Icons\ntfs.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Icons\rar.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Icons\rpm.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Icons\split.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Icons\squashfs.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Icons\tar.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Icons\vhd.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Icons\wim.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Icons\xar.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Icons\xz.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Icons\z.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Icons\zip.ico +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\Archive\Archive2.def +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\ArchiveExports.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\CodecExports.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\DllExports2.cpp +# End Source File +# Begin Source File + +SOURCE=.\resource.rc +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"StdAfx.h" +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# End Group +# Begin Group "Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Common\Buffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\CRC.cpp +# 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\MyCom.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyException.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyInitGuid.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyMap.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyMap.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.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyXml.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyXml.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 +# 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 "Compress" + +# PROP Default_Filter "" +# Begin Group "PPMD" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\PpmdDecoder.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\PpmdDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\PpmdEncoder.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\PpmdEncoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\PpmdRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\PpmdSubAlloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\PpmdType.h +# End Source File +# End Group +# Begin Group "Bit Coder" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\BitlDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BitlDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BitlEncoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BitmDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BitmEncoder.h +# End Source File +# End Group +# Begin Group "Rar Compress" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\Rar1Decoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Rar1Decoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Rar2Decoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Rar2Decoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Rar3Decoder.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Rar3Decoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Rar3Vm.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Rar3Vm.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\RarCodecsRegister.cpp +# End Source File +# End Group +# Begin Group "BZip2 Compress" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\BZip2Const.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BZip2Crc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BZip2Crc.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BZip2Decoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BZip2Decoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BZip2Encoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BZip2Encoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BZip2Register.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Mtf8.h +# End Source File +# End Group +# Begin Group "Zip Compress" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\Deflate64Register.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\DeflateConst.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\DeflateDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\DeflateDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\DeflateEncoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\DeflateEncoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\DeflateRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\ImplodeDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\ImplodeDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\ImplodeHuffmanDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\ImplodeHuffmanDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\PpmdZip.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\PpmdZip.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\ShrinkDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\ShrinkDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\ZlibDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\ZlibDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\ZlibEncoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\ZlibEncoder.h +# End Source File +# End Group +# Begin Group "7z 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\BranchCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BranchCoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BranchMisc.cpp +# End Source File +# Begin Source File + +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\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\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\RangeCoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\RangeCoderBit.h +# End Source File +# End Group +# Begin Group "Cab Compress" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\Lzx.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzx86Converter.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzx86Converter.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzxDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzxDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\QuantumDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\QuantumDecoder.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\Compress\ArjDecoder1.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\ArjDecoder1.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\ArjDecoder2.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\ArjDecoder2.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\DeltaFilter.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\HuffmanDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzhDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzhDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzOutWindow.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzOutWindow.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\ZDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\ZDecoder.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\HmacSha1.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\HmacSha1.h +# 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\Pbkdf2HmacSha1.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Pbkdf2HmacSha1.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\RandGen.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\RandGen.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Rar20Crypto.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Rar20Crypto.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\RarAes.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\RarAes.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Sha1.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Sha1.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\WzAes.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\WzAes.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\ZipCrypto.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\ZipCrypto.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\ZipStrong.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\ZipStrong.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\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\MemBlocks.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\MemBlocks.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\OutMemStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OutMemStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressMt.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressMt.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\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 "C" + +# PROP Default_Filter "" +# Begin Group "xz" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\..\C\Xz.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /W4 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# ADD CPP /W4 /WX +# 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)" == "7z - Win32 Release" + +# ADD CPP /W4 /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# ADD CPP /W4 /WX +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\XzCrc64.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\XzDec.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /W4 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# ADD CPP /W4 /WX +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\XzEnc.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\XzEnc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\XzIn.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /W4 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# ADD CPP /W4 /WX +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\..\..\C\7zBuf2.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\7zCrc.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\7zCrc.h +# 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)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Aes.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 + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bra.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bra86.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\BraIA64.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\BwtSort.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\BwtSort.h +# 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\HuffEnc.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\HuffEnc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzFind.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzFind.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzFindMt.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzFindMt.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzHash.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Dec.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Dec.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Enc.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Enc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzmaDec.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzmaDec.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzmaEnc.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzmaEnc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\MtCoder.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\MtCoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Ppmd.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Ppmd7.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Ppmd7.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Ppmd7Dec.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Ppmd7Enc.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Ppmd8.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Ppmd8.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Ppmd8Dec.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Ppmd8Enc.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\RotateDefs.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Sha256.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Sha256.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Sort.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Sort.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 "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\7zFolderOutStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zFolderOutStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHandlerOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHeader.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHeader.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zIn.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zIn.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zItem.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zOut.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zProperties.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zProperties.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zSpecStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zSpecStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zUpdate.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zUpdate.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zUpdateItem.h +# End Source File +# End Group +# Begin Group "Rar" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Rar\RarHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Rar\RarHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Rar\RarHeader.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Rar\RarHeader.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Rar\RarIn.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Rar\RarIn.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Rar\RarItem.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Rar\RarItem.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Rar\RarRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Rar\RarVolumeInStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Rar\RarVolumeInStream.h +# End Source File +# End Group +# Begin Group "Cab" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Cab\CabBlockInStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Cab\CabBlockInStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Cab\CabHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Cab\CabHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Cab\CabHeader.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Cab\CabHeader.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Cab\CabIn.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Cab\CabIn.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Cab\CabItem.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Cab\CabRegister.cpp +# End Source File +# End Group +# Begin Group "Chm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Chm\ChmHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Chm\ChmHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Chm\ChmHeader.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Chm\ChmHeader.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Chm\ChmIn.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Chm\ChmIn.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Chm\ChmRegister.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\CoderMixer2MT.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\CoderMixer2MT.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\DummyOutStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\DummyOutStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\FindSignature.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\FindSignature.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\HandlerOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\HandlerOut.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\InStreamWithCRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\InStreamWithCRC.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\ItemNameUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\ItemNameUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\MultiStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\MultiStream.h +# End Source File +# Begin Source File + +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\OutStreamWithSha1.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\OutStreamWithSha1.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 Group "Iso" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Iso\IsoHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Iso\IsoHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Iso\IsoHeader.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Iso\IsoHeader.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Iso\IsoIn.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Iso\IsoIn.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Iso\IsoItem.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Iso\IsoRegister.cpp +# End Source File +# End Group +# Begin Group "Nsis" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Nsis\NsisDecode.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Nsis\NsisDecode.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Nsis\NsisHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Nsis\NsisHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Nsis\NsisIn.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Nsis\NsisIn.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Nsis\NsisRegister.cpp +# End Source File +# End Group +# Begin Group "Tar" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarHandlerOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarHeader.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarHeader.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarIn.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarIn.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarItem.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarOut.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarUpdate.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Tar\TarUpdate.h +# End Source File +# End Group +# Begin Group "Zip" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipAddCommon.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipAddCommon.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipCompressionMode.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipHandlerOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipHeader.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipHeader.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipIn.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipIn.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipItem.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipItem.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipItemEx.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipOut.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipUpdate.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Zip\ZipUpdate.h +# End Source File +# End Group +# Begin Group "Wim" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Wim\WimHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Wim\WimHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Wim\WimHandlerOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Wim\WimIn.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Wim\WimIn.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Wim\WimRegister.cpp +# End Source File +# End Group +# Begin Group "Com" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Com\ComHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Com\ComHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Com\ComIn.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Com\ComIn.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Com\ComRegister.cpp +# End Source File +# End Group +# Begin Group "Hfs" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Hfs\HfsHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Hfs\HfsHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Hfs\HfsIn.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Hfs\HfsIn.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Hfs\HfsRegister.cpp +# End Source File +# End Group +# Begin Group "Udf" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Udf\UdfHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Udf\UdfHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Udf\UdfIn.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Udf\UdfIn.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Udf\UdfRegister.cpp +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\Archive\ApmHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\ArjHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Bz2Handler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\CpioHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\CramfsHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\DebHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\DeflateProps.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\DeflateProps.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\DmgHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\ElfHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\FatHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\FlvHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\GzHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\IArchive.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\LzhHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\LzmaHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\MachoHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\MbrHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\MslzHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\MubHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\NtfsHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\PeHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\PpmdHandler.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\RpmHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\SplitHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\SquashfsHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\SwfHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\VhdHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\XarHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\XzHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\ZHandler.cpp +# End Source File +# End Group +# Begin Group "7zip" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\ICoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\IDecl.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 "Windows" + +# PROP Default_Filter "" +# 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\PropVariant.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariant.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariantUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariantUtils.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\Time.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Time.h +# End Source File +# End Group +# Begin Group "Asm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\..\Asm\x86\7zAsm.asm +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\Asm\x86\7zCrcOpt.asm + +!IF "$(CFG)" == "7z - Win32 Release" + +# Begin Custom Build +OutDir=.\Release +InputPath=..\..\..\..\Asm\x86\7zCrcOpt.asm +InputName=7zCrcOpt + +"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml.exe -c -Fo$(OutDir)\$(InputName).obj $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# Begin Custom Build +OutDir=.\Debug +InputPath=..\..\..\..\Asm\x86\7zCrcOpt.asm +InputName=7zCrcOpt + +"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml.exe -c -omf -Fo$(OutDir)\$(InputName).obj $(InputPath) + +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\Asm\x86\AesOpt.asm + +!IF "$(CFG)" == "7z - Win32 Release" + +# PROP Ignore_Default_Tool 1 +# Begin Custom Build +OutDir=.\Release +InputPath=..\..\..\..\Asm\x86\AesOpt.asm +InputName=AesOpt + +"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml.exe -c -Fo$(OutDir)\$(InputName).obj $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# PROP Ignore_Default_Tool 1 +# Begin Custom Build +OutDir=.\Debug +InputPath=..\..\..\..\Asm\x86\AesOpt.asm +InputName=AesOpt + +"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml.exe -c -omf -WX -W3 -Fo$(OutDir)\$(InputName).obj $(InputPath) + +# End Custom Build + +!ENDIF + +# End Source File +# End Group +# End Target +# End Project diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsw b/CPP/7zip/Bundles/Format7zF/Format7z.dsw new file mode 100755 index 0000000..bb68d25 --- /dev/null +++ b/CPP/7zip/Bundles/Format7zF/Format7z.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"=.\Format7z.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/CPP/7zip/Bundles/Format7zF/StdAfx.cpp b/CPP/7zip/Bundles/Format7zF/StdAfx.cpp new file mode 100755 index 0000000..c6d3b1f --- /dev/null +++ b/CPP/7zip/Bundles/Format7zF/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/Bundles/Format7zF/StdAfx.h b/CPP/7zip/Bundles/Format7zF/StdAfx.h new file mode 100755 index 0000000..a4e6173 --- /dev/null +++ b/CPP/7zip/Bundles/Format7zF/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" +#include "../../../Common/NewHandler.h" + +#endif diff --git a/CPP/7zip/Bundles/Format7zF/makefile b/CPP/7zip/Bundles/Format7zF/makefile new file mode 100755 index 0000000..6327ba5 --- /dev/null +++ b/CPP/7zip/Bundles/Format7zF/makefile @@ -0,0 +1,369 @@ +PROG = 7z.dll +DEF_FILE = ../../Archive/Archive2.def +CFLAGS = $(CFLAGS) -I ../../../ \ + -DEXTERNAL_CODECS \ + +!IFNDEF UNDER_CE +CFLAGS = $(CFLAGS) -D_7ZIP_LARGE_PAGES +!ENDIF + +COMMON_OBJS = \ + $O\CRC.obj \ + $O\IntToString.obj \ + $O\MyMap.obj \ + $O\MyString.obj \ + $O\MyVector.obj \ + $O\MyXml.obj \ + $O\NewHandler.obj \ + $O\StringConvert.obj \ + $O\StringToInt.obj \ + $O\UTFConvert.obj \ + $O\Wildcard.obj \ + +WIN_OBJS = \ + $O\FileDir.obj \ + $O\FileFind.obj \ + $O\FileIO.obj \ + $O\PropVariant.obj \ + $O\PropVariantUtils.obj \ + $O\Synchronization.obj \ + $O\System.obj \ + $O\Time.obj \ + +7ZIP_COMMON_OBJS = \ + $O\CreateCoder.obj \ + $O\CWrappers.obj \ + $O\InBuffer.obj \ + $O\InOutTempBuffer.obj \ + $O\FilterCoder.obj \ + $O\LimitedStreams.obj \ + $O\LockedStream.obj \ + $O\MemBlocks.obj \ + $O\MethodId.obj \ + $O\MethodProps.obj \ + $O\OffsetStream.obj \ + $O\OutBuffer.obj \ + $O\OutMemStream.obj \ + $O\ProgressMt.obj \ + $O\ProgressUtils.obj \ + $O\StreamBinder.obj \ + $O\StreamObjects.obj \ + $O\StreamUtils.obj \ + $O\VirtThread.obj \ + +AR_OBJS = \ + $O\ArchiveExports.obj \ + $O\DllExports2.obj \ + $O\ApmHandler.obj \ + $O\ArjHandler.obj \ + $O\Bz2Handler.obj \ + $O\CpioHandler.obj \ + $O\CramfsHandler.obj \ + $O\DebHandler.obj \ + $O\DeflateProps.obj \ + $O\DmgHandler.obj \ + $O\ElfHandler.obj \ + $O\FatHandler.obj \ + $O\FlvHandler.obj \ + $O\GzHandler.obj \ + $O\LzhHandler.obj \ + $O\LzmaHandler.obj \ + $O\MachoHandler.obj \ + $O\MbrHandler.obj \ + $O\MslzHandler.obj \ + $O\MubHandler.obj \ + $O\NtfsHandler.obj \ + $O\PeHandler.obj \ + $O\PpmdHandler.obj \ + $O\RpmHandler.obj \ + $O\SplitHandler.obj \ + $O\SwfHandler.obj \ + $O\SquashfsHandler.obj \ + $O\VhdHandler.obj \ + $O\XarHandler.obj \ + $O\XzHandler.obj \ + $O\ZHandler.obj \ + +AR_COMMON_OBJS = \ + $O\CoderMixer2.obj \ + $O\CoderMixer2MT.obj \ + $O\CrossThreadProgress.obj \ + $O\DummyOutStream.obj \ + $O\FindSignature.obj \ + $O\InStreamWithCRC.obj \ + $O\ItemNameUtils.obj \ + $O\MultiStream.obj \ + $O\OutStreamWithCRC.obj \ + $O\OutStreamWithSha1.obj \ + $O\HandlerOut.obj \ + $O\ParseProperties.obj \ + + +7Z_OBJS = \ + $O\7zCompressionMode.obj \ + $O\7zDecode.obj \ + $O\7zEncode.obj \ + $O\7zExtract.obj \ + $O\7zFolderInStream.obj \ + $O\7zFolderOutStream.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 \ + +CAB_OBJS = \ + $O\CabBlockInStream.obj \ + $O\CabHandler.obj \ + $O\CabHeader.obj \ + $O\CabIn.obj \ + $O\CabRegister.obj \ + +CHM_OBJS = \ + $O\ChmHandler.obj \ + $O\ChmHeader.obj \ + $O\ChmIn.obj \ + $O\ChmRegister.obj \ + +COM_OBJS = \ + $O\ComHandler.obj \ + $O\ComIn.obj \ + $O\ComRegister.obj \ + +HFS_OBJS = \ + $O\HfsHandler.obj \ + $O\HfsIn.obj \ + $O\HfsRegister.obj \ + +ISO_OBJS = \ + $O\IsoHandler.obj \ + $O\IsoHeader.obj \ + $O\IsoIn.obj \ + $O\IsoRegister.obj \ + +NSIS_OBJS = \ + $O\NsisDecode.obj \ + $O\NsisHandler.obj \ + $O\NsisIn.obj \ + $O\NsisRegister.obj \ + +RAR_OBJS = \ + $O\RarHandler.obj \ + $O\RarHeader.obj \ + $O\RarIn.obj \ + $O\RarItem.obj \ + $O\RarVolumeInStream.obj \ + $O\RarRegister.obj \ + +TAR_OBJS = \ + $O\TarHandler.obj \ + $O\TarHandlerOut.obj \ + $O\TarHeader.obj \ + $O\TarIn.obj \ + $O\TarOut.obj \ + $O\TarUpdate.obj \ + $O\TarRegister.obj \ + +UDF_OBJS = \ + $O\UdfHandler.obj \ + $O\UdfIn.obj \ + $O\UdfRegister.obj \ + +WIM_OBJS = \ + $O\WimHandler.obj \ + $O\WimHandlerOut.obj \ + $O\WimIn.obj \ + $O\WimRegister.obj \ + +ZIP_OBJS = \ + $O\ZipAddCommon.obj \ + $O\ZipHandler.obj \ + $O\ZipHandlerOut.obj \ + $O\ZipHeader.obj \ + $O\ZipIn.obj \ + $O\ZipItem.obj \ + $O\ZipOut.obj \ + $O\ZipUpdate.obj \ + $O\ZipRegister.obj \ + +COMPRESS_OBJS = \ + $O\CodecExports.obj \ + $O\ArjDecoder1.obj \ + $O\ArjDecoder2.obj \ + $O\Bcj2Coder.obj \ + $O\Bcj2Register.obj \ + $O\BcjCoder.obj \ + $O\BcjRegister.obj \ + $O\BitlDecoder.obj \ + $O\BranchCoder.obj \ + $O\BranchMisc.obj \ + $O\BranchRegister.obj \ + $O\ByteSwap.obj \ + $O\BZip2Crc.obj \ + $O\BZip2Decoder.obj \ + $O\BZip2Encoder.obj \ + $O\BZip2Register.obj \ + $O\CopyCoder.obj \ + $O\CopyRegister.obj \ + $O\Deflate64Register.obj \ + $O\DeflateDecoder.obj \ + $O\DeflateEncoder.obj \ + $O\DeflateRegister.obj \ + $O\DeltaFilter.obj \ + $O\ImplodeDecoder.obj \ + $O\ImplodeHuffmanDecoder.obj \ + $O\LzhDecoder.obj \ + $O\Lzma2Decoder.obj \ + $O\Lzma2Encoder.obj \ + $O\Lzma2Register.obj \ + $O\LzmaDecoder.obj \ + $O\LzmaEncoder.obj \ + $O\LzmaRegister.obj \ + $O\LzOutWindow.obj \ + $O\Lzx86Converter.obj \ + $O\LzxDecoder.obj \ + $O\PpmdDecoder.obj \ + $O\PpmdEncoder.obj \ + $O\PpmdRegister.obj \ + $O\PpmdZip.obj \ + $O\QuantumDecoder.obj \ + $O\Rar1Decoder.obj \ + $O\Rar2Decoder.obj \ + $O\Rar3Decoder.obj \ + $O\Rar3Vm.obj \ + $O\RarCodecsRegister.obj \ + $O\ShrinkDecoder.obj \ + $O\ZlibDecoder.obj \ + $O\ZlibEncoder.obj \ + $O\ZDecoder.obj \ + +CRYPTO_OBJS = \ + $O\7zAes.obj \ + $O\7zAesRegister.obj \ + $O\HmacSha1.obj \ + $O\MyAes.obj \ + $O\Pbkdf2HmacSha1.obj \ + $O\RandGen.obj \ + $O\Rar20Crypto.obj \ + $O\RarAes.obj \ + $O\Sha1.obj \ + $O\WzAes.obj \ + $O\ZipCrypto.obj \ + $O\ZipStrong.obj \ + + +C_OBJS = \ + $O\7zBuf2.obj \ + $O\7zStream.obj \ + $O\Alloc.obj \ + $O\Bra.obj \ + $O\Bra86.obj \ + $O\BraIA64.obj \ + $O\BwtSort.obj \ + $O\CpuArch.obj \ + $O\Delta.obj \ + $O\HuffEnc.obj \ + $O\LzFind.obj \ + $O\LzFindMt.obj \ + $O\Lzma2Dec.obj \ + $O\Lzma2Enc.obj \ + $O\LzmaDec.obj \ + $O\LzmaEnc.obj \ + $O\MtCoder.obj \ + $O\Ppmd7.obj \ + $O\Ppmd7Dec.obj \ + $O\Ppmd7Enc.obj \ + $O\Ppmd8.obj \ + $O\Ppmd8Dec.obj \ + $O\Ppmd8Enc.obj \ + $O\Sha256.obj \ + $O\Sort.obj \ + $O\Threads.obj \ + $O\Xz.obj \ + $O\XzCrc64.obj \ + $O\XzDec.obj \ + $O\XzEnc.obj \ + $O\XzIn.obj \ + +!include "../../Aes.mak" +!include "../../Crc.mak" + +OBJS = \ + $O\StdAfx.obj \ + $(CONSOLE_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(AR_OBJS) \ + $(AR_COMMON_OBJS) \ + $(7Z_OBJS) \ + $(CAB_OBJS) \ + $(CHM_OBJS) \ + $(COM_OBJS) \ + $(HFS_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" + +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) +$(AR_OBJS): ../../Archive/$(*B).cpp + $(COMPL) +$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp + $(COMPL) + +$(7Z_OBJS): ../../Archive/7z/$(*B).cpp + $(COMPL) +$(CAB_OBJS): ../../Archive/Cab/$(*B).cpp + $(COMPL) +$(CHM_OBJS): ../../Archive/Chm/$(*B).cpp + $(COMPL) +$(COM_OBJS): ../../Archive/Com/$(*B).cpp + $(COMPL) +$(HFS_OBJS): ../../Archive/Hfs/$(*B).cpp + $(COMPL) +$(ISO_OBJS): ../../Archive/Iso/$(*B).cpp + $(COMPL) +$(NSIS_OBJS): ../../Archive/Nsis/$(*B).cpp + $(COMPL) +$(RAR_OBJS): ../../Archive/Rar/$(*B).cpp + $(COMPL) +$(TAR_OBJS): ../../Archive/Tar/$(*B).cpp + $(COMPL) +$(UDF_OBJS): ../../Archive/Udf/$(*B).cpp + $(COMPL) +$(WIM_OBJS): ../../Archive/Wim/$(*B).cpp + $(COMPL) +$(ZIP_OBJS): ../../Archive/Zip/$(*B).cpp + $(COMPL) + +$(COMPRESS_OBJS): ../../Compress/$(*B).cpp + $(COMPL_O2) + +$(CRYPTO_OBJS): ../../Crypto/$(*B).cpp + $(COMPL_O2) + +$(C_OBJS): ../../../../C/$(*B).c + $(COMPL_O2) + +!include "../../Asm.mak" diff --git a/CPP/7zip/Bundles/Format7zF/resource.rc b/CPP/7zip/Bundles/Format7zF/resource.rc new file mode 100755 index 0000000..2920e5e --- /dev/null +++ b/CPP/7zip/Bundles/Format7zF/resource.rc @@ -0,0 +1,37 @@ +#include "../../MyVersionInfo.rc" + +MY_VERSION_INFO_DLL("7z Standalone Plugin", "7za") + + +0 ICON "../../Archive/Icons/7z.ico" +1 ICON "../../Archive/Icons/zip.ico" +2 ICON "../../Archive/Icons/bz2.ico" +3 ICON "../../Archive/Icons/rar.ico" +4 ICON "../../Archive/Icons/arj.ico" +5 ICON "../../Archive/Icons/z.ico" +6 ICON "../../Archive/Icons/lzh.ico" +7 ICON "../../Archive/Icons/cab.ico" +8 ICON "../../Archive/Icons/iso.ico" +9 ICON "../../Archive/Icons/split.ico" +10 ICON "../../Archive/Icons/rpm.ico" +11 ICON "../../Archive/Icons/deb.ico" +12 ICON "../../Archive/Icons/cpio.ico" +13 ICON "../../Archive/Icons/tar.ico" +14 ICON "../../Archive/Icons/gz.ico" +15 ICON "../../Archive/Icons/wim.ico" +16 ICON "../../Archive/Icons/lzma.ico" +17 ICON "../../Archive/Icons/dmg.ico" +18 ICON "../../Archive/Icons/hfs.ico" +19 ICON "../../Archive/Icons/xar.ico" +20 ICON "../../Archive/Icons/vhd.ico" +21 ICON "../../Archive/Icons/fat.ico" +22 ICON "../../Archive/Icons/ntfs.ico" +23 ICON "../../Archive/Icons/xz.ico" +24 ICON "../../Archive/Icons/squashfs.ico" + + + +STRINGTABLE +BEGIN + 100 "7z:0 zip:1 bz2:2 bzip2:2 tbz2:2 tbz:2 rar:3 arj:4 z:5 taz:5 lzh:6 lha:6 cab:7 iso:8 001:9 rpm:10 deb:11 cpio:12 tar:13 gz:14 gzip:14 tgz:14 tpz:14 wim:15 swm:15 lzma:16 dmg:17 hfs:18 xar:19 vhd:20 fat:21 ntfs:22 xz:23 txz:23 squashfs:24" +END diff --git a/CPP/7zip/Bundles/Format7zR/StdAfx.cpp b/CPP/7zip/Bundles/Format7zR/StdAfx.cpp new file mode 100755 index 0000000..c6d3b1f --- /dev/null +++ b/CPP/7zip/Bundles/Format7zR/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/Bundles/Format7zR/StdAfx.h b/CPP/7zip/Bundles/Format7zR/StdAfx.h new file mode 100755 index 0000000..a4e6173 --- /dev/null +++ b/CPP/7zip/Bundles/Format7zR/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" +#include "../../../Common/NewHandler.h" + +#endif diff --git a/CPP/7zip/Bundles/Format7zR/makefile b/CPP/7zip/Bundles/Format7zR/makefile new file mode 100755 index 0000000..65d1f65 --- /dev/null +++ b/CPP/7zip/Bundles/Format7zR/makefile @@ -0,0 +1,149 @@ +PROG = 7zra.dll +DEF_FILE = ../../Archive/Archive2.def +CFLAGS = $(CFLAGS) -I ../../../ \ + -D_NO_CRYPTO + +COMMON_OBJS = \ + $O\CRC.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\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\LockedStream.obj \ + $O\MethodId.obj \ + $O\MethodProps.obj \ + $O\OutBuffer.obj \ + $O\ProgressUtils.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\CoderMixer2MT.obj \ + $O\CrossThreadProgress.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\7zFolderOutStream.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\BranchCoder.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\Bra.obj \ + $O\Bra86.obj \ + $O\BraIA64.obj \ + $O\CpuArch.obj \ + $O\Delta.obj \ + $O\LzFind.obj \ + $O\LzFindMt.obj \ + $O\Lzma2Dec.obj \ + $O\Lzma2Enc.obj \ + $O\LzmaDec.obj \ + $O\LzmaEnc.obj \ + $O\MtCoder.obj \ + $O\Threads.obj \ + +!include "../../Crc.mak" + +OBJS = \ + $O\StdAfx.obj \ + $(CONSOLE_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(AR_OBJS) \ + $(AR_COMMON_OBJS) \ + $(7Z_OBJS) \ + $(COMPRESS_OBJS) \ + $(C_OBJS) \ + $(ASM_OBJS) \ + $O\resource.res + + +!include "../../../Build.mak" + +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) +$(AR_OBJS): ../../Archive/$(*B).cpp + $(COMPL) +$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp + $(COMPL) + +$(7Z_OBJS): ../../Archive/7z/$(*B).cpp + $(COMPL) + +$(COMPRESS_OBJS): ../../Compress/$(*B).cpp + $(COMPL_O2) + +$(C_OBJS): ../../../../C/$(*B).c + $(COMPL_O2) + +!include "../../Asm.mak" diff --git a/CPP/7zip/Bundles/Format7zR/resource.rc b/CPP/7zip/Bundles/Format7zR/resource.rc new file mode 100755 index 0000000..b67ef0c --- /dev/null +++ b/CPP/7zip/Bundles/Format7zR/resource.rc @@ -0,0 +1,5 @@ +#include "../../MyVersionInfo.rc" + +MY_VERSION_INFO_DLL("7z Standalone Plugin", "7zr") + +101 ICON "../../Archive/Icons/7z.ico" diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp new file mode 100755 index 0000000..1f759b4 --- /dev/null +++ b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp @@ -0,0 +1,525 @@ +// LzmaAlone.cpp + +#include "StdAfx.h" + +#include + +#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/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" + + +using namespace NCommandLineParser; + +static const char *kCantAllocate = "Can not allocate memory"; +static const char *kReadError = "Read error"; +static const char *kWriteError = "Write error"; + +namespace NKey { +enum Enum +{ + kHelp1 = 0, + kHelp2, + kAlgo, + kDict, + kFb, + kMc, + kLc, + kLp, + kPb, + kMatchFinder, + kMultiThread, + kEOS, + kStdIn, + kStdOut, + kFilter86 +}; +} + +static const CSwitchForm kSwitchForms[] = +{ + { L"?", NSwitchType::kSimple, false }, + { L"H", NSwitchType::kSimple, false }, + { L"A", NSwitchType::kUnLimitedPostString, false, 1 }, + { L"D", NSwitchType::kUnLimitedPostString, false, 1 }, + { L"FB", NSwitchType::kUnLimitedPostString, false, 1 }, + { L"MC", NSwitchType::kUnLimitedPostString, false, 1 }, + { L"LC", NSwitchType::kUnLimitedPostString, false, 1 }, + { L"LP", NSwitchType::kUnLimitedPostString, false, 1 }, + { L"PB", NSwitchType::kUnLimitedPostString, false, 1 }, + { L"MF", NSwitchType::kUnLimitedPostString, false, 1 }, + { L"MT", NSwitchType::kUnLimitedPostString, false, 0 }, + { L"EOS", NSwitchType::kSimple, false }, + { L"SI", NSwitchType::kSimple, false }, + { L"SO", NSwitchType::kSimple, false }, + { L"F86", NSwitchType::kPostChar, false, 0, 0, L"+" } +}; + +static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]); + +static void PrintMessage(const char *s) +{ + fputs(s, stderr); +} + +static void PrintHelp() +{ + PrintMessage("\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 size - [12, 30], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -mc{N}: set number of cycles for match finder\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, hc4], default: bt4\n" + " -mt{N}: set number of CPU threads\n" + " -eos: write End Of Stream marker\n" + " -si: read data from stdin\n" + " -so: write data to stdout\n" + ); +} + +static void PrintHelpAndExit(const char *s) +{ + fprintf(stderr, "\nError: %s\n\n", s); + PrintHelp(); + throw -1; +} + +static void IncorrectCommand() +{ + PrintHelpAndExit("Incorrect command"); +} + +static void WriteArgumentsToStringList(int numArgs, const char *args[], UStringVector &strings) +{ + for (int i = 1; i < numArgs; i++) + strings.Add(MultiByteToUnicodeString(args[i])); +} + +static bool GetNumber(const wchar_t *s, UInt32 &value) +{ + value = 0; + if (MyStringLen(s) == 0) + return false; + const wchar_t *end; + UInt64 res = ConvertStringToUInt64(s, &end); + if (*end != L'\0') + return false; + if (res > 0xFFFFFFFF) + return false; + value = UInt32(res); + return true; +} + +static void ParseUInt32(const CParser &parser, int index, UInt32 &res) +{ + if (parser[index].ThereIs) + if (!GetNumber(parser[index].PostStrings[0], res)) + IncorrectCommand(); +} + +#define NT_CHECK_FAIL_ACTION PrintMessage("Unsupported Windows version"); return 1; + +int main2(int numArgs, const char *args[]) +{ + NT_CHECK + + PrintMessage("\nLZMA " MY_VERSION_COPYRIGHT_DATE "\n"); + + if (numArgs == 1) + { + PrintHelp(); + return 0; + } + + bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4); + if (unsupportedTypes) + { + PrintMessage("Unsupported base types. Edit Common/Types.h and recompile"); + return 1; + } + + UStringVector commandStrings; + WriteArgumentsToStringList(numArgs, args, commandStrings); + CParser parser(kNumSwitches); + try + { + parser.ParseStrings(kSwitchForms, commandStrings); + } + catch(...) + { + IncorrectCommand(); + } + + if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) + { + PrintHelp(); + return 0; + } + const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; + + int paramIndex = 0; + if (paramIndex >= nonSwitchStrings.Size()) + IncorrectCommand(); + const UString &command = nonSwitchStrings[paramIndex++]; + + bool dictDefined = false; + UInt32 dict = (UInt32)-1; + if(parser[NKey::kDict].ThereIs) + { + UInt32 dicLog; + if (!GetNumber(parser[NKey::kDict].PostStrings[0], dicLog)) + IncorrectCommand(); + dict = 1 << dicLog; + dictDefined = true; + } + UString mf = L"BT4"; + if (parser[NKey::kMatchFinder].ThereIs) + mf = parser[NKey::kMatchFinder].PostStrings[0]; + + UInt32 numThreads = (UInt32)-1; + + #ifndef _7ZIP_ST + if (parser[NKey::kMultiThread].ThereIs) + { + UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); + const UString &s = parser[NKey::kMultiThread].PostStrings[0]; + if (s.IsEmpty()) + numThreads = numCPUs; + else + if (!GetNumber(s, numThreads)) + IncorrectCommand(); + } + #endif + + if (command.CompareNoCase(L"b") == 0) + { + const UInt32 kNumDefaultItereations = 1; + UInt32 numIterations = kNumDefaultItereations; + { + if (paramIndex < nonSwitchStrings.Size()) + if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations)) + numIterations = kNumDefaultItereations; + } + return LzmaBenchCon(stderr, numIterations, numThreads, dict); + } + + if (numThreads == (UInt32)-1) + numThreads = 1; + + bool encodeMode = false; + if (command.CompareNoCase(L"e") == 0) + encodeMode = true; + else if (command.CompareNoCase(L"d") == 0) + encodeMode = false; + else + IncorrectCommand(); + + bool stdInMode = parser[NKey::kStdIn].ThereIs; + bool stdOutMode = parser[NKey::kStdOut].ThereIs; + + CMyComPtr inStream; + CInFileStream *inStreamSpec = 0; + if (stdInMode) + { + inStream = new CStdInFileStream; + MY_SET_BINARY_MODE(stdin); + } + else + { + if (paramIndex >= nonSwitchStrings.Size()) + IncorrectCommand(); + const UString &inputName = nonSwitchStrings[paramIndex++]; + inStreamSpec = new CInFileStream; + inStream = inStreamSpec; + if (!inStreamSpec->Open(GetSystemString(inputName))) + { + fprintf(stderr, "\nError: can not open input file %s\n", + (const char *)GetOemString(inputName)); + return 1; + } + } + + CMyComPtr outStream; + COutFileStream *outStreamSpec = NULL; + if (stdOutMode) + { + outStream = new CStdOutFileStream; + MY_SET_BINARY_MODE(stdout); + } + else + { + if (paramIndex >= nonSwitchStrings.Size()) + IncorrectCommand(); + const UString &outputName = nonSwitchStrings[paramIndex++]; + outStreamSpec = new COutFileStream; + outStream = outStreamSpec; + if (!outStreamSpec->Create(GetSystemString(outputName), true)) + { + fprintf(stderr, "\nError: can not open output file %s\n", + (const char *)GetOemString(outputName)); + return 1; + } + } + + if (parser[NKey::kFilter86].ThereIs) + { + // -f86 switch is for x86 filtered mode: BCJ + LZMA. + if (parser[NKey::kEOS].ThereIs || stdInMode) + throw "Can not use stdin in this mode"; + UInt64 fileSize; + inStreamSpec->File.GetLength(fileSize); + if (fileSize > 0xF0000000) + throw "File is too big"; + size_t inSize = (size_t)fileSize; + Byte *inBuffer = 0; + if (inSize != 0) + { + inBuffer = (Byte *)MyAlloc((size_t)inSize); + if (inBuffer == 0) + throw kCantAllocate; + } + + if (ReadStream_FAIL(inStream, inBuffer, inSize) != S_OK) + throw "Can not read"; + + Byte *outBuffer = 0; + size_t outSize; + if (encodeMode) + { + // we allocate 105% of original size for output buffer + outSize = (size_t)fileSize / 20 * 21 + (1 << 16); + if (outSize != 0) + { + outBuffer = (Byte *)MyAlloc((size_t)outSize); + if (outBuffer == 0) + throw kCantAllocate; + } + if (!dictDefined) + dict = 1 << 23; + int res = Lzma86_Encode(outBuffer, &outSize, inBuffer, inSize, + 5, dict, parser[NKey::kFilter86].PostCharIndex == 0 ? SZ_FILTER_YES : SZ_FILTER_AUTO); + if (res != 0) + { + fprintf(stderr, "\nEncoder error = %d\n", (int)res); + return 1; + } + } + else + { + UInt64 outSize64; + if (Lzma86_GetUnpackSize(inBuffer, inSize, &outSize64) != 0) + throw "data error"; + outSize = (size_t)outSize64; + if (outSize != outSize64) + throw "too big"; + if (outSize != 0) + { + outBuffer = (Byte *)MyAlloc(outSize); + if (outBuffer == 0) + throw kCantAllocate; + } + int res = Lzma86_Decode(outBuffer, &outSize, inBuffer, &inSize); + if (inSize != (size_t)fileSize) + throw "incorrect processed size"; + if (res != 0) + throw "LzmaDecoder error"; + } + if (WriteStream(outStream, outBuffer, outSize) != S_OK) + throw kWriteError; + MyFree(outBuffer); + MyFree(inBuffer); + return 0; + } + + + UInt64 fileSize; + if (encodeMode) + { + NCompress::NLzma::CEncoder *encoderSpec = new NCompress::NLzma::CEncoder; + CMyComPtr encoder = encoderSpec; + + if (!dictDefined) + dict = 1 << 23; + + UInt32 pb = 2; + UInt32 lc = 3; // = 0; for 32-bit data + UInt32 lp = 0; // = 2; for 32-bit data + 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) + if (!GetNumber(parser[NKey::kMc].PostStrings[0], mc)) + IncorrectCommand(); + + PROPID propIDs[] = + { + NCoderPropID::kDictionarySize, + NCoderPropID::kPosStateBits, + NCoderPropID::kLitContextBits, + NCoderPropID::kLitPosBits, + NCoderPropID::kAlgorithm, + NCoderPropID::kNumFastBytes, + NCoderPropID::kMatchFinder, + NCoderPropID::kEndMarker, + NCoderPropID::kNumThreads, + NCoderPropID::kMatchFinderCycles, + }; + const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]); + + 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; + + int numProps = kNumPropsMax; + if (!mcDefined) + numProps--; + + if (encoderSpec->SetCoderProperties(propIDs, props, numProps) != S_OK) + IncorrectCommand(); + encoderSpec->WriteCoderProperties(outStream); + + if (eos || stdInMode) + fileSize = (UInt64)(Int64)-1; + else + inStreamSpec->File.GetLength(fileSize); + + for (int i = 0; i < 8; i++) + { + Byte b = Byte(fileSize >> (8 * i)); + if (outStream->Write(&b, 1, 0) != S_OK) + { + PrintMessage(kWriteError); + return 1; + } + } + HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0); + if (result == E_OUTOFMEMORY) + { + PrintMessage("\nError: Can not allocate memory\n"); + return 1; + } + else if (result != S_OK) + { + fprintf(stderr, "\nEncoder error = %X\n", (unsigned int)result); + return 1; + } + } + else + { + NCompress::NLzma::CDecoder *decoderSpec = new NCompress::NLzma::CDecoder; + CMyComPtr decoder = decoderSpec; + decoderSpec->FinishStream = true; + const UInt32 kPropertiesSize = 5; + Byte header[kPropertiesSize + 8]; + if (ReadStream_FALSE(inStream, header, kPropertiesSize + 8) != S_OK) + { + PrintMessage(kReadError); + return 1; + } + if (decoderSpec->SetDecoderProperties2(header, kPropertiesSize) != S_OK) + { + PrintMessage("SetDecoderProperties error"); + return 1; + } + fileSize = 0; + for (int i = 0; i < 8; i++) + fileSize |= ((UInt64)header[kPropertiesSize + i]) << (8 * i); + + if (decoder->Code(inStream, outStream, 0, (fileSize == (UInt64)(Int64)-1) ? 0 : &fileSize, 0) != S_OK) + { + PrintMessage("Decoder error"); + return 1; + } + } + if (outStreamSpec != NULL) + { + if (outStreamSpec->Close() != S_OK) + { + PrintMessage("File closing error"); + return 1; + } + } + return 0; +} + +int MY_CDECL main(int numArgs, const char *args[]) +{ + try { return main2(numArgs, args); } + catch(const char *s) + { + fprintf(stderr, "\nError: %s\n", s); + return 1; + } + catch(...) + { + PrintMessage("\nError\n"); + return 1; + } +} diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp new file mode 100755 index 0000000..edac514 --- /dev/null +++ b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp @@ -0,0 +1,457 @@ +# 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 /W3 /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 /W3 /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\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\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\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\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 +# Begin Source File + +SOURCE=..\..\..\..\C\Types.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\LzmaAlone.cpp +# End Source File +# End Target +# End Project diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw new file mode 100755 index 0000000..c6a6662 --- /dev/null +++ b/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/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp b/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp new file mode 100755 index 0000000..c6d3b1f --- /dev/null +++ b/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/Bundles/LzmaCon/StdAfx.h b/CPP/7zip/Bundles/LzmaCon/StdAfx.h new file mode 100755 index 0000000..83fdd22 --- /dev/null +++ b/CPP/7zip/Bundles/LzmaCon/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" + +#endif diff --git a/CPP/7zip/Bundles/LzmaCon/makefile b/CPP/7zip/Bundles/LzmaCon/makefile new file mode 100755 index 0000000..b0b84f1 --- /dev/null +++ b/CPP/7zip/Bundles/LzmaCon/makefile @@ -0,0 +1,87 @@ +PROG = lzma.exe +MY_CONSOLE = 1 +CFLAGS = $(CFLAGS) + +LZMA_OBJS = \ + $O\LzmaAlone.obj \ + +COMPRESS_OBJS = \ + $O\LzmaDecoder.obj \ + $O\LzmaEncoder.obj \ + $O\LzmaRegister.obj \ + +COMMON_OBJS = \ + $O\CommandLineParser.obj \ + $O\CRC.obj \ + $O\IntToString.obj \ + $O\MyString.obj \ + $O\StringConvert.obj \ + $O\StringToInt.obj \ + $O\MyVector.obj + +WIN_OBJS = \ + $O\FileIO.obj \ + $O\System.obj + +7ZIP_COMMON_OBJS = \ + $O\CWrappers.obj \ + $O\CreateCoder.obj \ + $O\FileStreams.obj \ + $O\FilterCoder.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" + +OBJS = \ + $O\StdAfx.obj \ + $(LZMA_OBJS) \ + $(COMPRESS_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(UI_COMMON_OBJS) \ + $(CONSOLE_OBJS) \ + $(C_OBJS) \ + $(ASM_OBJS) \ + +!include "../../../Build.mak" + + +$(LZMA_OBJS): $(*B).cpp + $(COMPL) +$(COMPRESS_OBJS): ../../Compress/$(*B).cpp + $(COMPL_O2) +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) +$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp + $(COMPL) +$(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp + $(COMPL) +$(C_OBJS): ../../../../C/$(*B).c + $(COMPL_O2) + +!include "../../Asm.mak" diff --git a/CPP/7zip/Bundles/LzmaCon/makefile.gcc b/CPP/7zip/Bundles/LzmaCon/makefile.gcc new file mode 100755 index 0000000..59a70de --- /dev/null +++ b/CPP/7zip/Bundles/LzmaCon/makefile.gcc @@ -0,0 +1,155 @@ +PROG = lzma +CXX = g++ -O2 -Wall +CXX_C = gcc -O2 -Wall +LIB = -lm +RM = rm -f +CFLAGS = -c -D_7ZIP_ST + +ifdef SystemDrive +IS_MINGW = 1 +endif + +ifdef IS_MINGW +FILE_IO =FileIO +FILE_IO_2 =Windows/$(FILE_IO) +LIB2 = -luuid +else +FILE_IO =C_FileIO +FILE_IO_2 =Common/$(FILE_IO) +endif + +OBJS = \ + LzmaAlone.o \ + Bench.o \ + BenchCon.o \ + ConsoleClose.o \ + LzmaDecoder.o \ + LzmaEncoder.o \ + LzmaRegister.o \ + CreateCoder.o \ + CWrappers.o \ + FileStreams.o \ + FilterCoder.o \ + StreamUtils.o \ + $(FILE_IO).o \ + CommandLineParser.o \ + CRC.o \ + IntToString.o \ + MyString.o \ + StringConvert.o \ + StringToInt.o \ + MyVector.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) $(LIB) $(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 + +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 + +MyWindows.o: ../../../Common/MyWindows.cpp + $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp + +IntToString.o: ../../../Common/IntToString.cpp + $(CXX) $(CFLAGS) ../../../Common/IntToString.cpp + +MyString.o: ../../../Common/MyString.cpp + $(CXX) $(CFLAGS) ../../../Common/MyString.cpp + +StringConvert.o: ../../../Common/StringConvert.cpp + $(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp + +StringToInt.o: ../../../Common/StringToInt.cpp + $(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp + +MyVector.o: ../../../Common/MyVector.cpp + $(CXX) $(CFLAGS) ../../../Common/MyVector.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 + +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/CPP/7zip/Bundles/SFXCon/7z.ico b/CPP/7zip/Bundles/SFXCon/7z.ico new file mode 100755 index 0000000000000000000000000000000000000000..47ffb781e0b093aaa123dfb25d83bbd9c94faf41 GIT binary patch literal 1078 zcmcJN&9TBT41_np`H>QGVkm>sTw2QEm=4UhQpgM7fnfk8`dLen1YW7rM#Ip{a^6S> zeBUQNcGBNgI&wCkC$!TJD-~+nQb>|1B^{Pf<2d4-sPU>+M<|bvY`!ftT}cdij;Gwf ztL(j01N*F!jinv8@RYwNa?ZyGb8TQ3B#t>zkk}1x=2P&GJ=cF&I7;vFy#JDafwR$U zz2{mUad!Key&e9uF-zn1JjdpFj}GXS=Ob}j3LGZ`r^8_hKjL{@X5~_8i{jypFWG+L dSv+xdUN!3Ykk{D6Oj6*1O$q9mQ*X-ky9;9RJVF2f literal 0 HcmV?d00001 diff --git a/CPP/7zip/Bundles/SFXCon/Main.cpp b/CPP/7zip/Bundles/SFXCon/Main.cpp new file mode 100755 index 0000000..d285c48 --- /dev/null +++ b/CPP/7zip/Bundles/SFXCon/Main.cpp @@ -0,0 +1,444 @@ +// Main.cpp + +#include "StdAfx.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 "../../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" + +using namespace NWindows; +using namespace NFile; +using namespace NCommandLineParser; + +int g_CodePage = -1; +extern CStdOutStream *g_StdStream; + +static const char *kCopyrightString = +"\n7-Zip SFX " MY_VERSION_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'; +static const wchar_t *kRecursedPostCharSet = L"0-"; + +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] = + { + { L"?", NSwitchType::kSimple, false }, + { L"H", NSwitchType::kSimple, false }, + { L"BD", NSwitchType::kSimple, false }, + { L"Y", NSwitchType::kSimple, false }, + { L"P", NSwitchType::kUnLimitedPostString, false, 1 }, + { L"O", NSwitchType::kUnLimitedPostString, false, 1 }, + }; + +static const int kNumCommandForms = 3; + +namespace NCommandType { +enum EEnum +{ + kTest = 0, + // kExtract, + kFullExtract, + kList +}; + +} + +static const CCommandForm commandForms[kNumCommandForms] = +{ + { L"T", false }, + // { "E", false }, + { L"X", false }, + { L"L", false } +}; + +static const NRecursedType::EEnum kCommandRecursedDefault[kNumCommandForms] = +{ + NRecursedType::kRecursed +}; + +// static const bool kTestExtractRecursedDefault = true; +// static const bool kAddRecursedDefault = false; + +static const wchar_t *kUniversalWildcard = L"*"; +static const int kCommandIndex = 0; + +static const char *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 *kUserErrorMessage = "Incorrect command line"; // NExitCode::kUserError +// static const char *kIncorrectListFile = "Incorrect wildcard in listfile"; +static const char *kIncorrectWildCardInCommandLine = "Incorrect wildcard in command line"; + +// static const CSysString kFileIsNotArchiveMessageBefore = "File \""; +// static const CSysString kFileIsNotArchiveMessageAfter = "\" is not archive"; + +// static const char *kProcessArchiveMessage = " archive: "; + +static const char *kCantFindSFX = " cannot find sfx"; + + +struct CArchiveCommand +{ + NCommandType::EEnum CommandType; + NRecursedType::EEnum DefaultRecursedType() const; +}; + +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); +} + +bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command) +{ + UString commandStringUpper = commandString; + commandStringUpper.MakeUpper(); + UString postString; + int commandIndex = ParseCommand(kNumCommandForms, commandForms, commandStringUpper, + postString) ; + if (commandIndex < 0) + return false; + command.CommandType = (NCommandType::EEnum)commandIndex; + return true; +} + +// ------------------------------------------------------------------ +// 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.AddItem(include, name, recursed); + 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); +} + +void AddToCensorFromNonSwitchesStrings(NWildcard::CCensor &wildcardCensor, + const UStringVector & /* nonSwitchStrings */, NRecursedType::EEnum type, + bool /* thereAreSwitchIncludeWildCards */) +{ + AddCommandLineWildCardToCensor(wildcardCensor, kUniversalWildcard, true, type); +} + + +#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 +) +{ + #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 + + UString arcPath; + { + UString path; + NDLL::MyGetModuleFileName(NULL, path); + int fileNamePartStartIndex; + if (!NDirectory::MyGetFullPathName(path, arcPath, fileNamePartStartIndex)) + { + g_StdOut << "GetFullPathName Error"; + return NExitCode::kFatalError; + } + } + + #else + + UString arcPath = commandStrings.Front(); + + #endif + + commandStrings.Delete(0); + + NCommandLineParser::CParser parser(kNumSwitches); + try + { + parser.ParseStrings(kSwitchForms, commandStrings); + } + catch(...) + { + PrintHelpAndExit(); + } + + if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) + { + PrintHelp(); + return 0; + } + const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; + + int numNonSwitchStrings = nonSwitchStrings.Size(); + + CArchiveCommand command; + if (numNonSwitchStrings == 0) + command.CommandType = NCommandType::kFullExtract; + else + { + if (numNonSwitchStrings > 1) + PrintHelpAndExit(); + if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], command)) + PrintHelpAndExit(); + } + + + NRecursedType::EEnum recursedType; + recursedType = command.DefaultRecursedType(); + + NWildcard::CCensor wildcardCensor; + + bool thereAreSwitchIncludeWildCards; + thereAreSwitchIncludeWildCards = false; + AddToCensorFromNonSwitchesStrings(wildcardCensor, nonSwitchStrings, recursedType, + thereAreSwitchIncludeWildCards); + + 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; + + UString outputDir; + if (parser[NKey::kOutputDir].ThereIs) + { + outputDir = parser[NKey::kOutputDir].PostStrings[0]; + NName::NormalizeDirPathPrefix(outputDir); + } + + { + UStringVector v1, v2; + v1.Add(arcPath); + v2.Add(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->OutStream = g_StdStream; + + #ifndef _NO_CRYPTO + ecs->PasswordIsDefined = passwordEnabled; + ecs->Password = password; + #endif + + ecs->Init(); + + COpenCallbackConsole openCallback; + openCallback.OutStream = g_StdStream; + + #ifndef _NO_CRYPTO + openCallback.PasswordIsDefined = passwordEnabled; + openCallback.Password = password; + #endif + + CExtractOptions eo; + eo.StdOutMode = false; + eo.PathMode = NExtract::NPathMode::kFullPathnames; + eo.TestMode = command.CommandType == NCommandType::kTest; + eo.OverwriteMode = yesToAll ? + NExtract::NOverwriteMode::kWithoutPrompt : + NExtract::NOverwriteMode::kAskBefore; + eo.OutputDir = outputDir; + eo.YesToAll = yesToAll; + + UString errorMessage; + CDecompressStat stat; + HRESULT result = DecompressArchives( + codecs, CIntVector(), + v1, v2, + wildcardCensorHead, + eo, &openCallback, ecs, errorMessage, stat); + if (!errorMessage.IsEmpty()) + { + (*g_StdStream) << endl << "Error: " << errorMessage;; + if (result == S_OK) + result = E_FAIL; + } + + if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0) + { + if (ecs->NumArchiveErrors != 0) + (*g_StdStream) << endl << "Archive Errors: " << ecs->NumArchiveErrors << 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 + { + UInt64 numErrors = 0; + HRESULT result = ListArchives( + codecs, CIntVector(), + false, + v1, v2, + wildcardCensorHead, + true, false, + #ifndef _NO_CRYPTO + passwordEnabled, password, + #endif + numErrors); + if (numErrors > 0) + { + g_StdOut << endl << "Errors: " << numErrors; + return NExitCode::kFatalError; + } + if (result != S_OK) + throw CSystemException(result); + } + } + return 0; +} diff --git a/CPP/7zip/Bundles/SFXCon/SFXCon.dsp b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp new file mode 100755 index 0000000..39d943f --- /dev/null +++ b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp @@ -0,0 +1,821 @@ +# 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 /W3 /GX /O1 /I "..\..\..\\" /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.sfx" /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 /W3 /Gm /GX /ZI /Od /I "..\..\..\..\\" /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.sfx" /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\CoderMixer2MT.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\CoderMixer2MT.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\CrossThreadProgress.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 "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\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\7zFolderOutStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zFolderOutStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\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\7zRegister.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\BranchCoder.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\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 "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\Error.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Error.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\PropVariantConversions.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariantConversions.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Synchronization.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Synchronization.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\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\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\CpuArch.c +# SUBTRACT CPP /YX /Yc /Yu +# 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\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\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=.\Main.cpp +# End Source File +# End Target +# End Project diff --git a/CPP/7zip/Bundles/SFXCon/SFXCon.dsw b/CPP/7zip/Bundles/SFXCon/SFXCon.dsw new file mode 100755 index 0000000..bfbc2b7 --- /dev/null +++ b/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/CPP/7zip/Bundles/SFXCon/StdAfx.cpp b/CPP/7zip/Bundles/SFXCon/StdAfx.cpp new file mode 100755 index 0000000..c6d3b1f --- /dev/null +++ b/CPP/7zip/Bundles/SFXCon/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/Bundles/SFXCon/StdAfx.h b/CPP/7zip/Bundles/SFXCon/StdAfx.h new file mode 100755 index 0000000..a4e6173 --- /dev/null +++ b/CPP/7zip/Bundles/SFXCon/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" +#include "../../../Common/NewHandler.h" + +#endif diff --git a/CPP/7zip/Bundles/SFXCon/makefile b/CPP/7zip/Bundles/SFXCon/makefile new file mode 100755 index 0000000..2d06dc7 --- /dev/null +++ b/CPP/7zip/Bundles/SFXCon/makefile @@ -0,0 +1,164 @@ +PROG = 7zCon.sfx +MY_CONSOLE = 1 +CFLAGS = $(CFLAGS) -I ../../../ \ + -DEXTRACT_ONLY \ + -DNO_READ_FROM_CODER \ + -D_SFX \ + +SFX_CONSOLE_OBJS = \ + $O\Main.obj \ + +CONSOLE_OBJS = \ + $O\ConsoleClose.obj \ + $O\ExtractCallbackConsole.obj \ + $O\List.obj \ + $O\MainAr.obj \ + $O\OpenCallbackConsole.obj \ + $O\UserInputUtils.obj \ + +COMMON_OBJS = \ + $O\CommandLineParser.obj \ + $O\CRC.obj \ + $O\IntToString.obj \ + $O\NewHandler.obj \ + $O\StdInStream.obj \ + $O\StdOutStream.obj \ + $O\MyString.obj \ + $O\StringConvert.obj \ + $O\MyVector.obj \ + $O\Wildcard.obj \ + $O\UTFConvert.obj \ + +WIN_OBJS = \ + $O\DLL.obj \ + $O\Error.obj \ + $O\FileDir.obj \ + $O\FileFind.obj \ + $O\FileIO.obj \ + $O\FileName.obj \ + $O\PropVariant.obj \ + $O\PropVariantConversions.obj \ + $O\Synchronization.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\LockedStream.obj \ + $O\OutBuffer.obj \ + $O\ProgressUtils.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_COMMON_OBJS = \ + $O\CoderMixer2.obj \ + $O\CoderMixer2MT.obj \ + $O\CrossThreadProgress.obj \ + $O\ItemNameUtils.obj \ + $O\OutStreamWithCRC.obj \ + + +7Z_OBJS = \ + $O\7zDecode.obj \ + $O\7zExtract.obj \ + $O\7zFolderOutStream.obj \ + $O\7zHandler.obj \ + $O\7zHeader.obj \ + $O\7zIn.obj \ + $O\7zRegister.obj \ + +COMPRESS_OBJS = \ + $O\BranchCoder.obj \ + $O\Bcj2Coder.obj \ + $O\Bcj2Register.obj \ + $O\BcjCoder.obj \ + $O\BcjRegister.obj \ + $O\CopyCoder.obj \ + $O\CopyRegister.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\Bra86.obj \ + $O\CpuArch.obj \ + $O\Lzma2Dec.obj \ + $O\LzmaDec.obj \ + $O\Ppmd7.obj \ + $O\Ppmd7Dec.obj \ + $O\Sha256.obj \ + $O\Threads.obj \ + +!include "../../Aes.mak" +!include "../../Crc.mak" + +OBJS = \ + $O\StdAfx.obj \ + $(SFX_CONSOLE_OBJS) \ + $(CONSOLE_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(UI_COMMON_OBJS) \ + $(AR_COMMON_OBJS) \ + $(7Z_OBJS) \ + $(COMPRESS_OBJS) \ + $(CRYPTO_OBJS) \ + $(C_OBJS) \ + $(ASM_OBJS) \ + $O\resource.res + + +!include "../../../Build.mak" + +$(SFX_CONSOLE_OBJS): $(*B).cpp + $(COMPL) + +$(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp + $(COMPL) +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) +$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp + $(COMPL) +$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp + $(COMPL) + +$(7Z_OBJS): ../../Archive/7z/$(*B).cpp + $(COMPL) +$(COMPRESS_OBJS): ../../Compress/$(*B).cpp + $(COMPL) +$(CRYPTO_OBJS): ../../Crypto/$(*B).cpp + $(COMPL) +$(C_OBJS): ../../../../C/$(*B).c + $(COMPL_O2) + +!include "../../Asm.mak" diff --git a/CPP/7zip/Bundles/SFXCon/resource.rc b/CPP/7zip/Bundles/SFXCon/resource.rc new file mode 100755 index 0000000..97882cd --- /dev/null +++ b/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/CPP/7zip/Bundles/SFXSetup/ExtractCallback.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractCallback.cpp new file mode 100755 index 0000000..6863056 --- /dev/null +++ b/CPP/7zip/Bundles/SFXSetup/ExtractCallback.cpp @@ -0,0 +1,236 @@ +// ExtractCallback.h + +#include "StdAfx.h" + +#include "Common/Wildcard.h" + +#include "Windows/FileDir.h" +#include "Windows/FileFind.h" +#include "Windows/PropVariant.h" + +#include "ExtractCallback.h" + +using namespace NWindows; +using namespace NFile; + +static LPCWSTR kCantDeleteFile = L"Can not delete output file"; +static LPCWSTR kCantOpenFile = L"Can not open output file"; +static LPCWSTR kUnsupportedMethod = L"Unsupported Method"; + +void CExtractCallbackImp::Init(IInArchive *archiveHandler, + const UString &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 +} + +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) +{ + UString fullPath = _directoryPath; + for(int i = 0; i < dirPathParts.Size(); i++) + { + fullPath += dirPathParts[i]; + NDirectory::MyCreateDirectory(fullPath); + fullPath += NName::kDirDelimiter; + } +} + +STDMETHODIMP CExtractCallbackImp::GetStream(UInt32 index, + ISequentialOutStream **outStream, Int32 askExtractMode) +{ + #ifndef _NO_PROGRESS + if (ProgressDialog.Sync.GetStopped()) + return E_ABORT; + #endif + _outFileStream.Release(); + NCOM::CPropVariant propVariantName; + RINOK(_archiveHandler->GetProperty(index, kpidPath, &propVariantName)); + UString fullPath; + if (propVariantName.vt == VT_EMPTY) + fullPath = _itemDefaultName; + else + { + if (propVariantName.vt != VT_BSTR) + return E_FAIL; + fullPath = propVariantName.bstrVal; + } + _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); + } + + UString fullProcessedPath = _directoryPath + processedPath; + + if (_processedFileInfo.IsDir) + { + _diskFilePath = fullProcessedPath; + + if (isAnti) + NDirectory::MyRemoveDirectory(_diskFilePath); + else + NDirectory::SetDirTime(_diskFilePath, NULL, NULL, &_processedFileInfo.MTime); + return S_OK; + } + + NFind::CFileInfoW fileInfo; + if (fileInfo.Find(fullProcessedPath)) + { + if (!NDirectory::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) + NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attributes); + return S_OK; +} diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractCallback.h b/CPP/7zip/Bundles/SFXSetup/ExtractCallback.h new file mode 100755 index 0000000..8cac0c3 --- /dev/null +++ b/CPP/7zip/Bundles/SFXSetup/ExtractCallback.h @@ -0,0 +1,88 @@ +// ExtractCallback.h + +#ifndef __EXTRACT_CALLBACK_H +#define __EXTRACT_CALLBACK_H + +#include "resource.h" + +#include "Windows/ResourceString.h" + +#include "../../Archive/IArchive.h" + +#include "../../Common/FileStreams.h" +#include "../../ICoder.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; + UString _directoryPath; + UString _filePath; + UString _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 UString &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); + { + #ifdef LANG + ProgressDialog.SetText(LangLoadString(IDS_PROGRESS_EXTRACTING, 0x02000890)); + #else + ProgressDialog.SetText(NWindows::MyLoadStringW(IDS_PROGRESS_EXTRACTING)); + #endif + } + + ProgressDialog.Show(SW_SHOWNORMAL); + return S_OK; + } + virtual ~CExtractCallbackImp() { ProgressDialog.Destroy(); } + #endif + +}; + +#endif diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp new file mode 100755 index 0000000..ca400b4 --- /dev/null +++ b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp @@ -0,0 +1,130 @@ +// ExtractEngine.cpp + +#include "StdAfx.h" + +#include "Windows/FileDir.h" +#include "Windows/Thread.h" + +#include "../../UI/Common/OpenArchive.h" + +#include "../../UI/FileManager/FormatUtils.h" + +#include "ExtractCallback.h" +#include "ExtractEngine.h" + +using namespace NWindows; + +static LPCWSTR kCantFindArchive = L"Can not find archive file"; +static LPCWSTR kCantOpenArchive = L"Can not open the file as archive"; + +struct CThreadExtracting +{ + CCodecs *Codecs; + UString FileName; + UString DestFolder; + + CExtractCallbackImp *ExtractCallbackSpec; + CMyComPtr ExtractCallback; + + CArchiveLink ArchiveLink; + HRESULT Result; + UString ErrorMessage; + + void Process2() + { + NFile::NFind::CFileInfoW fi; + if (!fi.Find(FileName)) + { + ErrorMessage = kCantFindArchive; + Result = E_FAIL; + return; + } + + Result = ArchiveLink.Open2(Codecs, CIntVector(), false, NULL, FileName, ExtractCallbackSpec); + if (Result != S_OK) + { + if (Result != S_OK) + ErrorMessage = kCantOpenArchive; + return; + } + + UString dirPath = DestFolder; + NFile::NName::NormalizeDirPathPrefix(dirPath); + + if (!NFile::NDirectory::CreateComplexDirectory(dirPath)) + { + ErrorMessage = MyFormatNew(IDS_CANNOT_CREATE_FOLDER, + #ifdef LANG + 0x02000603, + #endif + dirPath); + Result = E_FAIL; + return; + } + + ExtractCallbackSpec->Init(ArchiveLink.GetArchive(), dirPath, L"Default", fi.MTime, 0); + + Result = ArchiveLink.GetArchive()->Extract(0, (UInt32)-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 UString &fileName, const UString &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; + #ifdef LANG + title = LangLoadString(IDS_PROGRESS_EXTRACTING, 0x02000890); + #else + title = NWindows::MyLoadStringW(IDS_PROGRESS_EXTRACTING); + #endif + 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/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h new file mode 100755 index 0000000..40170ef --- /dev/null +++ b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h @@ -0,0 +1,11 @@ +// ExtractEngine.h + +#ifndef __EXTRACTENGINE_H +#define __EXTRACTENGINE_H + +#include "../../UI/Common/LoadCodecs.h" + +HRESULT ExtractArchive(CCodecs *codecs, const UString &fileName, const UString &destFolder, + bool showProgress, bool &isCorrupt, UString &errorMessage); + +#endif diff --git a/CPP/7zip/Bundles/SFXSetup/Main.cpp b/CPP/7zip/Bundles/SFXSetup/Main.cpp new file mode 100755 index 0000000..225e140 --- /dev/null +++ b/CPP/7zip/Bundles/SFXSetup/Main.cpp @@ -0,0 +1,336 @@ +// Main.cpp + +#include "StdAfx.h" + +#include "Common/MyInitGuid.h" + +#include "Common/CommandLineParser.h" +#include "Common/StringConvert.h" +#include "Common/TextConfig.h" + +#include "Windows/DLL.h" +#include "Windows/FileDir.h" +#include "Windows/FileFind.h" +#include "Windows/FileIO.h" +#include "Windows/NtCheck.h" +#include "Windows/ResourceString.h" + +#include "../../UI/Explorer/MyMessages.h" + +#include "ExtractEngine.h" + +#include "resource.h" + +using namespace NWindows; + +HINSTANCE g_hInstance; + +static LPCTSTR kTempDirPrefix = TEXT("7zS"); + +#define _SHELL_EXECUTE + +static bool ReadDataString(LPCWSTR fileName, LPCSTR startID, + LPCSTR endID, AString &stringResult) +{ + stringResult.Empty(); + NFile::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[] = ",!@Install@!UTF-8!"; +static char kEndID[] = ",!@InstallEnd@!"; + +class CInstallIDInit +{ +public: + CInstallIDInit() + { + kStartID[0] = ';'; + kEndID[0] = ';'; + }; +} g_CInstallIDInit; + + +#ifndef UNDER_CE +class CCurrentDirRestorer +{ + CSysString m_CurrentDirectory; +public: + CCurrentDirRestorer() { NFile::NDirectory::MyGetCurrentDirectory(m_CurrentDirectory); } + ~CCurrentDirRestorer() { RestoreDirectory();} + bool RestoreDirectory() { return BOOLToBool(::SetCurrentDirectory(m_CurrentDirectory)); } +}; +#endif + +#define NT_CHECK_FAIL_ACTION ShowErrorMessage(L"Unsupported Windows version"); return 1; + +int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, + #ifdef UNDER_CE + LPWSTR + #else + LPSTR + #endif + /* lpCmdLine */,int /* nCmdShow */) +{ + g_hInstance = (HINSTANCE)hInstance; + + NT_CHECK + + // InitCommonControls(); + + UString archiveName, switches; + #ifdef _SHELL_EXECUTE + UString executeFile, executeParameters; + #endif + NCommandLineParser::SplitCommandLine(GetCommandLineW(), archiveName, switches); + + UString fullPath; + NDLL::MyGetModuleFileName(g_hInstance, fullPath); + + switches.Trim(); + bool assumeYes = false; + if (switches.Left(2).CompareNoCase(UString(L"-y")) == 0) + { + assumeYes = true; + switches = switches.Mid(2); + switches.Trim(); + } + + AString config; + if (!ReadDataString(fullPath, kStartID, kEndID, config)) + { + if (!assumeYes) + ShowErrorMessage(L"Can't load config info"); + return 1; + } + + UString dirPrefix = L"." WSTRING_PATH_SEPARATOR; + UString appLaunched; + bool showProgress = true; + if (!config.IsEmpty()) + { + CObjectVector pairs; + if (!GetTextConfig(config, pairs)) + { + if (!assumeYes) + ShowErrorMessage(L"Config failed"); + return 1; + } + UString friendlyName = GetTextConfigValue(pairs, L"Title"); + UString installPrompt = GetTextConfigValue(pairs, L"BeginPrompt"); + UString progress = GetTextConfigValue(pairs, L"Progress"); + if (progress.CompareNoCase(L"no") == 0) + showProgress = false; + int index = FindTextConfigItem(pairs, L"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, L"RunProgram"); + + #ifdef _SHELL_EXECUTE + executeFile = GetTextConfigValue(pairs, L"ExecuteFile"); + executeParameters = GetTextConfigValue(pairs, L"ExecuteParameters") + switches; + #endif + } + + NFile::NDirectory::CTempDirectory tempDir; + if (!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; + } + + UString tempDirPath = GetUnicodeString(tempDir.GetPath()); + { + 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) + { + errorMessage = NWindows::MyLoadStringW(IDS_EXTRACTION_ERROR_MESSAGE); + result = E_FAIL; + } + if (result != E_ABORT && !errorMessage.IsEmpty()) + ::MessageBoxW(0, errorMessage, NWindows::MyLoadStringW(IDS_EXTRACTION_ERROR_TITLE), MB_ICONERROR); + } + return 1; + } + } + + #ifndef UNDER_CE + CCurrentDirRestorer currentDirRestorer; + if (!SetCurrentDirectory(tempDir.GetPath())) + 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 += 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 (!NFile::NFind::DoesFileExist(GetSystemString(appLaunched))) + { + if (!assumeYes) + ShowErrorMessage(L"Can not find setup.exe"); + return 1; + } + } + + { + UString s2 = tempDirPath; + NFile::NName::NormalizeDirPathPrefix(s2); + appLaunched.Replace(L"%%T" WSTRING_PATH_SEPARATOR, s2); + } + + appLaunched.Replace(L"%%T", tempDirPath); + + if (!switches.IsEmpty()) + { + appLaunched += L' '; + 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) + ShowLastErrorMessage(); + return 1; + } + ::CloseHandle(processInformation.hThread); + hProcess = processInformation.hProcess; + } + if (hProcess != 0) + { + WaitForSingleObject(hProcess, INFINITE); + ::CloseHandle(hProcess); + } + return 0; +} diff --git a/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp new file mode 100755 index 0000000..dd71b26 --- /dev/null +++ b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp @@ -0,0 +1,748 @@ +# 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 /W3 /GX /O1 /I "..\..\..\\" /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 comctl32.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:windows /machine:I386 /out:"C:\Util\7zS.sfx" /opt:NOWIN98 +# 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 /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /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 comctl32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\UTIL\7zSfxS.exe" /pdbtype:sept + +!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 /W3 /GX /O1 /I "..\..\..\\" /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 comctl32.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:windows /machine:I386 /out:"C:\UTIL\7zWinSR.exe" +# SUBTRACT BASE LINK32 /debug /nodefaultlib +# ADD LINK32 comctl32.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:windows /machine:I386 /out:"C:\Util\7zSD.sfx" /opt:NOWIN98 +# 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\7zFolderOutStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zFolderOutStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\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\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\CoderMixer2MT.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\CoderMixer2MT.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\CrossThreadProgress.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\BranchCoder.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\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\Error.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Error.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\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\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\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\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\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\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\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\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\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=.\ExtractCallback.cpp +# End Source File +# Begin Source File + +SOURCE=.\ExtractCallback.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=.\Main.cpp +# End Source File +# Begin Source File + +SOURCE=.\setup.ico +# End Source File +# End Target +# End Project diff --git a/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw new file mode 100755 index 0000000..2970370 --- /dev/null +++ b/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/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp b/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp new file mode 100755 index 0000000..c6d3b1f --- /dev/null +++ b/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/Bundles/SFXSetup/StdAfx.h b/CPP/7zip/Bundles/SFXSetup/StdAfx.h new file mode 100755 index 0000000..8553620 --- /dev/null +++ b/CPP/7zip/Bundles/SFXSetup/StdAfx.h @@ -0,0 +1,10 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" +#include "../../../Common/NewHandler.h" +#include + +#endif diff --git a/CPP/7zip/Bundles/SFXSetup/makefile b/CPP/7zip/Bundles/SFXSetup/makefile new file mode 100755 index 0000000..0e3d4ec --- /dev/null +++ b/CPP/7zip/Bundles/SFXSetup/makefile @@ -0,0 +1,153 @@ +PROG = 7zS.sfx +CFLAGS = $(CFLAGS) -I ../../../ \ + -DNO_REGISTRY \ + -DEXTRACT_ONLY \ + -DNO_READ_FROM_CODER \ + -D_SFX \ + -D_NO_CRYPTO \ + +SFX_WIN_OBJS = \ + $O\Main.obj \ + $O\ExtractCallback.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\Error.obj \ + $O\FileDir.obj \ + $O\FileFind.obj \ + $O\FileIO.obj \ + $O\FileName.obj \ + $O\PropVariant.obj \ + $O\ResourceString.obj \ + $O\Synchronization.obj \ + $O\Window.obj \ + +WIN_CTRL_OBJS = \ + $O\Dialog.obj \ + +7ZIP_COMMON_OBJS = \ + $O\CreateCoder.obj \ + $O\FileStreams.obj \ + $O\InBuffer.obj \ + $O\FilterCoder.obj \ + $O\LimitedStreams.obj \ + $O\LockedStream.obj \ + $O\OutBuffer.obj \ + $O\ProgressUtils.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 \ + +FM_OBJS = \ + $O\FormatUtils.obj \ + $O\ProgressDialog.obj \ + +AR_COMMON_OBJS = \ + $O\CoderMixer2.obj \ + $O\CoderMixer2MT.obj \ + $O\CrossThreadProgress.obj \ + $O\ItemNameUtils.obj \ + $O\OutStreamWithCRC.obj \ + +7Z_OBJS = \ + $O\7zDecode.obj \ + $O\7zExtract.obj \ + $O\7zFolderOutStream.obj \ + $O\7zHandler.obj \ + $O\7zHeader.obj \ + $O\7zIn.obj \ + $O\7zRegister.obj \ + +COMPRESS_OBJS = \ + $O\BranchCoder.obj \ + $O\Bcj2Coder.obj \ + $O\Bcj2Register.obj \ + $O\BcjCoder.obj \ + $O\BcjRegister.obj \ + $O\CopyCoder.obj \ + $O\CopyRegister.obj \ + $O\Lzma2Decoder.obj \ + $O\Lzma2Register.obj \ + $O\LzmaDecoder.obj \ + $O\LzmaRegister.obj \ + +C_OBJS = \ + $O\Alloc.obj \ + $O\Bra86.obj \ + $O\CpuArch.obj \ + $O\Lzma2Dec.obj \ + $O\LzmaDec.obj \ + $O\Threads.obj \ + +!include "../../Crc.mak" + +OBJS = \ + $O\StdAfx.obj \ + $(SFX_WIN_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(WIN_CTRL_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(UI_COMMON_OBJS) \ + $(FM_OBJS)\ + $(AR_COMMON_OBJS) \ + $(7Z_OBJS) \ + $(COMPRESS_OBJS) \ + $O\MyMessages.obj \ + $(C_OBJS) \ + $(ASM_OBJS) \ + $O\resource.res + + +!include "../../../Build.mak" + +$(SFX_WIN_OBJS): $(*B).cpp + $(COMPL) + +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +$(WIN_CTRL_OBJS): ../../../Windows/Control/$(*B).cpp + $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) +$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp + $(COMPL) +$(FM_OBJS): ../../UI/FileManager//$(*B).cpp + $(COMPL) +$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp + $(COMPL) + +$(7Z_OBJS): ../../Archive/7z/$(*B).cpp + $(COMPL) +$(COMPRESS_OBJS): ../../Compress/$(*B).cpp + $(COMPL) + +$O\MyMessages.obj: ../../UI/Explorer/MyMessages.cpp + $(COMPL) + +$(C_OBJS): ../../../../C/$(*B).c + $(COMPL_O2) + +!include "../../Asm.mak" diff --git a/CPP/7zip/Bundles/SFXSetup/resource.h b/CPP/7zip/Bundles/SFXSetup/resource.h new file mode 100755 index 0000000..b1e7082 --- /dev/null +++ b/CPP/7zip/Bundles/SFXSetup/resource.h @@ -0,0 +1,6 @@ +#define IDI_ICON 1 + +#define IDS_EXTRACTION_ERROR_TITLE 7 +#define IDS_EXTRACTION_ERROR_MESSAGE 8 +#define IDS_CANNOT_CREATE_FOLDER 9 +#define IDS_PROGRESS_EXTRACTING 69 diff --git a/CPP/7zip/Bundles/SFXSetup/resource.rc b/CPP/7zip/Bundles/SFXSetup/resource.rc new file mode 100755 index 0000000..8230224 --- /dev/null +++ b/CPP/7zip/Bundles/SFXSetup/resource.rc @@ -0,0 +1,16 @@ +#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" +END + +#include "../../UI/FileManager/ProgressDialog.rc" diff --git a/CPP/7zip/Bundles/SFXSetup/setup.ico b/CPP/7zip/Bundles/SFXSetup/setup.ico new file mode 100755 index 0000000000000000000000000000000000000000..bb455be1e7ad179c85570c6493ac7d1461cba2f1 GIT binary patch literal 1078 zcmbu7Jx;?w5QQf(Qe2Vb1WAQbuCxVZQbeN6EmA@{7Ze^Th22>kg^G3y4w3>P${CFdNn8scvf(H_91kF@y~Ya7Bur@9ScTm2Bi#sLRE4yal`4mkQ@!aw}7 zWTN(bi8Wcqlv+E*i-;I&q+wd;QP+v;^s=dgUmMlyJkR3`T7piRrmp;asr~$Eep!{J zyqA^O6ze5*5q+uq&}52gi%&OS$kwQ)q8bk6ZMl&7JnD~ok?R}TKehT!WC{Hkb=VJW z(B&Ztzg~6>ujf8y*vkLjBIv7C)?0n?PqiQA{o`_(>cej6@RoYAr37>UDLI&)K+v8I zvI7h>7&x#2JFx#FTIT~W25p@?^nVTx8=|Js1Gv!nQ=M!17);i(w3<<_K1Z#7l5(n5 zWcs{rv|9R{QGVkm>sTw2QEm=4UhQpgM7fnfk8`dLen1YW7rM#Ip{a^6S> zeBUQNcGBNgI&wCkC$!TJD-~+nQb>|1B^{Pf<2d4-sPU>+M<|bvY`!ftT}cdij;Gwf ztL(j01N*F!jinv8@RYwNa?ZyGb8TQ3B#t>zkk}1x=2P&GJ=cF&I7;vFy#JDafwR$U zz2{mUad!Key&e9uF-zn1JjdpFj}GXS=Ob}j3LGZ`r^8_hKjL{@X5~_8i{jypFWG+L dSv+xdUN!3Ykk{D6Oj6*1O$q9mQ*X-ky9;9RJVF2f literal 0 HcmV?d00001 diff --git a/CPP/7zip/Bundles/SFXWin/Main.cpp b/CPP/7zip/Bundles/SFXWin/Main.cpp new file mode 100755 index 0000000..dc74a81 --- /dev/null +++ b/CPP/7zip/Bundles/SFXWin/Main.cpp @@ -0,0 +1,173 @@ +// Main.cpp + +#include "StdAfx.h" + +#include "Common/MyInitGuid.h" + +#include "Common/CommandLineParser.h" +#include "Common/StringConvert.h" + +#include "Windows/DLL.h" +#include "Windows/Error.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/GUI/ExtractGUI.h" +#include "../../UI/GUI/ExtractRes.h" + +HINSTANCE g_hInstance; + +#ifdef UNDER_CE +bool g_LVN_ITEMACTIVATE_Support = true; +#endif + +static const wchar_t *kUnknownExceptionMessage = L"ERROR: Unknown Error!"; + +void ErrorMessageForHRESULT(HRESULT res) +{ + ShowErrorMessage(HResultToMessage(res)); +} + +int APIENTRY WinMain2() +{ + UString password; + bool assumeYes = false; + bool outputFolderDefined = false; + UString outputFolder; + UStringVector commandStrings; + NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); + + #ifndef UNDER_CE + if (commandStrings.Size() > 0) + commandStrings.Delete(0); + #endif + + for (int i = 0; i < commandStrings.Size(); i++) + { + const UString &s = commandStrings[i]; + if (s.CompareNoCase(L"-y") == 0) + assumeYes = true; + else if (s.Left(2).CompareNoCase(L"-o") == 0) + { + outputFolder = s.Mid(2); + NWindows::NFile::NName::NormalizeDirPathPrefix(outputFolder); + outputFolderDefined = !outputFolder.IsEmpty(); + } + else if (s.Left(2).CompareNoCase(L"-p") == 0) + { + password = s.Mid(2); + } + } + + UString path; + NWindows::NDLL::MyGetModuleFileName(g_hInstance, path); + + UString fullPath; + int fileNamePartStartIndex; + if (!NWindows::NFile::NDirectory::MyGetFullPathName(path, fullPath, fileNamePartStartIndex)) + { + 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; + eo.OutputDir = outputFolderDefined ? outputFolder : + fullPath.Left(fileNamePartStartIndex); + eo.YesToAll = assumeYes; + eo.OverwriteMode = assumeYes ? + NExtract::NOverwriteMode::kWithoutPrompt : + NExtract::NOverwriteMode::kAskBefore; + eo.PathMode = NExtract::NPathMode::kFullPathnames; + eo.TestMode = false; + + UStringVector v1, v2; + v1.Add(fullPath); + v2.Add(fullPath); + NWildcard::CCensorNode wildcardCensor; + wildcardCensor.AddItem(true, L"*", true, true, true); + + bool messageWasDisplayed = false; + result = ExtractGUI(codecs, 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 + { + return WinMain2(); + } + catch(const CNewException &) + { + ErrorMessageForHRESULT(E_OUTOFMEMORY); + return NExitCode::kMemoryError; + } + catch(...) + { + ShowErrorMessage(kUnknownExceptionMessage); + return NExitCode::kFatalError; + } +} + diff --git a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp new file mode 100755 index 0000000..0859483 --- /dev/null +++ b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp @@ -0,0 +1,885 @@ +# 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 /W3 /GX /O1 /I "..\..\..\\" /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 /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /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\7z.sfx" /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 /W3 /GX /O1 /I "..\..\..\\" /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\7zFolderOutStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zFolderOutStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\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\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\CoderMixer2MT.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\CoderMixer2MT.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\CrossThreadProgress.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\BranchCoder.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\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\MessagesDialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\MessagesDialog.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\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 +# 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 +# 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\DLL.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\DLL.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Error.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Error.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\PropVariantConversions.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariantConversions.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\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\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\CpuArch.c +# SUBTRACT CPP /YX /Yc /Yu +# 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\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\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=.\Main.cpp +# End Source File +# Begin Source File + +SOURCE=.\resource.rc +# End Source File +# End Target +# End Project diff --git a/CPP/7zip/Bundles/SFXWin/SFXWin.dsw b/CPP/7zip/Bundles/SFXWin/SFXWin.dsw new file mode 100755 index 0000000..6695803 --- /dev/null +++ b/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/CPP/7zip/Bundles/SFXWin/StdAfx.cpp b/CPP/7zip/Bundles/SFXWin/StdAfx.cpp new file mode 100755 index 0000000..c6d3b1f --- /dev/null +++ b/CPP/7zip/Bundles/SFXWin/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/Bundles/SFXWin/StdAfx.h b/CPP/7zip/Bundles/SFXWin/StdAfx.h new file mode 100755 index 0000000..0ae3720 --- /dev/null +++ b/CPP/7zip/Bundles/SFXWin/StdAfx.h @@ -0,0 +1,12 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" +#include "../../../Common/NewHandler.h" + +#include +#include + +#endif diff --git a/CPP/7zip/Bundles/SFXWin/makefile b/CPP/7zip/Bundles/SFXWin/makefile new file mode 100755 index 0000000..86c1384 --- /dev/null +++ b/CPP/7zip/Bundles/SFXWin/makefile @@ -0,0 +1,191 @@ +PROG = 7z.sfx +CFLAGS = $(CFLAGS) -I ../../../ \ + -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 + +SFX_WIN_OBJS = \ + $O\Main.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\DLL.obj \ + $O\Error.obj \ + $O\FileDir.obj \ + $O\FileFind.obj \ + $O\FileIO.obj \ + $O\FileName.obj \ + $O\PropVariant.obj \ + $O\PropVariantConversions.obj \ + $O\ResourceString.obj \ + $O\Shell.obj \ + $O\Synchronization.obj \ + $O\Window.obj \ + +WIN_CTRL_OBJS = \ + $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\LockedStream.obj \ + $O\OutBuffer.obj \ + $O\ProgressUtils.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 \ + +FM_OBJS = \ + $O\ExtractCallback.obj \ + $O\FormatUtils.obj \ + $O\OverwriteDialog.obj \ + $O\PasswordDialog.obj \ + $O\ProgressDialog2.obj \ + +!IFDEF UNDER_CE +FM_OBJS = $(FM_OBJS) \ + $O\BrowseDialog.obj \ + $O\SysIconUtils.obj \ +!ENDIF + +AR_COMMON_OBJS = \ + $O\CoderMixer2.obj \ + $O\CoderMixer2MT.obj \ + $O\CrossThreadProgress.obj \ + $O\ItemNameUtils.obj \ + $O\OutStreamWithCRC.obj \ + +7Z_OBJS = \ + $O\7zDecode.obj \ + $O\7zExtract.obj \ + $O\7zFolderOutStream.obj \ + $O\7zHandler.obj \ + $O\7zHeader.obj \ + $O\7zIn.obj \ + $O\7zRegister.obj \ + +COMPRESS_OBJS = \ + $O\BranchCoder.obj \ + $O\Bcj2Coder.obj \ + $O\Bcj2Register.obj \ + $O\BcjCoder.obj \ + $O\BcjRegister.obj \ + $O\CopyCoder.obj \ + $O\CopyRegister.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\Bra86.obj \ + $O\CpuArch.obj \ + $O\Lzma2Dec.obj \ + $O\LzmaDec.obj \ + $O\Ppmd7.obj \ + $O\Ppmd7Dec.obj \ + $O\Sha256.obj \ + $O\Threads.obj \ + +!include "../../Aes.mak" +!include "../../Crc.mak" + +OBJS = \ + $O\StdAfx.obj \ + $(SFX_WIN_OBJS) \ + $(GUI_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(WIN_CTRL_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(UI_COMMON_OBJS) \ + $(FM_OBJS)\ + $(AR_COMMON_OBJS) \ + $(7Z_OBJS) \ + $(COMPRESS_OBJS) \ + $(CRYPTO_OBJS) \ + $O\MyMessages.obj \ + $(C_OBJS) \ + $(ASM_OBJS) \ + $O\resource.res + + +!include "../../../Build.mak" + +$(SFX_WIN_OBJS): $(*B).cpp + $(COMPL) + +$(GUI_OBJS): ../../UI/GUI/$(*B).cpp + $(COMPL) +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +$(WIN_CTRL_OBJS): ../../../Windows/Control/$(*B).cpp + $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) +$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp + $(COMPL) +$(FM_OBJS): ../../UI/FileManager/$(*B).cpp + $(COMPL) +$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp + $(COMPL) + +$(7Z_OBJS): ../../Archive/7z/$(*B).cpp + $(COMPL) +$(COMPRESS_OBJS): ../../Compress/$(*B).cpp + $(COMPL) +$(CRYPTO_OBJS): ../../Crypto/$(*B).cpp + $(COMPL) + +$O\MyMessages.obj: ../../UI/Explorer/MyMessages.cpp + $(COMPL) +$(C_OBJS): ../../../../C/$(*B).c + $(COMPL_O2) + +!include "../../Asm.mak" diff --git a/CPP/7zip/Bundles/SFXWin/resource.h b/CPP/7zip/Bundles/SFXWin/resource.h new file mode 100755 index 0000000..1c36de1 --- /dev/null +++ b/CPP/7zip/Bundles/SFXWin/resource.h @@ -0,0 +1 @@ +#define IDI_ICON 1 diff --git a/CPP/7zip/Bundles/SFXWin/resource.rc b/CPP/7zip/Bundles/SFXWin/resource.rc new file mode 100755 index 0000000..fb8e783 --- /dev/null +++ b/CPP/7zip/Bundles/SFXWin/resource.rc @@ -0,0 +1,43 @@ +#include "../../MyVersionInfo.rc" +#include "../../GuiCommon.rc" +#include "../../UI/GUI/ExtractDialogRes.h" +#include "resource.h" + +MY_VERSION_INFO_APP("7z SFX", "7z.sfx") + +#define xc 240 +#define yc 64 + +IDI_ICON ICON "7z.ico" + +IDD_DIALOG_EXTRACT MY_DIALOG +CAPTION "7-Zip self-extracting archive" +BEGIN + LTEXT "E&xtract to:", IDC_STATIC_EXTRACT_EXTRACT_TO, m, m, xc, 8 + EDITTEXT IDC_EXTRACT_COMBO_PATH, m, 21, xc - bxsDots - 12, 14, ES_AUTOHSCROLL + PUSHBUTTON "...", IDC_EXTRACT_BUTTON_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_DIALOG_EXTRACT_2 MY_DIALOG +CAPTION "7-Zip self-extracting archive" +BEGIN + LTEXT "E&xtract to:", IDC_STATIC_EXTRACT_EXTRACT_TO, m, m, xc - bxsDots - 12, 8 + EDITTEXT IDC_EXTRACT_COMBO_PATH, m, m + bys + 4, xc, 14, ES_AUTOHSCROLL + PUSHBUTTON "...", IDC_EXTRACT_BUTTON_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" diff --git a/CPP/7zip/Bundles/makefile b/CPP/7zip/Bundles/makefile new file mode 100755 index 0000000..e869ee4 --- /dev/null +++ b/CPP/7zip/Bundles/makefile @@ -0,0 +1,18 @@ +DIRS = \ + Alone\~ \ + Alone7z\~ \ + Fm\~ \ + Format7z\~ \ + Format7zF\~ \ + Format7zR\~ \ + Format7zExtract\~ \ + Format7zExtractR\~ \ + LzmaCon\~ \ + SFXCon\~ \ + SFXSetup\~ \ + SFXWin\~ \ + +all: $(DIRS) + +$(DIRS): +!include "../SubBuild.mak" diff --git a/CPP/7zip/Common/CWrappers.cpp b/CPP/7zip/Common/CWrappers.cpp new file mode 100755 index 0000000..66b8449 --- /dev/null +++ b/CPP/7zip/Common/CWrappers.cpp @@ -0,0 +1,226 @@ +// CWrappers.h + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "CWrappers.h" + +#include "StreamUtils.h" + +#define PROGRESS_UNKNOWN_VALUE ((UInt64)(Int64)-1) + +#define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x) + +static SRes CompressProgress(void *pp, UInt64 inSize, UInt64 outSize) +{ + CCompressProgressWrap *p = (CCompressProgressWrap *)pp; + p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outSize)); + return (SRes)p->Res; +} + +CCompressProgressWrap::CCompressProgressWrap(ICompressProgressInfo *progress) +{ + p.Progress = CompressProgress; + Progress = progress; + Res = SZ_OK; +} + +static const UInt32 kStreamStepSize = (UInt32)1 << 31; + +SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) +{ + 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; + } + return defaultRes; +} + +static SRes MyRead(void *object, void *data, size_t *size) +{ + CSeqInStreamWrap *p = (CSeqInStreamWrap *)object; + UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize); + p->Res = (p->Stream->Read(data, curSize, &curSize)); + *size = curSize; + if (p->Res == S_OK) + return SZ_OK; + return HRESULT_To_SRes(p->Res, SZ_ERROR_READ); +} + +static size_t MyWrite(void *object, const void *data, size_t size) +{ + CSeqOutStreamWrap *p = (CSeqOutStreamWrap *)object; + 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; +} + +CSeqInStreamWrap::CSeqInStreamWrap(ISequentialInStream *stream) +{ + p.Read = MyRead; + Stream = stream; +} + +CSeqOutStreamWrap::CSeqOutStreamWrap(ISequentialOutStream *stream) +{ + p.Write = MyWrite; + Stream = stream; + Res = SZ_OK; + Processed = 0; +} + +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_PROGRESS: return E_ABORT; + case SZ_ERROR_DATA: return S_FALSE; + } + return E_FAIL; +} + +static SRes InStreamWrap_Read(void *pp, void *data, size_t *size) +{ + CSeekInStreamWrap *p = (CSeekInStreamWrap *)pp; + 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(void *pp, Int64 *offset, ESzSeek origin) +{ + CSeekInStreamWrap *p = (CSeekInStreamWrap *)pp; + 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; +} + +CSeekInStreamWrap::CSeekInStreamWrap(IInStream *stream) +{ + Stream = stream; + p.Read = InStreamWrap_Read; + p.Seek = InStreamWrap_Seek; + Res = S_OK; +} + + +/* ---------- CByteInBufWrap ---------- */ + +void CByteInBufWrap::Free() +{ + ::MidFree(Buf); + Buf = 0; +} + +bool CByteInBufWrap::Alloc(UInt32 size) +{ + if (Buf == 0 || size != Size) + { + Free(); + Lim = Cur = Buf = (Byte *)::MidAlloc((size_t)size); + Size = size; + } + return (Buf != 0); +} + +Byte CByteInBufWrap::ReadByteFromNewBlock() +{ + 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(void *pp) +{ + CByteInBufWrap *p = (CByteInBufWrap *)pp; + if (p->Cur != p->Lim) + return *p->Cur++; + return p->ReadByteFromNewBlock(); +} + +CByteInBufWrap::CByteInBufWrap(): Buf(0) +{ + p.Read = Wrap_ReadByte; +} + + +/* ---------- CByteOutBufWrap ---------- */ + +void CByteOutBufWrap::Free() +{ + ::MidFree(Buf); + Buf = 0; +} + +bool CByteOutBufWrap::Alloc(size_t size) +{ + if (Buf == 0 || size != Size) + { + Free(); + Buf = (Byte *)::MidAlloc(size); + Size = size; + } + return (Buf != 0); +} + +HRESULT CByteOutBufWrap::Flush() +{ + 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(void *pp, Byte b) +{ + CByteOutBufWrap *p = (CByteOutBufWrap *)pp; + Byte *dest = p->Cur; + *dest = b; + p->Cur = ++dest; + if (dest == p->Lim) + p->Flush(); +} + +CByteOutBufWrap::CByteOutBufWrap(): Buf(0) +{ + p.Write = Wrap_WriteByte; +} diff --git a/CPP/7zip/Common/CWrappers.h b/CPP/7zip/Common/CWrappers.h new file mode 100755 index 0000000..dd4197c --- /dev/null +++ b/CPP/7zip/Common/CWrappers.h @@ -0,0 +1,109 @@ +// CWrappers.h + +#ifndef __C_WRAPPERS_H +#define __C_WRAPPERS_H + +#include "../ICoder.h" +#include "../../Common/MyCom.h" + +struct CCompressProgressWrap +{ + ICompressProgress p; + ICompressProgressInfo *Progress; + HRESULT Res; + CCompressProgressWrap(ICompressProgressInfo *progress); +}; + +struct CSeqInStreamWrap +{ + ISeqInStream p; + ISequentialInStream *Stream; + HRESULT Res; + CSeqInStreamWrap(ISequentialInStream *stream); +}; + +struct CSeekInStreamWrap +{ + ISeekInStream p; + IInStream *Stream; + HRESULT Res; + CSeekInStreamWrap(IInStream *stream); +}; + +struct CSeqOutStreamWrap +{ + ISeqOutStream p; + ISequentialOutStream *Stream; + HRESULT Res; + UInt64 Processed; + CSeqOutStreamWrap(ISequentialOutStream *stream); +}; + +HRESULT SResToHRESULT(SRes res); + +struct CByteInBufWrap +{ + IByteIn p; + const Byte *Cur; + const Byte *Lim; + Byte *Buf; + UInt32 Size; + ISequentialInStream *Stream; + UInt64 Processed; + bool Extra; + HRESULT Res; + + CByteInBufWrap(); + ~CByteInBufWrap() { Free(); } + void Free(); + bool Alloc(UInt32 size); + void Init() + { + Lim = Cur = Buf; + Processed = 0; + Extra = false; + Res = S_OK; + } + UInt64 GetProcessed() const { return Processed + (Cur - Buf); } + Byte ReadByteFromNewBlock(); + Byte ReadByte() + { + if (Cur != Lim) + return *Cur++; + return ReadByteFromNewBlock(); + } +}; + +struct CByteOutBufWrap +{ + IByteOut p; + Byte *Cur; + const Byte *Lim; + Byte *Buf; + size_t Size; + ISequentialOutStream *Stream; + UInt64 Processed; + HRESULT Res; + + CByteOutBufWrap(); + ~CByteOutBufWrap() { Free(); } + void Free(); + bool Alloc(size_t size); + void Init() + { + Cur = Buf; + Lim = Buf + Size; + Processed = 0; + Res = S_OK; + } + UInt64 GetProcessed() const { return Processed + (Cur - Buf); } + HRESULT Flush(); + void WriteByte(Byte b) + { + *Cur++ = b; + if (Cur == Lim) + Flush(); + } +}; + +#endif diff --git a/CPP/7zip/Common/CreateCoder.cpp b/CPP/7zip/Common/CreateCoder.cpp new file mode 100755 index 0000000..55bad3c --- /dev/null +++ b/CPP/7zip/Common/CreateCoder.cpp @@ -0,0 +1,293 @@ +// 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 int kNumCodecsMax = 64; +unsigned int g_NumCodecs = 0; +const CCodecInfo *g_Codecs[kNumCodecsMax]; +void RegisterCodec(const CCodecInfo *codecInfo) +{ + if (g_NumCodecs < kNumCodecsMax) + g_Codecs[g_NumCodecs++] = codecInfo; +} + +#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 LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector &externalCodecs) +{ + UInt32 num; + RINOK(codecsInfo->GetNumberOfMethods(&num)); + for (UInt32 i = 0; i < num; i++) + { + CCodecInfoEx info; + NWindows::NCOM::CPropVariant prop; + RINOK(codecsInfo->GetProperty(i, NMethodPropID::kID, &prop)); + // if (prop.vt != VT_BSTR) + // info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal); + // memmove(info.Id.ID, prop.bstrVal, info.Id.IDSize); + if (prop.vt != VT_UI8) + { + continue; // old Interface + // return E_INVALIDARG; + } + info.Id = prop.uhVal.QuadPart; + prop.Clear(); + + RINOK(codecsInfo->GetProperty(i, NMethodPropID::kName, &prop)); + if (prop.vt == VT_BSTR) + info.Name = prop.bstrVal; + else if (prop.vt != VT_EMPTY) + return E_INVALIDARG;; + + RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kInStreams, info.NumInStreams)); + RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kOutStreams, info.NumOutStreams)); + RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned)); + RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned)); + + externalCodecs.Add(info); + } + return S_OK; +} + +#endif + +bool FindMethod( + #ifdef EXTERNAL_CODECS + ICompressCodecsInfo * /* codecsInfo */, const CObjectVector *externalCodecs, + #endif + const UString &name, + CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams) +{ + UInt32 i; + for (i = 0; i < g_NumCodecs; i++) + { + const CCodecInfo &codec = *g_Codecs[i]; + if (name.CompareNoCase(codec.Name) == 0) + { + methodId = codec.Id; + numInStreams = codec.NumInStreams; + numOutStreams = 1; + return true; + } + } + #ifdef EXTERNAL_CODECS + if (externalCodecs) + for (i = 0; i < (UInt32)externalCodecs->Size(); i++) + { + const CCodecInfoEx &codec = (*externalCodecs)[i]; + if (codec.Name.CompareNoCase(name) == 0) + { + methodId = codec.Id; + numInStreams = codec.NumInStreams; + numOutStreams = codec.NumOutStreams; + return true; + } + } + #endif + return false; +} + +bool FindMethod( + #ifdef EXTERNAL_CODECS + ICompressCodecsInfo * /* codecsInfo */, const CObjectVector *externalCodecs, + #endif + CMethodId methodId, UString &name) +{ + UInt32 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 + if (externalCodecs) + for (i = 0; i < (UInt32)externalCodecs->Size(); i++) + { + const CCodecInfoEx &codec = (*externalCodecs)[i]; + if (methodId == codec.Id) + { + name = codec.Name; + return true; + } + } + #endif + return false; +} + +HRESULT CreateCoder( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + CMyComPtr &filter, + CMyComPtr &coder, + CMyComPtr &coder2, + bool encode, bool onlyCoder) +{ + bool created = false; + UInt32 i; + for (i = 0; i < g_NumCodecs; i++) + { + 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.NumInStreams == 1) coder = (ICompressCoder *)p; + else coder2 = (ICompressCoder2 *)p; + created = (p != 0); + break; + } + } + else + if (codec.CreateDecoder) + { + void *p = codec.CreateDecoder(); + if (codec.IsFilter) filter = (ICompressFilter *)p; + else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; + else coder2 = (ICompressCoder2 *)p; + created = (p != 0); + break; + } + } + } + + #ifdef EXTERNAL_CODECS + if (!created && externalCodecs) + for (i = 0; i < (UInt32)externalCodecs->Size(); i++) + { + const CCodecInfoEx &codec = (*externalCodecs)[i]; + if (codec.Id == methodId) + { + if (encode) + { + if (codec.EncoderIsAssigned) + { + if (codec.IsSimpleCodec()) + { + HRESULT result = codecsInfo->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder); + if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) + return result; + if (!coder) + { + RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter)); + } + } + else + { + RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2)); + } + break; + } + } + else + if (codec.DecoderIsAssigned) + { + if (codec.IsSimpleCodec()) + { + HRESULT result = codecsInfo->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder); + if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) + return result; + if (!coder) + { + RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter)); + } + } + else + { + RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2)); + } + break; + } + } + } + #endif + + if (onlyCoder && filter) + { + CFilterCoder *coderSpec = new CFilterCoder; + coder = coderSpec; + coderSpec->Filter = filter; + } + return S_OK; +} + +HRESULT CreateCoder( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + CMyComPtr &coder, + CMyComPtr &coder2, + bool encode) +{ + CMyComPtr filter; + return CreateCoder( + EXTERNAL_CODECS_LOC_VARS + methodId, + filter, coder, coder2, encode, true); +} + +HRESULT CreateCoder( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + CMyComPtr &coder, bool encode) +{ + CMyComPtr filter; + CMyComPtr coder2; + return CreateCoder( + EXTERNAL_CODECS_LOC_VARS + methodId, + coder, coder2, encode); +} + +HRESULT CreateFilter( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + CMyComPtr &filter, + bool encode) +{ + CMyComPtr coder; + CMyComPtr coder2; + return CreateCoder( + EXTERNAL_CODECS_LOC_VARS + methodId, + filter, coder, coder2, encode, false); +} diff --git a/CPP/7zip/Common/CreateCoder.h b/CPP/7zip/Common/CreateCoder.h new file mode 100755 index 0000000..9a59d45 --- /dev/null +++ b/CPP/7zip/Common/CreateCoder.h @@ -0,0 +1,98 @@ +// CreateCoder.h + +#ifndef __CREATE_CODER_H +#define __CREATE_CODER_H + +#include "../../Common/MyCom.h" +#include "../../Common/MyString.h" +#include "../ICoder.h" + +#include "MethodId.h" + +#ifdef EXTERNAL_CODECS + +struct CCodecInfoEx +{ + UString Name; + CMethodId Id; + UInt32 NumInStreams; + UInt32 NumOutStreams; + bool EncoderIsAssigned; + bool DecoderIsAssigned; + bool IsSimpleCodec() const { return NumOutStreams == 1 && NumInStreams == 1; } + CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {} +}; + +HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector &externalCodecs); + +#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 _codecsInfo = compressCodecsInfo; return LoadExternalCodecs(_codecsInfo, _externalCodecs); COM_TRY_END } +#define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler) + +#define EXTERNAL_CODECS_VARS2 _codecsInfo, &_externalCodecs + +#define DECL_EXTERNAL_CODECS_VARS CMyComPtr _codecsInfo; CObjectVector _externalCodecs; +#define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2, + +#define DECL_EXTERNAL_CODECS_LOC_VARS2 ICompressCodecsInfo *codecsInfo, const CObjectVector *externalCodecs +#define EXTERNAL_CODECS_LOC_VARS2 codecsInfo, 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 EXTERNAL_CODECS_VARS2 +#define DECL_EXTERNAL_CODECS_LOC_VARS2 +#define EXTERNAL_CODECS_LOC_VARS2 +#define DECL_EXTERNAL_CODECS_LOC_VARS +#define EXTERNAL_CODECS_LOC_VARS + +#endif + +bool FindMethod( + DECL_EXTERNAL_CODECS_LOC_VARS + const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams); + +bool FindMethod( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, UString &name); + + +HRESULT CreateCoder( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + CMyComPtr &filter, + CMyComPtr &coder, + CMyComPtr &coder2, + bool encode, bool onlyCoder); + +HRESULT CreateCoder( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + CMyComPtr &coder, + CMyComPtr &coder2, + bool encode); + +HRESULT CreateCoder( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + CMyComPtr &coder, bool encode); + +HRESULT CreateFilter( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + CMyComPtr &filter, + bool encode); + +#endif diff --git a/CPP/7zip/Common/FilePathAutoRename.cpp b/CPP/7zip/Common/FilePathAutoRename.cpp new file mode 100755 index 0000000..d357c5b --- /dev/null +++ b/CPP/7zip/Common/FilePathAutoRename.cpp @@ -0,0 +1,55 @@ +// FilePathAutoRename.cpp + +#include "StdAfx.h" + +#include "Common/Defs.h" +#include "Common/IntToString.h" + +#include "Windows/FileFind.h" + +#include "FilePathAutoRename.h" + +using namespace NWindows; + +static bool MakeAutoName(const UString &name, + const UString &extension, unsigned value, UString &path) +{ + wchar_t number[16]; + ConvertUInt32ToString(value, number); + path = name; + path += number; + path += extension; + return NFile::NFind::DoesFileOrDirExist(path); +} + +bool AutoRenamePath(UString &fullProcessedPath) +{ + UString path; + int dotPos = fullProcessedPath.ReverseFind(L'.'); + + int slashPos = fullProcessedPath.ReverseFind(L'/'); + #ifdef _WIN32 + int slash1Pos = fullProcessedPath.ReverseFind(L'\\'); + slashPos = MyMax(slashPos, slash1Pos); + #endif + + UString name, extension; + if (dotPos > slashPos && dotPos > 0) + { + name = fullProcessedPath.Left(dotPos); + extension = fullProcessedPath.Mid(dotPos); + } + else + name = fullProcessedPath; + name += L'_'; + unsigned left = 1, right = (1 << 30); + while (left != right) + { + unsigned mid = (left + right) / 2; + if (MakeAutoName(name, extension, mid, path)) + left = mid + 1; + else + right = mid; + } + return !MakeAutoName(name, extension, right, fullProcessedPath); +} diff --git a/CPP/7zip/Common/FilePathAutoRename.h b/CPP/7zip/Common/FilePathAutoRename.h new file mode 100755 index 0000000..4303962 --- /dev/null +++ b/CPP/7zip/Common/FilePathAutoRename.h @@ -0,0 +1,10 @@ +// Util/FilePathAutoRename.h + +#ifndef __FILEPATHAUTORENAME_H +#define __FILEPATHAUTORENAME_H + +#include "Common/MyString.h" + +bool AutoRenamePath(UString &fullProcessedPath); + +#endif diff --git a/CPP/7zip/Common/FileStreams.cpp b/CPP/7zip/Common/FileStreams.cpp new file mode 100755 index 0000000..de49911 --- /dev/null +++ b/CPP/7zip/Common/FileStreams.cpp @@ -0,0 +1,422 @@ +// 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 +} + +bool CInFileStream::Open(LPCTSTR fileName) +{ + return File.Open(fileName); +} + +#ifdef USE_WIN_FILE +#ifndef _UNICODE +bool CInFileStream::Open(LPCWSTR fileName) +{ + return File.Open(fileName); +} +#endif +#endif + +bool CInFileStream::OpenShared(LPCTSTR fileName, bool shareForWrite) +{ + return File.OpenShared(fileName, shareForWrite); +} + +#ifdef USE_WIN_FILE +#ifndef _UNICODE +bool CInFileStream::OpenShared(LPCWSTR fileName, bool shareForWrite) +{ + return File.OpenShared(fileName, shareForWrite); +} +#endif +#endif + +#ifdef SUPPORT_DEVICE_FILE + +static const UInt32 kClusterSize = 1 << 18; +CInFileStream::CInFileStream(): + VirtPos(0), + PhyPos(0), + Buffer(0), + BufferSize(0) +{ +} + +#endif + +CInFileStream::~CInFileStream() +{ + #ifdef SUPPORT_DEVICE_FILE + MidFree(Buffer); + #endif +} + +STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + #ifdef USE_WIN_FILE + + #ifdef SUPPORT_DEVICE_FILE + if (processedSize != NULL) + *processedSize = 0; + if (size == 0) + return S_OK; + if (File.IsDeviceFile) + { + if (File.LengthDefined) + { + if (VirtPos >= File.Length) + return VirtPos == File.Length ? S_OK : E_FAIL; + UInt64 rem = File.Length - VirtPos; + if (size > rem) + size = (UInt32)rem; + } + for (;;) + { + const UInt32 mask = kClusterSize - 1; + UInt64 mask2 = ~(UInt64)mask; + UInt64 alignedPos = VirtPos & mask2; + if (BufferSize > 0 && BufferStartPos == alignedPos) + { + UInt32 pos = (UInt32)VirtPos & mask; + if (pos >= BufferSize) + return S_OK; + UInt32 rem = MyMin(BufferSize - pos, size); + memcpy(data, Buffer + pos, rem); + VirtPos += rem; + if (processedSize != NULL) + *processedSize += rem; + return S_OK; + } + + bool useBuffer = false; + if ((VirtPos & mask) != 0 || ((ptrdiff_t)data & mask) != 0 ) + useBuffer = true; + else + { + UInt64 end = VirtPos + size; + if ((end & mask) != 0) + { + end &= mask2; + if (end <= VirtPos) + useBuffer = true; + else + size = (UInt32)(end - VirtPos); + } + } + if (!useBuffer) + break; + if (alignedPos != PhyPos) + { + UInt64 realNewPosition; + bool result = File.Seek(alignedPos, FILE_BEGIN, realNewPosition); + if (!result) + return ConvertBoolToHRESULT(result); + PhyPos = realNewPosition; + } + + BufferStartPos = alignedPos; + UInt32 readSize = kClusterSize; + if (File.LengthDefined) + readSize = (UInt32)MyMin(File.Length - PhyPos, (UInt64)kClusterSize); + + if (Buffer == 0) + { + Buffer = (Byte *)MidAlloc(kClusterSize); + if (Buffer == 0) + return E_OUTOFMEMORY; + } + bool result = File.Read1(Buffer, readSize, BufferSize); + if (!result) + return ConvertBoolToHRESULT(result); + + if (BufferSize == 0) + return S_OK; + PhyPos += BufferSize; + } + + 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 != NULL) + *processedSize = realProcessedSize; + #ifdef SUPPORT_DEVICE_FILE + VirtPos += realProcessedSize; + PhyPos += realProcessedSize; + #endif + return ConvertBoolToHRESULT(result); + + #else + + if (processedSize != NULL) + *processedSize = 0; + ssize_t res = File.Read(data, (size_t)size); + if (res == -1) + return E_FAIL; + if (processedSize != NULL) + *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, stdout); + if (processedSize != 0) + *processedSize = s2; + return (s2 = size) ? S_OK : 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 != NULL) + *processedSize = realProcessedSize; + if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE) + return S_OK; + return ConvertBoolToHRESULT(res != FALSE); + + #else + + if (processedSize != NULL) + *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 != NULL) + *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) + { + UInt64 newVirtPos = offset; + switch(seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: newVirtPos += VirtPos; break; + case STREAM_SEEK_END: newVirtPos += File.Length; break; + default: return STG_E_INVALIDFUNCTION; + } + VirtPos = newVirtPos; + if (newPosition) + *newPosition = newVirtPos; + return S_OK; + } + #endif + + UInt64 realNewPosition; + bool result = File.Seek(offset, seekOrigin, realNewPosition); + + #ifdef SUPPORT_DEVICE_FILE + PhyPos = VirtPos = realNewPosition; + #endif + + if (newPosition != NULL) + *newPosition = realNewPosition; + return ConvertBoolToHRESULT(result); + + #else + + off_t res = File.Seek(offset, seekOrigin); + if (res == -1) + return E_FAIL; + if (newPosition != NULL) + *newPosition = (UInt64)res; + return S_OK; + + #endif +} + +STDMETHODIMP CInFileStream::GetSize(UInt64 *size) +{ + return ConvertBoolToHRESULT(File.GetLength(*size)); +} + + +////////////////////////// +// 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.WritePart(data, size, realProcessedSize); + ProcessedSize += realProcessedSize; + if (processedSize != NULL) + *processedSize = realProcessedSize; + return ConvertBoolToHRESULT(result); + + #else + + if (processedSize != NULL) + *processedSize = 0; + ssize_t res = File.Write(data, (size_t)size); + if (res == -1) + return E_FAIL; + if (processedSize != NULL) + *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 != NULL) + *newPosition = realNewPosition; + return ConvertBoolToHRESULT(result); + + #else + + off_t res = File.Seek(offset, seekOrigin); + if (res == -1) + return E_FAIL; + if (newPosition != NULL) + *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 +} + +#ifdef UNDER_CE +STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + size_t s2 = fwrite(data, 1, size, stdout); + if (processedSize != 0) + *processedSize = s2; + return (s2 = size) ? S_OK : E_FAIL; +} +#else +STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != NULL) + *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; + data = (const void *)((const Byte *)data + realProcessedSize); + if (processedSize != NULL) + *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; + if (processedSize != NULL) + *processedSize = (UInt32)res; + return S_OK; + + return S_OK; + #endif +} + +#endif diff --git a/CPP/7zip/Common/FileStreams.h b/CPP/7zip/Common/FileStreams.h new file mode 100755 index 0000000..f979294 --- /dev/null +++ b/CPP/7zip/Common/FileStreams.h @@ -0,0 +1,144 @@ +// FileStreams.h + +#ifndef __FILESTREAMS_H +#define __FILESTREAMS_H + +#ifdef _WIN32 +#define USE_WIN_FILE +#endif + +#ifdef USE_WIN_FILE +#include "../../Windows/FileIO.h" +#else +#include "../../Common/C_FileIO.h" +#endif + +#include "../../Common/MyCom.h" + +#include "../IStream.h" + +class CInFileStream: + public IInStream, + public IStreamGetSize, + public CMyUnknownImp +{ +public: + #ifdef USE_WIN_FILE + NWindows::NFile::NIO::CInFile File; + #ifdef SUPPORT_DEVICE_FILE + UInt64 VirtPos; + UInt64 PhyPos; + UInt64 BufferStartPos; + Byte *Buffer; + UInt32 BufferSize; + #endif + #else + NC::NFile::NIO::CInFile File; + #endif + virtual ~CInFileStream(); + + #ifdef SUPPORT_DEVICE_FILE + CInFileStream(); + #endif + + bool Open(LPCTSTR fileName); + #ifdef USE_WIN_FILE + #ifndef _UNICODE + bool Open(LPCWSTR fileName); + #endif + #endif + + bool OpenShared(LPCTSTR fileName, bool shareForWrite); + #ifdef USE_WIN_FILE + #ifndef _UNICODE + bool OpenShared(LPCWSTR fileName, bool shareForWrite); + #endif + #endif + + MY_UNKNOWN_IMP2(IInStream, IStreamGetSize) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + + STDMETHOD(GetSize)(UInt64 *size); +}; + +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 +{ + #ifdef USE_WIN_FILE + NWindows::NFile::NIO::COutFile File; + #else + NC::NFile::NIO::COutFile File; + #endif +public: + virtual ~COutFileStream() {} + bool Create(LPCTSTR fileName, bool createAlways) + { + ProcessedSize = 0; + return File.Create(fileName, createAlways); + } + bool Open(LPCTSTR fileName, DWORD creationDisposition) + { + ProcessedSize = 0; + return File.Open(fileName, creationDisposition); + } + #ifdef USE_WIN_FILE + #ifndef _UNICODE + bool Create(LPCWSTR fileName, bool createAlways) + { + ProcessedSize = 0; + return File.Create(fileName, createAlways); + } + bool Open(LPCWSTR fileName, DWORD creationDisposition) + { + ProcessedSize = 0; + return File.Open(fileName, creationDisposition); + } + #endif + #endif + + 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); +}; + +class CStdOutFileStream: + public ISequentialOutStream, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP + + virtual ~CStdOutFileStream() {} + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + +#endif diff --git a/CPP/7zip/Common/FilterCoder.cpp b/CPP/7zip/Common/FilterCoder.cpp new file mode 100755 index 0000000..03a2aa0 --- /dev/null +++ b/CPP/7zip/Common/FilterCoder.cpp @@ -0,0 +1,247 @@ +// FilterCoder.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "../../Common/Defs.h" + +#include "FilterCoder.h" +#include "StreamUtils.h" + +static const UInt32 kBufferSize = 1 << 17; + +CFilterCoder::CFilterCoder() +{ + _buffer = (Byte *)::MidAlloc(kBufferSize); + if (_buffer == 0) + throw 1; +} + +CFilterCoder::~CFilterCoder() +{ + ::MidFree(_buffer); +} + +HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size) +{ + if (_outSizeIsDefined) + { + UInt64 remSize = _outSize - _nowPos64; + if (size > remSize) + size = (UInt32)remSize; + } + RINOK(WriteStream(outStream, _buffer, size)); + _nowPos64 += size; + return S_OK; +} + +STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + RINOK(Init()); + UInt32 bufferPos = 0; + _outSizeIsDefined = (outSize != 0); + if (_outSizeIsDefined) + _outSize = *outSize; + + while (!_outSizeIsDefined || _nowPos64 < _outSize) + { + size_t processedSize = kBufferSize - bufferPos; + + // Change it: It can be optimized using ReadPart + RINOK(ReadStream(inStream, _buffer + bufferPos, &processedSize)); + + UInt32 endPos = bufferPos + (UInt32)processedSize; + + bufferPos = Filter->Filter(_buffer, endPos); + if (bufferPos > endPos) + { + for (; endPos < bufferPos; endPos++) + _buffer[endPos] = 0; + bufferPos = Filter->Filter(_buffer, endPos); + } + + if (bufferPos == 0) + { + if (endPos == 0) + return S_OK; + return WriteWithLimit(outStream, endPos); + } + RINOK(WriteWithLimit(outStream, bufferPos)); + if (progress != NULL) + { + RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64)); + } + UInt32 i = 0; + while (bufferPos < endPos) + _buffer[i++] = _buffer[bufferPos++]; + bufferPos = i; + } + return S_OK; +} + +STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream) +{ + _bufferPos = 0; + _outStream = outStream; + return Init(); +} + +STDMETHODIMP CFilterCoder::ReleaseOutStream() +{ + _outStream.Release(); + return S_OK; +} + + +STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != NULL) + *processedSize = 0; + while (size > 0) + { + UInt32 sizeTemp = MyMin(size, kBufferSize - _bufferPos); + memcpy(_buffer + _bufferPos, data, sizeTemp); + size -= sizeTemp; + if (processedSize != NULL) + *processedSize += sizeTemp; + data = (const Byte *)data + sizeTemp; + UInt32 endPos = _bufferPos + sizeTemp; + _bufferPos = Filter->Filter(_buffer, endPos); + if (_bufferPos == 0) + { + _bufferPos = endPos; + break; + } + if (_bufferPos > endPos) + { + if (size != 0) + return E_FAIL; + break; + } + RINOK(WriteWithLimit(_outStream, _bufferPos)); + UInt32 i = 0; + while (_bufferPos < endPos) + _buffer[i++] = _buffer[_bufferPos++]; + _bufferPos = i; + } + return S_OK; +} + +STDMETHODIMP CFilterCoder::Flush() +{ + if (_bufferPos != 0) + { + // _buffer contains only data refused by previous Filter->Filter call. + UInt32 endPos = Filter->Filter(_buffer, _bufferPos); + if (endPos > _bufferPos) + { + for (; _bufferPos < endPos; _bufferPos++) + _buffer[_bufferPos] = 0; + if (Filter->Filter(_buffer, endPos) != endPos) + return E_FAIL; + } + RINOK(WriteWithLimit(_outStream, _bufferPos)); + _bufferPos = 0; + } + CMyComPtr flush; + _outStream.QueryInterface(IID_IOutStreamFlush, &flush); + if (flush) + return flush->Flush(); + return S_OK; +} + + +STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream) +{ + _convertedPosBegin = _convertedPosEnd = _bufferPos = 0; + _inStream = inStream; + return Init(); +} + +STDMETHODIMP CFilterCoder::ReleaseInStream() +{ + _inStream.Release(); + return S_OK; +} + +STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != NULL) + *processedSize = 0; + while (size > 0) + { + if (_convertedPosBegin != _convertedPosEnd) + { + UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin); + memcpy(data, _buffer + _convertedPosBegin, sizeTemp); + _convertedPosBegin += sizeTemp; + data = (void *)((Byte *)data + sizeTemp); + size -= sizeTemp; + if (processedSize != NULL) + *processedSize += sizeTemp; + break; + } + UInt32 i; + for (i = 0; _convertedPosEnd + i < _bufferPos; i++) + _buffer[i] = _buffer[_convertedPosEnd + i]; + _bufferPos = i; + _convertedPosBegin = _convertedPosEnd = 0; + size_t processedSizeTemp = kBufferSize - _bufferPos; + RINOK(ReadStream(_inStream, _buffer + _bufferPos, &processedSizeTemp)); + _bufferPos += (UInt32)processedSizeTemp; + _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); + if (_convertedPosEnd == 0) + { + if (_bufferPos == 0) + break; + _convertedPosEnd = _bufferPos; // check it + continue; + } + if (_convertedPosEnd > _bufferPos) + { + for (; _bufferPos < _convertedPosEnd; _bufferPos++) + _buffer[_bufferPos] = 0; + _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); + } + } + return S_OK; +} + +#ifndef _NO_CRYPTO +STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size) +{ + return _setPassword->CryptoSetPassword(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 _setDecoderProperties->SetDecoderProperties2(data, size); +} diff --git a/CPP/7zip/Common/FilterCoder.h b/CPP/7zip/Common/FilterCoder.h new file mode 100755 index 0000000..1b0125d --- /dev/null +++ b/CPP/7zip/Common/FilterCoder.h @@ -0,0 +1,128 @@ +// FilterCoder.h + +#ifndef __FILTER_CODER_H +#define __FILTER_CODER_H + +#include "../../Common/MyCom.h" +#include "../ICoder.h" +#include "../IPassword.h" + +#define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) if (iid == IID_ ## i) \ +{ if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \ +*outObject = (void *)(i *)this; AddRef(); return S_OK; } + +class CFilterCoder: + public ICompressCoder, + public ICompressSetInStream, + public ISequentialInStream, + public ICompressSetOutStream, + public ISequentialOutStream, + public IOutStreamFlush, + + #ifndef _NO_CRYPTO + public ICryptoSetPassword, + #endif + #ifndef EXTRACT_ONLY + public ICompressSetCoderProperties, + public ICompressWriteCoderProperties, + // public ICryptoResetSalt, + public ICryptoResetInitVector, + #endif + public ICompressSetDecoderProperties2, + public CMyUnknownImp +{ +protected: + Byte *_buffer; + CMyComPtr _inStream; + CMyComPtr _outStream; + UInt32 _bufferPos; + UInt32 _convertedPosBegin; + UInt32 _convertedPosEnd; + bool _outSizeIsDefined; + UInt64 _outSize; + UInt64 _nowPos64; + + HRESULT Init() + { + _nowPos64 = 0; + _outSizeIsDefined = false; + return Filter->Init(); + } + + CMyComPtr _setPassword; + #ifndef EXTRACT_ONLY + CMyComPtr _SetCoderProperties; + CMyComPtr _writeCoderProperties; + // CMyComPtr _CryptoResetSalt; + CMyComPtr _CryptoResetInitVector; + #endif + CMyComPtr _setDecoderProperties; +public: + CMyComPtr Filter; + + CFilterCoder(); + ~CFilterCoder(); + HRESULT WriteWithLimit(ISequentialOutStream *outStream, UInt32 size); + +public: + MY_QUERYINTERFACE_BEGIN2(ICompressCoder) + MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) + MY_QUERYINTERFACE_ENTRY(ISequentialInStream) + MY_QUERYINTERFACE_ENTRY(ICompressSetOutStream) + MY_QUERYINTERFACE_ENTRY(ISequentialOutStream) + MY_QUERYINTERFACE_ENTRY(IOutStreamFlush) + + #ifndef _NO_CRYPTO + MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword) + #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, _setDecoderProperties) + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + STDMETHOD(ReleaseInStream)(); + STDMETHOD(SetInStream)(ISequentialInStream *inStream); + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); \ + STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); + STDMETHOD(ReleaseOutStream)(); + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Flush)(); + + #ifndef _NO_CRYPTO + STDMETHOD(CryptoSetPassword)(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); +}; + +class CInStreamReleaser +{ +public: + CFilterCoder *FilterCoder; + CInStreamReleaser(): FilterCoder(0) {} + ~CInStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); } +}; + +class COutStreamReleaser +{ +public: + CFilterCoder *FilterCoder; + COutStreamReleaser(): FilterCoder(0) {} + ~COutStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); } +}; + +#endif diff --git a/CPP/7zip/Common/InBuffer.cpp b/CPP/7zip/Common/InBuffer.cpp new file mode 100755 index 0000000..3f84f48 --- /dev/null +++ b/CPP/7zip/Common/InBuffer.cpp @@ -0,0 +1,83 @@ +// InBuffer.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "InBuffer.h" + +CInBuffer::CInBuffer(): + _buffer(0), + _bufferLimit(0), + _bufferBase(0), + _stream(0), + _bufferSize(0) +{} + +bool CInBuffer::Create(UInt32 bufferSize) +{ + const UInt32 kMinBlockSize = 1; + if (bufferSize < kMinBlockSize) + bufferSize = kMinBlockSize; + if (_bufferBase != 0 && _bufferSize == bufferSize) + return true; + Free(); + _bufferSize = bufferSize; + _bufferBase = (Byte *)::MidAlloc(bufferSize); + return (_bufferBase != 0); +} + +void CInBuffer::Free() +{ + ::MidFree(_bufferBase); + _bufferBase = 0; +} + +void CInBuffer::SetStream(ISequentialInStream *stream) +{ + _stream = stream; +} + +void CInBuffer::Init() +{ + _processedSize = 0; + _buffer = _bufferBase; + _bufferLimit = _buffer; + _wasFinished = false; + #ifdef _NO_EXCEPTIONS + ErrorCode = S_OK; + #endif +} + +bool CInBuffer::ReadBlock() +{ + #ifdef _NO_EXCEPTIONS + if (ErrorCode != S_OK) + return false; + #endif + if (_wasFinished) + return false; + _processedSize += (_buffer - _bufferBase); + UInt32 numProcessedBytes; + HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes); + #ifdef _NO_EXCEPTIONS + ErrorCode = result; + #else + if (result != S_OK) + throw CInBufferException(result); + #endif + _buffer = _bufferBase; + _bufferLimit = _buffer + numProcessedBytes; + _wasFinished = (numProcessedBytes == 0); + return (!_wasFinished); +} + +Byte CInBuffer::ReadBlock2() +{ + if (!ReadBlock()) + { + _processedSize++; + return 0xFF; + } + return *_buffer++; +} diff --git a/CPP/7zip/Common/InBuffer.h b/CPP/7zip/Common/InBuffer.h new file mode 100755 index 0000000..cdd50f1 --- /dev/null +++ b/CPP/7zip/Common/InBuffer.h @@ -0,0 +1,81 @@ +// InBuffer.h + +#ifndef __INBUFFER_H +#define __INBUFFER_H + +#include "../IStream.h" +#include "../../Common/MyCom.h" +#include "../../Common/MyException.h" + +#ifndef _NO_EXCEPTIONS +struct CInBufferException: public CSystemException +{ + CInBufferException(HRESULT errorCode): CSystemException(errorCode) {} +}; +#endif + +class CInBuffer +{ + Byte *_buffer; + Byte *_bufferLimit; + Byte *_bufferBase; + CMyComPtr _stream; + UInt64 _processedSize; + UInt32 _bufferSize; + bool _wasFinished; + + bool ReadBlock(); + Byte ReadBlock2(); + +public: + #ifdef _NO_EXCEPTIONS + HRESULT ErrorCode; + #endif + + CInBuffer(); + ~CInBuffer() { Free(); } + + bool Create(UInt32 bufferSize); + void Free(); + + void SetStream(ISequentialInStream *stream); + void Init(); + void ReleaseStream() { _stream.Release(); } + + bool ReadByte(Byte &b) + { + if (_buffer >= _bufferLimit) + if (!ReadBlock()) + return false; + b = *_buffer++; + return true; + } + Byte ReadByte() + { + if (_buffer >= _bufferLimit) + return ReadBlock2(); + return *_buffer++; + } + UInt32 ReadBytes(Byte *buf, UInt32 size) + { + if ((UInt32)(_bufferLimit - _buffer) >= size) + { + for (UInt32 i = 0; i < size; i++) + buf[i] = _buffer[i]; + _buffer += size; + return size; + } + for (UInt32 i = 0; i < size; i++) + { + if (_buffer >= _bufferLimit) + if (!ReadBlock()) + return i; + buf[i] = *_buffer++; + } + return size; + } + UInt64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); } + bool WasFinished() const { return _wasFinished; } +}; + +#endif diff --git a/CPP/7zip/Common/InMemStream.cpp b/CPP/7zip/Common/InMemStream.cpp new file mode 100755 index 0000000..d39ccf5 --- /dev/null +++ b/CPP/7zip/Common/InMemStream.cpp @@ -0,0 +1,222 @@ +// InMemStream.cpp + +#include "StdAfx.h" + +#include + +#include "Windows/Thread.h" + +#include "InMemStream.h" +#include "../../Common/Defs.h" + +void CStreamInfo::Free(IInMemStreamMtCallback *callback) +{ + for (int i = 0; i < Blocks.Size(); i++) + { + callback->FreeBlock(Blocks[i]); + Blocks[i] = 0; + } +} + +bool CInMemStreamMt::Create(int numSubStreams, UInt64 subStreamSize) +{ + Free(); + _subStreamSize = subStreamSize; + size_t blockSize = Callback->GetBlockSize(); + for (int i = 0; i < numSubStreams; i++) + { + _streams.Add(CStreamInfo()); + CStreamInfo &blocks = _streams.Back(); + blocks.Create(); + for (UInt64 j = 0; (UInt64)j * blockSize < _subStreamSize; j++) + blocks.Blocks.Add(0); + } + if (!_streamIndexAllocator.AllocateList(numSubStreams)) + return false; + return true; +} + +void CInMemStreamMt::Free() +{ + while(_streams.Size() > 0) + { + _streams.Back().Free(Callback); + _streams.DeleteBack(); + } +} + +HRESULT CInMemStreamMt::Read() +{ + for (;;) + { + // printf("\n_streamIndexAllocator.AllocateItem\n"); + int index = _streamIndexAllocator.AllocateItem(); + /* + if (_stopReading) + return E_ABORT; + */ + // printf("\nread Index = %d\n", index); + CStreamInfo &blocks = _streams[index]; + blocks.Init(); + Callback->AddStreamIndexToQueue(index); + + for (;;) + { + const Byte *p = (const Byte *)blocks.Blocks[blocks.LastBlockIndex]; + if (p == 0) + { + void **pp = &blocks.Blocks[blocks.LastBlockIndex]; + HRESULT res = Callback->AllocateBlock(pp); + p = (const Byte *)*pp; + RINOK(res); + if (p == 0) + return E_FAIL; + } + size_t blockSize = Callback->GetBlockSize(); + UInt32 curSize = (UInt32)(blockSize - blocks.LastBlockPos); + UInt32 realProcessedSize; + UInt64 pos64 = (UInt64)blocks.LastBlockIndex * blockSize + blocks.LastBlockPos; + if (curSize > _subStreamSize - pos64) + curSize = (UInt32)(_subStreamSize - pos64); + RINOK(_stream->Read((void *)(p + blocks.LastBlockPos), curSize, &realProcessedSize)); + + blocks.Cs->Enter(); + if (realProcessedSize == 0) + { + blocks.StreamWasFinished = true; + blocks.CanReadEvent->Set(); + blocks.Cs->Leave(); + + Callback->AddStreamIndexToQueue(-1); + return S_OK; + } + + blocks.LastBlockPos += realProcessedSize; + if (blocks.LastBlockPos == blockSize) + { + blocks.LastBlockPos = 0; + blocks.LastBlockIndex++; + } + pos64 += realProcessedSize; + if (pos64 >= _subStreamSize) + blocks.StreamWasFinished = true; + blocks.CanReadEvent->Set(); + blocks.Cs->Leave(); + if (pos64 >= _subStreamSize) + break; + } + } +} + +static THREAD_FUNC_DECL CoderThread(void *threadCoderInfo) +{ + ((CInMemStreamMt *)threadCoderInfo)->ReadResult = ((CInMemStreamMt *)threadCoderInfo)->Read(); + return 0; +} + +HRes CInMemStreamMt::StartReadThread() +{ + // _stopReading = false; + NWindows::CThread Thread; + return Thread.Create(CoderThread, this); +} + +void CInMemStreamMt::FreeSubStream(int subStreamIndex) +{ + // printf("\nFreeSubStream\n"); + _streams[subStreamIndex].Free(Callback); + _streamIndexAllocator.FreeItem(subStreamIndex); + // printf("\nFreeSubStream end\n"); +} + +HRESULT CInMemStreamMt::ReadSubStream(int subStreamIndex, void *data, UInt32 size, UInt32 *processedSize, bool keepData) +{ + if (processedSize != NULL) + *processedSize = 0; + CStreamInfo &blocks = _streams[subStreamIndex]; + while (size > 0) + { + if (blocks.CurBlockPos == Callback->GetBlockSize()) + { + blocks.CurBlockPos = 0; + blocks.CurBlockIndex++; + } + UInt32 curSize; + UInt32 curPos = blocks.CurBlockPos; + + blocks.Cs->Enter(); + if (blocks.CurBlockIndex == blocks.LastBlockIndex) + { + curSize = blocks.LastBlockPos - curPos; + if (curSize == 0) + { + if (blocks.StreamWasFinished) + { + blocks.Cs->Leave(); + void *p = blocks.Blocks[blocks.CurBlockIndex]; + if (p != 0 && !keepData) + { + Callback->FreeBlock(p); + blocks.Blocks[blocks.CurBlockIndex] = 0; + } + return S_OK; + } + blocks.CanReadEvent->Reset(); + blocks.Cs->Leave(); + // printf("\nBlock Lock\n"); + blocks.CanReadEvent->Lock(); + // printf("\nAfter Lock\n"); + if (blocks.ExitResult != S_OK) + return blocks.ExitResult; + continue; + } + } + else + curSize = Callback->GetBlockSize() - curPos; + blocks.Cs->Leave(); + + if (curSize > size) + curSize = size; + void *p = blocks.Blocks[blocks.CurBlockIndex]; + memmove(data, (const Byte *)p + curPos, curSize); + data = (void *)((Byte *)data + curSize); + size -= curSize; + if (processedSize != NULL) + *processedSize += curSize; + curPos += curSize; + + bool needFree = false; + blocks.CurBlockPos = curPos; + + if (curPos == Callback->GetBlockSize()) + needFree = true; + blocks.Cs->Enter(); + if (blocks.CurBlockIndex == blocks.LastBlockIndex && + blocks.CurBlockPos == blocks.LastBlockPos && + blocks.StreamWasFinished) + needFree = true; + blocks.Cs->Leave(); + + if (needFree && !keepData) + { + Callback->FreeBlock(p); + blocks.Blocks[blocks.CurBlockIndex] = 0; + } + return S_OK; + } + return S_OK; +} + +STDMETHODIMP CInMemStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessedSize; + HRESULT result = mtStream->ReadSubStream(Index, data, size, &realProcessedSize, _keepData); + if (processedSize != NULL) + *processedSize = realProcessedSize; + if (realProcessedSize != 0) + { + // printf("\ns = %d\n", Index); + } + _size += realProcessedSize; + return result; +} diff --git a/CPP/7zip/Common/InMemStream.h b/CPP/7zip/Common/InMemStream.h new file mode 100755 index 0000000..e2e9fb3 --- /dev/null +++ b/CPP/7zip/Common/InMemStream.h @@ -0,0 +1,284 @@ +// InMemStream.h + +#ifndef __IN_MEM_STREAM_H +#define __IN_MEM_STREAM_H + +#include + +#include "../../../C/Alloc.h" + +#include "../../Common/MyCom.h" + +#include "MemBlocks.h" + +class CIntListCheck +{ +protected: + int *_data; +public: + CIntListCheck(): _data(0) {} + ~CIntListCheck() { FreeList(); } + + bool AllocateList(int numItems) + { + FreeList(); + if (numItems == 0) + return true; + _data = (int *)::MyAlloc(numItems * sizeof(int)); + return (_data != 0); + } + + void FreeList() + { + ::MyFree(_data); + _data = 0; + } +}; + + +class CResourceList : public CIntListCheck +{ + int _headFree; +public: + CResourceList(): _headFree(-1) {} + + bool AllocateList(int numItems) + { + FreeList(); + if (numItems == 0) + return true; + if (!CIntListCheck::AllocateList(numItems)) + return false; + for (int i = 0; i < numItems; i++) + _data[i] = i + 1; + _data[numItems - 1] = -1; + _headFree = 0; + return true; + } + + void FreeList() + { + CIntListCheck::FreeList(); + _headFree = -1; + } + + int AllocateItem() + { + int res = _headFree; + if (res >= 0) + _headFree = _data[res]; + return res; + } + + void FreeItem(int index) + { + if (index < 0) + return; + _data[index] = _headFree; + _headFree = index; + } +}; + +class CResourceListMt: public CResourceList +{ + NWindows::NSynchronization::CCriticalSection _criticalSection; +public: + NWindows::NSynchronization::CSemaphore Semaphore; + + HRes AllocateList(int numItems) + { + if (!CResourceList::AllocateList(numItems)) + return E_OUTOFMEMORY; + Semaphore.Close(); + return Semaphore.Create(numItems, numItems); + } + + int AllocateItem() + { + Semaphore.Lock(); + _criticalSection.Enter(); + int res = CResourceList::AllocateItem(); + _criticalSection.Leave(); + return res; + } + + void FreeItem(int index) + { + if (index < 0) + return; + _criticalSection.Enter(); + CResourceList::FreeItem(index); + _criticalSection.Leave(); + Semaphore.Release(); + } +}; + +class CIntQueueMt: public CIntListCheck +{ + int _numItems; + int _head; + int _cur; +public: + CIntQueueMt(): _numItems(0), _head(0), _cur(0) {} + NWindows::NSynchronization::CSemaphore Semaphore; + + HRes AllocateList(int numItems) + { + FreeList(); + if (numItems == 0) + return S_OK; + if (!CIntListCheck::AllocateList(numItems)) + return E_OUTOFMEMORY; + _numItems = numItems; + return Semaphore.Create(0, numItems); + } + + void FreeList() + { + CIntListCheck::FreeList(); + _numItems = 0; + _head = 0; + _cur = 0; + } + + void AddItem(int value) + { + _data[_head++] = value; + if (_head == _numItems) + _head = 0; + Semaphore.Release(); + // printf("\nRelease prev = %d\n", previousCount); + } + + int GetItem() + { + // Semaphore.Lock(); + int res = _data[_cur++]; + if (_cur == _numItems) + _cur = 0; + return res; + } +}; + +struct IInMemStreamMtCallback +{ + // must be same for all calls + virtual size_t GetBlockSize() = 0; + + // Out: + // result != S_OK stops Reading + // if *p = 0, result must be != S_OK; + // Locking is allowed + virtual HRESULT AllocateBlock(void **p) = 0; + + virtual void FreeBlock(void *p) = 0; + + // It must allow to add at least numSubStreams + 1 , + // where numSubStreams is value from CInMemStreamMt::Create + // value -1 means End of stream + // Locking is not allowed + virtual void AddStreamIndexToQueue(int index) = 0; +}; + +struct CStreamInfo +{ + CRecordVector Blocks; + + int LastBlockIndex; + size_t LastBlockPos; + bool StreamWasFinished; + + int CurBlockIndex; + size_t CurBlockPos; + + NWindows::NSynchronization::CCriticalSection *Cs; + NWindows::NSynchronization::CManualResetEvent *CanReadEvent; + + HRESULT ExitResult; + + CStreamInfo(): Cs(0), CanReadEvent(0), StreamWasFinished(false) { } + ~CStreamInfo() + { + delete Cs; + delete CanReadEvent; + // Free(); + } + void Create() + { + Cs = new NWindows::NSynchronization::CCriticalSection; + CanReadEvent = new NWindows::NSynchronization::CManualResetEvent; + } + + void Free(IInMemStreamMtCallback *callback); + void Init() + { + LastBlockIndex = CurBlockIndex = 0; + CurBlockPos = LastBlockPos = 0; + StreamWasFinished = false; + ExitResult = S_OK; + } + + // res must be != S_OK + void Exit(HRESULT res) + { + ExitResult = res; + CanReadEvent->Set(); + } +}; + + +class CInMemStreamMt +{ + CMyComPtr _stream; + NWindows::NSynchronization::CCriticalSection CS; + CObjectVector _streams; + int _nextFreeStreamIndex; + int _currentStreamIndex; + UInt64 _subStreamSize; + + CResourceListMt _streamIndexAllocator; + + // bool _stopReading; + +public: + HRESULT Read(); + HRESULT ReadResult; + IInMemStreamMtCallback *Callback; + void FreeSubStream(int subStreamIndex); + HRESULT ReadSubStream(int subStreamIndex, void *data, UInt32 size, UInt32 *processedSize, bool keepData); + + // numSubStreams: min = 1, good min = numThreads + bool Create(int numSubStreams, UInt64 subStreamSize); + ~CInMemStreamMt() { Free(); } + void SetStream(ISequentialInStream *stream) { _stream = stream; } + + // to stop reading you must implement + // returning Error in IInMemStreamMtCallback::AllocateBlock + // and then you must free at least one substream + HRes StartReadThread(); + + void Free(); + + // you must free at least one substream after that function to unlock waiting. + // void StopReading() { _stopReading = true; } +}; + +class CInMemStream: + public ISequentialInStream, + public CMyUnknownImp +{ + UInt64 _size; + bool _keepData; +public: + int Index; + CInMemStreamMt *mtStream; + void Init(bool keepData = false) + { + _size = 0; _keepData = keepData ; + } + MY_UNKNOWN_IMP + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + UInt64 GetSize() const { return _size; } +}; + +#endif diff --git a/CPP/7zip/Common/InOutTempBuffer.cpp b/CPP/7zip/Common/InOutTempBuffer.cpp new file mode 100755 index 0000000..13a7696 --- /dev/null +++ b/CPP/7zip/Common/InOutTempBuffer.cpp @@ -0,0 +1,122 @@ +// InOutTempBuffer.cpp + +#include "StdAfx.h" + +#include "../../../C/7zCrc.h" + +#include "InOutTempBuffer.h" +#include "StreamUtils.h" + +using namespace NWindows; +using namespace NFile; +using namespace NDirectory; + +static const UInt32 kTempBufSize = (1 << 20); + +static LPCTSTR kTempFilePrefixString = TEXT("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) + { + CSysString tempDirPath; + if (!MyGetTempPath(tempDirPath)) + return false; + if (_tempFile.Create(tempDirPath, kTempFilePrefixString, _tempFileName) == 0) + return false; + if (!_outFile.Create(_tempFileName, true)) + 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 (_bufPos < kTempBufSize) + { + UInt32 cur = MyMin(kTempBufSize - _bufPos, size); + memcpy(_buf + _bufPos, data, cur); + _crc = CrcUpdate(_crc, data, cur); + _bufPos += cur; + size -= cur; + data = ((const Byte *)data) + cur; + _size += 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(_tempFileName)) + 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 != NULL) + *processed = 0; + return E_FAIL; + } + if (processed != NULL) + *processed = size; + return S_OK; +} diff --git a/CPP/7zip/Common/InOutTempBuffer.h b/CPP/7zip/Common/InOutTempBuffer.h new file mode 100755 index 0000000..a69bc85 --- /dev/null +++ b/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 "../../Windows/FileIO.h" + +#include "../IStream.h" + +class CInOutTempBuffer +{ + NWindows::NFile::NDirectory::CTempFile _tempFile; + NWindows::NFile::NIO::COutFile _outFile; + Byte *_buf; + UInt32 _bufPos; + CSysString _tempFileName; + bool _tempFileCreated; + UInt64 _size; + UInt32 _crc; + + 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/CPP/7zip/Common/LimitedStreams.cpp b/CPP/7zip/Common/LimitedStreams.cpp new file mode 100755 index 0000000..dd2d2d5 --- /dev/null +++ b/CPP/7zip/Common/LimitedStreams.cpp @@ -0,0 +1,154 @@ +// LimitedStreams.cpp + +#include "StdAfx.h" + +#include "LimitedStreams.h" +#include "../../Common/Defs.h" + +STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessedSize = 0; + UInt32 sizeToRead = (UInt32)MyMin((_size - _pos), (UInt64)size); + HRESULT result = S_OK; + if (sizeToRead > 0) + { + result = _stream->Read(data, sizeToRead, &realProcessedSize); + _pos += realProcessedSize; + if (realProcessedSize == 0) + _wasFinished = true; + } + if (processedSize != NULL) + *processedSize = realProcessedSize; + return result; +} + +STDMETHODIMP CLimitedInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != NULL) + *processedSize = 0; + if (_virtPos >= _size) + return (_virtPos == _size) ? S_OK: E_FAIL; + UInt64 rem = _size - _virtPos; + if (rem < size) + size = (UInt32)rem; + UInt64 newPos = _startOffset + _virtPos; + if (newPos != _physPos) + { + _physPos = newPos; + RINOK(SeekToPhys()); + } + HRESULT res = _stream->Read(data, size, &size); + if (processedSize != NULL) + *processedSize = size; + _physPos += size; + _virtPos += size; + return res; +} + +STDMETHODIMP CLimitedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch(seekOrigin) + { + case STREAM_SEEK_SET: _virtPos = offset; break; + case STREAM_SEEK_CUR: _virtPos += offset; break; + case STREAM_SEEK_END: _virtPos = _size + offset; break; + default: return STG_E_INVALIDFUNCTION; + } + if (newPosition) + *newPosition = _virtPos; + return S_OK; +} + +STDMETHODIMP CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != NULL) + *processedSize = 0; + if (_virtPos >= Size) + return (_virtPos == Size) ? S_OK: E_FAIL; + + if (_curRem == 0) + { + UInt32 blockSize = (UInt32)1 << BlockSizeLog; + UInt32 virtBlock = (UInt32)(_virtPos >> BlockSizeLog); + UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1); + 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; + UInt64 rem = Size - _virtPos; + if (_curRem > rem) + _curRem = (UInt32)rem; + } + if (size > _curRem) + size = _curRem; + HRESULT res = Stream->Read(data, size, &size); + if (processedSize != NULL) + *processedSize = size; + _physPos += size; + _virtPos += size; + _curRem -= size; + return res; +} + +STDMETHODIMP CClusterInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + UInt64 newVirtPos = offset; + switch(seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: newVirtPos += _virtPos; break; + case STREAM_SEEK_END: newVirtPos += Size; break; + default: return STG_E_INVALIDFUNCTION; + } + if (_virtPos != newVirtPos) + _curRem = 0; + _virtPos = newVirtPos; + if (newPosition) + *newPosition = newVirtPos; + 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 CLimitedSequentialOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + HRESULT result = S_OK; + if (processedSize != NULL) + *processedSize = 0; + if (size > _size) + { + if (_size == 0) + { + _overflow = true; + if (!_overflowIsAllowed) + return E_FAIL; + if (processedSize != NULL) + *processedSize = size; + return S_OK; + } + size = (UInt32)_size; + } + if (_stream) + result = _stream->Write(data, size, &size); + _size -= size; + if (processedSize != NULL) + *processedSize = size; + return result; +} diff --git a/CPP/7zip/Common/LimitedStreams.h b/CPP/7zip/Common/LimitedStreams.h new file mode 100755 index 0000000..caec98f --- /dev/null +++ b/CPP/7zip/Common/LimitedStreams.h @@ -0,0 +1,125 @@ +// LimitedStreams.h + +#ifndef __LIMITED_STREAMS_H +#define __LIMITED_STREAMS_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_IMP + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + UInt64 GetSize() const { return _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_IMP1(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 CClusterInStream: + public IInStream, + public CMyUnknownImp +{ + UInt64 _virtPos; + UInt64 _physPos; + UInt32 _curRem; +public: + CMyComPtr Stream; + UInt64 StartOffset; + UInt64 Size; + int BlockSizeLog; + CRecordVector Vector; + + 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_IMP1(IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + +HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream); + +class CLimitedSequentialOutStream: + public ISequentialOutStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + UInt64 _size; + bool _overflow; + bool _overflowIsAllowed; +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(UInt64 size, bool overflowIsAllowed = false) + { + _size = size; + _overflow = false; + _overflowIsAllowed = overflowIsAllowed; + } + bool IsFinishedOK() const { return (_size == 0 && !_overflow); } + UInt64 GetRem() const { return _size; } +}; + +#endif diff --git a/CPP/7zip/Common/LockedStream.cpp b/CPP/7zip/Common/LockedStream.cpp new file mode 100755 index 0000000..d1bbf6d --- /dev/null +++ b/CPP/7zip/Common/LockedStream.cpp @@ -0,0 +1,23 @@ +// LockedStream.cpp + +#include "StdAfx.h" + +#include "LockedStream.h" + +HRESULT CLockedInStream::Read(UInt64 startPos, void *data, UInt32 size, + UInt32 *processedSize) +{ + NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); + RINOK(_stream->Seek(startPos, STREAM_SEEK_SET, NULL)); + return _stream->Read(data, size, processedSize); +} + +STDMETHODIMP CLockedSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessedSize = 0; + HRESULT result = _lockedInStream->Read(_pos, data, size, &realProcessedSize); + _pos += realProcessedSize; + if (processedSize != NULL) + *processedSize = realProcessedSize; + return result; +} diff --git a/CPP/7zip/Common/LockedStream.h b/CPP/7zip/Common/LockedStream.h new file mode 100755 index 0000000..e12e22a --- /dev/null +++ b/CPP/7zip/Common/LockedStream.h @@ -0,0 +1,38 @@ +// LockedStream.h + +#ifndef __LOCKEDSTREAM_H +#define __LOCKEDSTREAM_H + +#include "../../Windows/Synchronization.h" +#include "../../Common/MyCom.h" +#include "../IStream.h" + +class CLockedInStream +{ + CMyComPtr _stream; + NWindows::NSynchronization::CCriticalSection _criticalSection; +public: + void Init(IInStream *stream) + { _stream = stream; } + HRESULT Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize); +}; + +class CLockedSequentialInStreamImp: + public ISequentialInStream, + public CMyUnknownImp +{ + CLockedInStream *_lockedInStream; + UInt64 _pos; +public: + void Init(CLockedInStream *lockedInStream, UInt64 startPos) + { + _lockedInStream = lockedInStream; + _pos = startPos; + } + + MY_UNKNOWN_IMP + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); +}; + +#endif diff --git a/CPP/7zip/Common/MemBlocks.cpp b/CPP/7zip/Common/MemBlocks.cpp new file mode 100755 index 0000000..b7bcb56 --- /dev/null +++ b/CPP/7zip/Common/MemBlocks.cpp @@ -0,0 +1,183 @@ +// MemBlocks.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "MemBlocks.h" +#include "StreamUtils.h" + +bool CMemBlockManager::AllocateSpace(size_t numBlocks) +{ + FreeSpace(); + if (_blockSize < sizeof(void *) || numBlocks < 1) + return false; + size_t totalSize = numBlocks * _blockSize; + if (totalSize / _blockSize != numBlocks) + return false; + _data = ::MidAlloc(totalSize); + if (_data == 0) + return false; + Byte *p = (Byte *)_data; + for (size_t i = 0; i + 1 < numBlocks; i++, p += _blockSize) + *(Byte **)p = (p + _blockSize); + *(Byte **)p = 0; + _headFree = _data; + return true; +} + +void CMemBlockManager::FreeSpace() +{ + ::MidFree(_data); + _data = 0; + _headFree= 0; +} + +void *CMemBlockManager::AllocateBlock() +{ + if (_headFree == 0) + return 0; + void *p = _headFree; + _headFree = *(void **)_headFree; + return p; +} + +void CMemBlockManager::FreeBlock(void *p) +{ + if (p == 0) + return; + *(void **)p = _headFree; + _headFree = p; +} + + +HRes CMemBlockManagerMt::AllocateSpace(size_t numBlocks, size_t numNoLockBlocks) +{ + if (numNoLockBlocks > numBlocks) + return E_INVALIDARG; + if (!CMemBlockManager::AllocateSpace(numBlocks)) + return E_OUTOFMEMORY; + size_t numLockBlocks = numBlocks - numNoLockBlocks; + Semaphore.Close(); + return Semaphore.Create((LONG)numLockBlocks, (LONG)numLockBlocks); +} + +HRes CMemBlockManagerMt::AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_t numNoLockBlocks) +{ + if (numNoLockBlocks > desiredNumberOfBlocks) + return E_INVALIDARG; + for (;;) + { + if (AllocateSpace(desiredNumberOfBlocks, numNoLockBlocks) == 0) + return 0; + if (desiredNumberOfBlocks == numNoLockBlocks) + return E_OUTOFMEMORY; + desiredNumberOfBlocks = numNoLockBlocks + ((desiredNumberOfBlocks - numNoLockBlocks) >> 1); + } +} + +void CMemBlockManagerMt::FreeSpace() +{ + Semaphore.Close(); + CMemBlockManager::FreeSpace(); +} + +void *CMemBlockManagerMt::AllocateBlock() +{ + // Semaphore.Lock(); + NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); + return CMemBlockManager::AllocateBlock(); +} + +void CMemBlockManagerMt::FreeBlock(void *p, bool lockMode) +{ + if (p == 0) + return; + { + NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); + CMemBlockManager::FreeBlock(p); + } + if (lockMode) + Semaphore.Release(); +} + +void CMemBlocks::Free(CMemBlockManagerMt *manager) +{ + while(Blocks.Size() > 0) + { + manager->FreeBlock(Blocks.Back()); + Blocks.DeleteBack(); + } + TotalSize = 0; +} + +void CMemBlocks::FreeOpt(CMemBlockManagerMt *manager) +{ + Free(manager); + Blocks.ClearAndFree(); +} + +HRESULT CMemBlocks::WriteToStream(size_t blockSize, ISequentialOutStream *outStream) const +{ + UInt64 totalSize = TotalSize; + for (int blockIndex = 0; totalSize > 0; blockIndex++) + { + UInt32 curSize = (UInt32)blockSize; + if (totalSize < curSize) + curSize = (UInt32)totalSize; + if (blockIndex >= Blocks.Size()) + return E_FAIL; + RINOK(WriteStream(outStream, Blocks[blockIndex], curSize)); + totalSize -= curSize; + } + return S_OK; +} + + +void CMemLockBlocks::FreeBlock(int index, CMemBlockManagerMt *memManager) +{ + memManager->FreeBlock(Blocks[index], LockMode); + Blocks[index] = 0; +} + +void CMemLockBlocks::Free(CMemBlockManagerMt *memManager) +{ + while (Blocks.Size() > 0) + { + FreeBlock(Blocks.Size() - 1, memManager); + Blocks.DeleteBack(); + } + TotalSize = 0; +} + +HRes CMemLockBlocks::SwitchToNoLockMode(CMemBlockManagerMt *memManager) +{ + if (LockMode) + { + if (Blocks.Size() > 0) + { + RINOK(memManager->ReleaseLockedBlocks(Blocks.Size())); + } + LockMode = false; + } + return 0; +} + +void CMemLockBlocks::Detach(CMemLockBlocks &blocks, CMemBlockManagerMt *memManager) +{ + blocks.Free(memManager); + blocks.LockMode = LockMode; + UInt64 totalSize = 0; + size_t blockSize = memManager->GetBlockSize(); + for (int i = 0; i < Blocks.Size(); i++) + { + if (totalSize < TotalSize) + blocks.Blocks.Add(Blocks[i]); + else + FreeBlock(i, memManager); + Blocks[i] = 0; + totalSize += blockSize; + } + blocks.TotalSize = TotalSize; + Free(memManager); +} diff --git a/CPP/7zip/Common/MemBlocks.h b/CPP/7zip/Common/MemBlocks.h new file mode 100755 index 0000000..b0cdcf6 --- /dev/null +++ b/CPP/7zip/Common/MemBlocks.h @@ -0,0 +1,71 @@ +// MemBlocks.h + +#ifndef __MEM_BLOCKS_H +#define __MEM_BLOCKS_H + +#include "Common/MyVector.h" + +#include "Windows/Synchronization.h" + +#include "../IStream.h" + +class CMemBlockManager +{ + void *_data; + size_t _blockSize; + void *_headFree; +public: + CMemBlockManager(size_t blockSize = (1 << 20)): _data(0), _blockSize(blockSize), _headFree(0) {} + ~CMemBlockManager() { FreeSpace(); } + + bool AllocateSpace(size_t numBlocks); + void FreeSpace(); + size_t GetBlockSize() const { return _blockSize; } + void *AllocateBlock(); + void FreeBlock(void *p); +}; + + +class CMemBlockManagerMt: public CMemBlockManager +{ + NWindows::NSynchronization::CCriticalSection _criticalSection; +public: + NWindows::NSynchronization::CSemaphore Semaphore; + + CMemBlockManagerMt(size_t blockSize = (1 << 20)): CMemBlockManager(blockSize) {} + ~CMemBlockManagerMt() { FreeSpace(); } + + HRes AllocateSpace(size_t numBlocks, size_t numNoLockBlocks = 0); + HRes AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_t numNoLockBlocks = 0); + void FreeSpace(); + void *AllocateBlock(); + void FreeBlock(void *p, bool lockMode = true); + HRes ReleaseLockedBlocks(int number) { return Semaphore.Release(number); } +}; + + +class CMemBlocks +{ + void Free(CMemBlockManagerMt *manager); +public: + CRecordVector Blocks; + UInt64 TotalSize; + + CMemBlocks(): TotalSize(0) {} + + void FreeOpt(CMemBlockManagerMt *manager); + HRESULT WriteToStream(size_t blockSize, ISequentialOutStream *outStream) const; +}; + +struct CMemLockBlocks: public CMemBlocks +{ + bool LockMode; + + CMemLockBlocks(): LockMode(true) {}; + void Free(CMemBlockManagerMt *memManager); + void FreeBlock(int index, CMemBlockManagerMt *memManager); + HRes SwitchToNoLockMode(CMemBlockManagerMt *memManager); + void Detach(CMemLockBlocks &blocks, CMemBlockManagerMt *memManager); +}; + +#endif diff --git a/CPP/7zip/Common/MethodId.cpp b/CPP/7zip/Common/MethodId.cpp new file mode 100755 index 0000000..705cc4d --- /dev/null +++ b/CPP/7zip/Common/MethodId.cpp @@ -0,0 +1,27 @@ +// MethodId.cpp + +#include "StdAfx.h" + +#include "MethodId.h" +#include "../../Common/MyString.h" + +static inline wchar_t GetHex(Byte value) +{ + return (wchar_t)((value < 10) ? ('0' + value) : ('A' + (value - 10))); +} + +UString ConvertMethodIdToString(UInt64 id) +{ + wchar_t s[32]; + int len = 32; + s[--len] = 0; + do + { + s[--len] = GetHex((Byte)id & 0xF); + id >>= 4; + s[--len] = GetHex((Byte)id & 0xF); + id >>= 4; + } + while (id != 0); + return s + len; +} diff --git a/CPP/7zip/Common/MethodId.h b/CPP/7zip/Common/MethodId.h new file mode 100755 index 0000000..9551723 --- /dev/null +++ b/CPP/7zip/Common/MethodId.h @@ -0,0 +1,10 @@ +// MethodId.h + +#ifndef __7Z_METHOD_ID_H +#define __7Z_METHOD_ID_H + +#include "../../Common/Types.h" + +typedef UInt64 CMethodId; + +#endif diff --git a/CPP/7zip/Common/MethodProps.cpp b/CPP/7zip/Common/MethodProps.cpp new file mode 100755 index 0000000..937708e --- /dev/null +++ b/CPP/7zip/Common/MethodProps.cpp @@ -0,0 +1,99 @@ +// MethodProps.cpp + +#include "StdAfx.h" + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +#include "MethodProps.h" + +static const UInt64 k_LZMA = 0x030101; +static const UInt64 k_LZMA2 = 0x21; + +HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder) +{ + bool tryReduce = false; + UInt32 reducedDictionarySize = 1 << 10; + if (inSizeForReduce != 0 && (method.Id == k_LZMA || method.Id == k_LZMA2)) + { + for (;;) + { + const UInt32 step = (reducedDictionarySize >> 1); + if (reducedDictionarySize >= *inSizeForReduce) + { + tryReduce = true; + break; + } + reducedDictionarySize += step; + if (reducedDictionarySize >= *inSizeForReduce) + { + tryReduce = true; + break; + } + if (reducedDictionarySize >= ((UInt32)3 << 30)) + break; + reducedDictionarySize += step; + } + } + + { + int numProps = method.Props.Size(); + CMyComPtr setCoderProperties; + coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); + if (setCoderProperties == NULL) + { + if (numProps != 0) + return E_INVALIDARG; + } + else + { + CRecordVector propIDs; + NWindows::NCOM::CPropVariant *values = new NWindows::NCOM::CPropVariant[numProps]; + HRESULT res = S_OK; + try + { + for (int i = 0; i < numProps; i++) + { + const CProp &prop = method.Props[i]; + propIDs.Add(prop.Id); + NWindows::NCOM::CPropVariant &value = values[i]; + value = prop.Value; + // if (tryReduce && prop.Id == NCoderPropID::kDictionarySize && value.vt == VT_UI4 && reducedDictionarySize < value.ulVal) + if (tryReduce) + if (prop.Id == NCoderPropID::kDictionarySize) + if (value.vt == VT_UI4) + if (reducedDictionarySize < value.ulVal) + value.ulVal = reducedDictionarySize; + } + CMyComPtr setCoderProperties; + coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); + res = setCoderProperties->SetCoderProperties(&propIDs.Front(), values, numProps); + } + catch(...) + { + delete []values; + throw; + } + delete []values; + RINOK(res); + } + } + + /* + CMyComPtr writeCoderProperties; + coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); + if (writeCoderProperties != NULL) + { + CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp; + CMyComPtr outStream(outStreamSpec); + outStreamSpec->Init(); + RINOK(writeCoderProperties->WriteCoderProperties(outStream)); + size_t size = outStreamSpec->GetSize(); + filterProps.SetCapacity(size); + memmove(filterProps, outStreamSpec->GetBuffer(), size); + } + */ + return S_OK; +} + diff --git a/CPP/7zip/Common/MethodProps.h b/CPP/7zip/Common/MethodProps.h new file mode 100755 index 0000000..75b87f1 --- /dev/null +++ b/CPP/7zip/Common/MethodProps.h @@ -0,0 +1,41 @@ +// MethodProps.h + +#ifndef __7Z_METHOD_PROPS_H +#define __7Z_METHOD_PROPS_H + +#include "../../Common/MyVector.h" + +#include "../../Windows/PropVariant.h" + +#include "MethodId.h" + +struct CProp +{ + PROPID Id; + NWindows::NCOM::CPropVariant Value; +}; + +struct CMethod +{ + CMethodId Id; + CObjectVector Props; +}; + +struct CMethodsMode +{ + CObjectVector Methods; + #ifndef _7ZIP_ST + UInt32 NumThreads; + #endif + + CMethodsMode() + #ifndef _7ZIP_ST + : NumThreads(1) + #endif + {} + bool IsEmpty() const { return Methods.IsEmpty() ; } +}; + +HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder); + +#endif diff --git a/CPP/7zip/Common/OffsetStream.cpp b/CPP/7zip/Common/OffsetStream.cpp new file mode 100755 index 0000000..f10f54c --- /dev/null +++ b/CPP/7zip/Common/OffsetStream.cpp @@ -0,0 +1,35 @@ +// 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) + offset += _offset; + HRESULT result = _stream->Seek(offset, seekOrigin, &absoluteNewPosition); + if (newPosition != NULL) + *newPosition = absoluteNewPosition - _offset; + return result; +} + +STDMETHODIMP COffsetOutStream::SetSize(UInt64 newSize) +{ + return _stream->SetSize(_offset + newSize); +} diff --git a/CPP/7zip/Common/OffsetStream.h b/CPP/7zip/Common/OffsetStream.h new file mode 100755 index 0000000..972a8ce --- /dev/null +++ b/CPP/7zip/Common/OffsetStream.h @@ -0,0 +1,25 @@ +// OffsetStream.h + +#ifndef __OFFSETSTREAM_H +#define __OFFSETSTREAM_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/CPP/7zip/Common/OutBuffer.cpp b/CPP/7zip/Common/OutBuffer.cpp new file mode 100755 index 0000000..4e55f55 --- /dev/null +++ b/CPP/7zip/Common/OutBuffer.cpp @@ -0,0 +1,116 @@ +// OutBuffer.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "OutBuffer.h" + +bool COutBuffer::Create(UInt32 bufferSize) +{ + const UInt32 kMinBlockSize = 1; + if (bufferSize < kMinBlockSize) + bufferSize = kMinBlockSize; + if (_buffer != 0 && _bufferSize == bufferSize) + return true; + Free(); + _bufferSize = bufferSize; + _buffer = (Byte *)::MidAlloc(bufferSize); + return (_buffer != 0); +} + +void COutBuffer::Free() +{ + ::MidFree(_buffer); + _buffer = 0; +} + +void COutBuffer::SetStream(ISequentialOutStream *stream) +{ + _stream = stream; +} + +void COutBuffer::Init() +{ + _streamPos = 0; + _limitPos = _bufferSize; + _pos = 0; + _processedSize = 0; + _overDict = false; + #ifdef _NO_EXCEPTIONS + ErrorCode = S_OK; + #endif +} + +UInt64 COutBuffer::GetProcessedSize() const +{ + UInt64 res = _processedSize + _pos - _streamPos; + if (_streamPos > _pos) + res += _bufferSize; + return res; +} + + +HRESULT COutBuffer::FlushPart() +{ + // _streamPos < _bufferSize + UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos); + HRESULT result = S_OK; + #ifdef _NO_EXCEPTIONS + result = ErrorCode; + #endif + if (_buffer2 != 0) + { + memmove(_buffer2, _buffer + _streamPos, size); + _buffer2 += size; + } + + if (_stream != 0 + #ifdef _NO_EXCEPTIONS + && (ErrorCode == S_OK) + #endif + ) + { + UInt32 processedSize = 0; + result = _stream->Write(_buffer + _streamPos, size, &processedSize); + size = processedSize; + } + _streamPos += size; + if (_streamPos == _bufferSize) + _streamPos = 0; + if (_pos == _bufferSize) + { + _overDict = true; + _pos = 0; + } + _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize; + _processedSize += size; + return result; +} + +HRESULT COutBuffer::Flush() +{ + #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/CPP/7zip/Common/OutBuffer.h b/CPP/7zip/Common/OutBuffer.h new file mode 100755 index 0000000..e2e76ad --- /dev/null +++ b/CPP/7zip/Common/OutBuffer.h @@ -0,0 +1,64 @@ +// OutBuffer.h + +#ifndef __OUTBUFFER_H +#define __OUTBUFFER_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 *_buffer; + UInt32 _pos; + UInt32 _limitPos; + UInt32 _streamPos; + UInt32 _bufferSize; + CMyComPtr _stream; + UInt64 _processedSize; + Byte *_buffer2; + bool _overDict; + + HRESULT FlushPart(); +public: + #ifdef _NO_EXCEPTIONS + HRESULT ErrorCode; + #endif + + COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {} + ~COutBuffer() { Free(); } + + bool Create(UInt32 bufferSize); + void Free(); + + void SetMemStream(Byte *buffer) { _buffer2 = buffer; } + void SetStream(ISequentialOutStream *stream); + void Init(); + HRESULT Flush(); + void FlushWithCheck(); + void ReleaseStream() { _stream.Release(); } + + void WriteByte(Byte b) + { + _buffer[_pos++] = b; + 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; +}; + +#endif diff --git a/CPP/7zip/Common/OutMemStream.cpp b/CPP/7zip/Common/OutMemStream.cpp new file mode 100755 index 0000000..22ba984 --- /dev/null +++ b/CPP/7zip/Common/OutMemStream.cpp @@ -0,0 +1,142 @@ +// OutMemStream.cpp + +#include "StdAfx.h" + +#include "OutMemStream.h" + +void COutMemStream::Free() +{ + Blocks.Free(_memManager); + Blocks.LockMode = true; +} + +void COutMemStream::Init() +{ + WriteToRealStreamEvent.Reset(); + _unlockEventWasSent = false; + _realStreamMode = false; + Free(); + _curBlockPos = 0; + _curBlockIndex = 0; +} + +void COutMemStream::DetachData(CMemLockBlocks &blocks) +{ + Blocks.Detach(blocks, _memManager); + Free(); +} + + +HRESULT COutMemStream::WriteToRealStream() +{ + RINOK(Blocks.WriteToStream(_memManager->GetBlockSize(), OutSeqStream)); + Blocks.Free(_memManager); + return S_OK; +} + +STDMETHODIMP COutMemStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if (_realStreamMode) + return OutSeqStream->Write(data, size, processedSize); + if (processedSize != 0) + *processedSize = 0; + while(size != 0) + { + if ((int)_curBlockIndex < Blocks.Blocks.Size()) + { + Byte *p = (Byte *)Blocks.Blocks[(int)_curBlockIndex] + _curBlockPos; + size_t curSize = _memManager->GetBlockSize() - _curBlockPos; + if (size < curSize) + curSize = size; + memmove(p, data, curSize); + if (processedSize != 0) + *processedSize += (UInt32)curSize; + data = (const void *)((const Byte *)data + curSize); + size -= (UInt32)curSize; + _curBlockPos += curSize; + + UInt64 pos64 = GetPos(); + if (pos64 > Blocks.TotalSize) + Blocks.TotalSize = pos64; + if (_curBlockPos == _memManager->GetBlockSize()) + { + _curBlockIndex++; + _curBlockPos = 0; + } + continue; + } + HANDLE events[3] = { StopWritingEvent, WriteToRealStreamEvent, /* NoLockEvent, */ _memManager->Semaphore }; + DWORD waitResult = ::WaitForMultipleObjects((Blocks.LockMode ? 3 : 2), events, FALSE, INFINITE); + switch (waitResult) + { + case (WAIT_OBJECT_0 + 0): + return StopWriteResult; + case (WAIT_OBJECT_0 + 1): + { + _realStreamMode = true; + RINOK(WriteToRealStream()); + UInt32 processedSize2; + HRESULT res = OutSeqStream->Write(data, size, &processedSize2); + if (processedSize != 0) + *processedSize += processedSize2; + return res; + } + /* + case (WAIT_OBJECT_0 + 2): + { + // it has bug: no write. + if (!Blocks.SwitchToNoLockMode(_memManager)) + return E_FAIL; + break; + } + */ + case (WAIT_OBJECT_0 + 2): + break; + default: + return E_FAIL; + } + Blocks.Blocks.Add(_memManager->AllocateBlock()); + if (Blocks.Blocks.Back() == 0) + return E_FAIL; + } + return S_OK; +} + +STDMETHODIMP COutMemStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + if (_realStreamMode) + { + if (!OutStream) + return E_FAIL; + return OutStream->Seek(offset, seekOrigin, newPosition); + } + if (seekOrigin == STREAM_SEEK_CUR) + { + if (offset != 0) + return E_NOTIMPL; + } + else if (seekOrigin == STREAM_SEEK_SET) + { + if (offset != 0) + return E_NOTIMPL; + _curBlockIndex = 0; + _curBlockPos = 0; + } + else + return E_NOTIMPL; + if (newPosition != 0) + *newPosition = GetPos(); + return S_OK; +} + +STDMETHODIMP COutMemStream::SetSize(UInt64 newSize) +{ + if (_realStreamMode) + { + if (!OutStream) + return E_FAIL; + return OutStream->SetSize(newSize); + } + Blocks.TotalSize = newSize; + return S_OK; +} diff --git a/CPP/7zip/Common/OutMemStream.h b/CPP/7zip/Common/OutMemStream.h new file mode 100755 index 0000000..3037903 --- /dev/null +++ b/CPP/7zip/Common/OutMemStream.h @@ -0,0 +1,96 @@ +// OutMemStream.h + +#ifndef __OUTMEMSTREAM_H +#define __OUTMEMSTREAM_H + +#include "Common/MyCom.h" +#include "MemBlocks.h" + +class COutMemStream: + public IOutStream, + public CMyUnknownImp +{ + CMemBlockManagerMt *_memManager; + size_t _curBlockIndex; + size_t _curBlockPos; + bool _realStreamMode; + + bool _unlockEventWasSent; + NWindows::NSynchronization::CAutoResetEvent StopWritingEvent; + NWindows::NSynchronization::CAutoResetEvent WriteToRealStreamEvent; + // NWindows::NSynchronization::CAutoResetEvent NoLockEvent; + + HRESULT StopWriteResult; + CMemLockBlocks Blocks; + + UInt64 GetPos() const { return (UInt64)_curBlockIndex * _memManager->GetBlockSize() + _curBlockPos; } + + CMyComPtr OutSeqStream; + CMyComPtr OutStream; + +public: + + HRes CreateEvents() + { + RINOK(StopWritingEvent.CreateIfNotCreated()); + return WriteToRealStreamEvent.CreateIfNotCreated(); + } + + void SetOutStream(IOutStream *outStream) + { + OutStream = outStream; + OutSeqStream = outStream; + } + + void SetSeqOutStream(ISequentialOutStream *outStream) + { + OutStream = NULL; + OutSeqStream = outStream; + } + + void ReleaseOutStream() + { + OutStream.Release(); + OutSeqStream.Release(); + } + + COutMemStream(CMemBlockManagerMt *memManager): _memManager(memManager) { } + + ~COutMemStream() { Free(); } + void Free(); + + void Init(); + HRESULT WriteToRealStream(); + + void DetachData(CMemLockBlocks &blocks); + + bool WasUnlockEventSent() const { return _unlockEventWasSent; } + + void SetRealStreamMode() + { + _unlockEventWasSent = true; + WriteToRealStreamEvent.Set(); + } + + /* + void SetNoLockMode() + { + _unlockEventWasSent = true; + NoLockEvent.Set(); + } + */ + + void StopWriting(HRESULT res) + { + StopWriteResult = res; + StopWritingEvent.Set(); + } + + 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/CPP/7zip/Common/ProgressMt.cpp b/CPP/7zip/Common/ProgressMt.cpp new file mode 100755 index 0000000..e1e7f38 --- /dev/null +++ b/CPP/7zip/Common/ProgressMt.cpp @@ -0,0 +1,53 @@ +// ProgressMt.h + +#include "StdAfx.h" + +#include "ProgressMt.h" + +void CMtCompressProgressMixer::Init(int numItems, ICompressProgressInfo *progress) +{ + NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection); + InSizes.Clear(); + OutSizes.Clear(); + for (int i = 0; i < numItems; i++) + { + InSizes.Add(0); + OutSizes.Add(0); + } + TotalInSize = 0; + TotalOutSize = 0; + _progress = progress; +} + +void CMtCompressProgressMixer::Reinit(int index) +{ + NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection); + InSizes[index] = 0; + OutSizes[index] = 0; +} + +HRESULT CMtCompressProgressMixer::SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize) +{ + NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection); + if (inSize != 0) + { + UInt64 diff = *inSize - InSizes[index]; + InSizes[index] = *inSize; + TotalInSize += diff; + } + if (outSize != 0) + { + UInt64 diff = *outSize - OutSizes[index]; + OutSizes[index] = *outSize; + TotalOutSize += diff; + } + if (_progress) + return _progress->SetRatioInfo(&TotalInSize, &TotalOutSize); + return S_OK; +} + + +STDMETHODIMP CMtCompressProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) +{ + return _progress->SetRatioInfo(_index, inSize, outSize); +} diff --git a/CPP/7zip/Common/ProgressMt.h b/CPP/7zip/Common/ProgressMt.h new file mode 100755 index 0000000..4eeb02a --- /dev/null +++ b/CPP/7zip/Common/ProgressMt.h @@ -0,0 +1,46 @@ +// ProgressMt.h + +#ifndef __PROGRESSMT_H +#define __PROGRESSMT_H + +#include "../../Common/MyCom.h" +#include "../../Common/MyVector.h" +#include "../../Windows/Synchronization.h" + +#include "../ICoder.h" +#include "../IProgress.h" + +class CMtCompressProgressMixer +{ + CMyComPtr _progress; + CRecordVector InSizes; + CRecordVector OutSizes; + UInt64 TotalInSize; + UInt64 TotalOutSize; +public: + NWindows::NSynchronization::CCriticalSection CriticalSection; + void Init(int numItems, ICompressProgressInfo *progress); + void Reinit(int index); + HRESULT SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize); +}; + +class CMtCompressProgress: + public ICompressProgressInfo, + public CMyUnknownImp +{ + CMtCompressProgressMixer *_progress; + int _index; +public: + void Init(CMtCompressProgressMixer *progress, int index) + { + _progress = progress; + _index = index; + } + void Reinit() { _progress->Reinit(_index); } + + MY_UNKNOWN_IMP + + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); +}; + +#endif diff --git a/CPP/7zip/Common/ProgressUtils.cpp b/CPP/7zip/Common/ProgressUtils.cpp new file mode 100755 index 0000000..84a3eaf --- /dev/null +++ b/CPP/7zip/Common/ProgressUtils.cpp @@ -0,0 +1,42 @@ +// ProgressUtils.h + +#include "StdAfx.h" + +#include "ProgressUtils.h" + +CLocalProgress::CLocalProgress() +{ + ProgressOffset = InSize = OutSize = 0; + SendRatio = 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 inSizeNew = InSize, outSizeNew = OutSize; + if (inSize) + inSizeNew += (*inSize); + if (outSize) + outSizeNew += (*outSize); + if (SendRatio && _ratioProgress) + { + RINOK(_ratioProgress->SetRatioInfo(&inSizeNew, &outSizeNew)); + } + inSizeNew += ProgressOffset; + outSizeNew += ProgressOffset; + if (SendProgress) + return _progress->SetCompleted(_inSizeIsMain ? &inSizeNew : &outSizeNew); + return S_OK; +} + +HRESULT CLocalProgress::SetCur() +{ + return SetRatioInfo(NULL, NULL); +} diff --git a/CPP/7zip/Common/ProgressUtils.h b/CPP/7zip/Common/ProgressUtils.h new file mode 100755 index 0000000..c620484 --- /dev/null +++ b/CPP/7zip/Common/ProgressUtils.h @@ -0,0 +1,34 @@ +// ProgressUtils.h + +#ifndef __PROGRESSUTILS_H +#define __PROGRESSUTILS_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_IMP + + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); +}; + +#endif diff --git a/CPP/7zip/Common/RegisterArc.h b/CPP/7zip/Common/RegisterArc.h new file mode 100755 index 0000000..7066325 --- /dev/null +++ b/CPP/7zip/Common/RegisterArc.h @@ -0,0 +1,32 @@ +// RegisterArc.h + +#ifndef __REGISTER_ARC_H +#define __REGISTER_ARC_H + +#include "../Archive/IArchive.h" + +typedef IInArchive * (*CreateInArchiveP)(); +typedef IOutArchive * (*CreateOutArchiveP)(); + +struct CArcInfo +{ + const wchar_t *Name; + const wchar_t *Ext; + const wchar_t *AddExt; + Byte ClassId; + Byte Signature[16]; + int SignatureSize; + bool KeepName; + CreateInArchiveP CreateInArchive; + CreateOutArchiveP CreateOutArchive; +}; + +void RegisterArc(const CArcInfo *arcInfo); + +#define REGISTER_ARC_NAME(x) CRegister ## x + +#define REGISTER_ARC(x) struct REGISTER_ARC_NAME(x) { \ + REGISTER_ARC_NAME(x)() { RegisterArc(&g_ArcInfo); }}; \ + static REGISTER_ARC_NAME(x) g_RegisterArc; + +#endif diff --git a/CPP/7zip/Common/RegisterCodec.h b/CPP/7zip/Common/RegisterCodec.h new file mode 100755 index 0000000..c59ab66 --- /dev/null +++ b/CPP/7zip/Common/RegisterCodec.h @@ -0,0 +1,33 @@ +// RegisterCodec.h + +#ifndef __REGISTERCODEC_H +#define __REGISTERCODEC_H + +#include "../Common/MethodId.h" + +typedef void * (*CreateCodecP)(); +struct CCodecInfo +{ + CreateCodecP CreateDecoder; + CreateCodecP CreateEncoder; + CMethodId Id; + const wchar_t *Name; + UInt32 NumInStreams; + bool IsFilter; +}; + +void RegisterCodec(const CCodecInfo *codecInfo); + +#define REGISTER_CODEC_NAME(x) CRegisterCodec ## x + +#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(x) struct REGISTER_CODECS_NAME(x) { \ + REGISTER_CODECS_NAME(x)() { for (int i = 0; i < sizeof(g_CodecsInfo) / sizeof(g_CodecsInfo[0]); i++) \ + RegisterCodec(&g_CodecsInfo[i]); }}; \ + static REGISTER_CODECS_NAME(x) g_RegisterCodecs; + +#endif diff --git a/CPP/7zip/Common/StdAfx.h b/CPP/7zip/Common/StdAfx.h new file mode 100755 index 0000000..f56e92f --- /dev/null +++ b/CPP/7zip/Common/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../Common/MyWindows.h" +#include "../../Common/NewHandler.h" + +#endif diff --git a/CPP/7zip/Common/StreamBinder.cpp b/CPP/7zip/Common/StreamBinder.cpp new file mode 100755 index 0000000..cb3bf99 --- /dev/null +++ b/CPP/7zip/Common/StreamBinder.cpp @@ -0,0 +1,150 @@ +// StreamBinder.cpp + +#include "StdAfx.h" + +#include "StreamBinder.h" +#include "../../Common/Defs.h" +#include "../../Common/MyCom.h" + +using namespace NWindows; +using namespace NSynchronization; + +class CSequentialInStreamForBinder: + public ISequentialInStream, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); +private: + CStreamBinder *m_StreamBinder; +public: + ~CSequentialInStreamForBinder() { m_StreamBinder->CloseRead(); } + void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; } +}; + +STDMETHODIMP CSequentialInStreamForBinder::Read(void *data, UInt32 size, UInt32 *processedSize) + { return m_StreamBinder->Read(data, size, processedSize); } + +class CSequentialOutStreamForBinder: + public ISequentialOutStream, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + +private: + CStreamBinder *m_StreamBinder; +public: + ~CSequentialOutStreamForBinder() { m_StreamBinder->CloseWrite(); } + void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; } +}; + +STDMETHODIMP CSequentialOutStreamForBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) + { return m_StreamBinder->Write(data, size, processedSize); } + + +////////////////////////// +// CStreamBinder +// (_thereAreBytesToReadEvent && _bufferSize == 0) means that stream is finished. + +HRes CStreamBinder::CreateEvents() +{ + RINOK(_allBytesAreWritenEvent.Create(true)); + RINOK(_thereAreBytesToReadEvent.Create()); + return _readStreamIsClosedEvent.Create(); +} + +void CStreamBinder::ReInit() +{ + _thereAreBytesToReadEvent.Reset(); + _readStreamIsClosedEvent.Reset(); + ProcessedSize = 0; +} + + + +void CStreamBinder::CreateStreams(ISequentialInStream **inStream, + ISequentialOutStream **outStream) +{ + CSequentialInStreamForBinder *inStreamSpec = new + CSequentialInStreamForBinder; + CMyComPtr inStreamLoc(inStreamSpec); + inStreamSpec->SetBinder(this); + *inStream = inStreamLoc.Detach(); + + CSequentialOutStreamForBinder *outStreamSpec = new + CSequentialOutStreamForBinder; + CMyComPtr outStreamLoc(outStreamSpec); + outStreamSpec->SetBinder(this); + *outStream = outStreamLoc.Detach(); + + _buffer = NULL; + _bufferSize= 0; + ProcessedSize = 0; +} + +HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 sizeToRead = size; + if (size > 0) + { + RINOK(_thereAreBytesToReadEvent.Lock()); + sizeToRead = MyMin(_bufferSize, size); + if (_bufferSize > 0) + { + memcpy(data, _buffer, sizeToRead); + _buffer = ((const Byte *)_buffer) + sizeToRead; + _bufferSize -= sizeToRead; + if (_bufferSize == 0) + { + _thereAreBytesToReadEvent.Reset(); + _allBytesAreWritenEvent.Set(); + } + } + } + if (processedSize != NULL) + *processedSize = sizeToRead; + ProcessedSize += sizeToRead; + return S_OK; +} + +void CStreamBinder::CloseRead() +{ + _readStreamIsClosedEvent.Set(); +} + +HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if (size > 0) + { + _buffer = data; + _bufferSize = size; + _allBytesAreWritenEvent.Reset(); + _thereAreBytesToReadEvent.Set(); + + HANDLE events[2]; + events[0] = _allBytesAreWritenEvent; + events[1] = _readStreamIsClosedEvent; + DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE); + if (waitResult != WAIT_OBJECT_0 + 0) + { + // ReadingWasClosed = true; + return S_FALSE; + } + // if(!_allBytesAreWritenEvent.Lock()) + // return E_FAIL; + } + if (processedSize != NULL) + *processedSize = size; + return S_OK; +} + +void CStreamBinder::CloseWrite() +{ + // _bufferSize must be = 0 + _thereAreBytesToReadEvent.Set(); +} diff --git a/CPP/7zip/Common/StreamBinder.h b/CPP/7zip/Common/StreamBinder.h new file mode 100755 index 0000000..b5d6c0d --- /dev/null +++ b/CPP/7zip/Common/StreamBinder.h @@ -0,0 +1,32 @@ +// StreamBinder.h + +#ifndef __STREAMBINDER_H +#define __STREAMBINDER_H + +#include "../IStream.h" +#include "../../Windows/Synchronization.h" + +class CStreamBinder +{ + NWindows::NSynchronization::CManualResetEvent _allBytesAreWritenEvent; + NWindows::NSynchronization::CManualResetEvent _thereAreBytesToReadEvent; + NWindows::NSynchronization::CManualResetEvent _readStreamIsClosedEvent; + UInt32 _bufferSize; + const void *_buffer; +public: + // bool ReadingWasClosed; + UInt64 ProcessedSize; + CStreamBinder() {} + HRes CreateEvents(); + + void CreateStreams(ISequentialInStream **inStream, + ISequentialOutStream **outStream); + HRESULT Read(void *data, UInt32 size, UInt32 *processedSize); + void CloseRead(); + + HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize); + void CloseWrite(); + void ReInit(); +}; + +#endif diff --git a/CPP/7zip/Common/StreamObjects.cpp b/CPP/7zip/Common/StreamObjects.cpp new file mode 100755 index 0000000..a18f1bc --- /dev/null +++ b/CPP/7zip/Common/StreamObjects.cpp @@ -0,0 +1,221 @@ +// StreamObjects.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "StreamObjects.h" + +STDMETHODIMP CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (size == 0) + return S_OK; + if (_pos > _size) + return E_FAIL; + 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: _pos = offset; break; + case STREAM_SEEK_CUR: _pos += offset; break; + case STREAM_SEEK_END: _pos = _size + offset; break; + default: return STG_E_INVALIDFUNCTION; + } + if (newPosition) + *newPosition = _pos; + return S_OK; +} + +void CByteDynBuffer::Free() +{ + free(_buf); + _buf = 0; + _capacity = 0; +} + +bool CByteDynBuffer::EnsureCapacity(size_t cap) +{ + 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.SetCapacity(_size); + memcpy(dest, _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; + 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() +{ + MyFree(_tags); + _tags = 0; + MidFree(_data); + _data = 0; +} + +bool CCachedInStream::Alloc(unsigned blockSizeLog, unsigned numBlocksLog) +{ + 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) +{ + _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 E_FAIL; + + { + 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: _pos = offset; break; + case STREAM_SEEK_CUR: _pos = _pos + offset; break; + case STREAM_SEEK_END: _pos = _size + offset; break; + default: return STG_E_INVALIDFUNCTION; + } + if (newPosition != 0) + *newPosition = _pos; + return S_OK; +} diff --git a/CPP/7zip/Common/StreamObjects.h b/CPP/7zip/Common/StreamObjects.h new file mode 100755 index 0000000..ed1532c --- /dev/null +++ b/CPP/7zip/Common/StreamObjects.h @@ -0,0 +1,135 @@ +// StreamObjects.h + +#ifndef __STREAM_OBJECTS_H +#define __STREAM_OBJECTS_H + +#include "../../Common/Buffer.h" +#include "../../Common/MyCom.h" +#include "../IStream.h" + +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.GetCapacity(), ref); } + + MY_UNKNOWN_IMP1(IInStream) + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + +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(); + size_t GetCapacity() const { return _capacity; } + operator Byte*() const { return _buf; }; + operator const Byte*() const { return _buf; }; + bool EnsureCapacity(size_t capacity); +}; + +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_IMP + 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_IMP + 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_IMP + 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(); + bool Alloc(unsigned blockSizeLog, unsigned numBlocksLog); + void Init(UInt64 size); + + 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/CPP/7zip/Common/StreamUtils.cpp b/CPP/7zip/Common/StreamUtils.cpp new file mode 100755 index 0000000..57ff4ee --- /dev/null +++ b/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) +{ + 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) +{ + 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) +{ + 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) +{ + 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/CPP/7zip/Common/StreamUtils.h b/CPP/7zip/Common/StreamUtils.h new file mode 100755 index 0000000..30535ab --- /dev/null +++ b/CPP/7zip/Common/StreamUtils.h @@ -0,0 +1,13 @@ +// StreamUtils.h + +#ifndef __STREAMUTILS_H +#define __STREAMUTILS_H + +#include "../IStream.h" + +HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *size); +HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size); +HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size); +HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size); + +#endif diff --git a/CPP/7zip/Common/VirtThread.cpp b/CPP/7zip/Common/VirtThread.cpp new file mode 100755 index 0000000..c07caba --- /dev/null +++ b/CPP/7zip/Common/VirtThread.cpp @@ -0,0 +1,46 @@ +// 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->ExitEvent) + return 0; + t->Execute(); + t->FinishedEvent.Set(); + } +} + +WRes CVirtThread::Create() +{ + RINOK(StartEvent.CreateIfNotCreated()); + RINOK(FinishedEvent.CreateIfNotCreated()); + StartEvent.Reset(); + FinishedEvent.Reset(); + ExitEvent = false; + if (Thread.IsCreated()) + return S_OK; + return Thread.Create(CoderThread, this); +} + +void CVirtThread::Start() +{ + ExitEvent = false; + StartEvent.Set(); +} + +CVirtThread::~CVirtThread() +{ + ExitEvent = true; + if (StartEvent.IsCreated()) + StartEvent.Set(); + if (Thread.IsCreated()) + Thread.Wait(); +} + diff --git a/CPP/7zip/Common/VirtThread.h b/CPP/7zip/Common/VirtThread.h new file mode 100755 index 0000000..bfc10dc --- /dev/null +++ b/CPP/7zip/Common/VirtThread.h @@ -0,0 +1,23 @@ +// VirtThread.h + +#ifndef __VIRTTHREAD_H +#define __VIRTTHREAD_H + +#include "../../Windows/Synchronization.h" +#include "../../Windows/Thread.h" + +struct CVirtThread +{ + NWindows::NSynchronization::CAutoResetEvent StartEvent; + NWindows::NSynchronization::CAutoResetEvent FinishedEvent; + NWindows::CThread Thread; + bool ExitEvent; + + ~CVirtThread(); + WRes Create(); + void Start(); + void WaitFinish() { FinishedEvent.Lock(); } + virtual void Execute() = 0; +}; + +#endif diff --git a/CPP/7zip/Compress/ArjDecoder1.cpp b/CPP/7zip/Compress/ArjDecoder1.cpp new file mode 100755 index 0000000..9dff536 --- /dev/null +++ b/CPP/7zip/Compress/ArjDecoder1.cpp @@ -0,0 +1,309 @@ +// ArjDecoder1.cpp + +#include "StdAfx.h" + +#include "ArjDecoder1.h" + +namespace NCompress{ +namespace NArj { +namespace NDecoder1 { + +static const UInt32 kHistorySize = 26624; +static const UInt32 kMatchMinLen = 3; +static const UInt32 kMatchMaxLen = 256; + +// static const UInt32 kNC = 255 + kMatchMaxLen + 2 - kMatchMinLen; + +void CCoder::MakeTable(int nchar, Byte *bitlen, int tablebits, + UInt32 *table, int tablesize) +{ + UInt32 count[17], weight[17], start[18], *p; + UInt32 i, k, len, ch, jutbits, avail, nextcode, mask; + + for (i = 1; i <= 16; i++) + count[i] = 0; + for (i = 0; (int)i < nchar; i++) + count[bitlen[i]]++; + + start[1] = 0; + for (i = 1; i <= 16; i++) + start[i + 1] = start[i] + (count[i] << (16 - i)); + if (start[17] != (UInt32) (1 << 16)) + throw "Data error"; + + jutbits = 16 - tablebits; + for (i = 1; (int)i <= tablebits; i++) + { + start[i] >>= jutbits; + weight[i] = 1 << (tablebits - i); + } + while (i <= 16) + { + weight[i] = 1 << (16 - i); + i++; + } + + i = start[tablebits + 1] >> jutbits; + if (i != (UInt32) (1 << 16)) + { + k = 1 << tablebits; + while (i != k) + table[i++] = 0; + } + + avail = nchar; + mask = 1 << (15 - tablebits); + for (ch = 0; (int)ch < nchar; ch++) + { + if ((len = bitlen[ch]) == 0) + continue; + k = start[len]; + nextcode = k + weight[len]; + if ((int)len <= tablebits) + { + if (nextcode > (UInt32)tablesize) + throw "Data error"; + for (i = start[len]; i < nextcode; i++) + table[i] = ch; + } + else + { + p = &table[k >> jutbits]; + i = len - tablebits; + while (i != 0) + { + if (*p == 0) + { + right[avail] = left[avail] = 0; + *p = avail++; + } + if (k & mask) + p = &right[*p]; + else + p = &left[*p]; + k <<= 1; + i--; + } + *p = ch; + } + start[len] = nextcode; + } +} + +void CCoder::read_pt_len(int nn, int nbit, int i_special) +{ + UInt32 n = m_InBitStream.ReadBits(nbit); + if (n == 0) + { + UInt32 c = m_InBitStream.ReadBits(nbit); + int i; + for (i = 0; i < nn; i++) + pt_len[i] = 0; + for (i = 0; i < 256; i++) + pt_table[i] = c; + } + else + { + UInt32 i = 0; + while (i < n) + { + UInt32 bitBuf = m_InBitStream.GetValue(16); + int c = bitBuf >> 13; + if (c == 7) + { + UInt32 mask = 1 << (12); + while (mask & bitBuf) + { + mask >>= 1; + c++; + } + } + m_InBitStream.MovePos((c < 7) ? 3 : (int)(c - 3)); + pt_len[i++] = (Byte)c; + if (i == (UInt32)i_special) + { + c = m_InBitStream.ReadBits(2); + while (--c >= 0) + pt_len[i++] = 0; + } + } + while (i < (UInt32)nn) + pt_len[i++] = 0; + MakeTable(nn, pt_len, 8, pt_table, PTABLESIZE); + } +} + +void CCoder::read_c_len() +{ + int i, c, n; + UInt32 mask; + + n = m_InBitStream.ReadBits(CBIT); + if (n == 0) + { + c = m_InBitStream.ReadBits(CBIT); + for (i = 0; i < NC; i++) + c_len[i] = 0; + for (i = 0; i < CTABLESIZE; i++) + c_table[i] = c; + } + else + { + i = 0; + while (i < n) + { + UInt32 bitBuf = m_InBitStream.GetValue(16); + c = pt_table[bitBuf >> (8)]; + if (c >= NT) + { + mask = 1 << (7); + do + { + if (bitBuf & mask) + c = right[c]; + else + c = left[c]; + mask >>= 1; + } while (c >= NT); + } + m_InBitStream.MovePos((int)(pt_len[c])); + if (c <= 2) + { + if (c == 0) + c = 1; + else if (c == 1) + c = m_InBitStream.ReadBits(4) + 3; + else + c = m_InBitStream.ReadBits(CBIT) + 20; + while (--c >= 0) + c_len[i++] = 0; + } + else + c_len[i++] = (Byte)(c - 2); + } + while (i < NC) + c_len[i++] = 0; + MakeTable(NC, c_len, 12, c_table, CTABLESIZE); + } +} + +UInt32 CCoder::decode_c() +{ + UInt32 j, mask; + UInt32 bitbuf = m_InBitStream.GetValue(16); + j = c_table[bitbuf >> 4]; + if (j >= NC) + { + mask = 1 << (3); + do + { + if (bitbuf & mask) + j = right[j]; + else + j = left[j]; + mask >>= 1; + } while (j >= NC); + } + m_InBitStream.MovePos((int)(c_len[j])); + return j; +} + +UInt32 CCoder::decode_p() +{ + UInt32 j, mask; + UInt32 bitbuf = m_InBitStream.GetValue(16); + j = pt_table[bitbuf >> (8)]; + if (j >= NP) + { + mask = 1 << (7); + do + { + if (bitbuf & mask) + j = right[j]; + else + j = left[j]; + mask >>= 1; + } while (j >= NP); + } + m_InBitStream.MovePos((int)(pt_len[j])); + if (j != 0) + { + j--; + j = (1 << j) + m_InBitStream.ReadBits((int)j); + } + return j; +} + + +HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + if (outSize == NULL) + return E_INVALIDARG; + + if (!m_OutWindowStream.Create(kHistorySize)) + return E_OUTOFMEMORY; + if (!m_InBitStream.Create(1 << 20)) + return E_OUTOFMEMORY; + + // check it + for (int i = 0; i < CTABLESIZE; i++) + c_table[i] = 0; + + UInt64 pos = 0; + m_OutWindowStream.SetStream(outStream); + m_OutWindowStream.Init(false); + m_InBitStream.SetStream(inStream); + m_InBitStream.Init(); + + CCoderReleaser coderReleaser(this); + + UInt32 blockSize = 0; + + while(pos < *outSize) + { + if (blockSize == 0) + { + if (progress != NULL) + { + UInt64 packSize = m_InBitStream.GetProcessedSize(); + RINOK(progress->SetRatioInfo(&packSize, &pos)); + } + blockSize = m_InBitStream.ReadBits(16); + read_pt_len(NT, TBIT, 3); + read_c_len(); + read_pt_len(NP, PBIT, -1); + } + blockSize--; + + UInt32 number = decode_c(); + if (number < 256) + { + m_OutWindowStream.PutByte((Byte)number); + pos++; + continue; + } + else + { + UInt32 len = number - 256 + kMatchMinLen; + UInt32 distance = decode_p(); + if (distance >= pos) + return S_FALSE; + m_OutWindowStream.CopyBlock(distance, len); + pos += len; + } + } + coderReleaser.NeedFlush = false; + return m_OutWindowStream.Flush(); +} + +STDMETHODIMP CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + try { return CodeReal(inStream, outStream, inSize, outSize, progress);} + catch(const CInBufferException &e) { return e.ErrorCode; } + catch(const CLzOutWindowException &e) { return e.ErrorCode; } + catch(...) { return S_FALSE; } +} + +}}} diff --git a/CPP/7zip/Compress/ArjDecoder1.h b/CPP/7zip/Compress/ArjDecoder1.h new file mode 100755 index 0000000..f33cb36 --- /dev/null +++ b/CPP/7zip/Compress/ArjDecoder1.h @@ -0,0 +1,98 @@ +// ArjDecoder1.h + +#ifndef __COMPRESS_ARJ_DECODER1_H +#define __COMPRESS_ARJ_DECODER1_H + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +#include "../Common/InBuffer.h" + +#include "BitmDecoder.h" +#include "LzOutWindow.h" + +namespace NCompress { +namespace NArj { +namespace NDecoder1 { + +#define CODE_BIT 16 + +#define THRESHOLD 3 +#define DDICSIZ 26624 +#define MAXDICBIT 16 +#define MATCHBIT 8 +#define MAXMATCH 256 +#define NC (0xFF + MAXMATCH + 2 - THRESHOLD) +#define NP (MAXDICBIT + 1) +#define CBIT 9 +#define NT (CODE_BIT + 3) +#define PBIT 5 +#define TBIT 5 + +#if NT > NP +#define NPT NT +#else +#define NPT NP +#endif + +#define CTABLESIZE 4096 +#define PTABLESIZE 256 + + +class CCoder : + public ICompressCoder, + public CMyUnknownImp +{ + CLzOutWindow m_OutWindowStream; + NBitm::CDecoder m_InBitStream; + + UInt32 left[2 * NC - 1]; + UInt32 right[2 * NC - 1]; + Byte c_len[NC]; + Byte pt_len[NPT]; + + UInt32 c_table[CTABLESIZE]; + UInt32 pt_table[PTABLESIZE]; + + void ReleaseStreams() + { + m_OutWindowStream.ReleaseStream(); + m_InBitStream.ReleaseStream(); + } + + class CCoderReleaser + { + CCoder *m_Coder; + public: + bool NeedFlush; + CCoderReleaser(CCoder *coder): m_Coder(coder), NeedFlush(true) {} + ~CCoderReleaser() + { + if (NeedFlush) + m_Coder->m_OutWindowStream.Flush(); + m_Coder->ReleaseStreams(); + } + }; + friend class CCoderReleaser; + + void MakeTable(int nchar, Byte *bitlen, int tablebits, UInt32 *table, int tablesize); + + void read_c_len(); + void read_pt_len(int nn, int nbit, int i_special); + UInt32 decode_c(); + UInt32 decode_p(); + + HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); +public: + MY_UNKNOWN_IMP + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + +}; + +}}} + +#endif diff --git a/CPP/7zip/Compress/ArjDecoder2.cpp b/CPP/7zip/Compress/ArjDecoder2.cpp new file mode 100755 index 0000000..9cde081 --- /dev/null +++ b/CPP/7zip/Compress/ArjDecoder2.cpp @@ -0,0 +1,90 @@ +// ArjDecoder2.cpp + +#include "StdAfx.h" + +#include "ArjDecoder2.h" + +namespace NCompress{ +namespace NArj { +namespace NDecoder2 { + +static const UInt32 kHistorySize = 26624; +static const UInt32 kMatchMinLen = 3; + +HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo * /* progress */) +{ + if (outSize == NULL) + return E_INVALIDARG; + + if (!m_OutWindowStream.Create(kHistorySize)) + return E_OUTOFMEMORY; + if (!m_InBitStream.Create(1 << 20)) + return E_OUTOFMEMORY; + + UInt64 pos = 0; + m_OutWindowStream.SetStream(outStream); + m_OutWindowStream.Init(false); + m_InBitStream.SetStream(inStream); + m_InBitStream.Init(); + CCoderReleaser coderReleaser(this); + + while(pos < *outSize) + { + const UInt32 kStartWidth = 0; + const UInt32 kStopWidth = 7; + UInt32 power = 1 << kStartWidth; + UInt32 width; + UInt32 len = 0; + for (width = kStartWidth; width < kStopWidth; width++) + { + if (m_InBitStream.ReadBits(1) == 0) + break; + len += power; + power <<= 1; + } + if (width != 0) + len += m_InBitStream.ReadBits(width); + if (len == 0) + { + m_OutWindowStream.PutByte((Byte)m_InBitStream.ReadBits(8)); + pos++; + continue; + } + else + { + len = len - 1 + kMatchMinLen; + const UInt32 kStartWidth = 9; + const UInt32 kStopWidth = 13; + UInt32 power = 1 << kStartWidth; + UInt32 width; + UInt32 distance = 0; + for (width = kStartWidth; width < kStopWidth; width++) + { + if (m_InBitStream.ReadBits(1) == 0) + break; + distance += power; + power <<= 1; + } + if (width != 0) + distance += m_InBitStream.ReadBits(width); + if (distance >= pos) + return S_FALSE; + m_OutWindowStream.CopyBlock(distance, len); + pos += len; + } + } + coderReleaser.NeedFlush = false; + return m_OutWindowStream.Flush(); +} + +STDMETHODIMP CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + try { return CodeReal(inStream, outStream, inSize, outSize, progress);} + catch(const CInBufferException &e) { return e.ErrorCode; } + catch(const CLzOutWindowException &e) { return e.ErrorCode; } + catch(...) { return S_FALSE; } +} + +}}} diff --git a/CPP/7zip/Compress/ArjDecoder2.h b/CPP/7zip/Compress/ArjDecoder2.h new file mode 100755 index 0000000..4e947e2 --- /dev/null +++ b/CPP/7zip/Compress/ArjDecoder2.h @@ -0,0 +1,59 @@ +// ArjDecoder2.h + +#ifndef __COMPRESS_ARJ_DECODER2_H +#define __COMPRESS_ARJ_DECODER2_H + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +#include "../Common/InBuffer.h" + +#include "BitmDecoder.h" +#include "LzOutWindow.h" + +namespace NCompress { +namespace NArj { +namespace NDecoder2 { + +class CCoder : + public ICompressCoder, + public CMyUnknownImp +{ + CLzOutWindow m_OutWindowStream; + NBitm::CDecoder m_InBitStream; + + void ReleaseStreams() + { + m_OutWindowStream.ReleaseStream(); + m_InBitStream.ReleaseStream(); + } + + class CCoderReleaser + { + CCoder *m_Coder; + public: + bool NeedFlush; + CCoderReleaser(CCoder *coder): m_Coder(coder), NeedFlush(true) {} + ~CCoderReleaser() + { + if (NeedFlush) + m_Coder->m_OutWindowStream.Flush(); + m_Coder->ReleaseStreams(); + } + }; + friend class CCoderReleaser; + + HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); +public: + MY_UNKNOWN_IMP + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + +}; + +}}} + +#endif diff --git a/CPP/7zip/Compress/BZip2Const.h b/CPP/7zip/Compress/BZip2Const.h new file mode 100755 index 0000000..fe0c53f --- /dev/null +++ b/CPP/7zip/Compress/BZip2Const.h @@ -0,0 +1,54 @@ +// Compress/BZip2Const.h + +#ifndef __COMPRESS_BZIP2_CONST_H +#define __COMPRESS_BZIP2_CONST_H + +namespace NCompress { +namespace NBZip2 { + +const Byte kArSig0 = 'B'; +const Byte kArSig1 = 'Z'; +const Byte kArSig2 = 'h'; +const Byte kArSig3 = '0'; + +const Byte kFinSig0 = 0x17; +const Byte kFinSig1 = 0x72; +const Byte kFinSig2 = 0x45; +const Byte kFinSig3 = 0x38; +const Byte kFinSig4 = 0x50; +const Byte kFinSig5 = 0x90; + +const Byte kBlockSig0 = 0x31; +const Byte kBlockSig1 = 0x41; +const Byte kBlockSig2 = 0x59; +const Byte kBlockSig3 = 0x26; +const Byte kBlockSig4 = 0x53; +const Byte kBlockSig5 = 0x59; + +const int kNumOrigBits = 24; + +const int kNumTablesBits = 3; +const int kNumTablesMin = 2; +const int kNumTablesMax = 6; + +const int kNumLevelsBits = 5; + +const int kMaxHuffmanLen = 20; // Check it + +const int kMaxAlphaSize = 258; + +const int kGroupSize = 50; + +const int kBlockSizeMultMin = 1; +const int kBlockSizeMultMax = 9; +const UInt32 kBlockSizeStep = 100000; +const UInt32 kBlockSizeMax = kBlockSizeMultMax * kBlockSizeStep; + +const int kNumSelectorsBits = 15; +const UInt32 kNumSelectorsMax = (2 + (kBlockSizeMax / kGroupSize)); + +const int kRleModeRepSize = 4; + +}} + +#endif diff --git a/CPP/7zip/Compress/BZip2Crc.cpp b/CPP/7zip/Compress/BZip2Crc.cpp new file mode 100755 index 0000000..2a8277c --- /dev/null +++ b/CPP/7zip/Compress/BZip2Crc.cpp @@ -0,0 +1,26 @@ +// BZip2Crc.cpp + +#include "StdAfx.h" + +#include "BZip2Crc.h" + +UInt32 CBZip2Crc::Table[256]; + +static const UInt32 kBZip2CrcPoly = 0x04c11db7; /* AUTODIN II, Ethernet, & FDDI */ + +void CBZip2Crc::InitTable() +{ + for (UInt32 i = 0; i < 256; i++) + { + UInt32 r = (i << 24); + for (int j = 8; j > 0; j--) + r = (r & 0x80000000) ? ((r << 1) ^ kBZip2CrcPoly) : (r << 1); + Table[i] = r; + } +} + +class CBZip2CrcTableInit +{ +public: + CBZip2CrcTableInit() { CBZip2Crc::InitTable(); } +} g_BZip2CrcTableInit; diff --git a/CPP/7zip/Compress/BZip2Crc.h b/CPP/7zip/Compress/BZip2Crc.h new file mode 100755 index 0000000..ad1322f --- /dev/null +++ b/CPP/7zip/Compress/BZip2Crc.h @@ -0,0 +1,31 @@ +// BZip2Crc.h + +#ifndef __BZIP2_CRC_H +#define __BZIP2_CRC_H + +#include "Common/Types.h" + +class CBZip2Crc +{ + UInt32 _value; + static UInt32 Table[256]; +public: + static void InitTable(); + CBZip2Crc(): _value(0xFFFFFFFF) {}; + void Init() { _value = 0xFFFFFFFF; } + void UpdateByte(Byte b) { _value = Table[(_value >> 24) ^ b] ^ (_value << 8); } + void UpdateByte(unsigned int b) { _value = Table[(_value >> 24) ^ b] ^ (_value << 8); } + UInt32 GetDigest() const { return _value ^ 0xFFFFFFFF; } +}; + +class CBZip2CombinedCrc +{ + UInt32 _value; +public: + CBZip2CombinedCrc(): _value(0){}; + void Init() { _value = 0; } + void Update(UInt32 v) { _value = ((_value << 1) | (_value >> 31)) ^ v; } + UInt32 GetDigest() const { return _value ; } +}; + +#endif diff --git a/CPP/7zip/Compress/BZip2Decoder.cpp b/CPP/7zip/Compress/BZip2Decoder.cpp new file mode 100755 index 0000000..b2bebb3 --- /dev/null +++ b/CPP/7zip/Compress/BZip2Decoder.cpp @@ -0,0 +1,943 @@ +// BZip2Decoder.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "BZip2Decoder.h" +#include "Mtf8.h" + +namespace NCompress { +namespace NBZip2 { + +#undef NO_INLINE +#define NO_INLINE + +static const UInt32 kNumThreadsMax = 4; + +static const UInt32 kBufferSize = (1 << 17); + +static const UInt16 kRandNums[512] = { + 619, 720, 127, 481, 931, 816, 813, 233, 566, 247, + 985, 724, 205, 454, 863, 491, 741, 242, 949, 214, + 733, 859, 335, 708, 621, 574, 73, 654, 730, 472, + 419, 436, 278, 496, 867, 210, 399, 680, 480, 51, + 878, 465, 811, 169, 869, 675, 611, 697, 867, 561, + 862, 687, 507, 283, 482, 129, 807, 591, 733, 623, + 150, 238, 59, 379, 684, 877, 625, 169, 643, 105, + 170, 607, 520, 932, 727, 476, 693, 425, 174, 647, + 73, 122, 335, 530, 442, 853, 695, 249, 445, 515, + 909, 545, 703, 919, 874, 474, 882, 500, 594, 612, + 641, 801, 220, 162, 819, 984, 589, 513, 495, 799, + 161, 604, 958, 533, 221, 400, 386, 867, 600, 782, + 382, 596, 414, 171, 516, 375, 682, 485, 911, 276, + 98, 553, 163, 354, 666, 933, 424, 341, 533, 870, + 227, 730, 475, 186, 263, 647, 537, 686, 600, 224, + 469, 68, 770, 919, 190, 373, 294, 822, 808, 206, + 184, 943, 795, 384, 383, 461, 404, 758, 839, 887, + 715, 67, 618, 276, 204, 918, 873, 777, 604, 560, + 951, 160, 578, 722, 79, 804, 96, 409, 713, 940, + 652, 934, 970, 447, 318, 353, 859, 672, 112, 785, + 645, 863, 803, 350, 139, 93, 354, 99, 820, 908, + 609, 772, 154, 274, 580, 184, 79, 626, 630, 742, + 653, 282, 762, 623, 680, 81, 927, 626, 789, 125, + 411, 521, 938, 300, 821, 78, 343, 175, 128, 250, + 170, 774, 972, 275, 999, 639, 495, 78, 352, 126, + 857, 956, 358, 619, 580, 124, 737, 594, 701, 612, + 669, 112, 134, 694, 363, 992, 809, 743, 168, 974, + 944, 375, 748, 52, 600, 747, 642, 182, 862, 81, + 344, 805, 988, 739, 511, 655, 814, 334, 249, 515, + 897, 955, 664, 981, 649, 113, 974, 459, 893, 228, + 433, 837, 553, 268, 926, 240, 102, 654, 459, 51, + 686, 754, 806, 760, 493, 403, 415, 394, 687, 700, + 946, 670, 656, 610, 738, 392, 760, 799, 887, 653, + 978, 321, 576, 617, 626, 502, 894, 679, 243, 440, + 680, 879, 194, 572, 640, 724, 926, 56, 204, 700, + 707, 151, 457, 449, 797, 195, 791, 558, 945, 679, + 297, 59, 87, 824, 713, 663, 412, 693, 342, 606, + 134, 108, 571, 364, 631, 212, 174, 643, 304, 329, + 343, 97, 430, 751, 497, 314, 983, 374, 822, 928, + 140, 206, 73, 263, 980, 736, 876, 478, 430, 305, + 170, 514, 364, 692, 829, 82, 855, 953, 676, 246, + 369, 970, 294, 750, 807, 827, 150, 790, 288, 923, + 804, 378, 215, 828, 592, 281, 565, 555, 710, 82, + 896, 831, 547, 261, 524, 462, 293, 465, 502, 56, + 661, 821, 976, 991, 658, 869, 905, 758, 745, 193, + 768, 550, 608, 933, 378, 286, 215, 979, 792, 961, + 61, 688, 793, 644, 986, 403, 106, 366, 905, 644, + 372, 567, 466, 434, 645, 210, 389, 550, 919, 135, + 780, 773, 635, 389, 707, 100, 626, 958, 165, 504, + 920, 176, 193, 713, 857, 265, 203, 50, 668, 108, + 645, 990, 626, 197, 510, 357, 358, 850, 858, 364, + 936, 638 +}; + +bool CState::Alloc() +{ + if (!Counters) + Counters = (UInt32 *)::BigAlloc((256 + kBlockSizeMax) * sizeof(UInt32)); + return (Counters != 0); +} + +void CState::Free() +{ + ::BigFree(Counters); + Counters = 0; +} + +UInt32 CDecoder::ReadBits(unsigned numBits) { return m_InStream.ReadBits(numBits); } +Byte CDecoder::ReadByte() {return (Byte)ReadBits(8); } +bool CDecoder::ReadBit() { return ReadBits(1) != 0; } + +UInt32 CDecoder::ReadCrc() +{ + UInt32 crc = 0; + for (int i = 0; i < 4; i++) + { + crc <<= 8; + crc |= ReadByte(); + } + return crc; +} + +static UInt32 NO_INLINE ReadBits(NBitm::CDecoder *m_InStream, unsigned num) +{ + return m_InStream->ReadBits(num); +} + +static UInt32 NO_INLINE ReadBit(NBitm::CDecoder *m_InStream) +{ + return m_InStream->ReadBits(1); +} + +static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder *m_InStream, + UInt32 *CharCounters, UInt32 blockSizeMax, Byte *m_Selectors, CHuffmanDecoder *m_HuffmanDecoders, + UInt32 *blockSizeRes, UInt32 *origPtrRes, bool *randRes) +{ + if (randRes) + *randRes = ReadBit(m_InStream) ? true : false; + *origPtrRes = ReadBits(m_InStream, kNumOrigBits); + + // in original code it compares OrigPtr to (UInt32)(10 + blockSizeMax)) : why ? + if (*origPtrRes >= blockSizeMax) + return S_FALSE; + + CMtf8Decoder mtf; + mtf.StartInit(); + + int numInUse = 0; + { + Byte inUse16[16]; + int i; + for (i = 0; i < 16; i++) + inUse16[i] = (Byte)ReadBit(m_InStream); + for (i = 0; i < 256; i++) + if (inUse16[i >> 4]) + { + if (ReadBit(m_InStream)) + mtf.Add(numInUse++, (Byte)i); + } + if (numInUse == 0) + return S_FALSE; + // mtf.Init(numInUse); + } + int alphaSize = numInUse + 2; + + int numTables = ReadBits(m_InStream, kNumTablesBits); + if (numTables < kNumTablesMin || numTables > kNumTablesMax) + return S_FALSE; + + UInt32 numSelectors = ReadBits(m_InStream, kNumSelectorsBits); + if (numSelectors < 1 || numSelectors > kNumSelectorsMax) + return S_FALSE; + + { + Byte mtfPos[kNumTablesMax]; + int t = 0; + do + mtfPos[t] = (Byte)t; + while(++t < numTables); + UInt32 i = 0; + do + { + int j = 0; + while (ReadBit(m_InStream)) + if (++j >= numTables) + return S_FALSE; + Byte tmp = mtfPos[j]; + for (;j > 0; j--) + mtfPos[j] = mtfPos[j - 1]; + m_Selectors[i] = mtfPos[0] = tmp; + } + while(++i < numSelectors); + } + + int t = 0; + do + { + Byte lens[kMaxAlphaSize]; + int len = (int)ReadBits(m_InStream, kNumLevelsBits); + int i; + for (i = 0; i < alphaSize; i++) + { + for (;;) + { + if (len < 1 || len > kMaxHuffmanLen) + return S_FALSE; + if (!ReadBit(m_InStream)) + break; + len += 1 - (int)(ReadBit(m_InStream) << 1); + } + lens[i] = (Byte)len; + } + for (; i < kMaxAlphaSize; i++) + lens[i] = 0; + if(!m_HuffmanDecoders[t].SetCodeLengths(lens)) + return S_FALSE; + } + while(++t < numTables); + + { + for (int i = 0; i < 256; i++) + CharCounters[i] = 0; + } + + UInt32 blockSize = 0; + { + UInt32 groupIndex = 0; + UInt32 groupSize = 0; + CHuffmanDecoder *huffmanDecoder = 0; + int runPower = 0; + UInt32 runCounter = 0; + + for (;;) + { + if (groupSize == 0) + { + if (groupIndex >= numSelectors) + return S_FALSE; + groupSize = kGroupSize; + huffmanDecoder = &m_HuffmanDecoders[m_Selectors[groupIndex++]]; + } + groupSize--; + + UInt32 nextSym = huffmanDecoder->DecodeSymbol(m_InStream); + + if (nextSym < 2) + { + runCounter += ((UInt32)(nextSym + 1) << runPower++); + if (blockSizeMax - blockSize < runCounter) + return S_FALSE; + continue; + } + if (runCounter != 0) + { + UInt32 b = (UInt32)mtf.GetHead(); + CharCounters[b] += runCounter; + do + CharCounters[256 + blockSize++] = b; + while(--runCounter != 0); + runPower = 0; + } + if (nextSym <= (UInt32)numInUse) + { + UInt32 b = (UInt32)mtf.GetAndMove((int)nextSym - 1); + if (blockSize >= blockSizeMax) + return S_FALSE; + CharCounters[b]++; + CharCounters[256 + blockSize++] = b; + } + else if (nextSym == (UInt32)numInUse + 1) + break; + else + return S_FALSE; + } + } + *blockSizeRes = blockSize; + return (*origPtrRes < blockSize) ? S_OK : S_FALSE; +} + +static void NO_INLINE DecodeBlock1(UInt32 *charCounters, UInt32 blockSize) +{ + { + UInt32 sum = 0; + for (UInt32 i = 0; i < 256; i++) + { + sum += charCounters[i]; + charCounters[i] = sum - charCounters[i]; + } + } + + UInt32 *tt = charCounters + 256; + // Compute the T^(-1) vector + UInt32 i = 0; + do + tt[charCounters[tt[i] & 0xFF]++] |= (i << 8); + while(++i < blockSize); +} + +static UInt32 NO_INLINE DecodeBlock2(const UInt32 *tt, UInt32 blockSize, UInt32 OrigPtr, COutBuffer &m_OutStream) +{ + CBZip2Crc crc; + + // it's for speed optimization: prefetch & prevByte_init; + UInt32 tPos = tt[tt[OrigPtr] >> 8]; + unsigned prevByte = (unsigned)(tPos & 0xFF); + + unsigned numReps = 0; + + do + { + unsigned b = (unsigned)(tPos & 0xFF); + tPos = tt[tPos >> 8]; + + if (numReps == kRleModeRepSize) + { + for (; b > 0; b--) + { + crc.UpdateByte(prevByte); + m_OutStream.WriteByte((Byte)prevByte); + } + numReps = 0; + continue; + } + if (b != prevByte) + numReps = 0; + numReps++; + prevByte = b; + crc.UpdateByte(b); + m_OutStream.WriteByte((Byte)b); + + /* + prevByte = b; + crc.UpdateByte(b); + m_OutStream.WriteByte((Byte)b); + for (; --blockSize != 0;) + { + b = (unsigned)(tPos & 0xFF); + tPos = tt[tPos >> 8]; + crc.UpdateByte(b); + m_OutStream.WriteByte((Byte)b); + if (b != prevByte) + { + prevByte = b; + continue; + } + if (--blockSize == 0) + break; + + b = (unsigned)(tPos & 0xFF); + tPos = tt[tPos >> 8]; + crc.UpdateByte(b); + m_OutStream.WriteByte((Byte)b); + if (b != prevByte) + { + prevByte = b; + continue; + } + if (--blockSize == 0) + break; + + b = (unsigned)(tPos & 0xFF); + tPos = tt[tPos >> 8]; + crc.UpdateByte(b); + m_OutStream.WriteByte((Byte)b); + if (b != prevByte) + { + prevByte = b; + continue; + } + --blockSize; + break; + } + if (blockSize == 0) + break; + + b = (unsigned)(tPos & 0xFF); + tPos = tt[tPos >> 8]; + + for (; b > 0; b--) + { + crc.UpdateByte(prevByte); + m_OutStream.WriteByte((Byte)prevByte); + } + */ + } + while(--blockSize != 0); + return crc.GetDigest(); +} + +static UInt32 NO_INLINE DecodeBlock2Rand(const UInt32 *tt, UInt32 blockSize, UInt32 OrigPtr, COutBuffer &m_OutStream) +{ + CBZip2Crc crc; + + UInt32 randIndex = 1; + UInt32 randToGo = kRandNums[0] - 2; + + unsigned numReps = 0; + + // it's for speed optimization: prefetch & prevByte_init; + UInt32 tPos = tt[tt[OrigPtr] >> 8]; + unsigned prevByte = (unsigned)(tPos & 0xFF); + + do + { + unsigned b = (unsigned)(tPos & 0xFF); + tPos = tt[tPos >> 8]; + + { + if (randToGo == 0) + { + b ^= 1; + randToGo = kRandNums[randIndex++]; + randIndex &= 0x1FF; + } + randToGo--; + } + + if (numReps == kRleModeRepSize) + { + for (; b > 0; b--) + { + crc.UpdateByte(prevByte); + m_OutStream.WriteByte((Byte)prevByte); + } + numReps = 0; + continue; + } + if (b != prevByte) + numReps = 0; + numReps++; + prevByte = b; + crc.UpdateByte(b); + m_OutStream.WriteByte((Byte)b); + } + while(--blockSize != 0); + return crc.GetDigest(); +} + + +CDecoder::CDecoder() +{ + #ifndef _7ZIP_ST + m_States = 0; + m_NumThreadsPrev = 0; + NumThreads = 1; + #endif + _needInStreamInit = true; +} + +#ifndef _7ZIP_ST + +CDecoder::~CDecoder() +{ + Free(); +} + +#define RINOK_THREAD(x) { WRes __result_ = (x); if(__result_ != 0) return __result_; } + +HRESULT CDecoder::Create() +{ + RINOK_THREAD(CanProcessEvent.CreateIfNotCreated()); + RINOK_THREAD(CanStartWaitingEvent.CreateIfNotCreated()); + if (m_States != 0 && m_NumThreadsPrev == NumThreads) + return S_OK; + Free(); + MtMode = (NumThreads > 1); + m_NumThreadsPrev = NumThreads; + try + { + m_States = new CState[NumThreads]; + if (!m_States) + return E_OUTOFMEMORY; + } + catch(...) { return E_OUTOFMEMORY; } + for (UInt32 t = 0; t < NumThreads; t++) + { + CState &ti = m_States[t]; + ti.Decoder = this; + if (MtMode) + { + HRESULT res = ti.Create(); + if (res != S_OK) + { + NumThreads = t; + Free(); + return res; + } + } + } + return S_OK; +} + +void CDecoder::Free() +{ + if (!m_States) + return; + CloseThreads = true; + CanProcessEvent.Set(); + for (UInt32 t = 0; t < NumThreads; t++) + { + CState &s = m_States[t]; + if (MtMode) + s.Thread.Wait(); + s.Free(); + } + delete []m_States; + m_States = 0; +} + +#endif + +HRESULT CDecoder::ReadSignatures(bool &wasFinished, UInt32 &crc) +{ + wasFinished = false; + Byte s[6]; + for (int i = 0; i < 6; i++) + s[i] = ReadByte(); + crc = ReadCrc(); + if (s[0] == kFinSig0) + { + if (s[1] != kFinSig1 || + s[2] != kFinSig2 || + s[3] != kFinSig3 || + s[4] != kFinSig4 || + s[5] != kFinSig5) + return S_FALSE; + + wasFinished = true; + return (crc == CombinedCrc.GetDigest()) ? S_OK : S_FALSE; + } + if (s[0] != kBlockSig0 || + s[1] != kBlockSig1 || + s[2] != kBlockSig2 || + s[3] != kBlockSig3 || + s[4] != kBlockSig4 || + s[5] != kBlockSig5) + return S_FALSE; + CombinedCrc.Update(crc); + return S_OK; +} + +HRESULT CDecoder::DecodeFile(bool &isBZ, ICompressProgressInfo *progress) +{ + Progress = progress; + #ifndef _7ZIP_ST + RINOK(Create()); + for (UInt32 t = 0; t < NumThreads; t++) + { + CState &s = m_States[t]; + if (!s.Alloc()) + return E_OUTOFMEMORY; + if (MtMode) + { + RINOK(s.StreamWasFinishedEvent.Reset()); + RINOK(s.WaitingWasStartedEvent.Reset()); + RINOK(s.CanWriteEvent.Reset()); + } + } + #else + if (!m_States[0].Alloc()) + return E_OUTOFMEMORY; + #endif + + isBZ = false; + Byte s[6]; + int i; + for (i = 0; i < 4; i++) + s[i] = ReadByte(); + if (s[0] != kArSig0 || + s[1] != kArSig1 || + s[2] != kArSig2 || + s[3] <= kArSig3 || + s[3] > kArSig3 + kBlockSizeMultMax) + return S_OK; + isBZ = true; + UInt32 dicSize = (UInt32)(s[3] - kArSig3) * kBlockSizeStep; + + CombinedCrc.Init(); + #ifndef _7ZIP_ST + if (MtMode) + { + NextBlockIndex = 0; + StreamWasFinished1 = StreamWasFinished2 = false; + CloseThreads = false; + CanStartWaitingEvent.Reset(); + m_States[0].CanWriteEvent.Set(); + BlockSizeMax = dicSize; + Result1 = Result2 = S_OK; + CanProcessEvent.Set(); + UInt32 t; + for (t = 0; t < NumThreads; t++) + m_States[t].StreamWasFinishedEvent.Lock(); + CanProcessEvent.Reset(); + CanStartWaitingEvent.Set(); + for (t = 0; t < NumThreads; t++) + m_States[t].WaitingWasStartedEvent.Lock(); + CanStartWaitingEvent.Reset(); + RINOK(Result2); + RINOK(Result1); + } + else + #endif + { + CState &state = m_States[0]; + for (;;) + { + RINOK(SetRatioProgress(m_InStream.GetProcessedSize())); + bool wasFinished; + UInt32 crc; + RINOK(ReadSignatures(wasFinished, crc)); + if (wasFinished) + return S_OK; + + UInt32 blockSize, origPtr; + bool randMode; + RINOK(ReadBlock(&m_InStream, state.Counters, dicSize, + m_Selectors, m_HuffmanDecoders, + &blockSize, &origPtr, &randMode)); + DecodeBlock1(state.Counters, blockSize); + if ((randMode ? + DecodeBlock2Rand(state.Counters + 256, blockSize, origPtr, m_OutStream) : + DecodeBlock2(state.Counters + 256, blockSize, origPtr, m_OutStream)) != crc) + return S_FALSE; + } + } + return SetRatioProgress(m_InStream.GetProcessedSize()); +} + +HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + bool &isBZ, ICompressProgressInfo *progress) +{ + isBZ = false; + try + { + + if (!m_InStream.Create(kBufferSize)) + return E_OUTOFMEMORY; + if (!m_OutStream.Create(kBufferSize)) + return E_OUTOFMEMORY; + + if (inStream) + m_InStream.SetStream(inStream); + + CDecoderFlusher flusher(this, inStream != NULL); + + if (_needInStreamInit) + { + m_InStream.Init(); + _needInStreamInit = false; + } + _inStart = m_InStream.GetProcessedSize(); + + m_InStream.AlignToByte(); + + m_OutStream.SetStream(outStream); + m_OutStream.Init(); + + RINOK(DecodeFile(isBZ, progress)); + flusher.NeedFlush = false; + return Flush(); + + } + catch(const CInBufferException &e) { return e.ErrorCode; } + catch(const COutBufferException &e) { return e.ErrorCode; } + catch(...) { return E_FAIL; } +} + +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) +{ + _needInStreamInit = true; + bool isBZ; + RINOK(CodeReal(inStream, outStream, isBZ, progress)); + return isBZ ? S_OK : S_FALSE; +} + +HRESULT CDecoder::CodeResume(ISequentialOutStream *outStream, bool &isBZ, ICompressProgressInfo *progress) +{ + return CodeReal(NULL, outStream, isBZ, progress); +} + +STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { m_InStream.SetStream(inStream); return S_OK; } +STDMETHODIMP CDecoder::ReleaseInStream() { m_InStream.ReleaseStream(); return S_OK; } + +#ifndef _7ZIP_ST + +static THREAD_FUNC_DECL MFThread(void *p) { ((CState *)p)->ThreadFunc(); return 0; } + +HRESULT CState::Create() +{ + RINOK_THREAD(StreamWasFinishedEvent.CreateIfNotCreated()); + RINOK_THREAD(WaitingWasStartedEvent.CreateIfNotCreated()); + RINOK_THREAD(CanWriteEvent.CreateIfNotCreated()); + RINOK_THREAD(Thread.Create(MFThread, this)); + return S_OK; +} + +void CState::FinishStream() +{ + Decoder->StreamWasFinished1 = true; + StreamWasFinishedEvent.Set(); + Decoder->CS.Leave(); + Decoder->CanStartWaitingEvent.Lock(); + WaitingWasStartedEvent.Set(); +} + +void CState::ThreadFunc() +{ + for (;;) + { + Decoder->CanProcessEvent.Lock(); + Decoder->CS.Enter(); + if (Decoder->CloseThreads) + { + Decoder->CS.Leave(); + return; + } + if (Decoder->StreamWasFinished1) + { + FinishStream(); + continue; + } + HRESULT res = S_OK; + + UInt32 blockIndex = Decoder->NextBlockIndex; + UInt32 nextBlockIndex = blockIndex + 1; + if (nextBlockIndex == Decoder->NumThreads) + nextBlockIndex = 0; + Decoder->NextBlockIndex = nextBlockIndex; + UInt32 crc; + UInt64 packSize = 0; + UInt32 blockSize = 0, origPtr = 0; + bool randMode = false; + + try + { + bool wasFinished; + res = Decoder->ReadSignatures(wasFinished, crc); + if (res != S_OK) + { + Decoder->Result1 = res; + FinishStream(); + continue; + } + if (wasFinished) + { + Decoder->Result1 = res; + FinishStream(); + continue; + } + + res = ReadBlock(&Decoder->m_InStream, Counters, Decoder->BlockSizeMax, + Decoder->m_Selectors, Decoder->m_HuffmanDecoders, + &blockSize, &origPtr, &randMode); + if (res != S_OK) + { + Decoder->Result1 = res; + FinishStream(); + continue; + } + packSize = Decoder->m_InStream.GetProcessedSize(); + } + catch(const CInBufferException &e) { res = e.ErrorCode; if (res != S_OK) res = E_FAIL; } + catch(...) { res = E_FAIL; } + if (res != S_OK) + { + Decoder->Result1 = res; + FinishStream(); + continue; + } + + Decoder->CS.Leave(); + + DecodeBlock1(Counters, blockSize); + + bool needFinish = true; + try + { + Decoder->m_States[blockIndex].CanWriteEvent.Lock(); + needFinish = Decoder->StreamWasFinished2; + if (!needFinish) + { + if ((randMode ? + DecodeBlock2Rand(Counters + 256, blockSize, origPtr, Decoder->m_OutStream) : + DecodeBlock2(Counters + 256, blockSize, origPtr, Decoder->m_OutStream)) == crc) + res = Decoder->SetRatioProgress(packSize); + else + res = S_FALSE; + } + } + catch(const COutBufferException &e) { res = e.ErrorCode; if (res != S_OK) res = E_FAIL; } + catch(...) { res = E_FAIL; } + if (res != S_OK) + { + Decoder->Result2 = res; + Decoder->StreamWasFinished2 = true; + } + Decoder->m_States[nextBlockIndex].CanWriteEvent.Set(); + if (res != S_OK || needFinish) + { + StreamWasFinishedEvent.Set(); + Decoder->CanStartWaitingEvent.Lock(); + WaitingWasStartedEvent.Set(); + } + } +} + +STDMETHODIMP CDecoder::SetNumberOfThreads(UInt32 numThreads) +{ + NumThreads = numThreads; + if (NumThreads < 1) + NumThreads = 1; + if (NumThreads > kNumThreadsMax) + NumThreads = kNumThreadsMax; + return S_OK; +} + +#endif + +HRESULT CDecoder::SetRatioProgress(UInt64 packSize) +{ + if (!Progress) + return S_OK; + packSize -= _inStart; + UInt64 unpackSize = m_OutStream.GetProcessedSize(); + return Progress->SetRatioInfo(&packSize, &unpackSize); +} + + +// ---------- NSIS ---------- + +enum +{ + NSIS_STATE_INIT, + NSIS_STATE_NEW_BLOCK, + NSIS_STATE_DATA, + NSIS_STATE_FINISHED, + NSIS_STATE_ERROR +}; + +STDMETHODIMP CNsisDecoder::SetInStream(ISequentialInStream *inStream) { m_InStream.SetStream(inStream); return S_OK; } +STDMETHODIMP CNsisDecoder::ReleaseInStream() { m_InStream.ReleaseStream(); return S_OK; } + +STDMETHODIMP CNsisDecoder::SetOutStreamSize(const UInt64 * /* outSize */) +{ + _nsisState = NSIS_STATE_INIT; + return S_OK; +} + +STDMETHODIMP CNsisDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + try { + + *processedSize = 0; + if (_nsisState == NSIS_STATE_FINISHED) + return S_OK; + if (_nsisState == NSIS_STATE_ERROR) + return S_FALSE; + if (size == 0) + return S_OK; + + CState &state = m_State; + + if (_nsisState == NSIS_STATE_INIT) + { + if (!m_InStream.Create(kBufferSize)) + return E_OUTOFMEMORY; + if (!state.Alloc()) + return E_OUTOFMEMORY; + m_InStream.Init(); + _nsisState = NSIS_STATE_NEW_BLOCK; + } + + if (_nsisState == NSIS_STATE_NEW_BLOCK) + { + Byte b = (Byte)m_InStream.ReadBits(8); + if (b == kFinSig0) + { + _nsisState = NSIS_STATE_FINISHED; + return S_OK; + } + if (b != kBlockSig0) + { + _nsisState = NSIS_STATE_ERROR; + return S_FALSE; + } + UInt32 origPtr; + RINOK(ReadBlock(&m_InStream, state.Counters, 9 * kBlockSizeStep, + m_Selectors, m_HuffmanDecoders, &_blockSize, &origPtr, NULL)); + DecodeBlock1(state.Counters, _blockSize); + const UInt32 *tt = state.Counters + 256; + _tPos = tt[tt[origPtr] >> 8]; + _prevByte = (unsigned)(_tPos & 0xFF); + _numReps = 0; + _repRem = 0; + _nsisState = NSIS_STATE_DATA; + } + + UInt32 tPos = _tPos; + unsigned prevByte = _prevByte; + unsigned numReps = _numReps; + UInt32 blockSize = _blockSize; + const UInt32 *tt = state.Counters + 256; + + while (_repRem) + { + _repRem--; + *(Byte *)data = (Byte)prevByte; + data = (Byte *)data + 1; + (*processedSize)++; + if (--size == 0) + return S_OK; + } + + if (blockSize == 0) + { + _nsisState = NSIS_STATE_NEW_BLOCK; + return S_OK; + } + + do + { + unsigned b = (unsigned)(tPos & 0xFF); + tPos = tt[tPos >> 8]; + blockSize--; + + if (numReps == kRleModeRepSize) + { + numReps = 0; + while (b) + { + b--; + *(Byte *)data = (Byte)prevByte; + data = (Byte *)data + 1; + (*processedSize)++; + if (--size == 0) + break; + } + _repRem = b; + continue; + } + if (b != prevByte) + numReps = 0; + numReps++; + prevByte = b; + *(Byte *)data = (Byte)b; + data = (Byte *)data + 1; + (*processedSize)++; + size--; + } + while (size && blockSize); + _tPos = tPos; + _prevByte = prevByte; + _numReps = numReps; + _blockSize = blockSize; + return S_OK; + + } + catch(const CInBufferException &e) { return e.ErrorCode; } + catch(...) { return S_FALSE; } +} + +}} diff --git a/CPP/7zip/Compress/BZip2Decoder.h b/CPP/7zip/Compress/BZip2Decoder.h new file mode 100755 index 0000000..822a287 --- /dev/null +++ b/CPP/7zip/Compress/BZip2Decoder.h @@ -0,0 +1,205 @@ +// Compress/BZip2Decoder.h + +#ifndef __COMPRESS_BZIP2_DECODER_H +#define __COMPRESS_BZIP2_DECODER_H + +#include "../../Common/MyCom.h" + +#ifndef _7ZIP_ST +#include "../../Windows/Synchronization.h" +#include "../../Windows/Thread.h" +#endif + +#include "../ICoder.h" + +#include "../Common/InBuffer.h" +#include "../Common/OutBuffer.h" + +#include "BitmDecoder.h" +#include "BZip2Const.h" +#include "BZip2Crc.h" +#include "HuffmanDecoder.h" + +namespace NCompress { +namespace NBZip2 { + +typedef NCompress::NHuffman::CDecoder CHuffmanDecoder; + +class CDecoder; + +struct CState +{ + UInt32 *Counters; + + #ifndef _7ZIP_ST + + CDecoder *Decoder; + NWindows::CThread Thread; + bool m_OptimizeNumTables; + + NWindows::NSynchronization::CAutoResetEvent StreamWasFinishedEvent; + NWindows::NSynchronization::CAutoResetEvent WaitingWasStartedEvent; + + // it's not member of this thread. We just need one event per thread + NWindows::NSynchronization::CAutoResetEvent CanWriteEvent; + + Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size. + + HRESULT Create(); + void FinishStream(); + void ThreadFunc(); + + #endif + + CState(): Counters(0) {} + ~CState() { Free(); } + bool Alloc(); + void Free(); +}; + +class CDecoder : + public ICompressCoder, + #ifndef _7ZIP_ST + public ICompressSetCoderMt, + #endif + public CMyUnknownImp +{ +public: + COutBuffer m_OutStream; + Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size. + NBitm::CDecoder m_InStream; + Byte m_Selectors[kNumSelectorsMax]; + CHuffmanDecoder m_HuffmanDecoders[kNumTablesMax]; + UInt64 _inStart; + +private: + + bool _needInStreamInit; + + UInt32 ReadBits(unsigned numBits); + Byte ReadByte(); + bool ReadBit(); + UInt32 ReadCrc(); + HRESULT DecodeFile(bool &isBZ, ICompressProgressInfo *progress); + HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + bool &isBZ, ICompressProgressInfo *progress); + class CDecoderFlusher + { + CDecoder *_decoder; + public: + bool NeedFlush; + bool ReleaseInStream; + CDecoderFlusher(CDecoder *decoder, bool releaseInStream): + _decoder(decoder), + ReleaseInStream(releaseInStream), + NeedFlush(true) {} + ~CDecoderFlusher() + { + if (NeedFlush) + _decoder->Flush(); + _decoder->ReleaseStreams(ReleaseInStream); + } + }; + +public: + CBZip2CombinedCrc CombinedCrc; + ICompressProgressInfo *Progress; + + #ifndef _7ZIP_ST + CState *m_States; + UInt32 m_NumThreadsPrev; + + NWindows::NSynchronization::CManualResetEvent CanProcessEvent; + NWindows::NSynchronization::CCriticalSection CS; + UInt32 NumThreads; + bool MtMode; + UInt32 NextBlockIndex; + bool CloseThreads; + bool StreamWasFinished1; + bool StreamWasFinished2; + NWindows::NSynchronization::CManualResetEvent CanStartWaitingEvent; + + HRESULT Result1; + HRESULT Result2; + + UInt32 BlockSizeMax; + ~CDecoder(); + HRESULT Create(); + void Free(); + + #else + CState m_States[1]; + #endif + + CDecoder(); + + HRESULT SetRatioProgress(UInt64 packSize); + HRESULT ReadSignatures(bool &wasFinished, UInt32 &crc); + + HRESULT Flush() { return m_OutStream.Flush(); } + void ReleaseStreams(bool releaseInStream) + { + if (releaseInStream) + m_InStream.ReleaseStream(); + m_OutStream.ReleaseStream(); + } + + MY_QUERYINTERFACE_BEGIN2(ICompressCoder) + #ifndef _7ZIP_ST + MY_QUERYINTERFACE_ENTRY(ICompressSetCoderMt) + #endif + + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + + STDMETHOD(SetInStream)(ISequentialInStream *inStream); + STDMETHOD(ReleaseInStream)(); + + HRESULT CodeResume(ISequentialOutStream *outStream, bool &isBZ, ICompressProgressInfo *progress); + UInt64 GetInputProcessedSize() const { return m_InStream.GetProcessedSize(); } + + #ifndef _7ZIP_ST + STDMETHOD(SetNumberOfThreads)(UInt32 numThreads); + #endif +}; + + +class CNsisDecoder : + public ISequentialInStream, + public ICompressSetInStream, + public ICompressSetOutStreamSize, + public CMyUnknownImp +{ + NBitm::CDecoder m_InStream; + Byte m_Selectors[kNumSelectorsMax]; + CHuffmanDecoder m_HuffmanDecoders[kNumTablesMax]; + CState m_State; + + int _nsisState; + UInt32 _tPos; + unsigned _prevByte; + unsigned _repRem; + unsigned _numReps; + UInt32 _blockSize; + +public: + + MY_QUERYINTERFACE_BEGIN2(ISequentialInStream) + MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) + MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize) + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(SetInStream)(ISequentialInStream *inStream); + STDMETHOD(ReleaseInStream)(); + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/BZip2Encoder.cpp b/CPP/7zip/Compress/BZip2Encoder.cpp new file mode 100755 index 0000000..165713e --- /dev/null +++ b/CPP/7zip/Compress/BZip2Encoder.cpp @@ -0,0 +1,895 @@ +// BZip2Encoder.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" +#include "../../../C/BwtSort.h" +#include "../../../C/HuffEnc.h" + +#include "BZip2Crc.h" +#include "BZip2Encoder.h" +#include "Mtf8.h" + +namespace NCompress { +namespace NBZip2 { + +const int kMaxHuffmanLenForEncoding = 16; // it must be < kMaxHuffmanLen = 20 + +static const UInt32 kBufferSize = (1 << 17); +static const int kNumHuffPasses = 4; + +bool CThreadInfo::Alloc() +{ + if (m_BlockSorterIndex == 0) + { + m_BlockSorterIndex = (UInt32 *)::BigAlloc(BLOCK_SORT_BUF_SIZE(kBlockSizeMax) * sizeof(UInt32)); + if (m_BlockSorterIndex == 0) + return false; + } + + if (m_Block == 0) + { + m_Block = (Byte *)::MidAlloc(kBlockSizeMax * 5 + kBlockSizeMax / 10 + (20 << 10)); + if (m_Block == 0) + return false; + m_MtfArray = m_Block + kBlockSizeMax; + m_TempArray = m_MtfArray + kBlockSizeMax * 2 + 2; + } + return true; +} + +void CThreadInfo::Free() +{ + ::BigFree(m_BlockSorterIndex); + m_BlockSorterIndex = 0; + ::MidFree(m_Block); + m_Block = 0; +} + +#ifndef _7ZIP_ST + +static THREAD_FUNC_DECL MFThread(void *threadCoderInfo) +{ + return ((CThreadInfo *)threadCoderInfo)->ThreadFunc(); +} + +#define RINOK_THREAD(x) { WRes __result_ = (x); if(__result_ != 0) return __result_; } + +HRESULT CThreadInfo::Create() +{ + RINOK_THREAD(StreamWasFinishedEvent.Create()); + RINOK_THREAD(WaitingWasStartedEvent.Create()); + RINOK_THREAD(CanWriteEvent.Create()); + RINOK_THREAD(Thread.Create(MFThread, this)); + return S_OK; +} + +void CThreadInfo::FinishStream(bool needLeave) +{ + Encoder->StreamWasFinished = true; + StreamWasFinishedEvent.Set(); + if (needLeave) + Encoder->CS.Leave(); + Encoder->CanStartWaitingEvent.Lock(); + WaitingWasStartedEvent.Set(); +} + +DWORD CThreadInfo::ThreadFunc() +{ + for (;;) + { + Encoder->CanProcessEvent.Lock(); + Encoder->CS.Enter(); + if (Encoder->CloseThreads) + { + Encoder->CS.Leave(); + return 0; + } + if (Encoder->StreamWasFinished) + { + FinishStream(true); + continue; + } + HRESULT res = S_OK; + bool needLeave = true; + try + { + UInt32 blockSize = Encoder->ReadRleBlock(m_Block); + m_PackSize = Encoder->m_InStream.GetProcessedSize(); + m_BlockIndex = Encoder->NextBlockIndex; + if (++Encoder->NextBlockIndex == Encoder->NumThreads) + Encoder->NextBlockIndex = 0; + if (blockSize == 0) + { + FinishStream(true); + continue; + } + Encoder->CS.Leave(); + needLeave = false; + res = EncodeBlock3(blockSize); + } + catch(const CInBufferException &e) { res = e.ErrorCode; } + catch(const COutBufferException &e) { res = e.ErrorCode; } + catch(...) { res = E_FAIL; } + if (res != S_OK) + { + Encoder->Result = res; + FinishStream(needLeave); + continue; + } + } +} + +#endif + +CEncoder::CEncoder(): + NumPasses(1), + m_OptimizeNumTables(false), + m_BlockSizeMult(kBlockSizeMultMax) +{ + #ifndef _7ZIP_ST + ThreadsInfo = 0; + m_NumThreadsPrev = 0; + NumThreads = 1; + #endif +} + +#ifndef _7ZIP_ST +CEncoder::~CEncoder() +{ + Free(); +} + +HRESULT CEncoder::Create() +{ + RINOK_THREAD(CanProcessEvent.CreateIfNotCreated()); + RINOK_THREAD(CanStartWaitingEvent.CreateIfNotCreated()); + if (ThreadsInfo != 0 && m_NumThreadsPrev == NumThreads) + return S_OK; + try + { + Free(); + MtMode = (NumThreads > 1); + m_NumThreadsPrev = NumThreads; + ThreadsInfo = new CThreadInfo[NumThreads]; + if (ThreadsInfo == 0) + return E_OUTOFMEMORY; + } + catch(...) { return E_OUTOFMEMORY; } + for (UInt32 t = 0; t < NumThreads; t++) + { + CThreadInfo &ti = ThreadsInfo[t]; + ti.Encoder = this; + if (MtMode) + { + HRESULT res = ti.Create(); + if (res != S_OK) + { + NumThreads = t; + Free(); + return res; + } + } + } + return S_OK; +} + +void CEncoder::Free() +{ + if (!ThreadsInfo) + return; + CloseThreads = true; + CanProcessEvent.Set(); + for (UInt32 t = 0; t < NumThreads; t++) + { + CThreadInfo &ti = ThreadsInfo[t]; + if (MtMode) + ti.Thread.Wait(); + ti.Free(); + } + delete []ThreadsInfo; + ThreadsInfo = 0; +} +#endif + +UInt32 CEncoder::ReadRleBlock(Byte *buffer) +{ + UInt32 i = 0; + Byte prevByte; + if (m_InStream.ReadByte(prevByte)) + { + UInt32 blockSize = m_BlockSizeMult * kBlockSizeStep - 1; + int numReps = 1; + buffer[i++] = prevByte; + while (i < blockSize) // "- 1" to support RLE + { + Byte b; + if (!m_InStream.ReadByte(b)) + break; + if (b != prevByte) + { + if (numReps >= kRleModeRepSize) + buffer[i++] = (Byte)(numReps - kRleModeRepSize); + buffer[i++] = b; + numReps = 1; + prevByte = b; + continue; + } + numReps++; + if (numReps <= kRleModeRepSize) + buffer[i++] = b; + else if (numReps == kRleModeRepSize + 255) + { + buffer[i++] = (Byte)(numReps - kRleModeRepSize); + numReps = 0; + } + } + // it's to support original BZip2 decoder + if (numReps >= kRleModeRepSize) + buffer[i++] = (Byte)(numReps - kRleModeRepSize); + } + return i; +} + +void CThreadInfo::WriteBits2(UInt32 value, UInt32 numBits) + { m_OutStreamCurrent->WriteBits(value, numBits); } +void CThreadInfo::WriteByte2(Byte b) { WriteBits2(b , 8); } +void CThreadInfo::WriteBit2(bool v) { WriteBits2((v ? 1 : 0), 1); } +void CThreadInfo::WriteCrc2(UInt32 v) +{ + for (int i = 0; i < 4; i++) + WriteByte2(((Byte)(v >> (24 - i * 8)))); +} + +void CEncoder::WriteBits(UInt32 value, UInt32 numBits) + { m_OutStream.WriteBits(value, numBits); } +void CEncoder::WriteByte(Byte b) { WriteBits(b , 8); } +void CEncoder::WriteBit(bool v) { WriteBits((v ? 1 : 0), 1); } +void CEncoder::WriteCrc(UInt32 v) +{ + for (int i = 0; i < 4; i++) + WriteByte(((Byte)(v >> (24 - i * 8)))); +} + + +// blockSize > 0 +void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) +{ + WriteBit2(false); // Randomised = false + + { + UInt32 origPtr = BlockSort(m_BlockSorterIndex, block, blockSize); + // if (m_BlockSorterIndex[origPtr] != 0) throw 1; + m_BlockSorterIndex[origPtr] = blockSize; + WriteBits2(origPtr, kNumOrigBits); + } + + CMtf8Encoder mtf; + int numInUse = 0; + { + bool inUse[256]; + bool inUse16[16]; + UInt32 i; + for (i = 0; i < 256; i++) + inUse[i] = false; + for (i = 0; i < 16; i++) + inUse16[i] = false; + for (i = 0; i < blockSize; i++) + inUse[block[i]] = true; + for (i = 0; i < 256; i++) + if (inUse[i]) + { + inUse16[i >> 4] = true; + mtf.Buf[numInUse++] = (Byte)i; + } + for (i = 0; i < 16; i++) + WriteBit2(inUse16[i]); + for (i = 0; i < 256; i++) + if (inUse16[i >> 4]) + WriteBit2(inUse[i]); + } + int alphaSize = numInUse + 2; + + Byte *mtfs = m_MtfArray; + UInt32 mtfArraySize = 0; + UInt32 symbolCounts[kMaxAlphaSize]; + { + for (int i = 0; i < kMaxAlphaSize; i++) + symbolCounts[i] = 0; + } + + { + UInt32 rleSize = 0; + UInt32 i = 0; + const UInt32 *bsIndex = m_BlockSorterIndex; + block--; + do + { + int pos = mtf.FindAndMove(block[bsIndex[i]]); + if (pos == 0) + rleSize++; + else + { + while (rleSize != 0) + { + rleSize--; + mtfs[mtfArraySize++] = (Byte)(rleSize & 1); + symbolCounts[rleSize & 1]++; + rleSize >>= 1; + } + if (pos >= 0xFE) + { + mtfs[mtfArraySize++] = 0xFF; + mtfs[mtfArraySize++] = (Byte)(pos - 0xFE); + } + else + mtfs[mtfArraySize++] = (Byte)(pos + 1); + symbolCounts[pos + 1]++; + } + } + while (++i < blockSize); + + while (rleSize != 0) + { + rleSize--; + mtfs[mtfArraySize++] = (Byte)(rleSize & 1); + symbolCounts[rleSize & 1]++; + rleSize >>= 1; + } + + if (alphaSize < 256) + mtfs[mtfArraySize++] = (Byte)(alphaSize - 1); + else + { + mtfs[mtfArraySize++] = 0xFF; + mtfs[mtfArraySize++] = (Byte)(alphaSize - 256); + } + symbolCounts[alphaSize - 1]++; + } + + UInt32 numSymbols = 0; + { + for (int i = 0; i < kMaxAlphaSize; i++) + numSymbols += symbolCounts[i]; + } + + int bestNumTables = kNumTablesMin; + UInt32 bestPrice = 0xFFFFFFFF; + UInt32 startPos = m_OutStreamCurrent->GetPos(); + Byte startCurByte = m_OutStreamCurrent->GetCurByte(); + for (int nt = kNumTablesMin; nt <= kNumTablesMax + 1; nt++) + { + int numTables; + + if(m_OptimizeNumTables) + { + m_OutStreamCurrent->SetPos(startPos); + m_OutStreamCurrent->SetCurState((startPos & 7), startCurByte); + if (nt <= kNumTablesMax) + numTables = nt; + else + numTables = bestNumTables; + } + else + { + if (numSymbols < 200) numTables = 2; + else if (numSymbols < 600) numTables = 3; + else if (numSymbols < 1200) numTables = 4; + else if (numSymbols < 2400) numTables = 5; + else numTables = 6; + } + + WriteBits2(numTables, kNumTablesBits); + + UInt32 numSelectors = (numSymbols + kGroupSize - 1) / kGroupSize; + WriteBits2(numSelectors, kNumSelectorsBits); + + { + UInt32 remFreq = numSymbols; + int gs = 0; + int t = numTables; + do + { + UInt32 tFreq = remFreq / t; + int ge = gs; + UInt32 aFreq = 0; + while (aFreq < tFreq) // && ge < alphaSize) + aFreq += symbolCounts[ge++]; + + if (ge - 1 > gs && t != numTables && t != 1 && (((numTables - t) & 1) == 1)) + aFreq -= symbolCounts[--ge]; + + Byte *lens = Lens[t - 1]; + int i = 0; + do + lens[i] = (i >= gs && i < ge) ? 0 : 1; + while (++i < alphaSize); + gs = ge; + remFreq -= aFreq; + } + while(--t != 0); + } + + + for (int pass = 0; pass < kNumHuffPasses; pass++) + { + { + int t = 0; + do + memset(Freqs[t], 0, sizeof(Freqs[t])); + while(++t < numTables); + } + + { + UInt32 mtfPos = 0; + UInt32 g = 0; + do + { + UInt32 symbols[kGroupSize]; + int i = 0; + do + { + UInt32 symbol = mtfs[mtfPos++]; + if (symbol >= 0xFF) + symbol += mtfs[mtfPos++]; + symbols[i] = symbol; + } + while (++i < kGroupSize && mtfPos < mtfArraySize); + + UInt32 bestPrice = 0xFFFFFFFF; + int t = 0; + do + { + const Byte *lens = Lens[t]; + UInt32 price = 0; + int j = 0; + do + price += lens[symbols[j]]; + while (++j < i); + if (price < bestPrice) + { + m_Selectors[g] = (Byte)t; + bestPrice = price; + } + } + while(++t < numTables); + UInt32 *freqs = Freqs[m_Selectors[g++]]; + int j = 0; + do + freqs[symbols[j]]++; + while (++j < i); + } + while (mtfPos < mtfArraySize); + } + + int t = 0; + do + { + UInt32 *freqs = Freqs[t]; + int i = 0; + do + if (freqs[i] == 0) + freqs[i] = 1; + while(++i < alphaSize); + Huffman_Generate(freqs, Codes[t], Lens[t], kMaxAlphaSize, kMaxHuffmanLenForEncoding); + } + while(++t < numTables); + } + + { + Byte mtfSel[kNumTablesMax]; + { + int t = 0; + do + mtfSel[t] = (Byte)t; + while(++t < numTables); + } + + UInt32 i = 0; + do + { + Byte sel = m_Selectors[i]; + int pos; + for (pos = 0; mtfSel[pos] != sel; pos++) + WriteBit2(true); + WriteBit2(false); + for (; pos > 0; pos--) + mtfSel[pos] = mtfSel[pos - 1]; + mtfSel[0] = sel; + } + while(++i < numSelectors); + } + + { + int t = 0; + do + { + const Byte *lens = Lens[t]; + UInt32 len = lens[0]; + WriteBits2(len, kNumLevelsBits); + int i = 0; + do + { + UInt32 level = lens[i]; + while (len != level) + { + WriteBit2(true); + if (len < level) + { + WriteBit2(false); + len++; + } + else + { + WriteBit2(true); + len--; + } + } + WriteBit2(false); + } + while (++i < alphaSize); + } + while(++t < numTables); + } + + { + UInt32 groupSize = 0; + UInt32 groupIndex = 0; + const Byte *lens = 0; + const UInt32 *codes = 0; + UInt32 mtfPos = 0; + do + { + UInt32 symbol = mtfs[mtfPos++]; + if (symbol >= 0xFF) + symbol += mtfs[mtfPos++]; + if (groupSize == 0) + { + groupSize = kGroupSize; + int t = m_Selectors[groupIndex++]; + lens = Lens[t]; + codes = Codes[t]; + } + groupSize--; + m_OutStreamCurrent->WriteBits(codes[symbol], lens[symbol]); + } + while (mtfPos < mtfArraySize); + } + + if (!m_OptimizeNumTables) + break; + UInt32 price = m_OutStreamCurrent->GetPos() - startPos; + if (price <= bestPrice) + { + if (nt == kNumTablesMax) + break; + bestPrice = price; + bestNumTables = nt; + } + } +} + +// blockSize > 0 +UInt32 CThreadInfo::EncodeBlockWithHeaders(const Byte *block, UInt32 blockSize) +{ + WriteByte2(kBlockSig0); + WriteByte2(kBlockSig1); + WriteByte2(kBlockSig2); + WriteByte2(kBlockSig3); + WriteByte2(kBlockSig4); + WriteByte2(kBlockSig5); + + CBZip2Crc crc; + int numReps = 0; + Byte prevByte = block[0]; + UInt32 i = 0; + do + { + Byte b = block[i]; + if (numReps == kRleModeRepSize) + { + for (; b > 0; b--) + crc.UpdateByte(prevByte); + numReps = 0; + continue; + } + if (prevByte == b) + numReps++; + else + { + numReps = 1; + prevByte = b; + } + crc.UpdateByte(b); + } + while (++i < blockSize); + UInt32 crcRes = crc.GetDigest(); + WriteCrc2(crcRes); + EncodeBlock(block, blockSize); + return crcRes; +} + +void CThreadInfo::EncodeBlock2(const Byte *block, UInt32 blockSize, UInt32 numPasses) +{ + UInt32 numCrcs = m_NumCrcs; + bool needCompare = false; + + UInt32 startBytePos = m_OutStreamCurrent->GetBytePos(); + UInt32 startPos = m_OutStreamCurrent->GetPos(); + Byte startCurByte = m_OutStreamCurrent->GetCurByte(); + Byte endCurByte = 0; + UInt32 endPos = 0; + if (numPasses > 1 && blockSize >= (1 << 10)) + { + UInt32 blockSize0 = blockSize / 2; + for (;(block[blockSize0] == block[blockSize0 - 1] || + block[blockSize0 - 1] == block[blockSize0 - 2]) && + blockSize0 < blockSize; blockSize0++); + if (blockSize0 < blockSize) + { + EncodeBlock2(block, blockSize0, numPasses - 1); + EncodeBlock2(block + blockSize0, blockSize - blockSize0, numPasses - 1); + endPos = m_OutStreamCurrent->GetPos(); + endCurByte = m_OutStreamCurrent->GetCurByte(); + if ((endPos & 7) > 0) + WriteBits2(0, 8 - (endPos & 7)); + m_OutStreamCurrent->SetCurState((startPos & 7), startCurByte); + needCompare = true; + } + } + + UInt32 startBytePos2 = m_OutStreamCurrent->GetBytePos(); + UInt32 startPos2 = m_OutStreamCurrent->GetPos(); + UInt32 crcVal = EncodeBlockWithHeaders(block, blockSize); + UInt32 endPos2 = m_OutStreamCurrent->GetPos(); + + if (needCompare) + { + UInt32 size2 = endPos2 - startPos2; + if (size2 < endPos - startPos) + { + UInt32 numBytes = m_OutStreamCurrent->GetBytePos() - startBytePos2; + Byte *buffer = m_OutStreamCurrent->GetStream(); + for (UInt32 i = 0; i < numBytes; i++) + buffer[startBytePos + i] = buffer[startBytePos2 + i]; + m_OutStreamCurrent->SetPos(startPos + endPos2 - startPos2); + m_NumCrcs = numCrcs; + m_CRCs[m_NumCrcs++] = crcVal; + } + else + { + m_OutStreamCurrent->SetPos(endPos); + m_OutStreamCurrent->SetCurState((endPos & 7), endCurByte); + } + } + else + { + m_NumCrcs = numCrcs; + m_CRCs[m_NumCrcs++] = crcVal; + } +} + +HRESULT CThreadInfo::EncodeBlock3(UInt32 blockSize) +{ + CMsbfEncoderTemp outStreamTemp; + outStreamTemp.SetStream(m_TempArray); + outStreamTemp.Init(); + m_OutStreamCurrent = &outStreamTemp; + + m_NumCrcs = 0; + + EncodeBlock2(m_Block, blockSize, Encoder->NumPasses); + + #ifndef _7ZIP_ST + if (Encoder->MtMode) + Encoder->ThreadsInfo[m_BlockIndex].CanWriteEvent.Lock(); + #endif + for (UInt32 i = 0; i < m_NumCrcs; i++) + Encoder->CombinedCrc.Update(m_CRCs[i]); + Encoder->WriteBytes(m_TempArray, outStreamTemp.GetPos(), outStreamTemp.GetCurByte()); + HRESULT res = S_OK; + #ifndef _7ZIP_ST + if (Encoder->MtMode) + { + UInt32 blockIndex = m_BlockIndex + 1; + if (blockIndex == Encoder->NumThreads) + blockIndex = 0; + + if (Encoder->Progress) + { + UInt64 unpackSize = Encoder->m_OutStream.GetProcessedSize(); + res = Encoder->Progress->SetRatioInfo(&m_PackSize, &unpackSize); + } + + Encoder->ThreadsInfo[blockIndex].CanWriteEvent.Set(); + } + #endif + return res; +} + +void CEncoder::WriteBytes(const Byte *data, UInt32 sizeInBits, Byte lastByte) +{ + UInt32 bytesSize = (sizeInBits / 8); + for (UInt32 i = 0; i < bytesSize; i++) + m_OutStream.WriteBits(data[i], 8); + WriteBits(lastByte, (sizeInBits & 7)); +} + + +HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) +{ + #ifndef _7ZIP_ST + Progress = progress; + RINOK(Create()); + for (UInt32 t = 0; t < NumThreads; t++) + #endif + { + #ifndef _7ZIP_ST + CThreadInfo &ti = ThreadsInfo[t]; + if (MtMode) + { + RINOK(ti.StreamWasFinishedEvent.Reset()); + RINOK(ti.WaitingWasStartedEvent.Reset()); + RINOK(ti.CanWriteEvent.Reset()); + } + #else + CThreadInfo &ti = ThreadsInfo; + ti.Encoder = this; + #endif + + ti.m_OptimizeNumTables = m_OptimizeNumTables; + + if (!ti.Alloc()) + return E_OUTOFMEMORY; + } + + + if (!m_InStream.Create(kBufferSize)) + return E_OUTOFMEMORY; + if (!m_OutStream.Create(kBufferSize)) + return E_OUTOFMEMORY; + + + m_InStream.SetStream(inStream); + m_InStream.Init(); + + m_OutStream.SetStream(outStream); + m_OutStream.Init(); + + CFlusher flusher(this); + + CombinedCrc.Init(); + #ifndef _7ZIP_ST + NextBlockIndex = 0; + StreamWasFinished = false; + CloseThreads = false; + CanStartWaitingEvent.Reset(); + #endif + + WriteByte(kArSig0); + WriteByte(kArSig1); + WriteByte(kArSig2); + WriteByte((Byte)(kArSig3 + m_BlockSizeMult)); + + #ifndef _7ZIP_ST + + if (MtMode) + { + ThreadsInfo[0].CanWriteEvent.Set(); + Result = S_OK; + CanProcessEvent.Set(); + UInt32 t; + for (t = 0; t < NumThreads; t++) + ThreadsInfo[t].StreamWasFinishedEvent.Lock(); + CanProcessEvent.Reset(); + CanStartWaitingEvent.Set(); + for (t = 0; t < NumThreads; t++) + ThreadsInfo[t].WaitingWasStartedEvent.Lock(); + CanStartWaitingEvent.Reset(); + RINOK(Result); + } + else + #endif + { + for (;;) + { + CThreadInfo &ti = + #ifndef _7ZIP_ST + ThreadsInfo[0]; + #else + ThreadsInfo; + #endif + UInt32 blockSize = ReadRleBlock(ti.m_Block); + if (blockSize == 0) + break; + RINOK(ti.EncodeBlock3(blockSize)); + if (progress) + { + UInt64 packSize = m_InStream.GetProcessedSize(); + UInt64 unpackSize = m_OutStream.GetProcessedSize(); + RINOK(progress->SetRatioInfo(&packSize, &unpackSize)); + } + } + } + WriteByte(kFinSig0); + WriteByte(kFinSig1); + WriteByte(kFinSig2); + WriteByte(kFinSig3); + WriteByte(kFinSig4); + WriteByte(kFinSig5); + + WriteCrc(CombinedCrc.GetDigest()); + return Flush(); +} + +STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + try { return CodeReal(inStream, outStream, inSize, outSize, progress); } + catch(const CInBufferException &e) { return e.ErrorCode; } + catch(const COutBufferException &e) { return e.ErrorCode; } + catch(...) { return S_FALSE; } +} + +HRESULT CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) +{ + for(UInt32 i = 0; i < numProps; i++) + { + const PROPVARIANT &prop = props[i]; + switch(propIDs[i]) + { + case NCoderPropID::kNumPasses: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 numPasses = prop.ulVal; + if (numPasses == 0) + numPasses = 1; + if (numPasses > kNumPassesMax) + numPasses = kNumPassesMax; + NumPasses = numPasses; + m_OptimizeNumTables = (NumPasses > 1); + break; + } + case NCoderPropID::kDictionarySize: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 dictionary = prop.ulVal / kBlockSizeStep; + if (dictionary < kBlockSizeMultMin) + dictionary = kBlockSizeMultMin; + else if (dictionary > kBlockSizeMultMax) + dictionary = kBlockSizeMultMax; + m_BlockSizeMult = dictionary; + break; + } + case NCoderPropID::kNumThreads: + { + #ifndef _7ZIP_ST + if (prop.vt != VT_UI4) + return E_INVALIDARG; + NumThreads = prop.ulVal; + if (NumThreads < 1) + NumThreads = 1; + #endif + break; + } + default: + return E_INVALIDARG; + } + } + return S_OK; +} + +#ifndef _7ZIP_ST +STDMETHODIMP CEncoder::SetNumberOfThreads(UInt32 numThreads) +{ + NumThreads = numThreads; + if (NumThreads < 1) + NumThreads = 1; + return S_OK; +} +#endif + +}} diff --git a/CPP/7zip/Compress/BZip2Encoder.h b/CPP/7zip/Compress/BZip2Encoder.h new file mode 100755 index 0000000..287ec50 --- /dev/null +++ b/CPP/7zip/Compress/BZip2Encoder.h @@ -0,0 +1,245 @@ +// BZip2Encoder.h + +#ifndef __COMPRESS_BZIP2_ENCODER_H +#define __COMPRESS_BZIP2_ENCODER_H + +#include "../../Common/Defs.h" +#include "../../Common/MyCom.h" + +#ifndef _7ZIP_ST +#include "../../Windows/Synchronization.h" +#include "../../Windows/Thread.h" +#endif + +#include "../ICoder.h" + +#include "../Common/InBuffer.h" +#include "../Common/OutBuffer.h" + +#include "BitmEncoder.h" +#include "BZip2Const.h" +#include "BZip2Crc.h" + +namespace NCompress { +namespace NBZip2 { + +class CMsbfEncoderTemp +{ + UInt32 m_Pos; + int m_BitPos; + Byte m_CurByte; + Byte *Buffer; +public: + void SetStream(Byte *buffer) { Buffer = buffer; } + Byte *GetStream() const { return Buffer; } + + void Init() + { + m_Pos = 0; + m_BitPos = 8; + m_CurByte = 0; + } + + void Flush() + { + if (m_BitPos < 8) + WriteBits(0, m_BitPos); + } + + void WriteBits(UInt32 value, int numBits) + { + while (numBits > 0) + { + int numNewBits = MyMin(numBits, m_BitPos); + numBits -= numNewBits; + + m_CurByte <<= numNewBits; + UInt32 newBits = value >> numBits; + m_CurByte |= Byte(newBits); + value -= (newBits << numBits); + + m_BitPos -= numNewBits; + + if (m_BitPos == 0) + { + Buffer[m_Pos++] = m_CurByte; + m_BitPos = 8; + } + } + } + + UInt32 GetBytePos() const { return m_Pos ; } + UInt32 GetPos() const { return m_Pos * 8 + (8 - m_BitPos); } + Byte GetCurByte() const { return m_CurByte; } + void SetPos(UInt32 bitPos) + { + m_Pos = bitPos / 8; + m_BitPos = 8 - ((int)bitPos & 7); + } + void SetCurState(int bitPos, Byte curByte) + { + m_BitPos = 8 - bitPos; + m_CurByte = curByte; + } +}; + +class CEncoder; + +const int kNumPassesMax = 10; + +class CThreadInfo +{ +public: + Byte *m_Block; +private: + Byte *m_MtfArray; + Byte *m_TempArray; + UInt32 *m_BlockSorterIndex; + + CMsbfEncoderTemp *m_OutStreamCurrent; + + Byte Lens[kNumTablesMax][kMaxAlphaSize]; + UInt32 Freqs[kNumTablesMax][kMaxAlphaSize]; + UInt32 Codes[kNumTablesMax][kMaxAlphaSize]; + + Byte m_Selectors[kNumSelectorsMax]; + + UInt32 m_CRCs[1 << kNumPassesMax]; + UInt32 m_NumCrcs; + + UInt32 m_BlockIndex; + + void WriteBits2(UInt32 value, UInt32 numBits); + void WriteByte2(Byte b); + void WriteBit2(bool v); + void WriteCrc2(UInt32 v); + + void EncodeBlock(const Byte *block, UInt32 blockSize); + UInt32 EncodeBlockWithHeaders(const Byte *block, UInt32 blockSize); + void EncodeBlock2(const Byte *block, UInt32 blockSize, UInt32 numPasses); +public: + bool m_OptimizeNumTables; + CEncoder *Encoder; + #ifndef _7ZIP_ST + NWindows::CThread Thread; + + NWindows::NSynchronization::CAutoResetEvent StreamWasFinishedEvent; + NWindows::NSynchronization::CAutoResetEvent WaitingWasStartedEvent; + + // it's not member of this thread. We just need one event per thread + NWindows::NSynchronization::CAutoResetEvent CanWriteEvent; + + UInt64 m_PackSize; + + Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size. + HRESULT Create(); + void FinishStream(bool needLeave); + DWORD ThreadFunc(); + #endif + + CThreadInfo(): m_BlockSorterIndex(0), m_Block(0) {} + ~CThreadInfo() { Free(); } + bool Alloc(); + void Free(); + + HRESULT EncodeBlock3(UInt32 blockSize); +}; + +class CEncoder : + public ICompressCoder, + public ICompressSetCoderProperties, + #ifndef _7ZIP_ST + public ICompressSetCoderMt, + #endif + public CMyUnknownImp +{ + UInt32 m_BlockSizeMult; + bool m_OptimizeNumTables; + + UInt32 m_NumPassesPrev; + + UInt32 m_NumThreadsPrev; +public: + CInBuffer m_InStream; + Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size. + CBitmEncoder m_OutStream; + UInt32 NumPasses; + CBZip2CombinedCrc CombinedCrc; + + #ifndef _7ZIP_ST + CThreadInfo *ThreadsInfo; + NWindows::NSynchronization::CManualResetEvent CanProcessEvent; + NWindows::NSynchronization::CCriticalSection CS; + UInt32 NumThreads; + bool MtMode; + UInt32 NextBlockIndex; + + bool CloseThreads; + bool StreamWasFinished; + NWindows::NSynchronization::CManualResetEvent CanStartWaitingEvent; + + HRESULT Result; + ICompressProgressInfo *Progress; + #else + CThreadInfo ThreadsInfo; + #endif + + UInt32 ReadRleBlock(Byte *buffer); + void WriteBytes(const Byte *data, UInt32 sizeInBits, Byte lastByte); + + void WriteBits(UInt32 value, UInt32 numBits); + void WriteByte(Byte b); + void WriteBit(bool v); + void WriteCrc(UInt32 v); + + #ifndef _7ZIP_ST + HRESULT Create(); + void Free(); + #endif + +public: + CEncoder(); + #ifndef _7ZIP_ST + ~CEncoder(); + #endif + + HRESULT Flush() { return m_OutStream.Flush(); } + + void ReleaseStreams() + { + m_InStream.ReleaseStream(); + m_OutStream.ReleaseStream(); + } + + class CFlusher + { + CEncoder *_coder; + public: + CFlusher(CEncoder *coder): _coder(coder) {} + ~CFlusher() + { + _coder->ReleaseStreams(); + } + }; + + #ifndef _7ZIP_ST + MY_UNKNOWN_IMP2(ICompressSetCoderMt, ICompressSetCoderProperties) + #else + MY_UNKNOWN_IMP1(ICompressSetCoderProperties) + #endif + + HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); + + #ifndef _7ZIP_ST + STDMETHOD(SetNumberOfThreads)(UInt32 numThreads); + #endif +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/BZip2Register.cpp b/CPP/7zip/Compress/BZip2Register.cpp new file mode 100755 index 0000000..f10e594 --- /dev/null +++ b/CPP/7zip/Compress/BZip2Register.cpp @@ -0,0 +1,20 @@ +// BZip2Register.cpp + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" + +#include "BZip2Decoder.h" + +static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NBZip2::CDecoder); } +#if !defined(EXTRACT_ONLY) && !defined(BZIP2_EXTRACT_ONLY) +#include "BZip2Encoder.h" +static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NBZip2::CEncoder); } +#else +#define CreateCodecOut 0 +#endif + +static CCodecInfo g_CodecInfo = + { CreateCodec, CreateCodecOut, 0x040202, L"BZip2", 1, false }; + +REGISTER_CODEC(BZip2) diff --git a/CPP/7zip/Compress/Bcj2Coder.cpp b/CPP/7zip/Compress/Bcj2Coder.cpp new file mode 100755 index 0000000..05590e7 --- /dev/null +++ b/CPP/7zip/Compress/Bcj2Coder.cpp @@ -0,0 +1,386 @@ +// Bcj2Coder.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "Bcj2Coder.h" + +namespace NCompress { +namespace NBcj2 { + +inline bool IsJcc(Byte b0, Byte b1) { return (b0 == 0x0F && (b1 & 0xF0) == 0x80); } +inline bool IsJ(Byte b0, Byte b1) { return ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)); } +inline unsigned GetIndex(Byte b0, Byte b1) { return ((b1 == 0xE8) ? b0 : ((b1 == 0xE9) ? 256 : 257)); } + +#ifndef EXTRACT_ONLY + +static const int kBufferSize = 1 << 17; + +static bool inline Test86MSByte(Byte b) +{ + return (b == 0 || b == 0xFF); +} + +bool CEncoder::Create() +{ + if (!_mainStream.Create(1 << 18)) + return false; + if (!_callStream.Create(1 << 18)) + return false; + if (!_jumpStream.Create(1 << 18)) + return false; + if (!_rangeEncoder.Create(1 << 20)) + return false; + if (_buffer == 0) + { + _buffer = (Byte *)MidAlloc(kBufferSize); + if (_buffer == 0) + return false; + } + return true; +} + +CEncoder::~CEncoder() +{ + ::MidFree(_buffer); +} + +HRESULT CEncoder::Flush() +{ + RINOK(_mainStream.Flush()); + RINOK(_callStream.Flush()); + RINOK(_jumpStream.Flush()); + _rangeEncoder.FlushData(); + return _rangeEncoder.FlushStream(); +} + +const UInt32 kDefaultLimit = (1 << 24); + +HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, + ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, + ICompressProgressInfo *progress) +{ + if (numInStreams != 1 || numOutStreams != 4) + return E_INVALIDARG; + + if (!Create()) + return E_OUTOFMEMORY; + + bool sizeIsDefined = false; + UInt64 inSize = 0; + if (inSizes != NULL) + if (inSizes[0] != NULL) + { + inSize = *inSizes[0]; + if (inSize <= kDefaultLimit) + sizeIsDefined = true; + } + + CCoderReleaser releaser(this); + + ISequentialInStream *inStream = inStreams[0]; + + _mainStream.SetStream(outStreams[0]); + _mainStream.Init(); + _callStream.SetStream(outStreams[1]); + _callStream.Init(); + _jumpStream.SetStream(outStreams[2]); + _jumpStream.Init(); + _rangeEncoder.SetStream(outStreams[3]); + _rangeEncoder.Init(); + for (int i = 0; i < 256 + 2; i++) + _statusEncoder[i].Init(); + + CMyComPtr getSubStreamSize; + { + inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize); + } + + UInt32 nowPos = 0; + UInt64 nowPos64 = 0; + UInt32 bufferPos = 0; + + Byte prevByte = 0; + + UInt64 subStreamIndex = 0; + UInt64 subStreamStartPos = 0; + UInt64 subStreamEndPos = 0; + + for (;;) + { + UInt32 processedSize = 0; + for (;;) + { + UInt32 size = kBufferSize - (bufferPos + processedSize); + UInt32 processedSizeLoc; + if (size == 0) + break; + RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc)); + if (processedSizeLoc == 0) + break; + processedSize += processedSizeLoc; + } + UInt32 endPos = bufferPos + processedSize; + + if (endPos < 5) + { + // change it + for (bufferPos = 0; bufferPos < endPos; bufferPos++) + { + Byte b = _buffer[bufferPos]; + _mainStream.WriteByte(b); + UInt32 index; + if (b == 0xE8) + index = prevByte; + else if (b == 0xE9) + index = 256; + else if (IsJcc(prevByte, b)) + index = 257; + else + { + prevByte = b; + continue; + } + _statusEncoder[index].Encode(&_rangeEncoder, 0); + prevByte = b; + } + return Flush(); + } + + bufferPos = 0; + + UInt32 limit = endPos - 5; + while(bufferPos <= limit) + { + Byte b = _buffer[bufferPos]; + _mainStream.WriteByte(b); + if (!IsJ(prevByte, b)) + { + bufferPos++; + prevByte = b; + continue; + } + Byte nextByte = _buffer[bufferPos + 4]; + UInt32 src = + (UInt32(nextByte) << 24) | + (UInt32(_buffer[bufferPos + 3]) << 16) | + (UInt32(_buffer[bufferPos + 2]) << 8) | + (_buffer[bufferPos + 1]); + UInt32 dest = (nowPos + bufferPos + 5) + src; + // if (Test86MSByte(nextByte)) + bool convert; + if (getSubStreamSize != NULL) + { + UInt64 currentPos = (nowPos64 + bufferPos); + while (subStreamEndPos < currentPos) + { + UInt64 subStreamSize; + HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize); + if (result == S_OK) + { + subStreamStartPos = subStreamEndPos; + subStreamEndPos += subStreamSize; + subStreamIndex++; + } + else if (result == S_FALSE || result == E_NOTIMPL) + { + getSubStreamSize.Release(); + subStreamStartPos = 0; + subStreamEndPos = subStreamStartPos - 1; + } + else + return result; + } + if (getSubStreamSize == NULL) + { + if (sizeIsDefined) + convert = (dest < inSize); + else + convert = Test86MSByte(nextByte); + } + else if (subStreamEndPos - subStreamStartPos > kDefaultLimit) + convert = Test86MSByte(nextByte); + else + { + UInt64 dest64 = (currentPos + 5) + Int64(Int32(src)); + convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos); + } + } + else if (sizeIsDefined) + convert = (dest < inSize); + else + convert = Test86MSByte(nextByte); + unsigned index = GetIndex(prevByte, b); + if (convert) + { + _statusEncoder[index].Encode(&_rangeEncoder, 1); + bufferPos += 5; + COutBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; + for (int i = 24; i >= 0; i -= 8) + s.WriteByte((Byte)(dest >> i)); + prevByte = nextByte; + } + else + { + _statusEncoder[index].Encode(&_rangeEncoder, 0); + bufferPos++; + prevByte = b; + } + } + nowPos += bufferPos; + nowPos64 += bufferPos; + + if (progress != NULL) + { + /* + const UInt64 compressedSize = + _mainStream.GetProcessedSize() + + _callStream.GetProcessedSize() + + _jumpStream.GetProcessedSize() + + _rangeEncoder.GetProcessedSize(); + */ + RINOK(progress->SetRatioInfo(&nowPos64, NULL)); + } + + UInt32 i = 0; + while(bufferPos < endPos) + _buffer[i++] = _buffer[bufferPos++]; + bufferPos = i; + } +} + +STDMETHODIMP CEncoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, + ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, + ICompressProgressInfo *progress) +{ + try + { + return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); + } + catch(const COutBufferException &e) { return e.ErrorCode; } + catch(...) { return S_FALSE; } +} + +#endif + + +STDMETHODIMP CDecoder::SetInBufSize(UInt32 streamIndex, UInt32 size) { _inBufSizes[streamIndex] = size; return S_OK; } +STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outBufSize = size; return S_OK; } + +CDecoder::CDecoder(): + _outBufSize(1 << 16) +{ + _inBufSizes[0] = 1 << 20; + _inBufSizes[1] = 1 << 20; + _inBufSizes[2] = 1 << 20; + _inBufSizes[3] = 1 << 20; +} + +HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams, const UInt64 ** /* inSizes */, UInt32 numInStreams, + ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, + ICompressProgressInfo *progress) +{ + if (numInStreams != 4 || numOutStreams != 1) + return E_INVALIDARG; + + if (!_mainInStream.Create(_inBufSizes[0])) + return E_OUTOFMEMORY; + if (!_callStream.Create(_inBufSizes[1])) + return E_OUTOFMEMORY; + if (!_jumpStream.Create(_inBufSizes[2])) + return E_OUTOFMEMORY; + if (!_rangeDecoder.Create(_inBufSizes[3])) + return E_OUTOFMEMORY; + if (!_outStream.Create(_outBufSize)) + return E_OUTOFMEMORY; + + CCoderReleaser releaser(this); + + _mainInStream.SetStream(inStreams[0]); + _callStream.SetStream(inStreams[1]); + _jumpStream.SetStream(inStreams[2]); + _rangeDecoder.SetStream(inStreams[3]); + _outStream.SetStream(outStreams[0]); + + _mainInStream.Init(); + _callStream.Init(); + _jumpStream.Init(); + _rangeDecoder.Init(); + _outStream.Init(); + + for (int i = 0; i < 256 + 2; i++) + _statusDecoder[i].Init(); + + Byte prevByte = 0; + UInt32 processedBytes = 0; + for (;;) + { + if (processedBytes >= (1 << 20) && progress != NULL) + { + /* + const UInt64 compressedSize = + _mainInStream.GetProcessedSize() + + _callStream.GetProcessedSize() + + _jumpStream.GetProcessedSize() + + _rangeDecoder.GetProcessedSize(); + */ + const UInt64 nowPos64 = _outStream.GetProcessedSize(); + RINOK(progress->SetRatioInfo(NULL, &nowPos64)); + processedBytes = 0; + } + UInt32 i; + Byte b = 0; + const UInt32 kBurstSize = (1 << 18); + for (i = 0; i < kBurstSize; i++) + { + if (!_mainInStream.ReadByte(b)) + return Flush(); + _outStream.WriteByte(b); + if (IsJ(prevByte, b)) + break; + prevByte = b; + } + processedBytes += i; + if (i == kBurstSize) + continue; + unsigned index = GetIndex(prevByte, b); + if (_statusDecoder[index].Decode(&_rangeDecoder) == 1) + { + UInt32 src = 0; + CInBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; + for (int i = 0; i < 4; i++) + { + Byte b0; + if(!s.ReadByte(b0)) + return S_FALSE; + src <<= 8; + src |= ((UInt32)b0); + } + UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ; + _outStream.WriteByte((Byte)(dest)); + _outStream.WriteByte((Byte)(dest >> 8)); + _outStream.WriteByte((Byte)(dest >> 16)); + _outStream.WriteByte((Byte)(dest >> 24)); + prevByte = (Byte)(dest >> 24); + processedBytes += 4; + } + else + prevByte = b; + } +} + +STDMETHODIMP CDecoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, + ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, + ICompressProgressInfo *progress) +{ + try + { + return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); + } + catch(const CInBufferException &e) { return e.ErrorCode; } + catch(const COutBufferException &e) { return e.ErrorCode; } + catch(...) { return S_FALSE; } +} + +}} diff --git a/CPP/7zip/Compress/Bcj2Coder.h b/CPP/7zip/Compress/Bcj2Coder.h new file mode 100755 index 0000000..c8f0893 --- /dev/null +++ b/CPP/7zip/Compress/Bcj2Coder.h @@ -0,0 +1,115 @@ +// Bcj2Coder.h + +#ifndef __COMPRESS_BCJ2_CODER_H +#define __COMPRESS_BCJ2_CODER_H + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +#include "RangeCoderBit.h" + +namespace NCompress { +namespace NBcj2 { + +const int kNumMoveBits = 5; + +#ifndef EXTRACT_ONLY + +class CEncoder: + public ICompressCoder2, + public CMyUnknownImp +{ + Byte *_buffer; + bool Create(); + + COutBuffer _mainStream; + COutBuffer _callStream; + COutBuffer _jumpStream; + NCompress::NRangeCoder::CEncoder _rangeEncoder; + NCompress::NRangeCoder::CBitEncoder _statusEncoder[256 + 2]; + + HRESULT Flush(); +public: + void ReleaseStreams() + { + _mainStream.ReleaseStream(); + _callStream.ReleaseStream(); + _jumpStream.ReleaseStream(); + _rangeEncoder.ReleaseStream(); + } + + class CCoderReleaser + { + CEncoder *_coder; + public: + CCoderReleaser(CEncoder *coder): _coder(coder) {} + ~CCoderReleaser() { _coder->ReleaseStreams(); } + }; + +public: + MY_UNKNOWN_IMP + + HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, + ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, + ICompressProgressInfo *progress); + STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, + ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, + ICompressProgressInfo *progress); + CEncoder(): _buffer(0) {}; + ~CEncoder(); +}; + +#endif + +class CDecoder: + public ICompressCoder2, + public ICompressSetBufSize, + public CMyUnknownImp +{ + CInBuffer _mainInStream; + CInBuffer _callStream; + CInBuffer _jumpStream; + NCompress::NRangeCoder::CDecoder _rangeDecoder; + NCompress::NRangeCoder::CBitDecoder _statusDecoder[256 + 2]; + + COutBuffer _outStream; + UInt32 _inBufSizes[4]; + UInt32 _outBufSize; + +public: + void ReleaseStreams() + { + _mainInStream.ReleaseStream(); + _callStream.ReleaseStream(); + _jumpStream.ReleaseStream(); + _rangeDecoder.ReleaseStream(); + _outStream.ReleaseStream(); + } + + HRESULT Flush() { return _outStream.Flush(); } + class CCoderReleaser + { + CDecoder *_coder; + public: + CCoderReleaser(CDecoder *coder): _coder(coder) {} + ~CCoderReleaser() { _coder->ReleaseStreams(); } + }; + +public: + MY_UNKNOWN_IMP1(ICompressSetBufSize); + HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, + ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, + ICompressProgressInfo *progress); + STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, + ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, + ICompressProgressInfo *progress); + + STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size); + STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size); + CDecoder(); +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/Bcj2Register.cpp b/CPP/7zip/Compress/Bcj2Register.cpp new file mode 100755 index 0000000..b063f3f --- /dev/null +++ b/CPP/7zip/Compress/Bcj2Register.cpp @@ -0,0 +1,19 @@ +// Bcj2Register.cpp + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" + +#include "Bcj2Coder.h" + +static void *CreateCodec() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CDecoder()); } +#ifndef EXTRACT_ONLY +static void *CreateCodecOut() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CEncoder()); } +#else +#define CreateCodecOut 0 +#endif + +static CCodecInfo g_CodecInfo = + { CreateCodec, CreateCodecOut, 0x0303011B, L"BCJ2", 4, false }; + +REGISTER_CODEC(BCJ2) diff --git a/CPP/7zip/Compress/BcjCoder.cpp b/CPP/7zip/Compress/BcjCoder.cpp new file mode 100755 index 0000000..108c573 --- /dev/null +++ b/CPP/7zip/Compress/BcjCoder.cpp @@ -0,0 +1,15 @@ +// BcjCoder.cpp + +#include "StdAfx.h" + +#include "BcjCoder.h" + +UInt32 CBCJ_x86_Encoder::SubFilter(Byte *data, UInt32 size) +{ + return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 1); +} + +UInt32 CBCJ_x86_Decoder::SubFilter(Byte *data, UInt32 size) +{ + return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 0); +} diff --git a/CPP/7zip/Compress/BcjCoder.h b/CPP/7zip/Compress/BcjCoder.h new file mode 100755 index 0000000..c86d5fc --- /dev/null +++ b/CPP/7zip/Compress/BcjCoder.h @@ -0,0 +1,19 @@ +// BcjCoder.h + +#ifndef __COMPRESS_BCJ_CODER_H +#define __COMPRESS_BCJ_CODER_H + +#include "../../../C/Bra.h" + +#include "BranchCoder.h" + +struct CBranch86 +{ + UInt32 _prevMask; + void x86Init() { x86_Convert_Init(_prevMask); } +}; + +MyClassB(BCJ_x86, 0x01, 3, CBranch86 , + virtual void SubInit() { x86Init(); }) + +#endif diff --git a/CPP/7zip/Compress/BcjRegister.cpp b/CPP/7zip/Compress/BcjRegister.cpp new file mode 100755 index 0000000..09e53c6 --- /dev/null +++ b/CPP/7zip/Compress/BcjRegister.cpp @@ -0,0 +1,19 @@ +// BcjRegister.cpp + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" + +#include "BcjCoder.h" + +static void *CreateCodec() { return (void *)(ICompressFilter *)(new CBCJ_x86_Decoder()); } +#ifndef EXTRACT_ONLY +static void *CreateCodecOut() { return (void *)(ICompressFilter *)(new CBCJ_x86_Encoder()); } +#else +#define CreateCodecOut 0 +#endif + +static CCodecInfo g_CodecInfo = + { CreateCodec, CreateCodecOut, 0x03030103, L"BCJ", 1, true }; + +REGISTER_CODEC(BCJ) diff --git a/CPP/7zip/Compress/BitlDecoder.cpp b/CPP/7zip/Compress/BitlDecoder.cpp new file mode 100755 index 0000000..6022e8b --- /dev/null +++ b/CPP/7zip/Compress/BitlDecoder.cpp @@ -0,0 +1,24 @@ +// BitlDecoder.cpp + +#include "StdAfx.h" + +#include "BitlDecoder.h" + +namespace NBitl { + +Byte kInvertTable[256]; + +struct CInverterTableInitializer +{ + CInverterTableInitializer() + { + for (int i = 0; i < 256; i++) + { + int x = ((i & 0x55) << 1) | ((i & 0xAA) >> 1); + x = ((x & 0x33) << 2) | ((x & 0xCC) >> 2); + kInvertTable[i] = (Byte)(((x & 0x0F) << 4) | ((x & 0xF0) >> 4)); + } + } +} g_InverterTableInitializer; + +} diff --git a/CPP/7zip/Compress/BitlDecoder.h b/CPP/7zip/Compress/BitlDecoder.h new file mode 100755 index 0000000..99ee24f --- /dev/null +++ b/CPP/7zip/Compress/BitlDecoder.h @@ -0,0 +1,141 @@ +// BitlDecoder.h -- the Least Significant Bit of byte is First + +#ifndef __BITL_DECODER_H +#define __BITL_DECODER_H + +#include "../IStream.h" + +namespace NBitl { + +const unsigned kNumBigValueBits = 8 * 4; +const unsigned kNumValueBytes = 3; +const unsigned kNumValueBits = 8 * kNumValueBytes; + +const UInt32 kMask = (1 << kNumValueBits) - 1; + +extern Byte kInvertTable[256]; + +template +class CBaseDecoder +{ +protected: + unsigned m_BitPos; + UInt32 m_Value; + TInByte m_Stream; +public: + UInt32 NumExtraBytes; + bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); } + void SetStream(ISequentialInStream *inStream) { m_Stream.SetStream(inStream); } + void ReleaseStream() { m_Stream.ReleaseStream(); } + void Init() + { + m_Stream.Init(); + m_BitPos = kNumBigValueBits; + m_Value = 0; + NumExtraBytes = 0; + } + UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() + NumExtraBytes - (kNumBigValueBits - m_BitPos) / 8; } + + void Normalize() + { + for (; m_BitPos >= 8; m_BitPos -= 8) + { + Byte b = 0; + if (!m_Stream.ReadByte(b)) + { + b = 0xFF; // check it + NumExtraBytes++; + } + m_Value = (b << (kNumBigValueBits - m_BitPos)) | m_Value; + } + } + + UInt32 ReadBits(unsigned numBits) + { + Normalize(); + UInt32 res = m_Value & ((1 << numBits) - 1); + m_BitPos += numBits; + m_Value >>= numBits; + return res; + } + + bool ExtraBitsWereRead() const + { + if (NumExtraBytes == 0) + return false; + return ((UInt32)(kNumBigValueBits - m_BitPos) < (NumExtraBytes << 3)); + } +}; + +template +class CDecoder: public CBaseDecoder +{ + UInt32 m_NormalValue; + +public: + void Init() + { + CBaseDecoder::Init(); + m_NormalValue = 0; + } + + void Normalize() + { + for (; this->m_BitPos >= 8; this->m_BitPos -= 8) + { + Byte b = 0; + if (!this->m_Stream.ReadByte(b)) + { + b = 0xFF; // check it + this->NumExtraBytes++; + } + m_NormalValue = (b << (kNumBigValueBits - this->m_BitPos)) | m_NormalValue; + this->m_Value = (this->m_Value << 8) | kInvertTable[b]; + } + } + + UInt32 GetValue(unsigned numBits) + { + Normalize(); + return ((this->m_Value >> (8 - this->m_BitPos)) & kMask) >> (kNumValueBits - numBits); + } + + void MovePos(unsigned numBits) + { + this->m_BitPos += numBits; + m_NormalValue >>= numBits; + } + + UInt32 ReadBits(unsigned numBits) + { + Normalize(); + UInt32 res = m_NormalValue & ((1 << numBits) - 1); + MovePos(numBits); + return res; + } + + void AlignToByte() { MovePos((32 - this->m_BitPos) & 7); } + + Byte ReadByte() + { + if (this->m_BitPos == kNumBigValueBits) + { + Byte b = 0; + if (!this->m_Stream.ReadByte(b)) + { + b = 0xFF; + this->NumExtraBytes++; + } + return b; + } + { + Byte b = (Byte)(m_NormalValue & 0xFF); + MovePos(8); + return b; + } + } +}; + +} + +#endif diff --git a/CPP/7zip/Compress/BitlEncoder.h b/CPP/7zip/Compress/BitlEncoder.h new file mode 100755 index 0000000..2169092 --- /dev/null +++ b/CPP/7zip/Compress/BitlEncoder.h @@ -0,0 +1,57 @@ +// BitlEncoder.h -- the Least Significant Bit of byte is First + +#ifndef __BITL_ENCODER_H +#define __BITL_ENCODER_H + +#include "../Common/OutBuffer.h" + +class CBitlEncoder +{ + COutBuffer m_Stream; + unsigned m_BitPos; + Byte m_CurByte; +public: + bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); } + void SetStream(ISequentialOutStream *outStream) { m_Stream.SetStream(outStream); } + void ReleaseStream() { m_Stream.ReleaseStream(); } + UInt32 GetBitPosition() const { return (8 - m_BitPos); } + UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() + (8 - m_BitPos + 7) /8; } + void Init() + { + m_Stream.Init(); + m_BitPos = 8; + m_CurByte = 0; + } + HRESULT Flush() + { + FlushByte(); + return m_Stream.Flush(); + } + void FlushByte() + { + if (m_BitPos < 8) + m_Stream.WriteByte(m_CurByte); + m_BitPos = 8; + m_CurByte = 0; + } + void WriteBits(UInt32 value, unsigned numBits) + { + while (numBits > 0) + { + if (numBits < m_BitPos) + { + m_CurByte |= (value & ((1 << numBits) - 1)) << (8 - m_BitPos); + m_BitPos -= numBits; + return; + } + numBits -= m_BitPos; + m_Stream.WriteByte((Byte)(m_CurByte | (value << (8 - m_BitPos)))); + value >>= m_BitPos; + m_BitPos = 8; + m_CurByte = 0; + } + } + void WriteByte(Byte b) { m_Stream.WriteByte(b);} +}; + +#endif diff --git a/CPP/7zip/Compress/BitmDecoder.h b/CPP/7zip/Compress/BitmDecoder.h new file mode 100755 index 0000000..e44dfe3 --- /dev/null +++ b/CPP/7zip/Compress/BitmDecoder.h @@ -0,0 +1,66 @@ +// BitmDecoder.h -- the Most Significant Bit of byte is First + +#ifndef __BITM_DECODER_H +#define __BITM_DECODER_H + +#include "../IStream.h" + +namespace NBitm { + +const unsigned kNumBigValueBits = 8 * 4; +const unsigned kNumValueBytes = 3; +const unsigned kNumValueBits = 8 * kNumValueBytes; + +const UInt32 kMask = (1 << kNumValueBits) - 1; + +template +class CDecoder +{ + unsigned m_BitPos; + UInt32 m_Value; +public: + TInByte m_Stream; + bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); } + void SetStream(ISequentialInStream *inStream) { m_Stream.SetStream(inStream);} + void ReleaseStream() { m_Stream.ReleaseStream();} + + void Init() + { + m_Stream.Init(); + m_BitPos = kNumBigValueBits; + Normalize(); + } + + UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() - (kNumBigValueBits - m_BitPos) / 8; } + + void Normalize() + { + for (;m_BitPos >= 8; m_BitPos -= 8) + m_Value = (m_Value << 8) | m_Stream.ReadByte(); + } + + UInt32 GetValue(unsigned numBits) const + { + // return (m_Value << m_BitPos) >> (kNumBigValueBits - numBits); + return ((m_Value >> (8 - m_BitPos)) & kMask) >> (kNumValueBits - numBits); + } + + void MovePos(unsigned numBits) + { + m_BitPos += numBits; + Normalize(); + } + + UInt32 ReadBits(unsigned numBits) + { + UInt32 res = GetValue(numBits); + MovePos(numBits); + return res; + } + + void AlignToByte() { MovePos((32 - m_BitPos) & 7); } +}; + +} + +#endif diff --git a/CPP/7zip/Compress/BitmEncoder.h b/CPP/7zip/Compress/BitmEncoder.h new file mode 100755 index 0000000..e7d7cc1 --- /dev/null +++ b/CPP/7zip/Compress/BitmEncoder.h @@ -0,0 +1,50 @@ +// BitmEncoder.h -- the Most Significant Bit of byte is First + +#ifndef __BITM_ENCODER_H +#define __BITM_ENCODER_H + +#include "../IStream.h" + +template +class CBitmEncoder +{ + TOutByte m_Stream; + unsigned m_BitPos; + Byte m_CurByte; +public: + bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); } + void SetStream(ISequentialOutStream *outStream) { m_Stream.SetStream(outStream);} + void ReleaseStream() { m_Stream.ReleaseStream(); } + UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() + (8 - m_BitPos + 7) / 8; } + void Init() + { + m_Stream.Init(); + m_BitPos = 8; + m_CurByte = 0; + } + HRESULT Flush() + { + if (m_BitPos < 8) + WriteBits(0, m_BitPos); + return m_Stream.Flush(); + } + void WriteBits(UInt32 value, unsigned numBits) + { + while (numBits > 0) + { + if (numBits < m_BitPos) + { + m_CurByte |= ((Byte)value << (m_BitPos -= numBits)); + return; + } + numBits -= m_BitPos; + UInt32 newBits = (value >> numBits); + value -= (newBits << numBits); + m_Stream.WriteByte((Byte)(m_CurByte | newBits)); + m_BitPos = 8; + m_CurByte = 0; + } + } +}; + +#endif diff --git a/CPP/7zip/Compress/BranchCoder.cpp b/CPP/7zip/Compress/BranchCoder.cpp new file mode 100755 index 0000000..6cacc66 --- /dev/null +++ b/CPP/7zip/Compress/BranchCoder.cpp @@ -0,0 +1,19 @@ +// BranchCoder.cpp + +#include "StdAfx.h" + +#include "BranchCoder.h" + +STDMETHODIMP CBranchConverter::Init() +{ + _bufferPos = 0; + SubInit(); + return S_OK; +} + +STDMETHODIMP_(UInt32) CBranchConverter::Filter(Byte *data, UInt32 size) +{ + UInt32 processedSize = SubFilter(data, size); + _bufferPos += processedSize; + return processedSize; +} diff --git a/CPP/7zip/Compress/BranchCoder.h b/CPP/7zip/Compress/BranchCoder.h new file mode 100755 index 0000000..473286a --- /dev/null +++ b/CPP/7zip/Compress/BranchCoder.h @@ -0,0 +1,44 @@ +// BranchCoder.h + +#ifndef __COMPRESS_BRANCH_CODER_H +#define __COMPRESS_BRANCH_CODER_H + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +class CBranchConverter: + public ICompressFilter, + public CMyUnknownImp +{ +protected: + UInt32 _bufferPos; + virtual void SubInit() {} + virtual UInt32 SubFilter(Byte *data, UInt32 size) = 0; +public: + MY_UNKNOWN_IMP; + STDMETHOD(Init)(); + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); +}; + +#define MyClassEncoderA(Name) class C ## Name: public CBranchConverter \ + { public: UInt32 SubFilter(Byte *data, UInt32 size); }; + +#define MyClassDecoderA(Name) class C ## Name: public CBranchConverter \ + { public: UInt32 SubFilter(Byte *data, UInt32 size); }; + +#define MyClassEncoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ + { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; + +#define MyClassDecoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ + { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; + +#define MyClassA(Name, id, subId) \ +MyClassEncoderA(Name ## _Encoder) \ +MyClassDecoderA(Name ## _Decoder) + +#define MyClassB(Name, id, subId, ADD_ITEMS, ADD_INIT) \ +MyClassEncoderB(Name ## _Encoder, ADD_ITEMS, ADD_INIT) \ +MyClassDecoderB(Name ## _Decoder, ADD_ITEMS, ADD_INIT) + +#endif diff --git a/CPP/7zip/Compress/BranchMisc.cpp b/CPP/7zip/Compress/BranchMisc.cpp new file mode 100755 index 0000000..1a46bb1 --- /dev/null +++ b/CPP/7zip/Compress/BranchMisc.cpp @@ -0,0 +1,37 @@ +// BranchMisc.cpp + +#include "StdAfx.h" + +#include "../../../C/Bra.h" + +#include "BranchMisc.h" + +UInt32 CBC_ARM_Encoder::SubFilter(Byte *data, UInt32 size) + { return (UInt32)::ARM_Convert(data, size, _bufferPos, 1); } + +UInt32 CBC_ARM_Decoder::SubFilter(Byte *data, UInt32 size) + { return (UInt32)::ARM_Convert(data, size, _bufferPos, 0); } + +UInt32 CBC_ARMT_Encoder::SubFilter(Byte *data, UInt32 size) + { return (UInt32)::ARMT_Convert(data, size, _bufferPos, 1); } + +UInt32 CBC_ARMT_Decoder::SubFilter(Byte *data, UInt32 size) + { return (UInt32)::ARMT_Convert(data, size, _bufferPos, 0); } + +UInt32 CBC_PPC_Encoder::SubFilter(Byte *data, UInt32 size) + { return (UInt32)::PPC_Convert(data, size, _bufferPos, 1); } + +UInt32 CBC_PPC_Decoder::SubFilter(Byte *data, UInt32 size) + { return (UInt32)::PPC_Convert(data, size, _bufferPos, 0); } + +UInt32 CBC_SPARC_Encoder::SubFilter(Byte *data, UInt32 size) + { return (UInt32)::SPARC_Convert(data, size, _bufferPos, 1); } + +UInt32 CBC_SPARC_Decoder::SubFilter(Byte *data, UInt32 size) + { return (UInt32)::SPARC_Convert(data, size, _bufferPos, 0); } + +UInt32 CBC_IA64_Encoder::SubFilter(Byte *data, UInt32 size) + { return (UInt32)::IA64_Convert(data, size, _bufferPos, 1); } + +UInt32 CBC_IA64_Decoder::SubFilter(Byte *data, UInt32 size) + { return (UInt32)::IA64_Convert(data, size, _bufferPos, 0); } diff --git a/CPP/7zip/Compress/BranchMisc.h b/CPP/7zip/Compress/BranchMisc.h new file mode 100755 index 0000000..053e923 --- /dev/null +++ b/CPP/7zip/Compress/BranchMisc.h @@ -0,0 +1,14 @@ +// BranchMisc.h + +#ifndef __COMPRESS_BRANCH_MISC_H +#define __COMPRESS_BRANCH_MISC_H + +#include "BranchCoder.h" + +MyClassA(BC_ARM, 0x05, 1) +MyClassA(BC_ARMT, 0x07, 1) +MyClassA(BC_PPC, 0x02, 5) +MyClassA(BC_SPARC, 0x08, 5) +MyClassA(BC_IA64, 0x04, 1) + +#endif diff --git a/CPP/7zip/Compress/BranchRegister.cpp b/CPP/7zip/Compress/BranchRegister.cpp new file mode 100755 index 0000000..bc55dd6 --- /dev/null +++ b/CPP/7zip/Compress/BranchRegister.cpp @@ -0,0 +1,30 @@ +// BranchRegister.cpp + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" + +#include "BranchMisc.h" + +#define CREATE_CODEC(x) \ + static void *CreateCodec ## x() { return (void *)(ICompressFilter *)(new C ## x ## _Decoder); } \ + static void *CreateCodec ## x ## Out() { return (void *)(ICompressFilter *)(new C ## x ## _Encoder); } + +CREATE_CODEC(BC_PPC) +CREATE_CODEC(BC_IA64) +CREATE_CODEC(BC_ARM) +CREATE_CODEC(BC_ARMT) +CREATE_CODEC(BC_SPARC) + +#define METHOD_ITEM(x, id1, id2, name) { CreateCodec ## x, CreateCodec ## x ## Out, 0x03030000 + (id1 * 256) + id2, name, 1, true } + +static CCodecInfo g_CodecsInfo[] = +{ + METHOD_ITEM(BC_PPC, 0x02, 0x05, L"PPC"), + METHOD_ITEM(BC_IA64, 0x04, 1, L"IA64"), + METHOD_ITEM(BC_ARM, 0x05, 1, L"ARM"), + METHOD_ITEM(BC_ARMT, 0x07, 1, L"ARMT"), + METHOD_ITEM(BC_SPARC, 0x08, 0x05, L"SPARC") +}; + +REGISTER_CODECS(Branch) diff --git a/CPP/7zip/Compress/ByteSwap.cpp b/CPP/7zip/Compress/ByteSwap.cpp new file mode 100755 index 0000000..7f028fb --- /dev/null +++ b/CPP/7zip/Compress/ByteSwap.cpp @@ -0,0 +1,73 @@ +// ByteSwap.cpp + +#include "StdAfx.h" + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +#include "../Common/RegisterCodec.h" + +class CByteSwap2: + public ICompressFilter, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP + STDMETHOD(Init)(); + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); +}; + +class CByteSwap4: + public ICompressFilter, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP + STDMETHOD(Init)(); + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); +}; + +STDMETHODIMP CByteSwap2::Init() { return S_OK; } + +STDMETHODIMP_(UInt32) CByteSwap2::Filter(Byte *data, UInt32 size) +{ + const UInt32 kStep = 2; + UInt32 i; + for (i = 0; i + kStep <= size; i += kStep) + { + Byte b = data[i]; + data[i] = data[i + 1]; + data[i + 1] = b; + } + return i; +} + +STDMETHODIMP CByteSwap4::Init() { return S_OK; } + +STDMETHODIMP_(UInt32) CByteSwap4::Filter(Byte *data, UInt32 size) +{ + const UInt32 kStep = 4; + UInt32 i; + for (i = 0; i + kStep <= size; i += kStep) + { + Byte b0 = data[i]; + Byte b1 = data[i + 1]; + data[i] = data[i + 3]; + data[i + 1] = data[i + 2]; + data[i + 2] = b1; + data[i + 3] = b0; + } + return i; +} + +static void *CreateCodec2() { return (void *)(ICompressFilter *)(new CByteSwap2); } +static void *CreateCodec4() { return (void *)(ICompressFilter *)(new CByteSwap4); } + +static CCodecInfo g_CodecsInfo[] = +{ + { CreateCodec2, CreateCodec2, 0x020302, L"Swap2", 1, true }, + { CreateCodec4, CreateCodec4, 0x020304, L"Swap4", 1, true } +}; + +REGISTER_CODECS(ByteSwap) diff --git a/CPP/7zip/Compress/Codec.def b/CPP/7zip/Compress/Codec.def new file mode 100755 index 0000000..aab87ef --- /dev/null +++ b/CPP/7zip/Compress/Codec.def @@ -0,0 +1,4 @@ +EXPORTS + CreateObject PRIVATE + GetNumberOfMethods PRIVATE + GetMethodProperty PRIVATE diff --git a/CPP/7zip/Compress/CodecExports.cpp b/CPP/7zip/Compress/CodecExports.cpp new file mode 100755 index 0000000..84a27cf --- /dev/null +++ b/CPP/7zip/Compress/CodecExports.cpp @@ -0,0 +1,160 @@ +// CodecExports.cpp + +#include "StdAfx.h" + +#include "../../Common/ComTry.h" + +#include "../../Windows/PropVariant.h" + +#include "../ICoder.h" + +#include "../Common/RegisterCodec.h" + +extern unsigned int g_NumCodecs; +extern const CCodecInfo *g_Codecs[]; + +static const UInt16 kDecodeId = 0x2790; + +DEFINE_GUID(CLSID_CCodec, +0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + +static inline HRESULT SetPropString(const char *s, unsigned int 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 SetPropString((const char *)&guid, sizeof(GUID), value); +} + +static HRESULT SetClassID(CMethodId id, bool encode, PROPVARIANT *value) +{ + GUID clsId = CLSID_CCodec; + for (int i = 0; i < sizeof(id); i++, id >>= 8) + clsId.Data4[i] = (Byte)(id & 0xFF); + if (encode) + clsId.Data3++; + return SetPropGUID(clsId, value); +} + +static HRESULT FindCodecClassId(const GUID *clsID, UInt32 isCoder2, bool isFilter, bool &encode, int &index) +{ + index = -1; + if (clsID->Data1 != CLSID_CCodec.Data1 || + clsID->Data2 != CLSID_CCodec.Data2 || + (clsID->Data3 & ~1) != kDecodeId) + return S_OK; + encode = (clsID->Data3 != kDecodeId); + UInt64 id = 0; + for (int j = 0; j < 8; j++) + id |= ((UInt64)clsID->Data4[j]) << (8 * j); + for (unsigned i = 0; i < g_NumCodecs; i++) + { + const CCodecInfo &codec = *g_Codecs[i]; + if (id != codec.Id || encode && !codec.CreateEncoder || !encode && !codec.CreateDecoder) + continue; + if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter || + codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2) + return E_NOINTERFACE; + index = i; + return S_OK; + } + return S_OK; +} + +STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject) +{ + COM_TRY_BEGIN + *outObject = 0; + bool isCoder = (*iid == IID_ICompressCoder) != 0; + bool isCoder2 = (*iid == IID_ICompressCoder2) != 0; + bool isFilter = (*iid == IID_ICompressFilter) != 0; + const CCodecInfo &codec = *g_Codecs[index]; + if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter || + codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2) + return E_NOINTERFACE; + if (encode) + { + if (!codec.CreateEncoder) + return CLASS_E_CLASSNOTAVAILABLE; + *outObject = codec.CreateEncoder(); + } + else + { + if (!codec.CreateDecoder) + return CLASS_E_CLASSNOTAVAILABLE; + *outObject = codec.CreateDecoder(); + } + if (isCoder) + ((ICompressCoder *)*outObject)->AddRef(); + else if (isCoder2) + ((ICompressCoder2 *)*outObject)->AddRef(); + else + ((ICompressFilter *)*outObject)->AddRef(); + return S_OK; + COM_TRY_END +} + +STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject) +{ + *outObject = 0; + bool isCoder = (*iid == IID_ICompressCoder) != 0; + bool isCoder2 = (*iid == IID_ICompressCoder2) != 0; + bool isFilter = (*iid == IID_ICompressFilter) != 0; + if (!isCoder && !isCoder2 && !isFilter) + return E_NOINTERFACE; + 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 CreateCoder2(encode, codecIndex, iid, 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: + if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0) + value->vt = VT_BSTR; + break; + case NMethodPropID::kDecoder: + if (codec.CreateDecoder) + return SetClassID(codec.Id, false, value); + break; + case NMethodPropID::kEncoder: + if (codec.CreateEncoder) + return SetClassID(codec.Id, true, value); + break; + case NMethodPropID::kInStreams: + { + if (codec.NumInStreams != 1) + { + value->vt = VT_UI4; + value->ulVal = (ULONG)codec.NumInStreams; + } + break; + } + } + return S_OK; +} + +STDAPI GetNumberOfMethods(UINT32 *numCodecs) +{ + *numCodecs = g_NumCodecs; + return S_OK; +} diff --git a/CPP/7zip/Compress/CopyCoder.cpp b/CPP/7zip/Compress/CopyCoder.cpp new file mode 100755 index 0000000..da15d04 --- /dev/null +++ b/CPP/7zip/Compress/CopyCoder.cpp @@ -0,0 +1,67 @@ +// Compress/CopyCoder.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "../Common/StreamUtils.h" + +#include "CopyCoder.h" + +namespace NCompress { + +static const UInt32 kBufferSize = 1 << 17; + +CCopyCoder::~CCopyCoder() +{ + ::MidFree(_buffer); +} + +STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 *outSize, + ICompressProgressInfo *progress) +{ + if (_buffer == 0) + { + _buffer = (Byte *)::MidAlloc(kBufferSize); + if (_buffer == 0) + return E_OUTOFMEMORY; + } + + TotalSize = 0; + for (;;) + { + UInt32 size = kBufferSize; + if (outSize != 0) + if (size > *outSize - TotalSize) + size = (UInt32)(*outSize - TotalSize); + RINOK(inStream->Read(_buffer, size, &size)); + if (size == 0) + break; + if (outStream) + { + RINOK(WriteStream(outStream, _buffer, size)); + } + TotalSize += size; + if (progress != NULL) + { + RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize)); + } + } + return S_OK; +} + +STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value) +{ + *value = TotalSize; + return S_OK; +} + +HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress) +{ + CMyComPtr copyCoder = new NCompress::CCopyCoder; + return copyCoder->Code(inStream, outStream, NULL, NULL, progress); +} + +} diff --git a/CPP/7zip/Compress/CopyCoder.h b/CPP/7zip/Compress/CopyCoder.h new file mode 100755 index 0000000..16c42ee --- /dev/null +++ b/CPP/7zip/Compress/CopyCoder.h @@ -0,0 +1,34 @@ +// 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 ICompressGetInStreamProcessedSize, + public CMyUnknownImp +{ + Byte *_buffer; +public: + UInt64 TotalSize; + CCopyCoder(): TotalSize(0), _buffer(0) {}; + ~CCopyCoder(); + + MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize) + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); +}; + +HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress); + +} + +#endif diff --git a/CPP/7zip/Compress/CopyRegister.cpp b/CPP/7zip/Compress/CopyRegister.cpp new file mode 100755 index 0000000..3ef2459 --- /dev/null +++ b/CPP/7zip/Compress/CopyRegister.cpp @@ -0,0 +1,14 @@ +// CopyRegister.cpp + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" + +#include "CopyCoder.h" + +static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::CCopyCoder); } + +static CCodecInfo g_CodecInfo = +{ CreateCodec, CreateCodec, 0x00, L"Copy", 1, false }; + +REGISTER_CODEC(Copy) diff --git a/CPP/7zip/Compress/Deflate64Register.cpp b/CPP/7zip/Compress/Deflate64Register.cpp new file mode 100755 index 0000000..6d6a904 --- /dev/null +++ b/CPP/7zip/Compress/Deflate64Register.cpp @@ -0,0 +1,20 @@ +// Deflate64Register.cpp + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" + +#include "DeflateDecoder.h" + +static void *CreateCodecDeflate64() { return (void *)(ICompressCoder *)(new NCompress::NDeflate::NDecoder::CCOMCoder64); } +#if !defined(EXTRACT_ONLY) && !defined(DEFLATE_EXTRACT_ONLY) +#include "DeflateEncoder.h" +static void *CreateCodecOutDeflate64() { return (void *)(ICompressCoder *)(new NCompress::NDeflate::NEncoder::CCOMCoder64); } +#else +#define CreateCodecOutDeflate64 0 +#endif + +static CCodecInfo g_CodecInfo = + { CreateCodecDeflate64, CreateCodecOutDeflate64, 0x040109, L"Deflate64", 1, false }; + +REGISTER_CODEC(Deflate64) diff --git a/CPP/7zip/Compress/DeflateConst.h b/CPP/7zip/Compress/DeflateConst.h new file mode 100755 index 0000000..b5c28d7 --- /dev/null +++ b/CPP/7zip/Compress/DeflateConst.h @@ -0,0 +1,134 @@ +// DeflateConst.h + +#ifndef __DEFLATE_CONST_H +#define __DEFLATE_CONST_H + +namespace NCompress { +namespace NDeflate { + +const int kNumHuffmanBits = 15; + +const UInt32 kHistorySize32 = (1 << 15); +const UInt32 kHistorySize64 = (1 << 16); + +const UInt32 kDistTableSize32 = 30; +const UInt32 kDistTableSize64 = 32; + +const UInt32 kNumLenSymbols32 = 256; +const UInt32 kNumLenSymbols64 = 255; // don't change it. It must be <= 255. +const UInt32 kNumLenSymbolsMax = kNumLenSymbols32; + +const UInt32 kNumLenSlots = 29; + +const UInt32 kFixedDistTableSize = 32; +const UInt32 kFixedLenTableSize = 31; + +const UInt32 kSymbolEndOfBlock = 0x100; +const UInt32 kSymbolMatch = kSymbolEndOfBlock + 1; + +const UInt32 kMainTableSize = kSymbolMatch + kNumLenSlots; +const UInt32 kFixedMainTableSize = kSymbolMatch + kFixedLenTableSize; + +const UInt32 kLevelTableSize = 19; + +const UInt32 kTableDirectLevels = 16; +const UInt32 kTableLevelRepNumber = kTableDirectLevels; +const UInt32 kTableLevel0Number = kTableLevelRepNumber + 1; +const UInt32 kTableLevel0Number2 = kTableLevel0Number + 1; + +const UInt32 kLevelMask = 0xF; + +const Byte kLenStart32[kFixedLenTableSize] = + {0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224, 255, 0, 0}; +const Byte kLenStart64[kFixedLenTableSize] = + {0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224, 0, 0, 0}; + +const Byte kLenDirectBits32[kFixedLenTableSize] = + {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0}; +const Byte kLenDirectBits64[kFixedLenTableSize] = + {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 16, 0, 0}; + +const UInt32 kDistStart[kDistTableSize64] = + {0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768, + 1024,1536,2048,3072,4096,6144,8192,12288,16384,24576,32768,49152}; +const Byte kDistDirectBits[kDistTableSize64] = + {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14}; + +const Byte kLevelDirectBits[3] = {2, 3, 7}; + +const Byte kCodeLengthAlphabetOrder[kLevelTableSize] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + +const UInt32 kMatchMinLen = 3; +const UInt32 kMatchMaxLen32 = kNumLenSymbols32 + kMatchMinLen - 1; //256 + 2 +const UInt32 kMatchMaxLen64 = kNumLenSymbols64 + kMatchMinLen - 1; //255 + 2 +const UInt32 kMatchMaxLen = kMatchMaxLen32; + +const int kFinalBlockFieldSize = 1; + +namespace NFinalBlockField +{ + enum + { + kNotFinalBlock = 0, + kFinalBlock = 1 + }; +} + +const int kBlockTypeFieldSize = 2; + +namespace NBlockType +{ + enum + { + kStored = 0, + kFixedHuffman = 1, + kDynamicHuffman = 2 + }; +} + +const int kNumLenCodesFieldSize = 5; +const int kNumDistCodesFieldSize = 5; +const int kNumLevelCodesFieldSize = 4; + +const UInt32 kNumLitLenCodesMin = 257; +const UInt32 kNumDistCodesMin = 1; +const UInt32 kNumLevelCodesMin = 4; + +const int kLevelFieldSize = 3; + +const int kStoredBlockLengthFieldSize = 16; + +struct CLevels +{ + Byte litLenLevels[kFixedMainTableSize]; + Byte distLevels[kFixedDistTableSize]; + + void SubClear() + { + UInt32 i; + for(i = kNumLitLenCodesMin; i < kFixedMainTableSize; i++) + litLenLevels[i] = 0; + for(i = 0; i < kFixedDistTableSize; i++) + distLevels[i] = 0; + } + + void SetFixedLevels() + { + int i; + + for (i = 0; i < 144; i++) + litLenLevels[i] = 8; + for (; i < 256; i++) + litLenLevels[i] = 9; + for (; i < 280; i++) + litLenLevels[i] = 7; + for (; i < 288; i++) + litLenLevels[i] = 8; + for (i = 0; i < kFixedDistTableSize; i++) // test it: InfoZip only uses kDistTableSize + distLevels[i] = 5; + } +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/DeflateDecoder.cpp b/CPP/7zip/Compress/DeflateDecoder.cpp new file mode 100755 index 0000000..1f1f333 --- /dev/null +++ b/CPP/7zip/Compress/DeflateDecoder.cpp @@ -0,0 +1,353 @@ +// DeflateDecoder.cpp + +#include "StdAfx.h" + +#include "DeflateDecoder.h" + +namespace NCompress { +namespace NDeflate { +namespace NDecoder { + +static const int kLenIdFinished = -1; +static const int kLenIdNeedInit = -2; + +CCoder::CCoder(bool deflate64Mode, bool deflateNSIS): + _deflate64Mode(deflate64Mode), + _deflateNSIS(deflateNSIS), + _keepHistory(false), + _needInitInStream(true), + ZlibMode(false) {} + +UInt32 CCoder::ReadBits(int numBits) +{ + return m_InBitStream.ReadBits(numBits); +} + +bool CCoder::DeCodeLevelTable(Byte *values, int numSymbols) +{ + int i = 0; + do + { + UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream); + if (number < kTableDirectLevels) + values[i++] = (Byte)number; + else if (number < kLevelTableSize) + { + if (number == kTableLevelRepNumber) + { + if (i == 0) + return false; + int num = ReadBits(2) + 3; + for (; num > 0 && i < numSymbols; num--, i++) + values[i] = values[i - 1]; + } + else + { + int num; + if (number == kTableLevel0Number) + num = ReadBits(3) + 3; + else + num = ReadBits(7) + 11; + for (;num > 0 && i < numSymbols; num--) + values[i++] = 0; + } + } + else + return false; + } + while(i < numSymbols); + return true; +} + +#define RIF(x) { if (!(x)) return false; } + +bool CCoder::ReadTables(void) +{ + m_FinalBlock = (ReadBits(kFinalBlockFieldSize) == NFinalBlockField::kFinalBlock); + UInt32 blockType = ReadBits(kBlockTypeFieldSize); + if (blockType > NBlockType::kDynamicHuffman) + return false; + + if (blockType == NBlockType::kStored) + { + m_StoredMode = true; + m_InBitStream.AlignToByte(); + m_StoredBlockSize = ReadBits(kStoredBlockLengthFieldSize); + if (_deflateNSIS) + return true; + return (m_StoredBlockSize == (UInt16)~ReadBits(kStoredBlockLengthFieldSize)); + } + + m_StoredMode = false; + + CLevels levels; + if (blockType == NBlockType::kFixedHuffman) + { + levels.SetFixedLevels(); + _numDistLevels = _deflate64Mode ? kDistTableSize64 : kDistTableSize32; + } + else + { + int numLitLenLevels = ReadBits(kNumLenCodesFieldSize) + kNumLitLenCodesMin; + _numDistLevels = ReadBits(kNumDistCodesFieldSize) + kNumDistCodesMin; + int numLevelCodes = ReadBits(kNumLevelCodesFieldSize) + kNumLevelCodesMin; + + if (!_deflate64Mode) + if (_numDistLevels > kDistTableSize32) + return false; + + Byte levelLevels[kLevelTableSize]; + for (int i = 0; i < kLevelTableSize; i++) + { + int position = kCodeLengthAlphabetOrder[i]; + if(i < numLevelCodes) + levelLevels[position] = (Byte)ReadBits(kLevelFieldSize); + else + levelLevels[position] = 0; + } + + RIF(m_LevelDecoder.SetCodeLengths(levelLevels)); + + Byte tmpLevels[kFixedMainTableSize + kFixedDistTableSize]; + if (!DeCodeLevelTable(tmpLevels, numLitLenLevels + _numDistLevels)) + return false; + + levels.SubClear(); + memcpy(levels.litLenLevels, tmpLevels, numLitLenLevels); + memcpy(levels.distLevels, tmpLevels + numLitLenLevels, _numDistLevels); + } + RIF(m_MainDecoder.SetCodeLengths(levels.litLenLevels)); + return m_DistDecoder.SetCodeLengths(levels.distLevels); +} + +HRESULT CCoder::CodeSpec(UInt32 curSize) +{ + if (_remainLen == kLenIdFinished) + return S_OK; + if (_remainLen == kLenIdNeedInit) + { + if (!_keepHistory) + if (!m_OutWindowStream.Create(_deflate64Mode ? kHistorySize64: kHistorySize32)) + return E_OUTOFMEMORY; + RINOK(InitInStream(_needInitInStream)); + m_OutWindowStream.Init(_keepHistory); + m_FinalBlock = false; + _remainLen = 0; + _needReadTable = true; + } + + if (curSize == 0) + return S_OK; + + while(_remainLen > 0 && curSize > 0) + { + _remainLen--; + Byte b = m_OutWindowStream.GetByte(_rep0); + m_OutWindowStream.PutByte(b); + curSize--; + } + + while(curSize > 0) + { + if (_needReadTable) + { + if (m_FinalBlock) + { + _remainLen = kLenIdFinished; + break; + } + if (!ReadTables()) + return S_FALSE; + _needReadTable = false; + } + + if(m_StoredMode) + { + for (; m_StoredBlockSize > 0 && curSize > 0; m_StoredBlockSize--, curSize--) + m_OutWindowStream.PutByte(m_InBitStream.ReadByte()); + _needReadTable = (m_StoredBlockSize == 0); + continue; + } + while(curSize > 0) + { + if (m_InBitStream.NumExtraBytes > 4) + return S_FALSE; + + UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream); + if (number < 0x100) + { + m_OutWindowStream.PutByte((Byte)number); + curSize--; + continue; + } + else if (number == kSymbolEndOfBlock) + { + _needReadTable = true; + break; + } + else if (number < kMainTableSize) + { + number -= kSymbolMatch; + UInt32 len; + { + int numBits; + if (_deflate64Mode) + { + len = kLenStart64[number]; + numBits = kLenDirectBits64[number]; + } + else + { + len = kLenStart32[number]; + numBits = kLenDirectBits32[number]; + } + len += kMatchMinLen + m_InBitStream.ReadBits(numBits); + } + UInt32 locLen = len; + if (locLen > curSize) + locLen = (UInt32)curSize; + number = m_DistDecoder.DecodeSymbol(&m_InBitStream); + if (number >= _numDistLevels) + return S_FALSE; + UInt32 distance = kDistStart[number] + m_InBitStream.ReadBits(kDistDirectBits[number]); + if (!m_OutWindowStream.CopyBlock(distance, locLen)) + return S_FALSE; + curSize -= locLen; + len -= locLen; + if (len != 0) + { + _remainLen = (Int32)len; + _rep0 = distance; + break; + } + } + else + return S_FALSE; + } + } + return S_OK; +} + +#ifdef _NO_EXCEPTIONS + +#define DEFLATE_TRY_BEGIN +#define DEFLATE_TRY_END + +#else + +#define DEFLATE_TRY_BEGIN try { +#define DEFLATE_TRY_END } \ + catch(const CInBufferException &e) { return e.ErrorCode; } \ + catch(const CLzOutWindowException &e) { return e.ErrorCode; } \ + catch(...) { return S_FALSE; } + +#endif + +HRESULT CCoder::CodeReal(ISequentialOutStream *outStream, + const UInt64 *outSize, ICompressProgressInfo *progress) +{ + DEFLATE_TRY_BEGIN + m_OutWindowStream.SetStream(outStream); + CCoderReleaser flusher(this); + + const UInt64 inStart = _needInitInStream ? 0 : m_InBitStream.GetProcessedSize(); + const UInt64 start = m_OutWindowStream.GetProcessedSize(); + for (;;) + { + UInt32 curSize = 1 << 18; + if (outSize != 0) + { + const UInt64 rem = *outSize - (m_OutWindowStream.GetProcessedSize() - start); + if (curSize > rem) + curSize = (UInt32)rem; + } + if (curSize == 0) + break; + RINOK(CodeSpec(curSize)); + if (_remainLen == kLenIdFinished) + break; + if (progress != NULL) + { + const UInt64 inSize = m_InBitStream.GetProcessedSize() - inStart; + const UInt64 nowPos64 = m_OutWindowStream.GetProcessedSize() - start; + RINOK(progress->SetRatioInfo(&inSize, &nowPos64)); + } + } + if (_remainLen == kLenIdFinished && ZlibMode) + { + m_InBitStream.AlignToByte(); + for (int i = 0; i < 4; i++) + ZlibFooter[i] = m_InBitStream.ReadByte(); + } + flusher.NeedFlush = false; + HRESULT res = Flush(); + if (res == S_OK && InputEofError()) + return S_FALSE; + return res; + DEFLATE_TRY_END +} + +HRESULT CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + SetInStream(inStream); + SetOutStreamSize(outSize); + HRESULT res = CodeReal(outStream, outSize, progress); + ReleaseInStream(); + return res; +} + +STDMETHODIMP CCoder::GetInStreamProcessedSize(UInt64 *value) +{ + if (value == NULL) + return E_INVALIDARG; + *value = m_InBitStream.GetProcessedSize(); + return S_OK; +} + +STDMETHODIMP CCoder::SetInStream(ISequentialInStream *inStream) +{ + m_InBitStream.SetStream(inStream); + return S_OK; +} + +STDMETHODIMP CCoder::ReleaseInStream() +{ + m_InBitStream.ReleaseStream(); + return S_OK; +} + +STDMETHODIMP CCoder::SetOutStreamSize(const UInt64 * /* outSize */) +{ + _remainLen = kLenIdNeedInit; + _needInitInStream = true; + m_OutWindowStream.Init(_keepHistory); + return S_OK; +} + +#ifndef NO_READ_FROM_CODER + +STDMETHODIMP CCoder::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + DEFLATE_TRY_BEGIN + if (processedSize) + *processedSize = 0; + const UInt64 startPos = m_OutWindowStream.GetProcessedSize(); + m_OutWindowStream.SetMemStream((Byte *)data); + RINOK(CodeSpec(size)); + if (processedSize) + *processedSize = (UInt32)(m_OutWindowStream.GetProcessedSize() - startPos); + return Flush(); + DEFLATE_TRY_END +} + +#endif + +STDMETHODIMP CCoder::CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + _remainLen = kLenIdNeedInit; + m_OutWindowStream.Init(_keepHistory); + return CodeReal(outStream, outSize, progress); +} + +}}} diff --git a/CPP/7zip/Compress/DeflateDecoder.h b/CPP/7zip/Compress/DeflateDecoder.h new file mode 100755 index 0000000..1cc5890 --- /dev/null +++ b/CPP/7zip/Compress/DeflateDecoder.h @@ -0,0 +1,157 @@ +// DeflateDecoder.h + +#ifndef __DEFLATE_DECODER_H +#define __DEFLATE_DECODER_H + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +#include "../Common/InBuffer.h" + +#include "BitlDecoder.h" +#include "DeflateConst.h" +#include "HuffmanDecoder.h" +#include "LzOutWindow.h" + +namespace NCompress { +namespace NDeflate { +namespace NDecoder { + +class CCoder: + public ICompressCoder, + public ICompressGetInStreamProcessedSize, + #ifndef NO_READ_FROM_CODER + public ICompressSetInStream, + public ICompressSetOutStreamSize, + public ISequentialInStream, + #endif + public CMyUnknownImp +{ + CLzOutWindow m_OutWindowStream; + NBitl::CDecoder m_InBitStream; + NCompress::NHuffman::CDecoder m_MainDecoder; + NCompress::NHuffman::CDecoder m_DistDecoder; + NCompress::NHuffman::CDecoder m_LevelDecoder; + + UInt32 m_StoredBlockSize; + + bool m_FinalBlock; + bool m_StoredMode; + UInt32 _numDistLevels; + + + bool _deflateNSIS; + bool _deflate64Mode; + bool _keepHistory; + bool _needInitInStream; + Int32 _remainLen; + UInt32 _rep0; + bool _needReadTable; + + UInt32 ReadBits(int numBits); + + bool DeCodeLevelTable(Byte *values, int numSymbols); + bool ReadTables(); + + HRESULT Flush() { return m_OutWindowStream.Flush(); } + class CCoderReleaser + { + CCoder *_coder; + public: + bool NeedFlush; + CCoderReleaser(CCoder *coder): _coder(coder), NeedFlush(true) {} + ~CCoderReleaser() + { + if (NeedFlush) + _coder->Flush(); + _coder->ReleaseOutStream(); + } + }; + friend class CCoderReleaser; + + HRESULT CodeSpec(UInt32 curSize); +public: + bool ZlibMode; + Byte ZlibFooter[4]; + + CCoder(bool deflate64Mode, bool deflateNSIS = false); + virtual ~CCoder() {}; + + void SetKeepHistory(bool keepHistory) { _keepHistory = keepHistory; } + + void ReleaseOutStream() + { + m_OutWindowStream.ReleaseStream(); + } + + HRESULT CodeReal(ISequentialOutStream *outStream, + const UInt64 *outSize, ICompressProgressInfo *progress); + + #ifndef NO_READ_FROM_CODER + MY_UNKNOWN_IMP4( + ICompressGetInStreamProcessedSize, + ICompressSetInStream, + ICompressSetOutStreamSize, + ISequentialInStream + ) + #else + MY_UNKNOWN_IMP1( + ICompressGetInStreamProcessedSize) + #endif + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + + STDMETHOD(SetInStream)(ISequentialInStream *inStream); + STDMETHOD(ReleaseInStream)(); + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); + + #ifndef NO_READ_FROM_CODER + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + #endif + + STDMETHOD(CodeResume)(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress); + + HRESULT InitInStream(bool needInit) + { + if (!m_InBitStream.Create(1 << 17)) + return E_OUTOFMEMORY; + if (needInit) + { + m_InBitStream.Init(); + _needInitInStream = false; + } + return S_OK; + } + + void AlignToByte() { m_InBitStream.AlignToByte(); } + Byte ReadByte() { return (Byte)m_InBitStream.ReadBits(8); } + bool InputEofError() const { return m_InBitStream.ExtraBitsWereRead(); } + UInt64 GetInputProcessedSize() const { return m_InBitStream.GetProcessedSize(); } + + // IGetInStreamProcessedSize + STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); +}; + +class CCOMCoder : public CCoder +{ +public: + CCOMCoder(): CCoder(false) {} +}; + +class CNsisCOMCoder : public CCoder +{ +public: + CNsisCOMCoder(): CCoder(false, true) {} +}; + +class CCOMCoder64 : public CCoder +{ +public: + CCOMCoder64(): CCoder(true) {} +}; + +}}} + +#endif diff --git a/CPP/7zip/Compress/DeflateEncoder.cpp b/CPP/7zip/Compress/DeflateEncoder.cpp new file mode 100755 index 0000000..f2a51f1 --- /dev/null +++ b/CPP/7zip/Compress/DeflateEncoder.cpp @@ -0,0 +1,986 @@ +// DeflateEncoder.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" +#include "../../../C/HuffEnc.h" + +#include "Common/ComTry.h" + +#include "DeflateEncoder.h" + +#undef NO_INLINE + +#ifdef _MSC_VER +#define NO_INLINE MY_NO_INLINE +#else +#define NO_INLINE +#endif + +namespace NCompress { +namespace NDeflate { +namespace NEncoder { + +const int kNumDivPassesMax = 10; // [0, 16); ratio/speed/ram tradeoff; use big value for better compression ratio. +const UInt32 kNumTables = (1 << kNumDivPassesMax); + +static UInt32 kFixedHuffmanCodeBlockSizeMax = (1 << 8); // [0, (1 << 32)); ratio/speed tradeoff; use big value for better compression ratio. +static UInt32 kDivideCodeBlockSizeMin = (1 << 7); // [1, (1 << 32)); ratio/speed tradeoff; use small value for better compression ratio. +static UInt32 kDivideBlockSizeMin = (1 << 6); // [1, (1 << 32)); ratio/speed tradeoff; use small value for better compression ratio. + +static const UInt32 kMaxUncompressedBlockSize = ((1 << 16) - 1) * 1; // [1, (1 << 32)) +static const UInt32 kMatchArraySize = kMaxUncompressedBlockSize * 10; // [kMatchMaxLen * 2, (1 << 32)) +static const UInt32 kMatchArrayLimit = kMatchArraySize - kMatchMaxLen * 4 * sizeof(UInt16); +static const UInt32 kBlockUncompressedSizeThreshold = kMaxUncompressedBlockSize - + kMatchMaxLen - kNumOpts; + +static const int kMaxCodeBitLength = 11; +static const int kMaxLevelBitLength = 7; + +static Byte kNoLiteralStatPrice = 11; +static Byte kNoLenStatPrice = 11; +static Byte kNoPosStatPrice = 6; + +static Byte g_LenSlots[kNumLenSymbolsMax]; +static Byte g_FastPos[1 << 9]; + +class CFastPosInit +{ +public: + CFastPosInit() + { + int i; + for(i = 0; i < kNumLenSlots; i++) + { + int c = kLenStart32[i]; + int j = 1 << kLenDirectBits32[i]; + for(int k = 0; k < j; k++, c++) + g_LenSlots[c] = (Byte)i; + } + + const int kFastSlots = 18; + int c = 0; + for (Byte slotFast = 0; slotFast < kFastSlots; slotFast++) + { + UInt32 k = (1 << kDistDirectBits[slotFast]); + for (UInt32 j = 0; j < k; j++, c++) + g_FastPos[c] = slotFast; + } + } +}; + +static CFastPosInit g_FastPosInit; + + +inline UInt32 GetPosSlot(UInt32 pos) +{ + if (pos < 0x200) + return g_FastPos[pos]; + return g_FastPos[pos >> 8] + 16; +} + +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } +static void SzFree(void *p, void *address) { p = p; MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +CCoder::CCoder(bool deflate64Mode): + m_Deflate64Mode(deflate64Mode), + m_NumPasses(1), + m_NumDivPasses(1), + m_NumFastBytes(32), + _fastMode(false), + _btMode(true), + m_OnePosMatchesMemory(0), + m_DistanceMemory(0), + m_Created(false), + m_Values(0), + m_Tables(0), + m_MatchFinderCycles(0) + // m_SetMfPasses(0) +{ + m_MatchMaxLen = deflate64Mode ? kMatchMaxLen64 : kMatchMaxLen32; + m_NumLenCombinations = deflate64Mode ? kNumLenSymbols64 : kNumLenSymbols32; + m_LenStart = deflate64Mode ? kLenStart64 : kLenStart32; + m_LenDirectBits = deflate64Mode ? kLenDirectBits64 : kLenDirectBits32; + MatchFinder_Construct(&_lzInWindow); +} + +HRESULT CCoder::Create() +{ + COM_TRY_BEGIN + if (m_Values == 0) + { + m_Values = (CCodeValue *)MyAlloc((kMaxUncompressedBlockSize) * sizeof(CCodeValue)); + if (m_Values == 0) + return E_OUTOFMEMORY; + } + if (m_Tables == 0) + { + m_Tables = (CTables *)MyAlloc((kNumTables) * sizeof(CTables)); + if (m_Tables == 0) + return E_OUTOFMEMORY; + } + + if (m_IsMultiPass) + { + if (m_OnePosMatchesMemory == 0) + { + m_OnePosMatchesMemory = (UInt16 *)::MidAlloc(kMatchArraySize * sizeof(UInt16)); + if (m_OnePosMatchesMemory == 0) + return E_OUTOFMEMORY; + } + } + else + { + if (m_DistanceMemory == 0) + { + m_DistanceMemory = (UInt16 *)MyAlloc((kMatchMaxLen + 2) * 2 * sizeof(UInt16)); + if (m_DistanceMemory == 0) + return E_OUTOFMEMORY; + m_MatchDistances = m_DistanceMemory; + } + } + + if (!m_Created) + { + _lzInWindow.btMode = _btMode ? 1 : 0; + _lzInWindow.numHashBytes = 3; + if (!MatchFinder_Create(&_lzInWindow, + m_Deflate64Mode ? kHistorySize64 : kHistorySize32, + kNumOpts + kMaxUncompressedBlockSize, + m_NumFastBytes, m_MatchMaxLen - m_NumFastBytes, &g_Alloc)) + return E_OUTOFMEMORY; + if (!m_OutStream.Create(1 << 20)) + return E_OUTOFMEMORY; + } + if (m_MatchFinderCycles != 0) + _lzInWindow.cutValue = m_MatchFinderCycles; + m_Created = true; + return S_OK; + COM_TRY_END +} + +HRESULT CCoder::BaseSetEncoderProperties2(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) +{ + for (UInt32 i = 0; i < numProps; i++) + { + const PROPVARIANT &prop = props[i]; + switch(propIDs[i]) + { + case NCoderPropID::kNumPasses: + if (prop.vt != VT_UI4) + return E_INVALIDARG; + m_NumDivPasses = prop.ulVal; + if (m_NumDivPasses == 0) + m_NumDivPasses = 1; + if (m_NumDivPasses == 1) + m_NumPasses = 1; + else if (m_NumDivPasses <= kNumDivPassesMax) + m_NumPasses = 2; + else + { + m_NumPasses = 2 + (m_NumDivPasses - kNumDivPassesMax); + m_NumDivPasses = kNumDivPassesMax; + } + break; + case NCoderPropID::kNumFastBytes: + if (prop.vt != VT_UI4) + return E_INVALIDARG; + m_NumFastBytes = prop.ulVal; + if(m_NumFastBytes < kMatchMinLen || m_NumFastBytes > m_MatchMaxLen) + return E_INVALIDARG; + break; + case NCoderPropID::kMatchFinderCycles: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + m_MatchFinderCycles = prop.ulVal; + break; + } + case NCoderPropID::kAlgorithm: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 maximize = prop.ulVal; + _fastMode = (maximize == 0); + _btMode = !_fastMode; + break; + } + default: + return E_INVALIDARG; + } + } + return S_OK; +} + +void CCoder::Free() +{ + ::MidFree(m_OnePosMatchesMemory); m_OnePosMatchesMemory = 0; + ::MyFree(m_DistanceMemory); m_DistanceMemory = 0; + ::MyFree(m_Values); m_Values = 0; + ::MyFree(m_Tables); m_Tables = 0; +} + +CCoder::~CCoder() +{ + Free(); + MatchFinder_Free(&_lzInWindow, &g_Alloc); +} + +NO_INLINE void CCoder::GetMatches() +{ + if (m_IsMultiPass) + { + m_MatchDistances = m_OnePosMatchesMemory + m_Pos; + if (m_SecondPass) + { + m_Pos += *m_MatchDistances + 1; + return; + } + } + + UInt32 distanceTmp[kMatchMaxLen * 2 + 3]; + + UInt32 numPairs = (_btMode) ? + Bt3Zip_MatchFinder_GetMatches(&_lzInWindow, distanceTmp): + Hc3Zip_MatchFinder_GetMatches(&_lzInWindow, distanceTmp); + + *m_MatchDistances = (UInt16)numPairs; + + if (numPairs > 0) + { + UInt32 i; + for(i = 0; i < numPairs; i += 2) + { + m_MatchDistances[i + 1] = (UInt16)distanceTmp[i]; + m_MatchDistances[i + 2] = (UInt16)distanceTmp[i + 1]; + } + UInt32 len = distanceTmp[numPairs - 2]; + if (len == m_NumFastBytes && m_NumFastBytes != m_MatchMaxLen) + { + UInt32 numAvail = Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) + 1; + const Byte *pby = Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow) - 1; + const Byte *pby2 = pby - (distanceTmp[numPairs - 1] + 1); + if (numAvail > m_MatchMaxLen) + numAvail = m_MatchMaxLen; + for (; len < numAvail && pby[len] == pby2[len]; len++); + m_MatchDistances[i - 1] = (UInt16)len; + } + } + if (m_IsMultiPass) + m_Pos += numPairs + 1; + if (!m_SecondPass) + m_AdditionalOffset++; +} + +void CCoder::MovePos(UInt32 num) +{ + if (!m_SecondPass && num > 0) + { + if (_btMode) + Bt3Zip_MatchFinder_Skip(&_lzInWindow, num); + else + Hc3Zip_MatchFinder_Skip(&_lzInWindow, num); + m_AdditionalOffset += num; + } +} + +static const UInt32 kIfinityPrice = 0xFFFFFFF; + +NO_INLINE UInt32 CCoder::Backward(UInt32 &backRes, UInt32 cur) +{ + m_OptimumEndIndex = cur; + UInt32 posMem = m_Optimum[cur].PosPrev; + UInt16 backMem = m_Optimum[cur].BackPrev; + do + { + UInt32 posPrev = posMem; + UInt16 backCur = backMem; + backMem = m_Optimum[posPrev].BackPrev; + posMem = m_Optimum[posPrev].PosPrev; + m_Optimum[posPrev].BackPrev = backCur; + m_Optimum[posPrev].PosPrev = (UInt16)cur; + cur = posPrev; + } + while(cur > 0); + backRes = m_Optimum[0].BackPrev; + m_OptimumCurrentIndex = m_Optimum[0].PosPrev; + return m_OptimumCurrentIndex; +} + +NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes) +{ + if(m_OptimumEndIndex != m_OptimumCurrentIndex) + { + UInt32 len = m_Optimum[m_OptimumCurrentIndex].PosPrev - m_OptimumCurrentIndex; + backRes = m_Optimum[m_OptimumCurrentIndex].BackPrev; + m_OptimumCurrentIndex = m_Optimum[m_OptimumCurrentIndex].PosPrev; + return len; + } + m_OptimumCurrentIndex = m_OptimumEndIndex = 0; + + GetMatches(); + + UInt32 numDistancePairs = m_MatchDistances[0]; + if(numDistancePairs == 0) + return 1; + + const UInt16 *matchDistances = m_MatchDistances + 1; + UInt32 lenMain = matchDistances[numDistancePairs - 2]; + + if(lenMain > m_NumFastBytes) + { + backRes = matchDistances[numDistancePairs - 1]; + MovePos(lenMain - 1); + return lenMain; + } + m_Optimum[1].Price = m_LiteralPrices[Inline_MatchFinder_GetIndexByte(&_lzInWindow, 0 - m_AdditionalOffset)]; + m_Optimum[1].PosPrev = 0; + + m_Optimum[2].Price = kIfinityPrice; + m_Optimum[2].PosPrev = 1; + + + UInt32 offs = 0; + for(UInt32 i = kMatchMinLen; i <= lenMain; i++) + { + UInt32 distance = matchDistances[offs + 1]; + m_Optimum[i].PosPrev = 0; + m_Optimum[i].BackPrev = (UInt16)distance; + m_Optimum[i].Price = m_LenPrices[i - kMatchMinLen] + m_PosPrices[GetPosSlot(distance)]; + if (i == matchDistances[offs]) + offs += 2; + } + + UInt32 cur = 0; + UInt32 lenEnd = lenMain; + for (;;) + { + ++cur; + if(cur == lenEnd || cur == kNumOptsBase || m_Pos >= kMatchArrayLimit) + return Backward(backRes, cur); + GetMatches(); + matchDistances = m_MatchDistances + 1; + + UInt32 numDistancePairs = m_MatchDistances[0]; + UInt32 newLen = 0; + if(numDistancePairs != 0) + { + newLen = matchDistances[numDistancePairs - 2]; + if(newLen > m_NumFastBytes) + { + UInt32 len = Backward(backRes, cur); + m_Optimum[cur].BackPrev = matchDistances[numDistancePairs - 1]; + m_OptimumEndIndex = cur + newLen; + m_Optimum[cur].PosPrev = (UInt16)m_OptimumEndIndex; + MovePos(newLen - 1); + return len; + } + } + UInt32 curPrice = m_Optimum[cur].Price; + UInt32 curAnd1Price = curPrice + m_LiteralPrices[Inline_MatchFinder_GetIndexByte(&_lzInWindow, cur - m_AdditionalOffset)]; + COptimal &optimum = m_Optimum[cur + 1]; + if (curAnd1Price < optimum.Price) + { + optimum.Price = curAnd1Price; + optimum.PosPrev = (UInt16)cur; + } + if(numDistancePairs == 0) + continue; + while(lenEnd < cur + newLen) + m_Optimum[++lenEnd].Price = kIfinityPrice; + offs = 0; + UInt32 distance = matchDistances[offs + 1]; + curPrice += m_PosPrices[GetPosSlot(distance)]; + for(UInt32 lenTest = kMatchMinLen; ; lenTest++) + { + UInt32 curAndLenPrice = curPrice + m_LenPrices[lenTest - kMatchMinLen]; + COptimal &optimum = m_Optimum[cur + lenTest]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = (UInt16)cur; + optimum.BackPrev = (UInt16)distance; + } + if (lenTest == matchDistances[offs]) + { + offs += 2; + if (offs == numDistancePairs) + break; + curPrice -= m_PosPrices[GetPosSlot(distance)]; + distance = matchDistances[offs + 1]; + curPrice += m_PosPrices[GetPosSlot(distance)]; + } + } + } +} + +UInt32 CCoder::GetOptimalFast(UInt32 &backRes) +{ + GetMatches(); + UInt32 numDistancePairs = m_MatchDistances[0]; + if (numDistancePairs == 0) + return 1; + UInt32 lenMain = m_MatchDistances[numDistancePairs - 1]; + backRes = m_MatchDistances[numDistancePairs]; + MovePos(lenMain - 1); + return lenMain; +} + +void CTables::InitStructures() +{ + UInt32 i; + for(i = 0; i < 256; i++) + litLenLevels[i] = 8; + litLenLevels[i++] = 13; + for(;i < kFixedMainTableSize; i++) + litLenLevels[i] = 5; + for(i = 0; i < kFixedDistTableSize; i++) + distLevels[i] = 5; +} + +NO_INLINE void CCoder::LevelTableDummy(const Byte *levels, int numLevels, UInt32 *freqs) +{ + int prevLen = 0xFF; + int nextLen = levels[0]; + int count = 0; + int maxCount = 7; + int minCount = 4; + if (nextLen == 0) + { + maxCount = 138; + minCount = 3; + } + for (int n = 0; n < numLevels; n++) + { + int curLen = nextLen; + nextLen = (n < numLevels - 1) ? levels[n + 1] : 0xFF; + count++; + if (count < maxCount && curLen == nextLen) + continue; + + if (count < minCount) + freqs[curLen] += (UInt32)count; + else if (curLen != 0) + { + if (curLen != prevLen) + { + freqs[curLen]++; + count--; + } + freqs[kTableLevelRepNumber]++; + } + else if (count <= 10) + freqs[kTableLevel0Number]++; + else + freqs[kTableLevel0Number2]++; + + count = 0; + prevLen = curLen; + + if (nextLen == 0) + { + maxCount = 138; + minCount = 3; + } + else if (curLen == nextLen) + { + maxCount = 6; + minCount = 3; + } + else + { + maxCount = 7; + minCount = 4; + } + } +} + +NO_INLINE void CCoder::WriteBits(UInt32 value, int numBits) +{ + m_OutStream.WriteBits(value, numBits); +} + +#define WRITE_HF2(codes, lens, i) m_OutStream.WriteBits(codes[i], lens[i]) +#define WRITE_HF(i) WriteBits(codes[i], lens[i]) + +NO_INLINE void CCoder::LevelTableCode(const Byte *levels, int numLevels, const Byte *lens, const UInt32 *codes) +{ + int prevLen = 0xFF; + int nextLen = levels[0]; + int count = 0; + int maxCount = 7; + int minCount = 4; + if (nextLen == 0) + { + maxCount = 138; + minCount = 3; + } + for (int n = 0; n < numLevels; n++) + { + int curLen = nextLen; + nextLen = (n < numLevels - 1) ? levels[n + 1] : 0xFF; + count++; + if (count < maxCount && curLen == nextLen) + continue; + + if (count < minCount) + for(int i = 0; i < count; i++) + WRITE_HF(curLen); + else if (curLen != 0) + { + if (curLen != prevLen) + { + WRITE_HF(curLen); + count--; + } + WRITE_HF(kTableLevelRepNumber); + WriteBits(count - 3, 2); + } + else if (count <= 10) + { + WRITE_HF(kTableLevel0Number); + WriteBits(count - 3, 3); + } + else + { + WRITE_HF(kTableLevel0Number2); + WriteBits(count - 11, 7); + } + + count = 0; + prevLen = curLen; + + if (nextLen == 0) + { + maxCount = 138; + minCount = 3; + } + else if (curLen == nextLen) + { + maxCount = 6; + minCount = 3; + } + else + { + maxCount = 7; + minCount = 4; + } + } +} + +NO_INLINE void CCoder::MakeTables(unsigned maxHuffLen) +{ + Huffman_Generate(mainFreqs, mainCodes, m_NewLevels.litLenLevels, kFixedMainTableSize, maxHuffLen); + Huffman_Generate(distFreqs, distCodes, m_NewLevels.distLevels, kDistTableSize64, maxHuffLen); +} + +NO_INLINE UInt32 Huffman_GetPrice(const UInt32 *freqs, const Byte *lens, UInt32 num) +{ + UInt32 price = 0; + UInt32 i; + for (i = 0; i < num; i++) + price += lens[i] * freqs[i]; + return price; +} + +NO_INLINE UInt32 Huffman_GetPrice_Spec(const UInt32 *freqs, const Byte *lens, UInt32 num, const Byte *extraBits, UInt32 extraBase) +{ + return Huffman_GetPrice(freqs, lens, num) + + Huffman_GetPrice(freqs + extraBase, extraBits, num - extraBase); +} + +NO_INLINE UInt32 CCoder::GetLzBlockPrice() const +{ + return + Huffman_GetPrice_Spec(mainFreqs, m_NewLevels.litLenLevels, kFixedMainTableSize, m_LenDirectBits, kSymbolMatch) + + Huffman_GetPrice_Spec(distFreqs, m_NewLevels.distLevels, kDistTableSize64, kDistDirectBits, 0); +} + +NO_INLINE void CCoder::TryBlock() +{ + memset(mainFreqs, 0, sizeof(mainFreqs)); + memset(distFreqs, 0, sizeof(distFreqs)); + + m_ValueIndex = 0; + UInt32 blockSize = BlockSizeRes; + BlockSizeRes = 0; + for (;;) + { + if (m_OptimumCurrentIndex == m_OptimumEndIndex) + { + if (m_Pos >= kMatchArrayLimit || BlockSizeRes >= blockSize || !m_SecondPass && + ((Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) == 0) || m_ValueIndex >= m_ValueBlockSize)) + break; + } + UInt32 pos; + UInt32 len; + if (_fastMode) + len = GetOptimalFast(pos); + else + len = GetOptimal(pos); + CCodeValue &codeValue = m_Values[m_ValueIndex++]; + if (len >= kMatchMinLen) + { + UInt32 newLen = len - kMatchMinLen; + codeValue.Len = (UInt16)newLen; + mainFreqs[kSymbolMatch + g_LenSlots[newLen]]++; + codeValue.Pos = (UInt16)pos; + distFreqs[GetPosSlot(pos)]++; + } + else + { + Byte b = Inline_MatchFinder_GetIndexByte(&_lzInWindow, 0 - m_AdditionalOffset); + mainFreqs[b]++; + codeValue.SetAsLiteral(); + codeValue.Pos = b; + } + m_AdditionalOffset -= len; + BlockSizeRes += len; + } + mainFreqs[kSymbolEndOfBlock]++; + m_AdditionalOffset += BlockSizeRes; + m_SecondPass = true; +} + +NO_INLINE void CCoder::SetPrices(const CLevels &levels) +{ + if (_fastMode) + return; + UInt32 i; + for(i = 0; i < 256; i++) + { + Byte price = levels.litLenLevels[i]; + m_LiteralPrices[i] = ((price != 0) ? price : kNoLiteralStatPrice); + } + + for(i = 0; i < m_NumLenCombinations; i++) + { + UInt32 slot = g_LenSlots[i]; + Byte price = levels.litLenLevels[kSymbolMatch + slot]; + m_LenPrices[i] = (Byte)(((price != 0) ? price : kNoLenStatPrice) + m_LenDirectBits[slot]); + } + + for(i = 0; i < kDistTableSize64; i++) + { + Byte price = levels.distLevels[i]; + m_PosPrices[i] = (Byte)(((price != 0) ? price: kNoPosStatPrice) + kDistDirectBits[i]); + } +} + +NO_INLINE void Huffman_ReverseBits(UInt32 *codes, const Byte *lens, UInt32 num) +{ + for (UInt32 i = 0; i < num; i++) + { + UInt32 x = codes[i]; + x = ((x & 0x5555) << 1) | ((x & 0xAAAA) >> 1); + x = ((x & 0x3333) << 2) | ((x & 0xCCCC) >> 2); + x = ((x & 0x0F0F) << 4) | ((x & 0xF0F0) >> 4); + codes[i] = (((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8)) >> (16 - lens[i]); + } +} + +NO_INLINE void CCoder::WriteBlock() +{ + Huffman_ReverseBits(mainCodes, m_NewLevels.litLenLevels, kFixedMainTableSize); + Huffman_ReverseBits(distCodes, m_NewLevels.distLevels, kDistTableSize64); + + for (UInt32 i = 0; i < m_ValueIndex; i++) + { + const CCodeValue &codeValue = m_Values[i]; + if (codeValue.IsLiteral()) + WRITE_HF2(mainCodes, m_NewLevels.litLenLevels, codeValue.Pos); + else + { + UInt32 len = codeValue.Len; + UInt32 lenSlot = g_LenSlots[len]; + WRITE_HF2(mainCodes, m_NewLevels.litLenLevels, kSymbolMatch + lenSlot); + m_OutStream.WriteBits(len - m_LenStart[lenSlot], m_LenDirectBits[lenSlot]); + UInt32 dist = codeValue.Pos; + UInt32 posSlot = GetPosSlot(dist); + WRITE_HF2(distCodes, m_NewLevels.distLevels, posSlot); + m_OutStream.WriteBits(dist - kDistStart[posSlot], kDistDirectBits[posSlot]); + } + } + WRITE_HF2(mainCodes, m_NewLevels.litLenLevels, kSymbolEndOfBlock); +} + +static UInt32 GetStorePrice(UInt32 blockSize, int bitPosition) +{ + UInt32 price = 0; + do + { + UInt32 nextBitPosition = (bitPosition + kFinalBlockFieldSize + kBlockTypeFieldSize) & 7; + int numBitsForAlign = nextBitPosition > 0 ? (8 - nextBitPosition): 0; + UInt32 curBlockSize = (blockSize < (1 << 16)) ? blockSize : (1 << 16) - 1; + price += kFinalBlockFieldSize + kBlockTypeFieldSize + numBitsForAlign + (2 + 2) * 8 + curBlockSize * 8; + bitPosition = 0; + blockSize -= curBlockSize; + } + while(blockSize != 0); + return price; +} + +void CCoder::WriteStoreBlock(UInt32 blockSize, UInt32 additionalOffset, bool finalBlock) +{ + do + { + UInt32 curBlockSize = (blockSize < (1 << 16)) ? blockSize : (1 << 16) - 1; + blockSize -= curBlockSize; + WriteBits((finalBlock && (blockSize == 0) ? NFinalBlockField::kFinalBlock: NFinalBlockField::kNotFinalBlock), kFinalBlockFieldSize); + WriteBits(NBlockType::kStored, kBlockTypeFieldSize); + m_OutStream.FlushByte(); + WriteBits((UInt16)curBlockSize, kStoredBlockLengthFieldSize); + WriteBits((UInt16)~curBlockSize, kStoredBlockLengthFieldSize); + const Byte *data = Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow)- additionalOffset; + for(UInt32 i = 0; i < curBlockSize; i++) + m_OutStream.WriteByte(data[i]); + additionalOffset -= curBlockSize; + } + while(blockSize != 0); +} + +NO_INLINE UInt32 CCoder::TryDynBlock(int tableIndex, UInt32 numPasses) +{ + CTables &t = m_Tables[tableIndex]; + BlockSizeRes = t.BlockSizeRes; + UInt32 posTemp = t.m_Pos; + SetPrices(t); + + for (UInt32 p = 0; p < numPasses; p++) + { + m_Pos = posTemp; + TryBlock(); + unsigned numHuffBits = + (m_ValueIndex > 18000 ? 12 : + (m_ValueIndex > 7000 ? 11 : + (m_ValueIndex > 2000 ? 10 : 9))); + MakeTables(numHuffBits); + SetPrices(m_NewLevels); + } + + (CLevels &)t = m_NewLevels; + + m_NumLitLenLevels = kMainTableSize; + while(m_NumLitLenLevels > kNumLitLenCodesMin && m_NewLevels.litLenLevels[m_NumLitLenLevels - 1] == 0) + m_NumLitLenLevels--; + + m_NumDistLevels = kDistTableSize64; + while(m_NumDistLevels > kNumDistCodesMin && m_NewLevels.distLevels[m_NumDistLevels - 1] == 0) + m_NumDistLevels--; + + UInt32 levelFreqs[kLevelTableSize]; + memset(levelFreqs, 0, sizeof(levelFreqs)); + + LevelTableDummy(m_NewLevels.litLenLevels, m_NumLitLenLevels, levelFreqs); + LevelTableDummy(m_NewLevels.distLevels, m_NumDistLevels, levelFreqs); + + Huffman_Generate(levelFreqs, levelCodes, levelLens, kLevelTableSize, kMaxLevelBitLength); + + m_NumLevelCodes = kNumLevelCodesMin; + for (UInt32 i = 0; i < kLevelTableSize; i++) + { + Byte level = levelLens[kCodeLengthAlphabetOrder[i]]; + if (level > 0 && i >= m_NumLevelCodes) + m_NumLevelCodes = i + 1; + m_LevelLevels[i] = level; + } + + return GetLzBlockPrice() + + Huffman_GetPrice_Spec(levelFreqs, levelLens, kLevelTableSize, kLevelDirectBits, kTableDirectLevels) + + kNumLenCodesFieldSize + kNumDistCodesFieldSize + kNumLevelCodesFieldSize + + m_NumLevelCodes * kLevelFieldSize + kFinalBlockFieldSize + kBlockTypeFieldSize; +} + +NO_INLINE UInt32 CCoder::TryFixedBlock(int tableIndex) +{ + CTables &t = m_Tables[tableIndex]; + BlockSizeRes = t.BlockSizeRes; + m_Pos = t.m_Pos; + m_NewLevels.SetFixedLevels(); + SetPrices(m_NewLevels); + TryBlock(); + return kFinalBlockFieldSize + kBlockTypeFieldSize + GetLzBlockPrice(); +} + +NO_INLINE UInt32 CCoder::GetBlockPrice(int tableIndex, int numDivPasses) +{ + CTables &t = m_Tables[tableIndex]; + t.StaticMode = false; + UInt32 price = TryDynBlock(tableIndex, m_NumPasses); + t.BlockSizeRes = BlockSizeRes; + UInt32 numValues = m_ValueIndex; + UInt32 posTemp = m_Pos; + UInt32 additionalOffsetEnd = m_AdditionalOffset; + + if (m_CheckStatic && m_ValueIndex <= kFixedHuffmanCodeBlockSizeMax) + { + const UInt32 fixedPrice = TryFixedBlock(tableIndex); + t.StaticMode = (fixedPrice < price); + if (t.StaticMode) + price = fixedPrice; + } + + const UInt32 storePrice = GetStorePrice(BlockSizeRes, 0); // bitPosition + t.StoreMode = (storePrice <= price); + if (t.StoreMode) + price = storePrice; + + t.UseSubBlocks = false; + + if (numDivPasses > 1 && numValues >= kDivideCodeBlockSizeMin) + { + CTables &t0 = m_Tables[(tableIndex << 1)]; + (CLevels &)t0 = t; + t0.BlockSizeRes = t.BlockSizeRes >> 1; + t0.m_Pos = t.m_Pos; + UInt32 subPrice = GetBlockPrice((tableIndex << 1), numDivPasses - 1); + + UInt32 blockSize2 = t.BlockSizeRes - t0.BlockSizeRes; + if (t0.BlockSizeRes >= kDivideBlockSizeMin && blockSize2 >= kDivideBlockSizeMin) + { + CTables &t1 = m_Tables[(tableIndex << 1) + 1]; + (CLevels &)t1 = t; + t1.BlockSizeRes = blockSize2; + t1.m_Pos = m_Pos; + m_AdditionalOffset -= t0.BlockSizeRes; + subPrice += GetBlockPrice((tableIndex << 1) + 1, numDivPasses - 1); + t.UseSubBlocks = (subPrice < price); + if (t.UseSubBlocks) + price = subPrice; + } + } + m_AdditionalOffset = additionalOffsetEnd; + m_Pos = posTemp; + return price; +} + +void CCoder::CodeBlock(int tableIndex, bool finalBlock) +{ + CTables &t = m_Tables[tableIndex]; + if (t.UseSubBlocks) + { + CodeBlock((tableIndex << 1), false); + CodeBlock((tableIndex << 1) + 1, finalBlock); + } + else + { + if (t.StoreMode) + WriteStoreBlock(t.BlockSizeRes, m_AdditionalOffset, finalBlock); + else + { + WriteBits((finalBlock ? NFinalBlockField::kFinalBlock: NFinalBlockField::kNotFinalBlock), kFinalBlockFieldSize); + if (t.StaticMode) + { + WriteBits(NBlockType::kFixedHuffman, kBlockTypeFieldSize); + TryFixedBlock(tableIndex); + int i; + const int kMaxStaticHuffLen = 9; + for (i = 0; i < kFixedMainTableSize; i++) + mainFreqs[i] = (UInt32)1 << (kMaxStaticHuffLen - m_NewLevels.litLenLevels[i]); + for (i = 0; i < kFixedDistTableSize; i++) + distFreqs[i] = (UInt32)1 << (kMaxStaticHuffLen - m_NewLevels.distLevels[i]); + MakeTables(kMaxStaticHuffLen); + } + else + { + if (m_NumDivPasses > 1 || m_CheckStatic) + TryDynBlock(tableIndex, 1); + WriteBits(NBlockType::kDynamicHuffman, kBlockTypeFieldSize); + WriteBits(m_NumLitLenLevels - kNumLitLenCodesMin, kNumLenCodesFieldSize); + WriteBits(m_NumDistLevels - kNumDistCodesMin, kNumDistCodesFieldSize); + WriteBits(m_NumLevelCodes - kNumLevelCodesMin, kNumLevelCodesFieldSize); + + for (UInt32 i = 0; i < m_NumLevelCodes; i++) + WriteBits(m_LevelLevels[i], kLevelFieldSize); + + Huffman_ReverseBits(levelCodes, levelLens, kLevelTableSize); + LevelTableCode(m_NewLevels.litLenLevels, m_NumLitLenLevels, levelLens, levelCodes); + LevelTableCode(m_NewLevels.distLevels, m_NumDistLevels, levelLens, levelCodes); + } + WriteBlock(); + } + m_AdditionalOffset -= t.BlockSizeRes; + } +} + +SRes Read(void *object, void *data, size_t *size) +{ + const UInt32 kStepSize = (UInt32)1 << 31; + UInt32 curSize = ((*size < kStepSize) ? (UInt32)*size : kStepSize); + HRESULT res = ((CSeqInStream *)object)->RealStream->Read(data, curSize, &curSize); + *size = curSize; + return (SRes)res; +} + +HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */ , const UInt64 * /* outSize */ , ICompressProgressInfo *progress) +{ + m_CheckStatic = (m_NumPasses != 1 || m_NumDivPasses != 1); + m_IsMultiPass = (m_CheckStatic || (m_NumPasses != 1 || m_NumDivPasses != 1)); + + RINOK(Create()); + + m_ValueBlockSize = (7 << 10) + (1 << 12) * m_NumDivPasses; + + UInt64 nowPos = 0; + + _seqInStream.RealStream = inStream; + _seqInStream.SeqInStream.Read = Read; + _lzInWindow.stream = &_seqInStream.SeqInStream; + + MatchFinder_Init(&_lzInWindow); + m_OutStream.SetStream(outStream); + m_OutStream.Init(); + + CCoderReleaser coderReleaser(this); + + m_OptimumEndIndex = m_OptimumCurrentIndex = 0; + + CTables &t = m_Tables[1]; + t.m_Pos = 0; + t.InitStructures(); + + m_AdditionalOffset = 0; + do + { + t.BlockSizeRes = kBlockUncompressedSizeThreshold; + m_SecondPass = false; + GetBlockPrice(1, m_NumDivPasses); + CodeBlock(1, Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) == 0); + nowPos += m_Tables[1].BlockSizeRes; + if (progress != NULL) + { + UInt64 packSize = m_OutStream.GetProcessedSize(); + RINOK(progress->SetRatioInfo(&nowPos, &packSize)); + } + } + while (Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) != 0); + if (_lzInWindow.result != SZ_OK) + return _lzInWindow.result; + return m_OutStream.Flush(); +} + +HRESULT CCoder::BaseCode(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + try { return CodeReal(inStream, outStream, inSize, outSize, progress); } + catch(const COutBufferException &e) { return e.ErrorCode; } + catch(...) { return E_FAIL; } +} + +STDMETHODIMP CCOMCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) + { return BaseCode(inStream, outStream, inSize, outSize, progress); } + +STDMETHODIMP CCOMCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) + { return BaseSetEncoderProperties2(propIDs, props, numProps); } + +STDMETHODIMP CCOMCoder64::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) + { return BaseCode(inStream, outStream, inSize, outSize, progress); } + +STDMETHODIMP CCOMCoder64::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) + { return BaseSetEncoderProperties2(propIDs, props, numProps); } + +}}} diff --git a/CPP/7zip/Compress/DeflateEncoder.h b/CPP/7zip/Compress/DeflateEncoder.h new file mode 100755 index 0000000..7ad262b --- /dev/null +++ b/CPP/7zip/Compress/DeflateEncoder.h @@ -0,0 +1,211 @@ +// DeflateEncoder.h + +#ifndef __DEFLATE_ENCODER_H +#define __DEFLATE_ENCODER_H + +#include "../../../C/LzFind.h" + +#include "Common/MyCom.h" + +#include "../ICoder.h" + +#include "BitlEncoder.h" +#include "DeflateConst.h" + +namespace NCompress { +namespace NDeflate { +namespace NEncoder { + +struct CCodeValue +{ + UInt16 Len; + UInt16 Pos; + void SetAsLiteral() { Len = (1 << 15); } + bool IsLiteral() const { return (Len >= (1 << 15)); } +}; + +struct COptimal +{ + UInt32 Price; + UInt16 PosPrev; + UInt16 BackPrev; +}; + +const UInt32 kNumOptsBase = 1 << 12; +const UInt32 kNumOpts = kNumOptsBase + kMatchMaxLen; + +class CCoder; + +struct CTables: public CLevels +{ + bool UseSubBlocks; + bool StoreMode; + bool StaticMode; + UInt32 BlockSizeRes; + UInt32 m_Pos; + void InitStructures(); +}; + +typedef struct _CSeqInStream +{ + ISeqInStream SeqInStream; + CMyComPtr RealStream; +} CSeqInStream; + +class CCoder +{ + CMatchFinder _lzInWindow; + CBitlEncoder m_OutStream; + + CSeqInStream _seqInStream; + +public: + CCodeValue *m_Values; + + UInt16 *m_MatchDistances; + UInt32 m_NumFastBytes; + bool _fastMode; + bool _btMode; + + UInt16 *m_OnePosMatchesMemory; + UInt16 *m_DistanceMemory; + + UInt32 m_Pos; + + int m_NumPasses; + int m_NumDivPasses; + bool m_CheckStatic; + bool m_IsMultiPass; + UInt32 m_ValueBlockSize; + + UInt32 m_NumLenCombinations; + UInt32 m_MatchMaxLen; + const Byte *m_LenStart; + const Byte *m_LenDirectBits; + + bool m_Created; + bool m_Deflate64Mode; + + Byte m_LevelLevels[kLevelTableSize]; + int m_NumLitLenLevels; + int m_NumDistLevels; + UInt32 m_NumLevelCodes; + UInt32 m_ValueIndex; + + bool m_SecondPass; + UInt32 m_AdditionalOffset; + + UInt32 m_OptimumEndIndex; + UInt32 m_OptimumCurrentIndex; + + Byte m_LiteralPrices[256]; + Byte m_LenPrices[kNumLenSymbolsMax]; + Byte m_PosPrices[kDistTableSize64]; + + CLevels m_NewLevels; + UInt32 mainFreqs[kFixedMainTableSize]; + UInt32 distFreqs[kDistTableSize64]; + UInt32 mainCodes[kFixedMainTableSize]; + UInt32 distCodes[kDistTableSize64]; + UInt32 levelCodes[kLevelTableSize]; + Byte levelLens[kLevelTableSize]; + + UInt32 BlockSizeRes; + + CTables *m_Tables; + COptimal m_Optimum[kNumOpts]; + + UInt32 m_MatchFinderCycles; + // IMatchFinderSetNumPasses *m_SetMfPasses; + + void GetMatches(); + void MovePos(UInt32 num); + UInt32 Backward(UInt32 &backRes, UInt32 cur); + UInt32 GetOptimal(UInt32 &backRes); + UInt32 GetOptimalFast(UInt32 &backRes); + + void LevelTableDummy(const Byte *levels, int numLevels, UInt32 *freqs); + + void WriteBits(UInt32 value, int numBits); + void LevelTableCode(const Byte *levels, int numLevels, const Byte *lens, const UInt32 *codes); + + void MakeTables(unsigned maxHuffLen); + UInt32 GetLzBlockPrice() const; + void TryBlock(); + UInt32 TryDynBlock(int tableIndex, UInt32 numPasses); + + UInt32 TryFixedBlock(int tableIndex); + + void SetPrices(const CLevels &levels); + void WriteBlock(); + + HRESULT Create(); + void Free(); + + void WriteStoreBlock(UInt32 blockSize, UInt32 additionalOffset, bool finalBlock); + void WriteTables(bool writeMode, bool finalBlock); + + void WriteBlockData(bool writeMode, bool finalBlock); + + void ReleaseStreams() + { + _seqInStream.RealStream.Release(); + m_OutStream.ReleaseStream(); + } + class CCoderReleaser + { + CCoder *m_Coder; + public: + CCoderReleaser(CCoder *coder): m_Coder(coder) {} + ~CCoderReleaser() { m_Coder->ReleaseStreams(); } + }; + friend class CCoderReleaser; + + UInt32 GetBlockPrice(int tableIndex, int numDivPasses); + void CodeBlock(int tableIndex, bool finalBlock); + +public: + CCoder(bool deflate64Mode = false); + ~CCoder(); + + HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + + HRESULT BaseCode(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + + HRESULT BaseSetEncoderProperties2(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); +}; + + +class CCOMCoder : + public ICompressCoder, + public ICompressSetCoderProperties, + public CMyUnknownImp, + public CCoder +{ +public: + MY_UNKNOWN_IMP1(ICompressSetCoderProperties) + CCOMCoder(): CCoder(false) {}; + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); +}; + +class CCOMCoder64 : + public ICompressCoder, + public ICompressSetCoderProperties, + public CMyUnknownImp, + public CCoder +{ +public: + MY_UNKNOWN_IMP1(ICompressSetCoderProperties) + CCOMCoder64(): CCoder(true) {}; + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); +}; + +}}} + +#endif diff --git a/CPP/7zip/Compress/DeflateRegister.cpp b/CPP/7zip/Compress/DeflateRegister.cpp new file mode 100755 index 0000000..d8a9c8d --- /dev/null +++ b/CPP/7zip/Compress/DeflateRegister.cpp @@ -0,0 +1,21 @@ +// DeflateRegister.cpp + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" + +#include "DeflateDecoder.h" + +static void *CreateCodecDeflate() { return (void *)(ICompressCoder *)(new NCompress::NDeflate::NDecoder::CCOMCoder); } + +#if !defined(EXTRACT_ONLY) && !defined(DEFLATE_EXTRACT_ONLY) +#include "DeflateEncoder.h" +static void *CreateCodecOutDeflate() { return (void *)(ICompressCoder *)(new NCompress::NDeflate::NEncoder::CCOMCoder); } +#else +#define CreateCodecOutDeflate 0 +#endif + +static CCodecInfo g_CodecInfo = + { CreateCodecDeflate, CreateCodecOutDeflate, 0x040108, L"Deflate", 1, false }; + +REGISTER_CODEC(Deflate) diff --git a/CPP/7zip/Compress/DeltaFilter.cpp b/CPP/7zip/Compress/DeltaFilter.cpp new file mode 100755 index 0000000..e7e3822 --- /dev/null +++ b/CPP/7zip/Compress/DeltaFilter.cpp @@ -0,0 +1,112 @@ +// DeltaFilter.cpp + +#include "StdAfx.h" + +#include "../../../C/Delta.h" + +#include "../Common/RegisterCodec.h" + +#include "BranchCoder.h" + +struct CDelta +{ + unsigned _delta; + Byte _state[DELTA_STATE_SIZE]; + CDelta(): _delta(1) {} + void DeltaInit() { Delta_Init(_state); } +}; + +class CDeltaEncoder: + public ICompressFilter, + public ICompressSetCoderProperties, + public ICompressWriteCoderProperties, + CDelta, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties) + STDMETHOD(Init)(); + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); + STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); +}; + +class CDeltaDecoder: + public ICompressFilter, + public ICompressSetDecoderProperties2, + CDelta, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2) + STDMETHOD(Init)(); + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); +}; + +STDMETHODIMP CDeltaEncoder::Init() +{ + DeltaInit(); + return S_OK; +} + +STDMETHODIMP_(UInt32) CDeltaEncoder::Filter(Byte *data, UInt32 size) +{ + Delta_Encode(_state, _delta, data, size); + return size; +} + +STDMETHODIMP CDeltaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) +{ + UInt32 delta = _delta; + for (UInt32 i = 0; i < numProps; i++) + { + const PROPVARIANT &prop = props[i]; + if (propIDs[i] != NCoderPropID::kDefaultProp || prop.vt != VT_UI4 || prop.ulVal < 1 || prop.ulVal > 256) + return E_INVALIDARG; + delta = prop.ulVal; + } + _delta = delta; + return S_OK; +} + +STDMETHODIMP CDeltaEncoder::WriteCoderProperties(ISequentialOutStream *outStream) +{ + Byte prop = (Byte)(_delta - 1); + return outStream->Write(&prop, 1, NULL); +} + +STDMETHODIMP CDeltaDecoder::Init() +{ + DeltaInit(); + return S_OK; +} + +STDMETHODIMP_(UInt32) CDeltaDecoder::Filter(Byte *data, UInt32 size) +{ + Delta_Decode(_state, _delta, data, size); + return size; +} + +STDMETHODIMP CDeltaDecoder::SetDecoderProperties2(const Byte *props, UInt32 size) +{ + if (size != 1) + return E_INVALIDARG; + _delta = (unsigned)props[0] + 1; + return S_OK; +} + +#define CREATE_CODEC(x) \ + static void *CreateCodec ## x() { return (void *)(ICompressFilter *)(new C ## x ## Decoder); } \ + static void *CreateCodec ## x ## Out() { return (void *)(ICompressFilter *)(new C ## x ## Encoder); } + +CREATE_CODEC(Delta) + +#define METHOD_ITEM(x, id, name) { CreateCodec ## x, CreateCodec ## x ## Out, id, name, 1, true } + +static CCodecInfo g_CodecsInfo[] = +{ + METHOD_ITEM(Delta, 3, L"Delta") +}; + +REGISTER_CODECS(Delta) diff --git a/CPP/7zip/Compress/DllExports.cpp b/CPP/7zip/Compress/DllExports.cpp new file mode 100755 index 0000000..9b04f89 --- /dev/null +++ b/CPP/7zip/Compress/DllExports.cpp @@ -0,0 +1,45 @@ +// DllExports.cpp + +#include "StdAfx.h" + +#include "../../Common/MyInitGuid.h" + +#include "../ICoder.h" + +#include "../Common/RegisterCodec.h" + +static const unsigned int kNumCodecsMax = 32; +unsigned int g_NumCodecs = 0; +const CCodecInfo *g_Codecs[kNumCodecsMax]; +void RegisterCodec(const CCodecInfo *codecInfo) +{ + if (g_NumCodecs < kNumCodecsMax) + g_Codecs[g_NumCodecs++] = codecInfo; +} + +#ifdef _WIN32 +extern "C" +BOOL WINAPI DllMain( + #ifdef UNDER_CE + HANDLE + #else + HINSTANCE + #endif + , DWORD /* dwReason */, LPVOID /*lpReserved*/) +{ + return TRUE; +} +#endif + +static const UInt16 kDecodeId = 0x2790; + +DEFINE_GUID(CLSID_CCodec, +0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + +STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject); + +STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) +{ + return CreateCoder(clsid, iid, outObject); +} + diff --git a/CPP/7zip/Compress/DllExports2.cpp b/CPP/7zip/Compress/DllExports2.cpp new file mode 100755 index 0000000..774b582 --- /dev/null +++ b/CPP/7zip/Compress/DllExports2.cpp @@ -0,0 +1,28 @@ +// DllExports.cpp + +#include "StdAfx.h" + +#include "../../Common/MyInitGuid.h" + +#include "../ICoder.h" + +#include "../Common/RegisterCodec.h" + +extern "C" +BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /*lpReserved*/) +{ + return TRUE; +} + +static const UInt16 kDecodeId = 0x2790; + +DEFINE_GUID(CLSID_CCodec, +0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + +STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject); + +STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) +{ + return CreateCoder(clsid, iid, outObject); +} + diff --git a/CPP/7zip/Compress/HuffmanDecoder.h b/CPP/7zip/Compress/HuffmanDecoder.h new file mode 100755 index 0000000..f71a582 --- /dev/null +++ b/CPP/7zip/Compress/HuffmanDecoder.h @@ -0,0 +1,89 @@ +// Compress/HuffmanDecoder.h + +#ifndef __COMPRESS_HUFFMAN_DECODER_H +#define __COMPRESS_HUFFMAN_DECODER_H + +#include "../../Common/Types.h" + +namespace NCompress { +namespace NHuffman { + +const int kNumTableBits = 9; + +template +class CDecoder +{ + UInt32 m_Limits[kNumBitsMax + 1]; // m_Limits[i] = value limit for symbols with length = i + UInt32 m_Positions[kNumBitsMax + 1]; // m_Positions[i] = index in m_Symbols[] of first symbol with length = i + UInt32 m_Symbols[m_NumSymbols]; + Byte m_Lengths[1 << kNumTableBits]; // Table oh length for short codes. + +public: + + bool SetCodeLengths(const Byte *codeLengths) + { + int lenCounts[kNumBitsMax + 1]; + UInt32 tmpPositions[kNumBitsMax + 1]; + int i; + for(i = 1; i <= kNumBitsMax; i++) + lenCounts[i] = 0; + UInt32 symbol; + for (symbol = 0; symbol < m_NumSymbols; symbol++) + { + int len = codeLengths[symbol]; + if (len > kNumBitsMax) + return false; + lenCounts[len]++; + m_Symbols[symbol] = 0xFFFFFFFF; + } + lenCounts[0] = 0; + m_Positions[0] = m_Limits[0] = 0; + UInt32 startPos = 0; + UInt32 index = 0; + const UInt32 kMaxValue = (1 << kNumBitsMax); + for (i = 1; i <= kNumBitsMax; i++) + { + startPos += lenCounts[i] << (kNumBitsMax - i); + if (startPos > kMaxValue) + return false; + m_Limits[i] = (i == kNumBitsMax) ? kMaxValue : startPos; + m_Positions[i] = m_Positions[i - 1] + lenCounts[i - 1]; + tmpPositions[i] = m_Positions[i]; + if(i <= kNumTableBits) + { + UInt32 limit = (m_Limits[i] >> (kNumBitsMax - kNumTableBits)); + for (; index < limit; index++) + m_Lengths[index] = (Byte)i; + } + } + for (symbol = 0; symbol < m_NumSymbols; symbol++) + { + int len = codeLengths[symbol]; + if (len != 0) + m_Symbols[tmpPositions[len]++] = symbol; + } + return true; + } + + template + UInt32 DecodeSymbol(TBitDecoder *bitStream) + { + int numBits; + UInt32 value = bitStream->GetValue(kNumBitsMax); + if (value < m_Limits[kNumTableBits]) + numBits = m_Lengths[value >> (kNumBitsMax - kNumTableBits)]; + else + for (numBits = kNumTableBits + 1; value >= m_Limits[numBits]; numBits++); + bitStream->MovePos(numBits); + UInt32 index = m_Positions[numBits] + + ((value - m_Limits[numBits - 1]) >> (kNumBitsMax - numBits)); + if (index >= m_NumSymbols) + // throw CDecoderException(); // test it + return 0xFFFFFFFF; + return m_Symbols[index]; + } +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/ImplodeDecoder.cpp b/CPP/7zip/Compress/ImplodeDecoder.cpp new file mode 100755 index 0000000..6c5e362 --- /dev/null +++ b/CPP/7zip/Compress/ImplodeDecoder.cpp @@ -0,0 +1,219 @@ +// Implode/Decoder.cpp + +#include "StdAfx.h" + +#include "ImplodeDecoder.h" +#include "Common/Defs.h" + +namespace NCompress { +namespace NImplode { +namespace NDecoder { + +class CException +{ +public: + enum ECauseType + { + kData + } m_Cause; + CException(ECauseType cause): m_Cause(cause) {} +}; + +static const int kNumDistanceLowDirectBitsForBigDict = 7; +static const int kNumDistanceLowDirectBitsForSmallDict = 6; + +static const int kNumBitsInByte = 8; + +// static const int kLevelStructuresNumberFieldSize = kNumBitsInByte; +static const int kLevelStructuresNumberAdditionalValue = 1; + +static const int kNumLevelStructureLevelBits = 4; +static const int kLevelStructureLevelAdditionalValue = 1; + +static const int kNumLevelStructureRepNumberBits = 4; +static const int kLevelStructureRepNumberAdditionalValue = 1; + + +static const int kLiteralTableSize = (1 << kNumBitsInByte); +static const int kDistanceTableSize = 64; +static const int kLengthTableSize = 64; + +static const UInt32 kHistorySize = + (1 << MyMax(kNumDistanceLowDirectBitsForBigDict, + kNumDistanceLowDirectBitsForSmallDict)) * + kDistanceTableSize; // = 8 KB; + +static const int kNumAdditionalLengthBits = 8; + +static const UInt32 kMatchMinLenWhenLiteralsOn = 3; +static const UInt32 kMatchMinLenWhenLiteralsOff = 2; + +static const UInt32 kMatchMinLenMax = MyMax(kMatchMinLenWhenLiteralsOn, + kMatchMinLenWhenLiteralsOff); // 3 + +// static const UInt32 kMatchMaxLenMax = kMatchMinLenMax + (kLengthTableSize - 1) + (1 << kNumAdditionalLengthBits) - 1; // or 2 + +enum +{ + kMatchId = 0, + kLiteralId = 1 +}; + + +CCoder::CCoder(): + m_LiteralDecoder(kLiteralTableSize), + m_LengthDecoder(kLengthTableSize), + m_DistanceDecoder(kDistanceTableSize) +{ +} + +void CCoder::ReleaseStreams() +{ + m_OutWindowStream.ReleaseStream(); + m_InBitStream.ReleaseStream(); +} + +bool CCoder::ReadLevelItems(NImplode::NHuffman::CDecoder &decoder, + Byte *levels, int numLevelItems) +{ + int numCodedStructures = m_InBitStream.ReadBits(kNumBitsInByte) + + kLevelStructuresNumberAdditionalValue; + int currentIndex = 0; + for(int i = 0; i < numCodedStructures; i++) + { + int level = m_InBitStream.ReadBits(kNumLevelStructureLevelBits) + + kLevelStructureLevelAdditionalValue; + int rep = m_InBitStream.ReadBits(kNumLevelStructureRepNumberBits) + + kLevelStructureRepNumberAdditionalValue; + if (currentIndex + rep > numLevelItems) + throw CException(CException::kData); + for(int j = 0; j < rep; j++) + levels[currentIndex++] = (Byte)level; + } + if (currentIndex != numLevelItems) + return false; + return decoder.SetCodeLengths(levels); +} + + +bool CCoder::ReadTables(void) +{ + if (m_LiteralsOn) + { + Byte literalLevels[kLiteralTableSize]; + if (!ReadLevelItems(m_LiteralDecoder, literalLevels, kLiteralTableSize)) + return false; + } + + Byte lengthLevels[kLengthTableSize]; + if (!ReadLevelItems(m_LengthDecoder, lengthLevels, kLengthTableSize)) + return false; + + Byte distanceLevels[kDistanceTableSize]; + return ReadLevelItems(m_DistanceDecoder, distanceLevels, kDistanceTableSize); +} + +class CCoderReleaser +{ + CCoder *m_Coder; +public: + CCoderReleaser(CCoder *coder): m_Coder(coder) {} + ~CCoderReleaser() { m_Coder->ReleaseStreams(); } +}; + +HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + if (!m_InBitStream.Create(1 << 20)) + return E_OUTOFMEMORY; + if (!m_OutWindowStream.Create(kHistorySize)) + return E_OUTOFMEMORY; + if (outSize == NULL) + return E_INVALIDARG; + UInt64 pos = 0, unPackSize = *outSize; + + m_OutWindowStream.SetStream(outStream); + m_OutWindowStream.Init(false); + m_InBitStream.SetStream(inStream); + m_InBitStream.Init(); + CCoderReleaser coderReleaser(this); + + if (!ReadTables()) + return S_FALSE; + + while(pos < unPackSize) + { + if (progress != NULL && pos % (1 << 16) == 0) + { + UInt64 packSize = m_InBitStream.GetProcessedSize(); + RINOK(progress->SetRatioInfo(&packSize, &pos)); + } + if(m_InBitStream.ReadBits(1) == kMatchId) // match + { + UInt32 lowDistBits = m_InBitStream.ReadBits(m_NumDistanceLowDirectBits); + UInt32 distance = m_DistanceDecoder.DecodeSymbol(&m_InBitStream); + if (distance >= kDistanceTableSize) + return S_FALSE; + distance = (distance << m_NumDistanceLowDirectBits) + lowDistBits; + UInt32 lengthSymbol = m_LengthDecoder.DecodeSymbol(&m_InBitStream); + if (lengthSymbol >= kLengthTableSize) + return S_FALSE; + UInt32 length = lengthSymbol + m_MinMatchLength; + if (lengthSymbol == kLengthTableSize - 1) // special symbol = 63 + length += m_InBitStream.ReadBits(kNumAdditionalLengthBits); + while(distance >= pos && length > 0) + { + m_OutWindowStream.PutByte(0); + pos++; + length--; + } + if (length > 0) + m_OutWindowStream.CopyBlock(distance, length); + pos += length; + } + else + { + Byte b; + if (m_LiteralsOn) + { + UInt32 temp = m_LiteralDecoder.DecodeSymbol(&m_InBitStream); + if (temp >= kLiteralTableSize) + return S_FALSE; + b = (Byte)temp; + } + else + b = (Byte)m_InBitStream.ReadBits(kNumBitsInByte); + m_OutWindowStream.PutByte(b); + pos++; + } + } + if (pos > unPackSize) + return S_FALSE; + return m_OutWindowStream.Flush(); +} + +STDMETHODIMP CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + try { return CodeReal(inStream, outStream, inSize, outSize, progress); } + catch(const CLzOutWindowException &e) { return e.ErrorCode; } + catch(...) { return S_FALSE; } +} + +STDMETHODIMP CCoder::SetDecoderProperties2(const Byte *data, UInt32 size) +{ + if (size < 1) + return E_INVALIDARG; + Byte flag = data[0]; + m_BigDictionaryOn = ((flag & 2) != 0); + m_NumDistanceLowDirectBits = m_BigDictionaryOn ? + kNumDistanceLowDirectBitsForBigDict: + kNumDistanceLowDirectBitsForSmallDict; + m_LiteralsOn = ((flag & 4) != 0); + m_MinMatchLength = m_LiteralsOn ? + kMatchMinLenWhenLiteralsOn : + kMatchMinLenWhenLiteralsOff; + return S_OK; +} + +}}} diff --git a/CPP/7zip/Compress/ImplodeDecoder.h b/CPP/7zip/Compress/ImplodeDecoder.h new file mode 100755 index 0000000..2b45f05 --- /dev/null +++ b/CPP/7zip/Compress/ImplodeDecoder.h @@ -0,0 +1,57 @@ +// ImplodeDecoder.h + +#ifndef __COMPRESS_IMPLODE_DECODER_H +#define __COMPRESS_IMPLODE_DECODER_H + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +#include "ImplodeHuffmanDecoder.h" +#include "LzOutWindow.h" + +namespace NCompress { +namespace NImplode { +namespace NDecoder { + +class CCoder: + public ICompressCoder, + public ICompressSetDecoderProperties2, + public CMyUnknownImp +{ + CLzOutWindow m_OutWindowStream; + NBitl::CDecoder m_InBitStream; + + NImplode::NHuffman::CDecoder m_LiteralDecoder; + NImplode::NHuffman::CDecoder m_LengthDecoder; + NImplode::NHuffman::CDecoder m_DistanceDecoder; + + bool m_BigDictionaryOn; + bool m_LiteralsOn; + + int m_NumDistanceLowDirectBits; + UInt32 m_MinMatchLength; + + bool ReadLevelItems(NImplode::NHuffman::CDecoder &table, Byte *levels, int numLevelItems); + bool ReadTables(); + void DeCodeLevelTable(Byte *newLevels, int numLevels); +public: + CCoder(); + + MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2) + + void ReleaseStreams(); + HRESULT Flush() { return m_OutWindowStream.Flush(); } + + HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); +}; + +}}} + +#endif diff --git a/CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp b/CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp new file mode 100755 index 0000000..c7a1634 --- /dev/null +++ b/CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp @@ -0,0 +1,89 @@ +// ImplodeHuffmanDecoder.cpp + +#include "StdAfx.h" + +#include "ImplodeHuffmanDecoder.h" + +namespace NCompress { +namespace NImplode { +namespace NHuffman { + +CDecoder::CDecoder(UInt32 numSymbols): + m_NumSymbols(numSymbols) +{ + m_Symbols = new UInt32[m_NumSymbols]; +} + +CDecoder::~CDecoder() +{ + delete []m_Symbols; +} + +bool CDecoder::SetCodeLengths(const Byte *codeLengths) +{ + // int lenCounts[kNumBitsInLongestCode + 1], tmpPositions[kNumBitsInLongestCode + 1]; + int lenCounts[kNumBitsInLongestCode + 2], tmpPositions[kNumBitsInLongestCode + 1]; + int i; + for(i = 0; i <= kNumBitsInLongestCode; i++) + lenCounts[i] = 0; + UInt32 symbolIndex; + for (symbolIndex = 0; symbolIndex < m_NumSymbols; symbolIndex++) + lenCounts[codeLengths[symbolIndex]]++; + // lenCounts[0] = 0; + + // tmpPositions[0] = m_Positions[0] = m_Limitits[0] = 0; + m_Limitits[kNumBitsInLongestCode + 1] = 0; + m_Positions[kNumBitsInLongestCode + 1] = 0; + lenCounts[kNumBitsInLongestCode + 1] = 0; + + + UInt32 startPos = 0; + static const UInt32 kMaxValue = (1 << kNumBitsInLongestCode); + + for (i = kNumBitsInLongestCode; i > 0; i--) + { + startPos += lenCounts[i] << (kNumBitsInLongestCode - i); + if (startPos > kMaxValue) + return false; + m_Limitits[i] = startPos; + m_Positions[i] = m_Positions[i + 1] + lenCounts[i + 1]; + tmpPositions[i] = m_Positions[i] + lenCounts[i]; + + } + + // if _ZIP_MODE do not throw exception for trees containing only one node + // #ifndef _ZIP_MODE + if (startPos != kMaxValue) + return false; + // #endif + + for (symbolIndex = 0; symbolIndex < m_NumSymbols; symbolIndex++) + if (codeLengths[symbolIndex] != 0) + m_Symbols[--tmpPositions[codeLengths[symbolIndex]]] = symbolIndex; + return true; +} + +UInt32 CDecoder::DecodeSymbol(CInBit *inStream) +{ + UInt32 numBits = 0; + UInt32 value = inStream->GetValue(kNumBitsInLongestCode); + int i; + for(i = kNumBitsInLongestCode; i > 0; i--) + { + if (value < m_Limitits[i]) + { + numBits = i; + break; + } + } + if (i == 0) + return 0xFFFFFFFF; + inStream->MovePos(numBits); + UInt32 index = m_Positions[numBits] + + ((value - m_Limitits[numBits + 1]) >> (kNumBitsInLongestCode - numBits)); + if (index >= m_NumSymbols) + return 0xFFFFFFFF; + return m_Symbols[index]; +} + +}}} diff --git a/CPP/7zip/Compress/ImplodeHuffmanDecoder.h b/CPP/7zip/Compress/ImplodeHuffmanDecoder.h new file mode 100755 index 0000000..8936c09 --- /dev/null +++ b/CPP/7zip/Compress/ImplodeHuffmanDecoder.h @@ -0,0 +1,34 @@ +// ImplodeHuffmanDecoder.h + +#ifndef __IMPLODE_HUFFMAN_DECODER_H +#define __IMPLODE_HUFFMAN_DECODER_H + +#include "../Common/InBuffer.h" + +#include "BitlDecoder.h" + +namespace NCompress { +namespace NImplode { +namespace NHuffman { + +const int kNumBitsInLongestCode = 16; + +typedef NBitl::CDecoder CInBit; + +class CDecoder +{ + UInt32 m_Limitits[kNumBitsInLongestCode + 2]; // m_Limitits[i] = value limit for symbols with length = i + UInt32 m_Positions[kNumBitsInLongestCode + 2]; // m_Positions[i] = index in m_Symbols[] of first symbol with length = i + UInt32 m_NumSymbols; // number of symbols in m_Symbols + UInt32 *m_Symbols; // symbols: at first with len=1 then 2, ... 15. +public: + CDecoder(UInt32 numSymbols); + ~CDecoder(); + + bool SetCodeLengths(const Byte *codeLengths); + UInt32 DecodeSymbol(CInBit *inStream); +}; + +}}} + +#endif diff --git a/CPP/7zip/Compress/LzOutWindow.cpp b/CPP/7zip/Compress/LzOutWindow.cpp new file mode 100755 index 0000000..b047894 --- /dev/null +++ b/CPP/7zip/Compress/LzOutWindow.cpp @@ -0,0 +1,14 @@ +// LzOutWindow.cpp + +#include "StdAfx.h" + +#include "LzOutWindow.h" + +void CLzOutWindow::Init(bool solid) +{ + if (!solid) + COutBuffer::Init(); + #ifdef _NO_EXCEPTIONS + ErrorCode = S_OK; + #endif +} diff --git a/CPP/7zip/Compress/LzOutWindow.h b/CPP/7zip/Compress/LzOutWindow.h new file mode 100755 index 0000000..bbec7ad --- /dev/null +++ b/CPP/7zip/Compress/LzOutWindow.h @@ -0,0 +1,66 @@ +// LzOutWindow.h + +#ifndef __LZ_OUT_WINDOW_H +#define __LZ_OUT_WINDOW_H + +#include "../IStream.h" + +#include "../Common/OutBuffer.h" + +#ifndef _NO_EXCEPTIONS +typedef COutBufferException CLzOutWindowException; +#endif + +class CLzOutWindow: public COutBuffer +{ +public: + void Init(bool solid = false); + + // distance >= 0, len > 0, + bool CopyBlock(UInt32 distance, UInt32 len) + { + UInt32 pos = _pos - distance - 1; + if (distance >= _pos) + { + if (!_overDict || distance >= _bufferSize) + return false; + pos += _bufferSize; + } + if (_limitPos - _pos > len && _bufferSize - pos > len) + { + const Byte *src = _buffer + pos; + Byte *dest = _buffer + _pos; + _pos += len; + do + *dest++ = *src++; + while(--len != 0); + } + else do + { + if (pos == _bufferSize) + pos = 0; + _buffer[_pos++] = _buffer[pos++]; + if (_pos == _limitPos) + FlushWithCheck(); + } + while(--len != 0); + return true; + } + + void PutByte(Byte b) + { + _buffer[_pos++] = b; + if (_pos == _limitPos) + FlushWithCheck(); + } + + Byte GetByte(UInt32 distance) const + { + UInt32 pos = _pos - distance - 1; + if (pos >= _bufferSize) + pos += _bufferSize; + return _buffer[pos]; + } +}; + +#endif diff --git a/CPP/7zip/Compress/LzhDecoder.cpp b/CPP/7zip/Compress/LzhDecoder.cpp new file mode 100755 index 0000000..e1591f4 --- /dev/null +++ b/CPP/7zip/Compress/LzhDecoder.cpp @@ -0,0 +1,220 @@ +// LzhDecoder.cpp + +#include "StdAfx.h" + +#include "LzhDecoder.h" + +#include "Windows/Defs.h" + +namespace NCompress{ +namespace NLzh { +namespace NDecoder { + +static const UInt32 kHistorySize = (1 << 16); + +static const int kBlockSizeBits = 16; +static const int kNumCBits = 9; +static const int kNumLevelBits = 5; // smallest integer such that (1 << kNumLevelBits) > kNumLevelSymbols/ + +UInt32 CCoder::ReadBits(int numBits) { return m_InBitStream.ReadBits(numBits); } + +HRESULT CCoder::ReadLevelTable() +{ + int n = ReadBits(kNumLevelBits); + if (n == 0) + { + m_LevelHuffman.Symbol = ReadBits(kNumLevelBits); + if (m_LevelHuffman.Symbol >= kNumLevelSymbols) + return S_FALSE; + } + else + { + if (n > kNumLevelSymbols) + return S_FALSE; + m_LevelHuffman.Symbol = -1; + Byte lens[kNumLevelSymbols]; + int i = 0; + while (i < n) + { + int c = m_InBitStream.ReadBits(3); + if (c == 7) + while (ReadBits(1)) + if (c++ > kMaxHuffmanLen) + return S_FALSE; + lens[i++] = (Byte)c; + if (i == kNumSpecLevelSymbols) + { + c = ReadBits(2); + while (--c >= 0) + lens[i++] = 0; + } + } + while (i < kNumLevelSymbols) + lens[i++] = 0; + m_LevelHuffman.SetCodeLengths(lens); + } + return S_OK; +} + +HRESULT CCoder::ReadPTable(int numBits) +{ + int n = ReadBits(numBits); + if (n == 0) + { + m_PHuffmanDecoder.Symbol = ReadBits(numBits); + if (m_PHuffmanDecoder.Symbol >= kNumDistanceSymbols) + return S_FALSE; + } + else + { + if (n > kNumDistanceSymbols) + return S_FALSE; + m_PHuffmanDecoder.Symbol = -1; + Byte lens[kNumDistanceSymbols]; + int i = 0; + while (i < n) + { + int c = m_InBitStream.ReadBits(3); + if (c == 7) + while (ReadBits(1)) + { + if (c > kMaxHuffmanLen) + return S_FALSE; + c++; + } + lens[i++] = (Byte)c; + } + while (i < kNumDistanceSymbols) + lens[i++] = 0; + m_PHuffmanDecoder.SetCodeLengths(lens); + } + return S_OK; +} + +HRESULT CCoder::ReadCTable() +{ + int n = ReadBits(kNumCBits); + if (n == 0) + { + m_CHuffmanDecoder.Symbol = ReadBits(kNumCBits); + if (m_CHuffmanDecoder.Symbol >= kNumCSymbols) + return S_FALSE; + } + else + { + if (n > kNumCSymbols) + return S_FALSE; + m_CHuffmanDecoder.Symbol = -1; + Byte lens[kNumCSymbols]; + int i = 0; + while (i < n) + { + int c = m_LevelHuffman.Decode(&m_InBitStream); + if (c < kNumSpecLevelSymbols) + { + if (c == 0) + c = 1; + else if (c == 1) + c = ReadBits(4) + 3; + else + c = ReadBits(kNumCBits) + 20; + while (--c >= 0) + { + if (i > kNumCSymbols) + return S_FALSE; + lens[i++] = 0; + } + } + else + lens[i++] = (Byte)(c - 2); + } + while (i < kNumCSymbols) + lens[i++] = 0; + m_CHuffmanDecoder.SetCodeLengths(lens); + } + return S_OK; +} + +STDMETHODIMP CCoder::CodeReal(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, + ICompressProgressInfo *progress) +{ + if (outSize == NULL) + return E_INVALIDARG; + + if (!m_OutWindowStream.Create(kHistorySize)) + return E_OUTOFMEMORY; + if (!m_InBitStream.Create(1 << 20)) + return E_OUTOFMEMORY; + + UInt64 pos = 0; + m_OutWindowStream.SetStream(outStream); + m_OutWindowStream.Init(false); + m_InBitStream.SetStream(inStream); + m_InBitStream.Init(); + + CCoderReleaser coderReleaser(this); + + int pbit; + if (m_NumDictBits <= 13) + pbit = 4; + else + pbit = 5; + + UInt32 blockSize = 0; + + while(pos < *outSize) + { + // for (i = 0; i < dictSize; i++) dtext[i] = 0x20; + + if (blockSize == 0) + { + if (progress != NULL) + { + UInt64 packSize = m_InBitStream.GetProcessedSize(); + RINOK(progress->SetRatioInfo(&packSize, &pos)); + } + blockSize = ReadBits(kBlockSizeBits); + ReadLevelTable(); + ReadCTable(); + RINOK(ReadPTable(pbit)); + } + blockSize--; + UInt32 c = m_CHuffmanDecoder.Decode(&m_InBitStream); + if (c < 256) + { + m_OutWindowStream.PutByte((Byte)c); + pos++; + } + else if (c >= kNumCSymbols) + return S_FALSE; + else + { + // offset = (interface->method == LARC_METHOD_NUM) ? 0x100 - 2 : 0x100 - 3; + UInt32 len = c - 256 + kMinMatch; + UInt32 distance = m_PHuffmanDecoder.Decode(&m_InBitStream); + if (distance != 0) + distance = (1 << (distance - 1)) + ReadBits(distance - 1); + if (distance >= pos) + return S_FALSE; + if (pos + len > *outSize) + len = (UInt32)(*outSize - pos); + pos += len; + m_OutWindowStream.CopyBlock(distance, len); + } + } + coderReleaser.NeedFlush = false; + return m_OutWindowStream.Flush(); +} + +STDMETHODIMP CCoder::Code(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress) +{ + try { return CodeReal(inStream, outStream, inSize, outSize, progress);} + catch(const CInBufferException &e) { return e.ErrorCode; } + catch(const CLzOutWindowException &e) { return e.ErrorCode; } + catch(...) { return S_FALSE; } +} + +}}} diff --git a/CPP/7zip/Compress/LzhDecoder.h b/CPP/7zip/Compress/LzhDecoder.h new file mode 100755 index 0000000..3048797 --- /dev/null +++ b/CPP/7zip/Compress/LzhDecoder.h @@ -0,0 +1,106 @@ +// LzhDecoder.h + +#ifndef __COMPRESS_LZH_DECODER_H +#define __COMPRESS_LZH_DECODER_H + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +#include "../Common/InBuffer.h" + +#include "BitmDecoder.h" +#include "HuffmanDecoder.h" +#include "LzOutWindow.h" + +namespace NCompress { +namespace NLzh { +namespace NDecoder { + +const int kMaxHuffmanLen = 16; // Check it + +const int kNumSpecLevelSymbols = 3; +const int kNumLevelSymbols = kNumSpecLevelSymbols + kMaxHuffmanLen; + +const int kDictBitsMax = 16; +const int kNumDistanceSymbols = kDictBitsMax + 1; + +const int kMaxMatch = 256; +const int kMinMatch = 3; +const int kNumCSymbols = 256 + kMaxMatch + 2 - kMinMatch; + +template +class CHuffmanDecoder:public NCompress::NHuffman::CDecoder +{ +public: + int Symbol; + template + UInt32 Decode(TBitDecoder *bitStream) + { + if (Symbol >= 0) + return (UInt32)Symbol; + return DecodeSymbol(bitStream); + } +}; + +class CCoder : + public ICompressCoder, + public CMyUnknownImp +{ + CLzOutWindow m_OutWindowStream; + NBitm::CDecoder m_InBitStream; + + int m_NumDictBits; + + CHuffmanDecoder m_LevelHuffman; + CHuffmanDecoder m_PHuffmanDecoder; + CHuffmanDecoder m_CHuffmanDecoder; + + void ReleaseStreams() + { + m_OutWindowStream.ReleaseStream(); + m_InBitStream.ReleaseStream(); + } + + class CCoderReleaser + { + CCoder *m_Coder; + public: + bool NeedFlush; + CCoderReleaser(CCoder *coder): m_Coder(coder), NeedFlush(true) {} + ~CCoderReleaser() + { + if (NeedFlush) + m_Coder->m_OutWindowStream.Flush(); + m_Coder->ReleaseStreams(); + } + }; + friend class CCoderReleaser; + + void MakeTable(int nchar, Byte *bitlen, int tablebits, + UInt32 *table, int tablesize); + + UInt32 ReadBits(int numBits); + HRESULT ReadLevelTable(); + HRESULT ReadPTable(int numBits); + HRESULT ReadCTable(); + +public: + + MY_UNKNOWN_IMP + + STDMETHOD(CodeReal)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); + + STDMETHOD(Code)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); + + void SetDictionary(int numDictBits) { m_NumDictBits = numDictBits; } + CCoder(): m_NumDictBits(0) {} +}; + +}}} + +#endif diff --git a/CPP/7zip/Compress/Lzma2Decoder.cpp b/CPP/7zip/Compress/Lzma2Decoder.cpp new file mode 100755 index 0000000..8d3d830 --- /dev/null +++ b/CPP/7zip/Compress/Lzma2Decoder.cpp @@ -0,0 +1,189 @@ +// Lzma2Decoder.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "../Common/StreamUtils.h" + +#include "Lzma2Decoder.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_PROGRESS: return E_ABORT; + case SZ_ERROR_DATA: return S_FALSE; + } + return E_FAIL; +} + +namespace NCompress { +namespace NLzma2 { + +static const UInt32 kInBufSize = 1 << 20; + +CDecoder::CDecoder(): _inBuf(0), _outSizeDefined(false) +{ + Lzma2Dec_Construct(&_state); +} + +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } +static void SzFree(void *p, void *address) { p = p; MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +CDecoder::~CDecoder() +{ + Lzma2Dec_Free(&_state, &g_Alloc); + MyFree(_inBuf); +} + +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size) +{ + if (size != 1) return SZ_ERROR_UNSUPPORTED; + RINOK(SResToHRESULT(Lzma2Dec_Allocate(&_state, prop[0], &g_Alloc))); + if (_inBuf == 0) + { + _inBuf = (Byte *)MyAlloc(kInBufSize); + if (_inBuf == 0) + return E_OUTOFMEMORY; + } + + return S_OK; +} + +STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) { *value = _inSizeProcessed; return S_OK; } +STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; } +STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; } + +STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) +{ + _outSizeDefined = (outSize != NULL); + if (_outSizeDefined) + _outSize = *outSize; + + Lzma2Dec_Init(&_state); + + _inPos = _inSize = 0; + _inSizeProcessed = _outSizeProcessed = 0; + return S_OK; +} + +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 * /* inSize */, + const UInt64 *outSize, ICompressProgressInfo *progress) +{ + if (_inBuf == 0) + return S_FALSE; + SetOutStreamSize(outSize); + + for (;;) + { + if (_inPos == _inSize) + { + _inPos = _inSize = 0; + RINOK(inStream->Read(_inBuf, kInBufSize, &_inSize)); + } + + SizeT dicPos = _state.decoder.dicPos; + SizeT curSize = _state.decoder.dicBufSize - dicPos; + const UInt32 kStepSize = ((UInt32)1 << 22); + if (curSize > kStepSize) + curSize = (SizeT)kStepSize; + + ELzmaFinishMode finishMode = LZMA_FINISH_ANY; + if (_outSizeDefined) + { + const UInt64 rem = _outSize - _outSizeProcessed; + if (rem < curSize) + { + curSize = (SizeT)rem; + /* + // finishMode = LZMA_FINISH_END; + we can't use LZMA_FINISH_END here to allow partial decoding + */ + } + } + + SizeT inSizeProcessed = _inSize - _inPos; + ELzmaStatus status; + SRes res = Lzma2Dec_DecodeToDic(&_state, dicPos + curSize, _inBuf + _inPos, &inSizeProcessed, finishMode, &status); + + _inPos += (UInt32)inSizeProcessed; + _inSizeProcessed += inSizeProcessed; + SizeT outSizeProcessed = _state.decoder.dicPos - dicPos; + _outSizeProcessed += outSizeProcessed; + + bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0); + bool stopDecoding = (_outSizeDefined && _outSizeProcessed >= _outSize); + + if (res != 0 || _state.decoder.dicPos == _state.decoder.dicBufSize || finished || stopDecoding) + { + HRESULT res2 = WriteStream(outStream, _state.decoder.dic, _state.decoder.dicPos); + if (res != 0) + return S_FALSE; + RINOK(res2); + if (stopDecoding) + return S_OK; + if (finished) + return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE); + } + if (_state.decoder.dicPos == _state.decoder.dicBufSize) + _state.decoder.dicPos = 0; + + if (progress != NULL) + { + RINOK(progress->SetRatioInfo(&_inSizeProcessed, &_outSizeProcessed)); + } + } +} + +#ifndef NO_READ_FROM_CODER + +STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + do + { + if (_inPos == _inSize) + { + _inPos = _inSize = 0; + RINOK(_inStream->Read(_inBuf, kInBufSize, &_inSize)); + } + { + SizeT inProcessed = _inSize - _inPos; + + if (_outSizeDefined) + { + const UInt64 rem = _outSize - _outSizeProcessed; + if (rem < size) + size = (UInt32)rem; + } + + SizeT outProcessed = size; + ELzmaStatus status; + SRes res = Lzma2Dec_DecodeToBuf(&_state, (Byte *)data, &outProcessed, + _inBuf + _inPos, &inProcessed, LZMA_FINISH_ANY, &status); + _inPos += (UInt32)inProcessed; + _inSizeProcessed += inProcessed; + _outSizeProcessed += outProcessed; + size -= (UInt32)outProcessed; + data = (Byte *)data + outProcessed; + if (processedSize) + *processedSize += (UInt32)outProcessed; + RINOK(SResToHRESULT(res)); + if (inProcessed == 0 && outProcessed == 0) + return S_OK; + } + } + while (size != 0); + return S_OK; +} + +#endif + +}} diff --git a/CPP/7zip/Compress/Lzma2Decoder.h b/CPP/7zip/Compress/Lzma2Decoder.h new file mode 100755 index 0000000..3540097 --- /dev/null +++ b/CPP/7zip/Compress/Lzma2Decoder.h @@ -0,0 +1,73 @@ +// Lzma2Decoder.h + +#ifndef __LZMA2_DECODER_H +#define __LZMA2_DECODER_H + +#include "../../../C/Lzma2Dec.h" + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +namespace NCompress { +namespace NLzma2 { + +class CDecoder: + public ICompressCoder, + public ICompressSetDecoderProperties2, + public ICompressGetInStreamProcessedSize, + #ifndef NO_READ_FROM_CODER + public ICompressSetInStream, + public ICompressSetOutStreamSize, + public ISequentialInStream, + #endif + public CMyUnknownImp +{ + CMyComPtr _inStream; + Byte *_inBuf; + UInt32 _inPos; + UInt32 _inSize; + CLzma2Dec _state; + bool _outSizeDefined; + UInt64 _outSize; + UInt64 _inSizeProcessed; + UInt64 _outSizeProcessed; +public: + + #ifndef NO_READ_FROM_CODER + MY_UNKNOWN_IMP5( + ICompressSetDecoderProperties2, + ICompressGetInStreamProcessedSize, + ICompressSetInStream, + ICompressSetOutStreamSize, + ISequentialInStream) + #else + MY_UNKNOWN_IMP2( + ICompressSetDecoderProperties2, + ICompressGetInStreamProcessedSize) + #endif + + 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(SetInStream)(ISequentialInStream *inStream); + STDMETHOD(ReleaseInStream)(); + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); + + #ifndef NO_READ_FROM_CODER + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + #endif + + CDecoder(); + virtual ~CDecoder(); + +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/Lzma2Encoder.cpp b/CPP/7zip/Compress/Lzma2Encoder.cpp new file mode 100755 index 0000000..871f146 --- /dev/null +++ b/CPP/7zip/Compress/Lzma2Encoder.cpp @@ -0,0 +1,94 @@ +// 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 { + +static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } +static void SzBigFree(void *, void *address) { BigFree(address); } +static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; + +static void *SzAlloc(void *, size_t size) { return MyAlloc(size); } +static void SzFree(void *, void *address) { MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +CEncoder::CEncoder() +{ + _encoder = 0; + _encoder = Lzma2Enc_Create(&g_Alloc, &g_BigAlloc); + if (_encoder == 0) + throw 1; +} + +CEncoder::~CEncoder() +{ + if (_encoder != 0) + Lzma2Enc_Destroy(_encoder); +} + +HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props) +{ + switch (propID) + { + case NCoderPropID::kBlockSize: + if (prop.vt != VT_UI4) return E_INVALIDARG; lzma2Props.blockSize = prop.ulVal; 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::WriteCoderProperties(ISequentialOutStream *outStream) +{ + Byte prop = Lzma2Enc_WriteProperties(_encoder); + return WriteStream(outStream, &prop, 1); +} + +STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) +{ + CSeqInStreamWrap inWrap(inStream); + CSeqOutStreamWrap outWrap(outStream); + CCompressProgressWrap progressWrap(progress); + + SRes res = Lzma2Enc_Encode(_encoder, &outWrap.p, &inWrap.p, progress ? &progressWrap.p : NULL); + if (res == SZ_ERROR_READ && inWrap.Res != S_OK) + return inWrap.Res; + if (res == SZ_ERROR_WRITE && outWrap.Res != S_OK) + return outWrap.Res; + if (res == SZ_ERROR_PROGRESS && progressWrap.Res != S_OK) + return progressWrap.Res; + return SResToHRESULT(res); +} + +}} diff --git a/CPP/7zip/Compress/Lzma2Encoder.h b/CPP/7zip/Compress/Lzma2Encoder.h new file mode 100755 index 0000000..fc43702 --- /dev/null +++ b/CPP/7zip/Compress/Lzma2Encoder.h @@ -0,0 +1,36 @@ +// 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 CMyUnknownImp +{ + CLzma2EncHandle _encoder; +public: + MY_UNKNOWN_IMP2(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(); + virtual ~CEncoder(); +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/Lzma2Register.cpp b/CPP/7zip/Compress/Lzma2Register.cpp new file mode 100755 index 0000000..28430b4 --- /dev/null +++ b/CPP/7zip/Compress/Lzma2Register.cpp @@ -0,0 +1,20 @@ +// Lzma2Register.cpp + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" + +#include "Lzma2Decoder.h" + +static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NLzma2::CDecoder); } +#ifndef EXTRACT_ONLY +#include "Lzma2Encoder.h" +static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NLzma2::CEncoder); } +#else +#define CreateCodecOut 0 +#endif + +static CCodecInfo g_CodecInfo = + { CreateCodec, CreateCodecOut, 0x21, L"LZMA2", 1, false }; + +REGISTER_CODEC(LZMA2) diff --git a/CPP/7zip/Compress/LzmaDecoder.cpp b/CPP/7zip/Compress/LzmaDecoder.cpp new file mode 100755 index 0000000..9f15fdb --- /dev/null +++ b/CPP/7zip/Compress/LzmaDecoder.cpp @@ -0,0 +1,252 @@ +// 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(0), _propsWereSet(false), _outSizeDefined(false), + _inBufSize(1 << 20), + _outBufSize(1 << 22), + FinishStream(false) +{ + _inSizeProcessed = 0; + _inPos = _inSize = 0; + LzmaDec_Construct(&_state); +} + +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } +static void SzFree(void *p, void *address) { p = p; MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +CDecoder::~CDecoder() +{ + LzmaDec_Free(&_state, &g_Alloc); + MyFree(_inBuf); +} + +STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSize = size; return S_OK; } +STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outBufSize = size; return S_OK; } + +HRESULT CDecoder::CreateInputBuffer() +{ + if (_inBuf == 0 || _inBufSize != _inBufSizeAllocated) + { + MyFree(_inBuf); + _inBuf = (Byte *)MyAlloc(_inBufSize); + if (_inBuf == 0) + return E_OUTOFMEMORY; + _inBufSizeAllocated = _inBufSize; + } + return S_OK; +} + +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size) +{ + RINOK(SResToHRESULT(LzmaDec_Allocate(&_state, prop, size, &g_Alloc))); + _propsWereSet = true; + return CreateInputBuffer(); +} + +void CDecoder::SetOutStreamSizeResume(const UInt64 *outSize) +{ + _outSizeDefined = (outSize != NULL); + if (_outSizeDefined) + _outSize = *outSize; + _outSizeProcessed = 0; + _wrPos = 0; + LzmaDec_Init(&_state); +} + +STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) +{ + _inSizeProcessed = 0; + _inPos = _inSize = 0; + SetOutStreamSizeResume(outSize); + return S_OK; +} + +HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress) +{ + if (_inBuf == 0 || !_propsWereSet) + return S_FALSE; + + UInt64 startInProgress = _inSizeProcessed; + + SizeT next = (_state.dicBufSize - _state.dicPos < _outBufSize) ? _state.dicBufSize : (_state.dicPos + _outBufSize); + for (;;) + { + if (_inPos == _inSize) + { + _inPos = _inSize = 0; + RINOK(inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize)); + } + + SizeT dicPos = _state.dicPos; + SizeT curSize = next - dicPos; + + ELzmaFinishMode finishMode = LZMA_FINISH_ANY; + if (_outSizeDefined) + { + const UInt64 rem = _outSize - _outSizeProcessed; + if (rem <= curSize) + { + curSize = (SizeT)rem; + if (FinishStream) + finishMode = LZMA_FINISH_END; + } + } + + SizeT inSizeProcessed = _inSize - _inPos; + ELzmaStatus status; + SRes res = LzmaDec_DecodeToDic(&_state, dicPos + curSize, _inBuf + _inPos, &inSizeProcessed, finishMode, &status); + + _inPos += (UInt32)inSizeProcessed; + _inSizeProcessed += inSizeProcessed; + SizeT outSizeProcessed = _state.dicPos - dicPos; + _outSizeProcessed += outSizeProcessed; + + bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0); + bool stopDecoding = (_outSizeDefined && _outSizeProcessed >= _outSize); + + if (res != 0 || _state.dicPos == next || finished || stopDecoding) + { + HRESULT res2 = WriteStream(outStream, _state.dic + _wrPos, _state.dicPos - _wrPos); + + _wrPos = _state.dicPos; + if (_state.dicPos == _state.dicBufSize) + { + _state.dicPos = 0; + _wrPos = 0; + } + next = (_state.dicBufSize - _state.dicPos < _outBufSize) ? _state.dicBufSize : (_state.dicPos + _outBufSize); + + if (res != 0) + return S_FALSE; + RINOK(res2); + if (stopDecoding) + return S_OK; + if (finished) + return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE); + } + if (progress) + { + UInt64 inSize = _inSizeProcessed - startInProgress; + RINOK(progress->SetRatioInfo(&inSize, &_outSizeProcessed)); + } + } +} + +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + if (_inBuf == 0) + return E_INVALIDARG; + SetOutStreamSize(outSize); + return CodeSpec(inStream, outStream, progress); +} + +#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; + do + { + if (_inPos == _inSize) + { + _inPos = _inSize = 0; + RINOK(_inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize)); + } + { + SizeT inProcessed = _inSize - _inPos; + + if (_outSizeDefined) + { + const UInt64 rem = _outSize - _outSizeProcessed; + if (rem < size) + size = (UInt32)rem; + } + + SizeT outProcessed = size; + ELzmaStatus status; + SRes res = LzmaDec_DecodeToBuf(&_state, (Byte *)data, &outProcessed, + _inBuf + _inPos, &inProcessed, LZMA_FINISH_ANY, &status); + _inPos += (UInt32)inProcessed; + _inSizeProcessed += inProcessed; + _outSizeProcessed += outProcessed; + size -= (UInt32)outProcessed; + data = (Byte *)data + outProcessed; + if (processedSize) + *processedSize += (UInt32)outProcessed; + RINOK(SResToHRESULT(res)); + if (inProcessed == 0 && outProcessed == 0) + return S_OK; + } + } + while (size != 0); + return S_OK; +} + +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; + while (size > 0) + { + if (_inPos == _inSize) + { + _inPos = _inSize = 0; + RINOK(_inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize)); + if (_inSize == 0) + break; + } + { + UInt32 curSize = _inSize - _inPos; + if (curSize > size) + curSize = size; + memcpy(data, _inBuf + _inPos, curSize); + _inPos += curSize; + _inSizeProcessed += curSize; + size -= curSize; + data = (Byte *)data + curSize; + if (processedSize) + *processedSize += curSize; + } + } + return S_OK; +} + +#endif + +}} diff --git a/CPP/7zip/Compress/LzmaDecoder.h b/CPP/7zip/Compress/LzmaDecoder.h new file mode 100755 index 0000000..801a77b --- /dev/null +++ b/CPP/7zip/Compress/LzmaDecoder.h @@ -0,0 +1,84 @@ +// LzmaDecoder.h + +#ifndef __LZMA_DECODER_H +#define __LZMA_DECODER_H + +#include "../../../C/LzmaDec.h" + +#include "../../Common/MyCom.h" +#include "../ICoder.h" + +namespace NCompress { +namespace NLzma { + +class CDecoder: + public ICompressCoder, + public ICompressSetDecoderProperties2, + public ICompressSetBufSize, + #ifndef NO_READ_FROM_CODER + public ICompressSetInStream, + public ICompressSetOutStreamSize, + public ISequentialInStream, + #endif + public CMyUnknownImp +{ + CMyComPtr _inStream; + Byte *_inBuf; + UInt32 _inPos; + UInt32 _inSize; + CLzmaDec _state; + bool _propsWereSet; + bool _outSizeDefined; + UInt64 _outSize; + UInt64 _inSizeProcessed; + UInt64 _outSizeProcessed; + + UInt32 _inBufSizeAllocated; + UInt32 _inBufSize; + UInt32 _outBufSize; + SizeT _wrPos; + + 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(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(SetOutStreamSize)(const UInt64 *outSize); + STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size); + STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size); + + #ifndef NO_READ_FROM_CODER + + 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); + UInt64 GetInputProcessedSize() const { return _inSizeProcessed; } + + #endif + + bool FinishStream; + + CDecoder(); + virtual ~CDecoder(); +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/LzmaEncoder.cpp b/CPP/7zip/Compress/LzmaEncoder.cpp new file mode 100755 index 0000000..aa96c0e --- /dev/null +++ b/CPP/7zip/Compress/LzmaEncoder.cpp @@ -0,0 +1,149 @@ +// LzmaEncoder.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "../Common/CWrappers.h" +#include "../Common/StreamUtils.h" + +#include "LzmaEncoder.h" + +namespace NCompress { +namespace NLzma { + +static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } +static void SzBigFree(void *, void *address) { BigFree(address); } +static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; + +static void *SzAlloc(void *, size_t size) { return MyAlloc(size); } +static void SzFree(void *, void *address) { MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +CEncoder::CEncoder() +{ + _encoder = 0; + _encoder = LzmaEnc_Create(&g_Alloc); + if (_encoder == 0) + throw 1; +} + +CEncoder::~CEncoder() +{ + if (_encoder != 0) + LzmaEnc_Destroy(_encoder, &g_Alloc, &g_BigAlloc); +} + +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; + c = GetUpperChar(*s++); + if (c != L'\0') + return 0; + *btMode = 1; + *numHashBytes = numHashBytesLoc; + return 1; +} + +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 (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 v = prop.ulVal; + switch (propID) + { + case NCoderPropID::kNumFastBytes: ep.fb = v; break; + case NCoderPropID::kMatchFinderCycles: ep.mc = v; break; + case NCoderPropID::kAlgorithm: ep.algo = v; break; + case NCoderPropID::kDictionarySize: ep.dictSize = v; break; + case NCoderPropID::kPosStateBits: ep.pb = v; break; + case NCoderPropID::kLitPosBits: ep.lp = v; break; + case NCoderPropID::kLitContextBits: ep.lc = v; break; + 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_TRUE); break; + case NCoderPropID::kNumThreads: + if (prop.vt != VT_UI4) return E_INVALIDARG; props.numThreads = prop.ulVal; break; + default: + RINOK(SetLzmaProp(propID, prop, props)); + } + } + return SResToHRESULT(LzmaEnc_SetProps(_encoder, &props)); +} + +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); +} + +STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) +{ + CSeqInStreamWrap inWrap(inStream); + CSeqOutStreamWrap outWrap(outStream); + CCompressProgressWrap progressWrap(progress); + + SRes res = LzmaEnc_Encode(_encoder, &outWrap.p, &inWrap.p, progress ? &progressWrap.p : NULL, &g_Alloc, &g_BigAlloc); + if (res == SZ_ERROR_READ && inWrap.Res != S_OK) + return inWrap.Res; + if (res == SZ_ERROR_WRITE && outWrap.Res != S_OK) + return outWrap.Res; + if (res == SZ_ERROR_PROGRESS && progressWrap.Res != S_OK) + return progressWrap.Res; + return SResToHRESULT(res); +} + +}} diff --git a/CPP/7zip/Compress/LzmaEncoder.h b/CPP/7zip/Compress/LzmaEncoder.h new file mode 100755 index 0000000..c3e8961 --- /dev/null +++ b/CPP/7zip/Compress/LzmaEncoder.h @@ -0,0 +1,36 @@ +// 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 CMyUnknownImp +{ + CLzmaEncHandle _encoder; +public: + MY_UNKNOWN_IMP2(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(); + virtual ~CEncoder(); +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/LzmaRegister.cpp b/CPP/7zip/Compress/LzmaRegister.cpp new file mode 100755 index 0000000..9c67eaf --- /dev/null +++ b/CPP/7zip/Compress/LzmaRegister.cpp @@ -0,0 +1,20 @@ +// LzmaRegister.cpp + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" + +#include "LzmaDecoder.h" + +static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NLzma::CDecoder); } +#ifndef EXTRACT_ONLY +#include "LzmaEncoder.h" +static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NLzma::CEncoder); } +#else +#define CreateCodecOut 0 +#endif + +static CCodecInfo g_CodecInfo = + { CreateCodec, CreateCodecOut, 0x030101, L"LZMA", 1, false }; + +REGISTER_CODEC(LZMA) diff --git a/CPP/7zip/Compress/Lzx.h b/CPP/7zip/Compress/Lzx.h new file mode 100755 index 0000000..4d4ba84 --- /dev/null +++ b/CPP/7zip/Compress/Lzx.h @@ -0,0 +1,61 @@ +// Lzx.h + +#ifndef __COMPRESS_LZX_H +#define __COMPRESS_LZX_H + +namespace NCompress { +namespace NLzx { + +const unsigned kNumHuffmanBits = 16; +const UInt32 kNumRepDistances = 3; + +const UInt32 kNumLenSlots = 8; +const UInt32 kMatchMinLen = 2; +const UInt32 kNumLenSymbols = 249; +const UInt32 kMatchMaxLen = kMatchMinLen + (kNumLenSlots - 1) + kNumLenSymbols - 1; + +const unsigned kNumAlignBits = 3; +const UInt32 kAlignTableSize = 1 << kNumAlignBits; + +const UInt32 kNumPosSlots = 50; +const UInt32 kNumPosLenSlots = kNumPosSlots * kNumLenSlots; + +const UInt32 kMainTableSize = 256 + kNumPosLenSlots; +const UInt32 kLevelTableSize = 20; +const UInt32 kMaxTableSize = kMainTableSize; + +const unsigned kNumBlockTypeBits = 3; +const unsigned kBlockTypeVerbatim = 1; +const unsigned kBlockTypeAligned = 2; +const unsigned kBlockTypeUncompressed = 3; + +const unsigned kUncompressedBlockSizeNumBits = 24; + +const unsigned kNumBitsForPreTreeLevel = 4; + +const unsigned kLevelSymbolZeros = 17; +const unsigned kLevelSymbolZerosBig = 18; +const unsigned kLevelSymbolSame = 19; + +const unsigned kLevelSymbolZerosStartValue = 4; +const unsigned kLevelSymbolZerosNumBits = 4; + +const unsigned kLevelSymbolZerosBigStartValue = kLevelSymbolZerosStartValue + + (1 << kLevelSymbolZerosNumBits); +const unsigned kLevelSymbolZerosBigNumBits = 5; + +const unsigned kLevelSymbolSameNumBits = 1; +const unsigned kLevelSymbolSameStartValue = 4; + +const unsigned kNumBitsForAlignLevel = 3; + +const unsigned kNumDictionaryBitsMin = 15; +const unsigned kNumDictionaryBitsMax = 21; +const UInt32 kDictionarySizeMax = (1 << kNumDictionaryBitsMax); + +const unsigned kNumLinearPosSlotBits = 17; +const UInt32 kNumPowerPosSlots = 0x26; + +}} + +#endif diff --git a/CPP/7zip/Compress/Lzx86Converter.cpp b/CPP/7zip/Compress/Lzx86Converter.cpp new file mode 100755 index 0000000..c74a7fa --- /dev/null +++ b/CPP/7zip/Compress/Lzx86Converter.cpp @@ -0,0 +1,90 @@ +// Lzx86Converter.cpp + +#include "StdAfx.h" + +#include "../../Common/Defs.h" + +#include "Lzx86Converter.h" + +namespace NCompress { +namespace NLzx { + +static const int kResidue = 6 + 4; + +void Cx86ConvertOutStream::MakeTranslation() +{ + if (m_Pos <= kResidue) + return; + UInt32 numBytes = m_Pos - kResidue; + Byte *buffer = m_Buffer; + for (UInt32 i = 0; i < numBytes;) + { + if (buffer[i++] == 0xE8) + { + Int32 absValue = 0; + int j; + for(j = 0; j < 4; j++) + absValue += (UInt32)buffer[i + j] << (j * 8); + Int32 pos = (Int32)(m_ProcessedSize + i - 1); + if (absValue >= -pos && absValue < (Int32)m_TranslationSize) + { + UInt32 offset = (absValue >= 0) ? + absValue - pos : + absValue + m_TranslationSize; + for(j = 0; j < 4; j++) + { + buffer[i + j] = (Byte)(offset & 0xFF); + offset >>= 8; + } + } + i += 4; + } + } +} + +STDMETHODIMP Cx86ConvertOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != NULL) + *processedSize = 0; + if (!m_TranslationMode) + return m_Stream->Write(data, size, processedSize); + UInt32 realProcessedSize = 0; + while (realProcessedSize < size) + { + UInt32 writeSize = MyMin(size - realProcessedSize, kUncompressedBlockSize - m_Pos); + memmove(m_Buffer + m_Pos, (const Byte *)data + realProcessedSize, writeSize); + m_Pos += writeSize; + realProcessedSize += writeSize; + if (m_Pos == kUncompressedBlockSize) + { + RINOK(Flush()); + } + } + if (processedSize != NULL) + *processedSize = realProcessedSize; + return S_OK; +} + +HRESULT Cx86ConvertOutStream::Flush() +{ + if (m_Pos == 0) + return S_OK; + if (m_TranslationMode) + MakeTranslation(); + UInt32 pos = 0; + do + { + UInt32 processed; + RINOK(m_Stream->Write(m_Buffer + pos, m_Pos - pos, &processed)); + if (processed == 0) + return E_FAIL; + pos += processed; + } + while(pos < m_Pos); + m_ProcessedSize += m_Pos; + m_Pos = 0; + m_TranslationMode = (m_TranslationMode && (m_ProcessedSize < (1 << 30))); + return S_OK; +} + +}} diff --git a/CPP/7zip/Compress/Lzx86Converter.h b/CPP/7zip/Compress/Lzx86Converter.h new file mode 100755 index 0000000..a373e8b --- /dev/null +++ b/CPP/7zip/Compress/Lzx86Converter.h @@ -0,0 +1,46 @@ +// Lzx86Converter.h + +#ifndef __LZX_86_CONVERTER_H +#define __LZX_86_CONVERTER_H + +#include "../../Common/MyCom.h" + +#include "../IStream.h" + +namespace NCompress { +namespace NLzx { + +const int kUncompressedBlockSize = 1 << 15; + +class Cx86ConvertOutStream: + public ISequentialOutStream, + public CMyUnknownImp +{ + CMyComPtr m_Stream; + UInt32 m_ProcessedSize; + UInt32 m_Pos; + UInt32 m_TranslationSize; + bool m_TranslationMode; + Byte m_Buffer[kUncompressedBlockSize]; + + void MakeTranslation(); +public: + void SetStream(ISequentialOutStream *outStream) { m_Stream = outStream; } + void ReleaseStream() { m_Stream.Release(); } + void Init(bool translationMode, UInt32 translationSize) + { + m_TranslationMode = translationMode; + m_TranslationSize = translationSize; + m_ProcessedSize = 0; + m_Pos = 0; + } + HRESULT Flush(); + + MY_UNKNOWN_IMP + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/LzxDecoder.cpp b/CPP/7zip/Compress/LzxDecoder.cpp new file mode 100755 index 0000000..1c08feb --- /dev/null +++ b/CPP/7zip/Compress/LzxDecoder.cpp @@ -0,0 +1,387 @@ +// LzxDecoder.cpp + +#include "StdAfx.h" + +#include "../../Common/Defs.h" + +#include "LzxDecoder.h" + +namespace NCompress { +namespace NLzx { + +const int kLenIdNeedInit = -2; + +CDecoder::CDecoder(bool wimMode): + _keepHistory(false), + _skipByte(false), + _wimMode(wimMode) +{ + m_x86ConvertOutStreamSpec = new Cx86ConvertOutStream; + m_x86ConvertOutStream = m_x86ConvertOutStreamSpec; +} + +void CDecoder::ReleaseStreams() +{ + m_OutWindowStream.ReleaseStream(); + m_InBitStream.ReleaseStream(); + m_x86ConvertOutStreamSpec->ReleaseStream(); +} + +STDMETHODIMP CDecoder::Flush() +{ + RINOK(m_OutWindowStream.Flush()); + return m_x86ConvertOutStreamSpec->Flush(); +} + +UInt32 CDecoder::ReadBits(unsigned numBits) { return m_InBitStream.ReadBits(numBits); } + +#define RIF(x) { if (!(x)) return false; } + +bool CDecoder::ReadTable(Byte *lastLevels, Byte *newLevels, UInt32 numSymbols) +{ + Byte levelLevels[kLevelTableSize]; + UInt32 i; + for (i = 0; i < kLevelTableSize; i++) + levelLevels[i] = (Byte)ReadBits(kNumBitsForPreTreeLevel); + RIF(m_LevelDecoder.SetCodeLengths(levelLevels)); + unsigned num = 0; + Byte symbol = 0; + for (i = 0; i < numSymbols;) + { + if (num != 0) + { + lastLevels[i] = newLevels[i] = symbol; + i++; + num--; + continue; + } + UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream); + if (number == kLevelSymbolZeros) + { + num = kLevelSymbolZerosStartValue + (unsigned)ReadBits(kLevelSymbolZerosNumBits); + symbol = 0; + } + else if (number == kLevelSymbolZerosBig) + { + num = kLevelSymbolZerosBigStartValue + (unsigned)ReadBits(kLevelSymbolZerosBigNumBits); + symbol = 0; + } + else if (number == kLevelSymbolSame || number <= kNumHuffmanBits) + { + if (number <= kNumHuffmanBits) + num = 1; + else + { + num = kLevelSymbolSameStartValue + (unsigned)ReadBits(kLevelSymbolSameNumBits); + number = m_LevelDecoder.DecodeSymbol(&m_InBitStream); + if (number > kNumHuffmanBits) + return false; + } + symbol = Byte((17 + lastLevels[i] - number) % (kNumHuffmanBits + 1)); + } + else + return false; + } + return true; +} + +bool CDecoder::ReadTables(void) +{ + Byte newLevels[kMaxTableSize]; + { + if (_skipByte) + m_InBitStream.DirectReadByte(); + m_InBitStream.Normalize(); + + unsigned blockType = (unsigned)ReadBits(kNumBlockTypeBits); + if (blockType > kBlockTypeUncompressed) + return false; + if (_wimMode) + if (ReadBits(1) == 1) + m_UnCompressedBlockSize = (1 << 15); + else + m_UnCompressedBlockSize = ReadBits(16); + else + m_UnCompressedBlockSize = m_InBitStream.ReadBitsBig(kUncompressedBlockSizeNumBits); + + m_IsUncompressedBlock = (blockType == kBlockTypeUncompressed); + + _skipByte = (m_IsUncompressedBlock && ((m_UnCompressedBlockSize & 1) != 0)); + + if (m_IsUncompressedBlock) + { + ReadBits(16 - m_InBitStream.GetBitPosition()); + if (!m_InBitStream.ReadUInt32(m_RepDistances[0])) + return false; + m_RepDistances[0]--; + for (unsigned i = 1; i < kNumRepDistances; i++) + { + UInt32 rep = 0; + for (unsigned j = 0; j < 4; j++) + rep |= (UInt32)m_InBitStream.DirectReadByte() << (8 * j); + m_RepDistances[i] = rep - 1; + } + return true; + } + m_AlignIsUsed = (blockType == kBlockTypeAligned); + if (m_AlignIsUsed) + { + for (unsigned i = 0; i < kAlignTableSize; i++) + newLevels[i] = (Byte)ReadBits(kNumBitsForAlignLevel); + RIF(m_AlignDecoder.SetCodeLengths(newLevels)); + } + } + + RIF(ReadTable(m_LastMainLevels, newLevels, 256)); + RIF(ReadTable(m_LastMainLevels + 256, newLevels + 256, m_NumPosLenSlots)); + for (UInt32 i = 256 + m_NumPosLenSlots; i < kMainTableSize; i++) + newLevels[i] = 0; + RIF(m_MainDecoder.SetCodeLengths(newLevels)); + + RIF(ReadTable(m_LastLenLevels, newLevels, kNumLenSymbols)); + return m_LenDecoder.SetCodeLengths(newLevels); +} + +class CDecoderFlusher +{ + CDecoder *m_Decoder; +public: + bool NeedFlush; + CDecoderFlusher(CDecoder *decoder): m_Decoder(decoder), NeedFlush(true) {} + ~CDecoderFlusher() + { + if (NeedFlush) + m_Decoder->Flush(); + m_Decoder->ReleaseStreams(); + } +}; + + +void CDecoder::ClearPrevLevels() +{ + unsigned i; + for (i = 0; i < kMainTableSize; i++) + m_LastMainLevels[i] = 0; + for (i = 0; i < kNumLenSymbols; i++) + m_LastLenLevels[i] = 0; +} + + +HRESULT CDecoder::CodeSpec(UInt32 curSize) +{ + if (_remainLen == kLenIdNeedInit) + { + _remainLen = 0; + m_InBitStream.Init(); + if (!_keepHistory || !m_IsUncompressedBlock) + m_InBitStream.Normalize(); + if (!_keepHistory) + { + _skipByte = false; + m_UnCompressedBlockSize = 0; + ClearPrevLevels(); + UInt32 i86TranslationSize = 12000000; + bool translationMode = true; + if (!_wimMode) + { + translationMode = (ReadBits(1) != 0); + if (translationMode) + { + i86TranslationSize = ReadBits(16) << 16; + i86TranslationSize |= ReadBits(16); + } + } + m_x86ConvertOutStreamSpec->Init(translationMode, i86TranslationSize); + + for (unsigned i = 0 ; i < kNumRepDistances; i++) + m_RepDistances[i] = 0; + } + } + + while (_remainLen > 0 && curSize > 0) + { + m_OutWindowStream.PutByte(m_OutWindowStream.GetByte(m_RepDistances[0])); + _remainLen--; + curSize--; + } + + while (curSize > 0) + { + if (m_UnCompressedBlockSize == 0) + if (!ReadTables()) + return S_FALSE; + UInt32 next = (Int32)MyMin(m_UnCompressedBlockSize, curSize); + curSize -= next; + m_UnCompressedBlockSize -= next; + if (m_IsUncompressedBlock) + { + while (next > 0) + { + m_OutWindowStream.PutByte(m_InBitStream.DirectReadByte()); + next--; + } + } + else while (next > 0) + { + UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream); + if (number < 256) + { + m_OutWindowStream.PutByte((Byte)number); + next--; + } + else + { + UInt32 posLenSlot = number - 256; + if (posLenSlot >= m_NumPosLenSlots) + return S_FALSE; + UInt32 posSlot = posLenSlot / kNumLenSlots; + UInt32 lenSlot = posLenSlot % kNumLenSlots; + UInt32 len = kMatchMinLen + lenSlot; + if (lenSlot == kNumLenSlots - 1) + { + UInt32 lenTemp = m_LenDecoder.DecodeSymbol(&m_InBitStream); + if (lenTemp >= kNumLenSymbols) + return S_FALSE; + len += lenTemp; + } + + if (posSlot < kNumRepDistances) + { + UInt32 distance = m_RepDistances[posSlot]; + m_RepDistances[posSlot] = m_RepDistances[0]; + m_RepDistances[0] = distance; + } + else + { + UInt32 distance; + unsigned numDirectBits; + if (posSlot < kNumPowerPosSlots) + { + numDirectBits = (unsigned)(posSlot >> 1) - 1; + distance = ((2 | (posSlot & 1)) << numDirectBits); + } + else + { + numDirectBits = kNumLinearPosSlotBits; + distance = ((posSlot - 0x22) << kNumLinearPosSlotBits); + } + + if (m_AlignIsUsed && numDirectBits >= kNumAlignBits) + { + distance += (m_InBitStream.ReadBits(numDirectBits - kNumAlignBits) << kNumAlignBits); + UInt32 alignTemp = m_AlignDecoder.DecodeSymbol(&m_InBitStream); + if (alignTemp >= kAlignTableSize) + return S_FALSE; + distance += alignTemp; + } + else + distance += m_InBitStream.ReadBits(numDirectBits); + m_RepDistances[2] = m_RepDistances[1]; + m_RepDistances[1] = m_RepDistances[0]; + m_RepDistances[0] = distance - kNumRepDistances; + } + + UInt32 locLen = len; + if (locLen > next) + locLen = next; + + if (!m_OutWindowStream.CopyBlock(m_RepDistances[0], locLen)) + return S_FALSE; + + len -= locLen; + next -= locLen; + if (len != 0) + { + _remainLen = (int)len; + return S_OK; + } + } + } + } + return S_OK; +} + +HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + if (outSize == NULL) + return E_INVALIDARG; + UInt64 size = *outSize; + + RINOK(SetInStream(inStream)); + m_x86ConvertOutStreamSpec->SetStream(outStream); + m_OutWindowStream.SetStream(m_x86ConvertOutStream); + RINOK(SetOutStreamSize(outSize)); + + CDecoderFlusher flusher(this); + + const UInt64 start = m_OutWindowStream.GetProcessedSize(); + for (;;) + { + UInt32 curSize = 1 << 18; + UInt64 rem = size - (m_OutWindowStream.GetProcessedSize() - start); + if (curSize > rem) + curSize = (UInt32)rem; + if (curSize == 0) + break; + RINOK(CodeSpec(curSize)); + if (progress != NULL) + { + UInt64 inSize = m_InBitStream.GetProcessedSize(); + UInt64 nowPos64 = m_OutWindowStream.GetProcessedSize() - start; + RINOK(progress->SetRatioInfo(&inSize, &nowPos64)); + } + } + flusher.NeedFlush = false; + return Flush(); +} + +HRESULT CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + try { return CodeReal(inStream, outStream, inSize, outSize, progress); } + catch(const CLzOutWindowException &e) { return e.ErrorCode; } + catch(...) { return S_FALSE; } +} + +STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) +{ + m_InBitStream.SetStream(inStream); + return S_OK; +} + +STDMETHODIMP CDecoder::ReleaseInStream() +{ + m_InBitStream.ReleaseStream(); + return S_OK; +} + +STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) +{ + if (outSize == NULL) + return E_FAIL; + _remainLen = kLenIdNeedInit; + m_OutWindowStream.Init(_keepHistory); + return S_OK; +} + +HRESULT CDecoder::SetParams(unsigned numDictBits) +{ + if (numDictBits < kNumDictionaryBitsMin || numDictBits > kNumDictionaryBitsMax) + return E_INVALIDARG; + UInt32 numPosSlots; + if (numDictBits < 20) + numPosSlots = 30 + (numDictBits - 15) * 2; + else if (numDictBits == 20) + numPosSlots = 42; + else + numPosSlots = 50; + m_NumPosLenSlots = numPosSlots * kNumLenSlots; + if (!m_OutWindowStream.Create(kDictionarySizeMax)) + return E_OUTOFMEMORY; + if (!m_InBitStream.Create(1 << 16)) + return E_OUTOFMEMORY; + return S_OK; +} + +}} diff --git a/CPP/7zip/Compress/LzxDecoder.h b/CPP/7zip/Compress/LzxDecoder.h new file mode 100755 index 0000000..0cb9aff --- /dev/null +++ b/CPP/7zip/Compress/LzxDecoder.h @@ -0,0 +1,159 @@ +// LzxDecoder.h + +#ifndef __LZX_DECODER_H +#define __LZX_DECODER_H + +#include "../ICoder.h" + +#include "../Common/InBuffer.h" + +#include "HuffmanDecoder.h" +#include "LzOutWindow.h" +#include "Lzx.h" +#include "Lzx86Converter.h" + +namespace NCompress { +namespace NLzx { + +namespace NBitStream { + +const unsigned kNumBigValueBits = 8 * 4; +const unsigned kNumValueBits = 17; +const UInt32 kBitDecoderValueMask = (1 << kNumValueBits) - 1; + +class CDecoder +{ + CInBuffer m_Stream; + UInt32 m_Value; + unsigned m_BitPos; +public: + CDecoder() {} + bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); } + + void SetStream(ISequentialInStream *s) { m_Stream.SetStream(s); } + void ReleaseStream() { m_Stream.ReleaseStream(); } + + void Init() + { + m_Stream.Init(); + m_BitPos = kNumBigValueBits; + } + + UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() - (kNumBigValueBits - m_BitPos) / 8; } + + unsigned GetBitPosition() const { return m_BitPos & 0xF; } + + void Normalize() + { + for (; m_BitPos >= 16; m_BitPos -= 16) + { + Byte b0 = m_Stream.ReadByte(); + Byte b1 = m_Stream.ReadByte(); + m_Value = (m_Value << 8) | b1; + m_Value = (m_Value << 8) | b0; + } + } + + UInt32 GetValue(unsigned numBits) const + { + return ((m_Value >> ((32 - kNumValueBits) - m_BitPos)) & kBitDecoderValueMask) >> (kNumValueBits - numBits); + } + + void MovePos(unsigned numBits) + { + m_BitPos += numBits; + Normalize(); + } + + UInt32 ReadBits(unsigned numBits) + { + UInt32 res = GetValue(numBits); + MovePos(numBits); + return res; + } + + UInt32 ReadBitsBig(unsigned numBits) + { + unsigned numBits0 = numBits / 2; + unsigned numBits1 = numBits - numBits0; + UInt32 res = ReadBits(numBits0) << numBits1; + return res + ReadBits(numBits1); + } + + bool ReadUInt32(UInt32 &v) + { + if (m_BitPos != 0) + return false; + v = ((m_Value >> 16) & 0xFFFF) | ((m_Value << 16) & 0xFFFF0000); + m_BitPos = kNumBigValueBits; + return true; + } + + Byte DirectReadByte() { return m_Stream.ReadByte(); } + +}; +} + +class CDecoder : + public ICompressCoder, + public CMyUnknownImp +{ + NBitStream::CDecoder m_InBitStream; + CLzOutWindow m_OutWindowStream; + + UInt32 m_RepDistances[kNumRepDistances]; + UInt32 m_NumPosLenSlots; + + bool m_IsUncompressedBlock; + bool m_AlignIsUsed; + + NCompress::NHuffman::CDecoder m_MainDecoder; + NCompress::NHuffman::CDecoder m_LenDecoder; + NCompress::NHuffman::CDecoder m_AlignDecoder; + NCompress::NHuffman::CDecoder m_LevelDecoder; + + Byte m_LastMainLevels[kMainTableSize]; + Byte m_LastLenLevels[kNumLenSymbols]; + + Cx86ConvertOutStream *m_x86ConvertOutStreamSpec; + CMyComPtr m_x86ConvertOutStream; + + UInt32 m_UnCompressedBlockSize; + + bool _keepHistory; + int _remainLen; + bool _skipByte; + + bool _wimMode; + + UInt32 ReadBits(unsigned numBits); + bool ReadTable(Byte *lastLevels, Byte *newLevels, UInt32 numSymbols); + bool ReadTables(); + void ClearPrevLevels(); + + HRESULT CodeSpec(UInt32 size); + + HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); +public: + CDecoder(bool wimMode = false); + + MY_UNKNOWN_IMP + + void ReleaseStreams(); + STDMETHOD(Flush)(); + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + + STDMETHOD(SetInStream)(ISequentialInStream *inStream); + STDMETHOD(ReleaseInStream)(); + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); + + HRESULT SetParams(unsigned numDictBits); + void SetKeepHistory(bool keepHistory) { _keepHistory = keepHistory; } +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/Mtf8.h b/CPP/7zip/Compress/Mtf8.h new file mode 100755 index 0000000..c667e3d --- /dev/null +++ b/CPP/7zip/Compress/Mtf8.h @@ -0,0 +1,193 @@ +// Mtf8.h + +#ifndef __COMPRESS_MTF8_H +#define __COMPRESS_MTF8_H + +#include "../../../C/CpuArch.h" + +#include "../../Common/Types.h" + +namespace NCompress { + +struct CMtf8Encoder +{ + Byte Buf[256]; + + int FindAndMove(Byte v) + { + int pos; + for (pos = 0; Buf[pos] != v; pos++); + int resPos = pos; + for (; pos >= 8; pos -= 8) + { + Buf[pos] = Buf[pos - 1]; + Buf[pos - 1] = Buf[pos - 2]; + Buf[pos - 2] = Buf[pos - 3]; + Buf[pos - 3] = Buf[pos - 4]; + Buf[pos - 4] = Buf[pos - 5]; + Buf[pos - 5] = Buf[pos - 6]; + Buf[pos - 6] = Buf[pos - 7]; + Buf[pos - 7] = Buf[pos - 8]; + } + for (; pos > 0; pos--) + Buf[pos] = Buf[pos - 1]; + Buf[0] = v; + return resPos; + } +}; + +/* +struct CMtf8Decoder +{ + Byte Buf[256]; + + void Init(int) {}; + Byte GetHead() const { return Buf[0]; } + Byte GetAndMove(int pos) + { + Byte res = Buf[pos]; + for (; pos >= 8; pos -= 8) + { + Buf[pos] = Buf[pos - 1]; + Buf[pos - 1] = Buf[pos - 2]; + Buf[pos - 2] = Buf[pos - 3]; + Buf[pos - 3] = Buf[pos - 4]; + Buf[pos - 4] = Buf[pos - 5]; + Buf[pos - 5] = Buf[pos - 6]; + Buf[pos - 6] = Buf[pos - 7]; + Buf[pos - 7] = Buf[pos - 8]; + } + for (; pos > 0; pos--) + Buf[pos] = Buf[pos - 1]; + Buf[0] = res; + return res; + } +}; +*/ + +#ifdef MY_CPU_64BIT +typedef UInt64 CMtfVar; +#define MTF_MOVS 3 +#else +typedef UInt32 CMtfVar; +#define MTF_MOVS 2 +#endif + +#define MTF_MASK ((1 << MTF_MOVS) - 1) + + +struct CMtf8Decoder +{ + CMtfVar Buf[256 >> MTF_MOVS]; + + void StartInit() { memset(Buf, 0, sizeof(Buf)); } + void Add(unsigned int pos, Byte val) { Buf[pos >> MTF_MOVS] |= ((CMtfVar)val << ((pos & MTF_MASK) << 3)); } + Byte GetHead() const { return (Byte)Buf[0]; } + Byte GetAndMove(unsigned int pos) + { + UInt32 lim = ((UInt32)pos >> MTF_MOVS); + pos = (pos & MTF_MASK) << 3; + CMtfVar prev = (Buf[lim] >> pos) & 0xFF; + + UInt32 i = 0; + if ((lim & 1) != 0) + { + CMtfVar next = Buf[0]; + Buf[0] = (next << 8) | prev; + prev = (next >> (MTF_MASK << 3)); + i = 1; + lim -= 1; + } + for (; i < lim; i += 2) + { + CMtfVar n0 = Buf[i]; + CMtfVar n1 = Buf[i + 1]; + Buf[i ] = (n0 << 8) | prev; + Buf[i + 1] = (n1 << 8) | (n0 >> (MTF_MASK << 3)); + prev = (n1 >> (MTF_MASK << 3)); + } + CMtfVar next = Buf[i]; + CMtfVar mask = (((CMtfVar)0x100 << pos) - 1); + Buf[i] = (next & ~mask) | (((next << 8) | prev) & mask); + return (Byte)Buf[0]; + } +}; + +/* +const int kSmallSize = 64; +class CMtf8Decoder +{ + Byte SmallBuffer[kSmallSize]; + int SmallSize; + Byte Counts[16]; + int Size; +public: + Byte Buf[256]; + + Byte GetHead() const + { + if (SmallSize > 0) + return SmallBuffer[kSmallSize - SmallSize]; + return Buf[0]; + } + + void Init(int size) + { + Size = size; + SmallSize = 0; + for (int i = 0; i < 16; i++) + { + Counts[i] = ((size >= 16) ? 16 : size); + size -= Counts[i]; + } + } + + Byte GetAndMove(int pos) + { + if (pos < SmallSize) + { + Byte *p = SmallBuffer + kSmallSize - SmallSize; + Byte res = p[pos]; + for (; pos > 0; pos--) + p[pos] = p[pos - 1]; + SmallBuffer[kSmallSize - SmallSize] = res; + return res; + } + if (SmallSize == kSmallSize) + { + int i = Size - 1; + int g = 16; + do + { + g--; + int offset = (g << 4); + for (int t = Counts[g] - 1; t >= 0; t--, i--) + Buf[i] = Buf[offset + t]; + } + while(g != 0); + + for (i = kSmallSize - 1; i >= 0; i--) + Buf[i] = SmallBuffer[i]; + Init(Size); + } + pos -= SmallSize; + int g; + for (g = 0; pos >= Counts[g]; g++) + pos -= Counts[g]; + int offset = (g << 4); + Byte res = Buf[offset + pos]; + for (pos; pos < 16 - 1; pos++) + Buf[offset + pos] = Buf[offset + pos + 1]; + + SmallSize++; + SmallBuffer[kSmallSize - SmallSize] = res; + + Counts[g]--; + return res; + } +}; +*/ + +} + +#endif diff --git a/CPP/7zip/Compress/PpmdDecoder.cpp b/CPP/7zip/Compress/PpmdDecoder.cpp new file mode 100755 index 0000000..2373185 --- /dev/null +++ b/CPP/7zip/Compress/PpmdDecoder.cpp @@ -0,0 +1,167 @@ +// 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 +}; + +static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } +static void SzBigFree(void *, void *address) { BigFree(address); } +static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; + +CDecoder::~CDecoder() +{ + ::MidFree(_outBuf); + 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.p); + 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; +} + +#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/CPP/7zip/Compress/PpmdDecoder.h b/CPP/7zip/Compress/PpmdDecoder.h new file mode 100755 index 0000000..c61d1d0 --- /dev/null +++ b/CPP/7zip/Compress/PpmdDecoder.h @@ -0,0 +1,78 @@ +// 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, + #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; + MY_UNKNOWN_IMP4( + ICompressSetDecoderProperties2, + ICompressSetInStream, + ICompressSetOutStreamSize, + ISequentialInStream) + #else + MY_UNKNOWN_IMP1( + ICompressSetDecoderProperties2) + #endif + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); + 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.p; + Ppmd7_Construct(&_ppmd); + } + + ~CDecoder(); +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/PpmdEncoder.cpp b/CPP/7zip/Compress/PpmdEncoder.cpp new file mode 100755 index 0000000..3a8df78 --- /dev/null +++ b/CPP/7zip/Compress/PpmdEncoder.cpp @@ -0,0 +1,119 @@ +// PpmdEncoder.cpp +// 2009-03-11 : Igor Pavlov : Public domain + +#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 void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } +static void SzBigFree(void *, void *address) { BigFree(address); } +static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; + +CEncoder::CEncoder(): + _inBuf(NULL), + _usedMemSize(1 << 24), + _order(6) +{ + _rangeEnc.Stream = &_outStream.p; + Ppmd7_Construct(&_ppmd); +} + +CEncoder::~CEncoder() +{ + ::MidFree(_inBuf); + Ppmd7_Free(&_ppmd, &g_BigAlloc); +} + +STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) +{ + for (UInt32 i = 0; i < numProps; i++) + { + const PROPVARIANT &prop = props[i]; + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 v = (UInt32)prop.ulVal; + switch(propIDs[i]) + { + case NCoderPropID::kUsedMemorySize: + if (v < (1 << 16) || v > PPMD7_MAX_MEM_SIZE || (v & 3) != 0) + return E_INVALIDARG; + _usedMemSize = v; + break; + case NCoderPropID::kOrder: + if (v < 2 || v > 32) + return E_INVALIDARG; + _order = (Byte)v; + break; + default: + return E_INVALIDARG; + } + } + return S_OK; +} + +STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) +{ + const UInt32 kPropSize = 5; + Byte props[kPropSize]; + props[0] = _order; + SetUi32(props + 1, _usedMemSize); + 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, _usedMemSize, &g_BigAlloc)) + return E_OUTOFMEMORY; + + _outStream.Stream = outStream; + _outStream.Init(); + + Ppmd7z_RangeEnc_Init(&_rangeEnc); + Ppmd7_Init(&_ppmd, _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/CPP/7zip/Compress/PpmdEncoder.h b/CPP/7zip/Compress/PpmdEncoder.h new file mode 100755 index 0000000..9feb93d --- /dev/null +++ b/CPP/7zip/Compress/PpmdEncoder.h @@ -0,0 +1,48 @@ +// PpmdEncoder.h +// 2009-03-11 : Igor Pavlov : Public domain + +#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 { + +class CEncoder : + public ICompressCoder, + public ICompressSetCoderProperties, + public ICompressWriteCoderProperties, + public CMyUnknownImp +{ + Byte *_inBuf; + CByteOutBufWrap _outStream; + CPpmd7z_RangeEnc _rangeEnc; + CPpmd7 _ppmd; + + UInt32 _usedMemSize; + Byte _order; + +public: + MY_UNKNOWN_IMP2( + 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/CPP/7zip/Compress/PpmdRegister.cpp b/CPP/7zip/Compress/PpmdRegister.cpp new file mode 100755 index 0000000..e2fd007 --- /dev/null +++ b/CPP/7zip/Compress/PpmdRegister.cpp @@ -0,0 +1,21 @@ +// PpmdRegister.cpp +// 2009-05-30 : Igor Pavlov : Public domain + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" + +#include "PpmdDecoder.h" + +static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NPpmd::CDecoder); } +#ifndef EXTRACT_ONLY +#include "PpmdEncoder.h" +static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NPpmd::CEncoder); } +#else +#define CreateCodecOut 0 +#endif + +static CCodecInfo g_CodecInfo = + { CreateCodec, CreateCodecOut, 0x030401, L"PPMD", 1, false }; + +REGISTER_CODEC(PPMD) diff --git a/CPP/7zip/Compress/PpmdZip.cpp b/CPP/7zip/Compress/PpmdZip.cpp new file mode 100755 index 0000000..6356e87 --- /dev/null +++ b/CPP/7zip/Compress/PpmdZip.cpp @@ -0,0 +1,223 @@ +// PpmdZip.cpp +// 2010-03-24 : Igor Pavlov : Public domain + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "../Common/StreamUtils.h" + +#include "PpmdZip.h" + +namespace NCompress { +namespace NPpmdZip { + +static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } +static void SzBigFree(void *, void *address) { BigFree(address); } +static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; + +CDecoder::CDecoder(bool fullFileMode): + _fullFileMode(fullFileMode) +{ + _ppmd.Stream.In = &_inStream.p; + Ppmd8_Construct(&_ppmd); +} + +CDecoder::~CDecoder() +{ + Ppmd8_Free(&_ppmd, &g_BigAlloc); +} + +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + if (!_outStream.Alloc()) + return E_OUTOFMEMORY; + if (!_inStream.Alloc(1 << 20)) + return E_OUTOFMEMORY; + + _inStream.Stream = inStream; + _inStream.Init(); + + { + Byte buf[2]; + for (int i = 0; i < 2; i++) + buf[i] = _inStream.ReadByte(); + if (_inStream.Extra) + return S_FALSE; + + UInt32 val = GetUi16(buf); + UInt32 order = (val & 0xF) + 1; + UInt32 mem = ((val >> 4) & 0xFF) + 1; + UInt32 restor = (val >> 12); + if (order < 2 || restor > 2) + return S_FALSE; + + #ifndef PPMD8_FREEZE_SUPPORT + if (restor == 2) + return E_NOTIMPL; + #endif + + if (!Ppmd8_Alloc(&_ppmd, mem << 20, &g_BigAlloc)) + return E_OUTOFMEMORY; + + if (!Ppmd8_RangeDec_Init(&_ppmd)) + return S_FALSE; + Ppmd8_Init(&_ppmd, order, restor); + } + + bool wasFinished = false; + UInt64 processedSize = 0; + while (!outSize || processedSize < *outSize) + { + size_t size = kBufSize; + if (outSize != NULL) + { + const UInt64 rem = *outSize - processedSize; + if (size > rem) + size = (size_t)rem; + } + Byte *data = _outStream.Buf; + size_t i = 0; + int sym = 0; + do + { + sym = Ppmd8_DecodeSymbol(&_ppmd); + if (_inStream.Extra || sym < 0) + break; + data[i] = (Byte)sym; + } + while (++i != size); + processedSize += i; + + RINOK(WriteStream(outStream, _outStream.Buf, i)); + + RINOK(_inStream.Res); + if (_inStream.Extra) + return S_FALSE; + + if (sym < 0) + { + if (sym != -1) + return S_FALSE; + wasFinished = true; + break; + } + if (progress) + { + UInt64 inSize = _inStream.GetProcessed(); + RINOK(progress->SetRatioInfo(&inSize, &processedSize)); + } + } + RINOK(_inStream.Res); + if (_fullFileMode) + { + if (!wasFinished) + { + int res = Ppmd8_DecodeSymbol(&_ppmd); + RINOK(_inStream.Res); + if (_inStream.Extra || res != -1) + return S_FALSE; + } + if (!Ppmd8_RangeDec_IsFinishedOK(&_ppmd)) + return S_FALSE; + } + return S_OK; +} + + +// ---------- Encoder ---------- + +CEncoder::~CEncoder() +{ + Ppmd8_Free(&_ppmd, &g_BigAlloc); +} + +HRESULT CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) +{ + for (UInt32 i = 0; i < numProps; i++) + { + const PROPVARIANT &prop = props[i]; + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 v = (UInt32)prop.ulVal; + switch(propIDs[i]) + { + case NCoderPropID::kAlgorithm: + if (v > 1) + return E_INVALIDARG; + _restor = v; + break; + case NCoderPropID::kUsedMemorySize: + if (v < (1 << 20) || v > (1 << 28)) + return E_INVALIDARG; + _usedMemInMB = v >> 20; + break; + case NCoderPropID::kOrder: + if (v < PPMD8_MIN_ORDER || v > PPMD8_MAX_ORDER) + return E_INVALIDARG; + _order = (Byte)v; + break; + default: + return E_INVALIDARG; + } + } + return S_OK; +} + +CEncoder::CEncoder(): + _usedMemInMB(16), + _order(6), + _restor(PPMD8_RESTORE_METHOD_RESTART) +{ + _ppmd.Stream.Out = &_outStream.p; + Ppmd8_Construct(&_ppmd); +} + +HRESULT CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) +{ + if (!_inStream.Alloc()) + return E_OUTOFMEMORY; + if (!_outStream.Alloc(1 << 20)) + return E_OUTOFMEMORY; + if (!Ppmd8_Alloc(&_ppmd, _usedMemInMB << 20, &g_BigAlloc)) + return E_OUTOFMEMORY; + + _outStream.Stream = outStream; + _outStream.Init(); + + Ppmd8_RangeEnc_Init(&_ppmd); + Ppmd8_Init(&_ppmd, _order, _restor); + + UInt32 val = (UInt32)((_order - 1) + ((_usedMemInMB - 1) << 4) + (_restor << 12)); + _outStream.WriteByte((Byte)(val & 0xFF)); + _outStream.WriteByte((Byte)(val >> 8)); + RINOK(_outStream.Res); + + UInt64 processed = 0; + for (;;) + { + UInt32 size; + RINOK(inStream->Read(_inStream.Buf, kBufSize, &size)); + if (size == 0) + { + Ppmd8_EncodeSymbol(&_ppmd, -1); + Ppmd8_RangeEnc_FlushData(&_ppmd); + return _outStream.Flush(); + } + for (UInt32 i = 0; i < size; i++) + { + Ppmd8_EncodeSymbol(&_ppmd, _inStream.Buf[i]); + RINOK(_outStream.Res); + } + processed += size; + if (progress != NULL) + { + UInt64 outSize = _outStream.GetProcessed(); + RINOK(progress->SetRatioInfo(&processed, &outSize)); + } + } +} + +}} diff --git a/CPP/7zip/Compress/PpmdZip.h b/CPP/7zip/Compress/PpmdZip.h new file mode 100755 index 0000000..5614de2 --- /dev/null +++ b/CPP/7zip/Compress/PpmdZip.h @@ -0,0 +1,72 @@ +// PpmdZip.h +// 2010-03-11 : Igor Pavlov : Public domain + +#ifndef __COMPRESS_PPMD_ZIP_H +#define __COMPRESS_PPMD_ZIP_H + +#include "../../../C/Alloc.h" +#include "../../../C/Ppmd8.h" + +#include "../../Common/MyCom.h" + +#include "../Common/CWrappers.h" + +#include "../ICoder.h" + +namespace NCompress { +namespace NPpmdZip { + +static const UInt32 kBufSize = (1 << 20); + +struct CBuf +{ + Byte *Buf; + + CBuf(): Buf(0) {} + ~CBuf() { ::MidFree(Buf); } + bool Alloc() + { + if (!Buf) + Buf = (Byte *)::MidAlloc(kBufSize); + return (Buf != 0); + } +}; + +class CDecoder : + public ICompressCoder, + public CMyUnknownImp +{ + CByteInBufWrap _inStream; + CBuf _outStream; + CPpmd8 _ppmd; + bool _fullFileMode; +public: + MY_UNKNOWN_IMP + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + CDecoder(bool fullFileMode); + ~CDecoder(); +}; + +class CEncoder : + public ICompressCoder, + public CMyUnknownImp +{ + CByteOutBufWrap _outStream; + CBuf _inStream; + CPpmd8 _ppmd; + UInt32 _usedMemInMB; + unsigned _order; + unsigned _restor; +public: + MY_UNKNOWN_IMP + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + HRESULT SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); + CEncoder(); + ~CEncoder(); +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/QuantumDecoder.cpp b/CPP/7zip/Compress/QuantumDecoder.cpp new file mode 100755 index 0000000..e80f403 --- /dev/null +++ b/CPP/7zip/Compress/QuantumDecoder.cpp @@ -0,0 +1,175 @@ +// QuantumDecoder.cpp + +#include "StdAfx.h" + +#include "../../Common/Defs.h" + +#include "QuantumDecoder.h" + +namespace NCompress { +namespace NQuantum { + +static const int kLenIdNeedInit = -2; + +static const unsigned kNumLenSymbols = 27; +static const unsigned kMatchMinLen = 3; +static const unsigned kNumSimplePosSlots = 4; +static const unsigned kNumSimpleLenSlots = 6; + +void CDecoder::Init() +{ + m_Selector.Init(kNumSelectors); + unsigned i; + for (i = 0; i < kNumLitSelectors; i++) + m_Literals[i].Init(kNumLitSymbols); + unsigned numItems = (_numDictBits == 0 ? 1 : (_numDictBits << 1)); + const unsigned kNumPosSymbolsMax[kNumMatchSelectors] = { 24, 36, 42 }; + for (i = 0; i < kNumMatchSelectors; i++) + m_PosSlot[i].Init(MyMin(numItems, kNumPosSymbolsMax[i])); + m_LenSlot.Init(kNumLenSymbols); +} + +HRESULT CDecoder::CodeSpec(UInt32 curSize) +{ + if (_remainLen == kLenIdNeedInit) + { + if (!_keepHistory) + { + if (!_outWindowStream.Create((UInt32)1 << _numDictBits)) + return E_OUTOFMEMORY; + Init(); + } + if (!_rangeDecoder.Create(1 << 20)) + return E_OUTOFMEMORY; + _rangeDecoder.Init(); + _remainLen = 0; + } + if (curSize == 0) + return S_OK; + + while (_remainLen > 0 && curSize > 0) + { + _remainLen--; + Byte b = _outWindowStream.GetByte(_rep0); + _outWindowStream.PutByte(b); + curSize--; + } + + while (curSize > 0) + { + if (_rangeDecoder.Stream.WasFinished()) + return S_FALSE; + + unsigned selector = m_Selector.Decode(&_rangeDecoder); + if (selector < kNumLitSelectors) + { + Byte b = (Byte)((selector << (8 - kNumLitSelectorBits)) + m_Literals[selector].Decode(&_rangeDecoder)); + _outWindowStream.PutByte(b); + curSize--; + } + else + { + selector -= kNumLitSelectors; + unsigned len = selector + kMatchMinLen; + if (selector == 2) + { + unsigned lenSlot = m_LenSlot.Decode(&_rangeDecoder); + if (lenSlot >= kNumSimpleLenSlots) + { + lenSlot -= 2; + int numDirectBits = (int)(lenSlot >> 2); + len += ((4 | (lenSlot & 3)) << numDirectBits) - 2; + if (numDirectBits < 6) + len += _rangeDecoder.Stream.ReadBits(numDirectBits); + } + else + len += lenSlot; + } + UInt32 rep0 = m_PosSlot[selector].Decode(&_rangeDecoder); + if (rep0 >= kNumSimplePosSlots) + { + int numDirectBits = (int)((rep0 >> 1) - 1); + rep0 = ((2 | (rep0 & 1)) << numDirectBits) + _rangeDecoder.Stream.ReadBits(numDirectBits); + } + unsigned locLen = len; + if (len > curSize) + locLen = (unsigned)curSize; + if (!_outWindowStream.CopyBlock(rep0, locLen)) + return S_FALSE; + curSize -= locLen; + len -= locLen; + if (len != 0) + { + _remainLen = (int)len; + _rep0 = rep0; + break; + } + } + } + return _rangeDecoder.Stream.WasFinished() ? S_FALSE : S_OK; +} + +HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + if (outSize == NULL) + return E_INVALIDARG; + UInt64 size = *outSize; + + SetInStream(inStream); + _outWindowStream.SetStream(outStream); + SetOutStreamSize(outSize); + CDecoderFlusher flusher(this); + + const UInt64 start = _outWindowStream.GetProcessedSize(); + for (;;) + { + UInt32 curSize = 1 << 18; + UInt64 rem = size - (_outWindowStream.GetProcessedSize() - start); + if (curSize > rem) + curSize = (UInt32)rem; + if (curSize == 0) + break; + RINOK(CodeSpec(curSize)); + if (progress != NULL) + { + UInt64 inSize = _rangeDecoder.GetProcessedSize(); + UInt64 nowPos64 = _outWindowStream.GetProcessedSize() - start; + RINOK(progress->SetRatioInfo(&inSize, &nowPos64)); + } + } + flusher.NeedFlush = false; + return Flush(); +} + +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + try { return CodeReal(inStream, outStream, inSize, outSize, progress); } + catch(const CInBufferException &e) { return e.ErrorCode; } + catch(const CLzOutWindowException &e) { return e.ErrorCode; } + catch(...) { return S_FALSE; } +} + +STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) +{ + _rangeDecoder.SetStream(inStream); + return S_OK; +} + +STDMETHODIMP CDecoder::ReleaseInStream() +{ + _rangeDecoder.ReleaseStream(); + return S_OK; +} + +STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) +{ + if (outSize == NULL) + return E_FAIL; + _remainLen = kLenIdNeedInit; + _outWindowStream.Init(_keepHistory); + return S_OK; +} + +}} diff --git a/CPP/7zip/Compress/QuantumDecoder.h b/CPP/7zip/Compress/QuantumDecoder.h new file mode 100755 index 0000000..585eeef --- /dev/null +++ b/CPP/7zip/Compress/QuantumDecoder.h @@ -0,0 +1,264 @@ +// QuantumDecoder.h + +#ifndef __COMPRESS_QUANTUM_DECODER_H +#define __COMPRESS_QUANTUM_DECODER_H + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +#include "../Common/InBuffer.h" + +#include "LzOutWindow.h" + +namespace NCompress { +namespace NQuantum { + +class CStreamBitDecoder +{ + UInt32 Value; + CInBuffer Stream; +public: + bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } + void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } + void ReleaseStream() { Stream.ReleaseStream(); } + + void Finish() { Value = 0x10000; } + + void Init() + { + Stream.Init(); + Value = 0x10000; + } + + UInt64 GetProcessedSize() const { return Stream.GetProcessedSize(); } + bool WasFinished() const { return Stream.WasFinished(); } + + UInt32 ReadBit() + { + if (Value >= 0x10000) + Value = 0x100 | Stream.ReadByte(); + UInt32 res = (Value >> 7) & 1; + Value <<= 1; + return res; + } + + UInt32 ReadBits(int numBits) // numBits > 0 + { + UInt32 res = 0; + do + res = (res << 1) | ReadBit(); + while (--numBits != 0); + return res; + } +}; + +const unsigned kNumLitSelectorBits = 2; +const unsigned kNumLitSelectors = (1 << kNumLitSelectorBits); +const unsigned kNumLitSymbols = 1 << (8 - kNumLitSelectorBits); +const unsigned kNumMatchSelectors = 3; +const unsigned kNumSelectors = kNumLitSelectors + kNumMatchSelectors; +const unsigned kNumSymbolsMax = kNumLitSymbols; // 64 + +namespace NRangeCoder { + +class CDecoder +{ + UInt32 Low; + UInt32 Range; + UInt32 Code; +public: + CStreamBitDecoder Stream; + bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } + void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } + void ReleaseStream() { Stream.ReleaseStream(); } + + void Init() + { + Stream.Init(); + Low = 0; + Range = 0x10000; + Code = Stream.ReadBits(16); + } + + void Finish() + { + // we need these extra two Bit_reads + Stream.ReadBit(); + Stream.ReadBit(); + Stream.Finish(); + } + + UInt64 GetProcessedSize() const { return Stream.GetProcessedSize(); } + + UInt32 GetThreshold(UInt32 total) const + { + return ((Code + 1) * total - 1) / Range; // & 0xFFFF is not required; + } + + void Decode(UInt32 start, UInt32 end, UInt32 total) + { + UInt32 high = Low + end * Range / total - 1; + UInt32 offset = start * Range / total; + Code -= offset; + Low += offset; + for (;;) + { + if ((Low & 0x8000) != (high & 0x8000)) + { + if ((Low & 0x4000) == 0 || (high & 0x4000) != 0) + break; + Low &= 0x3FFF; + high |= 0x4000; + } + Low = (Low << 1) & 0xFFFF; + high = ((high << 1) | 1) & 0xFFFF; + Code = ((Code << 1) | Stream.ReadBit()); + } + Range = high - Low + 1; + } +}; + +const UInt16 kUpdateStep = 8; +const UInt16 kFreqSumMax = 3800; +const UInt16 kReorderCountStart = 4; +const UInt16 kReorderCount = 50; + +class CModelDecoder +{ + unsigned NumItems; + unsigned ReorderCount; + UInt16 Freqs[kNumSymbolsMax + 1]; + Byte Values[kNumSymbolsMax]; +public: + void Init(unsigned numItems) + { + NumItems = numItems; + ReorderCount = kReorderCountStart; + for (unsigned i = 0; i < numItems; i++) + { + Freqs[i] = (UInt16)(numItems - i); + Values[i] = (Byte)i; + } + Freqs[numItems] = 0; + } + + unsigned Decode(CDecoder *rangeDecoder) + { + UInt32 threshold = rangeDecoder->GetThreshold(Freqs[0]); + unsigned i; + for (i = 1; Freqs[i] > threshold; i++); + rangeDecoder->Decode(Freqs[i], Freqs[i - 1], Freqs[0]); + unsigned res = Values[--i]; + do + Freqs[i] += kUpdateStep; + while (i-- != 0); + + if (Freqs[0] > kFreqSumMax) + { + if (--ReorderCount == 0) + { + ReorderCount = kReorderCount; + for (i = 0; i < NumItems; i++) + Freqs[i] = (UInt16)(((Freqs[i] - Freqs[i + 1]) + 1) >> 1); + for (i = 0; i < NumItems - 1; i++) + for (unsigned j = i + 1; j < NumItems; j++) + if (Freqs[i] < Freqs[j]) + { + UInt16 tmpFreq = Freqs[i]; + Byte tmpVal = Values[i]; + Freqs[i] = Freqs[j]; + Values[i] = Values[j]; + Freqs[j] = tmpFreq; + Values[j] = tmpVal; + } + do + Freqs[i] = (UInt16)(Freqs[i] + Freqs[i + 1]); + while (i-- != 0); + } + else + { + i = NumItems - 1; + do + { + Freqs[i] >>= 1; + if (Freqs[i] <= Freqs[i + 1]) + Freqs[i] = (UInt16)(Freqs[i + 1] + 1); + } + while (i-- != 0); + } + } + return res; + } +}; + +} + +class CDecoder: + public ICompressCoder, + public ICompressSetInStream, + public ICompressSetOutStreamSize, + public CMyUnknownImp +{ + CLzOutWindow _outWindowStream; + NRangeCoder::CDecoder _rangeDecoder; + + UInt64 _outSize; + int _remainLen; // -1 means end of stream. // -2 means need Init + UInt32 _rep0; + + int _numDictBits; + bool _keepHistory; + + NRangeCoder::CModelDecoder m_Selector; + NRangeCoder::CModelDecoder m_Literals[kNumLitSelectors]; + NRangeCoder::CModelDecoder m_PosSlot[kNumMatchSelectors]; + NRangeCoder::CModelDecoder m_LenSlot; + void Init(); + HRESULT CodeSpec(UInt32 size); +public: + MY_UNKNOWN_IMP2( + ICompressSetInStream, + ICompressSetOutStreamSize) + + void ReleaseStreams() + { + _outWindowStream.ReleaseStream(); + ReleaseInStream(); + } + + class CDecoderFlusher + { + CDecoder *_decoder; + public: + bool NeedFlush; + CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {} + ~CDecoderFlusher() + { + if (NeedFlush) + _decoder->Flush(); + _decoder->ReleaseStreams(); + } + }; + + HRESULT Flush() { return _outWindowStream.Flush(); } + + HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + + STDMETHOD(SetInStream)(ISequentialInStream *inStream); + STDMETHOD(ReleaseInStream)(); + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); + + void SetParams(int numDictBits) { _numDictBits = numDictBits; } + void SetKeepHistory(bool keepHistory) { _keepHistory = keepHistory; } + CDecoder(): _keepHistory(false) {} + virtual ~CDecoder() {} +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/RangeCoder.h b/CPP/7zip/Compress/RangeCoder.h new file mode 100755 index 0000000..e9e8e32 --- /dev/null +++ b/CPP/7zip/Compress/RangeCoder.h @@ -0,0 +1,205 @@ +// Compress/RangeCoder.h +// 2009-05-30 : Igor Pavlov : Public domain + +#ifndef __COMPRESS_RANGE_CODER_H +#define __COMPRESS_RANGE_CODER_H + +#include "../Common/InBuffer.h" +#include "../Common/OutBuffer.h" + +namespace NCompress { +namespace NRangeCoder { + +const int kNumTopBits = 24; +const UInt32 kTopValue = (1 << kNumTopBits); + +class CEncoder +{ + UInt32 _cacheSize; + Byte _cache; +public: + UInt64 Low; + UInt32 Range; + COutBuffer Stream; + bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } + + void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); } + void Init() + { + Stream.Init(); + Low = 0; + Range = 0xFFFFFFFF; + _cacheSize = 1; + _cache = 0; + } + + void FlushData() + { + // Low += 1; + for(int i = 0; i < 5; i++) + ShiftLow(); + } + + HRESULT FlushStream() { return Stream.Flush(); } + + void ReleaseStream() { Stream.ReleaseStream(); } + + void Encode(UInt32 start, UInt32 size, UInt32 total) + { + Low += start * (Range /= total); + Range *= size; + while (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + + void ShiftLow() + { + if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0) + { + Byte temp = _cache; + do + { + Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32))); + temp = 0xFF; + } + while(--_cacheSize != 0); + _cache = (Byte)((UInt32)Low >> 24); + } + _cacheSize++; + Low = (UInt32)Low << 8; + } + + void EncodeDirectBits(UInt32 value, int numBits) + { + for (numBits--; numBits >= 0; numBits--) + { + Range >>= 1; + Low += Range & (0 - ((value >> numBits) & 1)); + if (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + } + + void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol) + { + UInt32 newBound = (Range >> numTotalBits) * size0; + if (symbol == 0) + Range = newBound; + else + { + Low += newBound; + Range -= newBound; + } + while (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + + UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; } +}; + +class CDecoder +{ +public: + CInBuffer Stream; + UInt32 Range; + UInt32 Code; + bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } + + void Normalize() + { + while (Range < kTopValue) + { + Code = (Code << 8) | Stream.ReadByte(); + Range <<= 8; + } + } + + void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } + void Init() + { + Stream.Init(); + Code = 0; + Range = 0xFFFFFFFF; + for(int i = 0; i < 5; i++) + Code = (Code << 8) | Stream.ReadByte(); + } + + void ReleaseStream() { Stream.ReleaseStream(); } + + UInt32 GetThreshold(UInt32 total) + { + return (Code) / ( Range /= total); + } + + void Decode(UInt32 start, UInt32 size) + { + Code -= start * Range; + Range *= size; + Normalize(); + } + + UInt32 DecodeDirectBits(int numTotalBits) + { + UInt32 range = Range; + UInt32 code = Code; + UInt32 result = 0; + for (int i = numTotalBits; i != 0; i--) + { + range >>= 1; + /* + result <<= 1; + if (code >= range) + { + code -= range; + result |= 1; + } + */ + UInt32 t = (code - range) >> 31; + code -= range & (t - 1); + result = (result << 1) | (1 - t); + + if (range < kTopValue) + { + code = (code << 8) | Stream.ReadByte(); + range <<= 8; + } + } + Range = range; + Code = code; + return result; + } + + UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) + { + UInt32 newBound = (Range >> numTotalBits) * size0; + UInt32 symbol; + if (Code < newBound) + { + symbol = 0; + Range = newBound; + } + else + { + symbol = 1; + Code -= newBound; + Range -= newBound; + } + Normalize(); + return symbol; + } + + UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); } +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/RangeCoderBit.h b/CPP/7zip/Compress/RangeCoderBit.h new file mode 100755 index 0000000..f06408c --- /dev/null +++ b/CPP/7zip/Compress/RangeCoderBit.h @@ -0,0 +1,114 @@ +// Compress/RangeCoderBit.h +// 2009-05-30 : Igor Pavlov : Public domain + +#ifndef __COMPRESS_RANGE_CODER_BIT_H +#define __COMPRESS_RANGE_CODER_BIT_H + +#include "RangeCoder.h" + +namespace NCompress { +namespace NRangeCoder { + +const int kNumBitModelTotalBits = 11; +const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits); + +const int kNumMoveReducingBits = 4; + +const int kNumBitPriceShiftBits = 4; +const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits; + +extern UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; + +template +class CBitModel +{ +public: + UInt32 Prob; + void UpdateModel(UInt32 symbol) + { + /* + Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits; + Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits); + */ + if (symbol == 0) + Prob += (kBitModelTotal - Prob) >> numMoveBits; + else + Prob -= (Prob) >> numMoveBits; + } +public: + void Init() { Prob = kBitModelTotal / 2; } +}; + +template +class CBitEncoder: public CBitModel +{ +public: + void Encode(CEncoder *encoder, UInt32 symbol) + { + /* + encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol); + this->UpdateModel(symbol); + */ + UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob; + if (symbol == 0) + { + encoder->Range = newBound; + this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; + } + else + { + encoder->Low += newBound; + encoder->Range -= newBound; + this->Prob -= (this->Prob) >> numMoveBits; + } + if (encoder->Range < kTopValue) + { + encoder->Range <<= 8; + encoder->ShiftLow(); + } + } + UInt32 GetPrice(UInt32 symbol) const + { + return ProbPrices[(this->Prob ^ ((-(int)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; + } + UInt32 GetPrice0() const { return ProbPrices[this->Prob >> kNumMoveReducingBits]; } + UInt32 GetPrice1() const { return ProbPrices[(this->Prob ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } +}; + + +template +class CBitDecoder: public CBitModel +{ +public: + UInt32 Decode(CDecoder *decoder) + { + UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob; + if (decoder->Code < newBound) + { + decoder->Range = newBound; + this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; + if (decoder->Range < kTopValue) + { + decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); + decoder->Range <<= 8; + } + return 0; + } + else + { + decoder->Range -= newBound; + decoder->Code -= newBound; + this->Prob -= (this->Prob) >> numMoveBits; + if (decoder->Range < kTopValue) + { + decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); + decoder->Range <<= 8; + } + return 1; + } + } +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/Rar1Decoder.cpp b/CPP/7zip/Compress/Rar1Decoder.cpp new file mode 100755 index 0000000..25fb2c0 --- /dev/null +++ b/CPP/7zip/Compress/Rar1Decoder.cpp @@ -0,0 +1,480 @@ +// Rar1Decoder.cpp +// According to unRAR license, this code may not be used to develop +// a program that creates RAR archives + +#include "StdAfx.h" + +#include "Rar1Decoder.h" + +namespace NCompress { +namespace NRar1 { + +static UInt32 PosL1[]={0,0,0,2,3,5,7,11,16,20,24,32,32, 256}; +static UInt32 PosL2[]={0,0,0,0,5,7,9,13,18,22,26,34,36, 256}; +static UInt32 PosHf0[]={0,0,0,0,0,8,16,24,33,33,33,33,33, 257}; +static UInt32 PosHf1[]={0,0,0,0,0,0,4,44,60,76,80,80,127, 257}; +static UInt32 PosHf2[]={0,0,0,0,0,0,2,7,53,117,233, 257,0}; +static UInt32 PosHf3[]={0,0,0,0,0,0,0,2,16,218,251, 257,0}; +static UInt32 PosHf4[]={0,0,0,0,0,0,0,0,0,255, 257,0,0}; + +static const UInt32 kHistorySize = (1 << 16); + +class CCoderReleaser +{ + CDecoder *m_Coder; +public: + CCoderReleaser(CDecoder *coder): m_Coder(coder) {} + ~CCoderReleaser() { m_Coder->ReleaseStreams(); } +}; + +CDecoder::CDecoder(): m_IsSolid(false) { } + +void CDecoder::InitStructures() +{ + for(int i = 0; i < kNumRepDists; i++) + m_RepDists[i] = 0; + m_RepDistPtr = 0; + LastLength = 0; + LastDist = 0; +} + +UInt32 CDecoder::ReadBits(int numBits) { return m_InBitStream.ReadBits(numBits); } + +HRESULT CDecoder::CopyBlock(UInt32 distance, UInt32 len) +{ + if (len == 0) + return S_FALSE; + m_UnpackSize -= len; + return m_OutWindowStream.CopyBlock(distance, len) ? S_OK : S_FALSE; +} + + +UInt32 CDecoder::DecodeNum(const UInt32 *posTab) +{ + UInt32 startPos = 2; + UInt32 num = m_InBitStream.GetValue(12); + for (;;) + { + UInt32 cur = (posTab[startPos + 1] - posTab[startPos]) << (12 - startPos); + if (num < cur) + break; + startPos++; + num -= cur; + } + m_InBitStream.MovePos(startPos); + return((num >> (12 - startPos)) + posTab[startPos]); +} + +static Byte kShortLen1[] = {1,3,4,4,5,6,7,8,8,4,4,5,6,6 }; +static Byte kShortLen1a[] = {1,4,4,4,5,6,7,8,8,4,4,5,6,6,4 }; +static Byte kShortLen2[] = {2,3,3,3,4,4,5,6,6,4,4,5,6,6 }; +static Byte kShortLen2a[] = {2,3,3,4,4,4,5,6,6,4,4,5,6,6,4 }; +static UInt32 kShortXor1[] = {0,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff,0xc0,0x80,0x90,0x98,0x9c,0xb0}; +static UInt32 kShortXor2[] = {0,0x40,0x60,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xc0,0x80,0x90,0x98,0x9c,0xb0}; + +HRESULT CDecoder::ShortLZ() +{ + UInt32 len, saveLen, dist; + int distancePlace; + Byte *kShortLen; + const UInt32 *kShortXor; + NumHuf = 0; + + if (LCount == 2) + { + if (ReadBits(1)) + return CopyBlock(LastDist, LastLength); + LCount = 0; + } + + UInt32 bitField = m_InBitStream.GetValue(8); + + if (AvrLn1 < 37) + { + kShortLen = Buf60 ? kShortLen1a : kShortLen1; + kShortXor = kShortXor1; + } + else + { + kShortLen = Buf60 ? kShortLen2a : kShortLen2; + kShortXor = kShortXor2; + } + + for (len = 0; ((bitField ^ kShortXor[len]) & (~(0xff >> kShortLen[len]))) != 0; len++); + m_InBitStream.MovePos(kShortLen[len]); + + if (len >= 9) + { + if (len == 9) + { + LCount++; + return CopyBlock(LastDist, LastLength); + } + if (len == 14) + { + LCount = 0; + len = DecodeNum(PosL2) + 5; + dist = 0x8000 + ReadBits(15) - 1; + LastLength = len; + LastDist = dist; + return CopyBlock(dist, len); + } + + LCount = 0; + saveLen = len; + dist = m_RepDists[(m_RepDistPtr - (len - 9)) & 3]; + len = DecodeNum(PosL1) + 2; + if (len == 0x101 && saveLen == 10) + { + Buf60 ^= 1; + return S_OK; + } + if (dist >= 256) + len++; + if (dist >= MaxDist3 - 1) + len++; + } + else + { + LCount = 0; + AvrLn1 += len; + AvrLn1 -= AvrLn1 >> 4; + + distancePlace = DecodeNum(PosHf2) & 0xff; + dist = ChSetA[distancePlace]; + if (--distancePlace != -1) + { + PlaceA[dist]--; + UInt32 lastDistance = ChSetA[distancePlace]; + PlaceA[lastDistance]++; + ChSetA[distancePlace + 1] = lastDistance; + ChSetA[distancePlace] = dist; + } + len += 2; + } + m_RepDists[m_RepDistPtr++] = dist; + m_RepDistPtr &= 3; + LastLength = len; + LastDist = dist; + return CopyBlock(dist, len); +} + + +HRESULT CDecoder::LongLZ() +{ + UInt32 len; + UInt32 dist; + UInt32 distancePlace, newDistancePlace; + UInt32 oldAvr2, oldAvr3; + + NumHuf = 0; + Nlzb += 16; + if (Nlzb > 0xff) + { + Nlzb = 0x90; + Nhfb >>= 1; + } + oldAvr2=AvrLn2; + + if (AvrLn2 >= 122) + len = DecodeNum(PosL2); + else if (AvrLn2 >= 64) + len = DecodeNum(PosL1); + else + { + UInt32 bitField = m_InBitStream.GetValue(16); + if (bitField < 0x100) + { + len = bitField; + m_InBitStream.MovePos(16); + } + else + { + for (len = 0; ((bitField << len) & 0x8000) == 0; len++) + ; + m_InBitStream.MovePos(len + 1); + } + } + + AvrLn2 += len; + AvrLn2 -= AvrLn2 >> 5; + + if (AvrPlcB > 0x28ff) + distancePlace = DecodeNum(PosHf2); + else if (AvrPlcB > 0x6ff) + distancePlace = DecodeNum(PosHf1); + else + distancePlace = DecodeNum(PosHf0); + + AvrPlcB += distancePlace; + AvrPlcB -= AvrPlcB >> 8; + for (;;) + { + dist = ChSetB[distancePlace & 0xff]; + newDistancePlace = NToPlB[dist++ & 0xff]++; + if (!(dist & 0xff)) + CorrHuff(ChSetB,NToPlB); + else + break; + } + + ChSetB[distancePlace] = ChSetB[newDistancePlace]; + ChSetB[newDistancePlace] = dist; + + dist = ((dist & 0xff00) >> 1) | ReadBits(7); + + oldAvr3 = AvrLn3; + if (len != 1 && len != 4) + if (len == 0 && dist <= MaxDist3) + { + AvrLn3++; + AvrLn3 -= AvrLn3 >> 8; + } + else + if (AvrLn3 > 0) + AvrLn3--; + len += 3; + if (dist >= MaxDist3) + len++; + if (dist <= 256) + len += 8; + if (oldAvr3 > 0xb0 || AvrPlc >= 0x2a00 && oldAvr2 < 0x40) + MaxDist3 = 0x7f00; + else + MaxDist3 = 0x2001; + m_RepDists[m_RepDistPtr++] = --dist; + m_RepDistPtr &= 3; + LastLength = len; + LastDist = dist; + return CopyBlock(dist, len); +} + + +HRESULT CDecoder::HuffDecode() +{ + UInt32 curByte, newBytePlace; + UInt32 len; + UInt32 dist; + int bytePlace; + + if (AvrPlc > 0x75ff) bytePlace = DecodeNum(PosHf4); + else if (AvrPlc > 0x5dff) bytePlace = DecodeNum(PosHf3); + else if (AvrPlc > 0x35ff) bytePlace = DecodeNum(PosHf2); + else if (AvrPlc > 0x0dff) bytePlace = DecodeNum(PosHf1); + else bytePlace = DecodeNum(PosHf0); + if (StMode) + { + if (--bytePlace == -1) + { + if (ReadBits(1)) + { + NumHuf = StMode = 0; + return S_OK; + } + else + { + len = (ReadBits(1)) ? 4 : 3; + dist = DecodeNum(PosHf2); + dist = (dist << 5) | ReadBits(5); + return CopyBlock(dist - 1, len); + } + } + } + else if (NumHuf++ >= 16 && FlagsCnt == 0) + StMode = 1; + bytePlace &= 0xff; + AvrPlc += bytePlace; + AvrPlc -= AvrPlc >> 8; + Nhfb+=16; + if (Nhfb > 0xff) + { + Nhfb=0x90; + Nlzb >>= 1; + } + + m_UnpackSize --; + m_OutWindowStream.PutByte((Byte)(ChSet[bytePlace] >> 8)); + + for (;;) + { + curByte = ChSet[bytePlace]; + newBytePlace = NToPl[curByte++ & 0xff]++; + if ((curByte & 0xff) > 0xa1) + CorrHuff(ChSet, NToPl); + else + break; + } + + ChSet[bytePlace] = ChSet[newBytePlace]; + ChSet[newBytePlace] = curByte; + return S_OK; +} + + +void CDecoder::GetFlagsBuf() +{ + UInt32 flags, newFlagsPlace; + UInt32 flagsPlace = DecodeNum(PosHf2); + + for (;;) + { + flags = ChSetC[flagsPlace]; + FlagBuf = flags >> 8; + newFlagsPlace = NToPlC[flags++ & 0xff]++; + if ((flags & 0xff) != 0) + break; + CorrHuff(ChSetC, NToPlC); + } + + ChSetC[flagsPlace] = ChSetC[newFlagsPlace]; + ChSetC[newFlagsPlace] = flags; +} + +void CDecoder::InitData() +{ + if (!m_IsSolid) + { + AvrPlcB = AvrLn1 = AvrLn2 = AvrLn3 = NumHuf = Buf60 = 0; + AvrPlc = 0x3500; + MaxDist3 = 0x2001; + Nhfb = Nlzb = 0x80; + } + FlagsCnt = 0; + FlagBuf = 0; + StMode = 0; + LCount = 0; +} + +void CDecoder::CorrHuff(UInt32 *CharSet,UInt32 *NumToPlace) +{ + int i; + for (i = 7; i >= 0; i--) + for (int j = 0; j < 32; j++, CharSet++) + *CharSet = (*CharSet & ~0xff) | i; + memset(NumToPlace, 0, sizeof(NToPl)); + for (i = 6; i >= 0; i--) + NumToPlace[i] = (7 - i) * 32; +} + +void CDecoder::InitHuff() +{ + for (UInt32 i = 0; i < 256; i++) + { + Place[i] = PlaceA[i] = PlaceB[i] = i; + PlaceC[i] = (~i + 1) & 0xff; + ChSet[i] = ChSetB[i] = i << 8; + ChSetA[i] = i; + ChSetC[i] = ((~i + 1) & 0xff) << 8; + } + memset(NToPl, 0, sizeof(NToPl)); + memset(NToPlB, 0, sizeof(NToPlB)); + memset(NToPlC, 0, sizeof(NToPlC)); + CorrHuff(ChSetB, NToPlB); +} + +HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo * /* progress */) +{ + if (inSize == NULL || outSize == NULL) + return E_INVALIDARG; + + if (!m_OutWindowStream.Create(kHistorySize)) + return E_OUTOFMEMORY; + if (!m_InBitStream.Create(1 << 20)) + return E_OUTOFMEMORY; + + m_UnpackSize = (Int64)*outSize; + m_OutWindowStream.SetStream(outStream); + m_OutWindowStream.Init(m_IsSolid); + m_InBitStream.SetStream(inStream); + m_InBitStream.Init(); + + CCoderReleaser coderReleaser(this); + InitData(); + if (!m_IsSolid) + { + InitStructures(); + InitHuff(); + } + if (m_UnpackSize > 0) + { + GetFlagsBuf(); + FlagsCnt = 8; + } + + while (m_UnpackSize > 0) + { + if (StMode) + { + RINOK(HuffDecode()); + continue; + } + + if (--FlagsCnt < 0) + { + GetFlagsBuf(); + FlagsCnt=7; + } + + if (FlagBuf & 0x80) + { + FlagBuf <<= 1; + if (Nlzb > Nhfb) + { + RINOK(LongLZ()); + } + else + { + RINOK(HuffDecode()); + } + } + else + { + FlagBuf <<= 1; + if (--FlagsCnt < 0) + { + GetFlagsBuf(); + FlagsCnt = 7; + } + if (FlagBuf & 0x80) + { + FlagBuf <<= 1; + if (Nlzb > Nhfb) + { + RINOK(HuffDecode()); + } + else + { + RINOK(LongLZ()); + } + } + else + { + FlagBuf <<= 1; + RINOK(ShortLZ()); + } + } + } + if (m_UnpackSize < 0) + return S_FALSE; + return m_OutWindowStream.Flush(); +} + +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + try { return CodeReal(inStream, outStream, inSize, outSize, progress); } + catch(const CInBufferException &e) { return e.ErrorCode; } + catch(const CLzOutWindowException &e) { return e.ErrorCode; } + catch(...) { return S_FALSE; } +} + +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) +{ + if (size < 1) + return E_INVALIDARG; + m_IsSolid = (data[0] != 0); + return S_OK; +} + +}} diff --git a/CPP/7zip/Compress/Rar1Decoder.h b/CPP/7zip/Compress/Rar1Decoder.h new file mode 100755 index 0000000..1b960e4 --- /dev/null +++ b/CPP/7zip/Compress/Rar1Decoder.h @@ -0,0 +1,88 @@ +// Rar1Decoder.h +// According to unRAR license, this code may not be used to develop +// a program that creates RAR archives + +#ifndef __COMPRESS_RAR1_DECODER_H +#define __COMPRESS_RAR1_DECODER_H + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +#include "../Common/InBuffer.h" + +#include "BitmDecoder.h" +#include "HuffmanDecoder.h" +#include "LzOutWindow.h" + +namespace NCompress { +namespace NRar1 { + +const UInt32 kNumRepDists = 4; + +typedef NBitm::CDecoder CBitDecoder; + +class CDecoder : + public ICompressCoder, + public ICompressSetDecoderProperties2, + public CMyUnknownImp +{ +public: + CLzOutWindow m_OutWindowStream; + CBitDecoder m_InBitStream; + + UInt32 m_RepDists[kNumRepDists]; + UInt32 m_RepDistPtr; + + UInt32 LastDist; + UInt32 LastLength; + + Int64 m_UnpackSize; + bool m_IsSolid; + + UInt32 ReadBits(int numBits); + HRESULT CopyBlock(UInt32 distance, UInt32 len); + + UInt32 DecodeNum(const UInt32 *posTab); + HRESULT ShortLZ(); + HRESULT LongLZ(); + HRESULT HuffDecode(); + void GetFlagsBuf(); + void InitData(); + void InitHuff(); + void CorrHuff(UInt32 *CharSet, UInt32 *NumToPlace); + void OldUnpWriteBuf(); + + UInt32 ChSet[256],ChSetA[256],ChSetB[256],ChSetC[256]; + UInt32 Place[256],PlaceA[256],PlaceB[256],PlaceC[256]; + UInt32 NToPl[256],NToPlB[256],NToPlC[256]; + UInt32 FlagBuf,AvrPlc,AvrPlcB,AvrLn1,AvrLn2,AvrLn3; + int Buf60,NumHuf,StMode,LCount,FlagsCnt; + UInt32 Nhfb,Nlzb,MaxDist3; + + void InitStructures(); + + HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + +public: + CDecoder(); + + MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2) + + void ReleaseStreams() + { + m_OutWindowStream.ReleaseStream(); + m_InBitStream.ReleaseStream(); + } + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); + +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/Rar2Decoder.cpp b/CPP/7zip/Compress/Rar2Decoder.cpp new file mode 100755 index 0000000..742e628 --- /dev/null +++ b/CPP/7zip/Compress/Rar2Decoder.cpp @@ -0,0 +1,391 @@ +// Rar2Decoder.cpp +// According to unRAR license, this code may not be used to develop +// a program that creates RAR archives + +#include "StdAfx.h" + +#include "Rar2Decoder.h" + +namespace NCompress { +namespace NRar2 { + +namespace NMultimedia { + +Byte CFilter::Decode(int &channelDelta, Byte deltaByte) +{ + D4 = D3; + D3 = D2; + D2 = LastDelta - D1; + D1 = LastDelta; + int predictedValue = ((8 * LastChar + K1 * D1 + K2 * D2 + K3 * D3 + K4 * D4 + K5 * channelDelta) >> 3); + + Byte realValue = (Byte)(predictedValue - deltaByte); + int i = ((int)(signed char)deltaByte) << 3; + + Dif[0] += abs(i); + Dif[1] += abs(i - D1); + Dif[2] += abs(i + D1); + Dif[3] += abs(i - D2); + Dif[4] += abs(i + D2); + Dif[5] += abs(i - D3); + Dif[6] += abs(i + D3); + Dif[7] += abs(i - D4); + Dif[8] += abs(i + D4); + Dif[9] += abs(i - channelDelta); + Dif[10] += abs(i + channelDelta); + + channelDelta = LastDelta = (signed char)(realValue - LastChar); + LastChar = realValue; + + if (((++ByteCount) & 0x1F) == 0) + { + UInt32 minDif = Dif[0]; + UInt32 numMinDif = 0; + Dif[0] = 0; + for (i = 1; i < sizeof(Dif) / sizeof(Dif[0]); i++) + { + if (Dif[i] < minDif) + { + minDif = Dif[i]; + numMinDif = i; + } + Dif[i] = 0; + } + switch(numMinDif) + { + case 1: if (K1 >= -16) K1--; break; + case 2: if (K1 < 16) K1++; break; + case 3: if (K2 >= -16) K2--; break; + case 4: if (K2 < 16) K2++; break; + case 5: if (K3 >= -16) K3--; break; + case 6: if (K3 < 16) K3++; break; + case 7: if (K4 >= -16) K4--; break; + case 8: if (K4 < 16) K4++; break; + case 9: if (K5 >= -16) K5--; break; + case 10:if (K5 < 16) K5++; break; + } + } + return realValue; +} +} + +static const char *kNumberErrorMessage = "Number error"; + +static const UInt32 kHistorySize = 1 << 20; + +static const int kNumStats = 11; + +static const UInt32 kWindowReservSize = (1 << 22) + 256; + +CDecoder::CDecoder(): + m_IsSolid(false) +{ +} + +void CDecoder::InitStructures() +{ + m_MmFilter.Init(); + for(int i = 0; i < kNumRepDists; i++) + m_RepDists[i] = 0; + m_RepDistPtr = 0; + m_LastLength = 0; + memset(m_LastLevels, 0, kMaxTableSize); +} + +UInt32 CDecoder::ReadBits(int numBits) { return m_InBitStream.ReadBits(numBits); } + +#define RIF(x) { if (!(x)) return false; } + +bool CDecoder::ReadTables(void) +{ + Byte levelLevels[kLevelTableSize]; + Byte newLevels[kMaxTableSize]; + m_AudioMode = (ReadBits(1) == 1); + + if (ReadBits(1) == 0) + memset(m_LastLevels, 0, kMaxTableSize); + int numLevels; + if (m_AudioMode) + { + m_NumChannels = ReadBits(2) + 1; + if (m_MmFilter.CurrentChannel >= m_NumChannels) + m_MmFilter.CurrentChannel = 0; + numLevels = m_NumChannels * kMMTableSize; + } + else + numLevels = kHeapTablesSizesSum; + + int i; + for (i = 0; i < kLevelTableSize; i++) + levelLevels[i] = (Byte)ReadBits(4); + RIF(m_LevelDecoder.SetCodeLengths(levelLevels)); + i = 0; + while (i < numLevels) + { + UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream); + if (number < kTableDirectLevels) + { + newLevels[i] = (Byte)((number + m_LastLevels[i]) & kLevelMask); + i++; + } + else + { + if (number == kTableLevelRepNumber) + { + int t = ReadBits(2) + 3; + for (int reps = t; reps > 0 && i < numLevels ; reps--, i++) + newLevels[i] = newLevels[i - 1]; + } + else + { + int num; + if (number == kTableLevel0Number) + num = ReadBits(3) + 3; + else if (number == kTableLevel0Number2) + num = ReadBits(7) + 11; + else + return false; + for (;num > 0 && i < numLevels; num--) + newLevels[i++] = 0; + } + } + } + if (m_AudioMode) + for (i = 0; i < m_NumChannels; i++) + { + RIF(m_MMDecoders[i].SetCodeLengths(&newLevels[i * kMMTableSize])); + } + else + { + RIF(m_MainDecoder.SetCodeLengths(&newLevels[0])); + RIF(m_DistDecoder.SetCodeLengths(&newLevels[kMainTableSize])); + RIF(m_LenDecoder.SetCodeLengths(&newLevels[kMainTableSize + kDistTableSize])); + } + memcpy(m_LastLevels, newLevels, kMaxTableSize); + return true; +} + +bool CDecoder::ReadLastTables() +{ + // it differs a little from pure RAR sources; + // UInt64 ttt = m_InBitStream.GetProcessedSize() + 2; + // + 2 works for: return 0xFF; in CInBuffer::ReadByte. + if (m_InBitStream.GetProcessedSize() + 7 <= m_PackSize) // test it: probably incorrect; + // if (m_InBitStream.GetProcessedSize() + 2 <= m_PackSize) // test it: probably incorrect; + if (m_AudioMode) + { + UInt32 symbol = m_MMDecoders[m_MmFilter.CurrentChannel].DecodeSymbol(&m_InBitStream); + if (symbol == 256) + return ReadTables(); + if (symbol >= kMMTableSize) + return false; + } + else + { + UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream); + if (number == kReadTableNumber) + return ReadTables(); + if (number >= kMainTableSize) + return false; + } + return true; +} + +class CCoderReleaser +{ + CDecoder *m_Coder; +public: + CCoderReleaser(CDecoder *coder): m_Coder(coder) {} + ~CCoderReleaser() + { + m_Coder->ReleaseStreams(); + } +}; + +bool CDecoder::DecodeMm(UInt32 pos) +{ + while (pos-- > 0) + { + UInt32 symbol = m_MMDecoders[m_MmFilter.CurrentChannel].DecodeSymbol(&m_InBitStream); + if (symbol == 256) + return true; + if (symbol >= kMMTableSize) + return false; + /* + Byte byPredict = m_Predictor.Predict(); + Byte byReal = (Byte)(byPredict - (Byte)symbol); + m_Predictor.Update(byReal, byPredict); + */ + Byte byReal = m_MmFilter.Decode((Byte)symbol); + m_OutWindowStream.PutByte(byReal); + if (++m_MmFilter.CurrentChannel == m_NumChannels) + m_MmFilter.CurrentChannel = 0; + } + return true; +} + +bool CDecoder::DecodeLz(Int32 pos) +{ + while (pos > 0) + { + UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream); + UInt32 length, distance; + if (number < 256) + { + m_OutWindowStream.PutByte(Byte(number)); + pos--; + continue; + } + else if (number >= kMatchNumber) + { + number -= kMatchNumber; + length = kNormalMatchMinLen + UInt32(kLenStart[number]) + + m_InBitStream.ReadBits(kLenDirectBits[number]); + number = m_DistDecoder.DecodeSymbol(&m_InBitStream); + if (number >= kDistTableSize) + return false; + distance = kDistStart[number] + m_InBitStream.ReadBits(kDistDirectBits[number]); + if (distance >= kDistLimit3) + { + length += 2 - ((distance - kDistLimit4) >> 31); + // length++; + // if (distance >= kDistLimit4) + // length++; + } + } + else if (number == kRepBothNumber) + { + length = m_LastLength; + if (length == 0) + return false; + distance = m_RepDists[(m_RepDistPtr + 4 - 1) & 3]; + } + else if (number < kLen2Number) + { + distance = m_RepDists[(m_RepDistPtr - (number - kRepNumber + 1)) & 3]; + number = m_LenDecoder.DecodeSymbol(&m_InBitStream); + if (number >= kLenTableSize) + return false; + length = 2 + kLenStart[number] + m_InBitStream.ReadBits(kLenDirectBits[number]); + if (distance >= kDistLimit2) + { + length++; + if (distance >= kDistLimit3) + { + length += 2 - ((distance - kDistLimit4) >> 31); + // length++; + // if (distance >= kDistLimit4) + // length++; + } + } + } + else if (number < kReadTableNumber) + { + number -= kLen2Number; + distance = kLen2DistStarts[number] + + m_InBitStream.ReadBits(kLen2DistDirectBits[number]); + length = 2; + } + else if (number == kReadTableNumber) + return true; + else + return false; + m_RepDists[m_RepDistPtr++ & 3] = distance; + m_LastLength = length; + if (!m_OutWindowStream.CopyBlock(distance, length)) + return false; + pos -= length; + } + return true; +} + +HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + if (inSize == NULL || outSize == NULL) + return E_INVALIDARG; + + if (!m_OutWindowStream.Create(kHistorySize)) + return E_OUTOFMEMORY; + if (!m_InBitStream.Create(1 << 20)) + return E_OUTOFMEMORY; + + m_PackSize = *inSize; + + UInt64 pos = 0, unPackSize = *outSize; + + m_OutWindowStream.SetStream(outStream); + m_OutWindowStream.Init(m_IsSolid); + m_InBitStream.SetStream(inStream); + m_InBitStream.Init(); + + CCoderReleaser coderReleaser(this); + if (!m_IsSolid) + { + InitStructures(); + if (unPackSize == 0) + { + if (m_InBitStream.GetProcessedSize() + 2 <= m_PackSize) // test it: probably incorrect; + if (!ReadTables()) + return S_FALSE; + return S_OK; + } + if (!ReadTables()) + return S_FALSE; + } + + UInt64 startPos = m_OutWindowStream.GetProcessedSize(); + while(pos < unPackSize) + { + UInt32 blockSize = 1 << 20; + if (blockSize > unPackSize - pos) + blockSize = (UInt32)(unPackSize - pos); + UInt64 blockStartPos = m_OutWindowStream.GetProcessedSize(); + if (m_AudioMode) + { + if (!DecodeMm(blockSize)) + return S_FALSE; + } + else + { + if (!DecodeLz((Int32)blockSize)) + return S_FALSE; + } + UInt64 globalPos = m_OutWindowStream.GetProcessedSize(); + pos = globalPos - blockStartPos; + if (pos < blockSize) + if (!ReadTables()) + return S_FALSE; + pos = globalPos - startPos; + if (progress != 0) + { + UInt64 packSize = m_InBitStream.GetProcessedSize(); + RINOK(progress->SetRatioInfo(&packSize, &pos)); + } + } + if (pos > unPackSize) + return S_FALSE; + + if (!ReadLastTables()) + return S_FALSE; + return m_OutWindowStream.Flush(); +} + +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + try { return CodeReal(inStream, outStream, inSize, outSize, progress); } + catch(const CInBufferException &e) { return e.ErrorCode; } + catch(const CLzOutWindowException &e) { return e.ErrorCode; } + catch(...) { return S_FALSE; } +} + +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) +{ + if (size < 1) + return E_INVALIDARG; + m_IsSolid = (data[0] != 0); + return S_OK; +} + +}} diff --git a/CPP/7zip/Compress/Rar2Decoder.h b/CPP/7zip/Compress/Rar2Decoder.h new file mode 100755 index 0000000..65cc973 --- /dev/null +++ b/CPP/7zip/Compress/Rar2Decoder.h @@ -0,0 +1,174 @@ +// Rar2Decoder.h +// According to unRAR license, this code may not be used to develop +// a program that creates RAR archives + +#ifndef __COMPRESS_RAR2_DECODER_H +#define __COMPRESS_RAR2_DECODER_H + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +#include "../Common/InBuffer.h" + +#include "BitmDecoder.h" +#include "HuffmanDecoder.h" +#include "LzOutWindow.h" + +namespace NCompress { +namespace NRar2 { + +const UInt32 kNumRepDists = 4; +const UInt32 kDistTableSize = 48; + +const int kMMTableSize = 256 + 1; + +const UInt32 kMainTableSize = 298; +const UInt32 kLenTableSize = 28; + +const UInt32 kDistTableStart = kMainTableSize; +const UInt32 kLenTableStart = kDistTableStart + kDistTableSize; + +const UInt32 kHeapTablesSizesSum = kMainTableSize + kDistTableSize + kLenTableSize; + +const UInt32 kLevelTableSize = 19; + +const UInt32 kMMTablesSizesSum = kMMTableSize * 4; + +const UInt32 kMaxTableSize = kMMTablesSizesSum; + +const UInt32 kTableDirectLevels = 16; +const UInt32 kTableLevelRepNumber = kTableDirectLevels; +const UInt32 kTableLevel0Number = kTableLevelRepNumber + 1; +const UInt32 kTableLevel0Number2 = kTableLevel0Number + 1; + +const UInt32 kLevelMask = 0xF; + + +const UInt32 kRepBothNumber = 256; +const UInt32 kRepNumber = kRepBothNumber + 1; +const UInt32 kLen2Number = kRepNumber + 4; + +const UInt32 kLen2NumNumbers = 8; +const UInt32 kReadTableNumber = kLen2Number + kLen2NumNumbers; +const UInt32 kMatchNumber = kReadTableNumber + 1; + +const Byte kLenStart[kLenTableSize] = {0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224}; +const Byte kLenDirectBits[kLenTableSize] = {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5}; + +const UInt32 kDistStart[kDistTableSize] = {0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576,32768U,49152U,65536,98304,131072,196608,262144,327680,393216,458752,524288,589824,655360,720896,786432,851968,917504,983040}; +const Byte kDistDirectBits[kDistTableSize] = {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; + +const Byte kLevelDirectBits[kLevelTableSize] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7}; + +const Byte kLen2DistStarts[kLen2NumNumbers]={0,4,8,16,32,64,128,192}; +const Byte kLen2DistDirectBits[kLen2NumNumbers]={2,2,3, 4, 5, 6, 6, 6}; + +const UInt32 kDistLimit2 = 0x101 - 1; +const UInt32 kDistLimit3 = 0x2000 - 1; +const UInt32 kDistLimit4 = 0x40000 - 1; + +const UInt32 kMatchMaxLen = 255 + 2; +const UInt32 kMatchMaxLenMax = 255 + 5; +const UInt32 kNormalMatchMinLen = 3; + +namespace NMultimedia { + +struct CFilter +{ + int K1,K2,K3,K4,K5; + int D1,D2,D3,D4; + int LastDelta; + UInt32 Dif[11]; + UInt32 ByteCount; + int LastChar; + + Byte Decode(int &channelDelta, Byte delta); + + void Init() { memset(this, 0, sizeof(*this)); } + +}; + +const int kNumChanelsMax = 4; + +class CFilter2 +{ +public: + CFilter m_Filters[kNumChanelsMax]; + int m_ChannelDelta; + int CurrentChannel; + + void Init() { memset(this, 0, sizeof(*this)); } + Byte Decode(Byte delta) + { + return m_Filters[CurrentChannel].Decode(m_ChannelDelta, delta); + } + +}; + +} + +typedef NBitm::CDecoder CBitDecoder; + +const int kNumHuffmanBits = 15; + +class CDecoder : + public ICompressCoder, + public ICompressSetDecoderProperties2, + public CMyUnknownImp +{ + CLzOutWindow m_OutWindowStream; + CBitDecoder m_InBitStream; + NHuffman::CDecoder m_MainDecoder; + NHuffman::CDecoder m_DistDecoder; + NHuffman::CDecoder m_LenDecoder; + NHuffman::CDecoder m_MMDecoders[NMultimedia::kNumChanelsMax]; + NHuffman::CDecoder m_LevelDecoder; + + bool m_AudioMode; + + NMultimedia::CFilter2 m_MmFilter; + int m_NumChannels; + + UInt32 m_RepDists[kNumRepDists]; + UInt32 m_RepDistPtr; + + UInt32 m_LastLength; + + Byte m_LastLevels[kMaxTableSize]; + + UInt64 m_PackSize; + bool m_IsSolid; + + void InitStructures(); + UInt32 ReadBits(int numBits); + bool ReadTables(); + bool ReadLastTables(); + + bool DecodeMm(UInt32 pos); + bool DecodeLz(Int32 pos); + + HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + +public: + CDecoder(); + + MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2) + + void ReleaseStreams() + { + m_OutWindowStream.ReleaseStream(); + m_InBitStream.ReleaseStream(); + } + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); + +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/Rar3Decoder.cpp b/CPP/7zip/Compress/Rar3Decoder.cpp new file mode 100755 index 0000000..fd76212 --- /dev/null +++ b/CPP/7zip/Compress/Rar3Decoder.cpp @@ -0,0 +1,897 @@ +// Rar3Decoder.cpp +// According to unRAR license, this code may not be used to develop +// a program that creates RAR archives + +/* This code uses Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "../Common/StreamUtils.h" + +#include "Rar3Decoder.h" + +namespace NCompress { +namespace NRar3 { + +static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } +static void SzBigFree(void *, void *address) { BigFree(address); } +static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; + +static const UInt32 kNumAlignReps = 15; + +static const UInt32 kSymbolReadTable = 256; +static const UInt32 kSymbolRep = 259; +static const UInt32 kSymbolLen2 = kSymbolRep + kNumReps; + +static const Byte kLenStart[kLenTableSize] = {0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224}; +static const Byte kLenDirectBits[kLenTableSize] = {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5}; + +static const Byte kDistDirectBits[kDistTableSize] = + {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 18,18,18,18,18,18,18,18,18,18,18,18}; + +static const Byte kLevelDirectBits[kLevelTableSize] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +static const Byte kLen2DistStarts[kNumLen2Symbols]={0,4,8,16,32,64,128,192}; +static const Byte kLen2DistDirectBits[kNumLen2Symbols]={2,2,3, 4, 5, 6, 6, 6}; + +static const UInt32 kDistLimit3 = 0x2000 - 2; +static const UInt32 kDistLimit4 = 0x40000 - 2; + +static const UInt32 kNormalMatchMinLen = 3; + +static const UInt32 kVmDataSizeMax = 1 << 16; +static const UInt32 kVmCodeSizeMax = 1 << 16; + +extern "C" { + +static UInt32 Range_GetThreshold(void *pp, UInt32 total) +{ + CRangeDecoder *p = (CRangeDecoder *)pp; + return p->Code / (p->Range /= total); +} + +static void Range_Decode(void *pp, UInt32 start, UInt32 size) +{ + CRangeDecoder *p = (CRangeDecoder *)pp; + start *= p->Range; + p->Low += start; + p->Code -= start; + p->Range *= size; + p->Normalize(); +} + +static UInt32 Range_DecodeBit(void *pp, UInt32 size0) +{ + CRangeDecoder *p = (CRangeDecoder *)pp; + if (p->Code / (p->Range >>= 14) < size0) + { + Range_Decode(p, 0, size0); + return 0; + } + else + { + Range_Decode(p, size0, (1 << 14) - size0); + return 1; + } +} + +} + +CRangeDecoder::CRangeDecoder() +{ + s.GetThreshold = Range_GetThreshold; + s.Decode = Range_Decode; + s.DecodeBit = Range_DecodeBit; +} + +CDecoder::CDecoder(): + _window(0), + _winPos(0), + _wrPtr(0), + _lzSize(0), + _writtenFileSize(0), + _vmData(0), + _vmCode(0), + m_IsSolid(false) +{ + Ppmd7_Construct(&_ppmd); +} + +CDecoder::~CDecoder() +{ + InitFilters(); + ::MidFree(_vmData); + ::MidFree(_window); + Ppmd7_Free(&_ppmd, &g_BigAlloc); +} + +HRESULT CDecoder::WriteDataToStream(const Byte *data, UInt32 size) +{ + return WriteStream(_outStream, data, size); +} + +HRESULT CDecoder::WriteData(const Byte *data, UInt32 size) +{ + HRESULT res = S_OK; + if (_writtenFileSize < _unpackSize) + { + UInt32 curSize = size; + UInt64 remain = _unpackSize - _writtenFileSize; + if (remain < curSize) + curSize = (UInt32)remain; + res = WriteDataToStream(data, curSize); + } + _writtenFileSize += size; + return res; +} + +HRESULT CDecoder::WriteArea(UInt32 startPtr, UInt32 endPtr) +{ + if (startPtr <= endPtr) + return WriteData(_window + startPtr, endPtr - startPtr); + RINOK(WriteData(_window + startPtr, kWindowSize - startPtr)); + return WriteData(_window, endPtr); +} + +void CDecoder::ExecuteFilter(int tempFilterIndex, NVm::CBlockRef &outBlockRef) +{ + CTempFilter *tempFilter = _tempFilters[tempFilterIndex]; + tempFilter->InitR[6] = (UInt32)_writtenFileSize; + NVm::SetValue32(&tempFilter->GlobalData[0x24], (UInt32)_writtenFileSize); + NVm::SetValue32(&tempFilter->GlobalData[0x28], (UInt32)(_writtenFileSize >> 32)); + CFilter *filter = _filters[tempFilter->FilterIndex]; + _vm.Execute(filter, tempFilter, outBlockRef, filter->GlobalData); + delete tempFilter; + _tempFilters[tempFilterIndex] = 0; +} + +HRESULT CDecoder::WriteBuf() +{ + UInt32 writtenBorder = _wrPtr; + UInt32 writeSize = (_winPos - writtenBorder) & kWindowMask; + for (int i = 0; i < _tempFilters.Size(); i++) + { + CTempFilter *filter = _tempFilters[i]; + if (filter == NULL) + continue; + if (filter->NextWindow) + { + filter->NextWindow = false; + continue; + } + UInt32 blockStart = filter->BlockStart; + UInt32 blockSize = filter->BlockSize; + if (((blockStart - writtenBorder) & kWindowMask) < writeSize) + { + if (writtenBorder != blockStart) + { + RINOK(WriteArea(writtenBorder, blockStart)); + writtenBorder = blockStart; + writeSize = (_winPos - writtenBorder) & kWindowMask; + } + if (blockSize <= writeSize) + { + UInt32 blockEnd = (blockStart + blockSize) & kWindowMask; + if (blockStart < blockEnd || blockEnd == 0) + _vm.SetMemory(0, _window + blockStart, blockSize); + else + { + UInt32 tailSize = kWindowSize - blockStart; + _vm.SetMemory(0, _window + blockStart, tailSize); + _vm.SetMemory(tailSize, _window, blockEnd); + } + NVm::CBlockRef outBlockRef; + ExecuteFilter(i, outBlockRef); + while (i + 1 < _tempFilters.Size()) + { + CTempFilter *nextFilter = _tempFilters[i + 1]; + if (nextFilter == NULL || nextFilter->BlockStart != blockStart || + nextFilter->BlockSize != outBlockRef.Size || nextFilter->NextWindow) + break; + _vm.SetMemory(0, _vm.GetDataPointer(outBlockRef.Offset), outBlockRef.Size); + ExecuteFilter(++i, outBlockRef); + } + WriteDataToStream(_vm.GetDataPointer(outBlockRef.Offset), outBlockRef.Size); + _writtenFileSize += outBlockRef.Size; + writtenBorder = blockEnd; + writeSize = (_winPos - writtenBorder) & kWindowMask; + } + else + { + for (int j = i; j < _tempFilters.Size(); j++) + { + CTempFilter *filter = _tempFilters[j]; + if (filter != NULL && filter->NextWindow) + filter->NextWindow = false; + } + _wrPtr = writtenBorder; + return S_OK; // check it + } + } + } + + _wrPtr = _winPos; + return WriteArea(writtenBorder, _winPos); +} + +void CDecoder::InitFilters() +{ + _lastFilter = 0; + int i; + for (i = 0; i < _tempFilters.Size(); i++) + delete _tempFilters[i]; + _tempFilters.Clear(); + for (i = 0; i < _filters.Size(); i++) + delete _filters[i]; + _filters.Clear(); +} + +bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize) +{ + CMemBitDecoder inp; + inp.Init(_vmData, codeSize); + + UInt32 filterIndex; + if (firstByte & 0x80) + { + filterIndex = NVm::ReadEncodedUInt32(inp); + if (filterIndex == 0) + InitFilters(); + else + filterIndex--; + } + else + filterIndex = _lastFilter; + if (filterIndex > (UInt32)_filters.Size()) + return false; + _lastFilter = filterIndex; + bool newFilter = (filterIndex == (UInt32)_filters.Size()); + + CFilter *filter; + if (newFilter) + { + // check if too many filters + if (filterIndex > 1024) + return false; + filter = new CFilter; + _filters.Add(filter); + } + else + { + filter = _filters[filterIndex]; + filter->ExecCount++; + } + + int numEmptyItems = 0; + int i; + for (i = 0; i < _tempFilters.Size(); i++) + { + _tempFilters[i - numEmptyItems] = _tempFilters[i]; + if (_tempFilters[i] == NULL) + numEmptyItems++; + if (numEmptyItems > 0) + _tempFilters[i] = NULL; + } + if (numEmptyItems == 0) + { + _tempFilters.Add(NULL); + numEmptyItems = 1; + } + CTempFilter *tempFilter = new CTempFilter; + _tempFilters[_tempFilters.Size() - numEmptyItems] = tempFilter; + tempFilter->FilterIndex = filterIndex; + tempFilter->ExecCount = filter->ExecCount; + + UInt32 blockStart = NVm::ReadEncodedUInt32(inp); + if (firstByte & 0x40) + blockStart += 258; + tempFilter->BlockStart = (blockStart + _winPos) & kWindowMask; + if (firstByte & 0x20) + filter->BlockSize = NVm::ReadEncodedUInt32(inp); + tempFilter->BlockSize = filter->BlockSize; + tempFilter->NextWindow = _wrPtr != _winPos && ((_wrPtr - _winPos) & kWindowMask) <= blockStart; + + memset(tempFilter->InitR, 0, sizeof(tempFilter->InitR)); + tempFilter->InitR[3] = NVm::kGlobalOffset; + tempFilter->InitR[4] = tempFilter->BlockSize; + tempFilter->InitR[5] = tempFilter->ExecCount; + if (firstByte & 0x10) + { + UInt32 initMask = inp.ReadBits(NVm::kNumGpRegs); + for (int i = 0; i < NVm::kNumGpRegs; i++) + if (initMask & (1 << i)) + tempFilter->InitR[i] = NVm::ReadEncodedUInt32(inp); + } + if (newFilter) + { + UInt32 vmCodeSize = NVm::ReadEncodedUInt32(inp); + if (vmCodeSize >= kVmCodeSizeMax || vmCodeSize == 0) + return false; + for (UInt32 i = 0; i < vmCodeSize; i++) + _vmCode[i] = (Byte)inp.ReadBits(8); + _vm.PrepareProgram(_vmCode, vmCodeSize, filter); + } + + tempFilter->AllocateEmptyFixedGlobal(); + + Byte *globalData = &tempFilter->GlobalData[0]; + for (i = 0; i < NVm::kNumGpRegs; i++) + NVm::SetValue32(&globalData[i * 4], tempFilter->InitR[i]); + NVm::SetValue32(&globalData[NVm::NGlobalOffset::kBlockSize], tempFilter->BlockSize); + NVm::SetValue32(&globalData[NVm::NGlobalOffset::kBlockPos], 0); // It was commented. why? + NVm::SetValue32(&globalData[NVm::NGlobalOffset::kExecCount], tempFilter->ExecCount); + + if (firstByte & 8) + { + UInt32 dataSize = NVm::ReadEncodedUInt32(inp); + if (dataSize > NVm::kGlobalSize - NVm::kFixedGlobalSize) + return false; + CRecordVector &globalData = tempFilter->GlobalData; + int requredSize = (int)(dataSize + NVm::kFixedGlobalSize); + if (globalData.Size() < requredSize) + { + globalData.Reserve(requredSize); + for (; globalData.Size() < requredSize; i++) + globalData.Add(0); + } + for (UInt32 i = 0; i < dataSize; i++) + globalData[NVm::kFixedGlobalSize + i] = (Byte)inp.ReadBits(8); + } + return true; +} + +bool CDecoder::ReadVmCodeLZ() +{ + UInt32 firstByte = ReadBits(8); + UInt32 length = (firstByte & 7) + 1; + if (length == 7) + length = ReadBits(8) + 7; + else if (length == 8) + length = ReadBits(16); + if (length > kVmDataSizeMax) + return false; + for (UInt32 i = 0; i < length; i++) + _vmData[i] = (Byte)ReadBits(8); + return AddVmCode(firstByte, length); +} + +bool CDecoder::ReadVmCodePPM() +{ + int firstByte = DecodePpmSymbol(); + if (firstByte < 0) + return false; + UInt32 length = (firstByte & 7) + 1; + if (length == 7) + { + int b1 = DecodePpmSymbol(); + if (b1 < 0) + return false; + length = b1 + 7; + } + else if (length == 8) + { + int b1 = DecodePpmSymbol(); + if (b1 < 0) + return false; + int b2 = DecodePpmSymbol(); + if (b2 < 0) + return false; + length = b1 * 256 + b2; + } + if (length > kVmDataSizeMax) + return false; + for (UInt32 i = 0; i < length; i++) + { + int b = DecodePpmSymbol(); + if (b < 0) + return false; + _vmData[i] = (Byte)b; + } + return AddVmCode(firstByte, length); +} + +#define RIF(x) { if (!(x)) return S_FALSE; } + +UInt32 CDecoder::ReadBits(int numBits) { return m_InBitStream.bitDecoder.ReadBits(numBits); } + +///////////////////////////////////////////////// +// PPM + +HRESULT CDecoder::InitPPM() +{ + Byte maxOrder = (Byte)ReadBits(7); + + bool reset = ((maxOrder & 0x20) != 0); + int maxMB = 0; + if (reset) + maxMB = (Byte)ReadBits(8); + else + { + if (PpmError || !Ppmd7_WasAllocated(&_ppmd)) + return S_FALSE; + } + if (maxOrder & 0x40) + PpmEscChar = (Byte)ReadBits(8); + m_InBitStream.InitRangeCoder(); + /* + if (m_InBitStream.m_BitPos != 0) + return S_FALSE; + */ + if (reset) + { + PpmError = true; + maxOrder = (maxOrder & 0x1F) + 1; + if (maxOrder > 16) + maxOrder = 16 + (maxOrder - 16) * 3; + if (maxOrder == 1) + { + Ppmd7_Free(&_ppmd, &g_BigAlloc); + return S_FALSE; + } + if (!Ppmd7_Alloc(&_ppmd, (maxMB + 1) << 20, &g_BigAlloc)) + return E_OUTOFMEMORY; + Ppmd7_Init(&_ppmd, maxOrder); + PpmError = false; + } + return S_OK; +} + +int CDecoder::DecodePpmSymbol() { return Ppmd7_DecodeSymbol(&_ppmd, &m_InBitStream.s); } + +HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing) +{ + keepDecompressing = false; + if (PpmError) + return S_FALSE; + do + { + if (((_wrPtr - _winPos) & kWindowMask) < 260 && _wrPtr != _winPos) + { + RINOK(WriteBuf()); + if (_writtenFileSize > _unpackSize) + { + keepDecompressing = false; + return S_OK; + } + } + int c = DecodePpmSymbol(); + if (c < 0) + { + PpmError = true; + return S_FALSE; + } + if (c == PpmEscChar) + { + int nextCh = DecodePpmSymbol(); + if (nextCh < 0) + { + PpmError = true; + return S_FALSE; + } + if (nextCh == 0) + return ReadTables(keepDecompressing); + if (nextCh == 2 || nextCh == -1) + return S_OK; + if (nextCh == 3) + { + if (!ReadVmCodePPM()) + { + PpmError = true; + return S_FALSE; + } + continue; + } + if (nextCh == 4 || nextCh == 5) + { + UInt32 distance = 0; + UInt32 length = 4; + if (nextCh == 4) + { + for (int i = 0; i < 3; i++) + { + int c = DecodePpmSymbol(); + if (c < 0) + { + PpmError = true; + return S_FALSE; + } + distance = (distance << 8) + (Byte)c; + } + distance++; + length += 28; + } + int c = DecodePpmSymbol(); + if (c < 0) + { + PpmError = true; + return S_FALSE; + } + length += c; + if (distance >= _lzSize) + return S_FALSE; + CopyBlock(distance, length); + num -= (Int32)length; + continue; + } + } + PutByte((Byte)c); + num--; + } + while (num >= 0); + keepDecompressing = true; + return S_OK; +} + +///////////////////////////////////////////////// +// LZ + +HRESULT CDecoder::ReadTables(bool &keepDecompressing) +{ + keepDecompressing = true; + ReadBits((8 - m_InBitStream.bitDecoder.GetBitPosition()) & 7); + if (ReadBits(1) != 0) + { + _lzMode = false; + return InitPPM(); + } + + _lzMode = true; + PrevAlignBits = 0; + PrevAlignCount = 0; + + Byte levelLevels[kLevelTableSize]; + Byte newLevels[kTablesSizesSum]; + + if (ReadBits(1) == 0) + memset(m_LastLevels, 0, kTablesSizesSum); + + int i; + for (i = 0; i < kLevelTableSize; i++) + { + UInt32 length = ReadBits(4); + if (length == 15) + { + UInt32 zeroCount = ReadBits(4); + if (zeroCount != 0) + { + zeroCount += 2; + while (zeroCount-- > 0 && i < kLevelTableSize) + levelLevels[i++]=0; + i--; + continue; + } + } + levelLevels[i] = (Byte)length; + } + RIF(m_LevelDecoder.SetCodeLengths(levelLevels)); + i = 0; + while (i < kTablesSizesSum) + { + UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream.bitDecoder); + if (number < 16) + { + newLevels[i] = Byte((number + m_LastLevels[i]) & 15); + i++; + } + else if (number > kLevelTableSize) + return S_FALSE; + else + { + int num; + if (((number - 16) & 1) == 0) + num = ReadBits(3) + 3; + else + num = ReadBits(7) + 11; + if (number < 18) + { + if (i == 0) + return S_FALSE; + for (; num > 0 && i < kTablesSizesSum; num--, i++) + newLevels[i] = newLevels[i - 1]; + } + else + { + for (; num > 0 && i < kTablesSizesSum; num--) + newLevels[i++] = 0; + } + } + } + TablesRead = true; + + // original code has check here: + /* + if (InAddr > ReadTop) + { + keepDecompressing = false; + return true; + } + */ + + RIF(m_MainDecoder.SetCodeLengths(&newLevels[0])); + RIF(m_DistDecoder.SetCodeLengths(&newLevels[kMainTableSize])); + RIF(m_AlignDecoder.SetCodeLengths(&newLevels[kMainTableSize + kDistTableSize])); + RIF(m_LenDecoder.SetCodeLengths(&newLevels[kMainTableSize + kDistTableSize + kAlignTableSize])); + + memcpy(m_LastLevels, newLevels, kTablesSizesSum); + return S_OK; +} + +class CCoderReleaser +{ + CDecoder *m_Coder; +public: + CCoderReleaser(CDecoder *coder): m_Coder(coder) {} + ~CCoderReleaser() + { + m_Coder->ReleaseStreams(); + } +}; + +HRESULT CDecoder::ReadEndOfBlock(bool &keepDecompressing) +{ + if (ReadBits(1) != 0) + { + // old file + TablesRead = false; + return ReadTables(keepDecompressing); + } + // new file + keepDecompressing = false; + TablesRead = (ReadBits(1) == 0); + return S_OK; +} + +UInt32 kDistStart[kDistTableSize]; + +class CDistInit +{ +public: + CDistInit() { Init(); } + void Init() + { + UInt32 start = 0; + for (UInt32 i = 0; i < kDistTableSize; i++) + { + kDistStart[i] = start; + start += (1 << kDistDirectBits[i]); + } + } +} g_DistInit; + +HRESULT CDecoder::DecodeLZ(bool &keepDecompressing) +{ + UInt32 rep0 = _reps[0]; + UInt32 rep1 = _reps[1]; + UInt32 rep2 = _reps[2]; + UInt32 rep3 = _reps[3]; + UInt32 length = _lastLength; + for (;;) + { + if (((_wrPtr - _winPos) & kWindowMask) < 260 && _wrPtr != _winPos) + { + RINOK(WriteBuf()); + if (_writtenFileSize > _unpackSize) + { + keepDecompressing = false; + return S_OK; + } + } + UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream.bitDecoder); + if (number < 256) + { + PutByte((Byte)number); + continue; + } + else if (number == kSymbolReadTable) + { + RINOK(ReadEndOfBlock(keepDecompressing)); + break; + } + else if (number == 257) + { + if (!ReadVmCodeLZ()) + return S_FALSE; + continue; + } + else if (number == 258) + { + if (length == 0) + return S_FALSE; + } + else if (number < kSymbolRep + 4) + { + if (number != kSymbolRep) + { + UInt32 distance; + if (number == kSymbolRep + 1) + distance = rep1; + else + { + if (number == kSymbolRep + 2) + distance = rep2; + else + { + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + + UInt32 number = m_LenDecoder.DecodeSymbol(&m_InBitStream.bitDecoder); + if (number >= kLenTableSize) + return S_FALSE; + length = 2 + kLenStart[number] + m_InBitStream.bitDecoder.ReadBits(kLenDirectBits[number]); + } + else + { + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + if (number < 271) + { + number -= 263; + rep0 = kLen2DistStarts[number] + m_InBitStream.bitDecoder.ReadBits(kLen2DistDirectBits[number]); + length = 2; + } + else if (number < 299) + { + number -= 271; + length = kNormalMatchMinLen + (UInt32)kLenStart[number] + m_InBitStream.bitDecoder.ReadBits(kLenDirectBits[number]); + UInt32 number = m_DistDecoder.DecodeSymbol(&m_InBitStream.bitDecoder); + if (number >= kDistTableSize) + return S_FALSE; + rep0 = kDistStart[number]; + int numBits = kDistDirectBits[number]; + if (number >= (kNumAlignBits * 2) + 2) + { + if (numBits > kNumAlignBits) + rep0 += (m_InBitStream.bitDecoder.ReadBits(numBits - kNumAlignBits) << kNumAlignBits); + if (PrevAlignCount > 0) + { + PrevAlignCount--; + rep0 += PrevAlignBits; + } + else + { + UInt32 number = m_AlignDecoder.DecodeSymbol(&m_InBitStream.bitDecoder); + if (number < (1 << kNumAlignBits)) + { + rep0 += number; + PrevAlignBits = number; + } + else if (number == (1 << kNumAlignBits)) + { + PrevAlignCount = kNumAlignReps; + rep0 += PrevAlignBits; + } + else + return S_FALSE; + } + } + else + rep0 += m_InBitStream.bitDecoder.ReadBits(numBits); + length += ((kDistLimit4 - rep0) >> 31) + ((kDistLimit3 - rep0) >> 31); + } + else + return S_FALSE; + } + if (rep0 >= _lzSize) + return S_FALSE; + CopyBlock(rep0, length); + } + _reps[0] = rep0; + _reps[1] = rep1; + _reps[2] = rep2; + _reps[3] = rep3; + _lastLength = length; + + return S_OK; +} + +HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress) +{ + _writtenFileSize = 0; + if (!m_IsSolid) + { + _lzSize = 0; + _winPos = 0; + _wrPtr = 0; + for (int i = 0; i < kNumReps; i++) + _reps[i] = 0; + _lastLength = 0; + memset(m_LastLevels, 0, kTablesSizesSum); + TablesRead = false; + PpmEscChar = 2; + PpmError = true; + InitFilters(); + } + if (!m_IsSolid || !TablesRead) + { + bool keepDecompressing; + RINOK(ReadTables(keepDecompressing)); + if (!keepDecompressing) + return S_OK; + } + + for (;;) + { + bool keepDecompressing; + if (_lzMode) + { + RINOK(DecodeLZ(keepDecompressing)) + } + else + { + RINOK(DecodePPM(1 << 18, keepDecompressing)) + } + UInt64 packSize = m_InBitStream.bitDecoder.GetProcessedSize(); + RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize)); + if (!keepDecompressing) + break; + } + RINOK(WriteBuf()); + UInt64 packSize = m_InBitStream.bitDecoder.GetProcessedSize(); + RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize)); + if (_writtenFileSize < _unpackSize) + return S_FALSE; + return S_OK; +} + +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + try + { + if (inSize == NULL || outSize == NULL) + return E_INVALIDARG; + + if (_vmData == 0) + { + _vmData = (Byte *)::MidAlloc(kVmDataSizeMax + kVmCodeSizeMax); + if (_vmData == 0) + return E_OUTOFMEMORY; + _vmCode = _vmData + kVmDataSizeMax; + } + + if (_window == 0) + { + _window = (Byte *)::MidAlloc(kWindowSize); + if (_window == 0) + return E_OUTOFMEMORY; + } + if (!m_InBitStream.bitDecoder.Create(1 << 20)) + return E_OUTOFMEMORY; + if (!_vm.Create()) + return E_OUTOFMEMORY; + + + m_InBitStream.bitDecoder.SetStream(inStream); + m_InBitStream.bitDecoder.Init(); + _outStream = outStream; + + CCoderReleaser coderReleaser(this); + _unpackSize = *outSize; + return CodeReal(progress); + } + catch(const CInBufferException &e) { return e.ErrorCode; } + catch(...) { return S_FALSE; } + // CNewException is possible here. But probably CNewException is caused + // by error in data stream. +} + +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) +{ + if (size < 1) + return E_INVALIDARG; + m_IsSolid = (data[0] != 0); + return S_OK; +} + +}} diff --git a/CPP/7zip/Compress/Rar3Decoder.h b/CPP/7zip/Compress/Rar3Decoder.h new file mode 100755 index 0000000..634f157 --- /dev/null +++ b/CPP/7zip/Compress/Rar3Decoder.h @@ -0,0 +1,267 @@ +// Rar3Decoder.h +// According to unRAR license, this code may not be used to develop +// a program that creates RAR archives + +/* This code uses Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ + +#ifndef __COMPRESS_RAR3_DECODER_H +#define __COMPRESS_RAR3_DECODER_H + +#include "../../../C/Ppmd7.h" + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +#include "../Common/InBuffer.h" + +#include "BitmDecoder.h" +#include "HuffmanDecoder.h" +#include "Rar3Vm.h" + +namespace NCompress { +namespace NRar3 { + +const UInt32 kWindowSize = 1 << 22; +const UInt32 kWindowMask = (kWindowSize - 1); + +const UInt32 kNumReps = 4; +const UInt32 kNumLen2Symbols = 8; +const UInt32 kLenTableSize = 28; +const UInt32 kMainTableSize = 256 + 1 + 1 + 1 + kNumReps + kNumLen2Symbols + kLenTableSize; +const UInt32 kDistTableSize = 60; + +const int kNumAlignBits = 4; +const UInt32 kAlignTableSize = (1 << kNumAlignBits) + 1; + +const UInt32 kLevelTableSize = 20; + +const UInt32 kTablesSizesSum = kMainTableSize + kDistTableSize + kAlignTableSize + kLenTableSize; + +class CBitDecoder +{ + UInt32 m_Value; + unsigned m_BitPos; +public: + CInBuffer m_Stream; + bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); } + void SetStream(ISequentialInStream *inStream) { m_Stream.SetStream(inStream);} + void ReleaseStream() { m_Stream.ReleaseStream();} + + void Init() + { + m_Stream.Init(); + m_BitPos = 0; + m_Value = 0; + } + + UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() - (m_BitPos) / 8; } + UInt32 GetBitPosition() const { return ((8 - m_BitPos) & 7); } + + UInt32 GetValue(unsigned numBits) + { + if (m_BitPos < numBits) + { + m_BitPos += 8; + m_Value = (m_Value << 8) | m_Stream.ReadByte(); + if (m_BitPos < numBits) + { + m_BitPos += 8; + m_Value = (m_Value << 8) | m_Stream.ReadByte(); + } + } + return m_Value >> (m_BitPos - numBits); + } + + void MovePos(unsigned numBits) + { + m_BitPos -= numBits; + m_Value = m_Value & ((1 << m_BitPos) - 1); + } + + UInt32 ReadBits(unsigned numBits) + { + UInt32 res = GetValue(numBits); + MovePos(numBits); + return res; + } +}; + +const UInt32 kTopValue = (1 << 24); +const UInt32 kBot = (1 << 15); + +struct CRangeDecoder +{ + IPpmd7_RangeDec s; + UInt32 Range; + UInt32 Code; + UInt32 Low; + CBitDecoder bitDecoder; + SRes Res; + +public: + void InitRangeCoder() + { + Code = 0; + Low = 0; + Range = 0xFFFFFFFF; + for (int i = 0; i < 4; i++) + Code = (Code << 8) | bitDecoder.ReadBits(8); + } + + void Normalize() + { + while ((Low ^ (Low + Range)) < kTopValue || + Range < kBot && ((Range = (0 - Low) & (kBot - 1)), 1)) + { + Code = (Code << 8) | bitDecoder.m_Stream.ReadByte(); + Range <<= 8; + Low <<= 8; + } + } + + CRangeDecoder(); +}; + +struct CFilter: public NVm::CProgram +{ + CRecordVector GlobalData; + UInt32 BlockStart; + UInt32 BlockSize; + UInt32 ExecCount; + CFilter(): BlockStart(0), BlockSize(0), ExecCount(0) {} +}; + +struct CTempFilter: public NVm::CProgramInitState +{ + UInt32 BlockStart; + UInt32 BlockSize; + UInt32 ExecCount; + bool NextWindow; + + UInt32 FilterIndex; +}; + +const int kNumHuffmanBits = 15; + +class CDecoder: + public ICompressCoder, + public ICompressSetDecoderProperties2, + public CMyUnknownImp +{ + CRangeDecoder m_InBitStream; + Byte *_window; + UInt32 _winPos; + UInt32 _wrPtr; + UInt64 _lzSize; + UInt64 _unpackSize; + UInt64 _writtenFileSize; // if it's > _unpackSize, then _unpackSize only written + CMyComPtr _outStream; + NHuffman::CDecoder m_MainDecoder; + NHuffman::CDecoder m_DistDecoder; + NHuffman::CDecoder m_AlignDecoder; + NHuffman::CDecoder m_LenDecoder; + NHuffman::CDecoder m_LevelDecoder; + + UInt32 _reps[kNumReps]; + UInt32 _lastLength; + + Byte m_LastLevels[kTablesSizesSum]; + + Byte *_vmData; + Byte *_vmCode; + NVm::CVm _vm; + CRecordVector _filters; + CRecordVector _tempFilters; + UInt32 _lastFilter; + + bool m_IsSolid; + + bool _lzMode; + + UInt32 PrevAlignBits; + UInt32 PrevAlignCount; + + bool TablesRead; + + CPpmd7 _ppmd; + int PpmEscChar; + bool PpmError; + + HRESULT WriteDataToStream(const Byte *data, UInt32 size); + HRESULT WriteData(const Byte *data, UInt32 size); + HRESULT WriteArea(UInt32 startPtr, UInt32 endPtr); + void ExecuteFilter(int tempFilterIndex, NVm::CBlockRef &outBlockRef); + HRESULT WriteBuf(); + + void InitFilters(); + bool AddVmCode(UInt32 firstByte, UInt32 codeSize); + bool ReadVmCodeLZ(); + bool ReadVmCodePPM(); + + UInt32 ReadBits(int numBits); + + HRESULT InitPPM(); + int DecodePpmSymbol(); + HRESULT DecodePPM(Int32 num, bool &keepDecompressing); + + HRESULT ReadTables(bool &keepDecompressing); + HRESULT ReadEndOfBlock(bool &keepDecompressing); + HRESULT DecodeLZ(bool &keepDecompressing); + HRESULT CodeReal(ICompressProgressInfo *progress); +public: + CDecoder(); + ~CDecoder(); + + MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2) + + void ReleaseStreams() + { + _outStream.Release(); + m_InBitStream.bitDecoder.ReleaseStream(); + } + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); + + void CopyBlock(UInt32 distance, UInt32 len) + { + _lzSize += len; + UInt32 pos = (_winPos - distance - 1) & kWindowMask; + Byte *window = _window; + UInt32 winPos = _winPos; + if (kWindowSize - winPos > len && kWindowSize - pos > len) + { + const Byte *src = window + pos; + Byte *dest = window + winPos; + _winPos += len; + do + *dest++ = *src++; + while(--len != 0); + return; + } + do + { + window[winPos] = window[pos]; + winPos = (winPos + 1) & kWindowMask; + pos = (pos + 1) & kWindowMask; + } + while(--len != 0); + _winPos = winPos; + } + + void PutByte(Byte b) + { + _window[_winPos] = b; + _winPos = (_winPos + 1) & kWindowMask; + _lzSize++; + } + + +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/Rar3Vm.cpp b/CPP/7zip/Compress/Rar3Vm.cpp new file mode 100755 index 0000000..9e28614 --- /dev/null +++ b/CPP/7zip/Compress/Rar3Vm.cpp @@ -0,0 +1,1091 @@ +// Rar3Vm.cpp +// According to unRAR license, this code may not be used to develop +// a program that creates RAR archives + +/* +Note: + Due to performance considerations Rar VM may set Flags C incorrectly + for some operands (SHL x, 0, ... ). + Check implementation of concrete VM command + to see if it sets flags right. +*/ + +#include "StdAfx.h" + +#include "../../../C/7zCrc.h" +#include "../../../C/Alloc.h" + +#include "Rar3Vm.h" + +namespace NCompress { +namespace NRar3 { + +UInt32 CMemBitDecoder::ReadBits(int numBits) +{ + UInt32 res = 0; + for (;;) + { + Byte b = _bitPos < _bitSize ? _data[_bitPos >> 3] : 0; + int avail = (int)(8 - (_bitPos & 7)); + if (numBits <= avail) + { + _bitPos += numBits; + return res | (b >> (avail - numBits)) & ((1 << numBits) - 1); + } + numBits -= avail; + res |= (UInt32)(b & ((1 << avail) - 1)) << numBits; + _bitPos += avail; + } +} + +UInt32 CMemBitDecoder::ReadBit() { return ReadBits(1); } + +namespace NVm { + +static const UInt32 kStackRegIndex = kNumRegs - 1; + +static const UInt32 FLAG_C = 1; +static const UInt32 FLAG_Z = 2; +static const UInt32 FLAG_S = 0x80000000; + +static const Byte CF_OP0 = 0; +static const Byte CF_OP1 = 1; +static const Byte CF_OP2 = 2; +static const Byte CF_OPMASK = 3; +static const Byte CF_BYTEMODE = 4; +static const Byte CF_JUMP = 8; +static const Byte CF_PROC = 16; +static const Byte CF_USEFLAGS = 32; +static const Byte CF_CHFLAGS = 64; + +static Byte kCmdFlags[]= +{ + /* CMD_MOV */ CF_OP2 | CF_BYTEMODE, + /* CMD_CMP */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS, + /* CMD_ADD */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS, + /* CMD_SUB */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS, + /* CMD_JZ */ CF_OP1 | CF_JUMP | CF_USEFLAGS, + /* CMD_JNZ */ CF_OP1 | CF_JUMP | CF_USEFLAGS, + /* CMD_INC */ CF_OP1 | CF_BYTEMODE | CF_CHFLAGS, + /* CMD_DEC */ CF_OP1 | CF_BYTEMODE | CF_CHFLAGS, + /* CMD_JMP */ CF_OP1 | CF_JUMP, + /* CMD_XOR */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS, + /* CMD_AND */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS, + /* CMD_OR */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS, + /* CMD_TEST */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS, + /* CMD_JS */ CF_OP1 | CF_JUMP | CF_USEFLAGS, + /* CMD_JNS */ CF_OP1 | CF_JUMP | CF_USEFLAGS, + /* CMD_JB */ CF_OP1 | CF_JUMP | CF_USEFLAGS, + /* CMD_JBE */ CF_OP1 | CF_JUMP | CF_USEFLAGS, + /* CMD_JA */ CF_OP1 | CF_JUMP | CF_USEFLAGS, + /* CMD_JAE */ CF_OP1 | CF_JUMP | CF_USEFLAGS, + /* CMD_PUSH */ CF_OP1, + /* CMD_POP */ CF_OP1, + /* CMD_CALL */ CF_OP1 | CF_PROC, + /* CMD_RET */ CF_OP0 | CF_PROC, + /* CMD_NOT */ CF_OP1 | CF_BYTEMODE, + /* CMD_SHL */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS, + /* CMD_SHR */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS, + /* CMD_SAR */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS, + /* CMD_NEG */ CF_OP1 | CF_BYTEMODE | CF_CHFLAGS, + /* CMD_PUSHA */ CF_OP0, + /* CMD_POPA */ CF_OP0, + /* CMD_PUSHF */ CF_OP0 | CF_USEFLAGS, + /* CMD_POPF */ CF_OP0 | CF_CHFLAGS, + /* CMD_MOVZX */ CF_OP2, + /* CMD_MOVSX */ CF_OP2, + /* CMD_XCHG */ CF_OP2 | CF_BYTEMODE, + /* CMD_MUL */ CF_OP2 | CF_BYTEMODE, + /* CMD_DIV */ CF_OP2 | CF_BYTEMODE, + /* CMD_ADC */ CF_OP2 | CF_BYTEMODE | CF_USEFLAGS | CF_CHFLAGS , + /* CMD_SBB */ CF_OP2 | CF_BYTEMODE | CF_USEFLAGS | CF_CHFLAGS , + /* CMD_PRINT */ CF_OP0 +}; + +CVm::CVm(): Mem(NULL) {} + +bool CVm::Create() +{ + if (Mem == NULL) + Mem = (Byte *)::MyAlloc(kSpaceSize + 4); + return (Mem != NULL); +} + +CVm::~CVm() +{ + ::MyFree(Mem); +} + +// CVm::Execute can change CProgram object: it clears progarm if VM returns error. + +bool CVm::Execute(CProgram *prg, const CProgramInitState *initState, + CBlockRef &outBlockRef, CRecordVector &outGlobalData) +{ + memcpy(R, initState->InitR, sizeof(initState->InitR)); + R[kStackRegIndex] = kSpaceSize; + R[kNumRegs] = 0; + Flags = 0; + + UInt32 globalSize = MyMin((UInt32)initState->GlobalData.Size(), kGlobalSize); + if (globalSize != 0) + memcpy(Mem + kGlobalOffset, &initState->GlobalData[0], globalSize); + UInt32 staticSize = MyMin((UInt32)prg->StaticData.Size(), kGlobalSize - globalSize); + if (staticSize != 0) + memcpy(Mem + kGlobalOffset + globalSize, &prg->StaticData[0], staticSize); + + bool res = true; + #ifdef RARVM_STANDARD_FILTERS + if (prg->StandardFilterIndex >= 0) + ExecuteStandardFilter(prg->StandardFilterIndex); + else + #endif + { + res = ExecuteCode(prg); + if (!res) + prg->Commands[0].OpCode = CMD_RET; + } + UInt32 newBlockPos = GetFixedGlobalValue32(NGlobalOffset::kBlockPos) & kSpaceMask; + UInt32 newBlockSize = GetFixedGlobalValue32(NGlobalOffset::kBlockSize) & kSpaceMask; + if (newBlockPos + newBlockSize >= kSpaceSize) + newBlockPos = newBlockSize = 0; + outBlockRef.Offset = newBlockPos; + outBlockRef.Size = newBlockSize; + + outGlobalData.Clear(); + UInt32 dataSize = GetFixedGlobalValue32(NGlobalOffset::kGlobalMemOutSize); + dataSize = MyMin(dataSize, kGlobalSize - kFixedGlobalSize); + if (dataSize != 0) + { + dataSize += kFixedGlobalSize; + outGlobalData.Reserve(dataSize); + for (UInt32 i = 0; i < dataSize; i++) + outGlobalData.Add(Mem[kGlobalOffset + i]); + } + return res; +} + + +#define SET_IP(IP) \ + if ((IP) >= numCommands) return true; \ + if (--maxOpCount <= 0) return false; \ + cmd = commands + (IP); + +#define GET_FLAG_S_B(res) (((res) & 0x80) ? FLAG_S : 0) +#define SET_IP_OP1 { UInt32 val = GetOperand32(&cmd->Op1); SET_IP(val); } +#define FLAGS_UPDATE_SZ Flags = res == 0 ? FLAG_Z : res & FLAG_S +#define FLAGS_UPDATE_SZ_B Flags = (res & 0xFF) == 0 ? FLAG_Z : GET_FLAG_S_B(res) + +UInt32 CVm::GetOperand32(const COperand *op) const +{ + switch(op->Type) + { + case OP_TYPE_REG: return R[op->Data]; + case OP_TYPE_REGMEM: return GetValue32(&Mem[(op->Base + R[op->Data]) & kSpaceMask]); + default: return op->Data; + } +} + +void CVm::SetOperand32(const COperand *op, UInt32 val) +{ + switch(op->Type) + { + case OP_TYPE_REG: R[op->Data] = val; return; + case OP_TYPE_REGMEM: SetValue32(&Mem[(op->Base + R[op->Data]) & kSpaceMask], val); return; + } +} + +Byte CVm::GetOperand8(const COperand *op) const +{ + switch(op->Type) + { + case OP_TYPE_REG: return (Byte)R[op->Data]; + case OP_TYPE_REGMEM: return Mem[(op->Base + R[op->Data]) & kSpaceMask];; + default: return (Byte)op->Data; + } +} + +void CVm::SetOperand8(const COperand *op, Byte val) +{ + switch(op->Type) + { + case OP_TYPE_REG: R[op->Data] = (R[op->Data] & 0xFFFFFF00) | val; return; + case OP_TYPE_REGMEM: Mem[(op->Base + R[op->Data]) & kSpaceMask] = val; return; + } +} + +UInt32 CVm::GetOperand(bool byteMode, const COperand *op) const +{ + if (byteMode) + return GetOperand8(op); + return GetOperand32(op); +} + +void CVm::SetOperand(bool byteMode, const COperand *op, UInt32 val) +{ + if (byteMode) + SetOperand8(op, (Byte)(val & 0xFF)); + else + SetOperand32(op, val); +} + +bool CVm::ExecuteCode(const CProgram *prg) +{ + Int32 maxOpCount = 25000000; + const CCommand *commands = &prg->Commands[0]; + const CCommand *cmd = commands; + UInt32 numCommands = prg->Commands.Size(); + for (;;) + { + switch(cmd->OpCode) + { + #ifndef RARVM_NO_VM + + case CMD_MOV: + SetOperand32(&cmd->Op1, GetOperand32(&cmd->Op2)); + break; + case CMD_MOVB: + SetOperand8(&cmd->Op1, GetOperand8(&cmd->Op2)); + break; + case CMD_CMP: + { + UInt32 v1 = GetOperand32(&cmd->Op1); + UInt32 res = v1 - GetOperand32(&cmd->Op2); + Flags = res == 0 ? FLAG_Z : (res > v1) | (res & FLAG_S); + } + break; + case CMD_CMPB: + { + Byte v1 = GetOperand8(&cmd->Op1); + Byte res = v1 - GetOperand8(&cmd->Op2); + res &= 0xFF; + Flags = res == 0 ? FLAG_Z : (res > v1) | GET_FLAG_S_B(res); + } + break; + case CMD_ADD: + { + UInt32 v1 = GetOperand32(&cmd->Op1); + UInt32 res = v1 + GetOperand32(&cmd->Op2); + SetOperand32(&cmd->Op1, res); + Flags = (res < v1) | (res == 0 ? FLAG_Z : (res & FLAG_S)); + } + break; + case CMD_ADDB: + { + Byte v1 = GetOperand8(&cmd->Op1); + Byte res = v1 + GetOperand8(&cmd->Op2); + res &= 0xFF; + SetOperand8(&cmd->Op1, (Byte)res); + Flags = (res < v1) | (res == 0 ? FLAG_Z : GET_FLAG_S_B(res)); + } + break; + case CMD_ADC: + { + UInt32 v1 = GetOperand(cmd->ByteMode, &cmd->Op1); + UInt32 FC = (Flags & FLAG_C); + UInt32 res = v1 + GetOperand(cmd->ByteMode, &cmd->Op2) + FC; + if (cmd->ByteMode) + res &= 0xFF; + SetOperand(cmd->ByteMode, &cmd->Op1, res); + Flags = (res < v1 || res == v1 && FC) | (res == 0 ? FLAG_Z : (res & FLAG_S)); + } + break; + case CMD_SUB: + { + UInt32 v1 = GetOperand32(&cmd->Op1); + UInt32 res = v1 - GetOperand32(&cmd->Op2); + SetOperand32(&cmd->Op1, res); + Flags = res == 0 ? FLAG_Z : (res > v1) | (res & FLAG_S); + } + break; + case CMD_SUBB: + { + UInt32 v1 = GetOperand8(&cmd->Op1); + UInt32 res = v1 - GetOperand8(&cmd->Op2); + SetOperand8(&cmd->Op1, (Byte)res); + Flags = res == 0 ? FLAG_Z : (res > v1) | (res & FLAG_S); + } + break; + case CMD_SBB: + { + UInt32 v1 = GetOperand(cmd->ByteMode, &cmd->Op1); + UInt32 FC = (Flags & FLAG_C); + UInt32 res = v1 - GetOperand(cmd->ByteMode, &cmd->Op2) - FC; + // Flags = res == 0 ? FLAG_Z : (res > v1 || res == v1 && FC) | (res & FLAG_S); + if (cmd->ByteMode) + res &= 0xFF; + SetOperand(cmd->ByteMode, &cmd->Op1, res); + Flags = (res > v1 || res == v1 && FC) | (res == 0 ? FLAG_Z : (res & FLAG_S)); + } + break; + case CMD_INC: + { + UInt32 res = GetOperand32(&cmd->Op1) + 1; + SetOperand32(&cmd->Op1, res); + FLAGS_UPDATE_SZ; + } + break; + case CMD_INCB: + { + Byte res = GetOperand8(&cmd->Op1) + 1; + SetOperand8(&cmd->Op1, res);; + FLAGS_UPDATE_SZ_B; + } + break; + case CMD_DEC: + { + UInt32 res = GetOperand32(&cmd->Op1) - 1; + SetOperand32(&cmd->Op1, res); + FLAGS_UPDATE_SZ; + } + break; + case CMD_DECB: + { + Byte res = GetOperand8(&cmd->Op1) - 1; + SetOperand8(&cmd->Op1, res);; + FLAGS_UPDATE_SZ_B; + } + break; + case CMD_XOR: + { + UInt32 res = GetOperand32(&cmd->Op1) ^ GetOperand32(&cmd->Op2); + SetOperand32(&cmd->Op1, res); + FLAGS_UPDATE_SZ; + } + break; + case CMD_XORB: + { + Byte res = GetOperand8(&cmd->Op1) ^ GetOperand8(&cmd->Op2); + SetOperand8(&cmd->Op1, res); + FLAGS_UPDATE_SZ_B; + } + break; + case CMD_AND: + { + UInt32 res = GetOperand32(&cmd->Op1) & GetOperand32(&cmd->Op2); + SetOperand32(&cmd->Op1, res); + FLAGS_UPDATE_SZ; + } + break; + case CMD_ANDB: + { + Byte res = GetOperand8(&cmd->Op1) & GetOperand8(&cmd->Op2); + SetOperand8(&cmd->Op1, res); + FLAGS_UPDATE_SZ_B; + } + break; + case CMD_OR: + { + UInt32 res = GetOperand32(&cmd->Op1) | GetOperand32(&cmd->Op2); + SetOperand32(&cmd->Op1, res); + FLAGS_UPDATE_SZ; + } + break; + case CMD_ORB: + { + Byte res = GetOperand8(&cmd->Op1) | GetOperand8(&cmd->Op2); + SetOperand8(&cmd->Op1, res); + FLAGS_UPDATE_SZ_B; + } + break; + case CMD_TEST: + { + UInt32 res = GetOperand32(&cmd->Op1) & GetOperand32(&cmd->Op2); + FLAGS_UPDATE_SZ; + } + break; + case CMD_TESTB: + { + Byte res = GetOperand8(&cmd->Op1) & GetOperand8(&cmd->Op2); + FLAGS_UPDATE_SZ_B; + } + break; + case CMD_NOT: + SetOperand(cmd->ByteMode, &cmd->Op1, ~GetOperand(cmd->ByteMode, &cmd->Op1)); + break; + case CMD_NEG: + { + UInt32 res = 0 - GetOperand32(&cmd->Op1); + SetOperand32(&cmd->Op1, res); + Flags = res == 0 ? FLAG_Z : FLAG_C | (res & FLAG_S); + } + break; + case CMD_NEGB: + { + Byte res = (Byte)(0 - GetOperand8(&cmd->Op1)); + SetOperand8(&cmd->Op1, res); + Flags = res == 0 ? FLAG_Z : FLAG_C | GET_FLAG_S_B(res); + } + break; + + case CMD_SHL: + { + UInt32 v1 = GetOperand32(&cmd->Op1); + int v2 = (int)GetOperand32(&cmd->Op2); + UInt32 res = v1 << v2; + SetOperand32(&cmd->Op1, res); + Flags = (res == 0 ? FLAG_Z : (res & FLAG_S)) | ((v1 << (v2 - 1)) & 0x80000000 ? FLAG_C : 0); + } + break; + case CMD_SHLB: + { + Byte v1 = GetOperand8(&cmd->Op1); + int v2 = (int)GetOperand8(&cmd->Op2); + Byte res = (Byte)(v1 << v2); + SetOperand8(&cmd->Op1, res); + Flags = (res == 0 ? FLAG_Z : GET_FLAG_S_B(res)) | ((v1 << (v2 - 1)) & 0x80 ? FLAG_C : 0); + } + break; + case CMD_SHR: + { + UInt32 v1 = GetOperand32(&cmd->Op1); + int v2 = (int)GetOperand32(&cmd->Op2); + UInt32 res = v1 >> v2; + SetOperand32(&cmd->Op1, res); + Flags = (res == 0 ? FLAG_Z : (res & FLAG_S)) | ((v1 >> (v2 - 1)) & FLAG_C); + } + break; + case CMD_SHRB: + { + Byte v1 = GetOperand8(&cmd->Op1); + int v2 = (int)GetOperand8(&cmd->Op2); + Byte res = (Byte)(v1 >> v2); + SetOperand8(&cmd->Op1, res); + Flags = (res == 0 ? FLAG_Z : GET_FLAG_S_B(res)) | ((v1 >> (v2 - 1)) & FLAG_C); + } + break; + case CMD_SAR: + { + UInt32 v1 = GetOperand32(&cmd->Op1); + int v2 = (int)GetOperand32(&cmd->Op2); + UInt32 res = UInt32(((Int32)v1) >> v2); + SetOperand32(&cmd->Op1, res); + Flags= (res == 0 ? FLAG_Z : (res & FLAG_S)) | ((v1 >> (v2 - 1)) & FLAG_C); + } + break; + case CMD_SARB: + { + Byte v1 = GetOperand8(&cmd->Op1); + int v2 = (int)GetOperand8(&cmd->Op2); + Byte res = (Byte)(((signed char)v1) >> v2); + SetOperand8(&cmd->Op1, res); + Flags= (res == 0 ? FLAG_Z : GET_FLAG_S_B(res)) | ((v1 >> (v2 - 1)) & FLAG_C); + } + break; + + case CMD_JMP: + SET_IP_OP1; + continue; + case CMD_JZ: + if ((Flags & FLAG_Z) != 0) + { + SET_IP_OP1; + continue; + } + break; + case CMD_JNZ: + if ((Flags & FLAG_Z) == 0) + { + SET_IP_OP1; + continue; + } + break; + case CMD_JS: + if ((Flags & FLAG_S) != 0) + { + SET_IP_OP1; + continue; + } + break; + case CMD_JNS: + if ((Flags & FLAG_S) == 0) + { + SET_IP_OP1; + continue; + } + break; + case CMD_JB: + if ((Flags & FLAG_C) != 0) + { + SET_IP_OP1; + continue; + } + break; + case CMD_JBE: + if ((Flags & (FLAG_C | FLAG_Z)) != 0) + { + SET_IP_OP1; + continue; + } + break; + case CMD_JA: + if ((Flags & (FLAG_C | FLAG_Z)) == 0) + { + SET_IP_OP1; + continue; + } + break; + case CMD_JAE: + if ((Flags & FLAG_C) == 0) + { + SET_IP_OP1; + continue; + } + break; + + case CMD_PUSH: + R[kStackRegIndex] -= 4; + SetValue32(&Mem[R[kStackRegIndex] & kSpaceMask], GetOperand32(&cmd->Op1)); + break; + case CMD_POP: + SetOperand32(&cmd->Op1, GetValue32(&Mem[R[kStackRegIndex] & kSpaceMask])); + R[kStackRegIndex] += 4; + break; + case CMD_CALL: + R[kStackRegIndex] -= 4; + SetValue32(&Mem[R[kStackRegIndex] & kSpaceMask], (UInt32)(cmd - commands + 1)); + SET_IP_OP1; + continue; + + case CMD_PUSHA: + { + for (UInt32 i = 0, SP = R[kStackRegIndex] - 4; i < kNumRegs; i++, SP -= 4) + SetValue32(&Mem[SP & kSpaceMask], R[i]); + R[kStackRegIndex] -= kNumRegs * 4; + } + break; + case CMD_POPA: + { + for (UInt32 i = 0, SP = R[kStackRegIndex]; i < kNumRegs; i++, SP += 4) + R[kStackRegIndex - i] = GetValue32(&Mem[SP & kSpaceMask]); + } + break; + case CMD_PUSHF: + R[kStackRegIndex] -= 4; + SetValue32(&Mem[R[kStackRegIndex]&kSpaceMask], Flags); + break; + case CMD_POPF: + Flags = GetValue32(&Mem[R[kStackRegIndex] & kSpaceMask]); + R[kStackRegIndex] += 4; + break; + + case CMD_MOVZX: + SetOperand32(&cmd->Op1, GetOperand8(&cmd->Op2)); + break; + case CMD_MOVSX: + SetOperand32(&cmd->Op1, (UInt32)(Int32)(signed char)GetOperand8(&cmd->Op2)); + break; + case CMD_XCHG: + { + UInt32 v1 = GetOperand(cmd->ByteMode, &cmd->Op1); + SetOperand(cmd->ByteMode, &cmd->Op1, GetOperand(cmd->ByteMode, &cmd->Op2)); + SetOperand(cmd->ByteMode, &cmd->Op2, v1); + } + break; + case CMD_MUL: + { + UInt32 res = GetOperand32(&cmd->Op1) * GetOperand32(&cmd->Op2); + SetOperand32(&cmd->Op1, res); + } + break; + case CMD_MULB: + { + Byte res = GetOperand8(&cmd->Op1) * GetOperand8(&cmd->Op2); + SetOperand8(&cmd->Op1, res); + } + break; + case CMD_DIV: + { + UInt32 divider = GetOperand(cmd->ByteMode, &cmd->Op2); + if (divider != 0) + { + UInt32 res = GetOperand(cmd->ByteMode, &cmd->Op1) / divider; + SetOperand(cmd->ByteMode, &cmd->Op1, res); + } + } + break; + + #endif + + case CMD_RET: + { + if (R[kStackRegIndex] >= kSpaceSize) + return true; + UInt32 ip = GetValue32(&Mem[R[kStackRegIndex] & kSpaceMask]); + SET_IP(ip); + R[kStackRegIndex] += 4; + continue; + } + case CMD_PRINT: + break; + } + cmd++; + --maxOpCount; + } +} + + +////////////////////////////////////////////////////// +// Read program + +UInt32 ReadEncodedUInt32(CMemBitDecoder &inp) +{ + switch(inp.ReadBits(2)) + { + case 0: + return inp.ReadBits(4); + case 1: + { + UInt32 v = inp.ReadBits(4); + if (v == 0) + return 0xFFFFFF00 | inp.ReadBits(8); + else + return (v << 4) | inp.ReadBits(4); + } + case 2: + return inp.ReadBits(16); + default: + return inp.ReadBits(32); + } +} + +void CVm::DecodeArg(CMemBitDecoder &inp, COperand &op, bool byteMode) +{ + if (inp.ReadBit()) + { + op.Type = OP_TYPE_REG; + op.Data = inp.ReadBits(kNumRegBits); + } + else if (inp.ReadBit() == 0) + { + op.Type = OP_TYPE_INT; + if (byteMode) + op.Data = inp.ReadBits(8); + else + op.Data = ReadEncodedUInt32(inp); + } + else + { + op.Type = OP_TYPE_REGMEM; + if (inp.ReadBit() == 0) + { + op.Data = inp.ReadBits(kNumRegBits); + op.Base = 0; + } + else + { + if (inp.ReadBit() == 0) + op.Data = inp.ReadBits(kNumRegBits); + else + op.Data = kNumRegs; + op.Base = ReadEncodedUInt32(inp); + } + } +} + +void CVm::ReadVmProgram(const Byte *code, UInt32 codeSize, CProgram *prg) +{ + CMemBitDecoder inp; + inp.Init(code, codeSize); + + prg->StaticData.Clear(); + if (inp.ReadBit()) + { + UInt32 dataSize = ReadEncodedUInt32(inp) + 1; + for (UInt32 i = 0; inp.Avail() && i < dataSize; i++) + prg->StaticData.Add((Byte)inp.ReadBits(8)); + } + while (inp.Avail()) + { + prg->Commands.Add(CCommand()); + CCommand *cmd = &prg->Commands.Back(); + if (inp.ReadBit() == 0) + cmd->OpCode = (ECommand)inp.ReadBits(3); + else + cmd->OpCode = (ECommand)(8 + inp.ReadBits(5)); + if (kCmdFlags[cmd->OpCode] & CF_BYTEMODE) + cmd->ByteMode = (inp.ReadBit()) ? true : false; + else + cmd->ByteMode = 0; + int opNum = (kCmdFlags[cmd->OpCode] & CF_OPMASK); + if (opNum > 0) + { + DecodeArg(inp, cmd->Op1, cmd->ByteMode); + if (opNum == 2) + DecodeArg(inp, cmd->Op2, cmd->ByteMode); + else + { + if (cmd->Op1.Type == OP_TYPE_INT && (kCmdFlags[cmd->OpCode] & (CF_JUMP | CF_PROC))) + { + int Distance = cmd->Op1.Data; + if (Distance >= 256) + Distance -= 256; + else + { + if (Distance >= 136) + Distance -= 264; + else if (Distance >= 16) + Distance -= 8; + else if (Distance >= 8) + Distance -= 16; + Distance += prg->Commands.Size() - 1; + } + cmd->Op1.Data = Distance; + } + } + } + if (cmd->ByteMode) + { + switch (cmd->OpCode) + { + case CMD_MOV: cmd->OpCode = CMD_MOVB; break; + case CMD_CMP: cmd->OpCode = CMD_CMPB; break; + case CMD_ADD: cmd->OpCode = CMD_ADDB; break; + case CMD_SUB: cmd->OpCode = CMD_SUBB; break; + case CMD_INC: cmd->OpCode = CMD_INCB; break; + case CMD_DEC: cmd->OpCode = CMD_DECB; break; + case CMD_XOR: cmd->OpCode = CMD_XORB; break; + case CMD_AND: cmd->OpCode = CMD_ANDB; break; + case CMD_OR: cmd->OpCode = CMD_ORB; break; + case CMD_TEST: cmd->OpCode = CMD_TESTB; break; + case CMD_NEG: cmd->OpCode = CMD_NEGB; break; + case CMD_SHL: cmd->OpCode = CMD_SHLB; break; + case CMD_SHR: cmd->OpCode = CMD_SHRB; break; + case CMD_SAR: cmd->OpCode = CMD_SARB; break; + case CMD_MUL: cmd->OpCode = CMD_MULB; break; + } + } + } +} + +#ifdef RARVM_STANDARD_FILTERS + +enum EStandardFilter +{ + SF_E8, + SF_E8E9, + SF_ITANIUM, + SF_RGB, + SF_AUDIO, + SF_DELTA, + SF_UPCASE +}; + +struct StandardFilterSignature +{ + UInt32 Length; + UInt32 CRC; + EStandardFilter Type; +} +kStdFilters[]= +{ + { 53, 0xad576887, SF_E8 }, + { 57, 0x3cd7e57e, SF_E8E9 }, + { 120, 0x3769893f, SF_ITANIUM }, + { 29, 0x0e06077d, SF_DELTA }, + { 149, 0x1c2c5dc8, SF_RGB }, + { 216, 0xbc85e701, SF_AUDIO }, + { 40, 0x46b9c560, SF_UPCASE } +}; + +static int FindStandardFilter(const Byte *code, UInt32 codeSize) +{ + UInt32 crc = CrcCalc(code, codeSize); + for (int i = 0; i < sizeof(kStdFilters) / sizeof(kStdFilters[0]); i++) + { + StandardFilterSignature &sfs = kStdFilters[i]; + if (sfs.CRC == crc && sfs.Length == codeSize) + return i; + } + return -1; +} + +#endif + +void CVm::PrepareProgram(const Byte *code, UInt32 codeSize, CProgram *prg) +{ + Byte xorSum = 0; + for (UInt32 i = 1; i < codeSize; i++) + xorSum ^= code[i]; + + prg->Commands.Clear(); + #ifdef RARVM_STANDARD_FILTERS + prg->StandardFilterIndex = -1; + #endif + + if (xorSum == code[0] && codeSize > 0) + { + #ifdef RARVM_STANDARD_FILTERS + prg->StandardFilterIndex = FindStandardFilter(code, codeSize); + if (prg->StandardFilterIndex >= 0) + return; + #endif + // 1 byte for checksum + ReadVmProgram(code + 1, codeSize - 1, prg); + } + prg->Commands.Add(CCommand()); + CCommand *cmd = &prg->Commands.Back(); + cmd->OpCode = CMD_RET; +} + +void CVm::SetMemory(UInt32 pos, const Byte *data, UInt32 dataSize) +{ + if (pos < kSpaceSize && data != Mem + pos) + memmove(Mem + pos, data, MyMin(dataSize, kSpaceSize - pos)); +} + +#ifdef RARVM_STANDARD_FILTERS + +static void E8E9Decode(Byte *data, UInt32 dataSize, UInt32 fileOffset, bool e9) +{ + if (dataSize <= 4) + return; + dataSize -= 4; + const UInt32 kFileSize = 0x1000000; + Byte cmpByte2 = (e9 ? 0xE9 : 0xE8); + for (UInt32 curPos = 0; curPos < dataSize;) + { + Byte curByte = *(data++); + curPos++; + if (curByte == 0xE8 || curByte == cmpByte2) + { + UInt32 offset = curPos + fileOffset; + UInt32 addr = (Int32)GetValue32(data); + if (addr < kFileSize) + SetValue32(data, addr - offset); + else if ((Int32)addr < 0 && (Int32)(addr + offset) >= 0) + SetValue32(data, addr + kFileSize); + data += 4; + curPos += 4; + } + } +} + +static inline UInt32 ItaniumGetOpType(const Byte *data, int bitPos) +{ + return (data[(unsigned int)bitPos >> 3] >> (bitPos & 7)) & 0xF; +} + + +static void ItaniumDecode(Byte *data, UInt32 dataSize, UInt32 fileOffset) +{ + UInt32 curPos = 0; + fileOffset >>= 4; + while (curPos < dataSize - 21) + { + int b = (data[0] & 0x1F) - 0x10; + if (b >= 0) + { + static Byte kCmdMasks[16] = {4,4,6,6,0,0,7,7,4,4,0,0,4,4,0,0}; + Byte cmdMask = kCmdMasks[b]; + if (cmdMask != 0) + for (int i = 0; i < 3; i++) + if (cmdMask & (1 << i)) + { + int startPos = i * 41 + 18; + if (ItaniumGetOpType(data, startPos + 24) == 5) + { + const UInt32 kMask = 0xFFFFF; + Byte *p = data + ((unsigned int)startPos >> 3); + UInt32 bitField = ((UInt32)p[0]) | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16); + int inBit = (startPos & 7); + UInt32 offset = (bitField >> inBit) & kMask; + UInt32 andMask = ~(kMask << inBit); + bitField = ((offset - fileOffset) & kMask) << inBit; + for (int j = 0; j < 3; j++) + { + p[j] &= andMask; + p[j] |= bitField; + andMask >>= 8; + bitField >>= 8; + } + } + } + } + data += 16; + curPos += 16; + fileOffset++; + } +} + +static void DeltaDecode(Byte *data, UInt32 dataSize, UInt32 numChannels) +{ + UInt32 srcPos = 0; + UInt32 border = dataSize * 2; + for (UInt32 curChannel = 0; curChannel < numChannels; curChannel++) + { + Byte prevByte = 0; + for (UInt32 destPos = dataSize + curChannel; destPos < border; destPos += numChannels) + data[destPos] = (prevByte = prevByte - data[srcPos++]); + } +} + +static void RgbDecode(Byte *srcData, UInt32 dataSize, UInt32 width, UInt32 posR) +{ + Byte *destData = srcData + dataSize; + const UInt32 numChannels = 3; + for (UInt32 curChannel = 0; curChannel < numChannels; curChannel++) + { + Byte prevByte = 0; + + for (UInt32 i = curChannel; i < dataSize; i+= numChannels) + { + unsigned int predicted; + if (i < width) + predicted = prevByte; + else + { + unsigned int upperLeftByte = destData[i - width]; + unsigned int upperByte = destData[i - width + 3]; + predicted = prevByte + upperByte - upperLeftByte; + int pa = abs((int)(predicted - prevByte)); + int pb = abs((int)(predicted - upperByte)); + int pc = abs((int)(predicted - upperLeftByte)); + if (pa <= pb && pa <= pc) + predicted = prevByte; + else + if (pb <= pc) + predicted = upperByte; + else + predicted = upperLeftByte; + } + destData[i] = prevByte = (Byte)(predicted - *(srcData++)); + } + } + if (dataSize < 3) + return; + for (UInt32 i = posR, border = dataSize - 2; i < border; i += 3) + { + Byte g = destData[i + 1]; + destData[i] = destData[i] + g; + destData[i + 2] = destData[i + 2] + g; + } +} + +static void AudioDecode(Byte *srcData, UInt32 dataSize, UInt32 numChannels) +{ + Byte *destData = srcData + dataSize; + for (UInt32 curChannel = 0; curChannel < numChannels; curChannel++) + { + UInt32 prevByte = 0, prevDelta = 0, dif[7]; + Int32 D1 = 0, D2 = 0, D3; + Int32 K1 = 0, K2 = 0, K3 = 0; + memset(dif, 0, sizeof(dif)); + + for (UInt32 i = curChannel, byteCount = 0; i < dataSize; i += numChannels, byteCount++) + { + D3 = D2; + D2 = prevDelta - D1; + D1 = prevDelta; + + UInt32 predicted = 8 * prevByte + K1 * D1 + K2 * D2 + K3 * D3; + predicted = (predicted >> 3) & 0xFF; + + UInt32 curByte = *(srcData++); + + predicted -= curByte; + destData[i] = (Byte)predicted; + prevDelta = (UInt32)(Int32)(signed char)(predicted - prevByte); + prevByte = predicted; + + Int32 D = ((Int32)(signed char)curByte) << 3; + + dif[0] += abs(D); + dif[1] += abs(D - D1); + dif[2] += abs(D + D1); + dif[3] += abs(D - D2); + dif[4] += abs(D + D2); + dif[5] += abs(D - D3); + dif[6] += abs(D + D3); + + if ((byteCount & 0x1F) == 0) + { + UInt32 minDif = dif[0], numMinDif = 0; + dif[0] = 0; + for (int j = 1; j < sizeof(dif) / sizeof(dif[0]); j++) + { + if (dif[j] < minDif) + { + minDif = dif[j]; + numMinDif = j; + } + dif[j] = 0; + } + switch (numMinDif) + { + case 1: if (K1 >= -16) K1--; break; + case 2: if (K1 < 16) K1++; break; + case 3: if (K2 >= -16) K2--; break; + case 4: if (K2 < 16) K2++; break; + case 5: if (K3 >= -16) K3--; break; + case 6: if (K3 < 16) K3++; break; + } + } + } + } +} + +static UInt32 UpCaseDecode(Byte *data, UInt32 dataSize) +{ + UInt32 srcPos = 0, destPos = dataSize; + while (srcPos < dataSize) + { + Byte curByte = data[srcPos++]; + if (curByte == 2 && (curByte = data[srcPos++]) != 2) + curByte -= 32; + data[destPos++] = curByte; + } + return destPos - dataSize; +} + +void CVm::ExecuteStandardFilter(int filterIndex) +{ + UInt32 dataSize = R[4]; + if (dataSize >= kGlobalOffset) + return; + EStandardFilter filterType = kStdFilters[filterIndex].Type; + + switch (filterType) + { + case SF_E8: + case SF_E8E9: + E8E9Decode(Mem, dataSize, R[6], (filterType == SF_E8E9)); + break; + case SF_ITANIUM: + ItaniumDecode(Mem, dataSize, R[6]); + break; + case SF_DELTA: + if (dataSize >= kGlobalOffset / 2) + break; + SetBlockPos(dataSize); + DeltaDecode(Mem, dataSize, R[0]); + break; + case SF_RGB: + if (dataSize >= kGlobalOffset / 2) + break; + { + UInt32 width = R[0]; + if (width <= 3) + break; + SetBlockPos(dataSize); + RgbDecode(Mem, dataSize, width, R[1]); + } + break; + case SF_AUDIO: + if (dataSize >= kGlobalOffset / 2) + break; + SetBlockPos(dataSize); + AudioDecode(Mem, dataSize, R[0]); + break; + case SF_UPCASE: + if (dataSize >= kGlobalOffset / 2) + break; + UInt32 destSize = UpCaseDecode(Mem, dataSize); + SetBlockSize(destSize); + SetBlockPos(dataSize); + break; + } +} + +#endif + +}}} diff --git a/CPP/7zip/Compress/Rar3Vm.h b/CPP/7zip/Compress/Rar3Vm.h new file mode 100755 index 0000000..0d16e42 --- /dev/null +++ b/CPP/7zip/Compress/Rar3Vm.h @@ -0,0 +1,179 @@ +// Rar3Vm.h +// According to unRAR license, this code may not be used to develop +// a program that creates RAR archives + +#ifndef __COMPRESS_RAR3_VM_H +#define __COMPRESS_RAR3_VM_H + +#include "../../../C/CpuArch.h" + +#include "Common/MyVector.h" +#include "Common/Types.h" + +#define RARVM_STANDARD_FILTERS + +namespace NCompress { +namespace NRar3 { + +class CMemBitDecoder +{ + const Byte *_data; + UInt32 _bitSize; + UInt32 _bitPos; +public: + void Init(const Byte *data, UInt32 byteSize) + { + _data = data; + _bitSize = (byteSize << 3); + _bitPos = 0; + } + UInt32 ReadBits(int numBits); + UInt32 ReadBit(); + bool Avail() const { return (_bitPos < _bitSize); } +}; + +namespace NVm { + +inline UInt32 GetValue32(const void *addr) { return GetUi32(addr); } +inline void SetValue32(void *addr, UInt32 value) { SetUi32(addr, value); } + +UInt32 ReadEncodedUInt32(CMemBitDecoder &inp); + +const int kNumRegBits = 3; +const UInt32 kNumRegs = 1 << kNumRegBits; +const UInt32 kNumGpRegs = kNumRegs - 1; + +const UInt32 kSpaceSize = 0x40000; +const UInt32 kSpaceMask = kSpaceSize -1; +const UInt32 kGlobalOffset = 0x3C000; +const UInt32 kGlobalSize = 0x2000; +const UInt32 kFixedGlobalSize = 64; + +namespace NGlobalOffset +{ + const UInt32 kBlockSize = 0x1C; + const UInt32 kBlockPos = 0x20; + const UInt32 kExecCount = 0x2C; + const UInt32 kGlobalMemOutSize = 0x30; +} + +enum ECommand +{ + CMD_MOV, CMD_CMP, CMD_ADD, CMD_SUB, CMD_JZ, CMD_JNZ, CMD_INC, CMD_DEC, + CMD_JMP, CMD_XOR, CMD_AND, CMD_OR, CMD_TEST, CMD_JS, CMD_JNS, CMD_JB, + CMD_JBE, CMD_JA, CMD_JAE, CMD_PUSH, CMD_POP, CMD_CALL, CMD_RET, CMD_NOT, + CMD_SHL, CMD_SHR, CMD_SAR, CMD_NEG, CMD_PUSHA,CMD_POPA, CMD_PUSHF,CMD_POPF, + CMD_MOVZX,CMD_MOVSX,CMD_XCHG, CMD_MUL, CMD_DIV, CMD_ADC, CMD_SBB, CMD_PRINT, + + CMD_MOVB, CMD_CMPB, CMD_ADDB, CMD_SUBB, CMD_INCB, CMD_DECB, + CMD_XORB, CMD_ANDB, CMD_ORB, CMD_TESTB,CMD_NEGB, + CMD_SHLB, CMD_SHRB, CMD_SARB, CMD_MULB +}; + +enum EOpType {OP_TYPE_REG, OP_TYPE_INT, OP_TYPE_REGMEM, OP_TYPE_NONE}; + +// Addr in COperand object can link (point) to CVm object!!! + +struct COperand +{ + EOpType Type; + UInt32 Data; + UInt32 Base; + COperand(): Type(OP_TYPE_NONE), Data(0), Base(0) {} +}; + +struct CCommand +{ + ECommand OpCode; + bool ByteMode; + COperand Op1, Op2; +}; + +struct CBlockRef +{ + UInt32 Offset; + UInt32 Size; +}; + +struct CProgram +{ + CRecordVector Commands; + #ifdef RARVM_STANDARD_FILTERS + int StandardFilterIndex; + #endif + CRecordVector StaticData; +}; + +struct CProgramInitState +{ + UInt32 InitR[kNumGpRegs]; + CRecordVector GlobalData; + + void AllocateEmptyFixedGlobal() + { + GlobalData.Clear(); + GlobalData.Reserve(NVm::kFixedGlobalSize); + for (UInt32 i = 0; i < NVm::kFixedGlobalSize; i++) + GlobalData.Add(0); + } +}; + +class CVm +{ + static UInt32 GetValue(bool byteMode, const void *addr) + { + if (byteMode) + return(*(const Byte *)addr); + else + return GetUi32(addr); + } + + static void SetValue(bool byteMode, void *addr, UInt32 value) + { + if (byteMode) + *(Byte *)addr = (Byte)value; + else + SetUi32(addr, value); + } + + UInt32 GetFixedGlobalValue32(UInt32 globalOffset) { return GetValue(false, &Mem[kGlobalOffset + globalOffset]); } + + void SetBlockSize(UInt32 v) { SetValue(&Mem[kGlobalOffset + NGlobalOffset::kBlockSize], v); } + void SetBlockPos(UInt32 v) { SetValue(&Mem[kGlobalOffset + NGlobalOffset::kBlockPos], v); } +public: + static void SetValue(void *addr, UInt32 value) { SetValue(false, addr, value); } +private: + UInt32 GetOperand32(const COperand *op) const; + void SetOperand32(const COperand *op, UInt32 val); + Byte GetOperand8(const COperand *op) const; + void SetOperand8(const COperand *op, Byte val); + UInt32 GetOperand(bool byteMode, const COperand *op) const; + void SetOperand(bool byteMode, const COperand *op, UInt32 val); + + void DecodeArg(CMemBitDecoder &inp, COperand &op, bool byteMode); + + bool ExecuteCode(const CProgram *prg); + + #ifdef RARVM_STANDARD_FILTERS + void ExecuteStandardFilter(int filterIndex); + #endif + + Byte *Mem; + UInt32 R[kNumRegs + 1]; // R[kNumRegs] = 0 always (speed optimization) + UInt32 Flags; + void ReadVmProgram(const Byte *code, UInt32 codeSize, CProgram *prg); +public: + CVm(); + ~CVm(); + bool Create(); + void PrepareProgram(const Byte *code, UInt32 codeSize, CProgram *prg); + void SetMemory(UInt32 pos, const Byte *data, UInt32 dataSize); + bool Execute(CProgram *prg, const CProgramInitState *initState, + CBlockRef &outBlockRef, CRecordVector &outGlobalData); + const Byte *GetDataPointer(UInt32 offset) const { return Mem + offset; } + +}; + +#endif + +}}} diff --git a/CPP/7zip/Compress/RarCodecsRegister.cpp b/CPP/7zip/Compress/RarCodecsRegister.cpp new file mode 100755 index 0000000..cb6242b --- /dev/null +++ b/CPP/7zip/Compress/RarCodecsRegister.cpp @@ -0,0 +1,26 @@ +// RarCodecsRegister.cpp + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" + +#include "Rar1Decoder.h" +#include "Rar2Decoder.h" +#include "Rar3Decoder.h" + +#define CREATE_CODEC(x) static void *CreateCodec ## x() { return (void *)(ICompressCoder *)(new NCompress::NRar ## x::CDecoder); } + +CREATE_CODEC(1) +CREATE_CODEC(2) +CREATE_CODEC(3) + +#define RAR_CODEC(x, name) { CreateCodec ## x, 0, 0x040300 + x, L"Rar" name, 1, false } + +static CCodecInfo g_CodecsInfo[] = +{ + RAR_CODEC(1, L"1"), + RAR_CODEC(2, L"2"), + RAR_CODEC(3, L"3"), +}; + +REGISTER_CODECS(Rar) diff --git a/CPP/7zip/Compress/ShrinkDecoder.cpp b/CPP/7zip/Compress/ShrinkDecoder.cpp new file mode 100755 index 0000000..d4e06fe --- /dev/null +++ b/CPP/7zip/Compress/ShrinkDecoder.cpp @@ -0,0 +1,145 @@ +// ShrinkDecoder.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "../Common/InBuffer.h" +#include "../Common/OutBuffer.h" + +#include "BitlDecoder.h" +#include "ShrinkDecoder.h" + +namespace NCompress { +namespace NShrink { + +static const UInt32 kBufferSize = (1 << 20); +static const int kNumMinBits = 9; + +HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) +{ + NBitl::CBaseDecoder inBuffer; + COutBuffer outBuffer; + + if (!inBuffer.Create(kBufferSize)) + return E_OUTOFMEMORY; + inBuffer.SetStream(inStream); + inBuffer.Init(); + + if (!outBuffer.Create(kBufferSize)) + return E_OUTOFMEMORY; + outBuffer.SetStream(outStream); + outBuffer.Init(); + + UInt64 prevPos = 0; + int numBits = kNumMinBits; + UInt32 head = 257; + bool needPrev = false; + UInt32 lastSymbol = 0; + + int i; + for (i = 0; i < kNumItems; i++) + _parents[i] = 0; + for (i = 0; i < kNumItems; i++) + _suffixes[i] = 0; + for (i = 0; i < 257; i++) + _isFree[i] = false; + for (; i < kNumItems; i++) + _isFree[i] = true; + + for (;;) + { + UInt32 symbol = inBuffer.ReadBits(numBits); + if (inBuffer.ExtraBitsWereRead()) + break; + if (_isFree[symbol]) + return S_FALSE; + if (symbol == 256) + { + UInt32 symbol = inBuffer.ReadBits(numBits); + if (symbol == 1) + { + if (numBits < kNumMaxBits) + numBits++; + } + else if (symbol == 2) + { + if (needPrev) + _isFree[head - 1] = true; + for (i = 257; i < kNumItems; i++) + _isParent[i] = false; + for (i = 257; i < kNumItems; i++) + if (!_isFree[i]) + _isParent[_parents[i]] = true; + for (i = 257; i < kNumItems; i++) + if (!_isParent[i]) + _isFree[i] = true; + head = 257; + while (head < kNumItems && !_isFree[head]) + head++; + if (head < kNumItems) + { + needPrev = true; + _isFree[head] = false; + _parents[head] = (UInt16)lastSymbol; + head++; + } + } + else + return S_FALSE; + continue; + } + UInt32 cur = symbol; + i = 0; + int corectionIndex = -1; + while (cur >= 256) + { + if (cur == head - 1) + corectionIndex = i; + _stack[i++] = _suffixes[cur]; + cur = _parents[cur]; + } + _stack[i++] = (Byte)cur; + if (needPrev) + { + _suffixes[head - 1] = (Byte)cur; + if (corectionIndex >= 0) + _stack[corectionIndex] = (Byte)cur; + } + while (i > 0) + outBuffer.WriteByte((_stack[--i])); + while (head < kNumItems && !_isFree[head]) + head++; + if (head < kNumItems) + { + needPrev = true; + _isFree[head] = false; + _parents[head] = (UInt16)symbol; + head++; + } + else + needPrev = false; + lastSymbol = symbol; + + UInt64 nowPos = outBuffer.GetProcessedSize(); + if (progress != NULL && nowPos - prevPos > (1 << 18)) + { + prevPos = nowPos; + UInt64 packSize = inBuffer.GetProcessedSize(); + RINOK(progress->SetRatioInfo(&packSize, &nowPos)); + } + } + return outBuffer.Flush(); +} + +STDMETHODIMP CDecoder ::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + try { return CodeReal(inStream, outStream, inSize, outSize, progress); } + catch(const CInBufferException &e) { return e.ErrorCode; } + catch(const COutBufferException &e) { return e.ErrorCode; } + catch(...) { return S_FALSE; } +} + +}} diff --git a/CPP/7zip/Compress/ShrinkDecoder.h b/CPP/7zip/Compress/ShrinkDecoder.h new file mode 100755 index 0000000..00f4164 --- /dev/null +++ b/CPP/7zip/Compress/ShrinkDecoder.h @@ -0,0 +1,38 @@ +// ShrinkDecoder.h + +#ifndef __COMPRESS_SHRINK_DECODER_H +#define __COMPRESS_SHRINK_DECODER_H + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +namespace NCompress { +namespace NShrink { + +const int kNumMaxBits = 13; +const UInt32 kNumItems = 1 << kNumMaxBits; + +class CDecoder : + public ICompressCoder, + public CMyUnknownImp +{ + UInt16 _parents[kNumItems]; + Byte _suffixes[kNumItems]; + Byte _stack[kNumItems]; + bool _isFree[kNumItems]; + bool _isParent[kNumItems]; + +public: + MY_UNKNOWN_IMP + + HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/StdAfx.h b/CPP/7zip/Compress/StdAfx.h new file mode 100755 index 0000000..c28ffce --- /dev/null +++ b/CPP/7zip/Compress/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../Common/MyWindows.h" + +#endif diff --git a/CPP/7zip/Compress/ZDecoder.cpp b/CPP/7zip/Compress/ZDecoder.cpp new file mode 100755 index 0000000..55c20df --- /dev/null +++ b/CPP/7zip/Compress/ZDecoder.cpp @@ -0,0 +1,159 @@ +// ZDecoder.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "../Common/InBuffer.h" +#include "../Common/OutBuffer.h" + +#include "ZDecoder.h" + +namespace NCompress { +namespace NZ { + +static const UInt32 kBufferSize = (1 << 20); +static const Byte kNumBitsMask = 0x1F; +static const Byte kBlockModeMask = 0x80; +static const int kNumMinBits = 9; +static const int kNumMaxBits = 16; + +void CDecoder::Free() +{ + MyFree(_parents); _parents = 0; + MyFree(_suffixes); _suffixes = 0; + MyFree(_stack); _stack = 0; +} + +CDecoder::~CDecoder() { Free(); } + +HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) +{ + CInBuffer inBuffer; + COutBuffer outBuffer; + + if (!inBuffer.Create(kBufferSize)) + return E_OUTOFMEMORY; + inBuffer.SetStream(inStream); + inBuffer.Init(); + + if (!outBuffer.Create(kBufferSize)) + return E_OUTOFMEMORY; + outBuffer.SetStream(outStream); + outBuffer.Init(); + + int maxbits = _properties & kNumBitsMask; + if (maxbits < kNumMinBits || maxbits > kNumMaxBits) + return S_FALSE; + UInt32 numItems = 1 << maxbits; + bool blockMode = ((_properties & kBlockModeMask) != 0); + + if (maxbits != _numMaxBits || _parents == 0 || _suffixes == 0 || _stack == 0) + { + Free(); + _parents = (UInt16 *)MyAlloc(numItems * sizeof(UInt16)); if (_parents == 0) return E_OUTOFMEMORY; + _suffixes = (Byte *)MyAlloc(numItems * sizeof(Byte)); if (_suffixes == 0) return E_OUTOFMEMORY; + _stack = (Byte *)MyAlloc(numItems * sizeof(Byte)); if (_stack == 0) return E_OUTOFMEMORY; + _numMaxBits = maxbits; + } + + UInt64 prevPos = 0; + int numBits = kNumMinBits; + UInt32 head = blockMode ? 257 : 256; + + bool needPrev = false; + + unsigned bitPos = 0; + unsigned numBufBits = 0; + + Byte buf[kNumMaxBits + 4]; + + _parents[256] = 0; // virus protection + _suffixes[256] = 0; + + for (;;) + { + if (numBufBits == bitPos) + { + numBufBits = (unsigned)inBuffer.ReadBytes(buf, numBits) * 8; + bitPos = 0; + UInt64 nowPos = outBuffer.GetProcessedSize(); + if (progress != NULL && nowPos - prevPos >= (1 << 18)) + { + prevPos = nowPos; + UInt64 packSize = inBuffer.GetProcessedSize(); + RINOK(progress->SetRatioInfo(&packSize, &nowPos)); + } + } + unsigned bytePos = bitPos >> 3; + UInt32 symbol = buf[bytePos] | ((UInt32)buf[bytePos + 1] << 8) | ((UInt32)buf[bytePos + 2] << 16); + symbol >>= (bitPos & 7); + symbol &= (1 << numBits) - 1; + bitPos += numBits; + if (bitPos > numBufBits) + break; + if (symbol >= head) + return S_FALSE; + if (blockMode && symbol == 256) + { + numBufBits = bitPos = 0; + numBits = kNumMinBits; + head = 257; + needPrev = false; + continue; + } + UInt32 cur = symbol; + int i = 0; + while (cur >= 256) + { + _stack[i++] = _suffixes[cur]; + cur = _parents[cur]; + } + _stack[i++] = (Byte)cur; + if (needPrev) + { + _suffixes[head - 1] = (Byte)cur; + if (symbol == head - 1) + _stack[0] = (Byte)cur; + } + do + outBuffer.WriteByte((_stack[--i])); + while (i > 0); + if (head < numItems) + { + needPrev = true; + _parents[head++] = (UInt16)symbol; + if (head > ((UInt32)1 << numBits)) + { + if (numBits < maxbits) + { + numBufBits = bitPos = 0; + numBits++; + } + } + } + else + needPrev = false; + } + return outBuffer.Flush(); +} + +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + try { return CodeReal(inStream, outStream, inSize, outSize, progress); } + catch(const CInBufferException &e) { return e.ErrorCode; } + catch(const COutBufferException &e) { return e.ErrorCode; } + catch(...) { return S_FALSE; } +} + +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) +{ + if (size < 1) + return E_INVALIDARG; + _properties = data[0]; + return S_OK; +} + +}} diff --git a/CPP/7zip/Compress/ZDecoder.h b/CPP/7zip/Compress/ZDecoder.h new file mode 100755 index 0000000..6a6ed06 --- /dev/null +++ b/CPP/7zip/Compress/ZDecoder.h @@ -0,0 +1,42 @@ +// ZDecoder.h + +#ifndef __COMPRESS_Z_DECODER_H +#define __COMPRESS_Z_DECODER_H + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +namespace NCompress { +namespace NZ { + +class CDecoder: + public ICompressCoder, + public ICompressSetDecoderProperties2, + public CMyUnknownImp +{ + UInt16 *_parents; + Byte *_suffixes; + Byte *_stack; + Byte _properties; + int _numMaxBits; + +public: + CDecoder(): _parents(0), _suffixes(0), _stack(0), _properties(0), _numMaxBits(0) {}; + ~CDecoder(); + void Free(); + + MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2) + + HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/ZlibDecoder.cpp b/CPP/7zip/Compress/ZlibDecoder.cpp new file mode 100755 index 0000000..9cdce21 --- /dev/null +++ b/CPP/7zip/Compress/ZlibDecoder.cpp @@ -0,0 +1,89 @@ +// ZlibDecoder.cpp + +#include "StdAfx.h" + +#include "../Common/StreamUtils.h" + +#include "ZlibDecoder.h" + +namespace NCompress { +namespace NZlib { + +#define DEFLATE_TRY_BEGIN try { +#define DEFLATE_TRY_END } catch(...) { return S_FALSE; } + +#define ADLER_MOD 65521 +#define ADLER_LOOP_MAX 5550 + +UInt32 Adler32_Update(UInt32 adler, const Byte *buf, size_t size) +{ + UInt32 a = adler & 0xFFFF; + UInt32 b = (adler >> 16) & 0xFFFF; + while (size > 0) + { + unsigned curSize = (size > ADLER_LOOP_MAX) ? ADLER_LOOP_MAX : (unsigned )size; + unsigned i; + for (i = 0; i < curSize; i++) + { + a += buf[i]; + b += a; + } + buf += curSize; + size -= curSize; + a %= ADLER_MOD; + b %= ADLER_MOD; + } + return (b << 16) + a; +} + +STDMETHODIMP COutStreamWithAdler::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + HRESULT result = _stream->Write(data, size, &size); + _adler = Adler32_Update(_adler, (const Byte *)data, size); + if (processedSize != NULL) + *processedSize = size; + return result; +} + +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + DEFLATE_TRY_BEGIN + if (!AdlerStream) + AdlerStream = AdlerSpec = new COutStreamWithAdler; + if (!DeflateDecoder) + { + DeflateDecoderSpec = new NDeflate::NDecoder::CCOMCoder; + DeflateDecoderSpec->ZlibMode = true; + DeflateDecoder = DeflateDecoderSpec; + } + + Byte buf[2]; + RINOK(ReadStream_FALSE(inStream, buf, 2)); + int method = buf[0] & 0xF; + if (method != 8) + return S_FALSE; + // int dicSize = buf[0] >> 4; + if ((((UInt32)buf[0] << 8) + buf[1]) % 31 != 0) + return S_FALSE; + if ((buf[1] & 0x20) != 0) // dictPresent + return S_FALSE; + // int level = (buf[1] >> 6); + + AdlerSpec->SetStream(outStream); + AdlerSpec->Init(); + HRESULT res = DeflateDecoder->Code(inStream, AdlerStream, inSize, outSize, progress); + AdlerSpec->ReleaseStream(); + + if (res == S_OK) + { + const Byte *p = DeflateDecoderSpec->ZlibFooter; + UInt32 adler = ((UInt32)p[0] << 24) | ((UInt32)p[1] << 16) | ((UInt32)p[2] << 8) | p[3]; + if (adler != AdlerSpec->GetAdler()) + return S_FALSE; + } + return res; + DEFLATE_TRY_END +} + +}} diff --git a/CPP/7zip/Compress/ZlibDecoder.h b/CPP/7zip/Compress/ZlibDecoder.h new file mode 100755 index 0000000..f6c7c0b --- /dev/null +++ b/CPP/7zip/Compress/ZlibDecoder.h @@ -0,0 +1,48 @@ +// ZlibDecoder.h + +#ifndef __ZLIB_DECODER_H +#define __ZLIB_DECODER_H + +#include "DeflateDecoder.h" + +namespace NCompress { +namespace NZlib { + +const UInt32 ADLER_INIT_VAL = 1; + +class COutStreamWithAdler: + public ISequentialOutStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + UInt32 _adler; +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() { _adler = ADLER_INIT_VAL; } + UInt32 GetAdler() const { return _adler; } +}; + +class CDecoder: + public ICompressCoder, + public CMyUnknownImp +{ + COutStreamWithAdler *AdlerSpec; + CMyComPtr AdlerStream; + + NCompress::NDeflate::NDecoder::CCOMCoder *DeflateDecoderSpec; + CMyComPtr DeflateDecoder; +public: + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + + UInt64 GetInputProcessedSize() const { return DeflateDecoderSpec->GetInputProcessedSize() + 2; } + + MY_UNKNOWN_IMP +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/ZlibEncoder.cpp b/CPP/7zip/Compress/ZlibEncoder.cpp new file mode 100755 index 0000000..e023b74 --- /dev/null +++ b/CPP/7zip/Compress/ZlibEncoder.cpp @@ -0,0 +1,61 @@ +// ZlibEncoder.cpp + +#include "StdAfx.h" + +#include "../Common/StreamUtils.h" + +#include "ZlibEncoder.h" + +namespace NCompress { +namespace NZlib { + +#define DEFLATE_TRY_BEGIN try { +#define DEFLATE_TRY_END } catch(...) { return S_FALSE; } + +UInt32 Adler32_Update(UInt32 adler, const Byte *buf, size_t size); + +STDMETHODIMP CInStreamWithAdler::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + HRESULT result = _stream->Read(data, size, &size); + _adler = Adler32_Update(_adler, (const Byte *)data, size); + _size += size; + if (processedSize != NULL) + *processedSize = size; + return result; +} + +void CEncoder::Create() +{ + if (!DeflateEncoder) + DeflateEncoder = DeflateEncoderSpec = new NDeflate::NEncoder::CCOMCoder; +} + +STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 * /* outSize */, ICompressProgressInfo *progress) +{ + DEFLATE_TRY_BEGIN + if (!AdlerStream) + AdlerStream = AdlerSpec = new CInStreamWithAdler; + Create(); + + { + Byte buf[2] = { 0x78, 0xDA }; + RINOK(WriteStream(outStream, buf, 2)); + } + + AdlerSpec->SetStream(inStream); + AdlerSpec->Init(); + HRESULT res = DeflateEncoder->Code(AdlerStream, outStream, inSize, NULL, progress); + AdlerSpec->ReleaseStream(); + + RINOK(res); + + { + UInt32 a = AdlerSpec->GetAdler(); + Byte buf[4] = { (Byte)(a >> 24), (Byte)(a >> 16), (Byte)(a >> 8), (Byte)(a) }; + return WriteStream(outStream, buf, 4); + } + DEFLATE_TRY_END +} + +}} diff --git a/CPP/7zip/Compress/ZlibEncoder.h b/CPP/7zip/Compress/ZlibEncoder.h new file mode 100755 index 0000000..3cac950 --- /dev/null +++ b/CPP/7zip/Compress/ZlibEncoder.h @@ -0,0 +1,48 @@ +// ZlibEncoder.h + +#ifndef __ZLIB_ENCODER_H +#define __ZLIB_ENCODER_H + +#include "DeflateEncoder.h" + +namespace NCompress { +namespace NZlib { + +class CInStreamWithAdler: + public ISequentialInStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + UInt32 _adler; + UInt64 _size; +public: + MY_UNKNOWN_IMP + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + void SetStream(ISequentialInStream *stream) { _stream = stream; } + void ReleaseStream() { _stream.Release(); } + void Init() { _adler = 1; _size = 0; } // ADLER_INIT_VAL + UInt32 GetAdler() const { return _adler; } + UInt64 GetSize() const { return _size; } +}; + +class CEncoder: + public ICompressCoder, + public CMyUnknownImp +{ + CInStreamWithAdler *AdlerSpec; + CMyComPtr AdlerStream; + CMyComPtr DeflateEncoder; +public: + NCompress::NDeflate::NEncoder::CCOMCoder *DeflateEncoderSpec; + + void Create(); + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + UInt64 GetInputProcessedSize() const { return AdlerSpec->GetSize(); } + + MY_UNKNOWN_IMP +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/makefile b/CPP/7zip/Compress/makefile new file mode 100755 index 0000000..9be1878 --- /dev/null +++ b/CPP/7zip/Compress/makefile @@ -0,0 +1,7 @@ +DIRS = \ + LZMA_Alone\~ \ + +all: $(DIRS) + +$(DIRS): +!include "../SubBuild.mak" diff --git a/CPP/7zip/Crc.mak b/CPP/7zip/Crc.mak new file mode 100755 index 0000000..444f8fe --- /dev/null +++ b/CPP/7zip/Crc.mak @@ -0,0 +1,8 @@ +C_OBJS = $(C_OBJS) \ + $O\7zCrc.obj +!IF "$(CPU)" == "IA64" || "$(CPU)" == "MIPS" +C_OBJS = $(C_OBJS) \ +!ELSE +ASM_OBJS = $(ASM_OBJS) \ +!ENDIF + $O\7zCrcOpt.obj diff --git a/CPP/7zip/Crypto/7zAes.cpp b/CPP/7zip/Crypto/7zAes.cpp new file mode 100755 index 0000000..aca5c29 --- /dev/null +++ b/CPP/7zip/Crypto/7zAes.cpp @@ -0,0 +1,244 @@ +// 7zAes.cpp + +#include "StdAfx.h" + +#include "../../../C/Sha256.h" + +#include "Windows/Synchronization.h" + +#include "../Common/StreamObjects.h" +#include "../Common/StreamUtils.h" + +#include "7zAes.h" +#include "MyAes.h" + +#ifndef EXTRACT_ONLY +#include "RandGen.h" +#endif + +using namespace NWindows; + +namespace NCrypto { +namespace NSevenZ { + +bool CKeyInfo::IsEqualTo(const CKeyInfo &a) const +{ + if (SaltSize != a.SaltSize || NumCyclesPower != a.NumCyclesPower) + return false; + for (UInt32 i = 0; i < SaltSize; i++) + if (Salt[i] != a.Salt[i]) + return false; + return (Password == a.Password); +} + +void CKeyInfo::CalculateDigest() +{ + if (NumCyclesPower == 0x3F) + { + UInt32 pos; + for (pos = 0; pos < SaltSize; pos++) + Key[pos] = Salt[pos]; + for (UInt32 i = 0; i < Password.GetCapacity() && pos < kKeySize; i++) + Key[pos++] = Password[i]; + for (; pos < kKeySize; pos++) + Key[pos] = 0; + } + else + { + CSha256 sha; + Sha256_Init(&sha); + const UInt64 numRounds = (UInt64)1 << NumCyclesPower; + Byte temp[8] = { 0,0,0,0,0,0,0,0 }; + for (UInt64 round = 0; round < numRounds; round++) + { + Sha256_Update(&sha, Salt, (size_t)SaltSize); + Sha256_Update(&sha, Password, Password.GetCapacity()); + Sha256_Update(&sha, temp, 8); + for (int i = 0; i < 8; i++) + if (++(temp[i]) != 0) + break; + } + Sha256_Final(&sha, Key); + } +} + +bool CKeyInfoCache::Find(CKeyInfo &key) +{ + for (int i = 0; i < Keys.Size(); i++) + { + const CKeyInfo &cached = Keys[i]; + if (key.IsEqualTo(cached)) + { + for (int j = 0; j < kKeySize; j++) + key.Key[j] = cached.Key[j]; + if (i != 0) + { + Keys.Insert(0, cached); + Keys.Delete(i+1); + } + return true; + } + } + return false; +} + +void CKeyInfoCache::Add(CKeyInfo &key) +{ + if (Find(key)) + return; + if (Keys.Size() >= Size) + Keys.DeleteBack(); + Keys.Insert(0, key); +} + +static CKeyInfoCache g_GlobalKeyCache(32); +static NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection; + +CBase::CBase(): + _cachedKeys(16), + _ivSize(0) +{ + for (int i = 0; i < sizeof(_iv); i++) + _iv[i] = 0; +} + +void CBase::CalculateDigest() +{ + NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection); + if (_cachedKeys.Find(_key)) + g_GlobalKeyCache.Add(_key); + else + { + if (!g_GlobalKeyCache.Find(_key)) + { + _key.CalculateDigest(); + g_GlobalKeyCache.Add(_key); + } + _cachedKeys.Add(_key); + } +} + +#ifndef EXTRACT_ONLY + +/* +STDMETHODIMP CEncoder::ResetSalt() +{ + _key.SaltSize = 4; + g_RandomGenerator.Generate(_key.Salt, _key.SaltSize); + return S_OK; +} +*/ + +STDMETHODIMP CEncoder::ResetInitVector() +{ + _ivSize = 8; + g_RandomGenerator.Generate(_iv, (unsigned)_ivSize); + return S_OK; +} + +STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) +{ + // _key.Init(); + for (UInt32 i = _ivSize; i < sizeof(_iv); i++) + _iv[i] = 0; + + UInt32 ivSize = _ivSize; + + // _key.NumCyclesPower = 0x3F; + _key.NumCyclesPower = 19; + + Byte firstByte = (Byte)(_key.NumCyclesPower | + (((_key.SaltSize == 0) ? 0 : 1) << 7) | + (((ivSize == 0) ? 0 : 1) << 6)); + RINOK(outStream->Write(&firstByte, 1, NULL)); + if (_key.SaltSize == 0 && ivSize == 0) + return S_OK; + Byte saltSizeSpec = (Byte)((_key.SaltSize == 0) ? 0 : (_key.SaltSize - 1)); + Byte ivSizeSpec = (Byte)((ivSize == 0) ? 0 : (ivSize - 1)); + Byte secondByte = (Byte)(((saltSizeSpec) << 4) | ivSizeSpec); + RINOK(outStream->Write(&secondByte, 1, NULL)); + if (_key.SaltSize > 0) + { + RINOK(WriteStream(outStream, _key.Salt, _key.SaltSize)); + } + if (ivSize > 0) + { + RINOK(WriteStream(outStream, _iv, ivSize)); + } + return S_OK; +} + +HRESULT CEncoder::CreateFilter() +{ + _aesFilter = new CAesCbcEncoder; + return S_OK; +} + +#endif + +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) +{ + _key.Init(); + UInt32 i; + for (i = 0; i < sizeof(_iv); i++) + _iv[i] = 0; + if (size == 0) + return S_OK; + UInt32 pos = 0; + Byte firstByte = data[pos++]; + + _key.NumCyclesPower = firstByte & 0x3F; + if ((firstByte & 0xC0) == 0) + return S_OK; + _key.SaltSize = (firstByte >> 7) & 1; + UInt32 ivSize = (firstByte >> 6) & 1; + + if (pos >= size) + return E_INVALIDARG; + Byte secondByte = data[pos++]; + + _key.SaltSize += (secondByte >> 4); + ivSize += (secondByte & 0x0F); + + if (pos + _key.SaltSize + ivSize > size) + return E_INVALIDARG; + for (i = 0; i < _key.SaltSize; i++) + _key.Salt[i] = data[pos++]; + for (i = 0; i < ivSize; i++) + _iv[i] = data[pos++]; + return (_key.NumCyclesPower <= 24) ? S_OK : E_NOTIMPL; +} + +STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size) +{ + _key.Password.SetCapacity((size_t)size); + memcpy(_key.Password, data, (size_t)size); + return S_OK; +} + +STDMETHODIMP CBaseCoder::Init() +{ + CalculateDigest(); + if (_aesFilter == 0) + { + RINOK(CreateFilter()); + } + CMyComPtr cp; + RINOK(_aesFilter.QueryInterface(IID_ICryptoProperties, &cp)); + RINOK(cp->SetKey(_key.Key, sizeof(_key.Key))); + RINOK(cp->SetInitVector(_iv, sizeof(_iv))); + return S_OK; +} + +STDMETHODIMP_(UInt32) CBaseCoder::Filter(Byte *data, UInt32 size) +{ + return _aesFilter->Filter(data, size); +} + +HRESULT CDecoder::CreateFilter() +{ + _aesFilter = new CAesCbcDecoder; + return S_OK; +} + +}} diff --git a/CPP/7zip/Crypto/7zAes.h b/CPP/7zip/Crypto/7zAes.h new file mode 100755 index 0000000..08da666 --- /dev/null +++ b/CPP/7zip/Crypto/7zAes.h @@ -0,0 +1,117 @@ +// 7zAes.h + +#ifndef __CRYPTO_7Z_AES_H +#define __CRYPTO_7Z_AES_H + +#include "Common/Buffer.h" +#include "Common/MyCom.h" +#include "Common/MyVector.h" + +#include "../ICoder.h" +#include "../IPassword.h" + +namespace NCrypto { +namespace NSevenZ { + +const int kKeySize = 32; + +class CKeyInfo +{ +public: + int NumCyclesPower; + UInt32 SaltSize; + Byte Salt[16]; + CByteBuffer Password; + Byte Key[kKeySize]; + + bool IsEqualTo(const CKeyInfo &a) const; + void CalculateDigest(); + + CKeyInfo() { Init(); } + void Init() + { + NumCyclesPower = 0; + SaltSize = 0; + for (int i = 0; i < sizeof(Salt); i++) + Salt[i] = 0; + } +}; + +class CKeyInfoCache +{ + int Size; + CObjectVector Keys; +public: + CKeyInfoCache(int size): Size(size) {} + bool Find(CKeyInfo &key); + // HRESULT Calculate(CKeyInfo &key); + void Add(CKeyInfo &key); +}; + +class CBase +{ + CKeyInfoCache _cachedKeys; +protected: + CKeyInfo _key; + Byte _iv[16]; + UInt32 _ivSize; + void CalculateDigest(); + CBase(); +}; + +class CBaseCoder: + public ICompressFilter, + public ICryptoSetPassword, + public CMyUnknownImp, + public CBase +{ +protected: + CMyComPtr _aesFilter; + + virtual HRESULT CreateFilter() = 0; + #ifndef CRYPTO_AES + HRESULT CreateFilterFromDLL(REFCLSID clsID); + #endif +public: + STDMETHOD(Init)(); + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); + + STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); +}; + +#ifndef EXTRACT_ONLY + +class CEncoder: + public CBaseCoder, + public ICompressWriteCoderProperties, + // public ICryptoResetSalt, + public ICryptoResetInitVector +{ + virtual HRESULT CreateFilter(); +public: + MY_UNKNOWN_IMP3( + ICryptoSetPassword, + ICompressWriteCoderProperties, + // ICryptoResetSalt, + ICryptoResetInitVector) + STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); + // STDMETHOD(ResetSalt)(); + STDMETHOD(ResetInitVector)(); +}; +#endif + +class CDecoder: + public CBaseCoder, + public ICompressSetDecoderProperties2 +{ + virtual HRESULT CreateFilter(); +public: + MY_UNKNOWN_IMP2( + ICryptoSetPassword, + ICompressSetDecoderProperties2) + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); +}; + +}} + +#endif diff --git a/CPP/7zip/Crypto/7zAesRegister.cpp b/CPP/7zip/Crypto/7zAesRegister.cpp new file mode 100755 index 0000000..87f8ae9 --- /dev/null +++ b/CPP/7zip/Crypto/7zAesRegister.cpp @@ -0,0 +1,18 @@ +// 7zAesRegister.cpp + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" +#include "7zAes.h" + +static void *CreateCodec() { return (void *)(ICompressFilter *)(new NCrypto::NSevenZ::CDecoder()); } +#ifndef EXTRACT_ONLY +static void *CreateCodecOut() { return (void *)(ICompressFilter *)(new NCrypto::NSevenZ::CEncoder()); } +#else +#define CreateCodecOut 0 +#endif + +static CCodecInfo g_CodecInfo = + { CreateCodec, CreateCodecOut, 0x06F10701, L"7zAES", 1, true }; + +REGISTER_CODEC(7zAES) diff --git a/CPP/7zip/Crypto/Codec.def b/CPP/7zip/Crypto/Codec.def new file mode 100755 index 0000000..aab87ef --- /dev/null +++ b/CPP/7zip/Crypto/Codec.def @@ -0,0 +1,4 @@ +EXPORTS + CreateObject PRIVATE + GetNumberOfMethods PRIVATE + GetMethodProperty PRIVATE diff --git a/CPP/7zip/Crypto/HmacSha1.cpp b/CPP/7zip/Crypto/HmacSha1.cpp new file mode 100755 index 0000000..09621e9 --- /dev/null +++ b/CPP/7zip/Crypto/HmacSha1.cpp @@ -0,0 +1,109 @@ +// HmacSha1.cpp + +#include "StdAfx.h" + +#include "HmacSha1.h" + +namespace NCrypto { +namespace NSha1 { + +void CHmac::SetKey(const Byte *key, size_t keySize) +{ + Byte keyTemp[kBlockSize]; + size_t i; + for (i = 0; i < kBlockSize; i++) + keyTemp[i] = 0; + if(keySize > kBlockSize) + { + _sha.Init(); + _sha.Update(key, keySize); + _sha.Final(keyTemp); + keySize = kDigestSize; + } + else + for (i = 0; i < keySize; i++) + keyTemp[i] = key[i]; + for (i = 0; i < kBlockSize; i++) + keyTemp[i] ^= 0x36; + _sha.Init(); + _sha.Update(keyTemp, kBlockSize); + for (i = 0; i < kBlockSize; i++) + keyTemp[i] ^= 0x36 ^ 0x5C; + _sha2.Init(); + _sha2.Update(keyTemp, kBlockSize); +} + +void CHmac::Final(Byte *mac, size_t macSize) +{ + Byte digest[kDigestSize]; + _sha.Final(digest); + _sha2.Update(digest, kDigestSize); + _sha2.Final(digest); + for(size_t i = 0; i < macSize; i++) + mac[i] = digest[i]; +} + + +void CHmac32::SetKey(const Byte *key, size_t keySize) +{ + UInt32 keyTemp[kBlockSizeInWords]; + size_t i; + for (i = 0; i < kBlockSizeInWords; i++) + keyTemp[i] = 0; + if(keySize > kBlockSize) + { + CContext sha; + sha.Init(); + sha.Update(key, keySize); + Byte digest[kDigestSize]; + sha.Final(digest); + + for (int i = 0 ; i < kDigestSizeInWords; i++) + keyTemp[i] = + ((UInt32)(digest[i * 4 + 0]) << 24) | + ((UInt32)(digest[i * 4 + 1]) << 16) | + ((UInt32)(digest[i * 4 + 2]) << 8) | + ((UInt32)(digest[i * 4 + 3])); + keySize = kDigestSizeInWords; + } + else + for (size_t i = 0; i < keySize; i++) + keyTemp[i / 4] |= (key[i] << (24 - 8 * (i & 3))); + for (i = 0; i < kBlockSizeInWords; i++) + keyTemp[i] ^= 0x36363636; + _sha.Init(); + _sha.Update(keyTemp, kBlockSizeInWords); + for (i = 0; i < kBlockSizeInWords; i++) + keyTemp[i] ^= 0x36363636 ^ 0x5C5C5C5C; + _sha2.Init(); + _sha2.Update(keyTemp, kBlockSizeInWords); +} + +void CHmac32::Final(UInt32 *mac, size_t macSize) +{ + UInt32 digest[kDigestSizeInWords]; + _sha.Final(digest); + _sha2.Update(digest, kDigestSizeInWords); + _sha2.Final(digest); + for(size_t i = 0; i < macSize; i++) + mac[i] = digest[i]; +} + +void CHmac32::GetLoopXorDigest(UInt32 *mac, UInt32 numIteration) +{ + UInt32 block[kBlockSizeInWords]; + UInt32 block2[kBlockSizeInWords]; + _sha.PrepareBlock(block, kDigestSizeInWords); + _sha2.PrepareBlock(block2, kDigestSizeInWords); + for(unsigned int s = 0; s < kDigestSizeInWords; s++) + block[s] = mac[s]; + for(UInt32 i = 0; i < numIteration; i++) + { + _sha.GetBlockDigest(block, block2); + _sha2.GetBlockDigest(block2, block); + for (unsigned int s = 0; s < kDigestSizeInWords; s++) + mac[s] ^= block[s]; + } +} + +}} diff --git a/CPP/7zip/Crypto/HmacSha1.h b/CPP/7zip/Crypto/HmacSha1.h new file mode 100755 index 0000000..2b12340 --- /dev/null +++ b/CPP/7zip/Crypto/HmacSha1.h @@ -0,0 +1,39 @@ +// HmacSha1.h +// Implements HMAC-SHA-1 (RFC2104, FIPS-198) + +#ifndef __CRYPTO_HMAC_SHA1_H +#define __CRYPTO_HMAC_SHA1_H + +#include "Sha1.h" + +namespace NCrypto { +namespace NSha1 { + +// Use: SetKey(key, keySize); for () Update(data, size); Final(mac, macSize); + +class CHmac +{ + CContext _sha; + CContext _sha2; +public: + void SetKey(const Byte *key, size_t keySize); + void Update(const Byte *data, size_t dataSize) { _sha.Update(data, dataSize); } + void Final(Byte *mac, size_t macSize = kDigestSize); +}; + +class CHmac32 +{ + CContext32 _sha; + CContext32 _sha2; +public: + void SetKey(const Byte *key, size_t keySize); + void Update(const UInt32 *data, size_t dataSize) { _sha.Update(data, dataSize); } + void Final(UInt32 *mac, size_t macSize = kDigestSizeInWords); + + // It'sa for hmac function. in,out: mac[kDigestSizeInWords]. + void GetLoopXorDigest(UInt32 *mac, UInt32 numIteration); +}; + +}} + +#endif diff --git a/CPP/7zip/Crypto/MyAes.cpp b/CPP/7zip/Crypto/MyAes.cpp new file mode 100755 index 0000000..150cbfa --- /dev/null +++ b/CPP/7zip/Crypto/MyAes.cpp @@ -0,0 +1,48 @@ +// Crypto/MyAes.cpp + +#include "StdAfx.h" + +#include "MyAes.h" + +namespace NCrypto { + +struct CAesTabInit { CAesTabInit() { AesGenTables();} } g_AesTabInit; + +CAesCbcCoder::CAesCbcCoder() +{ + _offset = ((0 - (unsigned)(ptrdiff_t)_aes) & 0xF) / sizeof(UInt32); +} + +STDMETHODIMP CAesCbcCoder::Init() { return S_OK; } + +STDMETHODIMP_(UInt32) CAesCbcCoder::Filter(Byte *data, UInt32 size) +{ + 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; + _setKeyFunc(_aes + _offset + 4, data, size); + return S_OK; +} + +STDMETHODIMP CAesCbcCoder::SetInitVector(const Byte *data, UInt32 size) +{ + if (size != AES_BLOCK_SIZE) + return E_INVALIDARG; + AesCbc_Init(_aes + _offset, data); + return S_OK; +} + +CAesCbcEncoder::CAesCbcEncoder() { _codeFunc = g_AesCbc_Encode; _setKeyFunc = Aes_SetKey_Enc; } +CAesCbcDecoder::CAesCbcDecoder() { _codeFunc = g_AesCbc_Decode; _setKeyFunc = Aes_SetKey_Dec; } + +} diff --git a/CPP/7zip/Crypto/MyAes.h b/CPP/7zip/Crypto/MyAes.h new file mode 100755 index 0000000..ab38536 --- /dev/null +++ b/CPP/7zip/Crypto/MyAes.h @@ -0,0 +1,38 @@ +// 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 CMyUnknownImp +{ +protected: + AES_CODE_FUNC _codeFunc; + AES_SET_KEY_FUNC _setKeyFunc; + unsigned _offset; + UInt32 _aes[AES_NUM_IVMRK_WORDS + 3]; +public: + CAesCbcCoder(); + MY_UNKNOWN_IMP1(ICryptoProperties) + STDMETHOD(Init)(); + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); + STDMETHOD(SetKey)(const Byte *data, UInt32 size); + STDMETHOD(SetInitVector)(const Byte *data, UInt32 size); +}; + +struct CAesCbcEncoder: public CAesCbcCoder { CAesCbcEncoder(); }; +struct CAesCbcDecoder: public CAesCbcCoder { CAesCbcDecoder(); }; + +} + +#endif diff --git a/CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp b/CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp new file mode 100755 index 0000000..0ac6dc6 --- /dev/null +++ b/CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp @@ -0,0 +1,83 @@ +// Pbkdf2HmacSha1.cpp + +#include "StdAfx.h" + +#include "HmacSha1.h" + +namespace NCrypto { +namespace NSha1 { + +void Pbkdf2Hmac(const Byte *pwd, size_t pwdSize, const Byte *salt, size_t saltSize, + UInt32 numIterations, Byte *key, size_t keySize) +{ + CHmac baseCtx; + baseCtx.SetKey(pwd, pwdSize); + for (UInt32 i = 1; keySize > 0; i++) + { + CHmac ctx = baseCtx; + ctx.Update(salt, saltSize); + Byte u[kDigestSize] = { (Byte)(i >> 24), (Byte)(i >> 16), (Byte)(i >> 8), (Byte)(i) }; + const unsigned int curSize = (keySize < kDigestSize) ? (unsigned int)keySize : kDigestSize; + ctx.Update(u, 4); + ctx.Final(u, kDigestSize); + + unsigned int s; + for (s = 0; s < curSize; s++) + key[s] = u[s]; + + for (UInt32 j = numIterations; j > 1; j--) + { + ctx = baseCtx; + ctx.Update(u, kDigestSize); + ctx.Final(u, kDigestSize); + for (s = 0; s < curSize; s++) + key[s] ^= u[s]; + } + + key += curSize; + keySize -= curSize; + } +} + +void Pbkdf2Hmac32(const Byte *pwd, size_t pwdSize, const UInt32 *salt, size_t saltSize, + UInt32 numIterations, UInt32 *key, size_t keySize) +{ + CHmac32 baseCtx; + baseCtx.SetKey(pwd, pwdSize); + for (UInt32 i = 1; keySize > 0; i++) + { + CHmac32 ctx = baseCtx; + ctx.Update(salt, saltSize); + UInt32 u[kDigestSizeInWords] = { i }; + const unsigned int curSize = (keySize < kDigestSizeInWords) ? (unsigned int)keySize : kDigestSizeInWords; + ctx.Update(u, 1); + ctx.Final(u, kDigestSizeInWords); + + // Speed-optimized code start + ctx = baseCtx; + ctx.GetLoopXorDigest(u, numIterations - 1); + // Speed-optimized code end + + unsigned int s; + for (s = 0; s < curSize; s++) + key[s] = u[s]; + + /* + // Default code start + for (UInt32 j = numIterations; j > 1; j--) + { + ctx = baseCtx; + ctx.Update(u, kDigestSizeInWords); + ctx.Final(u, kDigestSizeInWords); + for (s = 0; s < curSize; s++) + key[s] ^= u[s]; + } + // Default code end + */ + + key += curSize; + keySize -= curSize; + } +} + +}} diff --git a/CPP/7zip/Crypto/Pbkdf2HmacSha1.h b/CPP/7zip/Crypto/Pbkdf2HmacSha1.h new file mode 100755 index 0000000..ea5d99f --- /dev/null +++ b/CPP/7zip/Crypto/Pbkdf2HmacSha1.h @@ -0,0 +1,21 @@ +// Pbkdf2HmacSha1.h +// Password-Based Key Derivation Function (RFC 2898, PKCS #5) based on HMAC-SHA-1 + +#ifndef __CRYPTO_PBKDF2_HMAC_SHA1_H +#define __CRYPTO_PBKDF2_HMAC_SHA1_H + +#include +#include "../../Common/Types.h" + +namespace NCrypto { +namespace NSha1 { + +void Pbkdf2Hmac(const Byte *pwd, size_t pwdSize, const Byte *salt, size_t saltSize, + UInt32 numIterations, Byte *key, size_t keySize); + +void Pbkdf2Hmac32(const Byte *pwd, size_t pwdSize, const UInt32 *salt, size_t saltSize, + UInt32 numIterations, UInt32 *key, size_t keySize); + +}} + +#endif diff --git a/CPP/7zip/Crypto/RandGen.cpp b/CPP/7zip/Crypto/RandGen.cpp new file mode 100755 index 0000000..66b3231 --- /dev/null +++ b/CPP/7zip/Crypto/RandGen.cpp @@ -0,0 +1,107 @@ +// RandGen.cpp + +#include "StdAfx.h" + +#include +#include "Windows/Synchronization.h" +#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. + +void CRandomGenerator::Init() +{ + NCrypto::NSha1::CContext hash; + hash.Init(); + + #ifdef _WIN32 + DWORD w = ::GetCurrentProcessId(); + hash.Update((const Byte *)&w, sizeof(w)); + w = ::GetCurrentThreadId(); + hash.Update((const Byte *)&w, sizeof(w)); + #else + pid_t pid = getpid(); + hash.Update((const Byte *)&pid, sizeof(pid)); + pid = getppid(); + hash.Update((const Byte *)&pid, sizeof(pid)); + #endif + + for (int i = 0; i < 1000; i++) + { + #ifdef _WIN32 + LARGE_INTEGER v; + if (::QueryPerformanceCounter(&v)) + hash.Update((const Byte *)&v.QuadPart, sizeof(v.QuadPart)); + #endif + + #ifdef USE_POSIX_TIME + #ifdef USE_POSIX_TIME2 + timeval v; + if (gettimeofday(&v, 0) == 0) + { + hash.Update((const Byte *)&v.tv_sec, sizeof(v.tv_sec)); + hash.Update((const Byte *)&v.tv_usec, sizeof(v.tv_usec)); + } + #endif + time_t v2 = time(NULL); + hash.Update((const Byte *)&v2, sizeof(v2)); + #endif + + DWORD tickCount = ::GetTickCount(); + hash.Update((const Byte *)&tickCount, sizeof(tickCount)); + + for (int j = 0; j < 100; j++) + { + hash.Final(_buff); + hash.Init(); + hash.Update(_buff, NCrypto::NSha1::kDigestSize); + } + } + hash.Final(_buff); + _needInit = false; +} + +static NWindows::NSynchronization::CCriticalSection g_CriticalSection; + +void CRandomGenerator::Generate(Byte *data, unsigned int size) +{ + g_CriticalSection.Enter(); + if (_needInit) + Init(); + while (size > 0) + { + NCrypto::NSha1::CContext hash; + + hash.Init(); + hash.Update(_buff, NCrypto::NSha1::kDigestSize); + hash.Final(_buff); + + hash.Init(); + UInt32 salt = 0xF672ABD1; + hash.Update((const Byte *)&salt, sizeof(salt)); + hash.Update(_buff, NCrypto::NSha1::kDigestSize); + Byte buff[NCrypto::NSha1::kDigestSize]; + hash.Final(buff); + for (unsigned int i = 0; i < NCrypto::NSha1::kDigestSize && size > 0; i++, size--) + *data++ = buff[i]; + } + g_CriticalSection.Leave(); +} + +CRandomGenerator g_RandomGenerator; diff --git a/CPP/7zip/Crypto/RandGen.h b/CPP/7zip/Crypto/RandGen.h new file mode 100755 index 0000000..a457897 --- /dev/null +++ b/CPP/7zip/Crypto/RandGen.h @@ -0,0 +1,21 @@ +// RandGen.h + +#ifndef __CRYPTO_RAND_GEN_H +#define __CRYPTO_RAND_GEN_H + +#include "Sha1.h" + +class CRandomGenerator +{ + Byte _buff[NCrypto::NSha1::kDigestSize]; + bool _needInit; + + void Init(); +public: + CRandomGenerator(): _needInit(true) {}; + void Generate(Byte *data, unsigned size); +}; + +extern CRandomGenerator g_RandomGenerator; + +#endif diff --git a/CPP/7zip/Crypto/Rar20Crypto.cpp b/CPP/7zip/Crypto/Rar20Crypto.cpp new file mode 100755 index 0000000..1ea8433 --- /dev/null +++ b/CPP/7zip/Crypto/Rar20Crypto.cpp @@ -0,0 +1,133 @@ +// Crypto/Rar20Crypto.cpp + +#include "StdAfx.h" + +#include "../../../C/7zCrc.h" +#include "../../../C/CpuArch.h" +#include "../../../C/RotateDefs.h" + +#include "Rar20Crypto.h" + +namespace NCrypto { +namespace NRar20 { + +static const int kNumRounds = 32; + +static const Byte InitSubstTable[256] = { + 215, 19,149, 35, 73,197,192,205,249, 28, 16,119, 48,221, 2, 42, + 232, 1,177,233, 14, 88,219, 25,223,195,244, 90, 87,239,153,137, + 255,199,147, 70, 92, 66,246, 13,216, 40, 62, 29,217,230, 86, 6, + 71, 24,171,196,101,113,218,123, 93, 91,163,178,202, 67, 44,235, + 107,250, 75,234, 49,167,125,211, 83,114,157,144, 32,193,143, 36, + 158,124,247,187, 89,214,141, 47,121,228, 61,130,213,194,174,251, + 97,110, 54,229,115, 57,152, 94,105,243,212, 55,209,245, 63, 11, + 164,200, 31,156, 81,176,227, 21, 76, 99,139,188,127, 17,248, 51, + 207,120,189,210, 8,226, 41, 72,183,203,135,165,166, 60, 98, 7, + 122, 38,155,170, 69,172,252,238, 39,134, 59,128,236, 27,240, 80, + 131, 3, 85,206,145, 79,154,142,159,220,201,133, 74, 64, 20,129, + 224,185,138,103,173,182, 43, 34,254, 82,198,151,231,180, 58, 10, + 118, 26,102, 12, 50,132, 22,191,136,111,162,179, 45, 4,148,108, + 161, 56, 78,126,242,222, 15,175,146, 23, 33,241,181,190, 77,225, + 0, 46,169,186, 68, 95,237, 65, 53,208,253,168, 9, 18,100, 52, + 116,184,160, 96,109, 37, 30,106,140,104,150, 5,204,117,112, 84 +}; + +void CData::UpdateKeys(const Byte *data) +{ + for (int i = 0; i < 16; i += 4) + for (int j = 0; j < 4; j++) + Keys[j] ^= g_CrcTable[data[i + j]]; +} + +static void Swap(Byte *b1, Byte *b2) +{ + Byte b = *b1; + *b1 = *b2; + *b2 = b; +} + +void CData::SetPassword(const Byte *password, UInt32 passwordLen) +{ + Keys[0] = 0xD3A3B879L; + Keys[1] = 0x3F6D12F7L; + Keys[2] = 0x7515A235L; + Keys[3] = 0xA4E7F123L; + + Byte psw[256]; + memset(psw, 0, sizeof(psw)); + memcpy(psw, password, passwordLen); + memcpy(SubstTable, InitSubstTable, sizeof(SubstTable)); + + for (UInt32 j = 0; j < 256; j++) + for (UInt32 i = 0; i < passwordLen; i += 2) + { + UInt32 n2 = (Byte)g_CrcTable[(psw[i + 1] + j) & 0xFF]; + UInt32 n1 = (Byte)g_CrcTable[(psw[i] - j) & 0xFF]; + for (UInt32 k = 1; (n1 & 0xFF) != n2; n1++, k++) + Swap(&SubstTable[n1 & 0xFF], &SubstTable[(n1 + i + k) & 0xFF]); + } + for (UInt32 i = 0; i < passwordLen; i+= 16) + EncryptBlock(&psw[i]); +} + +void CData::CryptBlock(Byte *buf, bool encrypt) +{ + Byte inBuf[16]; + UInt32 A, B, C, D, T, TA, TB; + + A = GetUi32(buf + 0) ^ Keys[0]; + B = GetUi32(buf + 4) ^ Keys[1]; + C = GetUi32(buf + 8) ^ Keys[2]; + D = GetUi32(buf + 12) ^ Keys[3]; + + if (!encrypt) + memcpy(inBuf, buf, sizeof(inBuf)); + + for (int i = 0; i < kNumRounds; i++) + { + UInt32 key = Keys[(encrypt ? i : (kNumRounds - 1 - i)) & 3]; + T = ((C + rotlFixed(D, 11)) ^ key); + TA = A ^ SubstLong(T); + T = ((D ^ rotlFixed(C, 17)) + key); + TB = B ^ SubstLong(T); + A = C; + B = D; + C = TA; + D = TB; + } + + SetUi32(buf + 0, C ^ Keys[0]); + SetUi32(buf + 4, D ^ Keys[1]); + SetUi32(buf + 8, A ^ Keys[2]); + SetUi32(buf + 12, B ^ Keys[3]); + + UpdateKeys(encrypt ? buf : inBuf); +} + +STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size) +{ + _cipher.SetPassword(data, size); + return S_OK; +} + +STDMETHODIMP CDecoder::Init() +{ + return S_OK; +} + +static const UInt32 kBlockSize = 16; + +STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size) +{ + if (size == 0) + return 0; + if (size < kBlockSize) + return kBlockSize; + UInt32 i; + size -= kBlockSize; + for (i = 0; i <= size; i += kBlockSize) + _cipher.DecryptBlock(data + i); + return i; +} + +}} diff --git a/CPP/7zip/Crypto/Rar20Crypto.h b/CPP/7zip/Crypto/Rar20Crypto.h new file mode 100755 index 0000000..36f5590 --- /dev/null +++ b/CPP/7zip/Crypto/Rar20Crypto.h @@ -0,0 +1,50 @@ +// Crypto/Rar20Crypto.h + +#ifndef __CRYPTO_RAR20_CRYPTO_H +#define __CRYPTO_RAR20_CRYPTO_H + +#include "Common/MyCom.h" + +#include "../ICoder.h" +#include "../IPassword.h" + +namespace NCrypto { +namespace NRar20 { + +class CData +{ + Byte SubstTable[256]; + UInt32 Keys[4]; + + UInt32 SubstLong(UInt32 t) + { + return (UInt32)SubstTable[(int)t & 255] | + ((UInt32)SubstTable[(int)(t >> 8) & 255] << 8) | + ((UInt32)SubstTable[(int)(t >> 16) & 255] << 16) | + ((UInt32)SubstTable[(int)(t >> 24) & 255] << 24); + } + void UpdateKeys(const Byte *data); + void CryptBlock(Byte *buf, bool encrypt); +public: + void EncryptBlock(Byte *buf) { CryptBlock(buf, true); } + void DecryptBlock(Byte *buf) { CryptBlock(buf, false); } + void SetPassword(const Byte *password, UInt32 passwordLen); +}; + +class CDecoder: + public ICompressFilter, + public ICryptoSetPassword, + public CMyUnknownImp +{ + CData _cipher; +public: + MY_UNKNOWN_IMP1(ICryptoSetPassword) + + STDMETHOD(Init)(); + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); + STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); +}; + +}} + +#endif diff --git a/CPP/7zip/Crypto/RarAes.cpp b/CPP/7zip/Crypto/RarAes.cpp new file mode 100755 index 0000000..a6a4642 --- /dev/null +++ b/CPP/7zip/Crypto/RarAes.cpp @@ -0,0 +1,134 @@ +// Crypto/RarAes.cpp +// Note: you must include MyAes.cpp to project to initialize AES tables + +#include "StdAfx.h" + +#include "RarAes.h" +#include "Sha1.h" + +namespace NCrypto { +namespace NRar29 { + +CDecoder::CDecoder(): + _thereIsSalt(false), + _needCalculate(true), + _rar350Mode(false) +{ + for (int i = 0; i < sizeof(_salt); i++) + _salt[i] = 0; +} + +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) +{ + bool thereIsSaltPrev = _thereIsSalt; + _thereIsSalt = false; + if (size == 0) + return S_OK; + if (size < 8) + return E_INVALIDARG; + _thereIsSalt = true; + bool same = false; + if (_thereIsSalt == thereIsSaltPrev) + { + same = true; + if (_thereIsSalt) + { + for (unsigned i = 0; i < sizeof(_salt); i++) + if (_salt[i] != data[i]) + { + same = false; + break; + } + } + } + for (unsigned i = 0; i < sizeof(_salt); i++) + _salt[i] = data[i]; + if (!_needCalculate && !same) + _needCalculate = true; + return S_OK; +} + +static const unsigned kMaxPasswordLength = 127 * 2; + +STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size) +{ + if (size > kMaxPasswordLength) + size = kMaxPasswordLength; + bool same = false; + if (size == buffer.GetCapacity()) + { + same = true; + for (UInt32 i = 0; i < size; i++) + if (data[i] != buffer[i]) + { + same = false; + break; + } + } + if (!_needCalculate && !same) + _needCalculate = true; + buffer.SetCapacity(size); + memcpy(buffer, data, size); + return S_OK; +} + +STDMETHODIMP CDecoder::Init() +{ + Calculate(); + SetKey(aesKey, kRarAesKeySize); + AesCbc_Init(_aes + _offset, _aesInit); + return S_OK; +} + +void CDecoder::Calculate() +{ + if (_needCalculate) + { + const unsigned kSaltSize = 8; + + Byte rawPassword[kMaxPasswordLength + kSaltSize]; + + memcpy(rawPassword, buffer, buffer.GetCapacity()); + + size_t rawLength = buffer.GetCapacity(); + + if (_thereIsSalt) + { + memcpy(rawPassword + rawLength, _salt, kSaltSize); + rawLength += kSaltSize; + } + + NSha1::CContext sha; + sha.Init(); + + // rar reverts hash for sha. + const unsigned kNumRounds = (1 << 18); + unsigned i; + for (i = 0; i < kNumRounds; i++) + { + sha.UpdateRar(rawPassword, rawLength, _rar350Mode); + Byte pswNum[3] = { (Byte)i, (Byte)(i >> 8), (Byte)(i >> 16) }; + sha.UpdateRar(pswNum, 3, _rar350Mode); + if (i % (kNumRounds / 16) == 0) + { + NSha1::CContext shaTemp = sha; + Byte digest[NSha1::kDigestSize]; + shaTemp.Final(digest); + _aesInit[i / (kNumRounds / 16)] = (Byte)digest[4 * 4 + 3]; + } + } + /* + // it's test message for sha + const char *message = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + sha.Update((const Byte *)message, strlen(message)); + */ + Byte digest[20]; + sha.Final(digest); + for (i = 0; i < 4; i++) + for (unsigned j = 0; j < 4; j++) + aesKey[i * 4 + j] = (digest[i * 4 + 3 - j]); + } + _needCalculate = false; +} + +}} diff --git a/CPP/7zip/Crypto/RarAes.h b/CPP/7zip/Crypto/RarAes.h new file mode 100755 index 0000000..e1cc4bc --- /dev/null +++ b/CPP/7zip/Crypto/RarAes.h @@ -0,0 +1,47 @@ +// Crypto/RarAes.h + +#ifndef __CRYPTO_RAR_AES_H +#define __CRYPTO_RAR_AES_H + +#include "../../../C/Aes.h" + +#include "Common/Buffer.h" + +#include "../IPassword.h" + +#include "MyAes.h" + +namespace NCrypto { +namespace NRar29 { + +const UInt32 kRarAesKeySize = 16; + +class CDecoder: + public CAesCbcDecoder, + public ICompressSetDecoderProperties2, + public ICryptoSetPassword +{ + Byte _salt[8]; + bool _thereIsSalt; + CByteBuffer buffer; + Byte aesKey[kRarAesKeySize]; + Byte _aesInit[AES_BLOCK_SIZE]; + bool _needCalculate; + bool _rar350Mode; + + void Calculate(); +public: + MY_UNKNOWN_IMP2( + ICryptoSetPassword, + ICompressSetDecoderProperties2) + STDMETHOD(Init)(); + STDMETHOD(CryptoSetPassword)(const Byte *aData, UInt32 aSize); + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); + + CDecoder(); + void SetRar350Mode(bool rar350Mode) { _rar350Mode = rar350Mode; } +}; + +}} + +#endif diff --git a/CPP/7zip/Crypto/Sha1.cpp b/CPP/7zip/Crypto/Sha1.cpp new file mode 100755 index 0000000..cc8bf4f --- /dev/null +++ b/CPP/7zip/Crypto/Sha1.cpp @@ -0,0 +1,229 @@ +// Crypto/Sha1.cpp +// This file is based on public domain +// Steve Reid and Wei Dai's code from Crypto++ + +#include "StdAfx.h" + +#include "../../../C/RotateDefs.h" + +#include "Sha1.h" + +namespace NCrypto { +namespace NSha1 { + +// define it for speed optimization +// #define _SHA1_UNROLL + +static const unsigned kNumW = + #ifdef _SHA1_UNROLL + 16; + #else + 80; + #endif + + +#define w0(i) (W[(i)] = data[(i)]) + +#ifdef _SHA1_UNROLL +#define w1(i) (W[(i)&15] = rotlFixed(W[((i)-3)&15] ^ W[((i)-8)&15] ^ W[((i)-14)&15] ^ W[((i)-16)&15], 1)) +#else +#define w1(i) (W[(i)] = rotlFixed(W[(i)-3] ^ W[(i)-8] ^ W[(i)-14] ^ W[(i)-16], 1)) +#endif + +#define f1(x,y,z) (z^(x&(y^z))) +#define f2(x,y,z) (x^y^z) +#define f3(x,y,z) ((x&y)|(z&(x|y))) +#define f4(x,y,z) (x^y^z) + +#define RK1(a,b,c,d,e,i, f, w, k) e += f(b,c,d) + w(i) + k + rotlFixed(a,5); b = rotlFixed(b,30); + +#define R0(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f1, w0, 0x5A827999) +#define R1(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f1, w1, 0x5A827999) +#define R2(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f2, w1, 0x6ED9EBA1) +#define R3(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f3, w1, 0x8F1BBCDC) +#define R4(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f4, w1, 0xCA62C1D6) + +#define RX_1_4(rx1, rx4, i) rx1(a,b,c,d,e,i); rx4(e,a,b,c,d,i+1); rx4(d,e,a,b,c,i+2); rx4(c,d,e,a,b,i+3); rx4(b,c,d,e,a,i+4); +#define RX_5(rx, i) RX_1_4(rx, rx, i); + +void CContextBase::Init() +{ + _state[0] = 0x67452301; + _state[1] = 0xEFCDAB89; + _state[2] = 0x98BADCFE; + _state[3] = 0x10325476; + _state[4] = 0xC3D2E1F0; + _count = 0; +} + +void CContextBase::GetBlockDigest(UInt32 *data, UInt32 *destDigest, bool returnRes) +{ + UInt32 a, b, c, d, e; + UInt32 W[kNumW]; + + a = _state[0]; + b = _state[1]; + c = _state[2]; + d = _state[3]; + e = _state[4]; + #ifdef _SHA1_UNROLL + RX_5(R0, 0); RX_5(R0, 5); RX_5(R0, 10); + #else + int i; + for (i = 0; i < 15; i += 5) { RX_5(R0, i); } + #endif + + RX_1_4(R0, R1, 15); + + + #ifdef _SHA1_UNROLL + RX_5(R2, 20); RX_5(R2, 25); RX_5(R2, 30); RX_5(R2, 35); + RX_5(R3, 40); RX_5(R3, 45); RX_5(R3, 50); RX_5(R3, 55); + RX_5(R4, 60); RX_5(R4, 65); RX_5(R4, 70); RX_5(R4, 75); + #else + i = 20; + for (; i < 40; i += 5) { RX_5(R2, i); } + for (; i < 60; i += 5) { RX_5(R3, i); } + for (; i < 80; i += 5) { RX_5(R4, i); } + #endif + + destDigest[0] = _state[0] + a; + destDigest[1] = _state[1] + b; + destDigest[2] = _state[2] + c; + destDigest[3] = _state[3] + d; + destDigest[4] = _state[4] + e; + + if (returnRes) + for (int i = 0 ; i < 16; i++) + data[i] = W[kNumW - 16 + i]; + + // Wipe variables + // a = b = c = d = e = 0; +} + +void CContextBase::PrepareBlock(UInt32 *block, unsigned size) const +{ + unsigned curBufferPos = size & 0xF; + block[curBufferPos++] = 0x80000000; + while (curBufferPos != (16 - 2)) + block[curBufferPos++] = 0; + const UInt64 lenInBits = (_count << 9) + ((UInt64)size << 5); + block[curBufferPos++] = (UInt32)(lenInBits >> 32); + block[curBufferPos++] = (UInt32)(lenInBits); +} + +void CContext::Update(const Byte *data, size_t size) +{ + unsigned curBufferPos = _count2; + while (size--) + { + int pos = (int)(curBufferPos & 3); + if (pos == 0) + _buffer[curBufferPos >> 2] = 0; + _buffer[curBufferPos >> 2] |= ((UInt32)*data++) << (8 * (3 - pos)); + if (++curBufferPos == kBlockSize) + { + curBufferPos = 0; + CContextBase::UpdateBlock(_buffer, false); + } + } + _count2 = curBufferPos; +} + +void CContext::UpdateRar(Byte *data, size_t size, bool rar350Mode) +{ + bool returnRes = false; + unsigned curBufferPos = _count2; + while (size--) + { + int pos = (int)(curBufferPos & 3); + if (pos == 0) + _buffer[curBufferPos >> 2] = 0; + _buffer[curBufferPos >> 2] |= ((UInt32)*data++) << (8 * (3 - pos)); + if (++curBufferPos == kBlockSize) + { + curBufferPos = 0; + CContextBase::UpdateBlock(_buffer, returnRes); + if (returnRes) + for (int i = 0; i < kBlockSizeInWords; i++) + { + UInt32 d = _buffer[i]; + data[i * 4 + 0 - kBlockSize] = (Byte)(d); + data[i * 4 + 1 - kBlockSize] = (Byte)(d >> 8); + data[i * 4 + 2 - kBlockSize] = (Byte)(d >> 16); + data[i * 4 + 3 - kBlockSize] = (Byte)(d >> 24); + } + returnRes = rar350Mode; + } + } + _count2 = curBufferPos; +} + +void CContext::Final(Byte *digest) +{ + const UInt64 lenInBits = (_count << 9) + ((UInt64)_count2 << 3); + unsigned curBufferPos = _count2; + int pos = (int)(curBufferPos & 3); + curBufferPos >>= 2; + if (pos == 0) + _buffer[curBufferPos] = 0; + _buffer[curBufferPos++] |= ((UInt32)0x80) << (8 * (3 - pos)); + + while (curBufferPos != (16 - 2)) + { + curBufferPos &= 0xF; + if (curBufferPos == 0) + UpdateBlock(); + _buffer[curBufferPos++] = 0; + } + _buffer[curBufferPos++] = (UInt32)(lenInBits >> 32); + _buffer[curBufferPos++] = (UInt32)(lenInBits); + UpdateBlock(); + + int i; + for (i = 0; i < kDigestSizeInWords; i++) + { + UInt32 state = _state[i] & 0xFFFFFFFF; + *digest++ = (Byte)(state >> 24); + *digest++ = (Byte)(state >> 16); + *digest++ = (Byte)(state >> 8); + *digest++ = (Byte)(state); + } + Init(); +} + +/////////////////////////// +// Words version + +void CContext32::Update(const UInt32 *data, size_t size) +{ + while (size--) + { + _buffer[_count2++] = *data++; + if (_count2 == kBlockSizeInWords) + { + _count2 = 0; + UpdateBlock(); + } + } +} + +void CContext32::Final(UInt32 *digest) +{ + const UInt64 lenInBits = (_count << 9) + ((UInt64)_count2 << 5); + unsigned curBufferPos = _count2; + _buffer[curBufferPos++] = 0x80000000; + while (curBufferPos != (16 - 2)) + { + curBufferPos &= 0xF; + if (curBufferPos == 0) + UpdateBlock(); + _buffer[curBufferPos++] = 0; + } + _buffer[curBufferPos++] = (UInt32)(lenInBits >> 32); + _buffer[curBufferPos++] = (UInt32)(lenInBits); + GetBlockDigest(_buffer, digest); + Init(); +} + +}} diff --git a/CPP/7zip/Crypto/Sha1.h b/CPP/7zip/Crypto/Sha1.h new file mode 100755 index 0000000..1317c53 --- /dev/null +++ b/CPP/7zip/Crypto/Sha1.h @@ -0,0 +1,68 @@ +// Crypto/Sha1.h +// This file is based on public domain +// Steve Reid and Wei Dai's code from Crypto++ + +#ifndef __CRYPTO_SHA1_H +#define __CRYPTO_SHA1_H + +#include +#include "../../Common/Types.h" + +// Sha1 implementation in RAR before version 3.60 has bug: +// it changes data bytes in some cases. +// So this class supports both versions: normal_SHA and rar3Mode + +namespace NCrypto { +namespace NSha1 { + +const unsigned kBlockSize = 64; +const unsigned kDigestSize = 20; + +const unsigned kBlockSizeInWords = (kBlockSize >> 2); +const unsigned kDigestSizeInWords = (kDigestSize >> 2); + +class CContextBase +{ +protected: + UInt32 _state[5]; + UInt64 _count; + void UpdateBlock(UInt32 *data, bool returnRes = false) + { + GetBlockDigest(data, _state, returnRes); + _count++; + } +public: + void Init(); + void GetBlockDigest(UInt32 *blockData, UInt32 *destDigest, bool returnRes = false); + // PrepareBlock can be used only when size <= 13. size in Words + void PrepareBlock(UInt32 *block, unsigned int size) const; +}; + +class CContextBase2: public CContextBase +{ +protected: + unsigned _count2; + UInt32 _buffer[kBlockSizeInWords]; + void UpdateBlock() { CContextBase::UpdateBlock(_buffer); } +public: + void Init() { CContextBase::Init(); _count2 = 0; } +}; + +class CContext: public CContextBase2 +{ +public: + void Update(const Byte *data, size_t size); + void UpdateRar(Byte *data, size_t size, bool rar350Mode); + void Final(Byte *digest); +}; + +class CContext32: public CContextBase2 +{ +public: + void Update(const UInt32 *data, size_t size); + void Final(UInt32 *digest); +}; + +}} + +#endif diff --git a/CPP/7zip/Crypto/StdAfx.h b/CPP/7zip/Crypto/StdAfx.h new file mode 100755 index 0000000..c28ffce --- /dev/null +++ b/CPP/7zip/Crypto/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../Common/MyWindows.h" + +#endif diff --git a/CPP/7zip/Crypto/WzAes.cpp b/CPP/7zip/Crypto/WzAes.cpp new file mode 100755 index 0000000..7a037d9 --- /dev/null +++ b/CPP/7zip/Crypto/WzAes.cpp @@ -0,0 +1,221 @@ +// Crypto/WzAes.cpp +/* +This code implements Brian Gladman's scheme +specified in password Based File Encryption Utility. + +Note: you must include MyAes.cpp to project to initialize AES tables +*/ + +#include "StdAfx.h" + +#include "../Common/StreamObjects.h" +#include "../Common/StreamUtils.h" + +#include "Pbkdf2HmacSha1.h" +#include "RandGen.h" +#include "WzAes.h" + +// define it if you don't want to use speed-optimized version of Pbkdf2HmacSha1 +// #define _NO_WZAES_OPTIMIZATIONS + +namespace NCrypto { +namespace NWzAes { + +const unsigned kAesKeySizeMax = 32; + +static const UInt32 kNumKeyGenIterations = 1000; + +STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size) +{ + if(size > kPasswordSizeMax) + return E_INVALIDARG; + _key.Password.SetCapacity(size); + memcpy(_key.Password, data, size); + return S_OK; +} + +#ifndef _NO_WZAES_OPTIMIZATIONS + +static void BytesToBeUInt32s(const Byte *src, UInt32 *dest, unsigned destSize) +{ + for (unsigned i = 0; i < destSize; i++) + dest[i] = + ((UInt32)(src[i * 4 + 0]) << 24) | + ((UInt32)(src[i * 4 + 1]) << 16) | + ((UInt32)(src[i * 4 + 2]) << 8) | + ((UInt32)(src[i * 4 + 3])); +} + +#endif + +STDMETHODIMP CBaseCoder::Init() +{ + UInt32 keySize = _key.GetKeySize(); + UInt32 keysTotalSize = 2 * keySize + kPwdVerifCodeSize; + Byte buf[2 * kAesKeySizeMax + kPwdVerifCodeSize]; + + // for (unsigned ii = 0; ii < 1000; ii++) + { + #ifdef _NO_WZAES_OPTIMIZATIONS + + NSha1::Pbkdf2Hmac( + _key.Password, _key.Password.GetCapacity(), + _key.Salt, _key.GetSaltSize(), + kNumKeyGenIterations, + buf, keysTotalSize); + + #else + + UInt32 buf32[(2 * kAesKeySizeMax + kPwdVerifCodeSize + 3) / 4]; + UInt32 key32SizeTotal = (keysTotalSize + 3) / 4; + UInt32 salt[kSaltSizeMax * 4]; + UInt32 saltSizeInWords = _key.GetSaltSize() / 4; + BytesToBeUInt32s(_key.Salt, salt, saltSizeInWords); + NSha1::Pbkdf2Hmac32( + _key.Password, _key.Password.GetCapacity(), + salt, saltSizeInWords, + kNumKeyGenIterations, + buf32, key32SizeTotal); + for (UInt32 j = 0; j < keysTotalSize; j++) + buf[j] = (Byte)(buf32[j / 4] >> (24 - 8 * (j & 3))); + + #endif + } + + _hmac.SetKey(buf + keySize, keySize); + memcpy(_key.PwdVerifComputed, buf + 2 * keySize, kPwdVerifCodeSize); + + AesCtr2_Init(&_aes); + Aes_SetKey_Enc(_aes.aes + _aes.offset + 8, buf, keySize); + return S_OK; +} + +HRESULT CEncoder::WriteHeader(ISequentialOutStream *outStream) +{ + UInt32 saltSize = _key.GetSaltSize(); + g_RandomGenerator.Generate(_key.Salt, saltSize); + Init(); + RINOK(WriteStream(outStream, _key.Salt, saltSize)); + return WriteStream(outStream, _key.PwdVerifComputed, kPwdVerifCodeSize); +} + +HRESULT CEncoder::WriteFooter(ISequentialOutStream *outStream) +{ + Byte mac[kMacSize]; + _hmac.Final(mac, kMacSize); + return WriteStream(outStream, mac, kMacSize); +} + +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) +{ + if (size != 1) + return E_INVALIDARG; + _key.Init(); + return SetKeyMode(data[0]) ? S_OK : E_INVALIDARG; +} + +HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream) +{ + UInt32 saltSize = _key.GetSaltSize(); + UInt32 extraSize = saltSize + kPwdVerifCodeSize; + Byte temp[kSaltSizeMax + kPwdVerifCodeSize]; + RINOK(ReadStream_FAIL(inStream, temp, extraSize)); + UInt32 i; + for (i = 0; i < saltSize; i++) + _key.Salt[i] = temp[i]; + for (i = 0; i < kPwdVerifCodeSize; i++) + _pwdVerifFromArchive[i] = temp[saltSize + i]; + return S_OK; +} + +static bool CompareArrays(const Byte *p1, const Byte *p2, UInt32 size) +{ + for (UInt32 i = 0; i < size; i++) + if (p1[i] != p2[i]) + return false; + return true; +} + +bool CDecoder::CheckPasswordVerifyCode() +{ + return CompareArrays(_key.PwdVerifComputed, _pwdVerifFromArchive, kPwdVerifCodeSize); +} + +HRESULT CDecoder::CheckMac(ISequentialInStream *inStream, bool &isOK) +{ + isOK = false; + Byte mac1[kMacSize]; + RINOK(ReadStream_FAIL(inStream, mac1, kMacSize)); + Byte mac2[kMacSize]; + _hmac.Final(mac2, kMacSize); + isOK = CompareArrays(mac1, mac2, kMacSize); + return S_OK; +} + +CAesCtr2::CAesCtr2() +{ + offset = ((0 - (unsigned)(ptrdiff_t)aes) & 0xF) / sizeof(UInt32); +} + +void AesCtr2_Init(CAesCtr2 *p) +{ + UInt32 *ctr = p->aes + p->offset + 4; + unsigned i; + for (i = 0; i < 4; i++) + ctr[i] = 0; + p->pos = AES_BLOCK_SIZE; +} + +void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size) +{ + unsigned pos = p->pos; + UInt32 *buf32 = p->aes + p->offset; + if (size == 0) + return; + if (pos != AES_BLOCK_SIZE) + { + const Byte *buf = (const Byte *)buf32; + do + *data++ ^= buf[pos++]; + while (--size != 0 && pos != AES_BLOCK_SIZE); + } + if (size >= 16) + { + SizeT size2 = size >> 4; + g_AesCtr_Code(buf32 + 4, data, size2); + size2 <<= 4; + data += size2; + size -= size2; + pos = AES_BLOCK_SIZE; + } + if (size != 0) + { + unsigned j; + const Byte *buf; + for (j = 0; j < 4; j++) + buf32[j] = 0; + g_AesCtr_Code(buf32 + 4, (Byte *)buf32, 1); + buf = (const Byte *)buf32; + pos = 0; + do + *data++ ^= buf[pos++]; + while (--size != 0 && pos != AES_BLOCK_SIZE); + } + p->pos = pos; +} + +STDMETHODIMP_(UInt32) CEncoder::Filter(Byte *data, UInt32 size) +{ + AesCtr2_Code(&_aes, data, size); + _hmac.Update(data, size); + return size; +} + +STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size) +{ + _hmac.Update(data, size); + AesCtr2_Code(&_aes, data, size); + return size; +} + +}} diff --git a/CPP/7zip/Crypto/WzAes.h b/CPP/7zip/Crypto/WzAes.h new file mode 100755 index 0000000..c6672c6 --- /dev/null +++ b/CPP/7zip/Crypto/WzAes.h @@ -0,0 +1,125 @@ +// Crypto/WzAes.h +/* +This code implements Brian Gladman's scheme +specified in password Based File Encryption Utility: + - AES encryption (128,192,256-bit) in Counter (CTR) mode. + - HMAC-SHA1 authentication for encrypted data (10 bytes) + - Keys are derived by PPKDF2(RFC2898)-HMAC-SHA1 from ASCII password and + Salt (saltSize = aesKeySize / 2). + - 2 bytes contain Password Verifier's Code +*/ + +#ifndef __CRYPTO_WZ_AES_H +#define __CRYPTO_WZ_AES_H + +#include "../../../C/Aes.h" + +#include "Common/Buffer.h" +#include "Common/MyCom.h" +#include "Common/MyVector.h" + +#include "../ICoder.h" +#include "../IPassword.h" + +#include "HmacSha1.h" + +namespace NCrypto { +namespace NWzAes { + +const unsigned kSaltSizeMax = 16; +const unsigned kMacSize = 10; + +const UInt32 kPasswordSizeMax = 99; // 128; + +// Password Verification Code Size +const unsigned kPwdVerifCodeSize = 2; + +enum EKeySizeMode +{ + kKeySizeMode_AES128 = 1, + kKeySizeMode_AES192 = 2, + kKeySizeMode_AES256 = 3 +}; + +class CKeyInfo +{ +public: + EKeySizeMode KeySizeMode; + Byte Salt[kSaltSizeMax]; + Byte PwdVerifComputed[kPwdVerifCodeSize]; + + CByteBuffer Password; + + UInt32 GetKeySize() const { return (8 * (KeySizeMode & 3) + 8); } + UInt32 GetSaltSize() const { return (4 * (KeySizeMode & 3) + 4); } + + CKeyInfo() { Init(); } + void Init() { KeySizeMode = kKeySizeMode_AES256; } +}; + +struct CAesCtr2 +{ + unsigned pos; + unsigned offset; + UInt32 aes[4 + AES_NUM_IVMRK_WORDS + 3]; + CAesCtr2(); +}; + +void AesCtr2_Init(CAesCtr2 *p); +void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size); + +class CBaseCoder: + public ICompressFilter, + public ICryptoSetPassword, + public CMyUnknownImp +{ +protected: + CKeyInfo _key; + NSha1::CHmac _hmac; + Byte _pwdVerifFromArchive[kPwdVerifCodeSize]; + CAesCtr2 _aes; + +public: + STDMETHOD(Init)(); + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) = 0; + + STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); + + UInt32 GetHeaderSize() const { return _key.GetSaltSize() + kPwdVerifCodeSize; } + bool SetKeyMode(unsigned mode) + { + if (mode < kKeySizeMode_AES128 || mode > kKeySizeMode_AES256) + return false; + _key.KeySizeMode = (EKeySizeMode)mode; + return true; + } +}; + +class CEncoder: + public CBaseCoder +{ +public: + MY_UNKNOWN_IMP1(ICryptoSetPassword) + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); + HRESULT WriteHeader(ISequentialOutStream *outStream); + HRESULT WriteFooter(ISequentialOutStream *outStream); +}; + +class CDecoder: + public CBaseCoder, + public ICompressSetDecoderProperties2 +{ +public: + MY_UNKNOWN_IMP2( + ICryptoSetPassword, + ICompressSetDecoderProperties2) + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); + HRESULT ReadHeader(ISequentialInStream *inStream); + bool CheckPasswordVerifyCode(); + HRESULT CheckMac(ISequentialInStream *inStream, bool &isOK); +}; + +}} + +#endif diff --git a/CPP/7zip/Crypto/ZipCrypto.cpp b/CPP/7zip/Crypto/ZipCrypto.cpp new file mode 100755 index 0000000..13f7f06 --- /dev/null +++ b/CPP/7zip/Crypto/ZipCrypto.cpp @@ -0,0 +1,88 @@ +// Crypto/ZipCrypto.cpp + +#include "StdAfx.h" + +#include "../../../C/7zCrc.h" + +#include "../Common/StreamUtils.h" + +#include "RandGen.h" +#include "ZipCrypto.h" + +namespace NCrypto { +namespace NZip { + +void CCipher::UpdateKeys(Byte b) +{ + Keys[0] = CRC_UPDATE_BYTE(Keys[0], b); + Keys[1] = (Keys[1] + (Keys[0] & 0xFF)) * 0x8088405 + 1; + Keys[2] = CRC_UPDATE_BYTE(Keys[2], (Byte)(Keys[1] >> 24)); +} + +STDMETHODIMP CCipher::CryptoSetPassword(const Byte *password, UInt32 passwordLen) +{ + Keys[0] = 0x12345678; + Keys[1] = 0x23456789; + Keys[2] = 0x34567890; + UInt32 i; + for (i = 0; i < passwordLen; i++) + UpdateKeys(password[i]); + for (i = 0; i < 3; i++) + Keys2[i] = Keys[i]; + return S_OK; +} + +STDMETHODIMP CCipher::Init() +{ + return S_OK; +} + +Byte CCipher::DecryptByteSpec() +{ + UInt32 temp = Keys[2] | 2; + return (Byte)((temp * (temp ^ 1)) >> 8); +} + +HRESULT CEncoder::WriteHeader(ISequentialOutStream *outStream, UInt32 crc) +{ + Byte h[kHeaderSize]; + g_RandomGenerator.Generate(h, kHeaderSize - 2); + h[kHeaderSize - 1] = (Byte)(crc >> 24); + h[kHeaderSize - 2] = (Byte)(crc >> 16); + RestoreKeys(); + Filter(h, kHeaderSize); + return WriteStream(outStream, h, kHeaderSize); +} + +STDMETHODIMP_(UInt32) CEncoder::Filter(Byte *data, UInt32 size) +{ + for (UInt32 i = 0; i < size; i++) + { + Byte b = data[i]; + data[i] = (Byte)(b ^ DecryptByteSpec());; + UpdateKeys(b); + } + return size; +} + +HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream) +{ + Byte h[kHeaderSize]; + RINOK(ReadStream_FAIL(inStream, h, kHeaderSize)); + RestoreKeys(); + Filter(h, kHeaderSize); + return S_OK; +} + +STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size) +{ + for (UInt32 i = 0; i < size; i++) + { + Byte c = (Byte)(data[i] ^ DecryptByteSpec()); + UpdateKeys(c); + data[i] = c; + } + return size; +} + +}} diff --git a/CPP/7zip/Crypto/ZipCrypto.h b/CPP/7zip/Crypto/ZipCrypto.h new file mode 100755 index 0000000..16a2515 --- /dev/null +++ b/CPP/7zip/Crypto/ZipCrypto.h @@ -0,0 +1,56 @@ +// Crypto/ZipCrypto.h + +#ifndef __CRYPTO_ZIP_CRYPTO_H +#define __CRYPTO_ZIP_CRYPTO_H + +#include "Common/MyCom.h" + +#include "../ICoder.h" +#include "../IPassword.h" + +namespace NCrypto { +namespace NZip { + +const unsigned kHeaderSize = 12; + +class CCipher: + public ICompressFilter, + public ICryptoSetPassword, + public CMyUnknownImp +{ + UInt32 Keys[3]; + UInt32 Keys2[3]; + +protected: + void UpdateKeys(Byte b); + Byte DecryptByteSpec(); + void RestoreKeys() + { + for (int i = 0; i < 3; i++) + Keys[i] = Keys2[i]; + } + +public: + STDMETHOD(Init)(); + STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); +}; + +class CEncoder: public CCipher +{ +public: + MY_UNKNOWN_IMP1(ICryptoSetPassword) + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); + HRESULT WriteHeader(ISequentialOutStream *outStream, UInt32 crc); +}; + +class CDecoder: public CCipher +{ +public: + MY_UNKNOWN_IMP1(ICryptoSetPassword) + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); + HRESULT ReadHeader(ISequentialInStream *inStream); +}; + +}} + +#endif diff --git a/CPP/7zip/Crypto/ZipStrong.cpp b/CPP/7zip/Crypto/ZipStrong.cpp new file mode 100755 index 0000000..c9b370e --- /dev/null +++ b/CPP/7zip/Crypto/ZipStrong.cpp @@ -0,0 +1,164 @@ +// Crypto/ZipStrong.cpp + +#include "StdAfx.h" + +#include "../../../C/7zCrc.h" +#include "../../../C/CpuArch.h" + +#include "../Common/StreamUtils.h" + +#include "MyAes.h" +#include "Sha1.h" +#include "ZipStrong.h" + +namespace NCrypto { +namespace NZipStrong { + +static const UInt16 kAES128 = 0x660E; + +// DeriveKey* function is similar to CryptDeriveKey() from Windows. +// But MSDN tells that we need such scheme only if +// "the required key length is longer than the hash value" +// but ZipStrong uses it always. + +static void DeriveKey2(const Byte *digest, Byte c, Byte *dest) +{ + Byte buf[64]; + memset(buf, c, 64); + for (unsigned i = 0; i < NSha1::kDigestSize; i++) + buf[i] ^= digest[i]; + NSha1::CContext sha; + sha.Init(); + sha.Update(buf, 64); + sha.Final(dest); +} + +static void DeriveKey(NSha1::CContext &sha, Byte *key) +{ + Byte digest[NSha1::kDigestSize]; + sha.Final(digest); + Byte temp[NSha1::kDigestSize * 2]; + DeriveKey2(digest, 0x36, temp); + DeriveKey2(digest, 0x5C, temp + NSha1::kDigestSize); + memcpy(key, temp, 32); +} + +void CKeyInfo::SetPassword(const Byte *data, UInt32 size) +{ + NSha1::CContext sha; + sha.Init(); + sha.Update(data, size); + DeriveKey(sha, MasterKey); +} + +STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size) +{ + _key.SetPassword(data, size); + return S_OK; +} + +HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream, UInt32 /* crc */, UInt64 /* unpackSize */) +{ + Byte temp[4]; + RINOK(ReadStream_FALSE(inStream, temp, 2)); + _ivSize = GetUi16(temp); + if (_ivSize == 0) + { + return E_NOTIMPL; + /* + SetUi32(_iv, crc); + for (int i = 0; i < 8; i++) + _iv[4 + i] = (Byte)(unpackSize >> (8 * i)); + SetUi32(_iv + 12, 0); + */ + } + else if (_ivSize == 16) + { + RINOK(ReadStream_FALSE(inStream, _iv, _ivSize)); + } + else + return E_NOTIMPL; + RINOK(ReadStream_FALSE(inStream, temp, 4)); + _remSize = GetUi32(temp); + const UInt32 kAlign = 16; + if (_remSize < 16 || _remSize > (1 << 18)) + return E_NOTIMPL; + if (_remSize + kAlign > _buf.GetCapacity()) + { + _buf.Free(); + _buf.SetCapacity(_remSize + kAlign); + _bufAligned = (Byte *)((ptrdiff_t)((Byte *)_buf + kAlign - 1) & ~(ptrdiff_t)(kAlign - 1)); + } + return ReadStream_FALSE(inStream, _bufAligned, _remSize); +} + +HRESULT CDecoder::CheckPassword(bool &passwOK) +{ + passwOK = false; + if (_remSize < 16) + return E_NOTIMPL; + Byte *p = _bufAligned; + UInt16 format = GetUi16(p); + if (format != 3) + return E_NOTIMPL; + UInt16 algId = GetUi16(p + 2); + if (algId < kAES128) + return E_NOTIMPL; + algId -= kAES128; + if (algId > 2) + return E_NOTIMPL; + UInt16 bitLen = GetUi16(p + 4); + UInt16 flags = GetUi16(p + 6); + if (algId * 64 + 128 != bitLen) + return E_NOTIMPL; + _key.KeySize = 16 + algId * 8; + if ((flags & 1) == 0) + return E_NOTIMPL; + if ((flags & 0x4000) != 0) + { + // Use 3DES + return E_NOTIMPL; + } + + UInt32 rdSize = GetUi16(p + 8); + if ((rdSize & 0xF) != 0 || rdSize + 16 > _remSize) + return E_NOTIMPL; + memmove(p, p + 10, rdSize); + Byte *validData = p + rdSize + 16; + if (GetUi32(validData - 6) != 0) // reserved + return E_NOTIMPL; + UInt32 validSize = GetUi16(validData - 2); + if ((validSize & 0xF) != 0 || 16 + rdSize + validSize != _remSize) + return E_NOTIMPL; + + + { + RINOK(SetKey(_key.MasterKey, _key.KeySize)); + RINOK(SetInitVector(_iv, 16)); + Init(); + Filter(p, rdSize); + } + + Byte fileKey[32]; + NSha1::CContext sha; + sha.Init(); + sha.Update(_iv, 16); + sha.Update(p, rdSize - 16); // we don't use last 16 bytes (PAD bytes) + DeriveKey(sha, fileKey); + + RINOK(SetKey(fileKey, _key.KeySize)); + RINOK(SetInitVector(_iv, 16)); + Init(); + Filter(validData, validSize); + + if (validSize < 4) + return E_NOTIMPL; + validSize -= 4; + if (GetUi32(validData + validSize) != CrcCalc(validData, validSize)) + return S_OK; + passwOK = true; + Init(); + return S_OK; +} + +}} diff --git a/CPP/7zip/Crypto/ZipStrong.h b/CPP/7zip/Crypto/ZipStrong.h new file mode 100755 index 0000000..f3f7d6d --- /dev/null +++ b/CPP/7zip/Crypto/ZipStrong.h @@ -0,0 +1,47 @@ +// Crypto/ZipStrong.h + +#ifndef __CRYPTO_ZIP_STRONG_H +#define __CRYPTO_ZIP_STRONG_H + +#include "Common/Buffer.h" + +#include "../IPassword.h" + +#include "MyAes.h" + +namespace NCrypto { +namespace NZipStrong { + +struct CKeyInfo +{ + Byte MasterKey[32]; + UInt32 KeySize; + void SetPassword(const Byte *data, UInt32 size); +}; + +class CBaseCoder: + public CAesCbcDecoder, + public ICryptoSetPassword +{ +protected: + CKeyInfo _key; + CByteBuffer _buf; + Byte *_bufAligned; +public: + STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); +}; + +class CDecoder: public CBaseCoder +{ + UInt32 _ivSize; + Byte _iv[16]; + UInt32 _remSize; +public: + MY_UNKNOWN_IMP1(ICryptoSetPassword) + HRESULT ReadHeader(ISequentialInStream *inStream, UInt32 crc, UInt64 unpackSize); + HRESULT CheckPassword(bool &passwOK); +}; + +}} + +#endif diff --git a/CPP/7zip/GuiCommon.rc b/CPP/7zip/GuiCommon.rc new file mode 100755 index 0000000..5280b4b --- /dev/null +++ b/CPP/7zip/GuiCommon.rc @@ -0,0 +1,70 @@ +#include +#include +#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 + +#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_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 diff --git a/CPP/7zip/Guid.txt b/CPP/7zip/Guid.txt new file mode 100755 index 0000000..cbd45a4 --- /dev/null +++ b/CPP/7zip/Guid.txt @@ -0,0 +1,170 @@ +{23170F69-40C1-278A-0000-00yy00xx0000} + +00 IProgress.h + + 05 IProgress + +01 IFolderArchive.h + + 05 IArchiveFolder + // 06 IInFolderArchive // old + 07 IFileExtractCallback.h::IFolderArchiveExtractCallback + 0A IOutFolderArchive + 0B IFolderArchiveUpdateCallback + 0C Agent.h::IArchiveFolderInternal + 0D + 0E IInFolderArchive + +03 IStream.h + + 01 ISequentialInStream + 02 ISequentialOutStream + 03 IInStream + 04 IOutStream + 06 IStreamGetSize + 07 IOutStreamFlush + + +04 ICoder.h + + 04 ICompressProgressInfo + 05 ICompressCoder + 18 ICompressCoder2 + 20 ICompressSetCoderProperties + 21 ICompressSetDecoderProperties // + 22 ICompressSetDecoderProperties2 + 23 ICompressWriteCoderProperties + 24 ICompressGetInStreamProcessedSize + 25 ICompressSetCoderMt + 30 ICompressGetSubStreamSize + 31 ICompressSetInStream + 32 ICompressSetOutStream + 33 ICompressSetInStreamSize + 34 ICompressSetOutStreamSize + 35 ICompressSetBufSize + 40 ICompressFilter + 60 ICompressCodecsInfo + 61 ISetCompressCodecsInfo + 80 ICryptoProperties + 88 ICryptoResetSalt + 8C ICryptoResetInitVector + 90 ICryptoSetPassword + A0 ICryptoSetCRC + + +05 IPassword.h + + 10 ICryptoGetTextPassword + 11 ICryptoGetTextPassword2 + + +06 IArchive.h + + 03 ISetProperties + + 10 IArchiveOpenCallback + 20 IArchiveExtractCallback + 30 IArchiveOpenVolumeCallback + 40 IInArchiveGetStream + 50 IArchiveOpenSetSubArchiveName + 60 IInArchive + 61 IArchiveOpenSeq + + 80 IArchiveUpdateCallback + 82 IArchiveUpdateCallback2 + A0 IOutArchive + + + +08 IFolder.h + + 00 IFolderFolder + 01 IEnumProperties + 02 IFolderGetTypeID + 03 IFolderGetPath + 04 IFolderWasChanged + 05 // IFolderReload + 06 IFolderOperations + 07 IFolderGetSystemIconIndex + 08 IFolderGetItemFullSize + 09 IFolderClone + 0A IFolderSetFlatMode + 0B IFolderOperationsExtractCallback + 0C // + 0D // + 0E IFolderProperties + 0F + 10 IFolderArcProps + 11 IGetFolderArcProps + + +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 + + 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 Bkf + E9 Chm + EA Split + EB Rpm + EC Deb + ED Cpio + EE Tar + EF GZip + +{23170F69-40C1-278A-1000-000100030000} CAgentArchiveHandle +{23170F69-40C1-278A-1000-000100020000} ContextMenu.h::CZipContextMenu + +{23170F69-40C1-278B- old codecs clsids + +{23170F69-40C1-278D-1000-000100020000} OptionsDialog.h::CLSID_CSevenZipOptions + +{23170F69-40C1-2790-id} Codec Decoders +{23170F69-40C1-2791-id} Codec Encoders diff --git a/CPP/7zip/ICoder.h b/CPP/7zip/ICoder.h new file mode 100755 index 0000000..cb74f98 --- /dev/null +++ b/CPP/7zip/ICoder.h @@ -0,0 +1,186 @@ +// 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; +}; + +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 **inStreams, const UInt64 **inSizes, UInt32 numInStreams, + ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, + ICompressProgressInfo *progress) PURE; +}; + +namespace NCoderPropID +{ + enum EEnum + { + kDefaultProp = 0, + kDictionarySize, + kUsedMemorySize, + kOrder, + kBlockSize, + kPosStateBits, + kLitContextBits, + kLitPosBits, + kNumFastBytes, + kMatchFinder, + kMatchFinderCycles, + kNumPasses, + kAlgorithm, + kNumThreads, + kEndMarker + }; +} + +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) +{ + 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(ICompressGetSubStreamSize, 0x30) +{ + STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE; +}; + +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; +}; + +CODER_INTERFACE(ICompressSetBufSize, 0x35) +{ + STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size) PURE; + STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size) PURE; +}; + +CODER_INTERFACE(ICompressFilter, 0x40) +{ + STDMETHOD(Init)() PURE; + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE; + // Filter converts as most as possible bytes + // Filter return outSize (UInt32) + // if (outSize <= size): Filter have converted outSize bytes + // if (outSize > size): Filter have not converted anything. + // and it needs at least outSize bytes to convert one block + // (it's for crypto block algorithms). +}; + +CODER_INTERFACE(ICompressCodecsInfo, 0x60) +{ + STDMETHOD(GetNumberOfMethods)(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; +}; + +CODER_INTERFACE(ICryptoSetPassword, 0x90) +{ + STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE; +}; + +CODER_INTERFACE(ICryptoSetCRC, 0xA0) +{ + STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE; +}; + +////////////////////// +// It's for DLL file +namespace NMethodPropID +{ + enum EEnum + { + kID, + kName, + kDecoder, + kEncoder, + kInStreams, + kOutStreams, + kDescription, + kDecoderIsAssigned, + kEncoderIsAssigned + }; +} + +#endif diff --git a/CPP/7zip/IDecl.h b/CPP/7zip/IDecl.h new file mode 100755 index 0000000..768bbe7 --- /dev/null +++ b/CPP/7zip/IDecl.h @@ -0,0 +1,15 @@ +// IDecl.h + +#ifndef __IDECL_H +#define __IDECL_H + +#include "../Common/MyUnknown.h" + +#define DECL_INTERFACE_SUB(i, base, groupId, subId) \ +DEFINE_GUID(IID_ ## i, \ +0x23170F69, 0x40C1, 0x278A, 0, 0, 0, (groupId), 0, (subId), 0, 0); \ +struct i: public base + +#define DECL_INTERFACE(i, groupId, subId) DECL_INTERFACE_SUB(i, IUnknown, groupId, subId) + +#endif diff --git a/CPP/7zip/IPassword.h b/CPP/7zip/IPassword.h new file mode 100755 index 0000000..5679d84 --- /dev/null +++ b/CPP/7zip/IPassword.h @@ -0,0 +1,24 @@ +// IPassword.h + +#ifndef __IPASSWORD_H +#define __IPASSWORD_H + +#include "../Common/MyUnknown.h" +#include "../Common/Types.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/CPP/7zip/IProgress.h b/CPP/7zip/IProgress.h new file mode 100755 index 0000000..09486ba --- /dev/null +++ b/CPP/7zip/IProgress.h @@ -0,0 +1,33 @@ +// Interface/IProgress.h + +#ifndef __IPROGRESS_H +#define __IPROGRESS_H + +#include "../Common/MyUnknown.h" +#include "../Common/Types.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) +}; + +/* +// {23170F69-40C1-278A-0000-000000050002} +DEFINE_GUID(IID_IProgress2, +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02); +MIDL_INTERFACE("23170F69-40C1-278A-0000-000000050002") +IProgress2: public IUnknown +{ +public: + STDMETHOD(SetTotal)(const UInt64 *total) PURE; + STDMETHOD(SetCompleted)(const UInt64 *completeValue) PURE; +}; +*/ + +#endif diff --git a/CPP/7zip/IStream.h b/CPP/7zip/IStream.h new file mode 100755 index 0000000..89f02f5 --- /dev/null +++ b/CPP/7zip/IStream.h @@ -0,0 +1,58 @@ +// IStream.h + +#ifndef __ISTREAM_H +#define __ISTREAM_H + +#include "../Common/MyUnknown.h" +#include "../Common/Types.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; + /* + Out: if size != 0, return_value = S_OK and (*processedSize == 0), + then there are no more bytes in stream. + if (size > 0) && there are bytes in stream, + this function must read at least 1 byte. + This function is allowed to read less than number of remaining bytes in stream. + You must call Read function in loop, if you need exact amount of data + */ +}; + +STREAM_INTERFACE(ISequentialOutStream, 0x02) +{ + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE; + /* + if (size > 0) this function must write at least 1 byte. + This function is allowed to write less than "size". + You must call Write function in loop, if you need to write exact amount of data + */ +}; + +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(IOutStreamFlush, 0x07) +{ + STDMETHOD(Flush)() PURE; +}; + +#endif diff --git a/CPP/7zip/MyVersion.h b/CPP/7zip/MyVersion.h new file mode 100755 index 0000000..f549249 --- /dev/null +++ b/CPP/7zip/MyVersion.h @@ -0,0 +1,8 @@ +#define MY_VER_MAJOR 9 +#define MY_VER_MINOR 20 +#define MY_VER_BUILD 0 +#define MY_VERSION "9.20" +#define MY_7ZIP_VERSION "7-Zip 9.20" +#define MY_DATE "2010-11-18" +#define MY_COPYRIGHT "Copyright (c) 1999-2010 Igor Pavlov" +#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE diff --git a/CPP/7zip/MyVersionInfo.rc b/CPP/7zip/MyVersionInfo.rc new file mode 100755 index 0000000..84e4ac3 --- /dev/null +++ b/CPP/7zip/MyVersionInfo.rc @@ -0,0 +1,52 @@ +#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 +#include "MyVersion.h" + +#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/CPP/7zip/PropID.h b/CPP/7zip/PropID.h new file mode 100755 index 0000000..1aabc65 --- /dev/null +++ b/CPP/7zip/PropID.h @@ -0,0 +1,76 @@ +// PropID.h + +#ifndef __7ZIP_PROPID_H +#define __7ZIP_PROPID_H + +enum +{ + kpidNoProperty = 0, + kpidMainSubfile = 1, + kpidHandlerItemIndex = 2, + 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, + kpidLink, + kpidError, + + kpidTotalSize = 0x1100, + kpidFreeSpace, + kpidClusterSize, + kpidVolumeName, + + kpidLocalName = 0x1200, + kpidProvider, + + kpidUserDefined = 0x10000 +}; + +#endif diff --git a/CPP/7zip/SubBuild.mak b/CPP/7zip/SubBuild.mak new file mode 100755 index 0000000..0c49d3b --- /dev/null +++ b/CPP/7zip/SubBuild.mak @@ -0,0 +1,3 @@ + cd $(@D) + $(MAKE) -nologo $(TARGETS) + cd .. diff --git a/CPP/7zip/UI/Agent/Agent.cpp b/CPP/7zip/UI/Agent/Agent.cpp new file mode 100755 index 0000000..acbedcb --- /dev/null +++ b/CPP/7zip/UI/Agent/Agent.cpp @@ -0,0 +1,645 @@ +// Agent.cpp + +#include "StdAfx.h" + +#include "../../../../C/Sort.h" + +#include "Common/ComTry.h" + +#include "../Common/ArchiveExtractCallback.h" + +#include "Agent.h" + +using namespace NWindows; + +STDMETHODIMP CAgentFolder::GetAgentFolder(CAgentFolder **agentFolder) +{ + *agentFolder = this; + return S_OK; +} + +void CAgentFolder::LoadFolder(CProxyFolder *folder) +{ + int i; + CProxyItem item; + item.Folder = folder; + for (i = 0; i < folder->Folders.Size(); i++) + { + item.Index = i; + _items.Add(item); + LoadFolder(&folder->Folders[i]); + } + int start = folder->Folders.Size(); + for (i = 0; i < folder->Files.Size(); i++) + { + item.Index = start + i; + _items.Add(item); + } +} + +STDMETHODIMP CAgentFolder::LoadItems() +{ + if (!_agentSpec->_archiveLink.IsOpen) + return E_FAIL; + _items.Clear(); + if (_flatMode) + LoadFolder(_proxyFolderItem); + return S_OK; +} + +STDMETHODIMP CAgentFolder::GetNumberOfItems(UInt32 *numItems) +{ + if (_flatMode) + *numItems = _items.Size(); + else + *numItems = _proxyFolderItem->Folders.Size() +_proxyFolderItem->Files.Size(); + return S_OK; +} + +UString CAgentFolder::GetName(UInt32 index) const +{ + UInt32 realIndex; + const CProxyFolder *folder; + if (_flatMode) + { + const CProxyItem &item = _items[index]; + folder = item.Folder; + realIndex = item.Index; + } + else + { + folder = _proxyFolderItem; + realIndex = index; + } + + if (realIndex < (UInt32)folder->Folders.Size()) + return folder->Folders[realIndex].Name; + return folder->Files[realIndex - folder->Folders.Size()].Name; +} + +UString CAgentFolder::GetPrefix(UInt32 index) const +{ + if (!_flatMode) + return UString(); + const CProxyItem &item = _items[index]; + const CProxyFolder *folder = item.Folder; + UString path; + while (folder != _proxyFolderItem) + { + path = folder->Name + UString(WCHAR_PATH_SEPARATOR) + path; + folder = folder->Parent; + } + return path; +} + +UString CAgentFolder::GetFullPathPrefixPlusPrefix(UInt32 index) const +{ + return _proxyFolderItem->GetFullPathPrefix() + GetPrefix(index); +} + +void CAgentFolder::GetPrefixIfAny(UInt32 index, NCOM::CPropVariant &prop) const +{ + if (!_flatMode) + return; + prop = GetPrefix(index); +} + + +STDMETHODIMP CAgentFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + const CProxyFolder *folder; + UInt32 realIndex; + if (_flatMode) + { + const CProxyItem &item = _items[itemIndex]; + folder = item.Folder; + realIndex = item.Index; + } + else + { + folder = _proxyFolderItem; + realIndex = itemIndex; + } + + if (realIndex < (UInt32)folder->Folders.Size()) + { + const CProxyFolder &item = folder->Folders[realIndex]; + if (!_flatMode && propID == kpidSize) + prop = item.Size; + else if (!_flatMode && propID == kpidPackSize) + prop = item.PackSize; + else + switch(propID) + { + case kpidIsDir: prop = true; break; + case kpidNumSubDirs: prop = item.NumSubFolders; break; + case kpidNumSubFiles: prop = item.NumSubFiles; break; + case kpidName: prop = item.Name; break; + case kpidCRC: + { + if (item.IsLeaf) + { + RINOK(_agentSpec->GetArchive()->GetProperty(item.Index, propID, value)); + } + if (item.CrcIsDefined && value->vt == VT_EMPTY) + prop = item.Crc; + break; + } + case kpidPrefix: GetPrefixIfAny(itemIndex, prop); break; + + default: + if (item.IsLeaf) + return _agentSpec->GetArchive()->GetProperty(item.Index, propID, value); + } + } + else + { + realIndex -= folder->Folders.Size(); + const CProxyFile &item = folder->Files[realIndex]; + switch(propID) + { + case kpidIsDir: prop = false; break; + case kpidName: prop = item.Name; break; + case kpidPrefix: GetPrefixIfAny(itemIndex, prop); break; + default: + return _agentSpec->GetArchive()->GetProperty(item.Index, propID, value); + } + } + prop.Detach(value); + return S_OK; +} + +HRESULT CAgentFolder::BindToFolder(CProxyFolder *folder, IFolderFolder **resultFolder) +{ + CMyComPtr parentFolder; + if (folder->Parent != _proxyFolderItem) + { + RINOK(BindToFolder(folder->Parent, &parentFolder)); + } + else + parentFolder = this; + CAgentFolder *folderSpec = new CAgentFolder; + CMyComPtr agentFolder = folderSpec; + folderSpec->Init(_proxyArchive, folder, parentFolder, _agentSpec); + *resultFolder = agentFolder.Detach(); + return S_OK; +} + +STDMETHODIMP CAgentFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder) +{ + COM_TRY_BEGIN + + CProxyFolder *folder; + UInt32 realIndex; + if (_flatMode) + { + const CProxyItem &item = _items[index]; + folder = item.Folder; + realIndex = item.Index; + } + else + { + folder = _proxyFolderItem; + realIndex = index; + } + if (realIndex >= (UInt32)folder->Folders.Size()) + return E_INVALIDARG; + return BindToFolder(&folder->Folders[realIndex], resultFolder); + COM_TRY_END +} + +STDMETHODIMP CAgentFolder::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder) +{ + COM_TRY_BEGIN + int index = _proxyFolderItem->FindDirSubItemIndex(name); + if (index < 0) + return E_INVALIDARG; + return BindToFolder(index, resultFolder); + COM_TRY_END +} + +STDMETHODIMP CAgentFolder::BindToParentFolder(IFolderFolder **resultFolder) +{ + COM_TRY_BEGIN + CMyComPtr parentFolder = _parentFolder; + *resultFolder = parentFolder.Detach(); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CAgentFolder::GetStream(UInt32 index, ISequentialInStream **stream) +{ + CMyComPtr getStream; + _agentSpec->GetArchive()->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream); + if (!getStream) + return S_OK; + + const CProxyFolder *folder; + UInt32 realIndex; + if (_flatMode) + { + const CProxyItem &item = _items[index]; + folder = item.Folder; + realIndex = item.Index; + } + else + { + folder = _proxyFolderItem; + realIndex = index; + } + + UInt32 indexInArchive; + if (realIndex < (UInt32)folder->Folders.Size()) + { + const CProxyFolder &item = folder->Folders[realIndex]; + if (!item.IsLeaf) + return S_OK; + indexInArchive = item.Index; + } + else + indexInArchive = folder->Files[realIndex - folder->Folders.Size()].Index; + return getStream->GetStream(indexInArchive, stream); +} + +STATPROPSTG kProperties[] = +{ + { NULL, kpidNumSubDirs, VT_UI4}, + { NULL, kpidNumSubFiles, VT_UI4}, + { NULL, kpidPrefix, VT_BSTR} +}; + +static const UInt32 kNumProperties = sizeof(kProperties) / sizeof(kProperties[0]); + +struct CArchiveItemPropertyTemp +{ + UString Name; + PROPID ID; + VARTYPE Type; +}; + +STDMETHODIMP CAgentFolder::GetNumberOfProperties(UInt32 *numProps) +{ + COM_TRY_BEGIN + RINOK(_agentSpec->GetArchive()->GetNumberOfProperties(numProps)); + *numProps += kNumProperties; + if (!_flatMode) + (*numProps)--; + if (!_agentSpec->_proxyArchive->ThereIsPathProp) + (*numProps)++; + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CAgentFolder::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) +{ + COM_TRY_BEGIN + UInt32 numProps; + _agentSpec->GetArchive()->GetNumberOfProperties(&numProps); + if (!_agentSpec->_proxyArchive->ThereIsPathProp) + { + if (index == 0) + { + *propID = kpidName; + *varType = VT_BSTR; + *name = 0; + return S_OK; + } + index--; + } + + if (index < numProps) + { + RINOK(_agentSpec->GetArchive()->GetPropertyInfo(index, name, propID, varType)); + if (*propID == kpidPath) + *propID = kpidName; + } + else + { + const STATPROPSTG &srcItem = kProperties[index - numProps]; + *propID = srcItem.propid; + *varType = srcItem.vt; + *name = 0; + } + return S_OK; + COM_TRY_END +} + +STATPROPSTG kFolderProps[] = +{ + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidNumSubDirs, VT_UI4}, + { NULL, kpidNumSubFiles, VT_UI4}, + { NULL, kpidCRC, VT_UI4} +}; + +static const UInt32 kNumFolderProps = sizeof(kFolderProps) / sizeof(kFolderProps[0]); + +STDMETHODIMP CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidSize: prop = _proxyFolderItem->Size; break; + case kpidPackSize: prop = _proxyFolderItem->PackSize; break; + case kpidNumSubDirs: prop = _proxyFolderItem->NumSubFolders; break; + case kpidNumSubFiles: prop = _proxyFolderItem->NumSubFiles; break; + case kpidName: prop = _proxyFolderItem->Name; break; + case kpidPath: prop = _proxyFolderItem->GetFullPathPrefix(); break; + case kpidType: prop = UString(L"7-Zip.") + _agentSpec->ArchiveType; break; + case kpidCRC: if (_proxyFolderItem->CrcIsDefined) prop = _proxyFolderItem->Crc; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CAgentFolder::GetNumberOfFolderProperties(UInt32 *numProps) +{ + *numProps = kNumFolderProps; + return S_OK; +} + +STDMETHODIMP CAgentFolder::GetFolderPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) +{ + // if (index < kNumFolderProps) + { + const STATPROPSTG &srcItem = kFolderProps[index]; + *propID = srcItem.propid; + *varType = srcItem.vt; + *name = 0; + return S_OK; + } +} + +STDMETHODIMP CAgentFolder::GetFolderArcProps(IFolderArcProps **object) +{ + CMyComPtr temp = _agentSpec; + *object = temp.Detach(); + return S_OK; +} + +#ifdef NEW_FOLDER_INTERFACE + +STDMETHODIMP CAgentFolder::SetFlatMode(Int32 flatMode) +{ + _flatMode = IntToBool(flatMode); + return S_OK; +} + +#endif + +void CAgentFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const +{ + if (!_flatMode) + { + _proxyFolderItem->GetRealIndices(indices, numItems, realIndices); + return; + } + realIndices.Clear(); + for(UInt32 i = 0; i < numItems; i++) + { + const CProxyItem &item = _items[indices[i]]; + const CProxyFolder *folder = item.Folder; + UInt32 realIndex = item.Index; + if (realIndex < (UInt32)folder->Folders.Size()) + continue; + realIndices.Add(folder->Files[realIndex - folder->Folders.Size()].Index); + } + HeapSort(&realIndices.Front(), realIndices.Size()); +} + +STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices, + UInt32 numItems, + NExtract::NPathMode::EEnum pathMode, + NExtract::NOverwriteMode::EEnum overwriteMode, + const wchar_t *path, + Int32 testMode, + IFolderArchiveExtractCallback *extractCallback2) +{ + COM_TRY_BEGIN + CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; + CMyComPtr extractCallback = extractCallbackSpec; + UStringVector pathParts; + CProxyFolder *currentProxyFolder = _proxyFolderItem; + while (currentProxyFolder->Parent) + { + pathParts.Insert(0, currentProxyFolder->Name); + currentProxyFolder = currentProxyFolder->Parent; + } + + /* + if (_flatMode) + pathMode = NExtract::NPathMode::kNoPathnames; + */ + + extractCallbackSpec->InitForMulti(false, pathMode, overwriteMode); + + extractCallbackSpec->Init(NULL, &_agentSpec->GetArc(), + extractCallback2, + false, testMode ? true : false, false, + (path ? path : L""), + pathParts, + (UInt64)(Int64)-1); + CUIntVector realIndices; + GetRealIndices(indices, numItems, realIndices); + return _agentSpec->GetArchive()->Extract(&realIndices.Front(), + realIndices.Size(), testMode, extractCallback); + COM_TRY_END +} + +///////////////////////////////////////// +// CAgent + +CAgent::CAgent(): + _proxyArchive(NULL), + _codecs(0) +{ +} + +CAgent::~CAgent() +{ + if (_proxyArchive != NULL) + delete _proxyArchive; +} + +STDMETHODIMP CAgent::Open( + IInStream *inStream, + const wchar_t *filePath, + const wchar_t *arcFormat, + BSTR *archiveType, + IArchiveOpenCallback *openArchiveCallback) +{ + COM_TRY_BEGIN + _archiveFilePath = filePath; + NFile::NFind::CFileInfoW fi; + if (!inStream) + { + if (!fi.Find(_archiveFilePath)) + return ::GetLastError(); + if (fi.IsDir()) + return E_FAIL; + } + CArcInfoEx archiverInfo0, archiverInfo1; + + _compressCodecsInfo.Release(); + _codecs = new CCodecs; + _compressCodecsInfo = _codecs; + RINOK(_codecs->Load()); + + CIntVector formatIndices; + if (!_codecs->FindFormatForArchiveType(arcFormat, formatIndices)) + return S_FALSE; + + RINOK(_archiveLink.Open(_codecs, formatIndices, false, inStream, _archiveFilePath, openArchiveCallback)); + + CArc &arc = _archiveLink.Arcs.Back(); + if (!inStream) + { + arc.MTimeDefined = !fi.IsDevice; + arc.MTime = fi.MTime; + } + + ArchiveType = _codecs->Formats[arc.FormatIndex].Name; + if (archiveType == 0) + return S_OK; + return StringToBstr(ArchiveType, archiveType); + COM_TRY_END +} + +STDMETHODIMP CAgent::ReOpen(IArchiveOpenCallback *openArchiveCallback) +{ + COM_TRY_BEGIN + if (_proxyArchive != NULL) + { + delete _proxyArchive; + _proxyArchive = NULL; + } + RINOK(_archiveLink.ReOpen(_codecs, _archiveFilePath, openArchiveCallback)); + return ReadItems(); + COM_TRY_END +} + +STDMETHODIMP CAgent::Close() +{ + COM_TRY_BEGIN + return _archiveLink.Close(); + COM_TRY_END +} + +/* +STDMETHODIMP CAgent::EnumProperties(IEnumSTATPROPSTG **EnumProperties) +{ + return _archive->EnumProperties(EnumProperties); +} +*/ + +HRESULT CAgent::ReadItems() +{ + if (_proxyArchive != NULL) + return S_OK; + _proxyArchive = new CProxyArchive(); + return _proxyArchive->Load(GetArc(), NULL); +} + +STDMETHODIMP CAgent::BindToRootFolder(IFolderFolder **resultFolder) +{ + COM_TRY_BEGIN + RINOK(ReadItems()); + CAgentFolder *folderSpec = new CAgentFolder; + CMyComPtr rootFolder = folderSpec; + folderSpec->Init(_proxyArchive, &_proxyArchive->RootFolder, NULL, this); + *resultFolder = rootFolder.Detach(); + return S_OK; + COM_TRY_END +} + + +STDMETHODIMP CAgent::Extract( + NExtract::NPathMode::EEnum pathMode, + NExtract::NOverwriteMode::EEnum overwriteMode, + const wchar_t *path, + Int32 testMode, + IFolderArchiveExtractCallback *extractCallback2) +{ + COM_TRY_BEGIN + CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; + CMyComPtr extractCallback = extractCallbackSpec; + extractCallbackSpec->InitForMulti(false, pathMode, overwriteMode); + extractCallbackSpec->Init(NULL, &GetArc(), + extractCallback2, + false, testMode ? true : false, false, + path, + UStringVector(), + (UInt64)(Int64)-1); + return GetArchive()->Extract(0, (UInt32)(Int32)-1, testMode, extractCallback); + COM_TRY_END +} + +STDMETHODIMP CAgent::GetNumberOfProperties(UInt32 *numProps) +{ + COM_TRY_BEGIN + return GetArchive()->GetNumberOfProperties(numProps); + COM_TRY_END +} + +STDMETHODIMP CAgent::GetPropertyInfo(UInt32 index, + BSTR *name, PROPID *propID, VARTYPE *varType) +{ + COM_TRY_BEGIN + RINOK(GetArchive()->GetPropertyInfo(index, name, propID, varType)); + if (*propID == kpidPath) + *propID = kpidName; + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CAgent::GetArcNumLevels(UInt32 *numLevels) +{ + *numLevels = _archiveLink.Arcs.Size(); + return S_OK; +} + +STDMETHODIMP CAgent::GetArcProp(UInt32 level, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + CArc &arc = _archiveLink.Arcs[level]; + switch(propID) + { + case kpidType: prop = GetTypeOfArc(arc); break; + case kpidPath: prop = arc.Path; break; + default: return arc.Archive->GetArchiveProperty(propID, value); + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CAgent::GetArcNumProps(UInt32 level, UInt32 *numProps) +{ + return _archiveLink.Arcs[level].Archive->GetNumberOfArchiveProperties(numProps); +} + +STDMETHODIMP CAgent::GetArcPropInfo(UInt32 level, UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) +{ + return _archiveLink.Arcs[level].Archive->GetArchivePropertyInfo(index, name, propID, varType); +} + +// MainItemProperty +STDMETHODIMP CAgent::GetArcProp2(UInt32 level, PROPID propID, PROPVARIANT *value) +{ + return _archiveLink.Arcs[level - 1].Archive->GetProperty(_archiveLink.Arcs[level].SubfileIndex, propID, value); +} + +STDMETHODIMP CAgent::GetArcNumProps2(UInt32 level, UInt32 *numProps) +{ + return _archiveLink.Arcs[level - 1].Archive->GetNumberOfProperties(numProps); +} + +STDMETHODIMP CAgent::GetArcPropInfo2(UInt32 level, UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) +{ + return _archiveLink.Arcs[level - 1].Archive->GetPropertyInfo(index, name, propID, varType); +} diff --git a/CPP/7zip/UI/Agent/Agent.h b/CPP/7zip/UI/Agent/Agent.h new file mode 100755 index 0000000..38d5f47 --- /dev/null +++ b/CPP/7zip/UI/Agent/Agent.h @@ -0,0 +1,251 @@ +// Agent/Agent.h + +#ifndef __AGENT_AGENT_H +#define __AGENT_AGENT_H + +#include "Common/MyCom.h" + +#include "Windows/PropVariant.h" + +#include "../Common/OpenArchive.h" +#include "../Common/UpdateAction.h" + +#ifdef NEW_FOLDER_INTERFACE +#include "../FileManager/IFolder.h" +#include "../Common/LoadCodecs.h" +#endif + +#include "AgentProxy.h" +#include "IFolderArchive.h" + +class CAgentFolder; + +DECL_INTERFACE(IArchiveFolderInternal, 0x01, 0xC) +{ + STDMETHOD(GetAgentFolder)(CAgentFolder **agentFolder) PURE; +}; + +struct CProxyItem +{ + CProxyFolder *Folder; + UInt32 Index; +}; + +class CAgent; + +class CAgentFolder: + public IFolderFolder, + public IFolderProperties, + public IGetFolderArcProps, + public IArchiveFolder, + public IArchiveFolderInternal, + public IInArchiveGetStream, +#ifdef NEW_FOLDER_INTERFACE + public IFolderOperations, + public IFolderSetFlatMode, +#endif + public CMyUnknownImp +{ +public: + + MY_QUERYINTERFACE_BEGIN2(IFolderFolder) + MY_QUERYINTERFACE_ENTRY(IFolderProperties) + MY_QUERYINTERFACE_ENTRY(IGetFolderArcProps) + MY_QUERYINTERFACE_ENTRY(IArchiveFolder) + MY_QUERYINTERFACE_ENTRY(IArchiveFolderInternal) + MY_QUERYINTERFACE_ENTRY(IInArchiveGetStream) + #ifdef NEW_FOLDER_INTERFACE + MY_QUERYINTERFACE_ENTRY(IFolderOperations) + MY_QUERYINTERFACE_ENTRY(IFolderSetFlatMode) + #endif + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + void LoadFolder(CProxyFolder *folder); + HRESULT BindToFolder(CProxyFolder *folder, IFolderFolder **resultFolder); + void GetRealIndices(const UINT32 *indices, UINT32 numItems, CUIntVector &realIndices) const; + + INTERFACE_FolderFolder(;) + INTERFACE_FolderProperties(;) + + STDMETHOD(GetFolderArcProps)(IFolderArcProps **object); + + // IArchiveFolder + STDMETHOD(Extract)(const UINT32 *indices, UINT32 numItems, + NExtract::NPathMode::EEnum pathMode, + NExtract::NOverwriteMode::EEnum overwriteMode, + const wchar_t *path, + Int32 testMode, + IFolderArchiveExtractCallback *extractCallback); + + STDMETHOD(GetAgentFolder)(CAgentFolder **agentFolder); + + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); + + #ifdef NEW_FOLDER_INTERFACE + INTERFACE_FolderOperations(;) + + STDMETHOD(SetFlatMode)(Int32 flatMode); + #endif + + CAgentFolder(): _proxyFolderItem(NULL), _flatMode(0) {} + + void Init(CProxyArchive *proxyHandler, + CProxyFolder *proxyFolderItem, + IFolderFolder *parentFolder, + CAgent *agent) + { + _proxyArchive = proxyHandler; + _proxyFolderItem = proxyFolderItem; + _parentFolder = parentFolder; + _agent = (IInFolderArchive *)agent; + _agentSpec = agent; + } + + void GetPathParts(UStringVector &pathParts); + HRESULT CommonUpdateOperation( + bool deleteOperation, + bool createFolderOperation, + bool renameOperation, + const wchar_t *newItemName, + const NUpdateArchive::CActionSet *actionSet, + const UINT32 *indices, UINT32 numItems, + IFolderArchiveUpdateCallback *updateCallback100); + + + UString GetPrefix(UInt32 index) const; + UString GetName(UInt32 index) const; + UString GetFullPathPrefixPlusPrefix(UInt32 index) const; + void GetPrefixIfAny(UInt32 index, NWindows::NCOM::CPropVariant &propVariant) const; + +public: + CProxyArchive *_proxyArchive; + CProxyFolder *_proxyFolderItem; + CMyComPtr _parentFolder; + CMyComPtr _agent; + CAgent *_agentSpec; + + CRecordVector _items; + bool _flatMode; +private: +}; + +class CAgent: + public IInFolderArchive, + public IFolderArcProps, + #ifndef EXTRACT_ONLY + public IOutFolderArchive, + public ISetProperties, + #endif + public CMyUnknownImp +{ +public: + + MY_QUERYINTERFACE_BEGIN2(IInFolderArchive) + MY_QUERYINTERFACE_ENTRY(IFolderArcProps) + #ifndef EXTRACT_ONLY + MY_QUERYINTERFACE_ENTRY(IOutFolderArchive) + MY_QUERYINTERFACE_ENTRY(ISetProperties) + #endif + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + INTERFACE_IInFolderArchive(;) + INTERFACE_IFolderArcProps(;) + + #ifndef EXTRACT_ONLY + INTERFACE_IOutFolderArchive(;) + + HRESULT CommonUpdate( + const wchar_t *newArchiveName, + int numUpdateItems, + IArchiveUpdateCallback *updateCallback); + + HRESULT CreateFolder( + const wchar_t *newArchiveName, + const wchar_t *folderName, + IFolderArchiveUpdateCallback *updateCallback100); + + HRESULT RenameItem( + const wchar_t *newArchiveName, + const UINT32 *indices, UINT32 numItems, + const wchar_t *newItemName, + IFolderArchiveUpdateCallback *updateCallback100); + + // ISetProperties + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties); + #endif + + CCodecs *_codecs; + CMyComPtr _compressCodecsInfo; + + CAgent(); + ~CAgent(); +private: + HRESULT ReadItems(); +public: + CProxyArchive *_proxyArchive; + CArchiveLink _archiveLink; + + + UString ArchiveType; + + UStringVector _names; + UString _folderPrefix; + + UString _archiveNamePrefix; + CAgentFolder *_agentFolder; + + UString _archiveFilePath; + + #ifndef EXTRACT_ONLY + CObjectVector m_PropNames; + CObjectVector m_PropValues; + #endif + + const CArc &GetArc() { return _archiveLink.Arcs.Back(); } + IInArchive *GetArchive() { if ( _archiveLink.Arcs.IsEmpty()) return 0; return GetArc().Archive; } + bool CanUpdate() const { return _archiveLink.Arcs.Size() <= 1; } + + UString GetTypeOfArc(const CArc &arc) const { return _codecs->Formats[arc.FormatIndex].Name; } + UString GetErrorMessage() const + { + UString s; + for (int i = _archiveLink.Arcs.Size() - 1; i >= 0; i--) + { + const CArc &arc = _archiveLink.Arcs[i]; + if (arc.ErrorMessage.IsEmpty()) + continue; + if (!s.IsEmpty()) + s += L"--------------------\n"; + s += arc.ErrorMessage; + s += L"\n\n["; + s += GetTypeOfArc(arc); + s += L"] "; + s += arc.Path; + s += L"\n"; + } + return s; + } +}; + +#ifdef NEW_FOLDER_INTERFACE +class CArchiveFolderManager: + public IFolderManager, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP1(IFolderManager) + + INTERFACE_IFolderManager(;) + + CArchiveFolderManager(): _codecs(0) {} +private: + void LoadFormats(); + int FindFormat(const UString &type); + CCodecs *_codecs; + CMyComPtr _compressCodecsInfo; +}; +#endif + +#endif diff --git a/CPP/7zip/UI/Agent/AgentOut.cpp b/CPP/7zip/UI/Agent/AgentOut.cpp new file mode 100755 index 0000000..8486697 --- /dev/null +++ b/CPP/7zip/UI/Agent/AgentOut.cpp @@ -0,0 +1,533 @@ +// AgentOut.cpp + +#include "StdAfx.h" + +#include "Common/IntToString.h" +#include "Common/StringConvert.h" + +#include "Windows/FileDir.h" +#include "Windows/PropVariant.h" +#include "Windows/PropVariantConversions.h" +#include "Windows/Time.h" + +#include "../../Compress/CopyCoder.h" + +#include "../../Common/FileStreams.h" + +#include "../Common/EnumDirItems.h" +#include "../Common/OpenArchive.h" +#include "../Common/UpdateCallback.h" +#include "../Common/UpdatePair.h" + +#include "Agent.h" +#include "UpdateCallbackAgent.h" + +using namespace NWindows; +using namespace NCOM; + +STDMETHODIMP CAgent::SetFolder(IFolderFolder *folder) +{ + _archiveNamePrefix.Empty(); + if (folder == NULL) + { + _agentFolder = NULL; + return S_OK; + } + else + { + CMyComPtr archiveFolder = folder; + CMyComPtr archiveFolderInternal; + RINOK(archiveFolder.QueryInterface(IID_IArchiveFolderInternal, &archiveFolderInternal)); + RINOK(archiveFolderInternal->GetAgentFolder(&_agentFolder)); + } + + UStringVector pathParts; + pathParts.Clear(); + CMyComPtr folderItem = folder; + if (folderItem != NULL) + for (;;) + { + CMyComPtr newFolder; + folderItem->BindToParentFolder(&newFolder); + if (newFolder == NULL) + break; + + NCOM::CPropVariant prop; + if (folderItem->GetFolderProperty(kpidName, &prop) == S_OK) + if (prop.vt == VT_BSTR) + pathParts.Insert(0, (const wchar_t *)prop.bstrVal); + folderItem = newFolder; + } + + for (int i = 0; i < pathParts.Size(); i++) + { + _archiveNamePrefix += pathParts[i]; + _archiveNamePrefix += WCHAR_PATH_SEPARATOR; + } + return S_OK; +} + +STDMETHODIMP CAgent::SetFiles(const wchar_t *folderPrefix, + const wchar_t **names, UInt32 numNames) +{ + _folderPrefix = folderPrefix; + _names.Clear(); + _names.Reserve(numNames); + for (UInt32 i = 0; i < numNames; i++) + _names.Add(names[i]); + return S_OK; +} + +static HRESULT EnumerateArchiveItems(CAgent *agent, + const CProxyFolder &item, + const UString &prefix, + CObjectVector &arcItems) +{ + int i; + for (i = 0; i < item.Files.Size(); i++) + { + const CProxyFile &fileItem = item.Files[i]; + CArcItem ai; + RINOK(agent->GetArc().GetItemMTime(fileItem.Index, ai.MTime, ai.MTimeDefined)); + + CPropVariant property; + agent->GetArchive()->GetProperty(fileItem.Index, kpidSize, &property); + ai.SizeDefined = (property.vt != VT_EMPTY); + if (ai.SizeDefined) + ai.Size = ConvertPropVariantToUInt64(property); + ai.IsDir = false; + ai.Name = prefix + fileItem.Name; + ai.Censored = true; // test it + ai.IndexInServer = fileItem.Index; + arcItems.Add(ai); + } + for (i = 0; i < item.Folders.Size(); i++) + { + const CProxyFolder &dirItem = item.Folders[i]; + UString fullName = prefix + dirItem.Name; + if (dirItem.IsLeaf) + { + CArcItem ai; + RINOK(agent->GetArc().GetItemMTime(dirItem.Index, ai.MTime, ai.MTimeDefined)); + ai.IsDir = true; + ai.SizeDefined = false; + ai.Name = fullName; + ai.Censored = true; // test it + ai.IndexInServer = dirItem.Index; + arcItems.Add(ai); + } + RINOK(EnumerateArchiveItems(agent, dirItem, fullName + UString(WCHAR_PATH_SEPARATOR), arcItems)); + } + return S_OK; +} + +struct CAgUpCallbackImp: public IUpdateProduceCallback +{ + const CObjectVector *_arcItems; + IFolderArchiveUpdateCallback *_callback; + + CAgUpCallbackImp(const CObjectVector *a, + IFolderArchiveUpdateCallback *callback): _arcItems(a), _callback(callback) {} + HRESULT ShowDeleteFile(int arcIndex); +}; + +HRESULT CAgUpCallbackImp::ShowDeleteFile(int arcIndex) +{ + return _callback->DeleteOperation((*_arcItems)[arcIndex].Name); +} + +STDMETHODIMP CAgent::DoOperation( + CCodecs *codecs, + int formatIndex, + const wchar_t *newArchiveName, + const Byte *stateActions, + const wchar_t *sfxModule, + IFolderArchiveUpdateCallback *updateCallback100) +{ + if (!CanUpdate()) + return E_NOTIMPL; + NUpdateArchive::CActionSet actionSet; + int i; + for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++) + actionSet.StateActions[i] = (NUpdateArchive::NPairAction::EEnum)stateActions[i]; + + CDirItems dirItems; + + { + UString folderPrefix = _folderPrefix; + NFile::NName::NormalizeDirPathPrefix(folderPrefix); + UStringVector errorPaths; + CRecordVector errorCodes; + dirItems.EnumerateDirItems2(folderPrefix, _archiveNamePrefix, _names, errorPaths, errorCodes); + if (errorCodes.Size() > 0) + return errorCodes.Front(); + } + + CMyComPtr outArchive; + if (GetArchive()) + { + RINOK(GetArchive()->QueryInterface(IID_IOutArchive, (void **)&outArchive)); + } + else + { + if (formatIndex < 0) + return E_FAIL; + RINOK(codecs->CreateOutArchive(formatIndex, outArchive)); + #ifdef EXTERNAL_CODECS + { + CMyComPtr setCompressCodecsInfo; + outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); + if (setCompressCodecsInfo) + { + RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs)); + } + } + #endif + + } + + NFileTimeType::EEnum fileTimeType; + UInt32 value; + RINOK(outArchive->GetFileTimeType(&value)); + + switch(value) + { + case NFileTimeType::kWindows: + case NFileTimeType::kDOS: + case NFileTimeType::kUnix: + fileTimeType = NFileTimeType::EEnum(value); + break; + default: + return E_FAIL; + } + + + CObjectVector arcItems; + if (GetArchive()) + { + RINOK(ReadItems()); + EnumerateArchiveItems(this, _proxyArchive->RootFolder, L"", arcItems); + } + + CRecordVector updatePairs2; + + { + CRecordVector updatePairs; + GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); + CAgUpCallbackImp upCallback(&arcItems, updateCallback100); + UpdateProduce(updatePairs, actionSet, updatePairs2, &upCallback); + } + + UInt32 numFiles = 0; + for (i = 0; i < updatePairs2.Size(); i++) + if (updatePairs2[i].NewData) + numFiles++; + + if (updateCallback100) + { + RINOK(updateCallback100->SetNumFiles(numFiles)); + } + + CUpdateCallbackAgent updateCallbackAgent; + updateCallbackAgent.SetCallback(updateCallback100); + CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; + CMyComPtr updateCallback(updateCallbackSpec ); + + updateCallbackSpec->DirItems = &dirItems; + updateCallbackSpec->ArcItems = &arcItems; + updateCallbackSpec->UpdatePairs = &updatePairs2; + updateCallbackSpec->Archive = GetArchive(); + updateCallbackSpec->Callback = &updateCallbackAgent; + + COutFileStream *outStreamSpec = new COutFileStream; + CMyComPtr outStream(outStreamSpec); + UString archiveName = newArchiveName; + { + UString resultPath; + int pos; + if (!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos)) + return E_FAIL; + NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos)); + } + if (!outStreamSpec->Create(archiveName, true)) + { + // ShowLastErrorMessage(); + return E_FAIL; + } + + CMyComPtr setProperties; + if (outArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties) == S_OK) + { + if (m_PropNames.Size() == 0) + { + RINOK(setProperties->SetProperties(0, 0, 0)); + } + else + { + CRecordVector names; + for(i = 0; i < m_PropNames.Size(); i++) + names.Add((const wchar_t *)m_PropNames[i]); + + NWindows::NCOM::CPropVariant *propValues = new NWindows::NCOM::CPropVariant[m_PropValues.Size()]; + try + { + for (int i = 0; i < m_PropValues.Size(); i++) + propValues[i] = m_PropValues[i]; + RINOK(setProperties->SetProperties(&names.Front(), propValues, names.Size())); + } + catch(...) + { + delete []propValues; + return E_FAIL; + } + delete []propValues; + } + } + m_PropNames.Clear(); + m_PropValues.Clear(); + + if (sfxModule != NULL) + { + CInFileStream *sfxStreamSpec = new CInFileStream; + CMyComPtr sfxStream(sfxStreamSpec); + if (!sfxStreamSpec->Open(sfxModule)) + return E_FAIL; + // throw "Can't open sfx module"; + RINOK(NCompress::CopyStream(sfxStream, outStream, NULL)); + } + + RINOK(outArchive->UpdateItems(outStream, updatePairs2.Size(),updateCallback)); + return outStreamSpec->Close(); +} + +STDMETHODIMP CAgent::DoOperation2( + const wchar_t *newArchiveName, + const Byte *stateActions, + const wchar_t *sfxModule, + IFolderArchiveUpdateCallback *updateCallback100) +{ + return DoOperation(_codecs, -1, newArchiveName, + stateActions, sfxModule, updateCallback100); +} + +HRESULT CAgent::CommonUpdate( + const wchar_t *newArchiveName, + int numUpdateItems, + IArchiveUpdateCallback *updateCallback) +{ + if (!CanUpdate()) + return E_NOTIMPL; + CMyComPtr outArchive; + RINOK(GetArchive()->QueryInterface(IID_IOutArchive, (void **)&outArchive)); + + COutFileStream *outStreamSpec = new COutFileStream; + CMyComPtr outStream(outStreamSpec); + + UString archiveName = newArchiveName; + { + UString resultPath; + int pos; + if (!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos)) + throw 141716; + NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos)); + } + + /* + bool isOK = false; + for (int i = 0; i < (1 << 16); i++) + { + resultName = newArchiveName; + if (i > 0) + { + wchar_t s[16]; + ConvertUInt32ToString(i, s); + resultName += s; + } + if (outStreamSpec->Open(realPath)) + { + isOK = true; + break; + } + if (::GetLastError() != ERROR_FILE_EXISTS) + return ::GetLastError(); + } + if (!isOK) + return ::GetLastError(); + */ + if (!outStreamSpec->Create(archiveName, true)) + { + // ShowLastErrorMessage(); + return E_FAIL; + } + + RINOK(outArchive->UpdateItems(outStream, numUpdateItems, updateCallback)); + return outStreamSpec->Close(); +} + + +STDMETHODIMP CAgent::DeleteItems( + const wchar_t *newArchiveName, + const UInt32 *indices, UInt32 numItems, + IFolderArchiveUpdateCallback *updateCallback100) +{ + if (!CanUpdate()) + return E_NOTIMPL; + CUpdateCallbackAgent updateCallbackAgent; + updateCallbackAgent.SetCallback(updateCallback100); + CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; + CMyComPtr updateCallback(updateCallbackSpec); + + CUIntVector realIndices; + _agentFolder->GetRealIndices(indices, numItems, realIndices); + CRecordVector updatePairs; + int curIndex = 0; + UInt32 numItemsInArchive; + RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive)); + for (UInt32 i = 0; i < numItemsInArchive; i++) + { + if (curIndex < realIndices.Size()) + if (realIndices[curIndex] == i) + { + curIndex++; + continue; + } + CUpdatePair2 up2; + up2.NewData = up2.NewProps = false; + up2.IsAnti = false; // check it. Maybe it can be undefined + up2.ArcIndex = i; + updatePairs.Add(up2); + } + updateCallbackSpec->UpdatePairs = &updatePairs; + updateCallbackSpec->Archive = GetArchive(); + updateCallbackSpec->Callback = &updateCallbackAgent; + return CommonUpdate(newArchiveName, updatePairs.Size(), updateCallback); +} + +HRESULT CAgent::CreateFolder( + const wchar_t *newArchiveName, + const wchar_t *folderName, + IFolderArchiveUpdateCallback *updateCallback100) +{ + if (!CanUpdate()) + return E_NOTIMPL; + CUpdateCallbackAgent updateCallbackAgent; + updateCallbackAgent.SetCallback(updateCallback100); + CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; + CMyComPtr updateCallback(updateCallbackSpec); + + CRecordVector updatePairs; + UInt32 numItemsInArchive; + RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive)); + for (UInt32 i = 0; i < numItemsInArchive; i++) + { + CUpdatePair2 up2; + up2.NewData = up2.NewProps = false; + up2.IsAnti = false; // check it. + up2.ArcIndex = i; + updatePairs.Add(up2); + } + CUpdatePair2 up2; + up2.NewData = up2.NewProps = true; + up2.IsAnti = false; + up2.DirIndex = 0; + + updatePairs.Add(up2); + + updatePairs.ReserveDown(); + + CDirItems dirItems; + CDirItem di; + + di.Attrib = FILE_ATTRIBUTE_DIRECTORY; + di.Size = 0; + di.Name = _agentFolder->_proxyFolderItem->GetFullPathPrefix() + folderName; + + FILETIME ft; + NTime::GetCurUtcFileTime(ft); + di.CTime = di.ATime = di.MTime = ft; + + dirItems.Items.Add(di); + + updateCallbackSpec->Callback = &updateCallbackAgent; + updateCallbackSpec->DirItems = &dirItems; + updateCallbackSpec->UpdatePairs = &updatePairs; + updateCallbackSpec->Archive = GetArchive(); + return CommonUpdate(newArchiveName, updatePairs.Size(), updateCallback); +} + + +HRESULT CAgent::RenameItem( + const wchar_t *newArchiveName, + const UInt32 *indices, UInt32 numItems, + const wchar_t *newItemName, + IFolderArchiveUpdateCallback *updateCallback100) +{ + if (!CanUpdate()) + return E_NOTIMPL; + if (numItems != 1) + return E_INVALIDARG; + CUpdateCallbackAgent updateCallbackAgent; + updateCallbackAgent.SetCallback(updateCallback100); + CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; + CMyComPtr updateCallback(updateCallbackSpec); + + CUIntVector realIndices; + _agentFolder->GetRealIndices(indices, numItems, realIndices); + + UString fullPrefix = _agentFolder->GetFullPathPrefixPlusPrefix(indices[0]); + UString oldItemPath = fullPrefix + _agentFolder->GetName(indices[0]); + UString newItemPath = fullPrefix + newItemName; + + CRecordVector updatePairs; + UStringVector newNames; + + int curIndex = 0; + UInt32 numItemsInArchive; + RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive)); + for (UInt32 i = 0; i < numItemsInArchive; i++) + { + if (curIndex < realIndices.Size()) + if (realIndices[curIndex] == i) + { + CUpdatePair2 up2; + up2.NewData = false; + up2.NewProps = true; + RINOK(GetArc().IsItemAnti(i, up2.IsAnti)); + up2.ArcIndex = i; + + UString oldFullPath; + RINOK(GetArc().GetItemPath(i, oldFullPath)); + + if (oldItemPath.CompareNoCase(oldFullPath.Left(oldItemPath.Length())) != 0) + return E_INVALIDARG; + + up2.NewNameIndex = newNames.Add(newItemPath + oldFullPath.Mid(oldItemPath.Length())); + updatePairs.Add(up2); + curIndex++; + continue; + } + CUpdatePair2 up2; + up2.NewData = up2.NewProps = false; + up2.IsAnti = false; + up2.ArcIndex = i; + updatePairs.Add(up2); + } + updateCallbackSpec->Callback = &updateCallbackAgent; + updateCallbackSpec->UpdatePairs = &updatePairs; + updateCallbackSpec->NewNames = &newNames; + updateCallbackSpec->Archive = GetArchive(); + return CommonUpdate(newArchiveName, updatePairs.Size(), updateCallback); +} + +STDMETHODIMP CAgent::SetProperties(const wchar_t **names, + const PROPVARIANT *values, Int32 numProperties) +{ + m_PropNames.Clear(); + m_PropValues.Clear(); + for (int i = 0; i < numProperties; i++) + { + m_PropNames.Add(names[i]); + m_PropValues.Add(values[i]); + } + return S_OK; +} diff --git a/CPP/7zip/UI/Agent/AgentProxy.cpp b/CPP/7zip/UI/Agent/AgentProxy.cpp new file mode 100755 index 0000000..3040fcc --- /dev/null +++ b/CPP/7zip/UI/Agent/AgentProxy.cpp @@ -0,0 +1,246 @@ +// AgentProxy.cpp + +#include "StdAfx.h" + +#include "../../../../C/Sort.h" + +#include "Windows/PropVariant.h" +#include "Windows/PropVariantConversions.h" + +#include "../Common/OpenArchive.h" + +#include "AgentProxy.h" + +using namespace NWindows; + +int CProxyFolder::FindDirSubItemIndex(const UString &name, int &insertPos) const +{ + int left = 0, right = Folders.Size(); + for (;;) + { + if (left == right) + { + insertPos = left; + return -1; + } + int mid = (left + right) / 2; + int compare = name.CompareNoCase(Folders[mid].Name); + if (compare == 0) + return mid; + if (compare < 0) + right = mid; + else + left = mid + 1; + } +} + +int CProxyFolder::FindDirSubItemIndex(const UString &name) const +{ + int insertPos; + return FindDirSubItemIndex(name, insertPos); +} + +void CProxyFolder::AddFileSubItem(UInt32 index, const UString &name) +{ + Files.Add(CProxyFile()); + Files.Back().Name = name; + Files.Back().Index = index; +} + +CProxyFolder* CProxyFolder::AddDirSubItem(UInt32 index, bool leaf, const UString &name) +{ + int insertPos; + int folderIndex = FindDirSubItemIndex(name, insertPos); + if (folderIndex >= 0) + { + CProxyFolder *item = &Folders[folderIndex]; + if (leaf) + { + item->Index = index; + item->IsLeaf = true; + } + return item; + } + Folders.Insert(insertPos, CProxyFolder()); + CProxyFolder *item = &Folders[insertPos]; + item->Name = name; + item->Index = index; + item->Parent = this; + item->IsLeaf = leaf; + return item; +} + +void CProxyFolder::Clear() +{ + Folders.Clear(); + Files.Clear(); +} + +void CProxyFolder::GetPathParts(UStringVector &pathParts) const +{ + pathParts.Clear(); + UString result; + const CProxyFolder *current = this; + while (current->Parent != NULL) + { + pathParts.Insert(0, (const wchar_t *)current->Name); + current = current->Parent; + } +} + +UString CProxyFolder::GetFullPathPrefix() const +{ + UString result; + const CProxyFolder *current = this; + while (current->Parent != NULL) + { + result = current->Name + UString(WCHAR_PATH_SEPARATOR) + result; + current = current->Parent; + } + return result; +} + +UString CProxyFolder::GetItemName(UInt32 index) const +{ + if (index < (UInt32)Folders.Size()) + return Folders[index].Name; + return Files[index - Folders.Size()].Name; +} + +void CProxyFolder::AddRealIndices(CUIntVector &realIndices) const +{ + if (IsLeaf) + realIndices.Add(Index); + int i; + for (i = 0; i < Folders.Size(); i++) + Folders[i].AddRealIndices(realIndices); + for (i = 0; i < Files.Size(); i++) + realIndices.Add(Files[i].Index); +} + +void CProxyFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const +{ + realIndices.Clear(); + for (UInt32 i = 0; i < numItems; i++) + { + int index = indices[i]; + int numDirItems = Folders.Size(); + if (index < numDirItems) + Folders[index].AddRealIndices(realIndices); + else + realIndices.Add(Files[index - numDirItems].Index); + } + HeapSort(&realIndices.Front(), realIndices.Size()); +} + +/////////////////////////////////////////////// +// CProxyArchive + +static UInt64 GetSize(IInArchive *archive, UInt32 index, PROPID propID) +{ + NCOM::CPropVariant prop; + if (archive->GetProperty(index, propID, &prop) == S_OK) + if (prop.vt != VT_EMPTY) + return ConvertPropVariantToUInt64(prop); + return 0; +} + +void CProxyFolder::CalculateSizes(IInArchive *archive) +{ + Size = PackSize = 0; + NumSubFolders = Folders.Size(); + NumSubFiles = Files.Size(); + CrcIsDefined = true; + Crc = 0; + int i; + for (i = 0; i < Files.Size(); i++) + { + UInt32 index = Files[i].Index; + Size += GetSize(archive, index, kpidSize); + PackSize += GetSize(archive, index, kpidPackSize); + { + NCOM::CPropVariant prop; + if (archive->GetProperty(index, kpidCRC, &prop) == S_OK && prop.vt == VT_UI4) + Crc += prop.ulVal; + else + CrcIsDefined = false; + } + } + for (i = 0; i < Folders.Size(); i++) + { + CProxyFolder &f = Folders[i]; + f.CalculateSizes(archive); + Size += f.Size; + PackSize += f.PackSize; + NumSubFiles += f.NumSubFiles; + NumSubFolders += f.NumSubFolders; + Crc += f.Crc; + if (!f.CrcIsDefined) + CrcIsDefined = false; + } +} + +HRESULT CProxyArchive::Load(const CArc &arc, IProgress *progress) +{ + RootFolder.Clear(); + IInArchive *archive = arc.Archive; + { + ThereIsPathProp = false; + UInt32 numProps; + archive->GetNumberOfProperties(&numProps); + for (UInt32 i = 0; i < numProps; i++) + { + CMyComBSTR name; + PROPID propID; + VARTYPE varType; + RINOK(archive->GetPropertyInfo(i, &name, &propID, &varType)); + if (propID == kpidPath) + { + ThereIsPathProp = true; + break; + } + } + } + + UInt32 numItems; + RINOK(archive->GetNumberOfItems(&numItems)); + if (progress != NULL) + { + UInt64 totalItems = numItems; + RINOK(progress->SetTotal(totalItems)); + } + UString fileName; + for (UInt32 i = 0; i < numItems; i++) + { + if (progress != NULL && (i & 0xFFFFF) == 0) + { + UInt64 currentItemIndex = i; + RINOK(progress->SetCompleted(¤tItemIndex)); + } + UString filePath; + RINOK(arc.GetItemPath(i, filePath)); + CProxyFolder *curItem = &RootFolder; + int len = filePath.Length(); + fileName.Empty(); + for (int j = 0; j < len; j++) + { + wchar_t c = filePath[j]; + if (c == WCHAR_PATH_SEPARATOR || c == L'/') + { + curItem = curItem->AddDirSubItem((UInt32)(Int32)-1, false, fileName); + fileName.Empty(); + } + else + fileName += c; + } + + bool isFolder; + RINOK(IsArchiveItemFolder(archive, i, isFolder)); + if (isFolder) + curItem->AddDirSubItem(i, true, fileName); + else + curItem->AddFileSubItem(i, fileName); + } + RootFolder.CalculateSizes(archive); + return S_OK; +} diff --git a/CPP/7zip/UI/Agent/AgentProxy.h b/CPP/7zip/UI/Agent/AgentProxy.h new file mode 100755 index 0000000..4a6cab7 --- /dev/null +++ b/CPP/7zip/UI/Agent/AgentProxy.h @@ -0,0 +1,53 @@ +// AgentProxy.h + +#ifndef __AGENT_PROXY_H +#define __AGENT_PROXY_H + +#include "Common/MyString.h" + +#include "../Common/OpenArchive.h" + +struct CProxyFile +{ + UInt32 Index; + UString Name; +}; + +struct CProxyFolder: public CProxyFile +{ + CProxyFolder *Parent; + CObjectVector Folders; + CObjectVector Files; + bool IsLeaf; + + bool CrcIsDefined; + UInt64 Size; + UInt64 PackSize; + UInt32 Crc; + UInt32 NumSubFolders; + UInt32 NumSubFiles; + + CProxyFolder(): Parent(NULL) {}; + int FindDirSubItemIndex(const UString &name, int &insertPos) const; + int FindDirSubItemIndex(const UString &name) const; + CProxyFolder* AddDirSubItem(UInt32 index, bool leaf, const UString &name); + void AddFileSubItem(UInt32 index, const UString &name); + void Clear(); + + void GetPathParts(UStringVector &pathParts) const; + UString GetFullPathPrefix() const; + UString GetItemName(UInt32 index) const; + void AddRealIndices(CUIntVector &realIndices) const; + void GetRealIndices(const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const; + void CalculateSizes(IInArchive *archive); +}; + +struct CProxyArchive +{ + CProxyFolder RootFolder; + bool ThereIsPathProp; + + HRESULT Load(const CArc &arc, IProgress *progress); +}; + +#endif diff --git a/CPP/7zip/UI/Agent/ArchiveFolder.cpp b/CPP/7zip/UI/Agent/ArchiveFolder.cpp new file mode 100755 index 0000000..0b75e5b --- /dev/null +++ b/CPP/7zip/UI/Agent/ArchiveFolder.cpp @@ -0,0 +1,59 @@ +// Agent/ArchiveFolder.cpp + +#include "StdAfx.h" + +#include "Common/ComTry.h" + +#include "../Common/ArchiveExtractCallback.h" + +#include "Agent.h" + +using namespace NWindows; +using namespace NCOM; + +STDMETHODIMP CAgentFolder::CopyTo(const UInt32 *indices, UInt32 numItems, + const wchar_t *path, IFolderOperationsExtractCallback *callback) +{ + COM_TRY_BEGIN + CArchiveExtractCallback *extractCallbackSpec = new + CArchiveExtractCallback; + CMyComPtr extractCallback = extractCallbackSpec; + UStringVector pathParts; + CProxyFolder *currentProxyFolder = _proxyFolderItem; + while (currentProxyFolder->Parent) + { + pathParts.Insert(0, currentProxyFolder->Name); + currentProxyFolder = currentProxyFolder->Parent; + } + + CMyComPtr extractCallback2; + { + CMyComPtr callbackWrap = callback; + RINOK(callbackWrap.QueryInterface( + IID_IFolderArchiveExtractCallback, &extractCallback2)); + } + + NExtract::NPathMode::EEnum pathMode = _flatMode ? + NExtract::NPathMode::kNoPathnames : + NExtract::NPathMode::kCurrentPathnames; + + extractCallbackSpec->InitForMulti(false, pathMode, NExtract::NOverwriteMode::kAskBefore); + extractCallbackSpec->Init(NULL, &_agentSpec->GetArc(), + extractCallback2, + false, false, false, + path, + pathParts, + (UInt64)(Int64)-1); + CUIntVector realIndices; + GetRealIndices(indices, numItems, realIndices); + return _agentSpec->GetArchive()->Extract(&realIndices.Front(), + realIndices.Size(), BoolToInt(false), extractCallback); + COM_TRY_END +} + +STDMETHODIMP CAgentFolder::MoveTo(const UInt32 * /* indices */, UInt32 /* numItems */, + const wchar_t * /* path */, IFolderOperationsExtractCallback * /* callback */) +{ + return E_NOTIMPL; +} + diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp new file mode 100755 index 0000000..d78e1bb --- /dev/null +++ b/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp @@ -0,0 +1,142 @@ +// Zip/ArchiveFolder.cpp + +#include "StdAfx.h" + +#include "Agent.h" + +#include "Common/StringConvert.h" + +extern HINSTANCE g_hInstance; + +static inline UINT GetCurrentFileCodePage() +{ + #ifdef UNDER_CE + return CP_ACP; + #else + return AreFileApisANSI() ? CP_ACP : CP_OEMCP; + #endif +} + +void CArchiveFolderManager::LoadFormats() +{ + if (!_codecs) + { + _compressCodecsInfo = _codecs = new CCodecs; + _codecs->Load(); + } +} + +int CArchiveFolderManager::FindFormat(const UString &type) +{ + for (int i = 0; i < _codecs->Formats.Size(); i++) + if (type.CompareNoCase(_codecs->Formats[i].Name) == 0) + return i; + return -1; +} + +STDMETHODIMP CArchiveFolderManager::OpenFolderFile(IInStream *inStream, + const wchar_t *filePath, const wchar_t *arcFormat, + IFolderFolder **resultFolder, IProgress *progress) +{ + CMyComPtr openArchiveCallback; + if (progress != 0) + { + CMyComPtr progressWrapper = progress; + progressWrapper.QueryInterface(IID_IArchiveOpenCallback, &openArchiveCallback); + } + CAgent *agent = new CAgent(); + CMyComPtr archive = agent; + RINOK(agent->Open(inStream, filePath, arcFormat, NULL, openArchiveCallback)); + return agent->BindToRootFolder(resultFolder); +} + +/* +HRESULT CAgent::FolderReOpen( + IArchiveOpenCallback *openArchiveCallback) +{ + return ReOpenArchive(_archive, _archiveFilePath); +} +*/ + + +/* +STDMETHODIMP CArchiveFolderManager::GetExtensions(const wchar_t *type, BSTR *extensions) +{ + *extensions = 0; + int formatIndex = FindFormat(type); + if (formatIndex < 0) + return E_INVALIDARG; + // Exts[0].Ext; + return StringToBstr(_codecs.Formats[formatIndex].GetAllExtensions(), extensions); +} +*/ + +static void AddIconExt(const CCodecIcons &lib, UString &dest) +{ + for (int j = 0; j < lib.IconPairs.Size(); j++) + { + if (!dest.IsEmpty()) + dest += L' '; + dest += lib.IconPairs[j].Ext; + } +} + +STDMETHODIMP CArchiveFolderManager::GetExtensions(BSTR *extensions) +{ + LoadFormats(); + *extensions = 0; + UString res; + for (int i = 0; i < _codecs->Libs.Size(); i++) + AddIconExt(_codecs->Libs[i], res); + AddIconExt(_codecs->InternalIcons, res); + return StringToBstr(res, extensions); +} + +STDMETHODIMP CArchiveFolderManager::GetIconPath(const wchar_t *ext, BSTR *iconPath, Int32 *iconIndex) +{ + LoadFormats(); + *iconPath = 0; + *iconIndex = 0; + for (int i = 0; i < _codecs->Libs.Size(); i++) + { + const CCodecLib &lib = _codecs->Libs[i]; + int ii; + if (lib.FindIconIndex(ext, ii)) + { + *iconIndex = ii; + return StringToBstr(GetUnicodeString(lib.Path, GetCurrentFileCodePage()), iconPath); + } + } + int ii; + if (_codecs->InternalIcons.FindIconIndex(ext, ii)) + { + *iconIndex = ii; + UString path; + NWindows::NDLL::MyGetModuleFileName(g_hInstance, path); + return StringToBstr(path, iconPath); + } + return S_OK; +} + +/* +STDMETHODIMP CArchiveFolderManager::GetTypes(BSTR *types) +{ + LoadFormats(); + UString typesStrings; + for(int i = 0; i < _codecs.Formats.Size(); i++) + { + const CArcInfoEx &ai = _codecs.Formats[i]; + if (ai.AssociateExts.Size() == 0) + continue; + if (i != 0) + typesStrings += L' '; + typesStrings += ai.Name; + } + return StringToBstr(typesStrings, types); +} +STDMETHODIMP CArchiveFolderManager::CreateFolderFile(const wchar_t * type, + const wchar_t * filePath, IProgress progress) +{ + return E_NOTIMPL; +} +*/ diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp new file mode 100755 index 0000000..5767346 --- /dev/null +++ b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp @@ -0,0 +1,214 @@ +// FolderOut.cpp + +#include "StdAfx.h" + +#include "Common/ComTry.h" + +#include "Windows/FileDir.h" + +#include "../Common/WorkDir.h" + +#include "Agent.h" + +using namespace NWindows; +using namespace NFile; +using namespace NDirectory; + +static LPCWSTR kTempArcivePrefix = L"7zA"; + +void CAgentFolder::GetPathParts(UStringVector &pathParts) +{ + _proxyFolderItem->GetPathParts(pathParts); +} + +HRESULT CAgentFolder::CommonUpdateOperation( + bool deleteOperation, + bool createFolderOperation, + bool renameOperation, + const wchar_t *newItemName, + const NUpdateArchive::CActionSet *actionSet, + const UINT32 *indices, UINT32 numItems, + IFolderArchiveUpdateCallback *updateCallback100) +{ + NWorkDir::CInfo workDirInfo; + workDirInfo.Load(); + UString archiveFilePath = _agentSpec->_archiveFilePath; + UString workDir = GetWorkDir(workDirInfo, archiveFilePath); + CreateComplexDirectory(workDir); + + CTempFileW tempFile; + UString tempFileName; + if (tempFile.Create(workDir, kTempArcivePrefix, tempFileName) == 0) + return E_FAIL; + + /* + if (SetOutProperties(anOutArchive, aCompressionInfo.Method) != S_OK) + return NFileOperationReturnCode::kError; + */ + + //////////////////////////// + // Save FolderItem; + + UStringVector pathParts; + GetPathParts(pathParts); + + HRESULT result; + if (deleteOperation) + result = _agentSpec->DeleteItems(tempFileName, + indices, numItems, updateCallback100); + else if (createFolderOperation) + { + result = _agentSpec->CreateFolder(tempFileName, + newItemName, updateCallback100); + } + else if (renameOperation) + { + result = _agentSpec->RenameItem( + tempFileName, + indices, numItems, + newItemName, + updateCallback100); + } + else + { + Byte actionSetByte[NUpdateArchive::NPairState::kNumValues]; + for (int i = 0; i < NUpdateArchive::NPairState::kNumValues; i++) + actionSetByte[i] = (Byte)actionSet->StateActions[i]; + result = _agentSpec->DoOperation2(tempFileName, actionSetByte, NULL, updateCallback100); + } + + if (result != S_OK) + return result; + + _agentSpec->Close(); + + // m_FolderItem = NULL; + + if (NFind::DoesFileExist(archiveFilePath)) + if (!DeleteFileAlways(archiveFilePath)) + return GetLastError(); + + tempFile.DisableDeleting(); + if (!MyMoveFile(tempFileName, archiveFilePath)) + return GetLastError(); + + { + CMyComPtr openCallback; + if (updateCallback100) + { + RINOK(updateCallback100->QueryInterface(IID_IArchiveOpenCallback, (void **)&openCallback)); + } + RINOK(_agentSpec->ReOpen(openCallback)); + } + + //////////////////////////// + // Restore FolderItem; + + CMyComPtr archiveFolder; + RINOK(_agentSpec->BindToRootFolder(&archiveFolder)); + for (int i = 0; i < pathParts.Size(); i++) + { + CMyComPtr newFolder; + archiveFolder->BindToFolder(pathParts[i], &newFolder); + if(!newFolder) + break; + archiveFolder = newFolder; + } + + CMyComPtr archiveFolderInternal; + RINOK(archiveFolder.QueryInterface(IID_IArchiveFolderInternal, &archiveFolderInternal)); + CAgentFolder *agentFolder; + RINOK(archiveFolderInternal->GetAgentFolder(&agentFolder)); + _proxyFolderItem = agentFolder->_proxyFolderItem; + _proxyArchive = agentFolder->_proxyArchive; + _parentFolder = agentFolder->_parentFolder; + + return S_OK; +} + +STDMETHODIMP CAgentFolder::CopyFrom( + const wchar_t *fromFolderPath, // test it + const wchar_t **itemsPaths, + UINT32 numItems, + IProgress *progress) +{ + COM_TRY_BEGIN + CMyComPtr updateCallback100; + if (progress != 0) + { + RINOK(progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&updateCallback100)); + } + try + { + RINOK(_agentSpec->SetFiles(fromFolderPath, itemsPaths, numItems)); + RINOK(_agentSpec->SetFolder(this)); + return CommonUpdateOperation(false, false, false, NULL, + &NUpdateArchive::kAddActionSet, 0, 0, updateCallback100); + } + catch(const UString &s) + { + RINOK(updateCallback100->UpdateErrorMessage(UString(L"Error: ") + s)); + return E_FAIL; + } + COM_TRY_END +} + +STDMETHODIMP CAgentFolder::Delete(const UINT32 *indices, UINT32 numItems, IProgress *progress) +{ + COM_TRY_BEGIN + RINOK(_agentSpec->SetFolder(this)); + CMyComPtr updateCallback100; + if (progress != 0) + { + CMyComPtr progressWrapper = progress; + RINOK(progressWrapper.QueryInterface( + IID_IFolderArchiveUpdateCallback, &updateCallback100)); + } + return CommonUpdateOperation(true, false, false, NULL, + &NUpdateArchive::kDeleteActionSet, indices, numItems, updateCallback100); + COM_TRY_END +} + +STDMETHODIMP CAgentFolder::CreateFolder(const wchar_t *name, IProgress *progress) +{ + COM_TRY_BEGIN + if (_proxyFolderItem->FindDirSubItemIndex(name) >= 0) + return ERROR_ALREADY_EXISTS; + RINOK(_agentSpec->SetFolder(this)); + CMyComPtr updateCallback100; + if (progress != 0) + { + CMyComPtr progressWrapper = progress; + RINOK(progressWrapper.QueryInterface(IID_IFolderArchiveUpdateCallback, &updateCallback100)); + } + return CommonUpdateOperation(false, true, false, name, NULL, NULL, 0, updateCallback100); + COM_TRY_END +} + +STDMETHODIMP CAgentFolder::Rename(UINT32 index, const wchar_t *newName, IProgress *progress) +{ + COM_TRY_BEGIN + CUIntVector indices; + indices.Add(index); + RINOK(_agentSpec->SetFolder(this)); + CMyComPtr updateCallback100; + if (progress != 0) + { + CMyComPtr progressWrapper = progress; + RINOK(progressWrapper.QueryInterface(IID_IFolderArchiveUpdateCallback, &updateCallback100)); + } + return CommonUpdateOperation(false, false, true, newName, NULL, &indices.Front(), + indices.Size(), updateCallback100); + COM_TRY_END +} + +STDMETHODIMP CAgentFolder::CreateFile(const wchar_t * /* name */, IProgress * /* progress */) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CAgentFolder::SetProperty(UINT32 /* index */, PROPID /* propID */, + const PROPVARIANT * /* value */, IProgress * /* progress */) +{ + return E_NOTIMPL; +} diff --git a/CPP/7zip/UI/Agent/IFolderArchive.h b/CPP/7zip/UI/Agent/IFolderArchive.h new file mode 100755 index 0000000..38fdf6e --- /dev/null +++ b/CPP/7zip/UI/Agent/IFolderArchive.h @@ -0,0 +1,73 @@ +// IFolderArchive.h + +#ifndef __IFOLDER_ARCHIVE_H +#define __IFOLDER_ARCHIVE_H + +#include "../../IDecl.h" +#include "../../Archive/IArchive.h" +#include "../../UI/Common/LoadCodecs.h" +#include "../../UI/FileManager/IFolder.h" + +#include "../Common/ExtractMode.h" +#include "../Common/IFileExtractCallback.h" + +#define FOLDER_ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 0x01, x) +#define FOLDER_ARCHIVE_INTERFACE(i, x) FOLDER_ARCHIVE_INTERFACE_SUB(i, IUnknown, x) + +#define INTERFACE_IArchiveFolder(x) \ + STDMETHOD(Extract)(const UInt32 *indices, UInt32 numItems, \ + NExtract::NPathMode::EEnum pathMode, \ + NExtract::NOverwriteMode::EEnum overwriteMode, \ + const wchar_t *path, Int32 testMode, \ + IFolderArchiveExtractCallback *extractCallback2) x; \ + +FOLDER_ARCHIVE_INTERFACE(IArchiveFolder, 0x05) +{ + INTERFACE_IArchiveFolder(PURE) +}; + +#define INTERFACE_IInFolderArchive(x) \ + STDMETHOD(Open)(IInStream *inStream, const wchar_t *filePath, const wchar_t *arcFormat, BSTR *archiveTypeRes, IArchiveOpenCallback *openArchiveCallback) x; \ + STDMETHOD(ReOpen)(IArchiveOpenCallback *openArchiveCallback) x; \ + STDMETHOD(Close)() x; \ + STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \ + STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \ + STDMETHOD(BindToRootFolder)(IFolderFolder **resultFolder) x; \ + STDMETHOD(Extract)(NExtract::NPathMode::EEnum pathMode, \ + NExtract::NOverwriteMode::EEnum overwriteMode, const wchar_t *path, \ + Int32 testMode, IFolderArchiveExtractCallback *extractCallback2) x; \ + +FOLDER_ARCHIVE_INTERFACE(IInFolderArchive, 0x0E) +{ + INTERFACE_IInFolderArchive(PURE) +}; + +#define INTERFACE_IFolderArchiveUpdateCallback(x) \ + STDMETHOD(CompressOperation)(const wchar_t *name) x; \ + STDMETHOD(DeleteOperation)(const wchar_t *name) x; \ + STDMETHOD(OperationResult)(Int32 operationResult) x; \ + STDMETHOD(UpdateErrorMessage)(const wchar_t *message) x; \ + STDMETHOD(SetNumFiles)(UInt64 numFiles) x; \ + +FOLDER_ARCHIVE_INTERFACE_SUB(IFolderArchiveUpdateCallback, IProgress, 0x0B) +{ + INTERFACE_IFolderArchiveUpdateCallback(PURE) +}; + +#define INTERFACE_IOutFolderArchive(x) \ + STDMETHOD(SetFolder)(IFolderFolder *folder) x; \ + STDMETHOD(SetFiles)(const wchar_t *folderPrefix, const wchar_t **names, UInt32 numNames) x; \ + STDMETHOD(DeleteItems)(const wchar_t *newArchiveName, \ + const UInt32 *indices, UInt32 numItems, IFolderArchiveUpdateCallback *updateCallback) x; \ + STDMETHOD(DoOperation)(CCodecs *codecs, int index, \ + const wchar_t *newArchiveName, const Byte *stateActions, const wchar_t *sfxModule, \ + IFolderArchiveUpdateCallback *updateCallback) x; \ + STDMETHOD(DoOperation2)(const wchar_t *newArchiveName, const Byte *stateActions, \ + const wchar_t *sfxModule, IFolderArchiveUpdateCallback *updateCallback) x; \ + +FOLDER_ARCHIVE_INTERFACE(IOutFolderArchive, 0x0A) +{ + INTERFACE_IOutFolderArchive(PURE) +}; + +#endif diff --git a/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp b/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp new file mode 100755 index 0000000..7bb234e --- /dev/null +++ b/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp @@ -0,0 +1,121 @@ +// UpdateCallbackAgent.h + +#include "StdAfx.h" + +#include "Windows/Error.h" +#include "Common/IntToString.h" + +#include "UpdateCallbackAgent.h" + +using namespace NWindows; + +void CUpdateCallbackAgent::SetCallback(IFolderArchiveUpdateCallback *callback) +{ + Callback = callback; + _compressProgress.Release(); + if (Callback) + Callback.QueryInterface(IID_ICompressProgressInfo, &_compressProgress); +} + +HRESULT CUpdateCallbackAgent::SetNumFiles(UInt64 numFiles) +{ + if (Callback) + return Callback->SetNumFiles(numFiles); + return S_OK; +} + + +HRESULT CUpdateCallbackAgent::SetTotal(UINT64 size) +{ + if (Callback) + return Callback->SetTotal(size); + return S_OK; +} + +HRESULT CUpdateCallbackAgent::SetCompleted(const UINT64 *completeValue) +{ + if (Callback) + return Callback->SetCompleted(completeValue); + return S_OK; +} + +HRESULT CUpdateCallbackAgent::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) +{ + if (_compressProgress) + return _compressProgress->SetRatioInfo(inSize, outSize); + return S_OK; +} + +HRESULT CUpdateCallbackAgent::CheckBreak() +{ + return S_OK; +} + +HRESULT CUpdateCallbackAgent::Finilize() +{ + return S_OK; +} + +HRESULT CUpdateCallbackAgent::OpenFileError(const wchar_t *name, DWORD systemError) +{ + // if (systemError == ERROR_SHARING_VIOLATION) + { + if (Callback) + { + RINOK(Callback->UpdateErrorMessage( + UString(L"WARNING: ") + + NError::MyFormatMessageW(systemError) + + UString(L": ") + + UString(name))); + return S_FALSE; + } + } + // FailedFiles.Add(name); + return systemError; +} + +HRESULT CUpdateCallbackAgent::GetStream(const wchar_t *name, bool /* isAnti */) +{ + if (Callback) + return Callback->CompressOperation(name); + return S_OK; +} + +HRESULT CUpdateCallbackAgent::SetOperationResult(Int32 operationResult) +{ + if (Callback) + return Callback->OperationResult(operationResult); + return S_OK; +} + +HRESULT CUpdateCallbackAgent::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) +{ + *password = NULL; + *passwordIsDefined = BoolToInt(false); + if (!_cryptoGetTextPassword) + { + if (!Callback) + return S_OK; + Callback.QueryInterface(IID_ICryptoGetTextPassword2, &_cryptoGetTextPassword); + if (!_cryptoGetTextPassword) + return S_OK; + } + return _cryptoGetTextPassword->CryptoGetTextPassword2(passwordIsDefined, password); +} + +HRESULT CUpdateCallbackAgent::CryptoGetTextPassword(BSTR *password) +{ + *password = NULL; + CMyComPtr getTextPassword; + Callback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); + if (!getTextPassword) + return E_NOTIMPL; + return getTextPassword->CryptoGetTextPassword(password); +} + +/* +HRESULT CUpdateCallbackAgent::ShowDeleteFile(const wchar_t *name) +{ + return Callback->DeleteOperation(name); +} +*/ diff --git a/CPP/7zip/UI/Agent/UpdateCallbackAgent.h b/CPP/7zip/UI/Agent/UpdateCallbackAgent.h new file mode 100755 index 0000000..53d09ff --- /dev/null +++ b/CPP/7zip/UI/Agent/UpdateCallbackAgent.h @@ -0,0 +1,19 @@ +// UpdateCallbackAgent.h + +#ifndef __UPDATECALLBACKAGENT_H +#define __UPDATECALLBACKAGENT_H + +#include "../Common/UpdateCallback.h" +#include "IFolderArchive.h" + +class CUpdateCallbackAgent: public IUpdateCallbackUI +{ + INTERFACE_IUpdateCallbackUI(;) + CMyComPtr _cryptoGetTextPassword; + CMyComPtr Callback; + CMyComPtr _compressProgress; +public: + void SetCallback(IFolderArchiveUpdateCallback *callback); +}; + +#endif diff --git a/CPP/7zip/UI/Client7z/Client7z.cpp b/CPP/7zip/UI/Client7z/Client7z.cpp new file mode 100755 index 0000000..7001fe8 --- /dev/null +++ b/CPP/7zip/UI/Client7z/Client7z.cpp @@ -0,0 +1,871 @@ +// Client7z.cpp + +#include "StdAfx.h" + +#include "Common/IntToString.h" +#include "Common/MyInitGuid.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/PropVariantConversions.h" + +#include "../../Common/FileStreams.h" + +#include "../../Archive/IArchive.h" + +#include "../../IPassword.h" +#include "../../MyVersion.h" + +// 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); + +using namespace NWindows; + +#define kDllName "7z.dll" + +static const char *kCopyrightString = MY_7ZIP_VERSION +" (" kDllName " client) " +MY_COPYRIGHT " " MY_DATE; + +static const char *kHelpString = +"Usage: Client7z.exe [a | l | x ] archive.7z [fileName ...]\n" +"Examples:\n" +" Client7z.exe a archive.7z f1.txt f2.txt : compress two files to archive.7z\n" +" Client7z.exe l archive.7z : List contents of archive.7z\n" +" Client7z.exe x archive.7z : eXtract files from archive.7z\n"; + + +typedef UINT32 (WINAPI * CreateObjectFunc)( + const GUID *clsID, + const GUID *interfaceID, + void **outObject); + + +void PrintString(const UString &s) +{ + printf("%s", (LPCSTR)GetOemString(s)); +} + +void PrintString(const AString &s) +{ + printf("%s", (LPCSTR)s); +} + +void PrintNewLine() +{ + PrintString("\n"); +} + +void PrintStringLn(const AString &s) +{ + PrintString(s); + PrintNewLine(); +} + +void PrintError(const AString &s) +{ + PrintNewLine(); + PrintString(s); + PrintNewLine(); +} + +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 *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); +} + + +////////////////////////////////////////////////////////////// +// Archive Extracting callback class + +static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file "; + +static const char *kTestingString = "Testing "; +static const char *kExtractingString = "Extracting "; +static const char *kSkippingString = "Skipping "; + +static const char *kUnsupportedMethod = "Unsupported Method"; +static const char *kCRCFailed = "CRC Failed"; +static const char *kDataError = "Data Error"; +static const char *kUnknownError = "Unknown 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; + UString _directoryPath; // Output directory + UString _filePath; // name inside arcvhive + UString _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 UString &directoryPath); + + UInt64 NumErrors; + bool PasswordIsDefined; + UString Password; + + CArchiveExtractCallback() : PasswordIsDefined(false) {} +}; + +void CArchiveExtractCallback::Init(IInArchive *archiveHandler, const UString &directoryPath) +{ + NumErrors = 0; + _archiveHandler = archiveHandler; + _directoryPath = directoryPath; + NFile::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)); + bool newFileSizeDefined = (prop.vt != VT_EMPTY); + UInt64 newFileSize; + if (newFileSizeDefined) + newFileSize = ConvertPropVariantToUInt64(prop); + } + + + { + // Create folders for file + int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR); + if (slashPos >= 0) + NFile::NDirectory::CreateComplexDirectory(_directoryPath + _filePath.Left(slashPos)); + } + + UString fullProcessedPath = _directoryPath + _filePath; + _diskFilePath = fullProcessedPath; + + if (_processedFileInfo.isDir) + { + NFile::NDirectory::CreateComplexDirectory(fullProcessedPath); + } + else + { + NFile::NFind::CFileInfoW fi; + if (fi.Find(fullProcessedPath)) + { + if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) + { + PrintString(UString(kCantDeleteOutputFile) + fullProcessedPath); + return E_ABORT; + } + } + + _outFileStreamSpec = new COutFileStream; + CMyComPtr outStreamLoc(_outFileStreamSpec); + if (!_outFileStreamSpec->Open(fullProcessedPath, CREATE_ALWAYS)) + { + PrintString((UString)L"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: PrintString(kExtractingString); break; + case NArchive::NExtract::NAskMode::kTest: PrintString(kTestingString); break; + case NArchive::NExtract::NAskMode::kSkip: PrintString(kSkippingString); break; + }; + PrintString(_filePath); + return S_OK; +} + +STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) +{ + switch(operationResult) + { + case NArchive::NExtract::NOperationResult::kOK: + break; + default: + { + NumErrors++; + PrintString(" "); + switch(operationResult) + { + case NArchive::NExtract::NOperationResult::kUnSupportedMethod: + PrintString(kUnsupportedMethod); + break; + case NArchive::NExtract::NOperationResult::kCRCError: + PrintString(kCRCFailed); + break; + case NArchive::NExtract::NOperationResult::kDataError: + PrintString(kDataError); + break; + default: + PrintString(kUnknownError); + } + } + } + + if (_outFileStream != NULL) + { + if (_processedFileInfo.MTimeDefined) + _outFileStreamSpec->SetMTime(&_processedFileInfo.MTime); + RINOK(_outFileStreamSpec->Close()); + } + _outFileStream.Release(); + if (_extractMode && _processedFileInfo.AttribDefined) + NFile::NDirectory::MySetFileAttributes(_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; + UString 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(EnumProperties)(IEnumSTATPROPSTG **enumerator); + 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; + + UString DirPrefix; + const CObjectVector *DirItems; + + bool PasswordIsDefined; + UString Password; + bool AskPassword; + + bool m_NeedBeClosed; + + UStringVector 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::EnumProperties(IEnumSTATPROPSTG ** /* enumerator */) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 /* index */, + Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive) +{ + if (newData != NULL) + *newData = BoolToInt(true); + if (newProperties != NULL) + *newProperties = BoolToInt(true); + if (indexInArchive != NULL) + *indexInArchive = (UInt32)-1; + return S_OK; +} + +STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + NWindows::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) +{ + PrintString("Compressing "); + if (name[0] == 0) + name = kEmptyFileAlias; + PrintString(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); + UString 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"); + // PrintString(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.Length() < 2) + res = UString(L'0') + res; + UString fileName = VolName; + fileName += L'.'; + fileName += res; + fileName += VolExt; + COutFileStream *streamSpec = new COutFileStream; + CMyComPtr streamLoc(streamSpec); + if (!streamSpec->Create(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 < 3) + { + PrintStringLn(kHelpString); + return 1; + } + NWindows::NDLL::CLibrary lib; + if (!lib.Load(TEXT(kDllName))) + { + PrintError("Can not load 7-zip library"); + return 1; + } + CreateObjectFunc createObjectFunc = (CreateObjectFunc)lib.GetProc("CreateObject"); + if (createObjectFunc == 0) + { + PrintError("Can not get CreateObject"); + return 1; + } + + char c; + { + AString command = args[1]; + if (command.Length() != 1) + { + PrintError("incorrect command"); + return 1; + } + c = MyCharLower(command[0]); + } + UString archiveName = GetUnicodeString(args[2]); + if (c == 'a') + { + // create archive command + if (numArgs < 4) + { + PrintStringLn(kHelpString); + return 1; + } + CObjectVector dirItems; + int i; + for (i = 3; i < numArgs; i++) + { + CDirItem di; + UString name = GetUnicodeString(args[i]); + + NFile::NFind::CFileInfoW fi; + if (!fi.Find(name)) + { + PrintString(UString(L"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 = 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_CFormat7z, &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 int kNumProps = sizeof(names) / sizeof(names[0]); + NWindows::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 (i = 0; i < updateCallbackSpec->FailedFiles.Size(); i++) + { + PrintNewLine(); + PrintString((UString)L"Error for file: " + updateCallbackSpec->FailedFiles[i]); + } + if (updateCallbackSpec->FailedFiles.Size() != 0) + return 1; + } + else + { + if (numArgs != 3) + { + PrintStringLn(kHelpString); + return 1; + } + + bool listCommand; + if (c == 'l') + listCommand = true; + else if (c == 'x') + listCommand = false; + else + { + PrintError("incorrect command"); + return 1; + } + + CMyComPtr archive; + if (createObjectFunc(&CLSID_CFormat7z, &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"); + return 1; + } + + { + CArchiveOpenCallback *openCallbackSpec = new CArchiveOpenCallback; + CMyComPtr openCallback(openCallbackSpec); + openCallbackSpec->PasswordIsDefined = false; + // openCallbackSpec->PasswordIsDefined = true; + // openCallbackSpec->Password = L"1"; + + if (archive->Open(file, 0, openCallback) != S_OK) + { + PrintError("Can not open archive"); + return 1; + } + } + + if (listCommand) + { + // List command + UInt32 numItems = 0; + archive->GetNumberOfItems(&numItems); + for (UInt32 i = 0; i < numItems; i++) + { + { + // Get uncompressed size of file + NWindows::NCOM::CPropVariant prop; + archive->GetProperty(i, kpidSize, &prop); + UString s = ConvertPropVariantToString(prop); + PrintString(s); + PrintString(" "); + } + { + // Get name of file + NWindows::NCOM::CPropVariant prop; + archive->GetProperty(i, kpidPath, &prop); + UString s = ConvertPropVariantToString(prop); + PrintString(s); + } + PrintString("\n"); + } + } + else + { + // Extract command + CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; + CMyComPtr extractCallback(extractCallbackSpec); + extractCallbackSpec->Init(archive, L""); // second parameter is output folder path + extractCallbackSpec->PasswordIsDefined = false; + // extractCallbackSpec->PasswordIsDefined = true; + // extractCallbackSpec->Password = L"1"; + HRESULT result = archive->Extract(NULL, (UInt32)(Int32)(-1), false, extractCallback); + if (result != S_OK) + { + PrintError("Extract Error"); + return 1; + } + } + } + return 0; +} diff --git a/CPP/7zip/UI/Client7z/Client7z.dsp b/CPP/7zip/UI/Client7z/Client7z.dsp new file mode 100755 index 0000000..34eb42b --- /dev/null +++ b/CPP/7zip/UI/Client7z/Client7z.dsp @@ -0,0 +1,226 @@ +# 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 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 /W3 /GX /O2 /I "..\..\..\\" /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 + +!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 /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /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 /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=.\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\PropVariantConversions.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariantConversions.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 +# End Target +# End Project diff --git a/CPP/7zip/UI/Client7z/Client7z.dsw b/CPP/7zip/UI/Client7z/Client7z.dsw new file mode 100755 index 0000000..4c26851 --- /dev/null +++ b/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/CPP/7zip/UI/Client7z/StdAfx.cpp b/CPP/7zip/UI/Client7z/StdAfx.cpp new file mode 100755 index 0000000..c6d3b1f --- /dev/null +++ b/CPP/7zip/UI/Client7z/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/UI/Client7z/StdAfx.h b/CPP/7zip/UI/Client7z/StdAfx.h new file mode 100755 index 0000000..2edddf4 --- /dev/null +++ b/CPP/7zip/UI/Client7z/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include +#include + +#endif diff --git a/CPP/7zip/UI/Client7z/makefile b/CPP/7zip/UI/Client7z/makefile new file mode 100755 index 0000000..e3a8239 --- /dev/null +++ b/CPP/7zip/UI/Client7z/makefile @@ -0,0 +1,45 @@ +PROG = 7z.exe +MY_CONSOLE = 1 +CFLAGS = $(CFLAGS) -I ../../../ + +CONSOLE_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\PropVariantConversions.obj \ + +7ZIP_COMMON_OBJS = \ + $O\FileStreams.obj \ + +OBJS = \ + $O\StdAfx.obj \ + $(CONSOLE_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + +!include "../../../Build.mak" + +$(CONSOLE_OBJS): $(*B).cpp + $(COMPL) +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp new file mode 100755 index 0000000..7fd012b --- /dev/null +++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp @@ -0,0 +1,1042 @@ +// ArchiveCommandLine.cpp + +#include "StdAfx.h" + +#ifdef _WIN32 +#ifndef UNDER_CE +#include +#endif +#endif +#include + +#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/Synchronization.h" +#endif + +#include "ArchiveCommandLine.h" +#include "EnumDirItems.h" +#include "SortUtils.h" +#include "Update.h" +#include "UpdateAction.h" + +extern bool g_CaseSensitive; + +#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; + +int g_CodePage = -1; + +namespace NKey { +enum Enum +{ + kHelp1 = 0, + kHelp2, + kHelp3, + kDisableHeaders, + kDisablePercents, + kArchiveType, + kYes, + #ifndef _NO_CRYPTO + kPassword, + #endif + kProperty, + kOutputDir, + kWorkingDir, + kInclude, + kExclude, + kArInclude, + kArExclude, + kNoArName, + kUpdate, + kVolume, + kRecursed, + kSfx, + kStdIn, + kStdOut, + kOverwrite, + kEmail, + kShowDialog, + kLargePages, + kListfileCharSet, + kConsoleCharSet, + kTechMode, + kShareForWrite, + kCaseSensitive, + kCalcCrc +}; + +} + + +static const wchar_t kRecursedIDChar = 'R'; +static const wchar_t *kRecursedPostCharSet = L"0-"; + +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 wchar_t *kOverwritePostCharSet = L"asut"; + +NExtract::NOverwriteMode::EEnum k_OverwriteModes[] = +{ + NExtract::NOverwriteMode::kWithoutPrompt, + NExtract::NOverwriteMode::kSkipExisting, + NExtract::NOverwriteMode::kAutoRename, + NExtract::NOverwriteMode::kAutoRenameExisting +}; + +static const CSwitchForm kSwitchForms[] = + { + { L"?", NSwitchType::kSimple, false }, + { L"H", NSwitchType::kSimple, false }, + { L"-HELP", NSwitchType::kSimple, false }, + { L"BA", NSwitchType::kSimple, false }, + { L"BD", NSwitchType::kSimple, false }, + { L"T", NSwitchType::kUnLimitedPostString, false, 1 }, + { L"Y", NSwitchType::kSimple, false }, + #ifndef _NO_CRYPTO + { L"P", NSwitchType::kUnLimitedPostString, false, 0 }, + #endif + { L"M", NSwitchType::kUnLimitedPostString, true, 1 }, + { L"O", NSwitchType::kUnLimitedPostString, false, 1 }, + { L"W", NSwitchType::kUnLimitedPostString, false, 0 }, + { L"I", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, + { L"X", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, + { L"AI", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, + { L"AX", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, + { L"AN", NSwitchType::kSimple, false }, + { L"U", NSwitchType::kUnLimitedPostString, true, 1}, + { L"V", NSwitchType::kUnLimitedPostString, true, 1}, + { L"R", NSwitchType::kPostChar, false, 0, 0, kRecursedPostCharSet }, + { L"SFX", NSwitchType::kUnLimitedPostString, false, 0 }, + { L"SI", NSwitchType::kUnLimitedPostString, false, 0 }, + { L"SO", NSwitchType::kSimple, false, 0 }, + { L"AO", NSwitchType::kPostChar, false, 1, 1, kOverwritePostCharSet}, + { L"SEML", NSwitchType::kUnLimitedPostString, false, 0}, + { L"AD", NSwitchType::kSimple, false }, + { L"SLP", NSwitchType::kUnLimitedPostString, false, 0}, + { L"SCS", NSwitchType::kUnLimitedPostString, false, 0}, + { L"SCC", NSwitchType::kUnLimitedPostString, false, 0}, + { L"SLT", NSwitchType::kSimple, false }, + { L"SSW", NSwitchType::kSimple, false }, + { L"SSC", NSwitchType::kPostChar, false, 0, 0, L"-" }, + { L"SCRC", NSwitchType::kSimple, false } + }; + +static const CCommandForm g_CommandForms[] = +{ + { L"A", false }, + { L"U", false }, + { L"D", false }, + { L"T", false }, + { L"E", false }, + { L"X", false }, + { L"L", false }, + { L"B", false }, + { L"I", false } +}; + +static const int kNumCommandForms = sizeof(g_CommandForms) / sizeof(g_CommandForms[0]); + +static const wchar_t *kUniversalWildcard = L"*"; +static const int kMinNonSwitchWords = 1; +static const int kCommandIndex = 0; + +// --------------------------- +// exception messages + +static const char *kUserErrorMessage = "Incorrect command line"; +static const char *kCannotFindListFile = "Cannot find listfile"; +static const char *kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch."; +static const char *kIncorrectWildCardInListFile = "Incorrect wildcard in listfile"; +static const char *kIncorrectWildCardInCommandLine = "Incorrect wildcard in command line"; +static const char *kTerminalOutError = "I won't write compressed data to a terminal"; +static const char *kSameTerminalError = "I won't write data and program's messages to same terminal"; +static const char *kEmptyFilePath = "Empty file path"; + +static void ThrowException(const char *errorMessage) +{ + throw CArchiveCommandLineException(errorMessage); +} + +static void ThrowUserErrorException() +{ + ThrowException(kUserErrorMessage); +} + +// --------------------------- + +bool CArchiveCommand::IsFromExtractGroup() const +{ + switch(CommandType) + { + case NCommandType::kTest: + case NCommandType::kExtract: + case NCommandType::kFullExtract: + return true; + default: + return false; + } +} + +NExtract::NPathMode::EEnum CArchiveCommand::GetPathMode() const +{ + switch(CommandType) + { + case NCommandType::kTest: + case NCommandType::kFullExtract: + return NExtract::NPathMode::kFullPathnames; + default: + return NExtract::NPathMode::kNoPathnames; + } +} + +bool CArchiveCommand::IsFromUpdateGroup() const +{ + return (CommandType == NCommandType::kAdd || + CommandType == NCommandType::kUpdate || + CommandType == NCommandType::kDelete); +} + +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 bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command) +{ + UString commandStringUpper = commandString; + commandStringUpper.MakeUpper(); + UString postString; + int commandIndex = ParseCommand(kNumCommandForms, g_CommandForms, commandStringUpper, + postString) ; + if (commandIndex < 0) + return false; + command.CommandType = (NCommandType::EEnum)commandIndex; + return true; +} + +// ------------------------------------------------------------------ +// filenames functions + +static void AddNameToCensor(NWildcard::CCensor &wildcardCensor, + const UString &name, bool include, NRecursedType::EEnum type) +{ + bool recursed = false; + + switch (type) + { + case NRecursedType::kWildCardOnlyRecursed: + recursed = DoesNameContainWildCard(name); + break; + case NRecursedType::kRecursed: + recursed = true; + break; + } + wildcardCensor.AddItem(include, name, recursed); +} + +static void AddToCensorFromListFile(NWildcard::CCensor &wildcardCensor, + LPCWSTR fileName, bool include, NRecursedType::EEnum type, UINT codePage) +{ + UStringVector names; + if (!NFind::DoesFileExist(fileName)) + throw kCannotFindListFile; + if (!ReadNamesFromListFile(fileName, names, codePage)) + throw kIncorrectListFile; + for (int i = 0; i < names.Size(); i++) + AddNameToCensor(wildcardCensor, names[i], include, type); +} + +static void AddToCensorFromNonSwitchesStrings( + int startIndex, + NWildcard::CCensor &wildcardCensor, + const UStringVector &nonSwitchStrings, NRecursedType::EEnum type, + bool thereAreSwitchIncludes, UINT codePage) +{ + if (nonSwitchStrings.Size() == startIndex && (!thereAreSwitchIncludes)) + AddNameToCensor(wildcardCensor, kUniversalWildcard, true, type); + for (int i = startIndex; i < nonSwitchStrings.Size(); i++) + { + const UString &s = nonSwitchStrings[i]; + if (s.IsEmpty()) + throw kEmptyFilePath; + if (s[0] == kFileListID) + AddToCensorFromListFile(wildcardCensor, s.Mid(1), true, type, codePage); + else + AddNameToCensor(wildcardCensor, s, true, type); + } +} + +#ifdef _WIN32 +static void ParseMapWithPaths(NWildcard::CCensor &wildcardCensor, + const UString &switchParam, bool include, + NRecursedType::EEnum commonRecursedType) +{ + int splitPos = switchParam.Find(L':'); + if (splitPos < 0) + ThrowUserErrorException(); + UString mappingName = switchParam.Left(splitPos); + + UString switchParam2 = switchParam.Mid(splitPos + 1); + splitPos = switchParam2.Find(L':'); + if (splitPos < 0) + ThrowUserErrorException(); + + UString mappingSize = switchParam2.Left(splitPos); + UString eventName = switchParam2.Mid(splitPos + 1); + + UInt64 dataSize64 = ConvertStringToUInt64(mappingSize, NULL); + UInt32 dataSize = (UInt32)dataSize64; + { + CFileMapping fileMapping; + if (fileMapping.Open(FILE_MAP_READ, GetSystemString(mappingName)) != 0) + ThrowException("Can not open mapping"); + LPVOID data = fileMapping.Map(FILE_MAP_READ, 0, dataSize); + if (data == NULL) + ThrowException("MapViewOfFile error"); + try + { + const wchar_t *curData = (const wchar_t *)data; + if (*curData != 0) + ThrowException("Incorrect mapping data"); + UInt32 numChars = dataSize / sizeof(wchar_t); + UString name; + for (UInt32 i = 1; i < numChars; i++) + { + wchar_t c = curData[i]; + if (c == L'\0') + { + AddNameToCensor(wildcardCensor, name, include, commonRecursedType); + name.Empty(); + } + else + name += c; + } + if (!name.IsEmpty()) + ThrowException("data error"); + } + catch(...) + { + UnmapViewOfFile(data); + throw; + } + UnmapViewOfFile(data); + } + + { + NSynchronization::CManualResetEvent event; + if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(eventName)) == S_OK) + event.Set(); + } +} +#endif + +static void AddSwitchWildCardsToCensor(NWildcard::CCensor &wildcardCensor, + const UStringVector &strings, bool include, + NRecursedType::EEnum commonRecursedType, UINT codePage) +{ + for (int i = 0; i < strings.Size(); i++) + { + const UString &name = strings[i]; + NRecursedType::EEnum recursedType; + int pos = 0; + if (name.Length() < kSomeCludePostStringMinSize) + ThrowUserErrorException(); + if (::MyCharUpper(name[pos]) == kRecursedIDChar) + { + pos++; + int index = UString(kRecursedPostCharSet).Find(name[pos]); + recursedType = GetRecursedTypeFromIndex(index); + if (index >= 0) + pos++; + } + else + recursedType = commonRecursedType; + if (name.Length() < pos + kSomeCludeAfterRecursedPostStringMinSize) + ThrowUserErrorException(); + UString tail = name.Mid(pos + 1); + if (name[pos] == kImmediateNameID) + AddNameToCensor(wildcardCensor, tail, include, recursedType); + else if (name[pos] == kFileListID) + AddToCensorFromListFile(wildcardCensor, tail, include, recursedType, codePage); + #ifdef _WIN32 + else if (name[pos] == kMapNameID) + ParseMapWithPaths(wildcardCensor, tail, include, recursedType); + #endif + else + ThrowUserErrorException(); + } +} + +#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::CFileInfoW fi; + if (fi.Find(prefix + name)) + name = fi.Name; +} + +static void ConvertToLongNames(const UString &prefix, CObjectVector &items) +{ + for (int i = 0; i < items.Size(); i++) + { + NWildcard::CItem &item = items[i]; + if (item.Recursive || item.PathParts.Size() != 1) + continue; + ConvertToLongName(prefix, item.PathParts.Front()); + } +} + +static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &node) +{ + ConvertToLongNames(prefix, node.IncludeItems); + ConvertToLongNames(prefix, node.ExcludeItems); + int i; + for (i = 0; i < node.SubNodes.Size(); i++) + ConvertToLongName(prefix, node.SubNodes[i].Name); + // mix folders with same name + for (i = 0; i < node.SubNodes.Size(); i++) + { + NWildcard::CCensorNode &nextNode1 = node.SubNodes[i]; + for (int j = i + 1; j < node.SubNodes.Size();) + { + const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j]; + if (nextNode1.Name.CompareNoCase(nextNode2.Name) == 0) + { + 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_t(NFile::NName::kDirDelimiter), nextNode); + } +} + +static void ConvertToLongNames(NWildcard::CCensor &censor) +{ + for (int i = 0; i < censor.Pairs.Size(); i++) + { + NWildcard::CPair &pair = censor.Pairs[i]; + ConvertToLongNames(pair.Prefix, pair.Head); + } +} + +#endif + +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; +} + +const UString kUpdatePairStateIDSet = L"PQRXYZW"; +const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1}; + +const UString kUpdatePairActionIDSet = L"0123"; //Ignore, Copy, Compress, Create Anti + +const wchar_t *kUpdateIgnoreItselfPostStringID = L"-"; +const wchar_t kUpdateNewArchivePostCharID = '!'; + + +static bool ParseUpdateCommandString2(const UString &command, + NUpdateArchive::CActionSet &actionSet, UString &postString) +{ + for (int i = 0; i < command.Length();) + { + wchar_t c = MyCharUpper(command[i]); + int statePos = kUpdatePairStateIDSet.Find(c); + if (statePos < 0) + { + postString = command.Mid(i); + return true; + } + i++; + if (i >= command.Length()) + return false; + int actionPos = kUpdatePairActionIDSet.Find(::MyCharUpper(command[i])); + if (actionPos < 0) + return false; + actionSet.StateActions[statePos] = GetUpdatePairActionType(actionPos); + if (kUpdatePairStateNotSupportedActions[statePos] == actionPos) + return false; + i++; + } + postString.Empty(); + return true; +} + +static void ParseUpdateCommandString(CUpdateOptions &options, + const UStringVector &updatePostStrings, + const NUpdateArchive::CActionSet &defaultActionSet) +{ + for (int i = 0; i < updatePostStrings.Size(); i++) + { + const UString &updateString = updatePostStrings[i]; + if (updateString.CompareNoCase(kUpdateIgnoreItselfPostStringID) == 0) + { + if (options.UpdateArchiveItself) + { + options.UpdateArchiveItself = false; + options.Commands.Delete(0); + } + } + else + { + NUpdateArchive::CActionSet actionSet = defaultActionSet; + + UString postString; + if (!ParseUpdateCommandString2(updateString, actionSet, postString)) + ThrowUserErrorException(); + if (postString.IsEmpty()) + { + if (options.UpdateArchiveItself) + options.Commands[0].ActionSet = actionSet; + } + else + { + if (MyCharUpper(postString[0]) != kUpdateNewArchivePostCharID) + ThrowUserErrorException(); + CUpdateArchiveCommand uc; + UString archivePath = postString.Mid(1); + if (archivePath.IsEmpty()) + ThrowUserErrorException(); + uc.UserArchivePath = archivePath; + uc.ActionSet = actionSet; + options.Commands.Add(uc); + } + } + } +} + +static const char kByteSymbol = 'B'; +static const char kKiloSymbol = 'K'; +static const char kMegaSymbol = 'M'; +static const char kGigaSymbol = 'G'; + +static bool ParseComplexSize(const UString &src, UInt64 &result) +{ + UString s = src; + s.MakeUpper(); + + const wchar_t *start = s; + const wchar_t *end; + UInt64 number = ConvertStringToUInt64(start, &end); + int numDigits = (int)(end - start); + if (numDigits == 0 || s.Length() > numDigits + 1) + return false; + if (s.Length() == numDigits) + { + result = number; + return true; + } + int numBits; + switch (s[numDigits]) + { + case kByteSymbol: + result = number; + return true; + case kKiloSymbol: + numBits = 10; + break; + case kMegaSymbol: + numBits = 20; + break; + case kGigaSymbol: + numBits = 30; + break; + default: + return false; + } + if (number >= ((UInt64)1 << (64 - numBits))) + return false; + result = number << numBits; + return true; +} + +static void SetAddCommandOptions( + NCommandType::EEnum commandType, + const CParser &parser, + CUpdateOptions &options) +{ + NUpdateArchive::CActionSet defaultActionSet; + switch(commandType) + { + case NCommandType::kAdd: + defaultActionSet = NUpdateArchive::kAddActionSet; + break; + case NCommandType::kDelete: + defaultActionSet = NUpdateArchive::kDeleteActionSet; + break; + default: + defaultActionSet = NUpdateArchive::kUpdateActionSet; + } + + 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()) + NDirectory::MyGetTempPath(options.WorkingDir); + else + options.WorkingDir = postString; + } + options.SfxMode = parser[NKey::kSfx].ThereIs; + if (options.SfxMode) + options.SfxModule = parser[NKey::kSfx].PostStrings[0]; + + if (parser[NKey::kVolume].ThereIs) + { + const UStringVector &sv = parser[NKey::kVolume].PostStrings; + for (int i = 0; i < sv.Size(); i++) + { + UInt64 size; + if (!ParseComplexSize(sv[i], size)) + ThrowException("Incorrect volume size"); + options.VolumesSizes.Add(size); + } + } +} + +static void SetMethodOptions(const CParser &parser, CObjectVector &properties) +{ + if (parser[NKey::kProperty].ThereIs) + { + // options.MethodMode.Properties.Clear(); + for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++) + { + CProperty property; + const UString &postString = parser[NKey::kProperty].PostStrings[i]; + int index = postString.Find(L'='); + if (index < 0) + property.Name = postString; + else + { + property.Name = postString.Left(index); + property.Value = postString.Mid(index + 1); + } + properties.Add(property); + } + } +} + +CArchiveCommandLineParser::CArchiveCommandLineParser(): + parser(sizeof(kSwitchForms) / sizeof(kSwitchForms[0])) {} + +void CArchiveCommandLineParser::Parse1(const UStringVector &commandStrings, + CArchiveCommandLineOptions &options) +{ + try + { + parser.ParseStrings(kSwitchForms, commandStrings); + } + catch(...) + { + ThrowUserErrorException(); + } + + options.IsInTerminal = MY_IS_TERMINAL(stdin); + options.IsStdOutTerminal = MY_IS_TERMINAL(stdout); + options.IsStdErrTerminal = MY_IS_TERMINAL(stderr); + options.StdInMode = parser[NKey::kStdIn].ThereIs; + options.StdOutMode = parser[NKey::kStdOut].ThereIs; + options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs; + options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs || parser[NKey::kHelp3].ThereIs; + + #ifdef _WIN32 + options.LargePages = false; + if (parser[NKey::kLargePages].ThereIs) + { + const UString &postString = parser[NKey::kLargePages].PostStrings.Front(); + if (postString.IsEmpty()) + options.LargePages = true; + } + #endif +} + +struct CCodePagePair +{ + const wchar_t *Name; + UINT CodePage; +}; + +static CCodePagePair g_CodePagePairs[] = +{ + { L"UTF-8", CP_UTF8 }, + { L"WIN", CP_ACP }, + { L"DOS", CP_OEMCP } +}; + +static int FindCharset(const NCommandLineParser::CParser &parser, int keyIndex, int defaultVal) +{ + if (!parser[keyIndex].ThereIs) + return defaultVal; + + UString name = parser[keyIndex].PostStrings.Back(); + name.MakeUpper(); + int i; + for (i = 0; i < sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0]); i++) + { + const CCodePagePair &pair = g_CodePagePairs[i]; + if (name.Compare(pair.Name) == 0) + return pair.CodePage; + } + if (i == sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0])) + ThrowUserErrorException(); + return -1; +} + +static bool ConvertStringToUInt32(const wchar_t *s, UInt32 &v) +{ + const wchar_t *end; + UInt64 number = ConvertStringToUInt64(s, &end); + if (*end != 0) + return false; + if (number > (UInt32)0xFFFFFFFF) + return false; + v = (UInt32)number; + return true; +} + +void EnumerateDirItemsAndSort(NWildcard::CCensor &wildcardCensor, + UStringVector &sortedPaths, + UStringVector &sortedFullPaths) +{ + UStringVector paths; + { + CDirItems dirItems; + { + UStringVector errorPaths; + CRecordVector errorCodes; + HRESULT res = EnumerateItems(wildcardCensor, dirItems, NULL, errorPaths, errorCodes); + if (res != S_OK || errorPaths.Size() > 0) + throw "cannot find archive"; + } + for (int i = 0; i < dirItems.Items.Size(); i++) + { + const CDirItem &dirItem = dirItems.Items[i]; + if (!dirItem.IsDir()) + paths.Add(dirItems.GetPhyPath(i)); + } + } + + if (paths.Size() == 0) + throw "there is no such archive"; + + UStringVector fullPaths; + + int i; + for (i = 0; i < paths.Size(); i++) + { + UString fullPath; + NFile::NDirectory::MyGetFullPathName(paths[i], fullPath); + fullPaths.Add(fullPath); + } + CIntVector indices; + SortFileNames(fullPaths, indices); + sortedPaths.Reserve(indices.Size()); + sortedFullPaths.Reserve(indices.Size()); + for (i = 0; i < indices.Size(); i++) + { + int index = indices[i]; + sortedPaths.Add(paths[index]); + sortedFullPaths.Add(fullPaths[index]); + } +} + +void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) +{ + const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; + int numNonSwitchStrings = nonSwitchStrings.Size(); + if (numNonSwitchStrings < kMinNonSwitchWords) + ThrowUserErrorException(); + + if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command)) + ThrowUserErrorException(); + + options.TechMode = parser[NKey::kTechMode].ThereIs; + options.CalcCrc = parser[NKey::kCalcCrc].ThereIs; + + if (parser[NKey::kCaseSensitive].ThereIs) + g_CaseSensitive = (parser[NKey::kCaseSensitive].PostCharIndex < 0); + + NRecursedType::EEnum recursedType; + if (parser[NKey::kRecursed].ThereIs) + recursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharIndex); + else + recursedType = NRecursedType::kNonRecursed; + + g_CodePage = FindCharset(parser, NKey::kConsoleCharSet, -1); + UINT codePage = FindCharset(parser, NKey::kListfileCharSet, CP_UTF8); + + bool thereAreSwitchIncludes = false; + if (parser[NKey::kInclude].ThereIs) + { + thereAreSwitchIncludes = true; + AddSwitchWildCardsToCensor(options.WildcardCensor, + parser[NKey::kInclude].PostStrings, true, recursedType, codePage); + } + if (parser[NKey::kExclude].ThereIs) + AddSwitchWildCardsToCensor(options.WildcardCensor, + parser[NKey::kExclude].PostStrings, false, recursedType, codePage); + + int curCommandIndex = kCommandIndex + 1; + bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs && + options.Command.CommandType != NCommandType::kBenchmark && + options.Command.CommandType != NCommandType::kInfo; + + bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); + bool isExtractOrList = isExtractGroupCommand || options.Command.CommandType == NCommandType::kList; + + if (isExtractOrList && options.StdInMode) + thereIsArchiveName = false; + + if (thereIsArchiveName) + { + if (curCommandIndex >= numNonSwitchStrings) + ThrowUserErrorException(); + options.ArchiveName = nonSwitchStrings[curCommandIndex++]; + if (options.ArchiveName.IsEmpty()) + ThrowUserErrorException(); + } + + AddToCensorFromNonSwitchesStrings( + curCommandIndex, options.WildcardCensor, + nonSwitchStrings, recursedType, 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]; + + if (isExtractOrList) + { + if (!options.WildcardCensor.AllAreRelative()) + ThrowException("Cannot use absolute pathnames for this command"); + + NWildcard::CCensor archiveWildcardCensor; + + if (parser[NKey::kArInclude].ThereIs) + AddSwitchWildCardsToCensor(archiveWildcardCensor, + parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, codePage); + if (parser[NKey::kArExclude].ThereIs) + AddSwitchWildCardsToCensor(archiveWildcardCensor, + parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, codePage); + + if (thereIsArchiveName) + AddNameToCensor(archiveWildcardCensor, options.ArchiveName, true, NRecursedType::kNonRecursed); + + #ifdef _WIN32 + ConvertToLongNames(archiveWildcardCensor); + #endif + + archiveWildcardCensor.ExtendExclude(); + + if (options.StdInMode) + { + UString arcName = parser[NKey::kStdIn].PostStrings.Front(); + options.ArchivePathsSorted.Add(arcName); + options.ArchivePathsFullSorted.Add(arcName); + } + else + { + EnumerateDirItemsAndSort(archiveWildcardCensor, + options.ArchivePathsSorted, + options.ArchivePathsFullSorted); + } + + if (isExtractGroupCommand) + { + SetMethodOptions(parser, options.ExtractProperties); + if (options.StdOutMode && options.IsStdOutTerminal && options.IsStdErrTerminal) + throw kSameTerminalError; + if (parser[NKey::kOutputDir].ThereIs) + { + options.OutputDir = parser[NKey::kOutputDir].PostStrings[0]; + NFile::NName::NormalizeDirPathPrefix(options.OutputDir); + } + + options.OverwriteMode = NExtract::NOverwriteMode::kAskBefore; + if (parser[NKey::kOverwrite].ThereIs) + options.OverwriteMode = k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex]; + else if (options.YesToAll) + options.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; + } + } + else if (options.Command.IsFromUpdateGroup()) + { + CUpdateOptions &updateOptions = options.UpdateOptions; + + SetAddCommandOptions(options.Command.CommandType, parser, updateOptions); + + SetMethodOptions(parser, updateOptions.MethodMode.Properties); + + if (parser[NKey::kShareForWrite].ThereIs) + updateOptions.OpenShareForWrite = true; + + options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs; + + if (options.EnablePercents) + { + if ((options.StdOutMode && !options.IsStdErrTerminal) || + (!options.StdOutMode && !options.IsStdOutTerminal)) + options.EnablePercents = false; + } + + updateOptions.EMailMode = parser[NKey::kEmail].ThereIs; + if (updateOptions.EMailMode) + { + updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front(); + if (updateOptions.EMailAddress.Length() > 0) + if (updateOptions.EMailAddress[0] == L'.') + { + updateOptions.EMailRemoveAfter = true; + updateOptions.EMailAddress.Delete(0); + } + } + + updateOptions.StdOutMode = options.StdOutMode; + updateOptions.StdInMode = options.StdInMode; + + if (updateOptions.StdOutMode && updateOptions.EMailMode) + throw "stdout mode and email mode cannot be combined"; + if (updateOptions.StdOutMode && options.IsStdOutTerminal) + throw kTerminalOutError; + if (updateOptions.StdInMode) + updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front(); + + #ifdef _WIN32 + ConvertToLongNames(options.WildcardCensor); + #endif + } + else if (options.Command.CommandType == NCommandType::kBenchmark) + { + options.NumThreads = (UInt32)-1; + options.DictionarySize = (UInt32)-1; + options.NumIterations = 1; + if (curCommandIndex < numNonSwitchStrings) + { + if (!ConvertStringToUInt32(nonSwitchStrings[curCommandIndex++], options.NumIterations)) + ThrowUserErrorException(); + } + for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++) + { + UString postString = parser[NKey::kProperty].PostStrings[i]; + postString.MakeUpper(); + if (postString.Length() < 2) + ThrowUserErrorException(); + if (postString[0] == 'D') + { + int pos = 1; + if (postString[pos] == '=') + pos++; + UInt32 logSize; + if (!ConvertStringToUInt32((const wchar_t *)postString + pos, logSize)) + ThrowUserErrorException(); + if (logSize > 31) + ThrowUserErrorException(); + options.DictionarySize = 1 << logSize; + } + else if (postString[0] == 'M' && postString[1] == 'T' ) + { + int pos = 2; + if (postString[pos] == '=') + pos++; + if (postString[pos] != 0) + if (!ConvertStringToUInt32((const wchar_t *)postString + pos, options.NumThreads)) + ThrowUserErrorException(); + } + else if (postString[0] == 'M' && postString[1] == '=' ) + { + int pos = 2; + if (postString[pos] != 0) + options.Method = postString.Mid(2); + } + else + ThrowUserErrorException(); + } + } + else if (options.Command.CommandType == NCommandType::kInfo) + { + } + else + ThrowUserErrorException(); + options.WildcardCensor.ExtendExclude(); +} diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.h b/CPP/7zip/UI/Common/ArchiveCommandLine.h new file mode 100755 index 0000000..491689e --- /dev/null +++ b/CPP/7zip/UI/Common/ArchiveCommandLine.h @@ -0,0 +1,111 @@ +// ArchiveCommandLine.h + +#ifndef __ARCHIVE_COMMAND_LINE_H +#define __ARCHIVE_COMMAND_LINE_H + +#include "Common/CommandLineParser.h" +#include "Common/Wildcard.h" + +#include "Extract.h" +#include "Update.h" + +struct CArchiveCommandLineException: public AString +{ + CArchiveCommandLineException(const char *errorMessage): AString(errorMessage) {} +}; + +namespace NCommandType { enum EEnum +{ + kAdd = 0, + kUpdate, + kDelete, + kTest, + kExtract, + kFullExtract, + kList, + kBenchmark, + kInfo +};} + +namespace NRecursedType { enum EEnum +{ + kRecursed, + kWildCardOnlyRecursed, + kNonRecursed +};} + +struct CArchiveCommand +{ + NCommandType::EEnum CommandType; + bool IsFromExtractGroup() const; + bool IsFromUpdateGroup() const; + bool IsTestMode() const { return CommandType == NCommandType::kTest; } + NExtract::NPathMode::EEnum GetPathMode() const; +}; + +struct CArchiveCommandLineOptions +{ + bool HelpMode; + + #ifdef _WIN32 + bool LargePages; + #endif + + bool IsInTerminal; + bool IsStdOutTerminal; + bool IsStdErrTerminal; + bool StdInMode; + bool StdOutMode; + bool EnableHeaders; + + bool YesToAll; + bool ShowDialog; + // NWildcard::CCensor ArchiveWildcardCensor; + NWildcard::CCensor WildcardCensor; + + CArchiveCommand Command; + UString ArchiveName; + + #ifndef _NO_CRYPTO + bool PasswordEnabled; + UString Password; + #endif + + bool TechMode; + // Extract + bool CalcCrc; + bool AppendName; + UString OutputDir; + NExtract::NOverwriteMode::EEnum OverwriteMode; + UStringVector ArchivePathsSorted; + UStringVector ArchivePathsFullSorted; + CObjectVector ExtractProperties; + + CUpdateOptions UpdateOptions; + UString ArcType; + bool EnablePercents; + + // Benchmark + UInt32 NumIterations; + UInt32 NumThreads; + UInt32 DictionarySize; + UString Method; + + + CArchiveCommandLineOptions(): StdInMode(false), StdOutMode(false) {}; +}; + +class CArchiveCommandLineParser +{ + NCommandLineParser::CParser parser; +public: + CArchiveCommandLineParser(); + void Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options); + void Parse2(CArchiveCommandLineOptions &options); +}; + +void EnumerateDirItemsAndSort(NWildcard::CCensor &wildcardCensor, + UStringVector &sortedPaths, + UStringVector &sortedFullPaths); + +#endif diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp new file mode 100755 index 0000000..2a322c5 --- /dev/null +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp @@ -0,0 +1,488 @@ +// ArchiveExtractCallback.cpp + +#include "StdAfx.h" + +#include "Common/ComTry.h" +#include "Common/Wildcard.h" + +#include "Windows/FileDir.h" +#include "Windows/FileFind.h" +#include "Windows/PropVariant.h" +#include "Windows/PropVariantConversions.h" + +#include "../../Common/FilePathAutoRename.h" + +#include "../Common/ExtractingFilePath.h" + +#include "ArchiveExtractCallback.h" + +using namespace NWindows; + +static const wchar_t *kCantAutoRename = L"ERROR: Can not create file with auto name"; +static const wchar_t *kCantRenameFile = L"ERROR: Can not rename existing file "; +static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file "; + +void CArchiveExtractCallback::Init( + const NWildcard::CCensorNode *wildcardCensor, + const CArc *arc, + IFolderArchiveExtractCallback *extractCallback2, + bool stdOutMode, bool testMode, bool crcMode, + const UString &directoryPath, + const UStringVector &removePathParts, + UInt64 packSize) +{ + _wildcardCensor = wildcardCensor; + + _stdOutMode = stdOutMode; + _testMode = testMode; + _crcMode = crcMode; + _unpTotal = 1; + _packTotal = packSize; + + _extractCallback2 = extractCallback2; + _compressProgress.Release(); + _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress); + + LocalProgressSpec->Init(extractCallback2, true); + LocalProgressSpec->SendProgress = false; + + + _removePathParts = removePathParts; + _arc = arc; + _directoryPath = directoryPath; + NFile::NName::NormalizeDirPathPrefix(_directoryPath); +} + +STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size) +{ + COM_TRY_BEGIN + _unpTotal = size; + 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; + + if (_multiArchives) + { + if (completeValue != NULL) + { + UInt64 packCur = LocalProgressSpec->InSize + MyMultDiv64(*completeValue, _unpTotal, _packTotal); + return _extractCallback2->SetCompleted(&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, UString &fullPath) +{ + fullPath = _directoryPath; + for (int i = 0; i < dirPathParts.Size(); i++) + { + if (i > 0) + fullPath += wchar_t(NFile::NName::kDirDelimiter); + fullPath += dirPathParts[i]; + NFile::NDirectory::MyCreateDirectory(fullPath); + } +} + +HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined) +{ + filetimeIsDefined = false; + 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() +{ + NCOM::CPropVariant prop; + RINOK(_arc->Archive->GetProperty(_index, kpidSize, &prop)); + _curSizeDefined = (prop.vt != VT_EMPTY); + if (_curSizeDefined) + _curSize = ConvertPropVariantToUInt64(prop); + return S_OK; +} + +STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) +{ + COM_TRY_BEGIN + _crcStream.Release(); + *outStream = 0; + _outFileStream.Release(); + + _encrypted = false; + _isSplit = false; + _curSize = 0; + _curSizeDefined = false; + _index = index; + + UString fullPath; + + IInArchive *archive = _arc->Archive; + RINOK(_arc->GetItemPath(index, fullPath)); + RINOK(IsArchiveItemFolder(archive, index, _fi.IsDir)); + + _filePath = fullPath; + + { + 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; + } + } + + RINOK(GetArchiveItemBoolProp(archive, index, kpidEncrypted, _encrypted)); + + RINOK(GetUnpackSize()); + + if (_wildcardCensor) + { + if (!_wildcardCensor->CheckPath(fullPath, !_fi.IsDir)) + return S_OK; + } + + if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) + { + if (_stdOutMode) + { + CMyComPtr outStreamLoc = new CStdOutFileStream; + *outStream = outStreamLoc.Detach(); + return S_OK; + } + + { + 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)); + + UStringVector pathParts; + SplitPathToParts(fullPath, pathParts); + + if (pathParts.IsEmpty()) + return E_FAIL; + int numRemovePathParts = 0; + switch(_pathMode) + { + case NExtract::NPathMode::kFullPathnames: + break; + case NExtract::NPathMode::kCurrentPathnames: + { + numRemovePathParts = _removePathParts.Size(); + if (pathParts.Size() <= numRemovePathParts) + return E_FAIL; + for (int i = 0; i < numRemovePathParts; i++) + if (_removePathParts[i].CompareNoCase(pathParts[i]) != 0) + return E_FAIL; + break; + } + case NExtract::NPathMode::kNoPathnames: + { + numRemovePathParts = pathParts.Size() - 1; + break; + } + } + pathParts.Delete(0, numRemovePathParts); + MakeCorrectPath(pathParts); + UString processedPath = MakePathNameFromParts(pathParts); + if (!isAnti) + { + if (!_fi.IsDir) + { + if (!pathParts.IsEmpty()) + pathParts.DeleteBack(); + } + + if (!pathParts.IsEmpty()) + { + UString fullPathNew; + CreateComplexDirectory(pathParts, fullPathNew); + if (_fi.IsDir) + NFile::NDirectory::SetDirTime(fullPathNew, + (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL, + (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL, + (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL)); + } + } + + + UString fullProcessedPath = _directoryPath + processedPath; + + if (_fi.IsDir) + { + _diskFilePath = fullProcessedPath; + if (isAnti) + NFile::NDirectory::MyRemoveDirectory(_diskFilePath); + return S_OK; + } + + if (!_isSplit) + { + NFile::NFind::CFileInfoW fileInfo; + if (fileInfo.Find(fullProcessedPath)) + { + switch(_overwriteMode) + { + case NExtract::NOverwriteMode::kSkipExisting: + return S_OK; + case NExtract::NOverwriteMode::kAskBefore: + { + Int32 overwiteResult; + RINOK(_extractCallback2->AskOverwrite( + fullProcessedPath, &fileInfo.MTime, &fileInfo.Size, fullPath, + _fi.MTimeDefined ? &_fi.MTime : NULL, + _curSizeDefined ? &_curSize : NULL, + &overwiteResult)) + + switch(overwiteResult) + { + case NOverwriteAnswer::kCancel: + return E_ABORT; + case NOverwriteAnswer::kNo: + return S_OK; + case NOverwriteAnswer::kNoToAll: + _overwriteMode = NExtract::NOverwriteMode::kSkipExisting; + return S_OK; + case NOverwriteAnswer::kYesToAll: + _overwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; + break; + case NOverwriteAnswer::kYes: + break; + case NOverwriteAnswer::kAutoRename: + _overwriteMode = NExtract::NOverwriteMode::kAutoRename; + break; + default: + return E_FAIL; + } + } + } + if (_overwriteMode == NExtract::NOverwriteMode::kAutoRename) + { + if (!AutoRenamePath(fullProcessedPath)) + { + UString message = UString(kCantAutoRename) + fullProcessedPath; + RINOK(_extractCallback2->MessageError(message)); + return E_FAIL; + } + } + else if (_overwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting) + { + UString existPath = fullProcessedPath; + if (!AutoRenamePath(existPath)) + { + UString message = kCantAutoRename + fullProcessedPath; + RINOK(_extractCallback2->MessageError(message)); + return E_FAIL; + } + if (!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath)) + { + UString message = UString(kCantRenameFile) + fullProcessedPath; + RINOK(_extractCallback2->MessageError(message)); + return E_FAIL; + } + } + else + if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) + { + UString message = UString(kCantDeleteOutputFile) + fullProcessedPath; + RINOK(_extractCallback2->MessageError(message)); + return S_OK; + // return E_FAIL; + } + } + } + if (!isAnti) + { + _outFileStreamSpec = new COutFileStream; + CMyComPtr outStreamLoc(_outFileStreamSpec); + if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS)) + { + // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit) + { + UString message = L"can not open output file " + fullProcessedPath; + RINOK(_extractCallback2->MessageError(message)); + return S_OK; + } + } + if (_isSplit) + { + RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL)); + } + _outFileStream = outStreamLoc; + *outStream = outStreamLoc.Detach(); + } + _diskFilePath = fullProcessedPath; + } + else + { + *outStream = NULL; + } + if (_crcMode) + { + _crcStreamSpec = new COutStreamWithCRC; + _crcStream = _crcStreamSpec; + CMyComPtr crcStream = _crcStreamSpec; + _crcStreamSpec->SetStream(*outStream); + if (*outStream) + (*outStream)->Release(); + *outStream = crcStream.Detach(); + _crcStreamSpec->Init(true); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) +{ + COM_TRY_BEGIN + _extractMode = false; + switch (askExtractMode) + { + case NArchive::NExtract::NAskMode::kExtract: + if (_testMode) + askExtractMode = NArchive::NExtract::NAskMode::kTest; + else + _extractMode = true; + break; + }; + return _extractCallback2->PrepareOperation(_filePath, _fi.IsDir, + askExtractMode, _isSplit ? &_position: 0); + COM_TRY_END +} + +STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) +{ + COM_TRY_BEGIN + switch(operationResult) + { + case NArchive::NExtract::NOperationResult::kOK: + case NArchive::NExtract::NOperationResult::kUnSupportedMethod: + case NArchive::NExtract::NOperationResult::kCRCError: + case NArchive::NExtract::NOperationResult::kDataError: + break; + default: + _outFileStream.Release(); + return E_FAIL; + } + if (_crcStream) + { + CrcSum += _crcStreamSpec->GetCRC(); + _curSize = _crcStreamSpec->GetSize(); + _curSizeDefined = true; + _crcStream.Release(); + } + if (_outFileStream) + { + _outFileStreamSpec->SetTime( + (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL, + (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL, + (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL)); + _curSize = _outFileStreamSpec->ProcessedSize; + _curSizeDefined = true; + RINOK(_outFileStreamSpec->Close()); + _outFileStream.Release(); + } + if (!_curSizeDefined) + GetUnpackSize(); + if (_curSizeDefined) + UnpackSize += _curSize; + if (_fi.IsDir) + NumFolders++; + else + NumFiles++; + + if (_extractMode && _fi.AttribDefined) + NFile::NDirectory::MySetFileAttributes(_diskFilePath, _fi.Attrib); + RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted)); + return S_OK; + COM_TRY_END +} + +/* +STDMETHODIMP CArchiveExtractCallback::GetInStream( + const wchar_t *name, ISequentialInStream **inStream) +{ + COM_TRY_BEGIN + CInFileStream *inFile = new CInFileStream; + CMyComPtr inStreamTemp = inFile; + if (!inFile->Open(_srcDirectoryPrefix + name)) + return ::GetLastError(); + *inStream = inStreamTemp.Detach(); + return S_OK; + COM_TRY_END +} +*/ + +STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) +{ + COM_TRY_BEGIN + if (!_cryptoGetTextPassword) + { + RINOK(_extractCallback2.QueryInterface(IID_ICryptoGetTextPassword, + &_cryptoGetTextPassword)); + } + return _cryptoGetTextPassword->CryptoGetTextPassword(password); + COM_TRY_END +} + diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h new file mode 100755 index 0000000..b7a6a47 --- /dev/null +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h @@ -0,0 +1,143 @@ +// 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 "../../Archive/Common/OutStreamWithCRC.h" + +#include "ExtractMode.h" +#include "IFileExtractCallback.h" +#include "OpenArchive.h" + +class CArchiveExtractCallback: + public IArchiveExtractCallback, + // public IArchiveVolumeExtractCallback, + public ICryptoGetTextPassword, + public ICompressProgressInfo, + public CMyUnknownImp +{ + const CArc *_arc; + const NWildcard::CCensorNode *_wildcardCensor; + CMyComPtr _extractCallback2; + CMyComPtr _compressProgress; + CMyComPtr _cryptoGetTextPassword; + UString _directoryPath; + NExtract::NPathMode::EEnum _pathMode; + NExtract::NOverwriteMode::EEnum _overwriteMode; + + UString _diskFilePath; + UString _filePath; + 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; + + bool IsDir; + } _fi; + + UInt32 _index; + UInt64 _curSize; + bool _curSizeDefined; + COutFileStream *_outFileStreamSpec; + CMyComPtr _outFileStream; + + COutStreamWithCRC *_crcStreamSpec; + CMyComPtr _crcStream; + + UStringVector _removePathParts; + + bool _stdOutMode; + bool _testMode; + bool _crcMode; + bool _multiArchives; + + CMyComPtr _localProgress; + UInt64 _packTotal; + UInt64 _unpTotal; + + void CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath); + HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined); + HRESULT GetUnpackSize(); + +public: + + CLocalProgress *LocalProgressSpec; + + UInt64 NumFolders; + UInt64 NumFiles; + UInt64 UnpackSize; + UInt32 CrcSum; + + MY_UNKNOWN_IMP2(ICryptoGetTextPassword, ICompressProgressInfo) + // COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback) + + INTERFACE_IArchiveExtractCallback(;) + + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); + + // IArchiveVolumeExtractCallback + // STDMETHOD(GetInStream)(const wchar_t *name, ISequentialInStream **inStream); + + STDMETHOD(CryptoGetTextPassword)(BSTR *password); + + CArchiveExtractCallback(): + WriteCTime(true), + WriteATime(true), + WriteMTime(true), + _multiArchives(false) + { + LocalProgressSpec = new CLocalProgress(); + _localProgress = LocalProgressSpec; + } + + void InitForMulti(bool multiArchives, + NExtract::NPathMode::EEnum pathMode, + NExtract::NOverwriteMode::EEnum overwriteMode) + { + _multiArchives = multiArchives; + _pathMode = pathMode; + _overwriteMode = overwriteMode; + NumFolders = NumFiles = UnpackSize = 0; + CrcSum = 0; + } + + void Init( + const NWildcard::CCensorNode *wildcardCensor, + const CArc *arc, + IFolderArchiveExtractCallback *extractCallback2, + bool stdOutMode, bool testMode, bool crcMode, + const UString &directoryPath, + const UStringVector &removePathParts, + UInt64 packSize); + +}; + +#endif diff --git a/CPP/7zip/UI/Common/ArchiveName.cpp b/CPP/7zip/UI/Common/ArchiveName.cpp new file mode 100755 index 0000000..c62c7f1 --- /dev/null +++ b/CPP/7zip/UI/Common/ArchiveName.cpp @@ -0,0 +1,54 @@ +// ArchiveName.cpp + +#include "StdAfx.h" + +#include "Windows/FileDir.h" +#include "Windows/FileFind.h" + +#include "ExtractingFilePath.h" + +using namespace NWindows; + +static UString CreateArchiveName2(const UString &srcName, bool fromPrev, bool keepName) +{ + UString resultName = L"Archive"; + if (fromPrev) + { + UString dirPrefix; + if (NFile::NDirectory::GetOnlyDirPrefix(srcName, dirPrefix)) + { + if (dirPrefix.Length() > 0) + if (dirPrefix[dirPrefix.Length() - 1] == WCHAR_PATH_SEPARATOR) + { + dirPrefix.Delete(dirPrefix.Length() - 1); + NFile::NFind::CFileInfoW fileInfo; + if (fileInfo.Find(dirPrefix)) + resultName = fileInfo.Name; + } + } + } + else + { + NFile::NFind::CFileInfoW fileInfo; + if (!fileInfo.Find(srcName)) + // return resultName; + return srcName; + resultName = fileInfo.Name; + if (!fileInfo.IsDir() && !keepName) + { + int dotPos = resultName.ReverseFind('.'); + if (dotPos > 0) + { + UString archiveName2 = resultName.Left(dotPos); + if (archiveName2.ReverseFind('.') < 0) + resultName = archiveName2; + } + } + } + return resultName; +} + +UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName) +{ + return GetCorrectFsPath(CreateArchiveName2(srcName, fromPrev, keepName)); +} diff --git a/CPP/7zip/UI/Common/ArchiveName.h b/CPP/7zip/UI/Common/ArchiveName.h new file mode 100755 index 0000000..ba18eea --- /dev/null +++ b/CPP/7zip/UI/Common/ArchiveName.h @@ -0,0 +1,10 @@ +// ArchiveName.h + +#ifndef __ARCHIVENAME_H +#define __ARCHIVENAME_H + +#include "Common/MyString.h" + +UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName); + +#endif diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp new file mode 100755 index 0000000..bb8b6cc --- /dev/null +++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp @@ -0,0 +1,133 @@ +// ArchiveOpenCallback.cpp + +#include "StdAfx.h" + +#include "Common/StringConvert.h" +#include "Common/ComTry.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; + } + 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 +} + +int COpenCallbackImp::FindName(const UString &name) +{ + for (int i = 0; i < FileNames.Size(); i++) + if (name.CompareNoCase(FileNames[i]) == 0) + return i; + return -1; +} + +struct CInFileStreamVol: public CInFileStream +{ + UString Name; + COpenCallbackImp *OpenCallbackImp; + CMyComPtr OpenCallbackRef; + ~CInFileStreamVol() + { + if (OpenCallbackRef) + { + int index = OpenCallbackImp->FindName(Name); + if (index >= 0) + OpenCallbackImp->FileNames.Delete(index); + } + } +}; + +STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream) +{ + COM_TRY_BEGIN + if (_subArchiveMode) + return S_FALSE; + if (Callback) + { + RINOK(Callback->Open_CheckBreak()); + } + *inStream = NULL; + UString fullPath = _folderPrefix + name; + if (!_fileInfo.Find(fullPath)) + return S_FALSE; + if (_fileInfo.IsDir()) + return S_FALSE; + CInFileStreamVol *inFile = new CInFileStreamVol; + CMyComPtr inStreamTemp = inFile; + if (!inFile->Open(fullPath)) + return ::GetLastError(); + *inStream = inStreamTemp.Detach(); + inFile->Name = name; + inFile->OpenCallbackImp = this; + inFile->OpenCallbackRef = this; + FileNames.Add(name); + TotalSize += _fileInfo.Size; + 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; + return Callback->Open_CryptoGetTextPassword(password); + COM_TRY_END +} +#endif + diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.h b/CPP/7zip/UI/Common/ArchiveOpenCallback.h new file mode 100755 index 0000000..a60fca3 --- /dev/null +++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.h @@ -0,0 +1,103 @@ +// ArchiveOpenCallback.h + +#ifndef __ARCHIVE_OPEN_CALLBACK_H +#define __ARCHIVE_OPEN_CALLBACK_H + +#include "Common/MyCom.h" +#include "Common/MyString.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(UString &password) x; \ + virtual bool Open_WasPasswordAsked() x; \ + virtual void Open_ClearPasswordWasAskedFlag() 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; \ + 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: + #ifndef _NO_CRYPTO + MY_UNKNOWN_IMP3( + IArchiveOpenVolumeCallback, + ICryptoGetTextPassword, + IArchiveOpenSetSubArchiveName + ) + #else + MY_UNKNOWN_IMP2( + IArchiveOpenVolumeCallback, + IArchiveOpenSetSubArchiveName + ) + #endif + + 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: + UString _folderPrefix; + NWindows::NFile::NFind::CFileInfoW _fileInfo; + bool _subArchiveMode; + UString _subArchiveName; +public: + UStringVector FileNames; + IOpenCallbackUI *Callback; + CMyComPtr ReOpenCallback; + UInt64 TotalSize; + + COpenCallbackImp(): Callback(NULL) {} + void Init(const UString &folderPrefix, const UString &fileName) + { + _folderPrefix = folderPrefix; + if (!_fileInfo.Find(_folderPrefix + fileName)) + throw 1; + FileNames.Clear(); + _subArchiveMode = false; + TotalSize = 0; + } + int FindName(const UString &name); +}; + +#endif diff --git a/CPP/7zip/UI/Common/Bench.cpp b/CPP/7zip/UI/Common/Bench.cpp new file mode 100755 index 0000000..0c85695 --- /dev/null +++ b/CPP/7zip/UI/Common/Bench.cpp @@ -0,0 +1,1028 @@ +// Bench.cpp + +#include "StdAfx.h" + +#include "Bench.h" + +#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" + +#ifndef _7ZIP_ST +#include "../../../Windows/Synchronization.h" +#include "../../../Windows/Thread.h" +#endif + +#include "../../../Windows/PropVariant.h" + +static const UInt32 kUncompressMinBlockSize = +#ifdef UNDER_CE +1 << 24; +#else +1 << 26; +#endif + +static const UInt32 kCrcBlockSize = +#ifdef UNDER_CE +1 << 25; +#else +1 << 30; +#endif + +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)) ); + } +}; + +class CBenchBuffer +{ +public: + size_t BufferSize; + Byte *Buffer; + CBenchBuffer(): Buffer(0) {} + virtual ~CBenchBuffer() { Free(); } + void Free() + { + ::MidFree(Buffer); + Buffer = 0; + } + bool Alloc(size_t bufferSize) + { + if (Buffer != 0 && BufferSize == bufferSize) + return true; + Free(); + Buffer = (Byte *)::MidAlloc(bufferSize); + BufferSize = bufferSize; + return (Buffer != 0); + } +}; + +class CBenchRandomGenerator: public CBenchBuffer +{ + CBaseRandomGenerator *RG; +public: + void Set(CBaseRandomGenerator *rg) { RG = rg; } + UInt32 GetVal(UInt32 &res, int numBits) + { + UInt32 val = res & (((UInt32)1 << numBits) - 1); + res >>= numBits; + return val; + } + UInt32 GetLen(UInt32 &res) + { + UInt32 len = GetVal(res, 2); + return GetVal(res, 1 + len); + } + void Generate() + { + UInt32 pos = 0; + UInt32 rep0 = 1; + while (pos < BufferSize) + { + UInt32 res = RG->GetRnd(); + res >>= 1; + if (GetVal(res, 1) == 0 || pos < 1024) + Buffer[pos++] = (Byte)(res & 0xFF); + else + { + UInt32 len; + len = 1 + GetLen(res); + if (GetVal(res, 3) != 0) + { + len += GetLen(res); + do + { + UInt32 ppp = GetVal(res, 5) + 6; + res = RG->GetRnd(); + if (ppp > 30) + continue; + rep0 = /* (1 << ppp) +*/ GetVal(res, ppp); + res = RG->GetRnd(); + } + while (rep0 >= pos); + rep0++; + } + + for (UInt32 i = 0; i < len && pos < BufferSize; i++, pos++) + Buffer[pos] = Buffer[pos - rep0]; + } + } + } +}; + + +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 != NULL) + *processedSize = size; + return S_OK; +} + +class CBenchmarkOutStream: + public ISequentialOutStream, + public CBenchBuffer, + public CMyUnknownImp +{ + // bool _overflow; +public: + UInt32 Pos; + // CBenchmarkOutStream(): _overflow(false) {} + void Init() + { + // _overflow = false; + Pos = 0; + } + 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; + memcpy(Buffer + Pos, data, curSize); + Pos += (UInt32)curSize; + if(processedSize != NULL) + *processedSize = (UInt32)curSize; + if (curSize != size) + { + // _overflow = true; + return E_FAIL; + } + return S_OK; +} + +class CCrcOutStream: + public ISequentialOutStream, + public CMyUnknownImp +{ +public: + UInt32 Crc; + MY_UNKNOWN_IMP + 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) +{ + Crc = CrcUpdate(Crc, data, size); + if (processedSize != NULL) + *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 +} + +#ifndef USE_POSIX_TIME +static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } +#endif + +static UInt64 GetUserTime() +{ + #ifdef USE_POSIX_TIME + return clock(); + #else + 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; + #endif +} + +static UInt64 GetUserFreq() +{ + #ifdef USE_POSIX_TIME + return CLOCKS_PER_SEC; + #else + return 10000000; + #endif +} + +class CBenchProgressStatus +{ + #ifndef _7ZIP_ST + NWindows::NSynchronization::CCriticalSection CS; + #endif +public: + HRESULT Res; + bool EncodeMode; + void SetResult(HRESULT res) + { + #ifndef _7ZIP_ST + NWindows::NSynchronization::CCriticalSectionLock lock(CS); + #endif + Res = res; + } + HRESULT GetResult() + { + #ifndef _7ZIP_ST + NWindows::NSynchronization::CCriticalSectionLock lock(CS); + #endif + return Res; + } +}; + +class CBenchProgressInfo: + public ICompressProgressInfo, + public CMyUnknownImp +{ +public: + CBenchProgressStatus *Status; + CBenchInfo BenchInfo; + HRESULT Res; + IBenchCallback *callback; + CBenchProgressInfo(): callback(0) {} + MY_UNKNOWN_IMP + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); +}; + +static void SetStartTime(CBenchInfo &bi) +{ + bi.GlobalFreq = GetFreq(); + bi.UserFreq = GetUserFreq(); + bi.GlobalTime = ::GetTimeCount(); + bi.UserTime = ::GetUserTime(); +} + +static void SetFinishTime(const CBenchInfo &biStart, CBenchInfo &dest) +{ + dest.GlobalFreq = GetFreq(); + dest.UserFreq = GetUserFreq(); + dest.GlobalTime = ::GetTimeCount() - biStart.GlobalTime; + dest.UserTime = ::GetUserTime() - biStart.UserTime; +} + +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 = BenchInfo; + SetFinishTime(BenchInfo, info); + if (Status->EncodeMode) + { + info.UnpackSize = *inSize; + info.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 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 (i << kSubBits) + j; + return (32 << kSubBits); +} + +static void NormalizeVals(UInt64 &v1, UInt64 &v2) +{ + while (v1 > 1000000) + { + v1 >>= 1; + v2 >>= 1; + } +} + +UInt64 GetUsage(const CBenchInfo &info) +{ + UInt64 userTime = info.UserTime; + UInt64 userFreq = info.UserFreq; + UInt64 globalTime = info.GlobalTime; + UInt64 globalFreq = info.GlobalFreq; + NormalizeVals(userTime, userFreq); + NormalizeVals(globalFreq, globalTime); + if (userFreq == 0) + userFreq = 1; + if (globalTime == 0) + globalTime = 1; + return userTime * globalFreq * 1000000 / userFreq / globalTime; +} + +UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating) +{ + UInt64 userTime = info.UserTime; + UInt64 userFreq = info.UserFreq; + UInt64 globalTime = info.GlobalTime; + UInt64 globalFreq = info.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 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size) +{ + UInt64 t = GetLogSize(dictionarySize) - (kBenchMinDicLogSize << kSubBits); + UInt64 numCommandsForOne = 870 + ((t * t * 5) >> (2 * kSubBits)); + UInt64 numCommands = (UInt64)(size) * numCommandsForOne; + return MyMultDiv64(numCommands, elapsedTime, freq); +} + +UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations) +{ + UInt64 numCommands = (inSize * 200 + outSize * 4) * numIterations; + return MyMultDiv64(numCommands, elapsedTime, freq); +} + +struct CEncoderInfo; + +struct CEncoderInfo +{ + #ifndef _7ZIP_ST + NWindows::CThread thread[2]; + #endif + CMyComPtr encoder; + CBenchProgressInfo *progressInfoSpec[2]; + CMyComPtr progressInfo[2]; + UInt32 NumIterations; + #ifdef USE_ALLOCA + size_t AllocaSize; + #endif + + struct CDecoderInfo + { + CEncoderInfo *Encoder; + UInt32 DecoderIndex; + #ifdef USE_ALLOCA + size_t AllocaSize; + #endif + bool CallbackMode; + }; + CDecoderInfo decodersInfo[2]; + + CMyComPtr decoders[2]; + HRESULT Results[2]; + CBenchmarkOutStream *outStreamSpec; + CMyComPtr outStream; + IBenchCallback *callback; + UInt32 crc; + UInt32 kBufferSize; + UInt32 compressedSize; + CBenchRandomGenerator rg; + CBenchmarkOutStream *propStreamSpec; + CMyComPtr propStream; + HRESULT Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rg); + HRESULT Encode(); + HRESULT Decode(UInt32 decoderIndex); + + CEncoderInfo(): outStreamSpec(0), callback(0), propStreamSpec(0) {} + + #ifndef _7ZIP_ST + static THREAD_FUNC_DECL EncodeThreadFunction(void *param) + { + CEncoderInfo *encoder = (CEncoderInfo *)param; + #ifdef USE_ALLOCA + alloca(encoder->AllocaSize); + #endif + HRESULT res = encoder->Encode(); + encoder->Results[0] = res; + 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(int 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(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rgLoc) +{ + rg.Set(rgLoc); + kBufferSize = dictionarySize + kAdditionalSize; + UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; + if (!rg.Alloc(kBufferSize)) + return E_OUTOFMEMORY; + rg.Generate(); + crc = CrcCalc(rg.Buffer, rg.BufferSize); + + outStreamSpec = new CBenchmarkOutStream; + if (!outStreamSpec->Alloc(kCompressedBufferSize)) + return E_OUTOFMEMORY; + + outStream = outStreamSpec; + + propStreamSpec = 0; + if (!propStream) + { + propStreamSpec = new CBenchmarkOutStream; + propStream = propStreamSpec; + } + if (!propStreamSpec->Alloc(kMaxLzmaPropSize)) + return E_OUTOFMEMORY; + propStreamSpec->Init(); + + PROPID propIDs[] = + { + NCoderPropID::kDictionarySize, + NCoderPropID::kNumThreads + }; + const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); + PROPVARIANT props[kNumProps]; + props[0].vt = VT_UI4; + props[0].ulVal = dictionarySize; + + props[1].vt = VT_UI4; + props[1].ulVal = numThreads; + + { + CMyComPtr setCoderProperties; + RINOK(encoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties)); + if (!setCoderProperties) + return E_FAIL; + RINOK(setCoderProperties->SetCoderProperties(propIDs, props, kNumProps)); + + CMyComPtr writeCoderProperties; + encoder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProperties); + if (writeCoderProperties) + { + RINOK(writeCoderProperties->WriteCoderProperties(propStream)); + } + } + return S_OK; +} + +HRESULT CEncoderInfo::Encode() +{ + CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; + CMyComPtr inStream = inStreamSpec; + inStreamSpec->Init(rg.Buffer, rg.BufferSize); + outStreamSpec->Init(); + + RINOK(encoder->Code(inStream, outStream, 0, 0, progressInfo[0])); + compressedSize = outStreamSpec->Pos; + encoder.Release(); + return S_OK; +} + +HRESULT CEncoderInfo::Decode(UInt32 decoderIndex) +{ + CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; + CMyComPtr inStream = inStreamSpec; + CMyComPtr &decoder = decoders[decoderIndex]; + + CMyComPtr compressSetDecoderProperties; + decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &compressSetDecoderProperties); + if (!compressSetDecoderProperties) + return E_FAIL; + + CCrcOutStream *crcOutStreamSpec = new CCrcOutStream; + CMyComPtr crcOutStream = crcOutStreamSpec; + + CBenchProgressInfo *pi = progressInfoSpec[decoderIndex]; + pi->BenchInfo.UnpackSize = 0; + pi->BenchInfo.PackSize = 0; + + for (UInt32 j = 0; j < NumIterations; j++) + { + inStreamSpec->Init(outStreamSpec->Buffer, compressedSize); + crcOutStreamSpec->Init(); + + RINOK(compressSetDecoderProperties->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos)); + UInt64 outSize = kBufferSize; + RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex])); + if (CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc) + return S_FALSE; + pi->BenchInfo.UnpackSize += kBufferSize; + pi->BenchInfo.PackSize += compressedSize; + } + decoder.Release(); + return S_OK; +} + +static const UInt32 kNumThreadsMax = (1 << 16); + +struct CBenchEncoders +{ + CEncoderInfo *encoders; + CBenchEncoders(UInt32 num): encoders(0) { encoders = new CEncoderInfo[num]; } + ~CBenchEncoders() { delete []encoders; } +}; + +HRESULT LzmaBench( + DECL_EXTERNAL_CODECS_LOC_VARS + UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback) +{ + UInt32 numEncoderThreads = + #ifndef _7ZIP_ST + (numThreads > 1 ? numThreads / 2 : 1); + #else + 1; + #endif + UInt32 numSubDecoderThreads = + #ifndef _7ZIP_ST + (numThreads > 1 ? 2 : 1); + #else + 1; + #endif + if (dictionarySize < (1 << kBenchMinDicLogSize) || numThreads < 1 || numEncoderThreads > kNumThreadsMax) + { + return E_INVALIDARG; + } + + 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; + + const UInt32 kLzmaId = 0x030101; + RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS kLzmaId, encoder.encoder, true)); + if (!encoder.encoder) + return E_NOTIMPL; + for (UInt32 j = 0; j < numSubDecoderThreads; j++) + { + RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS kLzmaId, encoder.decoders[j], false)); + if (!encoder.decoders[j]) + return E_NOTIMPL; + } + } + + CBaseRandomGenerator rg; + rg.Init(); + for (i = 0; i < numEncoderThreads; i++) + { + RINOK(encoders[i].Init(dictionarySize, numThreads, &rg)); + } + + CBenchProgressStatus status; + status.Res = S_OK; + status.EncodeMode = true; + + for (i = 0; i < numEncoderThreads; i++) + { + CEncoderInfo &encoder = encoders[i]; + for (int j = 0; j < 2; j++) + { + encoder.progressInfo[j] = encoder.progressInfoSpec[j] = new CBenchProgressInfo; + encoder.progressInfoSpec[j]->Status = &status; + } + if (i == 0) + { + encoder.progressInfoSpec[0]->callback = callback; + encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numEncoderThreads; + SetStartTime(encoder.progressInfoSpec[0]->BenchInfo); + } + + #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; + + SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info); + info.UnpackSize = 0; + info.PackSize = 0; + info.NumIterations = 1; // progressInfoSpec->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]; + encoder.NumIterations = 2 + kUncompressMinBlockSize / encoder.kBufferSize; + + if (i == 0) + { + encoder.progressInfoSpec[0]->callback = callback; + encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numDecoderThreads; + SetStartTime(encoder.progressInfoSpec[0]->BenchInfo); + } + + #ifndef _7ZIP_ST + 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); + SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, 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; +} + + +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) +{ + const UInt32 kBufferSize = dictionary; + const UInt32 kCompressedBufferSize = (kBufferSize / 2); + UInt32 numSubThreads = (numThreads > 1) ? 2 : 1; + UInt32 numBigThreads = numThreads / numSubThreads; + return (kBufferSize + kCompressedBufferSize + + GetLZMAUsage((numThreads > 1), dictionary) + (2 << 20)) * numBigThreads; +} + +static bool CrcBig(const void *data, UInt32 size, UInt32 numCycles, UInt32 crcBase) +{ + for (UInt32 i = 0; i < numCycles; i++) + if (CrcCalc(data, size) != crcBase) + return false; + return true; +} + +#ifndef _7ZIP_ST +struct CCrcInfo +{ + NWindows::CThread Thread; + const Byte *Data; + UInt32 Size; + UInt32 NumCycles; + UInt32 Crc; + bool Res; + void Wait() + { + Thread.Wait(); + Thread.Close(); + } +}; + +static THREAD_FUNC_DECL CrcThreadFunction(void *param) +{ + CCrcInfo *p = (CCrcInfo *)param; + p->Res = CrcBig(p->Data, p->Size, p->NumCycles, p->Crc); + return 0; +} + +struct CCrcThreads +{ + UInt32 NumThreads; + CCrcInfo *Items; + 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; +} + +HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed) +{ + if (numThreads == 0) + numThreads = 1; + + 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 numCycles = (kCrcBlockSize) / ((bufferSize >> 2) + 1) + 1; + + UInt64 timeVal; + #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]; + Byte *data = buf + (size_t)bufferSize * i; + info.Data = data; + info.NumCycles = numCycles; + info.Size = bufferSize; + info.Crc = RandGenCrc(data, bufferSize, RG); + } + timeVal = GetTimeCount(); + 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++) + if (!threads.Items[i].Res) + return S_FALSE; + } + else + #endif + { + UInt32 crc = RandGenCrc(buf, bufferSize, RG); + timeVal = GetTimeCount(); + if (!CrcBig(buf, bufferSize, numCycles, crc)) + return S_FALSE; + } + timeVal = GetTimeCount() - timeVal; + if (timeVal == 0) + timeVal = 1; + + UInt64 size = (UInt64)numCycles * totalSize; + speed = MyMultDiv64(size, timeVal, GetFreq()); + return S_OK; +} diff --git a/CPP/7zip/UI/Common/Bench.h b/CPP/7zip/UI/Common/Bench.h new file mode 100755 index 0000000..f6e8064 --- /dev/null +++ b/CPP/7zip/UI/Common/Bench.h @@ -0,0 +1,42 @@ +// Bench.h + +#ifndef __7ZIP_BENCH_H +#define __7ZIP_BENCH_H + +#include "../../Common/CreateCoder.h" + +struct CBenchInfo +{ + UInt64 GlobalTime; + UInt64 GlobalFreq; + UInt64 UserTime; + UInt64 UserFreq; + UInt64 UnpackSize; + UInt64 PackSize; + UInt32 NumIterations; + CBenchInfo(): NumIterations(0) {} +}; + +struct IBenchCallback +{ + virtual HRESULT SetEncodeResult(const CBenchInfo &info, bool final) = 0; + virtual HRESULT SetDecodeResult(const CBenchInfo &info, bool final) = 0; +}; + +UInt64 GetUsage(const CBenchInfo &benchOnfo); +UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating); +UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size); +UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations); + +HRESULT LzmaBench( + DECL_EXTERNAL_CODECS_LOC_VARS + UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback); + +const int kBenchMinDicLogSize = 18; + +UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary); + +bool CrcInternalTest(); +HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed); + +#endif diff --git a/CPP/7zip/UI/Common/CompressCall.cpp b/CPP/7zip/UI/Common/CompressCall.cpp new file mode 100755 index 0000000..5d591a0 --- /dev/null +++ b/CPP/7zip/UI/Common/CompressCall.cpp @@ -0,0 +1,246 @@ +// CompressCall.cpp + +#include "StdAfx.h" + +#include "Common/IntToString.h" +#include "Common/MyCom.h" +#include "Common/Random.h" +#include "Common/StringConvert.h" + +#include "Windows/FileDir.h" +#include "Windows/FileMapping.h" +#include "Windows/Process.h" +#include "Windows/Synchronization.h" + +#include "../FileManager/ProgramLocation.h" +#include "../FileManager/RegistryUtils.h" + +#include "CompressCall.h" + +using namespace NWindows; + +#define MY_TRY_BEGIN try { +#define MY_TRY_FINISH } \ + catch(...) { ErrorMessageHRESULT(E_FAIL); return E_FAIL; } + +static LPCWSTR kShowDialogSwitch = L" -ad"; +static LPCWSTR kEmailSwitch = L" -seml."; +static LPCWSTR kIncludeSwitch = L" -i"; +static LPCWSTR kArchiveTypeSwitch = L" -t"; +static LPCWSTR kArcIncludeSwitches = L" -an -ai"; +static LPCWSTR kStopSwitchParsing = L" --"; +static LPCWSTR kLargePagesDisable = L" -slp-"; + +UString GetQuotedString(const UString &s) +{ + return UString(L'\"') + s + UString(L'\"'); +} +static void ErrorMessage(LPCWSTR message) +{ + MessageBoxW(g_HWND, message, L"7-Zip", MB_ICONERROR | MB_OK); +} + +static void ErrorMessageHRESULT(HRESULT res, LPCWSTR s = NULL) +{ + UString s2 = HResultToMessage(res); + if (s) + { + s2 += L'\n'; + s2 += s; + } + ErrorMessage(s2); +} + +static HRESULT MyCreateProcess(LPCWSTR imageName, const UString ¶ms, + LPCWSTR curDir, bool waitFinish, + NSynchronization::CBaseEvent *event) +{ + CProcess process; + WRes res = process.Create(imageName, params, curDir); + if (res != 0) + { + ErrorMessageHRESULT(res, imageName); + return res; + } + if (waitFinish) + process.Wait(); + else if (event != NULL) + { + HANDLE handles[] = { process, *event }; + ::WaitForMultipleObjects(sizeof(handles) / sizeof(handles[0]), handles, FALSE, INFINITE); + } + return S_OK; +} + +static void AddLagePagesSwitch(UString ¶ms) +{ + if (!ReadLockMemoryEnable()) + params += kLargePagesDisable; +} + +static UString Get7zGuiPath() +{ + UString path; + GetProgramFolderPath(path); + return path + L"7zG.exe"; +} + +class CRandNameGenerator +{ + CRandom _random; +public: + CRandNameGenerator() { _random.Init(); } + UString GenerateName() + { + wchar_t temp[16]; + ConvertUInt32ToString((UInt32)_random.Generate(), temp); + return temp; + } +}; + +static HRESULT CreateMap(const UStringVector &names, + CFileMapping &fileMapping, NSynchronization::CManualResetEvent &event, + UString ¶ms) +{ + UInt32 totalSize = 1; + for (int i = 0; i < names.Size(); i++) + totalSize += (names[i].Length() + 1); + totalSize *= sizeof(wchar_t); + + CRandNameGenerator random; + + UString mappingName; + for (;;) + { + mappingName = L"7zMap" + random.GenerateName(); + + WRes res = fileMapping.Create(PAGE_READWRITE, totalSize, GetSystemString(mappingName)); + if (fileMapping.IsCreated() && res == 0) + break; + if (res != ERROR_ALREADY_EXISTS) + return res; + fileMapping.Close(); + } + + UString eventName; + for (;;) + { + eventName = L"7zEvent" + random.GenerateName(); + WRes res = event.CreateWithName(false, GetSystemString(eventName)); + if (event.IsCreated() && res == 0) + break; + if (res != ERROR_ALREADY_EXISTS) + return res; + event.Close(); + } + + params += L'#'; + params += mappingName; + params += L':'; + wchar_t temp[16]; + ConvertUInt32ToString(totalSize, temp); + params += temp; + + params += L':'; + params += eventName; + + LPVOID data = fileMapping.Map(FILE_MAP_WRITE, 0, totalSize); + if (data == NULL) + return E_FAIL; + CFileUnmapper unmapper(data); + { + wchar_t *cur = (wchar_t *)data; + *cur++ = 0; + for (int i = 0; i < names.Size(); i++) + { + const UString &s = names[i]; + int len = s.Length() + 1; + memcpy(cur, (const wchar_t *)s, len * sizeof(wchar_t)); + cur += len; + } + } + return S_OK; +} + +HRESULT CompressFiles( + const UString &arcPathPrefix, + const UString &arcName, + const UString &arcType, + const UStringVector &names, + bool email, bool showDialog, bool waitFinish) +{ + MY_TRY_BEGIN + UString params = L'a'; + + CFileMapping fileMapping; + NSynchronization::CManualResetEvent event; + params += kIncludeSwitch; + RINOK(CreateMap(names, fileMapping, event, params)); + + if (!arcType.IsEmpty()) + { + params += kArchiveTypeSwitch; + params += arcType; + } + + if (email) + params += kEmailSwitch; + + if (showDialog) + params += kShowDialogSwitch; + + AddLagePagesSwitch(params); + + params += kStopSwitchParsing; + params += L' '; + + params += GetQuotedString( + #ifdef UNDER_CE + arcPathPrefix + + #endif + arcName); + + return MyCreateProcess(Get7zGuiPath(), params, + (arcPathPrefix.IsEmpty()? 0: (LPCWSTR)arcPathPrefix), waitFinish, &event); + MY_TRY_FINISH +} + +static HRESULT ExtractGroupCommand(const UStringVector &arcPaths, UString ¶ms) +{ + AddLagePagesSwitch(params); + params += kArcIncludeSwitches; + CFileMapping fileMapping; + NSynchronization::CManualResetEvent event; + RINOK(CreateMap(arcPaths, fileMapping, event, params)); + return MyCreateProcess(Get7zGuiPath(), params, 0, false, &event); +} + +HRESULT ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog) +{ + MY_TRY_BEGIN + UString params = L'x'; + if (!outFolder.IsEmpty()) + { + params += L" -o"; + params += GetQuotedString(outFolder); + } + if (showDialog) + params += kShowDialogSwitch; + return ExtractGroupCommand(arcPaths, params); + MY_TRY_FINISH +} + +HRESULT TestArchives(const UStringVector &arcPaths) +{ + MY_TRY_BEGIN + UString params = L't'; + return ExtractGroupCommand(arcPaths, params); + MY_TRY_FINISH +} + +HRESULT Benchmark() +{ + MY_TRY_BEGIN + return MyCreateProcess(Get7zGuiPath(), L'b', 0, false, NULL); + MY_TRY_FINISH +} diff --git a/CPP/7zip/UI/Common/CompressCall.h b/CPP/7zip/UI/Common/CompressCall.h new file mode 100755 index 0000000..8cb4241 --- /dev/null +++ b/CPP/7zip/UI/Common/CompressCall.h @@ -0,0 +1,24 @@ +// CompressCall.h + +#ifndef __COMPRESS_CALL_H +#define __COMPRESS_CALL_H + +#include "Common/MyString.h" + +UString GetQuotedString(const UString &s); + +extern HWND g_HWND; +UString HResultToMessage(HRESULT errorCode); + +HRESULT CompressFiles( + const UString &arcPathPrefix, + const UString &arcName, + const UString &arcType, + const UStringVector &names, + bool email, bool showDialog, bool waitFinish); + +HRESULT ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog); +HRESULT TestArchives(const UStringVector &arcPaths); +HRESULT Benchmark(); + +#endif diff --git a/CPP/7zip/UI/Common/CompressCall2.cpp b/CPP/7zip/UI/Common/CompressCall2.cpp new file mode 100755 index 0000000..913afd8 --- /dev/null +++ b/CPP/7zip/UI/Common/CompressCall2.cpp @@ -0,0 +1,178 @@ +// CompressCall.cpp + +#include "StdAfx.h" + +#include "Common/MyException.h" + +#include "../../UI/common/ArchiveCommandLine.h" + +#include "../../UI/GUI/BenchmarkDialog.h" +#include "../../UI/GUI/ExtractGUI.h" +#include "../../UI/GUI/UpdateGUI.h" + +#include "../../UI/GUI/ExtractRes.h" + +#include "CompressCall.h" + +#define MY_TRY_BEGIN try { +#define MY_TRY_FINISH } \ + catch(CSystemException &e) { result = e.ErrorCode; } \ + catch(...) { result = E_FAIL; } \ + if (result != S_OK && result != E_ABORT) \ + ErrorMessageHRESULT(result); + +#define CREATE_CODECS \ + CCodecs *codecs = new CCodecs; \ + CMyComPtr compressCodecsInfo = codecs; \ + result = codecs->Load(); \ + if (result != S_OK) \ + throw CSystemException(result); + +UString GetQuotedString(const UString &s) +{ + return UString(L'\"') + s + UString(L'\"'); +} + +static void ErrorMessage(LPCWSTR message) +{ + MessageBoxW(g_HWND, message, L"7-Zip", MB_ICONERROR); +} + +static void ErrorMessageHRESULT(HRESULT res) +{ + ErrorMessage(HResultToMessage(res)); +} + +static void ErrorLangMessage(UINT resourceID, UInt32 langID) +{ + ErrorMessage(LangString(resourceID, langID)); +} + +HRESULT CompressFiles( + const UString &arcPathPrefix, + const UString &arcName, + const UString &arcType, + const UStringVector &names, + bool email, bool showDialog, bool /* waitFinish */) +{ + HRESULT result; + MY_TRY_BEGIN + CREATE_CODECS + + CUpdateCallbackGUI callback; + + callback.Init(); + + CUpdateOptions uo; + uo.EMailMode = email; + uo.SetAddActionCommand(); + + CIntVector formatIndices; + if (!codecs->FindFormatForArchiveType(arcType, formatIndices)) + { + ErrorLangMessage(IDS_UNSUPPORTED_ARCHIVE_TYPE, 0x0200060D); + return E_FAIL; + } + if (!uo.Init(codecs, formatIndices, arcPathPrefix + arcName)) + { + ErrorLangMessage(IDS_UPDATE_NOT_SUPPORTED, 0x02000601); + return E_FAIL; + } + + NWildcard::CCensor censor; + for (int i = 0; i < names.Size(); i++) + censor.AddItem(true, names[i], false); + + bool messageWasDisplayed = false; + result = UpdateGUI(codecs, censor, uo, showDialog, messageWasDisplayed, &callback, g_HWND); + + if (result != S_OK) + { + if (result != E_ABORT && messageWasDisplayed) + return E_FAIL; + throw CSystemException(result); + } + if (callback.FailedFiles.Size() > 0) + { + if (!messageWasDisplayed) + throw CSystemException(E_FAIL); + return E_FAIL; + } + MY_TRY_FINISH + return S_OK; +} + +static HRESULT ExtractGroupCommand(const UStringVector &arcPaths, + bool showDialog, const UString &outFolder, bool testMode) +{ + HRESULT result; + MY_TRY_BEGIN + CREATE_CODECS + + CExtractOptions eo; + eo.OutputDir = outFolder; + eo.TestMode = testMode; + + CExtractCallbackImp *ecs = new CExtractCallbackImp; + CMyComPtr extractCallback = ecs; + + ecs->Init(); + + // eo.CalcCrc = options.CalcCrc; + + UStringVector arcPathsSorted; + UStringVector arcFullPathsSorted; + { + NWildcard::CCensor acrCensor; + for (int i = 0; i < arcPaths.Size(); i++) + acrCensor.AddItem(true, arcPaths[i], false); + EnumerateDirItemsAndSort(acrCensor, arcPathsSorted, arcFullPathsSorted); + } + + CIntVector formatIndices; + + NWildcard::CCensor censor; + censor.AddItem(true, L"*", false); + + bool messageWasDisplayed = false; + result = ExtractGUI(codecs, formatIndices, arcPathsSorted, arcFullPathsSorted, + censor.Pairs.Front().Head, eo, showDialog, messageWasDisplayed, ecs, g_HWND); + if (result != S_OK) + { + if (result != E_ABORT && messageWasDisplayed) + return E_FAIL; + throw CSystemException(result); + } + return ecs->IsOK() ? S_OK : E_FAIL; + MY_TRY_FINISH + return result; +} + +HRESULT ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog) +{ + return ExtractGroupCommand(arcPaths, showDialog, outFolder, false); +} + +HRESULT TestArchives(const UStringVector &arcPaths) +{ + return ExtractGroupCommand(arcPaths, true, UString(), true); +} + +HRESULT Benchmark() +{ + HRESULT result; + MY_TRY_BEGIN + CREATE_CODECS + + #ifdef EXTERNAL_CODECS + CObjectVector externalCodecs; + RINOK(LoadExternalCodecs(codecs, externalCodecs)); + #endif + result = Benchmark( + #ifdef EXTERNAL_CODECS + codecs, &externalCodecs, + #endif + (UInt32)-1, (UInt32)-1, g_HWND); + MY_TRY_FINISH + return result; +} diff --git a/CPP/7zip/UI/Common/DefaultName.cpp b/CPP/7zip/UI/Common/DefaultName.cpp new file mode 100755 index 0000000..5c46500 --- /dev/null +++ b/CPP/7zip/UI/Common/DefaultName.cpp @@ -0,0 +1,35 @@ +// DefaultName.cpp + +#include "StdAfx.h" + +#include "DefaultName.h" + +static UString GetDefaultName3(const UString &fileName, + const UString &extension, const UString &addSubExtension) +{ + int extLength = extension.Length(); + int fileNameLength = fileName.Length(); + if (fileNameLength > extLength + 1) + { + int dotPos = fileNameLength - (extLength + 1); + if (fileName[dotPos] == '.') + if (extension.CompareNoCase(fileName.Mid(dotPos + 1)) == 0) + return fileName.Left(dotPos) + addSubExtension; + } + int dotPos = fileName.ReverseFind(L'.'); + 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/CPP/7zip/UI/Common/DefaultName.h b/CPP/7zip/UI/Common/DefaultName.h new file mode 100755 index 0000000..3989a1f --- /dev/null +++ b/CPP/7zip/UI/Common/DefaultName.h @@ -0,0 +1,11 @@ +// DefaultName.h + +#ifndef __DEFAULTNAME_H +#define __DEFAULTNAME_H + +#include "Common/MyString.h" + +UString GetDefaultName2(const UString &fileName, + const UString &extension, const UString &addSubExtension); + +#endif diff --git a/CPP/7zip/UI/Common/DirItem.h b/CPP/7zip/UI/Common/DirItem.h new file mode 100755 index 0000000..e10d6b9 --- /dev/null +++ b/CPP/7zip/UI/Common/DirItem.h @@ -0,0 +1,69 @@ +// DirItem.h + +#ifndef __DIR_ITEM_H +#define __DIR_ITEM_H + +#include "Common/MyString.h" +#include "Common/Types.h" +#include "../../Archive/IArchive.h" + +struct CDirItem +{ + UInt64 Size; + FILETIME CTime; + FILETIME ATime; + FILETIME MTime; + UString Name; + UInt32 Attrib; + int PhyParent; + int LogParent; + + CDirItem(): PhyParent(-1), LogParent(-1) {} + 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; +public: + CObjectVector Items; + + int GetNumFolders() const { return Prefixes.Size(); } + UString GetPhyPath(int index) const; + UString GetLogPath(int index) const; + + int AddPrefix(int phyParent, int logParent, const UString &prefix); + void DeleteLastPrefix(); + + void EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix, + UStringVector &errorPaths, CRecordVector &errorCodes); + + void EnumerateDirItems2( + const UString &phyPrefix, + const UString &logPrefix, + const UStringVector &filePaths, + UStringVector &errorPaths, CRecordVector &errorCodes); + + void ReserveDown(); +}; + +struct CArcItem +{ + UInt64 Size; + FILETIME MTime; + UString Name; + bool IsDir; + bool SizeDefined; + bool MTimeDefined; + bool Censored; + UInt32 IndexInServer; + int TimeType; + + CArcItem(): IsDir(false), SizeDefined(false), MTimeDefined(false), Censored(false), TimeType(-1) {} +}; + +#endif diff --git a/CPP/7zip/UI/Common/EnumDirItems.cpp b/CPP/7zip/UI/Common/EnumDirItems.cpp new file mode 100755 index 0000000..61ecaba --- /dev/null +++ b/CPP/7zip/UI/Common/EnumDirItems.cpp @@ -0,0 +1,361 @@ +// EnumDirItems.cpp + +#include "StdAfx.h" + +#include "EnumDirItems.h" + +using namespace NWindows; +using namespace NFile; +using namespace NName; + +void AddDirFileInfo(int phyParent, int logParent, + const NFind::CFileInfoW &fi, CObjectVector &dirItems) +{ + CDirItem di; + di.Size = fi.Size; + di.CTime = fi.CTime; + di.ATime = fi.ATime; + di.MTime = fi.MTime; + di.Attrib = fi.Attrib; + di.PhyParent = phyParent; + di.LogParent = logParent; + di.Name = fi.Name; + dirItems.Add(di); +} + +UString CDirItems::GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const +{ + UString path; + int len = name.Length(); + int i; + for (i = index; i >= 0; i = parents[i]) + len += Prefixes[i].Length(); + int totalLen = len; + wchar_t *p = path.GetBuffer(len); + p[len] = 0; + len -= name.Length(); + memcpy(p + len, (const wchar_t *)name, name.Length() * sizeof(wchar_t)); + for (i = index; i >= 0; i = parents[i]) + { + const UString &s = Prefixes[i]; + len -= s.Length(); + memcpy(p + len, (const wchar_t *)s, s.Length() * sizeof(wchar_t)); + } + path.ReleaseBuffer(totalLen); + return path; +} + +UString CDirItems::GetPhyPath(int index) const +{ + const CDirItem &di = Items[index]; + return GetPrefixesPath(PhyParents, di.PhyParent, di.Name); +} + +UString CDirItems::GetLogPath(int 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(); +} + +int 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(); +} + +void CDirItems::EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix, + UStringVector &errorPaths, CRecordVector &errorCodes) +{ + NFind::CEnumeratorW enumerator(phyPrefix + (wchar_t)kAnyStringWildcard); + for (;;) + { + NFind::CFileInfoW fi; + bool found; + if (!enumerator.Next(fi, found)) + { + errorCodes.Add(::GetLastError()); + errorPaths.Add(phyPrefix); + return; + } + if (!found) + break; + AddDirFileInfo(phyParent, logParent, fi, Items); + if (fi.IsDir()) + { + const UString name2 = fi.Name + (wchar_t)kDirDelimiter; + int parent = AddPrefix(phyParent, logParent, name2); + EnumerateDirectory(parent, parent, phyPrefix + name2, errorPaths, errorCodes); + } + } +} + +void CDirItems::EnumerateDirItems2(const UString &phyPrefix, const UString &logPrefix, + const UStringVector &filePaths, UStringVector &errorPaths, CRecordVector &errorCodes) +{ + int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, phyPrefix); + int logParent = logPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, logPrefix); + + for (int i = 0; i < filePaths.Size(); i++) + { + const UString &filePath = filePaths[i]; + NFind::CFileInfoW fi; + const UString phyPath = phyPrefix + filePath; + if (!fi.Find(phyPath)) + { + errorCodes.Add(::GetLastError()); + errorPaths.Add(phyPath); + continue; + } + int delimiter = filePath.ReverseFind((wchar_t)kDirDelimiter); + UString phyPrefixCur; + int phyParentCur = phyParent; + if (delimiter >= 0) + { + phyPrefixCur = filePath.Left(delimiter + 1); + phyParentCur = AddPrefix(phyParent, logParent, phyPrefixCur); + } + AddDirFileInfo(phyParentCur, logParent, fi, Items); + if (fi.IsDir()) + { + const UString name2 = fi.Name + (wchar_t)kDirDelimiter; + int parent = AddPrefix(phyParentCur, logParent, name2); + EnumerateDirectory(parent, parent, phyPrefix + phyPrefixCur + name2, errorPaths, errorCodes); + } + } + ReserveDown(); +} + +static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, + int phyParent, int logParent, const UString &phyPrefix, + const UStringVector &addArchivePrefix, + CDirItems &dirItems, + bool enterToSubFolders, + IEnumDirItemCallback *callback, + UStringVector &errorPaths, + CRecordVector &errorCodes); + +static HRESULT EnumerateDirItems_Spec(const NWildcard::CCensorNode &curNode, + int phyParent, int logParent, const UString &curFolderName, + const UString &phyPrefix, + const UStringVector &addArchivePrefix, + CDirItems &dirItems, + bool enterToSubFolders, + IEnumDirItemCallback *callback, + UStringVector &errorPaths, + CRecordVector &errorCodes) + +{ + const UString name2 = curFolderName + (wchar_t)kDirDelimiter; + int parent = dirItems.AddPrefix(phyParent, logParent, name2); + int numItems = dirItems.Items.Size(); + HRESULT res = EnumerateDirItems(curNode, parent, parent, phyPrefix + name2, + addArchivePrefix, dirItems, enterToSubFolders, callback, errorPaths, errorCodes); + if (numItems == dirItems.Items.Size()) + dirItems.DeleteLastPrefix(); + return res; +} + + +static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, + int phyParent, int logParent, const UString &phyPrefix, + const UStringVector &addArchivePrefix, // prefix from curNode + CDirItems &dirItems, + bool enterToSubFolders, + IEnumDirItemCallback *callback, + UStringVector &errorPaths, + CRecordVector &errorCodes) +{ + if (!enterToSubFolders) + if (curNode.NeedCheckSubDirs()) + enterToSubFolders = true; + if (callback) + RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix)); + + // try direct_names case at first + if (addArchivePrefix.IsEmpty() && !enterToSubFolders) + { + // check that all names are direct + int i; + for (i = 0; i < curNode.IncludeItems.Size(); i++) + { + const NWildcard::CItem &item = curNode.IncludeItems[i]; + if (item.Recursive || item.PathParts.Size() != 1) + break; + const UString &name = item.PathParts.Front(); + if (name.IsEmpty() || DoesNameContainWildCard(name)) + break; + } + if (i == curNode.IncludeItems.Size()) + { + // all names are direct (no wildcards) + // so we don't need file_system's dir enumerator + CRecordVector needEnterVector; + for (i = 0; i < curNode.IncludeItems.Size(); i++) + { + const NWildcard::CItem &item = curNode.IncludeItems[i]; + const UString &name = item.PathParts.Front(); + const UString fullPath = phyPrefix + name; + NFind::CFileInfoW fi; + if (!fi.Find(fullPath)) + { + errorCodes.Add(::GetLastError()); + errorPaths.Add(fullPath); + continue; + } + bool isDir = fi.IsDir(); + if (isDir && !item.ForDir || !isDir && !item.ForFile) + { + errorCodes.Add((DWORD)E_FAIL); + errorPaths.Add(fullPath); + continue; + } + { + UStringVector pathParts; + pathParts.Add(fi.Name); + if (curNode.CheckPathToRoot(false, pathParts, !isDir)) + continue; + } + AddDirFileInfo(phyParent, logParent, fi, dirItems.Items); + 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, callback, errorPaths, errorCodes)); + } + for (i = 0; i < curNode.SubNodes.Size(); i++) + { + if (i < needEnterVector.Size()) + if (!needEnterVector[i]) + continue; + const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i]; + const UString fullPath = phyPrefix + nextNode.Name; + NFind::CFileInfoW fi; + if (!fi.Find(fullPath)) + { + if (!nextNode.AreThereIncludeItems()) + continue; + errorCodes.Add(::GetLastError()); + errorPaths.Add(fullPath); + continue; + } + if (!fi.IsDir()) + { + errorCodes.Add((DWORD)E_FAIL); + errorPaths.Add(fullPath); + continue; + } + + RINOK(EnumerateDirItems_Spec(nextNode, phyParent, logParent, fi.Name, phyPrefix, + UStringVector(), dirItems, false, callback, errorPaths, errorCodes)); + } + return S_OK; + } + } + + + NFind::CEnumeratorW enumerator(phyPrefix + wchar_t(kAnyStringWildcard)); + for (int ttt = 0; ; ttt++) + { + NFind::CFileInfoW fi; + bool found; + if (!enumerator.Next(fi, found)) + { + errorCodes.Add(::GetLastError()); + errorPaths.Add(phyPrefix); + break; + } + if (!found) + break; + + if (callback && (ttt & 0xFF) == 0xFF) + RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix)); + const UString &name = fi.Name; + bool enterToSubFolders2 = enterToSubFolders; + UStringVector addArchivePrefixNew = addArchivePrefix; + addArchivePrefixNew.Add(name); + { + UStringVector addArchivePrefixNewTemp(addArchivePrefixNew); + if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fi.IsDir())) + continue; + } + if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir())) + { + AddDirFileInfo(phyParent, logParent, fi, dirItems.Items); + if (fi.IsDir()) + enterToSubFolders2 = true; + } + if (!fi.IsDir()) + continue; + + const NWildcard::CCensorNode *nextNode = 0; + if (addArchivePrefix.IsEmpty()) + { + int index = curNode.FindSubNode(name); + if (index >= 0) + nextNode = &curNode.SubNodes[index]; + } + if (!enterToSubFolders2 && nextNode == 0) + continue; + + addArchivePrefixNew = addArchivePrefix; + if (nextNode == 0) + { + nextNode = &curNode; + addArchivePrefixNew.Add(name); + } + + RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, name, phyPrefix, + addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes)); + } + return S_OK; +} + +HRESULT EnumerateItems( + const NWildcard::CCensor &censor, + CDirItems &dirItems, + IEnumDirItemCallback *callback, + UStringVector &errorPaths, + CRecordVector &errorCodes) +{ + for (int i = 0; i < censor.Pairs.Size(); i++) + { + const NWildcard::CPair &pair = censor.Pairs[i]; + int phyParent = pair.Prefix.IsEmpty() ? -1 : dirItems.AddPrefix(-1, -1, pair.Prefix); + RINOK(EnumerateDirItems(pair.Head, phyParent, -1, pair.Prefix, UStringVector(), dirItems, false, + callback, errorPaths, errorCodes)); + } + dirItems.ReserveDown(); + return S_OK; +} diff --git a/CPP/7zip/UI/Common/EnumDirItems.h b/CPP/7zip/UI/Common/EnumDirItems.h new file mode 100755 index 0000000..835ae02 --- /dev/null +++ b/CPP/7zip/UI/Common/EnumDirItems.h @@ -0,0 +1,25 @@ +// 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, + const NWindows::NFile::NFind::CFileInfoW &fi, CObjectVector &dirItems); + +struct IEnumDirItemCallback +{ + virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) = 0; +}; + +HRESULT EnumerateItems( + const NWildcard::CCensor &censor, + CDirItems &dirItems, + IEnumDirItemCallback *callback, + UStringVector &errorPaths, + CRecordVector &errorCodes); + +#endif diff --git a/CPP/7zip/UI/Common/ExitCode.h b/CPP/7zip/UI/Common/ExitCode.h new file mode 100755 index 0000000..d03ec6d --- /dev/null +++ b/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/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp new file mode 100755 index 0000000..2f5a293 --- /dev/null +++ b/CPP/7zip/UI/Common/Extract.cpp @@ -0,0 +1,263 @@ +// Extract.cpp + +#include "StdAfx.h" + +#include + +#include "Windows/FileDir.h" +#include "Windows/PropVariant.h" +#include "Windows/PropVariantConversions.h" + +#include "../Common/ExtractingFilePath.h" + +#include "Extract.h" +#include "SetProperties.h" + +using namespace NWindows; + +static HRESULT DecompressArchive( + const CArc &arc, + UInt64 packSize, + const NWildcard::CCensorNode &wildcardCensor, + const CExtractOptions &options, + IExtractCallbackUI *callback, + CArchiveExtractCallback *extractCallbackSpec, + UString &errorMessage, + UInt64 &stdInProcessed) +{ + stdInProcessed = 0; + IInArchive *archive = arc.Archive; + CRecordVector realIndices; + if (!options.StdInMode) + { + UInt32 numItems; + RINOK(archive->GetNumberOfItems(&numItems)); + + for (UInt32 i = 0; i < numItems; i++) + { + UString filePath; + RINOK(arc.GetItemPath(i, filePath)); + bool isFolder; + RINOK(IsArchiveItemFolder(archive, i, isFolder)); + if (!wildcardCensor.CheckPath(filePath, !isFolder)) + continue; + realIndices.Add(i); + } + if (realIndices.Size() == 0) + { + callback->ThereAreNoFiles(); + return S_OK; + } + } + + UStringVector removePathParts; + + UString outDir = options.OutputDir; + outDir.Replace(L"*", GetCorrectFsPath(arc.DefaultName)); + #ifdef _WIN32 + // GetCorrectFullFsPath doesn't like "..". + // outDir.TrimRight(); + // outDir = GetCorrectFullFsPath(outDir); + #endif + + if (!outDir.IsEmpty()) + if (!NFile::NDirectory::CreateComplexDirectory(outDir)) + { + HRESULT res = ::GetLastError(); + if (res == S_OK) + res = E_FAIL; + errorMessage = ((UString)L"Can not create output directory ") + outDir; + return res; + } + + extractCallbackSpec->Init( + options.StdInMode ? &wildcardCensor : NULL, + &arc, + callback, + options.StdOutMode, options.TestMode, options.CalcCrc, + outDir, + removePathParts, + packSize); + + #if !defined(_7ZIP_ST) && !defined(_SFX) + RINOK(SetProperties(archive, options.Properties)); + #endif + + HRESULT result; + Int32 testMode = (options.TestMode && !options.CalcCrc) ? 1: 0; + if (options.StdInMode) + { + result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, extractCallbackSpec); + NCOM::CPropVariant prop; + if (archive->GetArchiveProperty(kpidPhySize, &prop) == S_OK) + if (prop.vt == VT_UI8 || prop.vt == VT_UI4) + stdInProcessed = ConvertPropVariantToUInt64(prop); + } + else + result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, extractCallbackSpec); + + return callback->ExtractResult(result); +} + +HRESULT DecompressArchives( + CCodecs *codecs, const CIntVector &formatIndices, + UStringVector &arcPaths, UStringVector &arcPathsFull, + const NWildcard::CCensorNode &wildcardCensor, + const CExtractOptions &options, + IOpenCallbackUI *openCallback, + IExtractCallbackUI *extractCallback, + UString &errorMessage, + CDecompressStat &stat) +{ + stat.Clear(); + int i; + UInt64 totalPackSize = 0; + CRecordVector archiveSizes; + + int numArcs = options.StdInMode ? 1 : arcPaths.Size(); + + for (i = 0; i < numArcs; i++) + { + NFile::NFind::CFileInfoW fi; + fi.Size = 0; + if (!options.StdInMode) + { + const UString &arcPath = arcPaths[i]; + if (!fi.Find(arcPath)) + throw "there is no such archive"; + if (fi.IsDir()) + throw "can't decompress folder"; + } + archiveSizes.Add(fi.Size); + totalPackSize += fi.Size; + } + CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; + CMyComPtr ec(extractCallbackSpec); + bool multi = (numArcs > 1); + extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode); + if (multi) + { + RINOK(extractCallback->SetTotal(totalPackSize)); + } + for (i = 0; i < numArcs; i++) + { + const UString &arcPath = arcPaths[i]; + NFile::NFind::CFileInfoW fi; + if (options.StdInMode) + { + fi.Size = 0; + fi.Attrib = 0; + } + else + { + if (!fi.Find(arcPath) || fi.IsDir()) + throw "there is no such archive"; + } + + #ifndef _NO_CRYPTO + openCallback->Open_ClearPasswordWasAskedFlag(); + #endif + + RINOK(extractCallback->BeforeOpen(arcPath)); + CArchiveLink archiveLink; + + CIntVector formatIndices2 = formatIndices; + #ifndef _SFX + if (formatIndices.IsEmpty()) + { + int pos = arcPath.ReverseFind(L'.'); + if (pos >= 0) + { + UString s = arcPath.Mid(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.Mid(pos + 1)); + if (index2 >= 0 && s.CompareNoCase(L"rar") != 0) + { + formatIndices2.Add(index2); + formatIndices2.Add(index); + } + } + } + } + } + #endif + HRESULT result = archiveLink.Open2(codecs, formatIndices2, options.StdInMode, NULL, arcPath, openCallback); + if (result == E_ABORT) + return result; + + bool crypted = false; + #ifndef _NO_CRYPTO + crypted = openCallback->Open_WasPasswordAsked(); + #endif + + RINOK(extractCallback->OpenResult(arcPath, result, crypted)); + if (result != S_OK) + continue; + + if (!options.StdInMode) + for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) + { + int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]); + if (index >= 0 && index > i) + { + arcPaths.Delete(index); + arcPathsFull.Delete(index); + totalPackSize -= archiveSizes[index]; + archiveSizes.Delete(index); + numArcs = arcPaths.Size(); + } + } + if (archiveLink.VolumePaths.Size() != 0) + { + totalPackSize += archiveLink.VolumesSize; + RINOK(extractCallback->SetTotal(totalPackSize)); + } + + #ifndef _NO_CRYPTO + UString password; + RINOK(openCallback->Open_GetPasswordIfAny(password)); + if (!password.IsEmpty()) + { + RINOK(extractCallback->SetPassword(password)); + } + #endif + + for (int v = 0; v < archiveLink.Arcs.Size(); v++) + { + const UString &s = archiveLink.Arcs[v].ErrorMessage; + if (!s.IsEmpty()) + { + RINOK(extractCallback->MessageError(s)); + } + } + + CArc &arc = archiveLink.Arcs.Back(); + arc.MTimeDefined = (!options.StdInMode && !fi.IsDevice); + arc.MTime = fi.MTime; + + UInt64 packProcessed; + RINOK(DecompressArchive(arc, + fi.Size + archiveLink.VolumesSize, + wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage, packProcessed)); + if (!options.StdInMode) + packProcessed = fi.Size + archiveLink.VolumesSize; + extractCallbackSpec->LocalProgressSpec->InSize += packProcessed; + extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize; + if (!errorMessage.IsEmpty()) + return E_FAIL; + } + stat.NumFolders = extractCallbackSpec->NumFolders; + stat.NumFiles = extractCallbackSpec->NumFiles; + stat.UnpackSize = extractCallbackSpec->UnpackSize; + stat.CrcSum = extractCallbackSpec->CrcSum; + + stat.NumArchives = arcPaths.Size(); + stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize; + return S_OK; +} diff --git a/CPP/7zip/UI/Common/Extract.h b/CPP/7zip/UI/Common/Extract.h new file mode 100755 index 0000000..70926d7 --- /dev/null +++ b/CPP/7zip/UI/Common/Extract.h @@ -0,0 +1,76 @@ +// 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 CExtractOptions +{ + bool StdInMode; + bool StdOutMode; + bool YesToAll; + bool TestMode; + bool CalcCrc; + NExtract::NPathMode::EEnum PathMode; + NExtract::NOverwriteMode::EEnum OverwriteMode; + UString OutputDir; + + // bool ShowDialog; + // bool PasswordEnabled; + // UString Password; + #if !defined(_7ZIP_ST) && !defined(_SFX) + CObjectVector Properties; + #endif + + #ifdef EXTERNAL_CODECS + CCodecs *Codecs; + #endif + + CExtractOptions(): + StdInMode(false), + StdOutMode(false), + YesToAll(false), + TestMode(false), + CalcCrc(false), + PathMode(NExtract::NPathMode::kFullPathnames), + OverwriteMode(NExtract::NOverwriteMode::kAskBefore) + {} +}; + +struct CDecompressStat +{ + UInt64 NumArchives; + UInt64 UnpackSize; + UInt64 PackSize; + UInt64 NumFolders; + UInt64 NumFiles; + UInt32 CrcSum; + + void Clear() + { + NumArchives = UnpackSize = PackSize = NumFolders = NumFiles = 0; + CrcSum = 0; + } +}; + +HRESULT DecompressArchives( + CCodecs *codecs, const CIntVector &formatIndices, + UStringVector &archivePaths, UStringVector &archivePathsFull, + const NWildcard::CCensorNode &wildcardCensor, + const CExtractOptions &options, + IOpenCallbackUI *openCallback, + IExtractCallbackUI *extractCallback, + UString &errorMessage, + CDecompressStat &stat); + +#endif diff --git a/CPP/7zip/UI/Common/ExtractMode.h b/CPP/7zip/UI/Common/ExtractMode.h new file mode 100755 index 0000000..44c4053 --- /dev/null +++ b/CPP/7zip/UI/Common/ExtractMode.h @@ -0,0 +1,31 @@ +// ExtractMode.h + +#ifndef __EXTRACT_MODE_H +#define __EXTRACT_MODE_H + +namespace NExtract { + + namespace NPathMode + { + enum EEnum + { + kFullPathnames, + kCurrentPathnames, + kNoPathnames + }; + } + + namespace NOverwriteMode + { + enum EEnum + { + kAskBefore, + kWithoutPrompt, + kSkipExisting, + kAutoRename, + kAutoRenameExisting + }; + } +} + +#endif diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/CPP/7zip/UI/Common/ExtractingFilePath.cpp new file mode 100755 index 0000000..604148a --- /dev/null +++ b/CPP/7zip/UI/Common/ExtractingFilePath.cpp @@ -0,0 +1,142 @@ +// ExtractingFilePath.cpp + +#include "StdAfx.h" + +#include "../../../../C/Types.h" + +#include "Common/Wildcard.h" + +#include "ExtractingFilePath.h" + +static UString ReplaceIncorrectChars(const UString &s) +{ + #ifdef _WIN32 + UString res; + for (int i = 0; i < s.Length(); i++) + { + wchar_t c = s[i]; + if (c < 0x20 || c == '*' || c == '?' || c == '<' || c == '>' || c == '|' || c == ':' || c == '"') + c = '_'; + res += c; + } + res.TrimRight(); + while (!res.IsEmpty() && res[res.Length() - 1] == '.') + res.Delete(res.Length() - 1); + return res; + #else + return s; + #endif +} + +#ifdef _WIN32 +static const wchar_t *g_ReservedNames[] = +{ + L"CON", L"PRN", L"AUX", L"NUL" +}; + +static bool CheckTail(const UString &name, int len) +{ + int dotPos = name.Find(L'.'); + if (dotPos < 0) + dotPos = name.Length(); + UString s = name.Left(dotPos); + s.TrimRight(); + return (s.Length() != len); +} + +static bool CheckNameNum(const UString &name, const wchar_t *reservedName) +{ + int len = MyStringLen(reservedName); + if (name.Length() <= len) + return true; + if (name.Left(len).CompareNoCase(reservedName) != 0) + return true; + wchar_t c = name[len]; + if (c < L'0' || c > L'9') + return true; + return CheckTail(name, len + 1); +} + +static bool IsSupportedName(const UString &name) +{ + for (int i = 0; i < sizeof(g_ReservedNames) / sizeof(g_ReservedNames[0]); i++) + { + const wchar_t *reservedName = g_ReservedNames[i]; + int len = MyStringLen(reservedName); + if (name.Length() < len) + continue; + if (name.Left(len).CompareNoCase(reservedName) != 0) + continue; + if (!CheckTail(name, len)) + return false; + } + if (!CheckNameNum(name, L"COM")) + return false; + return CheckNameNum(name, L"LPT"); +} +#endif + +static UString GetCorrectFileName(const UString &path) +{ + if (path == L".." || path == L".") + return UString(); + return ReplaceIncorrectChars(path); +} + +void MakeCorrectPath(UStringVector &pathParts) +{ + for (int i = 0; i < pathParts.Size();) + { + UString &s = pathParts[i]; + s = GetCorrectFileName(s); + if (s.IsEmpty()) + pathParts.Delete(i); + else + { + #ifdef _WIN32 + if (!IsSupportedName(s)) + s = (UString)L"_" + s; + #endif + i++; + } + } +} + +UString MakePathNameFromParts(const UStringVector &parts) +{ + UString result; + for (int i = 0; i < parts.Size(); i++) + { + if (i != 0) + result += WCHAR_PATH_SEPARATOR; + result += parts[i]; + } + return result; +} + +UString GetCorrectFsPath(const UString &path) +{ + UString res = GetCorrectFileName(path); + #ifdef _WIN32 + if (!IsSupportedName(res)) + res = (UString)L"_" + res; + #endif + return res; +} + +UString GetCorrectFullFsPath(const UString &path) +{ + UStringVector parts; + SplitPathToParts(path, parts); + for (int i = 0; i < parts.Size(); i++) + { + UString &s = parts[i]; + #ifdef _WIN32 + while (!s.IsEmpty() && s[s.Length() - 1] == '.') + s.Delete(s.Length() - 1); + if (!IsSupportedName(s)) + s = (UString)L"_" + s; + #endif + } + return MakePathNameFromParts(parts); +} diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.h b/CPP/7zip/UI/Common/ExtractingFilePath.h new file mode 100755 index 0000000..54bdc72 --- /dev/null +++ b/CPP/7zip/UI/Common/ExtractingFilePath.h @@ -0,0 +1,13 @@ +// ExtractingFilePath.h + +#ifndef __EXTRACTING_FILE_PATH_H +#define __EXTRACTING_FILE_PATH_H + +#include "Common/MyString.h" + +UString MakePathNameFromParts(const UStringVector &parts); +void MakeCorrectPath(UStringVector &pathParts); +UString GetCorrectFsPath(const UString &path); +UString GetCorrectFullFsPath(const UString &path); + +#endif diff --git a/CPP/7zip/UI/Common/IFileExtractCallback.h b/CPP/7zip/UI/Common/IFileExtractCallback.h new file mode 100755 index 0000000..5aff92f --- /dev/null +++ b/CPP/7zip/UI/Common/IFileExtractCallback.h @@ -0,0 +1,46 @@ +// IFileExtractCallback.h + +#ifndef __IFILEEXTRACTCALLBACK_H +#define __IFILEEXTRACTCALLBACK_H + +#include "Common/MyString.h" +#include "../../IDecl.h" + +namespace NOverwriteAnswer +{ + enum EEnum + { + kYes, + kYesToAll, + kNo, + kNoToAll, + kAutoRename, + kCancel + }; +} + +DECL_INTERFACE_SUB(IFolderArchiveExtractCallback, IProgress, 0x01, 0x07) +{ +public: + STDMETHOD(AskOverwrite)( + const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, + const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, + Int32 *answer) PURE; + STDMETHOD(PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position) PURE; + STDMETHOD(MessageError)(const wchar_t *message) PURE; + STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted) PURE; +}; + +struct IExtractCallbackUI: IFolderArchiveExtractCallback +{ + virtual HRESULT BeforeOpen(const wchar_t *name) = 0; + virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted) = 0; + virtual HRESULT ThereAreNoFiles() = 0; + virtual HRESULT ExtractResult(HRESULT result) = 0; + + #ifndef _NO_CRYPTO + virtual HRESULT SetPassword(const UString &password) = 0; + #endif +}; + +#endif diff --git a/CPP/7zip/UI/Common/LoadCodecs.cpp b/CPP/7zip/UI/Common/LoadCodecs.cpp new file mode 100755 index 0000000..67a0cc7 --- /dev/null +++ b/CPP/7zip/UI/Common/LoadCodecs.cpp @@ -0,0 +1,681 @@ +// LoadCodecs.cpp + +#include "StdAfx.h" + +#include "LoadCodecs.h" + +#include "../../../Common/MyCom.h" +#ifdef NEW_FOLDER_INTERFACE +#include "../../../Common/StringToInt.h" +#endif +#include "../../../Windows/PropVariant.h" + +#include "../../ICoder.h" +#include "../../Common/RegisterArc.h" + +#ifdef EXTERNAL_CODECS +#include "../../../Windows/FileFind.h" +#include "../../../Windows/DLL.h" +#ifdef NEW_FOLDER_INTERFACE +#include "../../../Windows/ResourceString.h" +static const UINT kIconTypesResId = 100; +#endif + +#ifdef _WIN32 +#include "Windows/Registry.h" +#endif + +using namespace NWindows; +using namespace NFile; + +#ifdef _WIN32 +extern HINSTANCE g_hInstance; +#endif + +static CSysString GetLibraryFolderPrefix() +{ + #ifdef _WIN32 + TCHAR fullPath[MAX_PATH + 1]; + ::GetModuleFileName(g_hInstance, fullPath, MAX_PATH); + CSysString path = fullPath; + int pos = path.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); + return path.Left(pos + 1); + #else + return CSysString(); // FIX IT + #endif +} + +#define kCodecsFolderName TEXT("Codecs") +#define kFormatsFolderName TEXT("Formats") +static const TCHAR *kMainDll = TEXT("7z.dll"); + +#ifdef _WIN32 +static LPCTSTR kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip"); +static LPCTSTR kProgramPathValue = TEXT("Path"); +static bool ReadPathFromRegistry(HKEY baseKey, CSysString &path) +{ + NRegistry::CKey key; + if(key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS) + if (key.QueryValue(kProgramPathValue, path) == ERROR_SUCCESS) + { + NName::NormalizeDirPathPrefix(path); + return true; + } + return false; +} + +#endif + +CSysString GetBaseFolderPrefixFromRegistry() +{ + CSysString moduleFolderPrefix = GetLibraryFolderPrefix(); + #ifdef _WIN32 + if (!NFind::DoesFileExist(moduleFolderPrefix + kMainDll) && + !NFind::DoesDirExist(moduleFolderPrefix + kCodecsFolderName) && + !NFind::DoesDirExist(moduleFolderPrefix + kFormatsFolderName)) + { + CSysString path; + if (ReadPathFromRegistry(HKEY_CURRENT_USER, path)) + return path; + if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path)) + return path; + } + #endif + return moduleFolderPrefix; +} + +typedef UInt32 (WINAPI *GetNumberOfMethodsFunc)(UInt32 *numMethods); +typedef UInt32 (WINAPI *GetNumberOfFormatsFunc)(UInt32 *numFormats); +typedef UInt32 (WINAPI *GetHandlerPropertyFunc)(PROPID propID, PROPVARIANT *value); +typedef UInt32 (WINAPI *GetHandlerPropertyFunc2)(UInt32 index, PROPID propID, PROPVARIANT *value); +typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *iid, void **outObject); +typedef UInt32 (WINAPI *SetLargePageModeFunc)(); + + +static HRESULT GetCoderClass(GetMethodPropertyFunc getMethodProperty, UInt32 index, + PROPID propId, CLSID &clsId, bool &isAssigned) +{ + NWindows::NCOM::CPropVariant prop; + isAssigned = false; + RINOK(getMethodProperty(index, propId, &prop)); + if (prop.vt == VT_BSTR) + { + 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.GetMethodProperty = (GetMethodPropertyFunc)lib.Lib.GetProc("GetMethodProperty"); + if (lib.GetMethodProperty == NULL) + return S_OK; + + UInt32 numMethods = 1; + GetNumberOfMethodsFunc getNumberOfMethodsFunc = (GetNumberOfMethodsFunc)lib.Lib.GetProc("GetNumberOfMethods"); + if (getNumberOfMethodsFunc != NULL) + { + RINOK(getNumberOfMethodsFunc(&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); + } + return S_OK; +} + +static HRESULT ReadProp( + GetHandlerPropertyFunc getProp, + GetHandlerPropertyFunc2 getProp2, + UInt32 index, PROPID propID, NCOM::CPropVariant &prop) +{ + if (getProp2) + return getProp2(index, propID, &prop);; + return getProp(propID, &prop); +} + +static HRESULT ReadBoolProp( + GetHandlerPropertyFunc getProp, + GetHandlerPropertyFunc2 getProp2, + UInt32 index, PROPID propID, bool &res) +{ + NCOM::CPropVariant prop; + RINOK(ReadProp(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 ReadStringProp( + GetHandlerPropertyFunc getProp, + GetHandlerPropertyFunc2 getProp2, + UInt32 index, PROPID propID, UString &res) +{ + NCOM::CPropVariant prop; + RINOK(ReadProp(getProp, getProp2, index, propID, prop)); + if (prop.vt == VT_BSTR) + res = prop.bstrVal; + else if (prop.vt != VT_EMPTY) + return E_FAIL; + return S_OK; +} + +#endif + +static const unsigned int kNumArcsMax = 48; +static unsigned int g_NumArcs = 0; +static const CArcInfo *g_Arcs[kNumArcsMax]; +void RegisterArc(const CArcInfo *arcInfo) +{ + if (g_NumArcs < kNumArcsMax) + g_Arcs[g_NumArcs++] = arcInfo; +} + +static void SplitString(const UString &srcString, UStringVector &destStrings) +{ + destStrings.Clear(); + UString s; + int len = srcString.Length(); + if (len == 0) + return; + for (int 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); +} + +void CArcInfoEx::AddExts(const wchar_t *ext, const wchar_t *addExt) +{ + UStringVector exts, addExts; + if (ext != 0) + SplitString(ext, exts); + if (addExt != 0) + SplitString(addExt, addExts); + for (int i = 0; i < exts.Size(); i++) + { + CArcExtInfo extInfo; + extInfo.Ext = exts[i]; + if (i < addExts.Size()) + { + extInfo.AddExt = addExts[i]; + if (extInfo.AddExt == L"*") + extInfo.AddExt.Empty(); + } + Exts.Add(extInfo); + } +} + +#ifdef EXTERNAL_CODECS + +HRESULT CCodecs::LoadFormats() +{ + const NDLL::CLibrary &lib = Libs.Back().Lib; + GetHandlerPropertyFunc getProp = 0; + GetHandlerPropertyFunc2 getProp2 = (GetHandlerPropertyFunc2)lib.GetProc("GetHandlerProperty2"); + if (getProp2 == NULL) + { + getProp = (GetHandlerPropertyFunc)lib.GetProc("GetHandlerProperty"); + if (getProp == NULL) + return S_OK; + } + + UInt32 numFormats = 1; + GetNumberOfFormatsFunc getNumberOfFormats = (GetNumberOfFormatsFunc)lib.GetProc("GetNumberOfFormats"); + if (getNumberOfFormats != NULL) + { + RINOK(getNumberOfFormats(&numFormats)); + } + if (getProp2 == NULL) + numFormats = 1; + + for(UInt32 i = 0; i < numFormats; i++) + { + CArcInfoEx item; + item.LibIndex = Libs.Size() - 1; + item.FormatIndex = i; + + RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kName, item.Name)); + + NCOM::CPropVariant prop; + if (ReadProp(getProp, getProp2, i, NArchive::kClassID, prop) != S_OK) + continue; + if (prop.vt != VT_BSTR) + continue; + item.ClassID = *(const GUID *)prop.bstrVal; + prop.Clear(); + + UString ext, addExt; + RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kExtension, ext)); + RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kAddExtension, addExt)); + item.AddExts(ext, addExt); + + ReadBoolProp(getProp, getProp2, i, NArchive::kUpdate, item.UpdateEnabled); + if (item.UpdateEnabled) + ReadBoolProp(getProp, getProp2, i, NArchive::kKeepName, item.KeepName); + + if (ReadProp(getProp, getProp2, i, NArchive::kStartSignature, prop) == S_OK) + if (prop.vt == VT_BSTR) + { + UINT len = ::SysStringByteLen(prop.bstrVal); + item.StartSignature.SetCapacity(len); + memmove(item.StartSignature, prop.bstrVal, len); + } + Formats.Add(item); + } + return S_OK; +} + +#ifdef NEW_FOLDER_INTERFACE +void CCodecIcons::LoadIcons(HMODULE m) +{ + UString iconTypes = MyLoadStringW(m, kIconTypesResId); + UStringVector pairs; + SplitString(iconTypes, pairs); + for (int i = 0; i < pairs.Size(); i++) + { + const UString &s = pairs[i]; + int pos = s.Find(L':'); + CIconPair iconPair; + iconPair.IconIndex = -1; + if (pos < 0) + pos = s.Length(); + else + { + UString num = s.Mid(pos + 1); + if (!num.IsEmpty()) + { + const wchar_t *end; + iconPair.IconIndex = (UInt32)ConvertStringToUInt64(num, &end); + if (*end != L'\0') + continue; + } + } + iconPair.Ext = s.Left(pos); + IconPairs.Add(iconPair); + } +} + +bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const +{ + iconIndex = -1; + for (int i = 0; i < IconPairs.Size(); i++) + { + const CIconPair &pair = IconPairs[i]; + if (ext.CompareNoCase(pair.Ext) == 0) + { + iconIndex = pair.IconIndex; + return true; + } + } + return false; +} +#endif + +#ifdef _7ZIP_LARGE_PAGES +extern "C" +{ + extern SIZE_T g_LargePageSize; +} +#endif + +HRESULT CCodecs::LoadDll(const CSysString &dllPath, bool needCheckDll) +{ + if (needCheckDll) + { + NDLL::CLibrary library; + if (!library.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE)) + return S_OK; + } + Libs.Add(CCodecLib()); + CCodecLib &lib = Libs.Back(); + #ifdef NEW_FOLDER_INTERFACE + lib.Path = dllPath; + #endif + bool used = false; + HRESULT res = S_OK; + if (lib.Lib.Load(dllPath)) + { + #ifdef NEW_FOLDER_INTERFACE + lib.LoadIcons(); + #endif + + #ifdef _7ZIP_LARGE_PAGES + if (g_LargePageSize != 0) + { + SetLargePageModeFunc setLargePageMode = (SetLargePageModeFunc)lib.Lib.GetProc("SetLargePageMode"); + if (setLargePageMode != 0) + setLargePageMode(); + } + #endif + + lib.CreateObject = (CreateObjectFunc)lib.Lib.GetProc("CreateObject"); + if (lib.CreateObject != 0) + { + int startSize = Codecs.Size(); + res = LoadCodecs(); + used = (Codecs.Size() != startSize); + if (res == S_OK) + { + startSize = Formats.Size(); + res = LoadFormats(); + used = used || (Formats.Size() != startSize); + } + } + } + if (!used) + Libs.DeleteBack(); + return res; +} + +HRESULT CCodecs::LoadDllsFromFolder(const CSysString &folderPrefix) +{ + NFile::NFind::CEnumerator enumerator(folderPrefix + CSysString(TEXT("*"))); + NFile::NFind::CFileInfo fi; + while (enumerator.Next(fi)) + { + if (fi.IsDir()) + continue; + RINOK(LoadDll(folderPrefix + fi.Name, true)); + } + return S_OK; +} + +#endif + +#ifndef _SFX +static inline void SetBuffer(CByteBuffer &bb, const Byte *data, int size) +{ + bb.SetCapacity(size); + memmove((Byte *)bb, data, size); +} +#endif + +HRESULT CCodecs::Load() +{ + #ifdef NEW_FOLDER_INTERFACE + InternalIcons.LoadIcons(g_hInstance); + #endif + + Formats.Clear(); + #ifdef EXTERNAL_CODECS + Codecs.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.CreateOutArchive = arc.CreateOutArchive; + item.AddExts(arc.Ext, arc.AddExt); + item.UpdateEnabled = (arc.CreateOutArchive != 0); + item.KeepName = arc.KeepName; + + #ifndef _SFX + SetBuffer(item.StartSignature, arc.Signature, arc.SignatureSize); + #endif + Formats.Add(item); + } + #ifdef EXTERNAL_CODECS + const CSysString baseFolder = GetBaseFolderPrefixFromRegistry(); + RINOK(LoadDll(baseFolder + kMainDll, false)); + RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName TEXT(STRING_PATH_SEPARATOR))); + RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName TEXT(STRING_PATH_SEPARATOR))); + #endif + return S_OK; +} + +#ifndef _SFX + +int CCodecs::FindFormatForArchiveName(const UString &arcPath) const +{ + int slashPos1 = arcPath.ReverseFind(WCHAR_PATH_SEPARATOR); + int slashPos2 = arcPath.ReverseFind(L'.'); + int dotPos = arcPath.ReverseFind(L'.'); + if (dotPos < 0 || dotPos < slashPos1 || dotPos < slashPos2) + return -1; + UString ext = arcPath.Mid(dotPos + 1); + for (int i = 0; i < Formats.Size(); i++) + { + 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 (int i = 0; i < Formats.Size(); i++) + if (Formats[i].FindExtension(ext) >= 0) + return i; + return -1; +} + +int CCodecs::FindFormatForArchiveType(const UString &arcType) const +{ + for (int i = 0; i < Formats.Size(); i++) + if (Formats[i].Name.CompareNoCase(arcType) == 0) + return i; + return -1; +} + +bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const +{ + formatIndices.Clear(); + for (int pos = 0; pos < arcType.Length();) + { + int pos2 = arcType.Find('.', pos); + if (pos2 < 0) + pos2 = arcType.Length(); + const UString name = arcType.Mid(pos, pos2 - pos); + int index = FindFormatForArchiveType(name); + if (index < 0 && name != L"*") + { + formatIndices.Clear(); + return false; + } + formatIndices.Add(index); + pos = pos2 + 1; + } + return true; +} + +#endif + +#ifdef EXTERNAL_CODECS + +#ifdef EXPORT_CODECS +extern unsigned int g_NumCodecs; +STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject); +STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); +// STDAPI GetNumberOfMethods(UInt32 *numCodecs); +#endif + +STDMETHODIMP CCodecs::GetNumberOfMethods(UInt32 *numMethods) +{ + *numMethods = + #ifdef EXPORT_CODECS + g_NumCodecs + + #endif + Codecs.Size(); + 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 + + const CDllCodecInfo &ci = Codecs[index + #ifdef EXPORT_CODECS + - g_NumCodecs + #endif + ]; + + if (propID == NMethodPropID::kDecoderIsAssigned) + { + NWindows::NCOM::CPropVariant propVariant; + propVariant = ci.DecoderIsAssigned; + propVariant.Detach(value); + return S_OK; + } + if (propID == NMethodPropID::kEncoderIsAssigned) + { + NWindows::NCOM::CPropVariant propVariant; + propVariant = ci.EncoderIsAssigned; + propVariant.Detach(value); + return S_OK; + } + return Libs[ci.LibIndex].GetMethodProperty(ci.CodecIndex, propID, value); +} + +STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder) +{ + #ifdef EXPORT_CODECS + if (index < g_NumCodecs) + return CreateCoder2(false, index, iid, coder); + #endif + const CDllCodecInfo &ci = Codecs[index + #ifdef EXPORT_CODECS + - g_NumCodecs + #endif + ]; + if (ci.DecoderIsAssigned) + return Libs[ci.LibIndex].CreateObject(&ci.Decoder, iid, (void **)coder); + return S_OK; +} + +STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder) +{ + #ifdef EXPORT_CODECS + if (index < g_NumCodecs) + return CreateCoder2(true, index, iid, coder); + #endif + const CDllCodecInfo &ci = Codecs[index + #ifdef EXPORT_CODECS + - g_NumCodecs + #endif + ]; + if (ci.EncoderIsAssigned) + return Libs[ci.LibIndex].CreateObject(&ci.Encoder, iid, (void **)coder); + return S_OK; +} + +HRESULT CCodecs::CreateCoder(const UString &name, bool encode, CMyComPtr &coder) const +{ + for (int i = 0; i < Codecs.Size(); i++) + { + const CDllCodecInfo &codec = Codecs[i]; + if (encode && !codec.EncoderIsAssigned || !encode && !codec.DecoderIsAssigned) + continue; + const CCodecLib &lib = Libs[codec.LibIndex]; + UString res; + NWindows::NCOM::CPropVariant prop; + RINOK(lib.GetMethodProperty(codec.CodecIndex, NMethodPropID::kName, &prop)); + if (prop.vt == VT_BSTR) + res = prop.bstrVal; + else if (prop.vt != VT_EMPTY) + continue; + if (name.CompareNoCase(res) == 0) + return lib.CreateObject(encode ? &codec.Encoder : &codec.Decoder, &IID_ICompressCoder, (void **)&coder); + } + return CLASS_E_CLASSNOTAVAILABLE; +} + +int CCodecs::GetCodecLibIndex(UInt32 index) +{ + #ifdef EXPORT_CODECS + if (index < g_NumCodecs) + return -1; + #endif + #ifdef EXTERNAL_CODECS + const CDllCodecInfo &ci = Codecs[index + #ifdef EXPORT_CODECS + - g_NumCodecs + #endif + ]; + return ci.LibIndex; + #else + return -1; + #endif +} + +bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index) +{ + #ifdef EXPORT_CODECS + if (index < g_NumCodecs) + { + NWindows::NCOM::CPropVariant prop; + if (GetProperty(index, NMethodPropID::kEncoder, &prop) == S_OK) + if (prop.vt != VT_EMPTY) + return true; + return false; + } + #endif + #ifdef EXTERNAL_CODECS + const CDllCodecInfo &ci = Codecs[index + #ifdef EXPORT_CODECS + - g_NumCodecs + #endif + ]; + return ci.EncoderIsAssigned; + #else + return false; + #endif +} + +HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id) +{ + UString s; + NWindows::NCOM::CPropVariant prop; + RINOK(GetProperty(index, NMethodPropID::kID, &prop)); + if (prop.vt != VT_UI8) + return E_INVALIDARG; + id = prop.uhVal.QuadPart; + return S_OK; +} + +UString CCodecs::GetCodecName(UInt32 index) +{ + UString s; + NWindows::NCOM::CPropVariant prop; + if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK) + if (prop.vt == VT_BSTR) + s = prop.bstrVal; + return s; +} + +#endif diff --git a/CPP/7zip/UI/Common/LoadCodecs.h b/CPP/7zip/UI/Common/LoadCodecs.h new file mode 100755 index 0000000..5630b59 --- /dev/null +++ b/CPP/7zip/UI/Common/LoadCodecs.h @@ -0,0 +1,235 @@ +// LoadCodecs.h + +#ifndef __LOADCODECS_H +#define __LOADCODECS_H + +#include "../../../Common/Types.h" +#include "../../../Common/MyCom.h" +#include "../../../Common/MyString.h" +#include "../../../Common/Buffer.h" +#include "../../ICoder.h" + +#ifdef EXTERNAL_CODECS +#include "../../../Windows/DLL.h" +#endif + +struct CDllCodecInfo +{ + CLSID Encoder; + CLSID Decoder; + bool EncoderIsAssigned; + bool DecoderIsAssigned; + int LibIndex; + UInt32 CodecIndex; +}; + +#include "../../Archive/IArchive.h" + +typedef IInArchive * (*CreateInArchiveP)(); +typedef IOutArchive * (*CreateOutArchiveP)(); + +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 +{ + #ifdef EXTERNAL_CODECS + int LibIndex; + UInt32 FormatIndex; + CLSID ClassID; + #endif + bool UpdateEnabled; + CreateInArchiveP CreateInArchive; + CreateOutArchiveP CreateOutArchive; + UString Name; + CObjectVector Exts; + #ifndef _SFX + CByteBuffer StartSignature; + // CByteBuffer FinishSignature; + #ifdef NEW_FOLDER_INTERFACE + UStringVector AssociateExts; + #endif + #endif + bool KeepName; + UString GetMainExt() const + { + if (Exts.IsEmpty()) + return UString(); + return Exts[0].Ext; + } + int FindExtension(const UString &ext) const + { + for (int i = 0; i < Exts.Size(); i++) + if (ext.CompareNoCase(Exts[i].Ext) == 0) + return i; + return -1; + } + 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 wchar_t* ext, const wchar_t* addExt); + + CArcInfoEx(): + #ifdef EXTERNAL_CODECS + LibIndex(-1), + #endif + UpdateEnabled(false), + CreateInArchive(0), CreateOutArchive(0), + KeepName(false) + #ifndef _SFX + #endif + {} +}; + +#ifdef EXTERNAL_CODECS +typedef UInt32 (WINAPI *GetMethodPropertyFunc)(UInt32 index, PROPID propID, PROPVARIANT *value); +typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *interfaceID, void **outObject); + + +#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 + +struct CCodecLib +#ifdef NEW_FOLDER_INTERFACE +: public CCodecIcons +#endif +{ + NWindows::NDLL::CLibrary Lib; + GetMethodPropertyFunc GetMethodProperty; + CreateObjectFunc CreateObject; + #ifdef NEW_FOLDER_INTERFACE + CSysString Path; + void LoadIcons() { CCodecIcons::LoadIcons((HMODULE)Lib); } + #endif + CCodecLib(): GetMethodProperty(0) {} +}; +#endif + +class CCodecs: + #ifdef EXTERNAL_CODECS + public ICompressCodecsInfo, + #else + public IUnknown, + #endif + public CMyUnknownImp +{ +public: + #ifdef EXTERNAL_CODECS + CObjectVector Libs; + CObjectVector Codecs; + + #ifdef NEW_FOLDER_INTERFACE + CCodecIcons InternalIcons; + #endif + + HRESULT LoadCodecs(); + HRESULT LoadFormats(); + HRESULT LoadDll(const CSysString &path, bool needCheckDll); + HRESULT LoadDllsFromFolder(const CSysString &folderPrefix); + + HRESULT CreateArchiveHandler(const CArcInfoEx &ai, void **archive, bool outHandler) const + { + return Libs[ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive); + } + #endif + +public: + CObjectVector Formats; + 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 + + MY_UNKNOWN_IMP + + #ifdef EXTERNAL_CODECS + STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods); + STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); + STDMETHOD(CreateDecoder)(UInt32 index, const GUID *interfaceID, void **coder); + STDMETHOD(CreateEncoder)(UInt32 index, const GUID *interfaceID, void **coder); + #endif + + int GetCodecLibIndex(UInt32 index); + bool GetCodecEncoderIsAssigned(UInt32 index); + HRESULT GetCodecId(UInt32 index, UInt64 &id); + UString GetCodecName(UInt32 index); + + HRESULT CreateInArchive(int formatIndex, CMyComPtr &archive) const + { + const CArcInfoEx &ai = Formats[formatIndex]; + #ifdef EXTERNAL_CODECS + if (ai.LibIndex < 0) + #endif + { + archive = ai.CreateInArchive(); + return S_OK; + } + #ifdef EXTERNAL_CODECS + return CreateArchiveHandler(ai, (void **)&archive, false); + #endif + } + HRESULT CreateOutArchive(int formatIndex, CMyComPtr &archive) const + { + const CArcInfoEx &ai = Formats[formatIndex]; + #ifdef EXTERNAL_CODECS + if (ai.LibIndex < 0) + #endif + { + archive = ai.CreateOutArchive(); + return S_OK; + } + #ifdef EXTERNAL_CODECS + return CreateArchiveHandler(ai, (void **)&archive, true); + #endif + } + int FindOutFormatFromName(const UString &name) const + { + for (int i = 0; i < Formats.Size(); i++) + { + const CArcInfoEx &arc = Formats[i]; + if (!arc.UpdateEnabled) + continue; + if (arc.Name.CompareNoCase(name) == 0) + return i; + } + return -1; + } + + #ifdef EXTERNAL_CODECS + HRESULT CreateCoder(const UString &name, bool encode, CMyComPtr &coder) const; + #endif + +}; + +#endif diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp new file mode 100755 index 0000000..c489e0a --- /dev/null +++ b/CPP/7zip/UI/Common/OpenArchive.cpp @@ -0,0 +1,536 @@ +// OpenArchive.cpp + +#include "StdAfx.h" + +#include "Common/Wildcard.h" + +#include "Windows/FileDir.h" +#include "Windows/PropVariant.h" + +#include "../../Common/FileStreams.h" +#include "../../Common/StreamUtils.h" + +#include "DefaultName.h" +#include "OpenArchive.h" + +using namespace NWindows; + +// Static-SFX (for Linux) can be big. +const UInt64 kMaxCheckStartPosition = 1 << 22; + +HRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) +{ + NCOM::CPropVariant prop; + result = false; + RINOK(archive->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 IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) +{ + return GetArchiveItemBoolProp(archive, index, kpidIsDir, result); +} + +HRESULT CArc::GetItemPath(UInt32 index, UString &result) const +{ + { + NCOM::CPropVariant prop; + RINOK(Archive->GetProperty(index, kpidPath, &prop)); + if (prop.vt == VT_BSTR) + result = prop.bstrVal; + else if (prop.vt == VT_EMPTY) + result.Empty(); + else + return E_FAIL; + } + if (result.IsEmpty()) + { + result = DefaultName; + NCOM::CPropVariant prop; + RINOK(Archive->GetProperty(index, kpidExtension, &prop)); + if (prop.vt == VT_BSTR) + { + result += L'.'; + result += prop.bstrVal; + } + else if (prop.vt != VT_EMPTY) + return E_FAIL; + } + 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; +} +#endif + +#ifdef UNDER_CE +static const int kNumHashBytes = 1; +#define HASH_VAL(buf, pos) ((buf)[pos]) +#else +static const int kNumHashBytes = 2; +#define HASH_VAL(buf, pos) ((buf)[pos] | ((UInt32)(buf)[pos + 1] << 8)) +#endif + + +HRESULT CArc::OpenStream( + CCodecs *codecs, + int formatIndex, + IInStream *stream, + ISequentialInStream *seqStream, + IArchiveOpenCallback *callback) +{ + Archive.Release(); + ErrorMessage.Empty(); + const UString fileName = ExtractFileNameFromPath(Path); + UString extension; + { + int dotPos = fileName.ReverseFind(L'.'); + if (dotPos >= 0) + extension = fileName.Mid(dotPos + 1); + } + CIntVector orderIndices; + if (formatIndex >= 0) + orderIndices.Add(formatIndex); + else + { + + int i; + int numFinded = 0; + for (i = 0; i < codecs->Formats.Size(); i++) + if (codecs->Formats[i].FindExtension(extension) >= 0) + orderIndices.Insert(numFinded++, i); + else + orderIndices.Add(i); + + if (!stream) + { + if (numFinded != 1) + return E_NOTIMPL; + orderIndices.DeleteFrom(1); + } + + #ifndef _SFX + if (orderIndices.Size() >= 2 && (numFinded == 0 || extension.CompareNoCase(L"exe") == 0)) + { + CIntVector orderIndices2; + CByteBuffer byteBuffer; + const size_t kBufferSize = (1 << 21); + byteBuffer.SetCapacity(kBufferSize); + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + size_t processedSize = kBufferSize; + RINOK(ReadStream(stream, byteBuffer, &processedSize)); + if (processedSize == 0) + return S_FALSE; + + const Byte *buf = byteBuffer; + CByteBuffer hashBuffer; + const UInt32 kNumVals = 1 << (kNumHashBytes * 8); + hashBuffer.SetCapacity(kNumVals); + Byte *hash = hashBuffer; + memset(hash, 0xFF, kNumVals); + Byte prevs[256]; + if (orderIndices.Size() >= 256) + return S_FALSE; + int i; + for (i = 0; i < orderIndices.Size(); i++) + { + const CArcInfoEx &ai = codecs->Formats[orderIndices[i]]; + const CByteBuffer &sig = ai.StartSignature; + if (sig.GetCapacity() < kNumHashBytes) + continue; + UInt32 v = HASH_VAL(sig, 0); + prevs[i] = hash[v]; + hash[v] = (Byte)i; + } + + processedSize -= (kNumHashBytes - 1); + for (UInt32 pos = 0; pos < processedSize; pos++) + { + for (; pos < processedSize && hash[HASH_VAL(buf, pos)] == 0xFF; pos++); + if (pos == processedSize) + break; + UInt32 v = HASH_VAL(buf, pos); + Byte *ptr = &hash[v]; + int i = *ptr; + do + { + int index = orderIndices[i]; + const CArcInfoEx &ai = codecs->Formats[index]; + const CByteBuffer &sig = ai.StartSignature; + if (sig.GetCapacity() != 0 && pos + sig.GetCapacity() <= processedSize + (kNumHashBytes - 1) && + TestSignature(buf + pos, sig, sig.GetCapacity())) + { + orderIndices2.Add(index); + orderIndices[i] = 0xFF; + *ptr = prevs[i]; + } + else + ptr = &prevs[i]; + i = *ptr; + } + while (i != 0xFF); + } + + for (i = 0; i < orderIndices.Size(); i++) + { + int val = orderIndices[i]; + if (val != 0xFF) + orderIndices2.Add(val); + } + orderIndices = orderIndices2; + } + else if (extension == L"000" || extension == L"001") + { + CByteBuffer byteBuffer; + const size_t kBufferSize = (1 << 10); + byteBuffer.SetCapacity(kBufferSize); + Byte *buffer = byteBuffer; + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + size_t processedSize = kBufferSize; + RINOK(ReadStream(stream, buffer, &processedSize)); + if (processedSize >= 16) + { + Byte kRarHeader[] = {0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00}; + if (TestSignature(buffer, kRarHeader, 7) && buffer[9] == 0x73 && (buffer[10] & 1) != 0) + { + for (int i = 0; i < orderIndices.Size(); i++) + { + int index = orderIndices[i]; + const CArcInfoEx &ai = codecs->Formats[index]; + if (ai.Name.CompareNoCase(L"rar") != 0) + continue; + orderIndices.Delete(i--); + orderIndices.Insert(0, index); + break; + } + } + } + } + if (orderIndices.Size() >= 2) + { + int isoIndex = codecs->FindFormatForArchiveType(L"iso"); + int udfIndex = codecs->FindFormatForArchiveType(L"udf"); + int iIso = -1; + int iUdf = -1; + for (int i = 0; i < orderIndices.Size(); i++) + { + if (orderIndices[i] == isoIndex) iIso = i; + if (orderIndices[i] == udfIndex) iUdf = i; + } + if (iUdf > iIso && iIso >= 0) + { + orderIndices[iUdf] = isoIndex; + orderIndices[iIso] = udfIndex; + } + } + + #endif + } + + for (int i = 0; i < orderIndices.Size(); i++) + { + if (stream) + { + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + } + CMyComPtr archive; + + FormatIndex = orderIndices[i]; + RINOK(codecs->CreateInArchive(FormatIndex, archive)); + if (!archive) + continue; + + #ifdef EXTERNAL_CODECS + { + CMyComPtr setCompressCodecsInfo; + archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); + if (setCompressCodecsInfo) + { + RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs)); + } + } + #endif + + // OutputDebugStringW(codecs->Formats[FormatIndex].Name); + + HRESULT result; + if (stream) + result = archive->Open(stream, &kMaxCheckStartPosition, callback); + else + { + CMyComPtr openSeq; + archive.QueryInterface(IID_IArchiveOpenSeq, (void **)&openSeq); + if (!openSeq) + return E_NOTIMPL; + result = openSeq->OpenSeq(seqStream); + } + + if (result == S_FALSE) + continue; + RINOK(result); + + { + NCOM::CPropVariant prop; + archive->GetArchiveProperty(kpidError, &prop); + if (prop.vt != VT_EMPTY) + ErrorMessage = (prop.vt == VT_BSTR) ? prop.bstrVal : L"Unknown error"; + } + + Archive = archive; + const CArcInfoEx &format = codecs->Formats[FormatIndex]; + if (format.Exts.Size() == 0) + DefaultName = GetDefaultName2(fileName, L"", L""); + else + { + int subExtIndex = format.FindExtension(extension); + if (subExtIndex < 0) + subExtIndex = 0; + const CArcExtInfo &extInfo = format.Exts[subExtIndex]; + DefaultName = GetDefaultName2(fileName, extInfo.Ext, extInfo.AddExt); + } + return S_OK; + } + return S_FALSE; +} + +HRESULT CArc::OpenStreamOrFile( + CCodecs *codecs, + int formatIndex, + bool stdInMode, + IInStream *stream, + IArchiveOpenCallback *callback) +{ + CMyComPtr fileStream; + CMyComPtr seqStream; + if (stdInMode) + seqStream = new CStdInFileStream; + else if (!stream) + { + CInFileStream *fileStreamSpec = new CInFileStream; + fileStream = fileStreamSpec; + if (!fileStreamSpec->Open(Path)) + return GetLastError(); + stream = fileStream; + } + + /* + if (callback) + { + UInt64 fileSize; + RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize)); + RINOK(callback->SetTotal(NULL, &fileSize)) + } + */ + + return OpenStream(codecs, formatIndex, stream, seqStream, callback); +} + +HRESULT CArchiveLink::Close() +{ + for (int i = Arcs.Size() - 1; i >= 0; i--) + { + RINOK(Arcs[i].Archive->Close()); + } + IsOpen = false; + return S_OK; +} + +void CArchiveLink::Release() +{ + while (!Arcs.IsEmpty()) + Arcs.DeleteBack(); +} + +HRESULT CArchiveLink::Open( + CCodecs *codecs, + const CIntVector &formatIndices, + bool stdInMode, + IInStream *stream, + const UString &filePath, + IArchiveOpenCallback *callback) +{ + Release(); + if (formatIndices.Size() >= 32) + return E_NOTIMPL; + + HRESULT resSpec; + + for (;;) + { + resSpec = S_OK; + int formatIndex = -1; + if (formatIndices.Size() >= 1) + { + if (Arcs.Size() >= formatIndices.Size()) + break; + formatIndex = formatIndices[formatIndices.Size() - Arcs.Size() - 1]; + } + else if (Arcs.Size() >= 32) + break; + + if (Arcs.IsEmpty()) + { + CArc arc; + arc.Path = filePath; + arc.SubfileIndex = (UInt32)(Int32)-1; + RINOK(arc.OpenStreamOrFile(codecs, formatIndex, stdInMode, stream, callback)); + Arcs.Add(arc); + continue; + } + + const CArc &arc = Arcs.Back(); + + resSpec = (formatIndices.Size() == 0 ? S_OK : 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)); + + CMyComPtr setSubArchiveName; + callback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName); + if (setSubArchiveName) + setSubArchiveName->SetSubArchiveName(arc2.Path); + + arc2.SubfileIndex = mainSubfile; + HRESULT result = arc2.OpenStream(codecs, formatIndex, subStream, NULL, callback); + resSpec = (formatIndices.Size() == 0 ? S_OK : S_FALSE); + if (result == S_FALSE) + break; + RINOK(result); + RINOK(arc.GetItemMTime(mainSubfile, arc2.MTime, arc2.MTimeDefined)); + Arcs.Add(arc2); + } + IsOpen = !Arcs.IsEmpty(); + return S_OK; +} + +static void SetCallback(const UString &filePath, + IOpenCallbackUI *callbackUI, + IArchiveOpenCallback *reOpenCallback, + CMyComPtr &callback) +{ + COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; + callback = openCallbackSpec; + openCallbackSpec->Callback = callbackUI; + openCallbackSpec->ReOpenCallback = reOpenCallback; + + UString fullName; + int fileNamePartStartIndex; + NFile::NDirectory::MyGetFullPathName(filePath, fullName, fileNamePartStartIndex); + openCallbackSpec->Init( + fullName.Left(fileNamePartStartIndex), + fullName.Mid(fileNamePartStartIndex)); +} + +HRESULT CArchiveLink::Open2(CCodecs *codecs, + const CIntVector &formatIndices, + bool stdInMode, + IInStream *stream, + const UString &filePath, + IOpenCallbackUI *callbackUI) +{ + VolumesSize = 0; + COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; + CMyComPtr callback = openCallbackSpec; + openCallbackSpec->Callback = callbackUI; + + UString fullName, prefix, name; + if (!stream && !stdInMode) + { + int fileNamePartStartIndex; + if (!NFile::NDirectory::MyGetFullPathName(filePath, fullName, fileNamePartStartIndex)) + return GetLastError(); + prefix = fullName.Left(fileNamePartStartIndex); + name = fullName.Mid(fileNamePartStartIndex); + openCallbackSpec->Init(prefix, name); + } + else + { + openCallbackSpec->SetSubArchiveName(filePath); + } + + RINOK(Open(codecs, formatIndices, stdInMode, stream, filePath, callback)); + VolumePaths.Add(prefix + name); + for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++) + VolumePaths.Add(prefix + openCallbackSpec->FileNames[i]); + VolumesSize = openCallbackSpec->TotalSize; + return S_OK; +} + +HRESULT CArchiveLink::ReOpen(CCodecs *codecs, const UString &filePath, + IArchiveOpenCallback *callback) +{ + if (Arcs.Size() > 1) + return E_NOTIMPL; + + if (Arcs.Size() == 0) + return Open2(codecs, CIntVector(), false, NULL, filePath, 0); + + CMyComPtr openCallbackNew; + SetCallback(filePath, NULL, callback, openCallbackNew); + + CInFileStream *fileStreamSpec = new CInFileStream; + CMyComPtr stream(fileStreamSpec); + if (!fileStreamSpec->Open(filePath)) + return GetLastError(); + HRESULT res = GetArchive()->Open(stream, &kMaxCheckStartPosition, callback); + IsOpen = (res == S_OK); + return res; +} diff --git a/CPP/7zip/UI/Common/OpenArchive.h b/CPP/7zip/UI/Common/OpenArchive.h new file mode 100755 index 0000000..18ca0ea --- /dev/null +++ b/CPP/7zip/UI/Common/OpenArchive.h @@ -0,0 +1,87 @@ +// OpenArchive.h + +#ifndef __OPEN_ARCHIVE_H +#define __OPEN_ARCHIVE_H + +#include "Common/MyString.h" + +#include "Windows/FileFind.h" + +#include "../../Archive/IArchive.h" + +#include "ArchiveOpenCallback.h" +#include "LoadCodecs.h" + +HRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result); +HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result); + +struct CArc +{ + CMyComPtr Archive; + UString Path; + UString DefaultName; + int FormatIndex; + int SubfileIndex; + FILETIME MTime; + bool MTimeDefined; + UString ErrorMessage; + + CArc(): MTimeDefined(false) {} + + HRESULT GetItemPath(UInt32 index, UString &result) const; + HRESULT GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const; + HRESULT IsItemAnti(UInt32 index, bool &result) const + { return GetArchiveItemBoolProp(Archive, index, kpidIsAnti, result); } + + HRESULT OpenStream( + CCodecs *codecs, + int formatIndex, + IInStream *stream, + ISequentialInStream *seqStream, + IArchiveOpenCallback *callback); + + HRESULT OpenStreamOrFile( + CCodecs *codecs, + int formatIndex, + bool stdInMode, + IInStream *stream, + IArchiveOpenCallback *callback); +}; + +struct CArchiveLink +{ + CObjectVector Arcs; + UStringVector VolumePaths; + UInt64 VolumesSize; + bool IsOpen; + + CArchiveLink(): VolumesSize(0), IsOpen(false) {} + HRESULT Close(); + void Release(); + ~CArchiveLink() { Release(); } + + IInArchive *GetArchive() const { return Arcs.Back().Archive; } + + HRESULT Open( + CCodecs *codecs, + const CIntVector &formatIndices, + bool stdInMode, + IInStream *stream, + const UString &filePath, + IArchiveOpenCallback *callback); + + HRESULT Open2( + CCodecs *codecs, + const CIntVector &formatIndices, + bool stdInMode, + IInStream *stream, + const UString &filePath, + IOpenCallbackUI *callbackUI); + + HRESULT ReOpen( + CCodecs *codecs, + const UString &filePath, + IArchiveOpenCallback *callback); +}; + +#endif diff --git a/CPP/7zip/UI/Common/PropIDUtils.cpp b/CPP/7zip/UI/Common/PropIDUtils.cpp new file mode 100755 index 0000000..4a9e294 --- /dev/null +++ b/CPP/7zip/UI/Common/PropIDUtils.cpp @@ -0,0 +1,120 @@ +// PropIDUtils.cpp + +#include "StdAfx.h" + +#include "Common/IntToString.h" + +#include "Windows/FileFind.h" +#include "Windows/PropVariantConversions.h" + +#include "../../PropID.h" + +#include "PropIDUtils.h" + +using namespace NWindows; + +void ConvertUInt32ToHex(UInt32 value, wchar_t *s) +{ + for (int i = 0; i < 8; i++) + { + int t = value & 0xF; + value >>= 4; + s[7 - i] = (wchar_t)((t < 10) ? (L'0' + t) : (L'A' + (t - 10))); + } + s[8] = L'\0'; +} + +static const char g_WinAttrib[17] = "RHS8DAdNTsrCOnE_"; +/* +0 READONLY +1 HIDDEN +3 SYSTEM + +4 DIRECTORY +5 ARCHIVE +6 DEVICE +7 NORMAL +8 TEMPORARY +9 SPARSE_FILE +10 REPARSE_POINT +11 COMPRESSED +12 OFFLINE +13 NOT_CONTENT_INDEXED +14 ENCRYPTED + +16 VIRTUAL +*/ + +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 : L'-'; + +UString ConvertPropertyToString(const PROPVARIANT &prop, PROPID propID, bool full) +{ + switch(propID) + { + case kpidCTime: + case kpidATime: + case kpidMTime: + { + if (prop.vt != VT_FILETIME) + break; + FILETIME localFileTime; + if ((prop.filetime.dwHighDateTime == 0 && + prop.filetime.dwLowDateTime == 0) || + !::FileTimeToLocalFileTime(&prop.filetime, &localFileTime)) + return UString(); + return ConvertFileTimeToString(localFileTime, true, full); + } + case kpidCRC: + { + if (prop.vt != VT_UI4) + break; + wchar_t temp[12]; + ConvertUInt32ToHex(prop.ulVal, temp); + return temp; + } + case kpidAttrib: + { + if (prop.vt != VT_UI4) + break; + UInt32 a = prop.ulVal; + wchar_t sz[32]; + int pos = 0; + for (int i = 0; i < 16; i++) + if (a & (1 << i) && i != 7) + sz[pos++] = g_WinAttrib[i]; + sz[pos] = '\0'; + return sz; + } + case kpidPosixAttrib: + { + if (prop.vt != VT_UI4) + break; + UString res; + UInt32 a = prop.ulVal; + wchar_t temp[16]; + + temp[0] = kPosixTypes[(a >> 12) & 0xF]; + for (int i = 6; i >= 0; i -= 3) + { + temp[7 - i] = MY_ATTR_CHAR(a, i + 2, L'r'); + temp[8 - i] = MY_ATTR_CHAR(a, i + 1, L'w'); + temp[9 - i] = MY_ATTR_CHAR(a, i + 0, L'x'); + } + if ((a & 0x800) != 0) temp[3] = ((a & (1 << 6)) ? 's' : 'S'); + if ((a & 0x400) != 0) temp[6] = ((a & (1 << 3)) ? 's' : 'S'); + if ((a & 0x200) != 0) temp[9] = ((a & (1 << 0)) ? 't' : 'T'); + temp[10] = 0; + res = temp; + + a &= ~(UInt32)0xFFFF; + if (a != 0) + { + ConvertUInt32ToHex(a, temp); + res = UString(temp) + L' ' + res; + } + return res; + } + } + return ConvertPropVariantToString(prop); +} diff --git a/CPP/7zip/UI/Common/PropIDUtils.h b/CPP/7zip/UI/Common/PropIDUtils.h new file mode 100755 index 0000000..05c09e7 --- /dev/null +++ b/CPP/7zip/UI/Common/PropIDUtils.h @@ -0,0 +1,12 @@ +// PropIDUtils.h + +#ifndef __PROPID_UTILS_H +#define __PROPID_UTILS_H + +#include "Common/MyString.h" +#include "Common/Types.h" + +void ConvertUInt32ToHex(UInt32 value, wchar_t *s); +UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full = true); + +#endif diff --git a/CPP/7zip/UI/Common/Property.h b/CPP/7zip/UI/Common/Property.h new file mode 100755 index 0000000..5253d52 --- /dev/null +++ b/CPP/7zip/UI/Common/Property.h @@ -0,0 +1,14 @@ +// Property.h + +#ifndef __PROPERTY_H +#define __PROPERTY_H + +#include "Common/MyString.h" + +struct CProperty +{ + UString Name; + UString Value; +}; + +#endif diff --git a/CPP/7zip/UI/Common/SetProperties.cpp b/CPP/7zip/UI/Common/SetProperties.cpp new file mode 100755 index 0000000..b3347ce --- /dev/null +++ b/CPP/7zip/UI/Common/SetProperties.cpp @@ -0,0 +1,79 @@ +// SetProperties.cpp + +#include "StdAfx.h" + +#include "SetProperties.h" + +#include "Windows/PropVariant.h" +#include "Common/MyString.h" +#include "Common/StringToInt.h" +#include "Common/MyCom.h" + +#include "../../Archive/IArchive.h" + +using namespace NWindows; +using namespace NCOM; + +static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop) +{ + const wchar_t *endPtr; + UInt64 result = ConvertStringToUInt64(s, &endPtr); + if (endPtr - (const wchar_t *)s != s.Length()) + prop = s; + else if (result <= 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 + { + int 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[name.Length() - 1]; + if (c == L'-') + propVariant = false; + else if (c == L'+') + propVariant = true; + if (propVariant.vt != VT_EMPTY) + name = name.Left(name.Length() - 1); + } + } + 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/CPP/7zip/UI/Common/SetProperties.h b/CPP/7zip/UI/Common/SetProperties.h new file mode 100755 index 0000000..64c947c --- /dev/null +++ b/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/CPP/7zip/UI/Common/SortUtils.cpp b/CPP/7zip/UI/Common/SortUtils.cpp new file mode 100755 index 0000000..039adfa --- /dev/null +++ b/CPP/7zip/UI/Common/SortUtils.cpp @@ -0,0 +1,22 @@ +// SortUtils.cpp + +#include "StdAfx.h" + +#include "SortUtils.h" +#include "Common/Wildcard.h" + +static int CompareStrings(const int *p1, const int *p2, void *param) +{ + const UStringVector &strings = *(const UStringVector *)param; + return CompareFileNames(strings[*p1], strings[*p2]); +} + +void SortFileNames(const UStringVector &strings, CIntVector &indices) +{ + indices.Clear(); + int numItems = strings.Size(); + indices.Reserve(numItems); + for(int i = 0; i < numItems; i++) + indices.Add(i); + indices.Sort(CompareStrings, (void *)&strings); +} diff --git a/CPP/7zip/UI/Common/SortUtils.h b/CPP/7zip/UI/Common/SortUtils.h new file mode 100755 index 0000000..4835f11 --- /dev/null +++ b/CPP/7zip/UI/Common/SortUtils.h @@ -0,0 +1,10 @@ +// SortUtils.h + +#ifndef __SORTUTLS_H +#define __SORTUTLS_H + +#include "Common/MyString.h" + +void SortFileNames(const UStringVector &strings, CIntVector &indices); + +#endif diff --git a/CPP/7zip/UI/Common/StdAfx.h b/CPP/7zip/UI/Common/StdAfx.h new file mode 100755 index 0000000..ab2617e --- /dev/null +++ b/CPP/7zip/UI/Common/StdAfx.h @@ -0,0 +1,9 @@ +// stdafx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" +#include "../../../Common/NewHandler.h" + +#endif diff --git a/CPP/7zip/UI/Common/TempFiles.cpp b/CPP/7zip/UI/Common/TempFiles.cpp new file mode 100755 index 0000000..48fb4e7 --- /dev/null +++ b/CPP/7zip/UI/Common/TempFiles.cpp @@ -0,0 +1,22 @@ +// TempFiles.cpp + +#include "StdAfx.h" + +#include "TempFiles.h" + +#include "Windows/FileDir.h" +#include "Windows/FileIO.h" + +using namespace NWindows; +using namespace NFile; + +void CTempFiles::Clear() +{ + while(!Paths.IsEmpty()) + { + NDirectory::DeleteFileAlways((LPCWSTR)Paths.Back()); + Paths.DeleteBack(); + } +} + + diff --git a/CPP/7zip/UI/Common/TempFiles.h b/CPP/7zip/UI/Common/TempFiles.h new file mode 100755 index 0000000..9e8e131 --- /dev/null +++ b/CPP/7zip/UI/Common/TempFiles.h @@ -0,0 +1,16 @@ +// TempFiles.h + +#ifndef __TEMPFILES_H +#define __TEMPFILES_H + +#include "Common/MyString.h" + +class CTempFiles +{ + void Clear(); +public: + UStringVector Paths; + ~CTempFiles() { Clear(); } +}; + +#endif diff --git a/CPP/7zip/UI/Common/Update.cpp b/CPP/7zip/UI/Common/Update.cpp new file mode 100755 index 0000000..2e1cca0 --- /dev/null +++ b/CPP/7zip/UI/Common/Update.cpp @@ -0,0 +1,910 @@ +// Update.cpp + +#include "StdAfx.h" + +#include "Update.h" + +#include "Common/IntToString.h" +#include "Common/StringConvert.h" + +#ifdef _WIN32 +#include "Windows/DLL.h" +#endif + +#include "Windows/FileDir.h" +#include "Windows/FileFind.h" +#include "Windows/FileName.h" +#include "Windows/PropVariant.h" +#include "Windows/PropVariantConversions.h" +#include "Windows/Time.h" + +#include "../../Common/FileStreams.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 *kUpdateIsNotSupoorted = + "update operations are not supported for this archive"; + +using namespace NWindows; +using namespace NCOM; +using namespace NFile; +using namespace NName; + +static const wchar_t *kTempFolderPrefix = L"7zE"; + +using namespace NUpdateArchive; + +class COutMultiVolStream: + public IOutStream, + public CMyUnknownImp +{ + int _streamIndex; // required stream + UInt64 _offsetPos; // offset from start of _streamIndex index + UInt64 _absPos; + UInt64 _length; + + struct CSubStreamInfo + { + COutFileStream *StreamSpec; + CMyComPtr Stream; + UString Name; + UInt64 Pos; + UInt64 RealSize; + }; + CObjectVector Streams; +public: + // CMyComPtr VolumeCallback; + CRecordVector Sizes; + UString Prefix; + CTempFiles *TempFiles; + + void Init() + { + _streamIndex = 0; + _offsetPos = 0; + _absPos = 0; + _length = 0; + } + + HRESULT Close(); + + 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 (int i = 0; i < Streams.Size(); i++) + { + CSubStreamInfo &s = Streams[i]; + if (s.StreamSpec) + { + HRESULT res2 = s.StreamSpec->Close(); + if (res2 != S_OK) + res = res2; + } + } + return res; +} + +STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != NULL) + *processedSize = 0; + while(size > 0) + { + if (_streamIndex >= Streams.Size()) + { + CSubStreamInfo subStream; + + wchar_t temp[16]; + ConvertUInt32ToString(_streamIndex + 1, temp); + UString res = temp; + while (res.Length() < 3) + res = UString(L'0') + res; + UString name = Prefix + res; + subStream.StreamSpec = new COutFileStream; + subStream.Stream = subStream.StreamSpec; + if (!subStream.StreamSpec->Create(name, false)) + return ::GetLastError(); + { + // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS); + TempFiles->Paths.Add(name); + } + + subStream.Pos = 0; + subStream.RealSize = 0; + subStream.Name = name; + Streams.Add(subStream); + continue; + } + CSubStreamInfo &subStream = Streams[_streamIndex]; + + int index = _streamIndex; + if (index >= Sizes.Size()) + index = Sizes.Size() - 1; + UInt64 volSize = Sizes[index]; + + if (_offsetPos >= volSize) + { + _offsetPos -= volSize; + _streamIndex++; + continue; + } + if (_offsetPos != subStream.Pos) + { + // CMyComPtr outStream; + // RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream)); + RINOK(subStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); + subStream.Pos = _offsetPos; + } + + UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - 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 (_offsetPos > subStream.RealSize) + subStream.RealSize = _offsetPos; + if (processedSize != NULL) + *processedSize += realProcessed; + if (subStream.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 != NULL) + *newPosition = _absPos; + _streamIndex = 0; + return S_OK; +} + +STDMETHODIMP COutMultiVolStream::SetSize(UInt64 newSize) +{ + if (newSize < 0) + return E_INVALIDARG; + int i = 0; + while (i < Streams.Size()) + { + CSubStreamInfo &subStream = Streams[i++]; + if ((UInt64)newSize < subStream.RealSize) + { + RINOK(subStream.Stream->SetSize(newSize)); + subStream.RealSize = newSize; + break; + } + newSize -= subStream.RealSize; + } + while (i < Streams.Size()) + { + { + CSubStreamInfo &subStream = Streams.Back(); + subStream.Stream.Release(); + NDirectory::DeleteFileAlways(subStream.Name); + } + Streams.DeleteBack(); + } + _offsetPos = _absPos; + _streamIndex = 0; + _length = newSize; + return S_OK; +} + +static const wchar_t *kDefaultArchiveType = L"7z"; +static const wchar_t *kSFXExtension = + #ifdef _WIN32 + L"exe"; + #else + L""; + #endif + +bool CUpdateOptions::Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath) +{ + if (formatIndices.Size() > 1) + return false; + int arcTypeIndex = -1; + if (formatIndices.Size() != 0) + arcTypeIndex = formatIndices[0]; + if (arcTypeIndex >= 0) + MethodMode.FormatIndex = arcTypeIndex; + else + { + MethodMode.FormatIndex = codecs->FindFormatForArchiveName(arcPath); + // It works incorrectly for update command if archive has some non-default extension! + if (MethodMode.FormatIndex < 0) + MethodMode.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArchiveType); + } + if (MethodMode.FormatIndex < 0) + return false; + const CArcInfoEx &arcInfo = codecs->Formats[MethodMode.FormatIndex]; + if (!arcInfo.UpdateEnabled) + return false; + UString typeExt = arcInfo.GetMainExt(); + UString ext = typeExt; + if (SfxMode) + ext = kSFXExtension; + ArchivePath.BaseExtension = ext; + ArchivePath.VolExtension = typeExt; + ArchivePath.ParseFromPath(arcPath); + for (int i = 0; i < Commands.Size(); i++) + { + CUpdateArchiveCommand &uc = Commands[i]; + uc.ArchivePath.BaseExtension = ext; + uc.ArchivePath.VolExtension = typeExt; + uc.ArchivePath.ParseFromPath(uc.UserArchivePath); + } + return true; +} + +/* +struct CUpdateProduceCallbackImp: public IUpdateProduceCallback +{ + const CObjectVector *_arcItems; + IUpdateCallbackUI *_callback; + + CUpdateProduceCallbackImp(const CObjectVector *a, + IUpdateCallbackUI *callback): _arcItems(a), _callback(callback) {} + virtual HRESULT ShowDeleteFile(int arcIndex); +}; + +HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(int arcIndex) +{ + return _callback->ShowDeleteFile((*_arcItems)[arcIndex].Name); +} +*/ + +static HRESULT Compress( + CCodecs *codecs, + const CActionSet &actionSet, + IInArchive *archive, + const CCompressionMethodMode &compressionMethod, + CArchivePath &archivePath, + const CObjectVector &arcItems, + bool shareForWrite, + bool stdInMode, + /* const UString & stdInFileName, */ + bool stdOutMode, + const CDirItems &dirItems, + bool sfxMode, + const UString &sfxModule, + const CRecordVector &volumesSizes, + CTempFiles &tempFiles, + CUpdateErrorInfo &errorInfo, + IUpdateCallbackUI *callback) +{ + CMyComPtr outArchive; + if (archive != NULL) + { + CMyComPtr archive2 = archive; + HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive); + if (result != S_OK) + throw kUpdateIsNotSupoorted; + } + else + { + RINOK(codecs->CreateOutArchive(compressionMethod.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; + } + + CRecordVector updatePairs2; + + { + CRecordVector updatePairs; + GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // must be done only once!!! + // CUpdateProduceCallbackImp upCallback(&arcItems, callback); + UpdateProduce(updatePairs, actionSet, updatePairs2, NULL /* &upCallback */); + } + + UInt32 numFiles = 0; + for (int i = 0; i < updatePairs2.Size(); i++) + if (updatePairs2[i].NewData) + numFiles++; + + RINOK(callback->SetNumFiles(numFiles)); + + + CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; + CMyComPtr updateCallback(updateCallbackSpec); + + updateCallbackSpec->ShareForWrite = shareForWrite; + updateCallbackSpec->StdInMode = stdInMode; + updateCallbackSpec->Callback = callback; + updateCallbackSpec->DirItems = &dirItems; + updateCallbackSpec->ArcItems = &arcItems; + updateCallbackSpec->UpdatePairs = &updatePairs2; + + CMyComPtr outStream; + + if (!stdOutMode) + { + UString resultPath; + int pos; + if (!NFile::NDirectory::MyGetFullPathName(archivePath.GetFinalPath(), resultPath, pos)) + throw 1417161; + NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos)); + } + + COutFileStream *outStreamSpec = NULL; + COutMultiVolStream *volStreamSpec = NULL; + + if (volumesSizes.Size() == 0) + { + if (stdOutMode) + outStream = new CStdOutFileStream; + else + { + outStreamSpec = new COutFileStream; + outStream = outStreamSpec; + bool isOK = false; + UString realPath; + for (int i = 0; i < (1 << 16); i++) + { + if (archivePath.Temp) + { + if (i > 0) + { + wchar_t s[16]; + ConvertUInt32ToString(i, s); + archivePath.TempPostfix = s; + } + realPath = archivePath.GetTempPath(); + } + else + realPath = 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) + { + errorInfo.SystemError = ::GetLastError(); + errorInfo.FileName = realPath; + errorInfo.Message = L"7-Zip cannot open file"; + return E_FAIL; + } + } + } + else + { + if (stdOutMode) + return E_FAIL; + volStreamSpec = new COutMultiVolStream; + outStream = volStreamSpec; + volStreamSpec->Sizes = volumesSizes; + volStreamSpec->Prefix = archivePath.GetFinalPath() + UString(L"."); + volStreamSpec->TempFiles = &tempFiles; + volStreamSpec->Init(); + + /* + updateCallbackSpec->VolumesSizes = volumesSizes; + updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name; + if (!archivePath.VolExtension.IsEmpty()) + updateCallbackSpec->VolExt = UString(L'.') + archivePath.VolExtension; + */ + } + + RINOK(SetProperties(outArchive, compressionMethod.Properties)); + + if (sfxMode) + { + CInFileStream *sfxStreamSpec = new CInFileStream; + CMyComPtr sfxStream(sfxStreamSpec); + if (!sfxStreamSpec->Open(sfxModule)) + { + errorInfo.SystemError = ::GetLastError(); + errorInfo.Message = L"7-Zip cannot open SFX module"; + errorInfo.FileName = sfxModule; + return E_FAIL; + } + + CMyComPtr sfxOutStream; + COutFileStream *outStreamSpec = NULL; + if (volumesSizes.Size() == 0) + sfxOutStream = outStream; + else + { + outStreamSpec = new COutFileStream; + sfxOutStream = outStreamSpec; + UString realPath = archivePath.GetFinalPath(); + if (!outStreamSpec->Create(realPath, false)) + { + errorInfo.SystemError = ::GetLastError(); + errorInfo.FileName = realPath; + errorInfo.Message = L"7-Zip cannot open file"; + return E_FAIL; + } + } + RINOK(NCompress::CopyStream(sfxStream, sfxOutStream, NULL)); + if (outStreamSpec) + { + RINOK(outStreamSpec->Close()); + } + } + + HRESULT result = outArchive->UpdateItems(outStream, updatePairs2.Size(), updateCallback); + callback->Finilize(); + RINOK(result); + if (outStreamSpec) + result = outStreamSpec->Close(); + else if (volStreamSpec) + result = volStreamSpec->Close(); + return result; +} + +HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor, + const CArc &arc, + CObjectVector &arcItems) +{ + arcItems.Clear(); + UInt32 numItems; + IInArchive *archive = arc.Archive; + RINOK(archive->GetNumberOfItems(&numItems)); + arcItems.Reserve(numItems); + for (UInt32 i = 0; i < numItems; i++) + { + CArcItem ai; + + RINOK(arc.GetItemPath(i, ai.Name)); + RINOK(IsArchiveItemFolder(archive, i, ai.IsDir)); + ai.Censored = censor.CheckPath(ai.Name, !ai.IsDir); + RINOK(arc.GetItemMTime(i, ai.MTime, ai.MTimeDefined)); + + { + CPropVariant prop; + RINOK(archive->GetProperty(i, kpidSize, &prop)); + ai.SizeDefined = (prop.vt != VT_EMPTY); + if (ai.SizeDefined) + ai.Size = ConvertPropVariantToUInt64(prop); + } + + { + 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.Add(ai); + } + return S_OK; +} + + +static HRESULT UpdateWithItemLists( + CCodecs *codecs, + CUpdateOptions &options, + IInArchive *archive, + const CObjectVector &arcItems, + CDirItems &dirItems, + CTempFiles &tempFiles, + CUpdateErrorInfo &errorInfo, + IUpdateCallbackUI2 *callback) +{ + for(int i = 0; i < options.Commands.Size(); i++) + { + CUpdateArchiveCommand &command = options.Commands[i]; + if (options.StdOutMode) + { + RINOK(callback->StartArchive(L"stdout", archive != 0)); + } + else + { + RINOK(callback->StartArchive(command.ArchivePath.GetFinalPath(), + i == 0 && options.UpdateArchiveItself && archive != 0)); + } + + RINOK(Compress( + codecs, + command.ActionSet, archive, + options.MethodMode, + command.ArchivePath, + arcItems, + options.OpenShareForWrite, + options.StdInMode, + /* options.StdInFileName, */ + options.StdOutMode, + dirItems, + options.SfxMode, options.SfxModule, + options.VolumesSizes, + tempFiles, + errorInfo, callback)); + + RINOK(callback->FinishArchive()); + } + return S_OK; +} + +#if defined(_WIN32) && !defined(UNDER_CE) +class CCurrentDirRestorer +{ + UString _path; +public: + CCurrentDirRestorer() { NFile::NDirectory::MyGetCurrentDirectory(_path); } + ~CCurrentDirRestorer() { RestoreDirectory();} + bool RestoreDirectory() { return BOOLToBool(NFile::NDirectory::MySetCurrentDirectory(_path)); } +}; +#endif + +struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback +{ + IUpdateCallbackUI2 *Callback; + HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) + { + return Callback->ScanProgress(numFolders, numFiles, path); + } +}; + +#ifdef _WIN32 +typedef ULONG (FAR PASCAL MY_MAPISENDDOCUMENTS)( + ULONG_PTR ulUIParam, + LPSTR lpszDelimChar, + LPSTR lpszFilePaths, + LPSTR lpszFileNames, + ULONG ulReserved +); +typedef MY_MAPISENDDOCUMENTS FAR *MY_LPMAPISENDDOCUMENTS; +#endif + +HRESULT UpdateArchive( + CCodecs *codecs, + const NWildcard::CCensor &censor, + CUpdateOptions &options, + CUpdateErrorInfo &errorInfo, + IOpenCallbackUI *openCallback, + IUpdateCallbackUI2 *callback) +{ + if (options.StdOutMode && options.EMailMode) + return E_FAIL; + + if (options.VolumesSizes.Size() > 0 && (options.EMailMode || options.SfxMode)) + return E_NOTIMPL; + + if (options.SfxMode) + { + CProperty property; + property.Name = L"rsfx"; + property.Value = L"on"; + options.MethodMode.Properties.Add(property); + if (options.SfxModule.IsEmpty()) + { + errorInfo.Message = L"SFX file is not specified"; + return E_FAIL; + } + UString name = options.SfxModule; + #ifdef UNDER_CE + if (!NFind::DoesFileExist(name)) + #else + if (!NDirectory::MySearchPath(NULL, name, NULL, options.SfxModule)) + #endif + { + errorInfo.SystemError = ::GetLastError(); + errorInfo.Message = L"7-Zip cannot find specified SFX module"; + errorInfo.FileName = name; + return E_FAIL; + } + } + + + CArchiveLink arcLink; + const UString arcPath = options.ArchivePath.GetFinalPath(); + + if (!options.ArchivePath.OriginalPath.IsEmpty()) + { + NFind::CFileInfoW fi; + if (fi.Find(arcPath)) + { + if (fi.IsDir()) + throw "there is no such archive"; + if (options.VolumesSizes.Size() > 0) + return E_NOTIMPL; + CIntVector formatIndices; + if (options.MethodMode.FormatIndex >= 0) + formatIndices.Add(options.MethodMode.FormatIndex); + HRESULT result = arcLink.Open2(codecs, formatIndices, false, NULL, arcPath, openCallback); + if (result == E_ABORT) + return result; + RINOK(callback->OpenResult(arcPath, result)); + RINOK(result); + if (arcLink.VolumePaths.Size() > 1) + { + errorInfo.SystemError = (DWORD)E_NOTIMPL; + errorInfo.Message = L"Updating for multivolume archives is not implemented"; + return E_NOTIMPL; + } + + CArc &arc = arcLink.Arcs.Back(); + arc.MTimeDefined = !fi.IsDevice; + arc.MTime = fi.MTime; + } + } + else + { + /* + if (archiveType.IsEmpty()) + throw "type of archive is not specified"; + */ + } + + CDirItems dirItems; + 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; + for(int i = 0; i < options.Commands.Size(); i++) + if (options.Commands[i].ActionSet.NeedScanning()) + needScanning = true; + if (needScanning) + { + CEnumDirItemUpdateCallback enumCallback; + enumCallback.Callback = callback; + RINOK(callback->StartScanning()); + UStringVector errorPaths; + CRecordVector errorCodes; + HRESULT res = EnumerateItems(censor, dirItems, &enumCallback, errorPaths, errorCodes); + for (int i = 0; i < errorPaths.Size(); i++) + { + RINOK(callback->CanNotFindError(errorPaths[i], errorCodes[i])); + } + if (res != S_OK) + { + if (res != E_ABORT) + errorInfo.Message = L"Scanning error"; + return res; + } + RINOK(callback->FinishScanning()); + } + } + + UString tempDirPrefix; + bool usesTempDir = false; + + #ifdef _WIN32 + NDirectory::CTempDirectoryW tempDirectory; + if (options.EMailMode && options.EMailRemoveAfter) + { + tempDirectory.Create(kTempFolderPrefix); + tempDirPrefix = tempDirectory.GetPath(); + NormalizeDirPathPrefix(tempDirPrefix); + usesTempDir = true; + } + #endif + + CTempFiles tempFiles; + + bool createTempFile = false; + + bool thereIsInArchive = arcLink.IsOpen; + + 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; + NormalizeDirPathPrefix(ap.TempPrefix); + } + } + } + + for(int i = 0; i < options.Commands.Size(); i++) + { + CArchivePath &ap = options.Commands[i].ArchivePath; + if (usesTempDir) + { + // Check it + ap.Prefix = tempDirPrefix; + // ap.Temp = true; + // ap.TempPrefix = tempDirPrefix; + } + if (!options.StdOutMode && + (i > 0 || !createTempFile)) + { + const UString &path = ap.GetFinalPath(); + if (NFind::DoesFileOrDirExist(path)) + { + errorInfo.SystemError = 0; + errorInfo.Message = L"The file already exists"; + errorInfo.FileName = path; + return E_FAIL; + } + } + } + + CObjectVector arcItems; + if (thereIsInArchive) + { + RINOK(EnumerateInArchiveItems(censor, arcLink.Arcs.Back(), arcItems)); + } + + RINOK(UpdateWithItemLists(codecs, options, + thereIsInArchive ? arcLink.GetArchive() : 0, + arcItems, dirItems, + tempFiles, errorInfo, callback)); + + if (thereIsInArchive) + { + RINOK(arcLink.Close()); + arcLink.Release(); + } + + tempFiles.Paths.Clear(); + if (createTempFile) + { + try + { + CArchivePath &ap = options.Commands[0].ArchivePath; + const UString &tempPath = ap.GetTempPath(); + if (thereIsInArchive) + if (!NDirectory::DeleteFileAlways(arcPath)) + { + errorInfo.SystemError = ::GetLastError(); + errorInfo.Message = L"7-Zip cannot delete the file"; + errorInfo.FileName = arcPath; + return E_FAIL; + } + if (!NDirectory::MyMoveFile(tempPath, arcPath)) + { + errorInfo.SystemError = ::GetLastError(); + errorInfo.Message = L"7-Zip cannot move the file"; + errorInfo.FileName = tempPath; + errorInfo.FileName2 = arcPath; + return E_FAIL; + } + } + catch(...) + { + throw; + } + } + + #if defined(_WIN32) && !defined(UNDER_CE) + if (options.EMailMode) + { + NDLL::CLibrary mapiLib; + if (!mapiLib.Load(TEXT("Mapi32.dll"))) + { + errorInfo.SystemError = ::GetLastError(); + errorInfo.Message = L"7-Zip cannot load Mapi32.dll"; + return E_FAIL; + } + MY_LPMAPISENDDOCUMENTS fnSend = (MY_LPMAPISENDDOCUMENTS)mapiLib.GetProc("MAPISendDocuments"); + if (fnSend == 0) + { + errorInfo.SystemError = ::GetLastError(); + errorInfo.Message = L"7-Zip cannot find MAPISendDocuments function"; + return E_FAIL; + } + UStringVector fullPaths; + int i; + for(i = 0; i < options.Commands.Size(); i++) + { + CArchivePath &ap = options.Commands[i].ArchivePath; + UString arcPath; + if (!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath)) + { + errorInfo.SystemError = ::GetLastError(); + errorInfo.Message = L"GetFullPathName error"; + return E_FAIL; + } + fullPaths.Add(arcPath); + } + CCurrentDirRestorer curDirRestorer; + for(i = 0; i < fullPaths.Size(); i++) + { + UString arcPath = fullPaths[i]; + UString fileName = ExtractFileNameFromPath(arcPath); + AString path = GetAnsiString(arcPath); + AString name = GetAnsiString(fileName); + // Warning!!! MAPISendDocuments function changes Current directory + fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0); + } + } + #endif + return S_OK; +} diff --git a/CPP/7zip/UI/Common/Update.h b/CPP/7zip/UI/Common/Update.h new file mode 100755 index 0000000..6bc85b5 --- /dev/null +++ b/CPP/7zip/UI/Common/Update.h @@ -0,0 +1,175 @@ +// Update.h + +#ifndef __COMMON_UPDATE_H +#define __COMMON_UPDATE_H + +#include "Common/Wildcard.h" + +#include "ArchiveOpenCallback.h" +#include "LoadCodecs.h" +#include "Property.h" +#include "UpdateAction.h" +#include "UpdateCallback.h" + +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; + UString TempPrefix; // path(folder) for temp location + UString TempPostfix; + + CArchivePath(): Temp(false) {}; + + void ParseFromPath(const UString &path) + { + OriginalPath = path; + + SplitPathToParts(path, Prefix, Name); + int dotPos = Name.ReverseFind(L'.'); + if (dotPos < 0) + return; + if (dotPos == Name.Length() - 1) + { + Name = Name.Left(dotPos); + BaseExtension.Empty(); + return; + } + if (BaseExtension.CompareNoCase(Name.Mid(dotPos + 1)) == 0) + { + BaseExtension = Name.Mid(dotPos + 1); + Name = Name.Left(dotPos); + } + else + BaseExtension.Empty(); + } + + UString GetPathWithoutExt() const + { + return Prefix + Name; + } + + UString GetFinalPath() const + { + UString path = GetPathWithoutExt(); + if (!BaseExtension.IsEmpty()) + path += UString(L'.') + BaseExtension; + return path; + } + + + UString GetTempPath() const + { + UString path = TempPrefix + Name; + if (!BaseExtension.IsEmpty()) + path += UString(L'.') + BaseExtension; + path += L".tmp"; + path += TempPostfix; + return path; + } +}; + +struct CUpdateArchiveCommand +{ + UString UserArchivePath; + CArchivePath ArchivePath; + NUpdateArchive::CActionSet ActionSet; +}; + +struct CCompressionMethodMode +{ + int FormatIndex; + CObjectVector Properties; + CCompressionMethodMode(): FormatIndex(-1) {} +}; + +struct CUpdateOptions +{ + CCompressionMethodMode MethodMode; + + CObjectVector Commands; + bool UpdateArchiveItself; + CArchivePath ArchivePath; + + bool SfxMode; + UString SfxModule; + + bool OpenShareForWrite; + + bool StdInMode; + UString StdInFileName; + bool StdOutMode; + + bool EMailMode; + bool EMailRemoveAfter; + UString EMailAddress; + + UString WorkingDir; + + bool Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath); + + CUpdateOptions(): + UpdateArchiveItself(true), + SfxMode(false), + StdInMode(false), + StdOutMode(false), + EMailMode(false), + EMailRemoveAfter(false), + OpenShareForWrite(false) + {}; + + void SetAddActionCommand() + { + Commands.Clear(); + CUpdateArchiveCommand c; + c.ActionSet = NUpdateArchive::kAddActionSet; + Commands.Add(c); + } + + CRecordVector VolumesSizes; +}; + +struct CErrorInfo +{ + DWORD SystemError; + UString FileName; + UString FileName2; + UString Message; + // UStringVector ErrorPaths; + // CRecordVector ErrorCodes; + CErrorInfo(): SystemError(0) {}; +}; + +struct CUpdateErrorInfo: public CErrorInfo +{ +}; + +#define INTERFACE_IUpdateCallbackUI2(x) \ + INTERFACE_IUpdateCallbackUI(x) \ + virtual HRESULT OpenResult(const wchar_t *name, HRESULT result) x; \ + virtual HRESULT StartScanning() x; \ + virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) x; \ + virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) x; \ + virtual HRESULT FinishScanning() x; \ + virtual HRESULT StartArchive(const wchar_t *name, bool updating) x; \ + virtual HRESULT FinishArchive() x; \ + +struct IUpdateCallbackUI2: public IUpdateCallbackUI +{ + INTERFACE_IUpdateCallbackUI2(=0) +}; + +HRESULT UpdateArchive( + CCodecs *codecs, + const NWildcard::CCensor &censor, + CUpdateOptions &options, + CUpdateErrorInfo &errorInfo, + IOpenCallbackUI *openCallback, + IUpdateCallbackUI2 *callback); + +#endif diff --git a/CPP/7zip/UI/Common/UpdateAction.cpp b/CPP/7zip/UI/Common/UpdateAction.cpp new file mode 100755 index 0000000..2e3dd62 --- /dev/null +++ b/CPP/7zip/UI/Common/UpdateAction.cpp @@ -0,0 +1,64 @@ +// UpdateAction.cpp + +#include "StdAfx.h" + +#include "UpdateAction.h" + +namespace NUpdateArchive { + +const CActionSet kAddActionSet = +{{ + NPairAction::kCopy, + NPairAction::kCopy, + NPairAction::kCompress, + NPairAction::kCompress, + NPairAction::kCompress, + NPairAction::kCompress, + NPairAction::kCompress +}}; + +const CActionSet kUpdateActionSet = +{{ + NPairAction::kCopy, + NPairAction::kCopy, + NPairAction::kCompress, + NPairAction::kCopy, + NPairAction::kCompress, + NPairAction::kCopy, + NPairAction::kCompress +}}; + +const CActionSet kFreshActionSet = +{{ + NPairAction::kCopy, + NPairAction::kCopy, + NPairAction::kIgnore, + NPairAction::kCopy, + NPairAction::kCompress, + NPairAction::kCopy, + NPairAction::kCompress +}}; + +const CActionSet kSynchronizeActionSet = +{{ + NPairAction::kCopy, + NPairAction::kIgnore, + NPairAction::kCompress, + NPairAction::kCopy, + NPairAction::kCompress, + NPairAction::kCopy, + NPairAction::kCompress, +}}; + +const CActionSet kDeleteActionSet = +{{ + NPairAction::kCopy, + NPairAction::kIgnore, + NPairAction::kIgnore, + NPairAction::kIgnore, + NPairAction::kIgnore, + NPairAction::kIgnore, + NPairAction::kIgnore +}}; + +} diff --git a/CPP/7zip/UI/Common/UpdateAction.h b/CPP/7zip/UI/Common/UpdateAction.h new file mode 100755 index 0000000..7ad57ce --- /dev/null +++ b/CPP/7zip/UI/Common/UpdateAction.h @@ -0,0 +1,57 @@ +// UpdateAction.h + +#ifndef __UPDATE_ACTION_H +#define __UPDATE_ACTION_H + +namespace NUpdateArchive { + + namespace NPairState + { + const int 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 NeedScanning() const + { + int 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 kAddActionSet; + extern const CActionSet kUpdateActionSet; + extern const CActionSet kFreshActionSet; + extern const CActionSet kSynchronizeActionSet; + extern const CActionSet kDeleteActionSet; +} + +#endif diff --git a/CPP/7zip/UI/Common/UpdateCallback.cpp b/CPP/7zip/UI/Common/UpdateCallback.cpp new file mode 100755 index 0000000..55c9374 --- /dev/null +++ b/CPP/7zip/UI/Common/UpdateCallback.cpp @@ -0,0 +1,249 @@ +// UpdateCallback.cpp + +#include "StdAfx.h" + +#include "Common/ComTry.h" +#include "Common/Defs.h" +#include "Common/IntToString.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" + +#include "../../Common/FileStreams.h" + +#include "UpdateCallback.h" + +using namespace NWindows; + +CArchiveUpdateCallback::CArchiveUpdateCallback(): + Callback(0), + ShareForWrite(false), + StdInMode(false), + DirItems(0), + ArcItems(0), + UpdatePairs(0), + NewNames(0) + {} + + +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 +} + + +/* +STATPROPSTG kProperties[] = +{ + { 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(kProperties, sizeof(kProperties) / sizeof(kProperties[0]), 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 != NULL) *newData = BoolToInt(up.NewData); + if (newProps != NULL) *newProps = BoolToInt(up.NewProps); + if (indexInArchive != NULL) + { + *indexInArchive = (UInt32)-1; + if (up.ExistInArchive()) + *indexInArchive = (ArcItems == 0) ? up.ArcIndex : (*ArcItems)[up.ArcIndex].IndexInServer; + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + const CUpdatePair2 &up = (*UpdatePairs)[index]; + NWindows::NCOM::CPropVariant prop; + + if (propID == kpidIsAnti) + { + prop = up.IsAnti; + prop.Detach(value); + return S_OK; + } + + if (up.IsAnti) + { + switch(propID) + { + case kpidIsDir: + case kpidPath: + break; + case kpidSize: + prop = (UInt64)0; + prop.Detach(value); + return S_OK; + default: + prop.Detach(value); + return S_OK; + } + } + + 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.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; + } + } + else + { + if (propID == kpidPath) + { + if (up.NewNameIndex >= 0) + { + prop = (*NewNames)[up.NewNameIndex]; + prop.Detach(value); + return S_OK; + } + } + if (up.ExistInArchive() && Archive) + { + UInt32 indexInArchive; + if (ArcItems == 0) + indexInArchive = up.ArcIndex; + else + indexInArchive = (*ArcItems)[up.ArcIndex].IndexInServer; + return Archive->GetProperty(indexInArchive, propID, value); + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) +{ + COM_TRY_BEGIN + const CUpdatePair2 &up = (*UpdatePairs)[index]; + if (!up.NewData) + return E_FAIL; + + RINOK(Callback->CheckBreak()); + RINOK(Callback->Finilize()); + + if (up.IsAnti) + { + return Callback->GetStream((*ArcItems)[up.ArcIndex].Name, true); + } + const CDirItem &di = DirItems->Items[up.DirIndex]; + RINOK(Callback->GetStream(DirItems->GetLogPath(up.DirIndex), false)); + + if (di.IsDir()) + return S_OK; + + if (StdInMode) + { + CStdInFileStream *inStreamSpec = new CStdInFileStream; + CMyComPtr inStreamLoc(inStreamSpec); + *inStream = inStreamLoc.Detach(); + } + else + { + CInFileStream *inStreamSpec = new CInFileStream; + CMyComPtr inStreamLoc(inStreamSpec); + const UString path = DirItems->GetPhyPath(up.DirIndex); + if (!inStreamSpec->OpenShared(path, ShareForWrite)) + { + return Callback->OpenFileError(path, ::GetLastError()); + } + *inStream = inStreamLoc.Detach(); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 operationResult) +{ + COM_TRY_BEGIN + return Callback->SetOperationResult(operationResult); + 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 + wchar_t temp[16]; + ConvertUInt32ToString(index + 1, temp); + UString res = temp; + while (res.Length() < 2) + res = UString(L'0') + res; + UString fileName = VolName; + fileName += L'.'; + 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 +} diff --git a/CPP/7zip/UI/Common/UpdateCallback.h b/CPP/7zip/UI/Common/UpdateCallback.h new file mode 100755 index 0000000..2785ee9 --- /dev/null +++ b/CPP/7zip/UI/Common/UpdateCallback.h @@ -0,0 +1,74 @@ +// UpdateCallback.h + +#ifndef __UPDATECALLBACK_H +#define __UPDATECALLBACK_H + +#include "Common/MyCom.h" +#include "Common/MyString.h" + +#include "../../IPassword.h" +#include "../../ICoder.h" + +#include "../Common/UpdatePair.h" +#include "../Common/UpdateProduce.h" + +#define INTERFACE_IUpdateCallbackUI(x) \ + virtual HRESULT SetTotal(UInt64 size) x; \ + virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \ + virtual HRESULT SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) x; \ + virtual HRESULT CheckBreak() x; \ + virtual HRESULT Finilize() x; \ + virtual HRESULT SetNumFiles(UInt64 numFiles) x; \ + virtual HRESULT GetStream(const wchar_t *name, bool isAnti) x; \ + virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) x; \ + virtual HRESULT SetOperationResult(Int32 operationResult) x; \ + virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \ + virtual HRESULT CryptoGetTextPassword(BSTR *password) x; \ + /* virtual HRESULT ShowDeleteFile(const wchar_t *name) x; */ \ + /* virtual HRESULT CloseProgress() { return S_OK; }; */ + +struct IUpdateCallbackUI +{ + INTERFACE_IUpdateCallbackUI(=0) +}; + +class CArchiveUpdateCallback: + public IArchiveUpdateCallback2, + public ICryptoGetTextPassword2, + public ICryptoGetTextPassword, + public ICompressProgressInfo, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP4( + IArchiveUpdateCallback2, + ICryptoGetTextPassword2, + ICryptoGetTextPassword, + ICompressProgressInfo) + + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); + + INTERFACE_IArchiveUpdateCallback2(;) + + STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); + STDMETHOD(CryptoGetTextPassword)(BSTR *password); + +public: + CRecordVector VolumesSizes; + UString VolName; + UString VolExt; + + IUpdateCallbackUI *Callback; + + bool ShareForWrite; + bool StdInMode; + const CDirItems *DirItems; + const CObjectVector *ArcItems; + const CRecordVector *UpdatePairs; + const UStringVector *NewNames; + CMyComPtr Archive; + + CArchiveUpdateCallback(); +}; + +#endif diff --git a/CPP/7zip/UI/Common/UpdatePair.cpp b/CPP/7zip/UI/Common/UpdatePair.cpp new file mode 100755 index 0000000..812bff8 --- /dev/null +++ b/CPP/7zip/UI/Common/UpdatePair.cpp @@ -0,0 +1,158 @@ +// UpdatePair.cpp + +#include "StdAfx.h" + +#include + +#include "Common/Defs.h" +#include "Common/Wildcard.h" + +#include "Windows/Time.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 wchar_t *kDuplicateFileNameMessage = L"Duplicate filename:"; +static const wchar_t *kNotCensoredCollisionMessaged = L"Internal file name collision (file on disk, file in archive):"; + +static void ThrowError(const UString &message, const UString &s1, const UString &s2) +{ + UString m = message; + m += L'\n'; + m += s1; + m += L'\n'; + m += s2; + throw m; +} + +static void TestDuplicateString(const UStringVector &strings, const CIntVector &indices) +{ + for(int i = 0; i + 1 < indices.Size(); i++) + if (CompareFileNames(strings[indices[i]], strings[indices[i + 1]]) == 0) + ThrowError(kDuplicateFileNameMessage, strings[indices[i]], strings[indices[i + 1]]); +} + +void GetUpdatePairInfoList( + const CDirItems &dirItems, + const CObjectVector &arcItems, + NFileTimeType::EEnum fileTimeType, + CRecordVector &updatePairs) +{ + CIntVector dirIndices, arcIndices; + + int numDirItems = dirItems.Items.Size(); + int numArcItems = arcItems.Size(); + + + { + UStringVector arcNames; + arcNames.Reserve(numArcItems); + for (int i = 0; i < numArcItems; i++) + arcNames.Add(arcItems[i].Name); + SortFileNames(arcNames, arcIndices); + TestDuplicateString(arcNames, arcIndices); + } + + UStringVector dirNames; + { + dirNames.Reserve(numDirItems); + for (int i = 0; i < numDirItems; i++) + dirNames.Add(dirItems.GetLogPath(i)); + SortFileNames(dirNames, dirIndices); + TestDuplicateString(dirNames, dirIndices); + } + + int dirIndex = 0, arcIndex = 0; + while (dirIndex < numDirItems && arcIndex < numArcItems) + { + CUpdatePair pair; + int dirIndex2 = dirIndices[dirIndex]; + int arcIndex2 = arcIndices[arcIndex]; + const CDirItem &di = dirItems.Items[dirIndex2]; + const CArcItem &ai = arcItems[arcIndex2]; + int compareResult = CompareFileNames(dirNames[dirIndex2], ai.Name); + if (compareResult < 0) + { + pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; + pair.DirIndex = dirIndex2; + dirIndex++; + } + else if (compareResult > 0) + { + pair.State = ai.Censored ? + NUpdateArchive::NPairState::kOnlyInArchive: + NUpdateArchive::NPairState::kNotMasked; + pair.ArcIndex = arcIndex2; + arcIndex++; + } + else + { + if (!ai.Censored) + ThrowError(kNotCensoredCollisionMessaged, dirNames[dirIndex2], 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++; + } + updatePairs.Add(pair); + } + + for (; dirIndex < numDirItems; dirIndex++) + { + CUpdatePair pair; + pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; + pair.DirIndex = dirIndices[dirIndex]; + updatePairs.Add(pair); + } + + for (; arcIndex < numArcItems; arcIndex++) + { + CUpdatePair pair; + int arcIndex2 = arcIndices[arcIndex]; + pair.State = arcItems[arcIndex2].Censored ? + NUpdateArchive::NPairState::kOnlyInArchive: + NUpdateArchive::NPairState::kNotMasked; + pair.ArcIndex = arcIndex2; + updatePairs.Add(pair); + } + + updatePairs.ReserveDown(); +} diff --git a/CPP/7zip/UI/Common/UpdatePair.h b/CPP/7zip/UI/Common/UpdatePair.h new file mode 100755 index 0000000..5ee2665 --- /dev/null +++ b/CPP/7zip/UI/Common/UpdatePair.h @@ -0,0 +1,25 @@ +// 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; + CUpdatePair(): ArcIndex(-1), DirIndex(-1) {} +}; + +void GetUpdatePairInfoList( + const CDirItems &dirItems, + const CObjectVector &arcItems, + NFileTimeType::EEnum fileTimeType, + CRecordVector &updatePairs); + +#endif diff --git a/CPP/7zip/UI/Common/UpdateProduce.cpp b/CPP/7zip/UI/Common/UpdateProduce.cpp new file mode 100755 index 0000000..3ba677d --- /dev/null +++ b/CPP/7zip/UI/Common/UpdateProduce.cpp @@ -0,0 +1,58 @@ +// UpdateProduce.cpp + +#include "StdAfx.h" + +#include "UpdateProduce.h" + +using namespace NUpdateArchive; + +static const char *kUpdateActionSetCollision = "Internal collision in update action set"; + +void UpdateProduce( + const CRecordVector &updatePairs, + const CActionSet &actionSet, + CRecordVector &operationChain, + IUpdateProduceCallback *callback) +{ + for (int i = 0; i < updatePairs.Size(); i++) + { + const CUpdatePair &pair = updatePairs[i]; + + CUpdatePair2 up2; + up2.IsAnti = false; + up2.DirIndex = pair.DirIndex; + up2.ArcIndex = pair.ArcIndex; + up2.NewData = up2.NewProps = true; + + switch(actionSet.StateActions[pair.State]) + { + case NPairAction::kIgnore: + /* + if (pair.State != NPairState::kOnlyOnDisk) + IgnoreArchiveItem(m_ArchiveItems[pair.ArcIndex]); + // cout << "deleting"; + */ + if (callback) + callback->ShowDeleteFile(pair.ArcIndex); + continue; + + case NPairAction::kCopy: + if (pair.State == NPairState::kOnlyOnDisk) + throw kUpdateActionSetCollision; + up2.NewData = up2.NewProps = false; + break; + + case NPairAction::kCompress: + if (pair.State == NPairState::kOnlyInArchive || + pair.State == NPairState::kNotMasked) + throw kUpdateActionSetCollision; + break; + + case NPairAction::kCompressAsAnti: + up2.IsAnti = true; + break; + } + operationChain.Add(up2); + } + operationChain.ReserveDown(); +} diff --git a/CPP/7zip/UI/Common/UpdateProduce.h b/CPP/7zip/UI/Common/UpdateProduce.h new file mode 100755 index 0000000..c511caf --- /dev/null +++ b/CPP/7zip/UI/Common/UpdateProduce.h @@ -0,0 +1,35 @@ +// UpdateProduce.h + +#ifndef __UPDATE_PRODUCE_H +#define __UPDATE_PRODUCE_H + +#include "UpdatePair.h" + +struct CUpdatePair2 +{ + bool NewData; + bool NewProps; + bool IsAnti; + + int DirIndex; + int ArcIndex; + int NewNameIndex; + + bool ExistOnDisk() const { return DirIndex != -1; } + bool ExistInArchive() const { return ArcIndex != -1; } + + CUpdatePair2(): IsAnti(false), DirIndex(-1), ArcIndex(-1), NewNameIndex(-1) {} +}; + +struct IUpdateProduceCallback +{ + virtual HRESULT ShowDeleteFile(int arcIndex) = 0; +}; + +void UpdateProduce( + const CRecordVector &updatePairs, + const NUpdateArchive::CActionSet &actionSet, + CRecordVector &operationChain, + IUpdateProduceCallback *callback); + +#endif diff --git a/CPP/7zip/UI/Common/WorkDir.cpp b/CPP/7zip/UI/Common/WorkDir.cpp new file mode 100755 index 0000000..2989632 --- /dev/null +++ b/CPP/7zip/UI/Common/WorkDir.cpp @@ -0,0 +1,59 @@ +// WorkDir.cpp + +#include "StdAfx.h" + +#include "Common/StringConvert.h" +#include "Common/Wildcard.h" + +#include "Windows/FileDir.h" +#include "Windows/FileName.h" + +#include "WorkDir.h" + +using namespace NWindows; +using namespace NFile; + +UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path) +{ + NWorkDir::NMode::EEnum mode = workDirInfo.Mode; + #ifndef UNDER_CE + if (workDirInfo.ForRemovableOnly) + { + mode = NWorkDir::NMode::kCurrent; + UString prefix = path.Left(3); + if (prefix[1] == L':' && prefix[2] == L'\\') + { + 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 + switch(mode) + { + case NWorkDir::NMode::kCurrent: + { + return ExtractDirPrefixFromPath(path); + } + case NWorkDir::NMode::kSpecified: + { + UString tempDir = workDirInfo.Path; + NName::NormalizeDirPathPrefix(tempDir); + return tempDir; + } + default: + { + UString tempDir; + if (!NDirectory::MyGetTempPath(tempDir)) + throw 141717; + return tempDir; + } + } +} diff --git a/CPP/7zip/UI/Common/WorkDir.h b/CPP/7zip/UI/Common/WorkDir.h new file mode 100755 index 0000000..8208f3a --- /dev/null +++ b/CPP/7zip/UI/Common/WorkDir.h @@ -0,0 +1,10 @@ +// WorkDir.h + +#ifndef __WORKDIR_H +#define __WORKDIR_H + +#include "ZipRegistry.h" + +UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path); + +#endif diff --git a/CPP/7zip/UI/Common/ZipRegistry.cpp b/CPP/7zip/UI/Common/ZipRegistry.cpp new file mode 100755 index 0000000..be9776d --- /dev/null +++ b/CPP/7zip/UI/Common/ZipRegistry.cpp @@ -0,0 +1,293 @@ +// ZipRegistry.cpp + +#include "StdAfx.h" + +#include "Common/IntToString.h" +#include "Common/StringConvert.h" + +#include "Windows/FileDir.h" +#include "Windows/Registry.h" +#include "Windows/Synchronization.h" + +#include "ZipRegistry.h" + +using namespace NWindows; +using namespace NRegistry; + +static NSynchronization::CCriticalSection g_CS; +#define CS_LOCK NSynchronization::CCriticalSectionLock lock(g_CS); + +static const TCHAR *kCuPrefix = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-Zip") TEXT(STRING_PATH_SEPARATOR); + +static CSysString GetKeyPath(const CSysString &path) { return kCuPrefix + path; } + +static LONG OpenMainKey(CKey &key, LPCTSTR keyName) +{ + return key.Open(HKEY_CURRENT_USER, GetKeyPath(keyName), KEY_READ); +} + +static LONG CreateMainKey(CKey &key, LPCTSTR keyName) +{ + return key.Create(HKEY_CURRENT_USER, GetKeyPath(keyName)); +} + +namespace NExtract +{ + +static const TCHAR *kKeyName = TEXT("Extraction"); + +static const TCHAR *kExtractMode = TEXT("ExtractMode"); +static const TCHAR *kOverwriteMode = TEXT("OverwriteMode"); +static const TCHAR *kShowPassword = TEXT("ShowPassword"); +static const TCHAR *kPathHistory = TEXT("PathHistory"); + +void CInfo::Save() const +{ + CS_LOCK + CKey key; + CreateMainKey(key, kKeyName); + key.SetValue(kExtractMode, (UInt32)PathMode); + key.SetValue(kOverwriteMode, (UInt32)OverwriteMode); + key.SetValue(kShowPassword, ShowPassword); + key.RecurseDeleteKey(kPathHistory); + key.SetValue_Strings(kPathHistory, Paths); +} + + +void CInfo::Load() +{ + PathMode = NPathMode::kCurrentPathnames; + OverwriteMode = NOverwriteMode::kAskBefore; + ShowPassword = false; + Paths.Clear(); + + CS_LOCK + CKey key; + if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS) + return; + + key.GetValue_Strings(kPathHistory, Paths); + UInt32 v; + if (key.QueryValue(kExtractMode, v) == ERROR_SUCCESS && v <= NPathMode::kNoPathnames) + PathMode = (NPathMode::EEnum)v; + if (key.QueryValue(kOverwriteMode, v) == ERROR_SUCCESS && v <= NOverwriteMode::kAutoRenameExisting) + OverwriteMode = (NOverwriteMode::EEnum)v; + key.GetValue_IfOk(kShowPassword, ShowPassword); +} + +} + +namespace NCompression +{ + +static const TCHAR *kKeyName = TEXT("Compression"); + +static const TCHAR *kArcHistory = TEXT("ArcHistory"); +static const WCHAR *kArchiver = L"Archiver"; +static const TCHAR *kShowPassword = TEXT("ShowPassword"); +static const TCHAR *kEncryptHeaders = TEXT("EncryptHeaders"); + +static const TCHAR *kOptionsKeyName = TEXT("Options"); + +static const TCHAR *kLevel = TEXT("Level"); +static const TCHAR *kDictionary = TEXT("Dictionary"); +static const TCHAR *kOrder = TEXT("Order"); +static const TCHAR *kBlockSize = TEXT("BlockSize"); +static const TCHAR *kNumThreads = TEXT("NumThreads"); +static const WCHAR *kMethod = L"Method"; +static const WCHAR *kOptions = L"Options"; +static const WCHAR *kEncryptionMethod = L"EncryptionMethod"; + +static void SetRegString(CKey &key, const WCHAR *name, const UString &value) +{ + if (value.IsEmpty()) + key.DeleteValue(name); + else + key.SetValue(name, value); +} + +static void SetRegUInt32(CKey &key, const TCHAR *name, UInt32 value) +{ + if (value == (UInt32)-1) + key.DeleteValue(name); + else + key.SetValue(name, value); +} + +static void GetRegString(CKey &key, const WCHAR *name, UString &value) +{ + if (key.QueryValue(name, value) != ERROR_SUCCESS) + value.Empty(); +} + +static void GetRegUInt32(CKey &key, const TCHAR *name, UInt32 &value) +{ + if (key.QueryValue(name, value) != ERROR_SUCCESS) + value = (UInt32)-1; +} + +void CInfo::Save() const +{ + CS_LOCK + + CKey key; + CreateMainKey(key, kKeyName); + key.SetValue(kLevel, (UInt32)Level); + key.SetValue(kArchiver, ArcType); + key.SetValue(kShowPassword, ShowPassword); + key.SetValue(kEncryptHeaders, EncryptHeaders); + key.RecurseDeleteKey(kArcHistory); + key.SetValue_Strings(kArcHistory, ArcPaths); + + key.RecurseDeleteKey(kOptionsKeyName); + { + CKey optionsKey; + optionsKey.Create(key, kOptionsKeyName); + for (int i = 0; i < Formats.Size(); i++) + { + const CFormatOptions &fo = Formats[i]; + CKey fk; + fk.Create(optionsKey, fo.FormatID); + + SetRegUInt32(fk, kLevel, fo.Level); + SetRegUInt32(fk, kDictionary, fo.Dictionary); + SetRegUInt32(fk, kOrder, fo.Order); + SetRegUInt32(fk, kBlockSize, fo.BlockLogSize); + SetRegUInt32(fk, kNumThreads, fo.NumThreads); + + SetRegString(fk, kMethod, fo.Method); + SetRegString(fk, kOptions, fo.Options); + SetRegString(fk, kEncryptionMethod, fo.EncryptionMethod); + } + } +} + +void CInfo::Load() +{ + ArcPaths.Clear(); + Formats.Clear(); + + Level = 5; + ArcType = L"7z"; + ShowPassword = false; + EncryptHeaders = false; + + CS_LOCK + CKey key; + + if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS) + return; + + key.GetValue_Strings(kArcHistory, ArcPaths); + + { + CKey optionsKey; + if (optionsKey.Open(key, kOptionsKeyName, KEY_READ) == ERROR_SUCCESS) + { + CSysStringVector formatIDs; + optionsKey.EnumKeys(formatIDs); + for (int i = 0; i < formatIDs.Size(); i++) + { + CKey fk; + CFormatOptions fo; + fo.FormatID = formatIDs[i]; + if (fk.Open(optionsKey, fo.FormatID, KEY_READ) == ERROR_SUCCESS) + { + GetRegString(fk, kOptions, fo.Options); + GetRegString(fk, kMethod, fo.Method); + GetRegString(fk, kEncryptionMethod, fo.EncryptionMethod); + + GetRegUInt32(fk, kLevel, fo.Level); + GetRegUInt32(fk, kDictionary, fo.Dictionary); + GetRegUInt32(fk, kOrder, fo.Order); + GetRegUInt32(fk, kBlockSize, fo.BlockLogSize); + GetRegUInt32(fk, kNumThreads, fo.NumThreads); + + Formats.Add(fo); + } + } + } + } + + UString a; + if (key.QueryValue(kArchiver, a) == ERROR_SUCCESS) + ArcType = a; + key.GetValue_IfOk(kLevel, Level); + key.GetValue_IfOk(kShowPassword, ShowPassword); + key.GetValue_IfOk(kEncryptHeaders, EncryptHeaders); +} + +} + +static const TCHAR *kOptionsInfoKeyName = TEXT("Options"); + +namespace NWorkDir +{ +static const TCHAR *kWorkDirType = TEXT("WorkDirType"); +static const WCHAR *kWorkDirPath = L"WorkDirPath"; +static const TCHAR *kTempRemovableOnly = TEXT("TempRemovableOnly"); + + +void CInfo::Save()const +{ + CS_LOCK + CKey key; + CreateMainKey(key, kOptionsInfoKeyName); + key.SetValue(kWorkDirType, (UInt32)Mode); + key.SetValue(kWorkDirPath, Path); + key.SetValue(kTempRemovableOnly, ForRemovableOnly); +} + +void CInfo::Load() +{ + SetDefault(); + + CS_LOCK + CKey key; + if (OpenMainKey(key, kOptionsInfoKeyName) != ERROR_SUCCESS) + return; + + UInt32 dirType; + if (key.QueryValue(kWorkDirType, dirType) != ERROR_SUCCESS) + return; + switch (dirType) + { + case NMode::kSystem: + case NMode::kCurrent: + case NMode::kSpecified: + Mode = (NMode::EEnum)dirType; + } + if (key.QueryValue(kWorkDirPath, Path) != ERROR_SUCCESS) + { + Path.Empty(); + if (Mode == NMode::kSpecified) + Mode = NMode::kSystem; + } + key.GetValue_IfOk(kTempRemovableOnly, ForRemovableOnly); +} + +} + +static const TCHAR *kCascadedMenu = TEXT("CascadedMenu"); +static const TCHAR *kContextMenu = TEXT("ContextMenu"); + +void CContextMenuInfo::Save() const +{ + CS_LOCK + CKey key; + CreateMainKey(key, kOptionsInfoKeyName); + key.SetValue(kCascadedMenu, Cascaded); + key.SetValue(kContextMenu, Flags); +} + +void CContextMenuInfo::Load() +{ + Cascaded = true; + Flags = (UInt32)-1; + CS_LOCK + CKey key; + if (OpenMainKey(key, kOptionsInfoKeyName) != ERROR_SUCCESS) + return; + key.GetValue_IfOk(kCascadedMenu, Cascaded); + key.GetValue_IfOk(kContextMenu, Flags); +} diff --git a/CPP/7zip/UI/Common/ZipRegistry.h b/CPP/7zip/UI/Common/ZipRegistry.h new file mode 100755 index 0000000..1760d9b --- /dev/null +++ b/CPP/7zip/UI/Common/ZipRegistry.h @@ -0,0 +1,105 @@ +// ZipRegistry.h + +#ifndef __ZIP_REGISTRY_H +#define __ZIP_REGISTRY_H + +#include "Common/MyString.h" +#include "Common/Types.h" + +#include "ExtractMode.h" + +namespace NExtract +{ + struct CInfo + { + NPathMode::EEnum PathMode; + NOverwriteMode::EEnum OverwriteMode; + bool ShowPassword; + UStringVector Paths; + + void Save() const; + void Load(); + }; +} + +namespace NCompression +{ + struct CFormatOptions + { + UInt32 Level; + UInt32 Dictionary; + UInt32 Order; + UInt32 BlockLogSize; + UInt32 NumThreads; + + CSysString FormatID; + UString Method; + UString Options; + UString EncryptionMethod; + + void ResetForLevelChange() + { + BlockLogSize = NumThreads = Level = Dictionary = Order = UInt32(-1); + Method.Empty(); + // Options.Empty(); + // EncryptionMethod.Empty(); + } + CFormatOptions() { ResetForLevelChange(); } + }; + + struct CInfo + { + UInt32 Level; + bool ShowPassword; + bool EncryptHeaders; + UString ArcType; + UStringVector ArcPaths; + + CObjectVector Formats; + + void Save() const; + void Load(); + }; +} + +namespace NWorkDir +{ + namespace NMode + { + enum EEnum + { + kSystem, + kCurrent, + kSpecified + }; + } + struct CInfo + { + NMode::EEnum Mode; + UString Path; + bool ForRemovableOnly; + + void SetForRemovableOnlyDefault() { ForRemovableOnly = true; } + void SetDefault() + { + Mode = NMode::kSystem; + Path.Empty(); + SetForRemovableOnlyDefault(); + } + + void Save() const; + void Load(); + }; +} + + +struct CContextMenuInfo +{ + bool Cascaded; + UInt32 Flags; + + void Save() const; + void Load(); +}; + +#endif diff --git a/CPP/7zip/UI/Console/BenchCon.cpp b/CPP/7zip/UI/Console/BenchCon.cpp new file mode 100755 index 0000000..a31d8e0 --- /dev/null +++ b/CPP/7zip/UI/Console/BenchCon.cpp @@ -0,0 +1,297 @@ +// BenchCon.cpp + +#include "StdAfx.h" + +#include "../../../Common/IntToString.h" +#include "../../../Common/MyCom.h" + +#if !defined(_7ZIP_ST) || defined(_WIN32) +#include "../../../Windows/System.h" +#endif + +#include "../Common/Bench.h" + +#include "BenchCon.h" +#include "ConsoleClose.h" + +struct CTotalBenchRes +{ + UInt64 NumIterations; + UInt64 Rating; + UInt64 Usage; + UInt64 RPU; + void Init() { NumIterations = 0; Rating = 0; Usage = 0; RPU = 0; } + void Normalize() + { + if (NumIterations == 0) + return; + Rating /= NumIterations; + Usage /= NumIterations; + RPU /= NumIterations; + NumIterations = 1; + } + void SetMid(const CTotalBenchRes &r1, const CTotalBenchRes &r2) + { + Rating = (r1.Rating + r2.Rating) / 2; + Usage = (r1.Usage + r2.Usage) / 2; + RPU = (r1.RPU + r2.RPU) / 2; + NumIterations = (r1.NumIterations + r2.NumIterations) / 2; + } +}; + +struct CBenchCallback: public IBenchCallback +{ + CTotalBenchRes EncodeRes; + CTotalBenchRes DecodeRes; + FILE *f; + void Init() { EncodeRes.Init(); DecodeRes.Init(); } + void Normalize() { EncodeRes.Normalize(); DecodeRes.Normalize(); } + UInt32 dictionarySize; + HRESULT SetEncodeResult(const CBenchInfo &info, bool final); + HRESULT SetDecodeResult(const CBenchInfo &info, bool final); +}; + +static void NormalizeVals(UInt64 &v1, UInt64 &v2) +{ + while (v1 > 1000000) + { + v1 >>= 1; + v2 >>= 1; + } +} + +static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq) +{ + UInt64 elTime = elapsedTime; + NormalizeVals(freq, elTime); + if (elTime == 0) + elTime = 1; + return value * freq / elTime; +} + +static void PrintNumber(FILE *f, UInt64 value, int size) +{ + char s[32]; + ConvertUInt64ToString(value, s); + fprintf(f, " "); + for (int len = (int)strlen(s); len < size; len++) + fprintf(f, " "); + fputs(s, f); +} + +static void PrintRating(FILE *f, UInt64 rating) +{ + PrintNumber(f, rating / 1000000, 6); +} + +static void PrintResults(FILE *f, UInt64 usage, UInt64 rpu, UInt64 rating) +{ + PrintNumber(f, (usage + 5000) / 10000, 5); + PrintRating(f, rpu); + PrintRating(f, rating); +} + + +static void PrintResults(FILE *f, const CBenchInfo &info, UInt64 rating, CTotalBenchRes &res) +{ + UInt64 speed = MyMultDiv64(info.UnpackSize, info.GlobalTime, info.GlobalFreq); + PrintNumber(f, speed / 1024, 7); + UInt64 usage = GetUsage(info); + UInt64 rpu = GetRatingPerUsage(info, rating); + PrintResults(f, usage, rpu, rating); + res.NumIterations++; + res.RPU += rpu; + res.Rating += rating; + res.Usage += usage; +} + +static void PrintTotals(FILE *f, const CTotalBenchRes &res) +{ + fprintf(f, " "); + PrintResults(f, res.Usage, res.RPU, res.Rating); +} + + +HRESULT CBenchCallback::SetEncodeResult(const CBenchInfo &info, bool final) +{ + if (NConsoleClose::TestBreakSignal()) + return E_ABORT; + if (final) + { + UInt64 rating = GetCompressRating(dictionarySize, info.GlobalTime, info.GlobalFreq, info.UnpackSize); + PrintResults(f, info, rating, EncodeRes); + } + return S_OK; +} + +static const char *kSep = " | "; + + +HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final) +{ + if (NConsoleClose::TestBreakSignal()) + return E_ABORT; + if (final) + { + UInt64 rating = GetDecompressRating(info.GlobalTime, info.GlobalFreq, info.UnpackSize, info.PackSize, info.NumIterations); + fputs(kSep, f); + CBenchInfo info2 = info; + info2.UnpackSize *= info2.NumIterations; + info2.PackSize *= info2.NumIterations; + info2.NumIterations = 1; + PrintResults(f, info2, rating, DecodeRes); + } + return S_OK; +} + +static void PrintRequirements(FILE *f, const char *sizeString, UInt64 size, const char *threadsString, UInt32 numThreads) +{ + fprintf(f, "\nRAM %s ", sizeString); + PrintNumber(f, (size >> 20), 5); + fprintf(f, " MB, # %s %3d", threadsString, (unsigned int)numThreads); +} + +HRESULT LzmaBenchCon( + DECL_EXTERNAL_CODECS_LOC_VARS + FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary) +{ + if (!CrcInternalTest()) + return S_FALSE; + #ifndef _7ZIP_ST + UInt64 ramSize = NWindows::NSystem::GetRamSize(); // + UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); + PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs); + if (numThreads == (UInt32)-1) + numThreads = numCPUs; + if (numThreads > 1) + numThreads &= ~1; + if (dictionary == (UInt32)-1) + { + int dicSizeLog; + for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--) + if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize) + break; + dictionary = (1 << dicSizeLog); + } + #else + if (dictionary == (UInt32)-1) + dictionary = (1 << 22); + numThreads = 1; + #endif + + PrintRequirements(f, "usage:", GetBenchMemoryUsage(numThreads, dictionary), "Benchmark threads: ", numThreads); + + CBenchCallback callback; + callback.Init(); + callback.f = f; + + fprintf(f, "\n\nDict Compressing | Decompressing\n "); + int j; + for (j = 0; j < 2; j++) + { + fprintf(f, " Speed Usage R/U Rating"); + if (j == 0) + fputs(kSep, f); + } + fprintf(f, "\n "); + for (j = 0; j < 2; j++) + { + fprintf(f, " KB/s %% MIPS MIPS"); + if (j == 0) + fputs(kSep, f); + } + fprintf(f, "\n\n"); + for (UInt32 i = 0; i < numIterations; i++) + { + const int kStartDicLog = 22; + int pow = (dictionary < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog; + while (((UInt32)1 << pow) > dictionary) + pow--; + for (; ((UInt32)1 << pow) <= dictionary; pow++) + { + fprintf(f, "%2d:", pow); + callback.dictionarySize = (UInt32)1 << pow; + HRESULT res = LzmaBench( + EXTERNAL_CODECS_LOC_VARS + numThreads, callback.dictionarySize, &callback); + fprintf(f, "\n"); + RINOK(res); + } + } + callback.Normalize(); + fprintf(f, "----------------------------------------------------------------\nAvr:"); + PrintTotals(f, callback.EncodeRes); + fprintf(f, " "); + PrintTotals(f, callback.DecodeRes); + fprintf(f, "\nTot:"); + CTotalBenchRes midRes; + midRes.SetMid(callback.EncodeRes, callback.DecodeRes); + PrintTotals(f, midRes); + fprintf(f, "\n"); + return S_OK; +} + +struct CTempValues +{ + UInt64 *Values; + CTempValues(UInt32 num) { Values = new UInt64[num]; } + ~CTempValues() { delete []Values; } +}; + +HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary) +{ + if (!CrcInternalTest()) + return S_FALSE; + + #ifndef _7ZIP_ST + UInt64 ramSize = NWindows::NSystem::GetRamSize(); + UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); + PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs); + if (numThreads == (UInt32)-1) + numThreads = numCPUs; + #else + numThreads = 1; + #endif + if (dictionary == (UInt32)-1) + dictionary = (1 << 24); + + CTempValues speedTotals(numThreads); + fprintf(f, "\n\nSize"); + for (UInt32 ti = 0; ti < numThreads; ti++) + { + fprintf(f, " %5d", ti + 1); + speedTotals.Values[ti] = 0; + } + fprintf(f, "\n\n"); + + UInt64 numSteps = 0; + for (UInt32 i = 0; i < numIterations; i++) + { + for (int pow = 10; pow < 32; pow++) + { + UInt32 bufSize = (UInt32)1 << pow; + if (bufSize > dictionary) + break; + fprintf(f, "%2d: ", pow); + UInt64 speed; + for (UInt32 ti = 0; ti < numThreads; ti++) + { + if (NConsoleClose::TestBreakSignal()) + return E_ABORT; + RINOK(CrcBench(ti + 1, bufSize, speed)); + PrintNumber(f, (speed >> 20), 5); + speedTotals.Values[ti] += speed; + } + fprintf(f, "\n"); + numSteps++; + } + } + if (numSteps != 0) + { + fprintf(f, "\nAvg:"); + for (UInt32 ti = 0; ti < numThreads; ti++) + PrintNumber(f, ((speedTotals.Values[ti] / numSteps) >> 20), 5); + fprintf(f, "\n"); + } + return S_OK; +} diff --git a/CPP/7zip/UI/Console/BenchCon.h b/CPP/7zip/UI/Console/BenchCon.h new file mode 100755 index 0000000..c5eafbf --- /dev/null +++ b/CPP/7zip/UI/Console/BenchCon.h @@ -0,0 +1,16 @@ +// BenchCon.h + +#ifndef __BENCH_CON_H +#define __BENCH_CON_H + +#include + +#include "../../Common/CreateCoder.h" + +HRESULT LzmaBenchCon( + DECL_EXTERNAL_CODECS_LOC_VARS + FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary); + +HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary); + +#endif diff --git a/CPP/7zip/UI/Console/Console.dsp b/CPP/7zip/UI/Console/Console.dsp new file mode 100755 index 0000000..f58accd --- /dev/null +++ b/CPP/7zip/UI/Console/Console.dsp @@ -0,0 +1,845 @@ +# Microsoft Developer Studio Project File - Name="Console" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=Console - 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 "Console.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 "Console.mak" CFG="Console - Win32 DebugU" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Console - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "Console - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "Console - Win32 ReleaseU" (based on "Win32 (x86) Console Application") +!MESSAGE "Console - 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)" == "Console - 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 /W3 /GX /O1 /I "../../../" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /FAs /Yu"StdAfx.h" /FD /c +# ADD 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\7z.exe" /OPT:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "Console - 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 /W3 /Gm /GX /ZI /Od /I "../../../" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# 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\7z.exe" /pdbtype:sept + +!ELSEIF "$(CFG)" == "Console - Win32 ReleaseU" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Console___Win32_ReleaseU" +# PROP BASE Intermediate_Dir "Console___Win32_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 /Gz /MD /W3 /GX /O1 /I "../../../" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "../../../" /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# 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\7z.exe" +# 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\7zn.exe" /OPT:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "Console - Win32 DebugU" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Console___Win32_DebugU" +# PROP BASE Intermediate_Dir "Console___Win32_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 /Gz /W3 /Gm /GX /ZI /Od /I "../../../" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "../../../" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# 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\7z.exe" /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"C:\UTIL\7z.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "Console - Win32 Release" +# Name "Console - Win32 Debug" +# Name "Console - Win32 ReleaseU" +# Name "Console - Win32 DebugU" +# 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 "Console" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\BenchCon.cpp +# End Source File +# Begin Source File + +SOURCE=.\BenchCon.h +# End Source File +# Begin Source File + +SOURCE=.\ConsoleClose.cpp +# End Source File +# Begin Source File + +SOURCE=.\ConsoleClose.h +# End Source File +# Begin Source File + +SOURCE=.\ExtractCallbackConsole.cpp +# End Source File +# Begin Source File + +SOURCE=.\ExtractCallbackConsole.h +# End Source File +# Begin Source File + +SOURCE=.\List.cpp +# End Source File +# Begin Source File + +SOURCE=.\List.h +# End Source File +# Begin Source File + +SOURCE=.\Main.cpp +# End Source File +# Begin Source File + +SOURCE=.\MainAr.cpp +# End Source File +# Begin Source File + +SOURCE=.\OpenCallbackConsole.cpp +# End Source File +# Begin Source File + +SOURCE=.\OpenCallbackConsole.h +# End Source File +# Begin Source File + +SOURCE=.\PercentPrinter.cpp +# End Source File +# Begin Source File + +SOURCE=.\PercentPrinter.h +# End Source File +# Begin Source File + +SOURCE=.\UpdateCallbackConsole.cpp +# End Source File +# Begin Source File + +SOURCE=.\UpdateCallbackConsole.h +# End Source File +# Begin Source File + +SOURCE=.\UserInputUtils.cpp +# End Source File +# Begin Source File + +SOURCE=.\UserInputUtils.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\Error.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Error.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\MemoryLock.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\MemoryLock.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\NtCheck.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\PropVariantConversions.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariantConversions.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Registry.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Registry.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\Time.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Time.h +# End Source File +# End Group +# Begin Group "Common" + +# PROP Default_Filter "" +# 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\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\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\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\StringToInt.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringToInt.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 "UI Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\Common\ArchiveCommandLine.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ArchiveCommandLine.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ArchiveExtractCallback.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ArchiveExtractCallback.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ArchiveOpenCallback.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ArchiveOpenCallback.h +# End Source File +# Begin Source File + +SOURCE=..\Common\Bench.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\Bench.h +# End Source File +# Begin Source File + +SOURCE=..\Common\DefaultName.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\DefaultName.h +# End Source File +# Begin Source File + +SOURCE=..\Common\DirItem.h +# End Source File +# Begin Source File + +SOURCE=..\Common\EnumDirItems.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\EnumDirItems.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ExitCode.h +# End Source File +# Begin Source File + +SOURCE=..\Common\Extract.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\Extract.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ExtractingFilePath.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ExtractingFilePath.h +# End Source File +# Begin Source File + +SOURCE=..\Common\IFileExtractCallback.h +# End Source File +# Begin Source File + +SOURCE=..\Common\LoadCodecs.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\LoadCodecs.h +# End Source File +# Begin Source File + +SOURCE=..\Common\OpenArchive.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\OpenArchive.h +# End Source File +# Begin Source File + +SOURCE=..\Common\Property.h +# End Source File +# Begin Source File + +SOURCE=..\Common\PropIDUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\PropIDUtils.h +# End Source File +# Begin Source File + +SOURCE=..\Common\SetProperties.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\SetProperties.h +# End Source File +# Begin Source File + +SOURCE=..\Common\SortUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\SortUtils.h +# End Source File +# Begin Source File + +SOURCE=..\Common\TempFiles.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\TempFiles.h +# End Source File +# Begin Source File + +SOURCE=..\Common\Update.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\Update.h +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdateAction.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdateAction.h +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdateCallback.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdateCallback.h +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdatePair.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdatePair.h +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdateProduce.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdateProduce.h +# End Source File +# Begin Source File + +SOURCE=..\Common\WorkDir.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\WorkDir.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ZipRegistry.h +# End Source File +# End Group +# Begin Group "7-zip 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\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\ProgressUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\RegisterArc.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File +# End Group +# Begin Group "Compress" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\CopyCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\CopyCoder.h +# End Source File +# End Group +# Begin Group "C" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\..\C\7zCrc.c + +!IF "$(CFG)" == "Console - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Console - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Console - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Console - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\7zCrc.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\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\Threads.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Threads.h +# End Source File +# End Group +# Begin Group "ArchiveCommon" + +# PROP Default_Filter "" +# 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 "Asm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\..\Asm\x86\7zAsm.asm +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\Asm\x86\7zCrcOpt.asm + +!IF "$(CFG)" == "Console - Win32 Release" + +# Begin Custom Build +OutDir=.\Release +InputPath=..\..\..\..\Asm\x86\7zCrcOpt.asm +InputName=7zCrcOpt + +"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml.exe -c -Fo$(OutDir)\$(InputName).obj $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "Console - Win32 Debug" + +# Begin Custom Build +OutDir=.\Debug +InputPath=..\..\..\..\Asm\x86\7zCrcOpt.asm +InputName=7zCrcOpt + +"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml.exe -c -omf -Fo$(OutDir)\$(InputName).obj $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "Console - Win32 ReleaseU" + +# Begin Custom Build +OutDir=.\ReleaseU +InputPath=..\..\..\..\Asm\x86\7zCrcOpt.asm +InputName=7zCrcOpt + +"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml.exe -c -Fo$(OutDir)\$(InputName).obj $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "Console - Win32 DebugU" + +# Begin Custom Build +OutDir=.\DebugU +InputPath=..\..\..\..\Asm\x86\7zCrcOpt.asm +InputName=7zCrcOpt + +"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml.exe -c -omf -Fo$(OutDir)\$(InputName).obj $(InputPath) + +# End Custom Build + +!ENDIF + +# End Source File +# End Group +# End Target +# End Project diff --git a/CPP/7zip/UI/Console/Console.dsw b/CPP/7zip/UI/Console/Console.dsw new file mode 100755 index 0000000..6e37f11 --- /dev/null +++ b/CPP/7zip/UI/Console/Console.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "Console"=".\Console.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/CPP/7zip/UI/Console/ConsoleClose.cpp b/CPP/7zip/UI/Console/ConsoleClose.cpp new file mode 100755 index 0000000..9fbad17 --- /dev/null +++ b/CPP/7zip/UI/Console/ConsoleClose.cpp @@ -0,0 +1,73 @@ +// ConsoleClose.cpp + +#include "StdAfx.h" + +#include "ConsoleClose.h" + +static int g_BreakCounter = 0; +static const int kBreakAbortThreshold = 2; + +namespace NConsoleClose { + +#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 + +bool TestBreakSignal() +{ + #ifdef UNDER_CE + return false; + #else + /* + if (g_BreakCounter > 0) + return true; + */ + return (g_BreakCounter > 0); + #endif +} + +void CheckCtrlBreak() +{ + if (TestBreakSignal()) + throw CCtrlBreakException(); +} + +CCtrlHandlerSetter::CCtrlHandlerSetter() +{ + #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)) + throw "SetConsoleCtrlHandler fails"; + #endif +} + +} diff --git a/CPP/7zip/UI/Console/ConsoleClose.h b/CPP/7zip/UI/Console/ConsoleClose.h new file mode 100755 index 0000000..7101018 --- /dev/null +++ b/CPP/7zip/UI/Console/ConsoleClose.h @@ -0,0 +1,24 @@ +// ConsoleCloseUtils.h + +#ifndef __CONSOLECLOSEUTILS_H +#define __CONSOLECLOSEUTILS_H + +namespace NConsoleClose { + +bool TestBreakSignal(); + +class CCtrlHandlerSetter +{ +public: + CCtrlHandlerSetter(); + virtual ~CCtrlHandlerSetter(); +}; + +class CCtrlBreakException +{}; + +void CheckCtrlBreak(); + +} + +#endif diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp new file mode 100755 index 0000000..278b069 --- /dev/null +++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp @@ -0,0 +1,228 @@ +// ExtractCallbackConsole.h + +#include "StdAfx.h" + +#include "ExtractCallbackConsole.h" +#include "UserInputUtils.h" +#include "ConsoleClose.h" + +#include "Common/Wildcard.h" + +#include "Windows/FileDir.h" +#include "Windows/FileFind.h" +#include "Windows/Time.h" +#include "Windows/Defs.h" +#include "Windows/PropVariant.h" +#include "Windows/Error.h" +#include "Windows/PropVariantConversions.h" + +#include "../../Common/FilePathAutoRename.h" + +#include "../Common/ExtractingFilePath.h" + +using namespace NWindows; +using namespace NFile; +using namespace NDirectory; + +static const char *kTestString = "Testing "; +static const char *kExtractString = "Extracting "; +static const char *kSkipString = "Skipping "; + +// static const char *kCantAutoRename = "can not create file with auto name\n"; +// static const char *kCantRenameFile = "can not rename existing file\n"; +// static const char *kCantDeleteOutputFile = "can not delete output file "; +static const char *kError = "ERROR: "; +static const char *kMemoryExceptionMessage = "Can't allocate required memory!"; + +static const char *kProcessing = "Processing archive: "; +static const char *kEverythingIsOk = "Everything is Ok"; +static const char *kNoFiles = "No files to process"; + +static const char *kUnsupportedMethod = "Unsupported Method"; +static const char *kCrcFailed = "CRC Failed"; +static const char *kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?"; +static const char *kDataError = "Data Error"; +static const char *kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?"; +static const char *kUnknownError = "Unknown Error"; + +STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64) +{ + if (NConsoleClose::TestBreakSignal()) + return E_ABORT; + return S_OK; +} + +STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *) +{ + if (NConsoleClose::TestBreakSignal()) + return E_ABORT; + return S_OK; +} + +STDMETHODIMP CExtractCallbackConsole::AskOverwrite( + const wchar_t *existName, const FILETIME *, const UInt64 *, + const wchar_t *newName, const FILETIME *, const UInt64 *, + Int32 *answer) +{ + (*OutStream) << "file " << existName << + "\nalready exists. Overwrite with " << endl; + (*OutStream) << newName; + + NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(OutStream); + + 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; + default: return E_FAIL; + } + return S_OK; +} + +STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 askExtractMode, const UInt64 *position) +{ + switch (askExtractMode) + { + case NArchive::NExtract::NAskMode::kExtract: (*OutStream) << kExtractString; break; + case NArchive::NExtract::NAskMode::kTest: (*OutStream) << kTestString; break; + case NArchive::NExtract::NAskMode::kSkip: (*OutStream) << kSkipString; break; + }; + (*OutStream) << name; + if (position != 0) + (*OutStream) << " <" << *position << ">"; + return S_OK; +} + +STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message) +{ + (*OutStream) << message << endl; + NumFileErrorsInCurrentArchive++; + NumFileErrors++; + return S_OK; +} + +STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 operationResult, bool encrypted) +{ + switch(operationResult) + { + case NArchive::NExtract::NOperationResult::kOK: + break; + default: + { + NumFileErrorsInCurrentArchive++; + NumFileErrors++; + (*OutStream) << " "; + switch(operationResult) + { + case NArchive::NExtract::NOperationResult::kUnSupportedMethod: + (*OutStream) << kUnsupportedMethod; + break; + case NArchive::NExtract::NOperationResult::kCRCError: + (*OutStream) << (encrypted ? kCrcFailedEncrypted: kCrcFailed); + break; + case NArchive::NExtract::NOperationResult::kDataError: + (*OutStream) << (encrypted ? kDataErrorEncrypted : kDataError); + break; + default: + (*OutStream) << kUnknownError; + } + } + } + (*OutStream) << endl; + return S_OK; +} + +#ifndef _NO_CRYPTO + +HRESULT CExtractCallbackConsole::SetPassword(const UString &password) +{ + PasswordIsDefined = true; + Password = password; + return S_OK; +} + +STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password) +{ + if (!PasswordIsDefined) + { + Password = GetPassword(OutStream); + PasswordIsDefined = true; + } + return StringToBstr(Password, password); +} + +#endif + +HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name) +{ + NumArchives++; + NumFileErrorsInCurrentArchive = 0; + (*OutStream) << endl << kProcessing << name << endl; + return S_OK; +} + +HRESULT CExtractCallbackConsole::OpenResult(const wchar_t * /* name */, HRESULT result, bool encrypted) +{ + (*OutStream) << endl; + if (result != S_OK) + { + (*OutStream) << "Error: "; + if (result == S_FALSE) + { + (*OutStream) << (encrypted ? + "Can not open encrypted archive. Wrong password?" : + "Can not open file as archive"); + } + else + { + if (result == E_OUTOFMEMORY) + (*OutStream) << "Can't allocate required memory"; + else + (*OutStream) << NError::MyFormatMessage(result); + } + (*OutStream) << endl; + NumArchiveErrors++; + } + return S_OK; +} + +HRESULT CExtractCallbackConsole::ThereAreNoFiles() +{ + (*OutStream) << endl << kNoFiles << endl; + return S_OK; +} + +HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result) +{ + if (result == S_OK) + { + (*OutStream) << endl; + if (NumFileErrorsInCurrentArchive == 0) + (*OutStream) << kEverythingIsOk << endl; + else + { + NumArchiveErrors++; + (*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrentArchive << endl; + } + } + if (result == S_OK) + return result; + NumArchiveErrors++; + if (result == E_ABORT || result == ERROR_DISK_FULL) + return result; + (*OutStream) << endl << kError; + if (result == E_OUTOFMEMORY) + (*OutStream) << kMemoryExceptionMessage; + else + { + UString message; + NError::MyFormatMessage(result, message); + (*OutStream) << message; + } + (*OutStream) << endl; + return S_OK; +} diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.h b/CPP/7zip/UI/Console/ExtractCallbackConsole.h new file mode 100755 index 0000000..7086527 --- /dev/null +++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.h @@ -0,0 +1,73 @@ +// ExtractCallbackConsole.h + +#ifndef __EXTRACTCALLBACKCONSOLE_H +#define __EXTRACTCALLBACKCONSOLE_H + +#include "Common/MyString.h" +#include "Common/StdOutStream.h" +#include "../../Common/FileStreams.h" +#include "../../IPassword.h" +#include "../../Archive/IArchive.h" +#include "../Common/ArchiveExtractCallback.h" + +class CExtractCallbackConsole: + public IExtractCallbackUI, + #ifndef _NO_CRYPTO + public ICryptoGetTextPassword, + #endif + public CMyUnknownImp +{ +public: + MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback) + #ifndef _NO_CRYPTO + MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword) + #endif + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + STDMETHOD(SetTotal)(UInt64 total); + STDMETHOD(SetCompleted)(const UInt64 *completeValue); + + // IFolderArchiveExtractCallback + STDMETHOD(AskOverwrite)( + const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, + const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, + Int32 *answer); + STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position); + + STDMETHOD(MessageError)(const wchar_t *message); + STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted); + + HRESULT BeforeOpen(const wchar_t *name); + HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted); + HRESULT ThereAreNoFiles(); + HRESULT ExtractResult(HRESULT result); + + + #ifndef _NO_CRYPTO + HRESULT SetPassword(const UString &password); + STDMETHOD(CryptoGetTextPassword)(BSTR *password); + + bool PasswordIsDefined; + UString Password; + + #endif + + UInt64 NumArchives; + UInt64 NumArchiveErrors; + UInt64 NumFileErrors; + UInt64 NumFileErrorsInCurrentArchive; + + CStdOutStream *OutStream; + + void Init() + { + NumArchives = 0; + NumArchiveErrors = 0; + NumFileErrors = 0; + NumFileErrorsInCurrentArchive = 0; + } + +}; + +#endif diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp new file mode 100755 index 0000000..298adbd --- /dev/null +++ b/CPP/7zip/UI/Console/List.cpp @@ -0,0 +1,654 @@ +// List.cpp + +#include "StdAfx.h" + +#include "Common/IntToString.h" +#include "Common/MyCom.h" +#include "Common/StdOutStream.h" +#include "Common/StringConvert.h" + +#include "Windows/Error.h" +#include "Windows/FileDir.h" +#include "Windows/PropVariant.h" +#include "Windows/PropVariantConversions.h" + +#include "../../Archive/IArchive.h" + +#include "../Common/OpenArchive.h" +#include "../Common/PropIDUtils.h" + +#include "ConsoleClose.h" +#include "List.h" +#include "OpenCallbackConsole.h" + +using namespace NWindows; + +struct CPropIdToName +{ + PROPID PropID; + const wchar_t *Name; +}; + +static const CPropIdToName kPropIdToName[] = +{ + { kpidPath, L"Path" }, + { kpidName, L"Name" }, + { kpidIsDir, L"Folder" }, + { kpidSize, L"Size" }, + { kpidPackSize, L"Packed Size" }, + { kpidAttrib, L"Attributes" }, + { kpidCTime, L"Created" }, + { kpidATime, L"Accessed" }, + { kpidMTime, L"Modified" }, + { kpidSolid, L"Solid" }, + { kpidCommented, L"Commented" }, + { kpidEncrypted, L"Encrypted" }, + { kpidSplitBefore, L"Split Before" }, + { kpidSplitAfter, L"Split After" }, + { kpidDictionarySize, L"Dictionary Size" }, + { kpidCRC, L"CRC" }, + { kpidType, L"Type" }, + { kpidIsAnti, L"Anti" }, + { kpidMethod, L"Method" }, + { kpidHostOS, L"Host OS" }, + { kpidFileSystem, L"File System" }, + { kpidUser, L"User" }, + { kpidGroup, L"Group" }, + { kpidBlock, L"Block" }, + { kpidComment, L"Comment" }, + { kpidPosition, L"Position" }, + { kpidPrefix, L"Prefix" }, + { kpidNumSubDirs, L"Folders" }, + { kpidNumSubFiles, L"Files" }, + { kpidUnpackVer, L"Version" }, + { kpidVolume, L"Volume" }, + { kpidIsVolume, L"Multivolume" }, + { kpidOffset, L"Offset" }, + { kpidLinks, L"Links" }, + { kpidNumBlocks, L"Blocks" }, + { kpidNumVolumes, L"Volumes" }, + + { kpidBit64, L"64-bit" }, + { kpidBigEndian, L"Big-endian" }, + { kpidCpu, L"CPU" }, + { kpidPhySize, L"Physical Size" }, + { kpidHeadersSize, L"Headers Size" }, + { kpidChecksum, L"Checksum" }, + { kpidCharacts, L"Characteristics" }, + { kpidVa, L"Virtual Address" }, + { kpidId, L"ID" }, + { kpidShortName, L"Short Name" }, + { kpidCreatorApp, L"Creator Application"}, + { kpidSectorSize, L"Sector Size" }, + { kpidPosixAttrib, L"Mode" }, + { kpidLink, L"Link" }, + { kpidError, L"Error" }, + + { kpidTotalSize, L"Total Size" }, + { kpidFreeSpace, L"Free Space" }, + { kpidClusterSize, L"Cluster Size" }, + { kpidVolumeName, L"Label" } +}; + +static const char kEmptyAttribChar = '.'; + +static const char *kListing = "Listing archive: "; +static const wchar_t *kFilesMessage = L"files"; +static const wchar_t *kDirsMessage = L"folders"; + +static void GetAttribString(DWORD wa, bool isDir, char *s) +{ + s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? '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; + UString Name; + EAdjustment TitleAdjustment; + EAdjustment TextAdjustment; + int PrefixSpacesWidth; + int Width; +}; + +struct CFieldInfoInit +{ + PROPID PropID; + const wchar_t *Name; + EAdjustment TitleAdjustment; + EAdjustment TextAdjustment; + int PrefixSpacesWidth; + int Width; +}; + +static CFieldInfoInit kStandardFieldTable[] = +{ + { kpidMTime, L" Date Time", kLeft, kLeft, 0, 19 }, + { kpidAttrib, L"Attr", kRight, kCenter, 1, 5 }, + { kpidSize, L"Size", kRight, kRight, 1, 12 }, + { kpidPackSize, L"Compressed", kRight, kRight, 1, 12 }, + { kpidPath, L"Name", kLeft, kLeft, 2, 24 } +}; + +static void PrintSpaces(int numSpaces) +{ + for (int i = 0; i < numSpaces; i++) + g_StdOut << ' '; +} + +static void PrintString(EAdjustment adjustment, int width, const UString &textString) +{ + const int numSpaces = width - textString.Length(); + int numLeftSpaces = 0; + switch (adjustment) + { + case kLeft: + numLeftSpaces = 0; + break; + case kCenter: + numLeftSpaces = numSpaces / 2; + break; + case kRight: + numLeftSpaces = numSpaces; + break; + } + PrintSpaces(numLeftSpaces); + g_StdOut << textString; + PrintSpaces(numSpaces - numLeftSpaces); +} + +class CFieldPrinter +{ + CObjectVector _fields; +public: + void Clear() { _fields.Clear(); } + void Init(const CFieldInfoInit *standardFieldTable, int numItems); + HRESULT Init(IInArchive *archive); + void PrintTitle(); + void PrintTitleLines(); + HRESULT PrintItemInfo(const CArc &arc, UInt32 index, bool techMode); + HRESULT PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, + const UInt64 *size, const UInt64 *compressedSize); +}; + +void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems) +{ + Clear(); + for (int i = 0; i < numItems; i++) + { + CFieldInfo fieldInfo; + const CFieldInfoInit &fieldInfoInit = standardFieldTable[i]; + fieldInfo.PropID = fieldInfoInit.PropID; + fieldInfo.Name = fieldInfoInit.Name; + fieldInfo.TitleAdjustment = fieldInfoInit.TitleAdjustment; + fieldInfo.TextAdjustment = fieldInfoInit.TextAdjustment; + fieldInfo.PrefixSpacesWidth = fieldInfoInit.PrefixSpacesWidth; + fieldInfo.Width = fieldInfoInit.Width; + _fields.Add(fieldInfo); + } +} + +static UString GetPropName(PROPID propID, BSTR name) +{ + for (int i = 0; i < sizeof(kPropIdToName) / sizeof(kPropIdToName[0]); i++) + { + const CPropIdToName &propIdToName = kPropIdToName[i]; + if (propIdToName.PropID == propID) + return propIdToName.Name; + } + if (name) + return name; + wchar_t s[16]; + ConvertUInt32ToString(propID, s); + return s; +} + +HRESULT CFieldPrinter::Init(IInArchive *archive) +{ + Clear(); + 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)); + CFieldInfo fieldInfo; + fieldInfo.PropID = propID; + fieldInfo.Name = GetPropName(propID, name); + _fields.Add(fieldInfo); + } + return S_OK; +} + +void CFieldPrinter::PrintTitle() +{ + for (int i = 0; i < _fields.Size(); i++) + { + const CFieldInfo &fieldInfo = _fields[i]; + PrintSpaces(fieldInfo.PrefixSpacesWidth); + PrintString(fieldInfo.TitleAdjustment, + ((fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width), fieldInfo.Name); + } +} + +void CFieldPrinter::PrintTitleLines() +{ + for (int i = 0; i < _fields.Size(); i++) + { + const CFieldInfo &fieldInfo = _fields[i]; + PrintSpaces(fieldInfo.PrefixSpacesWidth); + for (int i = 0; i < fieldInfo.Width; i++) + g_StdOut << '-'; + } +} + + +static BOOL IsFileTimeZero(CONST FILETIME *lpFileTime) +{ + return (lpFileTime->dwLowDateTime == 0) && (lpFileTime->dwHighDateTime == 0); +} + +static const char *kEmptyTimeString = " "; +static void PrintTime(const NCOM::CPropVariant &prop) +{ + if (prop.vt != VT_FILETIME) + throw "incorrect item"; + if (IsFileTimeZero(&prop.filetime)) + g_StdOut << kEmptyTimeString; + else + { + FILETIME localFileTime; + if (!FileTimeToLocalFileTime(&prop.filetime, &localFileTime)) + throw "FileTimeToLocalFileTime error"; + char s[32]; + if (ConvertFileTimeToString(localFileTime, s, true, true)) + g_StdOut << s; + else + g_StdOut << kEmptyTimeString; + } +} + +HRESULT CFieldPrinter::PrintItemInfo(const CArc &arc, UInt32 index, bool techMode) +{ + /* + if (techMode) + { + g_StdOut << "Index = "; + g_StdOut << (UInt64)index; + g_StdOut << endl; + } + */ + for (int i = 0; i < _fields.Size(); i++) + { + const CFieldInfo &fieldInfo = _fields[i]; + if (!techMode) + PrintSpaces(fieldInfo.PrefixSpacesWidth); + + NCOM::CPropVariant prop; + if (fieldInfo.PropID == kpidPath) + { + UString s; + RINOK(arc.GetItemPath(index, s)); + prop = s; + } + else + { + RINOK(arc.Archive->GetProperty(index, fieldInfo.PropID, &prop)); + } + if (techMode) + { + g_StdOut << fieldInfo.Name << " = "; + } + int width = (fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width; + if (fieldInfo.PropID == kpidAttrib && (prop.vt == VT_EMPTY || prop.vt == VT_UI4)) + { + UInt32 attrib = (prop.vt == VT_EMPTY) ? 0 : prop.ulVal; + bool isFolder; + RINOK(IsArchiveItemFolder(arc.Archive, index, isFolder)); + char s[8]; + GetAttribString(attrib, isFolder, s); + g_StdOut << s; + } + else if (prop.vt == VT_EMPTY) + { + if (!techMode) + PrintSpaces(width); + } + else if (fieldInfo.PropID == kpidMTime) + { + PrintTime(prop); + } + else if (prop.vt == VT_BSTR) + { + if (techMode) + g_StdOut << prop.bstrVal; + else + PrintString(fieldInfo.TextAdjustment, width, prop.bstrVal); + } + else + { + UString s = ConvertPropertyToString(prop, fieldInfo.PropID); + s.Replace(wchar_t(0xA), L' '); + s.Replace(wchar_t(0xD), L' '); + + if (techMode) + g_StdOut << s; + else + PrintString(fieldInfo.TextAdjustment, width, s); + } + if (techMode) + g_StdOut << endl; + } + return S_OK; +} + +static void PrintNumberString(EAdjustment adjustment, int width, const UInt64 *value) +{ + wchar_t textString[32] = { 0 }; + if (value != NULL) + ConvertUInt64ToString(*value, textString); + PrintString(adjustment, width, textString); +} + + +HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, + const UInt64 *size, const UInt64 *compressedSize) +{ + for (int i = 0; i < _fields.Size(); i++) + { + const CFieldInfo &fieldInfo = _fields[i]; + PrintSpaces(fieldInfo.PrefixSpacesWidth); + NCOM::CPropVariant prop; + if (fieldInfo.PropID == kpidSize) + PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, size); + else if (fieldInfo.PropID == kpidPackSize) + PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, compressedSize); + else if (fieldInfo.PropID == kpidPath) + { + wchar_t textString[32]; + ConvertUInt64ToString(numFiles, textString); + UString temp = textString; + temp += L" "; + temp += kFilesMessage; + temp += L", "; + ConvertUInt64ToString(numDirs, textString); + temp += textString; + temp += L" "; + temp += kDirsMessage; + PrintString(fieldInfo.TextAdjustment, 0, temp); + } + else + PrintString(fieldInfo.TextAdjustment, fieldInfo.Width, L""); + } + return S_OK; +} + +bool GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &value) +{ + NCOM::CPropVariant prop; + if (archive->GetProperty(index, propID, &prop) != S_OK) + throw "GetPropertyValue error"; + if (prop.vt == VT_EMPTY) + return false; + value = ConvertPropVariantToUInt64(prop); + return true; +} + +static void PrintPropPair(const wchar_t *name, const wchar_t *value) +{ + g_StdOut << name << " = " << value << endl; +} + +HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, + bool stdInMode, + UStringVector &arcPaths, UStringVector &arcPathsFull, + const NWildcard::CCensorNode &wildcardCensor, + bool enableHeaders, bool techMode, + #ifndef _NO_CRYPTO + bool &passwordEnabled, UString &password, + #endif + UInt64 &numErrors) +{ + numErrors = 0; + CFieldPrinter fieldPrinter; + if (!techMode) + fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0])); + + UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0; + UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0; + int numArcs = /* stdInMode ? 1 : */ arcPaths.Size(); + for (int i = 0; i < numArcs; i++) + { + const UString &archiveName = arcPaths[i]; + UInt64 arcPackSize = 0; + if (!stdInMode) + { + NFile::NFind::CFileInfoW fi; + if (!fi.Find(archiveName) || fi.IsDir()) + { + g_StdOut << endl << "Error: " << archiveName << " is not file" << endl; + numErrors++; + continue; + } + arcPackSize = fi.Size; + } + + CArchiveLink archiveLink; + + COpenCallbackConsole openCallback; + openCallback.OutStream = &g_StdOut; + + #ifndef _NO_CRYPTO + + openCallback.PasswordIsDefined = passwordEnabled; + openCallback.Password = password; + + #endif + + HRESULT result = archiveLink.Open2(codecs, formatIndices, stdInMode, NULL, archiveName, &openCallback); + if (result != S_OK) + { + if (result == E_ABORT) + return result; + g_StdOut << endl << "Error: " << archiveName << ": "; + if (result == S_FALSE) + { + #ifndef _NO_CRYPTO + if (openCallback.Open_WasPasswordAsked()) + g_StdOut << "Can not open encrypted archive. Wrong password?"; + else + #endif + g_StdOut << "Can not open file as archive"; + } + else if (result == E_OUTOFMEMORY) + g_StdOut << "Can't allocate required memory"; + else + g_StdOut << NError::MyFormatMessage(result); + g_StdOut << endl; + numErrors++; + continue; + } + + if (!stdInMode) + for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) + { + int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]); + if (index >= 0 && index > i) + { + arcPaths.Delete(index); + arcPathsFull.Delete(index); + numArcs = arcPaths.Size(); + } + } + + if (enableHeaders) + { + g_StdOut << endl << kListing << archiveName << endl << endl; + + for (int i = 0; i < archiveLink.Arcs.Size(); i++) + { + const CArc &arc = archiveLink.Arcs[i]; + + g_StdOut << "--\n"; + PrintPropPair(L"Path", arc.Path); + PrintPropPair(L"Type", codecs->Formats[arc.FormatIndex].Name); + if (!arc.ErrorMessage.IsEmpty()) + PrintPropPair(L"Error", arc.ErrorMessage); + UInt32 numProps; + IInArchive *archive = arc.Archive; + if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK) + { + for (UInt32 j = 0; j < numProps; j++) + { + CMyComBSTR name; + PROPID propID; + VARTYPE vt; + RINOK(archive->GetArchivePropertyInfo(j, &name, &propID, &vt)); + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(propID, &prop)); + UString s = ConvertPropertyToString(prop, propID); + if (!s.IsEmpty()) + PrintPropPair(GetPropName(propID, name), s); + } + } + if (i != archiveLink.Arcs.Size() - 1) + { + UInt32 numProps; + g_StdOut << "----\n"; + if (archive->GetNumberOfProperties(&numProps) == S_OK) + { + UInt32 mainIndex = archiveLink.Arcs[i + 1].SubfileIndex; + for (UInt32 j = 0; j < numProps; j++) + { + CMyComBSTR name; + PROPID propID; + VARTYPE vt; + RINOK(archive->GetPropertyInfo(j, &name, &propID, &vt)); + NCOM::CPropVariant prop; + RINOK(archive->GetProperty(mainIndex, propID, &prop)); + UString s = ConvertPropertyToString(prop, propID); + if (!s.IsEmpty()) + PrintPropPair(GetPropName(propID, name), s); + } + } + } + + } + g_StdOut << endl; + if (techMode) + g_StdOut << "----------\n"; + } + + if (enableHeaders && !techMode) + { + fieldPrinter.PrintTitle(); + g_StdOut << endl; + fieldPrinter.PrintTitleLines(); + g_StdOut << endl; + } + + const CArc &arc = archiveLink.Arcs.Back(); + IInArchive *archive = arc.Archive; + if (techMode) + { + RINOK(fieldPrinter.Init(archive)); + } + UInt64 numFiles = 0, numDirs = 0, totalPackSize = 0, totalUnPackSize = 0; + UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0; + UInt32 numItems; + RINOK(archive->GetNumberOfItems(&numItems)); + for (UInt32 i = 0; i < numItems; i++) + { + if (NConsoleClose::TestBreakSignal()) + return E_ABORT; + + UString filePath; + HRESULT res = arc.GetItemPath(i, filePath); + if (stdInMode && res == E_INVALIDARG) + break; + RINOK(res); + + bool isFolder; + RINOK(IsArchiveItemFolder(archive, i, isFolder)); + if (!wildcardCensor.CheckPath(filePath, !isFolder)) + continue; + + fieldPrinter.PrintItemInfo(arc, i, techMode); + + UInt64 packSize, unpackSize; + if (!GetUInt64Value(archive, i, kpidSize, unpackSize)) + unpackSize = 0; + else + totalUnPackSizePointer = &totalUnPackSize; + if (!GetUInt64Value(archive, i, kpidPackSize, packSize)) + packSize = 0; + else + totalPackSizePointer = &totalPackSize; + + g_StdOut << endl; + + if (isFolder) + numDirs++; + else + numFiles++; + totalPackSize += packSize; + totalUnPackSize += unpackSize; + } + + if (!stdInMode && totalPackSizePointer == 0) + { + if (archiveLink.VolumePaths.Size() != 0) + arcPackSize += archiveLink.VolumesSize; + totalPackSize = (numFiles == 0) ? 0 : arcPackSize; + totalPackSizePointer = &totalPackSize; + } + if (totalUnPackSizePointer == 0 && numFiles == 0) + { + totalUnPackSize = 0; + totalUnPackSizePointer = &totalUnPackSize; + } + if (enableHeaders && !techMode) + { + fieldPrinter.PrintTitleLines(); + g_StdOut << endl; + fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer); + g_StdOut << endl; + } + if (totalPackSizePointer != 0) + { + totalPackSizePointer2 = &totalPackSize2; + totalPackSize2 += totalPackSize; + } + if (totalUnPackSizePointer != 0) + { + totalUnPackSizePointer2 = &totalUnPackSize2; + totalUnPackSize2 += totalUnPackSize; + } + numFiles2 += numFiles; + numDirs2 += numDirs; + } + if (enableHeaders && !techMode && numArcs > 1) + { + g_StdOut << endl; + fieldPrinter.PrintTitleLines(); + g_StdOut << endl; + fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2); + g_StdOut << endl; + g_StdOut << "Archives: " << numArcs << endl; + } + return S_OK; +} diff --git a/CPP/7zip/UI/Console/List.h b/CPP/7zip/UI/Console/List.h new file mode 100755 index 0000000..7ea02cc --- /dev/null +++ b/CPP/7zip/UI/Console/List.h @@ -0,0 +1,20 @@ +// List.h + +#ifndef __LIST_H +#define __LIST_H + +#include "Common/Wildcard.h" +#include "../Common/LoadCodecs.h" + +HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, + bool stdInMode, + UStringVector &archivePaths, UStringVector &archivePathsFull, + const NWildcard::CCensorNode &wildcardCensor, + bool enableHeaders, bool techMode, + #ifndef _NO_CRYPTO + bool &passwordEnabled, UString &password, + #endif + UInt64 &errors); + +#endif + diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp new file mode 100755 index 0000000..8946772 --- /dev/null +++ b/CPP/7zip/UI/Console/Main.cpp @@ -0,0 +1,598 @@ +// Main.cpp + +#include "StdAfx.h" + +#if defined( _WIN32) && defined( _7ZIP_LARGE_PAGES) +#include "../../../../C/Alloc.h" +#endif + +#include "Common/MyInitGuid.h" + +#include "Common/CommandLineParser.h" +#include "Common/IntToString.h" +#include "Common/MyException.h" +#include "Common/StdOutStream.h" +#include "Common/StringConvert.h" +#include "Common/StringToInt.h" + +#include "Windows/Error.h" +#ifdef _WIN32 +#include "Windows/MemoryLock.h" +#endif + +#include "../Common/ArchiveCommandLine.h" +#include "../Common/ExitCode.h" +#include "../Common/Extract.h" +#ifdef EXTERNAL_CODECS +#include "../Common/LoadCodecs.h" +#endif + +#include "BenchCon.h" +#include "ExtractCallbackConsole.h" +#include "List.h" +#include "OpenCallbackConsole.h" +#include "UpdateCallbackConsole.h" + +#include "../../MyVersion.h" + +using namespace NWindows; +using namespace NFile; +using namespace NCommandLineParser; + +HINSTANCE g_hInstance = 0; +extern CStdOutStream *g_StdStream; + +static const char *kCopyrightString = "\n7-Zip" +#ifndef EXTERNAL_CODECS +" (A)" +#endif + +#ifdef _WIN64 +" [64]" +#endif + +" " MY_VERSION_COPYRIGHT_DATE "\n"; + +static const char *kHelpString = + "\nUsage: 7z" +#ifdef _NO_CRYPTO + "r" +#else +#ifndef EXTERNAL_CODECS + "a" +#endif +#endif + " [...] [...]\n" + " [<@listfiles...>]\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" + " l: List contents of archive\n" +// " l[a|t][f]: List contents of archive\n" +// " a - with Additional fields\n" +// " t - with all fields\n" +// " f - with Full pathnames\n" + " t: Test integrity of archive\n" + " u: Update files to archive\n" + " x: eXtract files with full paths\n" + "\n" + " -ai[r[-|0]]{@listfile|!wildcard}: Include archives\n" + " -ax[r[-|0]]{@listfile|!wildcard}: eXclude archives\n" + " -bd: Disable percentage indicator\n" + " -i[r[-|0]]{@listfile|!wildcard}: Include filenames\n" + " -m{Parameters}: set compression Method\n" + " -o{Directory}: set Output directory\n" + #ifndef _NO_CRYPTO + " -p{Password}: set Password\n" + #endif + " -r[-|0]: Recurse subdirectories\n" + " -scs{UTF-8 | WIN | DOS}: set charset for list files\n" + " -sfx[{name}]: Create SFX archive\n" + " -si[{name}]: read data from stdin\n" + " -slt: show technical information for l (List) command\n" + " -so: write data to stdout\n" + " -ssc[-]: set sensitive case mode\n" + " -ssw: compress shared files\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 *kEverythingIsOk = "Everything is Ok"; +static const char *kUserErrorMessage = "Incorrect command line"; +static const char *kNoFormats = "7-Zip cannot find the code that works with archives."; +static const char *kUnsupportedArcTypeMessage = "Unsupported archive type"; + +static const wchar_t *kDefaultSfxModule = L"7zCon.sfx"; + +static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExitCode::EEnum code) +{ + s << message << endl; + throw code; +} + +static void PrintHelpAndExit(CStdOutStream &s) +{ + s << kHelpString; + ShowMessageAndThrowException(s, kUserErrorMessage, 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 + +static void ShowCopyrightAndHelp(CStdOutStream &s, bool needHelp) +{ + s << kCopyrightString; + // s << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << "\n"; + if (needHelp) + s << kHelpString; +} + +#ifdef EXTERNAL_CODECS +static void PrintString(CStdOutStream &stdStream, const AString &s, int size) +{ + int len = s.Length(); + stdStream << s; + for (int i = len; i < size; i++) + stdStream << ' '; +} +#endif + +static void PrintString(CStdOutStream &stdStream, const UString &s, int size) +{ + int len = s.Length(); + stdStream << s; + for (int i = len; i < size; i++) + stdStream << ' '; +} + +static inline char GetHex(Byte value) +{ + return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); +} + +int Main2( + #ifndef _WIN32 + int numArgs, const 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 + + if (commandStrings.Size() == 1) + { + ShowCopyrightAndHelp(g_StdOut, true); + return 0; + } + commandStrings.Delete(0); + + CArchiveCommandLineOptions options; + + CArchiveCommandLineParser parser; + + parser.Parse1(commandStrings, options); + + if (options.HelpMode) + { + ShowCopyrightAndHelp(g_StdOut, true); + return 0; + } + + #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) + if (options.LargePages) + { + SetLargePageSize(); + NSecurity::EnableLockMemoryPrivilege(); + } + #endif + + CStdOutStream &stdStream = options.StdOutMode ? g_StdErr : g_StdOut; + g_StdStream = &stdStream; + + if (options.EnableHeaders) + ShowCopyrightAndHelp(stdStream, false); + + parser.Parse2(options); + + 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); + + bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); + + if (codecs->Formats.Size() == 0 && + (isExtractGroupCommand || + options.Command.CommandType == NCommandType::kList || + options.Command.IsFromUpdateGroup())) + throw kNoFormats; + + CIntVector formatIndices; + if (!codecs->FindFormatForArchiveType(options.ArcType, formatIndices)) + throw kUnsupportedArcTypeMessage; + + if (options.Command.CommandType == NCommandType::kInfo) + { + stdStream << endl << "Formats:" << endl; + int i; + for (i = 0; i < codecs->Formats.Size(); i++) + { + const CArcInfoEx &arc = codecs->Formats[i]; + #ifdef EXTERNAL_CODECS + if (arc.LibIndex >= 0) + { + char s[16]; + ConvertUInt32ToString(arc.LibIndex, s); + PrintString(stdStream, s, 2); + } + else + #endif + stdStream << " "; + stdStream << ' '; + stdStream << (char)(arc.UpdateEnabled ? 'C' : ' '); + stdStream << (char)(arc.KeepName ? 'K' : ' '); + stdStream << " "; + PrintString(stdStream, arc.Name, 6); + stdStream << " "; + UString s; + for (int t = 0; t < arc.Exts.Size(); t++) + { + const CArcExtInfo &ext = arc.Exts[t]; + s += ext.Ext; + if (!ext.AddExt.IsEmpty()) + { + s += L" ("; + s += ext.AddExt; + s += L')'; + } + s += L' '; + } + PrintString(stdStream, s, 14); + stdStream << " "; + const CByteBuffer &sig = arc.StartSignature; + for (size_t j = 0; j < sig.GetCapacity(); j++) + { + Byte b = sig[j]; + if (b > 0x20 && b < 0x80) + { + stdStream << (char)b; + } + else + { + stdStream << GetHex((Byte)((b >> 4) & 0xF)); + stdStream << GetHex((Byte)(b & 0xF)); + } + stdStream << ' '; + } + stdStream << endl; + } + stdStream << endl << "Codecs:" << endl; + + #ifdef EXTERNAL_CODECS + UInt32 numMethods; + if (codecs->GetNumberOfMethods(&numMethods) == S_OK) + for (UInt32 j = 0; j < numMethods; j++) + { + int libIndex = codecs->GetCodecLibIndex(j); + if (libIndex >= 0) + { + char s[16]; + ConvertUInt32ToString(libIndex, s); + PrintString(stdStream, s, 2); + } + else + stdStream << " "; + stdStream << ' '; + stdStream << (char)(codecs->GetCodecEncoderIsAssigned(j) ? 'C' : ' '); + UInt64 id; + stdStream << " "; + HRESULT res = codecs->GetCodecId(j, id); + if (res != S_OK) + id = (UInt64)(Int64)-1; + char s[32]; + ConvertUInt64ToString(id, s, 16); + PrintString(stdStream, s, 8); + stdStream << " "; + PrintString(stdStream, codecs->GetCodecName(j), 11); + stdStream << endl; + /* + if (res != S_OK) + throw "incorrect Codec ID"; + */ + } + #endif + return S_OK; + } + else if (options.Command.CommandType == NCommandType::kBenchmark) + { + if (options.Method.CompareNoCase(L"CRC") == 0) + { + HRESULT res = CrcBenchCon((FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize); + if (res != S_OK) + { + if (res == S_FALSE) + { + stdStream << "\nCRC Error\n"; + return NExitCode::kFatalError; + } + throw CSystemException(res); + } + } + else + { + HRESULT res; + #ifdef EXTERNAL_CODECS + CObjectVector externalCodecs; + res = LoadExternalCodecs(compressCodecsInfo, externalCodecs); + if (res != S_OK) + throw CSystemException(res); + #endif + res = LzmaBenchCon( + #ifdef EXTERNAL_CODECS + compressCodecsInfo, &externalCodecs, + #endif + (FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize); + if (res != S_OK) + { + if (res == S_FALSE) + { + stdStream << "\nDecoding Error\n"; + return NExitCode::kFatalError; + } + throw CSystemException(res); + } + } + } + else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) + { + if (isExtractGroupCommand) + { + CExtractCallbackConsole *ecs = new CExtractCallbackConsole; + CMyComPtr extractCallback = ecs; + + ecs->OutStream = &stdStream; + + #ifndef _NO_CRYPTO + ecs->PasswordIsDefined = options.PasswordEnabled; + ecs->Password = options.Password; + #endif + + ecs->Init(); + + COpenCallbackConsole openCallback; + openCallback.OutStream = &stdStream; + + #ifndef _NO_CRYPTO + openCallback.PasswordIsDefined = options.PasswordEnabled; + openCallback.Password = options.Password; + #endif + + CExtractOptions eo; + eo.StdInMode = options.StdInMode; + eo.StdOutMode = options.StdOutMode; + eo.PathMode = options.Command.GetPathMode(); + eo.TestMode = options.Command.IsTestMode(); + eo.OverwriteMode = options.OverwriteMode; + eo.OutputDir = options.OutputDir; + eo.YesToAll = options.YesToAll; + eo.CalcCrc = options.CalcCrc; + #if !defined(_7ZIP_ST) && !defined(_SFX) + eo.Properties = options.ExtractProperties; + #endif + UString errorMessage; + CDecompressStat stat; + HRESULT result = DecompressArchives( + codecs, + formatIndices, + options.ArchivePathsSorted, + options.ArchivePathsFullSorted, + options.WildcardCensor.Pairs.Front().Head, + eo, &openCallback, ecs, errorMessage, stat); + if (!errorMessage.IsEmpty()) + { + stdStream << endl << "Error: " << errorMessage; + if (result == S_OK) + result = E_FAIL; + } + + stdStream << endl; + if (ecs->NumArchives > 1) + stdStream << "Archives: " << ecs->NumArchives << endl; + if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0) + { + if (ecs->NumArchives > 1) + { + stdStream << endl; + if (ecs->NumArchiveErrors != 0) + stdStream << "Archive Errors: " << ecs->NumArchiveErrors << endl; + if (ecs->NumFileErrors != 0) + stdStream << "Sub items Errors: " << ecs->NumFileErrors << endl; + } + if (result != S_OK) + throw CSystemException(result); + return NExitCode::kFatalError; + } + if (result != S_OK) + throw CSystemException(result); + if (stat.NumFolders != 0) + stdStream << "Folders: " << stat.NumFolders << endl; + if (stat.NumFiles != 1 || stat.NumFolders != 0) + stdStream << "Files: " << stat.NumFiles << endl; + stdStream + << "Size: " << stat.UnpackSize << endl + << "Compressed: " << stat.PackSize << endl; + if (options.CalcCrc) + { + char s[16]; + ConvertUInt32ToHexWithZeros(stat.CrcSum, s); + stdStream << "CRC: " << s << endl; + } + } + else + { + UInt64 numErrors = 0; + HRESULT result = ListArchives( + codecs, + formatIndices, + options.StdInMode, + options.ArchivePathsSorted, + options.ArchivePathsFullSorted, + options.WildcardCensor.Pairs.Front().Head, + options.EnableHeaders, + options.TechMode, + #ifndef _NO_CRYPTO + options.PasswordEnabled, + options.Password, + #endif + numErrors); + if (numErrors > 0) + { + g_StdOut << endl << "Errors: " << numErrors; + return NExitCode::kFatalError; + } + if (result != S_OK) + throw CSystemException(result); + } + } + else if (options.Command.IsFromUpdateGroup()) + { + CUpdateOptions &uo = options.UpdateOptions; + if (uo.SfxMode && uo.SfxModule.IsEmpty()) + uo.SfxModule = kDefaultSfxModule; + + COpenCallbackConsole openCallback; + openCallback.OutStream = &stdStream; + + #ifndef _NO_CRYPTO + bool passwordIsDefined = + options.PasswordEnabled && !options.Password.IsEmpty(); + openCallback.PasswordIsDefined = passwordIsDefined; + openCallback.Password = options.Password; + #endif + + CUpdateCallbackConsole callback; + callback.EnablePercents = options.EnablePercents; + + #ifndef _NO_CRYPTO + callback.PasswordIsDefined = passwordIsDefined; + callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty(); + callback.Password = options.Password; + #endif + callback.StdOutMode = uo.StdOutMode; + callback.Init(&stdStream); + + CUpdateErrorInfo errorInfo; + + if (!uo.Init(codecs, formatIndices, options.ArchiveName)) + throw kUnsupportedArcTypeMessage; + HRESULT result = UpdateArchive(codecs, + options.WildcardCensor, uo, + errorInfo, &openCallback, &callback); + + int exitCode = NExitCode::kSuccess; + if (callback.CantFindFiles.Size() > 0) + { + stdStream << endl; + stdStream << "WARNINGS for files:" << endl << endl; + int numErrors = callback.CantFindFiles.Size(); + for (int i = 0; i < numErrors; i++) + { + stdStream << callback.CantFindFiles[i] << " : "; + stdStream << NError::MyFormatMessageW(callback.CantFindCodes[i]) << endl; + } + stdStream << "----------------" << endl; + stdStream << "WARNING: Cannot find " << numErrors << " file"; + if (numErrors > 1) + stdStream << "s"; + stdStream << endl; + exitCode = NExitCode::kWarning; + } + + if (result != S_OK) + { + UString message; + if (!errorInfo.Message.IsEmpty()) + { + message += errorInfo.Message; + message += L"\n"; + } + if (!errorInfo.FileName.IsEmpty()) + { + message += errorInfo.FileName; + message += L"\n"; + } + if (!errorInfo.FileName2.IsEmpty()) + { + message += errorInfo.FileName2; + message += L"\n"; + } + if (errorInfo.SystemError != 0) + { + message += NError::MyFormatMessageW(errorInfo.SystemError); + message += L"\n"; + } + if (!message.IsEmpty()) + stdStream << L"\nError:\n" << message; + throw CSystemException(result); + } + int numErrors = callback.FailedFiles.Size(); + if (numErrors == 0) + { + if (callback.CantFindFiles.Size() == 0) + stdStream << kEverythingIsOk << endl; + } + else + { + stdStream << endl; + stdStream << "WARNINGS for files:" << endl << endl; + for (int i = 0; i < numErrors; i++) + { + stdStream << callback.FailedFiles[i] << " : "; + stdStream << NError::MyFormatMessageW(callback.FailedCodes[i]) << endl; + } + stdStream << "----------------" << endl; + stdStream << "WARNING: Cannot open " << numErrors << " file"; + if (numErrors > 1) + stdStream << "s"; + stdStream << endl; + exitCode = NExitCode::kWarning; + } + return exitCode; + } + else + PrintHelpAndExit(stdStream); + return 0; +} diff --git a/CPP/7zip/UI/Console/MainAr.cpp b/CPP/7zip/UI/Console/MainAr.cpp new file mode 100755 index 0000000..b6681b4 --- /dev/null +++ b/CPP/7zip/UI/Console/MainAr.cpp @@ -0,0 +1,125 @@ +// MainAr.cpp + +#include "StdAfx.h" + +#include "Common/MyException.h" +#include "Common/StdOutStream.h" + +#include "Windows/Error.h" +#include "Windows/NtCheck.h" + +#include "../Common/ArchiveCommandLine.h" +#include "../Common/ExitCode.h" + +#include "ConsoleClose.h" + +using namespace NWindows; + +CStdOutStream *g_StdStream = 0; + +extern int Main2( + #ifndef _WIN32 + int numArgs, const char *args[] + #endif +); + +static const char *kExceptionErrorMessage = "\n\nError:\n"; +static const char *kUserBreak = "\nBreak signaled\n"; +static const char *kMemoryExceptionMessage = "\n\nERROR: Can't allocate required memory!\n"; +static const char *kUnknownExceptionMessage = "\n\nUnknown Error\n"; +static const char *kInternalExceptionMessage = "\n\nInternal Error #"; + +#define NT_CHECK_FAIL_ACTION (*g_StdStream) << "Unsupported Windows version"; return NExitCode::kFatalError; + +int MY_CDECL main +( + #ifndef _WIN32 + int numArgs, const char *args[] + #endif +) +{ + g_StdStream = &g_StdOut; + + NT_CHECK + + NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter; + int res = 0; + try + { + res = Main2( + #ifndef _WIN32 + numArgs, args + #endif + ); + } + catch(const CNewException &) + { + (*g_StdStream) << kMemoryExceptionMessage; + return (NExitCode::kMemoryError); + } + catch(const NConsoleClose::CCtrlBreakException &) + { + (*g_StdStream) << endl << kUserBreak; + return (NExitCode::kUserBreak); + } + catch(const CArchiveCommandLineException &e) + { + (*g_StdStream) << kExceptionErrorMessage << e << endl; + return (NExitCode::kUserError); + } + catch(const CSystemException &systemError) + { + if (systemError.ErrorCode == E_OUTOFMEMORY) + { + (*g_StdStream) << kMemoryExceptionMessage; + return (NExitCode::kMemoryError); + } + if (systemError.ErrorCode == E_ABORT) + { + (*g_StdStream) << endl << kUserBreak; + return (NExitCode::kUserBreak); + } + UString message; + NError::MyFormatMessage(systemError.ErrorCode, message); + (*g_StdStream) << endl << endl << "System error:" << endl << message << endl; + return (NExitCode::kFatalError); + } + catch(NExitCode::EEnum &exitCode) + { + (*g_StdStream) << kInternalExceptionMessage << exitCode << endl; + return (exitCode); + } + /* + catch(const NExitCode::CMultipleErrors &multipleErrors) + { + (*g_StdStream) << endl << multipleErrors.NumErrors << " errors" << endl; + return (NExitCode::kFatalError); + } + */ + catch(const UString &s) + { + (*g_StdStream) << kExceptionErrorMessage << s << endl; + return (NExitCode::kFatalError); + } + catch(const AString &s) + { + (*g_StdStream) << kExceptionErrorMessage << s << endl; + return (NExitCode::kFatalError); + } + catch(const char *s) + { + (*g_StdStream) << kExceptionErrorMessage << s << endl; + return (NExitCode::kFatalError); + } + catch(int t) + { + (*g_StdStream) << kInternalExceptionMessage << t << endl; + return (NExitCode::kFatalError); + } + catch(...) + { + (*g_StdStream) << kUnknownExceptionMessage; + return (NExitCode::kFatalError); + } + return res; +} diff --git a/CPP/7zip/UI/Console/OpenCallbackConsole.cpp b/CPP/7zip/UI/Console/OpenCallbackConsole.cpp new file mode 100755 index 0000000..986a592 --- /dev/null +++ b/CPP/7zip/UI/Console/OpenCallbackConsole.cpp @@ -0,0 +1,58 @@ +// OpenCallbackConsole.cpp + +#include "StdAfx.h" + +#include "OpenCallbackConsole.h" + +#include "ConsoleClose.h" +#include "UserInputUtils.h" + +HRESULT COpenCallbackConsole::Open_CheckBreak() +{ + if (NConsoleClose::TestBreakSignal()) + return E_ABORT; + return S_OK; +} + +HRESULT COpenCallbackConsole::Open_SetTotal(const UInt64 *, const UInt64 *) +{ + return Open_CheckBreak(); +} + +HRESULT COpenCallbackConsole::Open_SetCompleted(const UInt64 *, const UInt64 *) +{ + return Open_CheckBreak(); +} + +#ifndef _NO_CRYPTO + +HRESULT COpenCallbackConsole::Open_CryptoGetTextPassword(BSTR *password) +{ + PasswordWasAsked = true; + RINOK(Open_CheckBreak()); + if (!PasswordIsDefined) + { + Password = GetPassword(OutStream); + PasswordIsDefined = true; + } + return StringToBstr(Password, password); +} + +HRESULT COpenCallbackConsole::Open_GetPasswordIfAny(UString &password) +{ + if (PasswordIsDefined) + password = Password; + return S_OK; +} + +bool COpenCallbackConsole::Open_WasPasswordAsked() +{ + return PasswordWasAsked; +} + +void COpenCallbackConsole::Open_ClearPasswordWasAskedFlag() +{ + PasswordWasAsked = false; +} + +#endif diff --git a/CPP/7zip/UI/Console/OpenCallbackConsole.h b/CPP/7zip/UI/Console/OpenCallbackConsole.h new file mode 100755 index 0000000..99e8c04 --- /dev/null +++ b/CPP/7zip/UI/Console/OpenCallbackConsole.h @@ -0,0 +1,24 @@ +// OpenCallbackConsole.h + +#ifndef __OPENCALLBACKCONSOLE_H +#define __OPENCALLBACKCONSOLE_H + +#include "Common/StdOutStream.h" +#include "../Common/ArchiveOpenCallback.h" + +class COpenCallbackConsole: public IOpenCallbackUI +{ +public: + INTERFACE_IOpenCallbackUI(;) + + CStdOutStream *OutStream; + + #ifndef _NO_CRYPTO + bool PasswordIsDefined; + bool PasswordWasAsked; + UString Password; + COpenCallbackConsole(): PasswordIsDefined(false), PasswordWasAsked(false) {} + #endif +}; + +#endif diff --git a/CPP/7zip/UI/Console/PercentPrinter.cpp b/CPP/7zip/UI/Console/PercentPrinter.cpp new file mode 100755 index 0000000..111ae25 --- /dev/null +++ b/CPP/7zip/UI/Console/PercentPrinter.cpp @@ -0,0 +1,90 @@ +// PercentPrinter.cpp + +#include "StdAfx.h" + +#include "Common/IntToString.h" +#include "Common/MyString.h" + +#include "PercentPrinter.h" + +const int kPaddingSize = 2; +const int kPercentsSize = 4; +const int kMaxExtraSize = kPaddingSize + 32 + kPercentsSize; + +static void ClearPrev(char *p, int num) +{ + int i; + for (i = 0; i < num; i++) *p++ = '\b'; + for (i = 0; i < num; i++) *p++ = ' '; + for (i = 0; i < num; i++) *p++ = '\b'; + *p = '\0'; +} + +void CPercentPrinter::ClosePrint() +{ + if (m_NumExtraChars == 0) + return; + char s[kMaxExtraSize * 3 + 1]; + ClearPrev(s, m_NumExtraChars); + (*OutStream) << s; + m_NumExtraChars = 0; +} + +void CPercentPrinter::PrintString(const char *s) +{ + ClosePrint(); + (*OutStream) << s; +} + +void CPercentPrinter::PrintString(const wchar_t *s) +{ + ClosePrint(); + (*OutStream) << s; +} + +void CPercentPrinter::PrintNewLine() +{ + ClosePrint(); + (*OutStream) << "\n"; +} + +void CPercentPrinter::RePrintRatio() +{ + char s[32]; + ConvertUInt64ToString(((m_Total == 0) ? 0 : (m_CurValue * 100 / m_Total)), s); + int size = (int)strlen(s); + s[size++] = '%'; + s[size] = '\0'; + + int extraSize = kPaddingSize + MyMax(size, kPercentsSize); + if (extraSize < m_NumExtraChars) + extraSize = m_NumExtraChars; + + char fullString[kMaxExtraSize * 3]; + char *p = fullString; + int i; + if (m_NumExtraChars == 0) + { + for (i = 0; i < extraSize; i++) + *p++ = ' '; + m_NumExtraChars = extraSize; + } + + for (i = 0; i < m_NumExtraChars; i++) + *p++ = '\b'; + m_NumExtraChars = extraSize; + for (; size < m_NumExtraChars; size++) + *p++ = ' '; + MyStringCopy(p, s); + (*OutStream) << fullString; + OutStream->Flush(); + m_PrevValue = m_CurValue; +} + +void CPercentPrinter::PrintRatio() +{ + if (m_CurValue < m_PrevValue + m_MinStepSize && + m_CurValue + m_MinStepSize > m_PrevValue && m_NumExtraChars != 0) + return; + RePrintRatio(); +} diff --git a/CPP/7zip/UI/Console/PercentPrinter.h b/CPP/7zip/UI/Console/PercentPrinter.h new file mode 100755 index 0000000..212e11e --- /dev/null +++ b/CPP/7zip/UI/Console/PercentPrinter.h @@ -0,0 +1,31 @@ +// PercentPrinter.h + +#ifndef __PERCENTPRINTER_H +#define __PERCENTPRINTER_H + +#include "Common/Types.h" +#include "Common/StdOutStream.h" + +class CPercentPrinter +{ + UInt64 m_MinStepSize; + UInt64 m_PrevValue; + UInt64 m_CurValue; + UInt64 m_Total; + int m_NumExtraChars; +public: + CStdOutStream *OutStream; + + CPercentPrinter(UInt64 minStepSize = 1): m_MinStepSize(minStepSize), + m_PrevValue(0), m_CurValue(0), m_Total(1), m_NumExtraChars(0) {} + void SetTotal(UInt64 total) { m_Total = total; m_PrevValue = 0; } + void SetRatio(UInt64 doneValue) { m_CurValue = doneValue; } + void PrintString(const char *s); + void PrintString(const wchar_t *s); + void PrintNewLine(); + void ClosePrint(); + void RePrintRatio(); + void PrintRatio(); +}; + +#endif diff --git a/CPP/7zip/UI/Console/StdAfx.cpp b/CPP/7zip/UI/Console/StdAfx.cpp new file mode 100755 index 0000000..c6d3b1f --- /dev/null +++ b/CPP/7zip/UI/Console/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/UI/Console/StdAfx.h b/CPP/7zip/UI/Console/StdAfx.h new file mode 100755 index 0000000..a4e6173 --- /dev/null +++ b/CPP/7zip/UI/Console/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" +#include "../../../Common/NewHandler.h" + +#endif diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp new file mode 100755 index 0000000..c482676 --- /dev/null +++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp @@ -0,0 +1,261 @@ +// UpdateCallbackConsole.cpp + +#include "StdAfx.h" + +#include "UpdateCallbackConsole.h" + +#include "Windows/Error.h" +#ifndef _7ZIP_ST +#include "Windows/Synchronization.h" +#endif + +#include "ConsoleClose.h" +#include "UserInputUtils.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 *kEmptyFileAlias = L"[Content]"; + +static const char *kCreatingArchiveMessage = "Creating archive "; +static const char *kUpdatingArchiveMessage = "Updating archive "; +static const char *kScanningMessage = "Scanning"; + + +HRESULT CUpdateCallbackConsole::OpenResult(const wchar_t *name, HRESULT result) +{ + (*OutStream) << endl; + if (result != S_OK) + (*OutStream) << "Error: " << name << " is not supported archive" << endl; + return S_OK; +} + +HRESULT CUpdateCallbackConsole::StartScanning() +{ + (*OutStream) << kScanningMessage; + return S_OK; +} + +HRESULT CUpdateCallbackConsole::ScanProgress(UInt64 /* numFolders */, UInt64 /* numFiles */, const wchar_t * /* path */) +{ + return CheckBreak(); +} + +HRESULT CUpdateCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError) +{ + CantFindFiles.Add(name); + CantFindCodes.Add(systemError); + // m_PercentPrinter.ClosePrint(); + if (!m_WarningsMode) + { + (*OutStream) << endl << endl; + m_PercentPrinter.PrintNewLine(); + m_WarningsMode = true; + } + m_PercentPrinter.PrintString(name); + m_PercentPrinter.PrintString(": WARNING: "); + m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError)); + m_PercentPrinter.PrintNewLine(); + return S_OK; +} + +HRESULT CUpdateCallbackConsole::FinishScanning() +{ + (*OutStream) << endl << endl; + return S_OK; +} + +HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating) +{ + if(updating) + (*OutStream) << kUpdatingArchiveMessage; + else + (*OutStream) << kCreatingArchiveMessage; + if (name != 0) + (*OutStream) << name; + else + (*OutStream) << "StdOut"; + (*OutStream) << endl << endl; + return S_OK; +} + +HRESULT CUpdateCallbackConsole::FinishArchive() +{ + (*OutStream) << endl; + return S_OK; +} + +HRESULT CUpdateCallbackConsole::CheckBreak() +{ + if (NConsoleClose::TestBreakSignal()) + return E_ABORT; + return S_OK; +} + +HRESULT CUpdateCallbackConsole::Finilize() +{ + MT_LOCK + if (m_NeedBeClosed) + { + if (EnablePercents) + { + m_PercentPrinter.ClosePrint(); + } + if (!StdOutMode && m_NeedNewLine) + { + m_PercentPrinter.PrintNewLine(); + m_NeedNewLine = false; + } + m_NeedBeClosed = false; + } + return S_OK; +} + +HRESULT CUpdateCallbackConsole::SetNumFiles(UInt64 /* numFiles */) +{ + return S_OK; +} + +HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size) +{ + MT_LOCK + if (EnablePercents) + m_PercentPrinter.SetTotal(size); + return S_OK; +} + +HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue) +{ + MT_LOCK + if (completeValue != NULL) + { + if (EnablePercents) + { + m_PercentPrinter.SetRatio(*completeValue); + m_PercentPrinter.PrintRatio(); + m_NeedBeClosed = true; + } + } + if (NConsoleClose::TestBreakSignal()) + return E_ABORT; + return S_OK; +} + +HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */) +{ + if (NConsoleClose::TestBreakSignal()) + return E_ABORT; + return S_OK; +} + +HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool isAnti) +{ + MT_LOCK + if (StdOutMode) + return S_OK; + if(isAnti) + m_PercentPrinter.PrintString("Anti item "); + else + m_PercentPrinter.PrintString("Compressing "); + if (name[0] == 0) + name = kEmptyFileAlias; + m_PercentPrinter.PrintString(name); + if (EnablePercents) + m_PercentPrinter.RePrintRatio(); + return S_OK; +} + +HRESULT CUpdateCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemError) +{ + MT_LOCK + FailedCodes.Add(systemError); + FailedFiles.Add(name); + // if (systemError == ERROR_SHARING_VIOLATION) + { + m_PercentPrinter.ClosePrint(); + m_PercentPrinter.PrintNewLine(); + m_PercentPrinter.PrintString("WARNING: "); + m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError)); + return S_FALSE; + } + // return systemError; +} + +HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 ) +{ + m_NeedBeClosed = true; + m_NeedNewLine = true; + return S_OK; +} + +HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) +{ + *password = NULL; + + #ifdef _NO_CRYPTO + + *passwordIsDefined = false; + return S_OK; + + #else + + if (!PasswordIsDefined) + { + if (AskPassword) + { + Password = GetPassword(OutStream); + PasswordIsDefined = true; + } + } + *passwordIsDefined = BoolToInt(PasswordIsDefined); + return StringToBstr(Password, password); + + #endif +} + +HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password) +{ + *password = NULL; + + #ifdef _NO_CRYPTO + + return E_NOTIMPL; + + #else + + if (!PasswordIsDefined) + { + { + Password = GetPassword(OutStream); + PasswordIsDefined = true; + } + } + return StringToBstr(Password, password); + + #endif +} + +/* +HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name) +{ + // MT_LOCK + if (StdOutMode) + return S_OK; + RINOK(Finilize()); + m_PercentPrinter.PrintString("Deleting "); + if (name[0] == 0) + name = kEmptyFileAlias; + m_PercentPrinter.PrintString(name); + if (EnablePercents) + m_PercentPrinter.RePrintRatio(); + m_NeedBeClosed = true; + m_NeedNewLine = true; + return S_OK; +} +*/ diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.h b/CPP/7zip/UI/Console/UpdateCallbackConsole.h new file mode 100755 index 0000000..59581f3 --- /dev/null +++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.h @@ -0,0 +1,62 @@ +// UpdateCallbackConsole.h + +#ifndef __UPDATE_CALLBACK_CONSOLE_H +#define __UPDATE_CALLBACK_CONSOLE_H + +#include "Common/StdOutStream.h" + +#include "../Common/Update.h" + +#include "PercentPrinter.h" + +class CUpdateCallbackConsole: public IUpdateCallbackUI2 +{ + CPercentPrinter m_PercentPrinter; + bool m_NeedBeClosed; + bool m_NeedNewLine; + + bool m_WarningsMode; + + CStdOutStream *OutStream; +public: + bool EnablePercents; + bool StdOutMode; + + #ifndef _NO_CRYPTO + bool PasswordIsDefined; + UString Password; + bool AskPassword; + #endif + + CUpdateCallbackConsole(): + m_PercentPrinter(1 << 16), + #ifndef _NO_CRYPTO + PasswordIsDefined(false), + AskPassword(false), + #endif + StdOutMode(false), + EnablePercents(true), + m_WarningsMode(false) + {} + + ~CUpdateCallbackConsole() { Finilize(); } + void Init(CStdOutStream *outStream) + { + m_NeedBeClosed = false; + m_NeedNewLine = false; + FailedFiles.Clear(); + FailedCodes.Clear(); + OutStream = outStream; + m_PercentPrinter.OutStream = outStream; + } + + INTERFACE_IUpdateCallbackUI2(;) + + UStringVector FailedFiles; + CRecordVector FailedCodes; + + UStringVector CantFindFiles; + CRecordVector CantFindCodes; +}; + +#endif diff --git a/CPP/7zip/UI/Console/UserInputUtils.cpp b/CPP/7zip/UI/Console/UserInputUtils.cpp new file mode 100755 index 0000000..68481c2 --- /dev/null +++ b/CPP/7zip/UI/Console/UserInputUtils.cpp @@ -0,0 +1,87 @@ +// 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 *kFirstQuestionMessage = "?\n"; +static const char *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) +{ + (*outStream) << kFirstQuestionMessage; + for (;;) + { + (*outStream) << kHelpQuestionMessage; + outStream->Flush(); + AString scannedString = g_StdIn.ScanStringUntilNewLine(); + scannedString.Trim(); + if (!scannedString.IsEmpty()) + switch( + ::MyCharUpper( + #ifdef UNDER_CE + (wchar_t) + #endif + 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 + +UString GetPassword(CStdOutStream *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); + UString res = g_StdIn.ScanUStringUntilNewLine(); + if (wasChanged) + SetConsoleMode(console, mode); + (*outStream) << "\n"; + outStream->Flush(); + return res; + #else + return g_StdIn.ScanUStringUntilNewLine(); + #endif +} diff --git a/CPP/7zip/UI/Console/UserInputUtils.h b/CPP/7zip/UI/Console/UserInputUtils.h new file mode 100755 index 0000000..3740ad7 --- /dev/null +++ b/CPP/7zip/UI/Console/UserInputUtils.h @@ -0,0 +1,24 @@ +// UserInputUtils.h + +#ifndef __USERINPUTUTILS_H +#define __USERINPUTUTILS_H + +#include "Common/StdOutStream.h" + +namespace NUserAnswerMode { + +enum EEnum +{ + kYes, + kNo, + kYesAll, + kNoAll, + kAutoRenameAll, + kQuit +}; +} + +NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream); +UString GetPassword(CStdOutStream *outStream); + +#endif diff --git a/CPP/7zip/UI/Console/makefile b/CPP/7zip/UI/Console/makefile new file mode 100755 index 0000000..0d40eb5 --- /dev/null +++ b/CPP/7zip/UI/Console/makefile @@ -0,0 +1,124 @@ +PROG = 7z.exe +MY_CONSOLE = 1 +CFLAGS = $(CFLAGS) -I ../../../ \ + -DEXTERNAL_CODECS \ + +!IFNDEF UNDER_CE +CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -D_7ZIP_LARGE_PAGES -DSUPPORT_DEVICE_FILE +!ENDIF + + +CONSOLE_OBJS = \ + $O\ConsoleClose.obj \ + $O\ExtractCallbackConsole.obj \ + $O\List.obj \ + $O\BenchCon.obj \ + $O\Main.obj \ + $O\MainAr.obj \ + $O\OpenCallbackConsole.obj \ + $O\PercentPrinter.obj \ + $O\UpdateCallbackConsole.obj \ + $O\UserInputUtils.obj \ + +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\Error.obj \ + $O\FileDir.obj \ + $O\FileFind.obj \ + $O\FileIO.obj \ + $O\FileName.obj \ + $O\MemoryLock.obj \ + $O\PropVariant.obj \ + $O\PropVariantConversions.obj \ + $O\Registry.obj \ + $O\System.obj \ + $O\Time.obj \ + +7ZIP_COMMON_OBJS = \ + $O\CreateCoder.obj \ + $O\FilePathAutoRename.obj \ + $O\FileStreams.obj \ + $O\FilterCoder.obj \ + $O\ProgressUtils.obj \ + $O\StreamUtils.obj \ + +UI_COMMON_OBJS = \ + $O\ArchiveCommandLine.obj \ + $O\ArchiveExtractCallback.obj \ + $O\ArchiveOpenCallback.obj \ + $O\DefaultName.obj \ + $O\EnumDirItems.obj \ + $O\Extract.obj \ + $O\ExtractingFilePath.obj \ + $O\Bench.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 \ + $O\WorkDir.obj \ + +AR_COMMON_OBJS = \ + $O\OutStreamWithCRC.obj \ + +C_OBJS = \ + $O\Alloc.obj \ + $O\CpuArch.obj \ + $O\Threads.obj \ + +!include "../../Crc.mak" + +OBJS = \ + $O\StdAfx.obj \ + $(CONSOLE_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(UI_COMMON_OBJS) \ + $(AR_COMMON_OBJS) \ + $O\CopyCoder.obj \ + $(C_OBJS) \ + $(ASM_OBJS) \ + $O\resource.res + +!include "../../../Build.mak" + +$(CONSOLE_OBJS): $(*B).cpp + $(COMPL) +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) +$(UI_COMMON_OBJS): ../Common/$(*B).cpp + $(COMPL) +$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp + $(COMPL) +$O\CopyCoder.obj: ../../Compress/$(*B).cpp + $(COMPL) +$(C_OBJS): ../../../../C/$(*B).c + $(COMPL_O2) + +!include "../../Asm.mak" diff --git a/CPP/7zip/UI/Console/resource.rc b/CPP/7zip/UI/Console/resource.rc new file mode 100755 index 0000000..20dfee1 --- /dev/null +++ b/CPP/7zip/UI/Console/resource.rc @@ -0,0 +1,3 @@ +#include "../../MyVersionInfo.rc" + +MY_VERSION_INFO_APP("7-Zip Console", "7z") diff --git a/CPP/7zip/UI/Explorer/7-zip.dll.manifest b/CPP/7zip/UI/Explorer/7-zip.dll.manifest new file mode 100755 index 0000000..9276dfb --- /dev/null +++ b/CPP/7zip/UI/Explorer/7-zip.dll.manifest @@ -0,0 +1 @@ +7-Zip Extension. diff --git a/CPP/7zip/UI/Explorer/ContextMenu.cpp b/CPP/7zip/UI/Explorer/ContextMenu.cpp new file mode 100755 index 0000000..b6d7d10 --- /dev/null +++ b/CPP/7zip/UI/Explorer/ContextMenu.cpp @@ -0,0 +1,829 @@ +// ContextMenu.cpp + +#include "StdAfx.h" + +#include "ContextMenu.h" + +#include "Common/StringConvert.h" + +#include "Windows/COM.h" +#include "Windows/FileDir.h" +#include "Windows/FileFind.h" +#include "Windows/Memory.h" +#include "Windows/Menu.h" +#include "Windows/Process.h" +#include "Windows/Shell.h" + +#include "../Common/ArchiveName.h" +#include "../Common/CompressCall.h" +#include "../Common/ExtractingFilePath.h" +#include "../Common/ZipRegistry.h" + +#include "../FileManager/FormatUtils.h" +#include "../FileManager/ProgramLocation.h" + +#ifdef LANG +#include "../FileManager/LangUtils.h" +#endif + +#include "ContextMenuFlags.h" +#include "MyMessages.h" + +#include "resource.h" + +using namespace NWindows; + + +#ifndef UNDER_CE +#define EMAIL_SUPPORT 1 +#endif + +extern LONG g_DllRefCount; + +CZipContextMenu::CZipContextMenu() { InterlockedIncrement(&g_DllRefCount); } +CZipContextMenu::~CZipContextMenu() { InterlockedDecrement(&g_DllRefCount); } + +HRESULT CZipContextMenu::GetFileNames(LPDATAOBJECT dataObject, UStringVector &fileNames) +{ + #ifndef UNDER_CE + fileNames.Clear(); + if (dataObject == NULL) + return E_FAIL; + FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; + NCOM::CStgMedium stgMedium; + HRESULT result = dataObject->GetData(&fmte, &stgMedium); + if (result != S_OK) + return result; + stgMedium._mustBeReleased = true; + + NShell::CDrop drop(false); + NMemory::CGlobalLock globalLock(stgMedium->hGlobal); + drop.Attach((HDROP)globalLock.GetPointer()); + drop.QueryFileNames(fileNames); + #endif + return S_OK; +} + +// IShellExtInit + +STDMETHODIMP CZipContextMenu::Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT dataObject, HKEY /* hkeyProgID */) +{ + // OutputDebugString(TEXT("::Initialize\r\n")); + _dropMode = false; + _dropPath.Empty(); + if (pidlFolder != 0) + { + #ifndef UNDER_CE + if (NShell::GetPathFromIDList(pidlFolder, _dropPath)) + { + // OutputDebugString(path); + // OutputDebugString(TEXT("\r\n")); + NFile::NName::NormalizeDirPathPrefix(_dropPath); + _dropMode = !_dropPath.IsEmpty(); + } + else + #endif + _dropPath.Empty(); + } + + /* + m_IsFolder = false; + if (pidlFolder == 0) + */ + // pidlFolder is NULL :( + return GetFileNames(dataObject, _fileNames); +} + +HRESULT CZipContextMenu::InitContextMenu(const wchar_t * /* folder */, const wchar_t **names, UInt32 numFiles) +{ + _fileNames.Clear(); + for (UInt32 i = 0; i < numFiles; i++) + _fileNames.Add(names[i]); + _dropMode = false; + return S_OK; +} + + +///////////////////////////// +// IContextMenu + +static LPCWSTR kMainVerb = L"SevenZip"; + +/* +static LPCTSTR kOpenVerb = TEXT("SevenOpen"); +static LPCTSTR kExtractVerb = TEXT("SevenExtract"); +static LPCTSTR kExtractHereVerb = TEXT("SevenExtractHere"); +static LPCTSTR kExtractToVerb = TEXT("SevenExtractTo"); +static LPCTSTR kTestVerb = TEXT("SevenTest"); +static LPCTSTR kCompressVerb = TEXT("SevenCompress"); +static LPCTSTR kCompressToVerb = TEXT("SevenCompressTo"); +static LPCTSTR kCompressEmailVerb = TEXT("SevenCompressEmail"); +static LPCTSTR kCompressToEmailVerb = TEXT("SevenCompressToEmail"); +*/ + +struct CContextMenuCommand +{ + UInt32 flag; + CZipContextMenu::ECommandInternalID CommandInternalID; + LPCWSTR Verb; + UINT ResourceID; + UINT ResourceHelpID; + UInt32 LangID; +}; + +static CContextMenuCommand g_Commands[] = +{ + { + NContextMenuFlags::kOpen, + CZipContextMenu::kOpen, + L"Open", + IDS_CONTEXT_OPEN, + IDS_CONTEXT_OPEN_HELP, + 0x02000103 + }, + { + NContextMenuFlags::kExtract, + CZipContextMenu::kExtract, + L"Extract", + IDS_CONTEXT_EXTRACT, + IDS_CONTEXT_EXTRACT_HELP, + 0x02000105 + }, + { + NContextMenuFlags::kExtractHere, + CZipContextMenu::kExtractHere, + L"ExtractHere", + IDS_CONTEXT_EXTRACT_HERE, + IDS_CONTEXT_EXTRACT_HERE_HELP, + 0x0200010B + }, + { + NContextMenuFlags::kExtractTo, + CZipContextMenu::kExtractTo, + L"ExtractTo", + IDS_CONTEXT_EXTRACT_TO, + IDS_CONTEXT_EXTRACT_TO_HELP, + 0x0200010D + }, + { + NContextMenuFlags::kTest, + CZipContextMenu::kTest, + L"Test", + IDS_CONTEXT_TEST, + IDS_CONTEXT_TEST_HELP, + 0x02000109 + }, + { + NContextMenuFlags::kCompress, + CZipContextMenu::kCompress, + L"Compress", + IDS_CONTEXT_COMPRESS, + IDS_CONTEXT_COMPRESS_HELP, + 0x02000107, + }, + { + NContextMenuFlags::kCompressEmail, + CZipContextMenu::kCompressEmail, + L"CompressEmail", + IDS_CONTEXT_COMPRESS_EMAIL, + IDS_CONTEXT_COMPRESS_EMAIL_HELP, + 0x02000111 + }, + { + NContextMenuFlags::kCompressTo7z, + CZipContextMenu::kCompressTo7z, + L"CompressTo7z", + IDS_CONTEXT_COMPRESS_TO, + IDS_CONTEXT_COMPRESS_TO_HELP, + 0x0200010F + }, + { + NContextMenuFlags::kCompressTo7zEmail, + CZipContextMenu::kCompressTo7zEmail, + L"CompressTo7zEmail", + IDS_CONTEXT_COMPRESS_TO_EMAIL, + IDS_CONTEXT_COMPRESS_TO_EMAIL_HELP, + 0x02000113 + }, + { + NContextMenuFlags::kCompressToZip, + CZipContextMenu::kCompressToZip, + L"CompressToZip", + IDS_CONTEXT_COMPRESS_TO, + IDS_CONTEXT_COMPRESS_TO_HELP, + 0x0200010F + }, + { + NContextMenuFlags::kCompressToZipEmail, + CZipContextMenu::kCompressToZipEmail, + L"CompressToZipEmail", + IDS_CONTEXT_COMPRESS_TO_EMAIL, + IDS_CONTEXT_COMPRESS_TO_EMAIL_HELP, + 0x02000113 + } +}; + +static int FindCommand(CZipContextMenu::ECommandInternalID &id) +{ + for (int i = 0; i < sizeof(g_Commands) / sizeof(g_Commands[0]); i++) + if (g_Commands[i].CommandInternalID == id) + return i; + return -1; +} + +void CZipContextMenu::FillCommand(ECommandInternalID id, UString &mainString, CCommandMapItem &commandMapItem) +{ + int i = FindCommand(id); + if (i < 0) + return; + const CContextMenuCommand &command = g_Commands[i]; + commandMapItem.CommandInternalID = command.CommandInternalID; + commandMapItem.Verb = (UString)kMainVerb + (UString)command.Verb; + commandMapItem.HelpString = LangString(command.ResourceHelpID, command.LangID + 1); + mainString = LangString(command.ResourceID, command.LangID); +} + +static bool MyInsertMenu(CMenu &menu, int pos, UINT id, const UString &s) +{ + CMenuItem menuItem; + menuItem.fType = MFT_STRING; + menuItem.fMask = MIIM_TYPE | MIIM_ID; + menuItem.wID = id; + menuItem.StringValue = s; + return menu.InsertItem(pos, true, menuItem); +} + +static const wchar_t *kArcExts[] = +{ + L"7z", + L"bz2", + L"gz", + L"rar", + L"zip" +}; + +static bool IsItArcExt(const UString &ext2) +{ + UString ext = ext2; + ext.MakeLower(); + for (int i = 0; i < sizeof(kArcExts) / sizeof(kArcExts[0]); i++) + if (ext.Compare(kArcExts[i]) == 0) + return true; + return false; +} + +static UString GetSubFolderNameForExtract(const UString &archiveName) +{ + int dotPos = archiveName.ReverseFind(L'.'); + if (dotPos < 0) + return archiveName + UString(L"~"); + const UString ext = archiveName.Mid(dotPos + 1); + UString res = archiveName.Left(dotPos); + res.TrimRight(); + dotPos = res.ReverseFind(L'.'); + if (dotPos > 0) + { + const UString ext2 = res.Mid(dotPos + 1); + if (ext.CompareNoCase(L"rar") == 0 && + (ext2.CompareNoCase(L"part001") == 0 || + ext2.CompareNoCase(L"part01") == 0 || + ext2.CompareNoCase(L"part1") == 0) || + IsItArcExt(ext2) && ext.CompareNoCase(L"001") == 0) + res = res.Left(dotPos); + res.TrimRight(); + } + return GetCorrectFullFsPath(res); +} + +static UString GetReducedString(const UString &s) +{ + const int kMaxSize = 64; + if (s.Length() < kMaxSize) + return s; + const int kFirstPartSize = kMaxSize / 2; + return s.Left(kFirstPartSize) + UString(L" ... ") + s.Right(kMaxSize - kFirstPartSize); +} + +static UString GetQuotedReducedString(const UString &s) +{ + UString s2 = GetReducedString(s); + s2.Replace(L"&", L"&&"); + return GetQuotedString(s2); +} + +static const char *kExtractExludeExtensions = + " 3gp" + " aac ans ape asc asm asp aspx avi awk" + " bas bat bmp" + " c cs cls clw cmd cpp csproj css ctl cxx" + " def dep dlg dsp dsw" + " eps" + " f f77 f90 f95 fla flac frm" + " gif" + " h hpp hta htm html hxx" + " ico idl inc ini inl" + " java jpeg jpg js" + " la" + " mak manifest wmv mov mp3 mp4 mpe mpeg mpg m4a" + " ofr ogg" + " pac pas pdf php php3 php4 php5 phptml pl pm png ps py pyo" + " ra rb rc reg rka rm rtf" + " sed sh shn shtml sln sql srt swa" + " tcl tex tiff tta txt" + " vb vcproj vbs" + " wav wma wv" + " xml xsd xsl xslt" + " "; + +static const char *kNoOpenAsExtensions = + " 7z arj bz2 cab chm cpio dmg flv gz lha lzh lzma rar swm tar tbz2 tgz wim xar xz z zip "; + +static bool FindExt(const char *p, const UString &name) +{ + int extPos = name.ReverseFind('.'); + if (extPos < 0) + return false; + UString ext = name.Mid(extPos + 1); + ext.MakeLower(); + AString ext2 = UnicodeStringToMultiByte(ext); + for (int i = 0; p[i] != 0;) + { + int j; + for (j = i; p[j] != ' '; j++); + if (ext2.Length() == j - i && memcmp(p + i, (const char *)ext2, ext2.Length()) == 0) + return true; + i = j + 1; + } + return false; +} + +static bool DoNeedExtract(const UString &name) +{ + return !FindExt(kExtractExludeExtensions, name); +} + +STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, + UINT commandIDFirst, UINT commandIDLast, UINT flags) +{ + LoadLangOneTime(); + if (_fileNames.Size() == 0) + return E_FAIL; + UINT currentCommandID = commandIDFirst; + if ((flags & 0x000F) != CMF_NORMAL && + (flags & CMF_VERBSONLY) == 0 && + (flags & CMF_EXPLORE) == 0) + return MAKE_HRESULT(SEVERITY_SUCCESS, 0, currentCommandID); + + _commandMap.Clear(); + + CMenu popupMenu; + CMenuDestroyer menuDestroyer; + + CContextMenuInfo ci; + ci.Load(); + MENUITEMINFO menuItem; + UINT subIndex = indexMenu; + if (ci.Cascaded) + { + CCommandMapItem commandMapItem; + if (!popupMenu.CreatePopup()) + return E_FAIL; + menuDestroyer.Attach(popupMenu); + commandMapItem.CommandInternalID = kCommandNULL; + commandMapItem.Verb = kMainVerb; + commandMapItem.HelpString = LangString(IDS_CONTEXT_CAPTION_HELP, 0x02000102); + _commandMap.Add(commandMapItem); + + menuItem.wID = currentCommandID++; + subIndex = 0; + } + else + { + popupMenu.Attach(hMenu); + } + + UInt32 contextMenuFlags = ci.Flags; + + UString mainString; + if (_fileNames.Size() == 1 && currentCommandID + 6 <= commandIDLast) + { + const UString &fileName = _fileNames.Front(); + UString folderPrefix; + NFile::NDirectory::GetOnlyDirPrefix(fileName, folderPrefix); + + NFile::NFind::CFileInfoW fileInfo; + if (!fileInfo.Find(fileName)) + return E_FAIL; + if (!fileInfo.IsDir() && DoNeedExtract(fileInfo.Name)) + { + // Open + bool thereIsMainOpenItem = ((contextMenuFlags & NContextMenuFlags::kOpen) != 0); + if (thereIsMainOpenItem) + { + CCommandMapItem commandMapItem; + FillCommand(kOpen, mainString, commandMapItem); + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString); + _commandMap.Add(commandMapItem); + } + if ((contextMenuFlags & NContextMenuFlags::kOpenAs) != 0 && + (!thereIsMainOpenItem || !FindExt(kNoOpenAsExtensions, fileInfo.Name))) + { + CMenu subMenu; + if (subMenu.CreatePopup()) + { + CCommandMapItem commandMapItem; + + CMenuItem menuItem; + menuItem.fType = MFT_STRING; + menuItem.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID; + menuItem.wID = currentCommandID++; + menuItem.hSubMenu = subMenu; + menuItem.StringValue = LangString(IDS_CONTEXT_OPEN, 0x02000103); + popupMenu.InsertItem(subIndex++, true, menuItem); + + commandMapItem.CommandInternalID = kCommandNULL; + commandMapItem.Verb = kMainVerb; + commandMapItem.HelpString = LangString(IDS_CONTEXT_OPEN_HELP, 0x02000104); + _commandMap.Add(commandMapItem); + + UINT subIndex2 = 0; + const wchar_t *exts[] = { L"", L"*", L"7z", L"zip", L"cab", L"rar" }; + for (int i = (thereIsMainOpenItem ? 1 : 0); i < sizeof(exts) / sizeof(exts[0]); i++) + { + CCommandMapItem commandMapItem; + if (i == 0) + FillCommand(kOpen, mainString, commandMapItem); + else + { + mainString = exts[i]; + commandMapItem.CommandInternalID = kOpen; + commandMapItem.Verb = (UString)kMainVerb + L".Open." + mainString; + commandMapItem.HelpString = mainString; + commandMapItem.ArcType = mainString; + } + MyInsertMenu(subMenu, subIndex2++, currentCommandID++, mainString); + _commandMap.Add(commandMapItem); + } + subMenu.Detach(); + } + } + } + } + + if (_fileNames.Size() > 0 && currentCommandID + 10 <= commandIDLast) + { + bool needExtract = false; + for(int i = 0; i < _fileNames.Size(); i++) + { + NFile::NFind::CFileInfoW fileInfo; + if (!fileInfo.Find(_fileNames[i])) + return E_FAIL; + if (!fileInfo.IsDir() && DoNeedExtract(fileInfo.Name)) + needExtract = true; + } + const UString &fileName = _fileNames.Front(); + if (needExtract) + { + UString folderPrefix; + NFile::NDirectory::GetOnlyDirPrefix(fileName, folderPrefix); + NFile::NFind::CFileInfoW fileInfo; + if (!fileInfo.Find(fileName)) + return E_FAIL; + // Extract + if ((contextMenuFlags & NContextMenuFlags::kExtract) != 0) + { + CCommandMapItem commandMapItem; + FillCommand(kExtract, mainString, commandMapItem); + if (_dropMode) + commandMapItem.Folder = _dropPath; + else + commandMapItem.Folder = folderPrefix; + commandMapItem.Folder += GetSubFolderNameForExtract(fileInfo.Name) + UString(WCHAR_PATH_SEPARATOR); + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString); + _commandMap.Add(commandMapItem); + } + + // Extract Here + if ((contextMenuFlags & NContextMenuFlags::kExtractHere) != 0) + { + CCommandMapItem commandMapItem; + FillCommand(kExtractHere, mainString, commandMapItem); + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString); + if (_dropMode) + commandMapItem.Folder = _dropPath; + else + commandMapItem.Folder = folderPrefix; + _commandMap.Add(commandMapItem); + } + + // Extract To + if ((contextMenuFlags & NContextMenuFlags::kExtractTo) != 0) + { + CCommandMapItem commandMapItem; + UString s; + FillCommand(kExtractTo, s, commandMapItem); + UString folder; + if (_fileNames.Size() == 1) + folder = GetSubFolderNameForExtract(fileInfo.Name); + else + folder = L'*'; + if (_dropMode) + commandMapItem.Folder = _dropPath; + else + commandMapItem.Folder = folderPrefix; + commandMapItem.Folder += folder; + s = MyFormatNew(s, GetQuotedReducedString(folder + UString(WCHAR_PATH_SEPARATOR))); + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s); + _commandMap.Add(commandMapItem); + } + // Test + if ((contextMenuFlags & NContextMenuFlags::kTest) != 0) + { + CCommandMapItem commandMapItem; + FillCommand(kTest, mainString, commandMapItem); + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString); + _commandMap.Add(commandMapItem); + } + } + UString archiveName = CreateArchiveName(fileName, _fileNames.Size() > 1, false); + UString archiveName7z = archiveName + L".7z"; + UString archiveNameZip = archiveName + L".zip"; + UString archivePathPrefix; + NFile::NDirectory::GetOnlyDirPrefix(fileName, archivePathPrefix); + + // Compress + if ((contextMenuFlags & NContextMenuFlags::kCompress) != 0) + { + CCommandMapItem commandMapItem; + if (_dropMode) + commandMapItem.Folder = _dropPath; + else + commandMapItem.Folder = archivePathPrefix; + commandMapItem.ArcName = archiveName; + FillCommand(kCompress, mainString, commandMapItem); + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString); + _commandMap.Add(commandMapItem); + } + + #ifdef EMAIL_SUPPORT + // CompressEmail + if ((contextMenuFlags & NContextMenuFlags::kCompressEmail) != 0 && !_dropMode) + { + CCommandMapItem commandMapItem; + commandMapItem.ArcName = archiveName; + FillCommand(kCompressEmail, mainString, commandMapItem); + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString); + _commandMap.Add(commandMapItem); + } + #endif + + // CompressTo7z + if (contextMenuFlags & NContextMenuFlags::kCompressTo7z) + { + CCommandMapItem commandMapItem; + UString s; + FillCommand(kCompressTo7z, s, commandMapItem); + if (_dropMode) + commandMapItem.Folder = _dropPath; + else + commandMapItem.Folder = archivePathPrefix; + commandMapItem.ArcName = archiveName7z; + commandMapItem.ArcType = L"7z"; + s = MyFormatNew(s, GetQuotedReducedString(archiveName7z)); + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s); + _commandMap.Add(commandMapItem); + } + + #ifdef EMAIL_SUPPORT + // CompressTo7zEmail + if ((contextMenuFlags & NContextMenuFlags::kCompressTo7zEmail) != 0 && !_dropMode) + { + CCommandMapItem commandMapItem; + UString s; + FillCommand(kCompressTo7zEmail, s, commandMapItem); + commandMapItem.ArcName = archiveName7z; + commandMapItem.ArcType = L"7z"; + s = MyFormatNew(s, GetQuotedReducedString(archiveName7z)); + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s); + _commandMap.Add(commandMapItem); + } + #endif + + // CompressToZip + if (contextMenuFlags & NContextMenuFlags::kCompressToZip) + { + CCommandMapItem commandMapItem; + UString s; + FillCommand(kCompressToZip, s, commandMapItem); + if (_dropMode) + commandMapItem.Folder = _dropPath; + else + commandMapItem.Folder = archivePathPrefix; + commandMapItem.ArcName = archiveNameZip; + commandMapItem.ArcType = L"zip"; + s = MyFormatNew(s, GetQuotedReducedString(archiveNameZip)); + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s); + _commandMap.Add(commandMapItem); + } + + #ifdef EMAIL_SUPPORT + // CompressToZipEmail + if ((contextMenuFlags & NContextMenuFlags::kCompressToZipEmail) != 0 && !_dropMode) + { + CCommandMapItem commandMapItem; + UString s; + FillCommand(kCompressToZipEmail, s, commandMapItem); + commandMapItem.ArcName = archiveNameZip; + commandMapItem.ArcType = L"zip"; + s = MyFormatNew(s, GetQuotedReducedString(archiveNameZip)); + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s); + _commandMap.Add(commandMapItem); + } + #endif + } + + + // don't use InsertMenu: See MSDN: + // PRB: Duplicate Menu Items In the File Menu For a Shell Context Menu Extension + // ID: Q214477 + + if (ci.Cascaded) + { + CMenuItem menuItem; + menuItem.fType = MFT_STRING; + menuItem.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID; + menuItem.wID = currentCommandID++; + menuItem.hSubMenu = popupMenu.Detach(); + menuDestroyer.Disable(); + menuItem.StringValue = LangString(IDS_CONTEXT_POPUP_CAPTION, 0x02000101); + CMenu menu; + menu.Attach(hMenu); + menu.InsertItem(indexMenu++, true, menuItem); + } + + return MAKE_HRESULT(SEVERITY_SUCCESS, 0, currentCommandID - commandIDFirst); +} + + +int CZipContextMenu::FindVerb(const UString &verb) +{ + for(int i = 0; i < _commandMap.Size(); i++) + if (_commandMap[i].Verb.Compare(verb) == 0) + return i; + return -1; +} + +static UString Get7zFmPath() +{ + UString path; + GetProgramFolderPath(path); + return path + L"7zFM.exe"; +} + +STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo) +{ + // ::OutputDebugStringA("1"); + int commandOffset; + + // It's fix for bug: crashing in XP. See example in MSDN: "Creating Context Menu Handlers". + + #ifndef UNDER_CE + if (commandInfo->cbSize == sizeof(CMINVOKECOMMANDINFOEX) && + (commandInfo->fMask & CMIC_MASK_UNICODE) != 0) + { + LPCMINVOKECOMMANDINFOEX commandInfoEx = (LPCMINVOKECOMMANDINFOEX)commandInfo; + if (HIWORD(commandInfoEx->lpVerbW) == 0) + commandOffset = LOWORD(commandInfo->lpVerb); + else + commandOffset = FindVerb(commandInfoEx->lpVerbW); + } + else + #endif + if (HIWORD(commandInfo->lpVerb) == 0) + commandOffset = LOWORD(commandInfo->lpVerb); + else + commandOffset = FindVerb(GetUnicodeString(commandInfo->lpVerb)); + + if (commandOffset < 0 || commandOffset >= _commandMap.Size()) + return E_FAIL; + + const CCommandMapItem commandMapItem = _commandMap[commandOffset]; + ECommandInternalID cmdID = commandMapItem.CommandInternalID; + + try + { + switch(cmdID) + { + case kOpen: + { + UString params; + params = GetQuotedString(_fileNames[0]); + if (commandMapItem.ArcType) + { + params += L" -t"; + params += commandMapItem.ArcType; + } + MyCreateProcess(Get7zFmPath(), params); + break; + } + case kExtract: + case kExtractHere: + case kExtractTo: + { + ExtractArchives(_fileNames, commandMapItem.Folder, (cmdID == kExtract)); + break; + } + case kTest: + { + TestArchives(_fileNames); + break; + } + case kCompress: + case kCompressEmail: + case kCompressTo7z: + case kCompressTo7zEmail: + case kCompressToZip: + case kCompressToZipEmail: + { + bool email = + (cmdID == kCompressEmail) || + (cmdID == kCompressTo7zEmail) || + (cmdID == kCompressToZipEmail); + bool showDialog = + (cmdID == kCompress) || + (cmdID == kCompressEmail); + CompressFiles(commandMapItem.Folder, + commandMapItem.ArcName, commandMapItem.ArcType, + _fileNames, email, showDialog, false); + break; + } + } + } + catch(...) + { + ::MessageBoxW(0, L"Error", L"7-Zip", MB_ICONERROR); + } + return S_OK; +} + +static void MyCopyString(void *dest, const wchar_t *src, bool writeInUnicode) +{ + if (writeInUnicode) + { + MyStringCopy((wchar_t *)dest, src); + } + else + MyStringCopy((char *)dest, (const char *)GetAnsiString(src)); +} + +STDMETHODIMP CZipContextMenu::GetCommandString(UINT_PTR commandOffset, UINT uType, + UINT * /* pwReserved */ , LPSTR pszName, UINT /* cchMax */) +{ + int cmdOffset = (int)commandOffset; + switch(uType) + { + #ifdef UNDER_CE + case GCS_VALIDATE: + #else + case GCS_VALIDATEA: + case GCS_VALIDATEW: + #endif + if (cmdOffset < 0 || cmdOffset >= _commandMap.Size()) + return S_FALSE; + else + return S_OK; + } + if (cmdOffset < 0 || cmdOffset >= _commandMap.Size()) + return E_FAIL; + #ifdef UNDER_CE + if (uType == GCS_HELPTEXT) + #else + if (uType == GCS_HELPTEXTA || uType == GCS_HELPTEXTW) + #endif + { + MyCopyString(pszName, _commandMap[cmdOffset].HelpString, + #ifdef UNDER_CE + true + #else + uType == GCS_HELPTEXTW + #endif + ); + return NO_ERROR; + } + #ifdef UNDER_CE + if (uType == GCS_VERB) + #else + if (uType == GCS_VERBA || uType == GCS_VERBW) + #endif + { + MyCopyString(pszName, _commandMap[cmdOffset].Verb, + #ifdef UNDER_CE + true + #else + uType == GCS_VERBW + #endif + ); + return NO_ERROR; + } + return E_FAIL; +} diff --git a/CPP/7zip/UI/Explorer/ContextMenu.h b/CPP/7zip/UI/Explorer/ContextMenu.h new file mode 100755 index 0000000..f6cb464 --- /dev/null +++ b/CPP/7zip/UI/Explorer/ContextMenu.h @@ -0,0 +1,70 @@ +// ContextMenu.h + +#ifndef __CONTEXT_MENU_H +#define __CONTEXT_MENU_H + +#include "Common/MyString.h" + +#include "../FileManager/MyCom2.h" + +class CZipContextMenu: + public IContextMenu, + public IShellExtInit, + public CMyUnknownImp +{ +public: + + enum ECommandInternalID + { + kCommandNULL, + kOpen, + kExtract, + kExtractHere, + kExtractTo, + kTest, + kCompress, + kCompressEmail, + kCompressTo7z, + kCompressTo7zEmail, + kCompressToZip, + kCompressToZipEmail + }; + + MY_UNKNOWN_IMP2_MT(IContextMenu, IShellExtInit) + + // IShellExtInit + STDMETHOD(Initialize)(LPCITEMIDLIST pidlFolder, LPDATAOBJECT dataObject, HKEY hkeyProgID); + + // IContextMenu + STDMETHOD(QueryContextMenu)(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags); + STDMETHOD(InvokeCommand)(LPCMINVOKECOMMANDINFO lpici); + STDMETHOD(GetCommandString)(UINT_PTR idCmd, UINT uType, UINT *pwReserved, LPSTR pszName, UINT cchMax); + + HRESULT InitContextMenu(const wchar_t *folder, const wchar_t **names, UINT32 numFiles); + + CZipContextMenu(); + ~CZipContextMenu(); + +private: + + struct CCommandMapItem + { + ECommandInternalID CommandInternalID; + UString Verb; + UString HelpString; + UString Folder; + UString ArcName; + UString ArcType; + }; + + UStringVector _fileNames; + bool _dropMode; + UString _dropPath; + CObjectVector _commandMap; + + HRESULT GetFileNames(LPDATAOBJECT dataObject, UStringVector &fileNames); + int FindVerb(const UString &verb); + void FillCommand(ECommandInternalID id, UString &mainString, CCommandMapItem &commandMapItem); +}; + +#endif diff --git a/CPP/7zip/UI/Explorer/ContextMenuFlags.h b/CPP/7zip/UI/Explorer/ContextMenuFlags.h new file mode 100755 index 0000000..19d1d12 --- /dev/null +++ b/CPP/7zip/UI/Explorer/ContextMenuFlags.h @@ -0,0 +1,24 @@ +// ContextMenuFlags.h + +#ifndef __CONTEXT_MENU_FLAGS_H +#define __CONTEXT_MENU_FLAGS_H + +namespace NContextMenuFlags +{ + const UInt32 kExtract = 1 << 0; + const UInt32 kExtractHere = 1 << 1; + const UInt32 kExtractTo = 1 << 2; + + const UInt32 kTest = 1 << 4; + const UInt32 kOpen = 1 << 5; + const UInt32 kOpenAs = 1 << 6; + + const UInt32 kCompress = 1 << 8; + const UInt32 kCompressTo7z = 1 << 9; + const UInt32 kCompressEmail = 1 << 10; + const UInt32 kCompressTo7zEmail = 1 << 11; + const UInt32 kCompressToZip = 1 << 12; + const UInt32 kCompressToZipEmail = 1 << 13; +} + +#endif diff --git a/CPP/7zip/UI/Explorer/DllExports.cpp b/CPP/7zip/UI/Explorer/DllExports.cpp new file mode 100755 index 0000000..4ad2863 --- /dev/null +++ b/CPP/7zip/UI/Explorer/DllExports.cpp @@ -0,0 +1,265 @@ +// DLLExports.cpp +// +// Notes: +// Win2000: +// If I register at HKCR\Folder\ShellEx then DLL is locked. +// otherwise it unloads after explorer closing. +// but if I call menu for desktop items it's locked all the time + +#include "StdAfx.h" + +#include "Common/MyInitGuid.h" + +#include +#include + +#include "Common/ComTry.h" +#include "Common/StringConvert.h" + +#include "Windows/DLL.h" +#include "Windows/Error.h" +#include "Windows/NtCheck.h" +#include "Windows/Registry.h" + +#include "../FileManager/IFolder.h" +#include "../FileManager/LangUtils.h" + +#include "ContextMenu.h" + +// {23170F69-40C1-278A-1000-000100020000} +DEFINE_GUID(CLSID_CZipContextMenu, +0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00); + +using namespace NWindows; + +HINSTANCE g_hInstance = 0; +HWND g_HWND = 0; + +UString HResultToMessage(HRESULT errorCode) +{ + UString message; + if (!NError::MyFormatMessage(errorCode, message)) + message.Empty(); + if (message.IsEmpty()) + message = L"Error"; + return message; +} + +LONG g_DllRefCount = 0; // Reference count of this DLL. + +static LPCWSTR kShellExtName = L"7-Zip Shell Extension"; +static LPCTSTR kClsidMask = TEXT("CLSID\\%s"); +static LPCTSTR kClsidInprocMask = TEXT("CLSID\\%s\\InprocServer32"); +static LPCTSTR kApprovedKeyPath = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"); + +// #define ODS(sz) OutputDebugString(L#sz) + +class CShellExtClassFactory: + public IClassFactory, + public CMyUnknownImp +{ +public: + CShellExtClassFactory() { InterlockedIncrement(&g_DllRefCount); } + ~CShellExtClassFactory() { InterlockedDecrement(&g_DllRefCount); } + + MY_UNKNOWN_IMP1_MT(IClassFactory) + + STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, void**); + STDMETHODIMP LockServer(BOOL); +}; + +STDMETHODIMP CShellExtClassFactory::CreateInstance(LPUNKNOWN pUnkOuter, + REFIID riid, void **ppvObj) +{ + // ODS("CShellExtClassFactory::CreateInstance()\r\n"); + *ppvObj = NULL; + if (pUnkOuter) + return CLASS_E_NOAGGREGATION; + + CZipContextMenu *shellExt; + try + { + shellExt = new CZipContextMenu(); + } + catch(...) { return E_OUTOFMEMORY; } + if (shellExt == NULL) + return E_OUTOFMEMORY; + + HRESULT res = shellExt->QueryInterface(riid, ppvObj); + if (res != S_OK) + delete shellExt; + return res; +} + + +STDMETHODIMP CShellExtClassFactory::LockServer(BOOL /* fLock */) +{ + return S_OK; // Check it +} + + +#define NT_CHECK_FAIL_ACTION return FALSE; + +extern "C" +BOOL WINAPI DllMain( + #ifdef UNDER_CE + HANDLE hInstance + #else + HINSTANCE hInstance + #endif + , DWORD dwReason, LPVOID) +{ + if (dwReason == DLL_PROCESS_ATTACH) + { + g_hInstance = (HINSTANCE)hInstance; + // ODS("In DLLMain, DLL_PROCESS_ATTACH\r\n"); + NT_CHECK + } + else if (dwReason == DLL_PROCESS_DETACH) + { + // ODS("In DLLMain, DLL_PROCESS_DETACH\r\n"); + } + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// Used to determine whether the DLL can be unloaded by OLE + +STDAPI DllCanUnloadNow(void) +{ + // ODS("In DLLCanUnloadNow\r\n"); + return (g_DllRefCount == 0 ? S_OK : S_FALSE); +} + +STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) +{ + // ODS("In DllGetClassObject\r\n"); + *ppv = NULL; + if (IsEqualIID(rclsid, CLSID_CZipContextMenu)) + { + CShellExtClassFactory *cf; + try + { + cf = new CShellExtClassFactory; + } + catch(...) { return E_OUTOFMEMORY; } + if (cf == 0) + return E_OUTOFMEMORY; + HRESULT res = cf->QueryInterface(riid, ppv); + if (res != S_OK) + delete cf; + return res; + } + return CLASS_E_CLASSNOTAVAILABLE; + // return _Module.GetClassObject(rclsid, riid, ppv); +} + +static BOOL GetStringFromIID(CLSID clsid, LPTSTR s, int size) +{ + LPWSTR pwsz; + if (StringFromIID(clsid, &pwsz) != S_OK) + return FALSE; + if (!pwsz) + return FALSE; + #ifdef UNICODE + for (int i = 0; i < size; i++) + { + s[i] = pwsz[i]; + if (pwsz[i] == 0) + break; + } + s[size - 1] = 0; + #else + WideCharToMultiByte(CP_ACP, 0, pwsz, -1, s, size, NULL, NULL); + #endif + CoTaskMemFree(pwsz); + s[size - 1] = 0; + return TRUE; +} + +typedef struct +{ + HKEY hRootKey; + LPCTSTR SubKey; + LPCWSTR ValueName; + LPCWSTR Data; +} CRegItem; + +static BOOL RegisterServer(CLSID clsid, LPCWSTR title) +{ + TCHAR clsidString[MAX_PATH]; + if (!GetStringFromIID(clsid, clsidString, MAX_PATH)) + return FALSE; + + UString modulePath; + if (!NDLL::MyGetModuleFileName(g_hInstance, modulePath)) + return FALSE; + + CRegItem clsidEntries[] = + { + HKEY_CLASSES_ROOT, kClsidMask, NULL, title, + HKEY_CLASSES_ROOT, kClsidInprocMask, NULL, modulePath, + HKEY_CLASSES_ROOT, kClsidInprocMask, L"ThreadingModel", L"Apartment", + NULL, NULL, NULL, NULL + }; + + //register the CLSID entries + for (int i = 0; clsidEntries[i].hRootKey; i++) + { + TCHAR subKey[MAX_PATH]; + const CRegItem &r = clsidEntries[i]; + wsprintf(subKey, r.SubKey, clsidString); + NRegistry::CKey key; + if (key.Create(r.hRootKey, subKey, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE) != NOERROR) + return FALSE; + key.SetValue(clsidEntries[i].ValueName, clsidEntries[i].Data); + } + + #if !defined(_WIN64) && !defined(UNDER_CE) + if (IsItWindowsNT()) + #endif + { + NRegistry::CKey key; + if (key.Create(HKEY_LOCAL_MACHINE, kApprovedKeyPath, NULL, + REG_OPTION_NON_VOLATILE, KEY_WRITE) == NOERROR) + key.SetValue(GetUnicodeString(clsidString), title); + } + return TRUE; +} + +STDAPI DllRegisterServer(void) +{ + return RegisterServer(CLSID_CZipContextMenu, kShellExtName) ? S_OK: SELFREG_E_CLASS; +} + +static BOOL UnregisterServer(CLSID clsid) +{ + TCHAR clsidString[MAX_PATH]; + if (!GetStringFromIID(clsid, clsidString, MAX_PATH)) + return FALSE; + + TCHAR subKey[MAX_PATH]; + wsprintf(subKey, kClsidInprocMask, clsidString); + RegDeleteKey(HKEY_CLASSES_ROOT, subKey); + + wsprintf (subKey, kClsidMask, clsidString); + RegDeleteKey(HKEY_CLASSES_ROOT, subKey); + + #if !defined(_WIN64) && !defined(UNDER_CE) + if (IsItWindowsNT()) + #endif + { + HKEY hKey; + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, kApprovedKeyPath, 0, KEY_SET_VALUE, &hKey) == NOERROR) + { + RegDeleteValue(hKey, clsidString); + RegCloseKey(hKey); + } + } + return TRUE; +} + +STDAPI DllUnregisterServer(void) +{ + return UnregisterServer(CLSID_CZipContextMenu) ? S_OK: SELFREG_E_CLASS; +} diff --git a/CPP/7zip/UI/Explorer/Explorer.def b/CPP/7zip/UI/Explorer/Explorer.def new file mode 100755 index 0000000..5374c37 --- /dev/null +++ b/CPP/7zip/UI/Explorer/Explorer.def @@ -0,0 +1,9 @@ +; 7-zip.def + +LIBRARY "7-zip" + +EXPORTS + DllCanUnloadNow PRIVATE + DllGetClassObject PRIVATE + DllRegisterServer PRIVATE + DllUnregisterServer PRIVATE diff --git a/CPP/7zip/UI/Explorer/Explorer.dsp b/CPP/7zip/UI/Explorer/Explorer.dsp new file mode 100755 index 0000000..e8fbc3a --- /dev/null +++ b/CPP/7zip/UI/Explorer/Explorer.dsp @@ -0,0 +1,558 @@ +# Microsoft Developer Studio Project File - Name="Explorer" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=Explorer - 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 "Explorer.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 "Explorer.mak" CFG="Explorer - Win32 DebugU" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Explorer - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "Explorer - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "Explorer - Win32 ReleaseU" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "Explorer - Win32 DebugU" (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)" == "Explorer - 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 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXPLORER_EXPORTS" /YX /FD /c +# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "EXPLORER_EXPORTS" /D "LANG" /Yu"StdAfx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-ZIP\7-Zip.dll" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "Explorer - 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 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXPLORER_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "EXPLORER_EXPORTS" /D "LANG" /Yu"StdAfx.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-ZIP\7-Zip.dll" /pdbtype:sept + +!ELSEIF "$(CFG)" == "Explorer - 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 1 +# 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 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "EXPLORER_EXPORTS" /D "LANG" /D "_MBCS" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "EXPLORER_EXPORTS" /D "LANG" /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 0x409 /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 comctl32.lib htmlhelp.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-ZIP\7-Zip.dll" /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 comctl32.lib htmlhelp.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-ZIP\7-Zipn.dll" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "Explorer - 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 1 +# 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 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "EXPLORER_EXPORTS" /D "LANG" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "EXPLORER_EXPORTS" /D "LANG" /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 comctl32.lib htmlhelp.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-ZIP\7-Zip.dll" /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-ZIP\7-Zip.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "Explorer - Win32 Release" +# Name "Explorer - Win32 Debug" +# Name "Explorer - Win32 ReleaseU" +# Name "Explorer - Win32 DebugU" +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\DllExports.cpp +# End Source File +# Begin Source File + +SOURCE=.\Explorer.def +# End Source File +# 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 "UI Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\Common\ArchiveName.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ArchiveName.h +# End Source File +# Begin Source File + +SOURCE=..\Common\CompressCall.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\CompressCall.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ExtractingFilePath.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ExtractingFilePath.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ZipRegistry.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ZipRegistry.h +# End Source File +# End Group +# Begin Group "Engine" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\ContextMenu.cpp +# End Source File +# Begin Source File + +SOURCE=.\ContextMenu.h +# End Source File +# Begin Source File + +SOURCE=.\MyMessages.cpp +# End Source File +# Begin Source File + +SOURCE=.\MyMessages.h +# End Source File +# End Group +# Begin Group "FileManager" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\FileManager\FormatUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\FileManager\FormatUtils.h +# End Source File +# Begin Source File + +SOURCE=..\FileManager\HelpUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\FileManager\HelpUtils.h +# End Source File +# Begin Source File + +SOURCE=..\FileManager\IFolder.h +# End Source File +# Begin Source File + +SOURCE=..\FileManager\LangUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\FileManager\LangUtils.h +# End Source File +# Begin Source File + +SOURCE=..\FileManager\ProgramLocation.cpp +# End Source File +# Begin Source File + +SOURCE=..\FileManager\ProgramLocation.h +# End Source File +# Begin Source File + +SOURCE=..\FileManager\RegistryUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\FileManager\RegistryUtils.h +# End Source File +# End Group +# Begin Group "C" + +# PROP Default_Filter "" +# 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 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\Lang.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Lang.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\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\Random.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Random.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\TextConfig.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\TextConfig.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 +# 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 +# Begin Source File + +SOURCE=..\..\..\Windows\Control\ListView.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\ListView.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\PropertyPage.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\PropertyPage.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\Error.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Error.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\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\Memory.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Memory.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Menu.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Menu.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Process.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Process.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Registry.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Registry.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\ResourceString.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\ResourceString.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Shell.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Shell.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Synchronization.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 Source File + +SOURCE=".\7-zip.dll.manifest" +# End Source File +# Begin Source File + +SOURCE=.\ContextMenuFlags.h +# End Source File +# Begin Source File + +SOURCE=.\RegistryContextMenu.cpp +# End Source File +# Begin Source File + +SOURCE=.\RegistryContextMenu.h +# End Source File +# End Target +# End Project diff --git a/CPP/7zip/UI/Explorer/Explorer.dsw b/CPP/7zip/UI/Explorer/Explorer.dsw new file mode 100755 index 0000000..38275b1 --- /dev/null +++ b/CPP/7zip/UI/Explorer/Explorer.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "Explorer"=".\Explorer.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/CPP/7zip/UI/Explorer/MyMessages.cpp b/CPP/7zip/UI/Explorer/MyMessages.cpp new file mode 100755 index 0000000..b8dc9dc --- /dev/null +++ b/CPP/7zip/UI/Explorer/MyMessages.cpp @@ -0,0 +1,58 @@ +// MyMessages.cpp + +#include "StdAfx.h" + +#include "MyMessages.h" + +#include "Windows/Error.h" +#include "Windows/ResourceString.h" + +#ifdef LANG +#include "../FileManager/LangUtils.h" +#endif + +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 + #ifdef LANG + , UInt32 langID + #endif + ) +{ + ShowErrorMessage(window, + #ifdef LANG + LangString(resID, langID) + #else + MyLoadStringW(resID) + #endif + ); +} + +void ShowErrorMessageRes(UINT resID + #ifdef LANG + , UInt32 langID + #endif + ) +{ + ShowErrorMessageHwndRes(0, resID + #ifdef LANG + , langID + #endif + ); +} + +void ShowErrorMessageDWORD(HWND window, DWORD errorCode) +{ + ShowErrorMessage(window, NError::MyFormatMessageW(errorCode)); +} + +void ShowLastErrorMessage(HWND window) +{ + ShowErrorMessageDWORD(window, ::GetLastError()); +} + diff --git a/CPP/7zip/UI/Explorer/MyMessages.h b/CPP/7zip/UI/Explorer/MyMessages.h new file mode 100755 index 0000000..3d38562 --- /dev/null +++ b/CPP/7zip/UI/Explorer/MyMessages.h @@ -0,0 +1,28 @@ +// MyMessages.h + +#ifndef __MYMESSAGES_H +#define __MYMESSAGES_H + +#include "Common/MyString.h" +#include "Common/Types.h" + +void ShowErrorMessage(HWND window, LPCWSTR message); +inline void ShowErrorMessage(LPCWSTR message) { ShowErrorMessage(0, message); } + +void ShowErrorMessageHwndRes(HWND window, UINT resID + #ifdef LANG + , UInt32 langID + #endif + ); + +void ShowErrorMessageRes(UINT resID + #ifdef LANG + , UInt32 langID + #endif + ); + +// void ShowErrorMessageDWORD(HWND window, DWORD errorCode); +// inline void ErrorMessageDWORD(DWORD errorCode) { ShowErrorMessageDWORD(0, errorCode); } +void ShowLastErrorMessage(HWND window = 0); + +#endif diff --git a/CPP/7zip/UI/Explorer/OptionsDialog.cpp b/CPP/7zip/UI/Explorer/OptionsDialog.cpp new file mode 100755 index 0000000..1c97a1d --- /dev/null +++ b/CPP/7zip/UI/Explorer/OptionsDialog.cpp @@ -0,0 +1,71 @@ +// OptionsDialog.cpp + +#include "StdAfx.h" + +#include "Windows/Control/PropertyPage.h" + +#include "../FileManager/DialogSize.h" +#include "../FileManager/LangUtils.h" + +#include "FoldersPage.h" +#include "FoldersPageRes.h" +#include "OptionsDialog.h" +#include "MenuPage.h" +#include "MenuPageRes.h" + +#include "resource.h" + +using namespace NWindows; + +static INT_PTR OptionsDialog(HWND hwndOwner) +{ + CMenuPage systemPage; + CFoldersPage foldersPage; + UINT32 langIDs[] = { 0x01000300, 0x01000200}; + + BIG_DIALOG_SIZE(200, 200); + UINT pageIDs[] = { SIZED_DIALOG(IDD_MENU), SIZED_DIALOG(IDD_FOLDERS) }; + NControl::CPropertyPage *pagePinters[] = { &systemPage, &foldersPage }; + CObjectVector pages; + const int kNumPages = sizeof(langIDs) / sizeof(langIDs[0]); + for (int i = 0; i < kNumPages; i++) + { + NControl::CPageInfo page; + page.Title = LangString(langIDs[i]); + page.ID = pageIDs[i]; + page.Page = pagePinters[i]; + pages.Add(page); + } + return NControl::MyPropertySheet(pages, hwndOwner, + LangString(IDS_CONFIG_DIALOG_CAPTION, 0x01000000)); +} + +STDMETHODIMP CSevenZipOptions::PluginOptions(HWND hWnd, + IPluginOptionsCallback * /* callback */) +{ + /* + CComBSTR programPath; + RINOK(callback->GetProgramPath(programName))); + */ + OptionsDialog(hWnd); + return S_OK; +} + +STDMETHODIMP CSevenZipOptions::GetFileExtensions(BSTR * /* extensions */) +{ + /* + UString extStrings; + CObjectVector formats; + NZipRootRegistry::ReadArchiverInfoList(formats); + for(int i = 0; i < formats.Size(); i++) + { + if (i != 0) + extStrings += L' '; + extStrings += formats[i].Extension; + } + CComBSTR valueTemp = extStrings; + *extensions = valueTemp.Detach(); + return S_OK; + */ + return E_NOTIMPL; +} diff --git a/CPP/7zip/UI/Explorer/OptionsDialog.h b/CPP/7zip/UI/Explorer/OptionsDialog.h new file mode 100755 index 0000000..e39d457 --- /dev/null +++ b/CPP/7zip/UI/Explorer/OptionsDialog.h @@ -0,0 +1,23 @@ +// OptionsDialog.h + +#ifndef __SEVENZIP_OPTIONSDIALOG_H +#define __SEVENZIP_OPTIONSDIALOG_H + +#include "../FileManager/PluginInterface.h" +#include "Common/MyCom.h" + +// {23170F69-40C1-278D-1000-000100020000} +DEFINE_GUID(CLSID_CSevenZipOptions, + 0x23170F69, 0x40C1, 0x278D, 0x10, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00); + +class CSevenZipOptions: + public IPluginOptions, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP + STDMETHOD(PluginOptions)(HWND hWnd, IPluginOptionsCallback *callback); + STDMETHOD(GetFileExtensions)(BSTR *extensions); +}; + +#endif diff --git a/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp b/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp new file mode 100755 index 0000000..f3322c7 --- /dev/null +++ b/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp @@ -0,0 +1,116 @@ +// RegistryContextMenu.cpp + +#include "StdAfx.h" + +#include "Windows/Registry.h" +#include "Windows/Synchronization.h" + +#include "RegistryContextMenu.h" + +using namespace NWindows; +using namespace NRegistry; + +namespace NZipRootRegistry { + +#ifndef UNDER_CE + +static NSynchronization::CCriticalSection g_CS; + +static const TCHAR *kContextMenuKeyName = TEXT("\\shellex\\ContextMenuHandlers\\7-Zip"); +static const TCHAR *kDragDropMenuKeyName = TEXT("\\shellex\\DragDropHandlers\\7-Zip"); + +static const TCHAR *kExtensionCLSID = TEXT("{23170F69-40C1-278A-1000-000100020000}"); + +static const TCHAR *kRootKeyNameForFile = TEXT("*"); +static const TCHAR *kRootKeyNameForFolder = TEXT("Folder"); +static const TCHAR *kRootKeyNameForDirectory = TEXT("Directory"); +static const TCHAR *kRootKeyNameForDrive = TEXT("Drive"); + +static CSysString GetFullContextMenuKeyName(const CSysString &keyName) + { return (keyName + kContextMenuKeyName); } + +static CSysString GetFullDragDropMenuKeyName(const CSysString &keyName) + { return (keyName + kDragDropMenuKeyName); } + +static bool CheckHandlerCommon(const CSysString &keyName) +{ + NSynchronization::CCriticalSectionLock lock(g_CS); + CKey key; + if (key.Open(HKEY_CLASSES_ROOT, keyName, KEY_READ) != ERROR_SUCCESS) + return false; + CSysString value; + if (key.QueryValue(NULL, value) != ERROR_SUCCESS) + return false; + value.MakeUpper(); + return (value.Compare(kExtensionCLSID) == 0); +} + +bool CheckContextMenuHandler() +{ + return + // CheckHandlerCommon(GetFullContextMenuKeyName(kRootKeyNameForFolder)) && + CheckHandlerCommon(GetFullContextMenuKeyName(kRootKeyNameForDirectory)) && + CheckHandlerCommon(GetFullContextMenuKeyName(kRootKeyNameForFile)) && + CheckHandlerCommon(GetFullDragDropMenuKeyName(kRootKeyNameForDirectory)) && + CheckHandlerCommon(GetFullDragDropMenuKeyName(kRootKeyNameForDrive)); +} + +static void DeleteContextMenuHandlerCommon(const CSysString &keyName) +{ + CKey rootKey; + rootKey.Attach(HKEY_CLASSES_ROOT); + rootKey.RecurseDeleteKey(GetFullContextMenuKeyName(keyName)); + rootKey.Detach(); +} + +static void DeleteDragDropMenuHandlerCommon(const CSysString &keyName) +{ + CKey rootKey; + rootKey.Attach(HKEY_CLASSES_ROOT); + rootKey.RecurseDeleteKey(GetFullDragDropMenuKeyName(keyName)); + rootKey.Detach(); +} + +void DeleteContextMenuHandler() +{ + DeleteContextMenuHandlerCommon(kRootKeyNameForFile); + DeleteContextMenuHandlerCommon(kRootKeyNameForFolder); + DeleteContextMenuHandlerCommon(kRootKeyNameForDirectory); + DeleteContextMenuHandlerCommon(kRootKeyNameForDrive); + DeleteDragDropMenuHandlerCommon(kRootKeyNameForFile); + DeleteDragDropMenuHandlerCommon(kRootKeyNameForFolder); + DeleteDragDropMenuHandlerCommon(kRootKeyNameForDirectory); + DeleteDragDropMenuHandlerCommon(kRootKeyNameForDrive); +} + +static void AddContextMenuHandlerCommon(const CSysString &keyName) +{ + DeleteContextMenuHandlerCommon(keyName); + NSynchronization::CCriticalSectionLock lock(g_CS); + CKey key; + key.Create(HKEY_CLASSES_ROOT, GetFullContextMenuKeyName(keyName)); + key.SetValue(NULL, kExtensionCLSID); +} + +static void AddDragDropMenuHandlerCommon(const CSysString &keyName) +{ + DeleteDragDropMenuHandlerCommon(keyName); + NSynchronization::CCriticalSectionLock lock(g_CS); + CKey key; + key.Create(HKEY_CLASSES_ROOT, GetFullDragDropMenuKeyName(keyName)); + key.SetValue(NULL, kExtensionCLSID); +} + +void AddContextMenuHandler() +{ + AddContextMenuHandlerCommon(kRootKeyNameForFile); + // AddContextMenuHandlerCommon(kRootKeyNameForFolder); + AddContextMenuHandlerCommon(kRootKeyNameForDirectory); + + AddDragDropMenuHandlerCommon(kRootKeyNameForDirectory); + AddDragDropMenuHandlerCommon(kRootKeyNameForDrive); +} + +#endif + +} diff --git a/CPP/7zip/UI/Explorer/RegistryContextMenu.h b/CPP/7zip/UI/Explorer/RegistryContextMenu.h new file mode 100755 index 0000000..5ea0fda --- /dev/null +++ b/CPP/7zip/UI/Explorer/RegistryContextMenu.h @@ -0,0 +1,16 @@ +// RegistryContextMenu.h + +#ifndef __REGISTRY_CONTEXT_MENU_H +#define __REGISTRY_CONTEXT_MENU_H + +namespace NZipRootRegistry { + +#ifndef UNDER_CE + bool CheckContextMenuHandler(); + void AddContextMenuHandler(); + void DeleteContextMenuHandler(); +#endif + +} + +#endif diff --git a/CPP/7zip/UI/Explorer/StdAfx.cpp b/CPP/7zip/UI/Explorer/StdAfx.cpp new file mode 100755 index 0000000..2b852f2 --- /dev/null +++ b/CPP/7zip/UI/Explorer/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "stdafx.h" diff --git a/CPP/7zip/UI/Explorer/StdAfx.h b/CPP/7zip/UI/Explorer/StdAfx.h new file mode 100755 index 0000000..b636632 --- /dev/null +++ b/CPP/7zip/UI/Explorer/StdAfx.h @@ -0,0 +1,24 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#define _WIN32_WINNT 0x0400 +// it's hack for Windows NT supporting +#define WINVER 0x0400 + +// #define _WIN32_IE 0x0500 +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "Common/NewHandler.h" + +#endif diff --git a/CPP/7zip/UI/Explorer/makefile b/CPP/7zip/UI/Explorer/makefile new file mode 100755 index 0000000..33787ac --- /dev/null +++ b/CPP/7zip/UI/Explorer/makefile @@ -0,0 +1,101 @@ +PROG = 7-zip.dll +DEF_FILE = Explorer.def +CFLAGS = $(CFLAGS) -I ../../../ \ + -DLANG \ + +!IFDEF UNDER_CE +LIBS = $(LIBS) Commctrl.lib +!ELSE +LIBS = $(LIBS) comctl32.lib htmlhelp.lib comdlg32.lib Mpr.lib Gdi32.lib +CFLAGS = $(CFLAGS) -DWIN_LONG_PATH +!ENDIF + +EXPLORER_OBJS = \ + $O\DllExports.obj \ + $O\ContextMenu.obj \ + $O\MyMessages.obj \ + $O\RegistryContextMenu.obj \ + +COMMON_OBJS = \ + $O\IntToString.obj \ + $O\Lang.obj \ + $O\MyString.obj \ + $O\MyVector.obj \ + $O\NewHandler.obj \ + $O\Random.obj \ + $O\StringConvert.obj \ + $O\StringToInt.obj \ + $O\TextConfig.obj \ + $O\UTFConvert.obj \ + $O\Wildcard.obj \ + +WIN_OBJS = \ + $O\DLL.obj \ + $O\Error.obj \ + $O\FileDir.obj \ + $O\FileFind.obj \ + $O\FileIO.obj \ + $O\FileName.obj \ + $O\Menu.obj \ + $O\Process.obj \ + $O\Registry.obj \ + $O\ResourceString.obj \ + $O\Shell.obj \ + $O\Synchronization.obj \ + $O\Window.obj \ + +!IFDEF UNDER_CE + +WIN_OBJS = $(WIN_OBJS) \ + $O\CommonDialog.obj \ + +!ENDIF + +WIN_CTRL_OBJS = \ + $O\Dialog.obj \ + $O\ListView.obj \ + $O\PropertyPage.obj \ + +UI_COMMON_OBJS = \ + $O\ArchiveName.obj \ + $O\CompressCall.obj \ + $O\ExtractingFilePath.obj \ + $O\ZipRegistry.obj \ + +FM_COMMON_OBJS = \ + $O\FormatUtils.obj \ + $O\HelpUtils.obj \ + $O\LangUtils.obj \ + $O\ProgramLocation.obj \ + $O\RegistryUtils.obj \ + +C_OBJS = \ + $O\Threads.obj \ + +OBJS = \ + $O\StdAfx.obj \ + $(EXPLORER_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(WIN_CTRL_OBJS) \ + $(UI_COMMON_OBJS) \ + $(FM_COMMON_OBJS)\ + $(C_OBJS) \ + $O\resource.res + +!include "../../../Build.mak" + +$(EXPLORER_OBJS): $(*B).cpp + $(COMPL) +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +$(WIN_CTRL_OBJS): ../../../Windows/Control/$(*B).cpp + $(COMPL) +$(UI_COMMON_OBJS): ../Common/$(*B).cpp + $(COMPL) +$(FM_COMMON_OBJS): ../FileManager/$(*B).cpp + $(COMPL) +$(C_OBJS): ../../../../C/$(*B).c + $(COMPL_O2) diff --git a/CPP/7zip/UI/Explorer/resource.h b/CPP/7zip/UI/Explorer/resource.h new file mode 100755 index 0000000..f3446df --- /dev/null +++ b/CPP/7zip/UI/Explorer/resource.h @@ -0,0 +1,28 @@ +#define IDS_CONTEXT_EXTRACT 142 +#define IDS_CONTEXT_EXTRACT_HELP 143 +#define IDS_CONTEXT_COMPRESS 144 +#define IDS_CONTEXT_COMPRESS_HELP 145 +#define IDS_CONTEXT_OPEN 146 +#define IDS_CONTEXT_OPEN_HELP 147 +#define IDS_CONTEXT_TEST 148 +#define IDS_CONTEXT_TEST_HELP 149 +#define IDS_CONTEXT_CAPTION_HELP 150 +#define IDS_CONTEXT_POPUP_CAPTION 151 + +#define IDS_CONTEXT_EXTRACT_HERE 152 +#define IDS_CONTEXT_EXTRACT_HERE_HELP 153 + +#define IDS_CONTEXT_EXTRACT_TO 154 +#define IDS_CONTEXT_EXTRACT_TO_HELP 155 + +#define IDS_CONTEXT_COMPRESS_TO 156 +#define IDS_CONTEXT_COMPRESS_TO_HELP 157 + +#define IDS_CONTEXT_COMPRESS_EMAIL 158 +#define IDS_CONTEXT_COMPRESS_EMAIL_HELP 159 + +#define IDS_CONTEXT_COMPRESS_TO_EMAIL 160 +#define IDS_CONTEXT_COMPRESS_TO_EMAIL_HELP 161 + +#define IDS_CONTEXT_FOLDER 170 +#define IDS_CONTEXT_ARCHIVE 171 diff --git a/CPP/7zip/UI/Explorer/resource.rc b/CPP/7zip/UI/Explorer/resource.rc new file mode 100755 index 0000000..684eb6e --- /dev/null +++ b/CPP/7zip/UI/Explorer/resource.rc @@ -0,0 +1,8 @@ +#include "../../MyVersionInfo.rc" +#include "resource2.rc" + +MY_VERSION_INFO_DLL("7-Zip Shell Extension", "7-zip") + +#ifndef UNDER_CE +1 24 MOVEABLE PURE "7-zip.dll.manifest" +#endif diff --git a/CPP/7zip/UI/Explorer/resource2.rc b/CPP/7zip/UI/Explorer/resource2.rc new file mode 100755 index 0000000..eddfe60 --- /dev/null +++ b/CPP/7zip/UI/Explorer/resource2.rc @@ -0,0 +1,27 @@ +#include "resource.h" + +STRINGTABLE +BEGIN + IDS_CONTEXT_EXTRACT "Extract files..." + IDS_CONTEXT_EXTRACT_HELP "Extracts files from the selected archive." + IDS_CONTEXT_COMPRESS "Add to archive..." + IDS_CONTEXT_COMPRESS_HELP "Adds the selected items to archive." + IDS_CONTEXT_OPEN "Open archive" + IDS_CONTEXT_OPEN_HELP "Opens the selected archive." + IDS_CONTEXT_TEST "Test archive" + IDS_CONTEXT_TEST_HELP "Tests integrity of the selected archive." + IDS_CONTEXT_CAPTION_HELP "7-Zip commands" + IDS_CONTEXT_POPUP_CAPTION "7-Zip" + IDS_CONTEXT_EXTRACT_HERE "Extract Here" + IDS_CONTEXT_EXTRACT_HERE_HELP "Extracts files from the selected archive to current folder." + IDS_CONTEXT_EXTRACT_TO "Extract to {0}" + IDS_CONTEXT_EXTRACT_TO_HELP "Extracts files to subfolder." + IDS_CONTEXT_COMPRESS_TO "Add to {0}" + IDS_CONTEXT_COMPRESS_TO_HELP "Adds the selected items to archive." + IDS_CONTEXT_COMPRESS_EMAIL "Compress and email..." + IDS_CONTEXT_COMPRESS_EMAIL_HELP "Compresses the selected items to archive and sends archive via email." + IDS_CONTEXT_COMPRESS_TO_EMAIL "Compress to {0} and email" + IDS_CONTEXT_COMPRESS_TO_EMAIL_HELP "Compresses the selected items to archive and sends archive via email." + IDS_CONTEXT_FOLDER "" + IDS_CONTEXT_ARCHIVE "" +END diff --git a/CPP/7zip/UI/Far/ExtractEngine.cpp b/CPP/7zip/UI/Far/ExtractEngine.cpp new file mode 100755 index 0000000..6e2b39c --- /dev/null +++ b/CPP/7zip/UI/Far/ExtractEngine.cpp @@ -0,0 +1,176 @@ +// ExtractEngine.h + +#include "StdAfx.h" + +#include "Common/StringConvert.h" + +#include "ExtractEngine.h" +#include "FarUtils.h" +#include "Messages.h" +#include "OverwriteDialog.h" + +using namespace NWindows; +using namespace NFar; + +extern void PrintMessage(const char *message); + +CExtractCallBackImp::~CExtractCallBackImp() +{ +} + +void CExtractCallBackImp::Init( + UINT codePage, + CProgressBox *progressBox, + bool passwordIsDefined, + const UString &password) +{ + m_PasswordIsDefined = passwordIsDefined; + m_Password = password; + m_CodePage = codePage; + m_ProgressBox = progressBox; +} + +STDMETHODIMP CExtractCallBackImp::SetTotal(UInt64 size) +{ + _total = size; + _totalIsDefined = true; + return S_OK; +} + +STDMETHODIMP CExtractCallBackImp::SetCompleted(const UInt64 *completeValue) +{ + if (WasEscPressed()) + return E_ABORT; + _processedIsDefined = (completeValue != NULL); + if (_processedIsDefined) + _processed = *completeValue; + if (m_ProgressBox != 0) + m_ProgressBox->Progress( + _totalIsDefined ? &_total: NULL, + _processedIsDefined ? &_processed: NULL, AString()); + return S_OK; +} + +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) +{ + NOverwriteDialog::CFileInfo oldFileInfo, newFileInfo; + oldFileInfo.TimeIsDefined = (existTime != 0); + if (oldFileInfo.TimeIsDefined) + oldFileInfo.Time = *existTime; + oldFileInfo.SizeIsDefined = (existSize != NULL); + if (oldFileInfo.SizeIsDefined) + oldFileInfo.Size = *existSize; + oldFileInfo.Name = existName; + + newFileInfo.TimeIsDefined = (newTime != 0); + if (newFileInfo.TimeIsDefined) + newFileInfo.Time = *newTime; + newFileInfo.SizeIsDefined = (newSize != NULL); + if (newFileInfo.SizeIsDefined) + newFileInfo.Size = *newSize; + newFileInfo.Name = newName; + + NOverwriteDialog::NResult::EEnum result = + NOverwriteDialog::Execute(oldFileInfo, newFileInfo); + + switch(result) + { + case NOverwriteDialog::NResult::kCancel: + // *answer = NOverwriteAnswer::kCancel; + // break; + return E_ABORT; + case NOverwriteDialog::NResult::kNo: + *answer = NOverwriteAnswer::kNo; + break; + case NOverwriteDialog::NResult::kNoToAll: + *answer = NOverwriteAnswer::kNoToAll; + break; + case NOverwriteDialog::NResult::kYesToAll: + *answer = NOverwriteAnswer::kYesToAll; + break; + case NOverwriteDialog::NResult::kYes: + *answer = NOverwriteAnswer::kYes; + break; + case NOverwriteDialog::NResult::kAutoRename: + *answer = NOverwriteAnswer::kAutoRename; + break; + default: + return E_FAIL; + } + return S_OK; +} + +STDMETHODIMP CExtractCallBackImp::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 /* askExtractMode */, const UInt64 * /* position */) +{ + if (WasEscPressed()) + return E_ABORT; + m_CurrentFilePath = name; + return S_OK; +} + +STDMETHODIMP CExtractCallBackImp::MessageError(const wchar_t *message) +{ + AString s = UnicodeStringToMultiByte(message, CP_OEMCP); + if (g_StartupInfo.ShowMessage((const char *)s) == -1) + return E_ABORT; + return S_OK; +} + +static void ReduceString(UString &s, int size) +{ + if (s.Length() > size) + s = s.Left(size / 2) + UString(L" ... ") + s.Right(size / 2); +} + +STDMETHODIMP CExtractCallBackImp::SetOperationResult(Int32 operationResult, bool encrypted) +{ + switch(operationResult) + { + case NArchive::NExtract::NOperationResult::kOK: + break; + default: + { + UINT idMessage; + switch(operationResult) + { + case NArchive::NExtract::NOperationResult::kUnSupportedMethod: + idMessage = NMessageID::kExtractUnsupportedMethod; + break; + case NArchive::NExtract::NOperationResult::kCRCError: + idMessage = encrypted ? + NMessageID::kExtractCRCFailedEncrypted : + NMessageID::kExtractCRCFailed; + break; + case NArchive::NExtract::NOperationResult::kDataError: + idMessage = encrypted ? + NMessageID::kExtractDataErrorEncrypted : + NMessageID::kExtractDataError; + break; + default: + return E_FAIL; + } + UString name = m_CurrentFilePath; + ReduceString(name, 70); + AString s = g_StartupInfo.GetMsgString(idMessage); + s.Replace(" '%s'", ""); + if (g_StartupInfo.ShowMessageLines(s + (AString)("\n") + UnicodeStringToMultiByte(name, m_CodePage)) == -1) + return E_ABORT; + } + } + return S_OK; +} + +extern HRESULT GetPassword(UString &password); + +STDMETHODIMP CExtractCallBackImp::CryptoGetTextPassword(BSTR *password) +{ + if (!m_PasswordIsDefined) + { + RINOK(GetPassword(m_Password)); + m_PasswordIsDefined = true; + } + return StringToBstr(m_Password, password); +} diff --git a/CPP/7zip/UI/Far/ExtractEngine.h b/CPP/7zip/UI/Far/ExtractEngine.h new file mode 100755 index 0000000..797089f --- /dev/null +++ b/CPP/7zip/UI/Far/ExtractEngine.h @@ -0,0 +1,68 @@ +// ExtractEngine.h + +#ifndef __EXTRACTENGINE_H +#define __EXTRACTENGINE_H + +#include "Common/MyCom.h" +#include "Common/MyString.h" + +#include "../../IPassword.h" +#include "../Agent/IFolderArchive.h" + +#include "ProgressBox.h" + +class CExtractCallBackImp: + public IFolderArchiveExtractCallback, + public ICryptoGetTextPassword, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP1(ICryptoGetTextPassword) + + // IProgress + STDMETHOD(SetTotal)(UInt64 size); + STDMETHOD(SetCompleted)(const UInt64 *completeValue); + + // IExtractCallBack + STDMETHOD(AskOverwrite)( + const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, + const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, + Int32 *result); + STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position); + + STDMETHOD(MessageError)(const wchar_t *message); + STDMETHOD(SetOperationResult)(Int32 resultEOperationResult, bool encrypted); + // ICryptoGetTextPassword + STDMETHOD(CryptoGetTextPassword)(BSTR *password); + +private: + UInt64 _total; + UInt64 _processed; + + bool _totalIsDefined; + bool _processedIsDefined; + + UString m_CurrentFilePath; + + CProgressBox *m_ProgressBox; + UINT m_CodePage; + + bool m_PasswordIsDefined; + UString m_Password; + + void CreateComplexDirectory(const UStringVector &dirPathParts); + /* + void GetPropertyValue(LPITEMIDLIST anItemIDList, PROPID aPropId, + PROPVARIANT *aValue); + bool IsEncrypted(LPITEMIDLIST anItemIDList); + */ + void AddErrorMessage(LPCTSTR message); +public: + CExtractCallBackImp(): _totalIsDefined(false), _processedIsDefined(false) {} + ~CExtractCallBackImp(); + void Init(UINT codePage, + CProgressBox *progressBox, + bool passwordIsDefined, const UString &password); +}; + +#endif diff --git a/CPP/7zip/UI/Far/Far.def b/CPP/7zip/UI/Far/Far.def new file mode 100755 index 0000000..9dd3930 --- /dev/null +++ b/CPP/7zip/UI/Far/Far.def @@ -0,0 +1,34 @@ +; 7-ZipFar.def : Declares the module parameters for the DLL. + +LIBRARY "7-ZipFar" + +EXPORTS + SetStartupInfo + OpenPlugin + OpenFilePlugin + ClosePlugin + GetFindData + FreeFindData + SetDirectory + GetPluginInfo + Configure + GetOpenPluginInfo + GetFiles + PutFiles + DeleteFiles + ProcessKey + + ;SetStartupInfoW + ;OpenPluginW + ;OpenFilePluginW + ;ClosePluginW + ;GetFindDataW + ;FreeFindDataW + ;SetDirectoryW + ;GetPluginInfoW + ;ConfigureW + ;GetOpenPluginInfoW + ;GetFilesW + ;PutFilesW + ;DeleteFilesW + ;ProcessKeyW diff --git a/CPP/7zip/UI/Far/Far.dsp b/CPP/7zip/UI/Far/Far.dsp new file mode 100755 index 0000000..cf55e20 --- /dev/null +++ b/CPP/7zip/UI/Far/Far.dsp @@ -0,0 +1,627 @@ +# Microsoft Developer Studio Project File - Name="Far" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=Far - 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 "Far.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 "Far.mak" CFG="Far - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Far - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "Far - 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)" == "Far - 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 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FAR_EXPORTS" /YX /FD /c +# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FAR_EXPORTS" /D "EXTERNAL_CODECS" /Yu"StdAfx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Program Files\Far\Plugins\7-Zip\7-ZipFar.dll" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "Far - 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 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FAR_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FAR_EXPORTS" /D "EXTERNAL_CODECS" /Yu"StdAfx.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\Far\Plugins\7-Zip\7-ZipFar.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "Far - Win32 Release" +# Name "Far - Win32 Debug" +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\Far.def +# 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 "Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Common\CRC.cpp +# 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 "Plugin" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\ExtractEngine.cpp +# End Source File +# Begin Source File + +SOURCE=.\ExtractEngine.h +# End Source File +# Begin Source File + +SOURCE=.\Main.cpp +# End Source File +# Begin Source File + +SOURCE=.\Messages.h +# End Source File +# Begin Source File + +SOURCE=.\OverwriteDialog.cpp +# End Source File +# Begin Source File + +SOURCE=.\OverwriteDialog.h +# End Source File +# Begin Source File + +SOURCE=.\Plugin.cpp +# End Source File +# Begin Source File + +SOURCE=.\Plugin.h +# End Source File +# Begin Source File + +SOURCE=.\PluginDelete.cpp +# End Source File +# Begin Source File + +SOURCE=.\PluginRead.cpp +# End Source File +# Begin Source File + +SOURCE=.\PluginWrite.cpp +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# Begin Source File + +SOURCE=.\UpdateCallback100.cpp +# End Source File +# Begin Source File + +SOURCE=.\UpdateCallback100.h +# End Source File +# End Group +# Begin Group "Far" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\FarPlugin.h +# End Source File +# Begin Source File + +SOURCE=.\FarUtils.cpp +# End Source File +# Begin Source File + +SOURCE=.\FarUtils.h +# End Source File +# Begin Source File + +SOURCE=.\ProgressBox.cpp +# End Source File +# Begin Source File + +SOURCE=.\ProgressBox.h +# 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\DLL.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\DLL.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Error.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Error.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\PropVariantConversions.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariantConversions.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Registry.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Registry.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\Time.cpp +# End Source File +# End Group +# Begin Group "UI Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\Common\ArchiveExtractCallback.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ArchiveExtractCallback.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ArchiveOpenCallback.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ArchiveOpenCallback.h +# End Source File +# Begin Source File + +SOURCE=..\Common\DefaultName.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\DefaultName.h +# End Source File +# Begin Source File + +SOURCE=..\Common\DirItem.h +# End Source File +# Begin Source File + +SOURCE=..\Common\EnumDirItems.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\EnumDirItems.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ExtractingFilePath.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ExtractingFilePath.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ExtractMode.h +# End Source File +# Begin Source File + +SOURCE=..\Common\HandlerLoader.h +# End Source File +# Begin Source File + +SOURCE=..\Common\LoadCodecs.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\LoadCodecs.h +# End Source File +# Begin Source File + +SOURCE=..\Common\OpenArchive.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\OpenArchive.h +# End Source File +# Begin Source File + +SOURCE=..\Common\PropIDUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\PropIDUtils.h +# End Source File +# Begin Source File + +SOURCE=..\Common\SortUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\SortUtils.h +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdateAction.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdateAction.h +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdateCallback.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdateCallback.h +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdatePair.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdatePair.h +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdateProduce.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdateProduce.h +# End Source File +# Begin Source File + +SOURCE=..\Common\WorkDir.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\WorkDir.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ZipRegistry.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ZipRegistry.h +# End Source File +# End Group +# Begin Group "Agent" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\Agent\Agent.cpp +# End Source File +# Begin Source File + +SOURCE=..\Agent\Agent.h +# End Source File +# Begin Source File + +SOURCE=..\Agent\AgentOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\Agent\AgentProxy.cpp +# End Source File +# Begin Source File + +SOURCE=..\Agent\AgentProxy.h +# End Source File +# Begin Source File + +SOURCE=..\Agent\IFolderArchive.h +# End Source File +# Begin Source File + +SOURCE=..\Agent\UpdateCallbackAgent.cpp +# End Source File +# Begin Source File + +SOURCE=..\Agent\UpdateCallbackAgent.h +# End Source File +# End Group +# Begin Group "Compress" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\CopyCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\CopyCoder.h +# End Source File +# End Group +# Begin Group "7-zip Common" + +# PROP Default_Filter "" +# 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\ProgressUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File +# End Group +# Begin Group "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\CpuArch.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Sort.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Sort.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 Group "Arc Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\OutStreamWithCRC.h +# End Source File +# End Group +# End Target +# End Project diff --git a/CPP/7zip/UI/Far/Far.dsw b/CPP/7zip/UI/Far/Far.dsw new file mode 100755 index 0000000..ed52003 --- /dev/null +++ b/CPP/7zip/UI/Far/Far.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "Far"=.\Far.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/CPP/7zip/UI/Far/FarPlugin.h b/CPP/7zip/UI/Far/FarPlugin.h new file mode 100755 index 0000000..6f583e8 --- /dev/null +++ b/CPP/7zip/UI/Far/FarPlugin.h @@ -0,0 +1,519 @@ +// FarPlugin.h + +// #include "plugin.hpp" + +const int kInfoPanelLineSize = 80; + +// #define __FAR_PLUGIN_H + +#ifdef UNDER_CE +typedef struct _CHAR_INFO { + union { + WCHAR UnicodeChar; + CHAR AsciiChar; + } Char; + WORD Attributes; +} CHAR_INFO, *PCHAR_INFO; +#endif + +#ifndef __FAR_PLUGIN_H +#define __FAR_PLUGIN_H + +#ifndef _WIN64 +#if defined(__BORLANDC__) && (__BORLANDC <= 0x520) + #pragma option -a1 +#elif defined(__GNUC__) || (defined(__WATCOMC__) && (__WATCOMC__ < 1100)) + #pragma pack(1) +#else + #pragma pack(push,1) +#endif +#endif + + #if _MSC_VER + #define _export + #endif + +#define NM 260 + +struct FarFindData +{ + DWORD dwFileAttributes; + FILETIME ftCreationTime; + FILETIME ftLastAccessTime; + FILETIME ftLastWriteTime; + DWORD nFileSizeHigh; + DWORD nFileSizeLow; + DWORD dwReserved0; + DWORD dwReserved1; + char cFileName[ MAX_PATH ]; + char cAlternateFileName[ 14 ]; +}; + +struct PluginPanelItem +{ + FarFindData FindData; + DWORD PackSizeHigh; + DWORD PackSize; + DWORD Flags; + DWORD NumberOfLinks; + char *Description; + char *Owner; + char **CustomColumnData; + int CustomColumnNumber; + DWORD_PTR UserData; + DWORD CRC32; + DWORD_PTR Reserved[2]; +}; + +#define PPIF_PROCESSDESCR 0x80000000 +#define PPIF_SELECTED 0x40000000 +#define PPIF_USERDATA 0x20000000 + +enum { + FMENU_SHOWAMPERSAND=1, + FMENU_WRAPMODE=2, + FMENU_AUTOHIGHLIGHT=4, + FMENU_REVERSEAUTOHIGHLIGHT=8 +}; + + +typedef int (WINAPI *FARAPIMENU)( + INT_PTR PluginNumber, + int X, + int Y, + int MaxHeight, + unsigned int Flags, + char *Title, + char *Bottom, + char *HelpTopic, + int *BreakKeys, + int *BreakCode, + struct FarMenuItem *Item, + int ItemsNumber +); + +typedef int (WINAPI *FARAPIDIALOG)( + INT_PTR PluginNumber, + int X1, + int Y1, + int X2, + int Y2, + char *HelpTopic, + struct FarDialogItem *Item, + int ItemsNumber +); + +enum { + FMSG_WARNING=1, + FMSG_ERRORTYPE=2, + FMSG_KEEPBACKGROUND=4, + FMSG_DOWN=8, + FMSG_LEFTALIGN=16 +}; + +typedef int (WINAPI *FARAPIMESSAGE)( + INT_PTR PluginNumber, + unsigned int Flags, + char *HelpTopic, + char **Items, + int ItemsNumber, + int ButtonsNumber +); + +typedef char* (WINAPI *FARAPIGETMSG)( + INT_PTR PluginNumber, + int MsgId +); + + +enum DialogItemTypes { + DI_TEXT, + DI_VTEXT, + DI_SINGLEBOX, + DI_DOUBLEBOX, + DI_EDIT, + DI_PSWEDIT, + DI_FIXEDIT, + DI_BUTTON, + DI_CHECKBOX, + DI_RADIOBUTTON +}; + +enum FarDialogItemFlags { + DIF_COLORMASK = 0xff, + DIF_SETCOLOR = 0x100, + DIF_BOXCOLOR = 0x200, + DIF_GROUP = 0x400, + DIF_LEFTTEXT = 0x800, + DIF_MOVESELECT = 0x1000, + DIF_SHOWAMPERSAND = 0x2000, + DIF_CENTERGROUP = 0x4000, + DIF_NOBRACKETS = 0x8000, + DIF_SEPARATOR = 0x10000, + DIF_EDITOR = 0x20000, + DIF_HISTORY = 0x40000 +}; + +struct FarDialogItem +{ + int Type; + int X1,Y1,X2,Y2; + int Focus; + union + { + int Selected; + const char *History; + const char *Mask; + struct FarList *ListItems; + int ListPos; + CHAR_INFO *VBuf; + }; + unsigned int Flags; + int DefaultButton; + char Data[512]; +}; + + +struct FarMenuItem +{ + char Text[128]; + int Selected; + int Checked; + int Separator; +}; + + +enum {FCTL_CLOSEPLUGIN,FCTL_GETPANELINFO,FCTL_GETANOTHERPANELINFO, + FCTL_UPDATEPANEL,FCTL_UPDATEANOTHERPANEL, + FCTL_REDRAWPANEL,FCTL_REDRAWANOTHERPANEL, + FCTL_SETANOTHERPANELDIR,FCTL_GETCMDLINE,FCTL_SETCMDLINE, + FCTL_SETSELECTION,FCTL_SETANOTHERSELECTION, + FCTL_SETVIEWMODE,FCTL_SETANOTHERVIEWMODE,FCTL_INSERTCMDLINE, + FCTL_SETUSERSCREEN,FCTL_SETPANELDIR,FCTL_SETCMDLINEPOS, + FCTL_GETCMDLINEPOS +}; + +enum {PTYPE_FILEPANEL,PTYPE_TREEPANEL,PTYPE_QVIEWPANEL,PTYPE_INFOPANEL}; + +struct PanelInfo +{ + int PanelType; + int Plugin; + RECT PanelRect; + struct PluginPanelItem *PanelItems; + int ItemsNumber; + struct PluginPanelItem *SelectedItems; + int SelectedItemsNumber; + int CurrentItem; + int TopPanelItem; + int Visible; + int Focus; + int ViewMode; + char ColumnTypes[80]; + char ColumnWidths[80]; + char CurDir[NM]; + int ShortNames; + int SortMode; + DWORD Flags; + DWORD Reserved; +}; + + +struct PanelRedrawInfo +{ + int CurrentItem; + int TopPanelItem; +}; + + +typedef int (WINAPI *FARAPICONTROL)( + HANDLE hPlugin, + int Command, + void *Param +); + +typedef HANDLE (WINAPI *FARAPISAVESCREEN)(int X1,int Y1,int X2,int Y2); + +typedef void (WINAPI *FARAPIRESTORESCREEN)(HANDLE hScreen); + +typedef int (WINAPI *FARAPIGETDIRLIST)( + char *Dir, + struct PluginPanelItem **pPanelItem, + int *pItemsNumber +); + +typedef int (WINAPI *FARAPIGETPLUGINDIRLIST)( + INT_PTR PluginNumber, + HANDLE hPlugin, + char *Dir, + struct PluginPanelItem **pPanelItem, + int *pItemsNumber +); + +typedef void (WINAPI *FARAPIFREEDIRLIST)(struct PluginPanelItem *PanelItem); + +enum VIEWER_FLAGS { + VF_NONMODAL=1,VF_DELETEONCLOSE=2 +}; + +typedef int (WINAPI *FARAPIVIEWER)( + char *FileName, + char *Title, + int X1, + int Y1, + int X2, + int Y2, + DWORD Flags +); + +typedef int (WINAPI *FARAPIEDITOR)( + char *FileName, + char *Title, + int X1, + int Y1, + int X2, + int Y2, + DWORD Flags, + int StartLine, + int StartChar +); + +typedef int (WINAPI *FARAPICMPNAME)( + char *Pattern, + char *String, + int SkipPath +); + + +#define FCT_DETECT 0x40000000 + +struct CharTableSet +{ + char DecodeTable[256]; + char EncodeTable[256]; + char UpperTable[256]; + char LowerTable[256]; + char TableName[128]; +}; + +typedef int (WINAPI *FARAPICHARTABLE)( + int Command, + char *Buffer, + int BufferSize +); + +typedef void (WINAPI *FARAPITEXT)( + int X, + int Y, + int Color, + char *Str +); + + +typedef int (WINAPI *FARAPIEDITORCONTROL)( + int Command, + void *Param +); + +struct PluginStartupInfo +{ + int StructSize; + char ModuleName[NM]; + INT_PTR ModuleNumber; + char *RootKey; + FARAPIMENU Menu; + FARAPIDIALOG Dialog; + FARAPIMESSAGE Message; + FARAPIGETMSG GetMsg; + FARAPICONTROL Control; + FARAPISAVESCREEN SaveScreen; + FARAPIRESTORESCREEN RestoreScreen; + FARAPIGETDIRLIST GetDirList; + FARAPIGETPLUGINDIRLIST GetPluginDirList; + FARAPIFREEDIRLIST FreeDirList; + FARAPIVIEWER Viewer; + FARAPIEDITOR Editor; + FARAPICMPNAME CmpName; + FARAPICHARTABLE CharTable; + FARAPITEXT Text; + FARAPIEDITORCONTROL EditorControl; +}; + + +enum PLUGIN_FLAGS { + PF_PRELOAD = 0x0001, + PF_DISABLEPANELS = 0x0002, + PF_EDITOR = 0x0004, + PF_VIEWER = 0x0008 +}; + + +struct PluginInfo +{ + int StructSize; + DWORD Flags; + char **DiskMenuStrings; + int *DiskMenuNumbers; + int DiskMenuStringsNumber; + char **PluginMenuStrings; + int PluginMenuStringsNumber; + char **PluginConfigStrings; + int PluginConfigStringsNumber; + char *CommandPrefix; +}; + +struct InfoPanelLine +{ + char Text[kInfoPanelLineSize]; + char Data[kInfoPanelLineSize]; + int Separator; +}; + + +struct PanelMode +{ + char *ColumnTypes; + char *ColumnWidths; + char **ColumnTitles; + int FullScreen; + int DetailedStatus; + int AlignExtensions; + int CaseConversion; + char *StatusColumnTypes; + char *StatusColumnWidths; + DWORD Reserved[2]; +}; + + +enum OPENPLUGININFO_FLAGS { + OPIF_USEFILTER = 0x0001, + OPIF_USESORTGROUPS = 0x0002, + OPIF_USEHIGHLIGHTING = 0x0004, + OPIF_ADDDOTS = 0x0008, + OPIF_RAWSELECTION = 0x0010, + OPIF_REALNAMES = 0x0020, + OPIF_SHOWNAMESONLY = 0x0040, + OPIF_SHOWRIGHTALIGNNAMES = 0x0080, + OPIF_SHOWPRESERVECASE = 0x0100, + OPIF_FINDFOLDERS = 0x0200, + OPIF_COMPAREFATTIME = 0x0400, + OPIF_EXTERNALGET = 0x0800, + OPIF_EXTERNALPUT = 0x1000, + OPIF_EXTERNALDELETE = 0x2000, + OPIF_EXTERNALMKDIR = 0x4000, + OPIF_USEATTRHIGHLIGHTING = 0x8000 +}; + + +enum OPENPLUGININFO_SORTMODES { + SM_DEFAULT,SM_UNSORTED,SM_NAME,SM_EXT,SM_MTIME,SM_CTIME, + SM_ATIME,SM_SIZE,SM_DESCR,SM_OWNER,SM_COMPRESSEDSIZE,SM_NUMLINKS +}; + + +struct KeyBarTitles +{ + char *Titles[12]; + char *CtrlTitles[12]; + char *AltTitles[12]; + char *ShiftTitles[12]; +}; + + +struct OpenPluginInfo +{ + int StructSize; + DWORD Flags; + char *HostFile; + char *CurDir; + char *Format; + char *PanelTitle; + struct InfoPanelLine *InfoLines; + int InfoLinesNumber; + char **DescrFiles; + int DescrFilesNumber; + struct PanelMode *PanelModesArray; + int PanelModesNumber; + int StartPanelMode; + int StartSortMode; + int StartSortOrder; + struct KeyBarTitles *KeyBar; + char *ShortcutData; +}; + +enum { + OPEN_DISKMENU, + OPEN_PLUGINSMENU, + OPEN_FINDLIST, + OPEN_SHORTCUT, + OPEN_COMMANDLINE, + OPEN_EDITOR, + OPEN_VIEWER +}; + +enum {PKF_CONTROL=1,PKF_ALT=2,PKF_SHIFT=4}; + +enum FAR_EVENTS { + FE_CHANGEVIEWMODE, + FE_REDRAW, + FE_IDLE, + FE_CLOSE, + FE_BREAK, + FE_COMMAND +}; + +enum OPERATION_MODES { + OPM_SILENT=1, + OPM_FIND=2, + OPM_VIEW=4, + OPM_EDIT=8, + OPM_TOPLEVEL=16, + OPM_DESCR=32 +}; + +#ifndef _WIN64 +#if defined(__BORLANDC__) && (__BORLANDC <= 0x520) + #pragma option -a. +#elif defined(__GNUC__) || (defined(__WATCOMC__) && (__WATCOMC__ < 1100)) + #pragma pack() +#else + #pragma pack(pop) +#endif +#endif + +/* +EXTERN_C_BEGIN + + void WINAPI _export ClosePluginW(HANDLE hPlugin); + int WINAPI _export CompareW(HANDLE hPlugin,const struct PluginPanelItem *Item1,const struct PluginPanelItem *Item2,unsigned int Mode); + int WINAPI _export ConfigureW(int ItemNumber); + int WINAPI _export DeleteFilesW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int OpMode); + void WINAPI _export ExitFARW(void); + void WINAPI _export FreeFindDataW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber); + void WINAPI _export FreeVirtualFindDataW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber); + int WINAPI _export GetFilesW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int Move,const wchar_t **DestPath,int OpMode); + int WINAPI _export GetFindDataW(HANDLE hPlugin,struct PluginPanelItem **pPanelItem,int *pItemsNumber,int OpMode); + int WINAPI _export GetMinFarVersionW(void); + void WINAPI _export GetOpenPluginInfoW(HANDLE hPlugin,struct OpenPluginInfo *Info); + void WINAPI _export GetPluginInfoW(struct PluginInfo *Info); + int WINAPI _export GetVirtualFindDataW(HANDLE hPlugin,struct PluginPanelItem **pPanelItem,int *pItemsNumber,const wchar_t *Path); + int WINAPI _export MakeDirectoryW(HANDLE hPlugin,const wchar_t **Name,int OpMode); + HANDLE WINAPI _export OpenFilePluginW(const wchar_t *Name,const unsigned char *Data,int DataSize,int OpMode); + HANDLE WINAPI _export OpenPluginW(int OpenFrom,INT_PTR Item); + int WINAPI _export ProcessDialogEventW(int Event,void *Param); + int WINAPI _export ProcessEditorEventW(int Event,void *Param); + int WINAPI _export ProcessEditorInputW(const INPUT_RECORD *Rec); + int WINAPI _export ProcessEventW(HANDLE hPlugin,int Event,void *Param); + int WINAPI _export ProcessHostFileW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int OpMode); + int WINAPI _export ProcessKeyW(HANDLE hPlugin,int Key,unsigned int ControlState); + int WINAPI _export ProcessSynchroEventW(int Event,void *Param); + int WINAPI _export ProcessViewerEventW(int Event,void *Param); + int WINAPI _export PutFilesW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int Move,const wchar_t *SrcPath,int OpMode); + int WINAPI _export SetDirectoryW(HANDLE hPlugin,const wchar_t *Dir,int OpMode); + int WINAPI _export SetFindListW(HANDLE hPlugin,const struct PluginPanelItem *PanelItem,int ItemsNumber); + void WINAPI _export SetStartupInfoW(const struct PluginStartupInfo *Info); + +EXTERN_C_END +*/ + +#endif diff --git a/CPP/7zip/UI/Far/FarUtils.cpp b/CPP/7zip/UI/Far/FarUtils.cpp new file mode 100755 index 0000000..cfdeb1b --- /dev/null +++ b/CPP/7zip/UI/Far/FarUtils.cpp @@ -0,0 +1,464 @@ +// FarUtils.cpp + +#include "StdAfx.h" + +#include "Common/StringConvert.h" + +#ifndef UNDER_CE +#include "Windows/Console.h" +#endif +#include "Windows/Defs.h" +#include "Windows/Error.h" + +#include "FarUtils.h" + +using namespace NWindows; + +namespace NFar { + +CStartupInfo g_StartupInfo; + +void CStartupInfo::Init(const PluginStartupInfo &pluginStartupInfo, + const CSysString &pluginNameForRegestry) +{ + m_Data = pluginStartupInfo; + m_RegistryPath = GetSystemString(pluginStartupInfo.RootKey); + m_RegistryPath += TEXT('\\'); + m_RegistryPath += pluginNameForRegestry; +} + +const char *CStartupInfo::GetMsgString(int messageId) +{ + return (const char*)m_Data.GetMsg(m_Data.ModuleNumber, messageId); +} + +int CStartupInfo::ShowMessage(unsigned int flags, + const char *helpTopic, const char **items, int numItems, int numButtons) +{ + return m_Data.Message(m_Data.ModuleNumber, flags, (char *)helpTopic, + (char **)items, numItems, numButtons); +} + +namespace NMessageID +{ + enum + { + kOk, + kCancel, + kWarning, + kError + }; +} + +int CStartupInfo::ShowMessage(const char *message) +{ + const char *items[]= { GetMsgString(NMessageID::kError), message, GetMsgString(NMessageID::kOk) }; + return ShowMessage(FMSG_WARNING, NULL, items, sizeof(items) / sizeof(items[0]), 1); +} + +static void SplitString(const AString &srcString, AStringVector &destStrings) +{ + destStrings.Clear(); + AString string; + int len = srcString.Length(); + if (len == 0) + return; + for (int i = 0; i < len; i++) + { + char c = srcString[i]; + if (c == '\n') + { + if (!string.IsEmpty()) + { + destStrings.Add(string); + string.Empty(); + } + } + else + string += c; + } + if (!string.IsEmpty()) + destStrings.Add(string); +} + +int CStartupInfo::ShowMessageLines(const char *message) +{ + AStringVector strings; + SplitString(message, strings); + const int kNumStringsMax = 20; + const char *items[kNumStringsMax + 1] = { GetMsgString(NMessageID::kError) }; + int pos = 1; + for (int i = 0; i < strings.Size() && pos < kNumStringsMax; i++) + items[pos++] = strings[i]; + items[pos++] = GetMsgString(NMessageID::kOk); + + return ShowMessage(FMSG_WARNING, NULL, items, pos, 1); +} + +int CStartupInfo::ShowMessage(int messageId) +{ + return ShowMessage(GetMsgString(messageId)); +} + +int CStartupInfo::ShowDialog(int X1, int Y1, int X2, int Y2, + const char *helpTopic, struct FarDialogItem *items, int numItems) +{ + return m_Data.Dialog(m_Data.ModuleNumber, X1, Y1, X2, Y2, (char *)helpTopic, + items, numItems); +} + +int CStartupInfo::ShowDialog(int sizeX, int sizeY, + const char *helpTopic, struct FarDialogItem *items, int numItems) +{ + return ShowDialog(-1, -1, sizeX, sizeY, helpTopic, items, numItems); +} + +inline static BOOL GetBOOLValue(bool v) { return (v? TRUE: FALSE); } + +void CStartupInfo::InitDialogItems(const CInitDialogItem *srcItems, + FarDialogItem *destItems, int numItems) +{ + for (int i = 0; i < numItems; i++) + { + const CInitDialogItem &srcItem = srcItems[i]; + FarDialogItem &destItem = destItems[i]; + + destItem.Type = srcItem.Type; + destItem.X1 = srcItem.X1; + destItem.Y1 = srcItem.Y1; + destItem.X2 = srcItem.X2; + destItem.Y2 = srcItem.Y2; + destItem.Focus = GetBOOLValue(srcItem.Focus); + if(srcItem.HistoryName != NULL) + destItem.History = srcItem.HistoryName; + else + destItem.Selected = GetBOOLValue(srcItem.Selected); + destItem.Flags = srcItem.Flags; + destItem.DefaultButton = GetBOOLValue(srcItem.DefaultButton); + + if(srcItem.DataMessageId < 0) + MyStringCopy(destItem.Data, srcItem.DataString); + else + MyStringCopy(destItem.Data, GetMsgString(srcItem.DataMessageId)); + + /* + if ((unsigned int)Init[i].Data < 0xFFF) + MyStringCopy(destItem.Data, GetMsg((unsigned int)srcItem.Data)); + else + MyStringCopy(destItem.Data,srcItem.Data); + */ + } +} + +// -------------------------------------------- + +HANDLE CStartupInfo::SaveScreen(int X1, int Y1, int X2, int Y2) +{ + return m_Data.SaveScreen(X1, Y1, X2, Y2); +} + +HANDLE CStartupInfo::SaveScreen() +{ + return SaveScreen(0, 0, -1, -1); +} + +void CStartupInfo::RestoreScreen(HANDLE handle) +{ + m_Data.RestoreScreen(handle); +} + +const TCHAR kRegestryKeyDelimiter = TEXT('\''); + +CSysString CStartupInfo::GetFullKeyName(const CSysString &keyName) const +{ + return (keyName.IsEmpty()) ? m_RegistryPath: + (m_RegistryPath + kRegestryKeyDelimiter + keyName); +} + + +LONG CStartupInfo::CreateRegKey(HKEY parentKey, + const CSysString &keyName, NRegistry::CKey &destKey) const +{ + return destKey.Create(parentKey, GetFullKeyName(keyName)); +} + +LONG CStartupInfo::OpenRegKey(HKEY parentKey, + const CSysString &keyName, NRegistry::CKey &destKey) const +{ + return destKey.Open(parentKey, GetFullKeyName(keyName)); +} + +void CStartupInfo::SetRegKeyValue(HKEY parentKey, const CSysString &keyName, + LPCTSTR valueName, LPCTSTR value) const +{ + NRegistry::CKey regKey; + CreateRegKey(parentKey, keyName, regKey); + regKey.SetValue(valueName, value); +} + +void CStartupInfo::SetRegKeyValue(HKEY parentKey, const CSysString &keyName, + LPCTSTR valueName, UINT32 value) const +{ + NRegistry::CKey regKey; + CreateRegKey(parentKey, keyName, regKey); + regKey.SetValue(valueName, value); +} + +void CStartupInfo::SetRegKeyValue(HKEY parentKey, const CSysString &keyName, + LPCTSTR valueName, bool value) const +{ + NRegistry::CKey regKey; + CreateRegKey(parentKey, keyName, regKey); + regKey.SetValue(valueName, value); +} + +CSysString CStartupInfo::QueryRegKeyValue(HKEY parentKey, const CSysString &keyName, + LPCTSTR valueName, const CSysString &valueDefault) const +{ + NRegistry::CKey regKey; + if (OpenRegKey(parentKey, keyName, regKey) != ERROR_SUCCESS) + return valueDefault; + + CSysString value; + if(regKey.QueryValue(valueName, value) != ERROR_SUCCESS) + return valueDefault; + + return value; +} + +UINT32 CStartupInfo::QueryRegKeyValue(HKEY parentKey, const CSysString &keyName, + LPCTSTR valueName, UINT32 valueDefault) const +{ + NRegistry::CKey regKey; + if (OpenRegKey(parentKey, keyName, regKey) != ERROR_SUCCESS) + return valueDefault; + + UINT32 value; + if(regKey.QueryValue(valueName, value) != ERROR_SUCCESS) + return valueDefault; + + return value; +} + +bool CStartupInfo::QueryRegKeyValue(HKEY parentKey, const CSysString &keyName, + LPCTSTR valueName, bool valueDefault) const +{ + NRegistry::CKey regKey; + if (OpenRegKey(parentKey, keyName, regKey) != ERROR_SUCCESS) + return valueDefault; + + bool value; + if(regKey.QueryValue(valueName, value) != ERROR_SUCCESS) + return valueDefault; + + return value; +} + +bool CStartupInfo::Control(HANDLE pluginHandle, int command, void *param) +{ + return BOOLToBool(m_Data.Control(pluginHandle, command, param)); +} + +bool CStartupInfo::ControlRequestActivePanel(int command, void *param) +{ + return Control(INVALID_HANDLE_VALUE, command, param); +} + +bool CStartupInfo::ControlGetActivePanelInfo(PanelInfo &panelInfo) +{ + return ControlRequestActivePanel(FCTL_GETPANELINFO, &panelInfo); +} + +bool CStartupInfo::ControlSetSelection(const PanelInfo &panelInfo) +{ + return ControlRequestActivePanel(FCTL_SETSELECTION, (void *)&panelInfo); +} + +bool CStartupInfo::ControlGetActivePanelCurrentItemInfo( + PluginPanelItem &pluginPanelItem) +{ + PanelInfo panelInfo; + if(!ControlGetActivePanelInfo(panelInfo)) + return false; + if(panelInfo.ItemsNumber <= 0) + throw "There are no items"; + pluginPanelItem = panelInfo.PanelItems[panelInfo.CurrentItem]; + return true; +} + +bool CStartupInfo::ControlGetActivePanelSelectedOrCurrentItems( + CObjectVector &pluginPanelItems) +{ + pluginPanelItems.Clear(); + PanelInfo panelInfo; + if(!ControlGetActivePanelInfo(panelInfo)) + return false; + if(panelInfo.ItemsNumber <= 0) + throw "There are no items"; + if (panelInfo.SelectedItemsNumber == 0) + pluginPanelItems.Add(panelInfo.PanelItems[panelInfo.CurrentItem]); + else + for (int i = 0; i < panelInfo.SelectedItemsNumber; i++) + pluginPanelItems.Add(panelInfo.SelectedItems[i]); + return true; +} + +bool CStartupInfo::ControlClearPanelSelection() +{ + PanelInfo panelInfo; + if(!ControlGetActivePanelInfo(panelInfo)) + return false; + for (int i = 0; i < panelInfo.ItemsNumber; i++) + panelInfo.PanelItems[i].Flags &= ~PPIF_SELECTED; + return ControlSetSelection(panelInfo); +} + +//////////////////////////////////////////////// +// menu function + +int CStartupInfo::Menu( + int x, + int y, + int maxHeight, + unsigned int flags, + const char *title, + const char *aBottom, + const char *helpTopic, + int *breakKeys, + int *breakCode, + struct FarMenuItem *items, + int numItems) +{ + return m_Data.Menu(m_Data.ModuleNumber, x, y, maxHeight, flags, (char *)title, + (char *)aBottom, (char *)helpTopic, breakKeys, breakCode, items, numItems); +} + +int CStartupInfo::Menu( + unsigned int flags, + const char *title, + const char *helpTopic, + struct FarMenuItem *items, + int numItems) +{ + return Menu(-1, -1, 0, flags, title, NULL, helpTopic, NULL, + NULL, items, numItems); +} + +int CStartupInfo::Menu( + unsigned int flags, + const char *title, + const char *helpTopic, + const CSysStringVector &items, + int selectedItem) +{ + CRecordVector farMenuItems; + for(int i = 0; i < items.Size(); i++) + { + FarMenuItem item; + item.Checked = 0; + item.Separator = 0; + item.Selected = (i == selectedItem); + CSysString reducedString = items[i].Left(sizeof(item.Text) / sizeof(item.Text[0]) - 1); + MyStringCopy(item.Text, (const char *)GetOemString(reducedString)); + farMenuItems.Add(item); + } + return Menu(flags, title, helpTopic, &farMenuItems.Front(), farMenuItems.Size()); +} + + +////////////////////////////////// +// CScreenRestorer + +CScreenRestorer::~CScreenRestorer() +{ + Restore(); +} +void CScreenRestorer::Save() +{ + if(m_Saved) + return; + m_HANDLE = g_StartupInfo.SaveScreen(); + m_Saved = true; +} + +void CScreenRestorer::Restore() +{ + if(m_Saved) + { + g_StartupInfo.RestoreScreen(m_HANDLE); + m_Saved = false; + } +}; + +static AString DWORDToString(DWORD number) +{ + char buffer[32]; + _ultoa(number, buffer, 10); + return buffer; +} + +void PrintErrorMessage(const char *message, int code) +{ + AString tmp = message; + tmp += " #"; + tmp += DWORDToString(code); + g_StartupInfo.ShowMessage(tmp); +} + +void PrintErrorMessage(const char *message, const char *text) +{ + AString tmp = message; + tmp += ":\n"; + tmp += text; + g_StartupInfo.ShowMessageLines(tmp); +} + +void PrintErrorMessage(const char *message, const wchar_t *text) +{ + PrintErrorMessage(message, UnicodeStringToMultiByte(text, CP_OEMCP)); +} + +bool WasEscPressed() +{ + #ifdef UNDER_CE + return false; + #else + NConsole::CIn inConsole; + HANDLE handle = ::GetStdHandle(STD_INPUT_HANDLE); + if(handle == INVALID_HANDLE_VALUE) + return true; + inConsole.Attach(handle); + for (;;) + { + DWORD numEvents; + if(!inConsole.GetNumberOfEvents(numEvents)) + return true; + if(numEvents == 0) + return false; + + INPUT_RECORD event; + if(!inConsole.ReadEvent(event, numEvents)) + return true; + if (event.EventType == KEY_EVENT && + event.Event.KeyEvent.bKeyDown && + event.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) + return true; + } + #endif +} + +void ShowErrorMessage(DWORD errorCode) +{ + UString message; + NError::MyFormatMessage(errorCode, message); + message.Replace(L"\x0D", L""); + message.Replace(L"\x0A", L" "); + g_StartupInfo.ShowMessage(UnicodeStringToMultiByte(message, CP_OEMCP)); +} + +void ShowLastErrorMessage() +{ + ShowErrorMessage(::GetLastError()); +} + +} diff --git a/CPP/7zip/UI/Far/FarUtils.h b/CPP/7zip/UI/Far/FarUtils.h new file mode 100755 index 0000000..52578dc --- /dev/null +++ b/CPP/7zip/UI/Far/FarUtils.h @@ -0,0 +1,187 @@ +// FarUtils.h + +#ifndef __FARUTILS_H +#define __FARUTILS_H + +#include "FarPlugin.h" +#include "Windows/Registry.h" + +namespace NFar { + +namespace NFileOperationReturnCode +{ + enum EEnum + { + kInterruptedByUser = -1, + kError = 0, + kSuccess = 1 + }; +} + +namespace NEditorReturnCode +{ + enum EEnum + { + kOpenError = 0, + kFileWasChanged = 1, + kFileWasNotChanged = 2, + kInterruptedByUser = 3 + }; +} + +struct CInitDialogItem +{ + DialogItemTypes Type; + int X1,Y1,X2,Y2; + bool Focus; + bool Selected; + unsigned int Flags; //FarDialogItemFlags Flags; + bool DefaultButton; + int DataMessageId; + const char *DataString; + const char *HistoryName; + // void InitToFarDialogItem(struct FarDialogItem &anItemDest); +}; + +class CStartupInfo +{ + PluginStartupInfo m_Data; + CSysString m_RegistryPath; + + CSysString GetFullKeyName(const CSysString &keyName) const; + LONG CreateRegKey(HKEY parentKey, + const CSysString &keyName, NWindows::NRegistry::CKey &destKey) const; + LONG OpenRegKey(HKEY parentKey, + const CSysString &keyName, NWindows::NRegistry::CKey &destKey) const; + +public: + void Init(const PluginStartupInfo &pluginStartupInfo, + const CSysString &pluginNameForRegestry); + const char *GetMsgString(int messageId); + int ShowMessage(unsigned int flags, const char *helpTopic, + const char **items, int numItems, int numButtons); + int ShowMessage(const char *message); + int ShowMessageLines(const char *message); + int ShowMessage(int messageId); + + int ShowDialog(int X1, int Y1, int X2, int Y2, + const char *helpTopic, struct FarDialogItem *items, int numItems); + int ShowDialog(int sizeX, int sizeY, + const char *helpTopic, struct FarDialogItem *items, int numItems); + + void InitDialogItems(const CInitDialogItem *srcItems, + FarDialogItem *destItems, int numItems); + + HANDLE SaveScreen(int X1, int Y1, int X2, int Y2); + HANDLE SaveScreen(); + void RestoreScreen(HANDLE handle); + + void SetRegKeyValue(HKEY parentKey, const CSysString &keyName, + const LPCTSTR valueName, LPCTSTR value) const; + void SetRegKeyValue(HKEY hRoot, const CSysString &keyName, + const LPCTSTR valueName, UINT32 value) const; + void SetRegKeyValue(HKEY hRoot, const CSysString &keyName, + const LPCTSTR valueName, bool value) const; + + CSysString QueryRegKeyValue(HKEY parentKey, const CSysString &keyName, + LPCTSTR valueName, const CSysString &valueDefault) const; + + UINT32 QueryRegKeyValue(HKEY parentKey, const CSysString &keyName, + LPCTSTR valueName, UINT32 valueDefault) const; + + bool QueryRegKeyValue(HKEY parentKey, const CSysString &keyName, + LPCTSTR valueName, bool valueDefault) const; + + bool Control(HANDLE plugin, int command, void *param); + bool ControlRequestActivePanel(int command, void *param); + bool ControlGetActivePanelInfo(PanelInfo &panelInfo); + bool ControlSetSelection(const PanelInfo &panelInfo); + bool ControlGetActivePanelCurrentItemInfo(PluginPanelItem &pluginPanelItem); + bool ControlGetActivePanelSelectedOrCurrentItems( + CObjectVector &pluginPanelItems); + + bool ControlClearPanelSelection(); + + int Menu( + int x, + int y, + int maxHeight, + unsigned int flags, + const char *title, + const char *aBottom, + const char *helpTopic, + int *breakKeys, + int *breakCode, + FarMenuItem *items, + int numItems); + int Menu( + unsigned int flags, + const char *title, + const char *helpTopic, + FarMenuItem *items, + int numItems); + + int Menu( + unsigned int flags, + const char *title, + const char *helpTopic, + const CSysStringVector &items, + int selectedItem); + + int Editor(const char *fileName, const char *title, + int X1, int Y1, int X2, int Y2, DWORD flags, int startLine, int startChar) + { return m_Data.Editor((char *)fileName, (char *)title, X1, Y1, X2, Y2, + flags, startLine, startChar); } + int Editor(const char *fileName) + { return Editor(fileName, NULL, 0, 0, -1, -1, 0, -1, -1); } + + int Viewer(const char *fileName, const char *title, + int X1, int Y1, int X2, int Y2, DWORD flags) + { return m_Data.Viewer((char *)fileName, (char *)title, X1, Y1, X2, Y2, flags); } + int Viewer(const char *fileName) + { return Viewer(fileName, NULL, 0, 0, -1, -1, VF_NONMODAL); } + +}; + +class CScreenRestorer +{ + bool m_Saved; + HANDLE m_HANDLE; +public: + CScreenRestorer(): m_Saved(false){}; + ~CScreenRestorer(); + void Save(); + void Restore(); +}; + + +extern CStartupInfo g_StartupInfo; + +void PrintErrorMessage(const char *message, int code); +void PrintErrorMessage(const char *message, const char *text); +void PrintErrorMessage(const char *message, const wchar_t *text); + +#define MY_TRY_BEGIN try\ + { + +#define MY_TRY_END1(x) }\ + catch(int n) { PrintErrorMessage(x, n); return; }\ + catch(const CSysString &s) { PrintErrorMessage(x, s); return; }\ + catch(const char *s) { PrintErrorMessage(x, s); return; }\ + catch(...) { g_StartupInfo.ShowMessage(x); return; } + +#define MY_TRY_END2(x, y) }\ + catch(int n) { PrintErrorMessage(x, n); return y; }\ + catch(const AString &s) { PrintErrorMessage(x, s); return y; }\ + catch(const char *s) { PrintErrorMessage(x, s); return y; }\ + catch(const UString &s) { PrintErrorMessage(x, s); return y; }\ + catch(const wchar_t *s) { PrintErrorMessage(x, s); return y; }\ + catch(...) { g_StartupInfo.ShowMessage(x); return y; } + +bool WasEscPressed(); +void ShowErrorMessage(DWORD errorCode); +void ShowLastErrorMessage(); + +} + +#endif diff --git a/CPP/7zip/UI/Far/Main.cpp b/CPP/7zip/UI/Far/Main.cpp new file mode 100755 index 0000000..1f4d89d --- /dev/null +++ b/CPP/7zip/UI/Far/Main.cpp @@ -0,0 +1,612 @@ +// Test Align for updating !!!!!!!!!!!!!!!!!! + +#include "StdAfx.h" + +#include "Common/MyInitGuid.h" + +#include "Common/StringConvert.h" + +#include "Windows/FileDir.h" +#include "Windows/NtCheck.h" + +#include "../../Common/FileStreams.h" + +#include "../Agent/Agent.h" + +#include "Messages.h" +#include "Plugin.h" +#include "ProgressBox.h" + +using namespace NWindows; +using namespace NFar; + +static const char *kCommandPrefix = "7-zip"; +static const TCHAR *kRegisrtryMainKeyName = TEXT(""); +static const TCHAR *kRegisrtryValueNameEnabled = TEXT("UsedByDefault3"); +static const char *kHelpTopicConfig = "Config"; +static bool kPluginEnabledDefault = true; + +HINSTANCE g_hInstance; + +#define NT_CHECK_FAIL_ACTION return FALSE; + +BOOL WINAPI DllMain( + #ifdef UNDER_CE + HANDLE + #else + HINSTANCE + #endif + hInstance, DWORD dwReason, LPVOID) +{ + if (dwReason == DLL_PROCESS_ATTACH) + { + g_hInstance = (HINSTANCE)hInstance; + NT_CHECK + } + return TRUE; +} + +static struct COptions +{ + bool Enabled; +} g_Options; + +static const TCHAR *kPliginNameForRegestry = TEXT("7-ZIP"); + +EXTERN_C void WINAPI SetStartupInfo(const PluginStartupInfo *info) +{ + MY_TRY_BEGIN; + g_StartupInfo.Init(*info, kPliginNameForRegestry); + g_Options.Enabled = g_StartupInfo.QueryRegKeyValue( + HKEY_CURRENT_USER, kRegisrtryMainKeyName, + kRegisrtryValueNameEnabled, kPluginEnabledDefault); + MY_TRY_END1("SetStartupInfo"); +} + +class COpenArchiveCallback: + public IArchiveOpenCallback, + public IArchiveOpenVolumeCallback, + public IProgress, + public ICryptoGetTextPassword, + public CMyUnknownImp +{ + DWORD m_StartTickValue; + bool m_MessageBoxIsShown; + + CProgressBox _progressBox; + + UInt64 _numFilesTotal; + UInt64 _numFilesCur; + UInt64 _numBytesTotal; + UInt64 _numBytesCur; + + bool _numFilesTotalDefined; + bool _numFilesCurDefined; + bool _numBytesTotalDefined; + bool _numBytesCurDefined; + + DWORD m_PrevTickCount; + + NWindows::NFile::NFind::CFileInfoW _fileInfo; +public: + bool PasswordIsDefined; + UString Password; + + UString _folderPrefix; + +public: + MY_UNKNOWN_IMP3( + IArchiveOpenVolumeCallback, + IProgress, + ICryptoGetTextPassword + ) + + // IProgress + STDMETHOD(SetTotal)(UInt64 total); + STDMETHOD(SetCompleted)(const UInt64 *aCompleteValue); + + // IArchiveOpenCallback + STDMETHOD(SetTotal)(const UInt64 *numFiles, const UInt64 *numBytes); + STDMETHOD(SetCompleted)(const UInt64 *numFiles, const UInt64 *numBytes); + + // IArchiveOpenVolumeCallback + STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value); + STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream); + + // ICryptoGetTextPassword + STDMETHOD(CryptoGetTextPassword)(BSTR *password); + + void Init() + { + PasswordIsDefined = false; + + _numFilesTotalDefined = false; + _numFilesCurDefined = false; + _numBytesTotalDefined = false; + _numBytesCurDefined = false; + + m_MessageBoxIsShown = false; + m_PrevTickCount = GetTickCount(); + } + void ShowMessage(); + + void LoadFileInfo(const UString &folderPrefix, const UString &fileName) + { + _folderPrefix = folderPrefix; + if (!_fileInfo.Find(_folderPrefix + fileName)) + throw 1; + } +}; + +void COpenArchiveCallback::ShowMessage() +{ + DWORD currentTime = GetTickCount(); + if (!m_MessageBoxIsShown) + { + if (currentTime - m_PrevTickCount < 100) + return; + _progressBox.Init( + // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle), + g_StartupInfo.GetMsgString(NMessageID::kReading), 48); + + m_MessageBoxIsShown = true; + } + else + { + if (currentTime - m_PrevTickCount < 200) + return; + } + m_PrevTickCount = currentTime; + + UInt64 total = 0, cur = 0; + bool curIsDefined = false, totalIsDefined = false; + + char message[256] = { 0 }; + if (_numFilesCurDefined) + ConvertUInt64ToStringAligned(_numFilesCur, message, 5); + + if (_numFilesTotalDefined) + { + strcat(message, " / "); + ConvertUInt64ToStringAligned(_numFilesTotal, message + strlen(message), 5); + total = _numFilesTotal; + totalIsDefined = true; + if (_numFilesCurDefined) + { + cur = _numFilesCur; + curIsDefined = true; + } + } + else if (_numBytesTotalDefined) + { + total = _numBytesTotal; + totalIsDefined = true; + if (_numBytesCurDefined) + { + cur = _numBytesCur; + curIsDefined = true; + } + } + _progressBox.Progress( + totalIsDefined ? &total: NULL, + curIsDefined ? &cur: NULL, + message); +} + +STDMETHODIMP COpenArchiveCallback::SetTotal(const UInt64 *numFiles, const UInt64 *numBytes) +{ + if (WasEscPressed()) + return E_ABORT; + + _numFilesTotalDefined = (numFiles != NULL); + if (_numFilesTotalDefined) + _numFilesTotal = *numFiles; + + _numBytesTotalDefined = (numBytes != NULL); + if (_numBytesTotalDefined) + _numBytesTotal = *numBytes; + + return S_OK; +} + +STDMETHODIMP COpenArchiveCallback::SetCompleted(const UInt64 *numFiles, const UInt64 *numBytes) +{ + if (WasEscPressed()) + return E_ABORT; + + _numFilesCurDefined = (numFiles != NULL); + if (_numFilesCurDefined) + _numFilesCur = *numFiles; + + _numBytesCurDefined = (numBytes != NULL); + if (_numBytesCurDefined) + _numBytesCur = *numBytes; + + // if (*numFiles % 100 != 0) + // return S_OK; + ShowMessage(); + return S_OK; +} + + +STDMETHODIMP COpenArchiveCallback::SetTotal(const UInt64 /* total */) +{ + if (WasEscPressed()) + return E_ABORT; + return S_OK; +} + +STDMETHODIMP COpenArchiveCallback::SetCompleted(const UInt64 *completed) +{ + if (WasEscPressed()) + return E_ABORT; + if (completed == NULL) + return S_OK; + ShowMessage(); + return S_OK; +} + +STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, IInStream **inStream) +{ + if (WasEscPressed()) + return E_ABORT; + *inStream = NULL; + UString fullPath = _folderPrefix + name; + if (!_fileInfo.Find(fullPath)) + return S_FALSE; + if (_fileInfo.IsDir()) + return S_FALSE; + CInFileStream *inFile = new CInFileStream; + CMyComPtr inStreamTemp = inFile; + if (!inFile->Open(fullPath)) + return ::GetLastError(); + *inStream = inStreamTemp.Detach(); + return S_OK; +} + + +STDMETHODIMP COpenArchiveCallback::GetProperty(PROPID propID, PROPVARIANT *value) +{ + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidName: prop = GetUnicodeString(_fileInfo.Name, CP_OEMCP); 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; +} + +HRESULT GetPassword(UString &password) +{ + if (WasEscPressed()) + return E_ABORT; + password.Empty(); + CInitDialogItem initItems[]= + { + { DI_DOUBLEBOX, 3, 1, 72, 4, false, false, 0, false, NMessageID::kGetPasswordTitle, NULL, NULL }, + { DI_TEXT, 5, 2, 0, 0, false, false, DIF_SHOWAMPERSAND, false, NMessageID::kEnterPasswordForFile, NULL, NULL }, + { DI_PSWEDIT, 5, 3, 70, 3, true, false, 0, true, -1, "", NULL } + }; + + const int kNumItems = sizeof(initItems)/sizeof(initItems[0]); + FarDialogItem dialogItems[kNumItems]; + g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumItems); + + // sprintf(DialogItems[1].Data,GetMsg(MGetPasswordForFile),FileName); + if (g_StartupInfo.ShowDialog(76, 6, NULL, dialogItems, kNumItems) < 0) + return (E_ABORT); + + AString oemPassword = dialogItems[2].Data; + password = MultiByteToUnicodeString(oemPassword, CP_OEMCP); + return S_OK; +} + +STDMETHODIMP COpenArchiveCallback::CryptoGetTextPassword(BSTR *password) +{ + if (!PasswordIsDefined) + { + RINOK(GetPassword(Password)); + PasswordIsDefined = true; + } + return StringToBstr(Password, password); +} + +/* +HRESULT OpenArchive(const CSysString &fileName, + IInFolderArchive **archiveHandlerResult, + CArchiverInfo &archiverInfoResult, + UString &defaultName, + IArchiveOpenCallback *openArchiveCallback) +{ + HRESULT OpenArchive(const CSysString &fileName, + IInArchive **archive, + CArchiverInfo &archiverInfoResult, + IArchiveOpenCallback *openArchiveCallback); +} +*/ + +static HANDLE MyOpenFilePluginW(const wchar_t *name) +{ + UString normalizedName = name; + normalizedName.Trim(); + UString fullName; + int fileNamePartStartIndex; + NFile::NDirectory::MyGetFullPathName(normalizedName, fullName, fileNamePartStartIndex); + NFile::NFind::CFileInfoW fileInfo; + if (!fileInfo.Find(fullName)) + return INVALID_HANDLE_VALUE; + if (fileInfo.IsDir()) + return INVALID_HANDLE_VALUE; + + + CMyComPtr archiveHandler; + + // CArchiverInfo archiverInfoResult; + // ::OutputDebugStringA("before OpenArchive\n"); + + CScreenRestorer screenRestorer; + { + screenRestorer.Save(); + } + + COpenArchiveCallback *openArchiveCallbackSpec = new COpenArchiveCallback; + CMyComPtr openArchiveCallback = openArchiveCallbackSpec; + + // if ((opMode & OPM_SILENT) == 0 && (opMode & OPM_FIND ) == 0) + openArchiveCallbackSpec->Init(); + openArchiveCallbackSpec->LoadFileInfo( + fullName.Left(fileNamePartStartIndex), + fullName.Mid(fileNamePartStartIndex)); + + // ::OutputDebugStringA("before OpenArchive\n"); + + CAgent *agent = new CAgent; + archiveHandler = agent; + CMyComBSTR archiveType; + HRESULT result = archiveHandler->Open(NULL, + GetUnicodeString(fullName, CP_OEMCP), UString(), &archiveType, openArchiveCallback); + /* + HRESULT result = ::OpenArchive(fullName, &archiveHandler, + archiverInfoResult, defaultName, openArchiveCallback); + */ + if (result != S_OK) + { + if (result == E_ABORT) + return (HANDLE)-2; + return INVALID_HANDLE_VALUE; + } + + UString errorMessage = agent->GetErrorMessage(); + if (!errorMessage.IsEmpty()) + PrintErrorMessage("7-Zip", UnicodeStringToMultiByte(errorMessage, CP_OEMCP)); + + // ::OutputDebugStringA("after OpenArchive\n"); + + CPlugin *plugin = new CPlugin( + fullName, + // defaultName, + archiveHandler, + (const wchar_t *)archiveType + ); + if (plugin == NULL) + return(INVALID_HANDLE_VALUE); + plugin->PasswordIsDefined = openArchiveCallbackSpec->PasswordIsDefined; + plugin->Password = openArchiveCallbackSpec->Password; + + return (HANDLE)(plugin); +} + +static HANDLE MyOpenFilePlugin(const char *name) +{ + UINT codePage = + #ifdef UNDER_CE + CP_OEMCP; + #else + ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; + #endif + return MyOpenFilePluginW(GetUnicodeString(name, codePage)); +} + +EXTERN_C HANDLE WINAPI OpenFilePlugin(char *name, const unsigned char * /* data */, int /* dataSize */) +{ + MY_TRY_BEGIN; + if (name == NULL || (!g_Options.Enabled)) + { + // if (!Opt.ProcessShiftF1) + return(INVALID_HANDLE_VALUE); + } + return MyOpenFilePlugin(name); + MY_TRY_END2("OpenFilePlugin", INVALID_HANDLE_VALUE); +} + +/* +EXTERN_C HANDLE WINAPI OpenFilePluginW(const wchar_t *name,const unsigned char *Data,int DataSize,int OpMode) +{ + MY_TRY_BEGIN; + if (name == NULL || (!g_Options.Enabled)) + { + // if (!Opt.ProcessShiftF1) + return(INVALID_HANDLE_VALUE); + } + return MyOpenFilePluginW(name); + ::OutputDebugStringA("OpenFilePluginW\n"); + MY_TRY_END2("OpenFilePluginW", INVALID_HANDLE_VALUE); +} +*/ + +EXTERN_C HANDLE WINAPI OpenPlugin(int openFrom, INT_PTR item) +{ + MY_TRY_BEGIN; + if(openFrom == OPEN_COMMANDLINE) + { + AString fileName = (const char *)item; + if(fileName.IsEmpty()) + return INVALID_HANDLE_VALUE; + if (fileName.Length() >= 2 && + fileName[0] == '\"' && fileName[fileName.Length() - 1] == '\"') + fileName = fileName.Mid(1, fileName.Length() - 2); + + return MyOpenFilePlugin(fileName); + } + if(openFrom == OPEN_PLUGINSMENU) + { + switch(item) + { + case 0: + { + PluginPanelItem pluginPanelItem; + if(!g_StartupInfo.ControlGetActivePanelCurrentItemInfo(pluginPanelItem)) + throw 142134; + return MyOpenFilePlugin(pluginPanelItem.FindData.cFileName); + } + case 1: + { + CObjectVector pluginPanelItem; + if(!g_StartupInfo.ControlGetActivePanelSelectedOrCurrentItems(pluginPanelItem)) + throw 142134; + if (CompressFiles(pluginPanelItem) == S_OK) + { + /* int t = */ g_StartupInfo.ControlClearPanelSelection(); + g_StartupInfo.ControlRequestActivePanel(FCTL_UPDATEPANEL, NULL); + g_StartupInfo.ControlRequestActivePanel(FCTL_REDRAWPANEL, NULL); + g_StartupInfo.ControlRequestActivePanel(FCTL_UPDATEANOTHERPANEL, NULL); + g_StartupInfo.ControlRequestActivePanel(FCTL_REDRAWANOTHERPANEL, NULL); + } + return INVALID_HANDLE_VALUE; + } + default: + throw 4282215; + } + } + return INVALID_HANDLE_VALUE; + MY_TRY_END2("OpenPlugin", INVALID_HANDLE_VALUE); +} + +EXTERN_C void WINAPI ClosePlugin(HANDLE plugin) +{ + MY_TRY_BEGIN; + delete (CPlugin *)plugin; + MY_TRY_END1("ClosePlugin"); +} + +EXTERN_C int WINAPI GetFindData(HANDLE plugin, struct PluginPanelItem **panelItems, int *itemsNumber, int opMode) +{ + MY_TRY_BEGIN; + return(((CPlugin *)plugin)->GetFindData(panelItems, itemsNumber, opMode)); + MY_TRY_END2("GetFindData", FALSE); +} + +EXTERN_C void WINAPI FreeFindData(HANDLE plugin, struct PluginPanelItem *panelItems, int itemsNumber) +{ + MY_TRY_BEGIN; + ((CPlugin *)plugin)->FreeFindData(panelItems, itemsNumber); + MY_TRY_END1("FreeFindData"); +} + +EXTERN_C int WINAPI GetFiles(HANDLE plugin, struct PluginPanelItem *panelItems, + int itemsNumber, int move, char *destPath, int opMode) +{ + MY_TRY_BEGIN; + return(((CPlugin *)plugin)->GetFiles(panelItems, itemsNumber, move, destPath, opMode)); + MY_TRY_END2("GetFiles", NFileOperationReturnCode::kError); +} + +EXTERN_C int WINAPI SetDirectory(HANDLE plugin, const char *dir, int opMode) +{ + MY_TRY_BEGIN; + return(((CPlugin *)plugin)->SetDirectory(dir, opMode)); + MY_TRY_END2("SetDirectory", FALSE); +} + +EXTERN_C void WINAPI GetPluginInfo(struct PluginInfo *info) +{ + MY_TRY_BEGIN; + + info->StructSize = sizeof(*info); + info->Flags = 0; + info->DiskMenuStrings = NULL; + info->DiskMenuNumbers = NULL; + info->DiskMenuStringsNumber = 0; + static const char *pluginMenuStrings[2]; + pluginMenuStrings[0] = g_StartupInfo.GetMsgString(NMessageID::kOpenArchiveMenuString); + pluginMenuStrings[1] = g_StartupInfo.GetMsgString(NMessageID::kCreateArchiveMenuString); + info->PluginMenuStrings = (char **)pluginMenuStrings; + info->PluginMenuStringsNumber = 2; + static const char *pluginCfgStrings[1]; + pluginCfgStrings[0] = g_StartupInfo.GetMsgString(NMessageID::kOpenArchiveMenuString); + info->PluginConfigStrings = (char **)pluginCfgStrings; + info->PluginConfigStringsNumber = sizeof(pluginCfgStrings) / sizeof(pluginCfgStrings[0]); + info->CommandPrefix = (char *)kCommandPrefix; + MY_TRY_END1("GetPluginInfo"); +} + +EXTERN_C int WINAPI Configure(int /* itemNumber */) +{ + MY_TRY_BEGIN; + + const int kEnabledCheckBoxIndex = 1; + + const int kYSize = 7; + + struct CInitDialogItem initItems[]= + { + { DI_DOUBLEBOX, 3, 1, 72, kYSize - 2, false, false, 0, false, NMessageID::kConfigTitle, NULL, NULL }, + { DI_CHECKBOX, 5, 2, 0, 0, true, g_Options.Enabled, 0, false, NMessageID::kConfigPluginEnabled, NULL, NULL }, + { DI_TEXT, 5, 3, 0, 0, false, false, DIF_BOXCOLOR | DIF_SEPARATOR, false, -1, "", NULL }, + { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, true, NMessageID::kOk, NULL, NULL }, + { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kCancel, NULL, NULL }, + }; + + const int kNumDialogItems = sizeof(initItems) / sizeof(initItems[0]); + const int kOkButtonIndex = kNumDialogItems - 2; + + FarDialogItem dialogItems[kNumDialogItems]; + g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumDialogItems); + + int askCode = g_StartupInfo.ShowDialog(76, kYSize, + kHelpTopicConfig, dialogItems, kNumDialogItems); + + if (askCode != kOkButtonIndex) + return (FALSE); + + g_Options.Enabled = BOOLToBool(dialogItems[kEnabledCheckBoxIndex].Selected); + + g_StartupInfo.SetRegKeyValue(HKEY_CURRENT_USER, kRegisrtryMainKeyName, + kRegisrtryValueNameEnabled, g_Options.Enabled); + return(TRUE); + MY_TRY_END2("Configure", FALSE); +} + +EXTERN_C void WINAPI GetOpenPluginInfo(HANDLE plugin,struct OpenPluginInfo *info) +{ + MY_TRY_BEGIN; + ((CPlugin *)plugin)->GetOpenPluginInfo(info); + MY_TRY_END1("GetOpenPluginInfo"); +} + +EXTERN_C int WINAPI PutFiles(HANDLE plugin, struct PluginPanelItem *panelItems, int itemsNumber, int move, int opMode) +{ + MY_TRY_BEGIN; + return(((CPlugin *)plugin)->PutFiles(panelItems, itemsNumber, move, opMode)); + MY_TRY_END2("PutFiles", NFileOperationReturnCode::kError); +} + +EXTERN_C int WINAPI DeleteFiles(HANDLE plugin, PluginPanelItem *panelItems, int itemsNumber, int opMode) +{ + MY_TRY_BEGIN; + return(((CPlugin *)plugin)->DeleteFiles(panelItems, itemsNumber, opMode)); + MY_TRY_END2("DeleteFiles", FALSE); +} + +EXTERN_C int WINAPI ProcessKey(HANDLE plugin, int key, unsigned int controlState) +{ + MY_TRY_BEGIN; + return (((CPlugin *)plugin)->ProcessKey(key, controlState)); + MY_TRY_END2("ProcessKey", FALSE); +} diff --git a/CPP/7zip/UI/Far/Messages.h b/CPP/7zip/UI/Far/Messages.h new file mode 100755 index 0000000..b2aadf5 --- /dev/null +++ b/CPP/7zip/UI/Far/Messages.h @@ -0,0 +1,184 @@ +// SevenZip/ Messages.h + +#ifndef __SEVENZIP_MESSAGES_H +#define __SEVENZIP_MESSAGES_H + +namespace NMessageID { + +enum EEnum +{ + kOk, + kCancel, + + kWarning, + kError, + + kArchiveType, + + kProperties, + + kYes, + kNo, + + kPath, + kName, + kExtension, + kIsFolder, + kSize, + kPackSize, + kAttributes, + kCTime, + kATime, + kMTime, + kSolid, + kCommented, + kEncrypted, + kSplitBefore, + kSplitAfter, + kDictionarySize, + kCRC, + kType, + kAnti, + kMethod, + kHostOS, + kFileSystem, + kUser, + kGroup, + kBlock, + kComment, + kPosition, + kNumSubFolders, + kNumSubFiles, + kUnpackVer, + kVolume, + kIsVolume, + kOffset, + kLinks, + kNumBlocks, + kNumVolumes, + + kBit64, + kBigEndian, + kCpu, + kPhySize, + kHeadersSize, + kChecksum, + kCharacts, + kVa, + kId, + kShortName, + kCreatorApp, + kSectorSize, + kPosixAttrib, + kLink, + + kTotalSize, + kFreeSpace, + kClusterSize, + kLabel, + + kGetPasswordTitle, + kEnterPasswordForFile, + + kExtractTitle, + kExtractTo, + + kExtractPathMode, + kExtractPathFull, + kExtractPathCurrent, + kExtractPathNo, + + kExtractOwerwriteMode, + kExtractOwerwriteAsk, + kExtractOwerwritePrompt, + kExtractOwerwriteSkip, + kExtractOwerwriteAutoRename, + kExtractOwerwriteAutoRenameExisting, + + kExtractFilesMode, + kExtractFilesSelected, + kExtractFilesAll, + + kExtractPassword, + + kExtractExtract, + kExtractCancel, + + kExtractCanNotOpenOutputFile, + + kExtractUnsupportedMethod, + kExtractCRCFailed, + kExtractDataError, + kExtractCRCFailedEncrypted, + kExtractDataErrorEncrypted, + + kOverwriteTitle, + kOverwriteMessage1, + kOverwriteMessageWouldYouLike, + kOverwriteMessageWithtTisOne, + + kOverwriteBytes, + kOverwriteModifiedOn, + + kOverwriteYes, + kOverwriteYesToAll, + kOverwriteNo, + kOverwriteNoToAll, + kOverwriteAutoRename, + kOverwriteCancel, + + kUpdateNotSupportedForThisArchive, + + kDeleteTitle, + kDeleteFile, + kDeleteFiles, + kDeleteNumberOfFiles, + kDeleteDelete, + kDeleteCancel, + + kUpdateTitle, + kUpdateAddToArchive, + + kUpdateMethod, + kUpdateMethodStore, + kUpdateMethodFastest, + kUpdateMethodFast, + kUpdateMethodNormal, + kUpdateMethodMaximum, + kUpdateMethodUltra, + + kUpdateMode, + kUpdateModeAdd, + kUpdateModeUpdate, + kUpdateModeFreshen, + kUpdateModeSynchronize, + + kUpdateAdd, + kUpdateSelectArchiver, + + kUpdateSelectArchiverMenuTitle, + + // kArcReadFiles, + + kWaitTitle, + + kReading, + kExtracting, + kDeleting, + kUpdating, + + // kReadingList, + + kMoveIsNotSupported, + + kOpenArchiveMenuString, + kCreateArchiveMenuString, + + kConfigTitle, + + kConfigPluginEnabled +}; + +} + +#endif diff --git a/CPP/7zip/UI/Far/OverwriteDialog.cpp b/CPP/7zip/UI/Far/OverwriteDialog.cpp new file mode 100755 index 0000000..9e4911d --- /dev/null +++ b/CPP/7zip/UI/Far/OverwriteDialog.cpp @@ -0,0 +1,112 @@ +// OverwriteDialog.cpp + +#include "StdAfx.h" + +#include + +#include "OverwriteDialog.h" + +#include "Common/StringConvert.h" + +#include "Windows/FileName.h" +#include "Windows/Defs.h" +#include "Windows/PropVariantConversions.h" + +#include "FarUtils.h" +#include "Messages.h" + +using namespace NWindows; +using namespace NFar; + +namespace NOverwriteDialog { + +struct CFileInfoStrings +{ + AString Size; + AString Time; +}; + +void SetFileInfoStrings(const CFileInfo &fileInfo, + CFileInfoStrings &fileInfoStrings) +{ + char buffer[256]; + + if (fileInfo.SizeIsDefined) + { + sprintf(buffer, "%I64u ", fileInfo.Size); + fileInfoStrings.Size = buffer; + fileInfoStrings.Size += g_StartupInfo.GetMsgString(NMessageID::kOverwriteBytes); + } + else + { + fileInfoStrings.Size = ""; + } + + FILETIME localFileTime; + fileInfoStrings.Time.Empty(); + if (fileInfo.TimeIsDefined) + { + if (!FileTimeToLocalFileTime(&fileInfo.Time, &localFileTime)) + throw 4190402; + UString timeString = ConvertFileTimeToString(localFileTime); + fileInfoStrings.Time = g_StartupInfo.GetMsgString(NMessageID::kOverwriteModifiedOn); + fileInfoStrings.Time += " "; + fileInfoStrings.Time += UnicodeStringToMultiByte(timeString, CP_OEMCP); + } +} + +NResult::EEnum Execute(const CFileInfo &oldFileInfo, const CFileInfo &newFileInfo) +{ + const int kYSize = 20; + const int kXSize = 76; + + CFileInfoStrings oldFileInfoStrings; + CFileInfoStrings newFileInfoStrings; + + SetFileInfoStrings(oldFileInfo, oldFileInfoStrings); + SetFileInfoStrings(newFileInfo, newFileInfoStrings); + + AString oldName = UnicodeStringToMultiByte(oldFileInfo.Name, CP_OEMCP); + AString newName = UnicodeStringToMultiByte(newFileInfo.Name, CP_OEMCP); + + struct CInitDialogItem initItems[]={ + { DI_DOUBLEBOX, 3, 1, kXSize - 4, kYSize - 2, false, false, 0, false, NMessageID::kOverwriteTitle, NULL, NULL }, + { DI_TEXT, 5, 2, 0, 0, false, false, 0, false, NMessageID::kOverwriteMessage1, NULL, NULL }, + + { DI_TEXT, 3, 3, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL }, + + { DI_TEXT, 5, 4, 0, 0, false, false, 0, false, NMessageID::kOverwriteMessageWouldYouLike, NULL, NULL }, + + { DI_TEXT, 7, 6, 0, 0, false, false, 0, false, -1, oldName, NULL }, + { DI_TEXT, 7, 7, 0, 0, false, false, 0, false, -1, oldFileInfoStrings.Size, NULL }, + { DI_TEXT, 7, 8, 0, 0, false, false, 0, false, -1, oldFileInfoStrings.Time, NULL }, + + { DI_TEXT, 5, 10, 0, 0, false, false, 0, false, NMessageID::kOverwriteMessageWithtTisOne, NULL, NULL }, + + { DI_TEXT, 7, 12, 0, 0, false, false, 0, false, -1, newName, NULL }, + { DI_TEXT, 7, 13, 0, 0, false, false, 0, false, -1, newFileInfoStrings.Size, NULL }, + { DI_TEXT, 7, 14, 0, 0, false, false, 0, false, -1, newFileInfoStrings.Time, NULL }, + + { DI_TEXT, 3, kYSize - 5, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL }, + + { DI_BUTTON, 0, kYSize - 4, 0, 0, true, false, DIF_CENTERGROUP, true, NMessageID::kOverwriteYes, NULL, NULL }, + { DI_BUTTON, 0, kYSize - 4, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kOverwriteYesToAll, NULL, NULL }, + { DI_BUTTON, 0, kYSize - 4, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kOverwriteNo, NULL, NULL }, + { DI_BUTTON, 0, kYSize - 4, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kOverwriteNoToAll, NULL, NULL }, + { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kOverwriteAutoRename, NULL, NULL }, + { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kOverwriteCancel, NULL, NULL } + }; + + const int kNumDialogItems = sizeof(initItems) / sizeof(initItems[0]); + FarDialogItem aDialogItems[kNumDialogItems]; + g_StartupInfo.InitDialogItems(initItems, aDialogItems, kNumDialogItems); + int anAskCode = g_StartupInfo.ShowDialog(kXSize, kYSize, + NULL, aDialogItems, kNumDialogItems); + const int kButtonStartPos = kNumDialogItems - 6; + if (anAskCode >= kButtonStartPos && anAskCode < kNumDialogItems) + return NResult::EEnum(anAskCode - kButtonStartPos); + return NResult::kCancel; +} + +} + diff --git a/CPP/7zip/UI/Far/OverwriteDialog.h b/CPP/7zip/UI/Far/OverwriteDialog.h new file mode 100755 index 0000000..76625f4 --- /dev/null +++ b/CPP/7zip/UI/Far/OverwriteDialog.h @@ -0,0 +1,37 @@ +// OverwriteDialog.h + +#ifndef OVERWRITEDIALOG_H +#define OVERWRITEDIALOG_H + +#include "Common/MyString.h" +#include "Common/Types.h" + +namespace NOverwriteDialog { + +struct CFileInfo +{ + bool SizeIsDefined; + bool TimeIsDefined; + UInt64 Size; + FILETIME Time; + UString Name; +}; + +namespace NResult +{ + enum EEnum + { + kYes, + kYesToAll, + kNo, + kNoToAll, + kAutoRename, + kCancel + }; +} + +NResult::EEnum Execute(const CFileInfo &oldFileInfo, const CFileInfo &newFileInfo); + +} + +#endif diff --git a/CPP/7zip/UI/Far/Plugin.cpp b/CPP/7zip/UI/Far/Plugin.cpp new file mode 100755 index 0000000..6263149 --- /dev/null +++ b/CPP/7zip/UI/Far/Plugin.cpp @@ -0,0 +1,871 @@ +// Plugin.cpp + +#include "StdAfx.h" + +#include "Common/IntToString.h" +#include "Common/StringConvert.h" +#include "Common/Wildcard.h" + +#include "Windows/FileDir.h" +#include "Windows/PropVariantConversions.h" + +#include "../Common/PropIDUtils.h" + +#include "FarUtils.h" +#include "Messages.h" +#include "Plugin.h" + +using namespace NWindows; +using namespace NFar; + +CPlugin::CPlugin(const UString &fileName, IInFolderArchive *archiveHandler, UString archiveTypeName): + m_ArchiveHandler(archiveHandler), + m_FileName(fileName), + _archiveTypeName(archiveTypeName) +{ + if (!m_FileInfo.Find(m_FileName)) + throw "error"; + archiveHandler->BindToRootFolder(&_folder); +} + +CPlugin::~CPlugin() {} + +static void MyGetFileTime(IFolderFolder *anArchiveFolder, UInt32 itemIndex, + PROPID propID, FILETIME &fileTime) +{ + NCOM::CPropVariant prop; + if (anArchiveFolder->GetProperty(itemIndex, propID, &prop) != S_OK) + throw 271932; + if (prop.vt == VT_EMPTY) + { + fileTime.dwHighDateTime = 0; + fileTime.dwLowDateTime = 0; + } + else + { + if (prop.vt != VT_FILETIME) + throw 4191730; + fileTime = prop.filetime; + } +} + +#define kDotsReplaceString "[[..]]" +#define kDotsReplaceStringU L"[[..]]" + +static void CopyStrLimited(char *dest, const AString &src, int len) +{ + len--; + if (src.Length() < len) + len = src.Length(); + memcpy(dest, src, sizeof(dest[0]) * len); + dest[len] = 0; +} + +#define COPY_STR_LIMITED(dest, src) CopyStrLimited(dest, src, sizeof(dest) / sizeof(dest[0])) + +void CPlugin::ReadPluginPanelItem(PluginPanelItem &panelItem, UInt32 itemIndex) +{ + NCOM::CPropVariant prop; + if (_folder->GetProperty(itemIndex, kpidName, &prop) != S_OK) + throw 271932; + + if (prop.vt != VT_BSTR) + throw 272340; + + AString oemString = UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP); + if (oemString == "..") + oemString = kDotsReplaceString; + + COPY_STR_LIMITED(panelItem.FindData.cFileName, oemString); + panelItem.FindData.cAlternateFileName[0] = 0; + + if (_folder->GetProperty(itemIndex, kpidAttrib, &prop) != S_OK) + throw 271932; + if (prop.vt == VT_UI4) + panelItem.FindData.dwFileAttributes = prop.ulVal; + else if (prop.vt == VT_EMPTY) + panelItem.FindData.dwFileAttributes = m_FileInfo.Attrib; + else + throw 21631; + + if (_folder->GetProperty(itemIndex, kpidIsDir, &prop) != S_OK) + throw 271932; + if (prop.vt == VT_BOOL) + { + if (VARIANT_BOOLToBool(prop.boolVal)) + panelItem.FindData.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY; + } + else if (prop.vt != VT_EMPTY) + throw 21632; + + if (_folder->GetProperty(itemIndex, kpidSize, &prop) != S_OK) + throw 271932; + UInt64 length; + if (prop.vt == VT_EMPTY) + length = 0; + else + length = ::ConvertPropVariantToUInt64(prop); + panelItem.FindData.nFileSizeLow = (UInt32)length; + panelItem.FindData.nFileSizeHigh = (UInt32)(length >> 32); + + MyGetFileTime(_folder, itemIndex, kpidCTime, panelItem.FindData.ftCreationTime); + MyGetFileTime(_folder, itemIndex, kpidATime, panelItem.FindData.ftLastAccessTime); + MyGetFileTime(_folder, itemIndex, kpidMTime, panelItem.FindData.ftLastWriteTime); + + if (panelItem.FindData.ftLastWriteTime.dwHighDateTime == 0 && + panelItem.FindData.ftLastWriteTime.dwLowDateTime == 0) + panelItem.FindData.ftLastWriteTime = m_FileInfo.MTime; + + if (_folder->GetProperty(itemIndex, kpidPackSize, &prop) != S_OK) + throw 271932; + if (prop.vt == VT_EMPTY) + length = 0; + else + length = ::ConvertPropVariantToUInt64(prop); + panelItem.PackSize = UInt32(length); + panelItem.PackSizeHigh = UInt32(length >> 32); + + panelItem.Flags = 0; + panelItem.NumberOfLinks = 0; + + panelItem.Description = NULL; + panelItem.Owner = NULL; + panelItem.CustomColumnData = NULL; + panelItem.CustomColumnNumber = 0; + + panelItem.CRC32 = 0; + panelItem.Reserved[0] = 0; + panelItem.Reserved[1] = 0; +} + +int CPlugin::GetFindData(PluginPanelItem **panelItems, int *itemsNumber, int opMode) +{ + // CScreenRestorer screenRestorer; + if ((opMode & OPM_SILENT) == 0 && (opMode & OPM_FIND ) == 0) + { + /* + screenRestorer.Save(); + const char *msgItems[]= + { + g_StartupInfo.GetMsgString(NMessageID::kWaitTitle), + g_StartupInfo.GetMsgString(NMessageID::kReadingList) + }; + g_StartupInfo.ShowMessage(0, NULL, msgItems, + sizeof(msgItems) / sizeof(msgItems[0]), 0); + */ + } + + UInt32 numItems; + _folder->GetNumberOfItems(&numItems); + *panelItems = new PluginPanelItem[numItems]; + try + { + for (UInt32 i = 0; i < numItems; i++) + { + PluginPanelItem &panelItem = (*panelItems)[i]; + ReadPluginPanelItem(panelItem, i); + panelItem.UserData = i; + } + } + catch(...) + { + delete [](*panelItems); + throw; + } + *itemsNumber = numItems; + return(TRUE); +} + +void CPlugin::FreeFindData(struct PluginPanelItem *panelItems, int itemsNumber) +{ + for (int i = 0; i < itemsNumber; i++) + if (panelItems[i].Description != NULL) + delete []panelItems[i].Description; + delete []panelItems; +} + +void CPlugin::EnterToDirectory(const UString &dirName) +{ + CMyComPtr newFolder; + UString s = dirName; + if (dirName == kDotsReplaceStringU) + s = L".."; + _folder->BindToFolder(s, &newFolder); + if (newFolder == NULL) + if (dirName.IsEmpty()) + return; + else + throw 40325; + _folder = newFolder; +} + +int CPlugin::SetDirectory(const char *aszDir, int /* opMode */) +{ + UString path = MultiByteToUnicodeString(aszDir, CP_OEMCP); + if (path == WSTRING_PATH_SEPARATOR) + { + _folder.Release(); + m_ArchiveHandler->BindToRootFolder(&_folder); + } + else if (path == L"..") + { + CMyComPtr newFolder; + _folder->BindToParentFolder(&newFolder); + if (newFolder == NULL) + throw 40312; + _folder = newFolder; + } + else if (path.IsEmpty()) + EnterToDirectory(path); + else + { + if (path[0] == WCHAR_PATH_SEPARATOR) + { + _folder.Release(); + m_ArchiveHandler->BindToRootFolder(&_folder); + path = path.Mid(1); + } + UStringVector pathParts; + SplitPathToParts(path, pathParts); + for (int i = 0; i < pathParts.Size(); i++) + EnterToDirectory(pathParts[i]); + } + GetCurrentDir(); + return TRUE; +} + +void CPlugin::GetPathParts(UStringVector &pathParts) +{ + pathParts.Clear(); + CMyComPtr folderItem = _folder; + for (;;) + { + CMyComPtr newFolder; + folderItem->BindToParentFolder(&newFolder); + if (newFolder == NULL) + break; + NCOM::CPropVariant prop; + if (folderItem->GetFolderProperty(kpidName, &prop) == S_OK) + if (prop.vt == VT_BSTR) + pathParts.Insert(0, (const wchar_t *)prop.bstrVal); + folderItem = newFolder; + } +} + +void CPlugin::GetCurrentDir() +{ + m_CurrentDir.Empty(); + UStringVector pathParts; + GetPathParts(pathParts); + for (int i = 0; i < pathParts.Size(); i++) + { + m_CurrentDir += WCHAR_PATH_SEPARATOR; + m_CurrentDir += pathParts[i]; + } +} + +static char *kPluginFormatName = "7-ZIP"; + + +struct CPROPIDToName +{ + PROPID PropID; + int PluginID; +}; + +static CPROPIDToName kPROPIDToName[] = +{ + { kpidPath, NMessageID::kPath }, + { kpidName, NMessageID::kName }, + { kpidExtension, NMessageID::kExtension }, + { kpidIsDir, NMessageID::kIsFolder }, + { kpidSize, NMessageID::kSize }, + { kpidPackSize, NMessageID::kPackSize }, + { kpidAttrib, NMessageID::kAttributes }, + { kpidCTime, NMessageID::kCTime }, + { kpidATime, NMessageID::kATime }, + { kpidMTime, NMessageID::kMTime }, + { kpidSolid, NMessageID::kSolid }, + { kpidCommented, NMessageID::kCommented }, + { kpidEncrypted, NMessageID::kEncrypted }, + { kpidSplitBefore, NMessageID::kSplitBefore }, + { kpidSplitAfter, NMessageID::kSplitAfter }, + { kpidDictionarySize, NMessageID::kDictionarySize }, + { kpidCRC, NMessageID::kCRC }, + { kpidType, NMessageID::kType }, + { kpidIsAnti, NMessageID::kAnti }, + { kpidMethod, NMessageID::kMethod }, + { kpidHostOS, NMessageID::kHostOS }, + { kpidFileSystem, NMessageID::kFileSystem }, + { kpidUser, NMessageID::kUser }, + { kpidGroup, NMessageID::kGroup }, + { kpidBlock, NMessageID::kBlock }, + { kpidComment, NMessageID::kComment }, + { kpidPosition, NMessageID::kPosition }, + { kpidNumSubDirs, NMessageID::kNumSubFolders }, + { kpidNumSubFiles, NMessageID::kNumSubFiles }, + { kpidUnpackVer, NMessageID::kUnpackVer }, + { kpidVolume, NMessageID::kVolume }, + { kpidIsVolume, NMessageID::kIsVolume }, + { kpidOffset, NMessageID::kOffset }, + { kpidLinks, NMessageID::kLinks }, + { kpidNumBlocks, NMessageID::kNumBlocks }, + { kpidNumVolumes, NMessageID::kNumVolumes }, + + { kpidBit64, NMessageID::kBit64 }, + { kpidBigEndian, NMessageID::kBigEndian }, + { kpidCpu, NMessageID::kCpu }, + { kpidPhySize, NMessageID::kPhySize }, + { kpidHeadersSize, NMessageID::kHeadersSize }, + { kpidChecksum, NMessageID::kChecksum }, + { kpidCharacts, NMessageID::kCharacts }, + { kpidVa, NMessageID::kVa }, + { kpidId, NMessageID::kId }, + { kpidShortName, NMessageID::kShortName}, + { kpidCreatorApp, NMessageID::kCreatorApp }, + { kpidSectorSize, NMessageID::kSectorSize }, + { kpidPosixAttrib, NMessageID::kPosixAttrib }, + { kpidLink, NMessageID::kLink }, + { kpidError, NMessageID::kError }, + + { kpidTotalSize, NMessageID::kTotalSize }, + { kpidFreeSpace, NMessageID::kFreeSpace }, + { kpidClusterSize, NMessageID::kClusterSize }, + { kpidVolumeName, NMessageID::kLabel } +}; + +static const int kNumPROPIDToName = sizeof(kPROPIDToName) / sizeof(kPROPIDToName[0]); + +static int FindPropertyToName(PROPID propID) +{ + for (int i = 0; i < kNumPROPIDToName; i++) + if (kPROPIDToName[i].PropID == propID) + return i; + return -1; +} + +/* +struct CPropertyIDInfo +{ + PROPID PropID; + const char *FarID; + int Width; + // char CharID; +}; + +static CPropertyIDInfo kPropertyIDInfos[] = +{ + { kpidName, "N", 0}, + { kpidSize, "S", 8}, + { kpidPackedSize, "P", 8}, + { kpidAttrib, "A", 0}, + { kpidCTime, "DC", 14}, + { kpidATime, "DA", 14}, + { kpidMTime, "DM", 14}, + + { kpidSolid, NULL, 0, 'S'}, + { kpidEncrypted, NULL, 0, 'P'} + + { kpidDictionarySize, IDS_PROPERTY_DICTIONARY_SIZE }, + { kpidSplitBefore, NULL, 'B'}, + { kpidSplitAfter, NULL, 'A'}, + { kpidComment, , NULL, 'C'}, + { kpidCRC, IDS_PROPERTY_CRC } + // { kpidType, L"Type" } +}; + +static const int kNumPropertyIDInfos = sizeof(kPropertyIDInfos) / + sizeof(kPropertyIDInfos[0]); + +static int FindPropertyInfo(PROPID propID) +{ + for (int i = 0; i < kNumPropertyIDInfos; i++) + if (kPropertyIDInfos[i].PropID == propID) + return i; + return -1; +} +*/ + +// char *g_Titles[] = { "a", "f", "v" }; +/* +static void SmartAddToString(AString &destString, const char *srcString) +{ + if (!destString.IsEmpty()) + destString += ','; + destString += srcString; +} +*/ + +/* +void CPlugin::AddColumn(PROPID propID) +{ + int index = FindPropertyInfo(propID); + if (index >= 0) + { + for (int i = 0; i < m_ProxyHandler->m_InternalProperties.Size(); i++) + { + const CArchiveItemProperty &aHandlerProperty = m_ProxyHandler->m_InternalProperties[i]; + if (aHandlerProperty.ID == propID) + break; + } + if (i == m_ProxyHandler->m_InternalProperties.Size()) + return; + + const CPropertyIDInfo &propertyIDInfo = kPropertyIDInfos[index]; + SmartAddToString(PanelModeColumnTypes, propertyIDInfo.FarID); + char tmp[32]; + itoa(propertyIDInfo.Width, tmp, 10); + SmartAddToString(PanelModeColumnWidths, tmp); + return; + } +} +*/ + +static AString GetNameOfProp(PROPID propID, const wchar_t *name) +{ + int index = FindPropertyToName(propID); + if (index < 0) + { + if (name) + return UnicodeStringToMultiByte((const wchar_t *)name, CP_OEMCP); + char s[32]; + ConvertUInt64ToString(propID, s); + return s; + } + return g_StartupInfo.GetMsgString(kPROPIDToName[index].PluginID); +} + +static AString GetNameOfProp2(PROPID propID, const wchar_t *name) +{ + AString s = GetNameOfProp(propID, name); + if (s.Length() > (kInfoPanelLineSize - 1)) + s = s.Left(kInfoPanelLineSize - 1); + return s; +} + +static AString ConvertSizeToString(UInt64 value) +{ + char s[32]; + ConvertUInt64ToString(value, s); + int i = MyStringLen(s); + int pos = sizeof(s) / sizeof(s[0]); + s[--pos] = L'\0'; + while (i > 3) + { + s[--pos] = s[--i]; + s[--pos] = s[--i]; + s[--pos] = s[--i]; + s[--pos] = ' '; + } + while (i > 0) + s[--pos] = s[--i]; + return s + pos; +} + +static AString PropToString(const NCOM::CPropVariant &prop, PROPID propID) +{ + AString s; + + if (prop.vt == VT_BSTR) + s = UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP); + else if (prop.vt == VT_BOOL) + { + int messageID = VARIANT_BOOLToBool(prop.boolVal) ? + NMessageID::kYes : NMessageID::kNo; + return g_StartupInfo.GetMsgString(messageID); + } + else if (prop.vt != VT_EMPTY) + { + if (( + propID == kpidSize || + propID == kpidPackSize || + propID == kpidNumSubDirs || + propID == kpidNumSubFiles || + propID == kpidNumBlocks || + propID == kpidPhySize || + propID == kpidHeadersSize || + propID == kpidClusterSize + ) && (prop.vt == VT_UI8 || prop.vt == VT_UI4)) + s = ConvertSizeToString(ConvertPropVariantToUInt64(prop)); + else + s = UnicodeStringToMultiByte(ConvertPropertyToString(prop, propID), CP_OEMCP); + } + s.Replace((char)0xA, ' '); + s.Replace((char)0xD, ' '); + return s; +} + +static AString PropToString2(const NCOM::CPropVariant &prop, PROPID propID) +{ + AString s = PropToString(prop, propID); + if (s.Length() > (kInfoPanelLineSize - 1)) + s = s.Left(kInfoPanelLineSize - 1); + return s; +} + +static void AddPropertyString(InfoPanelLine *lines, int &numItems, PROPID propID, const wchar_t *name, + const NCOM::CPropVariant &prop) +{ + if (prop.vt != VT_EMPTY) + { + AString val = PropToString2(prop, propID); + if (!val.IsEmpty()) + { + InfoPanelLine &item = lines[numItems++]; + COPY_STR_LIMITED(item.Text, GetNameOfProp2(propID, name)); + COPY_STR_LIMITED(item.Data, val); + } + } +} + +static void InsertSeparator(InfoPanelLine *lines, int &numItems) +{ + if (numItems < kNumInfoLinesMax) + { + InfoPanelLine &item = lines[numItems++]; + MyStringCopy(item.Text, ""); + MyStringCopy(item.Data, ""); + item.Separator = TRUE; + } +} + +void CPlugin::GetOpenPluginInfo(struct OpenPluginInfo *info) +{ + info->StructSize = sizeof(*info); + info->Flags = OPIF_USEFILTER | OPIF_USESORTGROUPS| OPIF_USEHIGHLIGHTING| + OPIF_ADDDOTS | OPIF_COMPAREFATTIME; + + COPY_STR_LIMITED(m_FileNameBuffer, UnicodeStringToMultiByte(m_FileName, CP_OEMCP)); + info->HostFile = m_FileNameBuffer; // test it it is not static + + COPY_STR_LIMITED(m_CurrentDirBuffer, UnicodeStringToMultiByte(m_CurrentDir, CP_OEMCP)); + info->CurDir = m_CurrentDirBuffer; + + info->Format = kPluginFormatName; + + UString name; + { + UString fullName; + int index; + NFile::NDirectory::MyGetFullPathName(m_FileName, fullName, index); + name = fullName.Mid(index); + } + + m_PannelTitle = + UString(L' ') + + _archiveTypeName + + UString(L':') + + name + + UString(L' '); + if (!m_CurrentDir.IsEmpty()) + { + // m_PannelTitle += '\\'; + m_PannelTitle += m_CurrentDir; + } + + COPY_STR_LIMITED(m_PannelTitleBuffer, UnicodeStringToMultiByte(m_PannelTitle, CP_OEMCP)); + info->PanelTitle = m_PannelTitleBuffer; + + memset(m_InfoLines, 0, sizeof(m_InfoLines)); + MyStringCopy(m_InfoLines[0].Text, ""); + m_InfoLines[0].Separator = TRUE; + + MyStringCopy(m_InfoLines[1].Text, g_StartupInfo.GetMsgString(NMessageID::kArchiveType)); + MyStringCopy(m_InfoLines[1].Data, (const char *)UnicodeStringToMultiByte(_archiveTypeName, CP_OEMCP)); + + int numItems = 2; + + { + CMyComPtr folderProperties; + _folder.QueryInterface(IID_IFolderProperties, &folderProperties); + if (folderProperties) + { + UInt32 numProps; + if (folderProperties->GetNumberOfFolderProperties(&numProps) == S_OK) + { + for (UInt32 i = 0; i < numProps && numItems < kNumInfoLinesMax; i++) + { + CMyComBSTR name; + PROPID propID; + VARTYPE vt; + if (folderProperties->GetFolderPropertyInfo(i, &name, &propID, &vt) != S_OK) + continue; + NCOM::CPropVariant prop; + if (_folder->GetFolderProperty(propID, &prop) != S_OK || prop.vt == VT_EMPTY) + continue; + + InfoPanelLine &item = m_InfoLines[numItems++]; + COPY_STR_LIMITED(item.Text, GetNameOfProp2(propID, name)); + COPY_STR_LIMITED(item.Data, PropToString2(prop, propID)); + } + } + } + } + + /* + if (numItems < kNumInfoLinesMax) + { + InsertSeparator(m_InfoLines, numItems); + } + */ + + { + CMyComPtr getFolderArcProps; + _folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps); + if (getFolderArcProps) + { + CMyComPtr getProps; + getFolderArcProps->GetFolderArcProps(&getProps); + if (getProps) + { + UInt32 numLevels; + if (getProps->GetArcNumLevels(&numLevels) != S_OK) + numLevels = 0; + for (UInt32 level2 = 0; level2 < numLevels; level2++) + { + { + UInt32 level = numLevels - 1 - level2; + UInt32 numProps; + if (getProps->GetArcNumProps(level, &numProps) == S_OK) + { + InsertSeparator(m_InfoLines, numItems); + for (Int32 i = -3; i < (Int32)numProps && numItems < kNumInfoLinesMax; i++) + { + CMyComBSTR name; + PROPID propID; + VARTYPE vt; + switch (i) + { + case -3: propID = kpidPath; break; + case -2: propID = kpidType; break; + case -1: propID = kpidError; break; + default: + if (getProps->GetArcPropInfo(level, i, &name, &propID, &vt) != S_OK) + continue; + } + NCOM::CPropVariant prop; + if (getProps->GetArcProp(level, propID, &prop) != S_OK) + continue; + AddPropertyString(m_InfoLines, numItems, propID, name, prop); + } + } + } + if (level2 != numLevels - 1) + { + UInt32 level = numLevels - 1 - level2; + UInt32 numProps; + if (getProps->GetArcNumProps2(level, &numProps) == S_OK) + { + InsertSeparator(m_InfoLines, numItems); + for (Int32 i = 0; i < (Int32)numProps && numItems < kNumInfoLinesMax; i++) + { + CMyComBSTR name; + PROPID propID; + VARTYPE vt; + if (getProps->GetArcPropInfo2(level, i, &name, &propID, &vt) != S_OK) + continue; + NCOM::CPropVariant prop; + if (getProps->GetArcProp2(level, propID, &prop) != S_OK) + continue; + AddPropertyString(m_InfoLines, numItems, propID, name, prop); + } + } + } + } + } + } + } + + //m_InfoLines[1].Separator = 0; + + info->InfoLines = m_InfoLines; + info->InfoLinesNumber = numItems; + + + info->DescrFiles = NULL; + info->DescrFilesNumber = 0; + + PanelModeColumnTypes.Empty(); + PanelModeColumnWidths.Empty(); + + /* + AddColumn(kpidName); + AddColumn(kpidSize); + AddColumn(kpidPackedSize); + AddColumn(kpidMTime); + AddColumn(kpidCTime); + AddColumn(kpidATime); + AddColumn(kpidAttrib); + + PanelMode.ColumnTypes = (char *)(const char *)PanelModeColumnTypes; + PanelMode.ColumnWidths = (char *)(const char *)PanelModeColumnWidths; + PanelMode.ColumnTitles = NULL; + PanelMode.FullScreen = TRUE; + PanelMode.DetailedStatus = FALSE; + PanelMode.AlignExtensions = FALSE; + PanelMode.CaseConversion = FALSE; + PanelMode.StatusColumnTypes = "N"; + PanelMode.StatusColumnWidths = "0"; + PanelMode.Reserved[0] = 0; + PanelMode.Reserved[1] = 0; + + info->PanelModesArray = &PanelMode; + info->PanelModesNumber = 1; + */ + + info->PanelModesArray = NULL; + info->PanelModesNumber = 0; + + info->StartPanelMode = 0; + info->StartSortMode = 0; + info->KeyBar = NULL; + info->ShortcutData = NULL; +} + +struct CArchiveItemProperty +{ + AString Name; + PROPID ID; + VARTYPE Type; +}; + +HRESULT CPlugin::ShowAttributesWindow() +{ + PluginPanelItem pluginPanelItem; + if (!g_StartupInfo.ControlGetActivePanelCurrentItemInfo(pluginPanelItem)) + return S_FALSE; + if (strcmp(pluginPanelItem.FindData.cFileName, "..") == 0 && + NFile::NFind::NAttributes::IsDir(pluginPanelItem.FindData.dwFileAttributes)) + return S_FALSE; + int itemIndex = (int)pluginPanelItem.UserData; + + CObjectVector properties; + UInt32 numProps; + RINOK(_folder->GetNumberOfProperties(&numProps)); + int i; + for (i = 0; i < (int)numProps; i++) + { + CMyComBSTR name; + PROPID propID; + VARTYPE vt; + RINOK(_folder->GetPropertyInfo(i, &name, &propID, &vt)); + CArchiveItemProperty prop; + prop.Type = vt; + prop.ID = propID; + if (prop.ID == kpidPath) + prop.ID = kpidName; + prop.Name = GetNameOfProp(propID, name); + properties.Add(prop); + } + + int size = 2; + CRecordVector initDialogItems; + + int xSize = 70; + CInitDialogItem idi = + { DI_DOUBLEBOX, 3, 1, xSize - 4, size - 2, false, false, 0, false, NMessageID::kProperties, NULL, NULL }; + initDialogItems.Add(idi); + AStringVector values; + + for (i = 0; i < properties.Size(); i++) + { + const CArchiveItemProperty &property = properties[i]; + + CInitDialogItem idi = + { DI_TEXT, 5, 3 + i, 0, 0, false, false, 0, false, 0, NULL, NULL }; + int index = FindPropertyToName(property.ID); + if (index < 0) + { + idi.DataMessageId = -1; + idi.DataString = property.Name; + } + else + idi.DataMessageId = kPROPIDToName[index].PluginID; + initDialogItems.Add(idi); + + NCOM::CPropVariant prop; + RINOK(_folder->GetProperty(itemIndex, property.ID, &prop)); + AString s = PropToString(prop, property.ID); + values.Add(s); + + { + CInitDialogItem idi = + { DI_TEXT, 30, 3 + i, 0, 0, false, false, 0, false, -1, NULL, NULL }; + initDialogItems.Add(idi); + } + } + + int numLines = values.Size(); + for (i = 0; i < numLines; i++) + { + CInitDialogItem &idi = initDialogItems[1 + i * 2 + 1]; + idi.DataString = values[i]; + } + + int numDialogItems = initDialogItems.Size(); + + CRecordVector dialogItems; + dialogItems.Reserve(numDialogItems); + for (i = 0; i < numDialogItems; i++) + dialogItems.Add(FarDialogItem()); + g_StartupInfo.InitDialogItems(&initDialogItems.Front(), + &dialogItems.Front(), numDialogItems); + + int maxLen = 0; + for (i = 0; i < numLines; i++) + { + FarDialogItem &dialogItem = dialogItems[1 + i * 2]; + int len = (int)strlen(dialogItem.Data); + if (len > maxLen) + maxLen = len; + } + int maxLen2 = 0; + const int kSpace = 10; + for (i = 0; i < numLines; i++) + { + FarDialogItem &dialogItem = dialogItems[1 + i * 2 + 1]; + int len = (int)strlen(dialogItem.Data); + if (len > maxLen2) + maxLen2 = len; + dialogItem.X1 = maxLen + kSpace; + } + size = numLines + 6; + xSize = maxLen + kSpace + maxLen2 + 5; + FarDialogItem &firstDialogItem = dialogItems.Front(); + firstDialogItem.Y2 = size - 2; + firstDialogItem.X2 = xSize - 4; + + /* int askCode = */ g_StartupInfo.ShowDialog(xSize, size, NULL, &dialogItems.Front(), numDialogItems); + return S_OK; +} + +int CPlugin::ProcessKey(int key, unsigned int controlState) +{ + if (controlState == PKF_CONTROL && key == 'A') + { + HRESULT result = ShowAttributesWindow(); + if (result == S_OK) + return TRUE; + if (result == S_FALSE) + return FALSE; + throw "Error"; + } + if ((controlState & PKF_ALT) != 0 && key == VK_F6) + { + UString folderPath; + if (!NFile::NDirectory::GetOnlyDirPrefix(m_FileName, folderPath)) + return FALSE; + PanelInfo panelInfo; + g_StartupInfo.ControlGetActivePanelInfo(panelInfo); + GetFilesReal(panelInfo.SelectedItems, + panelInfo.SelectedItemsNumber, FALSE, + UnicodeStringToMultiByte(folderPath, CP_OEMCP), OPM_SILENT, true); + g_StartupInfo.Control(this, FCTL_UPDATEPANEL, NULL); + g_StartupInfo.Control(this, FCTL_REDRAWPANEL, NULL); + g_StartupInfo.Control(this, FCTL_UPDATEANOTHERPANEL, NULL); + g_StartupInfo.Control(this, FCTL_REDRAWANOTHERPANEL, NULL); + return TRUE; + } + + return FALSE; +} diff --git a/CPP/7zip/UI/Far/Plugin.h b/CPP/7zip/UI/Far/Plugin.h new file mode 100755 index 0000000..f48d00b --- /dev/null +++ b/CPP/7zip/UI/Far/Plugin.h @@ -0,0 +1,88 @@ +// 7zip/Far/Plugin.h + +#ifndef __7ZIP_FAR_PLUGIN_H +#define __7ZIP_FAR_PLUGIN_H + +#include "Common/MyCom.h" + +#include "Windows/COM.h" +#include "Windows/FileFind.h" +#include "Windows/PropVariant.h" + +#include "../Agent/IFolderArchive.h" + +#include "FarUtils.h" + +const UInt32 kNumInfoLinesMax = 64; + +class CPlugin +{ + NWindows::NCOM::CComInitializer m_ComInitializer; + UString m_CurrentDir; + + UString m_PannelTitle; + + InfoPanelLine m_InfoLines[kNumInfoLinesMax]; + + char m_FileNameBuffer[1024]; + char m_CurrentDirBuffer[1024]; + char m_PannelTitleBuffer[1024]; + + AString PanelModeColumnTypes; + AString PanelModeColumnWidths; + PanelMode PanelMode; + void AddColumn(PROPID aPropID); + + void EnterToDirectory(const UString &dirName); + void GetPathParts(UStringVector &pathParts); + void GetCurrentDir(); +public: + UString m_FileName; + NWindows::NFile::NFind::CFileInfoW m_FileInfo; + + CMyComPtr m_ArchiveHandler; + CMyComPtr _folder; + + UString _archiveTypeName; + + bool PasswordIsDefined; + UString Password; + + CPlugin(const UString &fileName, IInFolderArchive *archiveHandler, UString archiveTypeName); + ~CPlugin(); + + void ReadPluginPanelItem(PluginPanelItem &panelItem, UInt32 itemIndex); + + int GetFindData(PluginPanelItem **panelItems,int *itemsNumber,int opMode); + void FreeFindData(PluginPanelItem *panelItem,int ItemsNumber); + int SetDirectory(const char *aszDir, int opMode); + void GetOpenPluginInfo(struct OpenPluginInfo *info); + int DeleteFiles(PluginPanelItem *panelItems, int itemsNumber, int opMode); + + HRESULT ExtractFiles( + bool decompressAllItems, + const UInt32 *indices, + UInt32 numIndices, + bool silent, + NExtract::NPathMode::EEnum pathMode, + NExtract::NOverwriteMode::EEnum overwriteMode, + const UString &destPath, + bool passwordIsDefined, const UString &password); + + NFar::NFileOperationReturnCode::EEnum GetFiles(struct PluginPanelItem *panelItem, int itemsNumber, + int move, char *destPath, int opMode); + + NFar::NFileOperationReturnCode::EEnum GetFilesReal(struct PluginPanelItem *panelItems, + int itemsNumber, int move, const char *_aDestPath, int opMode, bool showBox); + + NFar::NFileOperationReturnCode::EEnum PutFiles(struct PluginPanelItem *panelItems, int itemsNumber, + int move, int opMode); + + HRESULT ShowAttributesWindow(); + + int ProcessKey(int key, unsigned int controlState); +}; + +HRESULT CompressFiles(const CObjectVector &pluginPanelItems); + +#endif diff --git a/CPP/7zip/UI/Far/PluginCommon.cpp b/CPP/7zip/UI/Far/PluginCommon.cpp new file mode 100755 index 0000000..53ad88f --- /dev/null +++ b/CPP/7zip/UI/Far/PluginCommon.cpp @@ -0,0 +1,50 @@ +// SevenZip/Plugin.cpp + +#include "StdAfx.h" + +#include "Plugin.h" + +/* +void CPlugin::AddRealIndexOfFile(const CArchiveFolderItem &aFolder, + int anIndexInVector, vector &aRealIndexes) +{ + const CArchiveFolderFileItem &anItem = aFolder.m_FileSubItems[anIndexInVector]; + int aHandlerItemIndex = m_ProxyHandler->GetHandlerItemIndex(anItem.m_Properties); + if(aHandlerItemIndex < 0) + throw "error"; + aRealIndexes.push_back(aHandlerItemIndex); +} + +void CPlugin::AddRealIndexes(const CArchiveFolderItem &anItem, + vector &aRealIndexes) +{ + int aHandlerItemIndex = m_ProxyHandler->GetHandlerItemIndex(anItem.m_Properties); + if(aHandlerItemIndex >= 0) // test -1 value + aRealIndexes.push_back(aHandlerItemIndex); + for(int i = 0; i < anItem.m_DirSubItems.Size(); i++) + AddRealIndexes(anItem.m_DirSubItems[i], aRealIndexes); + for(i = 0; i < anItem.m_FileSubItems.Size(); i++) + AddRealIndexOfFile(anItem, i , aRealIndexes); +} + + +void CPlugin::GetRealIndexes(PluginPanelItem *aPanelItems, int anItemsNumber, + vector &aRealIndexes) +{ + aRealIndexes.clear(); + for(int i = 0; i < anItemsNumber; i++) + { + int anIndex = aPanelItems[i].UserData; + if (anIndex < m_FolderItem->m_DirSubItems.Size()) + { + const CArchiveFolderItem &anItem = m_FolderItem->m_DirSubItems[anIndex]; + AddRealIndexes(anItem, aRealIndexes); + } + else + AddRealIndexOfFile(*m_FolderItem, anIndex - m_FolderItem->m_DirSubItems.Size(), + aRealIndexes); + } + sort(aRealIndexes.begin(), aRealIndexes.end()); +} + +*/ diff --git a/CPP/7zip/UI/Far/PluginDelete.cpp b/CPP/7zip/UI/Far/PluginDelete.cpp new file mode 100755 index 0000000..b50576b --- /dev/null +++ b/CPP/7zip/UI/Far/PluginDelete.cpp @@ -0,0 +1,161 @@ +// PluginDelete.cpp + +#include "StdAfx.h" + +#include "Windows/FileDir.h" + +#include "../Common/WorkDir.h" + +#include "Messages.h" +#include "Plugin.h" +#include "UpdateCallback100.h" + +using namespace NFar; +using namespace NWindows; +using namespace NFile; +using namespace NDirectory; + +static LPCWSTR kTempArchivePrefix = L"7zA"; + +int CPlugin::DeleteFiles(PluginPanelItem *panelItems, int numItems, int opMode) +{ + if (numItems == 0) + return FALSE; + /* + if (!m_ArchiverInfo.UpdateEnabled) + { + g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive); + return FALSE; + } + */ + if ((opMode & OPM_SILENT) == 0) + { + const char *msgItems[]= + { + g_StartupInfo.GetMsgString(NMessageID::kDeleteTitle), + g_StartupInfo.GetMsgString(NMessageID::kDeleteFiles), + g_StartupInfo.GetMsgString(NMessageID::kDeleteDelete), + g_StartupInfo.GetMsgString(NMessageID::kDeleteCancel) + }; + char msg[1024]; + if (numItems == 1) + { + sprintf(msg, g_StartupInfo.GetMsgString(NMessageID::kDeleteFile), panelItems[0].FindData.cFileName); + msgItems[1] = msg; + } + else if (numItems > 1) + { + sprintf(msg, g_StartupInfo.GetMsgString(NMessageID::kDeleteNumberOfFiles), + numItems); + msgItems[1] = msg; + } + if (g_StartupInfo.ShowMessage(FMSG_WARNING, NULL, msgItems, + sizeof(msgItems) / sizeof(msgItems[0]), 2) != 0) + return (FALSE); + } + + CScreenRestorer screenRestorer; + CProgressBox progressBox; + CProgressBox *progressBoxPointer = NULL; + if ((opMode & OPM_SILENT) == 0 && (opMode & OPM_FIND ) == 0) + { + screenRestorer.Save(); + + progressBoxPointer = &progressBox; + progressBox.Init( + // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle), + g_StartupInfo.GetMsgString(NMessageID::kDeleting), 48); + } + + NWorkDir::CInfo workDirInfo; + workDirInfo.Load(); + + UString workDir = GetWorkDir(workDirInfo, m_FileName); + CreateComplexDirectory(workDir); + + CTempFileW tempFile; + UString tempFileName; + if (tempFile.Create(workDir, kTempArchivePrefix, tempFileName) == 0) + return FALSE; + + + CRecordVector indices; + indices.Reserve(numItems); + int i; + for (i = 0; i < numItems; i++) + indices.Add((UINT32)panelItems[i].UserData); + + //////////////////////////// + // Save _folder; + + UStringVector pathVector; + GetPathParts(pathVector); + + CMyComPtr outArchive; + HRESULT result = m_ArchiveHandler.QueryInterface(IID_IOutFolderArchive, &outArchive); + if (result != S_OK) + { + g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive); + return FALSE; + } + outArchive->SetFolder(_folder); + + CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp; + CMyComPtr updateCallback(updateCallbackSpec ); + + updateCallbackSpec->Init(/* m_ArchiveHandler, */ progressBoxPointer); + + + result = outArchive->DeleteItems( + tempFileName, + &indices.Front(), indices.Size(), + updateCallback); + updateCallback.Release(); + outArchive.Release(); + + if (result != S_OK) + { + ShowErrorMessage(result); + return FALSE; + } + + _folder.Release(); + m_ArchiveHandler->Close(); + + if (!DeleteFileAlways(m_FileName)) + { + ShowLastErrorMessage(); + return FALSE; + } + + tempFile.DisableDeleting(); + if (!MyMoveFile(tempFileName, m_FileName)) + { + ShowLastErrorMessage(); + return FALSE; + } + + result = m_ArchiveHandler->ReOpen(NULL); + if (result != S_OK) + { + ShowErrorMessage(result); + return FALSE; + } + + + //////////////////////////// + // Restore _folder; + + m_ArchiveHandler->BindToRootFolder(&_folder); + for (i = 0; i < pathVector.Size(); i++) + { + CMyComPtr newFolder; + _folder->BindToFolder(pathVector[i], &newFolder); + if (!newFolder) + break; + _folder = newFolder; + } + GetCurrentDir(); + + return TRUE; +} diff --git a/CPP/7zip/UI/Far/PluginRead.cpp b/CPP/7zip/UI/Far/PluginRead.cpp new file mode 100755 index 0000000..0725010 --- /dev/null +++ b/CPP/7zip/UI/Far/PluginRead.cpp @@ -0,0 +1,286 @@ +// PluginRead.cpp + +#include "StdAfx.h" + +#include "Plugin.h" + +#include "Messages.h" + +#include "Common/StringConvert.h" + +#include "Windows/FileName.h" +#include "Windows/FileFind.h" +#include "Windows/FileDir.h" +#include "Windows/Defs.h" + +#include "../Common/ZipRegistry.h" + +#include "ExtractEngine.h" + +using namespace NFar; +using namespace NWindows; + +static const char *kHelpTopicExtrFromSevenZip = "Extract"; + +static const char kDirDelimiter = '\\'; + +static const char *kExractPathHistoryName = "7-ZipExtractPath"; + +HRESULT CPlugin::ExtractFiles( + bool decompressAllItems, + const UINT32 *indices, + UINT32 numIndices, + bool silent, + NExtract::NPathMode::EEnum pathMode, + NExtract::NOverwriteMode::EEnum overwriteMode, + const UString &destPath, + bool passwordIsDefined, const UString &password) +{ + CScreenRestorer screenRestorer; + CProgressBox progressBox; + CProgressBox *progressBoxPointer = NULL; + if (!silent) + { + screenRestorer.Save(); + + progressBoxPointer = &progressBox; + progressBox.Init( + // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle), + g_StartupInfo.GetMsgString(NMessageID::kExtracting), 48); + } + + + CExtractCallBackImp *extractCallbackSpec = new CExtractCallBackImp; + CMyComPtr extractCallback(extractCallbackSpec); + + extractCallbackSpec->Init( + CP_OEMCP, + progressBoxPointer, + /* + GetDefaultName(m_FileName, m_ArchiverInfo.Extension), + m_FileInfo.MTime, m_FileInfo.Attributes, + */ + passwordIsDefined, password); + + if (decompressAllItems) + return m_ArchiveHandler->Extract(pathMode, overwriteMode, + destPath, BoolToInt(false), extractCallback); + else + { + CMyComPtr archiveFolder; + _folder.QueryInterface(IID_IArchiveFolder, &archiveFolder); + + return archiveFolder->Extract(indices, numIndices, pathMode, overwriteMode, + destPath, BoolToInt(false), extractCallback); + } +} + +NFileOperationReturnCode::EEnum CPlugin::GetFiles(struct PluginPanelItem *panelItems, + int itemsNumber, int move, char *destPath, int opMode) +{ + return GetFilesReal(panelItems, itemsNumber, move, + destPath, opMode, (opMode & OPM_SILENT) == 0); +} + +NFileOperationReturnCode::EEnum CPlugin::GetFilesReal(struct PluginPanelItem *panelItems, + int itemsNumber, int move, const char *destPathLoc, int opMode, bool showBox) +{ + if (move != 0) + { + g_StartupInfo.ShowMessage(NMessageID::kMoveIsNotSupported); + return NFileOperationReturnCode::kError; + } + + AString destPath = destPathLoc; + UString destPathU = GetUnicodeString(destPath, CP_OEMCP); + NFile::NName::NormalizeDirPathPrefix(destPathU); + destPath = UnicodeStringToMultiByte(destPathU, CP_OEMCP); + + bool extractSelectedFiles = true; + + NExtract::CInfo extractionInfo; + extractionInfo.PathMode = NExtract::NPathMode::kCurrentPathnames; + extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; + + bool silent = (opMode & OPM_SILENT) != 0; + bool decompressAllItems = false; + UString password = Password; + bool passwordIsDefined = PasswordIsDefined; + + if (!silent) + { + const int kPathIndex = 2; + + extractionInfo.Load(); + + const int kPathModeRadioIndex = 4; + const int kOverwriteModeRadioIndex = kPathModeRadioIndex + 4; + const int kNumOverwriteOptions = 6; + const int kFilesModeIndex = kOverwriteModeRadioIndex + kNumOverwriteOptions; + const int kXSize = 76; + const int kYSize = 19; + const int kPasswordYPos = 12; + + const int kXMid = kXSize / 2; + + AString oemPassword = UnicodeStringToMultiByte(password, CP_OEMCP); + + struct CInitDialogItem initItems[]={ + { DI_DOUBLEBOX, 3, 1, kXSize - 4, kYSize - 2, false, false, 0, false, NMessageID::kExtractTitle, NULL, NULL }, + { DI_TEXT, 5, 2, 0, 0, false, false, 0, false, NMessageID::kExtractTo, NULL, NULL }, + + { DI_EDIT, 5, 3, kXSize - 6, 3, true, false, DIF_HISTORY, false, -1, destPath, kExractPathHistoryName}, + // { DI_EDIT, 5, 3, kXSize - 6, 3, true, false, 0, false, -1, destPath, NULL}, + + { DI_SINGLEBOX, 4, 5, kXMid - 2, 5 + 4, false, false, 0, false, NMessageID::kExtractPathMode, NULL, NULL }, + { DI_RADIOBUTTON, 6, 6, 0, 0, false, + extractionInfo.PathMode == NExtract::NPathMode::kFullPathnames, + DIF_GROUP, false, NMessageID::kExtractPathFull, NULL, NULL }, + { DI_RADIOBUTTON, 6, 7, 0, 0, false, + extractionInfo.PathMode == NExtract::NPathMode::kCurrentPathnames, + 0, false, NMessageID::kExtractPathCurrent, NULL, NULL }, + { DI_RADIOBUTTON, 6, 8, 0, 0, false, + extractionInfo.PathMode == NExtract::NPathMode::kNoPathnames, + false, 0, NMessageID::kExtractPathNo, NULL, NULL }, + + { DI_SINGLEBOX, kXMid, 5, kXSize - 6, 5 + kNumOverwriteOptions, false, false, 0, false, NMessageID::kExtractOwerwriteMode, NULL, NULL }, + { DI_RADIOBUTTON, kXMid + 2, 6, 0, 0, false, + extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kAskBefore, + DIF_GROUP, false, NMessageID::kExtractOwerwriteAsk, NULL, NULL }, + { DI_RADIOBUTTON, kXMid + 2, 7, 0, 0, false, + extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kWithoutPrompt, + 0, false, NMessageID::kExtractOwerwritePrompt, NULL, NULL }, + { DI_RADIOBUTTON, kXMid + 2, 8, 0, 0, false, + extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kSkipExisting, + 0, false, NMessageID::kExtractOwerwriteSkip, NULL, NULL }, + { DI_RADIOBUTTON, kXMid + 2, 9, 0, 0, false, + extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kAutoRename, + 0, false, NMessageID::kExtractOwerwriteAutoRename, NULL, NULL }, + { DI_RADIOBUTTON, kXMid + 2, 10, 0, 0, false, + extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting, + 0, false, NMessageID::kExtractOwerwriteAutoRenameExisting, NULL, NULL }, + + { DI_SINGLEBOX, 4, 10, kXMid- 2, 10 + 3, false, false, 0, false, NMessageID::kExtractFilesMode, NULL, NULL }, + { DI_RADIOBUTTON, 6, 11, 0, 0, false, true, DIF_GROUP, false, NMessageID::kExtractFilesSelected, NULL, NULL }, + { DI_RADIOBUTTON, 6, 12, 0, 0, false, false, 0, false, NMessageID::kExtractFilesAll, NULL, NULL }, + + { DI_SINGLEBOX, kXMid, kPasswordYPos, kXSize - 6, kPasswordYPos + 2, false, false, 0, false, NMessageID::kExtractPassword, NULL, NULL }, + { DI_PSWEDIT, kXMid + 2, kPasswordYPos + 1, kXSize - 8, 12, false, false, 0, false, -1, oemPassword, NULL}, + + { DI_TEXT, 3, kYSize - 4, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL }, + + + { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, true, NMessageID::kExtractExtract, NULL, NULL }, + { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kExtractCancel, NULL, NULL } + }; + + const int kNumDialogItems = sizeof(initItems) / sizeof(initItems[0]); + const int kOkButtonIndex = kNumDialogItems - 2; + const int kPasswordIndex = kNumDialogItems - 4; + + FarDialogItem dialogItems[kNumDialogItems]; + g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumDialogItems); + for (;;) + { + int askCode = g_StartupInfo.ShowDialog(kXSize, kYSize, + kHelpTopicExtrFromSevenZip, dialogItems, kNumDialogItems); + if (askCode != kOkButtonIndex) + return NFileOperationReturnCode::kInterruptedByUser; + destPath = dialogItems[kPathIndex].Data; + destPathU = GetUnicodeString(destPath, CP_OEMCP); + destPathU.Trim(); + if (destPathU.IsEmpty()) + { + #ifdef UNDER_CE + destPathU = L"\\"; + #else + if (!NFile::NDirectory::MyGetCurrentDirectory(destPathU)) + throw 318016; + NFile::NName::NormalizeDirPathPrefix(destPathU); + #endif + break; + } + else + { + if (destPathU.Back() == kDirDelimiter) + break; + } + g_StartupInfo.ShowMessage("You must specify directory path"); + } + + if (dialogItems[kPathModeRadioIndex].Selected) + extractionInfo.PathMode = NExtract::NPathMode::kFullPathnames; + else if (dialogItems[kPathModeRadioIndex + 1].Selected) + extractionInfo.PathMode = NExtract::NPathMode::kCurrentPathnames; + else if (dialogItems[kPathModeRadioIndex + 2].Selected) + extractionInfo.PathMode = NExtract::NPathMode::kNoPathnames; + else + throw 31806; + + if (dialogItems[kOverwriteModeRadioIndex].Selected) + extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kAskBefore; + else if (dialogItems[kOverwriteModeRadioIndex + 1].Selected) + extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; + else if (dialogItems[kOverwriteModeRadioIndex + 2].Selected) + extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kSkipExisting; + else if (dialogItems[kOverwriteModeRadioIndex + 3].Selected) + extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kAutoRename; + else if (dialogItems[kOverwriteModeRadioIndex + 4].Selected) + extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kAutoRenameExisting; + else + throw 31806; + + if (dialogItems[kFilesModeIndex].Selected) + decompressAllItems = false; + else if (dialogItems[kFilesModeIndex + 1].Selected) + decompressAllItems = true; + else + throw 31806; + + extractionInfo.Save(); + + if (dialogItems[kFilesModeIndex].Selected) + extractSelectedFiles = true; + else if (dialogItems[kFilesModeIndex + 1].Selected) + extractSelectedFiles = false; + else + throw 31806; + + oemPassword = dialogItems[kPasswordIndex].Data; + password = MultiByteToUnicodeString(oemPassword, CP_OEMCP); + passwordIsDefined = !password.IsEmpty(); + } + + NFile::NDirectory::CreateComplexDirectory(destPathU); + + /* + vector realIndices; + if (!decompressAllItems) + GetRealIndexes(panelItems, itemsNumber, realIndices); + */ + CRecordVector indices; + indices.Reserve(itemsNumber); + for (int i = 0; i < itemsNumber; i++) + indices.Add((UINT32)panelItems[i].UserData); + + HRESULT result = ExtractFiles(decompressAllItems, &indices.Front(), itemsNumber, + !showBox, extractionInfo.PathMode, extractionInfo.OverwriteMode, + destPathU, + passwordIsDefined, password); + // HRESULT result = ExtractFiles(decompressAllItems, realIndices, !showBox, + // extractionInfo, destPath, passwordIsDefined, password); + if (result != S_OK) + { + if (result == E_ABORT) + return NFileOperationReturnCode::kInterruptedByUser; + ShowErrorMessage(result); + return NFileOperationReturnCode::kError; + } + + // if (move != 0) + // { + // if (DeleteFiles(panelItems, itemsNumber, opMode) == FALSE) + // return NFileOperationReturnCode::kError; + // } + return NFileOperationReturnCode::kSuccess; +} diff --git a/CPP/7zip/UI/Far/PluginWrite.cpp b/CPP/7zip/UI/Far/PluginWrite.cpp new file mode 100755 index 0000000..ad6c29b --- /dev/null +++ b/CPP/7zip/UI/Far/PluginWrite.cpp @@ -0,0 +1,780 @@ +// PluginWrite.cpp + +#include "StdAfx.h" + +#include "Plugin.h" + +#include "Common/Wildcard.h" +#include "Common/StringConvert.h" + +#include "Windows/FileDir.h" +#include "Windows/FileName.h" +#include "Windows/FileFind.h" +#include "Windows/Defs.h" +#include "Windows/PropVariant.h" + +#include "../Common/ZipRegistry.h" +#include "../Common/WorkDir.h" +#include "../Common/OpenArchive.h" + +#include "../Agent/Agent.h" + +#include "ProgressBox.h" +#include "Messages.h" +#include "UpdateCallback100.h" + +using namespace NWindows; +using namespace NFile; +using namespace NDirectory; +using namespace NFar; + +using namespace NUpdateArchive; + +static const char *kHelpTopic = "Update"; + +static LPCWSTR kTempArcivePrefix = L"7zA"; + +static const char *kArchiveHistoryKeyName = "7-ZipArcName"; + +static UINT32 g_MethodMap[] = { 0, 1, 3, 5, 7, 9 }; + +static HRESULT SetOutProperties(IOutFolderArchive *outArchive, UINT32 method) +{ + CMyComPtr setProperties; + if (outArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties) == S_OK) + { + UStringVector realNames; + realNames.Add(UString(L"x")); + NCOM::CPropVariant value = (UInt32)method; + CRecordVector names; + for(int i = 0; i < realNames.Size(); i++) + names.Add(realNames[i]); + RINOK(setProperties->SetProperties(&names.Front(), &value, names.Size())); + } + return S_OK; +} + +NFileOperationReturnCode::EEnum CPlugin::PutFiles( + struct PluginPanelItem *panelItems, int numItems, + int moveMode, int opMode) +{ + if(moveMode != 0) + { + g_StartupInfo.ShowMessage(NMessageID::kMoveIsNotSupported); + return NFileOperationReturnCode::kError; + } + if (numItems == 0) + return NFileOperationReturnCode::kError; + + /* + if (!m_ArchiverInfo.UpdateEnabled) + { + g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive); + return NFileOperationReturnCode::kError; + } + */ + + const int kYSize = 14; + const int kXMid = 38; + + NCompression::CInfo compressionInfo; + compressionInfo.Load(); + + int methodIndex = 0; + int i; + for (i = sizeof(g_MethodMap) / sizeof(g_MethodMap[0]) - 1; i >= 0; i--) + if (compressionInfo.Level >= g_MethodMap[i]) + { + methodIndex = i; + break; + } + + const int kMethodRadioIndex = 2; + const int kModeRadioIndex = kMethodRadioIndex + 7; + + struct CInitDialogItem initItems[]={ + { DI_DOUBLEBOX, 3, 1, 72, kYSize - 2, false, false, 0, false, NMessageID::kUpdateTitle, NULL, NULL }, + { DI_SINGLEBOX, 4, 2, kXMid - 2, 2 + 7, false, false, 0, false, NMessageID::kUpdateMethod, NULL, NULL }, + { DI_RADIOBUTTON, 6, 3, 0, 0, methodIndex == 0, methodIndex == 0, + DIF_GROUP, false, NMessageID::kUpdateMethodStore, NULL, NULL }, + { DI_RADIOBUTTON, 6, 4, 0, 0, methodIndex == 1, methodIndex == 1, + 0, false, NMessageID::kUpdateMethodFastest, NULL, NULL }, + { DI_RADIOBUTTON, 6, 5, 0, 0, methodIndex == 2, methodIndex == 2, + 0, false, NMessageID::kUpdateMethodFast, NULL, NULL }, + { DI_RADIOBUTTON, 6, 6, 0, 0, methodIndex == 3, methodIndex == 3, + 0, false, NMessageID::kUpdateMethodNormal, NULL, NULL }, + { DI_RADIOBUTTON, 6, 7, 0, 0, methodIndex == 4, methodIndex == 4, + 0, false, NMessageID::kUpdateMethodMaximum, NULL, NULL }, + { DI_RADIOBUTTON, 6, 8, 0, 0, methodIndex == 5, methodIndex == 5, + 0, false, NMessageID::kUpdateMethodUltra, NULL, NULL }, + + { DI_SINGLEBOX, kXMid, 2, 70, 2 + 5, false, false, 0, false, NMessageID::kUpdateMode, NULL, NULL }, + { DI_RADIOBUTTON, kXMid + 2, 3, 0, 0, false, true, + DIF_GROUP, false, NMessageID::kUpdateModeAdd, NULL, NULL }, + { DI_RADIOBUTTON, kXMid + 2, 4, 0, 0, false, false, + 0, false, NMessageID::kUpdateModeUpdate, NULL, NULL }, + { DI_RADIOBUTTON, kXMid + 2, 5, 0, 0, false, false, + 0, false, NMessageID::kUpdateModeFreshen, NULL, NULL }, + { DI_RADIOBUTTON, kXMid + 2, 6, 0, 0, false, false, + 0, false, NMessageID::kUpdateModeSynchronize, NULL, NULL }, + + { DI_TEXT, 3, kYSize - 4, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL }, + + { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, true, NMessageID::kUpdateAdd, NULL, NULL }, + { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kCancel, NULL, NULL } + }; + + const int kNumDialogItems = sizeof(initItems) / sizeof(initItems[0]); + const int kOkButtonIndex = kNumDialogItems - 2; + FarDialogItem dialogItems[kNumDialogItems]; + g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumDialogItems); + int askCode = g_StartupInfo.ShowDialog(76, kYSize, + kHelpTopic, dialogItems, kNumDialogItems); + if (askCode != kOkButtonIndex) + return NFileOperationReturnCode::kInterruptedByUser; + + compressionInfo.Level = g_MethodMap[0]; + for (i = 0; i < sizeof(g_MethodMap)/ sizeof(g_MethodMap[0]); i++) + if (dialogItems[kMethodRadioIndex + i].Selected) + compressionInfo.Level = g_MethodMap[i]; + + const CActionSet *actionSet; + + if (dialogItems[kModeRadioIndex].Selected) + actionSet = &kAddActionSet; + else if (dialogItems[kModeRadioIndex + 1].Selected) + actionSet = &kUpdateActionSet; + else if (dialogItems[kModeRadioIndex + 2].Selected) + actionSet = &kFreshActionSet; + else if (dialogItems[kModeRadioIndex + 3].Selected) + actionSet = &kSynchronizeActionSet; + else + throw 51751; + + compressionInfo.Save(); + + NWorkDir::CInfo workDirInfo; + workDirInfo.Load(); + UString workDir = GetWorkDir(workDirInfo, m_FileName); + CreateComplexDirectory(workDir); + + CTempFileW tempFile; + UString tempFileName; + if (tempFile.Create(workDir, kTempArcivePrefix, tempFileName) == 0) + return NFileOperationReturnCode::kError; + + + /* + CSysStringVector fileNames; + for(int i = 0; i < numItems; i++) + { + const PluginPanelItem &panelItem = panelItems[i]; + CSysString fullName; + if (!MyGetFullPathName(panelItem.FindData.cFileName, fullName)) + return NFileOperationReturnCode::kError; + fileNames.Add(fullName); + } + */ + + CScreenRestorer screenRestorer; + CProgressBox progressBox; + CProgressBox *progressBoxPointer = NULL; + if ((opMode & OPM_SILENT) == 0 && (opMode & OPM_FIND ) == 0) + { + screenRestorer.Save(); + + progressBoxPointer = &progressBox; + progressBox.Init( + // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle), + g_StartupInfo.GetMsgString(NMessageID::kUpdating), 48); + } + + //////////////////////////// + // Save FolderItem; + UStringVector aPathVector; + GetPathParts(aPathVector); + + /* + UString anArchivePrefix; + for(i = aPathVector.Size() - 1; i >= 0; i--) + { + anArchivePrefix += aPathVector[i]; + anArchivePrefix += wchar_t(NName::kDirDelimiter); + } + ///////////////////////////////// + */ + + UStringVector fileNames; + fileNames.Reserve(numItems); + for(i = 0; i < numItems; i++) + fileNames.Add(MultiByteToUnicodeString(panelItems[i].FindData.cFileName, CP_OEMCP)); + CRecordVector fileNamePointers; + fileNamePointers.Reserve(numItems); + for(i = 0; i < numItems; i++) + fileNamePointers.Add(fileNames[i]); + + CMyComPtr outArchive; + HRESULT result = m_ArchiveHandler.QueryInterface(IID_IOutFolderArchive, &outArchive); + if(result != S_OK) + { + g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive); + return NFileOperationReturnCode::kError; + } + outArchive->SetFolder(_folder); + + // CSysString aCurrentFolder; + // MyGetCurrentDirectory(aCurrentFolder); + // outArchive->SetFiles(MultiByteToUnicodeString(aCurrentFolder, CP_OEMCP), + outArchive->SetFiles(L"", + &fileNamePointers.Front(), fileNamePointers.Size()); + BYTE actionSetByte[NUpdateArchive::NPairState::kNumValues]; + for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++) + actionSetByte[i] = (BYTE)actionSet->StateActions[i]; + + CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp; + CMyComPtr updateCallback(updateCallbackSpec ); + + updateCallbackSpec->Init(/* m_ArchiveHandler, */ progressBoxPointer); + + if (SetOutProperties(outArchive, compressionInfo.Level) != S_OK) + return NFileOperationReturnCode::kError; + + result = outArchive->DoOperation2(tempFileName, actionSetByte, NULL, updateCallback); + updateCallback.Release(); + outArchive.Release(); + + /* + HRESULT result = Compress(fileNames, anArchivePrefix, *actionSet, + m_ProxyHandler.get(), + m_ArchiverInfo.ClassID, compressionInfo.Method == 0, + compressionInfo.Method == 2, tempFileName, progressBoxPointer); + */ + + if (result != S_OK) + { + ShowErrorMessage(result); + return NFileOperationReturnCode::kError; + } + + _folder.Release(); + m_ArchiveHandler->Close(); + + // m_FolderItem = NULL; + + if (!DeleteFileAlways(m_FileName)) + { + ShowLastErrorMessage(); + return NFileOperationReturnCode::kError; + } + + tempFile.DisableDeleting(); + if (!MyMoveFile(tempFileName, m_FileName)) + { + ShowLastErrorMessage(); + return NFileOperationReturnCode::kError; + } + + m_ArchiveHandler->ReOpen(NULL); + if (result != S_OK) + { + ShowErrorMessage(result); + return NFileOperationReturnCode::kError; + } + + /* + if(m_ProxyHandler->ReInit(NULL) != S_OK) + return NFileOperationReturnCode::kError; + */ + + //////////////////////////// + // Restore FolderItem; + + m_ArchiveHandler->BindToRootFolder(&_folder); + for (i = 0; i < aPathVector.Size(); i++) + { + CMyComPtr newFolder; + _folder->BindToFolder(aPathVector[i], &newFolder); + if(!newFolder ) + break; + _folder = newFolder; + } + + /* + if(moveMode != 0) + { + for(int i = 0; i < numItems; i++) + { + const PluginPanelItem &aPluginPanelItem = panelItems[i]; + bool result; + if(NFile::NFind::NAttributes::IsDir(aPluginPanelItem.FindData.dwFileAttributes)) + result = NFile::NDirectory::RemoveDirectoryWithSubItems( + aPluginPanelItem.FindData.cFileName); + else + result = NFile::NDirectory::DeleteFileAlways( + aPluginPanelItem.FindData.cFileName); + if(!result) + return NFileOperationReturnCode::kError; + } + } + */ + return NFileOperationReturnCode::kSuccess; +} + +namespace NPathType +{ + enum EEnum + { + kLocal, + kUNC + }; + EEnum GetPathType(const UString &path); +} + +struct CParsedPath +{ + UString Prefix; // Disk or UNC with slash + UStringVector PathParts; + void ParsePath(const UString &path); + UString MergePath() const; +}; + +static const wchar_t kDirDelimiter = WCHAR_PATH_SEPARATOR; +static const wchar_t kDiskDelimiter = L':'; + +namespace NPathType +{ + EEnum GetPathType(const UString &path) + { + if (path.Length() <= 2) + return kLocal; + if (path[0] == kDirDelimiter && path[1] == kDirDelimiter) + return kUNC; + return kLocal; + } +} + +void CParsedPath::ParsePath(const UString &path) +{ + int curPos = 0; + switch (NPathType::GetPathType(path)) + { + case NPathType::kLocal: + { + int posDiskDelimiter = path.Find(kDiskDelimiter); + if(posDiskDelimiter >= 0) + { + curPos = posDiskDelimiter + 1; + if (path.Length() > curPos) + if(path[curPos] == kDirDelimiter) + curPos++; + } + break; + } + case NPathType::kUNC: + { + int curPos = path.Find(kDirDelimiter, 2); + if(curPos < 0) + curPos = path.Length(); + else + curPos++; + } + } + Prefix = path.Left(curPos); + SplitPathToParts(path.Mid(curPos), PathParts); +} + +UString CParsedPath::MergePath() const +{ + UString result = Prefix; + for(int i = 0; i < PathParts.Size(); i++) + { + if (i != 0) + result += kDirDelimiter; + result += PathParts[i]; + } + return result; +} + + +/* +// {23170F69-40C1-278A-1000-000100030000} +DEFINE_GUID(CLSID_CAgentArchiveHandler, + 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00); +*/ + +HRESULT CompressFiles(const CObjectVector &pluginPanelItems) +{ + if (pluginPanelItems.Size() == 0) + return E_FAIL; + + UStringVector fileNames; + int i; + for(i = 0; i < pluginPanelItems.Size(); i++) + { + const PluginPanelItem &panelItem = pluginPanelItems[i]; + UString fullName; + if (strcmp(panelItem.FindData.cFileName, "..") == 0 && + NFind::NAttributes::IsDir(panelItem.FindData.dwFileAttributes)) + return E_FAIL; + if (strcmp(panelItem.FindData.cFileName, ".") == 0 && + NFind::NAttributes::IsDir(panelItem.FindData.dwFileAttributes)) + return E_FAIL; + UString fileNameUnicode = MultiByteToUnicodeString(panelItem.FindData.cFileName, CP_OEMCP); + if (!MyGetFullPathName(fileNameUnicode, fullName)) + return E_FAIL; + fileNames.Add(fullName); + } + + NCompression::CInfo compressionInfo; + compressionInfo.Load(); + + int archiverIndex = 0; + + CCodecs *codecs = new CCodecs; + CMyComPtr compressCodecsInfo = codecs; + if (codecs->Load() != S_OK) + throw "Can't load 7-Zip codecs"; + { + for (int i = 0; i < codecs->Formats.Size(); i++) + { + const CArcInfoEx &arcInfo = codecs->Formats[i]; + if (arcInfo.UpdateEnabled) + { + if (archiverIndex == -1) + archiverIndex = i; + if (arcInfo.Name.CompareNoCase(compressionInfo.ArcType) == 0) + archiverIndex = i; + } + } + } + + + UString resultPath; + { + CParsedPath parsedPath; + parsedPath.ParsePath(fileNames.Front()); + if(parsedPath.PathParts.Size() == 0) + return E_FAIL; + if (fileNames.Size() == 1 || parsedPath.PathParts.Size() == 1) + { + // CSysString pureName, dot, extension; + resultPath = parsedPath.PathParts.Back(); + } + else + { + parsedPath.PathParts.DeleteBack(); + resultPath = parsedPath.PathParts.Back(); + } + } + UString archiveNameSrc = resultPath; + UString archiveName = archiveNameSrc; + + const CArcInfoEx &arcInfo = codecs->Formats[archiverIndex]; + int prevFormat = archiverIndex; + + if (!arcInfo.KeepName) + { + int dotPos = archiveName.ReverseFind('.'); + int slashPos = MyMax(archiveName.ReverseFind('\\'), archiveName.ReverseFind('/')); + if (dotPos > slashPos) + archiveName = archiveName.Left(dotPos); + } + archiveName += L'.'; + archiveName += arcInfo.GetMainExt(); + + const CActionSet *actionSet = &kAddActionSet; + + for (;;) + { + AString archiveNameA = UnicodeStringToMultiByte(archiveName, CP_OEMCP); + const int kYSize = 16; + const int kXMid = 38; + + const int kArchiveNameIndex = 2; + const int kMethodRadioIndex = kArchiveNameIndex + 2; + const int kModeRadioIndex = kMethodRadioIndex + 7; + + const CArcInfoEx &arcInfo = codecs->Formats[archiverIndex]; + + char updateAddToArchiveString[512]; + const AString s = UnicodeStringToMultiByte(arcInfo.Name, CP_OEMCP); + + sprintf(updateAddToArchiveString, + g_StartupInfo.GetMsgString(NMessageID::kUpdateAddToArchive), (const char *)s); + + int methodIndex = 0; + int i; + for (i = sizeof(g_MethodMap) / sizeof(g_MethodMap[0]) - 1; i >= 0; i--) + if (compressionInfo.Level >= g_MethodMap[i]) + { + methodIndex = i; + break; + } + + struct CInitDialogItem initItems[]= + { + { DI_DOUBLEBOX, 3, 1, 72, kYSize - 2, false, false, 0, false, NMessageID::kUpdateTitle, NULL, NULL }, + + { DI_TEXT, 5, 2, 0, 0, false, false, 0, false, -1, updateAddToArchiveString, NULL }, + + { DI_EDIT, 5, 3, 70, 3, true, false, DIF_HISTORY, false, -1, archiveNameA, kArchiveHistoryKeyName}, + // { DI_EDIT, 5, 3, 70, 3, true, false, 0, false, -1, archiveName, NULL}, + + { DI_SINGLEBOX, 4, 4, kXMid - 2, 4 + 7, false, false, 0, false, NMessageID::kUpdateMethod, NULL, NULL }, + { DI_RADIOBUTTON, 6, 5, 0, 0, false, methodIndex == 0, + DIF_GROUP, false, NMessageID::kUpdateMethodStore, NULL, NULL }, + { DI_RADIOBUTTON, 6, 6, 0, 0, false, methodIndex == 1, + 0, false, NMessageID::kUpdateMethodFastest, NULL, NULL }, + { DI_RADIOBUTTON, 6, 7, 0, 0, false, methodIndex == 2, + 0, false, NMessageID::kUpdateMethodFast, NULL, NULL }, + { DI_RADIOBUTTON, 6, 8, 0, 0, false, methodIndex == 3, + 0, false, NMessageID::kUpdateMethodNormal, NULL, NULL }, + { DI_RADIOBUTTON, 6, 9, 0, 0, false, methodIndex == 4, + false, 0, NMessageID::kUpdateMethodMaximum, NULL, NULL }, + { DI_RADIOBUTTON, 6, 10, 0, 0, false, methodIndex == 5, + false, 0, NMessageID::kUpdateMethodUltra, NULL, NULL }, + + { DI_SINGLEBOX, kXMid, 4, 70, 4 + 5, false, false, 0, false, NMessageID::kUpdateMode, NULL, NULL }, + { DI_RADIOBUTTON, kXMid + 2, 5, 0, 0, false, + actionSet == &kAddActionSet, + DIF_GROUP, false, NMessageID::kUpdateModeAdd, NULL, NULL }, + { DI_RADIOBUTTON, kXMid + 2, 6, 0, 0, false, + actionSet == &kUpdateActionSet, + 0, false, NMessageID::kUpdateModeUpdate, NULL, NULL }, + { DI_RADIOBUTTON, kXMid + 2, 7, 0, 0, false, + actionSet == &kFreshActionSet, + 0, false, NMessageID::kUpdateModeFreshen, NULL, NULL }, + { DI_RADIOBUTTON, kXMid + 2, 8, 0, 0, false, + actionSet == &kSynchronizeActionSet, + 0, false, NMessageID::kUpdateModeSynchronize, NULL, NULL }, + + { DI_TEXT, 3, kYSize - 4, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL }, + + { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, true, NMessageID::kUpdateAdd, NULL, NULL }, + { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kUpdateSelectArchiver, NULL, NULL }, + { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kCancel, NULL, NULL } + }; + + const int kNumDialogItems = sizeof(initItems) / sizeof(initItems[0]); + + const int kOkButtonIndex = kNumDialogItems - 3; + const int kSelectarchiverButtonIndex = kNumDialogItems - 2; + + FarDialogItem dialogItems[kNumDialogItems]; + g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumDialogItems); + int askCode = g_StartupInfo.ShowDialog(76, kYSize, + kHelpTopic, dialogItems, kNumDialogItems); + + archiveNameA = dialogItems[kArchiveNameIndex].Data; + archiveNameA.Trim(); + archiveName = MultiByteToUnicodeString(archiveNameA, CP_OEMCP); + + compressionInfo.Level = g_MethodMap[0]; + for (i = 0; i < sizeof(g_MethodMap)/ sizeof(g_MethodMap[0]); i++) + if (dialogItems[kMethodRadioIndex + i].Selected) + compressionInfo.Level = g_MethodMap[i]; + + if (dialogItems[kModeRadioIndex].Selected) + actionSet = &kAddActionSet; + else if (dialogItems[kModeRadioIndex + 1].Selected) + actionSet = &kUpdateActionSet; + else if (dialogItems[kModeRadioIndex + 2].Selected) + actionSet = &kFreshActionSet; + else if (dialogItems[kModeRadioIndex + 3].Selected) + actionSet = &kSynchronizeActionSet; + else + throw 51751; + + if (askCode == kSelectarchiverButtonIndex) + { + CIntVector indices; + CSysStringVector archiverNames; + for(int i = 0; i < codecs->Formats.Size(); i++) + { + const CArcInfoEx &arc = codecs->Formats[i]; + if (arc.UpdateEnabled) + { + indices.Add(i); + archiverNames.Add(GetSystemString(arc.Name, CP_OEMCP)); + } + } + + int index = g_StartupInfo.Menu(FMENU_AUTOHIGHLIGHT, + g_StartupInfo.GetMsgString(NMessageID::kUpdateSelectArchiverMenuTitle), + NULL, archiverNames, archiverIndex); + if(index >= 0) + { + const CArcInfoEx &prevArchiverInfo = codecs->Formats[prevFormat]; + if (prevArchiverInfo.KeepName) + { + const UString &prevExtension = prevArchiverInfo.GetMainExt(); + const int prevExtensionLen = prevExtension.Length(); + if (archiveName.Right(prevExtensionLen).CompareNoCase(prevExtension) == 0) + { + int pos = archiveName.Length() - prevExtensionLen; + if (pos > 1) + { + int dotPos = archiveName.ReverseFind('.'); + if (dotPos == pos - 1) + archiveName = archiveName.Left(dotPos); + } + } + } + + archiverIndex = indices[index]; + const CArcInfoEx &arcInfo = codecs->Formats[archiverIndex]; + prevFormat = archiverIndex; + + if (arcInfo.KeepName) + archiveName = archiveNameSrc; + else + { + int dotPos = archiveName.ReverseFind('.'); + int slashPos = MyMax(archiveName.ReverseFind('\\'), archiveName.ReverseFind('/')); + if (dotPos > slashPos) + archiveName = archiveName.Left(dotPos); + } + archiveName += L'.'; + archiveName += arcInfo.GetMainExt(); + } + continue; + } + + if (askCode != kOkButtonIndex) + return E_ABORT; + + break; + } + + const CArcInfoEx &archiverInfoFinal = codecs->Formats[archiverIndex]; + compressionInfo.ArcType = archiverInfoFinal.Name; + compressionInfo.Save(); + + NWorkDir::CInfo workDirInfo; + workDirInfo.Load(); + + UString fullArchiveName; + if (!MyGetFullPathName(archiveName, fullArchiveName)) + return E_FAIL; + + UString workDir = GetWorkDir(workDirInfo, fullArchiveName); + CreateComplexDirectory(workDir); + + CTempFileW tempFile; + UString tempFileName; + if (tempFile.Create(workDir, kTempArcivePrefix, tempFileName) == 0) + return E_FAIL; + + + CScreenRestorer screenRestorer; + CProgressBox progressBox; + CProgressBox *progressBoxPointer = NULL; + + screenRestorer.Save(); + + progressBoxPointer = &progressBox; + progressBox.Init( + // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle), + g_StartupInfo.GetMsgString(NMessageID::kUpdating), 48); + + + NFind::CFileInfoW fileInfo; + + CMyComPtr outArchive; + + CMyComPtr archiveHandler; + if(fileInfo.Find(fullArchiveName)) + { + if (fileInfo.IsDir()) + throw "There is Directory with such name"; + + CAgent *agentSpec = new CAgent; + archiveHandler = agentSpec; + // CLSID realClassID; + CMyComBSTR archiveType; + RINOK(agentSpec->Open(NULL, + GetUnicodeString(fullArchiveName, CP_OEMCP), UString(), + // &realClassID, + &archiveType, + NULL)); + + if (archiverInfoFinal.Name.CompareNoCase((const wchar_t *)archiveType) != 0) + throw "Type of existing archive differs from specified type"; + HRESULT result = archiveHandler.QueryInterface( + IID_IOutFolderArchive, &outArchive); + if(result != S_OK) + { + g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive); + return E_FAIL; + } + } + else + { + // HRESULT result = outArchive.CoCreateInstance(classID); + CAgent *agentSpec = new CAgent; + outArchive = agentSpec; + + /* + HRESULT result = outArchive.CoCreateInstance(CLSID_CAgentArchiveHandler); + if (result != S_OK) + { + g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive); + return E_FAIL; + } + */ + } + + CRecordVector fileNamePointers; + fileNamePointers.Reserve(fileNames.Size()); + for(i = 0; i < fileNames.Size(); i++) + fileNamePointers.Add(fileNames[i]); + + outArchive->SetFolder(NULL); + // CSysString aCurrentFolder; + // MyGetCurrentDirectory(aCurrentFolder); + // outArchive->SetFiles(MultiByteToUnicodeString(aCurrentFolder, CP_OEMCP), + outArchive->SetFiles(L"", + &fileNamePointers.Front(), fileNamePointers.Size()); + BYTE actionSetByte[NUpdateArchive::NPairState::kNumValues]; + for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++) + actionSetByte[i] = (BYTE)actionSet->StateActions[i]; + + CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp; + CMyComPtr updateCallback(updateCallbackSpec ); + + updateCallbackSpec->Init(/* archiveHandler, */ progressBoxPointer); + + + RINOK(SetOutProperties(outArchive, compressionInfo.Level)); + + HRESULT result = outArchive->DoOperation( + codecs, archiverIndex, + tempFileName, actionSetByte, + NULL, updateCallback); + updateCallback.Release(); + outArchive.Release(); + + if (result != S_OK) + { + ShowErrorMessage(result); + return result; + } + + if(archiveHandler) + { + archiveHandler->Close(); + if (!DeleteFileAlways(fullArchiveName)) + { + ShowLastErrorMessage(); + return NFileOperationReturnCode::kError; + } + } + tempFile.DisableDeleting(); + if (!MyMoveFile(tempFileName, fullArchiveName)) + { + ShowLastErrorMessage(); + return E_FAIL; + } + + return S_OK; +} diff --git a/CPP/7zip/UI/Far/ProgressBox.cpp b/CPP/7zip/UI/Far/ProgressBox.cpp new file mode 100755 index 0000000..35d3f2d --- /dev/null +++ b/CPP/7zip/UI/Far/ProgressBox.cpp @@ -0,0 +1,112 @@ +// ProgressBox.cpp + +#include "StdAfx.h" + +#include + +#include "ProgressBox.h" +#include "Common/IntToString.h" +#include "FarUtils.h" + +static void CopySpaces(char *dest, int numSpaces) +{ + int i; + for (i = 0; i < numSpaces; i++) + dest[i] = ' '; + dest[i] = '\0'; +} + +void ConvertUInt64ToStringAligned(UInt64 value, char *s, int alignSize) +{ + char temp[32]; + ConvertUInt64ToString(value, temp); + int len = (int)strlen(temp); + int numSpaces = 0; + if (len < alignSize) + { + numSpaces = alignSize - len; + CopySpaces(s, numSpaces); + } + strcpy(s + numSpaces, temp); +} + + +// ---------- CMessageBox ---------- + +static const int kMaxLen = 255; + +void CMessageBox::Init(const AString &title, int width) +{ + _title = title; + _width = MyMin(width, kMaxLen); +} + +void CMessageBox::ShowMessages(const char *strings[], int numStrings) +{ + const int kNumStaticStrings = 1; + const int kNumStringsMax = 10; + + if (numStrings > kNumStringsMax) + numStrings = kNumStringsMax; + + const char *msgItems[kNumStaticStrings + kNumStringsMax]; + msgItems[0] = _title; + + char formattedMessages[kNumStringsMax][kMaxLen + 1]; + + for (int i = 0; i < numStrings; i++) + { + char *formattedMessage = formattedMessages[i]; + const char *s = strings[i]; + int len = (int)strlen(s); + if (len < kMaxLen) + { + int size = MyMax(_width, len); + int startPos = (size - len) / 2; + CopySpaces(formattedMessage, startPos); + strcpy(formattedMessage + startPos, s); + CopySpaces(formattedMessage + startPos + len, size - startPos - len); + } + else + { + strncpy(formattedMessage, s, kMaxLen); + formattedMessage[kMaxLen] = 0; + } + msgItems[kNumStaticStrings + i] = formattedMessage; + } + NFar::g_StartupInfo.ShowMessage(0, NULL, msgItems, kNumStaticStrings + numStrings, 0); +} + + +// ---------- CProgressBox ---------- + +void CProgressBox::Init(const AString &title, int width) +{ + CMessageBox::Init(title, width); + _prevMessage.Empty(); + _prevPercentMessage.Empty(); + _wasShown = false; +} + +void CProgressBox::Progress(const UInt64 *total, const UInt64 *completed, const AString &message) +{ + AString percentMessage; + if (total != 0 && completed != 0) + { + UInt64 totalVal = *total; + if (totalVal == 0) + totalVal = 1; + char buf[32]; + ConvertUInt64ToStringAligned(*completed * 100 / totalVal, buf, 3); + strcat(buf, "%"); + percentMessage = buf; + } + if (message != _prevMessage || percentMessage != _prevPercentMessage || !_wasShown) + { + _prevMessage = message; + _prevPercentMessage = percentMessage; + const char *strings[] = { message, percentMessage }; + ShowMessages(strings, sizeof(strings) / sizeof(strings[0])); + _wasShown = true; + } +} diff --git a/CPP/7zip/UI/Far/ProgressBox.h b/CPP/7zip/UI/Far/ProgressBox.h new file mode 100755 index 0000000..a83df87 --- /dev/null +++ b/CPP/7zip/UI/Far/ProgressBox.h @@ -0,0 +1,30 @@ +// ProgressBox.h + +#ifndef __PROGRESSBOX_H +#define __PROGRESSBOX_H + +#include "Common/MyString.h" +#include "Common/Types.h" + +void ConvertUInt64ToStringAligned(UInt64 value, char *s, int alignSize); + +class CMessageBox +{ + AString _title; + int _width; +public: + void Init(const AString &title, int width); + void ShowMessages(const char *strings[], int numStrings); +}; + +class CProgressBox: public CMessageBox +{ + AString _prevMessage; + AString _prevPercentMessage; + bool _wasShown; +public: + void Init(const AString &title, int width); + void Progress(const UInt64 *total, const UInt64 *completed, const AString &message); +}; + +#endif diff --git a/CPP/7zip/UI/Far/StdAfx.cpp b/CPP/7zip/UI/Far/StdAfx.cpp new file mode 100755 index 0000000..c6d3b1f --- /dev/null +++ b/CPP/7zip/UI/Far/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/UI/Far/StdAfx.h b/CPP/7zip/UI/Far/StdAfx.h new file mode 100755 index 0000000..0986203 --- /dev/null +++ b/CPP/7zip/UI/Far/StdAfx.h @@ -0,0 +1,13 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#define _CRT_SECURE_NO_DEPRECATE +#include +#include + +#include "Common/NewHandler.h" + +#endif + diff --git a/CPP/7zip/UI/Far/UpdateCallback100.cpp b/CPP/7zip/UI/Far/UpdateCallback100.cpp new file mode 100755 index 0000000..a93890d --- /dev/null +++ b/CPP/7zip/UI/Far/UpdateCallback100.cpp @@ -0,0 +1,66 @@ +// UpdateCallback.h + +#include "StdAfx.h" + +#include "UpdateCallback100.h" + +#include "Common/Defs.h" +#include "Common/StringConvert.h" +#include "FarUtils.h" + +using namespace NFar; + +STDMETHODIMP CUpdateCallback100Imp::SetNumFiles(UInt64 /* numFiles */) +{ + return S_OK; +} + +STDMETHODIMP CUpdateCallback100Imp::SetTotal(UInt64 size) +{ + _total = size; + return S_OK; +} + +STDMETHODIMP CUpdateCallback100Imp::SetCompleted(const UInt64 *completeValue) +{ + if (WasEscPressed()) + return E_ABORT; + if (_progressBox != 0) + _progressBox->Progress(&_total, completeValue, AString()); + return S_OK; +} + +STDMETHODIMP CUpdateCallback100Imp::CompressOperation(const wchar_t* /* name */) +{ + return S_OK; +} + +STDMETHODIMP CUpdateCallback100Imp::DeleteOperation(const wchar_t* /* name */) +{ + return S_OK; +} + +STDMETHODIMP CUpdateCallback100Imp::OperationResult(Int32 /* opRes */) +{ + return S_OK; +} + +STDMETHODIMP CUpdateCallback100Imp::UpdateErrorMessage(const wchar_t *message) +{ + if (g_StartupInfo.ShowMessage(UnicodeStringToMultiByte(message, CP_OEMCP)) == -1) + return E_ABORT; + return S_OK; +} + +extern HRESULT GetPassword(UString &password); + +STDMETHODIMP CUpdateCallback100Imp::CryptoGetTextPassword(BSTR *password) +{ + *password = NULL; + if (!m_PasswordIsDefined) + { + RINOK(GetPassword(m_Password)); + m_PasswordIsDefined = true; + } + return StringToBstr(m_Password, password); +} diff --git a/CPP/7zip/UI/Far/UpdateCallback100.h b/CPP/7zip/UI/Far/UpdateCallback100.h new file mode 100755 index 0000000..dd7ff54 --- /dev/null +++ b/CPP/7zip/UI/Far/UpdateCallback100.h @@ -0,0 +1,43 @@ +// UpdateCallback.h + +#ifndef __UPDATE_CALLBACK_H +#define __UPDATE_CALLBACK_H + +#include "Common/MyCom.h" + +#include "../Agent/IFolderArchive.h" + +#include "../../IPassword.h" + +#include "ProgressBox.h" + +class CUpdateCallback100Imp: + public IFolderArchiveUpdateCallback, + public ICryptoGetTextPassword, + public CMyUnknownImp +{ + // CMyComPtr _archiveHandler; + CProgressBox *_progressBox; + UInt64 _total; + bool m_PasswordIsDefined; + UString m_Password; + +public: + MY_UNKNOWN_IMP1(ICryptoGetTextPassword) + + INTERFACE_IProgress(;) + INTERFACE_IFolderArchiveUpdateCallback(;) + STDMETHOD(CryptoGetTextPassword)(BSTR *password); + + CUpdateCallback100Imp(): _total(0) {} + void Init(/* IInFolderArchive *archiveHandler, */ CProgressBox *progressBox) + { + // _archiveHandler = archiveHandler; + _progressBox = progressBox; + m_PasswordIsDefined = false; + } +}; + + + +#endif diff --git a/CPP/7zip/UI/Far/makefile b/CPP/7zip/UI/Far/makefile new file mode 100755 index 0000000..785b2ef --- /dev/null +++ b/CPP/7zip/UI/Far/makefile @@ -0,0 +1,119 @@ +PROG = 7-ZipFar.dll +DEF_FILE = Far.def +CFLAGS = $(CFLAGS) -I ../../../ \ + -DEXTERNAL_CODECS + +!IFNDEF UNDER_CE +CFLAGS = $(CFLAGS) -DWIN_LONG_PATH +!ENDIF + +FAR_OBJS = \ + $O\ExtractEngine.obj \ + $O\FarUtils.obj \ + $O\Main.obj \ + $O\OverwriteDialog.obj \ + $O\Plugin.obj \ + $O\PluginCommon.obj \ + $O\PluginDelete.obj \ + $O\PluginRead.obj \ + $O\PluginWrite.obj \ + $O\ProgressBox.obj \ + $O\UpdateCallback100.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\Error.obj \ + $O\FileDir.obj \ + $O\FileFind.obj \ + $O\FileIO.obj \ + $O\FileName.obj \ + $O\PropVariant.obj \ + $O\PropVariantConversions.obj \ + $O\Registry.obj \ + $O\Synchronization.obj \ + $O\Time.obj \ + +7ZIP_COMMON_OBJS = \ + $O\FilePathAutoRename.obj \ + $O\FileStreams.obj \ + $O\ProgressUtils.obj \ + $O\StreamUtils.obj \ + +UI_COMMON_OBJS = \ + $O\ArchiveExtractCallback.obj \ + $O\ArchiveOpenCallback.obj \ + $O\DefaultName.obj \ + $O\EnumDirItems.obj \ + $O\ExtractingFilePath.obj \ + $O\LoadCodecs.obj \ + $O\OpenArchive.obj \ + $O\PropIDUtils.obj \ + $O\SortUtils.obj \ + $O\UpdateAction.obj \ + $O\UpdateCallback.obj \ + $O\UpdatePair.obj \ + $O\UpdateProduce.obj \ + $O\WorkDir.obj \ + $O\ZipRegistry.obj \ + +AR_COMMON_OBJS = \ + $O\OutStreamWithCRC.obj \ + +AGENT_OBJS = \ + $O\Agent.obj \ + $O\AgentOut.obj \ + $O\AgentProxy.obj \ + $O\UpdateCallbackAgent.obj \ + +C_OBJS = \ + $O\Alloc.obj \ + $O\CpuArch.obj \ + $O\Sort.obj \ + $O\Threads.obj \ + +!include "../../Crc.mak" + +OBJS = \ + $O\StdAfx.obj \ + $(FAR_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(UI_COMMON_OBJS) \ + $(AR_COMMON_OBJS) \ + $(AGENT_OBJS) \ + $O\CopyCoder.obj \ + $(C_OBJS) \ + $(ASM_OBJS) \ + $O\resource.res + +!include "../../../Build.mak" + +$(FAR_OBJS): $(*B).cpp + $(COMPL) +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) +$(UI_COMMON_OBJS): ../Common/$(*B).cpp + $(COMPL) +$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp + $(COMPL) +$(AGENT_OBJS): ../Agent/$(*B).cpp + $(COMPL) +$O\CopyCoder.obj: ../../Compress/$(*B).cpp + $(COMPL) +$(C_OBJS): ../../../../C/$(*B).c + $(COMPL_O2) +!include "../../Asm.mak" diff --git a/CPP/7zip/UI/Far/resource.rc b/CPP/7zip/UI/Far/resource.rc new file mode 100755 index 0000000..7d04d2d --- /dev/null +++ b/CPP/7zip/UI/Far/resource.rc @@ -0,0 +1,3 @@ +#include "../../MyVersionInfo.rc" + +MY_VERSION_INFO_DLL("7-Zip Plugin for FAR Manager", "7-ZipFar") diff --git a/CPP/7zip/UI/FileManager/7zFM.exe.manifest b/CPP/7zip/UI/FileManager/7zFM.exe.manifest new file mode 100755 index 0000000..75af2e1 --- /dev/null +++ b/CPP/7zip/UI/FileManager/7zFM.exe.manifest @@ -0,0 +1 @@ +7-Zip File manager. diff --git a/CPP/7zip/UI/FileManager/7zipLogo.ico b/CPP/7zip/UI/FileManager/7zipLogo.ico new file mode 100755 index 0000000000000000000000000000000000000000..973241c847342d2aaa3927a3a8a96d02e61c9f6d GIT binary patch literal 9150 zcmeI2JIvEa5P*j`YX!%NjbrCwJ35K8t@FwiCC$-M&{ES;AyH6LoUWjvq@$prI#JLe z(I8RKQBhD(&>$fpBqSONq+jA@X8jDC@H+cE-CA@z98l;r);K2hpfBrn&xpN1;fBz0Q zZrp$mA3ngXTeslx0x`6E0r72>0&Y zgO49S!u|XA;memVaQ*sqxOVLt#BmH)uU>^`&z`}XH*etK!-w$v`E&UC^(%b-{287; zeF~2rJ%US@F2So;ui(?CPjKbR6?pOD1zfmr0e<}W!E>+99Yu~eM++P+u(JiiVkZ#? zNeW=>gezvfY;W5&uKyTJWmTGUfxeur9Y;DU3%PinUR^MWla_d-;@UpFUrT>6lIRVt5cA83(XHh zd|u|N1&^MnMplX9lZGc;Z%#QFe@`{T7J8nDd)R?_!tV3fed;a48Q+u#4X;S1mCfVR z^L*2*c)m5{0cO}+*iOG1jgUHCfTmP3*v?bIRfyCf|FM2X$qR@VJF{&(tL8bIc_K0l z!)GzV8R<9ov4>$LJYnjM`UTr~i}AG7uk?7A+W1e#gUJFbT9j~-kbcuP&s02T8!zrv z4qS>ZitmU=rYedk9FFsRiQ>A;j3zmyh&HS~PuRk1)Nd=#$SR&k(_IzfflW`PZC0Mf zXC$8D&6qdACdf0l>F2v%*#vX}O1x1{nv2MH=%$e|^UQ#JIihGop0$k^C0;dcOJh*x zDT@jjWep6k#*~qa4sSBp#uLG~;w734qj<`qLWJ$nMm@#jwZTb97#nQWji0UTMg5s z+%{UNGr6IbXJZB}-Qxc2z>3GQQAlZXaH#g1ctwO7YI%M#o|kU%>=o?_&euFT&jl51 z1>lle8>XexuMoIXXnBQGuXv3?EB(q{31hUes9W+lYSm)G2`L{+Klaw};@$>>HaxZ- zS~RT}Mai4+1NNUZ!q`xuWrXe;o?LoWgidXma$6c+9Wr6%?jbca%!Vh7i8G10P7ubT zzlK*hULB#s)re{F#wm@D7ONJ;&pbN_dY;Se{6Qb|{wrdyHt0_Zws<48fk^3dfQ;0A zr5_a?A`WQ3<#|MdWF1fBwLwQ*7LXpLw0XcjLIul3!F-HQ_MhT8R9x`di3Y=UyuzB- z3i2LW!SLMXsl1IA6$4%(6_3>|^EE{;Z#2{TDMNYSspolP6faS+C!?6ASMpRov(OkK4auIoKO1JYo+tA8 z8U=|rk0TOX%4I&5X-ayO@u~7P*Ar0`2hM_GT%@=yu8B|ldC@4?^&s)MPQgaCU@1d& zW{1aqXjYR9v5Z>J6Ir7mr;TdtH9U*#R^}JAzpEmr>Q?v@?75y-#He5uGVMZ?cwDE{ zBjJUN%@&Vq!oe)Jdj2KJze2>enc`h!zg{kMt9%sp>Ndo~n`b!#*v_ zO}r>;)&$k&rBpm0i``mmYeqcG;KC1QL$1$|CsjFY81^E_Dam$t)nv+Zv1qayG>edU zV}Zq>s&v&cGy{4+LS7n9`Yz}1Vc~}hB?GhHW8buSGReEL?A3+S2x=D+51fgq#6byy zVAkjQdY%m3Wu9@VGMe|)i=BG8!(P;}_5H;jXFXcOEveT$s#Mj!#M@gsJe(N6Y0`w0 z)B%css+2i1Ub^gg-H&}8HOBm%O~`sP@BDhoo3?(2+mtPu?iur0bcrV|Rg08s ze~(kcle3MyA?vU*O~HGRoC4Aio9I{?kx2CuX#55X=STjdmEXDuRr9;Q)VSQOmdpu0Rr?{Y845YGl00#pw+3Sg literal 0 HcmV?d00001 diff --git a/CPP/7zip/UI/FileManager/App.cpp b/CPP/7zip/UI/FileManager/App.cpp new file mode 100755 index 0000000..fb16e17 --- /dev/null +++ b/CPP/7zip/UI/FileManager/App.cpp @@ -0,0 +1,827 @@ +// App.cpp + +#include "StdAfx.h" + +#include "resource.h" +#include "OverwriteDialogRes.h" + +#include "Common/IntToString.h" +#include "Common/StringConvert.h" + +#include "Windows/COM.h" +#include "Windows/Error.h" +#include "Windows/FileDir.h" +#include "Windows/PropVariant.h" +#include "Windows/PropVariantConversions.h" +#include "Windows/Thread.h" + +#include "App.h" +#include "CopyDialog.h" +#include "ExtractCallback.h" +#include "FormatUtils.h" +#include "IFolder.h" +#include "LangUtils.h" +#include "RegistryUtils.h" +#include "ViewSettings.h" + +using namespace NWindows; +using namespace NFile; +using namespace NFind; + +extern DWORD g_ComCtl32Version; +extern HINSTANCE g_hInstance; + +static LPCWSTR kTempDirPrefix = L"7zE"; + +void CPanelCallbackImp::OnTab() +{ + if (g_App.NumPanels != 1) + _app->Panels[1 - _index].SetFocusToList(); + _app->RefreshTitle(); +} + +void CPanelCallbackImp::SetFocusToPath(int index) +{ + int newPanelIndex = index; + if (g_App.NumPanels == 1) + newPanelIndex = g_App.LastFocusedPanel; + _app->RefreshTitle(); + _app->Panels[newPanelIndex]._headerComboBox.SetFocus(); + _app->Panels[newPanelIndex]._headerComboBox.ShowDropDown(); +} + + +void CPanelCallbackImp::OnCopy(bool move, bool copyToSame) { _app->OnCopy(move, copyToSame, _index); } +void CPanelCallbackImp::OnSetSameFolder() { _app->OnSetSameFolder(_index); } +void CPanelCallbackImp::OnSetSubFolder() { _app->OnSetSubFolder(_index); } +void CPanelCallbackImp::PanelWasFocused() { _app->SetFocusedPanel(_index); _app->RefreshTitle(_index); } +void CPanelCallbackImp::DragBegin() { _app->DragBegin(_index); } +void CPanelCallbackImp::DragEnd() { _app->DragEnd(); } +void CPanelCallbackImp::RefreshTitle(bool always) { _app->RefreshTitle(_index, always); } + +void CApp::SetListSettings() +{ + bool showDots = ReadShowDots(); + bool showRealFileIcons = ReadShowRealFileIcons(); + + DWORD extendedStyle = LVS_EX_HEADERDRAGDROP; + if (ReadFullRow()) + extendedStyle |= LVS_EX_FULLROWSELECT; + if (ReadShowGrid()) + extendedStyle |= LVS_EX_GRIDLINES; + bool mySelectionMode = ReadAlternativeSelection(); + + if (ReadSingleClick()) + { + extendedStyle |= LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT; + /* + if (ReadUnderline()) + extendedStyle |= LVS_EX_UNDERLINEHOT; + */ + } + + for (int i = 0; i < kNumPanelsMax; i++) + { + CPanel &panel = Panels[i]; + panel._mySelectMode = mySelectionMode; + panel._showDots = showDots; + panel._showRealFileIcons = showRealFileIcons; + panel._exStyle = extendedStyle; + + DWORD style = (DWORD)panel._listView.GetStyle(); + if (mySelectionMode) + style |= LVS_SINGLESEL; + else + style &= ~LVS_SINGLESEL; + panel._listView.SetStyle(style); + panel.SetExtendedStyle(); + } +} + +void CApp::SetShowSystemMenu() +{ + ShowSystemMenu = ReadShowSystemMenu(); +} + +#ifndef ILC_COLOR32 +#define ILC_COLOR32 0x0020 +#endif + +HRESULT CApp::CreateOnePanel(int panelIndex, const UString &mainPath, const UString &arcFormat, + bool &archiveIsOpened, bool &encrypted) +{ + if (PanelsCreated[panelIndex]) + return S_OK; + m_PanelCallbackImp[panelIndex].Init(this, panelIndex); + UString path; + if (mainPath.IsEmpty()) + { + if (!::ReadPanelPath(panelIndex, path)) + path.Empty(); + } + else + path = mainPath; + int id = 1000 + 100 * panelIndex; + RINOK(Panels[panelIndex].Create(_window, _window, + id, path, arcFormat, &m_PanelCallbackImp[panelIndex], &AppState, archiveIsOpened, encrypted)); + PanelsCreated[panelIndex] = true; + return S_OK; +} + +static void CreateToolbar(HWND parent, + NWindows::NControl::CImageList &imageList, + NWindows::NControl::CToolBar &toolBar, + bool largeButtons) +{ + toolBar.Attach(::CreateWindowEx(0, TOOLBARCLASSNAME, NULL, 0 + | WS_CHILD + | WS_VISIBLE + | TBSTYLE_FLAT + | TBSTYLE_TOOLTIPS + | TBSTYLE_WRAPABLE + // | TBSTYLE_AUTOSIZE + // | CCS_NORESIZE + #ifdef UNDER_CE + | CCS_NODIVIDER + | CCS_NOPARENTALIGN + #endif + ,0,0,0,0, parent, NULL, g_hInstance, NULL)); + + // TB_BUTTONSTRUCTSIZE message, which is required for + // backward compatibility. + toolBar.ButtonStructSize(); + + imageList.Create( + largeButtons ? 48: 24, + largeButtons ? 36: 24, + ILC_MASK | ILC_COLOR32, 0, 0); + toolBar.SetImageList(0, imageList); +} + +struct CButtonInfo +{ + int CommandID; + UINT BitmapResID; + UINT Bitmap2ResID; + UINT StringResID; + UInt32 LangID; + UString GetText() const { return LangString(StringResID, LangID); } +}; + +static CButtonInfo g_StandardButtons[] = +{ + { IDM_COPY_TO, IDB_COPY, IDB_COPY2, IDS_BUTTON_COPY, 0x03020420}, + { IDM_MOVE_TO, IDB_MOVE, IDB_MOVE2, IDS_BUTTON_MOVE, 0x03020421}, + { IDM_DELETE, IDB_DELETE, IDB_DELETE2, IDS_BUTTON_DELETE, 0x03020422} , + { IDM_FILE_PROPERTIES, IDB_INFO, IDB_INFO2, IDS_BUTTON_INFO, 0x03020423} +}; + +static CButtonInfo g_ArchiveButtons[] = +{ + { kAddCommand, IDB_ADD, IDB_ADD2, IDS_ADD, 0x03020400}, + { kExtractCommand, IDB_EXTRACT, IDB_EXTRACT2, IDS_EXTRACT, 0x03020401}, + { kTestCommand , IDB_TEST, IDB_TEST2, IDS_TEST, 0x03020402} +}; + +static bool SetButtonText(int commandID, CButtonInfo *buttons, int numButtons, UString &s) +{ + for (int i = 0; i < numButtons; i++) + { + const CButtonInfo &b = buttons[i]; + if (b.CommandID == commandID) + { + s = b.GetText(); + return true; + } + } + return false; +} + +static void SetButtonText(int commandID, UString &s) +{ + if (SetButtonText(commandID, g_StandardButtons, + sizeof(g_StandardButtons) / sizeof(g_StandardButtons[0]), s)) + return; + SetButtonText(commandID, g_ArchiveButtons, + sizeof(g_ArchiveButtons) / sizeof(g_ArchiveButtons[0]), s); +} + +static void AddButton( + NControl::CImageList &imageList, + NControl::CToolBar &toolBar, + CButtonInfo &butInfo, bool showText, bool large) +{ + TBBUTTON but; + but.iBitmap = 0; + but.idCommand = butInfo.CommandID; + but.fsState = TBSTATE_ENABLED; + but.fsStyle = TBSTYLE_BUTTON; + but.dwData = 0; + + UString s = butInfo.GetText(); + but.iString = 0; + if (showText) + but.iString = (INT_PTR)(LPCWSTR)s; + + but.iBitmap = imageList.GetImageCount(); + HBITMAP b = ::LoadBitmap(g_hInstance, + large ? + MAKEINTRESOURCE(butInfo.BitmapResID): + MAKEINTRESOURCE(butInfo.Bitmap2ResID)); + if (b != 0) + { + imageList.AddMasked(b, RGB(255, 0, 255)); + ::DeleteObject(b); + } + #ifdef _UNICODE + toolBar.AddButton(1, &but); + #else + toolBar.AddButtonW(1, &but); + #endif +} + +void CApp::ReloadToolbars() +{ + _buttonsImageList.Destroy(); + _toolBar.Destroy(); + + + if (ShowArchiveToolbar || ShowStandardToolbar) + { + CreateToolbar(_window, _buttonsImageList, _toolBar, LargeButtons); + int i; + if (ShowArchiveToolbar) + for (i = 0; i < sizeof(g_ArchiveButtons) / sizeof(g_ArchiveButtons[0]); i++) + AddButton(_buttonsImageList, _toolBar, g_ArchiveButtons[i], ShowButtonsLables, LargeButtons); + if (ShowStandardToolbar) + for (i = 0; i < sizeof(g_StandardButtons) / sizeof(g_StandardButtons[0]); i++) + AddButton(_buttonsImageList, _toolBar, g_StandardButtons[i], ShowButtonsLables, LargeButtons); + + _toolBar.AutoSize(); + } +} + +void CApp::SaveToolbarChanges() +{ + SaveToolbar(); + ReloadToolbars(); + MoveSubWindows(); +} + +void MyLoadMenu(); + +HRESULT CApp::Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool &archiveIsOpened, bool &encrypted) +{ + _window.Attach(hwnd); + #ifdef UNDER_CE + _commandBar.Create(g_hInstance, hwnd, 1); + #endif + MyLoadMenu(); + #ifdef UNDER_CE + _commandBar.AutoSize(); + #endif + + ReadToolbar(); + ReloadToolbars(); + + int i; + for (i = 0; i < kNumPanelsMax; i++) + PanelsCreated[i] = false; + + AppState.Read(); + SetListSettings(); + SetShowSystemMenu(); + if (LastFocusedPanel >= kNumPanelsMax) + LastFocusedPanel = 0; + + CListMode listMode; + ReadListMode(listMode); + for (i = 0; i < kNumPanelsMax; i++) + { + CPanel &panel = Panels[i]; + panel._ListViewMode = listMode.Panels[i]; + panel._xSize = xSizes[i]; + panel._flatModeForArc = ReadFlatView(i); + } + for (i = 0; i < kNumPanelsMax; i++) + if (NumPanels > 1 || i == LastFocusedPanel) + { + if (NumPanels == 1) + Panels[i]._xSize = xSizes[0] + xSizes[1]; + bool archiveIsOpened2 = false; + bool encrypted2 = false; + bool mainPanel = (i == LastFocusedPanel); + RINOK(CreateOnePanel(i, mainPanel ? mainPath : L"", arcFormat, archiveIsOpened2, encrypted2)); + if (mainPanel) + { + archiveIsOpened = archiveIsOpened2; + encrypted = encrypted2; + } + } + SetFocusedPanel(LastFocusedPanel); + Panels[LastFocusedPanel].SetFocusToList(); + return S_OK; +} + +HRESULT CApp::SwitchOnOffOnePanel() +{ + if (NumPanels == 1) + { + NumPanels++; + bool archiveIsOpened, encrypted; + RINOK(CreateOnePanel(1 - LastFocusedPanel, UString(), UString(), archiveIsOpened, encrypted)); + Panels[1 - LastFocusedPanel].Enable(true); + Panels[1 - LastFocusedPanel].Show(SW_SHOWNORMAL); + } + else + { + NumPanels--; + Panels[1 - LastFocusedPanel].Enable(false); + Panels[1 - LastFocusedPanel].Show(SW_HIDE); + } + MoveSubWindows(); + return S_OK; +} + +void CApp::Save() +{ + AppState.Save(); + CListMode listMode; + for (int i = 0; i < kNumPanelsMax; i++) + { + const CPanel &panel = Panels[i]; + UString path; + if (panel._parentFolders.IsEmpty()) + path = panel._currentFolderPrefix; + else + path = GetFolderPath(panel._parentFolders[0].ParentFolder); + SavePanelPath(i, path); + listMode.Panels[i] = panel.GetListViewMode(); + SaveFlatView(i, panel._flatModeForArc); + } + SaveListMode(listMode); +} + +void CApp::Release() +{ + // It's for unloading COM dll's: don't change it. + for (int i = 0; i < kNumPanelsMax; i++) + Panels[i].Release(); +} + +// reduces path to part that exists on disk +static void ReducePathToRealFileSystemPath(UString &path) +{ + while (!path.IsEmpty()) + { + if (NFind::DoesDirExist(path)) + { + NName::NormalizeDirPathPrefix(path); + break; + } + int pos = path.ReverseFind(WCHAR_PATH_SEPARATOR); + if (pos < 0) + path.Empty(); + else + { + path = path.Left(pos + 1); + if (path.Length() == 3 && path[1] == L':') + break; + if (path.Length() > 2 && path[0] == '\\' && path[1] == '\\') + { + int nextPos = path.Find(WCHAR_PATH_SEPARATOR, 2); // pos after \\COMPNAME + if (nextPos > 0 && path.Find(WCHAR_PATH_SEPARATOR, nextPos + 1) == pos) + break; + } + path = path.Left(pos); + } + } +} + +// return true for dir\, if dir exist +static bool CheckFolderPath(const UString &path) +{ + UString pathReduced = path; + ReducePathToRealFileSystemPath(pathReduced); + return (pathReduced == path); +} + +static bool IsPathAbsolute(const UString &path) +{ + if (path.Length() >= 1 && path[0] == WCHAR_PATH_SEPARATOR) + return true; + #ifdef _WIN32 + if (path.Length() >= 3 && path[1] == L':' && path[2] == L'\\') + return true; + #endif + return false; +} + +extern UString ConvertSizeToString(UInt64 value); + +static UString AddSizeValue(UInt64 size) +{ + return MyFormatNew(IDS_FILE_SIZE, 0x02000982, ConvertSizeToString(size)); +} + +static void AddValuePair1(UINT resourceID, UInt32 langID, UInt64 size, UString &s) +{ + s += LangString(resourceID, langID); + s += L" "; + s += AddSizeValue(size); + s += L"\n"; +} + +void AddValuePair2(UINT resourceID, UInt32 langID, UInt64 num, UInt64 size, UString &s) +{ + if (num == 0) + return; + s += LangString(resourceID, langID); + s += L" "; + s += ConvertSizeToString(num); + + if (size != (UInt64)(Int64)-1) + { + s += L" ( "; + s += AddSizeValue(size); + s += L" )"; + } + s += L"\n"; +} + +static void AddPropValueToSum(IFolderFolder *folder, int index, PROPID propID, UInt64 &sum) +{ + if (sum == (UInt64)(Int64)-1) + return; + NCOM::CPropVariant prop; + folder->GetProperty(index, propID, &prop); + switch(prop.vt) + { + case VT_UI4: + case VT_UI8: + sum += ConvertPropVariantToUInt64(prop); + break; + default: + sum = (UInt64)(Int64)-1; + } +} + +UString CPanel::GetItemsInfoString(const CRecordVector &indices) +{ + UString info; + UInt64 numDirs, numFiles, filesSize, foldersSize; + numDirs = numFiles = filesSize = foldersSize = 0; + int i; + for (i = 0; i < indices.Size(); i++) + { + int index = indices[i]; + if (IsItemFolder(index)) + { + AddPropValueToSum(_folder, index, kpidSize, foldersSize); + numDirs++; + } + else + { + AddPropValueToSum(_folder, index, kpidSize, filesSize); + numFiles++; + } + } + + AddValuePair2(IDS_FOLDERS_COLON, 0x02000321, numDirs, foldersSize, info); + AddValuePair2(IDS_FILES_COLON, 0x02000320, numFiles, filesSize, info); + int numDefined = ((foldersSize != (UInt64)(Int64)-1) && foldersSize != 0) ? 1: 0; + numDefined += ((filesSize != (UInt64)(Int64)-1) && filesSize != 0) ? 1: 0; + if (numDefined == 2) + AddValuePair1(IDS_SIZE_COLON, 0x02000322, filesSize + foldersSize, info); + + info += L"\n"; + info += _currentFolderPrefix; + + for (i = 0; i < indices.Size() && i < kCopyDialog_NumInfoLines - 6; i++) + { + info += L"\n "; + int index = indices[i]; + info += GetItemRelPath(index); + if (IsItemFolder(index)) + info += WCHAR_PATH_SEPARATOR; + } + if (i != indices.Size()) + info += L"\n ..."; + return info; +} + +void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) +{ + int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex); + CPanel &srcPanel = Panels[srcPanelIndex]; + CPanel &destPanel = Panels[destPanelIndex]; + + CPanel::CDisableTimerProcessing disableTimerProcessing1(destPanel); + CPanel::CDisableTimerProcessing disableTimerProcessing2(srcPanel); + + if (!srcPanel.DoesItSupportOperations()) + { + srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + return; + } + + CRecordVector indices; + UString destPath; + bool useDestPanel = false; + + { + if (copyToSame) + { + int focusedItem = srcPanel._listView.GetFocusedItem(); + if (focusedItem < 0) + return; + int realIndex = srcPanel.GetRealItemIndex(focusedItem); + if (realIndex == kParentIndex) + return; + indices.Add(realIndex); + destPath = srcPanel.GetItemName(realIndex); + } + else + { + srcPanel.GetOperatedIndicesSmart(indices); + if (indices.Size() == 0) + return; + destPath = destPanel._currentFolderPrefix; + if (NumPanels == 1) + ReducePathToRealFileSystemPath(destPath); + } + + CCopyDialog copyDialog; + UStringVector copyFolders; + ReadCopyHistory(copyFolders); + + copyDialog.Strings = copyFolders; + copyDialog.Value = destPath; + + copyDialog.Title = move ? + LangString(IDS_MOVE, 0x03020202): + LangString(IDS_COPY, 0x03020201); + copyDialog.Static = move ? + LangString(IDS_MOVE_TO, 0x03020204): + LangString(IDS_COPY_TO, 0x03020203); + + copyDialog.Info = srcPanel.GetItemsInfoString(indices); + + if (copyDialog.Create(srcPanel.GetParent()) == IDCANCEL) + return; + + destPath = copyDialog.Value; + + if (destPath.IsEmpty()) + { + srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + return; + } + + if (!IsPathAbsolute(destPath)) + { + if (!srcPanel.IsFSFolder()) + { + srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + return; + } + destPath = srcPanel._currentFolderPrefix + destPath; + } + + #ifndef UNDER_CE + if (destPath.Length() > 0 && destPath[0] == '\\') + if (destPath.Length() == 1 || destPath[1] != '\\') + { + srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + return; + } + #endif + + if (indices.Size() > 1 || + (!destPath.IsEmpty() && destPath.Back() == WCHAR_PATH_SEPARATOR) || + NFind::DoesDirExist(destPath) || + srcPanel.IsArcFolder()) + { + NDirectory::CreateComplexDirectory(destPath); + NName::NormalizeDirPathPrefix(destPath); + if (!CheckFolderPath(destPath)) + { + if (NumPanels < 2 || destPath != destPanel._currentFolderPrefix || !destPanel.DoesItSupportOperations()) + { + srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + return; + } + useDestPanel = true; + } + } + else + { + int pos = destPath.ReverseFind(WCHAR_PATH_SEPARATOR); + if (pos >= 0) + { + UString prefix = destPath.Left(pos + 1); + NDirectory::CreateComplexDirectory(prefix); + if (!CheckFolderPath(prefix)) + { + srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + return; + } + } + } + + AddUniqueStringToHeadOfList(copyFolders, destPath); + while (copyFolders.Size() > 20) + copyFolders.DeleteBack(); + SaveCopyHistory(copyFolders); + } + + /* + if (destPath == destPanel._currentFolderPrefix) + { + if (destPanel.GetFolderTypeID() == L"PhysDrive") + useDestPanel = true; + } + */ + + bool useSrcPanel = (!useDestPanel || !srcPanel.IsFsOrDrivesFolder() || destPanel.IsFSFolder()); + bool useTemp = useSrcPanel && useDestPanel; + NFile::NDirectory::CTempDirectoryW tempDirectory; + UString tempDirPrefix; + if (useTemp) + { + tempDirectory.Create(kTempDirPrefix); + tempDirPrefix = tempDirectory.GetPath(); + NFile::NName::NormalizeDirPathPrefix(tempDirPrefix); + } + + CSelectedState srcSelState; + CSelectedState destSelState; + srcPanel.SaveSelectedState(srcSelState); + destPanel.SaveSelectedState(destSelState); + + HRESULT result; + if (useSrcPanel) + { + UString folder = useTemp ? tempDirPrefix : destPath; + result = srcPanel.CopyTo(indices, folder, move, true, 0); + if (result != S_OK) + { + disableTimerProcessing1.Restore(); + disableTimerProcessing2.Restore(); + // For Password: + srcPanel.SetFocusToList(); + if (result != E_ABORT) + srcPanel.MessageBoxError(result, L"Error"); + return; + } + } + + if (useDestPanel) + { + UStringVector filePaths; + UString folderPrefix; + if (useTemp) + folderPrefix = tempDirPrefix; + else + folderPrefix = srcPanel._currentFolderPrefix; + filePaths.Reserve(indices.Size()); + for (int i = 0; i < indices.Size(); i++) + filePaths.Add(srcPanel.GetItemRelPath(indices[i])); + + result = destPanel.CopyFrom(folderPrefix, filePaths, true, 0); + + if (result != S_OK) + { + disableTimerProcessing1.Restore(); + disableTimerProcessing2.Restore(); + // For Password: + srcPanel.SetFocusToList(); + if (result != E_ABORT) + srcPanel.MessageBoxError(result, L"Error"); + return; + } + } + + RefreshTitleAlways(); + if (copyToSame || move) + { + srcPanel.RefreshListCtrl(srcSelState); + } + if (!copyToSame) + { + destPanel.RefreshListCtrl(destSelState); + srcPanel.KillSelection(); + } + disableTimerProcessing1.Restore(); + disableTimerProcessing2.Restore(); + srcPanel.SetFocusToList(); +} + +void CApp::OnSetSameFolder(int srcPanelIndex) +{ + if (NumPanels <= 1) + return; + const CPanel &srcPanel = Panels[srcPanelIndex]; + CPanel &destPanel = Panels[1 - srcPanelIndex]; + destPanel.BindToPathAndRefresh(srcPanel._currentFolderPrefix); +} + +void CApp::OnSetSubFolder(int srcPanelIndex) +{ + if (NumPanels <= 1) + return; + const CPanel &srcPanel = Panels[srcPanelIndex]; + CPanel &destPanel = Panels[1 - srcPanelIndex]; + + int focusedItem = srcPanel._listView.GetFocusedItem(); + if (focusedItem < 0) + return; + int realIndex = srcPanel.GetRealItemIndex(focusedItem); + if (!srcPanel.IsItemFolder(realIndex)) + return; + + // destPanel.BindToFolder(srcPanel._currentFolderPrefix + srcPanel.GetItemName(realIndex) + WCHAR_PATH_SEPARATOR); + + CMyComPtr newFolder; + if (realIndex == kParentIndex) + { + if (srcPanel._folder->BindToParentFolder(&newFolder) != S_OK) + return; + } + else + { + if (srcPanel._folder->BindToFolder(realIndex, &newFolder) != S_OK) + return; + } + destPanel.CloseOpenFolders(); + destPanel._folder = newFolder; + destPanel.RefreshListCtrl(); +} + +/* +int CApp::GetFocusedPanelIndex() const +{ + return LastFocusedPanel; + HWND hwnd = ::GetFocus(); + for (;;) + { + if (hwnd == 0) + return 0; + for (int i = 0; i < kNumPanelsMax; i++) + { + if (PanelsCreated[i] && + ((HWND)Panels[i] == hwnd || Panels[i]._listView == hwnd)) + return i; + } + hwnd = GetParent(hwnd); + } +} +*/ + +static UString g_ToolTipBuffer; +static CSysString g_ToolTipBufferSys; + +void CApp::OnNotify(int /* ctrlID */, LPNMHDR pnmh) +{ + { + if (pnmh->code == TTN_GETDISPINFO) + { + LPNMTTDISPINFO info = (LPNMTTDISPINFO)pnmh; + info->hinst = 0; + g_ToolTipBuffer.Empty(); + SetButtonText((int)info->hdr.idFrom, g_ToolTipBuffer); + g_ToolTipBufferSys = GetSystemString(g_ToolTipBuffer); + info->lpszText = (LPTSTR)(LPCTSTR)g_ToolTipBufferSys; + return; + } + #ifndef _UNICODE + if (pnmh->code == TTN_GETDISPINFOW) + { + LPNMTTDISPINFOW info = (LPNMTTDISPINFOW)pnmh; + info->hinst = 0; + g_ToolTipBuffer.Empty(); + SetButtonText((int)info->hdr.idFrom, g_ToolTipBuffer); + info->lpszText = (LPWSTR)(LPCWSTR)g_ToolTipBuffer; + return; + } + #endif + } +} + +void CApp::RefreshTitle(bool always) +{ + UString path = GetFocusedPanel()._currentFolderPrefix; + if (path.IsEmpty()) + path += LangString(IDS_APP_TITLE, 0x03000000); + if (!always && path == PrevTitle) + return; + PrevTitle = path; + NWindows::MySetWindowText(_window, path); +} + +void CApp::RefreshTitle(int panelIndex, bool always) +{ + if (panelIndex != GetFocusedPanelIndex()) + return; + RefreshTitle(always); +} diff --git a/CPP/7zip/UI/FileManager/App.h b/CPP/7zip/UI/FileManager/App.h new file mode 100755 index 0000000..335d6eb --- /dev/null +++ b/CPP/7zip/UI/FileManager/App.h @@ -0,0 +1,315 @@ +// App.h + +#ifndef __APP_H +#define __APP_H + +#include "Windows/Control/CommandBar.h" +#include "Windows/Control/ImageList.h" + +#include "AppState.h" +#include "Panel.h" + +class CApp; + +extern CApp g_App; +extern HWND g_HWND; + +const int kNumPanelsMax = 2; + +extern bool g_IsSmallScreen; + +enum +{ + kAddCommand = kToolbarStartID, + kExtractCommand, + kTestCommand +}; + +class CPanelCallbackImp: public CPanelCallback +{ + CApp *_app; + int _index; +public: + void Init(CApp *app, int index) + { + _app = app; + _index = index; + } + virtual void OnTab(); + virtual void SetFocusToPath(int index); + virtual void OnCopy(bool move, bool copyToSame); + virtual void OnSetSameFolder(); + virtual void OnSetSubFolder(); + virtual void PanelWasFocused(); + virtual void DragBegin(); + virtual void DragEnd(); + virtual void RefreshTitle(bool always); +}; + +class CApp; + +class CDropTarget: + public IDropTarget, + public CMyUnknownImp +{ + CMyComPtr m_DataObject; + UStringVector m_SourcePaths; + int m_SelectionIndex; + bool m_DropIsAllowed; // = true, if data contain fillist + bool m_PanelDropIsAllowed; // = false, if current target_panel is source_panel. + // check it only if m_DropIsAllowed == true + int m_SubFolderIndex; + UString m_SubFolderName; + + CPanel *m_Panel; + bool m_IsAppTarget; // true, if we want to drop to app window (not to panel). + + bool m_SetPathIsOK; + + bool IsItSameDrive() const; + + void QueryGetData(IDataObject *dataObject); + bool IsFsFolderPath() const; + DWORD GetEffect(DWORD keyState, POINTL pt, DWORD allowedEffect); + void RemoveSelection(); + void PositionCursor(POINTL ptl); + UString GetTargetPath() const; + bool SetPath(bool enablePath) const; + bool SetPath(); + +public: + MY_UNKNOWN_IMP1_MT(IDropTarget) + STDMETHOD(DragEnter)(IDataObject * dataObject, DWORD keyState, POINTL pt, DWORD *effect); + STDMETHOD(DragOver)(DWORD keyState, POINTL pt, DWORD * effect); + STDMETHOD(DragLeave)(); + STDMETHOD(Drop)(IDataObject * dataObject, DWORD keyState, POINTL pt, DWORD *effect); + + CDropTarget(): + TargetPanelIndex(-1), + SrcPanelIndex(-1), + m_IsAppTarget(false), + m_Panel(0), + App(0), + m_PanelDropIsAllowed(false), + m_DropIsAllowed(false), + m_SelectionIndex(-1), + m_SubFolderIndex(-1), + m_SetPathIsOK(false) {} + + CApp *App; + int SrcPanelIndex; // index of D&D source_panel + int TargetPanelIndex; // what panel to use as target_panel of Application +}; + +class CApp +{ +public: + NWindows::CWindow _window; + bool ShowSystemMenu; + int NumPanels; + int LastFocusedPanel; + + bool ShowStandardToolbar; + bool ShowArchiveToolbar; + bool ShowButtonsLables; + bool LargeButtons; + + CAppState AppState; + CPanelCallbackImp m_PanelCallbackImp[kNumPanelsMax]; + CPanel Panels[kNumPanelsMax]; + bool PanelsCreated[kNumPanelsMax]; + + NWindows::NControl::CImageList _buttonsImageList; + + #ifdef UNDER_CE + NWindows::NControl::CCommandBar _commandBar; + #endif + NWindows::NControl::CToolBar _toolBar; + + CDropTarget *_dropTargetSpec; + CMyComPtr _dropTarget; + + CApp(): _window(0), NumPanels(2), LastFocusedPanel(0) {} + + void CreateDragTarget() + { + _dropTargetSpec = new CDropTarget(); + _dropTarget = _dropTargetSpec; + _dropTargetSpec->App = (this); + } + + void SetFocusedPanel(int index) + { + LastFocusedPanel = index; + _dropTargetSpec->TargetPanelIndex = LastFocusedPanel; + } + + void DragBegin(int panelIndex) + { + _dropTargetSpec->TargetPanelIndex = (NumPanels > 1) ? 1 - panelIndex : panelIndex; + _dropTargetSpec->SrcPanelIndex = panelIndex; + } + + void DragEnd() + { + _dropTargetSpec->TargetPanelIndex = LastFocusedPanel; + _dropTargetSpec->SrcPanelIndex = -1; + } + + + void OnCopy(bool move, bool copyToSame, int srcPanelIndex); + void OnSetSameFolder(int srcPanelIndex); + void OnSetSubFolder(int srcPanelIndex); + + HRESULT CreateOnePanel(int panelIndex, const UString &mainPath, const UString &arcFormat, bool &archiveIsOpened, bool &encrypted); + HRESULT Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool &archiveIsOpened, bool &encrypted); + void Read(); + void Save(); + void Release(); + + // void SetFocus(int panelIndex) { Panels[panelIndex].SetFocusToList(); } + void SetFocusToLastItem() { Panels[LastFocusedPanel].SetFocusToLastRememberedItem(); } + int GetFocusedPanelIndex() const { return LastFocusedPanel; } + bool IsPanelVisible(int index) const { return (NumPanels > 1 || index == LastFocusedPanel); } + CPanel &GetFocusedPanel() { return Panels[GetFocusedPanelIndex()]; } + + // File Menu + void OpenItem() { GetFocusedPanel().OpenSelectedItems(true); } + void OpenItemInside() { GetFocusedPanel().OpenFocusedItemAsInternal(); } + void OpenItemOutside() { GetFocusedPanel().OpenSelectedItems(false); } + void EditItem() { GetFocusedPanel().EditItem(); } + void Rename() { GetFocusedPanel().RenameFile(); } + void CopyTo() { OnCopy(false, false, GetFocusedPanelIndex()); } + void MoveTo() { OnCopy(true, false, GetFocusedPanelIndex()); } + void Delete(bool toRecycleBin) { GetFocusedPanel().DeleteItems(toRecycleBin); } + void CalculateCrc(); + void DiffFiles(); + void Split(); + void Combine(); + void Properties() { GetFocusedPanel().Properties(); } + void Comment() { GetFocusedPanel().ChangeComment(); } + + void CreateFolder() { GetFocusedPanel().CreateFolder(); } + void CreateFile() { GetFocusedPanel().CreateFile(); } + + // Edit + void EditCut() { GetFocusedPanel().EditCut(); } + void EditCopy() { GetFocusedPanel().EditCopy(); } + void EditPaste() { GetFocusedPanel().EditPaste(); } + + void SelectAll(bool selectMode) { GetFocusedPanel().SelectAll(selectMode); } + void InvertSelection() { GetFocusedPanel().InvertSelection(); } + void SelectSpec(bool selectMode) { GetFocusedPanel().SelectSpec(selectMode); } + void SelectByType(bool selectMode) { GetFocusedPanel().SelectByType(selectMode); } + + void RefreshStatusBar() { GetFocusedPanel().RefreshStatusBar(); } + + void SetListViewMode(UInt32 index) { GetFocusedPanel().SetListViewMode(index); } + UInt32 GetListViewMode() { return GetFocusedPanel().GetListViewMode(); } + PROPID GetSortID() { return GetFocusedPanel().GetSortID(); } + + void SortItemsWithPropID(PROPID propID) { GetFocusedPanel().SortItemsWithPropID(propID); } + + void OpenRootFolder() { GetFocusedPanel().OpenDrivesFolder(); } + void OpenParentFolder() { GetFocusedPanel().OpenParentFolder(); } + void FoldersHistory() { GetFocusedPanel().FoldersHistory(); } + void RefreshView() { GetFocusedPanel().OnReload(); } + void RefreshAllPanels() + { + for (int i = 0; i < NumPanels; i++) + { + int index = i; + if (NumPanels == 1) + index = LastFocusedPanel; + Panels[index].OnReload(); + } + } + + /* + void SysIconsWereChanged() + { + for (int i = 0; i < NumPanels; i++) + { + int index = i; + if (NumPanels == 1) + index = LastFocusedPanel; + Panels[index].SysIconsWereChanged(); + } + } + */ + + void SetListSettings(); + void SetShowSystemMenu(); + HRESULT SwitchOnOffOnePanel(); + bool GetFlatMode() { return Panels[LastFocusedPanel].GetFlatMode(); } + void ChangeFlatMode() { Panels[LastFocusedPanel].ChangeFlatMode(); } + + void OpenBookmark(int index) { GetFocusedPanel().OpenBookmark(index); } + void SetBookmark(int index) { GetFocusedPanel().SetBookmark(index); } + + void ReloadToolbars(); + void ReadToolbar() + { + UInt32 mask = ReadToolbarsMask(); + if (mask & ((UInt32)1 << 31)) + { + ShowButtonsLables = !g_IsSmallScreen; + LargeButtons = false; + ShowStandardToolbar = ShowArchiveToolbar = true; + } + else + { + ShowButtonsLables = ((mask & 1) != 0); + LargeButtons = ((mask & 2) != 0); + ShowStandardToolbar = ((mask & 4) != 0); + ShowArchiveToolbar = ((mask & 8) != 0); + } + } + void SaveToolbar() + { + UInt32 mask = 0; + if (ShowButtonsLables) mask |= 1; + if (LargeButtons) mask |= 2; + if (ShowStandardToolbar) mask |= 4; + if (ShowArchiveToolbar) mask |= 8; + SaveToolbarsMask(mask); + } + + void SaveToolbarChanges(); + + void SwitchStandardToolbar() + { + ShowStandardToolbar = !ShowStandardToolbar; + SaveToolbarChanges(); + } + void SwitchArchiveToolbar() + { + ShowArchiveToolbar = !ShowArchiveToolbar; + SaveToolbarChanges(); + } + void SwitchButtonsLables() + { + ShowButtonsLables = !ShowButtonsLables; + SaveToolbarChanges(); + } + void SwitchLargeButtons() + { + LargeButtons = !LargeButtons; + SaveToolbarChanges(); + } + + void AddToArchive() { GetFocusedPanel().AddToArchive(); } + void ExtractArchives() { GetFocusedPanel().ExtractArchives(); } + void TestArchives() { GetFocusedPanel().TestArchives(); } + + void OnNotify(int ctrlID, LPNMHDR pnmh); + + UString PrevTitle; + void RefreshTitle(bool always = false); + void RefreshTitleAlways() { RefreshTitle(true); } + void RefreshTitle(int panelIndex, bool always = false); + + void MoveSubWindows(); +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/AppState.h b/CPP/7zip/UI/FileManager/AppState.h new file mode 100755 index 0000000..3e86759 --- /dev/null +++ b/CPP/7zip/UI/FileManager/AppState.h @@ -0,0 +1,114 @@ +// AppState.h + +#ifndef __APP_STATE_H +#define __APP_STATE_H + +#include "Windows/Synchronization.h" + +#include "ViewSettings.h" + +void inline AddUniqueStringToHead(UStringVector &list, + const UString &string) +{ + for(int i = 0; i < list.Size();) + if (string.CompareNoCase(list[i]) == 0) + list.Delete(i); + else + i++; + list.Insert(0, string); +} + +class CFastFolders +{ + NWindows::NSynchronization::CCriticalSection _criticalSection; +public: + UStringVector Strings; + void SetString(int index, const UString &string) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); + while(Strings.Size() <= index) + Strings.Add(UString()); + Strings[index] = string; + } + UString GetString(int index) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); + if (index >= Strings.Size()) + return UString(); + return Strings[index]; + } + void Save() + { + NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); + SaveFastFolders(Strings); + } + void Read() + { + NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); + ReadFastFolders(Strings); + } +}; + +class CFolderHistory +{ + NWindows::NSynchronization::CCriticalSection _criticalSection; + UStringVector Strings; + void Normalize() + { + const int kMaxSize = 100; + if (Strings.Size() > kMaxSize) + Strings.Delete(kMaxSize, Strings.Size() - kMaxSize); + } + +public: + + void GetList(UStringVector &foldersHistory) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); + foldersHistory = Strings; + } + + void AddString(const UString &string) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); + AddUniqueStringToHead(Strings, string); + Normalize(); + } + + void RemoveAll() + { + NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); + Strings.Clear(); + } + + void Save() + { + NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); + SaveFolderHistory(Strings); + } + + void Read() + { + NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); + ReadFolderHistory(Strings); + Normalize(); + } +}; + +struct CAppState +{ + CFastFolders FastFolders; + CFolderHistory FolderHistory; + void Save() + { + FastFolders.Save(); + FolderHistory.Save(); + } + void Read() + { + FastFolders.Read(); + FolderHistory.Read(); + } +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.cpp b/CPP/7zip/UI/FileManager/BrowseDialog.cpp new file mode 100755 index 0000000..af9839b --- /dev/null +++ b/CPP/7zip/UI/FileManager/BrowseDialog.cpp @@ -0,0 +1,514 @@ +// BrowseDialog.cpp + +#include "StdAfx.h" + +#ifdef UNDER_CE + +#include "Common/IntToString.h" + +#include "Windows/PropVariantConversions.h" + +#include "BrowseDialog.h" +#include "LangUtils.h" +#include "PropertyNameRes.h" + +#ifndef _SFX +#include "RegistryUtils.h" +#endif + +using namespace NWindows; +using namespace NFile; +using namespace NFind; + +extern bool g_LVN_ITEMACTIVATE_Support; + +static const int kParentIndex = -1; + +#ifdef LANG +static CIDLangPair kIDLangPairs[] = +{ + { IDOK, 0x02000702 }, + { IDCANCEL, 0x02000710 } +}; +#endif + +static bool GetParentPath(const UString &path2, UString &dest, UString &focused) +{ + UString path = path2; + dest.Empty(); + if (path.IsEmpty()) + return false; + if (path.Back() == WCHAR_PATH_SEPARATOR) + path.DeleteBack(); + if (path.IsEmpty()) + return false; + int pos = path.ReverseFind(WCHAR_PATH_SEPARATOR); + if (pos < 0 || path.Back() == WCHAR_PATH_SEPARATOR) + return false; + focused = path.Mid(pos + 1); + dest = path.Left(pos + 1); + return true; +} + +bool CBrowseDialog::OnInit() +{ + #ifdef LANG + LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + #endif + if (!Title.IsEmpty()) + SetText(Title); + _list.Attach(GetItem(IDC_BROWSE_LIST)); + + #ifndef UNDER_CE + _list.SetUnicodeFormat(true); + #endif + + #ifndef _SFX + if (ReadSingleClick()) + _list.SetExtendedListViewStyle(LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT); + _showDots = ReadShowDots(); + #endif + + _list.SetImageList(GetSysImageList(true), LVSIL_SMALL); + _list.SetImageList(GetSysImageList(false), LVSIL_NORMAL); + + _list.InsertColumn(0, LangStringSpec(IDS_PROP_NAME, 0x02000204), 100); + _list.InsertColumn(1, LangStringSpec(IDS_PROP_MTIME, 0x0200020C), 100); + { + LV_COLUMNW column; + column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + column.fmt = LVCFMT_RIGHT; + column.iSubItem = 2; + UString s = LangStringSpec(IDS_PROP_SIZE, 0x02000207); + column.pszText = (wchar_t *)(const wchar_t *)s; + _list.InsertColumn(2, &column); + + // _list.InsertColumn(2, LangStringSpec(IDS_PROP_SIZE, 0x02000207), 100); + } + + _list.InsertItem(0, L"12345678901234567"); + _list.SetSubItem(0, 1, L"2009-09-09"); + _list.SetSubItem(0, 2, L"9999 MB"); + for (int i = 0; i < 3; i++) + _list.SetColumnWidthAuto(i); + _list.DeleteAllItems(); + + UString selectedName; + if (!FolderMode) + { + int pos = Path.ReverseFind(WCHAR_PATH_SEPARATOR); + if (pos >= 0 && Path.Back() != WCHAR_PATH_SEPARATOR) + { + selectedName = Path.Mid(pos + 1); + Path = Path.Left(pos + 1); + } + } + _ascending = true; + _sortIndex = 0; + + NormalizeSize(); + + while (Reload(Path, selectedName) != S_OK) + { + UString parent; + if (!GetParentPath(Path, parent, selectedName)) + break; + selectedName.Empty(); + Path = parent; + } + + return CModalDialog::OnInit(); +} + +bool CBrowseDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) +{ + int mx, my; + { + RECT rect; + GetClientRectOfItem(IDC_BROWSE_PARENT, rect); + mx = rect.left; + my = rect.top; + } + InvalidateRect(NULL); + + { + RECT rect; + GetClientRectOfItem(IDC_BROWSE_PATH, rect); + MoveItem(IDC_BROWSE_PATH, rect.left, rect.top, xSize - mx - rect.left, RECT_SIZE_Y(rect)); + } + + int bx1, bx2, by; + GetItemSizes(IDCANCEL, bx1, by); + GetItemSizes(IDOK, bx2, by); + int y = ySize - my - by; + int x = xSize - mx - bx1; + MoveItem(IDCANCEL, x, y, bx1, by); + MoveItem(IDOK, x - mx - bx2, y, bx2, by); + + { + RECT rect; + GetClientRectOfItem(IDC_BROWSE_LIST, rect); + _list.Move(rect.left, rect.top, xSize - mx - rect.left, y - my - rect.top); + } + return false; +} + +static UString ConvertSizeToStringShort(UInt64 value) +{ + wchar_t s[32]; + wchar_t c = L'\0', c2 = L'\0'; + if (value < (UInt64)10000) + { + c = L'\0'; + c2 = L'\0'; + } + else if (value < ((UInt64)10000 << 10)) + { + value >>= 10; + c = L'K'; + } + else if (value < ((UInt64)10000 << 20)) + { + value >>= 20; + c = L'M'; + } + else + { + value >>= 30; + c = L'G'; + } + ConvertUInt64ToString(value, s); + int p = MyStringLen(s); + if (c != 0) + s[p++] = L' '; + s[p++] = c; + s[p++] = c2; + s[p++] = L'\0'; + return s; +} + +int CBrowseDialog::CompareItems(LPARAM lParam1, LPARAM lParam2) +{ + if (lParam1 == kParentIndex) return -1; + if (lParam2 == kParentIndex) return 1; + const CFileInfoW &f1 = _files[(int)lParam1]; + const CFileInfoW &f2 = _files[(int)lParam2]; + + bool isDir1 = f1.IsDir(); + bool isDir2 = f2.IsDir(); + + if (isDir1 && !isDir2) return -1; + if (isDir2 && !isDir1) return 1; + + int result = 0; + switch(_sortIndex) + { + case 0: result = f1.Name.CompareNoCase(f2.Name); break; + case 1: result = CompareFileTime(&f1.MTime, &f2.MTime); break; + case 2: result = MyCompare(f1.Size, f2.Size); break; + } + return _ascending ? result: (-result); +} + +static int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) +{ + if (lpData == NULL) + return 0; + return ((CBrowseDialog*)lpData)->CompareItems(lParam1, lParam2); +} + +static HRESULT GetNormalizedError() +{ + HRESULT errorCode = GetLastError(); + return (errorCode == 0) ? 1 : errorCode; +} + +HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selectedName) +{ + CEnumeratorW enumerator(pathPrefix + L'*'); + CObjectVector files; + for (;;) + { + bool found; + CFileInfoW fi; + if (!enumerator.Next(fi, found)) + return GetNormalizedError(); + if (!found) + break; + files.Add(fi); + } + + Path = pathPrefix; + + _files = files; + + SetItemText(IDC_BROWSE_PATH, Path); + _list.SetRedraw(false); + _list.DeleteAllItems(); + + if (!Path.IsEmpty() && Path.Back() != WCHAR_PATH_SEPARATOR) + Path += WCHAR_PATH_SEPARATOR; + + LVITEMW item; + + int index = 0; + int cursorIndex = -1; + + #ifndef _SFX + if (_showDots) + { + UString itemName = L".."; + item.iItem = index; + if (selectedName.IsEmpty()) + cursorIndex = item.iItem; + 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, Path); + if (item.iImage < 0) + item.iImage = 0; + _list.InsertItem(&item); + _list.SetSubItem(index, subItem++, L""); + _list.SetSubItem(index, subItem++, L""); + index++; + } + #endif + + for (int i = 0; i < _files.Size(); i++) + { + const CFileInfoW &fi = _files[i]; + item.iItem = index; + if (fi.Name.CompareNoCase(selectedName) == 0) + cursorIndex = item.iItem; + item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; + int subItem = 0; + item.iSubItem = subItem++; + item.lParam = i; + item.pszText = (wchar_t *)(const wchar_t *)fi.Name; + item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, Path + fi.Name); + if (item.iImage < 0) + item.iImage = 0; + _list.InsertItem(&item); + { + FILETIME ft; + UString s; + if (FileTimeToLocalFileTime(&fi.MTime, &ft)) + s = ConvertFileTimeToString(ft, false, false); + _list.SetSubItem(index, subItem++, s); + } + { + UString s; + if (!fi.IsDir()) + s = ConvertSizeToStringShort(fi.Size); + _list.SetSubItem(index, subItem++, s); + } + index++; + } + + 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); + return S_OK; +} + +HRESULT CBrowseDialog::Reload() +{ + UString selectedCur; + int index = _list.GetNextSelectedItem(-1); + if (index >= 0) + { + int fileIndex = GetRealItemIndex(index); + if (fileIndex != kParentIndex) + selectedCur = _files[fileIndex].Name; + } + return Reload(Path, selectedCur); +} + +void CBrowseDialog::OpenParentFolder() +{ + UString parent, selected; + if (GetParentPath(Path, parent, selected)) + Reload(parent, selected); +} + +extern UString HResultToMessage(HRESULT errorCode); + +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(); + return true; + } + break; + case NM_DBLCLK: + case NM_RETURN: // probabably it's unused + if (!g_LVN_ITEMACTIVATE_Support) + { + OnItemEnter(); + return true; + } + 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: + { + LRESULT result; + bool boolResult = OnKeyDown(LPNMLVKEYDOWN(header), result); + return boolResult; + } + } + return false; +} + +bool CBrowseDialog::OnKeyDown(LPNMLVKEYDOWN keyDownInfo, LRESULT &result) +{ + bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0; + result = 0; + + switch(keyDownInfo->wVKey) + { + case VK_BACK: + OpenParentFolder(); + return true; + case 'R': + if (ctrl) + { + Reload(); + return true; + } + return false; + } + return false; +} + +bool CBrowseDialog::OnButtonClicked(int buttonID, HWND buttonHWND) +{ + switch(buttonID) + { + case IDC_BROWSE_PARENT: + OpenParentFolder(); + return true; + } + return CModalDialog::OnButtonClicked(buttonID, buttonHWND); +} + +void CBrowseDialog::ShowError(LPCWSTR s) { MessageBoxW(*this, s, L"7-Zip", MB_ICONERROR); } + +void CBrowseDialog::ShowSelectError() +{ + ShowError(FolderMode ? + L"You must select some folder": + L"You must select some file"); +} + +void CBrowseDialog::FinishOnOK() +{ + int index = _list.GetNextSelectedItem(-1); + if (index < 0) + { + if (!FolderMode) + { + ShowSelectError(); + return; + } + } + else + { + int fileIndex = GetRealItemIndex(index); + if (fileIndex == kParentIndex) + { + OpenParentFolder(); + return; + } + const CFileInfoW &file = _files[fileIndex]; + if (file.IsDir() != FolderMode) + { + ShowSelectError(); + return; + } + Path += file.Name; + } + End(IDOK); +} + +void CBrowseDialog::OnItemEnter() +{ + int index = _list.GetNextSelectedItem(-1); + if (index < 0) + return; + int fileIndex = GetRealItemIndex(index); + if (fileIndex == kParentIndex) + OpenParentFolder(); + else + { + const CFileInfoW &file = _files[fileIndex]; + if (!file.IsDir()) + { + if (!FolderMode) + FinishOnOK(); + else + ShowSelectError(); + return; + } + HRESULT res = Reload(Path + file.Name + WCHAR_PATH_SEPARATOR, L""); + if (res != S_OK) + ShowError(HResultToMessage(res)); + } +} + +void CBrowseDialog::OnOK() +{ + if (GetFocus() == _list) + { + OnItemEnter(); + return; + } + FinishOnOK(); +} + +static bool MyBrowse(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath, bool folderMode) +{ + CBrowseDialog dialog; + dialog.Title = title; + dialog.Path = initialFolder; + dialog.FolderMode = folderMode; + if (dialog.Create(owner) != IDOK) + return false; + resultPath = dialog.Path; + return true; +} + +bool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath) +{ + return MyBrowse(owner, title, initialFolder, resultPath, true); +} + +bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR initialFolder, LPCWSTR, UString &resultPath) +{ + return MyBrowse(owner, title, initialFolder, resultPath, false); +} + +#endif diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.h b/CPP/7zip/UI/FileManager/BrowseDialog.h new file mode 100755 index 0000000..624db1c --- /dev/null +++ b/CPP/7zip/UI/FileManager/BrowseDialog.h @@ -0,0 +1,77 @@ +// BrowseDialog.h + +#ifndef __BROWSE_DIALOG_H +#define __BROWSE_DIALOG_H + +#ifdef UNDER_CE + +#include "Windows/FileFind.h" + +#include "Windows/Control/Dialog.h" +#include "Windows/Control/ListView.h" + +#include "BrowseDialogRes.h" +#include "SysIconUtils.h" + +class CBrowseDialog: public NWindows::NControl::CModalDialog +{ + NWindows::NControl::CListView _list; + CObjectVector _files; + CExtToIconMap _extToIconMap; + int _sortIndex; + bool _ascending; + bool _showDots; + + virtual bool OnInit(); + virtual bool OnSize(WPARAM wParam, int xSize, int ySize); + virtual bool OnNotify(UINT controlID, LPNMHDR header); + virtual void OnOK(); + + virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); + virtual bool OnKeyDown(LPNMLVKEYDOWN keyDownInfo, LRESULT &result); + + void FinishOnOK(); + HRESULT Reload(const UString &pathPrefix, const UString &selectedName); + HRESULT Reload(); + void OpenParentFolder(); + + void OnItemEnter(); + + int GetRealItemIndex(int indexInListView) const + { + LPARAM param; + if (!_list.GetItemParam(indexInListView, param)) + return (int)-1; + return (int)param; + } + + void ShowError(LPCWSTR s); + void ShowSelectError(); +public: + UString Title; + UString Path; + bool FolderMode; + + CBrowseDialog(): FolderMode(true), _showDots(false) {} + + INT_PTR Create(HWND parent = 0) { return CModalDialog::Create(IDD_DIALOG_BROWSE, parent); } + int CompareItems(LPARAM lParam1, LPARAM lParam2); +}; + +bool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath); +bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR initialFolder, LPCWSTR s, UString &resultPath); + +#else + +#include "Windows/CommonDialog.h" +#include "Windows/Shell.h" + +#define MyBrowseForFolder(h, title, initialFolder, resultPath) \ + NShell::BrowseForFolder(h, title, initialFolder, resultPath) + +#define MyBrowseForFile(h, title, initialFolder, s, resultPath) \ + MyGetOpenFileName(h, title, initialFolder, s, resultPath) + +#endif + +#endif diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.rc b/CPP/7zip/UI/FileManager/BrowseDialog.rc new file mode 100755 index 0000000..e299ddc --- /dev/null +++ b/CPP/7zip/UI/FileManager/BrowseDialog.rc @@ -0,0 +1,17 @@ +#include "BrowseDialogRes.h" +#include "../../GuiCommon.rc" + +#define xc 180 +#define yc 160 + +IDD_DIALOG_BROWSE MY_RESIZE_DIALOG +CAPTION "7-Zip: Browse" +{ + LTEXT "", IDC_BROWSE_PATH, m + 20, m + 3, xc - 20, 8 + CONTROL "List1", IDC_BROWSE_LIST, "SysListView32", + LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_SINGLESEL | WS_BORDER | WS_TABSTOP, + m, m + 16, xc, yc - bys - m - 16 + PUSHBUTTON "OK", IDOK, bx2, by, bxs, bys + PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys + PUSHBUTTON "..", IDC_BROWSE_PARENT, m, m, 16, 14 +} diff --git a/CPP/7zip/UI/FileManager/BrowseDialogRes.h b/CPP/7zip/UI/FileManager/BrowseDialogRes.h new file mode 100755 index 0000000..17afcb1 --- /dev/null +++ b/CPP/7zip/UI/FileManager/BrowseDialogRes.h @@ -0,0 +1,4 @@ +#define IDD_DIALOG_BROWSE 509 +#define IDC_BROWSE_LIST 1000 +#define IDC_BROWSE_PATH 1001 +#define IDC_BROWSE_PARENT 1002 diff --git a/CPP/7zip/UI/FileManager/ClassDefs.cpp b/CPP/7zip/UI/FileManager/ClassDefs.cpp new file mode 100755 index 0000000..c1e06d9 --- /dev/null +++ b/CPP/7zip/UI/FileManager/ClassDefs.cpp @@ -0,0 +1,7 @@ +// ClassDefs.cpp + +#include "StdAfx.h" + +#include "Common/MyInitGuid.h" + +#include "../Agent/Agent.h" diff --git a/CPP/7zip/UI/FileManager/ComboDialog.cpp b/CPP/7zip/UI/FileManager/ComboDialog.cpp new file mode 100755 index 0000000..5195e61 --- /dev/null +++ b/CPP/7zip/UI/FileManager/ComboDialog.cpp @@ -0,0 +1,72 @@ +// ComboDialog.cpp + +#include "StdAfx.h" +#include "ComboDialog.h" + +#include "Windows/Control/Static.h" + +#ifdef LANG +#include "LangUtils.h" +#endif + +using namespace NWindows; + +#ifdef LANG +static CIDLangPair kIDLangPairs[] = +{ + { IDOK, 0x02000702 }, + { IDCANCEL, 0x02000710 } +}; +#endif + +bool CComboDialog::OnInit() +{ + #ifdef LANG + LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + #endif + _comboBox.Attach(GetItem(IDC_COMBO_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(IDC_COMBO_STATIC)); + staticContol.SetText(Static); + _comboBox.SetText(Value); + for(int i = 0; i < Strings.Size(); i++) + _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/CPP/7zip/UI/FileManager/ComboDialog.h b/CPP/7zip/UI/FileManager/ComboDialog.h new file mode 100755 index 0000000..5c30b08 --- /dev/null +++ b/CPP/7zip/UI/FileManager/ComboDialog.h @@ -0,0 +1,27 @@ +// 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_DIALOG_COMBO, parentWindow); } +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/ComboDialog.rc b/CPP/7zip/UI/FileManager/ComboDialog.rc new file mode 100755 index 0000000..7016710 --- /dev/null +++ b/CPP/7zip/UI/FileManager/ComboDialog.rc @@ -0,0 +1,13 @@ +#include "ComboDialogRes.h" +#include "../../GuiCommon.rc" + +#define xc 240 +#define yc 64 + +IDD_DIALOG_COMBO MY_RESIZE_DIALOG +CAPTION "Combo" +{ + LTEXT "", IDC_COMBO_STATIC, m, m, xc, 8 + COMBOBOX IDC_COMBO_COMBO, m, 20, xc, 65, MY_COMBO_WITH_EDIT + OK_CANCEL +} diff --git a/CPP/7zip/UI/FileManager/ComboDialogRes.h b/CPP/7zip/UI/FileManager/ComboDialogRes.h new file mode 100755 index 0000000..d887d67 --- /dev/null +++ b/CPP/7zip/UI/FileManager/ComboDialogRes.h @@ -0,0 +1,4 @@ +#define IDD_DIALOG_COMBO 505 + +#define IDC_COMBO_STATIC 1000 +#define IDC_COMBO_COMBO 1001 diff --git a/CPP/7zip/UI/FileManager/Copy.bmp b/CPP/7zip/UI/FileManager/Copy.bmp new file mode 100755 index 0000000000000000000000000000000000000000..0f28a3242313b2fce4f361f391f267e69917fe86 GIT binary patch literal 982 zcmd6kF%p6>5JlI~Su1a0Vd)v{y#p0TFjZ!9v>bs-t33<;1cEVqDjP#~32*<0O}O2k zd&%R0d_i0hXT(kp$Rgcb&ktWIh+s+x(+wF*M35LG3S*u!j%kI!l@OBs#W-$sA)Xg> z!=N2EXwMDWbA$HW0A3lKbKYLa4*X*naKzq_L=s;NLtZB|jnY!fi=pM^3oG7DhqU4+ x&S$x``dMzNf2;Z@zd*5rBCpHf-utS4qLx;Pe!`&del+{HGi%}fL z2&w%AcSDEgBemt7ue&Lb*B@JhpQknGRpmg9L9Z&QHdtpgR|dtsOU2HH_jhpI48@(n bTO&hwu^~4yge}au?;+d}MMD(F`i1-e?xnGF literal 0 HcmV?d00001 diff --git a/CPP/7zip/UI/FileManager/Delete2.bmp b/CPP/7zip/UI/FileManager/Delete2.bmp new file mode 100755 index 0000000000000000000000000000000000000000..60e08c6a7229f62f797efbf158f840552df93d2f GIT binary patch literal 406 zcmb7;u?@m75JfK%Qba*dNy!}a>_SCn$s?pf@-`kJ3wRdu{*Qx1g}C@$&i~(Ca=X8# za6I9aJdd2>VErptd) + { + dest->ptd = (DVTARGETDEVICE*)CoTaskMemAlloc(sizeof(DVTARGETDEVICE)); + *(dest->ptd) = *(src->ptd); + } +} + +CEnumFormatEtc::CEnumFormatEtc(const FORMATETC *pFormatEtc, ULONG numFormats) +{ + m_RefCount = 1; + m_Index = 0; + m_NumFormats = 0; + m_Formats = new FORMATETC[numFormats]; + if(m_Formats) + { + m_NumFormats = numFormats; + for(ULONG i = 0; i < numFormats; i++) + DeepCopyFormatEtc(&m_Formats[i], &pFormatEtc[i]); + } +} + +CEnumFormatEtc::~CEnumFormatEtc() +{ + if(m_Formats) + { + for(ULONG i = 0; i < m_NumFormats; i++) + if(m_Formats[i].ptd) + CoTaskMemFree(m_Formats[i].ptd); + delete[]m_Formats; + } +} + +STDMETHODIMP CEnumFormatEtc::Next(ULONG celt, FORMATETC *pFormatEtc, ULONG *pceltFetched) +{ + ULONG copied = 0; + if(celt == 0 || pFormatEtc == 0) + return E_INVALIDARG; + while(m_Index < m_NumFormats && copied < celt) + { + DeepCopyFormatEtc(&pFormatEtc[copied], &m_Formats[m_Index]); + copied++; + m_Index++; + } + if(pceltFetched != 0) + *pceltFetched = copied; + return (copied == celt) ? S_OK : S_FALSE; +} + +STDMETHODIMP CEnumFormatEtc::Skip(ULONG celt) +{ + m_Index += celt; + return (m_Index <= m_NumFormats) ? S_OK : S_FALSE; +} + +STDMETHODIMP CEnumFormatEtc::Reset(void) +{ + m_Index = 0; + return S_OK; +} + +STDMETHODIMP CEnumFormatEtc::Clone(IEnumFORMATETC ** ppEnumFormatEtc) +{ + HRESULT hResult = CreateEnumFormatEtc(m_NumFormats, m_Formats, ppEnumFormatEtc); + if(hResult == S_OK) + ((CEnumFormatEtc *)*ppEnumFormatEtc)->m_Index = m_Index; + return hResult; +} + +// replacement for SHCreateStdEnumFmtEtc +HRESULT CreateEnumFormatEtc(UINT numFormats, const FORMATETC *formats, IEnumFORMATETC **enumFormat) +{ + if(numFormats == 0 || formats == 0 || enumFormat == 0) + return E_INVALIDARG; + *enumFormat = new CEnumFormatEtc(formats, numFormats); + return (*enumFormat) ? S_OK : E_OUTOFMEMORY; +} diff --git a/CPP/7zip/UI/FileManager/EnumFormatEtc.h b/CPP/7zip/UI/FileManager/EnumFormatEtc.h new file mode 100755 index 0000000..f1aed49 --- /dev/null +++ b/CPP/7zip/UI/FileManager/EnumFormatEtc.h @@ -0,0 +1,10 @@ +// EnumFormatEtc.h + +#ifndef __ENUMFORMATETC_H +#define __ENUMFORMATETC_H + +#include + +HRESULT CreateEnumFormatEtc(UINT numFormats, const FORMATETC *formats, IEnumFORMATETC **enumFormat); + +#endif diff --git a/CPP/7zip/UI/FileManager/Extract.bmp b/CPP/7zip/UI/FileManager/Extract.bmp new file mode 100755 index 0000000000000000000000000000000000000000..0aeba923800097425a9570ea3848831665cd013e GIT binary patch literal 982 zcmZ?ry~fM{24z4}1BeZPSOtg~8CZZM149B-9?U@@8WG9-ggDO`ByeEpi6eOm$b@@$lz}@0 E00G|81poj5 literal 0 HcmV?d00001 diff --git a/CPP/7zip/UI/FileManager/Extract2.bmp b/CPP/7zip/UI/FileManager/Extract2.bmp new file mode 100755 index 0000000000000000000000000000000000000000..a7e5775386d993d44ff63c646c971be49d31e9e6 GIT binary patch literal 406 zcmZ?royN!j24z4}1BfM{n2~`6EUo~R2Xjz}1_lNoVrXc9P(TvM1mXsU0|yQOCH{jE q!~g#v77zm=NC-&Wr8y{vfxCAv04)atb|Cu<6p+J)nZrwS*8>24L-eu$ literal 0 HcmV?d00001 diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.cpp b/CPP/7zip/UI/FileManager/ExtractCallback.cpp new file mode 100755 index 0000000..b786d2f --- /dev/null +++ b/CPP/7zip/UI/FileManager/ExtractCallback.cpp @@ -0,0 +1,453 @@ +// ExtractCallback.cpp + +#include "StdAfx.h" + +#include "Windows/Error.h" +#include "Windows/FileDir.h" +#include "Windows/FileFind.h" + +#include "../../Common/FilePathAutoRename.h" + +#include "../GUI/ExtractRes.h" + +#include "ExtractCallback.h" +#include "FormatUtils.h" +#include "OverwriteDialog.h" +#ifndef _NO_CRYPTO +#include "PasswordDialog.h" +#endif + +using namespace NWindows; +using namespace NFile; +using namespace NFind; + +CExtractCallbackImp::~CExtractCallbackImp() {} + +void CExtractCallbackImp::Init() +{ + NumArchiveErrors = 0; + ThereAreMessageErrors = false; + #ifndef _SFX + NumFolders = NumFiles = 0; + NeedAddFile = false; + #endif +} + +void CExtractCallbackImp::AddErrorMessage(LPCWSTR message) +{ + ThereAreMessageErrors = true; + ProgressDialog->Sync.AddErrorMessage(message); +} + +STDMETHODIMP CExtractCallbackImp::SetNumFiles(UInt64 + #ifndef _SFX + numFiles + #endif + ) +{ + #ifndef _SFX + ProgressDialog->Sync.SetNumFilesTotal(numFiles); + #endif + return S_OK; +} + +STDMETHODIMP CExtractCallbackImp::SetTotal(UInt64 total) +{ + ProgressDialog->Sync.SetProgress(total, 0); + return S_OK; +} + +STDMETHODIMP CExtractCallbackImp::SetCompleted(const UInt64 *value) +{ + RINOK(ProgressDialog->Sync.ProcessStopAndPause()); + if (value != NULL) + ProgressDialog->Sync.SetPos(*value); + return S_OK; +} + +HRESULT CExtractCallbackImp::Open_CheckBreak() +{ + return ProgressDialog->Sync.ProcessStopAndPause(); +} + +HRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */) +{ + // if (numFiles != NULL) ProgressDialog->Sync.SetNumFilesTotal(*numFiles); + return S_OK; +} + +HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */) +{ + RINOK(ProgressDialog->Sync.ProcessStopAndPause()); + // if (numFiles != NULL) ProgressDialog->Sync.SetNumFilesCur(*numFiles); + return S_OK; +} + +#ifndef _NO_CRYPTO + +HRESULT CExtractCallbackImp::Open_CryptoGetTextPassword(BSTR *password) +{ + return CryptoGetTextPassword(password); +} + +HRESULT CExtractCallbackImp::Open_GetPasswordIfAny(UString &password) +{ + if (PasswordIsDefined) + password = Password; + return S_OK; +} + +bool CExtractCallbackImp::Open_WasPasswordAsked() +{ + return PasswordWasAsked; +} + +void CExtractCallbackImp::Open_ClearPasswordWasAskedFlag() +{ + PasswordWasAsked = false; +} + +#endif + + +#ifndef _SFX +STDMETHODIMP CExtractCallbackImp::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) +{ + ProgressDialog->Sync.SetRatioInfo(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 IDC_BUTTON_OVERWRITE_YES_TO_ALL: *answer = NOverwriteAnswer::kYesToAll; break; + case IDC_BUTTON_OVERWRITE_NO_TO_ALL: *answer = NOverwriteAnswer::kNoToAll; break; + case IDC_BUTTON_OVERWRITE_AUTO_RENAME: *answer = NOverwriteAnswer::kAutoRename; break; + default: return E_FAIL; + } + return S_OK; +} + + +STDMETHODIMP CExtractCallbackImp::PrepareOperation(const wchar_t *name, bool isFolder, Int32 /* askExtractMode */, const UInt64 * /* position */) +{ + _isFolder = isFolder; + return SetCurrentFilePath2(name); +} + +STDMETHODIMP CExtractCallbackImp::MessageError(const wchar_t *message) +{ + AddErrorMessage(message); + return S_OK; +} + +STDMETHODIMP CExtractCallbackImp::ShowMessage(const wchar_t *message) +{ + AddErrorMessage(message); + return S_OK; +} + +STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 operationResult, bool encrypted) +{ + switch(operationResult) + { + case NArchive::NExtract::NOperationResult::kOK: + break; + default: + { + UINT messageID; + UInt32 langID; + switch(operationResult) + { + case NArchive::NExtract::NOperationResult::kUnSupportedMethod: + messageID = IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_UNSUPPORTED_METHOD; + langID = 0x02000A91; + break; + case NArchive::NExtract::NOperationResult::kDataError: + messageID = encrypted ? + IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED: + IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_DATA_ERROR; + langID = encrypted ? 0x02000A94 : 0x02000A92; + break; + case NArchive::NExtract::NOperationResult::kCRCError: + messageID = encrypted ? + IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CRC_ENCRYPTED: + IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CRC; + langID = encrypted ? 0x02000A95 : 0x02000A93; + break; + default: + return E_FAIL; + } + if (_needWriteArchivePath) + { + if (!_currentArchivePath.IsEmpty()) + AddErrorMessage(_currentArchivePath); + _needWriteArchivePath = false; + } + AddErrorMessage( + MyFormatNew(messageID, + #ifdef LANG + langID, + #endif + _currentFilePath)); + } + } + #ifndef _SFX + if (_isFolder) + NumFolders++; + else + NumFiles++; + ProgressDialog->Sync.SetNumFilesCur(NumFiles); + #endif + return S_OK; +} + +//////////////////////////////////////// +// IExtractCallbackUI + +HRESULT CExtractCallbackImp::BeforeOpen(const wchar_t *name) +{ + #ifndef _SFX + ProgressDialog->Sync.SetTitleFileName(name); + #endif + _currentArchivePath = name; + return S_OK; +} + +HRESULT CExtractCallbackImp::SetCurrentFilePath2(const wchar_t *path) +{ + _currentFilePath = path; + #ifndef _SFX + ProgressDialog->Sync.SetCurrentFileName(path); + #endif + return S_OK; +} + +HRESULT CExtractCallbackImp::SetCurrentFilePath(const wchar_t *path) +{ + #ifndef _SFX + if (NeedAddFile) + NumFiles++; + NeedAddFile = true; + ProgressDialog->Sync.SetNumFilesCur(NumFiles); + #endif + return SetCurrentFilePath2(path); +} + +HRESULT CExtractCallbackImp::OpenResult(const wchar_t *name, HRESULT result, bool encrypted) +{ + if (result != S_OK) + { + UString message; + if (result == S_FALSE) + { + message = MyFormatNew(encrypted ? IDS_CANT_OPEN_ENCRYPTED_ARCHIVE : IDS_CANT_OPEN_ARCHIVE, + #ifdef LANG + (encrypted ? 0x0200060A : 0x02000609), + #endif + name); + } + else + { + message = name; + message += L": "; + UString message2; + if (result == E_OUTOFMEMORY) + message2 = + #ifdef LANG + LangString(IDS_MEM_ERROR, 0x0200060B); + #else + MyLoadStringW(IDS_MEM_ERROR); + #endif + else + NError::MyFormatMessage(result, message2); + message += message2; + } + MessageError(message); + NumArchiveErrors++; + } + _currentArchivePath = name; + _needWriteArchivePath = true; + return S_OK; +} + +HRESULT CExtractCallbackImp::ThereAreNoFiles() +{ + return S_OK; +} + +HRESULT CExtractCallbackImp::ExtractResult(HRESULT result) +{ + if (result == S_OK) + return result; + NumArchiveErrors++; + if (result == E_ABORT || result == ERROR_DISK_FULL) + return result; + MessageError(_currentFilePath); + MessageError(NError::MyFormatMessageW(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; + ProgressDialog->WaitCreating(); + if (dialog.Create(*ProgressDialog) == IDCANCEL) + return E_ABORT; + Password = dialog.Password; + PasswordIsDefined = true; + } + return StringToBstr(Password, password); +} + +#endif + +// IExtractCallBack3 +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); + + UString destPathSpec = destPath; + UString destPathSys = destPathSpec; + bool srcIsFolderSpec = IntToBool(srcIsFolder); + CFileInfoW destFileInfo; + if (destFileInfo.Find(destPathSys)) + { + if (srcIsFolderSpec) + { + if (!destFileInfo.IsDir()) + { + UString message = UString(L"can not replace file \'") + + destPathSpec + + UString(L"\' with folder with same name"); + RINOK(MessageError(message)); + return E_ABORT; + } + *writeAnswer = BoolToInt(false); + return S_OK; + } + if (destFileInfo.IsDir()) + { + UString message = UString(L"can not replace folder \'") + + destPathSpec + + UString(L"\' with file with same name"); + RINOK(MessageError(message)); + return E_FAIL; + } + + switch(OverwriteMode) + { + case NExtract::NOverwriteMode::kSkipExisting: + return S_OK; + case NExtract::NOverwriteMode::kAskBefore: + { + Int32 overwiteResult; + RINOK(AskOverwrite( + destPathSpec, + &destFileInfo.MTime, &destFileInfo.Size, + srcPath, + srcTime, srcSize, + &overwiteResult)); + switch(overwiteResult) + { + case NOverwriteAnswer::kCancel: + return E_ABORT; + case NOverwriteAnswer::kNo: + return S_OK; + case NOverwriteAnswer::kNoToAll: + OverwriteMode = NExtract::NOverwriteMode::kSkipExisting; + return S_OK; + case NOverwriteAnswer::kYesToAll: + OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; + break; + case NOverwriteAnswer::kYes: + break; + case NOverwriteAnswer::kAutoRename: + OverwriteMode = NExtract::NOverwriteMode::kAutoRename; + break; + default: + return E_FAIL; + } + } + } + if (OverwriteMode == NExtract::NOverwriteMode::kAutoRename) + { + if (!AutoRenamePath(destPathSys)) + { + UString message = UString(L"can not create name of file ") + + destPathSys; + RINOK(MessageError(message)); + return E_ABORT; + } + destPathResultTemp = destPathSys; + } + else + if (!NFile::NDirectory::DeleteFileAlways(destPathSys)) + { + UString message = UString(L"can not delete output file ") + + destPathSys; + RINOK(MessageError(message)); + return E_ABORT; + } + } + *writeAnswer = BoolToInt(true); + return StringToBstr(destPathResultTemp, destPathResult); +} diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.h b/CPP/7zip/UI/FileManager/ExtractCallback.h new file mode 100755 index 0000000..bb13d98 --- /dev/null +++ b/CPP/7zip/UI/FileManager/ExtractCallback.h @@ -0,0 +1,138 @@ +// ExtractCallback.h + +#ifndef __EXTRACT_CALLBACK_H +#define __EXTRACT_CALLBACK_H + +#include "Common/MyCom.h" + +#include "Windows/ResourceString.h" + +#include "../Agent/IFolderArchive.h" +#include "../Common/ArchiveOpenCallback.h" + +#ifndef _NO_CRYPTO +#include "../../IPassword.h" +#endif + +#include "IFolder.h" + +#include "ProgressDialog2.h" + +#ifdef LANG +#include "LangUtils.h" +#endif + +class CExtractCallbackImp: + public IExtractCallbackUI, + public IOpenCallbackUI, + public IFolderOperationsExtractCallback, + // public IFolderArchiveExtractCallback, // mkultiple from IProgress + #ifndef _SFX + public ICompressProgressInfo, + #endif + #ifndef _NO_CRYPTO + public ICryptoGetTextPassword, + #endif + public CMyUnknownImp +{ +public: + MY_QUERYINTERFACE_BEGIN2(IFolderOperationsExtractCallback) + MY_QUERYINTERFACE_ENTRY(IFolderArchiveExtractCallback) + #ifndef _SFX + MY_QUERYINTERFACE_ENTRY(ICompressProgressInfo) + #endif + #ifndef _NO_CRYPTO + MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword) + #endif + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + #ifndef _SFX + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); + #endif + + INTERFACE_IProgress(;) + INTERFACE_IOpenCallbackUI(;) + + // IFolderArchiveExtractCallback + // STDMETHOD(SetTotalFiles)(UInt64 total); + // STDMETHOD(SetCompletedFiles)(const UInt64 *value); + STDMETHOD(AskOverwrite)( + const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, + const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, + Int32 *answer); + STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position); + + STDMETHOD(MessageError)(const wchar_t *message); + STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted); + + // IExtractCallbackUI + + HRESULT BeforeOpen(const wchar_t *name); + HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted); + HRESULT ThereAreNoFiles(); + HRESULT ExtractResult(HRESULT result); + + #ifndef _NO_CRYPTO + HRESULT SetPassword(const UString &password); + #endif + + // 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); + + // ICryptoGetTextPassword + #ifndef _NO_CRYPTO + STDMETHOD(CryptoGetTextPassword)(BSTR *password); + #endif + +private: + UString _currentArchivePath; + bool _needWriteArchivePath; + + UString _currentFilePath; + bool _isFolder; + + HRESULT SetCurrentFilePath2(const wchar_t *filePath); + void AddErrorMessage(LPCWSTR message); +public: + 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 + + CExtractCallbackImp(): + #ifndef _NO_CRYPTO + PasswordIsDefined(false), + PasswordWasAsked(false), + #endif + OverwriteMode(NExtract::NOverwriteMode::kAskBefore) + {} + + ~CExtractCallbackImp(); + void Init(); + + bool IsOK() const { return NumArchiveErrors == 0 && !ThereAreMessageErrors; } +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/FM.cpp b/CPP/7zip/UI/FileManager/FM.cpp new file mode 100755 index 0000000..279c4a4 --- /dev/null +++ b/CPP/7zip/UI/FileManager/FM.cpp @@ -0,0 +1,855 @@ +// FM.cpp + +#include "StdAfx.h" + +#include "../../../../C/Alloc.h" + +#include "Windows/Error.h" +#include "Windows/MemoryLock.h" +#include "Windows/NtCheck.h" + +#ifndef UNDER_CE +#include "Windows/Security.h" +#endif + +#include "../GUI/ExtractRes.h" + +#include "resource.h" + +#include "App.h" +#include "FormatUtils.h" +#include "LangUtils.h" +#include "MyLoadMenu.h" +#include "Panel.h" +#include "RegistryUtils.h" +#include "StringUtils.h" +#include "ViewSettings.h" + +using namespace NWindows; +using namespace NFile; +using namespace NFind; + +#define MAX_LOADSTRING 100 + +#define MENU_HEIGHT 26 + +HINSTANCE g_hInstance; +HWND g_HWND; +bool g_OpenArchive = false; +static UString g_MainPath; +static UString g_ArcFormat; +static bool g_Maximized = false; + +#ifndef UNDER_CE +DWORD g_ComCtl32Version; +#endif + +bool g_IsSmallScreen = false; + +bool g_LVN_ITEMACTIVATE_Support = true; +// LVN_ITEMACTIVATE replaces both NM_DBLCLK & NM_RETURN +// Windows 2000 +// NT/98 + IE 3 (g_ComCtl32Version >= 4.70) + + +const int kNumDefaultPanels = 1; + +const int kSplitterWidth = 4; +int kSplitterRateMax = 1 << 16; +int kPanelSizeMin = 120; + +// bool OnMenuCommand(HWND hWnd, int id); + +class CSplitterPos +{ + int _ratio; // 10000 is max + int _pos; + int _fullWidth; + void SetRatioFromPos(HWND hWnd) + { _ratio = (_pos + kSplitterWidth / 2) * kSplitterRateMax / + MyMax(GetWidth(hWnd), 1); } +public: + int GetPos() const + { return _pos; } + int GetWidth(HWND hWnd) const + { + RECT rect; + ::GetClientRect(hWnd, &rect); + return rect.right; + } + void SetRatio(HWND hWnd, int aRatio) + { + _ratio = aRatio; + SetPosFromRatio(hWnd); + } + void SetPosPure(HWND hWnd, int pos) + { + int posMax = GetWidth(hWnd) - kSplitterWidth; + if (posMax < kPanelSizeMin * 2) + pos = posMax / 2; + else + { + if (pos > posMax - kPanelSizeMin) + pos = posMax - kPanelSizeMin; + else if (pos < kPanelSizeMin) + pos = kPanelSizeMin; + } + _pos = pos; + } + void SetPos(HWND hWnd, int pos) + { + _fullWidth = GetWidth(hWnd); + SetPosPure(hWnd, pos); + SetRatioFromPos(hWnd); + } + void SetPosFromRatio(HWND hWnd) + { + int fullWidth = GetWidth(hWnd); + if (_fullWidth != fullWidth && fullWidth != 0) + { + _fullWidth = fullWidth; + SetPosPure(hWnd, GetWidth(hWnd) * _ratio / kSplitterRateMax - kSplitterWidth / 2); + } + } +}; + +static bool g_CanChangeSplitter = false; +static UINT32 g_SplitterPos = 0; +static CSplitterPos g_Splitter; +static bool g_PanelsInfoDefined = false; + +static int g_StartCaptureMousePos; +static int g_StartCaptureSplitterPos; + +CApp g_App; + +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + +const wchar_t *kWindowClass = L"FM"; + +#ifdef UNDER_CE +#define WS_OVERLAPPEDWINDOW ( \ + WS_OVERLAPPED | \ + WS_CAPTION | \ + WS_SYSMENU | \ + WS_THICKFRAME | \ + WS_MINIMIZEBOX | \ + WS_MAXIMIZEBOX) +#endif + +// FUNCTION: InitInstance(HANDLE, int) +BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) +{ + CWindow wnd; + + g_hInstance = hInstance; + + ReloadLangSmart(); + + // LoadString(hInstance, IDS_CLASS, windowClass, MAX_LOADSTRING); + + // LoadString(hInstance, IDS_APP_TITLE, title, MAX_LOADSTRING); + UString title = LangString(IDS_APP_TITLE, 0x03000000); + + /* + //If it is already running, then focus on the window + hWnd = FindWindow(windowClass, title); + if (hWnd) + { + SetForegroundWindow ((HWND) (((DWORD)hWnd) | 0x01)); + return 0; + } + */ + + WNDCLASSW wc; + + // wc.style = CS_HREDRAW | CS_VREDRAW; + wc.style = 0; + wc.lpfnWndProc = (WNDPROC) WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON)); + + // wc.hCursor = LoadCursor (NULL, IDC_ARROW); + wc.hCursor = ::LoadCursor(0, IDC_SIZEWE); + // wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); + wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); + + wc.lpszMenuName = + #ifdef UNDER_CE + 0 + #else + MAKEINTRESOURCEW(IDM_MENU) + #endif + ; + + wc.lpszClassName = kWindowClass; + + MyRegisterClass(&wc); + + // RECT rect; + // GetClientRect(hWnd, &rect); + + DWORD style = WS_OVERLAPPEDWINDOW; + // DWORD style = 0; + + RECT rect; + bool maximized = false; + int x , y, xSize, ySize; + x = y = xSize = ySize = CW_USEDEFAULT; + bool windowPosIsRead = ReadWindowSize(rect, maximized); + + if (windowPosIsRead) + { + // x = rect.left; + // y = rect.top; + xSize = rect.right - rect.left; + ySize = rect.bottom - rect.top; + } + + UINT32 numPanels, currentPanel; + g_PanelsInfoDefined = ReadPanelsInfo(numPanels, currentPanel, g_SplitterPos); + if (g_PanelsInfoDefined) + { + if (numPanels < 1 || numPanels > 2) + numPanels = kNumDefaultPanels; + if (currentPanel >= 2) + currentPanel = 0; + } + else + { + numPanels = kNumDefaultPanels; + currentPanel = 0; + } + g_App.NumPanels = numPanels; + g_App.LastFocusedPanel = currentPanel; + + if (!wnd.Create(kWindowClass, title, style, + x, y, xSize, ySize, NULL, NULL, hInstance, NULL)) + return FALSE; + + if (nCmdShow == SW_SHOWNORMAL || + nCmdShow == SW_SHOW + #ifndef UNDER_CE + || nCmdShow == SW_SHOWDEFAULT + #endif + ) + { + if (maximized) + nCmdShow = SW_SHOWMAXIMIZED; + else + nCmdShow = SW_SHOWNORMAL; + } + + if (nCmdShow == SW_SHOWMAXIMIZED) + g_Maximized = true; + + #ifndef UNDER_CE + WINDOWPLACEMENT placement; + placement.length = sizeof(placement); + if (wnd.GetPlacement(&placement)) + { + if (windowPosIsRead) + placement.rcNormalPosition = rect; + placement.showCmd = nCmdShow; + wnd.SetPlacement(&placement); + } + else + #endif + wnd.Show(nCmdShow); + + return TRUE; +} + +/* +static void GetCommands(const UString &aCommandLine, UString &aCommands) +{ + UString aProgramName; + aCommands.Empty(); + bool aQuoteMode = false; + for (int i = 0; i < aCommandLine.Length(); i++) + { + wchar_t aChar = aCommandLine[i]; + if (aChar == L'\"') + aQuoteMode = !aQuoteMode; + else if (aChar == L' ' && !aQuoteMode) + { + if (!aQuoteMode) + { + i++; + break; + } + } + else + aProgramName += aChar; + } + aCommands = aCommandLine.Mid(i); +} +*/ + +#ifndef UNDER_CE +static DWORD GetDllVersion(LPCTSTR lpszDllName) +{ + HINSTANCE hinstDll; + DWORD dwVersion = 0; + hinstDll = LoadLibrary(lpszDllName); + if (hinstDll) + { + DLLGETVERSIONPROC pDllGetVersion; + pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hinstDll, "DllGetVersion"); + + /*Because some DLLs might not implement this function, you + must test for it explicitly. Depending on the particular + DLL, the lack of a DllGetVersion function can be a useful + indicator of the version. + */ + if (pDllGetVersion) + { + DLLVERSIONINFO dvi; + HRESULT hr; + + ZeroMemory(&dvi, sizeof(dvi)); + dvi.cbSize = sizeof(dvi); + + hr = (*pDllGetVersion)(&dvi); + + if (SUCCEEDED(hr)) + { + dwVersion = MAKELONG(dvi.dwMinorVersion, dvi.dwMajorVersion); + } + } + FreeLibrary(hinstDll); + } + return dwVersion; +} +#endif + +/* +#ifndef _WIN64 +typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); + +static bool IsWow64() +{ + LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress( + GetModuleHandle("kernel32"), "IsWow64Process"); + if (fnIsWow64Process == NULL) + return false; + BOOL isWow; + if (!fnIsWow64Process(GetCurrentProcess(),&isWow)) + return false; + return isWow != FALSE; +} +#endif +*/ + +bool IsLargePageSupported() +{ + #ifdef _WIN64 + return true; + #else + OSVERSIONINFO versionInfo; + versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); + if (!::GetVersionEx(&versionInfo)) + return false; + if (versionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || versionInfo.dwMajorVersion < 5) + return false; + if (versionInfo.dwMajorVersion > 5) + return true; + if (versionInfo.dwMinorVersion < 1) + return false; + if (versionInfo.dwMinorVersion > 1) + return true; + // return IsWow64(); + return false; + #endif +} + +#ifndef UNDER_CE +static void SetMemoryLock() +{ + if (!IsLargePageSupported()) + return; + // if (ReadLockMemoryAdd()) + NSecurity::AddLockMemoryPrivilege(); + + if (ReadLockMemoryEnable()) + NSecurity::EnableLockMemoryPrivilege(); +} +#endif + +/* +static const int kNumSwitches = 1; + +namespace NKey { +enum Enum +{ + kOpenArachive = 0 +}; + +} + +static const CSwitchForm kSwitchForms[kNumSwitches] = + { + { L"SOA", NSwitchType::kSimple, false }, + }; +*/ + +// int APIENTRY WinMain2(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, LPSTR /* lpCmdLine */, int /* nCmdShow */); + +#define NT_CHECK_FAIL_ACTION MessageBoxW(0, L"Unsupported Windows version", L"7-zip", MB_ICONERROR); return 1; + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, + #ifdef UNDER_CE + LPWSTR + #else + LPSTR + #endif + /* lpCmdLine */, int nCmdShow) +{ + #ifdef _WIN32 + + NT_CHECK + SetLargePageSize(); + + #endif + + InitCommonControls(); + + #ifndef UNDER_CE + g_ComCtl32Version = ::GetDllVersion(TEXT("comctl32.dll")); + g_LVN_ITEMACTIVATE_Support = (g_ComCtl32Version >= MAKELONG(71, 4)); + #endif + + g_IsSmallScreen = !NWindows::NControl::IsDialogSizeOK(200, 200); + + // OleInitialize is required for drag and drop. + #ifndef UNDER_CE + OleInitialize(NULL); + #endif + // Maybe needs CoInitializeEx also ? + // NCOM::CComInitializer comInitializer; + + UString commandsString; + // MessageBoxW(0, GetCommandLineW(), L"", 0); + + #ifdef UNDER_CE + commandsString = GetCommandLineW(); + #else + UString programString; + SplitStringToTwoStrings(GetCommandLineW(), programString, commandsString); + #endif + + commandsString.Trim(); + UString paramString, tailString; + SplitStringToTwoStrings(commandsString, paramString, tailString); + paramString.Trim(); + tailString.Trim(); + if (tailString.Left(2) == L"-t") + g_ArcFormat = tailString.Mid(2); + if (!paramString.IsEmpty()) + { + g_MainPath = paramString; + // return WinMain2(hInstance, hPrevInstance, lpCmdLine, nCmdShow); + + // MessageBoxW(0, paramString, L"", 0); + } + /* + UStringVector commandStrings; + NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); + NCommandLineParser::CParser parser(kNumSwitches); + try + { + parser.ParseStrings(kSwitchForms, commandStrings); + const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; + if (nonSwitchStrings.Size() > 1) + { + g_MainPath = nonSwitchStrings[1]; + // g_OpenArchive = parser[NKey::kOpenArachive].ThereIs; + CFileInfoW fileInfo; + if (FindFile(g_MainPath, fileInfo)) + { + if (!fileInfo.IsDir()) + g_OpenArchive = true; + } + } + } + catch(...) { } + */ + + + #ifndef UNDER_CE + SetMemoryLock(); + #endif + + MSG msg; + if (!InitInstance (hInstance, nCmdShow)) + return FALSE; + + #ifndef _UNICODE + if (g_IsNT) + { + HACCEL hAccels = LoadAcceleratorsW(hInstance, MAKEINTRESOURCEW(IDR_ACCELERATOR1)); + while (GetMessageW(&msg, NULL, 0, 0)) + { + if (TranslateAcceleratorW(g_HWND, hAccels, &msg) == 0) + { + TranslateMessage(&msg); + DispatchMessageW(&msg); + } + } + } + else + #endif + { + HACCEL hAccels = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1)); + while (GetMessage(&msg, NULL, 0, 0)) + { + if (TranslateAccelerator(g_HWND, hAccels, &msg) == 0) + { + // if (g_Hwnd != NULL || !IsDialogMessage(g_Hwnd, &msg)) + // if (!IsDialogMessage(g_Hwnd, &msg)) + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } + + g_HWND = 0; + #ifndef UNDER_CE + OleUninitialize(); + #endif + return (int)msg.wParam; +} + +static void SaveWindowInfo(HWND aWnd) +{ + #ifdef UNDER_CE + RECT rect; + if (!::GetWindowRect(aWnd, &rect)) + return; + SaveWindowSize(rect, g_Maximized); + #else + WINDOWPLACEMENT placement; + placement.length = sizeof(placement); + if (!::GetWindowPlacement(aWnd, &placement)) + return; + SaveWindowSize(placement.rcNormalPosition, BOOLToBool(::IsZoomed(aWnd))); + #endif + SavePanelsInfo(g_App.NumPanels, g_App.LastFocusedPanel, g_Splitter.GetPos()); +} + +static void ExecuteCommand(UINT commandID) +{ + CPanel::CDisableTimerProcessing disableTimerProcessing1(g_App.Panels[0]); + CPanel::CDisableTimerProcessing disableTimerProcessing2(g_App.Panels[1]); + + switch (commandID) + { + case kAddCommand: g_App.AddToArchive(); break; + case kExtractCommand: g_App.ExtractArchives(); break; + case kTestCommand: g_App.TestArchives(); break; + } +} + +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + int wmId, wmEvent; + switch (message) + { + case WM_COMMAND: + wmId = LOWORD(wParam); + wmEvent = HIWORD(wParam); + if ((HWND) lParam != NULL && wmEvent != 0) + break; + if (wmId >= kToolbarStartID) + { + ExecuteCommand(wmId); + return 0; + } + if (OnMenuCommand(hWnd, wmId)) + return 0; + break; + case WM_INITMENUPOPUP: + OnMenuActivating(hWnd, HMENU(wParam), LOWORD(lParam)); + break; + + /* + It doesn't help + case WM_EXITMENULOOP: + { + OnMenuUnActivating(hWnd); + break; + } + case WM_UNINITMENUPOPUP: + OnMenuUnActivating(hWnd, HMENU(wParam), lParam); + break; + */ + + case WM_CREATE: + { + g_HWND = hWnd; + /* + INITCOMMONCONTROLSEX icex; + icex.dwSize = sizeof(INITCOMMONCONTROLSEX); + icex.dwICC = ICC_BAR_CLASSES; + InitCommonControlsEx(&icex); + + // Toolbar buttons used to create the first 4 buttons. + TBBUTTON tbb [ ] = + { + // {0, 0, TBSTATE_ENABLED, BTNS_SEP, 0L, 0}, + // {VIEW_PARENTFOLDER, kParentFolderID, TBSTATE_ENABLED, BTNS_BUTTON, 0L, 0}, + // {0, 0, TBSTATE_ENABLED, BTNS_SEP, 0L, 0}, + {VIEW_NEWFOLDER, ID_FILE_CREATEFOLDER, TBSTATE_ENABLED, BTNS_BUTTON, 0L, 0}, + }; + + int baseID = 100; + NWindows::NControl::CToolBar aToolBar; + aToolBar.Attach(::CreateToolbarEx (hWnd, + WS_CHILD | WS_BORDER | WS_VISIBLE | TBSTYLE_TOOLTIPS, // | TBSTYLE_FLAT + baseID + 2, 11, + (HINSTANCE)HINST_COMMCTRL, IDB_VIEW_SMALL_COLOR, + (LPCTBBUTTON)&tbb, sizeof(tbb) / sizeof(tbb[0]), + 0, 0, 100, 30, sizeof (TBBUTTON))); + */ + // HCURSOR cursor = ::LoadCursor(0, IDC_SIZEWE); + // ::SetCursor(cursor); + + if (g_PanelsInfoDefined) + g_Splitter.SetPos(hWnd, g_SplitterPos); + else + { + g_Splitter.SetRatio(hWnd, kSplitterRateMax / 2); + g_SplitterPos = g_Splitter.GetPos(); + } + + RECT rect; + ::GetClientRect(hWnd, &rect); + int xSize = rect.right; + int xSizes[2]; + xSizes[0] = g_Splitter.GetPos(); + xSizes[1] = xSize - kSplitterWidth - xSizes[0]; + if (xSizes[1] < 0) + xSizes[1] = 0; + + g_App.CreateDragTarget(); + bool archiveIsOpened; + bool encrypted; + bool needOpenFile = false; + if (!g_MainPath.IsEmpty() /* && g_OpenArchive */) + { + if (NFile::NFind::DoesFileExist(g_MainPath)) + needOpenFile = true; + } + HRESULT res = g_App.Create(hWnd, g_MainPath, g_ArcFormat, xSizes, archiveIsOpened, encrypted); + + if (res == E_ABORT) + { + return -1; + } + if (needOpenFile && !archiveIsOpened || res != S_OK) + { + UString message = L"Error"; + if (res == S_FALSE || res == S_OK) + { + if (encrypted) + message = MyFormatNew(IDS_CANT_OPEN_ENCRYPTED_ARCHIVE, 0x0200060A, g_MainPath); + else + message = MyFormatNew(IDS_CANT_OPEN_ARCHIVE, 0x02000609, g_MainPath); + } + else + { + if (res != S_OK) + { + if (res == E_OUTOFMEMORY) + message = LangString(IDS_MEM_ERROR, 0x0200060B); + else + if (!NError::MyFormatMessage(res, message)) + message = L"Error"; + } + } + MessageBoxW(0, message, L"7-zip", MB_ICONERROR); + return -1; + } + // g_SplitterPos = 0; + + // ::DragAcceptFiles(hWnd, TRUE); + RegisterDragDrop(hWnd, g_App._dropTarget); + + break; + } + case WM_DESTROY: + { + // ::DragAcceptFiles(hWnd, FALSE); + RevokeDragDrop(hWnd); + g_App._dropTarget.Release(); + + g_App.Save(); + g_App.Release(); + SaveWindowInfo(hWnd); + PostQuitMessage(0); + break; + } + /* + case WM_MOVE: + { + break; + } + */ + case WM_LBUTTONDOWN: + g_StartCaptureMousePos = LOWORD(lParam); + g_StartCaptureSplitterPos = g_Splitter.GetPos(); + ::SetCapture(hWnd); + break; + case WM_LBUTTONUP: + { + ::ReleaseCapture(); + break; + } + case WM_MOUSEMOVE: + { + if ((wParam & MK_LBUTTON) != 0 && ::GetCapture() == hWnd) + { + g_Splitter.SetPos(hWnd, g_StartCaptureSplitterPos + + (short)LOWORD(lParam) - g_StartCaptureMousePos); + g_App.MoveSubWindows(); + } + break; + } + + case WM_SIZE: + { + if (g_CanChangeSplitter) + g_Splitter.SetPosFromRatio(hWnd); + else + { + g_Splitter.SetPos(hWnd, g_SplitterPos ); + g_CanChangeSplitter = true; + } + + g_Maximized = (wParam == SIZE_MAXIMIZED) || (wParam == SIZE_MAXSHOW); + + g_App.MoveSubWindows(); + /* + int xSize = LOWORD(lParam); + int ySize = HIWORD(lParam); + // int xSplitter = 2; + int xWidth = g_SplitPos; + // int xSplitPos = xWidth; + g_Panel[0]._listView.MoveWindow(0, 0, xWidth, ySize); + g_Panel[1]._listView.MoveWindow(xSize - xWidth, 0, xWidth, ySize); + */ + return 0; + break; + } + case WM_SETFOCUS: + // g_App.SetFocus(g_App.LastFocusedPanel); + g_App.SetFocusToLastItem(); + break; + /* + case WM_ACTIVATE: + { + int fActive = LOWORD(wParam); + switch (fActive) + { + case WA_INACTIVE: + { + // g_FocusIndex = g_App.LastFocusedPanel; + // g_App.LastFocusedPanel = g_App.GetFocusedPanelIndex(); + // return 0; + } + } + break; + } + */ + /* + case kLangWasChangedMessage: + MyLoadMenu(); + return 0; + */ + + /* + case WM_SETTINGCHANGE: + break; + */ + case WM_NOTIFY: + { + g_App.OnNotify((int)wParam, (LPNMHDR)lParam); + break; + } + /* + case WM_DROPFILES: + { + g_App.GetFocusedPanel().CompressDropFiles((HDROP)wParam); + return 0 ; + } + */ + } + #ifndef _UNICODE + if (g_IsNT) + return DefWindowProcW(hWnd, message, wParam, lParam); + else + #endif + return DefWindowProc(hWnd, message, wParam, lParam); + +} + +static int Window_GetRealHeight(NWindows::CWindow &w) +{ + RECT rect; + w.GetWindowRect(&rect); + int res = rect.bottom - rect.top; + #ifndef UNDER_CE + WINDOWPLACEMENT placement; + if (w.GetPlacement(&placement)) + res += placement.rcNormalPosition.top; + #endif + return res; +} + +void CApp::MoveSubWindows() +{ + HWND hWnd = _window; + RECT rect; + if (hWnd == 0) + return; + ::GetClientRect(hWnd, &rect); + int xSize = rect.right; + if (xSize == 0) + return; + int headerSize = 0; + #ifdef UNDER_CE + _commandBar.AutoSize(); + { + _commandBar.Show(true); // maybe we need it for + headerSize += _commandBar.Height(); + } + #endif + if (_toolBar) + { + _toolBar.AutoSize(); + #ifdef UNDER_CE + int h2 = Window_GetRealHeight(_toolBar); + _toolBar.Move(0, headerSize, xSize, h2); + #endif + headerSize += Window_GetRealHeight(_toolBar); + } + int ySize = MyMax((int)(rect.bottom - headerSize), 0); + + if (NumPanels > 1) + { + Panels[0].Move(0, headerSize, g_Splitter.GetPos(), ySize); + int xWidth1 = g_Splitter.GetPos() + kSplitterWidth; + Panels[1].Move(xWidth1, headerSize, xSize - xWidth1, ySize); + } + else + { + /* + int otherPanel = 1 - LastFocusedPanel; + if (PanelsCreated[otherPanel]) + Panels[otherPanel].Move(0, headerSize, 0, ySize); + */ + Panels[LastFocusedPanel].Move(0, headerSize, xSize, ySize); + } +} diff --git a/CPP/7zip/UI/FileManager/FM.dsp b/CPP/7zip/UI/FileManager/FM.dsp new file mode 100755 index 0000000..113db8b --- /dev/null +++ b/CPP/7zip/UI/FileManager/FM.dsp @@ -0,0 +1,1576 @@ +# Microsoft Developer Studio Project File - Name="FM" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=FM - 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 "FM.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 "FM.mak" CFG="FM - Win32 DebugU" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "FM - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "FM - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE "FM - Win32 ReleaseU" (based on "Win32 (x86) Application") +!MESSAGE "FM - Win32 DebugU" (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)" == "FM - 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 /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x409 /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 comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Program Files\7-ZIP\7zFM.exe" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "FM - 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 /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x409 /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 comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Program Files\7-ZIP\7zFM.exe" /pdbtype:sept + +!ELSEIF "$(CFG)" == "FM - 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 "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x409 /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 comctl32.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 comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Program Files\7-ZIP\7zFM.exe" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "FM - 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 "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x409 /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 comctl32.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 comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Program Files\7-ZIP\7zFM.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "FM - Win32 Release" +# Name "FM - Win32 Debug" +# Name "FM - Win32 ReleaseU" +# Name "FM - Win32 DebugU" +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\7zipLogo.ico +# End Source File +# Begin Source File + +SOURCE=.\add.bmp +# End Source File +# Begin Source File + +SOURCE=.\ClassDefs.cpp +# End Source File +# Begin Source File + +SOURCE=.\Copy.bmp +# End Source File +# Begin Source File + +SOURCE=.\Delete.bmp +# End Source File +# Begin Source File + +SOURCE=.\Extract.bmp +# End Source File +# Begin Source File + +SOURCE=.\FM.ico +# End Source File +# Begin Source File + +SOURCE=.\Move.bmp +# End Source File +# Begin Source File + +SOURCE=.\Parent.bmp +# End Source File +# Begin Source File + +SOURCE=.\Properties.bmp +# End Source File +# Begin Source File + +SOURCE=.\resource.rc +# ADD BASE RSC /l 0x419 +# ADD RSC /l 0x409 +# 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 +# Begin Source File + +SOURCE=.\Test.bmp +# End Source File +# End Group +# Begin Group "Archive" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\IArchive.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 "Folders" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\FSDrives.cpp +# End Source File +# Begin Source File + +SOURCE=.\FSDrives.h +# End Source File +# Begin Source File + +SOURCE=.\FSFolder.cpp +# End Source File +# Begin Source File + +SOURCE=.\FSFolder.h +# End Source File +# Begin Source File + +SOURCE=.\FSFolderCopy.cpp +# End Source File +# Begin Source File + +SOURCE=.\IFolder.h +# End Source File +# Begin Source File + +SOURCE=.\NetFolder.cpp +# End Source File +# Begin Source File + +SOURCE=.\NetFolder.h +# End Source File +# Begin Source File + +SOURCE=.\RootFolder.cpp +# End Source File +# Begin Source File + +SOURCE=.\RootFolder.h +# End Source File +# End Group +# Begin Group "Registry" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\RegistryAssociations.cpp +# End Source File +# Begin Source File + +SOURCE=.\RegistryAssociations.h +# End Source File +# Begin Source File + +SOURCE=.\RegistryPlugins.cpp +# End Source File +# Begin Source File + +SOURCE=.\RegistryPlugins.h +# End Source File +# Begin Source File + +SOURCE=.\RegistryUtils.cpp +# End Source File +# Begin Source File + +SOURCE=.\RegistryUtils.h +# End Source File +# Begin Source File + +SOURCE=.\ViewSettings.cpp +# End Source File +# Begin Source File + +SOURCE=.\ViewSettings.h +# End Source File +# End Group +# Begin Group "Panel" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\App.cpp +# End Source File +# Begin Source File + +SOURCE=.\App.h +# End Source File +# Begin Source File + +SOURCE=.\AppState.h +# End Source File +# Begin Source File + +SOURCE=.\EnumFormatEtc.cpp +# End Source File +# Begin Source File + +SOURCE=.\EnumFormatEtc.h +# End Source File +# Begin Source File + +SOURCE=.\FileFolderPluginOpen.cpp +# End Source File +# Begin Source File + +SOURCE=.\FileFolderPluginOpen.h +# End Source File +# Begin Source File + +SOURCE=.\Panel.cpp +# End Source File +# Begin Source File + +SOURCE=.\Panel.h +# End Source File +# Begin Source File + +SOURCE=.\PanelCopy.cpp +# End Source File +# Begin Source File + +SOURCE=.\PanelCrc.cpp +# End Source File +# Begin Source File + +SOURCE=.\PanelDrag.cpp +# End Source File +# Begin Source File + +SOURCE=.\PanelFolderChange.cpp +# End Source File +# Begin Source File + +SOURCE=.\PanelItemOpen.cpp +# End Source File +# Begin Source File + +SOURCE=.\PanelItems.cpp +# End Source File +# Begin Source File + +SOURCE=.\PanelKey.cpp +# End Source File +# Begin Source File + +SOURCE=.\PanelListNotify.cpp +# End Source File +# Begin Source File + +SOURCE=.\PanelMenu.cpp +# End Source File +# Begin Source File + +SOURCE=.\PanelOperations.cpp +# End Source File +# Begin Source File + +SOURCE=.\PanelSelect.cpp +# End Source File +# Begin Source File + +SOURCE=.\PanelSort.cpp +# End Source File +# Begin Source File + +SOURCE=.\PanelSplitFile.cpp +# End Source File +# End Group +# Begin Group "Dialog" + +# PROP Default_Filter "" +# Begin Group "Options" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\EditPage.cpp +# End Source File +# Begin Source File + +SOURCE=.\EditPage.h +# End Source File +# Begin Source File + +SOURCE=.\FoldersPage.cpp +# End Source File +# Begin Source File + +SOURCE=.\FoldersPage.h +# End Source File +# Begin Source File + +SOURCE=.\LangPage.cpp +# End Source File +# Begin Source File + +SOURCE=.\LangPage.h +# End Source File +# Begin Source File + +SOURCE=.\MenuPage.cpp +# End Source File +# Begin Source File + +SOURCE=.\MenuPage.h +# End Source File +# Begin Source File + +SOURCE=.\OptionsDialog.cpp +# End Source File +# Begin Source File + +SOURCE=.\SettingsPage.cpp +# End Source File +# Begin Source File + +SOURCE=.\SettingsPage.h +# End Source File +# Begin Source File + +SOURCE=.\SystemPage.cpp +# End Source File +# Begin Source File + +SOURCE=.\SystemPage.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\AboutDialog.cpp +# End Source File +# Begin Source File + +SOURCE=.\AboutDialog.h +# End Source File +# Begin Source File + +SOURCE=.\BrowseDialog.cpp +# End Source File +# Begin Source File + +SOURCE=.\BrowseDialog.h +# End Source File +# Begin Source File + +SOURCE=.\ComboDialog.cpp +# End Source File +# Begin Source File + +SOURCE=.\ComboDialog.h +# End Source File +# Begin Source File + +SOURCE=CopyDialog.cpp +# End Source File +# Begin Source File + +SOURCE=CopyDialog.h +# End Source File +# Begin Source File + +SOURCE=.\DialogSize.h +# End Source File +# Begin Source File + +SOURCE=.\ListViewDialog.cpp +# End Source File +# Begin Source File + +SOURCE=.\ListViewDialog.h +# End Source File +# Begin Source File + +SOURCE=MessagesDialog.cpp +# End Source File +# Begin Source File + +SOURCE=MessagesDialog.h +# End Source File +# Begin Source File + +SOURCE=OverwriteDialog.cpp +# End Source File +# Begin Source File + +SOURCE=OverwriteDialog.h +# End Source File +# Begin Source File + +SOURCE=.\PasswordDialog.cpp +# End Source File +# Begin Source File + +SOURCE=.\PasswordDialog.h +# End Source File +# Begin Source File + +SOURCE=.\ProgressDialog2.cpp +# End Source File +# Begin Source File + +SOURCE=.\ProgressDialog2.h +# End Source File +# Begin Source File + +SOURCE=.\SplitDialog.cpp +# End Source File +# Begin Source File + +SOURCE=.\SplitDialog.h +# End Source File +# End Group +# Begin Group "FM Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\ExtractCallback.cpp +# End Source File +# Begin Source File + +SOURCE=.\ExtractCallback.h +# End Source File +# Begin Source File + +SOURCE=.\FormatUtils.cpp +# End Source File +# Begin Source File + +SOURCE=.\FormatUtils.h +# End Source File +# Begin Source File + +SOURCE=.\HelpUtils.cpp +# End Source File +# Begin Source File + +SOURCE=.\HelpUtils.h +# End Source File +# Begin Source File + +SOURCE=.\LangUtils.cpp +# End Source File +# Begin Source File + +SOURCE=.\LangUtils.h +# End Source File +# Begin Source File + +SOURCE=.\ProgramLocation.cpp +# End Source File +# Begin Source File + +SOURCE=.\ProgramLocation.h +# End Source File +# Begin Source File + +SOURCE=.\UpdateCallback100.cpp +# End Source File +# Begin Source File + +SOURCE=.\UpdateCallback100.h +# End Source File +# End Group +# Begin Group "7-Zip Common" + +# PROP Default_Filter "" +# 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\ProgressUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressUtils.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 +# 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 + +!IF "$(CFG)" == "FM - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "FM - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "FM - Win32 ReleaseU" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "FM - 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\CpuArch.c + +!IF "$(CFG)" == "FM - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "FM - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "FM - Win32 ReleaseU" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "FM - 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\Sha256.c + +!IF "$(CFG)" == "FM - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "FM - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "FM - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "FM - 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\Sort.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Sort.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 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\CommandBar.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\Edit.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\ImageList.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 +# Begin Source File + +SOURCE=..\..\..\Windows\Control\ProgressBar.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\PropertyPage.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\PropertyPage.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\ReBar.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\Static.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\StatusBar.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\ToolBar.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\Trackbar.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\Window2.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\Window2.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\..\Windows\Clipboard.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Clipboard.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\COM.h +# End Source File +# 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\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\Error.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Error.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\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\Memory.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Memory.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\Menu.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Menu.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Net.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Net.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Process.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Process.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\PropVariantConversions.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariantConversions.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Registry.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Registry.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\ResourceString.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\ResourceString.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Security.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Security.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\Thread.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Time.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Time.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Timer.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\Buffer.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\Defs.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\DynamicBuffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Exception.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\Lang.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Lang.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\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\Random.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Random.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\TextConfig.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\TextConfig.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 +# End Group +# Begin Group "UI" + +# PROP Default_Filter "" +# Begin Group "UI Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\Common\ArchiveExtractCallback.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ArchiveExtractCallback.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ArchiveName.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ArchiveName.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ArchiveOpenCallback.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ArchiveOpenCallback.h +# End Source File +# Begin Source File + +SOURCE=..\Common\CompressCall.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\CompressCall.h +# End Source File +# Begin Source File + +SOURCE=..\Common\DefaultName.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\DefaultName.h +# End Source File +# Begin Source File + +SOURCE=..\Common\DirItem.h +# End Source File +# Begin Source File + +SOURCE=..\Common\EnumDirItems.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\EnumDirItems.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ExitCode.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ExtractingFilePath.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ExtractingFilePath.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ExtractMode.h +# End Source File +# Begin Source File + +SOURCE=..\Common\IFileExtractCallback.h +# End Source File +# Begin Source File + +SOURCE=..\Common\LoadCodecs.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\LoadCodecs.h +# End Source File +# Begin Source File + +SOURCE=..\Common\OpenArchive.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\OpenArchive.h +# End Source File +# Begin Source File + +SOURCE=..\Common\Property.h +# End Source File +# Begin Source File + +SOURCE=..\Common\PropIDUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\PropIDUtils.h +# End Source File +# Begin Source File + +SOURCE=..\Common\SortUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\SortUtils.h +# End Source File +# Begin Source File + +SOURCE=..\Common\StdAfx.h +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdateAction.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdateAction.h +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdateCallback.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdateCallback.h +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdatePair.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdatePair.h +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdateProduce.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdateProduce.h +# End Source File +# Begin Source File + +SOURCE=..\Common\WorkDir.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\WorkDir.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ZipRegistry.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ZipRegistry.h +# End Source File +# End Group +# Begin Group "Agent" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\Agent\Agent.cpp +# End Source File +# Begin Source File + +SOURCE=..\Agent\Agent.h +# End Source File +# Begin Source File + +SOURCE=..\Agent\AgentOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\Agent\AgentProxy.cpp +# End Source File +# Begin Source File + +SOURCE=..\Agent\AgentProxy.h +# End Source File +# Begin Source File + +SOURCE=..\Agent\ArchiveFolder.cpp +# End Source File +# Begin Source File + +SOURCE=..\Agent\ArchiveFolderOpen.cpp +# End Source File +# Begin Source File + +SOURCE=..\Agent\ArchiveFolderOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\Agent\IFolderArchive.h +# End Source File +# Begin Source File + +SOURCE=..\Agent\UpdateCallbackAgent.cpp +# End Source File +# Begin Source File + +SOURCE=..\Agent\UpdateCallbackAgent.h +# End Source File +# End Group +# Begin Group "Explorer" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\Explorer\ContextMenu.cpp +# End Source File +# Begin Source File + +SOURCE=..\Explorer\ContextMenu.h +# End Source File +# Begin Source File + +SOURCE=..\Explorer\RegistryContextMenu.cpp +# End Source File +# Begin Source File + +SOURCE=..\Explorer\RegistryContextMenu.h +# End Source File +# End Group +# End Group +# Begin Group "Compress" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\CopyCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\CopyCoder.h +# End Source File +# End Group +# Begin Group "Interface" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\ICoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\IDecl.h +# End Source File +# Begin Source File + +SOURCE=..\..\IPassword.h +# End Source File +# Begin Source File + +SOURCE=..\..\IProgress.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\7zFM.exe.manifest +# End Source File +# Begin Source File + +SOURCE=.\7zipLogo.ico +# End Source File +# Begin Source File + +SOURCE=.\Add2.bmp +# End Source File +# Begin Source File + +SOURCE=.\Copy2.bmp +# End Source File +# Begin Source File + +SOURCE=.\Delete2.bmp +# End Source File +# Begin Source File + +SOURCE=.\Extract2.bmp +# End Source File +# Begin Source File + +SOURCE=.\FilePlugins.cpp +# End Source File +# Begin Source File + +SOURCE=.\FilePlugins.h +# End Source File +# Begin Source File + +SOURCE=.\FM.cpp +# End Source File +# Begin Source File + +SOURCE=.\Info.bmp +# End Source File +# Begin Source File + +SOURCE=.\Info2.bmp +# End Source File +# Begin Source File + +SOURCE=.\Move2.bmp +# End Source File +# Begin Source File + +SOURCE=.\MyCom2.h +# End Source File +# Begin Source File + +SOURCE=.\MyLoadMenu.cpp +# End Source File +# Begin Source File + +SOURCE=.\MyLoadMenu.h +# End Source File +# Begin Source File + +SOURCE=.\OpenCallback.cpp +# End Source File +# Begin Source File + +SOURCE=.\OpenCallback.h +# End Source File +# Begin Source File + +SOURCE=.\PluginInterface.h +# End Source File +# Begin Source File + +SOURCE=.\PluginLoader.h +# End Source File +# Begin Source File + +SOURCE=.\PropertyName.cpp +# End Source File +# Begin Source File + +SOURCE=.\PropertyName.h +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# Begin Source File + +SOURCE=.\SplitUtils.cpp +# End Source File +# Begin Source File + +SOURCE=.\SplitUtils.h +# End Source File +# Begin Source File + +SOURCE=.\StringUtils.cpp +# End Source File +# Begin Source File + +SOURCE=.\StringUtils.h +# End Source File +# Begin Source File + +SOURCE=.\SysIconUtils.cpp +# End Source File +# Begin Source File + +SOURCE=.\SysIconUtils.h +# End Source File +# Begin Source File + +SOURCE=.\Test2.bmp +# End Source File +# Begin Source File + +SOURCE=.\TextPairs.cpp +# End Source File +# Begin Source File + +SOURCE=.\TextPairs.h +# End Source File +# End Target +# End Project diff --git a/CPP/7zip/UI/FileManager/FM.dsw b/CPP/7zip/UI/FileManager/FM.dsw new file mode 100755 index 0000000..38f65d2 --- /dev/null +++ b/CPP/7zip/UI/FileManager/FM.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "FM"=.\FM.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/CPP/7zip/UI/FileManager/FM.ico b/CPP/7zip/UI/FileManager/FM.ico new file mode 100755 index 0000000000000000000000000000000000000000..3a0a34da6298bb0a61612a7d60facaf16df8c2c5 GIT binary patch literal 4846 zcmeI0y-Qp{5WvT1AwiO}v65h{v=bHrcEKW@U}J5n{TFOfTxA^y2-{gCAt}=M7hIJh zZmmtMED|J;vlCKGelz>t-Sd1zC7y-2@AhLpcINkH_aP`UA(OJO&=G4tABntR?sSU0 zG$HbAQeEha!6(cPO$2ypSJ!8gb3aVwPzg(C=HA#L+uY|F%&gVyqVC5=ekR++ESG{Av9ul;Wa)M4eeX&C+eew2nv&`1X_=Xsk=fZAq3f*id;VhoZl-d_DXvhd+ME+s|J}6zGwj=(&giT|gJm z1=I2J<`U6I77=|!AJN;kgg&892nl^c&mviVltdM=%Z!3M!|F zj1iUyON7N=8J0-$NTNv42#c2iV`LFwiLiKC;D~TUI3gSo4lflP5rzmuguzM|;fOFq z7&5t((Mw34@*sP8tvXPVJK^P}CU=4X@>rqz0LM8MX{ZCZ8XzaZrN{M>Y;#%#WK*8I}x71|pNt zuK+BWjTxtmBE!OuP8`l8!;-BY&SJO0P5~VZ3WLI+FenTPgI^~YG7JiX!jNGg3>|+M z6b6MsVIVXeJq!wi!k_>s`7^FKGQot??~`MLD}sJ!3X<2&wBUHb-XBA!bY*F=*Z+P$y9 z=pWH`d02*a`>6JA{fF7=6+HFQuJTYAk!q)=%dPo00#)%%?ncLUH?CthZ?cMngGd-;CSp~|a aDxai%qSuvsRtNqM^Dvh>T(@qcet!W-FyKr8 literal 0 HcmV?d00001 diff --git a/CPP/7zip/UI/FileManager/FSDrives.cpp b/CPP/7zip/UI/FileManager/FSDrives.cpp new file mode 100755 index 0000000..2daf41a --- /dev/null +++ b/CPP/7zip/UI/FileManager/FSDrives.cpp @@ -0,0 +1,420 @@ +// FSDrives.cpp + +#include "StdAfx.h" + +#include "../../../../C/Alloc.h" + +#include "Common/ComTry.h" +#include "Common/StringConvert.h" + +#include "Windows/Defs.h" +#include "Windows/FileDir.h" +#include "Windows/FileIO.h" +#include "Windows/FileSystem.h" +#include "Windows/PropVariant.h" + +#include "../../PropID.h" + +#include "FSDrives.h" +#include "FSFolder.h" +#include "LangUtils.h" +#include "SysIconUtils.h" + +#include "resource.h" + +using namespace NWindows; +using namespace NFile; +using namespace NFind; + +static const wchar_t *kVolPrefix = L"\\\\.\\"; + +UString CDriveInfo::GetDeviceFileIoName() const +{ + return kVolPrefix + Name; +} + +struct CPhysTempBuffer +{ + void *buffer; + CPhysTempBuffer(): buffer(0) {} + ~CPhysTempBuffer() { MidFree(buffer); } +}; + +static HRESULT CopyFileSpec(LPCWSTR fromPath, LPCWSTR toPath, bool writeToDisk, UInt64 fileSize, + UInt32 bufferSize, UInt64 progressStart, IProgress *progress) +{ + NFile::NIO::CInFile inFile; + if (!inFile.Open(fromPath)) + return GetLastError(); + if (fileSize == (UInt64)(Int64)-1) + { + if (!inFile.GetLength(fileSize)) + ::GetLastError(); + } + NFile::NIO::COutFile outFile; + if (writeToDisk) + { + if (!outFile.Open(toPath, FILE_SHARE_WRITE, OPEN_EXISTING, 0)) + return GetLastError(); + } + else + if (!outFile.Create(toPath, true)) + return GetLastError(); + CPhysTempBuffer tempBuffer; + tempBuffer.buffer = MidAlloc(bufferSize); + if (tempBuffer.buffer == 0) + return E_OUTOFMEMORY; + + for (UInt64 pos = 0; pos < fileSize;) + { + UInt64 progressCur = progressStart + pos; + RINOK(progress->SetCompleted(&progressCur)); + UInt64 rem = fileSize - pos; + UInt32 curSize = (UInt32)MyMin(rem, (UInt64)bufferSize); + UInt32 processedSize; + if (!inFile.Read(tempBuffer.buffer, curSize, processedSize)) + return GetLastError(); + if (processedSize == 0) + break; + curSize = processedSize; + if (writeToDisk) + { + const UInt32 kMask = 0x1FF; + curSize = (curSize + kMask) & ~kMask; + if (curSize > bufferSize) + return E_FAIL; + } + + if (!outFile.Write(tempBuffer.buffer, curSize, processedSize)) + return GetLastError(); + if (curSize != processedSize) + return E_FAIL; + pos += curSize; + } + return S_OK; +} + +static const STATPROPSTG kProps[] = +{ + { NULL, kpidName, VT_BSTR}, + { NULL, kpidTotalSize, VT_UI8}, + { NULL, kpidFreeSpace, VT_UI8}, + { NULL, kpidType, VT_BSTR}, + { NULL, kpidVolumeName, VT_BSTR}, + { NULL, kpidFileSystem, VT_BSTR}, + { NULL, kpidClusterSize, VT_UI8} +}; + +static const char *kDriveTypes[] = +{ + "Unknown", + "No Root Dir", + "Removable", + "Fixed", + "Remote", + "CD-ROM", + "RAM disk" +}; + +STDMETHODIMP CFSDrives::LoadItems() +{ + _drives.Clear(); + + UStringVector driveStrings; + MyGetLogicalDriveStrings(driveStrings); + for (int i = 0; i < driveStrings.Size(); i++) + { + CDriveInfo di; + + const UString &driveName = driveStrings[i]; + + di.FullSystemName = driveName; + + di.Name = di.FullSystemName.Left(di.FullSystemName.Length() - 1); + di.ClusterSize = 0; + di.DriveSize = 0; + di.FreeSpace = 0; + di.DriveType = NFile::NSystem::MyGetDriveType(driveName); + bool needRead = true; + if (di.DriveType == DRIVE_CDROM || di.DriveType == DRIVE_REMOVABLE) + { + /* + DWORD dwSerialNumber;` + if (!::GetVolumeInformation(di.FullSystemName, + NULL, 0, &dwSerialNumber, NULL, NULL, NULL, 0)) + */ + di.KnownSizes = false; + { + needRead = false; + } + } + if (needRead) + { + UString volumeName, fileSystemName; + DWORD volumeSerialNumber, maximumComponentLength, fileSystemFlags; + NFile::NSystem::MyGetVolumeInformation(driveName, + volumeName, + &volumeSerialNumber, &maximumComponentLength, &fileSystemFlags, + fileSystemName); + di.VolumeName = volumeName; + di.FileSystemName = fileSystemName; + + NFile::NSystem::MyGetDiskFreeSpace(driveName, + di.ClusterSize, di.DriveSize, di.FreeSpace); + di.KnownSizes = true; + } + _drives.Add(di); + } + return S_OK; +} + +STDMETHODIMP CFSDrives::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _drives.Size(); + return S_OK; +} + +STDMETHODIMP CFSDrives::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value) +{ + if (itemIndex >= (UInt32)_drives.Size()) + return E_INVALIDARG; + NCOM::CPropVariant prop; + const CDriveInfo &di = _drives[itemIndex]; + switch(propID) + { + case kpidIsDir: prop = !_volumeMode; break; + case kpidName: prop = di.Name; break; + case kpidTotalSize: if (di.KnownSizes) prop = di.DriveSize; break; + case kpidFreeSpace: if (di.KnownSizes) prop = di.FreeSpace; break; + case kpidClusterSize: if (di.KnownSizes) prop = di.ClusterSize; break; + case kpidType: + if (di.DriveType < sizeof(kDriveTypes) / sizeof(kDriveTypes[0])) + prop = kDriveTypes[di.DriveType]; + break; + case kpidVolumeName: prop = di.VolumeName; break; + case kpidFileSystem: prop = di.FileSystemName; break; + } + prop.Detach(value); + return S_OK; +} + +HRESULT CFSDrives::BindToFolderSpec(const wchar_t *name, IFolderFolder **resultFolder) +{ + *resultFolder = 0; + if (_volumeMode) + return S_OK; + NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder; + CMyComPtr subFolder = fsFolderSpec; + RINOK(fsFolderSpec->Init(name, 0)); + *resultFolder = subFolder.Detach(); + return S_OK; +} + +STDMETHODIMP CFSDrives::BindToFolder(UInt32 index, IFolderFolder **resultFolder) +{ + *resultFolder = 0; + if (index >= (UInt32)_drives.Size()) + return E_INVALIDARG; + const CDriveInfo &di = _drives[index]; + /* + if (_volumeMode) + { + *resultFolder = 0; + CPhysDriveFolder *folderSpec = new CPhysDriveFolder; + CMyComPtr subFolder = folderSpec; + RINOK(folderSpec->Init(di.Name)); + *resultFolder = subFolder.Detach(); + return S_OK; + } + */ + return BindToFolderSpec(di.FullSystemName, resultFolder); +} + +STDMETHODIMP CFSDrives::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder) +{ + return BindToFolderSpec(name, resultFolder); +} + +STDMETHODIMP CFSDrives::BindToParentFolder(IFolderFolder **resultFolder) +{ + *resultFolder = 0; + return S_OK; +} + +IMP_IFolderFolder_Props(CFSDrives) + +STDMETHODIMP CFSDrives::GetFolderProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidType: prop = L"FSDrives"; break; + case kpidPath: + if (_volumeMode) + prop = kVolPrefix; + else + prop = LangString(IDS_COMPUTER, 0x03020300) + UString(WCHAR_PATH_SEPARATOR); + break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + + +STDMETHODIMP CFSDrives::GetSystemIconIndex(UInt32 index, Int32 *iconIndex) +{ + *iconIndex = 0; + const CDriveInfo &di = _drives[index]; + int iconIndexTemp; + if (GetRealIconIndex(di.FullSystemName, 0, iconIndexTemp) != 0) + { + *iconIndex = iconIndexTemp; + return S_OK; + } + return GetLastError(); +} + +UString CFSDrives::GetExt(int index) const +{ + const CDriveInfo &di = _drives[index]; + const wchar_t *ext = NULL; + if (di.DriveType == DRIVE_CDROM) + ext = L"iso"; + else if (di.FileSystemName.Find(L"NTFS") >= 0) + ext = L"ntfs"; + else if (di.FileSystemName.Find(L"FAT") >= 0) + ext = L"fat"; + else + ext = L"img"; + return (UString)L'.' + ext; +} + +HRESULT CFSDrives::GetLength(int index, UInt64 &length) const +{ + NFile::NIO::CInFile inFile; + if (!inFile.Open(_drives[index].GetDeviceFileIoName())) + return GetLastError(); + if (!inFile.LengthDefined) + return E_FAIL; + length = inFile.Length; + return S_OK; +} + +STDMETHODIMP CFSDrives::CopyTo(const UInt32 *indices, UInt32 numItems, + const wchar_t *path, IFolderOperationsExtractCallback *callback) +{ + if (numItems == 0) + return S_OK; + + if (!_volumeMode) + return E_NOTIMPL; + + UInt64 totalSize = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + { + const CDriveInfo &di = _drives[indices[i]]; + if (di.KnownSizes) + totalSize += di.DriveSize; + } + RINOK(callback->SetTotal(totalSize)); + RINOK(callback->SetNumFiles(numItems)); + + UString destPath = path; + if (destPath.IsEmpty()) + return E_INVALIDARG; + bool directName = (destPath[destPath.Length() - 1] != WCHAR_PATH_SEPARATOR); + if (directName) + { + if (numItems > 1) + return E_INVALIDARG; + } + + UInt64 completedSize = 0; + RINOK(callback->SetCompleted(&completedSize)); + for (i = 0; i < numItems; i++) + { + int index = indices[i]; + const CDriveInfo &di = _drives[index]; + UString destPath2 = destPath; + UString name = di.Name; + if (!directName) + { + UString destName = name; + if (!destName.IsEmpty() && destName[destName.Length() - 1] == L':') + { + destName.Delete(destName.Length() - 1); + destName += GetExt(index); + } + destPath2 += destName; + } + UString srcPath = di.GetDeviceFileIoName(); + + UInt64 fileSize = 0; + if (GetLength(index, fileSize) != S_OK) + { + return E_FAIL; + } + if (!di.KnownSizes) + totalSize += fileSize; + RINOK(callback->SetTotal(totalSize)); + + Int32 writeAskResult; + CMyComBSTR destPathResult; + RINOK(callback->AskWrite(srcPath, BoolToInt(false), NULL, &fileSize, + destPath2, &destPathResult, &writeAskResult)); + if (!IntToBool(writeAskResult)) + continue; + + RINOK(callback->SetCurrentFilePath(srcPath)); + + static const UInt32 kBufferSize = (4 << 20); + UInt32 bufferSize = (di.DriveType == DRIVE_REMOVABLE) ? (18 << 10) * 4 : kBufferSize; + RINOK(CopyFileSpec(srcPath, destPathResult, false, fileSize, bufferSize, completedSize, callback)); + completedSize += fileSize; + } + return S_OK; +} + +STDMETHODIMP CFSDrives::MoveTo( + const UInt32 * /* indices */, + UInt32 /* numItems */, + const wchar_t * /* path */, + IFolderOperationsExtractCallback * /* callback */) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CFSDrives::CopyFrom(const wchar_t * /* fromFolderPath */, + const wchar_t ** /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CFSDrives::CreateFolder(const wchar_t * /* name */, IProgress * /* progress */) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CFSDrives::CreateFile(const wchar_t * /* name */, IProgress * /* progress */) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CFSDrives::Rename(UInt32 /* index */, const wchar_t * /* newName */, IProgress * /* progress */) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CFSDrives::Delete(const UInt32 * /* indices */, UInt32 /* numItems */, IProgress * /* progress */) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CFSDrives::SetProperty(UInt32 /* index */, PROPID /* propID */, + const PROPVARIANT * /* value */, IProgress * /* progress */) +{ + return E_NOTIMPL; +} diff --git a/CPP/7zip/UI/FileManager/FSDrives.h b/CPP/7zip/UI/FileManager/FSDrives.h new file mode 100755 index 0000000..8513688 --- /dev/null +++ b/CPP/7zip/UI/FileManager/FSDrives.h @@ -0,0 +1,53 @@ +// FSDrives.h + +#ifndef __FS_DRIVES_H +#define __FS_DRIVES_H + +#include "Common/MyCom.h" +#include "Common/MyString.h" + +#include "IFolder.h" + +struct CDriveInfo +{ + UString Name; + UString FullSystemName; + bool KnownSizes; + UInt64 DriveSize; + UInt64 FreeSpace; + UInt64 ClusterSize; + // UString Type; + UString VolumeName; + UString FileSystemName; + UINT DriveType; + + UString GetDeviceFileIoName() const; +}; + +class CFSDrives: + public IFolderFolder, + public IFolderOperations, + public IFolderGetSystemIconIndex, + public CMyUnknownImp +{ + CObjectVector _drives; + bool _volumeMode; + + HRESULT BindToFolderSpec(const wchar_t *name, IFolderFolder **resultFolder); + UString GetExt(int index) const; + HRESULT GetLength(int index, UInt64 &length) const; +public: + MY_UNKNOWN_IMP2(IFolderGetSystemIconIndex, IFolderOperations) + + INTERFACE_FolderFolder(;) + INTERFACE_FolderOperations(;) + + STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex); + + void Init(bool volMode = false) + { + _volumeMode = volMode; + } +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/FSFolder.cpp b/CPP/7zip/UI/FileManager/FSFolder.cpp new file mode 100755 index 0000000..5664ccf --- /dev/null +++ b/CPP/7zip/UI/FileManager/FSFolder.cpp @@ -0,0 +1,665 @@ +// FSFolder.cpp + +#include "StdAfx.h" + +#include "Common/ComTry.h" +#include "Common/StringConvert.h" +#include "Common/UTFConvert.h" + +#include "Windows/FileDir.h" +#include "Windows/FileIO.h" +#include "Windows/PropVariant.h" + +#include "../../PropID.h" + +#include "FSDrives.h" +#include "FSFolder.h" + +#ifndef UNDER_CE +#include "NetFolder.h" +#endif + +#include "SysIconUtils.h" + +namespace NWindows { +namespace NFile { + +bool GetLongPath(LPCWSTR path, UString &longPath); + +}} + +using namespace NWindows; +using namespace NFile; +using namespace NFind; + +namespace NFsFolder { + +static STATPROPSTG kProps[] = +{ + { NULL, kpidName, VT_BSTR}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidATime, VT_FILETIME}, + { NULL, kpidAttrib, VT_UI4}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidComment, VT_BSTR}, + { NULL, kpidPrefix, VT_BSTR} +}; + +HRESULT CFSFolder::Init(const UString &path, IFolderFolder *parentFolder) +{ + _parentFolder = parentFolder; + _path = path; + + _findChangeNotification.FindFirst(_path, false, + FILE_NOTIFY_CHANGE_FILE_NAME | + FILE_NOTIFY_CHANGE_DIR_NAME | + FILE_NOTIFY_CHANGE_ATTRIBUTES | + FILE_NOTIFY_CHANGE_SIZE | + FILE_NOTIFY_CHANGE_LAST_WRITE /*| + FILE_NOTIFY_CHANGE_LAST_ACCESS | + FILE_NOTIFY_CHANGE_CREATION | + FILE_NOTIFY_CHANGE_SECURITY */); + if (!_findChangeNotification.IsHandleAllocated()) + { + DWORD lastError = GetLastError(); + CFindFile findFile; + CFileInfoW fi; + if (!findFile.FindFirst(_path + UString(L"*"), fi)) + return lastError; + } + return S_OK; +} + +HRESULT GetFolderSize(const UString &path, UInt64 &numFolders, UInt64 &numFiles, UInt64 &size, IProgress *progress) +{ + RINOK(progress->SetCompleted(NULL)); + numFiles = numFolders = size = 0; + CEnumeratorW enumerator(path + UString(WSTRING_PATH_SEPARATOR L"*")); + CFileInfoW fi; + while (enumerator.Next(fi)) + { + if (fi.IsDir()) + { + UInt64 subFolders, subFiles, subSize; + RINOK(GetFolderSize(path + UString(WCHAR_PATH_SEPARATOR) + fi.Name, subFolders, subFiles, subSize, progress)); + numFolders += subFolders; + numFolders++; + numFiles += subFiles; + size += subSize; + } + else + { + numFiles++; + size += fi.Size; + } + } + return S_OK; +} + +HRESULT CFSFolder::LoadSubItems(CDirItem &dirItem, const UString &path) +{ + { + CEnumeratorW enumerator(path + L"*"); + CDirItem fi; + while (enumerator.Next(fi)) + { + #ifndef UNDER_CE + fi.CompressedSizeIsDefined = false; + /* + if (!GetCompressedFileSize(_path + fi.Name, + fi.CompressedSize)) + fi.CompressedSize = fi.Size; + */ + #endif + if (fi.IsDir()) + { + // fi.Size = GetFolderSize(_path + fi.Name); + fi.Size = 0; + } + dirItem.Files.Add(fi); + } + } + if (!_flatMode) + return S_OK; + + for (int i = 0; i < dirItem.Files.Size(); i++) + { + CDirItem &item = dirItem.Files[i]; + if (item.IsDir()) + LoadSubItems(item, path + item.Name + WCHAR_PATH_SEPARATOR); + } + return S_OK; +} + +void CFSFolder::AddRefs(CDirItem &dirItem) +{ + int i; + for (i = 0; i < dirItem.Files.Size(); i++) + { + CDirItem &item = dirItem.Files[i]; + item.Parent = &dirItem; + _refs.Add(&item); + } + if (!_flatMode) + return; + for (i = 0; i < dirItem.Files.Size(); i++) + { + CDirItem &item = dirItem.Files[i]; + if (item.IsDir()) + AddRefs(item); + } +} + +STDMETHODIMP CFSFolder::LoadItems() +{ + // OutputDebugString(TEXT("Start\n")); + Int32 dummy; + WasChanged(&dummy); + Clear(); + RINOK(LoadSubItems(_root, _path)); + AddRefs(_root); + + // OutputDebugString(TEXT("Finish\n")); + _commentsAreLoaded = false; + return S_OK; +} + +static const wchar_t *kDescriptionFileName = L"descript.ion"; + +bool CFSFolder::LoadComments() +{ + if (_commentsAreLoaded) + return true; + _comments.Clear(); + _commentsAreLoaded = true; + NIO::CInFile file; + if (!file.Open(_path + kDescriptionFileName)) + return false; + UInt64 length; + if (!file.GetLength(length)) + return false; + if (length >= (1 << 28)) + return false; + AString s; + char *p = s.GetBuffer((int)((size_t)length + 1)); + UInt32 processedSize; + file.Read(p, (UInt32)length, processedSize); + p[length] = 0; + s.ReleaseBuffer(); + if (processedSize != length) + return false; + file.Close(); + UString unicodeString; + if (!ConvertUTF8ToUnicode(s, unicodeString)) + return false; + return _comments.ReadFromString(unicodeString); +} + +static bool IsAscii(const UString &testString) +{ + for (int i = 0; i < testString.Length(); i++) + if (testString[i] >= 0x80) + return false; + return true; +} + +bool CFSFolder::SaveComments() +{ + NIO::COutFile file; + if (!file.Create(_path + kDescriptionFileName, true)) + return false; + UString unicodeString; + _comments.SaveToString(unicodeString); + AString utfString; + ConvertUnicodeToUTF8(unicodeString, utfString); + UInt32 processedSize; + if (!IsAscii(unicodeString)) + { + Byte bom [] = { 0xEF, 0xBB, 0xBF, 0x0D, 0x0A }; + file.Write(bom , sizeof(bom), processedSize); + } + file.Write(utfString, utfString.Length(), processedSize); + _commentsAreLoaded = false; + return true; +} + +STDMETHODIMP CFSFolder::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _refs.Size(); + return S_OK; +} + +/* +STDMETHODIMP CFSFolder::GetNumberOfSubFolders(UInt32 *numSubFolders) +{ + UInt32 numSubFoldersLoc = 0; + for (int i = 0; i < _files.Size(); i++) + if (_files[i].IsDir()) + numSubFoldersLoc++; + *numSubFolders = numSubFoldersLoc; + return S_OK; +} +*/ + +#ifndef UNDER_CE +static bool MyGetCompressedFileSizeW(LPCWSTR fileName, UInt64 &size) +{ + DWORD highPart; + DWORD lowPart = ::GetCompressedFileSizeW(fileName, &highPart); + if (lowPart == INVALID_FILE_SIZE && ::GetLastError() != NO_ERROR) + { + #ifdef WIN_LONG_PATH + { + UString longPath; + if (GetLongPath(fileName, longPath)) + lowPart = ::GetCompressedFileSizeW(longPath, &highPart); + } + #endif + if (lowPart == INVALID_FILE_SIZE && ::GetLastError() != NO_ERROR) + return false; + } + size = (UInt64(highPart) << 32) | lowPart; + return true; +} +#endif + +STDMETHODIMP CFSFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + if (itemIndex >= (UInt32)_refs.Size()) + return E_INVALIDARG; + CDirItem &fi = *_refs[itemIndex]; + switch(propID) + { + case kpidIsDir: prop = fi.IsDir(); break; + case kpidName: prop = fi.Name; break; + case kpidSize: if (!fi.IsDir()) prop = fi.Size; break; + case kpidPackSize: + #ifdef UNDER_CE + prop = fi.Size; + #else + if (!fi.CompressedSizeIsDefined) + { + fi.CompressedSizeIsDefined = true; + if (fi.IsDir () || + !MyGetCompressedFileSizeW(_path + GetRelPath(fi), fi.CompressedSize)) + fi.CompressedSize = fi.Size; + } + prop = fi.CompressedSize; + #endif + break; + case kpidAttrib: prop = (UInt32)fi.Attrib; break; + case kpidCTime: prop = fi.CTime; break; + case kpidATime: prop = fi.ATime; break; + case kpidMTime: prop = fi.MTime; break; + case kpidComment: + { + LoadComments(); + UString comment; + if (_comments.GetValue(GetRelPath(fi), comment)) + prop = comment; + break; + } + case kpidPrefix: + { + if (_flatMode) + prop = GetPrefix(fi); + break; + } + } + prop.Detach(value); + return S_OK; +} + +HRESULT CFSFolder::BindToFolderSpec(const wchar_t *name, IFolderFolder **resultFolder) +{ + *resultFolder = 0; + CFSFolder *folderSpec = new CFSFolder; + CMyComPtr subFolder = folderSpec; + RINOK(folderSpec->Init(_path + name + UString(WCHAR_PATH_SEPARATOR), 0)); + *resultFolder = subFolder.Detach(); + return S_OK; +} + +UString CFSFolder::GetPrefix(const CDirItem &item) const +{ + UString path; + CDirItem *cur = item.Parent; + while (cur->Parent != 0) + { + path = cur->Name + UString(WCHAR_PATH_SEPARATOR) + path; + cur = cur->Parent; + } + return path; +} + +UString CFSFolder::GetRelPath(const CDirItem &item) const +{ + return GetPrefix(item) + item.Name; +} + +STDMETHODIMP CFSFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder) +{ + *resultFolder = 0; + const CDirItem &fi = *_refs[index]; + if (!fi.IsDir()) + return E_INVALIDARG; + return BindToFolderSpec(GetRelPath(fi), resultFolder); +} + +STDMETHODIMP CFSFolder::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder) +{ + return BindToFolderSpec(name, resultFolder); +} + +STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder) +{ + *resultFolder = 0; + if (_parentFolder) + { + CMyComPtr parentFolder = _parentFolder; + *resultFolder = parentFolder.Detach(); + return S_OK; + } + if (_path.IsEmpty()) + return E_INVALIDARG; + int pos = _path.ReverseFind(WCHAR_PATH_SEPARATOR); + if (pos < 0 || pos != _path.Length() - 1) + return E_FAIL; + UString parentPath = _path.Left(pos); + pos = parentPath.ReverseFind(WCHAR_PATH_SEPARATOR); + if (pos < 0) + { + #ifdef UNDER_CE + *resultFolder = 0; + #else + CFSDrives *drivesFolderSpec = new CFSDrives; + CMyComPtr drivesFolder = drivesFolderSpec; + drivesFolderSpec->Init(); + *resultFolder = drivesFolder.Detach(); + #endif + return S_OK; + } + UString parentPathReduced = parentPath.Left(pos); + parentPath = parentPath.Left(pos + 1); + #ifndef UNDER_CE + pos = parentPathReduced.ReverseFind(WCHAR_PATH_SEPARATOR); + if (pos == 1) + { + if (parentPath[0] != WCHAR_PATH_SEPARATOR) + return E_FAIL; + CNetFolder *netFolderSpec = new CNetFolder; + CMyComPtr netFolder = netFolderSpec; + netFolderSpec->Init(parentPath); + *resultFolder = netFolder.Detach(); + return S_OK; + } + #endif + CFSFolder *parentFolderSpec = new CFSFolder; + CMyComPtr parentFolder = parentFolderSpec; + RINOK(parentFolderSpec->Init(parentPath, 0)); + *resultFolder = parentFolder.Detach(); + return S_OK; +} + +STDMETHODIMP CFSFolder::GetNumberOfProperties(UInt32 *numProperties) +{ + *numProperties = sizeof(kProps) / sizeof(kProps[0]); + if (!_flatMode) + (*numProperties)--; + return S_OK; +} + +STDMETHODIMP CFSFolder::GetPropertyInfo IMP_IFolderFolder_GetProp(kProps) + +STDMETHODIMP CFSFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidType: prop = L"FSFolder"; break; + case kpidPath: prop = _path; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CFSFolder::WasChanged(Int32 *wasChanged) +{ + bool wasChangedMain = false; + for (;;) + { + if (!_findChangeNotification.IsHandleAllocated()) + { + *wasChanged = BoolToInt(false); + return S_OK; + } + + DWORD waitResult = ::WaitForSingleObject(_findChangeNotification, 0); + bool wasChangedLoc = (waitResult == WAIT_OBJECT_0); + if (wasChangedLoc) + { + _findChangeNotification.FindNext(); + wasChangedMain = true; + } + else + break; + } + *wasChanged = BoolToInt(wasChangedMain); + return S_OK; +} + +STDMETHODIMP CFSFolder::Clone(IFolderFolder **resultFolder) +{ + CFSFolder *fsFolderSpec = new CFSFolder; + CMyComPtr folderNew = fsFolderSpec; + fsFolderSpec->Init(_path, 0); + *resultFolder = folderNew.Detach(); + return S_OK; +} + +HRESULT CFSFolder::GetItemsFullSize(const UInt32 *indices, UInt32 numItems, + UInt64 &numFolders, UInt64 &numFiles, UInt64 &size, IProgress *progress) +{ + numFiles = numFolders = size = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + { + int index = indices[i]; + if (index >= _refs.Size()) + return E_INVALIDARG; + const CDirItem &fi = *_refs[index]; + if (fi.IsDir()) + { + UInt64 subFolders, subFiles, subSize; + RINOK(GetFolderSize(_path + GetRelPath(fi), subFolders, subFiles, subSize, progress)); + numFolders += subFolders; + numFolders++; + numFiles += subFiles; + size += subSize; + } + else + { + numFiles++; + size += fi.Size; + } + } + return S_OK; +} + +HRESULT CFSFolder::GetItemFullSize(int index, UInt64 &size, IProgress *progress) +{ + const CDirItem &fi = *_refs[index]; + if (fi.IsDir()) + { + /* + CMyComPtr subFolder; + RINOK(BindToFolder(index, &subFolder)); + CMyComPtr aFolderReload; + subFolder.QueryInterface(&aFolderReload); + aFolderReload->Reload(); + UInt32 numItems; + RINOK(subFolder->GetNumberOfItems(&numItems)); + CMyComPtr aGetItemFullSize; + subFolder.QueryInterface(&aGetItemFullSize); + for (UInt32 i = 0; i < numItems; i++) + { + UInt64 size; + RINOK(aGetItemFullSize->GetItemFullSize(i, &size)); + *totalSize += size; + } + */ + UInt64 numFolders, numFiles; + return GetFolderSize(_path + GetRelPath(fi), numFolders, numFiles, size, progress); + } + size = fi.Size; + return S_OK; +} + +STDMETHODIMP CFSFolder::GetItemFullSize(UInt32 index, PROPVARIANT *value, IProgress *progress) +{ + NCOM::CPropVariant prop; + if (index >= (UInt32)_refs.Size()) + return E_INVALIDARG; + UInt64 size = 0; + HRESULT result = GetItemFullSize(index, size, progress); + prop = size; + prop.Detach(value); + return result; +} + +HRESULT CFSFolder::GetComplexName(const wchar_t *name, UString &resultPath) +{ + UString newName = name; + resultPath = _path + newName; + if (newName.Length() < 1) + return S_OK; + if (newName[0] == WCHAR_PATH_SEPARATOR) + { + resultPath = newName; + return S_OK; + } + if (newName.Length() < 2) + return S_OK; + if (newName[1] == L':') + resultPath = newName; + return S_OK; +} + +STDMETHODIMP CFSFolder::CreateFolder(const wchar_t *name, IProgress * /* progress */) +{ + UString processedName; + RINOK(GetComplexName(name, processedName)); + if(NDirectory::MyCreateDirectory(processedName)) + return S_OK; + if(::GetLastError() == ERROR_ALREADY_EXISTS) + return ::GetLastError(); + if (!NDirectory::CreateComplexDirectory(processedName)) + return ::GetLastError(); + return S_OK; +} + +STDMETHODIMP CFSFolder::CreateFile(const wchar_t *name, IProgress * /* progress */) +{ + UString processedName; + RINOK(GetComplexName(name, processedName)); + NIO::COutFile outFile; + if (!outFile.Create(processedName, false)) + return ::GetLastError(); + return S_OK; +} + +STDMETHODIMP CFSFolder::Rename(UInt32 index, const wchar_t *newName, IProgress * /* progress */) +{ + const CDirItem &fi = *_refs[index]; + const UString fullPrefix = _path + GetPrefix(fi); + if (!NDirectory::MyMoveFile(fullPrefix + fi.Name, fullPrefix + newName)) + return GetLastError(); + return S_OK; +} + +STDMETHODIMP CFSFolder::Delete(const UInt32 *indices, UInt32 numItems,IProgress *progress) +{ + RINOK(progress->SetTotal(numItems)); + for (UInt32 i = 0; i < numItems; i++) + { + const CDirItem &fi = *_refs[indices[i]]; + const UString fullPath = _path + GetRelPath(fi); + bool result; + if (fi.IsDir()) + result = NDirectory::RemoveDirectoryWithSubItems(fullPath); + else + result = NDirectory::DeleteFileAlways(fullPath); + if (!result) + return GetLastError(); + UInt64 completed = i; + RINOK(progress->SetCompleted(&completed)); + } + return S_OK; +} + +STDMETHODIMP CFSFolder::SetProperty(UInt32 index, PROPID propID, + const PROPVARIANT *value, IProgress * /* progress */) +{ + if (index >= (UInt32)_refs.Size()) + return E_INVALIDARG; + CDirItem &fi = *_refs[index]; + if (fi.Parent->Parent != 0) + return E_NOTIMPL; + switch(propID) + { + case kpidComment: + { + UString filename = fi.Name; + filename.Trim(); + if (value->vt == VT_EMPTY) + _comments.DeletePair(filename); + else if (value->vt == VT_BSTR) + { + CTextPair pair; + pair.ID = filename; + pair.ID.Trim(); + pair.Value = value->bstrVal; + pair.Value.Trim(); + if (pair.Value.IsEmpty()) + _comments.DeletePair(filename); + else + _comments.AddPair(pair); + } + else + return E_INVALIDARG; + SaveComments(); + break; + } + default: + return E_NOTIMPL; + } + return S_OK; +} + +STDMETHODIMP CFSFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex) +{ + if (index >= (UInt32)_refs.Size()) + return E_INVALIDARG; + const CDirItem &fi = *_refs[index]; + *iconIndex = 0; + int iconIndexTemp; + if (GetRealIconIndex(_path + GetRelPath(fi), fi.Attrib, iconIndexTemp) != 0) + { + *iconIndex = iconIndexTemp; + return S_OK; + } + return GetLastError(); +} + +STDMETHODIMP CFSFolder::SetFlatMode(Int32 flatMode) +{ + _flatMode = IntToBool(flatMode); + return S_OK; +} + +} diff --git a/CPP/7zip/UI/FileManager/FSFolder.h b/CPP/7zip/UI/FileManager/FSFolder.h new file mode 100755 index 0000000..23797e0 --- /dev/null +++ b/CPP/7zip/UI/FileManager/FSFolder.h @@ -0,0 +1,123 @@ +// FSFolder.h + +#ifndef __FSFOLDER_H +#define __FSFOLDER_H + +#include "Common/MyCom.h" + +#include "Windows/FileFind.h" + +#include "IFolder.h" +#include "TextPairs.h" + +namespace NFsFolder { + +class CFSFolder; + +struct CFileInfoEx: public NWindows::NFile::NFind::CFileInfoW +{ + #ifndef UNDER_CE + bool CompressedSizeIsDefined; + UInt64 CompressedSize; + #endif +}; + +struct CDirItem; + +struct CDirItem: public CFileInfoEx +{ + CDirItem *Parent; + CObjectVector Files; + + CDirItem(): Parent(0) {} + void Clear() + { + Files.Clear(); + Parent = 0; + } +}; + +class CFSFolder: + public IFolderFolder, + public IFolderWasChanged, + public IFolderOperations, + // public IFolderOperationsDeleteToRecycleBin, + public IFolderGetItemFullSize, + public IFolderClone, + public IFolderGetSystemIconIndex, + public IFolderSetFlatMode, + public CMyUnknownImp +{ + UInt64 GetSizeOfItem(int anIndex) const; +public: + MY_QUERYINTERFACE_BEGIN2(IFolderFolder) + MY_QUERYINTERFACE_ENTRY(IFolderWasChanged) + // MY_QUERYINTERFACE_ENTRY(IFolderOperationsDeleteToRecycleBin) + MY_QUERYINTERFACE_ENTRY(IFolderOperations) + MY_QUERYINTERFACE_ENTRY(IFolderGetItemFullSize) + MY_QUERYINTERFACE_ENTRY(IFolderClone) + MY_QUERYINTERFACE_ENTRY(IFolderGetSystemIconIndex) + MY_QUERYINTERFACE_ENTRY(IFolderSetFlatMode) + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + + INTERFACE_FolderFolder(;) + INTERFACE_FolderOperations(;) + + STDMETHOD(WasChanged)(Int32 *wasChanged); + STDMETHOD(Clone)(IFolderFolder **resultFolder); + STDMETHOD(GetItemFullSize)(UInt32 index, PROPVARIANT *value, IProgress *progress); + + STDMETHOD(SetFlatMode)(Int32 flatMode); + + STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex); + +private: + UString _path; + CDirItem _root; + CRecordVector _refs; + + CMyComPtr _parentFolder; + + bool _commentsAreLoaded; + CPairsStorage _comments; + + bool _flatMode; + + NWindows::NFile::NFind::CFindChangeNotification _findChangeNotification; + + HRESULT GetItemsFullSize(const UInt32 *indices, UInt32 numItems, + UInt64 &numFolders, UInt64 &numFiles, UInt64 &size, IProgress *progress); + HRESULT GetItemFullSize(int index, UInt64 &size, IProgress *progress); + HRESULT GetComplexName(const wchar_t *name, UString &resultPath); + HRESULT BindToFolderSpec(const wchar_t *name, IFolderFolder **resultFolder); + + bool LoadComments(); + bool SaveComments(); + HRESULT LoadSubItems(CDirItem &dirItem, const UString &path); + void AddRefs(CDirItem &dirItem); +public: + HRESULT Init(const UString &path, IFolderFolder *parentFolder); + #ifdef UNDER_CE + HRESULT InitToRoot() { return Init(L"\\", NULL); } + #endif + + CFSFolder() : _flatMode(false) {} + + UString GetPrefix(const CDirItem &item) const; + UString GetRelPath(const CDirItem &item) const; + UString GetRelPath(UInt32 index) const { return GetRelPath(*_refs[index]); } + + void Clear() + { + _root.Clear(); + _refs.Clear(); + } +}; + +HRESULT GetFolderSize(const UString &path, UInt64 &numFolders, UInt64 &numFiles, UInt64 &size, IProgress *progress); + +} + +#endif diff --git a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp new file mode 100755 index 0000000..3cd14a6 --- /dev/null +++ b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp @@ -0,0 +1,547 @@ +// FSFolderCopy.cpp + +#include "StdAfx.h" + +#include + +#include "Common/StringConvert.h" + +#include "Windows/DLL.h" +#include "Windows/Error.h" +#include "Windows/FileDir.h" + +#include "../../Common/FilePathAutoRename.h" + +#include "FSFolder.h" + +using namespace NWindows; +using namespace NFile; +using namespace NFind; + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NFsFolder { + +/* +static bool IsItWindows2000orHigher() +{ + OSVERSIONINFO versionInfo; + versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); + if (!::GetVersionEx(&versionInfo)) + return false; + return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) && + (versionInfo.dwMajorVersion >= 5); +} +*/ + +struct CProgressInfo +{ + UInt64 StartPos; + IProgress *Progress; +}; + +#ifndef PROGRESS_CONTINUE + +#define PROGRESS_CONTINUE 0 +#define PROGRESS_CANCEL 1 + +#define COPY_FILE_FAIL_IF_EXISTS 0x00000001 + +typedef +DWORD +(WINAPI* LPPROGRESS_ROUTINE)( + LARGE_INTEGER TotalFileSize, + LARGE_INTEGER TotalBytesTransferred, + LARGE_INTEGER StreamSize, + LARGE_INTEGER StreamBytesTransferred, + DWORD dwStreamNumber, + DWORD dwCallbackReason, + HANDLE hSourceFile, + HANDLE hDestinationFile, + LPVOID lpData + ); + +#endif + +static DWORD CALLBACK CopyProgressRoutine( + LARGE_INTEGER /* TotalFileSize */, // file size + LARGE_INTEGER TotalBytesTransferred, // bytes transferred + LARGE_INTEGER /* StreamSize */, // bytes in stream + LARGE_INTEGER /* StreamBytesTransferred */, // bytes transferred for stream + DWORD /* dwStreamNumber */, // current stream + DWORD /* dwCallbackReason */, // callback reason + HANDLE /* hSourceFile */, // handle to source file + HANDLE /* hDestinationFile */, // handle to destination file + LPVOID lpData // from CopyFileEx +) +{ + CProgressInfo &progressInfo = *(CProgressInfo *)lpData; + UInt64 completed = progressInfo.StartPos + TotalBytesTransferred.QuadPart; + if (progressInfo.Progress->SetCompleted(&completed) != S_OK) + return PROGRESS_CANCEL; + return PROGRESS_CONTINUE; +} + +typedef BOOL (WINAPI * CopyFileExPointer)( + IN LPCSTR lpExistingFileName, + IN LPCSTR lpNewFileName, + IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL, + IN LPVOID lpData OPTIONAL, + IN LPBOOL pbCancel OPTIONAL, + IN DWORD dwCopyFlags + ); + +typedef BOOL (WINAPI * CopyFileExPointerW)( + IN LPCWSTR lpExistingFileName, + IN LPCWSTR lpNewFileName, + IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL, + IN LPVOID lpData OPTIONAL, + IN LPBOOL pbCancel OPTIONAL, + IN DWORD dwCopyFlags + ); + +#ifndef _UNICODE +static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } +static CSysString GetSysPath(LPCWSTR sysPath) + { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } +#endif + +static bool MyCopyFile(LPCWSTR existingFile, LPCWSTR newFile, IProgress *progress, UInt64 &completedSize) +{ + CProgressInfo progressInfo; + progressInfo.Progress = progress; + progressInfo.StartPos = completedSize; + BOOL CancelFlag = FALSE; + #ifndef _UNICODE + if (g_IsNT) + #endif + { + const wchar_t *k_DllName = + #ifdef UNDER_CE + L"coredll.dll" + #else + L"kernel32.dll" + #endif + ; + CopyFileExPointerW copyFunctionW = (CopyFileExPointerW) + My_GetProcAddress(::GetModuleHandleW(k_DllName), "CopyFileExW"); + if (copyFunctionW == 0) + return BOOLToBool(::CopyFileW(existingFile, newFile, TRUE)); + if (copyFunctionW(existingFile, newFile, CopyProgressRoutine, + &progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS)) + return true; + #ifdef WIN_LONG_PATH + UString longPathExisting, longPathNew; + if (!NDirectory::GetLongPaths(existingFile, newFile, longPathExisting, longPathNew)) + return false; + if (copyFunctionW(longPathExisting, longPathNew, CopyProgressRoutine, + &progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS)) + return true; + #endif + return false; + } + #ifndef _UNICODE + else + { + CopyFileExPointer copyFunction = (CopyFileExPointer) + ::GetProcAddress(::GetModuleHandleA("kernel32.dll"), + "CopyFileExA"); + if (copyFunction != 0) + { + if (copyFunction(GetSysPath(existingFile), GetSysPath(newFile), + CopyProgressRoutine,&progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS)) + return true; + if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return false; + } + return BOOLToBool(::CopyFile(GetSysPath(existingFile), GetSysPath(newFile), TRUE)); + } + #endif +} + +typedef BOOL (WINAPI * MoveFileWithProgressPointer)( + IN LPCWSTR lpExistingFileName, + IN LPCWSTR lpNewFileName, + IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL, + IN LPVOID lpData OPTIONAL, + IN DWORD dwFlags + ); + +static bool MyMoveFile(LPCWSTR existingFile, LPCWSTR newFile, IProgress *progress, UInt64 &completedSize) +{ + #ifndef UNDER_CE + // if (IsItWindows2000orHigher()) + // { + CProgressInfo progressInfo; + progressInfo.Progress = progress; + progressInfo.StartPos = completedSize; + + MoveFileWithProgressPointer moveFunction = (MoveFileWithProgressPointer) + My_GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), + "MoveFileWithProgressW"); + if (moveFunction != 0) + { + if (moveFunction( + existingFile, newFile, CopyProgressRoutine, + &progressInfo, MOVEFILE_COPY_ALLOWED)) + return true; + if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + { + #ifdef WIN_LONG_PATH + UString longPathExisting, longPathNew; + if (!NDirectory::GetLongPaths(existingFile, newFile, longPathExisting, longPathNew)) + return false; + if (moveFunction(longPathExisting, longPathNew, CopyProgressRoutine, + &progressInfo, MOVEFILE_COPY_ALLOWED)) + return true; + #endif + if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return false; + } + } + // } + // else + #endif + return NDirectory::MyMoveFile(existingFile, newFile); +} + +static HRESULT MyCopyFile( + const UString &srcPath, + const CFileInfoW &srcFileInfo, + const UString &destPathSpec, + IFolderOperationsExtractCallback *callback, + UInt64 &completedSize) +{ + UString destPath = destPathSpec; + if (destPath.CompareNoCase(srcPath) == 0) + { + UString message = UString(L"can not move file \'") + destPath + UString(L"\' onto itself"); + RINOK(callback->ShowMessage(message)); + return E_ABORT; + } + + Int32 writeAskResult; + CMyComBSTR destPathResult; + RINOK(callback->AskWrite( + srcPath, + BoolToInt(false), + &srcFileInfo.MTime, &srcFileInfo.Size, + destPath, + &destPathResult, + &writeAskResult)); + if (IntToBool(writeAskResult)) + { + UString destPathNew = UString(destPathResult); + RINOK(callback->SetCurrentFilePath(srcPath)); + if (!MyCopyFile(srcPath, destPathNew, callback, completedSize)) + { + UString message = NError::MyFormatMessageW(GetLastError()) + + UString(L" \'") + + UString(destPathNew) + + UString(L"\'"); + RINOK(callback->ShowMessage(message)); + return E_ABORT; + } + } + completedSize += srcFileInfo.Size; + return callback->SetCompleted(&completedSize); +} + +static UString CombinePath(const UString &folderPath, const UString &fileName) +{ + return folderPath + UString(WCHAR_PATH_SEPARATOR) + fileName; +} + +static HRESULT CopyFolder( + const UString &srcPath, + const UString &destPathSpec, + IFolderOperationsExtractCallback *callback, + UInt64 &completedSize) +{ + RINOK(callback->SetCompleted(&completedSize)); + + const UString destPath = destPathSpec; + int len = srcPath.Length(); + if (destPath.Length() >= len && srcPath.CompareNoCase(destPath.Left(len)) == 0) + { + if (destPath.Length() == len || destPath[len] == WCHAR_PATH_SEPARATOR) + { + UString message = UString(L"can not copy folder \'") + + destPath + UString(L"\' onto itself"); + RINOK(callback->ShowMessage(message)); + return E_ABORT; + } + } + + if (!NDirectory::CreateComplexDirectory(destPath)) + { + UString message = UString(L"can not create folder ") + destPath; + RINOK(callback->ShowMessage(message)); + return E_ABORT; + } + CEnumeratorW enumerator(CombinePath(srcPath, L"*")); + CFileInfoEx fi; + while (enumerator.Next(fi)) + { + const UString srcPath2 = CombinePath(srcPath, fi.Name); + const UString destPath2 = CombinePath(destPath, fi.Name); + if (fi.IsDir()) + { + RINOK(CopyFolder(srcPath2, destPath2, callback, completedSize)) + } + else + { + RINOK(MyCopyFile(srcPath2, fi, destPath2, callback, completedSize)); + } + } + return S_OK; +} + +STDMETHODIMP CFSFolder::CopyTo(const UInt32 *indices, UInt32 numItems, + const wchar_t *path, IFolderOperationsExtractCallback *callback) +{ + if (numItems == 0) + return S_OK; + + UInt64 numFolders, numFiles, totalSize; + GetItemsFullSize(indices, numItems, numFolders, numFiles, totalSize, callback); + RINOK(callback->SetTotal(totalSize)); + RINOK(callback->SetNumFiles(numFiles)); + + UString destPath = path; + if (destPath.IsEmpty()) + return E_INVALIDARG; + bool directName = (destPath[destPath.Length() - 1] != WCHAR_PATH_SEPARATOR); + if (directName) + { + if (numItems > 1) + return E_INVALIDARG; + } + /* + // doesn't work in network + else + if (!NDirectory::CreateComplexDirectory(destPath))) + { + DWORD lastError = ::GetLastError(); + UString message = UString(L"can not create folder ") + + destPath; + RINOK(callback->ShowMessage(message)); + return E_ABORT; + } + */ + + UInt64 completedSize = 0; + RINOK(callback->SetCompleted(&completedSize)); + for (UInt32 i = 0; i < numItems; i++) + { + const CDirItem &fi = *_refs[indices[i]]; + UString destPath2 = destPath; + if (!directName) + destPath2 += fi.Name; + UString srcPath = _path + GetPrefix(fi) + fi.Name; + if (fi.IsDir()) + { + RINOK(CopyFolder(srcPath, destPath2, callback, completedSize)); + } + else + { + RINOK(MyCopyFile(srcPath, fi, destPath2, callback, completedSize)); + } + } + return S_OK; +} + +///////////////////////////////////////////////// +// Move Operations + +HRESULT MyMoveFile( + const UString &srcPath, + const CFileInfoW &srcFileInfo, + const UString &destPathSpec, + IFolderOperationsExtractCallback *callback, + UInt64 &completedSize) +{ + UString destPath = destPathSpec; + if (destPath.CompareNoCase(srcPath) == 0) + { + UString message = UString(L"can not move file \'") + + destPath + + UString(L"\' onto itself"); + RINOK(callback->ShowMessage(message)); + return E_ABORT; + } + + Int32 writeAskResult; + CMyComBSTR destPathResult; + RINOK(callback->AskWrite( + srcPath, + BoolToInt(false), + &srcFileInfo.MTime, &srcFileInfo.Size, + destPath, + &destPathResult, + &writeAskResult)); + if (IntToBool(writeAskResult)) + { + UString destPathNew = UString(destPathResult); + RINOK(callback->SetCurrentFilePath(srcPath)); + if (!MyMoveFile(srcPath, destPathNew, callback, completedSize)) + { + UString message = UString(L"can not move to file ") + destPathNew; + RINOK(callback->ShowMessage(message)); + } + } + completedSize += srcFileInfo.Size; + RINOK(callback->SetCompleted(&completedSize)); + return S_OK; +} + +HRESULT MyMoveFolder( + const UString &srcPath, + const UString &destPathSpec, + IFolderOperationsExtractCallback *callback, + UInt64 &completedSize) +{ + UString destPath = destPathSpec; + int len = srcPath.Length(); + if (destPath.Length() >= len && srcPath.CompareNoCase(destPath.Left(len)) == 0) + { + if (destPath.Length() == len || destPath[len] == WCHAR_PATH_SEPARATOR) + { + UString message = UString(L"can not move folder \'") + + destPath + UString(L"\' onto itself"); + RINOK(callback->ShowMessage(message)); + return E_ABORT; + } + } + + if (MyMoveFile(srcPath, destPath, callback, completedSize)) + return S_OK; + + if (!NDirectory::CreateComplexDirectory(destPath)) + { + UString message = UString(L"can not create folder ") + destPath; + RINOK(callback->ShowMessage(message)); + return E_ABORT; + } + { + CEnumeratorW enumerator(CombinePath(srcPath, L"*")); + CFileInfoEx fi; + while (enumerator.Next(fi)) + { + const UString srcPath2 = CombinePath(srcPath, fi.Name); + const UString destPath2 = CombinePath(destPath, fi.Name); + if (fi.IsDir()) + { + RINOK(MyMoveFolder(srcPath2, destPath2, callback, completedSize)); + } + else + { + RINOK(MyMoveFile(srcPath2, fi, destPath2, callback, completedSize)); + } + } + } + if (!NDirectory::MyRemoveDirectory(srcPath)) + { + UString message = UString(L"can not remove folder") + srcPath; + RINOK(callback->ShowMessage(message)); + return E_ABORT; + } + return S_OK; +} + +STDMETHODIMP CFSFolder::MoveTo( + const UInt32 *indices, + UInt32 numItems, + const wchar_t *path, + IFolderOperationsExtractCallback *callback) +{ + if (numItems == 0) + return S_OK; + + UInt64 numFolders, numFiles, totalSize; + GetItemsFullSize(indices, numItems, numFolders, numFiles, totalSize, callback); + RINOK(callback->SetTotal(totalSize)); + RINOK(callback->SetNumFiles(numFiles)); + + UString destPath = path; + if (destPath.IsEmpty()) + return E_INVALIDARG; + bool directName = (destPath[destPath.Length() - 1] != WCHAR_PATH_SEPARATOR); + if (directName) + { + if (numItems > 1) + return E_INVALIDARG; + } + else + if (!NDirectory::CreateComplexDirectory(destPath)) + { + UString message = UString(L"can not create folder ") + + destPath; + RINOK(callback->ShowMessage(message)); + return E_ABORT; + } + + UInt64 completedSize = 0; + RINOK(callback->SetCompleted(&completedSize)); + for (UInt32 i = 0; i < numItems; i++) + { + const CDirItem &fi = *_refs[indices[i]]; + UString destPath2 = destPath; + if (!directName) + destPath2 += fi.Name; + UString srcPath = _path + GetPrefix(fi) + fi.Name; + if (fi.IsDir()) + { + RINOK(MyMoveFolder(srcPath, destPath2, callback, completedSize)); + } + else + { + RINOK(MyMoveFile(srcPath, fi, destPath2, callback, completedSize)); + } + } + return S_OK; +} + +STDMETHODIMP CFSFolder::CopyFrom(const wchar_t * /* fromFolderPath */, + const wchar_t ** /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */) +{ + /* + UInt64 numFolders, numFiles, totalSize; + numFiles = numFolders = totalSize = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + { + UString path = (UString)fromFolderPath + itemsPaths[i]; + + CFileInfoW fi; + if (!FindFile(path, fi)) + return ::GetLastError(); + if (fi.IsDir()) + { + UInt64 subFolders, subFiles, subSize; + RINOK(GetFolderSize(CombinePath(path, fi.Name), subFolders, subFiles, subSize, progress)); + numFolders += subFolders; + numFolders++; + numFiles += subFiles; + totalSize += subSize; + } + else + { + numFiles++; + totalSize += fi.Size; + } + } + RINOK(progress->SetTotal(totalSize)); + RINOK(callback->SetNumFiles(numFiles)); + for (i = 0; i < numItems; i++) + { + UString path = (UString)fromFolderPath + itemsPaths[i]; + } + return S_OK; + */ + return E_NOTIMPL; +} + +} diff --git a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp new file mode 100755 index 0000000..9a598ce --- /dev/null +++ b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp @@ -0,0 +1,166 @@ +// FileFolderPluginOpen.cpp + +#include "StdAfx.h" + +#include "resource.h" + +#include "Windows/Thread.h" + +#include "../Agent/Agent.h" + +#include "LangUtils.h" +#include "OpenCallback.h" +#include "PluginLoader.h" +#include "RegistryAssociations.h" +#include "RegistryPlugins.h" + +using namespace NWindows; +using namespace NRegistryAssociations; + +struct CThreadArchiveOpen +{ + UString Path; + UString ArcFormat; + CMyComPtr InStream; + CMyComPtr FolderManager; + CMyComPtr OpenCallback; + COpenArchiveCallback *OpenCallbackSpec; + + CMyComPtr Folder; + HRESULT Result; + + void Process() + { + try + { + CProgressCloser closer(OpenCallbackSpec->ProgressDialog); + Result = FolderManager->OpenFolderFile(InStream, Path, ArcFormat, &Folder, OpenCallback); + } + catch(...) { Result = E_FAIL; } + } + + static THREAD_FUNC_DECL MyThreadFunction(void *param) + { + ((CThreadArchiveOpen *)param)->Process(); + return 0; + } +}; + +/* +static int FindPlugin(const CObjectVector &plugins, const UString &pluginName) +{ + for (int i = 0; i < plugins.Size(); i++) + if (plugins[i].Name.CompareNoCase(pluginName) == 0) + return i; + return -1; +} +*/ + +HRESULT OpenFileFolderPlugin( + IInStream *inStream, + const UString &path, + const UString &arcFormat, + HMODULE *module, + IFolderFolder **resultFolder, + HWND parentWindow, + bool &encrypted, UString &password) +{ + CObjectVector plugins; + ReadFileFolderPluginInfoList(plugins); + + UString extension, name, pureName, dot; + + int slashPos = path.ReverseFind(WCHAR_PATH_SEPARATOR); + UString dirPrefix; + UString fileName; + if (slashPos >= 0) + { + dirPrefix = path.Left(slashPos + 1); + fileName = path.Mid(slashPos + 1); + } + else + fileName = path; + + NFile::NName::SplitNameToPureNameAndExtension(fileName, pureName, dot, extension); + + /* + if (!extension.IsEmpty()) + { + CExtInfo extInfo; + if (ReadInternalAssociation(extension, extInfo)) + { + for (int i = extInfo.Plugins.Size() - 1; i >= 0; i--) + { + int pluginIndex = FindPlugin(plugins, extInfo.Plugins[i]); + if (pluginIndex >= 0) + { + const CPluginInfo plugin = plugins[pluginIndex]; + plugins.Delete(pluginIndex); + plugins.Insert(0, plugin); + } + } + } + } + */ + + for (int i = 0; i < plugins.Size(); i++) + { + const CPluginInfo &plugin = plugins[i]; + if (!plugin.ClassIDDefined) + continue; + CPluginLibrary library; + + CThreadArchiveOpen t; + + if (plugin.FilePath.IsEmpty()) + t.FolderManager = new CArchiveFolderManager; + else if (library.LoadAndCreateManager(plugin.FilePath, plugin.ClassID, &t.FolderManager) != S_OK) + continue; + + t.OpenCallbackSpec = new COpenArchiveCallback; + t.OpenCallback = t.OpenCallbackSpec; + t.OpenCallbackSpec->PasswordIsDefined = encrypted; + t.OpenCallbackSpec->Password = password; + t.OpenCallbackSpec->ParentWindow = parentWindow; + + if (inStream) + t.OpenCallbackSpec->SetSubArchiveName(fileName); + else + t.OpenCallbackSpec->LoadFileInfo(dirPrefix, fileName); + + t.InStream = inStream; + t.Path = path; + t.ArcFormat = arcFormat; + + UString progressTitle = LangString(IDS_OPENNING, 0x03020283); + t.OpenCallbackSpec->ProgressDialog.MainWindow = parentWindow; + t.OpenCallbackSpec->ProgressDialog.MainTitle = LangString(IDS_APP_TITLE, 0x03000000); + t.OpenCallbackSpec->ProgressDialog.MainAddTitle = progressTitle + UString(L" "); + t.OpenCallbackSpec->ProgressDialog.WaitMode = true; + + { + NWindows::CThread thread; + RINOK(thread.Create(CThreadArchiveOpen::MyThreadFunction, &t)); + t.OpenCallbackSpec->StartProgressDialog(progressTitle, thread); + } + + if (t.Result == E_ABORT) + return t.Result; + + if (t.Result == S_OK) + { + // if (openCallbackSpec->PasswordWasAsked) + { + encrypted = t.OpenCallbackSpec->PasswordIsDefined; + password = t.OpenCallbackSpec->Password; + } + *module = library.Detach(); + *resultFolder = t.Folder.Detach(); + return S_OK; + } + + if (t.Result != S_FALSE) + return t.Result; + } + return S_FALSE; +} diff --git a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.h b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.h new file mode 100755 index 0000000..9aeac42 --- /dev/null +++ b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.h @@ -0,0 +1,9 @@ +// FileFolderPluginOpen.h + +#ifndef __FILE_FOLDER_PLUGIN_OPEN_H +#define __FILE_FOLDER_PLUGIN_OPEN_H + +HRESULT OpenFileFolderPlugin(IInStream *inStream, const UString &path, const UString &arcFormat, + HMODULE *module, IFolderFolder **resultFolder, HWND parentWindow, bool &encrypted, UString &password); + +#endif diff --git a/CPP/7zip/UI/FileManager/FilePlugins.cpp b/CPP/7zip/UI/FileManager/FilePlugins.cpp new file mode 100755 index 0000000..f5bb703 --- /dev/null +++ b/CPP/7zip/UI/FileManager/FilePlugins.cpp @@ -0,0 +1,119 @@ +// FilePlugins.cpp + +#include "StdAfx.h" + +#include "Common/MyCom.h" + +#include "../Agent/Agent.h" + +#include "FilePlugins.h" +#include "PluginLoader.h" +#include "StringUtils.h" + +using namespace NRegistryAssociations; + +int CExtDatabase::FindExtInfoBig(const UString &ext) +{ + for (int i = 0; i < ExtBigItems.Size(); i++) + if (ExtBigItems[i].Ext.CompareNoCase(ext) == 0) + return i; + return -1; +} + +int CExtDatabase::FindPlugin(const UString &plugin) +{ + for (int i = 0; i < Plugins.Size(); i++) + if (Plugins[i].Name.CompareNoCase(plugin) == 0) + return i; + return -1; +} + +void CExtDatabase::Read() +{ + /* + CObjectVector extItems; + ReadInternalAssociations(extItems); + */ + ReadFileFolderPluginInfoList(Plugins); + /* + for (int i = 0; i < extItems.Size(); i++) + { + const CExtInfo &extInfo = extItems[i]; + CExtInfoBig extInfoBig; + extInfoBig.Ext = extInfo.Ext; + extInfoBig.Associated = false; + for (int p = 0; p < extInfo.Plugins.Size(); p++) + { + int pluginIndex = FindPlugin(extInfo.Plugins[p]); + if (pluginIndex >= 0) + extInfoBig.PluginsPairs.Add(CPluginEnabledPair(pluginIndex, true)); + } + ExtBigItems.Add(extInfoBig); + } + */ + for (int pluginIndex = 0; pluginIndex < Plugins.Size(); pluginIndex++) + { + const CPluginInfo &pluginInfo = Plugins[pluginIndex]; + + CPluginLibrary pluginLibrary; + CMyComPtr folderManager; + + if (pluginInfo.FilePath.IsEmpty()) + folderManager = new CArchiveFolderManager; + else if (pluginLibrary.LoadAndCreateManager(pluginInfo.FilePath, + pluginInfo.ClassID, &folderManager) != S_OK) + continue; + CMyComBSTR extBSTR; + if (folderManager->GetExtensions(&extBSTR) != S_OK) + return; + const UString ext2 = (const wchar_t *)extBSTR; + UStringVector exts; + SplitString(ext2, exts); + for (int i = 0; i < exts.Size(); i++) + { + const UString &ext = exts[i]; + #ifdef UNDER_CE + if (ext == L"cab") + continue; + #endif + int index = FindExtInfoBig(ext); + if (index < 0) + { + CExtInfoBig extInfo; + extInfo.PluginsPairs.Add(CPluginEnabledPair(pluginIndex, false)); + extInfo.Associated = false; + extInfo.Ext = ext; + ExtBigItems.Add(extInfo); + } + else + { + CExtInfoBig &extInfo = ExtBigItems[index]; + int pluginIndexIndex = extInfo.FindPlugin(pluginIndex); + if (pluginIndexIndex < 0) + extInfo.PluginsPairs.Add(CPluginEnabledPair(pluginIndex, false)); + } + } + } +} + +void CExtDatabase::Save() +{ + /* + CObjectVector extItems; + for (int i = 0; i < ExtBigItems.Size(); i++) + { + const CExtInfoBig &extInfoBig = ExtBigItems[i]; + CExtInfo extInfo; + // extInfo.Enabled = extInfoBig.Associated; + extInfo.Ext = extInfoBig.Ext; + for (int p = 0; p < extInfoBig.PluginsPairs.Size(); p++) + { + CPluginEnabledPair pluginPair = extInfoBig.PluginsPairs[p]; + if (pluginPair.Enabled) + extInfo.Plugins.Add(Plugins[pluginPair.Index].Name); + } + extItems.Add(extInfo); + } + WriteInternalAssociations(extItems); + */ +} diff --git a/CPP/7zip/UI/FileManager/FilePlugins.h b/CPP/7zip/UI/FileManager/FilePlugins.h new file mode 100755 index 0000000..2258e27 --- /dev/null +++ b/CPP/7zip/UI/FileManager/FilePlugins.h @@ -0,0 +1,54 @@ +// FilePlugins.h + +#ifndef __FILEPLUGINS_H +#define __FILEPLUGINS_H + +#include "RegistryPlugins.h" +#include "RegistryAssociations.h" + +struct CPluginEnabledPair +{ + int Index; + bool Enabled; + CPluginEnabledPair(int index, bool enabled): Index(index),Enabled(enabled) {} +}; + +struct CExtInfoBig +{ + UString Ext; + bool Associated; + CRecordVector PluginsPairs; + int FindPlugin(int pluginIndex) + { + for (int i = 0; i < PluginsPairs.Size(); i++) + if (PluginsPairs[i].Index == pluginIndex) + return i; + return -1; + } +}; + +class CExtDatabase +{ +public: + CObjectVector ExtBigItems; + CObjectVector Plugins; + int FindExtInfoBig(const UString &ext); + int FindPlugin(const UString &plugin); + + UString GetMainPluginNameForExtItem(int extIndex) const + { + const CExtInfoBig &extInfo = ExtBigItems[extIndex]; + if (extInfo.PluginsPairs.IsEmpty()) + return UString(); + else + return Plugins[extInfo.PluginsPairs.Front().Index].Name; + } + + void Read(); + void Save(); +}; + + +#endif + + diff --git a/CPP/7zip/UI/FileManager/FoldersPage.cpp b/CPP/7zip/UI/FileManager/FoldersPage.cpp new file mode 100755 index 0000000..1469ca2 --- /dev/null +++ b/CPP/7zip/UI/FileManager/FoldersPage.cpp @@ -0,0 +1,151 @@ +// FoldersPage.cpp + +#include "StdAfx.h" + +#include "FoldersPageRes.h" +#include "FoldersPage.h" + +#include "../FileManager/BrowseDialog.h" +#include "../FileManager/HelpUtils.h" +#include "../FileManager/LangUtils.h" + +using namespace NWindows; + +static CIDLangPair kIDLangPairs[] = +{ + { IDC_FOLDERS_STATIC_WORKING_FOLDER, 0x01000210 }, + { IDC_FOLDERS_WORK_RADIO_SYSTEM, 0x01000211 }, + { IDC_FOLDERS_WORK_RADIO_CURRENT, 0x01000212 }, + { IDC_FOLDERS_WORK_RADIO_SPECIFIED, 0x01000213 }, + { IDC_FOLDERS_WORK_CHECK_FOR_REMOVABLE, 0x01000214 } +}; + +static const int kWorkModeButtons[] = +{ + IDC_FOLDERS_WORK_RADIO_SYSTEM, + IDC_FOLDERS_WORK_RADIO_CURRENT, + IDC_FOLDERS_WORK_RADIO_SPECIFIED +}; + +static const int kNumWorkModeButtons = sizeof(kWorkModeButtons) / sizeof(kWorkModeButtons[0]); + +bool CFoldersPage::OnInit() +{ + LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + m_WorkDirInfo.Load(); + + CheckButton(IDC_FOLDERS_WORK_CHECK_FOR_REMOVABLE, m_WorkDirInfo.ForRemovableOnly); + + CheckRadioButton(kWorkModeButtons[0], kWorkModeButtons[kNumWorkModeButtons - 1], + kWorkModeButtons[m_WorkDirInfo.Mode]); + + m_WorkPath.Init(*this, IDC_FOLDERS_WORK_EDIT_PATH); + m_ButtonSetWorkPath.Init(*this, IDC_FOLDERS_WORK_BUTTON_PATH); + + m_WorkPath.SetText(m_WorkDirInfo.Path); + + MyEnableControls(); + + return CPropertyPage::OnInit(); +} + +int CFoldersPage::GetWorkMode() const +{ + for (int i = 0; i < kNumWorkModeButtons; i++) + if(IsButtonCheckedBool(kWorkModeButtons[i])) + return i; + throw 0; +} + +void CFoldersPage::MyEnableControls() +{ + bool enablePath = (GetWorkMode() == NWorkDir::NMode::kSpecified); + m_WorkPath.Enable(enablePath); + m_ButtonSetWorkPath.Enable(enablePath); +} + +void CFoldersPage::GetWorkDir(NWorkDir::CInfo &workDirInfo) +{ + m_WorkPath.GetText(workDirInfo.Path); + workDirInfo.ForRemovableOnly = IsButtonCheckedBool(IDC_FOLDERS_WORK_CHECK_FOR_REMOVABLE); + workDirInfo.Mode = NWorkDir::NMode::EEnum(GetWorkMode()); +} + +/* +bool CFoldersPage::WasChanged() +{ + NWorkDir::CInfo workDirInfo; + GetWorkDir(workDirInfo); + return (workDirInfo.Mode != m_WorkDirInfo.Mode || + workDirInfo.ForRemovableOnly != m_WorkDirInfo.ForRemovableOnly || + workDirInfo.Path.Compare(m_WorkDirInfo.Path) != 0); +} +*/ + +void CFoldersPage::ModifiedEvent() +{ + Changed(); + /* + if (WasChanged()) + Changed(); + else + UnChanged(); + */ +} + +bool CFoldersPage::OnButtonClicked(int buttonID, HWND buttonHWND) +{ + for (int i = 0; i < kNumWorkModeButtons; i++) + if (buttonID == kWorkModeButtons[i]) + { + MyEnableControls(); + ModifiedEvent(); + return true; + } + switch(buttonID) + { + case IDC_FOLDERS_WORK_BUTTON_PATH: + OnFoldersWorkButtonPath(); + break; + case IDC_FOLDERS_WORK_CHECK_FOR_REMOVABLE: + break; + default: + return CPropertyPage::OnButtonClicked(buttonID, buttonHWND); + } + ModifiedEvent(); + return true; +} + +bool CFoldersPage::OnCommand(int code, int itemID, LPARAM lParam) +{ + if (code == EN_CHANGE && itemID == IDC_FOLDERS_WORK_EDIT_PATH) + { + ModifiedEvent(); + return true; + } + return CPropertyPage::OnCommand(code, itemID, lParam); +} + +void CFoldersPage::OnFoldersWorkButtonPath() +{ + UString currentPath; + m_WorkPath.GetText(currentPath); + UString title = LangString(IDS_FOLDERS_SET_WORK_PATH_TITLE, 0x01000281); + UString resultPath; + if (MyBrowseForFolder(HWND(*this), title, currentPath, resultPath)) + m_WorkPath.SetText(resultPath); +} + +LONG CFoldersPage::OnApply() +{ + GetWorkDir(m_WorkDirInfo); + m_WorkDirInfo.Save(); + return PSNRET_NOERROR; +} + +static LPCWSTR kFoldersTopic = L"fm/plugins/7-zip/options.htm#folders"; + +void CFoldersPage::OnNotifyHelp() +{ + ShowHelpWindow(NULL, kFoldersTopic); +} diff --git a/CPP/7zip/UI/FileManager/FoldersPage.h b/CPP/7zip/UI/FileManager/FoldersPage.h new file mode 100755 index 0000000..531bcfc --- /dev/null +++ b/CPP/7zip/UI/FileManager/FoldersPage.h @@ -0,0 +1,29 @@ +// FoldersPage.h + +#ifndef __FOLDERS_PAGE_H +#define __FOLDERS_PAGE_H + +#include "Windows/Control/PropertyPage.h" + +#include "../Common/ZipRegistry.h" + +class CFoldersPage : public NWindows::NControl::CPropertyPage +{ + NWorkDir::CInfo m_WorkDirInfo; + + void MyEnableControls(); + void ModifiedEvent(); + NWindows::NControl::CDialogChildControl m_WorkPath; + NWindows::NControl::CDialogChildControl m_ButtonSetWorkPath; + void OnFoldersWorkButtonPath(); + int GetWorkMode() const; + void GetWorkDir(NWorkDir::CInfo &workDirInfo); + // bool WasChanged(); + virtual bool OnInit(); + virtual bool OnCommand(int code, int itemID, LPARAM lParam); + virtual void OnNotifyHelp(); + virtual LONG OnApply(); + virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/FoldersPage.rc b/CPP/7zip/UI/FileManager/FoldersPage.rc new file mode 100755 index 0000000..0e5b3e9 --- /dev/null +++ b/CPP/7zip/UI/FileManager/FoldersPage.rc @@ -0,0 +1,23 @@ +#include "FoldersPageRes.h" +#include "../../GuiCommon.rc" + +#define xc 196 +#define yc 100 + +IDD_FOLDERS MY_PAGE +#include "FoldersPage2.rc" + +#ifdef UNDER_CE + +#undef xc +#define xc SMALL_PAGE_SIZE_X + +IDD_FOLDERS_2 MY_PAGE +#include "FoldersPage2.rc" + +#endif + +STRINGTABLE +BEGIN + IDS_FOLDERS_SET_WORK_PATH_TITLE "Specify a location for temporary archive files." +END diff --git a/CPP/7zip/UI/FileManager/FoldersPage2.rc b/CPP/7zip/UI/FileManager/FoldersPage2.rc new file mode 100755 index 0000000..e5c10e4 --- /dev/null +++ b/CPP/7zip/UI/FileManager/FoldersPage2.rc @@ -0,0 +1,16 @@ +CAPTION "Folders" +BEGIN + // GROUPBOX "&Working folder", IDC_FOLDERS_STATIC_WORKING_FOLDER, m, m, xc, 98 + + LTEXT "&Working folder", IDC_FOLDERS_STATIC_WORKING_FOLDER, m, m, xc, 8 + CONTROL "&System temp folder", IDC_FOLDERS_WORK_RADIO_SYSTEM, "Button", BS_AUTORADIOBUTTON | WS_GROUP, + m, 20, xc, 10 + CONTROL "&Current", IDC_FOLDERS_WORK_RADIO_CURRENT, "Button", BS_AUTORADIOBUTTON, + m, 34, xc, 10 + CONTROL "Specified:", IDC_FOLDERS_WORK_RADIO_SPECIFIED, "Button", BS_AUTORADIOBUTTON, + m, 48, xc, 10 + EDITTEXT IDC_FOLDERS_WORK_EDIT_PATH, m + m, 62, xc - m - m - bxsDots, 14, ES_AUTOHSCROLL + PUSHBUTTON "...", IDC_FOLDERS_WORK_BUTTON_PATH, xs - m - bxsDots, 61, bxsDots, bys + CONTROL "Use for removable drives only", IDC_FOLDERS_WORK_CHECK_FOR_REMOVABLE, MY_CHECKBOX, + m, 86, xc, 10 +END diff --git a/CPP/7zip/UI/FileManager/FoldersPageRes.h b/CPP/7zip/UI/FileManager/FoldersPageRes.h new file mode 100755 index 0000000..3cd6742 --- /dev/null +++ b/CPP/7zip/UI/FileManager/FoldersPageRes.h @@ -0,0 +1,13 @@ +#define IDD_FOLDERS 571 +#define IDD_FOLDERS_2 671 + +#define IDS_FOLDERS_SET_WORK_PATH_TITLE 877 + +#define IDC_FOLDERS_STATIC_WORKING_FOLDER 1001 + +#define IDC_FOLDERS_WORK_RADIO_SYSTEM 1011 +#define IDC_FOLDERS_WORK_RADIO_CURRENT 1012 +#define IDC_FOLDERS_WORK_RADIO_SPECIFIED 1013 +#define IDC_FOLDERS_WORK_EDIT_PATH 1014 +#define IDC_FOLDERS_WORK_BUTTON_PATH 1015 +#define IDC_FOLDERS_WORK_CHECK_FOR_REMOVABLE 1017 diff --git a/CPP/7zip/UI/FileManager/FormatUtils.cpp b/CPP/7zip/UI/FileManager/FormatUtils.cpp new file mode 100755 index 0000000..0f20a5b --- /dev/null +++ b/CPP/7zip/UI/FileManager/FormatUtils.cpp @@ -0,0 +1,40 @@ +// FormatUtils.cpp + +#include "StdAfx.h" + +#include "FormatUtils.h" +#include "Common/IntToString.h" +#include "Windows/ResourceString.h" + +#ifdef LANG +#include "LangUtils.h" +#endif + +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, + #ifdef LANG + UInt32 langID, + #endif + const UString &argument) +{ + return MyFormatNew( + #ifdef LANG + LangString(resourceID, langID), + #else + NWindows::MyLoadStringW(resourceID), + #endif + argument); +} diff --git a/CPP/7zip/UI/FileManager/FormatUtils.h b/CPP/7zip/UI/FileManager/FormatUtils.h new file mode 100755 index 0000000..84d72ad --- /dev/null +++ b/CPP/7zip/UI/FileManager/FormatUtils.h @@ -0,0 +1,18 @@ +// FormatUtils.h + +#ifndef __FORMATUTILS_H +#define __FORMATUTILS_H + +#include "Common/Types.h" +#include "Common/MyString.h" + +UString NumberToString(UInt64 number); + +UString MyFormatNew(const UString &format, const UString &argument); +UString MyFormatNew(UINT resourceID, + #ifdef LANG + UInt32 langID, + #endif + const UString &argument); + +#endif diff --git a/CPP/7zip/UI/FileManager/HelpUtils.cpp b/CPP/7zip/UI/FileManager/HelpUtils.cpp new file mode 100755 index 0000000..f92835e --- /dev/null +++ b/CPP/7zip/UI/FileManager/HelpUtils.cpp @@ -0,0 +1,27 @@ +// HelpUtils.cpp + +#include "StdAfx.h" + +#include + +#include "Common/StringConvert.h" +#include "HelpUtils.h" +#include "ProgramLocation.h" + +static LPCWSTR kHelpFileName = L"7-zip.chm::/"; + +#ifdef UNDER_CE +void ShowHelpWindow(HWND, LPCWSTR) +{ +} +#else +void ShowHelpWindow(HWND hwnd, LPCWSTR topicFile) +{ + UString path; + if (!::GetProgramFolderPath(path)) + return; + path += kHelpFileName; + path += topicFile; + HtmlHelp(hwnd, GetSystemString(path), HH_DISPLAY_TOPIC, NULL); +} +#endif diff --git a/CPP/7zip/UI/FileManager/HelpUtils.h b/CPP/7zip/UI/FileManager/HelpUtils.h new file mode 100755 index 0000000..fd6fb42 --- /dev/null +++ b/CPP/7zip/UI/FileManager/HelpUtils.h @@ -0,0 +1,10 @@ +// HelpUtils.h + +#ifndef __HELPUTILS_H +#define __HELPUTILS_H + +#include "Common/MyString.h" + +void ShowHelpWindow(HWND hwnd, LPCWSTR topicFile); + +#endif diff --git a/CPP/7zip/UI/FileManager/IFolder.h b/CPP/7zip/UI/FileManager/IFolder.h new file mode 100755 index 0000000..118c42d --- /dev/null +++ b/CPP/7zip/UI/FileManager/IFolder.h @@ -0,0 +1,161 @@ +// IFolder.h + +#ifndef __IFOLDER_H +#define __IFOLDER_H + +#include "../../IProgress.h" +#include "../../IStream.h" + +#define FOLDER_INTERFACE_SUB(i, b, x) DECL_INTERFACE_SUB(i, b, 8, x) +#define FOLDER_INTERFACE(i, x) FOLDER_INTERFACE_SUB(i, IUnknown, x) + +namespace NPlugin +{ + enum + { + kName = 0, + kType, + kClassID, + kOptionsClassID + }; +} + +#define INTERFACE_FolderFolder(x) \ + STDMETHOD(LoadItems)() x; \ + STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \ + STDMETHOD(GetProperty)(UInt32 itemIndex, PROPID propID, PROPVARIANT *value) x; \ + STDMETHOD(BindToFolder)(UInt32 index, IFolderFolder **resultFolder) x; \ + STDMETHOD(BindToFolder)(const wchar_t *name, IFolderFolder **resultFolder) x; \ + STDMETHOD(BindToParentFolder)(IFolderFolder **resultFolder) x; \ + STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \ + STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \ + STDMETHOD(GetFolderProperty)(PROPID propID, PROPVARIANT *value) x; \ + +FOLDER_INTERFACE(IFolderFolder, 0x00) +{ + INTERFACE_FolderFolder(PURE) +}; + +FOLDER_INTERFACE(IFolderWasChanged, 0x04) +{ + STDMETHOD(WasChanged)(Int32 *wasChanged) PURE; +}; + +FOLDER_INTERFACE_SUB(IFolderOperationsExtractCallback, IProgress, 0x0B) +{ + // STDMETHOD(SetTotalFiles)(UInt64 total) PURE; + // STDMETHOD(SetCompletedFiles)(const UInt64 *completedValue) PURE; + STDMETHOD(AskWrite)( + const wchar_t *srcPath, + Int32 srcIsFolder, + const FILETIME *srcTime, + const UInt64 *srcSize, + const wchar_t *destPathRequest, + BSTR *destPathResult, + Int32 *writeAnswer) PURE; + STDMETHOD(ShowMessage)(const wchar_t *message) PURE; + STDMETHOD(SetCurrentFilePath)(const wchar_t *filePath) PURE; + STDMETHOD(SetNumFiles)(UInt64 numFiles) PURE; +}; + +#define INTERFACE_FolderOperations(x) \ + STDMETHOD(CreateFolder)(const wchar_t *name, IProgress *progress) x; \ + STDMETHOD(CreateFile)(const wchar_t *name, IProgress *progress) x; \ + STDMETHOD(Rename)(UInt32 index, const wchar_t *newName, IProgress *progress) x; \ + STDMETHOD(Delete)(const UInt32 *indices, UInt32 numItems, IProgress *progress) x; \ + STDMETHOD(CopyTo)(const UInt32 *indices, UInt32 numItems, \ + const wchar_t *path, IFolderOperationsExtractCallback *callback) x; \ + STDMETHOD(MoveTo)(const UInt32 *indices, UInt32 numItems, \ + const wchar_t *path, IFolderOperationsExtractCallback *callback) x; \ + STDMETHOD(CopyFrom)(const wchar_t *fromFolderPath, \ + const wchar_t **itemsPaths, UInt32 numItems, IProgress *progress) x; \ + STDMETHOD(SetProperty)(UInt32 index, PROPID propID, const PROPVARIANT *value, IProgress *progress) x; \ + +FOLDER_INTERFACE(IFolderOperations, 0x06) +{ + INTERFACE_FolderOperations(PURE) +}; + +/* +FOLDER_INTERFACE2(IFolderOperationsDeleteToRecycleBin, 0x06, 0x03) +{ + STDMETHOD(DeleteToRecycleBin)(const UInt32 *indices, UInt32 numItems, IProgress *progress) PURE; +}; +*/ + +FOLDER_INTERFACE(IFolderGetSystemIconIndex, 0x07) +{ + STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex) PURE; +}; + +FOLDER_INTERFACE(IFolderGetItemFullSize, 0x08) +{ + STDMETHOD(GetItemFullSize)(UInt32 index, PROPVARIANT *value, IProgress *progress) PURE; +}; + +FOLDER_INTERFACE(IFolderClone, 0x09) +{ + STDMETHOD(Clone)(IFolderFolder **resultFolder) PURE; +}; + +FOLDER_INTERFACE(IFolderSetFlatMode, 0x0A) +{ + STDMETHOD(SetFlatMode)(Int32 flatMode) PURE; +}; + +#define INTERFACE_FolderProperties(x) \ + STDMETHOD(GetNumberOfFolderProperties)(UInt32 *numProperties) x; \ + STDMETHOD(GetFolderPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \ + +FOLDER_INTERFACE(IFolderProperties, 0x0E) +{ + INTERFACE_FolderProperties(PURE) +}; + +#define INTERFACE_IFolderArcProps(x) \ + STDMETHOD(GetArcNumLevels)(UInt32 *numLevels) x; \ + STDMETHOD(GetArcProp)(UInt32 level, PROPID propID, PROPVARIANT *value) x; \ + STDMETHOD(GetArcNumProps)(UInt32 level, UInt32 *numProps) x; \ + STDMETHOD(GetArcPropInfo)(UInt32 level, UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \ + STDMETHOD(GetArcProp2)(UInt32 level, PROPID propID, PROPVARIANT *value) x; \ + STDMETHOD(GetArcNumProps2)(UInt32 level, UInt32 *numProps) x; \ + STDMETHOD(GetArcPropInfo2)(UInt32 level, UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \ + +FOLDER_INTERFACE(IFolderArcProps, 0x10) +{ + INTERFACE_IFolderArcProps(PURE) +}; + +FOLDER_INTERFACE(IGetFolderArcProps, 0x11) +{ + STDMETHOD(GetFolderArcProps)(IFolderArcProps **object) PURE; +}; + +#define FOLDER_MANAGER_INTERFACE(i, x) DECL_INTERFACE(i, 9, x) + +#define INTERFACE_IFolderManager(x) \ + STDMETHOD(OpenFolderFile)(IInStream *inStream, const wchar_t *filePath, const wchar_t *arcFormat, IFolderFolder **resultFolder, IProgress *progress) x; \ + STDMETHOD(GetExtensions)(BSTR *extensions) x; \ + STDMETHOD(GetIconPath)(const wchar_t *ext, BSTR *iconPath, Int32 *iconIndex) x; \ + + // STDMETHOD(GetTypes)(BSTR *types) PURE; + // STDMETHOD(CreateFolderFile)(const wchar_t *type, const wchar_t *filePath, IProgress *progress) PURE; + +FOLDER_MANAGER_INTERFACE(IFolderManager, 0x05) +{ + INTERFACE_IFolderManager(PURE); +}; + + +#define IMP_IFolderFolder_GetProp(k) \ + (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ + { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ + const STATPROPSTG &srcItem = k[index]; \ + *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } \ + +#define IMP_IFolderFolder_Props(c) \ + STDMETHODIMP c::GetNumberOfProperties(UInt32 *numProperties) \ + { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ + STDMETHODIMP c::GetPropertyInfo IMP_IFolderFolder_GetProp(kProps) + +#endif diff --git a/CPP/7zip/UI/FileManager/Info.bmp b/CPP/7zip/UI/FileManager/Info.bmp new file mode 100755 index 0000000000000000000000000000000000000000..d769a661cdb50de2148266ab13ff8a6ff4c506ba GIT binary patch literal 982 zcmZ?ry~fM{24z4}1BeZPSOtg~8CZZM149B-9?U@@8W$O1HyCUnTAYC!sDS~C|3TvHXtsj5 wLqxnByE`v{{fp_Z3*cZQK^z?Vyja4AT0+-B5s$?%kj0qpq+Yy$%%{G;03j&CF#rGn literal 0 HcmV?d00001 diff --git a/CPP/7zip/UI/FileManager/Info2.bmp b/CPP/7zip/UI/FileManager/Info2.bmp new file mode 100755 index 0000000000000000000000000000000000000000..af724d2713f1daeffd244af7d325b80f69c4b961 GIT binary patch literal 406 zcmZ?royN!j24z4}1BfM{n2~`6EUo~R2Xjz}1_lNoVrXc9P(TvM1mXsU0|yQOCH{jE z!~g#v77zm=NC-&WB?FX$07Tyfpm7ZBQ1)&hfUy~N?`GhIntcH-eD^M?>;i<|3qUiW c#)FJOuz^m1S%vBwxHEzF!kvl74Oq+p0PREVl>h($ literal 0 HcmV?d00001 diff --git a/CPP/7zip/UI/FileManager/LangPage.cpp b/CPP/7zip/UI/FileManager/LangPage.cpp new file mode 100755 index 0000000..629bb7d --- /dev/null +++ b/CPP/7zip/UI/FileManager/LangPage.cpp @@ -0,0 +1,83 @@ +// LangPage.cpp + +#include "StdAfx.h" + +#include "Common/StringConvert.h" + +#include "Windows/ResourceString.h" + +#include "HelpUtils.h" +#include "LangPage.h" +#include "LangPageRes.h" +#include "LangUtils.h" +#include "RegistryUtils.h" + +static CIDLangPair kIDLangPairs[] = +{ + { IDC_LANG_STATIC_LANG, 0x01000401} +}; + +static LPCWSTR kLangTopic = L"fm/options.htm#language"; + +static UString NativeLangString(const UString &s) +{ + return L" (" + s + L')'; +} + +bool CLangPage::OnInit() +{ + LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + + _langCombo.Attach(GetItem(IDC_LANG_COMBO_LANG)); + + UString s = NWindows::MyLoadStringW(IDS_LANG_ENGLISH) + + NativeLangString(NWindows::MyLoadStringW(IDS_LANG_NATIVE)); + int index = (int)_langCombo.AddString(s); + _langCombo.SetItemData(index, _paths.Size()); + _paths.Add(L"-"); + _langCombo.SetCurSel(0); + + CObjectVector langs; + LoadLangs(langs); + for (int i = 0; i < langs.Size(); i++) + { + const CLangEx &lang = langs[i]; + UString name, nationalName; + if (!lang.Lang.GetMessage(0, name)) + name = lang.ShortName; + if (lang.Lang.GetMessage(1, nationalName) && !nationalName.IsEmpty()) + name += NativeLangString(nationalName); + + index = (int)_langCombo.AddString(name); + _langCombo.SetItemData(index, _paths.Size()); + _paths.Add(lang.ShortName); + if (g_LangID.CompareNoCase(lang.ShortName) == 0) + _langCombo.SetCurSel(index); + } + return CPropertyPage::OnInit(); +} + +LONG CLangPage::OnApply() +{ + int selectedIndex = _langCombo.GetCurSel(); + int pathIndex = (int)_langCombo.GetItemData(selectedIndex); + SaveRegLang(_paths[pathIndex]); + ReloadLang(); + LangWasChanged = true; + return PSNRET_NOERROR; +} + +void CLangPage::OnNotifyHelp() +{ + ShowHelpWindow(NULL, kLangTopic); +} + +bool CLangPage::OnCommand(int code, int itemID, LPARAM param) +{ + if (code == CBN_SELCHANGE && itemID == IDC_LANG_COMBO_LANG) + { + Changed(); + return true; + } + return CPropertyPage::OnCommand(code, itemID, param); +} diff --git a/CPP/7zip/UI/FileManager/LangPage.h b/CPP/7zip/UI/FileManager/LangPage.h new file mode 100755 index 0000000..8b63469 --- /dev/null +++ b/CPP/7zip/UI/FileManager/LangPage.h @@ -0,0 +1,22 @@ +// LangPage.h + +#ifndef __LANG_PAGE_H +#define __LANG_PAGE_H + +#include "Windows/Control/PropertyPage.h" +#include "Windows/Control/ComboBox.h" + +class CLangPage: public NWindows::NControl::CPropertyPage +{ + NWindows::NControl::CComboBox _langCombo; + UStringVector _paths; +public: + bool LangWasChanged; + CLangPage() { LangWasChanged = false; } + virtual bool OnInit(); + virtual void OnNotifyHelp(); + virtual bool OnCommand(int code, int itemID, LPARAM param); + virtual LONG OnApply(); +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/LangPage.rc b/CPP/7zip/UI/FileManager/LangPage.rc new file mode 100755 index 0000000..8134d6f --- /dev/null +++ b/CPP/7zip/UI/FileManager/LangPage.rc @@ -0,0 +1,37 @@ +#include "LangPageRes.h" +#include "../../GuiCommon.rc" + +#define xc 148 +#define yc 100 + +IDD_LANG MY_PAGE +CAPTION "Language" +{ + LTEXT "Language:", IDC_LANG_STATIC_LANG, m, m, xc, 8 + COMBOBOX IDC_LANG_COMBO_LANG, m, 20, xc, yc - 20, MY_COMBO_SORTED +} + + +#ifdef UNDER_CE + +#undef m +#undef xc + +#define m 4 +#define xc (SMALL_PAGE_SIZE_X + 8) + +IDD_LANG_2 MY_PAGE +CAPTION "Language" +{ + LTEXT "Language:", IDC_LANG_STATIC_LANG, m, m, xc, 8 + COMBOBOX IDC_LANG_COMBO_LANG, m, 20, xc, yc - 20, MY_COMBO_SORTED +} + +#endif + + +STRINGTABLE +BEGIN + IDS_LANG_ENGLISH "English" + IDS_LANG_NATIVE "English" +END diff --git a/CPP/7zip/UI/FileManager/LangPageRes.h b/CPP/7zip/UI/FileManager/LangPageRes.h new file mode 100755 index 0000000..fc2dcc7 --- /dev/null +++ b/CPP/7zip/UI/FileManager/LangPageRes.h @@ -0,0 +1,8 @@ +#define IDD_LANG 544 +#define IDD_LANG_2 644 + +#define IDS_LANG_ENGLISH 995 +#define IDS_LANG_NATIVE 996 + +#define IDC_LANG_STATIC_LANG 1000 +#define IDC_LANG_COMBO_LANG 1001 diff --git a/CPP/7zip/UI/FileManager/LangUtils.cpp b/CPP/7zip/UI/FileManager/LangUtils.cpp new file mode 100755 index 0000000..5786874 --- /dev/null +++ b/CPP/7zip/UI/FileManager/LangUtils.cpp @@ -0,0 +1,208 @@ +// LangUtils.cpp + +#include "StdAfx.h" + +#include "LangUtils.h" +#include "Common/StringConvert.h" +#include "Common/StringToInt.h" +#include "Windows/Synchronization.h" +#include "Windows/Window.h" +#include "Windows/FileFind.h" +#include "RegistryUtils.h" +#include "ProgramLocation.h" + +using namespace NWindows; + +static CLang g_Lang; +UString g_LangID; + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +void ReloadLang() +{ + ReadRegLang(g_LangID); + g_Lang.Clear(); + if (!g_LangID.IsEmpty() && g_LangID != L"-") + { + UString langPath = g_LangID; + if (langPath.Find(WCHAR_PATH_SEPARATOR) < 0) + { + if (langPath.Find(L'.') < 0) + langPath += L".txt"; + UString folderPath; + if (GetProgramFolderPath(folderPath)) + langPath = folderPath + UString(L"Lang" WSTRING_PATH_SEPARATOR) + langPath; + } + g_Lang.Open(langPath); + } +} + +static bool g_Loaded = false; +static NSynchronization::CCriticalSection g_CriticalSection; + +void LoadLangOneTime() +{ + NSynchronization::CCriticalSectionLock lock(g_CriticalSection); + if (g_Loaded) + return; + g_Loaded = true; + ReloadLang(); +} + +void LangSetDlgItemsText(HWND dialogWindow, CIDLangPair *idLangPairs, int numItems) +{ + for (int i = 0; i < numItems; i++) + { + const CIDLangPair &idLangPair = idLangPairs[i]; + UString message; + if (g_Lang.GetMessage(idLangPair.LangID, message)) + { + NWindows::CWindow window(GetDlgItem(dialogWindow, idLangPair.ControlID)); + window.SetText(message); + } + } +} + +void LangSetWindowText(HWND window, UInt32 langID) +{ + UString message; + if (g_Lang.GetMessage(langID, message)) + MySetWindowText(window, message); +} + +UString LangString(UInt32 langID) +{ + UString message; + if (g_Lang.GetMessage(langID, message)) + return message; + return UString(); +} + +UString LangString(UINT resourceID, UInt32 langID) +{ + UString message; + if (g_Lang.GetMessage(langID, message)) + return message; + return NWindows::MyLoadStringW(resourceID); +} + +void LoadLangs(CObjectVector &langs) +{ + langs.Clear(); + UString folderPath; + if (!::GetProgramFolderPath(folderPath)) + return; + folderPath += L"Lang" WSTRING_PATH_SEPARATOR; + NWindows::NFile::NFind::CEnumeratorW enumerator(folderPath + L"*.txt"); + NWindows::NFile::NFind::CFileInfoW fileInfo; + while (enumerator.Next(fileInfo)) + { + if (fileInfo.IsDir()) + continue; + CLangEx lang; + UString filePath = folderPath + fileInfo.Name; + const int kExtSize = 4; + const UString ext = fileInfo.Name.Right(kExtSize); + if (ext.CompareNoCase(L".txt") != 0) + continue; + lang.ShortName = fileInfo.Name.Left(fileInfo.Name.Length() - kExtSize); + if (lang.Lang.Open(filePath)) + langs.Add(lang); + } +} + +bool SplidID(const UString &id, WORD &primID, WORD &subID) +{ + primID = 0; + subID = 0; + const wchar_t *start = id; + const wchar_t *end; + UInt64 value = ConvertStringToUInt64(start, &end); + if (start == end) + return false; + primID = (WORD)value; + if (*end == 0) + return true; + if (*end != L'-') + return false; + start = end + 1; + value = ConvertStringToUInt64(start, &end); + if (start == end) + return false; + subID = (WORD)value; + return (*end == 0); +} + +typedef LANGID (WINAPI *GetUserDefaultUILanguageP)(); + +void FindMatchLang(UString &shortName) +{ + shortName.Empty(); + + LANGID SystemDefaultLangID = GetSystemDefaultLangID(); // Lang for non-Unicode in XP64 + LANGID UserDefaultLangID = GetUserDefaultLangID(); // Standarts and formats in XP64 + + if (SystemDefaultLangID != UserDefaultLangID) + return; + LANGID langID = UserDefaultLangID; + /* + LANGID SystemDefaultUILanguage; // english in XP64 + LANGID UserDefaultUILanguage; // english in XP64 + + GetUserDefaultUILanguageP fn = (GetUserDefaultUILanguageP)GetProcAddress( + GetModuleHandle("kernel32"), "GetUserDefaultUILanguage"); + if (fn != NULL) + UserDefaultUILanguage = fn(); + fn = (GetUserDefaultUILanguageP)GetProcAddress( + GetModuleHandle("kernel32"), "GetSystemDefaultUILanguage"); + if (fn != NULL) + SystemDefaultUILanguage = fn(); + */ + + WORD primLang = (WORD)(PRIMARYLANGID(langID)); + WORD subLang = (WORD)(SUBLANGID(langID)); + CObjectVector langs; + LoadLangs(langs); + for (int i = 0; i < langs.Size(); i++) + { + const CLangEx &lang = langs[i]; + UString id; + if (lang.Lang.GetMessage(0x00000002, id)) + { + WORD primID; + WORD subID; + if (SplidID(id, primID, subID)) + if (primID == primLang) + { + if (subID == 0) + shortName = lang.ShortName; + if (subLang == subID) + { + shortName = lang.ShortName; + return; + } + } + } + } +} + +void ReloadLangSmart() +{ + #ifndef _UNICODE + if (g_IsNT) + #endif + { + ReadRegLang(g_LangID); + if (g_LangID.IsEmpty()) + { + UString shortName; + FindMatchLang(shortName); + if (shortName.IsEmpty()) + shortName = L"-"; + SaveRegLang(shortName); + } + } + ReloadLang(); +} diff --git a/CPP/7zip/UI/FileManager/LangUtils.h b/CPP/7zip/UI/FileManager/LangUtils.h new file mode 100755 index 0000000..8a031be --- /dev/null +++ b/CPP/7zip/UI/FileManager/LangUtils.h @@ -0,0 +1,41 @@ +// LangUtils.h + +#ifndef __LANGUTILS_H +#define __LANGUTILS_H + +#include "Common/Lang.h" +#include "Windows/ResourceString.h" + +extern UString g_LangID; + +struct CIDLangPair +{ + int ControlID; + UInt32 LangID; +}; + +void ReloadLang(); +void LoadLangOneTime(); +void ReloadLangSmart(); + +struct CLangEx +{ + CLang Lang; + UString ShortName; +}; + +void LoadLangs(CObjectVector &langs); + +void LangSetDlgItemsText(HWND dialogWindow, CIDLangPair *idLangPairs, int numItems); +void LangSetWindowText(HWND window, UInt32 langID); + +UString LangString(UInt32 langID); +UString LangString(UINT resourceID, UInt32 langID); + +#ifdef LANG +#define LangStringSpec(resourceID, langID) LangString(resourceID, langID) +#else +#define LangStringSpec(resourceID, langID) NWindows::MyLoadStringW(resourceID) +#endif + +#endif diff --git a/CPP/7zip/UI/FileManager/ListViewDialog.cpp b/CPP/7zip/UI/FileManager/ListViewDialog.cpp new file mode 100755 index 0000000..11399f9 --- /dev/null +++ b/CPP/7zip/UI/FileManager/ListViewDialog.cpp @@ -0,0 +1,150 @@ +// ListViewDialog.cpp + +#include "StdAfx.h" + +#include "ListViewDialog.h" +#include "RegistryUtils.h" + +#ifdef LANG +#include "LangUtils.h" +static CIDLangPair kIDLangPairs[] = +{ + { IDOK, 0x02000702 }, + { IDCANCEL, 0x02000710 } +}; +#endif + +bool CListViewDialog::OnInit() +{ + #ifdef LANG + LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + #endif + _listView.Attach(GetItem(IDC_LISTVIEW_LIST)); + + if (ReadSingleClick()) + _listView.SetExtendedListViewStyle(LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT); + + SetText(Title); + + LVCOLUMN columnInfo; + columnInfo.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM; + columnInfo.fmt = LVCFMT_LEFT; + columnInfo.iSubItem = 0; + columnInfo.cx = 200; + + _listView.InsertColumn(0, &columnInfo); + + for (int i = 0; i < Strings.Size(); i++) + _listView.InsertItem(i, Strings[i]); + + if (Strings.Size() > 0) + _listView.SetItemState_FocusedSelected(0); + + _listView.SetColumnWidthAuto(0); + StringsWereChanged = false; + + NormalizeSize(); + return CModalDialog::OnInit(); +} + +bool CListViewDialog::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; + + /* + RECT rect; + GetClientRect(&rect); + rect.top = y - my; + InvalidateRect(&rect); + */ + InvalidateRect(NULL); + + MoveItem(IDCANCEL, x, y, bx1, by); + MoveItem(IDOK, x - mx - bx2, y, bx2, by); + /* + if (wParam == SIZE_MAXSHOW || wParam == SIZE_MAXIMIZED || wParam == SIZE_MAXHIDE) + mx = 0; + */ + _listView.Move(mx, my, xSize - mx * 2, y - my * 2); + return false; +} + +extern bool g_LVN_ITEMACTIVATE_Support; + +bool CListViewDialog::OnNotify(UINT /* controlID */, LPNMHDR header) +{ + if (header->hwndFrom != _listView) + return false; + switch(header->code) + { + case LVN_ITEMACTIVATE: + if (g_LVN_ITEMACTIVATE_Support) + { + OnOK(); + return true; + } + break; + case NM_DBLCLK: + case NM_RETURN: // probabably it's unused + if (!g_LVN_ITEMACTIVATE_Support) + { + OnOK(); + return true; + } + break; + + case LVN_KEYDOWN: + { + LPNMLVKEYDOWN keyDownInfo = LPNMLVKEYDOWN(header); + switch(keyDownInfo->wVKey) + { + case VK_DELETE: + { + if (!DeleteIsAllowed) + return false; + for (;;) + { + int index = _listView.GetNextSelectedItem(-1); + if (index < 0) + break; + StringsWereChanged = true; + _listView.DeleteItem(index); + Strings.Delete(index); + } + int focusedIndex = _listView.GetFocusedItem(); + if (focusedIndex >= 0) + _listView.SetItemState_FocusedSelected(focusedIndex); + _listView.SetColumnWidthAuto(0); + return true; + } + case 'A': + { + // probably that code is unused ? + /* + bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0; + if (ctrl) + { + int numItems = _listView.GetItemCount(); + for (int i = 0; i < numItems; i++) + _listView.SetItemState(i, LVIS_SELECTED, LVIS_SELECTED); + return true; + } + */ + } + } + } + } + return false; +} + +void CListViewDialog::OnOK() +{ + FocusedItemIndex = _listView.GetFocusedItem(); + CModalDialog::OnOK(); +} diff --git a/CPP/7zip/UI/FileManager/ListViewDialog.h b/CPP/7zip/UI/FileManager/ListViewDialog.h new file mode 100755 index 0000000..997d97f --- /dev/null +++ b/CPP/7zip/UI/FileManager/ListViewDialog.h @@ -0,0 +1,30 @@ +// ListViewDialog.h + +#ifndef __LISTVIEW_DIALOG_H +#define __LISTVIEW_DIALOG_H + +#include "Windows/Control/Dialog.h" +#include "Windows/Control/ListView.h" + +#include "ListViewDialogRes.h" + +class CListViewDialog: public NWindows::NControl::CModalDialog +{ + NWindows::NControl::CListView _listView; + virtual void OnOK(); + virtual bool OnInit(); + virtual bool OnSize(WPARAM wParam, int xSize, int ySize); + virtual bool OnNotify(UINT controlID, LPNMHDR header); +public: + UString Title; + bool DeleteIsAllowed; + bool StringsWereChanged; + UStringVector Strings; + int FocusedItemIndex; + + INT_PTR Create(HWND wndParent = 0) { return CModalDialog::Create(IDD_DIALOG_LISTVIEW, wndParent); } + + CListViewDialog(): DeleteIsAllowed(false) {} +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/ListViewDialog.rc b/CPP/7zip/UI/FileManager/ListViewDialog.rc new file mode 100755 index 0000000..e707e52 --- /dev/null +++ b/CPP/7zip/UI/FileManager/ListViewDialog.rc @@ -0,0 +1,14 @@ +#include "ListViewDialogRes.h" +#include "../../GuiCommon.rc" + +#define xc 320 +#define yc 240 + +IDD_DIALOG_LISTVIEW MY_RESIZE_DIALOG +CAPTION "ListView" +{ + CONTROL "List1", IDC_LISTVIEW_LIST, "SysListView32", LVS_REPORT | LVS_SHOWSELALWAYS | + LVS_AUTOARRANGE | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP, + m, m, xc, yc - bys - m + OK_CANCEL +} diff --git a/CPP/7zip/UI/FileManager/ListViewDialogRes.h b/CPP/7zip/UI/FileManager/ListViewDialogRes.h new file mode 100755 index 0000000..44d366a --- /dev/null +++ b/CPP/7zip/UI/FileManager/ListViewDialogRes.h @@ -0,0 +1,2 @@ +#define IDD_DIALOG_LISTVIEW 508 +#define IDC_LISTVIEW_LIST 1000 diff --git a/CPP/7zip/UI/FileManager/MenuPage.cpp b/CPP/7zip/UI/FileManager/MenuPage.cpp new file mode 100755 index 0000000..2eb4005 --- /dev/null +++ b/CPP/7zip/UI/FileManager/MenuPage.cpp @@ -0,0 +1,203 @@ +// MenuPage.cpp + +#include "StdAfx.h" + +#include "../Common/ZipRegistry.h" + +#include "../Explorer/ContextMenuFlags.h" +#include "../Explorer/RegistryContextMenu.h" +#include "../Explorer/resource.h" + +#include "HelpUtils.h" +#include "LangUtils.h" +#include "MenuPage.h" +#include "MenuPageRes.h" +#include "FormatUtils.h" + +using namespace NContextMenuFlags; + +static CIDLangPair kIDLangPairs[] = +{ + { IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU, 0x01000301}, + { IDC_SYSTEM_CASCADED_MENU, 0x01000302}, + { IDC_SYSTEM_STATIC_CONTEXT_MENU_ITEMS, 0x01000310} +}; + +static LPCWSTR kSystemTopic = L"fm/plugins/7-zip/options.htm#system"; + +struct CContextMenuItem +{ + int ControlID; + UInt32 LangID; + UInt32 Flag; +}; + +static CContextMenuItem kMenuItems[] = +{ + { IDS_CONTEXT_OPEN, 0x02000103, kOpen}, + { IDS_CONTEXT_OPEN, 0x02000103, kOpenAs}, + { IDS_CONTEXT_EXTRACT, 0x02000105, kExtract}, + { IDS_CONTEXT_EXTRACT_HERE, 0x0200010B, kExtractHere }, + { IDS_CONTEXT_EXTRACT_TO, 0x0200010D, kExtractTo }, + + { IDS_CONTEXT_TEST, 0x02000109, kTest}, + + { IDS_CONTEXT_COMPRESS, 0x02000107, kCompress }, + { IDS_CONTEXT_COMPRESS_TO, 0x0200010F, kCompressTo7z }, + { IDS_CONTEXT_COMPRESS_TO, 0x0200010F, kCompressToZip } + + #ifndef UNDER_CE + , + { IDS_CONTEXT_COMPRESS_EMAIL, 0x02000111, kCompressEmail }, + { IDS_CONTEXT_COMPRESS_TO_EMAIL, 0x02000113, kCompressTo7zEmail }, + { IDS_CONTEXT_COMPRESS_TO_EMAIL, 0x02000113, kCompressToZipEmail } + #endif +}; + +const int kNumMenuItems = sizeof(kMenuItems) / sizeof(kMenuItems[0]); + +bool CMenuPage::OnInit() +{ + _initMode = true; + LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + + #ifdef UNDER_CE + EnableItem(IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU, false); + #else + CheckButton(IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU, NZipRootRegistry::CheckContextMenuHandler()); + #endif + + CContextMenuInfo ci; + ci.Load(); + + CheckButton(IDC_SYSTEM_CASCADED_MENU, ci.Cascaded); + + _listView.Attach(GetItem(IDC_SYSTEM_OPTIONS_LIST)); + + UInt32 newFlags = LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT; + _listView.SetExtendedListViewStyle(newFlags, newFlags); + + _listView.InsertColumn(0, L"", 100); + + for (int i = 0; i < kNumMenuItems; i++) + { + CContextMenuItem &menuItem = kMenuItems[i]; + + UString s = LangString(menuItem.ControlID, menuItem.LangID); + if (menuItem.Flag == kOpenAs) + s += L" >"; + + switch(menuItem.ControlID) + { + case IDS_CONTEXT_EXTRACT_TO: + { + s = MyFormatNew(s, LangString(IDS_CONTEXT_FOLDER, 0x02000140)); + break; + } + case IDS_CONTEXT_COMPRESS_TO: + case IDS_CONTEXT_COMPRESS_TO_EMAIL: + { + UString s2 = LangString(IDS_CONTEXT_ARCHIVE, 0x02000141); + switch(menuItem.Flag) + { + case kCompressTo7z: + case kCompressTo7zEmail: + s2 += L".7z"; + break; + case kCompressToZip: + case kCompressToZipEmail: + s2 += L".zip"; + break; + } + s = MyFormatNew(s, s2); + break; + } + } + + int itemIndex = _listView.InsertItem(i, s); + _listView.SetCheckState(itemIndex, ((ci.Flags & menuItem.Flag) != 0)); + } + + _listView.SetColumnWidthAuto(0); + _initMode = false; + return CPropertyPage::OnInit(); +} + +#ifndef UNDER_CE +STDAPI DllRegisterServer(void); +STDAPI DllUnregisterServer(void); +HWND g_MenuPageHWND = 0; +#endif + +LONG CMenuPage::OnApply() +{ + #ifndef UNDER_CE + g_MenuPageHWND = *this; + if (IsButtonCheckedBool(IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU)) + { + DllRegisterServer(); + NZipRootRegistry::AddContextMenuHandler(); + } + else + { + DllUnregisterServer(); + NZipRootRegistry::DeleteContextMenuHandler(); + } + #endif + + CContextMenuInfo ci; + ci.Cascaded = IsButtonCheckedBool(IDC_SYSTEM_CASCADED_MENU); + ci.Flags = 0; + for (int i = 0; i < kNumMenuItems; i++) + if (_listView.GetCheckState(i)) + ci.Flags |= kMenuItems[i].Flag; + ci.Save(); + + return PSNRET_NOERROR; +} + +void CMenuPage::OnNotifyHelp() +{ + ShowHelpWindow(NULL, kSystemTopic); +} + +bool CMenuPage::OnButtonClicked(int buttonID, HWND buttonHWND) +{ + switch(buttonID) + { + case IDC_SYSTEM_CASCADED_MENU: + case IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU: + Changed(); + return true; + } + return CPropertyPage::OnButtonClicked(buttonID, buttonHWND); + +} + +bool CMenuPage::OnNotify(UINT controlID, LPNMHDR lParam) +{ + if (lParam->hwndFrom == HWND(_listView)) + { + switch(lParam->code) + { + case (LVN_ITEMCHANGED): + return OnItemChanged((const NMLISTVIEW *)lParam); + } + } + return CPropertyPage::OnNotify(controlID, lParam); +} + + +bool CMenuPage::OnItemChanged(const NMLISTVIEW *info) +{ + if (_initMode) + return true; + if ((info->uChanged & LVIF_STATE) != 0) + { + UINT oldState = info->uOldState & LVIS_STATEIMAGEMASK; + UINT newState = info->uNewState & LVIS_STATEIMAGEMASK; + if (oldState != newState) + Changed(); + } + return true; +} diff --git a/CPP/7zip/UI/FileManager/MenuPage.h b/CPP/7zip/UI/FileManager/MenuPage.h new file mode 100755 index 0000000..3491844 --- /dev/null +++ b/CPP/7zip/UI/FileManager/MenuPage.h @@ -0,0 +1,25 @@ +// MenuPage.h + +#ifndef __MENU_PAGE_H +#define __MENU_PAGE_H + +#include "Windows/Control/PropertyPage.h" +#include "Windows/Control/ListView.h" + +#include "../Common/LoadCodecs.h" + +class CMenuPage: public NWindows::NControl::CPropertyPage +{ + bool _initMode; + NWindows::NControl::CListView _listView; + + virtual bool OnInit(); + virtual void OnNotifyHelp(); + virtual bool OnNotify(UINT controlID, LPNMHDR lParam); + virtual bool OnItemChanged(const NMLISTVIEW *info); + virtual LONG OnApply(); + virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); +public: +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/MenuPage.rc b/CPP/7zip/UI/FileManager/MenuPage.rc new file mode 100755 index 0000000..72aff73 --- /dev/null +++ b/CPP/7zip/UI/FileManager/MenuPage.rc @@ -0,0 +1,24 @@ +#include "MenuPageRes.h" +#include "../../GuiCommon.rc" + +#define xc 196 +#define yc 174 + +IDD_MENU MY_PAGE +#include "MenuPage2.rc" + +#ifdef UNDER_CE + +#undef m +#undef xc +#undef yc + +#define m 4 +#define xc (SMALL_PAGE_SIZE_X + 8) + +#define yc 112 + +IDD_MENU_2 MY_PAGE +#include "MenuPage2.rc" + +#endif diff --git a/CPP/7zip/UI/FileManager/MenuPage2.rc b/CPP/7zip/UI/FileManager/MenuPage2.rc new file mode 100755 index 0000000..f0b1415 --- /dev/null +++ b/CPP/7zip/UI/FileManager/MenuPage2.rc @@ -0,0 +1,14 @@ +#define y 40 + +CAPTION "7-Zip" +BEGIN + CONTROL "Integrate 7-Zip to shell context menu", IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU, + MY_CHECKBOX, m, m, xc, 10 + CONTROL "Cascaded context menu", IDC_SYSTEM_CASCADED_MENU, + MY_CHECKBOX, m, m + 14, xc, 10 + LTEXT "Context menu items:", IDC_SYSTEM_STATIC_CONTEXT_MENU_ITEMS, + m, m + 28, xc, 8 + CONTROL "List", IDC_SYSTEM_OPTIONS_LIST, "SysListView32", + LVS_REPORT | LVS_SINGLESEL | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP, + m, m + y, xc, yc - y +END diff --git a/CPP/7zip/UI/FileManager/MenuPageRes.h b/CPP/7zip/UI/FileManager/MenuPageRes.h new file mode 100755 index 0000000..307c835 --- /dev/null +++ b/CPP/7zip/UI/FileManager/MenuPageRes.h @@ -0,0 +1,7 @@ +#define IDD_MENU 570 +#define IDD_MENU_2 670 + +#define IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU 1010 +#define IDC_SYSTEM_CASCADED_MENU 1011 +#define IDC_SYSTEM_STATIC_CONTEXT_MENU_ITEMS 1020 +#define IDC_SYSTEM_OPTIONS_LIST 1022 diff --git a/CPP/7zip/UI/FileManager/MessagesDialog.cpp b/CPP/7zip/UI/FileManager/MessagesDialog.cpp new file mode 100755 index 0000000..bcbb556 --- /dev/null +++ b/CPP/7zip/UI/FileManager/MessagesDialog.cpp @@ -0,0 +1,93 @@ +// MessagesDialog.cpp + +#include "StdAfx.h" + +#include "Common/IntToString.h" + +#include "Windows/ResourceString.h" + +#include "MessagesDialog.h" + +#ifdef LANG +#include "LangUtils.h" +#endif + +using namespace NWindows; + +#ifdef LANG +static CIDLangPair kIDLangPairs[] = +{ + { IDOK, 0x02000713 } +}; +#endif + +void CMessagesDialog::AddMessageDirect(LPCWSTR message) +{ + int itemIndex = _messageList.GetItemCount(); + wchar_t sz[32]; + ConvertInt64ToString(itemIndex, sz); + _messageList.InsertItem(itemIndex, sz); + _messageList.SetSubItem(itemIndex, 1, message); +} + +void CMessagesDialog::AddMessage(LPCWSTR message) +{ + UString s = message; + while (!s.IsEmpty()) + { + int pos = s.Find(L'\n'); + if (pos < 0) + break; + AddMessageDirect(s.Left(pos)); + s.Delete(0, pos + 1); + } + AddMessageDirect(s); +} + +bool CMessagesDialog::OnInit() +{ + #ifdef LANG + LangSetWindowText(HWND(*this), 0x02000A00); + LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + #endif + _messageList.Attach(GetItem(IDC_MESSAGE_LIST)); + + #ifndef UNDER_CE + _messageList.SetUnicodeFormat(true); + #endif + + _messageList.InsertColumn(0, L"", 30); + + const UString s = + #ifdef LANG + LangString(IDS_MESSAGES_DIALOG_MESSAGE_COLUMN, 0x02000A80); + #else + MyLoadStringW(IDS_MESSAGES_DIALOG_MESSAGE_COLUMN); + #endif + + _messageList.InsertColumn(1, s, 600); + + for (int i = 0; i < Messages->Size(); i++) + AddMessage((*Messages)[i]); + + _messageList.SetColumnWidthAuto(0); + _messageList.SetColumnWidthAuto(1); + NormalizeSize(); + return CModalDialog::OnInit(); +} + +bool CMessagesDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) +{ + int mx, my; + GetMargins(8, mx, my); + int bx, by; + GetItemSizes(IDOK, bx, by); + int y = ySize - my - by; + int x = xSize - mx - bx; + + InvalidateRect(NULL); + + MoveItem(IDOK, x, y, bx, by); + _messageList.Move(mx, my, xSize - mx * 2, y - my * 2); + return false; +} diff --git a/CPP/7zip/UI/FileManager/MessagesDialog.h b/CPP/7zip/UI/FileManager/MessagesDialog.h new file mode 100755 index 0000000..7a0db96 --- /dev/null +++ b/CPP/7zip/UI/FileManager/MessagesDialog.h @@ -0,0 +1,23 @@ +// MessagesDialog.h + +#ifndef __MESSAGES_DIALOG_H +#define __MESSAGES_DIALOG_H + +#include "Windows/Control/Dialog.h" +#include "Windows/Control/ListView.h" + +#include "MessagesDialogRes.h" + +class CMessagesDialog: public NWindows::NControl::CModalDialog +{ + NWindows::NControl::CListView _messageList; + void AddMessageDirect(LPCWSTR message); + void AddMessage(LPCWSTR message); + virtual bool OnInit(); + virtual bool OnSize(WPARAM wParam, int xSize, int ySize); +public: + const UStringVector *Messages; + INT_PTR Create(HWND parent = 0) { return CModalDialog::Create(IDD_DIALOG_MESSAGES, parent); } +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/MessagesDialog.rc b/CPP/7zip/UI/FileManager/MessagesDialog.rc new file mode 100755 index 0000000..273d852 --- /dev/null +++ b/CPP/7zip/UI/FileManager/MessagesDialog.rc @@ -0,0 +1,14 @@ +#include "MessagesDialogRes.h" +#include "../../GuiCommon.rc" + +#define xc 440 +#define yc 160 + +IDD_DIALOG_MESSAGES MY_RESIZE_DIALOG +CAPTION "7-Zip: Diagnostic messages" +{ + DEFPUSHBUTTON "&Close", IDOK, bx, by, bxs, bys + CONTROL "List1", IDC_MESSAGE_LIST, "SysListView32", + LVS_REPORT | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, + m, m, xc, yc - bys - m +} diff --git a/CPP/7zip/UI/FileManager/MessagesDialogRes.h b/CPP/7zip/UI/FileManager/MessagesDialogRes.h new file mode 100755 index 0000000..cfd83ab --- /dev/null +++ b/CPP/7zip/UI/FileManager/MessagesDialogRes.h @@ -0,0 +1,3 @@ +#define IDS_MESSAGES_DIALOG_MESSAGE_COLUMN 503 +#define IDD_DIALOG_MESSAGES 503 +#define IDC_MESSAGE_LIST 1000 diff --git a/CPP/7zip/UI/FileManager/Move.bmp b/CPP/7zip/UI/FileManager/Move.bmp new file mode 100755 index 0000000000000000000000000000000000000000..eb5f20f9452e1552440e557697b8031c6a232965 GIT binary patch literal 982 zcmd6kF%p6>5JlHZwF?Dj196A}pFr?YU$F3HRPu!Q^L zbCeh_)GP9aydV#vs3Om_9~YbAMKHws`G$%q(#tRm*qGvwX$mtWu7FVNFXGhbLf(8s z8wTyTK^-@!;|6uy0A3jSCBRq1h$BuB_+l8bC?mI2^K7Vje#4G;^C9i{ne!yKTA$=r p_fLL-;ybdu+y>82FR_6$IXIPrQ@JUZn{v6yri*pakgtND&A#Ouc!>Z2 literal 0 HcmV?d00001 diff --git a/CPP/7zip/UI/FileManager/Move2.bmp b/CPP/7zip/UI/FileManager/Move2.bmp new file mode 100755 index 0000000000000000000000000000000000000000..58679eff9de4015a2150c9f548028a5e355f7454 GIT binary patch literal 406 zcmbVHyA6df3^dY7ucD` 4 || + (vi.dwMajorVersion == 4 && vi.dwMinorVersion > 0)); + } + g_IsNew_fMask = false; + } +} g_Init_fMask; + +// it's hack for supporting Windows NT +// constants are from WinUser.h + +#if(WINVER < 0x0500) +#define MIIM_STRING 0x00000040 +#define MIIM_BITMAP 0x00000080 +#define MIIM_FTYPE 0x00000100 +#endif + +static UINT Get_fMaskForString() +{ + return g_IsNew_fMask ? MIIM_STRING : MIIM_TYPE; +} + +static UINT Get_fMaskForFTypeAndString() +{ + return g_IsNew_fMask ? (MIIM_STRING | MIIM_FTYPE) : MIIM_TYPE; +} +*/ + +static inline UINT Get_fMaskForString() { return MIIM_TYPE; } +static inline UINT Get_fMaskForFTypeAndString() { return MIIM_TYPE; } + +static void MyChangeMenu(HMENU menuLoc, int level, int menuIndex) +{ + CMenu menu; + menu.Attach(menuLoc); + for (int i = 0;; i++) + { + CMenuItem item; + item.fMask = Get_fMaskForString() | MIIM_SUBMENU | MIIM_ID; + item.fType = MFT_STRING; + if (!menu.GetItem(i, true, item)) + break; + { + UString newString; + if (item.hSubMenu) + { + UInt32 langID = 0; + if (level == 1 && menuIndex == kMenuIndex_Bookmarks) + langID = kAddToFavoritesLangID; + else + { + MyChangeMenu(item.hSubMenu, level + 1, i); + if (level == 1 && menuIndex == kMenuIndex_View) + langID = kToolbarsLangID; + else if (level == 0 && i < sizeof(kTopMenuLangIDs) / sizeof(kTopMenuLangIDs[0])) + langID = kTopMenuLangIDs[i]; + else + continue; + } + newString = LangString(langID); + if (newString.IsEmpty()) + continue; + } + else + { + int langPos = FindLangItem(item.wID); + if (langPos < 0) + continue; + newString = LangString(kIDLangPairs[langPos].LangID); + if (newString.IsEmpty()) + continue; + UString shorcutString = item.StringValue; + int tabPos = shorcutString.ReverseFind(wchar_t('\t')); + if (tabPos >= 0) + newString += shorcutString.Mid(tabPos); + } + { + item.StringValue = newString; + item.fMask = Get_fMaskForString(); + item.fType = MFT_STRING; + menu.SetItem(i, true, item); + } + } + } +} + +static CMenu g_FileMenu; + +struct CFileMenuDestroyer +{ + ~CFileMenuDestroyer() { if ((HMENU)g_FileMenu != 0) g_FileMenu.Destroy(); } +} g_FileMenuDestroyer; + + +static void CopyMenu(HMENU srcMenuSpec, HMENU destMenuSpec) +{ + CMenu srcMenu; + srcMenu.Attach(srcMenuSpec); + CMenu destMenu; + destMenu.Attach(destMenuSpec); + int startPos = 0; + for (int i = 0;; i++) + { + CMenuItem item; + item.fMask = MIIM_STATE | MIIM_ID | Get_fMaskForFTypeAndString(); + item.fType = MFT_STRING; + if (srcMenu.GetItem(i, true, item)) + { + if (destMenu.InsertItem(startPos, true, item)) + startPos++; + } + else + break; + } +} + +void MyLoadMenu() +{ + HMENU baseMenu; + + #ifdef UNDER_CE + + HMENU oldMenu = g_App._commandBar.GetMenu(0); + if (oldMenu) + ::DestroyMenu(oldMenu); + BOOL b = g_App._commandBar.InsertMenubar(g_hInstance, IDM_MENU, 0); + baseMenu = g_App._commandBar.GetMenu(0); + if (!g_LangID.IsEmpty()) + MyChangeMenu(baseMenu, 0, 0); + g_App._commandBar.DrawMenuBar(0); + + #else + + HWND hWnd = g_HWND; + HMENU oldMenu = ::GetMenu(hWnd); + ::SetMenu(hWnd, ::LoadMenu(g_hInstance, MAKEINTRESOURCE(IDM_MENU))); + ::DestroyMenu(oldMenu); + baseMenu = ::GetMenu(hWnd); + if (!g_LangID.IsEmpty()) + MyChangeMenu(baseMenu, 0, 0); + ::DrawMenuBar(hWnd); + + #endif + + if ((HMENU)g_FileMenu != 0) + g_FileMenu.Destroy(); + g_FileMenu.CreatePopup(); + CopyMenu(::GetSubMenu(baseMenu, 0), g_FileMenu); +} + +void OnMenuActivating(HWND /* hWnd */, HMENU hMenu, int position) +{ + HMENU mainMenu = + #ifdef UNDER_CE + g_App._commandBar.GetMenu(0); + #else + ::GetMenu(g_HWND) + #endif + ; + if (::GetSubMenu(mainMenu, position) != hMenu) + return; + if (position == kMenuIndex_File) + { + CMenu menu; + menu.Attach(hMenu); + menu.RemoveAllItems(); + g_App.GetFocusedPanel().CreateFileMenu(hMenu); + } + else if (position == kMenuIndex_Edit) + { + /* + CMenu menu; + menu.Attach(hMenu); + menu.EnableItem(IDM_EDIT_CUT, MF_ENABLED); + menu.EnableItem(IDM_EDIT_COPY, MF_ENABLED); + menu.EnableItem(IDM_EDIT_PASTE, IsClipboardFormatAvailableHDROP() ? MF_ENABLED : MF_GRAYED); + */ + } + else if (position == kMenuIndex_View) + { + // View; + CMenu menu; + menu.Attach(hMenu); + menu.CheckRadioItem(IDM_VIEW_LARGE_ICONS, IDM_VIEW_DETAILS, + IDM_VIEW_LARGE_ICONS + g_App.GetListViewMode(), MF_BYCOMMAND); + + menu.CheckRadioItem(IDM_VIEW_ARANGE_BY_NAME, IDM_VIEW_ARANGE_NO_SORT, + GetSortControlID(g_App.GetSortID()), MF_BYCOMMAND); + + menu.CheckItemByID(IDM_VIEW_TWO_PANELS, g_App.NumPanels == 2); + menu.CheckItemByID(IDM_VIEW_FLAT_VIEW, g_App.GetFlatMode()); + menu.CheckItemByID(IDM_VIEW_ARCHIVE_TOOLBAR, g_App.ShowArchiveToolbar); + menu.CheckItemByID(IDM_VIEW_STANDARD_TOOLBAR, g_App.ShowStandardToolbar); + menu.CheckItemByID(IDM_VIEW_TOOLBARS_LARGE_BUTTONS, g_App.LargeButtons); + menu.CheckItemByID(IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT, g_App.ShowButtonsLables); + } + else if (position == kMenuIndex_Bookmarks) + { + CMenu menu; + menu.Attach(hMenu); + + CMenu subMenu; + subMenu.Attach(menu.GetSubMenu(0)); + subMenu.RemoveAllItems(); + int i; + for (i = 0; i < 10; i++) + { + UString s = LangString(IDS_BOOKMARK, 0x03000720); + s += L" "; + wchar_t c = (wchar_t)(L'0' + i); + s += c; + s += L"\tAlt+Shift+"; + s += c; + subMenu.AppendItem(MF_STRING, kSetBookmarkMenuID + i, s); + } + + menu.RemoveAllItemsFrom(2); + + for (i = 0; i < 10; i++) + { + UString path = g_App.AppState.FastFolders.GetString(i); + const int kMaxSize = 100; + const int kFirstPartSize = kMaxSize / 2; + if (path.Length() > kMaxSize) + { + path = path.Left(kFirstPartSize) + UString(L" ... ") + + path.Right(kMaxSize - kFirstPartSize); + } + UString s = path; + if (s.IsEmpty()) + s = L"-"; + s += L"\tAlt+"; + s += (wchar_t)(L'0' + i); + menu.AppendItem(MF_STRING, kOpenBookmarkMenuID + i, s); + } + } +} + +/* +It doesn't help +void OnMenuUnActivating(HWND hWnd, HMENU hMenu, int id) +{ + if (::GetSubMenu(::GetMenu(g_HWND), 0) != hMenu) + return; +} +*/ + +void LoadFileMenu(HMENU hMenu, int startPos, bool programMenu, + bool isFsFolder, int numItems, bool allAreFiles) +{ + CMenu destMenu; + destMenu.Attach(hMenu); + + UString diffPath; + ReadRegDiff(diffPath); + + int numRealItems = startPos; + for (int i = 0;; i++) + { + CMenuItem item; + + item.fMask = MIIM_STATE | MIIM_ID | Get_fMaskForFTypeAndString(); + item.fType = MFT_STRING; + if (!g_FileMenu.GetItem(i, true, item)) + break; + { + if (!programMenu && item.wID == IDCLOSE) + continue; + + if (item.wID == IDM_FILE_DIFF && diffPath.IsEmpty()) + continue; + + bool isOneFsFile = (isFsFolder && numItems == 1 && allAreFiles); + bool disable = ((item.wID == IDM_FILE_SPLIT || item.wID == IDM_FILE_COMBINE) && !isOneFsFile); + + bool isBigScreen = NControl::IsDialogSizeOK(40, 200); + + if (!isBigScreen && (disable || item.IsSeparator())) + continue; + if (destMenu.InsertItem(startPos, true, item)) + startPos++; + if (disable) + destMenu.EnableItem(startPos - 1, MF_BYPOSITION | MF_GRAYED); + + if (!item.IsSeparator()) + numRealItems = startPos; + } + } + destMenu.RemoveAllItemsFrom(numRealItems); +} + +bool ExecuteFileCommand(int id) +{ + if (id >= kPluginMenuStartID) + { + g_App.GetFocusedPanel().InvokePluginCommand(id); + g_App.GetFocusedPanel()._sevenZipContextMenu.Release(); + g_App.GetFocusedPanel()._systemContextMenu.Release(); + return true; + } + + switch (id) + { + // File + case IDM_FILE_OPEN: + g_App.OpenItem(); + break; + case IDM_FILE_OPEN_INSIDE: + g_App.OpenItemInside(); + break; + case IDM_FILE_OPEN_OUTSIDE: + g_App.OpenItemOutside(); + break; + case IDM_FILE_VIEW: + break; + case IDM_FILE_EDIT: + g_App.EditItem(); + break; + case IDM_RENAME: + g_App.Rename(); + break; + case IDM_COPY_TO: + g_App.CopyTo(); + break; + case IDM_MOVE_TO: + g_App.MoveTo(); + break; + case IDM_DELETE: + { + bool shift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0; + g_App.Delete(!shift); + break; + } + case IDM_FILE_CRC: + g_App.CalculateCrc(); + break; + case IDM_FILE_DIFF: + g_App.DiffFiles(); + break; + case IDM_FILE_SPLIT: + g_App.Split(); + break; + case IDM_FILE_COMBINE: + g_App.Combine(); + break; + case IDM_FILE_PROPERTIES: + g_App.Properties(); + break; + case IDM_FILE_COMMENT: + g_App.Comment(); + break; + + case IDM_CREATE_FOLDER: + g_App.CreateFolder(); + break; + case IDM_CREATE_FILE: + g_App.CreateFile(); + break; + default: + return false; + } + return true; +} + +bool OnMenuCommand(HWND hWnd, int id) +{ + if (ExecuteFileCommand(id)) + return true; + + switch (id) + { + // File + case IDCLOSE: + SendMessage(hWnd, WM_ACTIVATE, MAKEWPARAM(WA_INACTIVE, 0), (LPARAM)hWnd); + SendMessage (hWnd, WM_CLOSE, 0, 0); + break; + + // Edit + case IDM_EDIT_CUT: + g_App.EditCut(); + break; + case IDM_EDIT_COPY: + g_App.EditCopy(); + break; + case IDM_EDIT_PASTE: + g_App.EditPaste(); + break; + case IDM_SELECT_ALL: + g_App.SelectAll(true); + g_App.RefreshStatusBar(); + break; + case IDM_DESELECT_ALL: + g_App.SelectAll(false); + g_App.RefreshStatusBar(); + break; + case IDM_INVERT_SELECTION: + g_App.InvertSelection(); + g_App.RefreshStatusBar(); + break; + case IDM_SELECT: + g_App.SelectSpec(true); + g_App.RefreshStatusBar(); + break; + case IDM_DESELECT: + g_App.SelectSpec(false); + g_App.RefreshStatusBar(); + break; + case IDM_SELECT_BY_TYPE: + g_App.SelectByType(true); + g_App.RefreshStatusBar(); + break; + case IDM_DESELECT_BY_TYPE: + g_App.SelectByType(false); + g_App.RefreshStatusBar(); + break; + + //View + case IDM_VIEW_LARGE_ICONS: + case IDM_VIEW_SMALL_ICONS: + case IDM_VIEW_LIST: + case IDM_VIEW_DETAILS: + { + UINT index = id - IDM_VIEW_LARGE_ICONS; + if (index < 4) + { + g_App.SetListViewMode(index); + /* + CMenu menu; + menu.Attach(::GetSubMenu(::GetMenu(hWnd), kMenuIndex_View)); + menu.CheckRadioItem(IDM_VIEW_LARGE_ICONS, IDM_VIEW_DETAILS, + id, MF_BYCOMMAND); + */ + } + break; + } + case IDM_VIEW_ARANGE_BY_NAME: + { + g_App.SortItemsWithPropID(kpidName); + break; + } + case IDM_VIEW_ARANGE_BY_TYPE: + { + g_App.SortItemsWithPropID(kpidExtension); + break; + } + case IDM_VIEW_ARANGE_BY_DATE: + { + g_App.SortItemsWithPropID(kpidMTime); + break; + } + case IDM_VIEW_ARANGE_BY_SIZE: + { + g_App.SortItemsWithPropID(kpidSize); + break; + } + case IDM_VIEW_ARANGE_NO_SORT: + { + g_App.SortItemsWithPropID(kpidNoProperty); + break; + } + + case IDM_OPEN_ROOT_FOLDER: + g_App.OpenRootFolder(); + break; + case IDM_OPEN_PARENT_FOLDER: + g_App.OpenParentFolder(); + break; + case IDM_FOLDERS_HISTORY: + g_App.FoldersHistory(); + break; + case IDM_VIEW_REFRESH: + g_App.RefreshView(); + break; + case IDM_VIEW_FLAT_VIEW: + g_App.ChangeFlatMode(); + break; + case IDM_VIEW_TWO_PANELS: + g_App.SwitchOnOffOnePanel(); + break; + case IDM_VIEW_STANDARD_TOOLBAR: + g_App.SwitchStandardToolbar(); + break; + case IDM_VIEW_ARCHIVE_TOOLBAR: + g_App.SwitchArchiveToolbar(); + break; + case IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT: + g_App.SwitchButtonsLables(); + break; + case IDM_VIEW_TOOLBARS_LARGE_BUTTONS: + g_App.SwitchLargeButtons(); + break; + + // Tools + case IDM_OPTIONS: + OptionsDialog(hWnd, g_hInstance); + break; + + case IDM_BENCHMARK: + { + CPanel::CDisableTimerProcessing disableTimerProcessing1(g_App.Panels[0]); + CPanel::CDisableTimerProcessing disableTimerProcessing2(g_App.Panels[1]); + Benchmark(); + break; + } + // Help + case IDM_HELP_CONTENTS: + ShowHelpWindow(NULL, kFMHelpTopic); + break; + case IDM_ABOUT: + { + CAboutDialog dialog; + dialog.Create(hWnd); + break; + } + default: + { + if (id >= kOpenBookmarkMenuID && id <= kOpenBookmarkMenuID + 9) + { + g_App.OpenBookmark(id - kOpenBookmarkMenuID); + return true; + } + else if (id >= kSetBookmarkMenuID && id <= kSetBookmarkMenuID + 9) + { + g_App.SetBookmark(id - kSetBookmarkMenuID); + return true; + } + return false; + } + } + return true; +} diff --git a/CPP/7zip/UI/FileManager/MyLoadMenu.h b/CPP/7zip/UI/FileManager/MyLoadMenu.h new file mode 100755 index 0000000..5353d94 --- /dev/null +++ b/CPP/7zip/UI/FileManager/MyLoadMenu.h @@ -0,0 +1,16 @@ +// MyLoadMenu.h + +#ifndef __MY_LOAD_MENU_H +#define __MY_LOAD_MENU_H + +void OnMenuActivating(HWND hWnd, HMENU hMenu, int position); +// void OnMenuUnActivating(HWND hWnd, HMENU hMenu, int id); +// void OnMenuUnActivating(HWND hWnd); + +bool OnMenuCommand(HWND hWnd, int id); +void MyLoadMenu(); +void LoadFileMenu(HMENU hMenu, int startPos, bool programMenu, + bool isFsFolder, int numItems, bool allAreFiles); +bool ExecuteFileCommand(int id); + +#endif diff --git a/CPP/7zip/UI/FileManager/NetFolder.cpp b/CPP/7zip/UI/FileManager/NetFolder.cpp new file mode 100755 index 0000000..adf6e5b --- /dev/null +++ b/CPP/7zip/UI/FileManager/NetFolder.cpp @@ -0,0 +1,272 @@ +// NetFolder.cpp + +#include "StdAfx.h" + +#include "Windows/PropVariant.h" + +#include "../../PropID.h" + +#include "FSFolder.h" +#include "NetFolder.h" +#include "SysIconUtils.h" + +using namespace NWindows; +using namespace NNet; + +static const STATPROPSTG kProps[] = +{ + { NULL, kpidName, VT_BSTR}, + { NULL, kpidLocalName, VT_BSTR}, + { NULL, kpidComment, VT_BSTR}, + { NULL, kpidProvider, VT_BSTR} +}; + +void CNetFolder::Init(const UString &path) +{ + /* + if (path.Length() > 2) + { + if (path[0] == L'\\' && path[1] == L'\\') + { + CResource netResource; + netResource.RemoteName = GetSystemString(path.Left(path.Length() - 1)); + netResource.Scope = RESOURCE_GLOBALNET; + netResource.Type = RESOURCETYPE_DISK; + netResource.DisplayType = RESOURCEDISPLAYTYPE_SERVER; + netResource.Usage = RESOURCEUSAGE_CONTAINER; + Init(&netResource, 0, path); + return; + } + } + Init(0, 0 , L""); + */ + CResourceW resource; + resource.RemoteNameIsDefined = true; + resource.RemoteName = path.Left(path.Length() - 1); + resource.ProviderIsDefined = false; + resource.LocalNameIsDefined = false; + resource.CommentIsDefined = false; + resource.Type = RESOURCETYPE_DISK; + resource.Scope = RESOURCE_GLOBALNET; + resource.Usage = 0; + resource.DisplayType = 0; + CResourceW destResource; + UString systemPathPart; + DWORD result = GetResourceInformation(resource, destResource, systemPathPart); + if (result == NO_ERROR) + Init(&destResource, 0, path); + else + Init(0, 0 , L""); + return; +} + +void CNetFolder::Init(const NWindows::NNet::CResourceW *netResource, + IFolderFolder *parentFolder, const UString &path) +{ + _path = path; + if (netResource == 0) + _netResourcePointer = 0; + else + { + _netResource = *netResource; + _netResourcePointer = &_netResource; + + // if (_netResource.DisplayType == RESOURCEDISPLAYTYPE_SERVER) + _path = _netResource.RemoteName + WCHAR_PATH_SEPARATOR; + } + _parentFolder = parentFolder; +} + +STDMETHODIMP CNetFolder::LoadItems() +{ + _items.Clear(); + CEnum enumerator; + + for (;;) + { + DWORD result = enumerator.Open( + RESOURCE_GLOBALNET, + RESOURCETYPE_DISK, + 0, // enumerate all resources + _netResourcePointer + ); + if (result == NO_ERROR) + break; + if (result != ERROR_ACCESS_DENIED) + return result; + if (_netResourcePointer != 0) + result = AddConnection2(_netResource, + 0, 0, CONNECT_INTERACTIVE); + if (result != NO_ERROR) + return result; + } + + for (;;) + { + CResourceEx resource; + DWORD result = enumerator.Next(resource); + if (result == NO_ERROR) + { + if (!resource.RemoteNameIsDefined) // For Win 98, I don't know what's wrong + resource.RemoteName = resource.Comment; + resource.Name = resource.RemoteName; + int pos = resource.Name.ReverseFind(WCHAR_PATH_SEPARATOR); + if (pos >= 0) + { + // _path = resource.Name.Left(pos + 1); + resource.Name = resource.Name.Mid(pos + 1); + } + _items.Add(resource); + } + else if (result == ERROR_NO_MORE_ITEMS) + break; + else + return result; + } + + /* + It's too slow for some systems. + if (_netResourcePointer && _netResource.DisplayType == RESOURCEDISPLAYTYPE_SERVER) + { + for (char c = 'a'; c <= 'z'; c++) + { + CResourceEx resource; + resource.Name = UString(wchar_t(c)) + L'$'; + resource.RemoteNameIsDefined = true; + resource.RemoteName = _path + resource.Name; + + NFile::NFind::CFindFile findFile; + NFile::NFind::CFileInfoW fileInfo; + if (!findFile.FindFirst(resource.RemoteName + UString(WCHAR_PATH_SEPARATOR) + UString(L"*"), fileInfo)) + continue; + resource.Usage = RESOURCEUSAGE_CONNECTABLE; + resource.LocalNameIsDefined = false; + resource.CommentIsDefined = false; + resource.ProviderIsDefined = false; + _items.Add(resource); + } + } + */ + return S_OK; +} + + +STDMETHODIMP CNetFolder::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _items.Size(); + return S_OK; +} + +STDMETHODIMP CNetFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + const CResourceEx &item = _items[itemIndex]; + switch(propID) + { + case kpidIsDir: prop = true; break; + case kpidName: + // if (item.RemoteNameIsDefined) + prop = item.Name; + break; + case kpidLocalName: if (item.LocalNameIsDefined) prop = item.LocalName; break; + case kpidComment: if (item.CommentIsDefined) prop = item.Comment; break; + case kpidProvider: if (item.ProviderIsDefined) prop = item.Provider; break; + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CNetFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder) +{ + *resultFolder = 0; + const CResourceEx &resource = _items[index]; + if (resource.Usage == RESOURCEUSAGE_CONNECTABLE || + resource.DisplayType == RESOURCEDISPLAYTYPE_SHARE) + { + NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder; + CMyComPtr subFolder = fsFolderSpec; + RINOK(fsFolderSpec->Init(resource.RemoteName + WCHAR_PATH_SEPARATOR, this)); + *resultFolder = subFolder.Detach(); + } + else + { + CNetFolder *netFolder = new CNetFolder; + CMyComPtr subFolder = netFolder; + netFolder->Init(&resource, this, resource.Name + WCHAR_PATH_SEPARATOR); + *resultFolder = subFolder.Detach(); + } + return S_OK; +} + +STDMETHODIMP CNetFolder::BindToFolder(const wchar_t * /* name */, IFolderFolder ** /* resultFolder */) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CNetFolder::BindToParentFolder(IFolderFolder **resultFolder) +{ + *resultFolder = 0; + if (_parentFolder) + { + CMyComPtr parentFolder = _parentFolder; + *resultFolder = parentFolder.Detach(); + return S_OK; + } + if (_netResourcePointer != 0) + { + CResourceW resourceParent; + DWORD result = GetResourceParent(_netResource, resourceParent); + if (result != NO_ERROR) + return result; + if (!_netResource.RemoteNameIsDefined) + return S_OK; + + CNetFolder *netFolder = new CNetFolder; + CMyComPtr subFolder = netFolder; + netFolder->Init(&resourceParent, 0, WCHAR_PATH_SEPARATOR); + *resultFolder = subFolder.Detach(); + } + return S_OK; +} + +IMP_IFolderFolder_Props(CNetFolder) + +STDMETHODIMP CNetFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) +{ + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidType: prop = L"NetFolder"; break; + case kpidPath: prop = _path; break; + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CNetFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex) +{ + if (index >= (UInt32)_items.Size()) + return E_INVALIDARG; + *iconIndex = 0; + const CResourceW &resource = _items[index]; + int iconIndexTemp; + if (resource.DisplayType == RESOURCEDISPLAYTYPE_SERVER || + resource.Usage == RESOURCEUSAGE_CONNECTABLE) + { + if (GetRealIconIndex(resource.RemoteName, 0, iconIndexTemp)) + { + *iconIndex = iconIndexTemp; + return S_OK; + } + } + else + { + if (GetRealIconIndex(TEXT(""), FILE_ATTRIBUTE_DIRECTORY, iconIndexTemp)) + { + *iconIndex = iconIndexTemp; + return S_OK; + } + // *anIconIndex = GetRealIconIndex(0, L"\\\\HOME"); + } + return GetLastError(); +} diff --git a/CPP/7zip/UI/FileManager/NetFolder.h b/CPP/7zip/UI/FileManager/NetFolder.h new file mode 100755 index 0000000..3fc1cdb --- /dev/null +++ b/CPP/7zip/UI/FileManager/NetFolder.h @@ -0,0 +1,40 @@ +// NetFolder.h + +#ifndef __NET_FOLDER_H +#define __NET_FOLDER_H + +#include "Common/MyCom.h" + +#include "Windows/Net.h" + +#include "IFolder.h" + +struct CResourceEx: public NWindows::NNet::CResourceW +{ + UString Name; +}; + +class CNetFolder: + public IFolderFolder, + public IFolderGetSystemIconIndex, + public CMyUnknownImp +{ + NWindows::NNet::CResourceW _netResource; + NWindows::NNet::CResourceW *_netResourcePointer; + + CObjectVector _items; + + CMyComPtr _parentFolder; + UString _path; +public: + MY_UNKNOWN_IMP1(IFolderGetSystemIconIndex) + INTERFACE_FolderFolder(;) + STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex); + + CNetFolder(): _netResourcePointer(0) {} + void Init(const UString &path); + void Init(const NWindows::NNet::CResourceW *netResource, + IFolderFolder *parentFolder, const UString &path); +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/OpenCallback.cpp b/CPP/7zip/UI/FileManager/OpenCallback.cpp new file mode 100755 index 0000000..08c3adf --- /dev/null +++ b/CPP/7zip/UI/FileManager/OpenCallback.cpp @@ -0,0 +1,123 @@ +// OpenCallback.cpp + +#include "StdAfx.h" + +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" + +#include "../../Common/FileStreams.h" + +#include "OpenCallback.h" +#include "PasswordDialog.h" + +using namespace NWindows; + +STDMETHODIMP COpenArchiveCallback::SetTotal(const UInt64 *numFiles, const UInt64 *numBytes) +{ + RINOK(ProgressDialog.Sync.ProcessStopAndPause()); + { + NSynchronization::CCriticalSectionLock lock(_criticalSection); + if (numFiles != NULL) + { + ProgressDialog.Sync.SetNumFilesTotal(*numFiles); + ProgressDialog.Sync.SetBytesProgressMode(false); + } + if (numBytes != NULL) + ProgressDialog.Sync.SetNumBytesTotal(*numBytes); + } + return S_OK; +} + +STDMETHODIMP COpenArchiveCallback::SetCompleted(const UInt64 *numFiles, const UInt64 *numBytes) +{ + RINOK(ProgressDialog.Sync.ProcessStopAndPause()); + NSynchronization::CCriticalSectionLock lock(_criticalSection); + if (numFiles != NULL) + ProgressDialog.Sync.SetNumFilesCur(*numFiles); + if (numBytes != NULL) + ProgressDialog.Sync.SetPos(*numBytes); + return S_OK; +} + +STDMETHODIMP COpenArchiveCallback::SetTotal(const UInt64 total) +{ + RINOK(ProgressDialog.Sync.ProcessStopAndPause()); + ProgressDialog.Sync.SetNumBytesTotal(total); + return S_OK; +} + +STDMETHODIMP COpenArchiveCallback::SetCompleted(const UInt64 *completed) +{ + RINOK(ProgressDialog.Sync.ProcessStopAndPause()); + if (completed != NULL) + ProgressDialog.Sync.SetPos(*completed); + return S_OK; +} + +STDMETHODIMP COpenArchiveCallback::GetProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + if (_subArchiveMode) + { + switch(propID) + { + case kpidName: prop = _subArchiveName; break; + } + } + 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; +} + +STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, + IInStream **inStream) +{ + *inStream = NULL; + if (_subArchiveMode) + return S_FALSE; + + NFile::NFind::CFileInfoW fileInfo; + + UString fullPath = _folderPrefix + name; + if (!fileInfo.Find(fullPath)) + return S_FALSE; + _fileInfo = fileInfo; + if (_fileInfo.IsDir()) + return S_FALSE; + CInFileStream *inFile = new CInFileStream; + CMyComPtr inStreamTemp = inFile; + if (!inFile->Open(fullPath)) + return ::GetLastError(); + *inStream = inStreamTemp.Detach(); + return S_OK; +} + +STDMETHODIMP COpenArchiveCallback::CryptoGetTextPassword(BSTR *password) +{ + PasswordWasAsked = true; + if (!PasswordIsDefined) + { + CPasswordDialog dialog; + + ProgressDialog.WaitCreating(); + if (dialog.Create(ProgressDialog) == IDCANCEL) + return E_ABORT; + + Password = dialog.Password; + PasswordIsDefined = true; + } + return StringToBstr(Password, password); +} diff --git a/CPP/7zip/UI/FileManager/OpenCallback.h b/CPP/7zip/UI/FileManager/OpenCallback.h new file mode 100755 index 0000000..31ef1f2 --- /dev/null +++ b/CPP/7zip/UI/FileManager/OpenCallback.h @@ -0,0 +1,92 @@ +// OpenCallback.h + +#ifndef __OPENCALLBACK_H +#define __OPENCALLBACK_H + +#include "Common/MyCom.h" +#include "Common/MyString.h" + +#include "Windows/FileFind.h" + +#include "../../IPassword.h" + +#include "../../Archive/IArchive.h" + +#ifdef _SFX +#include "ProgressDialog.h" +#else +#include "ProgressDialog2.h" +#endif + + +class COpenArchiveCallback: + public IArchiveOpenCallback, + public IArchiveOpenVolumeCallback, + public IArchiveOpenSetSubArchiveName, + public IProgress, + public ICryptoGetTextPassword, + public CMyUnknownImp +{ + UString _folderPrefix; + NWindows::NFile::NFind::CFileInfoW _fileInfo; + NWindows::NSynchronization::CCriticalSection _criticalSection; + bool _subArchiveMode; + UString _subArchiveName; + +public: + bool PasswordIsDefined; + bool PasswordWasAsked; + UString Password; + HWND ParentWindow; + CProgressDialog ProgressDialog; + + MY_UNKNOWN_IMP5( + IArchiveOpenCallback, + IArchiveOpenVolumeCallback, + IArchiveOpenSetSubArchiveName, + IProgress, + ICryptoGetTextPassword) + + INTERFACE_IProgress(;) + INTERFACE_IArchiveOpenCallback(;) + INTERFACE_IArchiveOpenVolumeCallback(;) + + // ICryptoGetTextPassword + STDMETHOD(CryptoGetTextPassword)(BSTR *password); + + STDMETHOD(SetSubArchiveName(const wchar_t *name)) + { + _subArchiveMode = true; + _subArchiveName = name; + return S_OK; + } + + COpenArchiveCallback(): + ParentWindow(0) + { + _subArchiveMode = false; + PasswordIsDefined = false; + PasswordWasAsked = false; + } + /* + void Init() + { + PasswordIsDefined = false; + _subArchiveMode = false; + } + */ + void LoadFileInfo(const UString &folderPrefix, const UString &fileName) + { + _folderPrefix = folderPrefix; + if (!_fileInfo.Find(_folderPrefix + fileName)) + throw 1; + } + void ShowMessage(const UInt64 *completed); + + INT_PTR StartProgressDialog(const UString &title, NWindows::CThread &thread) + { + return ProgressDialog.Create(title, thread, ParentWindow); + } +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/OptionsDialog.cpp b/CPP/7zip/UI/FileManager/OptionsDialog.cpp new file mode 100755 index 0000000..db237cd --- /dev/null +++ b/CPP/7zip/UI/FileManager/OptionsDialog.cpp @@ -0,0 +1,145 @@ +// OptionsDialog.cpp + +#include "StdAfx.h" + +#include "Windows/Control/Dialog.h" +#include "Windows/Control/PropertyPage.h" + +#include "DialogSize.h" +#include "EditPage.h" +#include "EditPageRes.h" +#include "FoldersPage.h" +#include "FoldersPageRes.h" +#include "LangPage.h" +#include "LangPageRes.h" +#include "MenuPage.h" +#include "MenuPageRes.h" +// #include "PluginsPage.h" +// #include "PluginsPageRes.h" +#include "SettingsPage.h" +#include "SettingsPageRes.h" +#include "SystemPage.h" +#include "SystemPageRes.h" + +#include "App.h" +#include "LangUtils.h" +#include "MyLoadMenu.h" +#include "ProgramLocation.h" + +#include "resource.h" + +using namespace NWindows; + +#ifndef UNDER_CE +typedef UINT32 (WINAPI * DllRegisterServerPtr)(); + +extern HWND g_MenuPageHWND; + +static void ShowMenuErrorMessage(const wchar_t *m) +{ + MessageBoxW(g_MenuPageHWND, m, L"7-Zip", MB_ICONERROR); +} + +static int DllRegisterServer2(const char *name) +{ + NWindows::NDLL::CLibrary lib; + + UString prefix; + GetProgramFolderPath(prefix); + if (!lib.Load(prefix + L"7-zip.dll")) + { + ShowMenuErrorMessage(L"7-Zip cannot load 7-zip.dll"); + return E_FAIL; + } + DllRegisterServerPtr f = (DllRegisterServerPtr)lib.GetProc(name); + if (f == NULL) + { + ShowMenuErrorMessage(L"Incorrect plugin"); + return E_FAIL; + } + HRESULT res = f(); + if (res != S_OK) + ShowMenuErrorMessage(HResultToMessage(res)); + return (int)res; +} + +STDAPI DllRegisterServer(void) +{ + #ifdef UNDER_CE + return S_OK; + #else + return DllRegisterServer2("DllRegisterServer"); + #endif +} + +STDAPI DllUnregisterServer(void) +{ + #ifdef UNDER_CE + return S_OK; + #else + return DllRegisterServer2("DllUnregisterServer"); + #endif +} + +#endif + +void OptionsDialog(HWND hwndOwner, HINSTANCE /* hInstance */) +{ + CSystemPage systemPage; + // CPluginsPage pluginsPage; + CEditPage editPage; + CSettingsPage settingsPage; + CLangPage langPage; + CMenuPage menuPage; + CFoldersPage foldersPage; + + CObjectVector pages; + UINT32 langIDs[] = { 0x03010300, + // 0x03010100, + 0xFFFFFFFF, + 0x01000200, 0x03010200, 0x03010400, 0x01000400}; + + BIG_DIALOG_SIZE(200, 200); + + UINT pageIDs[] = { + SIZED_DIALOG(IDD_SYSTEM), + // IDD_PLUGINS, + SIZED_DIALOG(IDD_MENU), + SIZED_DIALOG(IDD_FOLDERS), + SIZED_DIALOG(IDD_EDIT), + SIZED_DIALOG(IDD_SETTINGS), + SIZED_DIALOG(IDD_LANG) }; + NControl::CPropertyPage *pagePinters[] = { &systemPage, &menuPage, &foldersPage, &editPage, &settingsPage, &langPage }; + const int kNumPages = sizeof(langIDs) / sizeof(langIDs[0]); + for (int i = 0; i < kNumPages; i++) + { + NControl::CPageInfo page; + page.Title = LangString(langIDs[i]); + page.ID = pageIDs[i]; + page.Page = pagePinters[i]; + pages.Add(page); + } + + INT_PTR res = NControl::MyPropertySheet(pages, hwndOwner, LangString(IDS_OPTIONS, 0x03010000)); + if (res != -1 && res != 0) + { + if (langPage.LangWasChanged) + { + g_App._window.SetText(LangString(IDS_APP_TITLE, 0x03000000)); + MyLoadMenu(); + g_App.ReloadToolbars(); + g_App.MoveSubWindows(); + } + /* + if (systemPage.WasChanged) + { + // probably it doesn't work, since image list is locked? + g_App.SysIconsWereChanged(); + } + */ + g_App.SetListSettings(); + g_App.SetShowSystemMenu(); + g_App.RefreshAllPanels(); + // ::PostMessage(hwndOwner, kLangWasChangedMessage, 0 , 0); + } +} diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.cpp b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp new file mode 100755 index 0000000..17d2712 --- /dev/null +++ b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp @@ -0,0 +1,137 @@ +// OverwriteDialog.cpp + +#include "StdAfx.h" + +#include "Common/StringConvert.h" + +#include "Windows/FileName.h" +#include "Windows/Defs.h" +#include "Windows/ResourceString.h" +#include "Windows/Control/Static.h" +#include "Windows/PropVariantConversions.h" + +#include "FormatUtils.h" +#include "OverwriteDialog.h" + +// #include "../resource.h" + +#ifdef LANG +#include "LangUtils.h" +#endif + +using namespace NWindows; + +#ifdef LANG +static CIDLangPair kIDLangPairs[] = +{ + { IDC_STATIC_OVERWRITE_HEADER, 0x02000901}, + { IDC_STATIC_OVERWRITE_QUESTION_BEGIN, 0x02000902 }, + { IDC_STATIC_OVERWRITE_QUESTION_END, 0x02000903 }, + { IDYES, 0x02000705 }, + { IDC_BUTTON_OVERWRITE_YES_TO_ALL, 0x02000707 }, + { IDNO, 0x02000709 }, + { IDC_BUTTON_OVERWRITE_NO_TO_ALL,0x0200070B }, + { IDC_BUTTON_OVERWRITE_AUTO_RENAME, 0x02000911 }, + { IDCANCEL, 0x02000711 } +}; +#endif + +static const int kCurrentFileNameSizeLimit = 82; +static const int kCurrentFileNameSizeLimit2 = 30; + +void COverwriteDialog::ReduceString(UString &s) +{ + int size = _isBig ? kCurrentFileNameSizeLimit : kCurrentFileNameSizeLimit2; + if (s.Length() > size) + s = s.Left(size / 2) + UString(L" ... ") + s.Right(size / 2); +} + +void COverwriteDialog::SetFileInfoControl(int textID, int iconID, + const NOverwriteDialog::CFileInfo &fileInfo) +{ + UString sizeString; + if (fileInfo.SizeIsDefined) + sizeString = MyFormatNew(IDS_FILE_SIZE, + #ifdef LANG + 0x02000982, + #endif + NumberToString(fileInfo.Size)); + + const UString &fileName = fileInfo.Name; + int slashPos = fileName.ReverseFind(WCHAR_PATH_SEPARATOR); + UString s1, s2; + if (slashPos >= 0) + { + s1 = fileName.Left(slashPos + 1); + s2 = fileName.Mid(slashPos + 1); + } + else + s2 = fileName; + ReduceString(s1); + ReduceString(s2); + + UString fullString = s1 + L'\n' + s2; + fullString += L'\n'; + fullString += sizeString; + fullString += L'\n'; + + if (fileInfo.TimeIsDefined) + { + UString timeString; + FILETIME localFileTime; + if (!FileTimeToLocalFileTime(&fileInfo.Time, &localFileTime)) + throw 4190402; + timeString = ConvertFileTimeToString(localFileTime); + + fullString += + #ifdef LANG + LangString(IDS_FILE_MODIFIED, 0x02000983); + #else + MyLoadStringW(IDS_FILE_MODIFIED); + #endif + + fullString += L" "; + fullString += timeString; + } + + NWindows::NControl::CDialogChildControl control; + control.Init(*this, textID); + control.SetText(fullString); + + 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(HWND(*this), 0x02000900); + LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + #endif + SetFileInfoControl(IDC_STATIC_OVERWRITE_OLD_FILE_SIZE_TIME, IDC_STATIC_OVERWRITE_OLD_FILE_ICON, OldFileInfo); + SetFileInfoControl(IDC_STATIC_OVERWRITE_NEW_FILE_SIZE_TIME, IDC_STATIC_OVERWRITE_NEW_FILE_ICON, NewFileInfo); + NormalizePosition(); + return CModalDialog::OnInit(); +} + +bool COverwriteDialog::OnButtonClicked(int buttonID, HWND buttonHWND) +{ + switch(buttonID) + { + case IDYES: + case IDC_BUTTON_OVERWRITE_YES_TO_ALL: + case IDNO: + case IDC_BUTTON_OVERWRITE_NO_TO_ALL: + case IDC_BUTTON_OVERWRITE_AUTO_RENAME: + End(buttonID); + return true; + } + return CModalDialog::OnButtonClicked(buttonID, buttonHWND); +} diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.h b/CPP/7zip/UI/FileManager/OverwriteDialog.h new file mode 100755 index 0000000..3fef9b2 --- /dev/null +++ b/CPP/7zip/UI/FileManager/OverwriteDialog.h @@ -0,0 +1,71 @@ +// OverwriteDialog.h + +#ifndef __OVERWRITE_DIALOG_H +#define __OVERWRITE_DIALOG_H + +#include "Common/Types.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_DIALOG_OVERWRITE), parent); + } + + NOverwriteDialog::CFileInfo OldFileInfo; + NOverwriteDialog::CFileInfo NewFileInfo; +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.rc b/CPP/7zip/UI/FileManager/OverwriteDialog.rc new file mode 100755 index 0000000..55a08fc --- /dev/null +++ b/CPP/7zip/UI/FileManager/OverwriteDialog.rc @@ -0,0 +1,92 @@ +#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_DIALOG_OVERWRITE MY_DIALOG +CAPTION "Confirm File Replace" +BEGIN + LTEXT "Destination folder already contains processed file.", IDC_STATIC_OVERWRITE_HEADER, m, 7, xc, 8 + LTEXT "Would you like to replace the existing file", IDC_STATIC_OVERWRITE_QUESTION_BEGIN, m, 28, xc, 8 + + ICON "", IDC_STATIC_OVERWRITE_OLD_FILE_ICON, m, 44, iconSize, iconSize + LTEXT "", IDC_STATIC_OVERWRITE_OLD_FILE_SIZE_TIME, x, 44, fx, fy, SS_NOPREFIX + + LTEXT "with this one?",IDC_STATIC_OVERWRITE_QUESTION_END, m, 98, xc, 8 + + ICON "",IDC_STATIC_OVERWRITE_NEW_FILE_ICON, m, 114, iconSize, iconSize + LTEXT "",IDC_STATIC_OVERWRITE_NEW_FILE_SIZE_TIME, x, 114, fx, fy, SS_NOPREFIX + + PUSHBUTTON "&Yes", IDYES, bx3, by2, bxs, bys + PUSHBUTTON "Yes to &All", IDC_BUTTON_OVERWRITE_YES_TO_ALL, bx2, by2, bxs, bys + PUSHBUTTON "A&uto Rename", IDC_BUTTON_OVERWRITE_AUTO_RENAME, bx1, by2, bSizeBig, bys + PUSHBUTTON "&No", IDNO, bx3, by1, bxs, bys + PUSHBUTTON "No to A&ll", IDC_BUTTON_OVERWRITE_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_DIALOG_OVERWRITE_2 MY_DIALOG +CAPTION "Confirm File Replace" +BEGIN + LTEXT "Would you like to replace the existing file", IDC_STATIC_OVERWRITE_QUESTION_BEGIN, m, m, xc, 8 + + ICON "", IDC_STATIC_OVERWRITE_OLD_FILE_ICON, m, 20, iconSize, iconSize + LTEXT "", IDC_STATIC_OVERWRITE_OLD_FILE_SIZE_TIME, x, 20, fx, fy, SS_NOPREFIX + + LTEXT "with this one?",IDC_STATIC_OVERWRITE_QUESTION_END, m, 60, xc, 8 + + ICON "",IDC_STATIC_OVERWRITE_NEW_FILE_ICON, m, 72, iconSize, iconSize + LTEXT "",IDC_STATIC_OVERWRITE_NEW_FILE_SIZE_TIME, x, 72, fx, fy, SS_NOPREFIX + + PUSHBUTTON "&Yes", IDYES, bx3, by2, bxs, bys + PUSHBUTTON "Yes to &All", IDC_BUTTON_OVERWRITE_YES_TO_ALL, bx2, by2, bxs, bys + PUSHBUTTON "A&uto Rename", IDC_BUTTON_OVERWRITE_AUTO_RENAME, bx1, by2, bxs, bys + PUSHBUTTON "&No", IDNO, bx3, by1, bxs, bys + PUSHBUTTON "No to A&ll", IDC_BUTTON_OVERWRITE_NO_TO_ALL, bx2, by1, bxs, bys + PUSHBUTTON "&Cancel", IDCANCEL, bx1, by1, bxs, bys +END + +#endif + + +STRINGTABLE +BEGIN + IDS_FILE_MODIFIED "modified on" + IDS_FILE_SIZE "{0} bytes" +END diff --git a/CPP/7zip/UI/FileManager/OverwriteDialogRes.h b/CPP/7zip/UI/FileManager/OverwriteDialogRes.h new file mode 100755 index 0000000..42699db --- /dev/null +++ b/CPP/7zip/UI/FileManager/OverwriteDialogRes.h @@ -0,0 +1,20 @@ +#define IDD_DIALOG_OVERWRITE 502 +#define IDD_DIALOG_OVERWRITE_2 602 + +#define IDS_FILE_MODIFIED 600 +#define IDS_FILE_SIZE 601 + +#define IDC_STATIC_OVERWRITE_HEADER 1000 + +#define IDC_STATIC_OVERWRITE_QUESTION_BEGIN 1001 +#define IDC_STATIC_OVERWRITE_QUESTION_END 1002 + +#define IDC_STATIC_OVERWRITE_OLD_FILE_ICON 1003 +#define IDC_STATIC_OVERWRITE_NEW_FILE_ICON 1004 + +#define IDC_STATIC_OVERWRITE_OLD_FILE_SIZE_TIME 1005 +#define IDC_STATIC_OVERWRITE_NEW_FILE_SIZE_TIME 1006 + +#define IDC_BUTTON_OVERWRITE_YES_TO_ALL 1010 +#define IDC_BUTTON_OVERWRITE_NO_TO_ALL 1011 +#define IDC_BUTTON_OVERWRITE_AUTO_RENAME 1012 diff --git a/CPP/7zip/UI/FileManager/Panel.cpp b/CPP/7zip/UI/FileManager/Panel.cpp new file mode 100755 index 0000000..3106b84 --- /dev/null +++ b/CPP/7zip/UI/FileManager/Panel.cpp @@ -0,0 +1,991 @@ +// Panel.cpp + +#include "StdAfx.h" + +#include + +#include "Common/Defs.h" +#include "Common/IntToString.h" +#include "Common/StringConvert.h" + +#include "Windows/Error.h" +#include "Windows/PropVariant.h" +#include "Windows/Thread.h" + +#include "../../PropID.h" + +#include "resource.h" +#include "../GUI/ExtractRes.h" + +#include "../Common/ArchiveName.h" +#include "../Common/CompressCall.h" + +#include "../Agent/IFolderArchive.h" + +#include "App.h" +#include "ExtractCallback.h" +#include "FSFolder.h" +#include "FormatUtils.h" +#include "Panel.h" +#include "RootFolder.h" + + +using namespace NWindows; +using namespace NControl; + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +static const UINT_PTR kTimerID = 1; +static const UINT kTimerElapse = 1000; + +static DWORD kStyles[4] = { LVS_ICON, LVS_SMALLICON, LVS_LIST, LVS_REPORT }; + +// static const int kCreateFolderID = 101; +// static const UINT kFileChangeNotifyMessage = WM_APP; + +extern HINSTANCE g_hInstance; +extern DWORD g_ComCtl32Version; + +void CPanel::Release() +{ + // It's for unloading COM dll's: don't change it. + CloseOpenFolders(); + _sevenZipContextMenu.Release(); + _systemContextMenu.Release(); +} + +CPanel::~CPanel() +{ + CloseOpenFolders(); +} + +HWND CPanel::GetParent() +{ + HWND h = CWindow2::GetParent(); + return (h == 0) ? _mainWindow : h; +} + +static LPCWSTR kClassName = L"7-Zip::Panel"; + + +HRESULT CPanel::Create(HWND mainWindow, HWND parentWindow, UINT id, + const UString ¤tFolderPrefix, + const UString &arcFormat, + CPanelCallback *panelCallback, CAppState *appState, + bool &archiveIsOpened, bool &encrypted) +{ + _mainWindow = mainWindow; + _processTimer = true; + _processNotify = true; + + _panelCallback = panelCallback; + _appState = appState; + // _index = index; + _baseID = id; + _comboBoxID = _baseID + 3; + _statusBarID = _comboBoxID + 1; + + UString cfp = currentFolderPrefix; + + if (!currentFolderPrefix.IsEmpty()) + if (currentFolderPrefix[0] == L'.') + if (!NFile::NDirectory::MyGetFullPathName(currentFolderPrefix, cfp)) + cfp = currentFolderPrefix; + RINOK(BindToPath(cfp, arcFormat, archiveIsOpened, encrypted)); + + if (!CreateEx(0, kClassName, 0, WS_CHILD | WS_VISIBLE, + 0, 0, _xSize, 260, + parentWindow, (HMENU)(UINT_PTR)id, g_hInstance)) + return E_FAIL; + return S_OK; +} + +LRESULT CPanel::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case kShiftSelectMessage: + OnShiftSelectMessage(); + return 0; + case kReLoadMessage: + RefreshListCtrl(_selectedState); + return 0; + case kSetFocusToListView: + _listView.SetFocus(); + return 0; + case kOpenItemChanged: + return OnOpenItemChanged(lParam); + case kRefreshStatusBar: + OnRefreshStatusBar(); + return 0; + case kRefreshHeaderComboBox: + LoadFullPathAndShow(); + return 0; + case WM_TIMER: + OnTimer(); + return 0; + case WM_CONTEXTMENU: + if (OnContextMenu(HANDLE(wParam), GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))) + return 0; + break; + /* + case WM_DROPFILES: + CompressDropFiles(HDROP(wParam)); + return 0; + */ + } + return CWindow2::OnMessage(message, wParam, lParam); +} + +static LRESULT APIENTRY ListViewSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + CWindow tempDialog(hwnd); + CMyListView *w = (CMyListView *)(tempDialog.GetUserDataLongPtr()); + if (w == NULL) + return 0; + return w->OnMessage(message, wParam, lParam); +} + +LRESULT CMyListView::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + if (message == WM_CHAR) + { + UINT scanCode = (UINT)((lParam >> 16) & 0xFF); + bool extended = ((lParam & 0x1000000) != 0); + UINT virtualKey = MapVirtualKey(scanCode, 1); + if (virtualKey == VK_MULTIPLY || virtualKey == VK_ADD || + virtualKey == VK_SUBTRACT) + return 0; + if ((wParam == '/' && extended) + || wParam == '\\' || wParam == '/') + { + _panel->OpenDrivesFolder(); + return 0; + } + } + else if (message == WM_SYSCHAR) + { + // For Alt+Enter Beep disabling + UINT scanCode = (UINT)(lParam >> 16) & 0xFF; + UINT virtualKey = MapVirtualKey(scanCode, 1); + if (virtualKey == VK_RETURN || virtualKey == VK_MULTIPLY || + virtualKey == VK_ADD || virtualKey == VK_SUBTRACT) + return 0; + } + /* + else if (message == WM_SYSKEYDOWN) + { + // return 0; + } + */ + else if (message == WM_KEYDOWN) + { + bool alt = (::GetKeyState(VK_MENU) & 0x8000) != 0; + bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0; + // bool leftCtrl = (::GetKeyState(VK_LCONTROL) & 0x8000) != 0; + // bool RightCtrl = (::GetKeyState(VK_RCONTROL) & 0x8000) != 0; + bool shift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0; + switch(wParam) + { + /* + case VK_RETURN: + { + if (shift && !alt && !ctrl) + { + _panel->OpenSelectedItems(false); + return 0; + } + break; + } + */ + case VK_NEXT: + { + if (ctrl && !alt && !shift) + { + _panel->OpenFocusedItemAsInternal(); + return 0; + } + break; + } + case VK_PRIOR: + if (ctrl && !alt && !shift) + { + _panel->OpenParentFolder(); + return 0; + } + } + } + #ifdef UNDER_CE + else if (message == WM_KEYUP) + { + if (wParam == VK_F2) // it's VK_TSOFT2 + { + // Activate Menu + ::PostMessage(g_HWND, WM_SYSCOMMAND, SC_KEYMENU, 0); + return 0; + } + } + #endif + else if (message == WM_SETFOCUS) + { + _panel->_lastFocusedIsList = true; + _panel->_panelCallback->PanelWasFocused(); + } + #ifndef _UNICODE + if (g_IsNT) + return CallWindowProcW(_origWindowProc, *this, message, wParam, lParam); + else + #endif + return CallWindowProc(_origWindowProc, *this, message, wParam, lParam); +} + +/* +static LRESULT APIENTRY ComboBoxSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + CWindow tempDialog(hwnd); + CMyComboBox *w = (CMyComboBox *)(tempDialog.GetUserDataLongPtr()); + if (w == NULL) + return 0; + return w->OnMessage(message, wParam, lParam); +} + +LRESULT CMyComboBox::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + return CallWindowProc(_origWindowProc, *this, message, wParam, lParam); +} +*/ +static LRESULT APIENTRY ComboBoxEditSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + CWindow tempDialog(hwnd); + CMyComboBoxEdit *w = (CMyComboBoxEdit *)(tempDialog.GetUserDataLongPtr()); + if (w == NULL) + return 0; + return w->OnMessage(message, wParam, lParam); +} + +LRESULT CMyComboBoxEdit::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + // See MSDN / Subclassing a Combo Box / Creating a Combo-box Toolbar + switch (message) + { + case WM_SYSKEYDOWN: + switch (wParam) + { + case VK_F1: + case VK_F2: + { + // check ALT + if ((lParam & (1<<29)) == 0) + break; + bool alt = (::GetKeyState(VK_MENU) & 0x8000) != 0; + bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0; + bool shift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0; + if (alt && !ctrl && !shift) + { + _panel->_panelCallback->SetFocusToPath(wParam == VK_F1 ? 0 : 1); + return 0; + } + break; + } + } + break; + case WM_KEYDOWN: + switch (wParam) + { + case VK_TAB: + // SendMessage(hwndMain, WM_ENTER, 0, 0); + _panel->SetFocusToList(); + return 0; + case VK_F9: + { + bool alt = (::GetKeyState(VK_MENU) & 0x8000) != 0; + bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0; + bool shift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0; + if (!alt && !ctrl && !shift) + { + g_App.SwitchOnOffOnePanel();; + return 0; + } + break; + } + } + break; + case WM_CHAR: + switch (wParam) + { + case VK_TAB: + case VK_ESCAPE: + return 0; + } + } + #ifndef _UNICODE + if (g_IsNT) + return CallWindowProcW(_origWindowProc, *this, message, wParam, lParam); + else + #endif + return CallWindowProc(_origWindowProc, *this, message, wParam, lParam); +} + +bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */) +{ + // _virtualMode = false; + // _sortIndex = 0; + _sortID = kpidName; + _ascending = true; + _lastFocusedIsList = true; + + DWORD style = WS_CHILD | WS_VISIBLE; // | WS_BORDER ; // | LVS_SHAREIMAGELISTS; // | LVS_SHOWSELALWAYS;; + + style |= LVS_SHAREIMAGELISTS; + // style |= LVS_AUTOARRANGE; + style |= WS_CLIPCHILDREN; + style |= WS_CLIPSIBLINGS; + + const UInt32 kNumListModes = sizeof(kStyles) / sizeof(kStyles[0]); + if (_ListViewMode >= kNumListModes) + _ListViewMode = kNumListModes - 1; + + style |= kStyles[_ListViewMode] + | WS_TABSTOP + | LVS_EDITLABELS; + if (_mySelectMode) + style |= LVS_SINGLESEL; + + /* + if (_virtualMode) + style |= LVS_OWNERDATA; + */ + + DWORD exStyle; + exStyle = WS_EX_CLIENTEDGE; + + if (!_listView.CreateEx(exStyle, style, 0, 0, 116, 260, + HWND(*this), (HMENU)(UINT_PTR)(_baseID + 1), g_hInstance, NULL)) + return false; + + #ifndef UNDER_CE + _listView.SetUnicodeFormat(true); + #endif + + _listView.SetUserDataLongPtr(LONG_PTR(&_listView)); + _listView._panel = this; + + #ifndef _UNICODE + if(g_IsNT) + _listView._origWindowProc = + (WNDPROC)_listView.SetLongPtrW(GWLP_WNDPROC, LONG_PTR(ListViewSubclassProc)); + else + #endif + _listView._origWindowProc = + (WNDPROC)_listView.SetLongPtr(GWLP_WNDPROC, LONG_PTR(ListViewSubclassProc)); + + _listView.SetImageList(GetSysImageList(true), LVSIL_SMALL); + _listView.SetImageList(GetSysImageList(false), LVSIL_NORMAL); + + // _exStyle |= LVS_EX_HEADERDRAGDROP; + // DWORD extendedStyle = _listView.GetExtendedListViewStyle(); + // extendedStyle |= _exStyle; + // _listView.SetExtendedListViewStyle(extendedStyle); + SetExtendedStyle(); + + _listView.Show(SW_SHOW); + _listView.InvalidateRect(NULL, true); + _listView.Update(); + + // Ensure that the common control DLL is loaded. + INITCOMMONCONTROLSEX icex; + + icex.dwSize = sizeof(INITCOMMONCONTROLSEX); + icex.dwICC = ICC_BAR_CLASSES; + InitCommonControlsEx(&icex); + + TBBUTTON tbb [ ] = + { + // {0, 0, TBSTATE_ENABLED, BTNS_SEP, 0L, 0}, + {VIEW_PARENTFOLDER, kParentFolderID, TBSTATE_ENABLED, BTNS_BUTTON, 0L, 0}, + // {0, 0, TBSTATE_ENABLED, BTNS_SEP, 0L, 0}, + // {VIEW_NEWFOLDER, kCreateFolderID, TBSTATE_ENABLED, BTNS_BUTTON, 0L, 0}, + }; + + #ifndef UNDER_CE + if (g_ComCtl32Version >= MAKELONG(71, 4)) + #endif + { + icex.dwSize = sizeof(INITCOMMONCONTROLSEX); + icex.dwICC = ICC_COOL_CLASSES | ICC_BAR_CLASSES; + InitCommonControlsEx(&icex); + + _headerReBar.Attach(::CreateWindowEx(WS_EX_TOOLWINDOW, + REBARCLASSNAME, + NULL, WS_VISIBLE | WS_BORDER | WS_CHILD | + WS_CLIPCHILDREN | WS_CLIPSIBLINGS + | CCS_NODIVIDER + // | CCS_NOPARENTALIGN + | CCS_TOP + | RBS_VARHEIGHT + | RBS_BANDBORDERS + ,0,0,0,0, HWND(*this), NULL, g_hInstance, NULL)); + } + + DWORD toolbarStyle = WS_CHILD | WS_VISIBLE ; + if (_headerReBar) + { + toolbarStyle |= 0 + // | WS_CLIPCHILDREN + // | WS_CLIPSIBLINGS + + | TBSTYLE_TOOLTIPS + | CCS_NODIVIDER + | CCS_NORESIZE + | TBSTYLE_FLAT + ; + } + + _headerToolBar.Attach(::CreateToolbarEx ((*this), toolbarStyle, + _baseID + 2, 11, + (HINSTANCE)HINST_COMMCTRL, + IDB_VIEW_SMALL_COLOR, + (LPCTBBUTTON)&tbb, sizeof(tbb) / sizeof(tbb[0]), + 0, 0, 0, 0, sizeof (TBBUTTON))); + + #ifndef UNDER_CE + // Load ComboBoxEx class + icex.dwSize = sizeof(INITCOMMONCONTROLSEX); + icex.dwICC = ICC_USEREX_CLASSES; + InitCommonControlsEx(&icex); + #endif + + _headerComboBox.CreateEx(0, + #ifdef UNDER_CE + WC_COMBOBOXW + #else + WC_COMBOBOXEXW + #endif + , NULL, + WS_BORDER | WS_VISIBLE |WS_CHILD | CBS_DROPDOWN | CBS_AUTOHSCROLL, + 0, 0, 100, 520, + ((_headerReBar == 0) ? HWND(*this) : _headerToolBar), + (HMENU)(UINT_PTR)(_comboBoxID), + g_hInstance, NULL); + #ifndef UNDER_CE + _headerComboBox.SetUnicodeFormat(true); + + _headerComboBox.SetImageList(GetSysImageList(true)); + + _headerComboBox.SetExtendedStyle(CBES_EX_PATHWORDBREAKPROC, CBES_EX_PATHWORDBREAKPROC); + + /* + _headerComboBox.SetUserDataLongPtr(LONG_PTR(&_headerComboBox)); + _headerComboBox._panel = this; + _headerComboBox._origWindowProc = + (WNDPROC)_headerComboBox.SetLongPtr(GWLP_WNDPROC, + LONG_PTR(ComboBoxSubclassProc)); + */ + _comboBoxEdit.Attach(_headerComboBox.GetEditControl()); + + // _comboBoxEdit.SendMessage(CCM_SETUNICODEFORMAT, (WPARAM)(BOOL)TRUE, 0); + + _comboBoxEdit.SetUserDataLongPtr(LONG_PTR(&_comboBoxEdit)); + _comboBoxEdit._panel = this; + #ifndef _UNICODE + if(g_IsNT) + _comboBoxEdit._origWindowProc = + (WNDPROC)_comboBoxEdit.SetLongPtrW(GWLP_WNDPROC, LONG_PTR(ComboBoxEditSubclassProc)); + else + #endif + _comboBoxEdit._origWindowProc = + (WNDPROC)_comboBoxEdit.SetLongPtr(GWLP_WNDPROC, LONG_PTR(ComboBoxEditSubclassProc)); + + #endif + + if (_headerReBar) + { + REBARINFO rbi; + rbi.cbSize = sizeof(REBARINFO); // Required when using this struct. + rbi.fMask = 0; + rbi.himl = (HIMAGELIST)NULL; + _headerReBar.SetBarInfo(&rbi); + + // Send the TB_BUTTONSTRUCTSIZE message, which is required for + // backward compatibility. + // _headerToolBar.SendMessage(TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0); + SIZE size; + _headerToolBar.GetMaxSize(&size); + + REBARBANDINFO rbBand; + rbBand.cbSize = sizeof(REBARBANDINFO); // Required + rbBand.fMask = RBBIM_STYLE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE; + rbBand.fStyle = RBBS_NOGRIPPER; + rbBand.cxMinChild = size.cx; + rbBand.cyMinChild = size.cy; + rbBand.cyChild = size.cy; + rbBand.cx = size.cx; + rbBand.hwndChild = _headerToolBar; + _headerReBar.InsertBand(-1, &rbBand); + + RECT rc; + ::GetWindowRect(_headerComboBox, &rc); + rbBand.cxMinChild = 30; + rbBand.cyMinChild = rc.bottom - rc.top; + rbBand.cx = 1000; + rbBand.hwndChild = _headerComboBox; + _headerReBar.InsertBand(-1, &rbBand); + // _headerReBar.MaximizeBand(1, false); + } + + _statusBar.Create(WS_CHILD | WS_VISIBLE, L"Status", (*this), _statusBarID); + // _statusBar2.Create(WS_CHILD | WS_VISIBLE, L"Status", (*this), _statusBarID + 1); + + int sizes[] = {150, 250, 350, -1}; + _statusBar.SetParts(4, sizes); + // _statusBar2.SetParts(5, sizes); + + /* + RECT rect; + GetClientRect(&rect); + OnSize(0, rect.right - rect.left, rect.top - rect.bottom); + */ + + SetTimer(kTimerID, kTimerElapse); + + // InitListCtrl(); + RefreshListCtrl(); + RefreshStatusBar(); + + return true; +} + +void CPanel::OnDestroy() +{ + SaveListViewInfo(); + CWindow2::OnDestroy(); +} + +void CPanel::ChangeWindowSize(int xSize, int ySize) +{ + if ((HWND)*this == 0) + return; + int kHeaderSize; + int kStatusBarSize; + // int kStatusBar2Size; + RECT rect; + if (_headerReBar) + _headerReBar.GetWindowRect(&rect); + else + _headerToolBar.GetWindowRect(&rect); + + kHeaderSize = rect.bottom - rect.top; + + _statusBar.GetWindowRect(&rect); + kStatusBarSize = rect.bottom - rect.top; + + // _statusBar2.GetWindowRect(&rect); + // kStatusBar2Size = rect.bottom - rect.top; + + int yListViewSize = MyMax(ySize - kHeaderSize - kStatusBarSize, 0); + const int kStartXPos = 32; + if (_headerReBar) + { + } + else + { + _headerToolBar.Move(0, 0, xSize, 0); + _headerComboBox.Move(kStartXPos, 2, + MyMax(xSize - kStartXPos - 10, kStartXPos), 0); + } + _listView.Move(0, kHeaderSize, xSize, yListViewSize); + _statusBar.Move(0, kHeaderSize + yListViewSize, xSize, kStatusBarSize); + // _statusBar2.MoveWindow(0, kHeaderSize + yListViewSize + kStatusBarSize, xSize, kStatusBar2Size); + // _statusBar.MoveWindow(0, 100, xSize, kStatusBarSize); + // _statusBar2.MoveWindow(0, 200, xSize, kStatusBar2Size); +} + +bool CPanel::OnSize(WPARAM /* wParam */, int xSize, int ySize) +{ + if ((HWND)*this == 0) + return true; + if (_headerReBar) + _headerReBar.Move(0, 0, xSize, 0); + ChangeWindowSize(xSize, ySize); + return true; +} + +bool CPanel::OnNotifyReBar(LPNMHDR header, LRESULT & /* result */) +{ + switch(header->code) + { + case RBN_HEIGHTCHANGE: + { + RECT rect; + GetWindowRect(&rect); + ChangeWindowSize(rect.right - rect.left, rect.bottom - rect.top); + return false; + } + } + return false; +} + +bool CPanel::OnNotify(UINT /* controlID */, LPNMHDR header, LRESULT &result) +{ + if (!_processNotify) + return false; + if (header->hwndFrom == _headerComboBox) + return OnNotifyComboBox(header, result); + else if (header->hwndFrom == _headerReBar) + return OnNotifyReBar(header, result); + // if (header->hwndFrom == _listView) + else if (header->hwndFrom == _listView) + return OnNotifyList(header, result); + else if (::GetParent(header->hwndFrom) == _listView && + header->code == NM_RCLICK) + return OnRightClick((MY_NMLISTVIEW_NMITEMACTIVATE *)header, result); + return false; +} + +bool CPanel::OnCommand(int code, int itemID, LPARAM lParam, LRESULT &result) +{ + if (itemID == kParentFolderID) + { + OpenParentFolder(); + result = 0; + return true; + } + /* + if (itemID == kCreateFolderID) + { + CreateFolder(); + result = 0; + return true; + } + */ + if (itemID == _comboBoxID) + { + if (OnComboBoxCommand(code, lParam, result)) + return true; + } + return CWindow2::OnCommand(code, itemID, lParam, result); +} + +void CPanel::MessageBoxInfo(LPCWSTR message, LPCWSTR caption) + { ::MessageBoxW(HWND(*this), message, caption, MB_OK); } +void CPanel::MessageBox(LPCWSTR message, LPCWSTR caption) + { ::MessageBoxW(HWND(*this), message, caption, MB_OK | MB_ICONSTOP); } +void CPanel::MessageBox(LPCWSTR message) + { MessageBox(message, L"7-Zip"); } +void CPanel::MessageBoxMyError(LPCWSTR message) + { MessageBox(message, L"Error"); } + + +void CPanel::MessageBoxError(HRESULT errorCode, LPCWSTR caption) +{ + MessageBox(HResultToMessage(errorCode), caption); +} + +void CPanel::MessageBoxError(HRESULT errorCode) + { MessageBoxError(errorCode, L"7-Zip"); } +void CPanel::MessageBoxLastError(LPCWSTR caption) + { MessageBoxError(::GetLastError(), caption); } +void CPanel::MessageBoxLastError() + { MessageBoxLastError(L"Error"); } + +void CPanel::MessageBoxErrorLang(UINT resourceID, UInt32 langID) + { MessageBox(LangString(resourceID, langID)); } + + +void CPanel::SetFocusToList() +{ + _listView.SetFocus(); + // SetCurrentPathText(); +} + +void CPanel::SetFocusToLastRememberedItem() +{ + if (_lastFocusedIsList) + SetFocusToList(); + else + _headerComboBox.SetFocus(); +} + +UString CPanel::GetFolderTypeID() const +{ + NCOM::CPropVariant prop; + if (_folder->GetFolderProperty(kpidType, &prop) == S_OK) + if (prop.vt == VT_BSTR) + return (const wchar_t *)prop.bstrVal; + return L""; +} + +bool CPanel::IsFolderTypeEqTo(const wchar_t *s) const +{ + return GetFolderTypeID() == s; +} + +bool CPanel::IsRootFolder() const { return IsFolderTypeEqTo(L"RootFolder"); } +bool CPanel::IsFSFolder() const { return IsFolderTypeEqTo(L"FSFolder"); } +bool CPanel::IsFSDrivesFolder() const { return IsFolderTypeEqTo(L"FSDrives"); } +bool CPanel::IsArcFolder() const +{ + UString s = GetFolderTypeID(); + return s.Left(5) == L"7-Zip"; +} + +UString CPanel::GetFsPath() const +{ + if (IsFSDrivesFolder() && !IsDeviceDrivesPrefix()) + return UString(); + return _currentFolderPrefix; +} + +UString CPanel::GetDriveOrNetworkPrefix() const +{ + if (!IsFSFolder()) + return UString(); + UString drive = GetFsPath(); + if (drive.Length() < 3) + return UString(); + if (drive[0] == L'\\' && drive[1] == L'\\') + { + // if network + int pos = drive.Find(L'\\', 2); + if (pos < 0) + return UString(); + pos = drive.Find(L'\\', pos + 1); + if (pos < 0) + return UString(); + return drive.Left(pos + 1); + } + if (drive[1] != L':' || drive[2] != L'\\') + return UString(); + return drive.Left(3); +} + +bool CPanel::DoesItSupportOperations() const +{ + CMyComPtr folderOperations; + return _folder.QueryInterface(IID_IFolderOperations, &folderOperations) == S_OK; +} + +void CPanel::SetListViewMode(UInt32 index) +{ + if (index >= 4) + return; + _ListViewMode = index; + DWORD oldStyle = (DWORD)_listView.GetStyle(); + DWORD newStyle = kStyles[index]; + if ((oldStyle & LVS_TYPEMASK) != newStyle) + _listView.SetStyle((oldStyle & ~LVS_TYPEMASK) | newStyle); + // RefreshListCtrlSaveFocused(); +} + +void CPanel::ChangeFlatMode() +{ + _flatMode = !_flatMode; + if (_parentFolders.Size() > 0) + _flatModeForArc = _flatMode; + else + _flatModeForDisk = _flatMode; + RefreshListCtrlSaveFocused(); +} + + +void CPanel::RefreshStatusBar() +{ + PostMessage(kRefreshStatusBar); +} + +void CPanel::AddToArchive() +{ + CRecordVector indices; + GetOperatedItemIndices(indices); + if (!IsFsOrDrivesFolder()) + { + MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + return; + } + if (indices.Size() == 0) + { + MessageBoxErrorLang(IDS_SELECT_FILES, 0x03020A03); + return; + } + UStringVector names; + + UString curPrefix = _currentFolderPrefix; + UString destCurDirPrefix = _currentFolderPrefix; + if (IsFSDrivesFolder()) + { + destCurDirPrefix = ROOT_FS_FOLDER; + if (!IsDeviceDrivesPrefix()) + curPrefix.Empty(); + } + + for (int i = 0; i < indices.Size(); i++) + names.Add(curPrefix + GetItemRelPath(indices[i])); + const UString archiveName = CreateArchiveName(names.Front(), (names.Size() > 1), false); + HRESULT res = CompressFiles(destCurDirPrefix, archiveName, L"", names, false, true, false); + if (res != S_OK) + { + if (destCurDirPrefix.Length() >= MAX_PATH) + MessageBoxErrorLang(IDS_MESSAGE_UNSUPPORTED_OPERATION_FOR_LONG_PATH_FOLDER, 0x03020A01); + } + // KillSelection(); +} + +static UString GetSubFolderNameForExtract(const UString &archiveName) +{ + int slashPos = archiveName.ReverseFind(WCHAR_PATH_SEPARATOR); + int dotPos = archiveName.ReverseFind(L'.'); + if (dotPos < 0 || slashPos > dotPos) + return archiveName + UString(L"~"); + UString res = archiveName.Left(dotPos); + res.TrimRight(); + return res; +} + +void CPanel::GetFilePaths(const CRecordVector &indices, UStringVector &paths) +{ + for (int i = 0; i < indices.Size(); i++) + { + int index = indices[i]; + if (IsItemFolder(index)) + { + paths.Clear(); + break; + } + paths.Add(GetItemFullPath(index)); + } + if (paths.Size() == 0) + { + MessageBoxErrorLang(IDS_SELECT_FILES, 0x03020A03); + return; + } +} + +void CPanel::ExtractArchives() +{ + if (_parentFolders.Size() > 0) + { + _panelCallback->OnCopy(false, false); + return; + } + CRecordVector indices; + GetOperatedItemIndices(indices); + UStringVector paths; + GetFilePaths(indices, paths); + if (paths.IsEmpty()) + return; + UString folderName; + if (indices.Size() == 1) + folderName = GetSubFolderNameForExtract(GetItemRelPath(indices[0])); + else + folderName = L"*"; + ::ExtractArchives(paths, _currentFolderPrefix + folderName + UString(WCHAR_PATH_SEPARATOR), true); +} + +static void AddValuePair(UINT resourceID, UInt32 langID, UInt64 value, UString &s) +{ + wchar_t sz[32]; + s += LangString(resourceID, langID); + s += L' '; + ConvertUInt64ToString(value, sz); + s += sz; + s += L'\n'; +} + +class CThreadTest: public CProgressThreadVirt +{ + HRESULT ProcessVirt(); +public: + CRecordVector Indices; + CExtractCallbackImp *ExtractCallbackSpec; + CMyComPtr ExtractCallback; + CMyComPtr ArchiveFolder; +}; + +HRESULT CThreadTest::ProcessVirt() +{ + RINOK(ArchiveFolder->Extract(&Indices[0], Indices.Size(), + NExtract::NPathMode::kFullPathnames, NExtract::NOverwriteMode::kAskBefore, + NULL, BoolToInt(true), ExtractCallback)); + if (ExtractCallbackSpec->IsOK()) + { + UString s; + AddValuePair(IDS_FOLDERS_COLON, 0x02000321, ExtractCallbackSpec->NumFolders, s); + AddValuePair(IDS_FILES_COLON, 0x02000320, ExtractCallbackSpec->NumFiles, s); + // AddSizePair(IDS_SIZE_COLON, 0x02000322, Stat.UnpackSize, s); + // AddSizePair(IDS_COMPRESSED_COLON, 0x02000323, Stat.PackSize, s); + s += L'\n'; + s += LangString(IDS_MESSAGE_NO_ERRORS, 0x02000608); + OkMessage = s; + } + return S_OK; +} + +/* +static void AddSizePair(UINT resourceID, UInt32 langID, UInt64 value, UString &s) +{ + wchar_t sz[32]; + s += LangString(resourceID, langID); + s += L" "; + ConvertUInt64ToString(value, sz); + s += sz; + ConvertUInt64ToString(value >> 20, sz); + s += L" ("; + s += sz; + s += L" MB)"; + s += L'\n'; +} +*/ + +void CPanel::TestArchives() +{ + CRecordVector indices; + GetOperatedIndicesSmart(indices); + CMyComPtr archiveFolder; + _folder.QueryInterface(IID_IArchiveFolder, &archiveFolder); + if (archiveFolder) + { + { + CThreadTest extracter; + + extracter.ArchiveFolder = archiveFolder; + extracter.ExtractCallbackSpec = new CExtractCallbackImp; + extracter.ExtractCallback = extracter.ExtractCallbackSpec; + extracter.ExtractCallbackSpec->ProgressDialog = &extracter.ProgressDialog; + + if (indices.IsEmpty()) + return; + + extracter.Indices = indices; + + UString title = LangString(IDS_PROGRESS_TESTING, 0x02000F90); + UString progressWindowTitle = LangString(IDS_APP_TITLE, 0x03000000); + + extracter.ProgressDialog.CompressingMode = false; + extracter.ProgressDialog.MainWindow = GetParent(); + extracter.ProgressDialog.MainTitle = progressWindowTitle; + extracter.ProgressDialog.MainAddTitle = title + L" "; + + extracter.ExtractCallbackSpec->OverwriteMode = NExtract::NOverwriteMode::kAskBefore; + extracter.ExtractCallbackSpec->Init(); + + if (extracter.Create(title, GetParent()) != S_OK) + return; + + } + RefreshTitleAlways(); + return; + } + + if (!IsFSFolder()) + { + MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + return; + } + UStringVector paths; + GetFilePaths(indices, paths); + if (paths.IsEmpty()) + return; + ::TestArchives(paths); +} diff --git a/CPP/7zip/UI/FileManager/Panel.h b/CPP/7zip/UI/FileManager/Panel.h new file mode 100755 index 0000000..2f1bcde --- /dev/null +++ b/CPP/7zip/UI/FileManager/Panel.h @@ -0,0 +1,629 @@ +// Panel.h + +#ifndef __PANEL_H +#define __PANEL_H + +#include "../../../../C/Alloc.h" + +#include "Common/MyCom.h" + +#include "Windows/DLL.h" +#include "Windows/FileDir.h" +#include "Windows/FileFind.h" +#include "Windows/Handle.h" +#include "Windows/Synchronization.h" + +#include "Windows/Control/ComboBox.h" +#include "Windows/Control/Edit.h" +#include "Windows/Control/ListView.h" +#include "Windows/Control/ReBar.h" +#include "Windows/Control/Static.h" +#include "Windows/Control/StatusBar.h" +#include "Windows/Control/ToolBar.h" +#include "Windows/Control/Window2.h" + +#include "AppState.h" +#include "IFolder.h" +#include "MyCom2.h" +#include "ProgressDialog2.h" +#include "SysIconUtils.h" + +const int kParentFolderID = 100; +const int kPluginMenuStartID = 1000; +const int kToolbarStartID = 2000; + +const int kParentIndex = -1; + +#ifdef UNDER_CE +#define ROOT_FS_FOLDER L"\\" +#else +#define ROOT_FS_FOLDER L"C:\\\\" +#endif + +struct CPanelCallback +{ + virtual void OnTab() = 0; + virtual void SetFocusToPath(int index) = 0; + virtual void OnCopy(bool move, bool copyToSame) = 0; + virtual void OnSetSameFolder() = 0; + virtual void OnSetSubFolder() = 0; + virtual void PanelWasFocused() = 0; + virtual void DragBegin() = 0; + virtual void DragEnd() = 0; + virtual void RefreshTitle(bool always) = 0; +}; + +void PanelCopyItems(); + +struct CItemProperty +{ + UString Name; + PROPID ID; + VARTYPE Type; + int Order; + bool IsVisible; + UInt32 Width; +}; + +inline bool operator<(const CItemProperty &a1, const CItemProperty &a2) + { return (a1.Order < a2.Order); } + +inline bool operator==(const CItemProperty &a1, const CItemProperty &a2) + { return (a1.Order == a2.Order); } + +class CItemProperties: public CObjectVector +{ +public: + int FindItemWithID(PROPID id) + { + for (int i = 0; i < Size(); i++) + if ((*this)[i].ID == id) + return i; + return -1; + } +}; + +struct CTempFileInfo +{ + UString ItemName; + UString FolderPath; + UString FilePath; + NWindows::NFile::NFind::CFileInfoW FileInfo; + bool NeedDelete; + + CTempFileInfo(): NeedDelete(false) {} + void DeleteDirAndFile() const + { + if (NeedDelete) + { + NWindows::NFile::NDirectory::DeleteFileAlways(FilePath); + NWindows::NFile::NDirectory::MyRemoveDirectory(FolderPath); + } + } + bool WasChanged(const NWindows::NFile::NFind::CFileInfoW &newFileInfo) const + { + return newFileInfo.Size != FileInfo.Size || + CompareFileTime(&newFileInfo.MTime, &FileInfo.MTime) != 0; + } +}; + +struct CFolderLink: public CTempFileInfo +{ + NWindows::NDLL::CLibrary Library; + CMyComPtr ParentFolder; + bool UsePassword; + UString Password; + bool IsVirtual; + + UString VirtualPath; + CFolderLink(): UsePassword(false), IsVirtual(false) {} + + bool WasChanged(const NWindows::NFile::NFind::CFileInfoW &newFileInfo) const + { + return IsVirtual || CTempFileInfo::WasChanged(newFileInfo); + } + +}; + +enum MyMessages +{ + kShiftSelectMessage = WM_USER + 1, + kReLoadMessage, + kSetFocusToListView, + kOpenItemChanged, + kRefreshStatusBar, + kRefreshHeaderComboBox +}; + +UString GetFolderPath(IFolderFolder * folder); + +class CPanel; + +class CMyListView: public NWindows::NControl::CListView +{ +public: + WNDPROC _origWindowProc; + CPanel *_panel; + LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam); +}; + +/* +class CMyComboBox: public NWindows::NControl::CComboBoxEx +{ +public: + WNDPROC _origWindowProc; + CPanel *_panel; + LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam); +}; +*/ +class CMyComboBoxEdit: public NWindows::NControl::CEdit +{ +public: + WNDPROC _origWindowProc; + CPanel *_panel; + LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam); +}; + +struct CSelectedState +{ + int FocusedItem; + UString FocusedName; + bool SelectFocused; + UStringVector SelectedNames; + CSelectedState(): FocusedItem(-1), SelectFocused(false) {} +}; + +#ifdef UNDER_CE +#define MY_NMLISTVIEW_NMITEMACTIVATE NMLISTVIEW +#else +#define MY_NMLISTVIEW_NMITEMACTIVATE NMITEMACTIVATE +#endif + +class CPanel: public NWindows::NControl::CWindow2 +{ + CExtToIconMap _extToIconMap; + UINT _baseID; + int _comboBoxID; + UINT _statusBarID; + + CAppState *_appState; + + bool OnCommand(int code, int itemID, LPARAM lParam, LRESULT &result); + LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam); + virtual bool OnCreate(CREATESTRUCT *createStruct); + virtual bool OnSize(WPARAM wParam, int xSize, int ySize); + virtual void OnDestroy(); + virtual bool OnNotify(UINT controlID, LPNMHDR lParam, LRESULT &result); + + void AddComboBoxItem(const UString &name, int iconIndex, int indent, bool addToList); + + bool OnComboBoxCommand(UINT code, LPARAM param, LRESULT &result); + + #ifndef UNDER_CE + + LRESULT OnNotifyComboBoxEnter(const UString &s); + bool OnNotifyComboBoxEndEdit(PNMCBEENDEDITW info, LRESULT &result); + #ifndef _UNICODE + bool OnNotifyComboBoxEndEdit(PNMCBEENDEDIT info, LRESULT &result); + #endif + + #endif + + bool OnNotifyReBar(LPNMHDR lParam, LRESULT &result); + bool OnNotifyComboBox(LPNMHDR lParam, LRESULT &result); + void OnItemChanged(NMLISTVIEW *item); + void OnNotifyActivateItems(); + bool OnNotifyList(LPNMHDR lParam, LRESULT &result); + void OnDrag(LPNMLISTVIEW nmListView); + bool OnKeyDown(LPNMLVKEYDOWN keyDownInfo, LRESULT &result); + BOOL OnBeginLabelEdit(LV_DISPINFOW * lpnmh); + BOOL OnEndLabelEdit(LV_DISPINFOW * lpnmh); + void OnColumnClick(LPNMLISTVIEW info); + bool OnCustomDraw(LPNMLVCUSTOMDRAW lplvcd, LRESULT &result); + +public: + HWND _mainWindow; + CPanelCallback *_panelCallback; + + void SysIconsWereChanged() { _extToIconMap.Clear(); } + + void DeleteItems(bool toRecycleBin); + void DeleteItemsInternal(CRecordVector &indices); + void CreateFolder(); + void CreateFile(); + +private: + + void ChangeWindowSize(int xSize, int ySize); + + HRESULT InitColumns(); + // void InitColumns2(PROPID sortID); + void InsertColumn(int index); + + void SetFocusedSelectedItem(int index, bool select); + HRESULT RefreshListCtrl(const UString &focusedName, int focusedPos, bool selectFocused, + const UStringVector &selectedNames); + + void OnShiftSelectMessage(); + void OnArrowWithShift(); + + void OnInsert(); + // void OnUpWithShift(); + // void OnDownWithShift(); +public: + void UpdateSelection(); + void SelectSpec(bool selectMode); + void SelectByType(bool selectMode); + void SelectAll(bool selectMode); + void InvertSelection(); +private: + + // UString GetFileType(UInt32 index); + LRESULT SetItemText(LVITEMW &item); + + // CRecordVector m_ColumnsPropIDs; + +public: + NWindows::NControl::CReBar _headerReBar; + NWindows::NControl::CToolBar _headerToolBar; + NWindows::NControl:: + #ifdef UNDER_CE + CComboBox + #else + CComboBoxEx + #endif + _headerComboBox; + UStringVector ComboBoxPaths; + // CMyComboBox _headerComboBox; + CMyComboBoxEdit _comboBoxEdit; + CMyListView _listView; + NWindows::NControl::CStatusBar _statusBar; + bool _lastFocusedIsList; + // NWindows::NControl::CStatusBar _statusBar2; + + DWORD _exStyle; + bool _showDots; + bool _showRealFileIcons; + // bool _virtualMode; + // CUIntVector _realIndices; + bool _enableItemChangeNotify; + bool _mySelectMode; + CBoolVector _selectedStatusVector; + + CSelectedState _selectedState; + + HWND GetParent(); + + UInt32 GetRealIndex(const LVITEMW &item) const + { + /* + if (_virtualMode) + return _realIndices[item.iItem]; + */ + return (UInt32)item.lParam; + } + int GetRealItemIndex(int indexInListView) const + { + /* + if (_virtualMode) + return indexInListView; + */ + LPARAM param; + if (!_listView.GetItemParam(indexInListView, param)) + throw 1; + return (int)param; + } + + UInt32 _ListViewMode; + int _xSize; + + bool _flatMode; + bool _flatModeForDisk; + bool _flatModeForArc; + + bool _dontShowMode; + + + UString _currentFolderPrefix; + + CObjectVector _parentFolders; + NWindows::NDLL::CLibrary _library; + CMyComPtr _folder; + // CMyComPtr _folderGetSystemIconIndex; + + UStringVector _fastFolders; + + void GetSelectedNames(UStringVector &selectedNames); + void SaveSelectedState(CSelectedState &s); + HRESULT RefreshListCtrl(const CSelectedState &s); + HRESULT RefreshListCtrlSaveFocused(); + + UString GetItemName(int itemIndex) const; + UString GetItemPrefix(int itemIndex) const; + UString GetItemRelPath(int itemIndex) const; + UString GetItemFullPath(int itemIndex) const; + bool IsItemFolder(int itemIndex) const; + UInt64 GetItemSize(int itemIndex) const; + + //////////////////////// + // PanelFolderChange.cpp + + void SetToRootFolder(); + HRESULT BindToPath(const UString &fullPath, const UString &arcFormat, bool &archiveIsOpened, bool &encrypted); // can be prefix + HRESULT BindToPathAndRefresh(const UString &path); + void OpenDrivesFolder(); + + void SetBookmark(int index); + void OpenBookmark(int index); + + void LoadFullPath(); + void LoadFullPathAndShow(); + void FoldersHistory(); + void OpenParentFolder(); + void CloseOpenFolders(); + void OpenRootFolder(); + + + HRESULT Create(HWND mainWindow, HWND parentWindow, + UINT id, + const UString ¤tFolderPrefix, + const UString &arcFormat, + CPanelCallback *panelCallback, + CAppState *appState, bool &archiveIsOpened, bool &encrypted); + void SetFocusToList(); + void SetFocusToLastRememberedItem(); + + + void ReadListViewInfo(); + void SaveListViewInfo(); + + CPanel() : + // _virtualMode(flase), + _exStyle(0), + _showDots(false), + _showRealFileIcons(false), + _needSaveInfo(false), + _startGroupSelect(0), + _selectionIsDefined(false), + _ListViewMode(3), + _flatMode(false), + _flatModeForDisk(false), + _flatModeForArc(false), + _xSize(300), + _mySelectMode(false), + _enableItemChangeNotify(true), + _dontShowMode(false) + {} + + void SetExtendedStyle() + { + if (_listView != 0) + _listView.SetExtendedListViewStyle(_exStyle); + } + + + bool _needSaveInfo; + UString _typeIDString; + CListViewInfo _listViewInfo; + CItemProperties _properties; + CItemProperties _visibleProperties; + + PROPID _sortID; + // int _sortIndex; + bool _ascending; + + void Release(); + ~CPanel(); + void OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate); + bool OnRightClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate, LRESULT &result); + void ShowColumnsContextMenu(int x, int y); + + void OnTimer(); + void OnReload(); + bool OnContextMenu(HANDLE windowHandle, int xPos, int yPos); + + CMyComPtr _sevenZipContextMenu; + CMyComPtr _systemContextMenu; + HRESULT CreateShellContextMenu( + const CRecordVector &operatedIndices, + CMyComPtr &systemContextMenu); + void CreateSystemMenu(HMENU menu, + const CRecordVector &operatedIndices, + CMyComPtr &systemContextMenu); + void CreateSevenZipMenu(HMENU menu, + const CRecordVector &operatedIndices, + CMyComPtr &sevenZipContextMenu); + void CreateFileMenu(HMENU menu, + CMyComPtr &sevenZipContextMenu, + CMyComPtr &systemContextMenu, + bool programMenu); + void CreateFileMenu(HMENU menu); + bool InvokePluginCommand(int id); + bool InvokePluginCommand(int id, IContextMenu *sevenZipContextMenu, + IContextMenu *systemContextMenu); + + void InvokeSystemCommand(const char *command); + void Properties(); + void EditCut(); + void EditCopy(); + void EditPaste(); + + int _startGroupSelect; + + bool _selectionIsDefined; + bool _selectMark; + int _prevFocusedItem; + + + // void SortItems(int index); + void SortItemsWithPropID(PROPID propID); + + void GetSelectedItemsIndices(CRecordVector &indices) const; + void GetOperatedItemIndices(CRecordVector &indices) const; + void GetAllItemIndices(CRecordVector &indices) const; + void GetOperatedIndicesSmart(CRecordVector &indices) const; + // void GetOperatedListViewIndices(CRecordVector &indices) const; + void KillSelection(); + + UString GetFolderTypeID() const; + bool IsFolderTypeEqTo(const wchar_t *s) const; + bool IsRootFolder() const; + bool IsFSFolder() const; + bool IsFSDrivesFolder() const; + bool IsArcFolder() const; + bool IsFsOrDrivesFolder() const { return IsFSFolder() || IsFSDrivesFolder(); } + bool IsDeviceDrivesPrefix() const { return _currentFolderPrefix == L"\\\\.\\"; } + bool IsFsOrPureDrivesFolder() const { return IsFSFolder() || (IsFSDrivesFolder() && !IsDeviceDrivesPrefix()); } + + UString GetFsPath() const; + UString GetDriveOrNetworkPrefix() const; + + bool DoesItSupportOperations() const; + + bool _processTimer; + bool _processNotify; + + class CDisableTimerProcessing + { + bool _processTimerMem; + bool _processNotifyMem; + + CPanel &_panel; + public: + + CDisableTimerProcessing(CPanel &panel): _panel(panel) + { + Disable(); + } + void Disable() + { + _processTimerMem = _panel._processTimer; + _processNotifyMem = _panel._processNotify; + _panel._processTimer = false; + _panel._processNotify = false; + } + void Restore() + { + _panel._processTimer = _processTimerMem; + _panel._processNotify = _processNotifyMem; + } + ~CDisableTimerProcessing() + { + Restore(); + } + CDisableTimerProcessing& operator=(const CDisableTimerProcessing &) {; } + }; + + // bool _passwordIsDefined; + // UString _password; + + HRESULT RefreshListCtrl(); + + void MessageBoxInfo(LPCWSTR message, LPCWSTR caption); + void MessageBox(LPCWSTR message); + void MessageBox(LPCWSTR message, LPCWSTR caption); + void MessageBoxMyError(LPCWSTR message); + void MessageBoxError(HRESULT errorCode, LPCWSTR caption); + void MessageBoxError(HRESULT errorCode); + void MessageBoxLastError(LPCWSTR caption); + void MessageBoxLastError(); + + void MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID, UInt32 langID); + + void MessageBoxErrorLang(UINT resourceID, UInt32 langID); + + void OpenFocusedItemAsInternal(); + void OpenSelectedItems(bool internal); + + void OpenFolderExternal(int index); + + void OpenFolder(int index); + HRESULT OpenParentArchiveFolder(); + HRESULT OpenItemAsArchive(IInStream *inStream, + const CTempFileInfo &tempFileInfo, + const UString &virtualFilePath, + const UString &arcFormat, + bool &encrypted); + HRESULT OpenItemAsArchive(const UString &name, const UString &arcFormat, bool &encrypted); + HRESULT OpenItemAsArchive(int index); + void OpenItemInArchive(int index, bool tryInternal, bool tryExternal, + bool editMode); + HRESULT OnOpenItemChanged(const UString &folderPath, const UString &itemName, bool usePassword, const UString &password); + LRESULT OnOpenItemChanged(LPARAM lParam); + + void OpenItem(int index, bool tryInternal, bool tryExternal); + void EditItem(); + void EditItem(int index); + + void RenameFile(); + void ChangeComment(); + + void SetListViewMode(UInt32 index); + UInt32 GetListViewMode() const { return _ListViewMode; } + PROPID GetSortID() const { return _sortID; } + + void ChangeFlatMode(); + bool GetFlatMode() const { return _flatMode; } + + void RefreshStatusBar(); + void OnRefreshStatusBar(); + + void AddToArchive(); + + void GetFilePaths(const CRecordVector &indices, UStringVector &paths); + void ExtractArchives(); + void TestArchives(); + + HRESULT CopyTo(const CRecordVector &indices, const UString &folder, + bool moveMode, bool showErrorMessages, UStringVector *messages, + bool &usePassword, UString &password); + + HRESULT CopyTo(const CRecordVector &indices, const UString &folder, + bool moveMode, bool showErrorMessages, UStringVector *messages) + { + bool usePassword = false; + UString password; + if (_parentFolders.Size() > 0) + { + const CFolderLink &fl = _parentFolders.Back(); + usePassword = fl.UsePassword; + password = fl.Password; + } + return CopyTo(indices, folder, moveMode, showErrorMessages, messages, usePassword, password); + } + + HRESULT CopyFrom(const UString &folderPrefix, const UStringVector &filePaths, + bool showErrorMessages, UStringVector *messages); + + void CopyFromNoAsk(const UStringVector &filePaths); + void CopyFromAsk(const UStringVector &filePaths); + + // empty folderPath means create new Archive to path of first fileName. + void DropObject(IDataObject * dataObject, const UString &folderPath); + + // empty folderPath means create new Archive to path of first fileName. + void CompressDropFiles(const UStringVector &fileNames, const UString &folderPath); + + void RefreshTitle(bool always = false) { _panelCallback->RefreshTitle(always); } + void RefreshTitleAlways() { RefreshTitle(true); } + + UString GetItemsInfoString(const CRecordVector &indices); +}; + +class CMyBuffer +{ + void *_data; +public: + CMyBuffer(): _data(0) {} + operator void *() { return _data; } + bool Allocate(size_t size) + { + if (_data != 0) + return false; + _data = ::MidAlloc(size); + return _data != 0; + } + ~CMyBuffer() { ::MidFree(_data); } +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/PanelCopy.cpp b/CPP/7zip/UI/FileManager/PanelCopy.cpp new file mode 100755 index 0000000..20e656e --- /dev/null +++ b/CPP/7zip/UI/FileManager/PanelCopy.cpp @@ -0,0 +1,227 @@ +// PanelExtract.cpp + +#include "StdAfx.h" + +#include "Panel.h" +#include "resource.h" +#include "LangUtils.h" +#include "ExtractCallback.h" +#include "Windows/Thread.h" +//////////////////////////////////////////////////////////////// + +#include "UpdateCallback100.h" + +using namespace NWindows; + +class CPanelCopyThread: public CProgressThreadVirt +{ + HRESULT ProcessVirt(); +public: + CMyComPtr FolderOperations; + CRecordVector Indices; + UString DestPath; + CExtractCallbackImp *ExtractCallbackSpec; + CMyComPtr ExtractCallback; + HRESULT Result; + bool MoveMode; + + CPanelCopyThread(): MoveMode(false), Result(E_FAIL) {} +}; + +HRESULT CPanelCopyThread::ProcessVirt() +{ + if (MoveMode) + Result = FolderOperations->MoveTo(&Indices.Front(), Indices.Size(), DestPath, ExtractCallback); + else + Result = FolderOperations->CopyTo(&Indices.Front(), Indices.Size(), DestPath, ExtractCallback); + return Result; +} + +HRESULT CPanel::CopyTo(const CRecordVector &indices, const UString &folder, + bool moveMode, bool showErrorMessages, UStringVector *messages, + bool &usePassword, UString &password) +{ + CMyComPtr folderOperations; + if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) + { + UString errorMessage = LangString(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + if (showErrorMessages) + MessageBox(errorMessage); + else if (messages != 0) + messages->Add(errorMessage); + return E_FAIL; + } + + HRESULT res; + { + CPanelCopyThread extracter; + + + extracter.ExtractCallbackSpec = new CExtractCallbackImp; + extracter.ExtractCallback = extracter.ExtractCallbackSpec; + extracter.ExtractCallbackSpec->ProgressDialog = &extracter.ProgressDialog; + extracter.ProgressDialog.CompressingMode = false; + + UString title = moveMode ? + LangString(IDS_MOVING, 0x03020206): + LangString(IDS_COPYING, 0x03020205); + UString progressWindowTitle = LangString(IDS_APP_TITLE, 0x03000000); + + extracter.ProgressDialog.MainWindow = GetParent(); + extracter.ProgressDialog.MainTitle = progressWindowTitle; + extracter.ProgressDialog.MainAddTitle = title + L" "; + + extracter.ExtractCallbackSpec->OverwriteMode = NExtract::NOverwriteMode::kAskBefore; + extracter.ExtractCallbackSpec->Init(); + extracter.Indices = indices; + extracter.DestPath = folder; + extracter.FolderOperations = folderOperations; + extracter.MoveMode = moveMode; + + extracter.ExtractCallbackSpec->PasswordIsDefined = usePassword; + extracter.ExtractCallbackSpec->Password = password; + + RINOK(extracter.Create(title, GetParent())); + + if (messages != 0) + *messages = extracter.ProgressDialog.Sync.Messages; + res = extracter.Result; + + if (res == S_OK && extracter.ExtractCallbackSpec->IsOK()) + { + usePassword = extracter.ExtractCallbackSpec->PasswordIsDefined; + password = extracter.ExtractCallbackSpec->Password; + } + } + RefreshTitleAlways(); + return res; +} + + +struct CThreadUpdate +{ + CMyComPtr FolderOperations; + UString FolderPrefix; + UStringVector FileNames; + CRecordVector FileNamePointers; + CProgressDialog ProgressDialog; + CMyComPtr UpdateCallback; + CUpdateCallback100Imp *UpdateCallbackSpec; + HRESULT Result; + + void Process() + { + try + { + CProgressCloser closer(ProgressDialog); + Result = FolderOperations->CopyFrom( + FolderPrefix, + &FileNamePointers.Front(), + FileNamePointers.Size(), + UpdateCallback); + } + catch(...) { Result = E_FAIL; } + } + static THREAD_FUNC_DECL MyThreadFunction(void *param) + { + ((CThreadUpdate *)param)->Process(); + return 0; + } +}; + +HRESULT CPanel::CopyFrom(const UString &folderPrefix, const UStringVector &filePaths, + bool showErrorMessages, UStringVector *messages) +{ + CMyComPtr folderOperations; + _folder.QueryInterface(IID_IFolderOperations, &folderOperations); + HRESULT res; + if (!folderOperations) + res = E_NOINTERFACE; + else + { + CThreadUpdate updater; + updater.UpdateCallbackSpec = new CUpdateCallback100Imp; + updater.UpdateCallback = updater.UpdateCallbackSpec; + + updater.UpdateCallbackSpec->ProgressDialog = &updater.ProgressDialog; + + UString title = LangString(IDS_COPYING, 0x03020205); + UString progressWindowTitle = LangString(IDS_APP_TITLE, 0x03000000); + + updater.ProgressDialog.MainWindow = GetParent(); + updater.ProgressDialog.MainTitle = progressWindowTitle; + updater.ProgressDialog.MainAddTitle = title + UString(L" "); + + updater.UpdateCallbackSpec->Init(false, L""); + updater.FolderOperations = folderOperations; + updater.FolderPrefix = folderPrefix; + updater.FileNames.Reserve(filePaths.Size()); + int i; + for(i = 0; i < filePaths.Size(); i++) + updater.FileNames.Add(filePaths[i]); + updater.FileNamePointers.Reserve(updater.FileNames.Size()); + for(i = 0; i < updater.FileNames.Size(); i++) + updater.FileNamePointers.Add(updater.FileNames[i]); + + NWindows::CThread thread; + RINOK(thread.Create(CThreadUpdate::MyThreadFunction, &updater)); + updater.ProgressDialog.Create(title, thread, GetParent()); + + if (messages != 0) + *messages = updater.ProgressDialog.Sync.Messages; + + res = updater.Result; + } + + if (res == E_NOINTERFACE) + { + UString errorMessage = LangString(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + if (showErrorMessages) + MessageBox(errorMessage); + else if (messages != 0) + messages->Add(errorMessage); + return E_ABORT; + } + + RefreshTitleAlways(); + return res; +} + +void CPanel::CopyFromNoAsk(const UStringVector &filePaths) +{ + CDisableTimerProcessing disableTimerProcessing(*this); + + CSelectedState srcSelState; + SaveSelectedState(srcSelState); + + HRESULT result = CopyFrom(L"", filePaths, true, 0); + + if (result != S_OK) + { + disableTimerProcessing.Restore(); + // For Password: + SetFocusToList(); + if (result != E_ABORT) + MessageBoxError(result); + return; + } + + RefreshListCtrl(srcSelState); + + disableTimerProcessing.Restore(); + SetFocusToList(); +} + +void CPanel::CopyFromAsk(const UStringVector &filePaths) +{ + UString title = LangString(IDS_CONFIRM_FILE_COPY, 0x03020222); + UString message = LangString(IDS_WANT_TO_COPY_FILES, 0x03020223); + message += L"\n\'"; + message += _currentFolderPrefix; + message += L"\' ?"; + int res = ::MessageBoxW(*(this), message, title, MB_YESNOCANCEL | MB_ICONQUESTION); + if (res != IDYES) + return; + + CopyFromNoAsk(filePaths); +} diff --git a/CPP/7zip/UI/FileManager/PanelCrc.cpp b/CPP/7zip/UI/FileManager/PanelCrc.cpp new file mode 100755 index 0000000..cb67088 --- /dev/null +++ b/CPP/7zip/UI/FileManager/PanelCrc.cpp @@ -0,0 +1,342 @@ +// PanelSplitFile.cpp + +#include "StdAfx.h" + +#include "../../../../C/7zCrc.h" +#include "../../../../C/Sha256.h" + +#include "Common/IntToString.h" + +#include "Windows/FileFind.h" +#include "Windows/FileIO.h" +#include "Windows/FileName.h" + +#include "OverwriteDialogRes.h" + +#include "App.h" +#include "FormatUtils.h" +#include "LangUtils.h" + +#include "../Common/PropIDUtils.h" + +#include "resource.h" + +using namespace NWindows; +using namespace NFile; + +static const UInt32 kBufSize = (1 << 15); + +struct CDirEnumerator +{ + bool FlatMode; + UString BasePrefix; + UStringVector FileNames; + + CObjectVector Enumerators; + UStringVector Prefixes; + int Index; + HRESULT GetNextFile(NFind::CFileInfoW &fileInfo, bool &filled, UString &fullPath); + void Init(); + + CDirEnumerator(): FlatMode(false) {}; +}; + +void CDirEnumerator::Init() +{ + Enumerators.Clear(); + Prefixes.Clear(); + Index = 0; +} + +static HRESULT GetNormalizedError() +{ + HRESULT errorCode = GetLastError(); + return (errorCode == 0) ? E_FAIL : errorCode; +} + +HRESULT CDirEnumerator::GetNextFile(NFind::CFileInfoW &fileInfo, bool &filled, UString &resPath) +{ + filled = false; + for (;;) + { + if (Enumerators.IsEmpty()) + { + if (Index >= FileNames.Size()) + return S_OK; + const UString &path = FileNames[Index]; + int pos = path.ReverseFind(WCHAR_PATH_SEPARATOR); + resPath.Empty(); + if (pos >= 0) + resPath = path.Left(pos + 1); + + #ifdef _WIN32 + // it's for "c:" paths/ + if (BasePrefix.IsEmpty() && path.Length() == 2 && path[1] == ':') + { + fileInfo.Name = path; + fileInfo.Attrib = FILE_ATTRIBUTE_DIRECTORY; + fileInfo.Size = 0; + } + else + #endif + if (!fileInfo.Find(BasePrefix + path)) + { + WRes errorCode = GetNormalizedError(); + resPath = path; + return errorCode; + } + Index++; + break; + } + bool found; + if (!Enumerators.Back().Next(fileInfo, found)) + { + HRESULT errorCode = GetNormalizedError(); + resPath = Prefixes.Back(); + return errorCode; + } + if (found) + { + resPath = Prefixes.Back(); + break; + } + Enumerators.DeleteBack(); + Prefixes.DeleteBack(); + } + resPath += fileInfo.Name; + if (!FlatMode && fileInfo.IsDir()) + { + UString prefix = resPath + WCHAR_PATH_SEPARATOR; + Enumerators.Add(NFind::CEnumeratorW(BasePrefix + prefix + (UString)(wchar_t)NName::kAnyStringWildcard)); + Prefixes.Add(prefix); + } + filled = true; + return S_OK; +} + +static void ConvertByteToHex(unsigned value, wchar_t *s) +{ + for (int i = 0; i < 2; i++) + { + unsigned t = value & 0xF; + value >>= 4; + s[1 - i] = (wchar_t)((t < 10) ? (L'0' + t) : (L'A' + (t - 10))); + } +} + +class CThreadCrc: public CProgressThreadVirt +{ + UInt64 NumFilesScan; + UInt64 NumFiles; + UInt64 NumFolders; + UInt64 DataSize; + UInt32 DataCrcSum; + Byte Sha256Sum[SHA256_DIGEST_SIZE]; + UInt32 DataNameCrcSum; + + UString GetResultMessage() const; + HRESULT ProcessVirt(); +public: + CDirEnumerator Enumerator; + +}; + +UString CThreadCrc::GetResultMessage() const +{ + UString s; + wchar_t sz[32]; + + s += LangString(IDS_FILES_COLON, 0x02000320); + s += L' '; + ConvertUInt64ToString(NumFiles, sz); + s += sz; + s += L'\n'; + + s += LangString(IDS_FOLDERS_COLON, 0x02000321); + s += L' '; + ConvertUInt64ToString(NumFolders, sz); + s += sz; + s += L'\n'; + + s += LangString(IDS_SIZE_COLON, 0x02000322); + s += L' '; + ConvertUInt64ToString(DataSize, sz); + s += MyFormatNew(IDS_FILE_SIZE, 0x02000982, sz); + s += L'\n'; + + s += LangString(IDS_CHECKSUM_CRC_DATA, 0x03020721); + s += L' '; + ConvertUInt32ToHex(DataCrcSum, sz); + s += sz; + s += L'\n'; + + s += LangString(IDS_CHECKSUM_CRC_DATA_NAMES, 0x03020722); + s += L' '; + ConvertUInt32ToHex(DataNameCrcSum, sz); + s += sz; + s += L'\n'; + + if (NumFiles == 1 && NumFilesScan == 1) + { + s += L"SHA-256: "; + for (int i = 0; i < SHA256_DIGEST_SIZE; i++) + { + wchar_t s2[4]; + ConvertByteToHex(Sha256Sum[i], s2); + s2[2] = 0; + s += s2; + } + } + return s; +} + +HRESULT CThreadCrc::ProcessVirt() +{ + DataSize = NumFolders = NumFiles = NumFilesScan = DataCrcSum = DataNameCrcSum = 0; + memset(Sha256Sum, 0, SHA256_DIGEST_SIZE); + // ProgressDialog.WaitCreating(); + + CMyBuffer bufferObject; + if (!bufferObject.Allocate(kBufSize)) + return E_OUTOFMEMORY; + Byte *buffer = (Byte *)(void *)bufferObject; + + UInt64 totalSize = 0; + + Enumerator.Init(); + + UString scanningStr = LangString(IDS_SCANNING, 0x03020800); + scanningStr += L' '; + + CProgressSync &sync = ProgressDialog.Sync; + + for (;;) + { + NFind::CFileInfoW fileInfo; + bool filled; + UString resPath; + HRESULT errorCode = Enumerator.GetNextFile(fileInfo, filled, resPath); + if (errorCode != 0) + { + ErrorPath1 = resPath; + return errorCode; + } + if (!filled) + break; + if (!fileInfo.IsDir()) + { + totalSize += fileInfo.Size; + NumFilesScan++; + } + sync.SetCurrentFileName(scanningStr + resPath); + sync.SetProgress(totalSize, 0); + RINOK(sync.SetPosAndCheckPaused(0)); + } + sync.SetNumFilesTotal(NumFilesScan); + sync.SetProgress(totalSize, 0); + + Enumerator.Init(); + + for (;;) + { + NFind::CFileInfoW fileInfo; + bool filled; + UString resPath; + HRESULT errorCode = Enumerator.GetNextFile(fileInfo, filled, resPath); + if (errorCode != 0) + { + ErrorPath1 = resPath; + return errorCode; + } + if (!filled) + break; + + UInt32 crc = CRC_INIT_VAL; + CSha256 sha256; + Sha256_Init(&sha256); + + if (fileInfo.IsDir()) + NumFolders++; + else + { + NIO::CInFile inFile; + if (!inFile.Open(Enumerator.BasePrefix + resPath)) + { + errorCode = GetNormalizedError(); + ErrorPath1 = resPath; + return errorCode; + } + sync.SetCurrentFileName(resPath); + sync.SetNumFilesCur(NumFiles); + NumFiles++; + for (;;) + { + UInt32 processedSize; + if (!inFile.Read(buffer, kBufSize, processedSize)) + { + errorCode = GetNormalizedError(); + ErrorPath1 = resPath; + return errorCode; + } + if (processedSize == 0) + break; + crc = CrcUpdate(crc, buffer, processedSize); + if (NumFilesScan == 1) + Sha256_Update(&sha256, buffer, processedSize); + + DataSize += processedSize; + RINOK(sync.SetPosAndCheckPaused(DataSize)); + } + DataCrcSum += CRC_GET_DIGEST(crc); + if (NumFilesScan == 1) + Sha256_Final(&sha256, Sha256Sum); + } + for (int i = 0; i < resPath.Length(); i++) + { + wchar_t c = resPath[i]; + crc = CRC_UPDATE_BYTE(crc, ((Byte)(c & 0xFF))); + crc = CRC_UPDATE_BYTE(crc, ((Byte)((c >> 8) & 0xFF))); + } + DataNameCrcSum += CRC_GET_DIGEST(crc); + RINOK(sync.SetPosAndCheckPaused(DataSize)); + } + sync.SetNumFilesCur(NumFiles); + OkMessage = GetResultMessage(); + OkMessageTitle = LangString(IDS_CHECKSUM_INFORMATION, 0x03020720); + return S_OK; +} + +void CApp::CalculateCrc() +{ + int srcPanelIndex = GetFocusedPanelIndex(); + CPanel &srcPanel = Panels[srcPanelIndex]; + if (!srcPanel.IsFsOrDrivesFolder()) + { + srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + return; + } + CRecordVector indices; + srcPanel.GetOperatedItemIndices(indices); + if (indices.IsEmpty()) + return; + + { + CThreadCrc t; + for (int i = 0; i < indices.Size(); i++) + t.Enumerator.FileNames.Add(srcPanel.GetItemRelPath(indices[i])); + t.Enumerator.BasePrefix = srcPanel.GetFsPath(); + t.Enumerator.FlatMode = GetFlatMode(); + + t.ProgressDialog.ShowCompressionInfo = false; + + UString title = LangString(IDS_CHECKSUM_CALCULATING, 0x03020710); + + t.ProgressDialog.MainWindow = _window; + t.ProgressDialog.MainTitle = LangString(IDS_APP_TITLE, 0x03000000); + t.ProgressDialog.MainAddTitle = title + UString(L' '); + + if (t.Create(title, _window) != S_OK) + return; + } + RefreshTitleAlways(); +} diff --git a/CPP/7zip/UI/FileManager/PanelDrag.cpp b/CPP/7zip/UI/FileManager/PanelDrag.cpp new file mode 100755 index 0000000..cae2746 --- /dev/null +++ b/CPP/7zip/UI/FileManager/PanelDrag.cpp @@ -0,0 +1,800 @@ +// PanelDrag.cpp + +#include "StdAfx.h" + +#ifdef UNDER_CE +#include +#endif + +#include "Common/StringConvert.h" + +#include "Windows/Memory.h" +#include "Windows/FileDir.h" +#include "Windows/Shell.h" + +#include "../Common/ArchiveName.h" +#include "../Common/CompressCall.h" + +#include "MessagesDialog.h" + +#include "App.h" +#include "EnumFormatEtc.h" + +using namespace NWindows; + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +static wchar_t *kTempDirPrefix = L"7zE"; +static LPCTSTR kSvenZipSetFolderFormat = TEXT("7-Zip::SetTargetFolder"); + +//////////////////////////////////////////////////////// + +class CDataObject: + public IDataObject, + public CMyUnknownImp +{ +private: + FORMATETC m_Etc; + UINT m_SetFolderFormat; + +public: + MY_UNKNOWN_IMP1_MT(IDataObject) + + STDMETHODIMP GetData(LPFORMATETC pformatetcIn, LPSTGMEDIUM medium); + STDMETHODIMP GetDataHere(LPFORMATETC pformatetc, LPSTGMEDIUM medium); + STDMETHODIMP QueryGetData(LPFORMATETC pformatetc ); + + STDMETHODIMP GetCanonicalFormatEtc ( LPFORMATETC /* pformatetc */, LPFORMATETC pformatetcOut) + { pformatetcOut->ptd = NULL; return ResultFromScode(E_NOTIMPL); } + + STDMETHODIMP SetData(LPFORMATETC etc, STGMEDIUM *medium, BOOL release); + STDMETHODIMP EnumFormatEtc(DWORD drection, LPENUMFORMATETC *enumFormatEtc); + + STDMETHODIMP DAdvise(FORMATETC * /* etc */, DWORD /* advf */, LPADVISESINK /* pAdvSink */, DWORD * /* pdwConnection */) + { return OLE_E_ADVISENOTSUPPORTED; } + STDMETHODIMP DUnadvise(DWORD /* dwConnection */) { return OLE_E_ADVISENOTSUPPORTED; } + STDMETHODIMP EnumDAdvise( LPENUMSTATDATA * /* ppenumAdvise */) { return OLE_E_ADVISENOTSUPPORTED; } + + CDataObject(); + + NMemory::CGlobal hGlobal; + UString Path; +}; + +CDataObject::CDataObject() +{ + m_SetFolderFormat = RegisterClipboardFormat(kSvenZipSetFolderFormat); + m_Etc.cfFormat = CF_HDROP; + m_Etc.ptd = NULL; + m_Etc.dwAspect = DVASPECT_CONTENT; + m_Etc.lindex = -1; + m_Etc.tymed = TYMED_HGLOBAL; +} + +STDMETHODIMP CDataObject::SetData(LPFORMATETC etc, STGMEDIUM *medium, BOOL /* release */) +{ + if (etc->cfFormat == m_SetFolderFormat && etc->tymed == TYMED_HGLOBAL && + etc->dwAspect == DVASPECT_CONTENT && medium->tymed == TYMED_HGLOBAL) + { + Path.Empty(); + if (medium->hGlobal == 0) + return S_OK; + size_t size = GlobalSize(medium->hGlobal) / sizeof(wchar_t); + const wchar_t *src = (const wchar_t *)GlobalLock(medium->hGlobal); + if (src != 0) + { + for (size_t i = 0; i < size; i++) + { + wchar_t c = src[i]; + if (c == 0) + break; + Path += c; + } + GlobalUnlock(medium->hGlobal); + return S_OK; + } + } + return E_NOTIMPL; +} + +static HGLOBAL DuplicateGlobalMem(HGLOBAL srcGlobal) +{ + SIZE_T size = GlobalSize(srcGlobal); + const void *src = GlobalLock(srcGlobal); + if (src == 0) + return 0; + HGLOBAL destGlobal = GlobalAlloc(GHND | GMEM_SHARE, size); + if (destGlobal != 0) + { + void *dest = GlobalLock(destGlobal); + if (dest == 0) + { + GlobalFree(destGlobal); + destGlobal = 0; + } + else + { + memcpy(dest, src, size); + GlobalUnlock(destGlobal); + } + } + GlobalUnlock(srcGlobal); + return destGlobal; +} + +STDMETHODIMP CDataObject::GetData(LPFORMATETC etc, LPSTGMEDIUM medium) +{ + RINOK(QueryGetData(etc)); + medium->tymed = m_Etc.tymed; + medium->pUnkForRelease = 0; + medium->hGlobal = DuplicateGlobalMem(hGlobal); + if (medium->hGlobal == 0) + return E_OUTOFMEMORY; + return S_OK; +} + +STDMETHODIMP CDataObject::GetDataHere(LPFORMATETC /* etc */, LPSTGMEDIUM /* medium */) +{ + // Seems Windows doesn't call it, so we will not implement it. + return E_UNEXPECTED; +} + + +STDMETHODIMP CDataObject::QueryGetData(LPFORMATETC etc) +{ + if ((m_Etc.tymed & etc->tymed) && + m_Etc.cfFormat == etc->cfFormat && + m_Etc.dwAspect == etc->dwAspect) + return S_OK; + return DV_E_FORMATETC; +} + +STDMETHODIMP CDataObject::EnumFormatEtc(DWORD direction, LPENUMFORMATETC FAR* enumFormatEtc) +{ + if (direction != DATADIR_GET) + return E_NOTIMPL; + return CreateEnumFormatEtc(1, &m_Etc, enumFormatEtc); +} + +//////////////////////////////////////////////////////// + +class CDropSource: + public IDropSource, + public CMyUnknownImp +{ + DWORD m_Effect; +public: + MY_UNKNOWN_IMP1_MT(IDropSource) + STDMETHOD(QueryContinueDrag)(BOOL escapePressed, DWORD keyState); + STDMETHOD(GiveFeedback)(DWORD effect); + + + bool NeedExtract; + CPanel *Panel; + CRecordVector Indices; + UString Folder; + CDataObject *DataObjectSpec; + CMyComPtr DataObject; + + bool NeedPostCopy; + HRESULT Result; + UStringVector Messages; + + CDropSource(): NeedPostCopy(false), Panel(0), Result(S_OK), m_Effect(DROPEFFECT_NONE) {} +}; + +STDMETHODIMP CDropSource::QueryContinueDrag(BOOL escapePressed, DWORD keyState) +{ + if (escapePressed == TRUE) + return DRAGDROP_S_CANCEL; + if ((keyState & MK_LBUTTON) == 0) + { + if (m_Effect == DROPEFFECT_NONE) + return DRAGDROP_S_CANCEL; + Result = S_OK; + bool needExtract = NeedExtract; + // MoveMode = (((keyState & MK_SHIFT) != 0) && MoveIsAllowed); + if (!DataObjectSpec->Path.IsEmpty()) + { + needExtract = false; + NeedPostCopy = true; + } + if (needExtract) + { + Result = Panel->CopyTo(Indices, Folder, + false, // moveMode, + false, // showMessages + &Messages); + if (Result != S_OK || !Messages.IsEmpty()) + return DRAGDROP_S_CANCEL; + } + return DRAGDROP_S_DROP; + } + return S_OK; +} + +STDMETHODIMP CDropSource::GiveFeedback(DWORD effect) +{ + m_Effect = effect; + return DRAGDROP_S_USEDEFAULTCURSORS; +} + +static bool CopyNamesToHGlobal(NMemory::CGlobal &hgDrop, const UStringVector &names) +{ + size_t totalLength = 1; + + #ifndef _UNICODE + if (!g_IsNT) + { + AStringVector namesA; + int i; + for (i = 0; i < names.Size(); i++) + namesA.Add(GetSystemString(names[i])); + for (i = 0; i < names.Size(); i++) + totalLength += namesA[i].Length() + 1; + + if (!hgDrop.Alloc(GHND | GMEM_SHARE, totalLength * sizeof(CHAR) + sizeof(DROPFILES))) + return false; + + NMemory::CGlobalLock dropLock(hgDrop); + DROPFILES* dropFiles = (DROPFILES*)dropLock.GetPointer(); + if (dropFiles == 0) + return false; + dropFiles->fNC = FALSE; + dropFiles->pt.x = 0; + dropFiles->pt.y = 0; + dropFiles->pFiles = sizeof(DROPFILES); + dropFiles->fWide = FALSE; + CHAR *p = (CHAR *)((BYTE *)dropFiles + sizeof(DROPFILES)); + for (i = 0; i < names.Size(); i++) + { + const AString &s = namesA[i]; + int fullLength = s.Length() + 1; + MyStringCopy(p, (const char *)s); + p += fullLength; + totalLength -= fullLength; + } + *p = 0; + } + else + #endif + { + int i; + for (i = 0; i < names.Size(); i++) + totalLength += names[i].Length() + 1; + + if (!hgDrop.Alloc(GHND | GMEM_SHARE, totalLength * sizeof(WCHAR) + sizeof(DROPFILES))) + return false; + + NMemory::CGlobalLock dropLock(hgDrop); + DROPFILES* dropFiles = (DROPFILES*)dropLock.GetPointer(); + if (dropFiles == 0) + return false; + dropFiles->fNC = FALSE; + dropFiles->pt.x = 0; + dropFiles->pt.y = 0; + dropFiles->pFiles = sizeof(DROPFILES); + dropFiles->fWide = TRUE; + WCHAR *p = (WCHAR *)((BYTE *)dropFiles + sizeof(DROPFILES)); + for (i = 0; i < names.Size(); i++) + { + const UString &s = names[i]; + int fullLength = s.Length() + 1; + MyStringCopy(p, (const WCHAR *)s); + p += fullLength; + totalLength -= fullLength; + } + *p = 0; + } + return true; +} + +void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */) +{ + CPanel::CDisableTimerProcessing disableTimerProcessing2(*this); + if (!DoesItSupportOperations()) + return; + CRecordVector indices; + GetOperatedItemIndices(indices); + if (indices.Size() == 0) + return; + + // CSelectedState selState; + // SaveSelectedState(selState); + + UString dirPrefix; + NFile::NDirectory::CTempDirectoryW tempDirectory; + + bool isFSFolder = IsFSFolder(); + if (isFSFolder) + dirPrefix = _currentFolderPrefix; + else + { + tempDirectory.Create(kTempDirPrefix); + dirPrefix = tempDirectory.GetPath(); + NFile::NName::NormalizeDirPathPrefix(dirPrefix); + } + + CDataObject *dataObjectSpec = new CDataObject; + CMyComPtr dataObject = dataObjectSpec; + + { + UStringVector names; + for (int i = 0; i < indices.Size(); i++) + { + UInt32 index = indices[i]; + UString s; + if (isFSFolder) + s = GetItemRelPath(index); + else + s = GetItemName(index); + names.Add(dirPrefix + s); + } + if (!CopyNamesToHGlobal(dataObjectSpec->hGlobal, names)) + return; + } + + CDropSource *dropSourceSpec = new CDropSource; + CMyComPtr dropSource = dropSourceSpec; + dropSourceSpec->NeedExtract = !isFSFolder; + dropSourceSpec->Panel = this; + dropSourceSpec->Indices = indices; + dropSourceSpec->Folder = dirPrefix; + dropSourceSpec->DataObjectSpec = dataObjectSpec; + dropSourceSpec->DataObject = dataObjectSpec; + + bool moveIsAllowed = isFSFolder; + + DWORD effectsOK = DROPEFFECT_COPY; + if (moveIsAllowed) + effectsOK |= DROPEFFECT_MOVE; + DWORD effect; + _panelCallback->DragBegin(); + HRESULT res = DoDragDrop(dataObject, dropSource, effectsOK, &effect); + _panelCallback->DragEnd(); + bool canceled = (res == DRAGDROP_S_CANCEL); + if (res == DRAGDROP_S_DROP) + { + res = dropSourceSpec->Result; + if (dropSourceSpec->NeedPostCopy) + if (!dataObjectSpec->Path.IsEmpty()) + { + NFile::NName::NormalizeDirPathPrefix(dataObjectSpec->Path); + res = CopyTo(indices, dataObjectSpec->Path, + (effect == DROPEFFECT_MOVE),// dropSourceSpec->MoveMode, + false, // showErrorMessages + &dropSourceSpec->Messages); + } + /* + if (effect == DROPEFFECT_MOVE) + RefreshListCtrl(selState); + */ + } + else + { + if (res != DRAGDROP_S_CANCEL && res != S_OK) + MessageBoxError(res); + res = dropSourceSpec->Result; + } + + if (!dropSourceSpec->Messages.IsEmpty()) + { + CMessagesDialog messagesDialog; + messagesDialog.Messages = &dropSourceSpec->Messages; + messagesDialog.Create((*this)); + } + if (res != S_OK && res != E_ABORT) + MessageBoxError(res); + if (res == S_OK && dropSourceSpec->Messages.IsEmpty() && !canceled) + KillSelection(); +} + +void CDropTarget::QueryGetData(IDataObject *dataObject) +{ + FORMATETC etc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + m_DropIsAllowed = (dataObject->QueryGetData(&etc) == S_OK); + +} + +static void MySetDropHighlighted(HWND hWnd, int index, bool enable) +{ + LVITEM item; + item.mask = LVIF_STATE; + item.iItem = index; + item.iSubItem = 0; + item.state = enable ? LVIS_DROPHILITED : 0; + item.stateMask = LVIS_DROPHILITED; + item.pszText = 0; + ListView_SetItem(hWnd, &item); +} + +void CDropTarget::RemoveSelection() +{ + if (m_SelectionIndex >= 0 && m_Panel != 0) + MySetDropHighlighted(m_Panel->_listView, m_SelectionIndex, false); + m_SelectionIndex = -1; +} + +#ifdef UNDER_CE +#define ChildWindowFromPointEx(hwndParent, pt, uFlags) ChildWindowFromPoint(hwndParent, pt) +#endif + +void CDropTarget::PositionCursor(POINTL ptl) +{ + m_SubFolderIndex = -1; + POINT pt; + pt.x = ptl.x; + pt.y = ptl.y; + + RemoveSelection(); + m_IsAppTarget = true; + m_Panel = NULL; + + m_PanelDropIsAllowed = true; + if (!m_DropIsAllowed) + return; + { + POINT pt2 = pt; + App->_window.ScreenToClient(&pt2); + for (int i = 0; i < kNumPanelsMax; i++) + if (App->IsPanelVisible(i)) + if (App->Panels[i].IsEnabled()) + if (ChildWindowFromPointEx(App->_window, pt2, + CWP_SKIPINVISIBLE | CWP_SKIPDISABLED) == (HWND)App->Panels[i]) + { + m_Panel = &App->Panels[i]; + m_IsAppTarget = false; + if (i == SrcPanelIndex) + { + m_PanelDropIsAllowed = false; + return; + } + break; + } + if (m_IsAppTarget) + { + if (TargetPanelIndex >= 0) + m_Panel = &App->Panels[TargetPanelIndex]; + return; + } + } + + /* + m_PanelDropIsAllowed = m_Panel->DoesItSupportOperations(); + if (!m_PanelDropIsAllowed) + return; + */ + + if (!m_Panel->IsFsOrPureDrivesFolder()) + return; + + if (WindowFromPoint(pt) != (HWND)m_Panel->_listView) + return; + + LVHITTESTINFO info; + m_Panel->_listView.ScreenToClient(&pt); + info.pt = pt; + int index = ListView_HitTest(m_Panel->_listView, &info); + if (index < 0) + return; + int realIndex = m_Panel->GetRealItemIndex(index); + if (realIndex == kParentIndex) + return; + if (!m_Panel->IsItemFolder(realIndex)) + return; + m_SubFolderIndex = realIndex; + m_SubFolderName = m_Panel->GetItemName(m_SubFolderIndex); + MySetDropHighlighted(m_Panel->_listView, index, true); + m_SelectionIndex = index; +} + +bool CDropTarget::IsFsFolderPath() const +{ + if (!m_IsAppTarget && m_Panel != 0) + return (m_Panel->IsFSFolder() || (m_Panel->IsFSDrivesFolder() && m_SelectionIndex >= 0)); + return false; +} + +static void ReadUnicodeStrings(const wchar_t *p, size_t size, UStringVector &names) +{ + names.Clear(); + UString name; + for (;size > 0; size--) + { + wchar_t c = *p++; + if (c == 0) + { + if (name.IsEmpty()) + break; + names.Add(name); + name.Empty(); + } + else + name += c; + } +} + +static void ReadAnsiStrings(const char *p, size_t size, UStringVector &names) +{ + names.Clear(); + AString name; + for (;size > 0; size--) + { + char c = *p++; + if (c == 0) + { + if (name.IsEmpty()) + break; + names.Add(GetUnicodeString(name)); + name.Empty(); + } + else + name += c; + } +} + +static void GetNamesFromDataObject(IDataObject *dataObject, UStringVector &names) +{ + names.Clear(); + FORMATETC etc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + STGMEDIUM medium; + HRESULT res = dataObject->GetData(&etc, &medium); + if (res != S_OK) + return; + if (medium.tymed != TYMED_HGLOBAL) + return; + { + NMemory::CGlobal global; + global.Attach(medium.hGlobal); + size_t blockSize = GlobalSize(medium.hGlobal); + NMemory::CGlobalLock dropLock(medium.hGlobal); + const DROPFILES* dropFiles = (DROPFILES*)dropLock.GetPointer(); + if (dropFiles == 0) + return; + if (blockSize < dropFiles->pFiles) + return; + size_t size = blockSize - dropFiles->pFiles; + const void *namesData = (const Byte *)dropFiles + dropFiles->pFiles; + if (dropFiles->fWide) + ReadUnicodeStrings((const wchar_t *)namesData, size / sizeof(wchar_t), names); + else + ReadAnsiStrings((const char *)namesData, size, names); + } +} + +bool CDropTarget::IsItSameDrive() const +{ + if (m_Panel == 0) + return false; + if (!IsFsFolderPath()) + return false; + UString drive; + if (m_Panel->IsFSFolder()) + { + drive = m_Panel->GetDriveOrNetworkPrefix(); + if (drive.IsEmpty()) + return false; + } + else if (m_Panel->IsFSDrivesFolder() && m_SelectionIndex >= 0) + drive = m_SubFolderName + WCHAR_PATH_SEPARATOR; + else + return false; + + if (m_SourcePaths.Size() == 0) + return false; + for (int i = 0; i < m_SourcePaths.Size(); i++) + { + const UString &path = m_SourcePaths[i]; + if (drive.CompareNoCase(path.Left(drive.Length())) != 0) + return false; + } + return true; + +} + +DWORD CDropTarget::GetEffect(DWORD keyState, POINTL /* pt */, DWORD allowedEffect) +{ + if (!m_DropIsAllowed || !m_PanelDropIsAllowed) + return DROPEFFECT_NONE; + + if (!IsFsFolderPath() || !m_SetPathIsOK) + allowedEffect &= ~DROPEFFECT_MOVE; + + DWORD effect = 0; + if (keyState & MK_CONTROL) + effect = allowedEffect & DROPEFFECT_COPY; + else if (keyState & MK_SHIFT) + effect = allowedEffect & DROPEFFECT_MOVE; + if (effect == 0) + { + if (allowedEffect & DROPEFFECT_COPY) + effect = DROPEFFECT_COPY; + if (allowedEffect & DROPEFFECT_MOVE) + { + if (IsItSameDrive()) + effect = DROPEFFECT_MOVE; + } + } + if (effect == 0) + return DROPEFFECT_NONE; + return effect; +} + +UString CDropTarget::GetTargetPath() const +{ + if (!IsFsFolderPath()) + return UString(); + UString path = m_Panel->_currentFolderPrefix; + if (m_Panel->IsFSDrivesFolder()) + path.Empty(); + if (m_SubFolderIndex >= 0 && !m_SubFolderName.IsEmpty()) + { + path += m_SubFolderName; + path += WCHAR_PATH_SEPARATOR; + } + return path; +} + +bool CDropTarget::SetPath(bool enablePath) const +{ + UINT setFolderFormat = RegisterClipboardFormat(kSvenZipSetFolderFormat); + + FORMATETC etc = { (CLIPFORMAT)setFolderFormat, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + STGMEDIUM medium; + medium.tymed = etc.tymed; + medium.pUnkForRelease = 0; + UString path; + if (enablePath) + path = GetTargetPath(); + size_t size = path.Length() + 1; + medium.hGlobal = GlobalAlloc(GHND | GMEM_SHARE, size * sizeof(wchar_t)); + if (medium.hGlobal == 0) + return false; + wchar_t *dest = (wchar_t *)GlobalLock(medium.hGlobal); + if (dest == 0) + { + GlobalUnlock(medium.hGlobal); + return false; + } + MyStringCopy(dest, (const wchar_t *)path); + GlobalUnlock(medium.hGlobal); + bool res = m_DataObject->SetData(&etc, &medium, FALSE) == S_OK; + GlobalFree(medium.hGlobal); + return res; +} + +bool CDropTarget::SetPath() +{ + m_SetPathIsOK = SetPath(m_DropIsAllowed && m_PanelDropIsAllowed && IsFsFolderPath()); + return m_SetPathIsOK; +} + +STDMETHODIMP CDropTarget::DragEnter(IDataObject * dataObject, DWORD keyState, + POINTL pt, DWORD *effect) +{ + GetNamesFromDataObject(dataObject, m_SourcePaths); + QueryGetData(dataObject); + m_DataObject = dataObject; + return DragOver(keyState, pt, effect); +} + + +STDMETHODIMP CDropTarget::DragOver(DWORD keyState, POINTL pt, DWORD *effect) +{ + PositionCursor(pt); + SetPath(); + *effect = GetEffect(keyState, pt, *effect); + return S_OK; +} + + +STDMETHODIMP CDropTarget::DragLeave() +{ + RemoveSelection(); + SetPath(false); + m_DataObject.Release(); + return S_OK; +} + +// We suppose that there was ::DragOver for same POINTL_pt before ::Drop +// So SetPath() is same as in Drop. + +STDMETHODIMP CDropTarget::Drop(IDataObject *dataObject, DWORD keyState, + POINTL pt, DWORD * effect) +{ + QueryGetData(dataObject); + PositionCursor(pt); + m_DataObject = dataObject; + bool needDrop = true; + if (m_DropIsAllowed && m_PanelDropIsAllowed) + if (IsFsFolderPath()) + needDrop = !SetPath(); + *effect = GetEffect(keyState, pt, *effect); + if (m_DropIsAllowed && m_PanelDropIsAllowed) + { + if (needDrop) + { + UString path = GetTargetPath(); + if (m_IsAppTarget && m_Panel) + if (m_Panel->IsFSFolder()) + path = m_Panel->_currentFolderPrefix; + m_Panel->DropObject(dataObject, path); + } + } + RemoveSelection(); + m_DataObject.Release(); + return S_OK; +} + +void CPanel::DropObject(IDataObject *dataObject, const UString &folderPath) +{ + UStringVector names; + GetNamesFromDataObject(dataObject, names); + CompressDropFiles(names, folderPath); +} + +/* +void CPanel::CompressDropFiles(HDROP dr) +{ + UStringVector fileNames; + { + NShell::CDrop drop(true); + drop.Attach(dr); + drop.QueryFileNames(fileNames); + } + CompressDropFiles(fileNamesUnicode); +} +*/ + +static bool IsFolderInTemp(const UString &path) +{ + UString tempPath; + if (!NFile::NDirectory::MyGetTempPath(tempPath)) + return false; + if (tempPath.IsEmpty()) + return false; + return (tempPath.CompareNoCase(path.Left(tempPath.Length())) == 0); +} + +static bool AreThereNamesFromTemp(const UStringVector &fileNames) +{ + UString tempPath; + if (!NFile::NDirectory::MyGetTempPath(tempPath)) + return false; + if (tempPath.IsEmpty()) + return false; + for (int i = 0; i < fileNames.Size(); i++) + if (tempPath.CompareNoCase(fileNames[i].Left(tempPath.Length())) == 0) + return true; + return false; +} + +void CPanel::CompressDropFiles(const UStringVector &fileNames, const UString &folderPath) +{ + if (fileNames.Size() == 0) + return; + bool createNewArchive = true; + if (!IsFSFolder()) + createNewArchive = !DoesItSupportOperations(); + + if (createNewArchive) + { + UString folderPath2 = folderPath; + if (folderPath2.IsEmpty()) + { + NFile::NDirectory::GetOnlyDirPrefix(fileNames.Front(), folderPath2); + if (IsFolderInTemp(folderPath2)) + folderPath2 = ROOT_FS_FOLDER; + } + const UString archiveName = CreateArchiveName(fileNames.Front(), (fileNames.Size() > 1), false); + CompressFiles(folderPath2, archiveName, L"", fileNames, + false, // email + true, // showDialog + AreThereNamesFromTemp(fileNames) // waitFinish + ); + } + else + CopyFromAsk(fileNames); +} diff --git a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp new file mode 100755 index 0000000..b03bb67 --- /dev/null +++ b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp @@ -0,0 +1,613 @@ +// PanelFolderChange.cpp + +#include "StdAfx.h" + +#include "Common/StringConvert.h" +#include "Common/Wildcard.h" + +#include "Windows/PropVariant.h" + +#include "../../PropID.h" + +#ifdef UNDER_CE +#include "FSFolder.h" +#else +#include "FSDrives.h" +#endif +#include "LangUtils.h" +#include "ListViewDialog.h" +#include "Panel.h" +#include "RootFolder.h" +#include "ViewSettings.h" + +#include "resource.h" + +using namespace NWindows; +using namespace NFile; +using namespace NFind; + +void CPanel::SetToRootFolder() +{ + _folder.Release(); + _library.Free(); + CRootFolder *rootFolderSpec = new CRootFolder; + _folder = rootFolderSpec; + rootFolderSpec->Init(); +} + +HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bool &archiveIsOpened, bool &encrypted) +{ + archiveIsOpened = false; + encrypted = false; + CDisableTimerProcessing disableTimerProcessing1(*this); + + if (_parentFolders.Size() > 0) + { + const UString &virtPath = _parentFolders.Back().VirtualPath; + if (fullPath.Left(virtPath.Length()) == virtPath) + { + for (;;) + { + CMyComPtr newFolder; + HRESULT res = _folder->BindToParentFolder(&newFolder); + if (!newFolder || res != S_OK) + break; + _folder = newFolder; + } + UStringVector parts; + SplitPathToParts(fullPath.Mid(virtPath.Length()), parts); + for (int i = 0; i < parts.Size(); i++) + { + const UString &s = parts[i]; + if ((i == 0 || i == parts.Size() - 1) && s.IsEmpty()) + continue; + CMyComPtr newFolder; + HRESULT res = _folder->BindToFolder(s, &newFolder); + if (!newFolder || res != S_OK) + break; + _folder = newFolder; + } + return S_OK; + } + } + + CloseOpenFolders(); + UString sysPath = fullPath; + CFileInfoW fileInfo; + UStringVector reducedParts; + while (!sysPath.IsEmpty()) + { + if (fileInfo.Find(sysPath)) + break; + int pos = sysPath.ReverseFind(WCHAR_PATH_SEPARATOR); + if (pos < 0) + sysPath.Empty(); + else + { + if (reducedParts.Size() > 0 || pos < sysPath.Length() - 1) + reducedParts.Add(sysPath.Mid(pos + 1)); + sysPath = sysPath.Left(pos); + } + } + SetToRootFolder(); + CMyComPtr newFolder; + if (sysPath.IsEmpty()) + { + if (_folder->BindToFolder(fullPath, &newFolder) == S_OK) + _folder = newFolder; + } + else if (fileInfo.IsDir()) + { + NName::NormalizeDirPathPrefix(sysPath); + if (_folder->BindToFolder(sysPath, &newFolder) == S_OK) + _folder = newFolder; + } + else + { + UString dirPrefix; + if (!NDirectory::GetOnlyDirPrefix(sysPath, dirPrefix)) + dirPrefix.Empty(); + if (_folder->BindToFolder(dirPrefix, &newFolder) == S_OK) + { + _folder = newFolder; + LoadFullPath(); + UString fileName; + if (NDirectory::GetOnlyName(sysPath, fileName)) + { + HRESULT res = OpenItemAsArchive(fileName, arcFormat, encrypted); + if (res != S_FALSE) + { + RINOK(res); + } + /* + if (res == E_ABORT) + return res; + */ + if (res == S_OK) + { + archiveIsOpened = true; + for (int i = reducedParts.Size() - 1; i >= 0; i--) + { + CMyComPtr newFolder; + _folder->BindToFolder(reducedParts[i], &newFolder); + if (!newFolder) + break; + _folder = newFolder; + } + } + } + } + } + return S_OK; +} + +HRESULT CPanel::BindToPathAndRefresh(const UString &path) +{ + CDisableTimerProcessing disableTimerProcessing1(*this); + bool archiveIsOpened, encrypted; + RINOK(BindToPath(path, UString(), archiveIsOpened, encrypted)); + RefreshListCtrl(UString(), -1, true, UStringVector()); + return S_OK; +} + +void CPanel::SetBookmark(int index) +{ + _appState->FastFolders.SetString(index, _currentFolderPrefix); +} + +void CPanel::OpenBookmark(int index) +{ + BindToPathAndRefresh(_appState->FastFolders.GetString(index)); +} + +UString GetFolderPath(IFolderFolder *folder) +{ + NCOM::CPropVariant prop; + if (folder->GetFolderProperty(kpidPath, &prop) == S_OK) + if (prop.vt == VT_BSTR) + return (wchar_t *)prop.bstrVal; + return UString(); +} + +void CPanel::LoadFullPath() +{ + _currentFolderPrefix.Empty(); + for (int i = 0; i < _parentFolders.Size(); i++) + { + const CFolderLink &folderLink = _parentFolders[i]; + _currentFolderPrefix += GetFolderPath(folderLink.ParentFolder); + _currentFolderPrefix += folderLink.ItemName; + _currentFolderPrefix += WCHAR_PATH_SEPARATOR; + } + if (_folder) + _currentFolderPrefix += GetFolderPath(_folder); +} + +static int GetRealIconIndex(LPCWSTR path, DWORD attributes) +{ + int index = -1; + if (GetRealIconIndex(path, attributes, index) != 0) + return index; + return -1; +} + +void CPanel::LoadFullPathAndShow() +{ + LoadFullPath(); + _appState->FolderHistory.AddString(_currentFolderPrefix); + + _headerComboBox.SetText(_currentFolderPrefix); + + #ifndef UNDER_CE + COMBOBOXEXITEM item; + item.mask = 0; + + UString path = _currentFolderPrefix; + if (path.Length() > + #ifdef _WIN32 + 3 + #else + 1 + #endif + && path[path.Length() - 1] == WCHAR_PATH_SEPARATOR) + path.Delete(path.Length() - 1); + + CFileInfoW info; + DWORD attrib = FILE_ATTRIBUTE_DIRECTORY; + if (info.Find(path)) + attrib = info.Attrib; + + item.iImage = GetRealIconIndex(path, attrib); + + if (item.iImage >= 0) + { + item.iSelectedImage = item.iImage; + item.mask |= (CBEIF_IMAGE | CBEIF_SELECTEDIMAGE); + } + item.iItem = -1; + _headerComboBox.SetItem(&item); + #endif + + RefreshTitle(); +} + +#ifndef UNDER_CE +LRESULT CPanel::OnNotifyComboBoxEnter(const UString &s) +{ + if (BindToPathAndRefresh(GetUnicodeString(s)) == S_OK) + { + PostMessage(kSetFocusToListView); + return TRUE; + } + return FALSE; +} + +bool CPanel::OnNotifyComboBoxEndEdit(PNMCBEENDEDITW info, LRESULT &result) +{ + if (info->iWhy == CBENF_ESCAPE) + { + _headerComboBox.SetText(_currentFolderPrefix); + PostMessage(kSetFocusToListView); + result = FALSE; + return true; + } + + /* + if (info->iWhy == CBENF_DROPDOWN) + { + result = FALSE; + return true; + } + */ + + if (info->iWhy == CBENF_RETURN) + { + // When we use Edit control and press Enter. + UString s; + _headerComboBox.GetText(s); + result = OnNotifyComboBoxEnter(s); + return true; + } + return false; +} +#endif + +#ifndef _UNICODE +bool CPanel::OnNotifyComboBoxEndEdit(PNMCBEENDEDIT info, LRESULT &result) +{ + if (info->iWhy == CBENF_ESCAPE) + { + _headerComboBox.SetText(_currentFolderPrefix); + PostMessage(kSetFocusToListView); + result = FALSE; + return true; + } + /* + if (info->iWhy == CBENF_DROPDOWN) + { + result = FALSE; + return true; + } + */ + + if (info->iWhy == CBENF_RETURN) + { + UString s; + _headerComboBox.GetText(s); + // GetUnicodeString(info->szText) + result = OnNotifyComboBoxEnter(s); + return true; + } + return false; +} +#endif + +void CPanel::AddComboBoxItem(const UString &name, int iconIndex, int indent, bool addToList) +{ + #ifdef UNDER_CE + + UString s; + iconIndex = iconIndex; + for (int i = 0; i < indent; i++) + s += L" "; + _headerComboBox.AddString(s + name); + + #else + + COMBOBOXEXITEMW item; + item.mask = CBEIF_TEXT | CBEIF_INDENT; + item.iSelectedImage = item.iImage = iconIndex; + if (iconIndex >= 0) + item.mask |= (CBEIF_IMAGE | CBEIF_SELECTEDIMAGE); + item.iItem = -1; + item.iIndent = indent; + item.pszText = (LPWSTR)(LPCWSTR)name; + _headerComboBox.InsertItem(&item); + + #endif + + if (addToList) + ComboBoxPaths.Add(name); +} + +extern UString RootFolder_GetName_Computer(int &iconIndex); +extern UString RootFolder_GetName_Network(int &iconIndex); +extern UString RootFolder_GetName_Documents(int &iconIndex); + +bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result) +{ + result = FALSE; + switch(code) + { + case CBN_DROPDOWN: + { + ComboBoxPaths.Clear(); + _headerComboBox.ResetContent(); + + int i; + UStringVector pathParts; + + SplitPathToParts(_currentFolderPrefix, pathParts); + UString sumPass; + if (!pathParts.IsEmpty()) + pathParts.DeleteBack(); + for (i = 0; i < pathParts.Size(); i++) + { + UString name = pathParts[i]; + sumPass += name; + sumPass += WCHAR_PATH_SEPARATOR; + CFileInfoW info; + DWORD attrib = FILE_ATTRIBUTE_DIRECTORY; + if (info.Find(sumPass)) + attrib = info.Attrib; + AddComboBoxItem(name.IsEmpty() ? L"\\" : name, GetRealIconIndex(sumPass, attrib), i, false); + ComboBoxPaths.Add(sumPass); + } + + #ifndef UNDER_CE + + int iconIndex; + UString name; + name = RootFolder_GetName_Documents(iconIndex); + AddComboBoxItem(name, iconIndex, 0, true); + + name = RootFolder_GetName_Computer(iconIndex); + AddComboBoxItem(name, iconIndex, 0, true); + + UStringVector driveStrings; + MyGetLogicalDriveStrings(driveStrings); + for (i = 0; i < driveStrings.Size(); i++) + { + UString s = driveStrings[i]; + ComboBoxPaths.Add(s); + int iconIndex = GetRealIconIndex(s, 0); + if (s.Length() > 0 && s[s.Length() - 1] == WCHAR_PATH_SEPARATOR) + s.Delete(s.Length() - 1); + AddComboBoxItem(s, iconIndex, 1, false); + } + + name = RootFolder_GetName_Network(iconIndex); + AddComboBoxItem(name, iconIndex, 0, true); + + #endif + + return false; + } + + case CBN_SELENDOK: + { + code = code; + int index = _headerComboBox.GetCurSel(); + if (index >= 0) + { + UString pass = ComboBoxPaths[index]; + _headerComboBox.SetCurSel(-1); + // _headerComboBox.SetText(pass); // it's fix for seclecting by mouse. + if (BindToPathAndRefresh(pass) == S_OK) + { + PostMessage(kSetFocusToListView); + #ifdef UNDER_CE + PostMessage(kRefreshHeaderComboBox); + #endif + + return true; + } + } + return false; + } + /* + case CBN_CLOSEUP: + { + LoadFullPathAndShow(); + true; + + } + case CBN_SELCHANGE: + { + // LoadFullPathAndShow(); + return true; + } + */ + } + return false; +} + +bool CPanel::OnNotifyComboBox(LPNMHDR header, LRESULT &result) +{ + #ifndef UNDER_CE + switch(header->code) + { + case CBEN_BEGINEDIT: + { + _lastFocusedIsList = false; + _panelCallback->PanelWasFocused(); + break; + } + #ifndef _UNICODE + case CBEN_ENDEDIT: + { + return OnNotifyComboBoxEndEdit((PNMCBEENDEDIT)header, result); + } + #endif + case CBEN_ENDEDITW: + { + return OnNotifyComboBoxEndEdit((PNMCBEENDEDITW)header, result); + } + } + #endif + return false; +} + + +void CPanel::FoldersHistory() +{ + CListViewDialog listViewDialog; + listViewDialog.DeleteIsAllowed = true; + listViewDialog.Title = LangString(IDS_FOLDERS_HISTORY, 0x03020260); + _appState->FolderHistory.GetList(listViewDialog.Strings); + if (listViewDialog.Create(GetParent()) == IDCANCEL) + return; + UString selectString; + if (listViewDialog.StringsWereChanged) + { + _appState->FolderHistory.RemoveAll(); + for (int i = listViewDialog.Strings.Size() - 1; i >= 0; i--) + _appState->FolderHistory.AddString(listViewDialog.Strings[i]); + if (listViewDialog.FocusedItemIndex >= 0) + selectString = listViewDialog.Strings[listViewDialog.FocusedItemIndex]; + } + else + { + if (listViewDialog.FocusedItemIndex >= 0) + selectString = listViewDialog.Strings[listViewDialog.FocusedItemIndex]; + } + if (listViewDialog.FocusedItemIndex >= 0) + BindToPathAndRefresh(selectString); +} + +void CPanel::OpenParentFolder() +{ + LoadFullPath(); // Maybe we don't need it ?? + UString focucedName; + if (!_currentFolderPrefix.IsEmpty() && + _currentFolderPrefix.Back() == WCHAR_PATH_SEPARATOR) + { + focucedName = _currentFolderPrefix; + focucedName.DeleteBack(); + if (focucedName != L"\\\\.") + { + int pos = focucedName.ReverseFind(WCHAR_PATH_SEPARATOR); + if (pos >= 0) + focucedName = focucedName.Mid(pos + 1); + } + } + + CDisableTimerProcessing disableTimerProcessing1(*this); + CMyComPtr newFolder; + _folder->BindToParentFolder(&newFolder); + if (newFolder) + _folder = newFolder; + else + { + if (_parentFolders.IsEmpty()) + { + SetToRootFolder(); + if (focucedName.IsEmpty()) + focucedName = GetItemName(0); + } + else + { + _folder.Release(); + _library.Free(); + CFolderLink &link = _parentFolders.Back(); + _folder = link.ParentFolder; + _library.Attach(link.Library.Detach()); + focucedName = link.ItemName; + if (_parentFolders.Size() > 1) + OpenParentArchiveFolder(); + _parentFolders.DeleteBack(); + if (_parentFolders.IsEmpty()) + _flatMode = _flatModeForDisk; + } + } + + UStringVector selectedItems; + /* + if (!focucedName.IsEmpty()) + selectedItems.Add(focucedName); + */ + LoadFullPath(); + // ::SetCurrentDirectory(::_currentFolderPrefix); + RefreshListCtrl(focucedName, -1, true, selectedItems); + _listView.EnsureVisible(_listView.GetFocusedItem(), false); + RefreshStatusBar(); +} + +void CPanel::CloseOpenFolders() +{ + while (_parentFolders.Size() > 0) + { + _folder.Release(); + _library.Free(); + _folder = _parentFolders.Back().ParentFolder; + _library.Attach(_parentFolders.Back().Library.Detach()); + if (_parentFolders.Size() > 1) + OpenParentArchiveFolder(); + _parentFolders.DeleteBack(); + } + _flatMode = _flatModeForDisk; + _folder.Release(); + _library.Free(); +} + +void CPanel::OpenRootFolder() +{ + CDisableTimerProcessing disableTimerProcessing1(*this); + _parentFolders.Clear(); + SetToRootFolder(); + RefreshListCtrl(UString(), -1, true, UStringVector()); + // ::SetCurrentDirectory(::_currentFolderPrefix); + /* + BeforeChangeFolder(); + _currentFolderPrefix.Empty(); + AfterChangeFolder(); + SetCurrentPathText(); + RefreshListCtrl(UString(), 0, UStringVector()); + _listView.EnsureVisible(_listView.GetFocusedItem(), false); + */ +} + +void CPanel::OpenDrivesFolder() +{ + CloseOpenFolders(); + #ifdef UNDER_CE + NFsFolder::CFSFolder *folderSpec = new NFsFolder::CFSFolder; + _folder = folderSpec; + folderSpec->InitToRoot(); + #else + CFSDrives *folderSpec = new CFSDrives; + _folder = folderSpec; + folderSpec->Init(); + #endif + RefreshListCtrl(); +} + +void CPanel::OpenFolder(int index) +{ + if (index == kParentIndex) + { + OpenParentFolder(); + return; + } + CMyComPtr newFolder; + _folder->BindToFolder(index, &newFolder); + if (!newFolder) + return; + _folder = newFolder; + LoadFullPath(); + // ::SetCurrentDirectory(::_currentFolderPrefix); + RefreshListCtrl(); + UINT state = LVIS_SELECTED; + _listView.SetItemState(_listView.GetFocusedItem(), state, state); + _listView.EnsureVisible(_listView.GetFocusedItem(), false); +} diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp new file mode 100755 index 0000000..0fa708f --- /dev/null +++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp @@ -0,0 +1,757 @@ +// PanelItemOpen.cpp + +#include "StdAfx.h" + +#include "Common/AutoPtr.h" +#include "Common/StringConvert.h" + +#include "Windows/Error.h" +#include "Windows/FileDir.h" +#include "Windows/FileFind.h" +#include "Windows/Process.h" +#include "Windows/PropVariant.h" +#include "Windows/Thread.h" + +#include "../Common/ExtractingFilePath.h" + +#include "App.h" + +#include "FileFolderPluginOpen.h" +#include "FormatUtils.h" +#include "LangUtils.h" +#include "RegistryUtils.h" +#include "UpdateCallback100.h" + +#include "resource.h" + +using namespace NWindows; +using namespace NSynchronization; +using namespace NFile; +using namespace NDirectory; + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +static wchar_t *kTempDirPrefix = L"7zO"; + + +static bool IsNameVirus(const UString &name) +{ + return (name.Find(L" ") >= 0); +} + +struct CTmpProcessInfo: public CTempFileInfo +{ + HANDLE ProcessHandle; + HWND Window; + UString FullPathFolderPrefix; + bool UsePassword; + UString Password; + CTmpProcessInfo(): UsePassword(false) {} +}; + +class CTmpProcessInfoRelease +{ + CTmpProcessInfo *_tmpProcessInfo; +public: + bool _needDelete; + CTmpProcessInfoRelease(CTmpProcessInfo &tmpProcessInfo): + _tmpProcessInfo(&tmpProcessInfo), _needDelete(true) {} + ~CTmpProcessInfoRelease() + { + if (_needDelete) + _tmpProcessInfo->DeleteDirAndFile(); + } +}; + +HRESULT CPanel::OpenItemAsArchive(IInStream *inStream, + const CTempFileInfo &tempFileInfo, + const UString &virtualFilePath, + const UString &arcFormat, + bool &encrypted) +{ + encrypted = false; + CFolderLink folderLink; + (CTempFileInfo &)folderLink = tempFileInfo; + if (inStream) + folderLink.IsVirtual = true; + else + { + if (!folderLink.FileInfo.Find(folderLink.FilePath)) + return ::GetLastError(); + if (folderLink.FileInfo.IsDir()) + return S_FALSE; + folderLink.IsVirtual = false; + } + + folderLink.VirtualPath = virtualFilePath; + + CMyComPtr newFolder; + + // _passwordIsDefined = false; + // _password.Empty(); + + NDLL::CLibrary library; + + UString password; + RINOK(OpenFileFolderPlugin(inStream, + folderLink.FilePath.IsEmpty() ? virtualFilePath : folderLink.FilePath, + arcFormat, + &library, &newFolder, GetParent(), encrypted, password)); + + folderLink.Password = password; + folderLink.UsePassword = encrypted; + + folderLink.ParentFolder = _folder; + _parentFolders.Add(folderLink); + _parentFolders.Back().Library.Attach(_library.Detach()); + + _folder.Release(); + _library.Free(); + _folder = newFolder; + _library.Attach(library.Detach()); + + _flatMode = _flatModeForArc; + + CMyComPtr getFolderArcProps; + _folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps); + if (getFolderArcProps) + { + CMyComPtr arcProps; + getFolderArcProps->GetFolderArcProps(&arcProps); + if (arcProps) + { + UString s; + UInt32 numLevels; + if (arcProps->GetArcNumLevels(&numLevels) != S_OK) + numLevels = 0; + for (UInt32 level2 = 0; level2 < numLevels; level2++) + { + UInt32 level = numLevels - 1 - level2; + PROPID propIDs[] = { kpidError, kpidPath, kpidType } ; + UString values[3]; + for (Int32 i = 0; i < 3; i++) + { + CMyComBSTR name; + NCOM::CPropVariant prop; + if (arcProps->GetArcProp(level, propIDs[i], &prop) != S_OK) + continue; + if (prop.vt != VT_EMPTY) + values[i] = (prop.vt == VT_BSTR) ? prop.bstrVal : L"?"; + } + if (!values[0].IsEmpty()) + { + if (!s.IsEmpty()) + s += L"--------------------\n"; + s += values[0]; s += L"\n\n["; + s += values[2]; s += L"] "; + s += values[1]; s += L"\n"; + } + } + if (!s.IsEmpty()) + MessageBox(s); + } + } + + return S_OK; +} + +HRESULT CPanel::OpenItemAsArchive(const UString &name, const UString &arcFormat, bool &encrypted) +{ + CTempFileInfo tfi; + tfi.ItemName = name; + tfi.FolderPath = _currentFolderPrefix; + tfi.FilePath = _currentFolderPrefix + name; + return OpenItemAsArchive(NULL, tfi, _currentFolderPrefix + name, arcFormat, encrypted); +} + +HRESULT CPanel::OpenItemAsArchive(int index) +{ + CDisableTimerProcessing disableTimerProcessing1(*this); + bool encrypted; + RINOK(OpenItemAsArchive(GetItemRelPath(index), UString(), encrypted)); + RefreshListCtrl(); + return S_OK; +} + +HRESULT CPanel::OpenParentArchiveFolder() +{ + CDisableTimerProcessing disableTimerProcessing1(*this); + if (_parentFolders.Size() < 2) + return S_OK; + const CFolderLink &folderLink = _parentFolders.Back(); + NFind::CFileInfoW newFileInfo; + if (newFileInfo.Find(folderLink.FilePath)) + { + if (folderLink.WasChanged(newFileInfo)) + { + UString message = MyFormatNew(IDS_WANT_UPDATE_MODIFIED_FILE, + 0x03020280, folderLink.ItemName); + if (::MessageBoxW(HWND(*this), message, L"7-Zip", MB_OKCANCEL | MB_ICONQUESTION) == IDOK) + { + if (OnOpenItemChanged(folderLink.FolderPath, folderLink.ItemName, + folderLink.UsePassword, folderLink.Password) != S_OK) + { + ::MessageBoxW(HWND(*this), MyFormatNew(IDS_CANNOT_UPDATE_FILE, + 0x03020281, folderLink.FilePath), L"7-Zip", MB_OK | MB_ICONSTOP); + return S_OK; + } + } + } + } + folderLink.DeleteDirAndFile(); + return S_OK; +} + +static const char *kStartExtensions = + #ifdef UNDER_CE + " cab" + #endif + " exe bat com" + " chm" + " msi doc xls ppt pps wps wpt wks xlr wdb vsd pub" + + " docx docm dotx dotm xlsx xlsm xltx xltm xlsb xps" + " xlam pptx pptm potx potm ppam ppsx ppsm xsn" + " mpp" + " msg" + " dwf" + + " flv swf" + + " odt ods" + " wb3" + " pdf" + " "; + +static bool FindExt(const char *p, const UString &name) +{ + int extPos = name.ReverseFind('.'); + if (extPos < 0) + return false; + UString ext = name.Mid(extPos + 1); + ext.MakeLower(); + AString ext2 = UnicodeStringToMultiByte(ext); + for (int i = 0; p[i] != 0;) + { + int j; + for (j = i; p[j] != ' '; j++); + if (ext2.Length() == j - i && memcmp(p + i, (const char *)ext2, ext2.Length()) == 0) + return true; + i = j + 1; + } + return false; +} + +static bool DoItemAlwaysStart(const UString &name) +{ + return FindExt(kStartExtensions, name); +} + +static UString GetQuotedString(const UString &s) +{ + return UString(L'\"') + s + UString(L'\"'); +} + +static HRESULT StartEditApplication(const UString &path, HWND window, CProcess &process) +{ + UString command; + ReadRegEditor(command); + if (command.IsEmpty()) + { + #ifdef UNDER_CE + command = L"\\Windows\\"; + #else + if (!MyGetWindowsDirectory(command)) + return 0; + NFile::NName::NormalizeDirPathPrefix(command); + #endif + command += L"notepad.exe"; + } + + HRESULT res = process.Create(command, GetQuotedString(path), NULL); + if (res != SZ_OK) + ::MessageBoxW(window, LangString(IDS_CANNOT_START_EDITOR, 0x03020282), L"7-Zip", MB_OK | MB_ICONSTOP); + return res; +} + +void CApp::DiffFiles() +{ + const CPanel &panel = GetFocusedPanel(); + + CRecordVector indices; + panel.GetSelectedItemsIndices(indices); + + UString path1, path2; + if (indices.Size() == 2) + { + path1 = panel.GetItemFullPath(indices[0]); + path2 = panel.GetItemFullPath(indices[1]); + } + else if (indices.Size() == 1 && NumPanels >= 2) + { + const CPanel &destPanel = Panels[1 - LastFocusedPanel]; + path1 = panel.GetItemFullPath(indices[0]); + const UString relPath = panel.GetItemRelPath(indices[0]); + CRecordVector indices2; + destPanel.GetSelectedItemsIndices(indices2); + if (indices2.Size() == 1) + path2 = destPanel.GetItemFullPath(indices2[0]); + else + path2 = destPanel._currentFolderPrefix + relPath; + } + else + return; + + UString command; + ReadRegDiff(command); + if (command.IsEmpty()) + return; + + UString param = GetQuotedString(path1) + L' ' + GetQuotedString(path2); + + HRESULT res = MyCreateProcess(command, param); + if (res == SZ_OK) + return; + ::MessageBoxW(_window, LangString(IDS_CANNOT_START_EDITOR, 0x03020282), L"7-Zip", MB_OK | MB_ICONSTOP); +} + +#ifndef _UNICODE +typedef BOOL (WINAPI * ShellExecuteExWP)(LPSHELLEXECUTEINFOW lpExecInfo); +#endif + +static HRESULT StartApplication(const UString &dir, const UString &path, HWND window, CProcess &process) +{ + UINT32 result; + #ifndef _UNICODE + if (g_IsNT) + { + SHELLEXECUTEINFOW execInfo; + execInfo.cbSize = sizeof(execInfo); + execInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT; + execInfo.hwnd = NULL; + execInfo.lpVerb = NULL; + execInfo.lpFile = path; + execInfo.lpParameters = NULL; + execInfo.lpDirectory = dir.IsEmpty() ? NULL : (LPCWSTR)dir; + execInfo.nShow = SW_SHOWNORMAL; + execInfo.hProcess = 0; + ShellExecuteExWP shellExecuteExW = (ShellExecuteExWP) + ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "ShellExecuteExW"); + if (shellExecuteExW == 0) + return 0; + shellExecuteExW(&execInfo); + result = (UINT32)(UINT_PTR)execInfo.hInstApp; + process.Attach(execInfo.hProcess); + } + else + #endif + { + 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; + const CSysString sysPath = GetSystemString(path); + const CSysString sysDir = GetSystemString(dir); + execInfo.lpFile = sysPath; + execInfo.lpParameters = NULL; + execInfo.lpDirectory = + #ifdef UNDER_CE + NULL + #else + sysDir.IsEmpty() ? NULL : (LPCTSTR)sysDir + #endif + ; + execInfo.nShow = SW_SHOWNORMAL; + execInfo.hProcess = 0; + ::ShellExecuteEx(&execInfo); + result = (UINT32)(UINT_PTR)execInfo.hInstApp; + process.Attach(execInfo.hProcess); + } + if (result <= 32) + { + switch(result) + { + case SE_ERR_NOASSOC: + ::MessageBoxW(window, + NError::MyFormatMessageW(::GetLastError()), + // L"There is no application associated with the given file name extension", + L"7-Zip", MB_OK | MB_ICONSTOP); + } + } + return S_OK; +} + +static void StartApplicationDontWait(const UString &dir, const UString &path, HWND window) +{ + CProcess process; + StartApplication(dir, path, window, process); +} + +void CPanel::EditItem(int index) +{ + if (!_parentFolders.IsEmpty()) + { + OpenItemInArchive(index, false, true, true); + return; + } + CProcess process; + StartEditApplication(GetItemFullPath(index), (HWND)*this, process); +} + +void CPanel::OpenFolderExternal(int index) +{ + UString fsPrefix = GetFsPath(); + UString name; + if (index == kParentIndex) + { + int pos = fsPrefix.ReverseFind(WCHAR_PATH_SEPARATOR); + if (pos >= 0 && pos == fsPrefix.Length() - 1) + { + UString s = fsPrefix.Left(pos); + pos = s.ReverseFind(WCHAR_PATH_SEPARATOR); + if (pos >= 0) + fsPrefix = s.Left(pos + 1); + } + name = fsPrefix; + } + else + name = fsPrefix + GetItemRelPath(index) + WCHAR_PATH_SEPARATOR; + StartApplicationDontWait(fsPrefix, name, (HWND)*this); +} + +void CPanel::OpenItem(int index, bool tryInternal, bool tryExternal) +{ + CDisableTimerProcessing disableTimerProcessing1(*this); + if (!_parentFolders.IsEmpty()) + { + OpenItemInArchive(index, tryInternal, tryExternal, false); + return; + } + UString name = GetItemRelPath(index); + if (IsNameVirus(name)) + { + MessageBoxErrorLang(IDS_VIRUS, 0x03020284); + return; + } + UString prefix = GetFsPath(); + UString fullPath = prefix + name; + if (tryInternal) + if (!tryExternal || !DoItemAlwaysStart(name)) + { + HRESULT res = OpenItemAsArchive(index); + if (res == S_OK || res == E_ABORT) + return; + if (res != S_FALSE) + { + MessageBoxError(res); + return; + } + } + if (tryExternal) + { + // SetCurrentDirectory opens HANDLE to folder!!! + // NDirectory::MySetCurrentDirectory(prefix); + StartApplicationDontWait(prefix, fullPath, (HWND)*this); + } +} + +class CThreadCopyFrom: public CProgressThreadVirt +{ + HRESULT ProcessVirt(); +public: + UString PathPrefix; + UString Name; + + CMyComPtr FolderOperations; + CMyComPtr UpdateCallback; + CUpdateCallback100Imp *UpdateCallbackSpec; +}; + +HRESULT CThreadCopyFrom::ProcessVirt() +{ + UStringVector fileNames; + CRecordVector fileNamePointers; + fileNames.Add(Name); + fileNamePointers.Add(fileNames[0]); + return FolderOperations->CopyFrom(PathPrefix, &fileNamePointers.Front(), fileNamePointers.Size(), UpdateCallback); +} + +HRESULT CPanel::OnOpenItemChanged(const UString &folderPath, const UString &itemName, + bool usePassword, const UString &password) +{ + CMyComPtr folderOperations; + if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) + { + MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + return E_FAIL; + } + + CThreadCopyFrom t; + t.UpdateCallbackSpec = new CUpdateCallback100Imp; + t.UpdateCallback = t.UpdateCallbackSpec; + t.UpdateCallbackSpec->ProgressDialog = &t.ProgressDialog; + t.Name = itemName; + t.PathPrefix = folderPath; + NName::NormalizeDirPathPrefix(t.PathPrefix); + t.FolderOperations = folderOperations; + t.UpdateCallbackSpec->Init(usePassword, password); + RINOK(t.Create(itemName, (HWND)*this)); + return t.Result; +} + +LRESULT CPanel::OnOpenItemChanged(LPARAM lParam) +{ + CTmpProcessInfo &tmpProcessInfo = *(CTmpProcessInfo *)lParam; + // LoadCurrentPath() + if (tmpProcessInfo.FullPathFolderPrefix != _currentFolderPrefix) + return 0; + + CSelectedState state; + SaveSelectedState(state); + + HRESULT result = OnOpenItemChanged(tmpProcessInfo.FolderPath, tmpProcessInfo.ItemName, + tmpProcessInfo.UsePassword, tmpProcessInfo.Password); + if (result != S_OK) + return 0; + RefreshListCtrl(state); + return 1; +} + +/* +class CTmpProcessInfoList +{ +public: + CObjectVector _items; +} g_TmpProcessInfoList; +*/ + +class CExitEventLauncher +{ +public: + NWindows::NSynchronization::CManualResetEvent _exitEvent; + CExitEventLauncher() + { + if (_exitEvent.Create(false) != S_OK) + throw 9387173; + }; + ~CExitEventLauncher() { _exitEvent.Set(); } +} g_ExitEventLauncher; + +static THREAD_FUNC_DECL MyThreadFunction(void *param) +{ + CMyAutoPtr tmpProcessInfoPtr((CTmpProcessInfo *)param); + const CTmpProcessInfo *tmpProcessInfo = tmpProcessInfoPtr.get(); + + HANDLE hProcess = tmpProcessInfo->ProcessHandle; + HANDLE events[2] = { g_ExitEventLauncher._exitEvent, hProcess}; + DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE); + ::CloseHandle(hProcess); + if (waitResult == WAIT_OBJECT_0 + 0) + return 0; + if (waitResult != WAIT_OBJECT_0 + 1) + return 1; + Sleep(200); + NFind::CFileInfoW newFileInfo; + if (newFileInfo.Find(tmpProcessInfo->FilePath)) + { + if (tmpProcessInfo->WasChanged(newFileInfo)) + { + UString message = MyFormatNew(IDS_WANT_UPDATE_MODIFIED_FILE, + 0x03020280, tmpProcessInfo->ItemName); + if (::MessageBoxW(g_HWND, message, L"7-Zip", MB_OKCANCEL | MB_ICONQUESTION) == IDOK) + { + if (SendMessage(tmpProcessInfo->Window, kOpenItemChanged, 0, (LONG_PTR)tmpProcessInfo) != 1) + { + ::MessageBoxW(g_HWND, MyFormatNew(IDS_CANNOT_UPDATE_FILE, + 0x03020281, tmpProcessInfo->FilePath), L"7-Zip", MB_OK | MB_ICONSTOP); + return 0; + } + } + } + } + tmpProcessInfo->DeleteDirAndFile(); + return 0; +} + +void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bool editMode) +{ + const UString name = GetItemName(index); + if (IsNameVirus(name)) + { + MessageBoxErrorLang(IDS_VIRUS, 0x03020284); + return; + } + + CMyComPtr folderOperations; + if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) + { + MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + return; + } + + bool tryAsArchive = tryInternal && (!tryExternal || !DoItemAlwaysStart(name)); + + UString fullVirtPath = _currentFolderPrefix + name; + + NFile::NDirectory::CTempDirectoryW tempDirectory; + tempDirectory.Create(kTempDirPrefix); + UString tempDir = tempDirectory.GetPath(); + UString tempDirNorm = tempDir; + NFile::NName::NormalizeDirPathPrefix(tempDirNorm); + + UString tempFilePath = tempDirNorm + GetCorrectFsPath(name); + + CTempFileInfo tempFileInfo; + tempFileInfo.ItemName = name; + tempFileInfo.FolderPath = tempDir; + tempFileInfo.FilePath = tempFilePath; + tempFileInfo.NeedDelete = true; + + if (tryAsArchive) + { + CMyComPtr getStream; + _folder.QueryInterface(IID_IInArchiveGetStream, &getStream); + if (getStream) + { + CMyComPtr subSeqStream; + getStream->GetStream(index, &subSeqStream); + if (subSeqStream) + { + CMyComPtr subStream; + subSeqStream.QueryInterface(IID_IInStream, &subStream); + if (subStream) + { + bool encrypted; + if (OpenItemAsArchive(subStream, tempFileInfo, fullVirtPath, UString(), encrypted) == S_OK) + { + tempDirectory.DisableDeleting(); + RefreshListCtrl(); + return; + } + } + } + } + } + + + CRecordVector indices; + indices.Add(index); + + UStringVector messages; + + bool usePassword = false; + UString password; + if (_parentFolders.Size() > 0) + { + const CFolderLink &fl = _parentFolders.Back(); + usePassword = fl.UsePassword; + password = fl.Password; + } + + HRESULT result = CopyTo(indices, tempDirNorm, false, true, &messages, usePassword, password); + + if (_parentFolders.Size() > 0) + { + CFolderLink &fl = _parentFolders.Back(); + fl.UsePassword = usePassword; + fl.Password = password; + } + + if (!messages.IsEmpty()) + return; + if (result != S_OK) + { + if (result != E_ABORT) + MessageBoxError(result); + return; + } + + + if (tryAsArchive) + { + bool encrypted; + if (OpenItemAsArchive(NULL, tempFileInfo, fullVirtPath, UString(), encrypted) == S_OK) + { + tempDirectory.DisableDeleting(); + RefreshListCtrl(); + return; + } + } + + CMyAutoPtr tmpProcessInfoPtr(new CTmpProcessInfo()); + CTmpProcessInfo *tmpProcessInfo = tmpProcessInfoPtr.get(); + tmpProcessInfo->FolderPath = tempDir; + tmpProcessInfo->FilePath = tempFilePath; + tmpProcessInfo->NeedDelete = true; + tmpProcessInfo->UsePassword = usePassword; + tmpProcessInfo->Password = password; + + if (!tmpProcessInfo->FileInfo.Find(tempFilePath)) + return; + + CTmpProcessInfoRelease tmpProcessInfoRelease(*tmpProcessInfo); + + if (!tryExternal) + return; + + CProcess process; + HRESULT res; + if (editMode) + res = StartEditApplication(tempFilePath, (HWND)*this, process); + else + res = StartApplication(tempDirNorm, tempFilePath, (HWND)*this, process); + + if ((HANDLE)process == 0) + return; + + tmpProcessInfo->Window = (HWND)(*this); + tmpProcessInfo->FullPathFolderPrefix = _currentFolderPrefix; + tmpProcessInfo->ItemName = name; + tmpProcessInfo->ProcessHandle = process.Detach(); + + NWindows::CThread thread; + if (thread.Create(MyThreadFunction, tmpProcessInfo) != S_OK) + throw 271824; + tempDirectory.DisableDeleting(); + tmpProcessInfoPtr.release(); + tmpProcessInfoRelease._needDelete = false; +} + +/* +static const UINT64 kTimeLimit = UINT64(10000000) * 3600 * 24; + +static bool CheckDeleteItem(UINT64 currentFileTime, UINT64 folderFileTime) +{ + return (currentFileTime - folderFileTime > kTimeLimit && + folderFileTime - currentFileTime > kTimeLimit); +} + +void DeleteOldTempFiles() +{ + UString tempPath; + if(!NFile::NDirectory::MyGetTempPath(tempPath)) + throw 1; + + UINT64 currentFileTime; + NTime::GetCurUtcFileTime(currentFileTime); + UString searchWildCard = tempPath + kTempDirPrefix + L"*.tmp"; + searchWildCard += WCHAR(NName::kAnyStringWildcard); + NFind::CEnumeratorW enumerator(searchWildCard); + NFind::CFileInfoW fileInfo; + while(enumerator.Next(fileInfo)) + { + if (!fileInfo.IsDir()) + continue; + const UINT64 &cTime = *(const UINT64 *)(&fileInfo.CTime); + if(CheckDeleteItem(cTime, currentFileTime)) + RemoveDirectoryWithSubItems(tempPath + fileInfo.Name); + } +} +*/ diff --git a/CPP/7zip/UI/FileManager/PanelItems.cpp b/CPP/7zip/UI/FileManager/PanelItems.cpp new file mode 100755 index 0000000..d301900 --- /dev/null +++ b/CPP/7zip/UI/FileManager/PanelItems.cpp @@ -0,0 +1,806 @@ +// PanelItems.cpp + +#include "StdAfx.h" + +#include "../../../../C/Sort.h" + +#include "Common/StringConvert.h" + +#include "Windows/Menu.h" +#include "Windows/PropVariant.h" +#include "Windows/PropVariantConversions.h" + +#include "../../PropID.h" + +#include "resource.h" + +#include "LangUtils.h" +#include "Panel.h" +#include "PropertyName.h" +#include "RootFolder.h" + +using namespace NWindows; + +static int GetColumnAlign(PROPID propID, VARTYPE varType) +{ + switch(propID) + { + case kpidCTime: + case kpidATime: + case kpidMTime: + return LVCFMT_LEFT; + } + switch(varType) + { + case VT_UI1: + case VT_I2: + case VT_UI2: + case VT_I4: + case VT_INT: + case VT_UI4: + case VT_UINT: + case VT_I8: + case VT_UI8: + case VT_BOOL: + return LVCFMT_RIGHT; + + case VT_EMPTY: + case VT_I1: + case VT_FILETIME: + case VT_BSTR: + return LVCFMT_LEFT; + + default: + return LVCFMT_CENTER; + } +} + +HRESULT CPanel::InitColumns() +{ + if (_needSaveInfo) + SaveListViewInfo(); + + _listView.DeleteAllItems(); + _selectedStatusVector.Clear(); + + ReadListViewInfo(); + + + PROPID sortID; + /* + if (_listViewInfo.SortIndex >= 0) + sortID = _listViewInfo.Columns[_listViewInfo.SortIndex].PropID; + */ + sortID = _listViewInfo.SortID; + + _ascending = _listViewInfo.Ascending; + + _properties.Clear(); + + _needSaveInfo = true; + + UInt32 numProperties; + _folder->GetNumberOfProperties(&numProperties); + int i; + for (i = 0; i < (int)numProperties; i++) + { + CMyComBSTR name; + PROPID propID; + VARTYPE varType; + + RINOK(_folder->GetPropertyInfo(i, &name, &propID, &varType)); + + if (propID == kpidIsDir) + continue; + + CItemProperty prop; + prop.Type = varType; + prop.ID = propID; + prop.Name = GetNameOfProperty(propID, name); + prop.Order = -1; + prop.IsVisible = true; + prop.Width = 100; + _properties.Add(prop); + } + // InitColumns2(sortID); + + for (;;) + if (!_listView.DeleteColumn(0)) + break; + + int order = 0; + for (i = 0; i < _listViewInfo.Columns.Size(); i++) + { + const CColumnInfo &columnInfo = _listViewInfo.Columns[i]; + int index = _properties.FindItemWithID(columnInfo.PropID); + if (index >= 0) + { + CItemProperty &item = _properties[index]; + item.IsVisible = columnInfo.IsVisible; + item.Width = columnInfo.Width; + if (columnInfo.IsVisible) + item.Order = order++; + continue; + } + } + for (i = 0; i < _properties.Size(); i++) + { + CItemProperty &item = _properties[i]; + if (item.Order < 0) + item.Order = order++; + } + + _visibleProperties.Clear(); + for (i = 0; i < _properties.Size(); i++) + { + const CItemProperty &prop = _properties[i]; + if (prop.IsVisible) + _visibleProperties.Add(prop); + } + + // _sortIndex = 0; + _sortID = kpidName; + /* + if (_listViewInfo.SortIndex >= 0) + { + int sortIndex = _properties.FindItemWithID(sortID); + if (sortIndex >= 0) + _sortIndex = sortIndex; + } + */ + _sortID = _listViewInfo.SortID; + + for (i = 0; i < _visibleProperties.Size(); i++) + { + InsertColumn(i); + } + return S_OK; +} + +void CPanel::InsertColumn(int index) +{ + const CItemProperty &prop = _visibleProperties[index]; + LV_COLUMNW column; + column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM | LVCF_ORDER; + column.cx = prop.Width; + column.fmt = GetColumnAlign(prop.ID, prop.Type); + column.iOrder = prop.Order; + column.iSubItem = index; + column.pszText = const_cast((const wchar_t *)prop.Name); + _listView.InsertColumn(index, &column); +} + +HRESULT CPanel::RefreshListCtrl() +{ + return RefreshListCtrl(UString(), -1, true, UStringVector()); +} + +int CALLBACK CompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData); + + +void CPanel::GetSelectedNames(UStringVector &selectedNames) +{ + selectedNames.Clear(); + + CRecordVector indices; + GetSelectedItemsIndices(indices); + selectedNames.Reserve(indices.Size()); + for (int i = 0; i < indices.Size(); i++) + selectedNames.Add(GetItemRelPath(indices[i])); + + /* + for (int i = 0; i < _listView.GetItemCount(); i++) + { + const int kSize = 1024; + WCHAR name[kSize + 1]; + LVITEMW item; + item.iItem = i; + item.pszText = name; + item.cchTextMax = kSize; + item.iSubItem = 0; + item.mask = LVIF_TEXT | LVIF_PARAM; + if (!_listView.GetItem(&item)) + continue; + int realIndex = GetRealIndex(item); + if (realIndex == kParentIndex) + continue; + if (_selectedStatusVector[realIndex]) + selectedNames.Add(item.pszText); + } + */ + selectedNames.Sort(); +} + +void CPanel::SaveSelectedState(CSelectedState &s) +{ + s.FocusedName.Empty(); + s.SelectedNames.Clear(); + s.FocusedItem = _listView.GetFocusedItem(); + { + if (s.FocusedItem >= 0) + { + int realIndex = GetRealItemIndex(s.FocusedItem); + if (realIndex != kParentIndex) + s.FocusedName = GetItemRelPath(realIndex); + /* + const int kSize = 1024; + WCHAR name[kSize + 1]; + LVITEMW item; + item.iItem = focusedItem; + item.pszText = name; + item.cchTextMax = kSize; + item.iSubItem = 0; + item.mask = LVIF_TEXT; + if (_listView.GetItem(&item)) + focusedName = item.pszText; + */ + } + } + GetSelectedNames(s.SelectedNames); +} + +HRESULT CPanel::RefreshListCtrl(const CSelectedState &s) +{ + bool selectFocused = s.SelectFocused; + if (_mySelectMode) + selectFocused = true; + return RefreshListCtrl(s.FocusedName, s.FocusedItem, selectFocused, s.SelectedNames); +} + +HRESULT CPanel::RefreshListCtrlSaveFocused() +{ + CSelectedState state; + SaveSelectedState(state); + return RefreshListCtrl(state); +} + +void CPanel::SetFocusedSelectedItem(int index, bool select) +{ + UINT state = LVIS_FOCUSED; + if (select) + state |= LVIS_SELECTED; + _listView.SetItemState(index, state, state); + if (!_mySelectMode && select) + { + int realIndex = GetRealItemIndex(index); + if (realIndex != kParentIndex) + _selectedStatusVector[realIndex] = true; + } +} + +HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool selectFocused, + const UStringVector &selectedNames) +{ + _dontShowMode = false; + LoadFullPathAndShow(); + // OutputDebugStringA("=======\n"); + // OutputDebugStringA("s1 \n"); + CDisableTimerProcessing timerProcessing(*this); + + if (focusedPos < 0) + focusedPos = 0; + + _listView.SetRedraw(false); + // m_RedrawEnabled = false; + + LVITEMW item; + ZeroMemory(&item, sizeof(item)); + + _listView.DeleteAllItems(); + _selectedStatusVector.Clear(); + // _realIndices.Clear(); + _startGroupSelect = 0; + + _selectionIsDefined = false; + + // m_Files.Clear(); + // _folder.Release(); + + if (!_folder) + { + // throw 1; + SetToRootFolder(); + } + + _headerToolBar.EnableButton(kParentFolderID, !IsRootFolder()); + + CMyComPtr folderSetFlatMode; + _folder.QueryInterface(IID_IFolderSetFlatMode, &folderSetFlatMode); + if (folderSetFlatMode) + folderSetFlatMode->SetFlatMode(BoolToInt(_flatMode)); + + RINOK(_folder->LoadItems()); + RINOK(InitColumns()); + + // OutputDebugString(TEXT("Start Dir\n")); + UInt32 numItems; + _folder->GetNumberOfItems(&numItems); + + bool showDots = _showDots && !IsRootFolder(); + + _listView.SetItemCount(numItems + (showDots ? 1 : 0)); + + _selectedStatusVector.Reserve(numItems); + int cursorIndex = -1; + + CMyComPtr folderGetSystemIconIndex; + if (!IsFSFolder() || _showRealFileIcons) + _folder.QueryInterface(IID_IFolderGetSystemIconIndex, &folderGetSystemIconIndex); + + if (showDots) + { + UString itemName = L".."; + item.iItem = _listView.GetItemCount(); + if (itemName.CompareNoCase(focusedName) == 0) + cursorIndex = item.iItem; + item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; + int subItem = 0; + item.iSubItem = subItem++; + item.lParam = kParentIndex; + item.pszText = const_cast((const wchar_t *)itemName); + UInt32 attrib = FILE_ATTRIBUTE_DIRECTORY; + item.iImage = _extToIconMap.GetIconIndex(attrib, itemName); + if (item.iImage < 0) + item.iImage = 0; + if (_listView.InsertItem(&item) == -1) + return E_FAIL; + } + + // OutputDebugStringA("S1\n"); + + for (UInt32 i = 0; i < numItems; i++) + { + UString itemName = GetItemName(i); + const UString relPath = GetItemRelPath(i); + if (relPath.CompareNoCase(focusedName) == 0) + cursorIndex = _listView.GetItemCount(); + bool selected = false; + if (selectedNames.FindInSorted(relPath) >= 0) + selected = true; + _selectedStatusVector.Add(selected); + + item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; + + if (!_mySelectMode) + if (selected) + { + item.mask |= LVIF_STATE; + item.state = LVIS_SELECTED; + } + + int subItem = 0; + item.iItem = _listView.GetItemCount(); + + item.iSubItem = subItem++; + item.lParam = i; + + UString correctedName; + if (itemName.Find(L" ") >= 0) + { + int pos = 0; + for (;;) + { + int posNew = itemName.Find(L" ", pos); + if (posNew < 0) + { + correctedName += itemName.Mid(pos); + break; + } + correctedName += itemName.Mid(pos, posNew - pos); + correctedName += L" ... "; + pos = posNew; + while (itemName[++pos] == ' '); + } + item.pszText = const_cast((const wchar_t *)correctedName); + } + else + item.pszText = const_cast((const wchar_t *)itemName); + + NCOM::CPropVariant prop; + RINOK(_folder->GetProperty(i, kpidAttrib, &prop)); + UInt32 attrib = 0; + if (prop.vt == VT_UI4) + attrib = prop.ulVal; + else if (IsItemFolder(i)) + attrib |= FILE_ATTRIBUTE_DIRECTORY; + + bool defined = false; + + if (folderGetSystemIconIndex) + { + folderGetSystemIconIndex->GetSystemIconIndex(i, &item.iImage); + defined = (item.iImage > 0); + } + if (!defined) + { + if (_currentFolderPrefix.IsEmpty()) + { + int iconIndexTemp; + GetRealIconIndex(itemName + WCHAR_PATH_SEPARATOR, attrib, iconIndexTemp); + item.iImage = iconIndexTemp; + } + else + { + item.iImage = _extToIconMap.GetIconIndex(attrib, itemName); + } + } + if (item.iImage < 0) + item.iImage = 0; + + if (_listView.InsertItem(&item) == -1) + return E_FAIL; // error + } + // OutputDebugStringA("End2\n"); + + if (_listView.GetItemCount() > 0 && cursorIndex >= 0) + SetFocusedSelectedItem(cursorIndex, selectFocused); + _listView.SortItems(CompareItems, (LPARAM)this); + if (cursorIndex < 0 && _listView.GetItemCount() > 0) + { + if (focusedPos >= _listView.GetItemCount()) + focusedPos = _listView.GetItemCount() - 1; + // we select item only in showDots mode. + SetFocusedSelectedItem(focusedPos, showDots); + } + // m_RedrawEnabled = true; + _listView.EnsureVisible(_listView.GetFocusedItem(), false); + _listView.SetRedraw(true); + _listView.InvalidateRect(NULL, true); + // OutputDebugStringA("End1\n"); + /* + _listView.UpdateWindow(); + */ + return S_OK; +} + +void CPanel::GetSelectedItemsIndices(CRecordVector &indices) const +{ + indices.Clear(); + /* + int itemIndex = -1; + while ((itemIndex = _listView.GetNextItem(itemIndex, LVNI_SELECTED)) != -1) + { + LPARAM param; + if (_listView.GetItemParam(itemIndex, param)) + indices.Add(param); + } + */ + for (int i = 0; i < _selectedStatusVector.Size(); i++) + if (_selectedStatusVector[i]) + indices.Add(i); + HeapSort(&indices.Front(), indices.Size()); +} + +void CPanel::GetOperatedItemIndices(CRecordVector &indices) const +{ + GetSelectedItemsIndices(indices); + if (!indices.IsEmpty()) + return; + if (_listView.GetSelectedCount() == 0) + return; + int focusedItem = _listView.GetFocusedItem(); + if (focusedItem >= 0) + { + if (_listView.GetItemState(focusedItem, LVIS_SELECTED) == LVIS_SELECTED) + { + int realIndex = GetRealItemIndex(focusedItem); + if (realIndex != kParentIndex) + indices.Add(realIndex); + } + } +} + +void CPanel::GetAllItemIndices(CRecordVector &indices) const +{ + indices.Clear(); + UInt32 numItems; + if (_folder->GetNumberOfItems(&numItems) == S_OK) + for (UInt32 i = 0; i < numItems; i++) + indices.Add(i); +} + +void CPanel::GetOperatedIndicesSmart(CRecordVector &indices) const +{ + GetOperatedItemIndices(indices); + if (indices.IsEmpty() || (indices.Size() == 1 && indices[0] == (UInt32)(Int32)-1)) + GetAllItemIndices(indices); +} + +/* +void CPanel::GetOperatedListViewIndices(CRecordVector &indices) const +{ + indices.Clear(); + int numItems = _listView.GetItemCount(); + for (int i = 0; i < numItems; i++) + { + int realIndex = GetRealItemIndex(i); + if (realIndex >= 0) + if (_selectedStatusVector[realIndex]) + indices.Add(i); + } + if (indices.IsEmpty()) + { + int focusedItem = _listView.GetFocusedItem(); + if (focusedItem >= 0) + indices.Add(focusedItem); + } +} +*/ + +void CPanel::EditItem() +{ + int focusedItem = _listView.GetFocusedItem(); + if (focusedItem < 0) + return; + int realIndex = GetRealItemIndex(focusedItem); + if (realIndex == kParentIndex) + return; + if (!IsItemFolder(realIndex)) + EditItem(realIndex); +} + +void CPanel::OpenFocusedItemAsInternal() +{ + int focusedItem = _listView.GetFocusedItem(); + if (focusedItem < 0) + return; + int realIndex = GetRealItemIndex(focusedItem); + if (IsItemFolder(realIndex)) + OpenFolder(realIndex); + else + OpenItem(realIndex, true, false); +} + +void CPanel::OpenSelectedItems(bool tryInternal) +{ + CRecordVector indices; + GetOperatedItemIndices(indices); + if (indices.Size() > 20) + { + MessageBoxErrorLang(IDS_TOO_MANY_ITEMS, 0x02000606); + return; + } + + int focusedItem = _listView.GetFocusedItem(); + if (focusedItem >= 0) + { + int realIndex = GetRealItemIndex(focusedItem); + if (realIndex == kParentIndex && (tryInternal || indices.Size() == 0) && + _listView.GetItemState(focusedItem, LVIS_SELECTED) == LVIS_SELECTED) + indices.Insert(0, realIndex); + } + + bool dirIsStarted = false; + for (int i = 0; i < indices.Size(); i++) + { + UInt32 index = indices[i]; + // CFileInfo &aFile = m_Files[index]; + if (IsItemFolder(index)) + { + if (!dirIsStarted) + { + if (tryInternal) + { + OpenFolder(index); + dirIsStarted = true; + break; + } + else + OpenFolderExternal(index); + } + } + else + OpenItem(index, (tryInternal && indices.Size() == 1), true); + } +} + +UString CPanel::GetItemName(int itemIndex) const +{ + if (itemIndex == kParentIndex) + return L".."; + NCOM::CPropVariant prop; + if (_folder->GetProperty(itemIndex, kpidName, &prop) != S_OK) + throw 2723400; + if (prop.vt != VT_BSTR) + throw 2723401; + return prop.bstrVal; +} + +UString CPanel::GetItemPrefix(int itemIndex) const +{ + if (itemIndex == kParentIndex) + return UString(); + NCOM::CPropVariant prop; + if (_folder->GetProperty(itemIndex, kpidPrefix, &prop) != S_OK) + throw 2723400; + UString prefix; + if (prop.vt == VT_BSTR) + prefix = prop.bstrVal; + return prefix; +} + +UString CPanel::GetItemRelPath(int itemIndex) const +{ + return GetItemPrefix(itemIndex) + GetItemName(itemIndex); +} + +UString CPanel::GetItemFullPath(int itemIndex) const +{ + return _currentFolderPrefix + GetItemRelPath(itemIndex); +} + +bool CPanel::IsItemFolder(int itemIndex) const +{ + if (itemIndex == kParentIndex) + return true; + NCOM::CPropVariant prop; + if (_folder->GetProperty(itemIndex, kpidIsDir, &prop) != S_OK) + throw 2723400; + if (prop.vt == VT_BOOL) + return VARIANT_BOOLToBool(prop.boolVal); + if (prop.vt == VT_EMPTY) + return false; + return false; +} + +UINT64 CPanel::GetItemSize(int itemIndex) const +{ + if (itemIndex == kParentIndex) + return 0; + NCOM::CPropVariant prop; + if (_folder->GetProperty(itemIndex, kpidSize, &prop) != S_OK) + throw 2723400; + if (prop.vt == VT_EMPTY) + return 0; + return ConvertPropVariantToUInt64(prop); +} + +void CPanel::ReadListViewInfo() +{ + _typeIDString = GetFolderTypeID(); + if (!_typeIDString.IsEmpty()) + ::ReadListViewInfo(_typeIDString, _listViewInfo); +} + +void CPanel::SaveListViewInfo() +{ + int i; + for (i = 0; i < _visibleProperties.Size(); i++) + { + CItemProperty &prop = _visibleProperties[i]; + LVCOLUMN winColumnInfo; + winColumnInfo.mask = LVCF_ORDER | LVCF_WIDTH; + if (!_listView.GetColumn(i, &winColumnInfo)) + throw 1; + prop.Order = winColumnInfo.iOrder; + prop.Width = winColumnInfo.cx; + } + + CListViewInfo viewInfo; + + // PROPID sortPropID = _properties[_sortIndex].ID; + PROPID sortPropID = _sortID; + + _visibleProperties.Sort(); + for (i = 0; i < _visibleProperties.Size(); i++) + { + const CItemProperty &prop = _visibleProperties[i]; + CColumnInfo columnInfo; + columnInfo.IsVisible = prop.IsVisible; + columnInfo.PropID = prop.ID; + columnInfo.Width = prop.Width; + viewInfo.Columns.Add(columnInfo); + } + for (i = 0; i < _properties.Size(); i++) + { + const CItemProperty &prop = _properties[i]; + if (!prop.IsVisible) + { + CColumnInfo columnInfo; + columnInfo.IsVisible = prop.IsVisible; + columnInfo.PropID = prop.ID; + columnInfo.Width = prop.Width; + viewInfo.Columns.Add(columnInfo); + } + } + + // viewInfo.SortIndex = viewInfo.FindColumnWithID(sortPropID); + viewInfo.SortID = sortPropID; + + viewInfo.Ascending = _ascending; + if (!_listViewInfo.IsEqual(viewInfo)) + { + ::SaveListViewInfo(_typeIDString, viewInfo); + _listViewInfo = viewInfo; + } +} + + +bool CPanel::OnRightClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActiveate, LRESULT &result) +{ + if (itemActiveate->hdr.hwndFrom == HWND(_listView)) + return false; + POINT point; + ::GetCursorPos(&point); + ShowColumnsContextMenu(point.x, point.y); + result = TRUE; + return true; +} + +void CPanel::ShowColumnsContextMenu(int x, int y) +{ + + CMenu menu; + CMenuDestroyer menuDestroyer(menu); + + menu.CreatePopup(); + + const int kCommandStart = 100; + for (int i = 0; i < _properties.Size(); i++) + { + const CItemProperty &prop = _properties[i]; + UINT flags = MF_STRING; + if (prop.IsVisible) + flags |= MF_CHECKED; + if (i == 0) + flags |= MF_GRAYED; + menu.AppendItem(flags, kCommandStart + i, prop.Name); + } + int menuResult = menu.Track(TPM_LEFTALIGN | TPM_RETURNCMD | TPM_NONOTIFY, x, y, _listView); + if (menuResult >= kCommandStart && menuResult <= kCommandStart + _properties.Size()) + { + int index = menuResult - kCommandStart; + CItemProperty &prop = _properties[index]; + prop.IsVisible = !prop.IsVisible; + + if (prop.IsVisible) + { + int prevVisibleSize = _visibleProperties.Size(); + prop.Order = prevVisibleSize; + _visibleProperties.Add(prop); + InsertColumn(prevVisibleSize); + } + else + { + int visibleIndex = _visibleProperties.FindItemWithID(prop.ID); + _visibleProperties.Delete(visibleIndex); + /* + if (_sortIndex == index) + { + _sortIndex = 0; + _ascending = true; + } + */ + if (_sortID == prop.ID) + { + _sortID = kpidName; + _ascending = true; + } + + _listView.DeleteColumn(visibleIndex); + } + } +} + +void CPanel::OnReload() +{ + HRESULT res = RefreshListCtrlSaveFocused(); + if (res != S_OK) + MessageBoxError(res); + OnRefreshStatusBar(); +} + +void CPanel::OnTimer() +{ + if (!_processTimer) + return; + CMyComPtr folderWasChanged; + if (_folder.QueryInterface(IID_IFolderWasChanged, &folderWasChanged) != S_OK) + return; + Int32 wasChanged; + if (folderWasChanged->WasChanged(&wasChanged) != S_OK) + return; + if (wasChanged == 0) + return; + OnReload(); +} diff --git a/CPP/7zip/UI/FileManager/PanelKey.cpp b/CPP/7zip/UI/FileManager/PanelKey.cpp new file mode 100755 index 0000000..834bee9 --- /dev/null +++ b/CPP/7zip/UI/FileManager/PanelKey.cpp @@ -0,0 +1,335 @@ +// PanelKey.cpp + +#include "StdAfx.h" + +#include "Panel.h" +#include "HelpUtils.h" + +#include "../../PropID.h" +#include "App.h" + +// static LPCWSTR kHelpTopic = L"FM/index.htm"; + +struct CVKeyPropIDPair +{ + WORD VKey; + PROPID PropID; +}; + +static CVKeyPropIDPair g_VKeyPropIDPairs[] = +{ + { VK_F3, kpidName }, + { VK_F4, kpidExtension }, + { VK_F5, kpidMTime }, + { VK_F6, kpidSize }, + { VK_F7, kpidNoProperty } +}; + +static int FindVKeyPropIDPair(WORD vKey) +{ + for (int i = 0; i < sizeof(g_VKeyPropIDPairs) / sizeof(g_VKeyPropIDPairs[0]); i++) + if (g_VKeyPropIDPairs[i].VKey == vKey) + return i; + return -1; +} + + +bool CPanel::OnKeyDown(LPNMLVKEYDOWN keyDownInfo, LRESULT &result) +{ + if (keyDownInfo->wVKey == VK_TAB && keyDownInfo->hdr.hwndFrom == _listView) + { + _panelCallback->OnTab(); + return false; + } + bool alt = (::GetKeyState(VK_MENU) & 0x8000) != 0; + bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0; + // bool leftCtrl = (::GetKeyState(VK_LCONTROL) & 0x8000) != 0; + bool rightCtrl = (::GetKeyState(VK_RCONTROL) & 0x8000) != 0; + bool shift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0; + result = 0; + + if (keyDownInfo->wVKey >= '0' && keyDownInfo->wVKey <= '9' && + (rightCtrl || alt)) + { + int index = keyDownInfo->wVKey - '0'; + if (shift) + { + SetBookmark(index); + return true; + } + else + { + OpenBookmark(index); + return true; + } + } + + if ((keyDownInfo->wVKey == VK_F2 || + keyDownInfo->wVKey == VK_F1) && alt && !ctrl && !shift) + { + _panelCallback->SetFocusToPath(keyDownInfo->wVKey == VK_F1 ? 0 : 1); + return true; + } + + if ((keyDownInfo->wVKey == VK_F9) && !alt && !ctrl && !shift) + { + g_App.SwitchOnOffOnePanel(); + } + + if(keyDownInfo->wVKey >= VK_F3 && keyDownInfo->wVKey <= VK_F12 && ctrl) + { + int index = FindVKeyPropIDPair(keyDownInfo->wVKey); + if (index >= 0) + SortItemsWithPropID(g_VKeyPropIDPairs[index].PropID); + } + + switch(keyDownInfo->wVKey) + { + case VK_SHIFT: + { + _selectionIsDefined = false; + _prevFocusedItem = _listView.GetFocusedItem(); + break; + } + /* + case VK_F1: + { + // ShowHelpWindow(NULL, kHelpTopic); + break; + } + */ + case VK_F2: + { + if (!alt && !ctrl &&!shift) + { + RenameFile(); + return true; + } + break; + } + case VK_F4: + { + if (!alt && !ctrl && !shift) + { + EditItem(); + return true; + } + if (!alt && !ctrl && shift) + { + CreateFile(); + return true; + } + break; + } + case VK_F5: + { + if (!alt && !ctrl) + { + _panelCallback->OnCopy(false, shift); + return true; + } + break; + } + case VK_F6: + { + if (!alt && !ctrl) + { + _panelCallback->OnCopy(true, shift); + return true; + } + break; + } + /* + case VK_F7: + { + if (!alt && !ctrl && !shift) + { + CreateFolder(); + return true; + } + break; + } + */ + case VK_DELETE: + { + DeleteItems(!shift); + return true; + } + case VK_INSERT: + { + if (!alt) + { + if (ctrl && !shift) + { + EditCopy(); + return true; + } + if (shift && !ctrl) + { + EditPaste(); + return true; + } + if (!shift && !ctrl && _mySelectMode) + { + OnInsert(); + return true; + } + } + return false; + } + case VK_DOWN: + { + if(shift) + OnArrowWithShift(); + return false; + } + case VK_UP: + { + if (alt) + _panelCallback->OnSetSameFolder(); + else if(shift) + OnArrowWithShift(); + return false; + } + case VK_RIGHT: + { + if (alt) + _panelCallback->OnSetSubFolder(); + else if(shift) + OnArrowWithShift(); + return false; + } + case VK_LEFT: + { + if (alt) + _panelCallback->OnSetSubFolder(); + else if(shift) + OnArrowWithShift(); + return false; + } + case VK_NEXT: + { + if (ctrl && !alt && !shift) + { + // EnterToFocused(); + return true; + } + break; + } + case VK_ADD: + { + if (alt) + SelectByType(true); + else if (shift) + SelectAll(true); + else if(!ctrl) + SelectSpec(true); + return true; + } + case VK_SUBTRACT: + { + if (alt) + SelectByType(false); + else if (shift) + SelectAll(false); + else + SelectSpec(false); + return true; + } + /* + case VK_DELETE: + CommandDelete(); + return 0; + case VK_F1: + CommandHelp(); + return 0; + */ + case VK_BACK: + OpenParentFolder(); + return true; + /* + case VK_DIVIDE: + case '\\': + case '/': + case VK_OEM_5: + { + // OpenRootFolder(); + OpenDrivesFolder(); + + return true; + } + */ + case 'A': + if(ctrl) + { + SelectAll(true); + return true; + } + return false; + case 'X': + if (ctrl) + { + EditCut(); + return true; + } + return false; + case 'C': + if (ctrl) + { + EditCopy(); + return true; + } + return false; + case 'V': + if (ctrl) + { + EditPaste(); + return true; + } + return false; + case 'N': + if (ctrl) + { + CreateFile(); + return true; + } + return false; + case 'R': + if(ctrl) + { + OnReload(); + return true; + } + return false; + case 'Z': + if(ctrl) + { + ChangeComment(); + return true; + } + return false; + case '1': + case '2': + case '3': + case '4': + if(ctrl) + { + int styleIndex = keyDownInfo->wVKey - '1'; + SetListViewMode(styleIndex); + return true; + } + return false; + case VK_MULTIPLY: + { + InvertSelection(); + return true; + } + case VK_F12: + if (alt && !ctrl && !shift) + { + FoldersHistory(); + return true; + } + } + return false; +} diff --git a/CPP/7zip/UI/FileManager/PanelListNotify.cpp b/CPP/7zip/UI/FileManager/PanelListNotify.cpp new file mode 100755 index 0000000..efc5f0d --- /dev/null +++ b/CPP/7zip/UI/FileManager/PanelListNotify.cpp @@ -0,0 +1,429 @@ +// PanelListNotify.cpp + +#include "StdAfx.h" + +#include "resource.h" + +#include "Common/IntToString.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/PropVariantConversions.h" + +#include "../Common/PropIDUtils.h" +#include "../../PropID.h" + +#include "Panel.h" +#include "FormatUtils.h" + +using namespace NWindows; + +/* +static UString ConvertSizeToStringShort(UInt64 value) +{ + wchar_t s[32]; + wchar_t c, c2 = L'B'; + if (value < (UInt64)10000) + { + c = L'B'; + c2 = L'\0'; + } + else if (value < ((UInt64)10000 << 10)) + { + value >>= 10; + c = L'K'; + } + else if (value < ((UInt64)10000 << 20)) + { + value >>= 20; + c = L'M'; + } + else + { + value >>= 30; + c = L'G'; + } + ConvertUInt64ToString(value, s); + int p = MyStringLen(s); + s[p++] = L' '; + s[p++] = c; + s[p++] = c2; + s[p++] = L'\0'; + return s; +} +*/ + +UString ConvertSizeToString(UInt64 value) +{ + wchar_t s[32]; + ConvertUInt64ToString(value, s); + int i = MyStringLen(s); + int pos = sizeof(s) / sizeof(s[0]); + s[--pos] = L'\0'; + while (i > 3) + { + s[--pos] = s[--i]; + s[--pos] = s[--i]; + s[--pos] = s[--i]; + s[--pos] = L' '; + } + while (i > 0) + s[--pos] = s[--i]; + return s + pos; +} + +LRESULT CPanel::SetItemText(LVITEMW &item) +{ + if (_dontShowMode) + return 0; + + UINT32 realIndex = GetRealIndex(item); + /* + if ((item.mask & LVIF_IMAGE) != 0) + { + bool defined = false; + CComPtr folderGetSystemIconIndex; + _folder.QueryInterface(&folderGetSystemIconIndex); + if (folderGetSystemIconIndex) + { + folderGetSystemIconIndex->GetSystemIconIndex(index, &item.iImage); + defined = (item.iImage > 0); + } + if (!defined) + { + NCOM::CPropVariant prop; + _folder->GetProperty(index, kpidAttrib, &prop); + UINT32 attrib = 0; + if (prop.vt == VT_UI4) + attrib = prop.ulVal; + else if (IsItemFolder(index)) + attrib |= FILE_ATTRIBUTE_DIRECTORY; + if (_currentFolderPrefix.IsEmpty()) + throw 1; + else + item.iImage = _extToIconMap.GetIconIndex(attrib, GetSystemString(GetItemName(index))); + } + // item.iImage = 1; + } + */ + + if ((item.mask & LVIF_TEXT) == 0) + return 0; + + if (realIndex == kParentIndex) + return 0; + UString s; + UINT32 subItemIndex = item.iSubItem; + PROPID propID = _visibleProperties[subItemIndex].ID; + /* + { + NCOM::CPropVariant property; + if (propID == kpidType) + string = GetFileType(index); + else + { + HRESULT result = m_ArchiveFolder->GetProperty(index, propID, &property); + if (result != S_OK) + { + // PrintMessage("GetPropertyValue error"); + return 0; + } + string = ConvertPropertyToString(property, propID, false); + } + } + */ + // const NFind::CFileInfo &aFileInfo = m_Files[index]; + + NCOM::CPropVariant prop; + /* + bool needRead = true; + if (propID == kpidSize) + { + CComPtr getItemFullSize; + if (_folder.QueryInterface(&getItemFullSize) == S_OK) + { + if (getItemFullSize->GetItemFullSize(index, &prop) == S_OK) + needRead = false; + } + } + if (needRead) + */ + + HRESULT res = _folder->GetProperty(realIndex, propID, &prop); + if (res != S_OK) + s = UString(L"Error: ") + HResultToMessage(res); + else + if ((prop.vt == VT_UI8 || prop.vt == VT_UI4) && ( + propID == kpidSize || + propID == kpidPackSize || + propID == kpidNumSubDirs || + propID == kpidNumSubFiles || + propID == kpidPosition || + propID == kpidNumBlocks || + propID == kpidClusterSize || + propID == kpidTotalSize || + propID == kpidFreeSpace + )) + s = ConvertSizeToString(ConvertPropVariantToUInt64(prop)); + else + { + s = ConvertPropertyToString(prop, propID, false); + s.Replace(wchar_t(0xA), L' '); + s.Replace(wchar_t(0xD), L' '); + } + int size = item.cchTextMax; + if (size > 0) + { + if (s.Length() + 1 > size) + s = s.Left(size - 1); + MyStringCopy(item.pszText, (const wchar_t *)s); + } + return 0; +} + +#ifndef UNDER_CE +extern DWORD g_ComCtl32Version; +#endif + +void CPanel::OnItemChanged(NMLISTVIEW *item) +{ + int index = (int)item->lParam; + if (index == kParentIndex) + return; + bool oldSelected = (item->uOldState & LVIS_SELECTED) != 0; + bool newSelected = (item->uNewState & LVIS_SELECTED) != 0; + // Don't change this code. It works only with such check + if (oldSelected != newSelected) + _selectedStatusVector[index] = newSelected; +} + +extern bool g_LVN_ITEMACTIVATE_Support; + +void CPanel::OnNotifyActivateItems() +{ + // bool leftCtrl = (::GetKeyState(VK_LCONTROL) & 0x8000) != 0; + // bool rightCtrl = (::GetKeyState(VK_RCONTROL) & 0x8000) != 0; + bool alt = (::GetKeyState(VK_MENU) & 0x8000) != 0; + bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0; + bool shift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0; + if (!shift && alt && !ctrl) + Properties(); + else + OpenSelectedItems(!shift || alt || ctrl); +} + +bool CPanel::OnNotifyList(LPNMHDR header, LRESULT &result) +{ + switch(header->code) + { + case LVN_ITEMCHANGED: + { + if (_enableItemChangeNotify) + { + if (!_mySelectMode) + OnItemChanged((LPNMLISTVIEW)header); + RefreshStatusBar(); + } + return false; + } + /* + + case LVN_ODSTATECHANGED: + { + break; + } + */ + + case LVN_GETDISPINFOW: + { + LV_DISPINFOW *dispInfo = (LV_DISPINFOW *)header; + + //is the sub-item information being requested? + + if ((dispInfo->item.mask & LVIF_TEXT) != 0 || + (dispInfo->item.mask & LVIF_IMAGE) != 0) + SetItemText(dispInfo->item); + return false; + } + case LVN_KEYDOWN: + { + bool boolResult = OnKeyDown(LPNMLVKEYDOWN(header), result); + RefreshStatusBar(); + return boolResult; + } + + case LVN_COLUMNCLICK: + OnColumnClick(LPNMLISTVIEW(header)); + return false; + + case LVN_ITEMACTIVATE: + if (g_LVN_ITEMACTIVATE_Support) + { + OnNotifyActivateItems(); + return false; + } + break; + case NM_DBLCLK: + case NM_RETURN: + if (!g_LVN_ITEMACTIVATE_Support) + { + OnNotifyActivateItems(); + return false; + } + break; + + case NM_RCLICK: + RefreshStatusBar(); + break; + + /* + return OnRightClick((LPNMITEMACTIVATE)header, result); + */ + /* + case NM_CLICK: + SendRefreshStatusBarMessage(); + return 0; + + // TODO : Handler default action... + return 0; + case LVN_ITEMCHANGED: + { + NMLISTVIEW *pNMLV = (NMLISTVIEW *) lpnmh; + SelChange(pNMLV); + return TRUE; + } + case NM_SETFOCUS: + return onSetFocus(NULL); + case NM_KILLFOCUS: + return onKillFocus(NULL); + */ + case NM_CLICK: + { + // we need SetFocusToList, if we drag-select items from other panel. + SetFocusToList(); + RefreshStatusBar(); + if (_mySelectMode) + #ifndef UNDER_CE + if (g_ComCtl32Version >= MAKELONG(71, 4)) + #endif + OnLeftClick((MY_NMLISTVIEW_NMITEMACTIVATE *)header); + return false; + } + case LVN_BEGINLABELEDITW: + result = OnBeginLabelEdit((LV_DISPINFOW *)header); + return true; + case LVN_ENDLABELEDITW: + result = OnEndLabelEdit((LV_DISPINFOW *)header); + return true; + + case NM_CUSTOMDRAW: + { + if (_mySelectMode) + return OnCustomDraw((LPNMLVCUSTOMDRAW)header, result); + break; + } + case LVN_BEGINDRAG: + { + OnDrag((LPNMLISTVIEW)header); + RefreshStatusBar(); + break; + } + // case LVN_BEGINRDRAG: + } + return false; +} + +bool CPanel::OnCustomDraw(LPNMLVCUSTOMDRAW lplvcd, LRESULT &result) +{ + switch(lplvcd->nmcd.dwDrawStage) + { + case CDDS_PREPAINT : + result = CDRF_NOTIFYITEMDRAW; + return true; + + case CDDS_ITEMPREPAINT: + /* + SelectObject(lplvcd->nmcd.hdc, + GetFontForItem(lplvcd->nmcd.dwItemSpec, + lplvcd->nmcd.lItemlParam) ); + lplvcd->clrText = GetColorForItem(lplvcd->nmcd.dwItemSpec, + lplvcd->nmcd.lItemlParam); + lplvcd->clrTextBk = GetBkColorForItem(lplvcd->nmcd.dwItemSpec, + lplvcd->nmcd.lItemlParam); + */ + int realIndex = (int)lplvcd->nmcd.lItemlParam; + bool selected = false; + if (realIndex != kParentIndex) + selected = _selectedStatusVector[realIndex]; + if (selected) + lplvcd->clrTextBk = RGB(255, 192, 192); + // lplvcd->clrText = RGB(255, 0, 128); + else + lplvcd->clrTextBk = _listView.GetBkColor(); + // lplvcd->clrText = RGB(0, 0, 0); + // result = CDRF_NEWFONT; + result = CDRF_NOTIFYITEMDRAW; + return true; + + // return false; + // return true; + /* + case CDDS_SUBITEM | CDDS_ITEMPREPAINT: + if (lplvcd->iSubItem == 0) + { + // lplvcd->clrText = RGB(255, 0, 0); + lplvcd->clrTextBk = RGB(192, 192, 192); + } + else + { + lplvcd->clrText = RGB(0, 0, 0); + lplvcd->clrTextBk = RGB(255, 255, 255); + } + return true; + */ + + /* At this point, you can change the background colors for the item + and any subitems and return CDRF_NEWFONT. If the list-view control + is in report mode, you can simply return CDRF_NOTIFYSUBITEMREDRAW + to customize the item's subitems individually */ + } + return false; +} + +void CPanel::OnRefreshStatusBar() +{ + CRecordVector indices; + GetOperatedItemIndices(indices); + + _statusBar.SetText(0, MyFormatNew(IDS_N_SELECTED_ITEMS, 0x02000301, NumberToString(indices.Size()))); + + UString selectSizeString; + + if (indices.Size() > 0) + { + UInt64 totalSize = 0; + for (int i = 0; i < indices.Size(); i++) + totalSize += GetItemSize(indices[i]); + selectSizeString = ConvertSizeToString(totalSize); + } + _statusBar.SetText(1, selectSizeString); + + int focusedItem = _listView.GetFocusedItem(); + UString sizeString; + UString dateString; + if (focusedItem >= 0 && _listView.GetSelectedCount() > 0) + { + int realIndex = GetRealItemIndex(focusedItem); + if (realIndex != kParentIndex) + { + sizeString = ConvertSizeToString(GetItemSize(realIndex)); + NCOM::CPropVariant prop; + if (_folder->GetProperty(realIndex, kpidMTime, &prop) == S_OK) + dateString = ConvertPropertyToString(prop, kpidMTime, false); + } + } + _statusBar.SetText(2, sizeString); + _statusBar.SetText(3, dateString); + // _statusBar.SetText(4, nameString); + // _statusBar2.SetText(1, MyFormatNew(L"{0} bytes", NumberToStringW(totalSize))); +} diff --git a/CPP/7zip/UI/FileManager/PanelMenu.cpp b/CPP/7zip/UI/FileManager/PanelMenu.cpp new file mode 100755 index 0000000..13a3ae1 --- /dev/null +++ b/CPP/7zip/UI/FileManager/PanelMenu.cpp @@ -0,0 +1,679 @@ +#include "StdAfx.h" + +#include "Common/StringConvert.h" + +#include "Windows/COM.h" +#include "Windows/Clipboard.h" +#include "Windows/Menu.h" +#include "Windows/PropVariant.h" +#include "Windows/PropVariantConversions.h" + +#include "../../PropID.h" +#include "../Common/PropIDUtils.h" +#include "../Explorer/ContextMenu.h" + +#include "App.h" +#include "LangUtils.h" +#include "MyLoadMenu.h" +#include "PropertyName.h" + +#include "resource.h" +#include "PropertyNameRes.h" + +using namespace NWindows; + +LONG g_DllRefCount = 0; + +static const UINT kSevenZipStartMenuID = kPluginMenuStartID ; +static const UINT kSystemStartMenuID = kPluginMenuStartID + 100; + +void CPanel::InvokeSystemCommand(const char *command) +{ + NCOM::CComInitializer comInitializer; + if (!IsFsOrPureDrivesFolder()) + return; + CRecordVector operatedIndices; + GetOperatedItemIndices(operatedIndices); + if (operatedIndices.IsEmpty()) + return; + CMyComPtr contextMenu; + if (CreateShellContextMenu(operatedIndices, contextMenu) != S_OK) + return; + + CMINVOKECOMMANDINFO ci; + ZeroMemory(&ci, sizeof(ci)); + ci.cbSize = sizeof(CMINVOKECOMMANDINFO); + ci.hwnd = GetParent(); + ci.lpVerb = command; + contextMenu->InvokeCommand(&ci); +} + +static const wchar_t *kSeparator = L"----------------------------\n"; +static const wchar_t *kSeparatorSmall = L"----\n"; +static const wchar_t *kPropValueSeparator = L": "; + +extern UString ConvertSizeToString(UInt64 value); + +static void AddPropertyString(PROPID propID, const wchar_t *nameBSTR, + const NCOM::CPropVariant &prop, UString &s) +{ + if (prop.vt != VT_EMPTY) + { + UString val; + + if ((prop.vt == VT_UI8 || prop.vt == VT_UI4) && ( + propID == kpidSize || + propID == kpidPackSize || + propID == kpidNumSubDirs || + propID == kpidNumSubFiles || + propID == kpidNumBlocks || + propID == kpidClusterSize || + propID == kpidTotalSize || + propID == kpidFreeSpace || + propID == kpidPhySize || + propID == kpidHeadersSize || + propID == kpidFreeSpace + )) + val = ConvertSizeToString(ConvertPropVariantToUInt64(prop)); + else + val = ConvertPropertyToString(prop, propID); + + if (!val.IsEmpty()) + { + s += GetNameOfProperty(propID, nameBSTR); + s += kPropValueSeparator; + /* + if (propID == kpidComment) + s += L'\n'; + */ + s += val; + s += L'\n'; + } + } +} + +void CPanel::Properties() +{ + CMyComPtr getFolderArcProps; + _folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps); + if (!getFolderArcProps) + { + InvokeSystemCommand("properties"); + return; + } + + { + UString message; + + CRecordVector operatedIndices; + GetOperatedItemIndices(operatedIndices); + if (operatedIndices.Size() == 1) + { + UInt32 index = operatedIndices[0]; + // message += L"Item:\n"; + UInt32 numProps; + if (_folder->GetNumberOfProperties(&numProps) == S_OK) + { + for (UInt32 i = 0; i < numProps; i++) + { + CMyComBSTR name; + PROPID propID; + VARTYPE varType; + + if (_folder->GetPropertyInfo(i, &name, &propID, &varType) != S_OK) + continue; + + NCOM::CPropVariant prop; + if (_folder->GetProperty(index, propID, &prop) != S_OK) + continue; + AddPropertyString(propID, name, prop, message); + } + } + message += kSeparator; + } + + /* + message += LangString(IDS_PROP_FILE_TYPE, 0x02000214); + message += kPropValueSeparator; + message += GetFolderTypeID(); + message += L"\n"; + */ + + { + NCOM::CPropVariant prop; + if (_folder->GetFolderProperty(kpidPath, &prop) == S_OK) + { + AddPropertyString(kpidName, L"Path", prop, message); + } + } + + CMyComPtr folderProperties; + _folder.QueryInterface(IID_IFolderProperties, &folderProperties); + if (folderProperties) + { + UInt32 numProps; + if (folderProperties->GetNumberOfFolderProperties(&numProps) == S_OK) + { + for (UInt32 i = 0; i < numProps; i++) + { + CMyComBSTR name; + PROPID propID; + VARTYPE vt; + if (folderProperties->GetFolderPropertyInfo(i, &name, &propID, &vt) != S_OK) + continue; + NCOM::CPropVariant prop; + if (_folder->GetFolderProperty(propID, &prop) != S_OK) + continue; + AddPropertyString(propID, name, prop, message); + } + } + } + + CMyComPtr getFolderArcProps; + _folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps); + if (getFolderArcProps) + { + CMyComPtr getProps; + getFolderArcProps->GetFolderArcProps(&getProps); + if (getProps) + { + UInt32 numLevels; + if (getProps->GetArcNumLevels(&numLevels) != S_OK) + numLevels = 0; + for (UInt32 level2 = 0; level2 < numLevels; level2++) + { + { + UInt32 level = numLevels - 1 - level2; + UInt32 numProps; + if (getProps->GetArcNumProps(level, &numProps) == S_OK) + { + message += kSeparator; + for (Int32 i = -3; i < (Int32)numProps; i++) + { + CMyComBSTR name; + PROPID propID; + VARTYPE vt; + switch (i) + { + case -3: propID = kpidPath; break; + case -2: propID = kpidType; break; + case -1: propID = kpidError; break; + default: + if (getProps->GetArcPropInfo(level, i, &name, &propID, &vt) != S_OK) + continue; + } + NCOM::CPropVariant prop; + if (getProps->GetArcProp(level, propID, &prop) != S_OK) + continue; + AddPropertyString(propID, name, prop, message); + } + } + } + if (level2 != numLevels - 1) + { + UInt32 level = numLevels - 1 - level2; + UInt32 numProps; + if (getProps->GetArcNumProps2(level, &numProps) == S_OK) + { + message += kSeparatorSmall; + for (Int32 i = 0; i < (Int32)numProps; i++) + { + CMyComBSTR name; + PROPID propID; + VARTYPE vt; + if (getProps->GetArcPropInfo2(level, i, &name, &propID, &vt) != S_OK) + continue; + NCOM::CPropVariant prop; + if (getProps->GetArcProp2(level, propID, &prop) != S_OK) + continue; + AddPropertyString(propID, name, prop, message); + } + } + } + } + } + } + ::MessageBoxW(*(this), message, LangString(IDS_PROPERTIES, 0x03020900), MB_OK); + } +} + +void CPanel::EditCut() +{ + // InvokeSystemCommand("cut"); +} + +void CPanel::EditCopy() +{ + /* + CMyComPtr getFolderArcProps; + _folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps); + if (!getFolderArcProps) + { + InvokeSystemCommand("copy"); + return; + } + */ + UString s; + CRecordVector indices; + GetSelectedItemsIndices(indices); + for (int i = 0; i < indices.Size(); i++) + { + if (i > 0) + s += L"\xD\n"; + s += GetItemName(indices[i]); + } + ClipboardSetText(_mainWindow, s); +} + +void CPanel::EditPaste() +{ + /* + UStringVector names; + ClipboardGetFileNames(names); + CopyFromNoAsk(names); + UString s; + for (int i = 0; i < names.Size(); i++) + { + s += L" "; + s += names[i]; + } + + MessageBoxW(0, s, L"", 0); + */ + + // InvokeSystemCommand("paste"); +} + +HRESULT CPanel::CreateShellContextMenu( + const CRecordVector &operatedIndices, + CMyComPtr &systemContextMenu) +{ + systemContextMenu.Release(); + UString folderPath = GetFsPath(); + + CMyComPtr desktopFolder; + RINOK(::SHGetDesktopFolder(&desktopFolder)); + if (!desktopFolder) + { + // ShowMessage("Failed to get Desktop folder."); + return E_FAIL; + } + + // Separate the file from the folder. + + + // Get a pidl for the folder the file + // is located in. + LPITEMIDLIST parentPidl; + DWORD eaten; + RINOK(desktopFolder->ParseDisplayName( + GetParent(), 0, (wchar_t *)(const wchar_t *)folderPath, + &eaten, &parentPidl, 0)); + + // Get an IShellFolder for the folder + // the file is located in. + CMyComPtr parentFolder; + RINOK(desktopFolder->BindToObject(parentPidl, + 0, IID_IShellFolder, (void**)&parentFolder)); + if (!parentFolder) + { + // ShowMessage("Invalid file name."); + return E_FAIL; + } + + // Get a pidl for the file itself. + CRecordVector pidls; + pidls.Reserve(operatedIndices.Size()); + for (int i = 0; i < operatedIndices.Size(); i++) + { + LPITEMIDLIST pidl; + UString fileName = GetItemRelPath(operatedIndices[i]); + if (IsFSDrivesFolder()) + fileName += WCHAR_PATH_SEPARATOR; + RINOK(parentFolder->ParseDisplayName(GetParent(), 0, + (wchar_t *)(const wchar_t *)fileName, &eaten, &pidl, 0)); + pidls.Add(pidl); + } + + ITEMIDLIST temp; + if (pidls.Size() == 0) + { + temp.mkid.cb = 0; + /* + LPITEMIDLIST pidl; + HRESULT result = parentFolder->ParseDisplayName(GetParent(), 0, + L"." WSTRING_PATH_SEPARATOR, &eaten, &pidl, 0); + if (result != NOERROR) + return; + */ + pidls.Add(&temp); + } + + // Get the IContextMenu for the file. + CMyComPtr cm; + RINOK( parentFolder->GetUIObjectOf(GetParent(), pidls.Size(), + (LPCITEMIDLIST *)&pidls.Front(), IID_IContextMenu, 0, (void**)&cm)); + if (!cm) + { + // ShowMessage("Unable to get context menu interface."); + return E_FAIL; + } + systemContextMenu = cm; + return S_OK; +} + +void CPanel::CreateSystemMenu(HMENU menuSpec, + const CRecordVector &operatedIndices, + CMyComPtr &systemContextMenu) +{ + systemContextMenu.Release(); + + CreateShellContextMenu(operatedIndices, systemContextMenu); + + if (systemContextMenu == 0) + return; + + // Set up a CMINVOKECOMMANDINFO structure. + CMINVOKECOMMANDINFO ci; + ZeroMemory(&ci, sizeof(ci)); + ci.cbSize = sizeof(CMINVOKECOMMANDINFO); + ci.hwnd = GetParent(); + + /* + if (Sender == GoBtn) + { + // Verbs that can be used are cut, paste, + // properties, delete, and so on. + String action; + if (CutRb->Checked) + action = "cut"; + else if (CopyRb->Checked) + action = "copy"; + else if (DeleteRb->Checked) + action = "delete"; + else if (PropertiesRb->Checked) + action = "properties"; + + ci.lpVerb = action.c_str(); + result = cm->InvokeCommand(&ci); + if (result) + ShowMessage( + "Error copying file to clipboard."); + + } + else + */ + { + // HMENU hMenu = CreatePopupMenu(); + CMenu popupMenu; + // CMenuDestroyer menuDestroyer(popupMenu); + if(!popupMenu.CreatePopup()) + throw 210503; + + HMENU hMenu = popupMenu; + + DWORD Flags = CMF_EXPLORE; + // Optionally the shell will show the extended + // context menu on some operating systems when + // the shift key is held down at the time the + // context menu is invoked. The following is + // commented out but you can uncommnent this + // line to show the extended context menu. + // Flags |= 0x00000080; + systemContextMenu->QueryContextMenu(hMenu, 0, kSystemStartMenuID, 0x7FFF, Flags); + + + { + CMenu menu; + menu.Attach(menuSpec); + CMenuItem menuItem; + menuItem.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID; + menuItem.fType = MFT_STRING; + menuItem.hSubMenu = popupMenu.Detach(); + // menuDestroyer.Disable(); + menuItem.StringValue = LangString(IDS_SYSTEM, 0x030202A0); + menu.InsertItem(0, true, menuItem); + } + /* + if (Cmd < 100 && Cmd != 0) + { + ci.lpVerb = MAKEINTRESOURCE(Cmd - 1); + ci.lpParameters = ""; + ci.lpDirectory = ""; + ci.nShow = SW_SHOWNORMAL; + cm->InvokeCommand(&ci); + } + // If Cmd is > 100 then it's one of our + // inserted menu items. + else + // Find the menu item. + for (int i = 0; i < popupMenu1->Items->Count; i++) + { + TMenuItem* menu = popupMenu1->Items->Items[i]; + // Call its OnClick handler. + if (menu->Command == Cmd - 100) + menu->OnClick(this); + } + // Release the memory allocated for the menu. + DestroyMenu(hMenu); + */ + } +} + +void CPanel::CreateFileMenu(HMENU menuSpec) +{ + CreateFileMenu(menuSpec, _sevenZipContextMenu, _systemContextMenu, true); +} + +void CPanel::CreateSevenZipMenu(HMENU menuSpec, + const CRecordVector &operatedIndices, + CMyComPtr &sevenZipContextMenu) +{ + sevenZipContextMenu.Release(); + + CMenu menu; + menu.Attach(menuSpec); + // CMenuDestroyer menuDestroyer(menu); + // menu.CreatePopup(); + + bool sevenZipMenuCreated = false; + + CZipContextMenu *contextMenuSpec = new CZipContextMenu; + CMyComPtr contextMenu = contextMenuSpec; + // if (contextMenu.CoCreateInstance(CLSID_CZipContextMenu, IID_IContextMenu) == S_OK) + { + /* + CMyComPtr initContextMenu; + if (contextMenu.QueryInterface(IID_IInitContextMenu, &initContextMenu) != S_OK) + return; + */ + UString currentFolderUnicode = _currentFolderPrefix; + UStringVector names; + int i; + for(i = 0; i < operatedIndices.Size(); i++) + names.Add(currentFolderUnicode + GetItemRelPath(operatedIndices[i])); + CRecordVector namePointers; + for(i = 0; i < operatedIndices.Size(); i++) + namePointers.Add(names[i]); + + // NFile::NDirectory::MySetCurrentDirectory(currentFolderUnicode); + if (contextMenuSpec->InitContextMenu(currentFolderUnicode, &namePointers.Front(), + operatedIndices.Size()) == S_OK) + { + HRESULT res = contextMenu->QueryContextMenu(menu, 0, kSevenZipStartMenuID, + kSystemStartMenuID - 1, 0); + sevenZipMenuCreated = (HRESULT_SEVERITY(res) == SEVERITY_SUCCESS); + if (sevenZipMenuCreated) + sevenZipContextMenu = contextMenu; + // int code = HRESULT_CODE(res); + // int nextItemID = code; + } + } +} + +void CPanel::CreateFileMenu(HMENU menuSpec, + CMyComPtr &sevenZipContextMenu, + CMyComPtr &systemContextMenu, + bool programMenu) +{ + sevenZipContextMenu.Release(); + systemContextMenu.Release(); + + CRecordVector operatedIndices; + GetOperatedItemIndices(operatedIndices); + + CMenu menu; + menu.Attach(menuSpec); + + CreateSevenZipMenu(menu, operatedIndices, sevenZipContextMenu); + if (g_App.ShowSystemMenu) + CreateSystemMenu(menu, operatedIndices, systemContextMenu); + + /* + if (menu.GetItemCount() > 0) + menu.AppendItem(MF_SEPARATOR, 0, (LPCTSTR)0); + */ + + int i; + for (i = 0; i < operatedIndices.Size(); i++) + if (IsItemFolder(operatedIndices[i])) + break; + bool allAreFiles = (i == operatedIndices.Size()); + LoadFileMenu(menu, menu.GetItemCount(), programMenu, + IsFSFolder(), operatedIndices.Size(), allAreFiles); +} + +bool CPanel::InvokePluginCommand(int id) +{ + return InvokePluginCommand(id, _sevenZipContextMenu, _systemContextMenu); +} + +bool CPanel::InvokePluginCommand(int id, + IContextMenu *sevenZipContextMenu, IContextMenu *systemContextMenu) +{ + UInt32 offset; + bool isSystemMenu = (id >= kSystemStartMenuID); + if (isSystemMenu) + offset = id - kSystemStartMenuID; + else + offset = id - kSevenZipStartMenuID; + + #ifdef UNDER_CE + CMINVOKECOMMANDINFO + #else + CMINVOKECOMMANDINFOEX + #endif + commandInfo; + commandInfo.cbSize = sizeof(commandInfo); + commandInfo.fMask = 0 + #ifndef UNDER_CE + | CMIC_MASK_UNICODE + #endif + ; + commandInfo.hwnd = GetParent(); + commandInfo.lpVerb = (LPCSTR)(MAKEINTRESOURCE(offset)); + commandInfo.lpParameters = NULL; + CSysString currentFolderSys = GetSystemString(_currentFolderPrefix); + commandInfo.lpDirectory = (LPCSTR)(LPCTSTR)(currentFolderSys); + commandInfo.nShow = SW_SHOW; + commandInfo.lpParameters = NULL; + #ifndef UNDER_CE + commandInfo.lpTitle = ""; + commandInfo.lpVerbW = (LPCWSTR)(MAKEINTRESOURCEW(offset)); + UString currentFolderUnicode = _currentFolderPrefix; + commandInfo.lpDirectoryW = currentFolderUnicode; + commandInfo.lpTitleW = L""; + // commandInfo.ptInvoke.x = xPos; + // commandInfo.ptInvoke.y = yPos; + commandInfo.ptInvoke.x = 0; + commandInfo.ptInvoke.y = 0; + #endif + HRESULT result; + if (isSystemMenu) + result = systemContextMenu->InvokeCommand(LPCMINVOKECOMMANDINFO(&commandInfo)); + else + result = sevenZipContextMenu->InvokeCommand(LPCMINVOKECOMMANDINFO(&commandInfo)); + if (result == NOERROR) + { + KillSelection(); + return true; + } + return false; +} + +bool CPanel::OnContextMenu(HANDLE windowHandle, int xPos, int yPos) +{ + if (::GetParent((HWND)windowHandle) == _listView) + { + ShowColumnsContextMenu(xPos, yPos); + return true; + } + + if (windowHandle != _listView) + return false; + /* + POINT point; + point.x = xPos; + point.y = yPos; + if (!_listView.ScreenToClient(&point)) + return false; + + LVHITTESTINFO info; + info.pt = point; + int index = _listView.HitTest(&info); + */ + + CRecordVector operatedIndices; + GetOperatedItemIndices(operatedIndices); + + if (xPos < 0 || yPos < 0) + { + if (operatedIndices.Size() == 0) + { + xPos = 0; + yPos = 0; + } + else + { + int itemIndex = _listView.GetNextItem(-1, LVNI_FOCUSED); + if (itemIndex == -1) + return false; + RECT rect; + if (!_listView.GetItemRect(itemIndex, &rect, LVIR_ICON)) + return false; + xPos = (rect.left + rect.right) / 2; + yPos = (rect.top + rect.bottom) / 2; + } + POINT point = {xPos, yPos}; + _listView.ClientToScreen(&point); + xPos = point.x; + yPos = point.y; + } + + CMenu menu; + CMenuDestroyer menuDestroyer(menu); + menu.CreatePopup(); + + CMyComPtr sevenZipContextMenu; + CMyComPtr systemContextMenu; + CreateFileMenu(menu, sevenZipContextMenu, systemContextMenu, false); + + int result = menu.Track(TPM_LEFTALIGN + #ifndef UNDER_CE + | TPM_RIGHTBUTTON + #endif + | TPM_RETURNCMD | TPM_NONOTIFY, + xPos, yPos, _listView); + + if (result == 0) + return true; + + if (result >= kPluginMenuStartID) + { + InvokePluginCommand(result, sevenZipContextMenu, systemContextMenu); + return true; + } + if (ExecuteFileCommand(result)) + return true; + return true; +} diff --git a/CPP/7zip/UI/FileManager/PanelOperations.cpp b/CPP/7zip/UI/FileManager/PanelOperations.cpp new file mode 100755 index 0000000..864f952 --- /dev/null +++ b/CPP/7zip/UI/FileManager/PanelOperations.cpp @@ -0,0 +1,465 @@ +// PanelOperations.cpp + +#include "StdAfx.h" + +#include "Common/DynamicBuffer.h" +#include "Common/StringConvert.h" + +#include "Windows/COM.h" +#include "Windows/FileDir.h" +#include "Windows/PropVariant.h" +#include "Windows/ResourceString.h" +#include "Windows/Thread.h" + +#include "ComboDialog.h" + +#include "FSFolder.h" +#include "FormatUtils.h" +#include "LangUtils.h" +#include "Panel.h" +#include "UpdateCallback100.h" + +#include "resource.h" + +using namespace NWindows; +using namespace NFile; + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +enum EFolderOpType +{ + FOLDER_TYPE_CREATE_FOLDER = 0, + FOLDER_TYPE_DELETE = 1, + FOLDER_TYPE_RENAME = 2 +}; + +class CThreadFolderOperations: public CProgressThreadVirt +{ + HRESULT ProcessVirt(); +public: + EFolderOpType OpType; + UString Name; + UInt32 Index; + CRecordVector Indices; + + CMyComPtr FolderOperations; + CMyComPtr UpdateCallback; + CUpdateCallback100Imp *UpdateCallbackSpec; + + HRESULT Result; + + CThreadFolderOperations(EFolderOpType opType): OpType(opType), Result(E_FAIL) {} + HRESULT DoOperation(CPanel &panel, const UString &progressTitle, const UString &titleError); +}; + +HRESULT CThreadFolderOperations::ProcessVirt() +{ + NCOM::CComInitializer comInitializer; + switch(OpType) + { + case FOLDER_TYPE_CREATE_FOLDER: + Result = FolderOperations->CreateFolder(Name, UpdateCallback); + break; + case FOLDER_TYPE_DELETE: + Result = FolderOperations->Delete(&Indices.Front(), Indices.Size(), UpdateCallback); + break; + case FOLDER_TYPE_RENAME: + Result = FolderOperations->Rename(Index, Name, UpdateCallback); + break; + default: + Result = E_FAIL; + } + return Result; +} + + +HRESULT CThreadFolderOperations::DoOperation(CPanel &panel, const UString &progressTitle, const UString &titleError) +{ + UpdateCallbackSpec = new CUpdateCallback100Imp; + UpdateCallback = UpdateCallbackSpec; + UpdateCallbackSpec->ProgressDialog = &ProgressDialog; + + ProgressDialog.WaitMode = true; + ProgressDialog.Sync.SetErrorMessageTitle(titleError); + Result = S_OK; + + bool usePassword = false; + UString password; + if (panel._parentFolders.Size() > 0) + { + const CFolderLink &fl = panel._parentFolders.Back(); + usePassword = fl.UsePassword; + password = fl.Password; + } + + UpdateCallbackSpec->Init(usePassword, password); + + ProgressDialog.MainWindow = panel._mainWindow; // panel.GetParent() + ProgressDialog.MainTitle = LangString(IDS_APP_TITLE, 0x03000000); + ProgressDialog.MainAddTitle = progressTitle + UString(L" "); + + RINOK(Create(progressTitle, ProgressDialog.MainWindow)); + return Result; +} + +#ifndef _UNICODE +typedef int (WINAPI * SHFileOperationWP)(LPSHFILEOPSTRUCTW lpFileOp); +#endif + +void CPanel::DeleteItems(bool toRecycleBin) +{ + CPanel::CDisableTimerProcessing disableTimerProcessing2(*this); + CRecordVector indices; + GetOperatedItemIndices(indices); + if (indices.IsEmpty()) + return; + CSelectedState state; + SaveSelectedState(state); + + #ifndef UNDER_CE + // WM6 / SHFileOperationW doesn't ask user! So we use internal delete + bool useInternalDelete = false; + if (IsFSFolder() && toRecycleBin) + { + #ifndef _UNICODE + if (!g_IsNT) + { + CDynamicBuffer buffer; + size_t size = 0; + for (int i = 0; i < indices.Size(); i++) + { + const AString path = GetSystemString(GetFsPath() + GetItemRelPath(indices[i])); + buffer.EnsureCapacity(size + path.Length() + 1); + memmove(((CHAR *)buffer) + size, (const CHAR *)path, (path.Length() + 1) * sizeof(CHAR)); + size += path.Length() + 1; + } + buffer.EnsureCapacity(size + 1); + ((CHAR *)buffer)[size] = 0; + SHFILEOPSTRUCTA fo; + fo.hwnd = GetParent(); + fo.wFunc = FO_DELETE; + fo.pFrom = (const CHAR *)buffer; + fo.pTo = 0; + fo.fFlags = 0; + if (toRecycleBin) + fo.fFlags |= FOF_ALLOWUNDO; + // fo.fFlags |= FOF_NOCONFIRMATION; + // fo.fFlags |= FOF_NOERRORUI; + // fo.fFlags |= FOF_SILENT; + // fo.fFlags |= FOF_WANTNUKEWARNING; + fo.fAnyOperationsAborted = FALSE; + fo.hNameMappings = 0; + fo.lpszProgressTitle = 0; + /* int res = */ ::SHFileOperationA(&fo); + } + else + #endif + { + CDynamicBuffer buffer; + size_t size = 0; + int maxLen = 0; + for (int i = 0; i < indices.Size(); i++) + { + // L"\\\\?\\") doesn't work here. + const UString path = GetFsPath() + GetItemRelPath(indices[i]); + if (path.Length() > maxLen) + maxLen = path.Length(); + buffer.EnsureCapacity(size + path.Length() + 1); + memmove(((WCHAR *)buffer) + size, (const WCHAR *)path, (path.Length() + 1) * sizeof(WCHAR)); + size += path.Length() + 1; + } + buffer.EnsureCapacity(size + 1); + ((WCHAR *)buffer)[size] = 0; + if (maxLen >= MAX_PATH) + { + if (toRecycleBin) + { + MessageBoxErrorLang(IDS_ERROR_LONG_PATH_TO_RECYCLE, 0x03020218); + return; + } + useInternalDelete = true; + } + else + { + SHFILEOPSTRUCTW fo; + fo.hwnd = GetParent(); + fo.wFunc = FO_DELETE; + fo.pFrom = (const WCHAR *)buffer; + fo.pTo = 0; + fo.fFlags = 0; + if (toRecycleBin) + fo.fFlags |= FOF_ALLOWUNDO; + fo.fAnyOperationsAborted = FALSE; + fo.hNameMappings = 0; + fo.lpszProgressTitle = 0; + int res; + #ifdef _UNICODE + res = ::SHFileOperationW(&fo); + #else + SHFileOperationWP shFileOperationW = (SHFileOperationWP) + ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHFileOperationW"); + if (shFileOperationW == 0) + return; + res = shFileOperationW(&fo); + #endif + } + } + /* + if (fo.fAnyOperationsAborted) + MessageBoxError(result, LangString(IDS_ERROR_DELETING, 0x03020217)); + */ + } + else + useInternalDelete = true; + if (useInternalDelete) + #endif + DeleteItemsInternal(indices); + RefreshListCtrl(state); +} + +void CPanel::MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID, UInt32 langID) +{ + if (errorCode == E_NOINTERFACE) + MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + else + MessageBoxError(errorCode, LangString(resourceID, langID)); +} + +void CPanel::DeleteItemsInternal(CRecordVector &indices) +{ + CMyComPtr folderOperations; + if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) + { + MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_ERROR_DELETING, 0x03020217); + return; + } + + UString title; + UString message; + if (indices.Size() == 1) + { + int index = indices[0]; + const UString itemName = GetItemRelPath(index); + if (IsItemFolder(index)) + { + title = LangString(IDS_CONFIRM_FOLDER_DELETE, 0x03020211); + message = MyFormatNew(IDS_WANT_TO_DELETE_FOLDER, 0x03020214, itemName); + } + else + { + title = LangString(IDS_CONFIRM_FILE_DELETE, 0x03020210); + message = MyFormatNew(IDS_WANT_TO_DELETE_FILE, 0x03020213, itemName); + } + } + else + { + title = LangString(IDS_CONFIRM_ITEMS_DELETE, 0x03020212); + message = MyFormatNew(IDS_WANT_TO_DELETE_ITEMS, 0x03020215, + NumberToString(indices.Size())); + } + if (::MessageBoxW(GetParent(), message, title, MB_OKCANCEL | MB_ICONQUESTION) != IDOK) + return; + + { + CThreadFolderOperations op(FOLDER_TYPE_DELETE); + op.FolderOperations = folderOperations; + op.Indices = indices; + op.DoOperation(*this, + LangString(IDS_DELETING, 0x03020216), + LangString(IDS_ERROR_DELETING, 0x03020217)); + } + RefreshTitleAlways(); +} + +BOOL CPanel::OnBeginLabelEdit(LV_DISPINFOW * lpnmh) +{ + int realIndex = GetRealIndex(lpnmh->item); + if (realIndex == kParentIndex) + return TRUE; + CMyComPtr folderOperations; + if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) + return TRUE; + return FALSE; +} + +BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh) +{ + if (lpnmh->item.pszText == NULL) + return FALSE; + CMyComPtr folderOperations; + if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) + { + MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_ERROR_RENAMING, 0x03020221); + return FALSE; + } + const UString newName = lpnmh->item.pszText; + CPanel::CDisableTimerProcessing disableTimerProcessing2(*this); + + SaveSelectedState(_selectedState); + + int realIndex = GetRealIndex(lpnmh->item); + if (realIndex == kParentIndex) + return FALSE; + const UString prefix = GetItemPrefix(realIndex); + + + { + CThreadFolderOperations op(FOLDER_TYPE_RENAME); + op.FolderOperations = folderOperations; + op.Index = realIndex; + op.Name = newName; + HRESULT res = op.DoOperation(*this, + LangString(IDS_RENAMING, 0x03020220), + LangString(IDS_ERROR_RENAMING, 0x03020221)); + if (res != S_OK) + return FALSE; + } + + // Can't use RefreshListCtrl here. + // RefreshListCtrlSaveFocused(); + _selectedState.FocusedName = prefix + newName; + _selectedState.SelectFocused = true; + + // We need clear all items to disable GetText before Reload: + // number of items can change. + // _listView.DeleteAllItems(); + // But seems it can still call GetText (maybe for current item) + // so we can't delete items. + + _dontShowMode = true; + + PostMessage(kReLoadMessage); + return TRUE; +} + +void CPanel::CreateFolder() +{ + CMyComPtr folderOperations; + if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) + { + MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_CREATE_FOLDER_ERROR, 0x03020233); + return; + } + CPanel::CDisableTimerProcessing disableTimerProcessing2(*this); + CSelectedState state; + SaveSelectedState(state); + CComboDialog comboDialog; + comboDialog.Title = LangString(IDS_CREATE_FOLDER, 0x03020230); + comboDialog.Static = LangString(IDS_CREATE_FOLDER_NAME, 0x03020231); + comboDialog.Value = LangString(IDS_CREATE_FOLDER_DEFAULT_NAME, /*0x03020232*/ (UInt32)-1); + if (comboDialog.Create(GetParent()) == IDCANCEL) + return; + + UString newName = comboDialog.Value; + + { + CThreadFolderOperations op(FOLDER_TYPE_CREATE_FOLDER); + op.FolderOperations = folderOperations; + op.Name = newName; + HRESULT res = op.DoOperation(*this, + LangString(IDS_CREATE_FOLDER, 0x03020230), + LangString(IDS_CREATE_FOLDER_ERROR, 0x03020233)); + if (res != S_OK) + return; + } + int pos = newName.Find(WCHAR_PATH_SEPARATOR); + if (pos >= 0) + newName = newName.Left(pos); + if (!_mySelectMode) + state.SelectedNames.Clear(); + state.FocusedName = newName; + state.SelectFocused = true; + RefreshTitleAlways(); + RefreshListCtrl(state); +} + +void CPanel::CreateFile() +{ + CMyComPtr folderOperations; + if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) + { + MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_CREATE_FILE_ERROR, 0x03020243); + return; + } + CPanel::CDisableTimerProcessing disableTimerProcessing2(*this); + CSelectedState state; + SaveSelectedState(state); + CComboDialog comboDialog; + comboDialog.Title = LangString(IDS_CREATE_FILE, 0x03020240); + comboDialog.Static = LangString(IDS_CREATE_FILE_NAME, 0x03020241); + comboDialog.Value = LangString(IDS_CREATE_FILE_DEFAULT_NAME, /*0x03020242*/ (UInt32)-1); + if (comboDialog.Create(GetParent()) == IDCANCEL) + return; + UString newName = comboDialog.Value; + HRESULT result = folderOperations->CreateFile(newName, 0); + if (result != S_OK) + { + MessageBoxErrorForUpdate(result, IDS_CREATE_FILE_ERROR, 0x03020243); + return; + } + int pos = newName.Find(WCHAR_PATH_SEPARATOR); + if (pos >= 0) + newName = newName.Left(pos); + if (!_mySelectMode) + state.SelectedNames.Clear(); + state.FocusedName = newName; + state.SelectFocused = true; + RefreshListCtrl(state); +} + +void CPanel::RenameFile() +{ + int index = _listView.GetFocusedItem(); + if (index >= 0) + _listView.EditLabel(index); +} + +void CPanel::ChangeComment() +{ + CPanel::CDisableTimerProcessing disableTimerProcessing2(*this); + int index = _listView.GetFocusedItem(); + if (index < 0) + return; + int realIndex = GetRealItemIndex(index); + if (realIndex == kParentIndex) + return; + CSelectedState state; + SaveSelectedState(state); + CMyComPtr folderOperations; + if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) + { + MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + return; + } + + UString comment; + { + NCOM::CPropVariant propVariant; + if (_folder->GetProperty(realIndex, kpidComment, &propVariant) != S_OK) + return; + if (propVariant.vt == VT_BSTR) + comment = propVariant.bstrVal; + else if (propVariant.vt != VT_EMPTY) + return; + } + UString name = GetItemRelPath(realIndex); + CComboDialog comboDialog; + comboDialog.Title = name + L" " + LangString(IDS_COMMENT, 0x03020290); + comboDialog.Value = comment; + comboDialog.Static = LangString(IDS_COMMENT2, 0x03020291); + if (comboDialog.Create(GetParent()) == IDCANCEL) + return; + NCOM::CPropVariant propVariant = comboDialog.Value; + + HRESULT result = folderOperations->SetProperty(realIndex, kpidComment, &propVariant, NULL); + if (result != S_OK) + { + if (result == E_NOINTERFACE) + MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + else + MessageBoxError(result, L"Set Comment Error"); + } + RefreshListCtrl(state); +} diff --git a/CPP/7zip/UI/FileManager/PanelSelect.cpp b/CPP/7zip/UI/FileManager/PanelSelect.cpp new file mode 100755 index 0000000..21e5a21 --- /dev/null +++ b/CPP/7zip/UI/FileManager/PanelSelect.cpp @@ -0,0 +1,306 @@ +// PanelSelect.cpp + +#include "StdAfx.h" + +#include "resource.h" + +#include "Common/StringConvert.h" +#include "Common/Wildcard.h" + +#include "Panel.h" + +#include "ComboDialog.h" + +#include "LangUtils.h" + +void CPanel::OnShiftSelectMessage() +{ + if (!_mySelectMode) + return; + int focusedItem = _listView.GetFocusedItem(); + if (focusedItem < 0) + return; + if (!_selectionIsDefined) + return; + int startItem = MyMin(focusedItem, _prevFocusedItem); + int finishItem = MyMax(focusedItem, _prevFocusedItem); + for (int i = 0; i < _listView.GetItemCount(); i++) + { + int realIndex = GetRealItemIndex(i); + if (realIndex == kParentIndex) + continue; + if (i >= startItem && i <= finishItem) + if (_selectedStatusVector[realIndex] != _selectMark) + { + _selectedStatusVector[realIndex] = _selectMark; + _listView.RedrawItem(i); + } + } + _prevFocusedItem = focusedItem; +} + +void CPanel::OnArrowWithShift() +{ + if (!_mySelectMode) + return; + int focusedItem = _listView.GetFocusedItem(); + if (focusedItem < 0) + return; + int realIndex = GetRealItemIndex(focusedItem); + if (_selectionIsDefined) + { + if (realIndex != kParentIndex) + _selectedStatusVector[realIndex] = _selectMark; + } + else + { + if (realIndex == kParentIndex) + { + _selectionIsDefined = true; + _selectMark = true; + } + else + { + _selectionIsDefined = true; + _selectMark = !_selectedStatusVector[realIndex]; + _selectedStatusVector[realIndex] = _selectMark; + } + } + _prevFocusedItem = focusedItem; + PostMessage(kShiftSelectMessage); + _listView.RedrawItem(focusedItem); +} + +void CPanel::OnInsert() +{ + /* + const int kState = CDIS_MARKED; // LVIS_DROPHILITED; + UINT state = (_listView.GetItemState(focusedItem, LVIS_CUT) == 0) ? + LVIS_CUT : 0; + _listView.SetItemState(focusedItem, state, LVIS_CUT); + // _listView.SetItemState(focusedItem, LVIS_SELECTED, LVIS_SELECTED); + + */ + int focusedItem = _listView.GetFocusedItem(); + if (focusedItem < 0) + return; + int realIndex = GetRealItemIndex(focusedItem); + bool isSelected = !_selectedStatusVector[realIndex]; + if (realIndex != kParentIndex) + _selectedStatusVector[realIndex] = isSelected; + + if (!_mySelectMode) + _listView.SetItemState(focusedItem, isSelected ? LVIS_SELECTED: 0, LVIS_SELECTED); + + _listView.RedrawItem(focusedItem); + + int nextIndex = focusedItem + 1; + if (nextIndex < _listView.GetItemCount()) + { + _listView.SetItemState_FocusedSelected(nextIndex); + _listView.EnsureVisible(nextIndex, false); + } +} + +/* +void CPanel::OnUpWithShift() +{ + int focusedItem = _listView.GetFocusedItem(); + if (focusedItem < 0) + return; + int index = GetRealItemIndex(focusedItem); + _selectedStatusVector[index] = !_selectedStatusVector[index]; + _listView.RedrawItem(index); +} + +void CPanel::OnDownWithShift() +{ + int focusedItem = _listView.GetFocusedItem(); + if (focusedItem < 0) + return; + int index = GetRealItemIndex(focusedItem); + _selectedStatusVector[index] = !_selectedStatusVector[index]; + _listView.RedrawItem(index); +} +*/ + +void CPanel::UpdateSelection() +{ + if (!_mySelectMode) + { + bool enableTemp = _enableItemChangeNotify; + _enableItemChangeNotify = false; + int numItems = _listView.GetItemCount(); + for (int i = 0; i < numItems; i++) + { + int realIndex = GetRealItemIndex(i); + if (realIndex != kParentIndex) + { + UINT value = 0; + value = _selectedStatusVector[realIndex] ? LVIS_SELECTED: 0; + _listView.SetItemState(i, value, LVIS_SELECTED); + } + } + _enableItemChangeNotify = enableTemp; + } + _listView.RedrawAllItems(); +} + + +void CPanel::SelectSpec(bool selectMode) +{ + CComboDialog comboDialog; + comboDialog.Title = selectMode ? + LangString(IDS_SELECT, 0x03020250): + LangString(IDS_DESELECT, 0x03020251); + comboDialog.Static = LangString(IDS_SELECT_MASK, 0x03020252); + comboDialog.Value = L"*"; + if (comboDialog.Create(GetParent()) == IDCANCEL) + return; + const UString &mask = comboDialog.Value; + for (int i = 0; i < _selectedStatusVector.Size(); i++) + if (CompareWildCardWithName(mask, GetItemName(i))) + _selectedStatusVector[i] = selectMode; + UpdateSelection(); +} + +void CPanel::SelectByType(bool selectMode) +{ + int focusedItem = _listView.GetFocusedItem(); + if (focusedItem < 0) + return; + int realIndex = GetRealItemIndex(focusedItem); + UString name = GetItemName(realIndex); + bool isItemFolder = IsItemFolder(realIndex); + + /* + UINT32 numItems; + _folder->GetNumberOfItems(&numItems); + if ((UInt32)_selectedStatusVector.Size() != numItems) + throw 11111; + */ + + if (isItemFolder) + { + for (int i = 0; i < _selectedStatusVector.Size(); i++) + if (IsItemFolder(i) == isItemFolder) + _selectedStatusVector[i] = selectMode; + } + else + { + int pos = name.ReverseFind(L'.'); + if (pos < 0) + { + for (int i = 0; i < _selectedStatusVector.Size(); i++) + if (IsItemFolder(i) == isItemFolder && GetItemName(i).ReverseFind(L'.') < 0) + _selectedStatusVector[i] = selectMode; + } + else + { + UString mask = UString(L'*') + name.Mid(pos); + for (int i = 0; i < _selectedStatusVector.Size(); i++) + if (IsItemFolder(i) == isItemFolder && CompareWildCardWithName(mask, GetItemName(i))) + _selectedStatusVector[i] = selectMode; + } + } + UpdateSelection(); +} + +void CPanel::SelectAll(bool selectMode) +{ + for (int i = 0; i < _selectedStatusVector.Size(); i++) + _selectedStatusVector[i] = selectMode; + UpdateSelection(); +} + +void CPanel::InvertSelection() +{ + if (!_mySelectMode) + { + int numSelected = 0; + for (int i = 0; i < _selectedStatusVector.Size(); i++) + if (_selectedStatusVector[i]) + numSelected++; + if (numSelected == 1) + { + int focused = _listView.GetFocusedItem(); + if (focused >= 0) + { + int realIndex = GetRealItemIndex(focused); + if (realIndex >= 0) + if (_selectedStatusVector[realIndex]) + _selectedStatusVector[realIndex] = false; + } + } + } + for (int i = 0; i < _selectedStatusVector.Size(); i++) + _selectedStatusVector[i] = !_selectedStatusVector[i]; + UpdateSelection(); +} + +void CPanel::KillSelection() +{ + SelectAll(false); + if (!_mySelectMode) + { + int focused = _listView.GetFocusedItem(); + if (focused >= 0) + { + // CPanel::OnItemChanged notify for LVIS_SELECTED change doesn't work here. Why? + // so we change _selectedStatusVector[realIndex] here. + int realIndex = GetRealItemIndex(focused); + if (realIndex != kParentIndex) + _selectedStatusVector[realIndex] = true; + _listView.SetItemState(focused, LVIS_SELECTED, LVIS_SELECTED); + } + } +} + +void CPanel::OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate) +{ + if (itemActivate->hdr.hwndFrom != HWND(_listView)) + return; + // It will be work only for Version 4.71 (IE 4); + int indexInList = itemActivate->iItem; + if (indexInList < 0) + return; + #ifndef UNDER_CE + if ((itemActivate->uKeyFlags & LVKF_SHIFT) != 0) + { + // int focusedIndex = _listView.GetFocusedItem(); + int focusedIndex = _startGroupSelect; + if (focusedIndex < 0) + return; + int startItem = MyMin(focusedIndex, indexInList); + int finishItem = MyMax(focusedIndex, indexInList); + for (int i = 0; i < _selectedStatusVector.Size(); i++) + { + int realIndex = GetRealItemIndex(i); + if (realIndex == kParentIndex) + continue; + bool selected = (i >= startItem && i <= finishItem); + if (_selectedStatusVector[realIndex] != selected) + { + _selectedStatusVector[realIndex] = selected; + _listView.RedrawItem(i); + } + } + } + else + #endif + { + _startGroupSelect = indexInList; + #ifndef UNDER_CE + if ((itemActivate->uKeyFlags & LVKF_CONTROL) != 0) + { + int realIndex = GetRealItemIndex(indexInList); + if (realIndex != kParentIndex) + { + _selectedStatusVector[realIndex] = !_selectedStatusVector[realIndex]; + _listView.RedrawItem(indexInList); + } + } + #endif + } + return; +} diff --git a/CPP/7zip/UI/FileManager/PanelSort.cpp b/CPP/7zip/UI/FileManager/PanelSort.cpp new file mode 100755 index 0000000..3f896e0 --- /dev/null +++ b/CPP/7zip/UI/FileManager/PanelSort.cpp @@ -0,0 +1,160 @@ +// PanelSort.cpp + +#include "StdAfx.h" + +#include "Windows/PropVariant.h" + +#include "../../PropID.h" + +#include "Panel.h" + +using namespace NWindows; + +static UString GetExtension(const UString &name) +{ + int dotPos = name.ReverseFind(L'.'); + if (dotPos < 0) + return UString(); + return name.Mid(dotPos); +} + +int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) +{ + if (lpData == NULL) + return 0; + CPanel *panel = (CPanel*)lpData; + + switch(panel->_sortID) + { + // if (panel->_sortIndex == 0) + case kpidName: + { + const UString name1 = panel->GetItemName((int)lParam1); + const UString name2 = panel->GetItemName((int)lParam2); + int res = name1.CompareNoCase(name2); + /* + if (res != 0 || !panel->_flatMode) + return res; + const UString prefix1 = panel->GetItemPrefix(lParam1); + const UString prefix2 = panel->GetItemPrefix(lParam2); + return res = prefix1.CompareNoCase(prefix2); + */ + return res; + } + case kpidNoProperty: + { + return MyCompare(lParam1, lParam2); + } + case kpidExtension: + { + const UString ext1 = GetExtension(panel->GetItemName((int)lParam1)); + const UString ext2 = GetExtension(panel->GetItemName((int)lParam2)); + return ext1.CompareNoCase(ext2); + } + } + /* + if (panel->_sortIndex == 1) + return MyCompare(file1.Size, file2.Size); + return ::CompareFileTime(&file1.MTime, &file2.MTime); + */ + + // PROPID propID = panel->_properties[panel->_sortIndex].ID; + PROPID propID = panel->_sortID; + + NCOM::CPropVariant prop1, prop2; + // Name must be first property + panel->_folder->GetProperty((UINT32)lParam1, propID, &prop1); + panel->_folder->GetProperty((UINT32)lParam2, propID, &prop2); + if (prop1.vt != prop2.vt) + { + return MyCompare(prop1.vt, prop2.vt); + } + if (prop1.vt == VT_BSTR) + { + return _wcsicmp(prop1.bstrVal, prop2.bstrVal); + } + return prop1.Compare(prop2); + // return 0; +} + +int CALLBACK CompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) +{ + if (lpData == NULL) return 0; + if (lParam1 == kParentIndex) return -1; + if (lParam2 == kParentIndex) return 1; + + CPanel *panel = (CPanel*)lpData; + + bool isDir1 = panel->IsItemFolder((int)lParam1); + bool isDir2 = panel->IsItemFolder((int)lParam2); + + if (isDir1 && !isDir2) return -1; + if (isDir2 && !isDir1) return 1; + + int result = CompareItems2(lParam1, lParam2, lpData); + return panel->_ascending ? result: (-result); +} + + +/* +void CPanel::SortItems(int index) +{ + if (index == _sortIndex) + _ascending = !_ascending; + else + { + _sortIndex = index; + _ascending = true; + switch (_properties[_sortIndex].ID) + { + case kpidSize: + case kpidPackedSize: + case kpidCTime: + case kpidATime: + case kpidMTime: + _ascending = false; + break; + } + } + _listView.SortItems(CompareItems, (LPARAM)this); + _listView.EnsureVisible(_listView.GetFocusedItem(), false); +} +void CPanel::SortItemsWithPropID(PROPID propID) +{ + int index = _properties.FindItemWithID(propID); + if (index >= 0) + SortItems(index); +} +*/ +void CPanel::SortItemsWithPropID(PROPID propID) +{ + if (propID == _sortID) + _ascending = !_ascending; + else + { + _sortID = propID; + _ascending = true; + switch (propID) + { + case kpidSize: + case kpidPackSize: + case kpidCTime: + case kpidATime: + case kpidMTime: + _ascending = false; + break; + } + } + _listView.SortItems(CompareItems, (LPARAM)this); + _listView.EnsureVisible(_listView.GetFocusedItem(), false); +} + + +void CPanel::OnColumnClick(LPNMLISTVIEW info) +{ + /* + int index = _properties.FindItemWithID(_visibleProperties[info->iSubItem].ID); + SortItems(index); + */ + SortItemsWithPropID(_visibleProperties[info->iSubItem].ID); +} diff --git a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp new file mode 100755 index 0000000..61388d7 --- /dev/null +++ b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp @@ -0,0 +1,494 @@ +// PanelSplitFile.cpp + +#include "StdAfx.h" + +#include "Common/IntToString.h" + +#include "Windows/Error.h" +#include "Windows/FileIO.h" +#include "Windows/FileFind.h" + +#include "../GUI/ExtractRes.h" + +#include "resource.h" + +#include "App.h" +#include "CopyDialog.h" +#include "FormatUtils.h" +#include "LangUtils.h" +#include "SplitDialog.h" +#include "SplitUtils.h" + +using namespace NWindows; + +static const wchar_t *g_Message_FileWriteError = L"File write error"; + +struct CVolSeqName +{ + UString UnchangedPart; + UString ChangedPart; + CVolSeqName(): ChangedPart(L"000") {}; + + void SetNumDigits(UInt64 numVolumes) + { + ChangedPart = L"000"; + while (numVolumes > 999) + { + numVolumes /= 10; + ChangedPart += L'0'; + } + } + + bool ParseName(const UString &name) + { + if (name.Right(2) != L"01") + return false; + int numLetters = 2; + while (numLetters < name.Length()) + { + if (name[name.Length() - numLetters - 1] != '0') + break; + numLetters++; + } + UnchangedPart = name.Left(name.Length() - numLetters); + ChangedPart = name.Right(numLetters); + return true; + } + + UString GetNextName() + { + UString newName; + int i; + int numLetters = ChangedPart.Length(); + for (i = numLetters - 1; i >= 0; i--) + { + wchar_t c = ChangedPart[i]; + if (c == L'9') + { + c = L'0'; + newName = c + newName; + if (i == 0) + newName = UString(L'1') + newName; + continue; + } + c++; + newName = c + newName; + i--; + for (; i >= 0; i--) + newName = ChangedPart[i] + newName; + break; + } + ChangedPart = newName; + return UnchangedPart + ChangedPart; + } +}; + +static const UInt32 kBufSize = (1 << 20); + +class CThreadSplit: public CProgressThreadVirt +{ + HRESULT ProcessVirt(); +public: + UString FilePath; + UString VolBasePath; + UInt64 NumVolumes; + CRecordVector VolumeSizes; +}; + +HRESULT CThreadSplit::ProcessVirt() +{ + NFile::NIO::CInFile inFile; + if (!inFile.Open(FilePath)) + return GetLastError(); + NFile::NIO::COutFile outFile; + CMyBuffer bufferObject; + if (!bufferObject.Allocate(kBufSize)) + return E_OUTOFMEMORY; + Byte *buffer = (Byte *)(void *)bufferObject; + UInt64 curVolSize = 0; + CVolSeqName seqName; + seqName.SetNumDigits(NumVolumes); + UInt64 length; + if (!inFile.GetLength(length)) + return GetLastError(); + + CProgressSync &sync = ProgressDialog.Sync; + sync.SetProgress(length, 0); + UInt64 pos = 0; + + UInt64 numFiles = 0; + int volIndex = 0; + + for (;;) + { + UInt64 volSize; + if (volIndex < VolumeSizes.Size()) + volSize = VolumeSizes[volIndex]; + else + volSize = VolumeSizes.Back(); + + UInt32 needSize = (UInt32)(MyMin((UInt64)kBufSize, volSize - curVolSize)); + UInt32 processedSize; + if (!inFile.Read(buffer, needSize, processedSize)) + return GetLastError(); + if (processedSize == 0) + break; + needSize = processedSize; + if (curVolSize == 0) + { + UString name = VolBasePath; + name += L'.'; + name += seqName.GetNextName(); + sync.SetCurrentFileName(name); + sync.SetNumFilesCur(numFiles++); + if (!outFile.Create(name, false)) + { + HRESULT res = GetLastError(); + ErrorPath1 = name; + return res; + } + } + if (!outFile.Write(buffer, needSize, processedSize)) + return GetLastError(); + if (needSize != processedSize) + throw g_Message_FileWriteError; + curVolSize += processedSize; + if (curVolSize == volSize) + { + outFile.Close(); + if (volIndex < VolumeSizes.Size()) + volIndex++; + curVolSize = 0; + } + pos += processedSize; + RINOK(sync.SetPosAndCheckPaused(pos)); + } + sync.SetNumFilesCur(numFiles); + return S_OK; +} + +void CApp::Split() +{ + int srcPanelIndex = GetFocusedPanelIndex(); + CPanel &srcPanel = Panels[srcPanelIndex]; + if (!srcPanel.IsFSFolder()) + { + srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + return; + } + CRecordVector indices; + srcPanel.GetOperatedItemIndices(indices); + if (indices.IsEmpty()) + return; + if (indices.Size() != 1) + { + srcPanel.MessageBoxErrorLang(IDS_SELECT_ONE_FILE, 0x03020A02); + return; + } + int index = indices[0]; + if (srcPanel.IsItemFolder(index)) + { + srcPanel.MessageBoxErrorLang(IDS_SELECT_ONE_FILE, 0x03020A02); + return; + } + const UString itemName = srcPanel.GetItemName(index); + + UString srcPath = srcPanel._currentFolderPrefix + srcPanel.GetItemPrefix(index); + UString path = srcPath; + int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex); + CPanel &destPanel = Panels[destPanelIndex]; + if (NumPanels > 1) + if (destPanel.IsFSFolder()) + path = destPanel._currentFolderPrefix; + CSplitDialog splitDialog; + splitDialog.FilePath = srcPanel.GetItemRelPath(index); + splitDialog.Path = path; + if (splitDialog.Create(srcPanel.GetParent()) == IDCANCEL) + return; + + NFile::NFind::CFileInfoW fileInfo; + if (!fileInfo.Find(srcPath + itemName)) + { + srcPanel.MessageBoxMyError(L"Can not find file"); + return; + } + if (fileInfo.Size <= splitDialog.VolumeSizes.Front()) + { + srcPanel.MessageBoxErrorLang(IDS_SPLIT_VOL_MUST_BE_SMALLER, 0x03020522); + return; + } + const UInt64 numVolumes = GetNumberOfVolumes(fileInfo.Size, splitDialog.VolumeSizes); + if (numVolumes >= 100) + { + wchar_t s[32]; + ConvertUInt64ToString(numVolumes, s); + if (::MessageBoxW(srcPanel, MyFormatNew(IDS_SPLIT_CONFIRM_MESSAGE, 0x03020521, s), + LangString(IDS_SPLIT_CONFIRM_TITLE, 0x03020520), + MB_YESNOCANCEL | MB_ICONQUESTION) != IDYES) + return; + } + + path = splitDialog.Path; + NFile::NName::NormalizeDirPathPrefix(path); + if (!NFile::NDirectory::CreateComplexDirectory(path)) + { + srcPanel.MessageBoxMyError(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, 0x02000603, path)); + return; + } + + { + CThreadSplit spliter; + spliter.NumVolumes = numVolumes; + + CProgressDialog &progressDialog = spliter.ProgressDialog; + + UString progressWindowTitle = LangString(IDS_APP_TITLE, 0x03000000); + UString title = LangString(IDS_SPLITTING, 0x03020510); + + progressDialog.ShowCompressionInfo = false; + + progressDialog.MainWindow = _window; + progressDialog.MainTitle = progressWindowTitle; + progressDialog.MainAddTitle = title + UString(L" "); + progressDialog.Sync.SetTitleFileName(itemName); + + + spliter.FilePath = srcPath + itemName; + spliter.VolBasePath = path + itemName; + spliter.VolumeSizes = splitDialog.VolumeSizes; + + // if (splitDialog.VolumeSizes.Size() == 0) return; + + // CPanel::CDisableTimerProcessing disableTimerProcessing1(srcPanel); + // CPanel::CDisableTimerProcessing disableTimerProcessing2(destPanel); + + if (spliter.Create(title, _window) != 0) + return; + } + RefreshTitleAlways(); + + + // disableTimerProcessing1.Restore(); + // disableTimerProcessing2.Restore(); + // srcPanel.SetFocusToList(); + // srcPanel.RefreshListCtrlSaveFocused(); +} + + +class CThreadCombine: public CProgressThreadVirt +{ + HRESULT ProcessVirt(); +public: + UString InputDirPrefix; + UStringVector Names; + UString OutputPath; + UInt64 TotalSize; +}; + +HRESULT CThreadCombine::ProcessVirt() +{ + NFile::NIO::COutFile outFile; + if (!outFile.Create(OutputPath, false)) + { + HRESULT res = GetLastError(); + ErrorPath1 = OutputPath; + return res; + } + + CProgressSync &sync = ProgressDialog.Sync; + sync.SetProgress(TotalSize, 0); + + CMyBuffer bufferObject; + if (!bufferObject.Allocate(kBufSize)) + return E_OUTOFMEMORY; + Byte *buffer = (Byte *)(void *)bufferObject; + UInt64 pos = 0; + for (int i = 0; i < Names.Size(); i++) + { + NFile::NIO::CInFile inFile; + const UString nextName = InputDirPrefix + Names[i]; + if (!inFile.Open(nextName)) + { + HRESULT res = GetLastError(); + ErrorPath1 = nextName; + return res; + } + sync.SetCurrentFileName(nextName); + for (;;) + { + UInt32 processedSize; + if (!inFile.Read(buffer, kBufSize, processedSize)) + { + HRESULT res = GetLastError(); + ErrorPath1 = nextName; + return res; + } + if (processedSize == 0) + break; + UInt32 needSize = processedSize; + if (!outFile.Write(buffer, needSize, processedSize)) + { + HRESULT res = GetLastError(); + ErrorPath1 = OutputPath; + return res; + } + if (needSize != processedSize) + throw g_Message_FileWriteError; + pos += processedSize; + RINOK(sync.SetPosAndCheckPaused(pos)); + } + } + return S_OK; +} + +extern void AddValuePair2(UINT resourceID, UInt32 langID, UInt64 num, UInt64 size, UString &s); + +static void AddInfoFileName(const UString &name, UString &dest) +{ + dest += L"\n "; + dest += name; +} + +void CApp::Combine() +{ + int srcPanelIndex = GetFocusedPanelIndex(); + CPanel &srcPanel = Panels[srcPanelIndex]; + if (!srcPanel.IsFSFolder()) + { + srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + return; + } + CRecordVector indices; + srcPanel.GetOperatedItemIndices(indices); + if (indices.IsEmpty()) + return; + int index = indices[0]; + if (indices.Size() != 1 || srcPanel.IsItemFolder(index)) + { + srcPanel.MessageBoxErrorLang(IDS_COMBINE_SELECT_ONE_FILE, 0x03020620); + return; + } + const UString itemName = srcPanel.GetItemName(index); + + UString srcPath = srcPanel._currentFolderPrefix + srcPanel.GetItemPrefix(index); + UString path = srcPath; + int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex); + CPanel &destPanel = Panels[destPanelIndex]; + if (NumPanels > 1) + if (destPanel.IsFSFolder()) + path = destPanel._currentFolderPrefix; + + CVolSeqName volSeqName; + if (!volSeqName.ParseName(itemName)) + { + srcPanel.MessageBoxErrorLang(IDS_COMBINE_CANT_DETECT_SPLIT_FILE, 0x03020621); + return; + } + + { + CThreadCombine combiner; + + UString nextName = itemName; + combiner.TotalSize = 0; + for (;;) + { + NFile::NFind::CFileInfoW fileInfo; + if (!fileInfo.Find(srcPath + nextName) || fileInfo.IsDir()) + break; + combiner.Names.Add(nextName); + combiner.TotalSize += fileInfo.Size; + nextName = volSeqName.GetNextName(); + } + if (combiner.Names.Size() == 1) + { + srcPanel.MessageBoxErrorLang(IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART, 0x03020622); + return; + } + + if (combiner.TotalSize == 0) + { + srcPanel.MessageBoxMyError(L"No data"); + return; + } + + UString info; + AddValuePair2(IDS_FILES_COLON, 0x02000320, combiner.Names.Size(), combiner.TotalSize, info); + + info += L"\n"; + info += srcPath; + + int i; + for (i = 0; i < combiner.Names.Size() && i < 2; i++) + AddInfoFileName(combiner.Names[i], info); + if (i != combiner.Names.Size()) + { + if (i + 1 != combiner.Names.Size()) + AddInfoFileName(L"...", info); + AddInfoFileName(combiner.Names.Back(), info); + } + + { + CCopyDialog copyDialog; + copyDialog.Value = path; + copyDialog.Title = LangString(IDS_COMBINE, 0x03020600); + copyDialog.Title += ' '; + copyDialog.Title += srcPanel.GetItemRelPath(index); + copyDialog.Static = LangString(IDS_COMBINE_TO, 0x03020601); + copyDialog.Info = info; + if (copyDialog.Create(srcPanel.GetParent()) == IDCANCEL) + return; + path = copyDialog.Value; + } + + NFile::NName::NormalizeDirPathPrefix(path); + if (!NFile::NDirectory::CreateComplexDirectory(path)) + { + srcPanel.MessageBoxMyError(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, 0x02000603, path)); + return; + } + + UString outName = volSeqName.UnchangedPart; + while (!outName.IsEmpty()) + { + int lastIndex = outName.Length() - 1; + if (outName[lastIndex] != L'.') + break; + outName.Delete(lastIndex); + } + if (outName.IsEmpty()) + outName = L"file"; + + NFile::NFind::CFileInfoW fileInfo; + UString destFilePath = path + outName; + combiner.OutputPath = destFilePath; + if (fileInfo.Find(destFilePath)) + { + srcPanel.MessageBoxMyError(MyFormatNew(IDS_FILE_EXIST, 0x03020A04, destFilePath)); + return; + } + + CProgressDialog &progressDialog = combiner.ProgressDialog; + progressDialog.ShowCompressionInfo = false; + + UString progressWindowTitle = LangString(IDS_APP_TITLE, 0x03000000); + UString title = LangString(IDS_COMBINING, 0x03020610); + + progressDialog.MainWindow = _window; + progressDialog.MainTitle = progressWindowTitle; + progressDialog.MainAddTitle = title + UString(L" "); + + combiner.InputDirPrefix = srcPath; + + // CPanel::CDisableTimerProcessing disableTimerProcessing1(srcPanel); + // CPanel::CDisableTimerProcessing disableTimerProcessing2(destPanel); + + if (combiner.Create(title, _window) != 0) + return; + } + RefreshTitleAlways(); + + // disableTimerProcessing1.Restore(); + // disableTimerProcessing2.Restore(); + // srcPanel.SetFocusToList(); + // srcPanel.RefreshListCtrlSaveFocused(); +} diff --git a/CPP/7zip/UI/FileManager/PasswordDialog.cpp b/CPP/7zip/UI/FileManager/PasswordDialog.cpp new file mode 100755 index 0000000..4c7bf8b --- /dev/null +++ b/CPP/7zip/UI/FileManager/PasswordDialog.cpp @@ -0,0 +1,51 @@ +// PasswordDialog.cpp + +#include "StdAfx.h" + +#include "PasswordDialog.h" + +#ifdef LANG +#include "LangUtils.h" +#endif + +#ifdef LANG +static CIDLangPair kIDLangPairs[] = +{ + { IDC_STATIC_PASSWORD_HEADER, 0x02000B01 }, + { IDC_CHECK_PASSWORD_SHOW, 0x02000B02 }, + { IDOK, 0x02000702 }, + { IDCANCEL, 0x02000710 } +}; +#endif + + +bool CPasswordDialog::OnInit() +{ + #ifdef LANG + LangSetWindowText(HWND(*this), 0x02000B00); + LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + #endif + _passwordControl.Attach(GetItem(IDC_EDIT_PASSWORD)); + _passwordControl.SetText(Password); + _passwordControl.SetPasswordChar(TEXT('*')); + return CModalDialog::OnInit(); +} + +bool CPasswordDialog::OnButtonClicked(int buttonID, HWND buttonHWND) +{ + if (buttonID == IDC_CHECK_PASSWORD_SHOW) + { + _passwordControl.SetPasswordChar(IsButtonCheckedBool(IDC_CHECK_PASSWORD_SHOW) ? 0: TEXT('*')); + UString password; + _passwordControl.GetText(password); + _passwordControl.SetText(password); + return true; + } + return CDialog::OnButtonClicked(buttonID, buttonHWND); +} + +void CPasswordDialog::OnOK() +{ + _passwordControl.GetText(Password); + CModalDialog::OnOK(); +} diff --git a/CPP/7zip/UI/FileManager/PasswordDialog.h b/CPP/7zip/UI/FileManager/PasswordDialog.h new file mode 100755 index 0000000..9f7241f --- /dev/null +++ b/CPP/7zip/UI/FileManager/PasswordDialog.h @@ -0,0 +1,21 @@ +// PasswordDialog.h + +#ifndef __PASSWORDDIALOG_H +#define __PASSWORDDIALOG_H + +#include "Windows/Control/Dialog.h" +#include "Windows/Control/Edit.h" +#include "PasswordDialogRes.h" + +class CPasswordDialog: public NWindows::NControl::CModalDialog +{ + NWindows::NControl::CEdit _passwordControl; + virtual void OnOK(); + virtual bool OnInit(); + virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); +public: + UString Password; + INT_PTR Create(HWND parentWindow = 0) { return CModalDialog::Create(IDD_DIALOG_PASSWORD, parentWindow); } +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/PasswordDialog.rc b/CPP/7zip/UI/FileManager/PasswordDialog.rc new file mode 100755 index 0000000..385ffaa --- /dev/null +++ b/CPP/7zip/UI/FileManager/PasswordDialog.rc @@ -0,0 +1,14 @@ +#include "PasswordDialogRes.h" +#include "../../GuiCommon.rc" + +#define xc 140 +#define yc 72 + +IDD_DIALOG_PASSWORD MY_DIALOG +CAPTION "Enter password" +BEGIN + LTEXT "&Enter password:", IDC_STATIC_PASSWORD_HEADER, m, m, xc, 8 + EDITTEXT IDC_EDIT_PASSWORD, m, 20, xc, 14, ES_PASSWORD | ES_AUTOHSCROLL + CONTROL "&Show password", IDC_CHECK_PASSWORD_SHOW, MY_CHECKBOX, m, 42, xc, 10 + OK_CANCEL +END diff --git a/CPP/7zip/UI/FileManager/PasswordDialogRes.h b/CPP/7zip/UI/FileManager/PasswordDialogRes.h new file mode 100755 index 0000000..7225e57 --- /dev/null +++ b/CPP/7zip/UI/FileManager/PasswordDialogRes.h @@ -0,0 +1,4 @@ +#define IDD_DIALOG_PASSWORD 501 +#define IDC_STATIC_PASSWORD_HEADER 1000 +#define IDC_EDIT_PASSWORD 1001 +#define IDC_CHECK_PASSWORD_SHOW 1002 diff --git a/CPP/7zip/UI/FileManager/PluginInterface.h b/CPP/7zip/UI/FileManager/PluginInterface.h new file mode 100755 index 0000000..cb8b790 --- /dev/null +++ b/CPP/7zip/UI/FileManager/PluginInterface.h @@ -0,0 +1,31 @@ +// PluginInterface.h + +#ifndef __PLUGIN_INTERFACE_H +#define __PLUGIN_INTERFACE_H + +/* +#include "../../../Common/Types.h" +#include "../../IDecl.h" + +#define PLUGIN_INTERFACE(i, x) DECL_INTERFACE(i, 0x0A, x) + +PLUGIN_INTERFACE(IInitContextMenu, 0x00) +{ + STDMETHOD(InitContextMenu)(const wchar_t *folder, const wchar_t **names, UINT32 numFiles) PURE; +}; + +PLUGIN_INTERFACE(IPluginOptionsCallback, 0x01) +{ + STDMETHOD(GetProgramFolderPath)(BSTR *value) PURE; + STDMETHOD(GetProgramPath)(BSTR *value) PURE; + STDMETHOD(GetRegistryCUPath)(BSTR *value) PURE; +}; + +PLUGIN_INTERFACE(IPluginOptions, 0x02) +{ + STDMETHOD(PluginOptions)(HWND hWnd, IPluginOptionsCallback *callback) PURE; + // STDMETHOD(GetFileExtensions)(BSTR *extensions) PURE; +}; +*/ + +#endif diff --git a/CPP/7zip/UI/FileManager/PluginLoader.h b/CPP/7zip/UI/FileManager/PluginLoader.h new file mode 100755 index 0000000..895b01d --- /dev/null +++ b/CPP/7zip/UI/FileManager/PluginLoader.h @@ -0,0 +1,28 @@ +// PluginLoader.h + +#ifndef __PLUGIN_LOADER_H +#define __PLUGIN_LOADER_H + +#include "Windows/DLL.h" + +typedef UINT32 (WINAPI * CreateObjectPointer)(const GUID *clsID, const GUID *interfaceID, void **outObject); + +class CPluginLibrary: public NWindows::NDLL::CLibrary +{ +public: + HRESULT CreateManager(REFGUID clsID, IFolderManager **manager) + { + CreateObjectPointer createObject = (CreateObjectPointer)GetProc("CreateObject"); + if (createObject == NULL) + return GetLastError(); + return createObject(&clsID, &IID_IFolderManager, (void **)manager); + } + HRESULT LoadAndCreateManager(LPCWSTR filePath, REFGUID clsID, IFolderManager **manager) + { + if (!Load(filePath)) + return GetLastError(); + return CreateManager(clsID, manager); + } +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/PluginsPage.cpp b/CPP/7zip/UI/FileManager/PluginsPage.cpp new file mode 100755 index 0000000..ac7afba --- /dev/null +++ b/CPP/7zip/UI/FileManager/PluginsPage.cpp @@ -0,0 +1,207 @@ +// PluginsPage.cpp + +#include "StdAfx.h" + +#include "Common/MyCom.h" + +#include "Windows/DLL.h" + +#include "HelpUtils.h" +#include "LangUtils.h" +#include "PluginsPage.h" +#include "PluginsPageRes.h" +#include "ProgramLocation.h" +#include "PluginInterface.h" + +static CIDLangPair kIDLangPairs[] = +{ + { IDC_PLUGINS_STATIC_PLUGINS, 0x03010101}, + { IDC_PLUGINS_BUTTON_OPTIONS, 0x03010110} +}; + +static LPCWSTR kPluginsTopic = L"FM/options.htm#plugins"; + +bool CPluginsPage::OnInit() +{ + LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + + _listView.Attach(GetItem(IDC_PLUGINS_LIST)); + + UINT32 newFlags = /* LVS_EX_CHECKBOXES | */ LVS_EX_FULLROWSELECT; + _listView.SetExtendedListViewStyle(newFlags, newFlags); + + _listView.InsertColumn(0, L"Plugins", 50); + + ReadFileFolderPluginInfoList(_plugins); + + _listView.SetRedraw(false); + // _listView.DeleteAllItems(); + for (int i = 0; i < _plugins.Size(); i++) + { + const CPluginInfo &p = _plugins[i]; + if (!p.OptionsClassIDDefined) + continue; + LVITEMW item; + item.iItem = i; + item.mask = LVIF_TEXT | LVIF_STATE; + UString pluginName = p.Name; + item.pszText = (WCHAR *)(const WCHAR *)pluginName; + item.state = 0; + item.stateMask = UINT(-1); + item.iSubItem = 0; + _listView.InsertItem(&item); + _listView.SetCheckState(i, true); + } + _listView.SetRedraw(true); + if (_listView.GetItemCount() > 0) + { + UINT state = LVIS_SELECTED | LVIS_FOCUSED; + _listView.SetItemState(0, state, state); + } + _listView.SetColumnWidthAuto(0); + + return CPropertyPage::OnInit(); +} + +LONG CPluginsPage::OnApply() +{ + /* + int selectedIndex = m_Lang.GetCurSel(); + int aPathIndex = m_Lang.GetItemData(selectedIndex); + SaveRegLang(m_Paths[aPathIndex]); + ReloadLang(); + */ + return PSNRET_NOERROR; +} + +void CPluginsPage::OnNotifyHelp() +{ + ShowHelpWindow(NULL, kPluginsTopic); +} + +bool CPluginsPage::OnButtonClicked(int buttonID, HWND buttonHWND) +{ + switch(buttonID) + { + case IDC_PLUGINS_BUTTON_OPTIONS: + OnButtonOptions(); + break; + default: + return CPropertyPage::OnButtonClicked(buttonID, buttonHWND); + } + return true; +} + +class CPluginOptionsCallback: + public IPluginOptionsCallback, + public CMyUnknownImp +{ + UString _pluginName; +public: + MY_UNKNOWN_IMP + + STDMETHOD(GetProgramFolderPath)(BSTR *value); + STDMETHOD(GetProgramPath)(BSTR *Value); + STDMETHOD(GetRegistryCUPath)(BSTR *Value); + void Init(const UString &pluginName) + { _pluginName = pluginName; } +}; + +STDMETHODIMP CPluginOptionsCallback::GetProgramFolderPath(BSTR *value) +{ + *value = 0; + UString folder; + if (!::GetProgramFolderPath(folder)) + return E_FAIL; + return StringToBstr(folder, value); +} + +static UString GetDefaultProgramName() +{ + return L"7zFM.exe"; +} + +STDMETHODIMP CPluginOptionsCallback::GetProgramPath(BSTR *value) +{ + *value = 0; + UString folder; + if (!::GetProgramFolderPath(folder)) + return E_FAIL; + return StringToBstr(folder + GetDefaultProgramName(), value); +} + +STDMETHODIMP CPluginOptionsCallback::GetRegistryCUPath(BSTR *value) +{ + return StringToBstr(UString(L"Software" + WSTRING_PATH_SEPARATOR L"7-Zip" + WSTRING_PATH_SEPARATOR L"FM" + WSTRING_PATH_SEPARATOR L"Plugins" + WSTRING_PATH_SEPARATOR) + _pluginName, value); +} + +void CPluginsPage::OnButtonOptions() +{ + int index = _listView.GetSelectionMark(); + if (index < 0) + return; + + CPluginInfo pluginInfo = _plugins[index]; + if (!pluginInfo.OptionsClassIDDefined) + { + MessageBoxW(HWND(*this), L"There are no options", L"7-Zip", 0); + return; + } + NWindows::NDLL::CLibrary lib; + CMyComPtr pluginOptions; + if (!lib.Load(pluginInfo.FilePath)) + { + MessageBoxW(HWND(*this), L"Can't load plugin", L"7-Zip", 0); + return; + } + typedef UINT32 (WINAPI * CreateObjectPointer)(const GUID *clsID, const GUID *interfaceID, void **outObject); + CreateObjectPointer createObject = (CreateObjectPointer)lib.GetProc("CreateObject"); + if (createObject == NULL) + { + MessageBoxW(HWND(*this), L"Incorrect plugin", L"7-Zip", 0); + return; + } + if (createObject(&pluginInfo.OptionsClassID, &IID_IPluginOptions, (void **)&pluginOptions) != S_OK) + { + MessageBoxW(HWND(*this), L"There are no options", L"7-Zip", 0); + return; + } + CPluginOptionsCallback *callbackSpec = new CPluginOptionsCallback; + CMyComPtr callback(callbackSpec); + callbackSpec->Init(pluginInfo.Name); + pluginOptions->PluginOptions(HWND(*this), callback); +} + +bool CPluginsPage::OnNotify(UINT controlID, LPNMHDR lParam) +{ + if (lParam->hwndFrom == HWND(_listView) && lParam->code == LVN_ITEMCHANGED) + { + const NMLISTVIEW *aNMListView = (const NMLISTVIEW *)lParam; + if ((aNMListView->uChanged & LVIF_STATE) != 0) + { + UINT oldState = aNMListView->uOldState & LVIS_STATEIMAGEMASK; + UINT newState = aNMListView->uNewState & LVIS_STATEIMAGEMASK; + if (oldState != newState) + Changed(); + } + return true; + } + return CPropertyPage::OnNotify(controlID, lParam); +} + +/* +bool CPluginsPage::OnCommand(int code, int itemID, LPARAM lParam) +{ + if (code == CBN_SELCHANGE && itemID == IDC_LANG_COMBO_LANG) + { + Changed(); + return true; + } + return CPropertyPage::OnCommand(code, itemID, lParam); +} + +*/ diff --git a/CPP/7zip/UI/FileManager/PluginsPage.h b/CPP/7zip/UI/FileManager/PluginsPage.h new file mode 100755 index 0000000..a265979 --- /dev/null +++ b/CPP/7zip/UI/FileManager/PluginsPage.h @@ -0,0 +1,26 @@ +// PluginsPage.h + +#include "Windows/Control/ListView.h" + +#ifndef __PLUGINSPAGE_H +#define __PLUGINSPAGE_H + +#include "Windows/Control/PropertyPage.h" +#include "Windows/Control/ComboBox.h" + +#include "RegistryPlugins.h" + +class CPluginsPage: public NWindows::NControl::CPropertyPage +{ + NWindows::NControl::CListView _listView; + CObjectVector _plugins; +public: + virtual bool OnInit(); + virtual void OnNotifyHelp(); + virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); + virtual void OnButtonOptions(); + virtual LONG OnApply(); + virtual bool OnNotify(UINT controlID, LPNMHDR lParam); +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/PluginsPage.rc b/CPP/7zip/UI/FileManager/PluginsPage.rc new file mode 100755 index 0000000..598dedf --- /dev/null +++ b/CPP/7zip/UI/FileManager/PluginsPage.rc @@ -0,0 +1,15 @@ +#include "PluginsPageRes.h" +#include "../../GuiCommon.rc" + +#define xc 96 +#define yc 80 + +IDD_PLUGINS MY_PAGE +CAPTION "Plugins" +BEGIN + LTEXT "&Plugins:", IDC_PLUGINS_STATIC_PLUGINS, m, m, xc, 8 + CONTROL "List1", IDC_PLUGINS_LIST, "SysListView32", + LVS_REPORT | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, + m, 20, xc, 40 + PUSHBUTTON "Options...", IDC_PLUGINS_BUTTON_OPTIONS, m, by, bxs, bys +END diff --git a/CPP/7zip/UI/FileManager/PluginsPageRes.h b/CPP/7zip/UI/FileManager/PluginsPageRes.h new file mode 100755 index 0000000..d7dee12 --- /dev/null +++ b/CPP/7zip/UI/FileManager/PluginsPageRes.h @@ -0,0 +1,4 @@ +#define IDD_PLUGINS 541 +#define IDC_PLUGINS_STATIC_PLUGINS 1000 +#define IDC_PLUGINS_LIST 1001 +#define IDC_PLUGINS_BUTTON_OPTIONS 1002 diff --git a/CPP/7zip/UI/FileManager/ProgramLocation.cpp b/CPP/7zip/UI/FileManager/ProgramLocation.cpp new file mode 100755 index 0000000..a9edf32 --- /dev/null +++ b/CPP/7zip/UI/FileManager/ProgramLocation.cpp @@ -0,0 +1,24 @@ +// ProgramLocation.cpp + +#include "StdAfx.h" + +#include "../../../../C/Types.h" + +#include "ProgramLocation.h" + +#include "Windows/DLL.h" + +using namespace NWindows; + +extern HINSTANCE g_hInstance; + +bool GetProgramFolderPath(UString &folder) +{ + if (!NDLL::MyGetModuleFileName(g_hInstance, folder)) + return false; + int pos = folder.ReverseFind(WCHAR_PATH_SEPARATOR); + if (pos < 0) + return false; + folder = folder.Left(pos + 1); + return true; +} diff --git a/CPP/7zip/UI/FileManager/ProgramLocation.h b/CPP/7zip/UI/FileManager/ProgramLocation.h new file mode 100755 index 0000000..f3e6e6b --- /dev/null +++ b/CPP/7zip/UI/FileManager/ProgramLocation.h @@ -0,0 +1,10 @@ +// ProgramLocation.h + +#ifndef __PROGRAM_LOCATION_H +#define __PROGRAM_LOCATION_H + +#include "Common/MyString.h" + +bool GetProgramFolderPath(UString &folder); // normalized + +#endif diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.cpp b/CPP/7zip/UI/FileManager/ProgressDialog.cpp new file mode 100755 index 0000000..2361972 --- /dev/null +++ b/CPP/7zip/UI/FileManager/ProgressDialog.cpp @@ -0,0 +1,204 @@ +// 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 + +#ifdef LANG +static CIDLangPair kIDLangPairs[] = +{ + { IDCANCEL, 0x02000711 } +}; +#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)-1; + _prevPercentValue = -1; + + _wasCreated = true; + _dialogCreatedEvent.Set(); + + #ifdef LANG + // LangSetWindowText(HWND(*this), 0x02000C00); + LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[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 += L"% "; + 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; + int res = ::MessageBoxW(HWND(*this), L"Are you sure you want to cancel?", _title, MB_YESNOCANCEL); + _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) + { + PostMessage(kCloseMessage); + _needClose = false; + } +} + +bool CProgressDialog::OnExternalCloseMessage() +{ + End(0); + return true; +} diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.h b/CPP/7zip/UI/FileManager/ProgressDialog.h new file mode 100755 index 0000000..e065bee --- /dev/null +++ b/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_DIALOG_PROGRESS, wndParent); + thread.Wait(); + return res; + } + + enum + { + kCloseMessage = WM_USER + 1 + }; + + virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam); + + void ProcessWasFinished() + { + WaitCreating(); + if (_wasCreated) + PostMessage(kCloseMessage); + else + _needClose = true; + }; +}; + + +class CProgressCloser +{ + CProgressDialog *_p; +public: + CProgressCloser(CProgressDialog &p) : _p(&p) {} + ~CProgressCloser() { _p->ProcessWasFinished(); } +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.rc b/CPP/7zip/UI/FileManager/ProgressDialog.rc new file mode 100755 index 0000000..36317f4 --- /dev/null +++ b/CPP/7zip/UI/FileManager/ProgressDialog.rc @@ -0,0 +1,12 @@ +#include "ProgressDialogRes.h" +#include "../../GuiCommon.rc" + +#define xc 172 +#define yc 44 + +IDD_DIALOG_PROGRESS MY_DIALOG +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/CPP/7zip/UI/FileManager/ProgressDialog2.cpp b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp new file mode 100755 index 0000000..3c418a3 --- /dev/null +++ b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp @@ -0,0 +1,1009 @@ +// ProgressDialog2.cpp + +#include "StdAfx.h" + +#include "Common/IntToString.h" +#include "Common/StringConvert.h" + +#include "Windows/Control/Static.h" +#include "Windows/Error.h" + +#include "ProgressDialog2.h" +#include "DialogSize.h" + +#include "ProgressDialog2Res.h" + +#include "../GUI/ExtractRes.h" + +using namespace NWindows; + +extern HINSTANCE g_hInstance; + +static const UINT_PTR kTimerID = 3; + +static const UINT kCloseMessage = WM_USER + 1; + +static const UINT kTimerElapse = + #ifdef UNDER_CE + 500 + #else + 100 + #endif + ; + +#include "LangUtils.h" + +#ifdef LANG +static CIDLangPair kIDLangPairs[] = +{ + { IDCANCEL, 0x02000C00 }, + { IDC_PROGRESS_ELAPSED, 0x02000C01 }, + { IDC_PROGRESS_REMAINING, 0x02000C02 }, + { IDC_PROGRESS_TOTAL, 0x02000C03 }, + { IDC_PROGRESS_SPEED, 0x02000C04 }, + { IDC_PROGRESS_UNPACKED, 0x02000C05 }, + { IDC_PROGRESS_PACKED, 0x02000323 }, + { IDC_PROGRESS_RATIO, 0x02000C06 }, + { IDC_PROGRESS_SPEED, 0x02000C04 }, + { IDC_PROGRESS_FILES, 0x02000320 }, + { IDC_PROGRESS_ERRORS, 0x0308000A }, + { IDC_BUTTON_PROGRESS_PRIORITY, 0x02000C10 }, + { IDC_BUTTON_PAUSE, 0x02000C12 }, + { IDCANCEL, 0x02000711 }, +}; +#endif + +HRESULT CProgressSync::ProcessStopAndPause() +{ + for (;;) + { + if (GetStopped()) + return E_ABORT; + if (!GetPaused()) + break; + ::Sleep(100); + } + return S_OK; +} + +HRESULT CProgressSync::SetPosAndCheckPaused(UInt64 completed) +{ + RINOK(ProcessStopAndPause()); + SetPos(completed); + return S_OK; +} + + +CProgressDialog::CProgressDialog(): _timer(0), CompressingMode(true) + #ifndef _SFX + , MainWindow(0) + #endif + { + 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; + } + +#ifndef _SFX +CProgressDialog::~CProgressDialog() +{ + AddToTitle(L""); +} +void CProgressDialog::AddToTitle(LPCWSTR s) +{ + if (MainWindow != 0) + { + CWindow window(MainWindow); + window.SetText(s + UString(MainTitle)); + } +} + +#endif + +static const int kTitleFileNameSizeLimit = 36; +static const int kCurrentFileNameSizeLimit = 82; + +static void ReduceString(UString &s, int size) +{ + if (s.Length() > size) + s = s.Left(size / 2) + UString(L" ... ") + s.Right(size / 2); +} + +void CProgressDialog::EnableErrorsControls(bool enable) +{ + int cmdShow = enable ? SW_SHOW : SW_HIDE; + ShowItem(IDC_PROGRESS_ERRORS, cmdShow); + ShowItem(IDC_PROGRESS_ERRORS_VALUE, cmdShow); + ShowItem(IDC_PROGRESS_LIST, cmdShow); +} + +bool CProgressDialog::OnInit() +{ + _range = (UInt64)(Int64)-1; + _prevPercentValue = (UInt32)-1; + _prevElapsedSec = (UInt32)-1; + _prevRemainingSec = (UInt32)-1; + _prevSpeed = (UInt32)-1; + _prevMode = kSpeedBytes; + _prevTime = ::GetTickCount(); + _elapsedTime = 0; + _foreground = true; + + m_ProgressBar.Attach(GetItem(IDC_PROGRESS1)); + _messageList.Attach(GetItem(IDC_PROGRESS_LIST)); + + _wasCreated = true; + _dialogCreatedEvent.Set(); + + #ifdef LANG + LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + #endif + + + CWindow window(GetItem(IDC_BUTTON_PROGRESS_PRIORITY)); + window.GetText(backgroundString); + backgroundedString = backgroundString; + backgroundedString.Replace(L"&", L""); + + window = GetItem(IDC_BUTTON_PAUSE); + window.GetText(pauseString); + + foregroundString = LangStringSpec(IDS_PROGRESS_FOREGROUND, 0x02000C11); + continueString = LangStringSpec(IDS_PROGRESS_CONTINUE, 0x02000C13); + pausedString = LangStringSpec(IDS_PROGRESS_PAUSED, 0x02000C20); + + SetText(_title); + SetPauseText(); + SetPriorityText(); + + + #ifndef UNDER_CE + _messageList.SetUnicodeFormat(true); + #endif + + _messageList.InsertColumn(0, L"", 30); + + const UString s = LangStringSpec(IDS_MESSAGES_DIALOG_MESSAGE_COLUMN, 0x02000A80); + + _messageList.InsertColumn(1, s, 600); + + _messageList.SetColumnWidthAuto(0); + _messageList.SetColumnWidthAuto(1); + + + EnableErrorsControls(false); + + GetItemSizes(IDCANCEL, buttonSizeX, buttonSizeY); + _numReduceSymbols = kCurrentFileNameSizeLimit; + NormalizeSize(true); + + if (!ShowCompressionInfo) + { + HideItem(IDC_PROGRESS_PACKED); + HideItem(IDC_PROGRESS_PACKED_VALUE); + HideItem(IDC_PROGRESS_RATIO); + HideItem(IDC_PROGRESS_RATIO_VALUE); + } + + 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(); + + return CModalDialog::OnInit(); +} + +bool CProgressDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) +{ + int sY; + int sStep; + int mx, my; + { + RECT rect; + GetClientRectOfItem(IDC_PROGRESS_ELAPSED, rect); + mx = rect.left; + my = rect.top; + sY = rect.bottom - rect.top; + GetClientRectOfItem(IDC_PROGRESS_REMAINING, rect); + sStep = rect.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(IDC_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 rect; + GetClientRectOfItem(IDC_PROGRESS_LIST, rect); + int y = rect.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(IDC_BUTTON_PAUSE, xPos, yPos, bSizeX, buttonSizeY); + xPos -= (mx2 + bSizeX); + MoveItem(IDC_BUTTON_PROGRESS_PRIORITY, 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_VALUE_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; + + UINT IDs[] = + { + IDC_PROGRESS_ELAPSED, IDC_PROGRESS_ELAPSED_VALUE, + IDC_PROGRESS_REMAINING, IDC_PROGRESS_REMAINING_VALUE, + IDC_PROGRESS_FILES, IDC_PROGRESS_FILES_VALUE, + IDC_PROGRESS_RATIO, IDC_PROGRESS_RATIO_VALUE, + IDC_PROGRESS_ERRORS, IDC_PROGRESS_ERRORS_VALUE, + + IDC_PROGRESS_TOTAL, IDC_PROGRESS_TOTAL_VALUE, + IDC_PROGRESS_SPEED, IDC_PROGRESS_SPEED_VALUE, + IDC_PROGRESS_UNPACKED, IDC_PROGRESS_UNPACKED_VALUE, + IDC_PROGRESS_PACKED, IDC_PROGRESS_PACKED_VALUE + }; + + yPos = my; + for (int i = 0; i < sizeof(IDs) / sizeof(IDs[0]); i += 2) + { + int x = mx; + const int kNumColumn1Items = 5 * 2; + if (i >= kNumColumn1Items) + { + if (i == kNumColumn1Items) + yPos = my; + x = mx + gSize + padSize; + } + MoveItem(IDs[i], x, yPos, labelSize, sY); + MoveItem(IDs[i + 1], x + labelSize, yPos, valueSize, sY); + yPos += sStep; + } + return false; +} + +void CProgressDialog::OnCancel() { Sync.SetStopped(true); } +void CProgressDialog::OnOK() { } + +static void ConvertSizeToString(UInt64 value, wchar_t *s) +{ + const wchar_t *kModif = L" KM"; + for (int i = 0; ; i++) + if (i == 2 || value < (UInt64(10000) << (i * 10))) + { + ConvertUInt64ToString(value >> (i * 10), s); + s += wcslen(s); + *s++ = ' '; + if (i != 0) + *s++ = kModif[i]; + *s++ = L'B'; + *s++ = L'\0'; + return; + } +} + +void CProgressDialog::SetRange(UInt64 range) +{ + _range = range; + _previousPos = (UInt64)(Int64)-1; + _converter.Init(range); + m_ProgressBar.SetRange32(0, _converter.Count(range)); +} + +void CProgressDialog::SetPos(UInt64 pos) +{ + bool redraw = true; + if (pos < _range && pos > _previousPos) + { + if (pos - _previousPos < (_range >> 10)) + redraw = false; + } + if(redraw) + { + m_ProgressBar.SetPos(_converter.Count(pos)); // Test it for 100% + _previousPos = pos; + } +} + +static void GetTimeString(UInt64 timeValue, TCHAR *s) +{ + wsprintf(s, TEXT("%02d:%02d:%02d"), + UInt32(timeValue / 3600), + UInt32((timeValue / 60) % 60), + UInt32(timeValue % 60)); +} + +void CProgressDialog::ShowSize(int id, UInt64 value) +{ + wchar_t s[40]; + s[0] = 0; + if (value != (UInt64)(Int64)-1) + ConvertSizeToString(value, s); + SetItemText(id, s); +} + +void CProgressDialog::UpdateStatInfo(bool showAll) +{ + UInt64 total, completed, totalFiles, completedFiles, inSize, outSize; + bool bytesProgressMode; + Sync.GetProgress(total, completed, totalFiles, completedFiles, inSize, outSize, bytesProgressMode); + + UInt32 curTime = ::GetTickCount(); + + UInt64 progressTotal = bytesProgressMode ? total : totalFiles; + UInt64 progressCompleted = bytesProgressMode ? completed : completedFiles; + + if (progressTotal != _range) + SetRange(progressTotal); + if (progressTotal == (UInt64)(Int64)-1) + { + SetPos(0); + SetRange(progressCompleted); + } + else + SetPos(progressCompleted); + + wchar_t s[32] = { 0 }; + if (total != (UInt64)(Int64)-1) + ConvertSizeToString(total, s); + SetItemText(IDC_PROGRESS_TOTAL_VALUE, s); + + _elapsedTime += (curTime - _prevTime); + _prevTime = curTime; + + UInt32 elapsedSec = _elapsedTime / 1000; + + bool elapsedChanged = false; + if (elapsedSec != _prevElapsedSec) + { + TCHAR s[40]; + GetTimeString(elapsedSec, s); + SetItemText(IDC_PROGRESS_ELAPSED_VALUE, s); + _prevElapsedSec = elapsedSec; + elapsedChanged = true; + } + + if (elapsedChanged || showAll) + { + { + UInt64 numErrors; + + { + NWindows::NSynchronization::CCriticalSectionLock lock(Sync._cs); + numErrors = Sync.Messages.Size(); + } + if (numErrors > 0) + { + UpdateMessagesDialog(); + TCHAR s[40]; + ConvertUInt64ToString(numErrors, s); + SetItemText(IDC_PROGRESS_ERRORS_VALUE, s); + if (!_errorsWereDisplayed) + { + _errorsWereDisplayed = true; + EnableErrorsControls(true); + } + } + } + + if (completed != 0) + { + + if (total == (UInt64)(Int64)-1) + { + SetItemText(IDC_PROGRESS_REMAINING_VALUE, L""); + } + else + { + UInt64 remainingTime = 0; + if (completed < total) + remainingTime = _elapsedTime * (total - completed) / completed; + UInt64 remainingSec = remainingTime / 1000; + if (remainingSec != _prevRemainingSec) + { + TCHAR s[40]; + GetTimeString(remainingSec, s); + SetItemText(IDC_PROGRESS_REMAINING_VALUE, s); + _prevRemainingSec = remainingSec; + } + } + { + UInt32 elapsedTime = (_elapsedTime == 0) ? 1 : _elapsedTime; + UInt64 speedB = (completed * 1000) / elapsedTime; + UInt64 speedKB = speedB / 1024; + UInt64 speedMB = speedKB / 1024; + const UInt32 kLimit1 = 10; + TCHAR s[40]; + bool needRedraw = false; + if (speedMB >= kLimit1) + { + if (_prevMode != kSpeedMBytes || speedMB != _prevSpeed) + { + ConvertUInt64ToString(speedMB, s); + lstrcat(s, TEXT(" MB/s")); + _prevMode = kSpeedMBytes; + _prevSpeed = speedMB; + needRedraw = true; + } + } + else if (speedKB >= kLimit1) + { + if (_prevMode != kSpeedKBytes || speedKB != _prevSpeed) + { + ConvertUInt64ToString(speedKB, s); + lstrcat(s, TEXT(" KB/s")); + _prevMode = kSpeedKBytes; + _prevSpeed = speedKB; + needRedraw = true; + } + } + else + { + if (_prevMode != kSpeedBytes || speedB != _prevSpeed) + { + ConvertUInt64ToString(speedB, s); + lstrcat(s, TEXT(" B/s")); + _prevMode = kSpeedBytes; + _prevSpeed = speedB; + needRedraw = true; + } + } + if (needRedraw) + SetItemText(IDC_PROGRESS_SPEED_VALUE, s); + } + } + + if (total == 0) + total = 1; + UInt32 percentValue = (UInt32)(completed * 100 / total); + UString titleName; + Sync.GetTitleFileName(titleName); + if (percentValue != _prevPercentValue || _prevTitleName != titleName) + { + _prevPercentValue = percentValue; + SetTitleText(); + _prevTitleName = titleName; + } + + TCHAR s[64]; + ConvertUInt64ToString(completedFiles, s); + if (totalFiles != (UInt64)(Int64)-1) + { + lstrcat(s, TEXT(" / ")); + ConvertUInt64ToString(totalFiles, s + lstrlen(s)); + } + + SetItemText(IDC_PROGRESS_FILES_VALUE, s); + + const UInt64 packSize = CompressingMode ? outSize : inSize; + const UInt64 unpackSize = CompressingMode ? inSize : outSize; + + if (unpackSize == (UInt64)(Int64)-1 && packSize == (UInt64)(Int64)-1) + { + ShowSize(IDC_PROGRESS_UNPACKED_VALUE, completed); + SetItemText(IDC_PROGRESS_PACKED_VALUE, L""); + } + else + { + ShowSize(IDC_PROGRESS_UNPACKED_VALUE, unpackSize); + ShowSize(IDC_PROGRESS_PACKED_VALUE, packSize); + + if (packSize != (UInt64)(Int64)-1 && unpackSize != (UInt64)(Int64)-1 && unpackSize != 0) + { + UInt64 ratio = packSize * 100 / unpackSize; + ConvertUInt64ToString(ratio, s); + lstrcat(s, TEXT("%")); + SetItemText(IDC_PROGRESS_RATIO_VALUE, s); + } + } + } + + + UString fileName; + Sync.GetCurrentFileName(fileName); + if (_prevFileName != fileName) + { + int slashPos = fileName.ReverseFind(WCHAR_PATH_SEPARATOR); + UString s1, s2; + if (slashPos >= 0) + { + s1 = fileName.Left(slashPos + 1); + s2 = fileName.Mid(slashPos + 1); + } + else + s2 = fileName; + ReduceString(s1, _numReduceSymbols); + ReduceString(s2, _numReduceSymbols); + UString s = s1 + L"\n" + s2; + SetItemText(IDC_PROGRESS_FILE_NAME, s); + _prevFileName == fileName; + } +} + +bool CProgressDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */) +{ + if (Sync.GetPaused()) + 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 res = WaitForMultipleObjects(sizeof(h) / sizeof(h[0]), h, FALSE, + #ifdef UNDER_CE + 2500 + #else + 1000 + #endif + ); + if (res == WAIT_OBJECT_0 && !Sync.ThereIsMessage()) + return 0; + } + _title = title; + BIG_DIALOG_SIZE(360, 192); + res = CModalDialog::Create(SIZED_DIALOG(IDD_DIALOG_PROGRESS), wndParent); + } + catch(...) + { + _wasCreated = true; + _dialogCreatedEvent.Set(); + res = res; + } + thread.Wait(); + if (!MessagesDisplayed) + MessageBoxW(wndParent, L"Progress Error", L"7-Zip", MB_ICONERROR | MB_OK); + return res; +} + +bool CProgressDialog::OnExternalCloseMessage() +{ + UpdateStatInfo(true); + + HideItem(IDC_BUTTON_PROGRESS_PRIORITY); + HideItem(IDC_BUTTON_PAUSE); + SetItemText(IDCANCEL, LangStringSpec(IDS_CLOSE, 0x02000713)); + + bool thereAreMessages; + UString okMessage; + UString okMessageTitle; + UString errorMessage; + UString errorMessageTitle; + { + NWindows::NSynchronization::CCriticalSectionLock lock(Sync._cs); + errorMessage = Sync.ErrorMessage; + errorMessageTitle = Sync.ErrorMessageTitle; + okMessage = Sync.OkMessage; + okMessageTitle = Sync.OkMessageTitle; + thereAreMessages = !Sync.Messages.IsEmpty(); + } + if (!errorMessage.IsEmpty()) + { + MessagesDisplayed = true; + if (errorMessageTitle.IsEmpty()) + errorMessageTitle = L"7-Zip"; + MessageBoxW(*this, errorMessage, errorMessageTitle, MB_ICONERROR | MB_OK); + } + else if (!thereAreMessages) + { + MessagesDisplayed = true; + if (!okMessage.IsEmpty()) + { + if (okMessageTitle.IsEmpty()) + okMessageTitle = L"7-Zip"; + MessageBoxW(*this, okMessage, okMessageTitle, 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 title; + if (Sync.GetPaused()) + { + title = pausedString; + title += L' '; + } + if (_prevPercentValue != (UInt32)-1) + { + wchar_t s[64]; + ConvertUInt64ToString(_prevPercentValue, s); + title += s; + title += L'%'; + } + if (!_foreground) + { + title += L' '; + title += backgroundedString; + } + title += L' '; + UString totalTitle = title + _title; + UString fileName; + Sync.GetTitleFileName(fileName); + if (!fileName.IsEmpty()) + { + ReduceString(fileName, kTitleFileNameSizeLimit); + totalTitle += L' '; + totalTitle += fileName; + } + SetText(totalTitle); + #ifndef _SFX + AddToTitle(title + MainAddTitle); + #endif +} + +void CProgressDialog::SetPauseText() +{ + SetItemText(IDC_BUTTON_PAUSE, Sync.GetPaused() ? + continueString : pauseString); + SetTitleText(); +} + +void CProgressDialog::OnPauseButton() +{ + bool paused = !Sync.GetPaused(); + Sync.SetPaused(paused); + UInt32 curTime = ::GetTickCount(); + if (paused) + _elapsedTime += (curTime - _prevTime); + _prevTime = curTime; + SetPauseText(); +} + +void CProgressDialog::SetPriorityText() +{ + SetItemText(IDC_BUTTON_PROGRESS_PRIORITY, _foreground ? + backgroundString : + foregroundString); + 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) +{ + int itemIndex = _messageList.GetItemCount(); + wchar_t sz[32]; + ConvertInt64ToString(itemIndex, sz); + _messageList.InsertItem(itemIndex, sz); + _messageList.SetSubItem(itemIndex, 1, message); +} + +void CProgressDialog::AddMessage(LPCWSTR message) +{ + UString s = message; + while (!s.IsEmpty()) + { + int pos = s.Find(L'\n'); + if (pos < 0) + break; + AddMessageDirect(s.Left(pos)); + s.Delete(0, pos + 1); + } + AddMessageDirect(s); +} + +static unsigned GetNumDigits(UInt32 value) +{ + unsigned i; + for (i = 0; value >= 10; i++) + value /= 10; + return i; +} + +void CProgressDialog::UpdateMessagesDialog() +{ + UStringVector messages; + { + NWindows::NSynchronization::CCriticalSectionLock lock(Sync._cs); + for (int i = _numPostedMessages; i < Sync.Messages.Size(); i++) + messages.Add(Sync.Messages[i]); + _numPostedMessages = Sync.Messages.Size(); + } + if (!messages.IsEmpty()) + { + for (int i = 0; i < messages.Size(); i++) + 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.GetPaused(); + if (!paused) + OnPauseButton(); + _inCancelMessageBox = true; + int res = ::MessageBoxW(HWND(*this), + LangStringSpec(IDS_PROGRESS_ASK_CANCEL, 0x02000C30), + _title, MB_YESNOCANCEL); + _inCancelMessageBox = false; + if (!paused) + OnPauseButton(); + if (res == IDCANCEL || res == IDNO) + { + if (_externalCloseMessageWasReceived) + OnExternalCloseMessage(); + return true; + } + + _cancelWasPressed = true; + MessagesDisplayed = true; + break; + } + + case IDC_BUTTON_PAUSE: + OnPauseButton(); + return true; + case IDC_BUTTON_PROGRESS_PRIORITY: + OnPriorityButton(); + return true; + } + return CModalDialog::OnButtonClicked(buttonID, buttonHWND); +} + +void CProgressDialog::CheckNeedClose() +{ + if (_needClose) + { + PostMessage(kCloseMessage); + _needClose = false; + } +} + +void CProgressDialog::ProcessWasFinished() +{ + // Set Window title here. + if (!WaitMode) + WaitCreating(); + + if (_wasCreated) + PostMessage(kCloseMessage); + else + _needClose = true; +} + + +HRESULT CProgressThreadVirt::Create(const UString &title, HWND parentWindow) +{ + NWindows::CThread thread; + RINOK(thread.Create(MyThreadFunction, this)); + ProgressDialog.Create(title, thread, parentWindow); + return S_OK; +} + +UString HResultToMessage(HRESULT errorCode) +{ + UString message; + if (errorCode == E_OUTOFMEMORY) + message = LangStringSpec(IDS_MEM_ERROR, 0x0200060B); + else if (!NError::MyFormatMessage(errorCode, message)) + message.Empty(); + if (message.IsEmpty()) + message = L"Error"; + return message; +} + +static void AddMessageToString(UString &dest, const UString &src) +{ + if (!src.IsEmpty()) + { + if (!dest.IsEmpty()) + dest += L'\n'; + dest += src; + } +} + +void CProgressThreadVirt::Process() +{ + CProgressCloser closer(ProgressDialog); + 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(...) { m = L"Error"; } + if (Result != E_ABORT) + { + if (m.IsEmpty() && Result != S_OK) + m = HResultToMessage(Result); + } + AddMessageToString(m, ErrorMessage); + AddMessageToString(m, ErrorPath1); + AddMessageToString(m, ErrorPath2); + + if (m.IsEmpty()) + { + if (!OkMessage.IsEmpty()) + { + ProgressDialog.Sync.SetOkMessageTitle(OkMessageTitle); + ProgressDialog.Sync.SetOkMessage(OkMessage); + } + } + else + { + ProgressDialog.Sync.SetErrorMessage(m); + if (Result == S_OK) + Result = E_FAIL; + } +} diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.h b/CPP/7zip/UI/FileManager/ProgressDialog2.h new file mode 100755 index 0000000..52b20ce --- /dev/null +++ b/CPP/7zip/UI/FileManager/ProgressDialog2.h @@ -0,0 +1,359 @@ +// ProgressDialog2.h + +#ifndef __PROGRESS_DIALOG2_H +#define __PROGRESS_DIALOG2_H + +#include "Windows/Synchronization.h" +#include "Windows/Thread.h" + +#include "Windows/Control/Dialog.h" +#include "Windows/Control/ListView.h" +#include "Windows/Control/ProgressBar.h" + +class CProgressSync +{ + bool _stopped; + bool _paused; + bool _bytesProgressMode; + + UInt64 _totalBytes; + UInt64 _curBytes; + UInt64 _totalFiles; + UInt64 _curFiles; + UInt64 _inSize; + UInt64 _outSize; + + UString _titleFileName; + UString _currentFileName; + +public: + UStringVector Messages; + UString ErrorMessage; + UString ErrorMessageTitle; + + UString OkMessage; + UString OkMessageTitle; + + NWindows::NSynchronization::CCriticalSection _cs; + + CProgressSync(): + _stopped(false), _paused(false), + _totalBytes((UInt64)(Int64)-1), _curBytes(0), + _totalFiles((UInt64)(Int64)-1), _curFiles(0), + _inSize((UInt64)(Int64)-1), + _outSize((UInt64)(Int64)-1), + _bytesProgressMode(true) + {} + + 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 SetBytesProgressMode(bool bytesProgressMode) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + _bytesProgressMode = bytesProgressMode; + } + void SetProgress(UInt64 total, UInt64 completed) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + _totalBytes = total; + _curBytes = completed; + } + void SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + if (inSize) + _inSize = *inSize; + if (outSize) + _outSize = *outSize; + } + void SetPos(UInt64 completed) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + _curBytes = completed; + } + void SetNumBytesTotal(UInt64 value) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + _totalBytes = value; + } + void SetNumFilesTotal(UInt64 value) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + _totalFiles = value; + } + void SetNumFilesCur(UInt64 value) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + _curFiles = value; + } + HRESULT ProcessStopAndPause(); + HRESULT SetPosAndCheckPaused(UInt64 completed); + void GetProgress(UInt64 &total, UInt64 &completed, + UInt64 &totalFiles, UInt64 &curFiles, + UInt64 &inSize, UInt64 &outSize, + bool &bytesProgressMode) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + total = _totalBytes; + completed = _curBytes; + totalFiles = _totalFiles; + curFiles = _curFiles; + inSize = _inSize; + outSize = _outSize; + bytesProgressMode = _bytesProgressMode; + } + void SetTitleFileName(const UString &fileName) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + _titleFileName = fileName; + } + void GetTitleFileName(UString &fileName) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + fileName = _titleFileName; + } + void SetCurrentFileName(const UString &fileName) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + _currentFileName = fileName; + } + void GetCurrentFileName(UString &fileName) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + fileName = _currentFileName; + } + + void AddErrorMessage(LPCWSTR message) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + Messages.Add(message); + } + + void SetErrorMessage(const UString &message) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + ErrorMessage = message; + } + + void SetOkMessage(const UString &message) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + OkMessage = message; + } + + void SetOkMessageTitle(const UString &title) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + OkMessageTitle = title; + } + + void SetErrorMessageTitle(const UString &title) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + ErrorMessageTitle = title; + } + + bool ThereIsMessage() const + { + return !Messages.IsEmpty() || !ErrorMessage.IsEmpty() || !OkMessage.IsEmpty(); + } +}; + +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); } +}; + +enum ESpeedMode +{ + kSpeedBytes, + kSpeedKBytes, + kSpeedMBytes +}; + +class CProgressDialog: public NWindows::NControl::CModalDialog +{ + UString _prevFileName; + UString _prevTitleName; +private: + UString backgroundString; + UString backgroundedString; + UString foregroundString; + UString pauseString; + UString continueString; + UString pausedString; + + int buttonSizeX; + int buttonSizeY; + + UINT_PTR _timer; + + UString _title; + CU64ToI32Converter _converter; + UInt64 _previousPos; + UInt64 _range; + NWindows::NControl::CProgressBar m_ProgressBar; + NWindows::NControl::CListView _messageList; + + UInt32 _prevPercentValue; + UInt32 _prevTime; + UInt32 _elapsedTime; + UInt32 _prevElapsedSec; + UInt64 _prevRemainingSec; + ESpeedMode _prevMode; + UInt64 _prevSpeed; + + bool _foreground; + + int _numReduceSymbols; + + bool _wasCreated; + bool _needClose; + + UInt32 _numPostedMessages; + UInt32 _numAutoSizeMessages; + + bool _errorsWereDisplayed; + + bool _waitCloseByCancelButton; + bool _cancelWasPressed; + + bool _inCancelMessageBox; + bool _externalCloseMessageWasReceived; + + void UpdateStatInfo(bool showAll); + bool OnTimer(WPARAM timerID, LPARAM callback); + void SetRange(UInt64 range); + void SetPos(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); + + void SetTitleText(); + void ShowSize(int id, UInt64 value); + + void UpdateMessagesDialog(); + + void AddMessageDirect(LPCWSTR message); + 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; + + #ifndef _SFX + HWND MainWindow; + 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); + + + virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam); + + void ProcessWasFinished(); +}; + + +class CProgressCloser +{ + CProgressDialog *_p; +public: + CProgressCloser(CProgressDialog &p) : _p(&p) {} + ~CProgressCloser() { _p->ProcessWasFinished(); } +}; + +class CProgressThreadVirt +{ +protected: + UString ErrorMessage; + UString ErrorPath1; + UString ErrorPath2; + UString OkMessage; + UString OkMessageTitle; + + // error if any of HRESULT, ErrorMessage, ErrorPath + virtual HRESULT ProcessVirt() = 0; + void Process(); +public: + HRESULT Result; + bool ThreadFinishedOK; // if there is no fatal exception + CProgressDialog ProgressDialog; + + 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 Create(const UString &title, HWND parentWindow = 0); + CProgressThreadVirt(): Result(E_FAIL), ThreadFinishedOK(false) {} +}; + +UString HResultToMessage(HRESULT errorCode); + +#endif diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.rc b/CPP/7zip/UI/FileManager/ProgressDialog2.rc new file mode 100755 index 0000000..51b7a08 --- /dev/null +++ b/CPP/7zip/UI/FileManager/ProgressDialog2.rc @@ -0,0 +1,41 @@ +#include "ProgressDialog2Res.h" +#include "../../GuiCommon.rc" + +#undef DIALOG_ID +#define DIALOG_ID IDD_DIALOG_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_DIALOG_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_PROGRESS_CONTINUE "&Continue" + IDS_PROGRESS_ASK_CANCEL "Are you sure you want to cancel?" + IDS_CLOSE "&Close" + IDS_MESSAGES_DIALOG_MESSAGE_COLUMN "Message" +} diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2Res.h b/CPP/7zip/UI/FileManager/ProgressDialog2Res.h new file mode 100755 index 0000000..2282bc6 --- /dev/null +++ b/CPP/7zip/UI/FileManager/ProgressDialog2Res.h @@ -0,0 +1,41 @@ +#define IDD_DIALOG_PROGRESS 500 +#define IDD_DIALOG_PROGRESS_2 600 + +#define IDC_BUTTON_PAUSE 50 +#define IDC_BUTTON_PROGRESS_PRIORITY 51 + +#define IDS_PROGRESS_PAUSED 700 +#define IDS_PROGRESS_FOREGROUND 701 +#define IDS_PROGRESS_CONTINUE 702 +#define IDS_PROGRESS_ASK_CANCEL 703 +#define IDS_CLOSE 704 +#define IDS_MESSAGES_DIALOG_MESSAGE_COLUMN 503 + +#define IDC_PROGRESS1 1000 +#define IDC_PROGRESS_ELAPSED 1002 +#define IDC_PROGRESS_ELAPSED_VALUE 1003 +#define IDC_PROGRESS_REMAINING 1004 +#define IDC_PROGRESS_REMAINING_VALUE 1005 +#define IDC_PROGRESS_SPEED 1006 +#define IDC_PROGRESS_SPEED_VALUE 1007 +#define IDC_PROGRESS_TOTAL 1008 +#define IDC_PROGRESS_TOTAL_VALUE 1009 +#define IDC_PROGRESS_FILE_NAME 1010 + +#define IDC_PROGRESS_FILES 1012 +#define IDC_PROGRESS_FILES_VALUE 1013 +#define IDC_PROGRESS_RATIO 1014 +#define IDC_PROGRESS_RATIO_VALUE 1015 +#define IDC_PROGRESS_PACKED 1016 +#define IDC_PROGRESS_PACKED_VALUE 1017 +#define IDC_PROGRESS_UNPACKED 1018 +#define IDC_PROGRESS_UNPACKED_VALUE 1019 + +#define IDC_PROGRESS_ERRORS 1030 +#define IDC_PROGRESS_ERRORS_VALUE 1031 +#define IDC_PROGRESS_LIST 1032 + +#define MY_PROGRESS_VALUE_UNITS 44 +#define MY_PROGRESS_LABEL_UNITS_MIN 60 +#define MY_PROGRESS_LABEL_UNITS_START 90 +#define MY_PROGRESS_PAD_UNITS 4 diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2a.rc b/CPP/7zip/UI/FileManager/ProgressDialog2a.rc new file mode 100755 index 0000000..9ae7122 --- /dev/null +++ b/CPP/7zip/UI/FileManager/ProgressDialog2a.rc @@ -0,0 +1,78 @@ +#undef bxs +#define bxs 80 + +#define x0s MY_PROGRESS_LABEL_UNITS_START +#define x1s MY_PROGRESS_VALUE_UNITS +#define x2s MY_PROGRESS_LABEL_UNITS_START +#define x3s MY_PROGRESS_VALUE_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 z0z +#undef z1 +#undef z2 +#undef z2 + +#define y0 m +#define y1 (y0 + k) +#define y2 (y1 + k) +#define y3 (y2 + k) +#define y4 (y3 + k) + +#define z2 (y4 + k + 1) +#define z2s 24 + +#define z1 (z2 + z2s) + +#define z0 (z1 + z1s + m) +#define z0s 48 + +#define yc (z0 + z0s + bys) + + +DIALOG_ID MY_RESIZE_DIALOG +CAPTION "Progress" +{ + PUSHBUTTON "&Background", IDC_BUTTON_PROGRESS_PRIORITY, bx3, by, bxs, bys + PUSHBUTTON "&Pause", IDC_BUTTON_PAUSE, bx2, by, bxs, bys + DEFPUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys + + LTEXT "Elapsed time:", IDC_PROGRESS_ELAPSED, m, y0, x0s, 8 + LTEXT "Remaining time:", IDC_PROGRESS_REMAINING, m, y1, x0s, 8 + LTEXT "Files:", IDC_PROGRESS_FILES, m, y2, x0s, 8 + LTEXT "Compression ratio:",IDC_PROGRESS_RATIO, m, y3, x0s, 8 + LTEXT "Errors:", IDC_PROGRESS_ERRORS, m, y4, x0s, 8 + + LTEXT "Total size:", IDC_PROGRESS_TOTAL, x2, y0, x2s, 8 + LTEXT "Speed:", IDC_PROGRESS_SPEED, x2, y1, x2s, 8 + LTEXT "Processed:", IDC_PROGRESS_UNPACKED, x2, y2, x2s, 8 + LTEXT "Compressed size:", IDC_PROGRESS_PACKED, x2, y3, x2s, 8 + + RTEXT "", IDC_PROGRESS_ELAPSED_VALUE, x1, y0, x1s, 8 + RTEXT "", IDC_PROGRESS_REMAINING_VALUE, x1, y1, x1s, 8 + RTEXT "", IDC_PROGRESS_FILES_VALUE, x1, y2, x1s, 8 + RTEXT "", IDC_PROGRESS_RATIO_VALUE, x1, y3, x1s, 8 + RTEXT "", IDC_PROGRESS_ERRORS_VALUE, x1, y4, x1s, 8 + + RTEXT "", IDC_PROGRESS_TOTAL_VALUE, x3, y0, x3s, 8 + RTEXT "", IDC_PROGRESS_SPEED_VALUE, x3, y1, x3s, 8 + RTEXT "", IDC_PROGRESS_UNPACKED_VALUE, x3, y2, x3s, 8 + RTEXT "", IDC_PROGRESS_PACKED_VALUE, x3, y3, x3s, 8 + + LTEXT "", IDC_PROGRESS_FILE_NAME, m, z2, xc, z2s, SS_NOPREFIX | SS_LEFTNOWORDWRAP + CONTROL "Progress1", IDC_PROGRESS1, "msctls_progress32", PBS_SMOOTH | WS_BORDER, m, z1, xc, z1s + + + CONTROL "List1", IDC_PROGRESS_LIST, "SysListView32", + LVS_REPORT | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, + m, z0, xc, z0s +} diff --git a/CPP/7zip/UI/FileManager/ProgressDialogRes.h b/CPP/7zip/UI/FileManager/ProgressDialogRes.h new file mode 100755 index 0000000..7f98281 --- /dev/null +++ b/CPP/7zip/UI/FileManager/ProgressDialogRes.h @@ -0,0 +1,3 @@ +#define IDD_DIALOG_PROGRESS 500 + +#define IDC_PROGRESS1 1000 diff --git a/CPP/7zip/UI/FileManager/PropertyName.cpp b/CPP/7zip/UI/FileManager/PropertyName.cpp new file mode 100755 index 0000000..a6bac78 --- /dev/null +++ b/CPP/7zip/UI/FileManager/PropertyName.cpp @@ -0,0 +1,110 @@ +// PropertyName.cpp + +#include "StdAfx.h" + +#include "Common/IntToString.h" + +#include "Windows/ResourceString.h" + +#include "../../PropID.h" + +#include "LangUtils.h" +#include "PropertyName.h" + +#include "resource.h" +#include "PropertyNameRes.h" + +struct CPropertyIDNamePair +{ + PROPID PropID; + UINT ResourceID; + UInt32 LangID; +}; + +static CPropertyIDNamePair kPropertyIDNamePairs[] = +{ + { kpidPath, IDS_PROP_PATH, 0x02000203 }, + { kpidName, IDS_PROP_NAME, 0x02000204 }, + { kpidExtension, IDS_PROP_EXTENSION, 0x02000205 }, + { kpidIsDir, IDS_PROP_IS_FOLDER, 0x02000206}, + { kpidSize, IDS_PROP_SIZE, 0x02000207}, + { kpidPackSize, IDS_PROP_PACKED_SIZE, 0x02000208 }, + { kpidAttrib, IDS_PROP_ATTRIBUTES, 0x02000209 }, + { kpidCTime, IDS_PROP_CTIME, 0x0200020A }, + { kpidATime, IDS_PROP_ATIME, 0x0200020B }, + { kpidMTime, IDS_PROP_MTIME, 0x0200020C }, + { kpidSolid, IDS_PROP_SOLID, 0x0200020D }, + { kpidCommented, IDS_PROP_C0MMENTED, 0x0200020E }, + { kpidEncrypted, IDS_PROP_ENCRYPTED, 0x0200020F }, + { kpidSplitBefore, IDS_PROP_SPLIT_BEFORE, 0x02000210 }, + { kpidSplitAfter, IDS_PROP_SPLIT_AFTER, 0x02000211 }, + { kpidDictionarySize, IDS_PROP_DICTIONARY_SIZE, 0x02000212 }, + { kpidCRC, IDS_PROP_CRC, 0x02000213 }, + { kpidType, IDS_PROP_FILE_TYPE, 0x02000214}, + { kpidIsAnti, IDS_PROP_ANTI, 0x02000215 }, + { kpidMethod, IDS_PROP_METHOD, 0x02000216 }, + { kpidHostOS, IDS_PROP_HOST_OS, 0x02000217 }, + { kpidFileSystem, IDS_PROP_FILE_SYSTEM, 0x02000218}, + { kpidUser, IDS_PROP_USER, 0x02000219}, + { kpidGroup, IDS_PROP_GROUP, 0x0200021A}, + { kpidBlock, IDS_PROP_BLOCK, 0x0200021B }, + { kpidComment, IDS_PROP_COMMENT, 0x0200021C }, + { kpidPosition, IDS_PROP_POSITION, 0x0200021D }, + { kpidPrefix, IDS_PROP_PREFIX, 0x0200021E }, + { kpidNumSubDirs, IDS_PROP_FOLDERS, 0x0200021F }, + { kpidNumSubFiles, IDS_PROP_FILES, 0x02000220 }, + { kpidUnpackVer, IDS_PROP_VERSION, 0x02000221}, + { kpidVolume, IDS_PROP_VOLUME, 0x02000222}, + { kpidIsVolume, IDS_PROP_IS_VOLUME, 0x02000223}, + { kpidOffset, IDS_PROP_OFFSET, 0x02000224}, + { kpidLinks, IDS_PROP_LINKS, 0x02000225}, + { kpidNumBlocks, IDS_PROP_NUM_BLOCKS, 0x02000226}, + { kpidNumVolumes, IDS_PROP_NUM_VOLUMES, 0x02000227}, + + { kpidBit64, IDS_PROP_BIT64, 0x02000229}, + { kpidBigEndian, IDS_PROP_BIG_ENDIAN, 0x0200022A}, + { kpidCpu, IDS_PROP_CPU, 0x0200022B}, + { kpidPhySize, IDS_PROP_PHY_SIZE, 0x0200022C}, + { kpidHeadersSize, IDS_PROP_HEADERS_SIZE, 0x0200022D}, + { kpidChecksum, IDS_PROP_CHECKSUM, 0x0200022E}, + { kpidCharacts, IDS_PROP_CHARACTS, 0x0200022F}, + { kpidVa, IDS_PROP_VA, 0x02000230}, + { kpidId, IDS_PROP_ID, 0x02000231 }, + { kpidShortName, IDS_PROP_SHORT_NAME, 0x02000232 }, + { kpidCreatorApp, IDS_PROP_CREATOR_APP, 0x02000233 }, + { kpidSectorSize, IDS_PROP_SECTOR_SIZE, 0x02000234 }, + { kpidPosixAttrib, IDS_PROP_POSIX_ATTRIB, 0x02000235 }, + { kpidLink, IDS_PROP_LINK, 0x02000236 }, + { kpidError, IDS_PROP_ERROR, 0x02000605 }, + + { kpidTotalSize, IDS_PROP_TOTAL_SIZE, 0x03031100 }, + { kpidFreeSpace, IDS_PROP_FREE_SPACE, 0x03031101 }, + { kpidClusterSize, IDS_PROP_CLUSTER_SIZE, 0x03031102}, + { kpidVolumeName, IDS_PROP_VOLUME_NAME, 0x03031103 }, + + { kpidLocalName, IDS_PROP_LOCAL_NAME, 0x03031200 }, + { kpidProvider, IDS_PROP_PROVIDER, 0x03031201 } +}; + +int FindProperty(PROPID propID) +{ + for (int i = 0; i < sizeof(kPropertyIDNamePairs) / sizeof(kPropertyIDNamePairs[0]); i++) + if (kPropertyIDNamePairs[i].PropID == propID) + return i; + return -1; +} + +UString GetNameOfProperty(PROPID propID, const wchar_t *name) +{ + int index = FindProperty(propID); + if (index < 0) + { + if (name) + return name; + wchar_t s[16]; + ConvertUInt32ToString(propID, s); + return s; + } + const CPropertyIDNamePair &pair = kPropertyIDNamePairs[index]; + return LangString(pair.ResourceID, pair.LangID); +} diff --git a/CPP/7zip/UI/FileManager/PropertyName.h b/CPP/7zip/UI/FileManager/PropertyName.h new file mode 100755 index 0000000..9a590b4 --- /dev/null +++ b/CPP/7zip/UI/FileManager/PropertyName.h @@ -0,0 +1,10 @@ +// PropertyName.h + +#ifndef __PROPERTYNAME_H +#define __PROPERTYNAME_H + +#include "Common/MyString.h" + +UString GetNameOfProperty(PROPID propID, const wchar_t *name); + +#endif diff --git a/CPP/7zip/UI/FileManager/PropertyName.rc b/CPP/7zip/UI/FileManager/PropertyName.rc new file mode 100755 index 0000000..625b427 --- /dev/null +++ b/CPP/7zip/UI/FileManager/PropertyName.rc @@ -0,0 +1,60 @@ +#include "PropertyNameRes.h" + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +STRINGTABLE +BEGIN + IDS_PROP_PATH "Path" + IDS_PROP_NAME "Name" + IDS_PROP_EXTENSION "Extension" + IDS_PROP_IS_FOLDER "Folder" + IDS_PROP_SIZE "Size" + IDS_PROP_PACKED_SIZE "Packed Size" + IDS_PROP_ATTRIBUTES "Attributes" + IDS_PROP_CTIME "Created" + IDS_PROP_ATIME "Accessed" + IDS_PROP_MTIME "Modified" + IDS_PROP_SOLID "Solid" + IDS_PROP_C0MMENTED "Commented" + IDS_PROP_ENCRYPTED "Encrypted" + IDS_PROP_DICTIONARY_SIZE "Dictionary Size" + IDS_PROP_SPLIT_BEFORE "Split Before" + IDS_PROP_SPLIT_AFTER "Split After" + IDS_PROP_CRC "CRC" + IDS_PROP_FILE_TYPE "Type" + IDS_PROP_ANTI "Anti" + IDS_PROP_METHOD "Method" + IDS_PROP_HOST_OS "Host OS" + IDS_PROP_FILE_SYSTEM "File System" + IDS_PROP_USER "User" + IDS_PROP_GROUP "Group" + IDS_PROP_BLOCK "Block" + IDS_PROP_COMMENT "Comment" + IDS_PROP_POSITION "Position" + IDS_PROP_PREFIX "Path Prefix" + IDS_PROP_FOLDERS "Folders" + IDS_PROP_FILES "Files" + IDS_PROP_VERSION "Version" + IDS_PROP_VOLUME "Volume" + IDS_PROP_IS_VOLUME "Multivolume" + IDS_PROP_OFFSET "Offset" + IDS_PROP_LINKS "Links" + IDS_PROP_NUM_BLOCKS "Blocks" + IDS_PROP_NUM_VOLUMES "Volumes" + + IDS_PROP_BIT64 "64-bit" + IDS_PROP_BIG_ENDIAN "Big-endian" + IDS_PROP_CPU "CPU" + IDS_PROP_PHY_SIZE "Physical Size" + IDS_PROP_HEADERS_SIZE "Headers Size" + IDS_PROP_CHECKSUM "Checksum" + IDS_PROP_CHARACTS "Characteristics" + IDS_PROP_VA "Virtual Address" + IDS_PROP_ID "ID" + IDS_PROP_SHORT_NAME "Short Name" + IDS_PROP_CREATOR_APP "Creator Application" + IDS_PROP_SECTOR_SIZE "Sector Size" + IDS_PROP_POSIX_ATTRIB "Mode" + IDS_PROP_LINK "Link" + IDS_PROP_ERROR "Error" +END diff --git a/CPP/7zip/UI/FileManager/PropertyNameRes.h b/CPP/7zip/UI/FileManager/PropertyNameRes.h new file mode 100755 index 0000000..7859657 --- /dev/null +++ b/CPP/7zip/UI/FileManager/PropertyNameRes.h @@ -0,0 +1,53 @@ +#define IDS_PROP_PATH 3 +#define IDS_PROP_NAME 4 +#define IDS_PROP_EXTENSION 5 +#define IDS_PROP_IS_FOLDER 6 +#define IDS_PROP_SIZE 7 +#define IDS_PROP_PACKED_SIZE 8 +#define IDS_PROP_ATTRIBUTES 9 +#define IDS_PROP_CTIME 10 +#define IDS_PROP_ATIME 11 +#define IDS_PROP_MTIME 12 +#define IDS_PROP_SOLID 13 +#define IDS_PROP_C0MMENTED 14 +#define IDS_PROP_ENCRYPTED 15 +#define IDS_PROP_DICTIONARY_SIZE 16 +#define IDS_PROP_SPLIT_BEFORE 17 +#define IDS_PROP_SPLIT_AFTER 18 +#define IDS_PROP_CRC 19 +#define IDS_PROP_FILE_TYPE 20 +#define IDS_PROP_ANTI 21 +#define IDS_PROP_METHOD 22 +#define IDS_PROP_HOST_OS 23 +#define IDS_PROP_FILE_SYSTEM 24 +#define IDS_PROP_USER 25 +#define IDS_PROP_GROUP 26 +#define IDS_PROP_BLOCK 27 +#define IDS_PROP_COMMENT 28 +#define IDS_PROP_POSITION 29 +#define IDS_PROP_PREFIX 30 +#define IDS_PROP_FOLDERS 31 +#define IDS_PROP_FILES 32 +#define IDS_PROP_VERSION 33 +#define IDS_PROP_VOLUME 34 +#define IDS_PROP_IS_VOLUME 35 +#define IDS_PROP_OFFSET 36 +#define IDS_PROP_LINKS 37 +#define IDS_PROP_NUM_BLOCKS 38 +#define IDS_PROP_NUM_VOLUMES 39 + +#define IDS_PROP_BIT64 41 +#define IDS_PROP_BIG_ENDIAN 42 +#define IDS_PROP_CPU 43 +#define IDS_PROP_PHY_SIZE 44 +#define IDS_PROP_HEADERS_SIZE 45 +#define IDS_PROP_CHECKSUM 46 +#define IDS_PROP_CHARACTS 47 +#define IDS_PROP_VA 48 +#define IDS_PROP_ID 49 +#define IDS_PROP_SHORT_NAME 50 +#define IDS_PROP_CREATOR_APP 51 +#define IDS_PROP_SECTOR_SIZE 52 +#define IDS_PROP_POSIX_ATTRIB 53 +#define IDS_PROP_LINK 54 +#define IDS_PROP_ERROR 55 diff --git a/CPP/7zip/UI/FileManager/RegistryAssociations.cpp b/CPP/7zip/UI/FileManager/RegistryAssociations.cpp new file mode 100755 index 0000000..68f949c --- /dev/null +++ b/CPP/7zip/UI/FileManager/RegistryAssociations.cpp @@ -0,0 +1,312 @@ +// RegistryAssociations.cpp + +#include "StdAfx.h" + +#include "RegistryAssociations.h" + +#include "Common/IntToString.h" +#include "Common/StringConvert.h" +#include "Common/StringToInt.h" + +#include "Windows/Registry.h" +#include "Windows/Synchronization.h" + +#include "StringUtils.h" + +using namespace NWindows; +using namespace NRegistry; + +namespace NRegistryAssociations { + +static NSynchronization::CCriticalSection g_CriticalSection; + +#define REG_PATH_FM TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-Zip") TEXT(STRING_PATH_SEPARATOR) TEXT("FM") + +/* + +static const TCHAR *kCUKeyPath = REG_PATH_FM; +static const WCHAR *kExtPlugins = L"Plugins"; +static const TCHAR *kExtEnabled = TEXT("Enabled"); + +#define kAssociations TEXT("Associations") +#define kAssociationsPath REG_PATH_FM TEXT(STRING_PATH_SEPARATOR) kAssociations + +bool ReadInternalAssociation(const wchar_t *ext, CExtInfo &extInfo) +{ + NSynchronization::CCriticalSectionLock lock(g_CriticalSection); + CKey key; + if (key.Open(HKEY_CURRENT_USER, + CSysString(kAssociationsPath TEXT(STRING_PATH_SEPARATOR)) + + GetSystemString(ext), KEY_READ) != ERROR_SUCCESS) + return false; + UString pluginsString; + key.QueryValue(kExtPlugins, pluginsString); + SplitString(pluginsString, extInfo.Plugins); + return true; +} + +void ReadInternalAssociations(CObjectVector &items) +{ + items.Clear(); + NSynchronization::CCriticalSectionLock lock(g_CriticalSection); + CKey associationsKey; + if (associationsKey.Open(HKEY_CURRENT_USER, kAssociationsPath, KEY_READ) != ERROR_SUCCESS) + return; + CSysStringVector extNames; + associationsKey.EnumKeys(extNames); + for(int i = 0; i < extNames.Size(); i++) + { + const CSysString extName = extNames[i]; + CExtInfo extInfo; + // extInfo.Enabled = false; + extInfo.Ext = GetUnicodeString(extName); + CKey key; + if (key.Open(associationsKey, extName, KEY_READ) != ERROR_SUCCESS) + return; + UString pluginsString; + key.QueryValue(kExtPlugins, pluginsString); + SplitString(pluginsString, extInfo.Plugins); + // if (key.QueryValue(kExtEnabled, extInfo.Enabled) != ERROR_SUCCESS) + // extInfo.Enabled = false; + items.Add(extInfo); + } +} + +void WriteInternalAssociations(const CObjectVector &items) +{ + NSynchronization::CCriticalSectionLock lock(g_CriticalSection); + CKey mainKey; + mainKey.Create(HKEY_CURRENT_USER, kCUKeyPath); + mainKey.RecurseDeleteKey(kAssociations); + CKey associationsKey; + associationsKey.Create(mainKey, kAssociations); + for(int i = 0; i < items.Size(); i++) + { + const CExtInfo &extInfo = items[i]; + CKey key; + key.Create(associationsKey, GetSystemString(extInfo.Ext)); + key.SetValue(kExtPlugins, JoinStrings(extInfo.Plugins)); + // key.SetValue(kExtEnabled, extInfo.Enabled); + } +} +*/ + +/////////////////////////////////// +// External + +static const TCHAR *kShellNewKeyName = TEXT("ShellNew"); +static const TCHAR *kShellNewDataValueName = TEXT("Data"); + +static const TCHAR *kDefaultIconKeyName = TEXT("DefaultIcon"); +static const TCHAR *kShellKeyName = TEXT("shell"); +static const TCHAR *kOpenKeyName = TEXT("open"); +static const TCHAR *kCommandKeyName = TEXT("command"); +static const TCHAR *k7zipPrefix = TEXT("7-Zip."); + +static CSysString GetExtensionKeyName(const CSysString &extension) +{ + return CSysString(TEXT(".")) + extension; +} + +static CSysString GetExtProgramKeyName(const CSysString &extension) +{ + return CSysString(k7zipPrefix) + extension; +} + +static bool CheckShellExtensionInfo2(const CSysString &extension, + CSysString programKeyName, UString &iconPath, int &iconIndex) +{ + iconIndex = -1; + iconPath.Empty(); + NSynchronization::CCriticalSectionLock lock(g_CriticalSection); + CKey extKey; + if (extKey.Open(HKEY_CLASSES_ROOT, GetExtensionKeyName(extension), KEY_READ) != ERROR_SUCCESS) + return false; + if (extKey.QueryValue(NULL, programKeyName) != ERROR_SUCCESS) + return false; + UString s = GetUnicodeString(k7zipPrefix); + if (s.CompareNoCase(GetUnicodeString(programKeyName.Left(s.Length()))) != 0) + return false; + CKey iconKey; + if (extKey.Open(HKEY_CLASSES_ROOT, programKeyName + CSysString(TEXT(CHAR_PATH_SEPARATOR)) + kDefaultIconKeyName, KEY_READ) != ERROR_SUCCESS) + return false; + UString value; + if (extKey.QueryValue(NULL, value) == ERROR_SUCCESS) + { + int pos = value.ReverseFind(L','); + iconPath = value; + if (pos >= 0) + { + const wchar_t *end; + UInt64 index = ConvertStringToUInt64((const wchar_t *)value + pos + 1, &end); + if (*end == 0) + { + iconIndex = (int)index; + iconPath = value.Left(pos); + } + } + } + return true; +} + +bool CheckShellExtensionInfo(const CSysString &extension, UString &iconPath, int &iconIndex) +{ + NSynchronization::CCriticalSectionLock lock(g_CriticalSection); + CSysString programKeyName; + if (!CheckShellExtensionInfo2(extension, programKeyName, iconPath, iconIndex)) + return false; + CKey extProgKey; + return (extProgKey.Open(HKEY_CLASSES_ROOT, programKeyName, KEY_READ) == ERROR_SUCCESS); +} + +static void DeleteShellExtensionKey(const CSysString &extension) +{ + NSynchronization::CCriticalSectionLock lock(g_CriticalSection); + CKey rootKey; + rootKey.Attach(HKEY_CLASSES_ROOT); + rootKey.RecurseDeleteKey(GetExtensionKeyName(extension)); + rootKey.Detach(); +} + +static void DeleteShellExtensionProgramKey(const CSysString &extension) +{ + NSynchronization::CCriticalSectionLock lock(g_CriticalSection); + CKey rootKey; + rootKey.Attach(HKEY_CLASSES_ROOT); + rootKey.RecurseDeleteKey(GetExtProgramKeyName(extension)); + rootKey.Detach(); +} + +void DeleteShellExtensionInfo(const CSysString &extension) +{ + CSysString programKeyName; + UString iconPath; + int iconIndex; + if (CheckShellExtensionInfo2(extension, programKeyName, iconPath, iconIndex)) + DeleteShellExtensionKey(extension); + DeleteShellExtensionProgramKey(extension); +} + +void AddShellExtensionInfo(const CSysString &extension, + const UString &programTitle, + const UString &programOpenCommand, + const UString &iconPath, int iconIndex, + const void *shellNewData, int shellNewDataSize) +{ + DeleteShellExtensionKey(extension); + DeleteShellExtensionProgramKey(extension); + NSynchronization::CCriticalSectionLock lock(g_CriticalSection); + CSysString programKeyName; + { + CSysString ext = extension; + if (iconIndex < 0) + ext = TEXT("*"); + programKeyName = GetExtProgramKeyName(ext); + } + { + CKey extKey; + extKey.Create(HKEY_CLASSES_ROOT, GetExtensionKeyName(extension)); + extKey.SetValue(NULL, programKeyName); + if (shellNewData != NULL) + { + CKey shellNewKey; + shellNewKey.Create(extKey, kShellNewKeyName); + shellNewKey.SetValue(kShellNewDataValueName, shellNewData, shellNewDataSize); + } + } + CKey programKey; + programKey.Create(HKEY_CLASSES_ROOT, programKeyName); + programKey.SetValue(NULL, programTitle); + { + CKey iconKey; + iconKey.Create(programKey, kDefaultIconKeyName); + UString iconPathFull = iconPath; + if (iconIndex < 0) + iconIndex = 0; + // if (iconIndex >= 0) + { + iconPathFull += L","; + wchar_t s[16]; + ConvertUInt32ToString(iconIndex, s); + iconPathFull += s; + } + iconKey.SetValue(NULL, iconPathFull); + } + + CKey shellKey; + shellKey.Create(programKey, kShellKeyName); + shellKey.SetValue(NULL, TEXT("")); + + CKey openKey; + openKey.Create(shellKey, kOpenKeyName); + openKey.SetValue(NULL, TEXT("")); + + CKey commandKey; + commandKey.Create(openKey, kCommandKeyName); + + commandKey.SetValue(NULL, programOpenCommand); +} + +/////////////////////////// +// ContextMenu +/* + +static const TCHAR *kContextMenuKeyName = TEXT("\\shellex\\ContextMenuHandlers\\7-Zip"); +static const TCHAR *kContextMenuHandlerCLASSIDValue = + TEXT("{23170F69-40C1-278A-1000-000100020000}"); +static const TCHAR *kRootKeyNameForFile = TEXT("*"); +static const TCHAR *kRootKeyNameForFolder = TEXT("Folder"); + +static CSysString GetFullContextMenuKeyName(const CSysString &aKeyName) + { return (aKeyName + kContextMenuKeyName); } + +static bool CheckContextMenuHandlerCommon(const CSysString &aKeyName) +{ + NSynchronization::CCriticalSectionLock lock(&g_CriticalSection, true); + CKey aKey; + if (aKey.Open(HKEY_CLASSES_ROOT, GetFullContextMenuKeyName(aKeyName), KEY_READ) + != ERROR_SUCCESS) + return false; + CSysString aValue; + if (aKey.QueryValue(NULL, aValue) != ERROR_SUCCESS) + return false; + return (aValue.CompareNoCase(kContextMenuHandlerCLASSIDValue) == 0); +} + +bool CheckContextMenuHandler() +{ + return CheckContextMenuHandlerCommon(kRootKeyNameForFile) && + CheckContextMenuHandlerCommon(kRootKeyNameForFolder); +} + +static void DeleteContextMenuHandlerCommon(const CSysString &aKeyName) +{ + CKey rootKey; + rootKey.Attach(HKEY_CLASSES_ROOT); + rootKey.RecurseDeleteKey(GetFullContextMenuKeyName(aKeyName)); + rootKey.Detach(); +} + +void DeleteContextMenuHandler() +{ + DeleteContextMenuHandlerCommon(kRootKeyNameForFile); + DeleteContextMenuHandlerCommon(kRootKeyNameForFolder); +} + +static void AddContextMenuHandlerCommon(const CSysString &aKeyName) +{ + DeleteContextMenuHandlerCommon(aKeyName); + NSynchronization::CCriticalSectionLock lock(&g_CriticalSection, true); + CKey aKey; + aKey.Create(HKEY_CLASSES_ROOT, GetFullContextMenuKeyName(aKeyName)); + aKey.SetValue(NULL, kContextMenuHandlerCLASSIDValue); +} + +void AddContextMenuHandler() +{ + AddContextMenuHandlerCommon(kRootKeyNameForFile); + AddContextMenuHandlerCommon(kRootKeyNameForFolder); +} +*/ + +} diff --git a/CPP/7zip/UI/FileManager/RegistryAssociations.h b/CPP/7zip/UI/FileManager/RegistryAssociations.h new file mode 100755 index 0000000..1bdc909 --- /dev/null +++ b/CPP/7zip/UI/FileManager/RegistryAssociations.h @@ -0,0 +1,46 @@ +// RegistryAssociations.h + +#ifndef __REGISTRYASSOCIATIONS_H +#define __REGISTRYASSOCIATIONS_H + +#include "Common/MyString.h" + +namespace NRegistryAssociations { + + /* + struct CExtInfo + { + UString Ext; + UStringVector Plugins; + // bool Enabled; + }; + bool ReadInternalAssociation(const wchar_t *ext, CExtInfo &extInfo); + void ReadInternalAssociations(CObjectVector &items); + void WriteInternalAssociations(const CObjectVector &items); + */ + + bool CheckShellExtensionInfo(const CSysString &extension, UString &iconPath, int &iconIndex); + + // void ReadCompressionInfo(NZipSettings::NCompression::CInfo &anInfo, + void DeleteShellExtensionInfo(const CSysString &extension); + + void AddShellExtensionInfo(const CSysString &extension, + const UString &programTitle, + const UString &programOpenCommand, + const UString &iconPath, int iconIndex, + const void *shellNewData, int shellNewDataSize); + + + /////////////////////////// + // ContextMenu + /* + bool CheckContextMenuHandler(); + void AddContextMenuHandler(); + void DeleteContextMenuHandler(); + */ + +} + +// bool GetProgramDirPrefix(CSysString &aFolder); + +#endif diff --git a/CPP/7zip/UI/FileManager/RegistryPlugins.cpp b/CPP/7zip/UI/FileManager/RegistryPlugins.cpp new file mode 100755 index 0000000..13bd678 --- /dev/null +++ b/CPP/7zip/UI/FileManager/RegistryPlugins.cpp @@ -0,0 +1,141 @@ +// RegistryPlugins.cpp + +#include "StdAfx.h" + +#include "Windows/DLL.h" +#include "Windows/PropVariant.h" +#include "Windows/FileFind.h" + +#include "ProgramLocation.h" +#include "RegistryPlugins.h" +#include "IFolder.h" + +using namespace NWindows; +using namespace NFile; + +/* +static const TCHAR *kLMBasePath = TEXT("Software\\7-Zip\\FM"); + +static const TCHAR *kPluginsKeyName = TEXT("Plugins"); +static const TCHAR *kPluginsOpenClassIDValue = TEXT("CLSID"); +static const TCHAR *kPluginsOptionsClassIDValue = TEXT("Options"); +static const TCHAR *kPluginsTypeValue = TEXT("Type"); + +static CSysString GetFileFolderPluginsKeyName() +{ + return CSysString(kLMBasePath) + CSysString(TEXT('\\')) + + CSysString(kPluginsKeyName); +} + +*/ + +typedef UINT32 (WINAPI * GetPluginPropertyFunc)(PROPID propID, PROPVARIANT *value); + +static bool ReadPluginInfo(CPluginInfo &pluginInfo, bool needCheckDll) +{ + if (needCheckDll) + { + NDLL::CLibrary lib; + if (!lib.LoadEx(pluginInfo.FilePath, LOAD_LIBRARY_AS_DATAFILE)) + return false; + } + NDLL::CLibrary lib; + if (!lib.Load(pluginInfo.FilePath)) + return false; + GetPluginPropertyFunc getPluginProperty = (GetPluginPropertyFunc)lib.GetProc("GetPluginProperty"); + if (getPluginProperty == NULL) + return false; + + NCOM::CPropVariant prop; + if (getPluginProperty(NPlugin::kName, &prop) != S_OK) + return false; + if (prop.vt != VT_BSTR) + return false; + pluginInfo.Name = prop.bstrVal; + prop.Clear(); + + if (getPluginProperty(NPlugin::kClassID, &prop) != S_OK) + return false; + if (prop.vt == VT_EMPTY) + pluginInfo.ClassIDDefined = false; + else if (prop.vt != VT_BSTR) + return false; + else + { + pluginInfo.ClassIDDefined = true; + pluginInfo.ClassID = *(const GUID *)prop.bstrVal; + } + prop.Clear(); + + if (getPluginProperty(NPlugin::kOptionsClassID, &prop) != S_OK) + return false; + if (prop.vt == VT_EMPTY) + pluginInfo.OptionsClassIDDefined = false; + else if (prop.vt != VT_BSTR) + return false; + else + { + pluginInfo.OptionsClassIDDefined = true; + pluginInfo.OptionsClassID = *(const GUID *)prop.bstrVal; + } + prop.Clear(); + + if (getPluginProperty(NPlugin::kType, &prop) != S_OK) + return false; + if (prop.vt == VT_EMPTY) + pluginInfo.Type = kPluginTypeFF; + else if (prop.vt == VT_UI4) + pluginInfo.Type = (EPluginType)prop.ulVal; + else + return false; + return true; +} + +UString GetProgramFolderPrefix(); + +void ReadPluginInfoList(CObjectVector &plugins) +{ + plugins.Clear(); + + UString baseFolderPrefix; + GetProgramFolderPath(baseFolderPrefix); + { + CPluginInfo pluginInfo; + pluginInfo.FilePath = baseFolderPrefix + L"7-zip.dll"; + if (::ReadPluginInfo(pluginInfo, false)) + plugins.Add(pluginInfo); + } + UString folderPath = baseFolderPrefix + L"Plugins" WSTRING_PATH_SEPARATOR; + NFind::CEnumeratorW enumerator(folderPath + L"*"); + NFind::CFileInfoW fileInfo; + while (enumerator.Next(fileInfo)) + { + if (fileInfo.IsDir()) + continue; + CPluginInfo pluginInfo; + pluginInfo.FilePath = folderPath + fileInfo.Name; + if (::ReadPluginInfo(pluginInfo, true)) + plugins.Add(pluginInfo); + } +} + +void ReadFileFolderPluginInfoList(CObjectVector &plugins) +{ + ReadPluginInfoList(plugins); + for (int i = 0; i < plugins.Size();) + if (plugins[i].Type != kPluginTypeFF) + plugins.Delete(i); + else + i++; + { + CPluginInfo p; + // p.FilePath.Empty(); + p.Type = kPluginTypeFF; + p.Name = L"7-Zip"; + // p.ClassID = CLSID_CAgentArchiveHandler; + p.ClassIDDefined = true; + // p.OptionsClassID; + p.OptionsClassIDDefined = false; + plugins.Add(p); + } +} diff --git a/CPP/7zip/UI/FileManager/RegistryPlugins.h b/CPP/7zip/UI/FileManager/RegistryPlugins.h new file mode 100755 index 0000000..9af9682 --- /dev/null +++ b/CPP/7zip/UI/FileManager/RegistryPlugins.h @@ -0,0 +1,32 @@ +// RegistryPlugins.h + +#ifndef __REGISTRYPLUGINS_H +#define __REGISTRYPLUGINS_H + +#include "Common/MyString.h" + +enum EPluginType +{ + kPluginTypeFF = 0 +}; + +struct CPluginInfo +{ + UString FilePath; + EPluginType Type; + UString Name; + CLSID ClassID; + CLSID OptionsClassID; + bool ClassIDDefined; + bool OptionsClassIDDefined; + + // CSysString Extension; + // CSysString AddExtension; + // bool UpdateEnabled; + // bool KeepName; +}; + +void ReadPluginInfoList(CObjectVector &plugins); +void ReadFileFolderPluginInfoList(CObjectVector &plugins); + +#endif diff --git a/CPP/7zip/UI/FileManager/RegistryUtils.cpp b/CPP/7zip/UI/FileManager/RegistryUtils.cpp new file mode 100755 index 0000000..7c3aea9 --- /dev/null +++ b/CPP/7zip/UI/FileManager/RegistryUtils.cpp @@ -0,0 +1,160 @@ +// RegistryUtils.cpp + +#include "StdAfx.h" + +#include "Common/IntToString.h" + +#include "Windows/Registry.h" + +#include "RegistryUtils.h" + +using namespace NWindows; +using namespace NRegistry; + +#define REG_PATH_7Z TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-Zip") + +static const TCHAR *kCUBasePath = REG_PATH_7Z; +static const TCHAR *kCU_FMPath = REG_PATH_7Z TEXT(STRING_PATH_SEPARATOR) TEXT("FM"); +// static const TCHAR *kLM_Path = REG_PATH_7Z TEXT(STRING_PATH_SEPARATOR) TEXT("FM"); + +static const WCHAR *kLangValueName = L"Lang"; +static const WCHAR *kEditor = L"Editor"; +static const WCHAR *kDiff = L"Diff"; +static const TCHAR *kShowDots = TEXT("ShowDots"); +static const TCHAR *kShowRealFileIcons = TEXT("ShowRealFileIcons"); +static const TCHAR *kShowSystemMenu = TEXT("ShowSystemMenu"); + +static const TCHAR *kFullRow = TEXT("FullRow"); +static const TCHAR *kShowGrid = TEXT("ShowGrid"); +static const TCHAR *kAlternativeSelection = TEXT("AlternativeSelection"); +// static const TCHAR *kLockMemoryAdd = TEXT("LockMemoryAdd"); +static const TCHAR *kLargePagesEnable = TEXT("LargePages"); +static const TCHAR *kSingleClick = TEXT("SingleClick"); +// static const TCHAR *kUnderline = TEXT("Underline"); + +static const TCHAR *kFlatViewName = TEXT("FlatViewArc"); + +static void SaveCuString(LPCTSTR keyPath, LPCWSTR valuePath, LPCWSTR value) +{ + CKey key; + key.Create(HKEY_CURRENT_USER, keyPath); + key.SetValue(valuePath, value); +} + +static void ReadCuString(LPCTSTR keyPath, LPCWSTR valuePath, UString &res) +{ + res.Empty(); + CKey key; + if (key.Open(HKEY_CURRENT_USER, keyPath, KEY_READ) == ERROR_SUCCESS) + key.QueryValue(valuePath, res); +} + +void SaveRegLang(const UString &path) { SaveCuString(kCUBasePath, kLangValueName, path); } +void ReadRegLang(UString &path) { ReadCuString(kCUBasePath, kLangValueName, path); } + +void SaveRegEditor(const UString &path) { SaveCuString(kCU_FMPath, kEditor, path); } +void ReadRegEditor(UString &path) { ReadCuString(kCU_FMPath, kEditor, path); } + +void SaveRegDiff(const UString &path) { SaveCuString(kCU_FMPath, kDiff, path); } +void ReadRegDiff(UString &path) { ReadCuString(kCU_FMPath, kDiff, path); } + +static void Save7ZipOption(const TCHAR *value, bool enabled) +{ + CKey key; + key.Create(HKEY_CURRENT_USER, kCUBasePath); + key.SetValue(value, enabled); +} + +static void SaveOption(const TCHAR *value, bool enabled) +{ + CKey key; + key.Create(HKEY_CURRENT_USER, kCU_FMPath); + key.SetValue(value, enabled); +} + +static bool Read7ZipOption(const TCHAR *value, bool defaultValue) +{ + CKey key; + if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) == ERROR_SUCCESS) + { + bool enabled; + if (key.QueryValue(value, enabled) == ERROR_SUCCESS) + return enabled; + } + return defaultValue; +} + +static bool ReadOption(const TCHAR *value, bool defaultValue) +{ + CKey key; + if (key.Open(HKEY_CURRENT_USER, kCU_FMPath, KEY_READ) == ERROR_SUCCESS) + { + bool enabled; + if (key.QueryValue(value, enabled) == ERROR_SUCCESS) + return enabled; + } + return defaultValue; +} + +/* +static void SaveLmOption(const TCHAR *value, bool enabled) +{ + CKey key; + key.Create(HKEY_LOCAL_MACHINE, kLM_Path); + key.SetValue(value, enabled); +} + +static bool ReadLmOption(const TCHAR *value, bool defaultValue) +{ + CKey key; + if (key.Open(HKEY_LOCAL_MACHINE, kLM_Path, KEY_READ) == ERROR_SUCCESS) + { + bool enabled; + if (key.QueryValue(value, enabled) == ERROR_SUCCESS) + return enabled; + } + return defaultValue; +} +*/ + +void SaveShowDots(bool showDots) { SaveOption(kShowDots, showDots); } +bool ReadShowDots() { return ReadOption(kShowDots, false); } + +void SaveShowRealFileIcons(bool show) { SaveOption(kShowRealFileIcons, show); } +bool ReadShowRealFileIcons() { return ReadOption(kShowRealFileIcons, false); } + +void SaveShowSystemMenu(bool show) { SaveOption(kShowSystemMenu, show); } +bool ReadShowSystemMenu(){ return ReadOption(kShowSystemMenu, false); } + +void SaveFullRow(bool enable) { SaveOption(kFullRow, enable); } +bool ReadFullRow() { return ReadOption(kFullRow, false); } + +void SaveShowGrid(bool enable) { SaveOption(kShowGrid, enable); } +bool ReadShowGrid(){ return ReadOption(kShowGrid, false); } + +void SaveAlternativeSelection(bool enable) { SaveOption(kAlternativeSelection, enable); } +bool ReadAlternativeSelection(){ return ReadOption(kAlternativeSelection, false); } + +void SaveSingleClick(bool enable) { SaveOption(kSingleClick, enable); } +bool ReadSingleClick(){ return ReadOption(kSingleClick, false); } + +/* +void SaveUnderline(bool enable) { SaveOption(kUnderline, enable); } +bool ReadUnderline(){ return ReadOption(kUnderline, false); } +*/ + +// void SaveLockMemoryAdd(bool enable) { SaveLmOption(kLockMemoryAdd, enable); } +// bool ReadLockMemoryAdd() { return ReadLmOption(kLockMemoryAdd, true); } + +void SaveLockMemoryEnable(bool enable) { Save7ZipOption(kLargePagesEnable, enable); } +bool ReadLockMemoryEnable() { return Read7ZipOption(kLargePagesEnable, false); } + +static CSysString GetFlatViewName(UInt32 panelIndex) +{ + TCHAR panelString[16]; + ConvertUInt32ToString(panelIndex, panelString); + return (CSysString)kFlatViewName + panelString; +} + +void SaveFlatView(UInt32 panelIndex, bool enable) { SaveOption(GetFlatViewName(panelIndex), enable); } +bool ReadFlatView(UInt32 panelIndex) { return ReadOption(GetFlatViewName(panelIndex), false); } diff --git a/CPP/7zip/UI/FileManager/RegistryUtils.h b/CPP/7zip/UI/FileManager/RegistryUtils.h new file mode 100755 index 0000000..b636633 --- /dev/null +++ b/CPP/7zip/UI/FileManager/RegistryUtils.h @@ -0,0 +1,53 @@ +// RegistryUtils.h + +#ifndef __REGISTRY_UTILS_H +#define __REGISTRY_UTILS_H + +#include "Common/MyString.h" +#include "Common/Types.h" + +void SaveRegLang(const UString &path); +void ReadRegLang(UString &path); + +void SaveRegEditor(const UString &path); +void ReadRegEditor(UString &path); + +void SaveRegDiff(const UString &path); +void ReadRegDiff(UString &path); + +void SaveShowDots(bool showDots); +bool ReadShowDots(); + +void SaveShowRealFileIcons(bool show); +bool ReadShowRealFileIcons(); + +void SaveShowSystemMenu(bool showSystemMenu); +bool ReadShowSystemMenu(); + +void SaveFullRow(bool enable); +bool ReadFullRow(); + +void SaveShowGrid(bool enable); +bool ReadShowGrid(); + +void SaveAlternativeSelection(bool enable); +bool ReadAlternativeSelection(); + +// void SaveLockMemoryAdd(bool enable); +// bool ReadLockMemoryAdd(); + +bool ReadLockMemoryEnable(); +void SaveLockMemoryEnable(bool enable); + +void SaveSingleClick(bool enable); +bool ReadSingleClick(); + +/* +void SaveUnderline(bool enable); +bool ReadUnderline(); +*/ + +void SaveFlatView(UInt32 panelIndex, bool enable); +bool ReadFlatView(UInt32 panelIndex); + +#endif diff --git a/CPP/7zip/UI/FileManager/RootFolder.cpp b/CPP/7zip/UI/FileManager/RootFolder.cpp new file mode 100755 index 0000000..2942214 --- /dev/null +++ b/CPP/7zip/UI/FileManager/RootFolder.cpp @@ -0,0 +1,272 @@ +// RootFolder.cpp + +#include "StdAfx.h" + +#include "Common/StringConvert.h" + +#include "Windows/DLL.h" +#include "Windows/PropVariant.h" + +#include "../../PropID.h" + +#include "FSFolder.h" +#include "LangUtils.h" +#ifndef UNDER_CE +#include "NetFolder.h" +#include "FSDrives.h" +#endif +#include "RootFolder.h" +#include "SysIconUtils.h" + +#include "resource.h" + +using namespace NWindows; + +static const STATPROPSTG kProps[] = +{ + { NULL, kpidName, VT_BSTR} +}; + +UString RootFolder_GetName_Computer(int &iconIndex) +{ + #ifdef UNDER_CE + GetRealIconIndex(L"\\", FILE_ATTRIBUTE_DIRECTORY, iconIndex); + #else + iconIndex = GetIconIndexForCSIDL(CSIDL_DRIVES); + #endif + return LangString(IDS_COMPUTER, 0x03020300); +} + +UString RootFolder_GetName_Network(int &iconIndex) +{ + iconIndex = GetIconIndexForCSIDL(CSIDL_NETWORK); + return LangString(IDS_NETWORK, 0x03020301); +} + +UString RootFolder_GetName_Documents(int &iconIndex) +{ + iconIndex = GetIconIndexForCSIDL(CSIDL_PERSONAL); + return LangString(IDS_DOCUMENTS, 0x03020302); ; +} + +enum +{ + ROOT_INDEX_COMPUTER = 0 + #ifndef UNDER_CE + , ROOT_INDEX_DOCUMENTS + , ROOT_INDEX_NETWORK + , ROOT_INDEX_VOLUMES + #endif +}; + +#ifndef UNDER_CE +static const wchar_t *kVolPrefix = L"\\\\."; +#endif + +void CRootFolder::Init() +{ + _names[ROOT_INDEX_COMPUTER] = RootFolder_GetName_Computer(_iconIndices[ROOT_INDEX_COMPUTER]); + #ifndef UNDER_CE + _names[ROOT_INDEX_DOCUMENTS] = RootFolder_GetName_Documents(_iconIndices[ROOT_INDEX_DOCUMENTS]); + _names[ROOT_INDEX_NETWORK] = RootFolder_GetName_Network(_iconIndices[ROOT_INDEX_NETWORK]); + _names[ROOT_INDEX_VOLUMES] = kVolPrefix; + _iconIndices[ROOT_INDEX_VOLUMES] = GetIconIndexForCSIDL(CSIDL_DRIVES); + #endif +} + +STDMETHODIMP CRootFolder::LoadItems() +{ + Init(); + return S_OK; +} + +STDMETHODIMP CRootFolder::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = kNumRootFolderItems; + return S_OK; +} + +STDMETHODIMP CRootFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidIsDir: prop = true; break; + case kpidName: prop = _names[itemIndex]; break; + } + prop.Detach(value); + return S_OK; +} + +typedef BOOL (WINAPI *SHGetSpecialFolderPathWp)(HWND hwnd, LPWSTR pszPath, int csidl, BOOL fCreate); +typedef BOOL (WINAPI *SHGetSpecialFolderPathAp)(HWND hwnd, LPSTR pszPath, int csidl, BOOL fCreate); + +UString GetMyDocsPath() +{ + UString us; + WCHAR s[MAX_PATH + 1]; + SHGetSpecialFolderPathWp getW = (SHGetSpecialFolderPathWp) + #ifdef UNDER_CE + My_GetProcAddress(GetModuleHandle(TEXT("coredll.dll")), "SHGetSpecialFolderPath"); + #else + My_GetProcAddress(GetModuleHandle(TEXT("shell32.dll")), "SHGetSpecialFolderPathW"); + #endif + if (getW && getW(0, s, CSIDL_PERSONAL, FALSE)) + us = s; + #ifndef _UNICODE + else + { + SHGetSpecialFolderPathAp getA = (SHGetSpecialFolderPathAp) + ::GetProcAddress(::GetModuleHandleA("shell32.dll"), "SHGetSpecialFolderPathA"); + CHAR s2[MAX_PATH + 1]; + if (getA && getA(0, s2, CSIDL_PERSONAL, FALSE)) + us = GetUnicodeString(s2); + } + #endif + if (us.Length() > 0 && us[us.Length() - 1] != WCHAR_PATH_SEPARATOR) + us += WCHAR_PATH_SEPARATOR; + return us; +} + +STDMETHODIMP CRootFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder) +{ + *resultFolder = NULL; + CMyComPtr subFolder; + #ifdef UNDER_CE + if (index == ROOT_INDEX_COMPUTER) + { + NFsFolder::CFSFolder *fsFolder = new NFsFolder::CFSFolder; + subFolder = fsFolder; + fsFolder->InitToRoot(); + } + #else + if (index == ROOT_INDEX_COMPUTER || index == ROOT_INDEX_VOLUMES) + { + CFSDrives *fsDrivesSpec = new CFSDrives; + subFolder = fsDrivesSpec; + fsDrivesSpec->Init(index == ROOT_INDEX_VOLUMES); + } + else if (index == ROOT_INDEX_NETWORK) + { + CNetFolder *netFolderSpec = new CNetFolder; + subFolder = netFolderSpec; + netFolderSpec->Init(0, 0, _names[ROOT_INDEX_NETWORK] + WCHAR_PATH_SEPARATOR); + } + else if (index == ROOT_INDEX_DOCUMENTS) + { + UString s = GetMyDocsPath(); + if (!s.IsEmpty()) + { + NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder; + subFolder = fsFolderSpec; + RINOK(fsFolderSpec->Init(s, NULL)); + } + } + #endif + else + return E_INVALIDARG; + *resultFolder = subFolder.Detach(); + return S_OK; +} + +static bool AreEqualNames(const UString &name1, const UString &name2) +{ + return (name1 == name2 || name1 == (name2 + UString(WCHAR_PATH_SEPARATOR))); +} + +STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder) +{ + *resultFolder = 0; + UString name2 = name; + name2.Trim(); + if (name2.IsEmpty()) + { + CRootFolder *rootFolderSpec = new CRootFolder; + CMyComPtr rootFolder = rootFolderSpec; + rootFolderSpec->Init(); + *resultFolder = rootFolder.Detach(); + return S_OK; + } + for (int i = 0; i < kNumRootFolderItems; i++) + if (AreEqualNames(name2, _names[i])) + return BindToFolder((UInt32)i, resultFolder); + #ifdef UNDER_CE + if (name2 == L"\\") + return BindToFolder((UInt32)ROOT_INDEX_COMPUTER, resultFolder); + #else + if (AreEqualNames(name2, L"My Documents") || + AreEqualNames(name2, L"Documents")) + return BindToFolder((UInt32)ROOT_INDEX_DOCUMENTS, resultFolder); + #endif + if (AreEqualNames(name2, L"My Computer") || + AreEqualNames(name2, L"Computer")) + return BindToFolder((UInt32)ROOT_INDEX_COMPUTER, resultFolder); + if (name2 == UString(WCHAR_PATH_SEPARATOR)) + { + CMyComPtr subFolder = this; + *resultFolder = subFolder.Detach(); + return S_OK; + } + + if (name2.Length () < 2) + return E_INVALIDARG; + + CMyComPtr subFolder; + + #ifndef UNDER_CE + if (name2.Left(4) == kVolPrefix) + { + CFSDrives *folderSpec = new CFSDrives; + subFolder = folderSpec; + folderSpec->Init(true); + } + else + #endif + { + if (name2[name2.Length () - 1] != WCHAR_PATH_SEPARATOR) + name2 += WCHAR_PATH_SEPARATOR; + NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder; + subFolder = fsFolderSpec; + if (fsFolderSpec->Init(name2, 0) != S_OK) + { + #ifndef UNDER_CE + if (name2[0] == WCHAR_PATH_SEPARATOR) + { + CNetFolder *netFolderSpec = new CNetFolder; + subFolder = netFolderSpec; + netFolderSpec->Init(name2); + } + else + #endif + return E_INVALIDARG; + } + } + *resultFolder = subFolder.Detach(); + return S_OK; +} + +STDMETHODIMP CRootFolder::BindToParentFolder(IFolderFolder **resultFolder) +{ + *resultFolder = 0; + return S_OK; +} + +IMP_IFolderFolder_Props(CRootFolder) + +STDMETHODIMP CRootFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) +{ + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidType: prop = L"RootFolder"; break; + case kpidPath: prop = L""; break; + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CRootFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex) +{ + *iconIndex = _iconIndices[index]; + return S_OK; +} diff --git a/CPP/7zip/UI/FileManager/RootFolder.h b/CPP/7zip/UI/FileManager/RootFolder.h new file mode 100755 index 0000000..9f75ac6 --- /dev/null +++ b/CPP/7zip/UI/FileManager/RootFolder.h @@ -0,0 +1,33 @@ +// RootFolder.h + +#ifndef __ROOT_FOLDER_H +#define __ROOT_FOLDER_H + +#include "Common/MyString.h" + +#include "IFolder.h" + +const int kNumRootFolderItems = + #ifdef UNDER_CE + 1 + #else + 4 + #endif + ; + +class CRootFolder: + public IFolderFolder, + public IFolderGetSystemIconIndex, + public CMyUnknownImp +{ + UString _names[kNumRootFolderItems]; + int _iconIndices[kNumRootFolderItems]; + +public: + MY_UNKNOWN_IMP1(IFolderGetSystemIconIndex) + INTERFACE_FolderFolder(;) + STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex); + void Init(); +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/SettingsPage.cpp b/CPP/7zip/UI/FileManager/SettingsPage.cpp new file mode 100755 index 0000000..29d7429 --- /dev/null +++ b/CPP/7zip/UI/FileManager/SettingsPage.cpp @@ -0,0 +1,117 @@ +// SettingsPage.cpp + +#include "StdAfx.h" + +#include "Common/StringConvert.h" + +#ifndef UNDER_CE +#include "Windows/MemoryLock.h" +#endif + +#include "HelpUtils.h" +#include "LangUtils.h" +#include "ProgramLocation.h" +#include "RegistryUtils.h" +#include "SettingsPage.h" + +#include "SettingsPageRes.h" + +using namespace NWindows; + +static CIDLangPair kIDLangPairs[] = +{ + { IDC_SETTINGS_SHOW_DOTS, 0x03010401}, + { IDC_SETTINGS_SHOW_REAL_FILE_ICONS, 0x03010402}, + { IDC_SETTINGS_SHOW_SYSTEM_MENU, 0x03010410}, + { IDC_SETTINGS_FULL_ROW, 0x03010420}, + { IDC_SETTINGS_SHOW_GRID, 0x03010421}, + { IDC_SETTINGS_SINGLE_CLICK, 0x03010422}, + // { IDC_SETTINGS_UNDERLINE, 0x03010423} + { IDC_SETTINGS_ALTERNATIVE_SELECTION, 0x03010430}, + { IDC_SETTINGS_LARGE_PAGES, 0x03010440} +}; + +static LPCWSTR kEditTopic = L"FM/options.htm#settings"; + +extern bool IsLargePageSupported(); + +bool CSettingsPage::OnInit() +{ + LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + + CheckButton(IDC_SETTINGS_SHOW_DOTS, ReadShowDots()); + CheckButton(IDC_SETTINGS_SHOW_SYSTEM_MENU, ReadShowSystemMenu()); + CheckButton(IDC_SETTINGS_SHOW_REAL_FILE_ICONS, ReadShowRealFileIcons()); + + CheckButton(IDC_SETTINGS_FULL_ROW, ReadFullRow()); + CheckButton(IDC_SETTINGS_SHOW_GRID, ReadShowGrid()); + CheckButton(IDC_SETTINGS_ALTERNATIVE_SELECTION, ReadAlternativeSelection()); + if (IsLargePageSupported()) + CheckButton(IDC_SETTINGS_LARGE_PAGES, ReadLockMemoryEnable()); + else + EnableItem(IDC_SETTINGS_LARGE_PAGES, false); + CheckButton(IDC_SETTINGS_SINGLE_CLICK, ReadSingleClick()); + // CheckButton(IDC_SETTINGS_UNDERLINE, ReadUnderline()); + + // EnableSubItems(); + + return CPropertyPage::OnInit(); +} + +/* +void CSettingsPage::EnableSubItems() +{ + EnableItem(IDC_SETTINGS_UNDERLINE, IsButtonCheckedBool(IDC_SETTINGS_SINGLE_CLICK)); +} +*/ + +LONG CSettingsPage::OnApply() +{ + SaveShowDots(IsButtonCheckedBool(IDC_SETTINGS_SHOW_DOTS)); + SaveShowSystemMenu(IsButtonCheckedBool(IDC_SETTINGS_SHOW_SYSTEM_MENU)); + SaveShowRealFileIcons(IsButtonCheckedBool(IDC_SETTINGS_SHOW_REAL_FILE_ICONS)); + + SaveFullRow(IsButtonCheckedBool(IDC_SETTINGS_FULL_ROW)); + SaveShowGrid(IsButtonCheckedBool(IDC_SETTINGS_SHOW_GRID)); + SaveAlternativeSelection(IsButtonCheckedBool(IDC_SETTINGS_ALTERNATIVE_SELECTION)); + #ifndef UNDER_CE + if (IsLargePageSupported()) + { + bool enable = IsButtonCheckedBool(IDC_SETTINGS_LARGE_PAGES); + NSecurity::EnableLockMemoryPrivilege(enable); + SaveLockMemoryEnable(enable); + } + #endif + + SaveSingleClick(IsButtonCheckedBool(IDC_SETTINGS_SINGLE_CLICK)); + // SaveUnderline(IsButtonCheckedBool(IDC_SETTINGS_UNDERLINE)); + + return PSNRET_NOERROR; +} + +void CSettingsPage::OnNotifyHelp() +{ + ShowHelpWindow(NULL, kEditTopic); // change it +} + +bool CSettingsPage::OnButtonClicked(int buttonID, HWND buttonHWND) +{ + switch(buttonID) + { + case IDC_SETTINGS_SINGLE_CLICK: + /* + EnableSubItems(); + break; + */ + case IDC_SETTINGS_SHOW_DOTS: + case IDC_SETTINGS_SHOW_SYSTEM_MENU: + case IDC_SETTINGS_SHOW_REAL_FILE_ICONS: + case IDC_SETTINGS_FULL_ROW: + case IDC_SETTINGS_SHOW_GRID: + case IDC_SETTINGS_ALTERNATIVE_SELECTION: + case IDC_SETTINGS_LARGE_PAGES: + Changed(); + return true; + } + return CPropertyPage::OnButtonClicked(buttonID, buttonHWND); +} diff --git a/CPP/7zip/UI/FileManager/SettingsPage.h b/CPP/7zip/UI/FileManager/SettingsPage.h new file mode 100755 index 0000000..4d9d2fd --- /dev/null +++ b/CPP/7zip/UI/FileManager/SettingsPage.h @@ -0,0 +1,19 @@ +// SettingsPage.h + +#ifndef __SETTINGSPAGE_H +#define __SETTINGSPAGE_H + +#include "Windows/Control/PropertyPage.h" +#include "Windows/Control/Edit.h" + +class CSettingsPage: public NWindows::NControl::CPropertyPage +{ + // void EnableSubItems(); + bool OnButtonClicked(int buttonID, HWND buttonHWND); +public: + virtual bool OnInit(); + virtual void OnNotifyHelp(); + virtual LONG OnApply(); +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/SettingsPage.rc b/CPP/7zip/UI/FileManager/SettingsPage.rc new file mode 100755 index 0000000..7516318 --- /dev/null +++ b/CPP/7zip/UI/FileManager/SettingsPage.rc @@ -0,0 +1,22 @@ +#include "SettingsPageRes.h" +#include "../../GuiCommon.rc" + +#define xc 200 +#define yc 120 + +IDD_SETTINGS MY_PAGE +#include "SettingsPage2.rc" + + +#ifdef UNDER_CE + +#undef m +#undef xc + +#define m 4 +#define xc (SMALL_PAGE_SIZE_X + 8) + +IDD_SETTINGS_2 MY_PAGE +#include "SettingsPage2.rc" + +#endif diff --git a/CPP/7zip/UI/FileManager/SettingsPage2.rc b/CPP/7zip/UI/FileManager/SettingsPage2.rc new file mode 100755 index 0000000..f7c0549 --- /dev/null +++ b/CPP/7zip/UI/FileManager/SettingsPage2.rc @@ -0,0 +1,24 @@ +CAPTION "Settings" +BEGIN + CONTROL "Show "".."" item", IDC_SETTINGS_SHOW_DOTS, MY_CHECKBOX, + m, 8, xc, 10 + CONTROL "Show real file &icons", IDC_SETTINGS_SHOW_REAL_FILE_ICONS, MY_CHECKBOX, + m, 22, xc, 10 + CONTROL "Show system &menu", IDC_SETTINGS_SHOW_SYSTEM_MENU, MY_CHECKBOX, + m, 36, xc, 10 + CONTROL "&Full row select", IDC_SETTINGS_FULL_ROW, MY_CHECKBOX, + m, 50, xc, 10 + CONTROL "Show &grid lines", IDC_SETTINGS_SHOW_GRID, MY_CHECKBOX, + m, 64, xc, 10 + CONTROL "&Single-click to open an item", IDC_SETTINGS_SINGLE_CLICK, MY_CHECKBOX, + m, 78, xc, 10 + /* + CONTROL "&Underline current name", IDC_SETTINGS_UNDERLINE, "Button", BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP, + m + 12, 92, xc - 12, 10 + */ + + CONTROL "&Alternative selection mode", IDC_SETTINGS_ALTERNATIVE_SELECTION, MY_CHECKBOX, + m, 92, xc, 10 + CONTROL "Use &large memory pages", IDC_SETTINGS_LARGE_PAGES, MY_CHECKBOX, + m, 106, xc, 10 +END diff --git a/CPP/7zip/UI/FileManager/SettingsPageRes.h b/CPP/7zip/UI/FileManager/SettingsPageRes.h new file mode 100755 index 0000000..4517165 --- /dev/null +++ b/CPP/7zip/UI/FileManager/SettingsPageRes.h @@ -0,0 +1,13 @@ +#define IDD_SETTINGS 543 +#define IDD_SETTINGS_2 643 + +#define IDC_SETTINGS_SHOW_DOTS 1000 +#define IDC_SETTINGS_SHOW_REAL_FILE_ICONS 1001 + +#define IDC_SETTINGS_SHOW_SYSTEM_MENU 1010 +#define IDC_SETTINGS_FULL_ROW 1011 +#define IDC_SETTINGS_SHOW_GRID 1013 +#define IDC_SETTINGS_SINGLE_CLICK 1014 +#define IDC_SETTINGS_UNDERLINE 1015 +#define IDC_SETTINGS_ALTERNATIVE_SELECTION 1016 +#define IDC_SETTINGS_LARGE_PAGES 1017 diff --git a/CPP/7zip/UI/FileManager/SplitDialog.cpp b/CPP/7zip/UI/FileManager/SplitDialog.cpp new file mode 100755 index 0000000..fd7f796 --- /dev/null +++ b/CPP/7zip/UI/FileManager/SplitDialog.cpp @@ -0,0 +1,116 @@ +// SplitDialog.cpp + +#include "StdAfx.h" + +#include "Windows/FileName.h" + +#ifdef LANG +#include "LangUtils.h" +#endif + +#include "BrowseDialog.h" +#include "CopyDialogRes.h" +#include "SplitDialog.h" +#include "SplitUtils.h" +#include "resourceGui.h" + +using namespace NWindows; + +#ifdef LANG +static CIDLangPair kIDLangPairs[] = +{ + { IDC_STATIC_SPLIT_PATH, 0x03020501 }, + { IDC_STATIC_SPLIT_VOLUME, 0x02000D40 }, +}; +#endif + + +bool CSplitDialog::OnInit() +{ + #ifdef LANG + LangSetWindowText(HWND(*this), 0x03020500); + LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + #endif + _pathCombo.Attach(GetItem(IDC_COMBO_SPLIT_PATH)); + _volumeCombo.Attach(GetItem(IDC_COMBO_SPLIT_VOLUME)); + + if (!FilePath.IsEmpty()) + { + UString title; + GetText(title); + title += L' '; + title += FilePath; + SetText(title); + } + _pathCombo.SetText(Path); + AddVolumeItems(_volumeCombo); + _volumeCombo.SetCurSel(0); + NormalizeSize(); + return CModalDialog::OnInit(); +} + +bool CSplitDialog::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 yPos = ySize - my - by; + int xPos = xSize - mx - bx1; + + InvalidateRect(NULL); + + { + RECT rect; + GetClientRectOfItem(IDC_BUTTON_SPLIT_PATH, rect); + int bx = rect.right - rect.left; + MoveItem(IDC_BUTTON_SPLIT_PATH, xSize - mx - bx, rect.top, bx, rect.bottom - rect.top); + ChangeSubWindowSizeX(_pathCombo, xSize - mx - mx - bx - mx); + } + + MoveItem(IDCANCEL, xPos, yPos, bx1, by); + MoveItem(IDOK, xPos - mx - bx2, yPos, bx2, by); + + return false; +} + +bool CSplitDialog::OnButtonClicked(int buttonID, HWND buttonHWND) +{ + switch(buttonID) + { + case IDC_BUTTON_SPLIT_PATH: + OnButtonSetPath(); + return true; + } + return CModalDialog::OnButtonClicked(buttonID, buttonHWND); +} + +void CSplitDialog::OnButtonSetPath() +{ + UString currentPath; + _pathCombo.GetText(currentPath); + // UString title = L"Specify a location for output folder"; + UString title = LangStringSpec(IDS_SET_FOLDER, 0x03020209); + + UString resultPath; + if (!MyBrowseForFolder(HWND(*this), title, currentPath, resultPath)) + return; + NFile::NName::NormalizeDirPathPrefix(resultPath); + _pathCombo.SetCurSel(-1); + _pathCombo.SetText(resultPath); +} + +void CSplitDialog::OnOK() +{ + _pathCombo.GetText(Path); + UString volumeString; + _volumeCombo.GetText(volumeString); + volumeString.Trim(); + if (!ParseVolumeSizes(volumeString, VolumeSizes) || VolumeSizes.Size() == 0) + { + ::MessageBoxW(*this, LangString(IDS_INCORRECT_VOLUME_SIZE, 0x02000D41), L"7-Zip", 0); + return; + } + CModalDialog::OnOK(); +} diff --git a/CPP/7zip/UI/FileManager/SplitDialog.h b/CPP/7zip/UI/FileManager/SplitDialog.h new file mode 100755 index 0000000..6d4f820 --- /dev/null +++ b/CPP/7zip/UI/FileManager/SplitDialog.h @@ -0,0 +1,28 @@ +// SplitDialog.h + +#ifndef __SPLIT_DIALOG_H +#define __SPLIT_DIALOG_H + +#include "Windows/Control/Dialog.h" +#include "Windows/Control/ComboBox.h" + +#include "SplitDialogRes.h" + +class CSplitDialog: public NWindows::NControl::CModalDialog +{ + NWindows::NControl::CComboBox _pathCombo; + NWindows::NControl::CComboBox _volumeCombo; + virtual void OnOK(); + virtual bool OnInit(); + virtual bool OnSize(WPARAM wParam, int xSize, int ySize); + virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); + void OnButtonSetPath(); +public: + UString FilePath; + UString Path; + CRecordVector VolumeSizes; + INT_PTR Create(HWND parentWindow = 0) + { return CModalDialog::Create(IDD_DIALOG_SPLIT, parentWindow); } +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/SplitDialog.rc b/CPP/7zip/UI/FileManager/SplitDialog.rc new file mode 100755 index 0000000..31dad22 --- /dev/null +++ b/CPP/7zip/UI/FileManager/SplitDialog.rc @@ -0,0 +1,16 @@ +#include "SplitDialogRes.h" +#include "../../GuiCommon.rc" + +#define xc 288 +#define yc 96 + +IDD_DIALOG_SPLIT MY_RESIZE_DIALOG +CAPTION "Split File" +BEGIN + LTEXT "&Split to:", IDC_STATIC_SPLIT_PATH, m, m, xc, 8 + COMBOBOX IDC_COMBO_SPLIT_PATH, m, 20, xc - bxsDots - m, 64, MY_COMBO_WITH_EDIT + PUSHBUTTON "...", IDC_BUTTON_SPLIT_PATH, xs - m - bxsDots, 18, bxsDots, bys, WS_GROUP + LTEXT "Split to &volumes, bytes:", IDC_STATIC_SPLIT_VOLUME, m, 44, xc, 8 + COMBOBOX IDC_COMBO_SPLIT_VOLUME, m, 56, 96, 52, MY_COMBO_WITH_EDIT + OK_CANCEL +END diff --git a/CPP/7zip/UI/FileManager/SplitDialogRes.h b/CPP/7zip/UI/FileManager/SplitDialogRes.h new file mode 100755 index 0000000..a3e874d --- /dev/null +++ b/CPP/7zip/UI/FileManager/SplitDialogRes.h @@ -0,0 +1,7 @@ +#define IDD_DIALOG_SPLIT 504 +#define IDC_STATIC_SPLIT_PATH 1000 +#define IDC_COMBO_SPLIT_PATH 1001 +#define IDC_BUTTON_SPLIT_PATH 1002 +#define IDC_STATIC_SPLIT_VOLUME 1010 +#define IDC_COMBO_SPLIT_VOLUME 1011 + diff --git a/CPP/7zip/UI/FileManager/SplitUtils.cpp b/CPP/7zip/UI/FileManager/SplitUtils.cpp new file mode 100755 index 0000000..a51ff59 --- /dev/null +++ b/CPP/7zip/UI/FileManager/SplitUtils.cpp @@ -0,0 +1,86 @@ +// SplitUtils.cpp + +#include "StdAfx.h" + +#include "Common/StringToInt.h" + +#include "SplitUtils.h" +#include "StringUtils.h" + +bool ParseVolumeSizes(const UString &s, CRecordVector &values) +{ + values.Clear(); + UStringVector destStrings; + SplitString(s, destStrings); + bool prevIsNumber = false; + for (int i = 0; i < destStrings.Size(); i++) + { + UString subString = destStrings[i]; + subString.MakeUpper(); + if (subString.IsEmpty()) + return false; + if (subString == L"-") + return true; + if (prevIsNumber) + { + wchar_t c = subString[0]; + UInt64 &value = values.Back(); + prevIsNumber = false; + switch(c) + { + case L'B': + continue; + case L'K': + value <<= 10; + continue; + case L'M': + value <<= 20; + continue; + case L'G': + value <<= 30; + continue; + } + } + const wchar_t *start = subString; + const wchar_t *end; + UInt64 value = ConvertStringToUInt64(start, &end); + if (start == end) + return false; + if (value == 0) + return false; + values.Add(value); + prevIsNumber = true; + UString rem = subString.Mid((int)(end - start)); + if (!rem.IsEmpty()) + destStrings.Insert(i + 1, rem); + } + return true; +} + +void AddVolumeItems(NWindows::NControl::CComboBox &volumeCombo) +{ + volumeCombo.AddString(TEXT("10M")); + volumeCombo.AddString(TEXT("650M - CD")); + volumeCombo.AddString(TEXT("700M - CD")); + volumeCombo.AddString(TEXT("4480M - DVD")); + volumeCombo.AddString(TEXT("1457664 - 3.5\" floppy")); +} + +UInt64 GetNumberOfVolumes(UInt64 size, CRecordVector &volSizes) +{ + if (size == 0 || volSizes.Size() == 0) + return 1; + UInt64 numVolumes = 0; + for (int i = 0; i < volSizes.Size(); i++) + { + UInt64 volSize = volSizes[i]; + numVolumes++; + if (volSize >= size) + return numVolumes; + size -= volSize; + } + UInt64 volSize = volSizes.Back(); + if (volSize == 0) + return (UInt64)(Int64)-1; + return numVolumes + (size - 1) / volSize + 1; +} diff --git a/CPP/7zip/UI/FileManager/SplitUtils.h b/CPP/7zip/UI/FileManager/SplitUtils.h new file mode 100755 index 0000000..9fda0fd --- /dev/null +++ b/CPP/7zip/UI/FileManager/SplitUtils.h @@ -0,0 +1,15 @@ +// SplitUtils.h + +#ifndef __SPLITUTILS_H +#define __SPLITUTILS_H + +#include "Common/MyString.h" +#include "Common/Types.h" +#include "Windows/Control/ComboBox.h" + +bool ParseVolumeSizes(const UString &s, CRecordVector &values); +void AddVolumeItems(NWindows::NControl::CComboBox &volumeCombo); + +UInt64 GetNumberOfVolumes(UInt64 size, CRecordVector &volSizes); + +#endif diff --git a/CPP/7zip/UI/FileManager/StdAfx.cpp b/CPP/7zip/UI/FileManager/StdAfx.cpp new file mode 100755 index 0000000..c6d3b1f --- /dev/null +++ b/CPP/7zip/UI/FileManager/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/UI/FileManager/StdAfx.h b/CPP/7zip/UI/FileManager/StdAfx.h new file mode 100755 index 0000000..a9ae92e --- /dev/null +++ b/CPP/7zip/UI/FileManager/StdAfx.h @@ -0,0 +1,23 @@ +// stdafx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#define _WIN32_WINNT 0x0400 + +// it's for Windows NT supporting (MENUITEMINFOW) +#define WINVER 0x0400 + +#include +#include +#include +#include +#include +#include +#include + +// #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#include "Common/NewHandler.h" + +#endif diff --git a/CPP/7zip/UI/FileManager/StringUtils.cpp b/CPP/7zip/UI/FileManager/StringUtils.cpp new file mode 100755 index 0000000..7c7de13 --- /dev/null +++ b/CPP/7zip/UI/FileManager/StringUtils.cpp @@ -0,0 +1,68 @@ +// StringUtils.cpp + +#include "StdAfx.h" + +#include "StringUtils.h" + +void SplitStringToTwoStrings(const UString &src, UString &dest1, UString &dest2) +{ + dest1.Empty(); + dest2.Empty(); + bool quoteMode = false; + int i; + for (i = 0; i < src.Length(); i++) + { + wchar_t c = src[i]; + if (c == L'\"') + quoteMode = !quoteMode; + else if (c == L' ' && !quoteMode) + { + if (!quoteMode) + { + i++; + break; + } + } + else + dest1 += c; + } + dest2 = src.Mid(i); +} + +void SplitString(const UString &srcString, UStringVector &destStrings) +{ + destStrings.Clear(); + UString string; + int len = srcString.Length(); + if (len == 0) + return; + for (int i = 0; i < len; i++) + { + wchar_t c = srcString[i]; + if (c == L' ') + { + if (!string.IsEmpty()) + { + destStrings.Add(string); + string.Empty(); + } + } + else + string += c; + } + if (!string.IsEmpty()) + destStrings.Add(string); +} + +UString JoinStrings(const UStringVector &srcStrings) +{ + UString destString; + for (int i = 0; i < srcStrings.Size(); i++) + { + if (i != 0) + destString += L' '; + destString += srcStrings[i]; + } + return destString; +} + diff --git a/CPP/7zip/UI/FileManager/StringUtils.h b/CPP/7zip/UI/FileManager/StringUtils.h new file mode 100755 index 0000000..8857bff --- /dev/null +++ b/CPP/7zip/UI/FileManager/StringUtils.h @@ -0,0 +1,13 @@ +// StringUtils.h + +#ifndef __STRINGUTILS_H +#define __STRINGUTILS_H + +#include "Common/MyString.h" + +void SplitStringToTwoStrings(const UString &src, UString &dest1, UString &dest2); + +void SplitString(const UString &srcString, UStringVector &destStrings); +UString JoinStrings(const UStringVector &srcStrings); + +#endif diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.cpp b/CPP/7zip/UI/FileManager/SysIconUtils.cpp new file mode 100755 index 0000000..35fe0de --- /dev/null +++ b/CPP/7zip/UI/FileManager/SysIconUtils.cpp @@ -0,0 +1,159 @@ +// SysIconUtils.cpp + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "Common/StringConvert.h" +#endif + +#include "SysIconUtils.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +int GetIconIndexForCSIDL(int csidl) +{ + LPITEMIDLIST pidl = 0; + SHGetSpecialFolderLocation(NULL, csidl, &pidl); + if (pidl) + { + SHFILEINFO shellInfo; + SHGetFileInfo(LPCTSTR(pidl), FILE_ATTRIBUTE_NORMAL, + &shellInfo, sizeof(shellInfo), + SHGFI_PIDL | SHGFI_SYSICONINDEX); + IMalloc *pMalloc; + SHGetMalloc(&pMalloc); + if(pMalloc) + { + pMalloc->Free(pidl); + pMalloc->Release(); + } + return shellInfo.iIcon; + } + return 0; +} + +DWORD_PTR GetRealIconIndex(LPCTSTR path, DWORD attrib, int &iconIndex) +{ + SHFILEINFO shellInfo; + DWORD_PTR res = ::SHGetFileInfo(path, FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo, + sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX); + iconIndex = shellInfo.iIcon; + return res; +} + + +#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); +} + +#ifndef _UNICODE +// static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } +DWORD_PTR GetRealIconIndex(LPCWSTR path, DWORD attrib, int &iconIndex) +{ + if(g_IsNT) + { + SHFILEINFOW shellInfo; + DWORD_PTR res = ::MySHGetFileInfoW(path, FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo, + sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX); + iconIndex = shellInfo.iIcon; + return res; + } + else + return GetRealIconIndex(UnicodeStringToMultiByte(path), attrib, iconIndex); +} +#endif + +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); + 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); + typeName = shellInfo.szTypeName; + iconIndex = shellInfo.iIcon; + return res; + } +} + +int CExtToIconMap::GetIconIndex(DWORD attrib, const UString &fileName, UString &typeName) +{ + int dotPos = fileName.ReverseFind(L'.'); + if ((attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 || dotPos < 0) + { + CAttribIconPair pair; + pair.Attrib = attrib; + int index = _attribMap.FindInSorted(pair); + if (index >= 0) + { + typeName = _attribMap[index].TypeName; + return _attribMap[index].IconIndex; + } + GetRealIconIndex( + #ifdef UNDER_CE + L"\\" + #endif + L"__File__" + , attrib, pair.IconIndex, pair.TypeName); + _attribMap.AddToSorted(pair); + typeName = pair.TypeName; + return pair.IconIndex; + } + + CExtIconPair pair; + pair.Ext = fileName.Mid(dotPos + 1); + int index = _extMap.FindInSorted(pair); + if (index >= 0) + { + typeName = _extMap[index].TypeName; + return _extMap[index].IconIndex; + } + GetRealIconIndex(fileName.Mid(dotPos), attrib, pair.IconIndex, pair.TypeName); + _extMap.AddToSorted(pair); + typeName = pair.TypeName; + return pair.IconIndex; +} + +int CExtToIconMap::GetIconIndex(DWORD attrib, const UString &fileName) +{ + UString typeName; + return GetIconIndex(attrib, fileName, typeName); +} diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.h b/CPP/7zip/UI/FileManager/SysIconUtils.h new file mode 100755 index 0000000..59fcad5 --- /dev/null +++ b/CPP/7zip/UI/FileManager/SysIconUtils.h @@ -0,0 +1,57 @@ +// SysIconUtils.h + +#ifndef __SYS_ICON_UTILS_H +#define __SYS_ICON_UTILS_H + +#include "Common/MyString.h" + +struct CExtIconPair +{ + UString Ext; + int IconIndex; + UString TypeName; +}; + +struct CAttribIconPair +{ + DWORD Attrib; + int IconIndex; + UString TypeName; +}; + +inline bool operator==(const CExtIconPair &a1, const CExtIconPair &a2) { return a1.Ext == a2.Ext; } +inline bool operator< (const CExtIconPair &a1, const CExtIconPair &a2) { return a1.Ext < a2.Ext; } + +inline bool operator==(const CAttribIconPair &a1, const CAttribIconPair &a2) { return a1.Attrib == a2.Attrib; } +inline bool operator< (const CAttribIconPair &a1, const CAttribIconPair &a2) { return a1.Attrib < a2.Attrib; } + +class CExtToIconMap +{ + CObjectVector _extMap; + CObjectVector _attribMap; +public: + void Clear() + { + _extMap.Clear(); + _attribMap.Clear(); + } + int GetIconIndex(DWORD attrib, const UString &fileName, UString &typeName); + int GetIconIndex(DWORD attrib, const UString &fileName); +}; + +DWORD_PTR GetRealIconIndex(LPCTSTR path, DWORD attrib, int &iconIndex); +#ifndef _UNICODE +DWORD_PTR GetRealIconIndex(LPCWSTR path, DWORD attrib, int &iconIndex); +#endif +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/CPP/7zip/UI/FileManager/SystemPage.cpp b/CPP/7zip/UI/FileManager/SystemPage.cpp new file mode 100755 index 0000000..5b96869 --- /dev/null +++ b/CPP/7zip/UI/FileManager/SystemPage.cpp @@ -0,0 +1,402 @@ +// SystemPage.cpp + +#include "StdAfx.h" +#include "SystemPageRes.h" +#include "SystemPage.h" + +#include "Common/StringConvert.h" +#include "Common/MyCom.h" + +#include "Windows/Defs.h" +#include "Windows/Control/ListView.h" +#include "Windows/FileFind.h" + +#include "IFolder.h" +#include "HelpUtils.h" +#include "LangUtils.h" +#include "PluginLoader.h" +#include "ProgramLocation.h" +#include "StringUtils.h" + +#include "PropertyNameRes.h" +#include "../Agent/Agent.h" + +using namespace NRegistryAssociations; + +const int kRefreshpluginsListMessage = WM_USER + 1; +const int kUpdateDatabase = kRefreshpluginsListMessage + 1; + +static CIDLangPair kIDLangPairs[] = +{ + { IDC_SYSTEM_STATIC_ASSOCIATE, 0x03010302}, + { IDC_SYSTEM_SELECT_ALL, 0x03000330} +}; + +static LPCWSTR kSystemTopic = L"FM/options.htm#system"; + + +bool CSystemPage::OnInit() +{ + _initMode = true; + LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + + _listViewExt.Attach(GetItem(IDC_SYSTEM_LIST_ASSOCIATE)); + _listViewPlugins.Attach(GetItem(IDC_SYSTEM_LIST_PLUGINS)); + + /* + CheckButton(IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU, + NRegistryAssociations::CheckContextMenuHandler()); + */ + + UINT32 newFlags = LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT; + _listViewExt.SetExtendedListViewStyle(newFlags, newFlags); + _listViewPlugins.SetExtendedListViewStyle(newFlags, newFlags); + + _listViewExt.InsertColumn(0, LangString(IDS_PROP_EXTENSION, 0x02000205), 40); + const UString s = LangString(IDS_PLUGIN, 0x03010310); + _listViewExt.InsertColumn(1, s, 40); + + _listViewPlugins.InsertColumn(0, s, 40); + + _extDatabase.Read(); + + for (int i = 0; i < _extDatabase.ExtBigItems.Size(); i++) + { + CExtInfoBig &extInfo = _extDatabase.ExtBigItems[i]; + + int itemIndex = _listViewExt.InsertItem(i, (LPCWSTR)extInfo.Ext); + + UString iconPath; + int iconIndex; + extInfo.Associated = NRegistryAssociations::CheckShellExtensionInfo(GetSystemString(extInfo.Ext), iconPath, iconIndex); + if (extInfo.Associated && !NWindows::NFile::NFind::DoesFileExist(iconPath)) + extInfo.Associated = false; + _listViewExt.SetCheckState(itemIndex, extInfo.Associated); + + SetMainPluginText(itemIndex, i); + } + // _listViewExt.SortItems(); + + if (_listViewExt.GetItemCount() > 0) + _listViewExt.SetItemState_FocusedSelected(0); + RefreshPluginsList(-1); + _initMode = false; + + return CPropertyPage::OnInit(); +} + +void CSystemPage::SetMainPluginText(int itemIndex, int indexInDatabase) +{ + _listViewExt.SetSubItem(itemIndex, 1, _extDatabase.GetMainPluginNameForExtItem(indexInDatabase)); +} + +static UString GetProgramCommand() +{ + UString path = L"\""; + UString folder; + if (GetProgramFolderPath(folder)) + path += folder; + path += L"7zFM.exe\" \"%1\""; + return path; +} + +static UString GetIconPath(const UString &filePath, + const CLSID &clsID, const UString &extension, Int32 &iconIndex) +{ + CPluginLibrary library; + CMyComPtr folderManager; + CMyComPtr folder; + if (filePath.IsEmpty()) + folderManager = new CArchiveFolderManager; + else if (library.LoadAndCreateManager(filePath, clsID, &folderManager) != S_OK) + return UString(); + CMyComBSTR extBSTR; + if (folderManager->GetExtensions(&extBSTR) != S_OK) + return UString(); + const UString ext2 = (const wchar_t *)extBSTR; + UStringVector exts; + SplitString(ext2, exts); + for (int i = 0; i < exts.Size(); i++) + { + const UString &plugExt = exts[i]; + if (extension.CompareNoCase((const wchar_t *)plugExt) == 0) + { + CMyComBSTR iconPathTemp; + if (folderManager->GetIconPath(plugExt, &iconPathTemp, &iconIndex) != S_OK) + break; + if (iconPathTemp != 0) + return (const wchar_t *)iconPathTemp; + } + } + return UString(); +} + +LONG CSystemPage::OnApply() +{ + UpdateDatabase(); + _extDatabase.Save(); + UString command = GetProgramCommand(); + + for (int i = 0; i < _extDatabase.ExtBigItems.Size(); i++) + { + const CExtInfoBig &extInfo = _extDatabase.ExtBigItems[i]; + if (extInfo.Associated) + { + UString title = extInfo.Ext + UString(L" Archive"); + UString command = GetProgramCommand(); + UString iconPath; + Int32 iconIndex = -1; + if (!extInfo.PluginsPairs.IsEmpty()) + { + const CPluginInfo &plugin = _extDatabase.Plugins[extInfo.PluginsPairs[0].Index]; + iconPath = GetIconPath(plugin.FilePath, plugin.ClassID, extInfo.Ext, iconIndex); + } + NRegistryAssociations::AddShellExtensionInfo(GetSystemString(extInfo.Ext), + title, command, iconPath, iconIndex, NULL, 0); + } + else + NRegistryAssociations::DeleteShellExtensionInfo(GetSystemString(extInfo.Ext)); + } + /* + if (IsButtonCheckedBool(IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU)) + NRegistryAssociations::AddContextMenuHandler(); + else + NRegistryAssociations::DeleteContextMenuHandler(); + */ + #ifndef UNDER_CE + SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); + WasChanged = true; + #endif + return PSNRET_NOERROR; +} + +void CSystemPage::OnNotifyHelp() +{ + ShowHelpWindow(NULL, kSystemTopic); +} + +void CSystemPage::SelectAll() +{ + int count = _listViewExt.GetItemCount(); + for (int i = 0; i < count; i++) + _listViewExt.SetCheckState(i, true); + UpdateDatabase(); +} + +bool CSystemPage::OnButtonClicked(int buttonID, HWND buttonHWND) +{ + switch(buttonID) + { + case IDC_SYSTEM_SELECT_ALL: + { + SelectAll(); + Changed(); + return true; + } + } + return CPropertyPage::OnButtonClicked(buttonID, buttonHWND); +} + +bool CSystemPage::OnNotify(UINT controlID, LPNMHDR lParam) +{ + if (lParam->hwndFrom == HWND(_listViewExt)) + { + switch(lParam->code) + { + case (LVN_ITEMCHANGED): + return OnItemChanged((const NMLISTVIEW *)lParam); + case NM_RCLICK: + case NM_DBLCLK: + case LVN_KEYDOWN: + case NM_CLICK: + case LVN_BEGINRDRAG: + PostMessage(kRefreshpluginsListMessage, 0); + PostMessage(kUpdateDatabase, 0); + break; + } + } + else if (lParam->hwndFrom == HWND(_listViewPlugins)) + { + switch(lParam->code) + { + case NM_RCLICK: + case NM_DBLCLK: + // case LVN_KEYDOWN: + case NM_CLICK: + case LVN_BEGINRDRAG: + PostMessage(kUpdateDatabase, 0); + break; + + case (LVN_ITEMCHANGED): + { + OnItemChanged((const NMLISTVIEW *)lParam); + PostMessage(kUpdateDatabase, 0); + break; + } + case LVN_KEYDOWN: + { + OnPluginsKeyDown((LPNMLVKEYDOWN)lParam); + PostMessage(kUpdateDatabase, 0); + break; + } + } + } + return CPropertyPage::OnNotify(controlID, lParam); +} + +bool CSystemPage::OnPluginsKeyDown(LPNMLVKEYDOWN keyDownInfo) +{ + bool alt = (::GetKeyState(VK_MENU) & 0x8000) != 0; + // bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0; + switch(keyDownInfo->wVKey) + { + case VK_UP: + { + if (alt) + MovePlugin(true); + return true; + } + case VK_DOWN: + { + if (alt) + MovePlugin(false); + return true; + } + } + return false; +} + +void CSystemPage::MovePlugin(bool upDirection) +{ + int selectedPlugin = _listViewPlugins.GetSelectionMark(); + if (selectedPlugin < 0) + return; + int newIndex = selectedPlugin + (upDirection ? -1: 1); + if (newIndex < 0 || newIndex >= _listViewPlugins.GetItemCount()) + return; + int selectedExtIndex = GetSelectedExtIndex(); + if (selectedExtIndex < 0) + return; + CExtInfoBig &extInfo = _extDatabase.ExtBigItems[selectedExtIndex]; + CPluginEnabledPair pluginPairTemp = extInfo.PluginsPairs[newIndex]; + extInfo.PluginsPairs[newIndex] = extInfo.PluginsPairs[selectedPlugin]; + extInfo.PluginsPairs[selectedPlugin] = pluginPairTemp; + + SetMainPluginText(_listViewExt.GetSelectionMark(), selectedExtIndex); + RefreshPluginsList(newIndex); + + Changed(); +} + +bool CSystemPage::OnItemChanged(const NMLISTVIEW *info) +{ + if (_initMode) + return true; + if ((info->uChanged & LVIF_STATE) != 0) + { + UINT oldState = info->uOldState & LVIS_STATEIMAGEMASK; + UINT newState = info->uNewState & LVIS_STATEIMAGEMASK; + if (oldState != newState) + Changed(); + } + // PostMessage(kRefreshpluginsListMessage, 0); + // RefreshPluginsList(); + return true; +} + +bool CSystemPage::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case kRefreshpluginsListMessage: + RefreshPluginsList(-1); + return true; + case kUpdateDatabase: + UpdateDatabase(); + return true; + } + return CPropertyPage::OnMessage(message, wParam, lParam); +} + +void CSystemPage::UpdateDatabase() +{ + int i; + for (i = 0; i < _listViewExt.GetItemCount(); i++) + { + LPARAM param; + if (!_listViewExt.GetItemParam(i, param)) + return; + CExtInfoBig &extInfo = _extDatabase.ExtBigItems[(int)param]; + extInfo.Associated = _listViewExt.GetCheckState(i); + } + + int selectedExtIndex = GetSelectedExtIndex(); + if (selectedExtIndex < 0) + return; + + CExtInfoBig &extInfo = _extDatabase.ExtBigItems[selectedExtIndex]; + for (i = 0; i < _listViewPlugins.GetItemCount(); i++) + { + extInfo.PluginsPairs[i].Enabled = _listViewPlugins.GetCheckState(i); + } +} + + + +int CSystemPage::GetSelectedExtIndex() +{ + int selectedIndex = _listViewExt.GetSelectionMark(); + if (selectedIndex < 0) + return -1; + LPARAM param; + if (!_listViewExt.GetItemParam(selectedIndex, param)) + return -1; + return (int)param; +} + + +void CSystemPage::RefreshPluginsList(int selectIndex) +{ + _listViewPlugins.DeleteAllItems(); + int selectedExtIndex = GetSelectedExtIndex(); + if (selectedExtIndex < 0) + return; + const CExtInfoBig &extInfo = _extDatabase.ExtBigItems[selectedExtIndex]; + + _initMode = true; + for (int i = 0; i < extInfo.PluginsPairs.Size(); i++) + { + CPluginEnabledPair pluginPair = extInfo.PluginsPairs[i]; + int itemIndex = _listViewPlugins.InsertItem(i, _extDatabase.Plugins[pluginPair.Index].Name); + _listViewPlugins.SetCheckState(itemIndex, pluginPair.Enabled); + } + if (_listViewPlugins.GetItemCount() > 0) + { + if (selectIndex < 0) + selectIndex = 0; + _listViewPlugins.SetItemState_FocusedSelected(selectIndex); + } + _initMode = false; +} + + + +/* +static BYTE kZipShellNewData[] = + { 0x50-1, 0x4B, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0 }; + +static BYTE kRarShellNewData[] = + { 0x52-1, 0x61, 0x72, 0x21, 0x1A, 7, 0, 0xCF, 0x90, 0x73, 0, 0, 0x0D, 0, 0, 0, 0, 0, 0, 0}; + +class CSignatureMaker +{ +public: + CSignatureMaker() + { + kZipShellNewData[0]++; + kRarShellNewData[0]++; + }; +}; + +static CSignatureMaker g_SignatureMaker; +*/ diff --git a/CPP/7zip/UI/FileManager/SystemPage.h b/CPP/7zip/UI/FileManager/SystemPage.h new file mode 100755 index 0000000..54e6e70 --- /dev/null +++ b/CPP/7zip/UI/FileManager/SystemPage.h @@ -0,0 +1,41 @@ +// SystemPage.h + +#ifndef __SYSTEM_PAGE_H +#define __SYSTEM_PAGE_H + +#include "Windows/Control/PropertyPage.h" +#include "Windows/Control/ListView.h" + +#include "FilePlugins.h" + +class CSystemPage: public NWindows::NControl::CPropertyPage +{ + bool _initMode; + CExtDatabase _extDatabase; + + NWindows::NControl::CListView _listViewExt; + NWindows::NControl::CListView _listViewPlugins; + + void SetMainPluginText(int itemIndex, int indexInDatabase); + + int GetSelectedExtIndex(); + void RefreshPluginsList(int selectIndex); + void MovePlugin(bool upDirection); + void UpdateDatabase(); + void SelectAll(); + +public: + bool WasChanged; + CSystemPage(): WasChanged(false) {} + virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam); + virtual bool OnInit(); + virtual void OnNotifyHelp(); + virtual bool OnNotify(UINT controlID, LPNMHDR lParam); + virtual bool OnItemChanged(const NMLISTVIEW *info); + + virtual LONG OnApply(); + virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); + bool OnPluginsKeyDown(LPNMLVKEYDOWN keyDownInfo); +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/SystemPage.rc b/CPP/7zip/UI/FileManager/SystemPage.rc new file mode 100755 index 0000000..a2e4062 --- /dev/null +++ b/CPP/7zip/UI/FileManager/SystemPage.rc @@ -0,0 +1,43 @@ +#include "SystemPageRes.h" +#include "../../GuiCommon.rc" + +#define xc 200 +#define yc 200 + +IDD_SYSTEM MY_PAGE +CAPTION "System" +BEGIN + LTEXT "Associate 7-Zip with:", IDC_SYSTEM_STATIC_ASSOCIATE, m, m, xc, 8 + CONTROL "List1", IDC_SYSTEM_LIST_ASSOCIATE, "SysListView32", + LVS_LIST | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | WS_BORDER | WS_TABSTOP, + m, m + 12, xc, (yc - m - 12 - 1 - bys) + PUSHBUTTON "Select all", IDC_SYSTEM_SELECT_ALL, m, (ys - m - bys), 90, bys +END + +#ifdef UNDER_CE + +#undef m +#undef xc +#undef yc + +#define m 4 +#define xc (SMALL_PAGE_SIZE_X + 8) +#define yc (128 + 8) + +IDD_SYSTEM_2 MY_PAGE +CAPTION "System" +BEGIN + LTEXT "Associate 7-Zip with:", IDC_SYSTEM_STATIC_ASSOCIATE, m, m, xc, 8 + CONTROL "List1", IDC_SYSTEM_LIST_ASSOCIATE, "SysListView32", + LVS_LIST | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | WS_BORDER | WS_TABSTOP, + m, m + 12, xc, (yc - m - 12 - 1 - bys - 8) + PUSHBUTTON "Select all", IDC_SYSTEM_SELECT_ALL, m, (ys - m - bys - 8), 90, bys +END + +#endif + + +STRINGTABLE +BEGIN + IDS_PLUGIN "Plugin" +END diff --git a/CPP/7zip/UI/FileManager/SystemPageRes.h b/CPP/7zip/UI/FileManager/SystemPageRes.h new file mode 100755 index 0000000..c4667d3 --- /dev/null +++ b/CPP/7zip/UI/FileManager/SystemPageRes.h @@ -0,0 +1,8 @@ +#define IDD_SYSTEM 540 +#define IDD_SYSTEM_2 640 +#define IDS_PLUGIN 990 +// #define IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU 1010 +#define IDC_SYSTEM_STATIC_ASSOCIATE 1020 +#define IDC_SYSTEM_LIST_ASSOCIATE 1021 +#define IDC_SYSTEM_LIST_PLUGINS 1022 +#define IDC_SYSTEM_SELECT_ALL 1023 diff --git a/CPP/7zip/UI/FileManager/Test.bmp b/CPP/7zip/UI/FileManager/Test.bmp new file mode 100755 index 0000000000000000000000000000000000000000..ef85ba23048c126e221dfc0de529cd31ece7434f GIT binary patch literal 982 zcmdUtu?@m75JeAxL={g#LCFmC?7$R=@)lqxk3faoSjq%m!F>B1E1a*PLO8yQ<9jc5 zlW=jYzB}?FxETQ0*P;f&Kd=vy9gay|^#phuK!6#P=>u(S|K9$h$7?sfQ hsDzFyq2o%xpGGvvnWz=|LFp~^!q>ujwf>gh58jH$-9P{U literal 0 HcmV?d00001 diff --git a/CPP/7zip/UI/FileManager/Test2.bmp b/CPP/7zip/UI/FileManager/Test2.bmp new file mode 100755 index 0000000000000000000000000000000000000000..99b7dbf0388cebb05db9b120629d47e5fb7540e2 GIT binary patch literal 406 zcmb_X!3}^Q3@nKWFL?X(=^XxD$DavPI1eMR0ErWH1-w?k_}0Q*+q<-cWjzdOY~UFf zD+~>)Pu17vMS%#HLbwwcB@iga2&3qwQltWKL;~fnk@jbUx4lk$cEd9_BQbXaax+A3 chDU)$CPa49W0fQoY)<%tyOs7vl`!*jT==E^2LJ#7 literal 0 HcmV?d00001 diff --git a/CPP/7zip/UI/FileManager/TextPairs.cpp b/CPP/7zip/UI/FileManager/TextPairs.cpp new file mode 100755 index 0000000..f46bce7 --- /dev/null +++ b/CPP/7zip/UI/FileManager/TextPairs.cpp @@ -0,0 +1,189 @@ +// TextPairs.cpp + +#include "StdAfx.h" + +#include "TextPairs.h" + +static const wchar_t kNewLineChar = '\n'; +static const wchar_t kQuoteChar = '\"'; + +static const wchar_t kBOM = (wchar_t)0xFEFF; + +static bool IsSeparatorChar(wchar_t c) +{ + return (c == ' ' || c == '\t'); +} + +static void RemoveCr(UString &s) +{ + s.Replace(L"\x0D", L""); +} + +static UString GetIDString(const wchar_t *srcString, int &finishPos) +{ + UString result; + bool quotes = false; + for (finishPos = 0;;) + { + wchar_t c = srcString[finishPos]; + if (c == 0) + break; + finishPos++; + bool isSeparatorChar = IsSeparatorChar(c); + if (c == kNewLineChar || (isSeparatorChar && !quotes) + || (c == kQuoteChar && quotes)) + break; + else if (c == kQuoteChar) + quotes = true; + else + result += c; + } + result.Trim(); + RemoveCr(result); + return result; +} + +static UString GetValueString(const wchar_t *srcString, int &finishPos) +{ + UString result; + for (finishPos = 0;;) + { + wchar_t c = srcString[finishPos]; + if (c == 0) + break; + finishPos++; + if (c == kNewLineChar) + break; + result += c; + } + result.Trim(); + RemoveCr(result); + return result; +} + +static bool GetTextPairs(const UString &srcString, CObjectVector &pairs) +{ + pairs.Clear(); + int pos = 0; + + if (srcString.Length() > 0) + { + if (srcString[0] == kBOM) + pos++; + } + while (pos < srcString.Length()) + { + int finishPos; + UString id = GetIDString((const wchar_t *)srcString + pos, finishPos); + pos += finishPos; + if (id.IsEmpty()) + continue; + UString value = GetValueString((const wchar_t *)srcString + pos, finishPos); + pos += finishPos; + if (!id.IsEmpty()) + { + CTextPair pair; + pair.ID = id; + pair.Value = value; + pairs.Add(pair); + } + } + return true; +} + +static int ComparePairIDs(const UString &s1, const UString &s2) + { return s1.CompareNoCase(s2); } +static int ComparePairItems(const CTextPair &p1, const CTextPair &p2) + { return ComparePairIDs(p1.ID, p2.ID); } + +static int ComparePairItems(void *const *a1, void *const *a2, void * /* param */) + { return ComparePairItems(**(const CTextPair **)a1, **(const CTextPair **)a2); } + +void CPairsStorage::Sort() { Pairs.Sort(ComparePairItems, 0); } + +int CPairsStorage::FindID(const UString &id, int &insertPos) +{ + int left = 0, right = Pairs.Size(); + while (left != right) + { + int mid = (left + right) / 2; + int compResult = ComparePairIDs(id, Pairs[mid].ID); + if (compResult == 0) + return mid; + if (compResult < 0) + right = mid; + else + left = mid + 1; + } + insertPos = left; + return -1; +} + +int CPairsStorage::FindID(const UString &id) +{ + int pos; + return FindID(id, pos); +} + +void CPairsStorage::AddPair(const CTextPair &pair) +{ + int insertPos; + int pos = FindID(pair.ID, insertPos); + if (pos >= 0) + Pairs[pos] = pair; + else + Pairs.Insert(insertPos, pair); +} + +void CPairsStorage::DeletePair(const UString &id) +{ + int pos = FindID(id); + if (pos >= 0) + Pairs.Delete(pos); +} + +bool CPairsStorage::GetValue(const UString &id, UString &value) +{ + value.Empty(); + int pos = FindID(id); + if (pos < 0) + return false; + value = Pairs[pos].Value; + return true; +} + +UString CPairsStorage::GetValue(const UString &id) +{ + int pos = FindID(id); + if (pos < 0) + return UString(); + return Pairs[pos].Value; +} + +bool CPairsStorage::ReadFromString(const UString &text) +{ + bool result = ::GetTextPairs(text, Pairs); + if (result) + Sort(); + else + Pairs.Clear(); + return result; +} + +void CPairsStorage::SaveToString(UString &text) +{ + for (int i = 0; i < Pairs.Size(); i++) + { + const CTextPair &pair = Pairs[i]; + bool multiWord = (pair.ID.Find(L' ') >= 0); + if (multiWord) + text += L'\"'; + text += pair.ID; + if (multiWord) + text += L'\"'; + text += L' '; + text += pair.Value; + text += L'\x0D'; + text += L'\n'; + } +} diff --git a/CPP/7zip/UI/FileManager/TextPairs.h b/CPP/7zip/UI/FileManager/TextPairs.h new file mode 100755 index 0000000..2abe920 --- /dev/null +++ b/CPP/7zip/UI/FileManager/TextPairs.h @@ -0,0 +1,31 @@ +// TextPairs.h + +#ifndef __FM_TEXT_PAIRS_H +#define __FM_TEXT_PAIRS_H + +#include "Common/MyString.h" + +struct CTextPair +{ + UString ID; + UString Value; +}; + +class CPairsStorage +{ + CObjectVector Pairs; + int FindID(const UString &id, int &insertPos); + int FindID(const UString &id); + void Sort(); +public: + void Clear() { Pairs.Clear(); }; + bool ReadFromString(const UString &text); + void SaveToString(UString &text); + + bool GetValue(const UString &id, UString &value); + UString GetValue(const UString &id); + void AddPair(const CTextPair &pair); + void DeletePair(const UString &id); +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/UpdateCallback100.cpp b/CPP/7zip/UI/FileManager/UpdateCallback100.cpp new file mode 100755 index 0000000..7526dd7 --- /dev/null +++ b/CPP/7zip/UI/FileManager/UpdateCallback100.cpp @@ -0,0 +1,90 @@ +// UpdateCallback100.cpp + +#include "StdAfx.h" + +#include "PasswordDialog.h" +#include "UpdateCallback100.h" + +STDMETHODIMP CUpdateCallback100Imp::SetNumFiles(UInt64 numFiles) +{ + ProgressDialog->Sync.SetNumFilesTotal(numFiles); + return S_OK; +} + +STDMETHODIMP CUpdateCallback100Imp::SetTotal(UInt64 size) +{ + ProgressDialog->Sync.SetProgress(size, 0); + return S_OK; +} + +STDMETHODIMP CUpdateCallback100Imp::SetCompleted(const UInt64 *completeValue) +{ + RINOK(ProgressDialog->Sync.ProcessStopAndPause()); + if (completeValue != NULL) + ProgressDialog->Sync.SetPos(*completeValue); + return S_OK; +} + +STDMETHODIMP CUpdateCallback100Imp::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) +{ + ProgressDialog->Sync.SetRatioInfo(inSize, outSize); + return S_OK; +} + +STDMETHODIMP CUpdateCallback100Imp::CompressOperation(const wchar_t *name) +{ + ProgressDialog->Sync.SetCurrentFileName(name); + return S_OK; +} + +STDMETHODIMP CUpdateCallback100Imp::DeleteOperation(const wchar_t *name) +{ + ProgressDialog->Sync.SetCurrentFileName(name); + return S_OK; +} + +STDMETHODIMP CUpdateCallback100Imp::OperationResult(Int32 /* operationResult */) +{ + ProgressDialog->Sync.SetNumFilesCur(++_numFiles); + return S_OK; +} + +STDMETHODIMP CUpdateCallback100Imp::UpdateErrorMessage(const wchar_t *message) +{ + ProgressDialog->Sync.AddErrorMessage(message); + return S_OK; +} + +STDMETHODIMP CUpdateCallback100Imp::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) +{ + *password = NULL; + *passwordIsDefined = BoolToInt(_passwordIsDefined); + if (!_passwordIsDefined) + return S_OK; + return StringToBstr(_password, password); +} + +STDMETHODIMP CUpdateCallback100Imp::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */) +{ + return S_OK; +} + +STDMETHODIMP CUpdateCallback100Imp::SetCompleted(const UInt64 * /* files */, const UInt64 * /* bytes */) +{ + return ProgressDialog->Sync.ProcessStopAndPause(); +} + +STDMETHODIMP CUpdateCallback100Imp::CryptoGetTextPassword(BSTR *password) +{ + *password = NULL; + if (!_passwordIsDefined) + { + CPasswordDialog dialog; + ProgressDialog->WaitCreating(); + if (dialog.Create(*ProgressDialog) == IDCANCEL) + return E_ABORT; + _password = dialog.Password; + _passwordIsDefined = true; + } + return StringToBstr(_password, password); +} diff --git a/CPP/7zip/UI/FileManager/UpdateCallback100.h b/CPP/7zip/UI/FileManager/UpdateCallback100.h new file mode 100755 index 0000000..00411d6 --- /dev/null +++ b/CPP/7zip/UI/FileManager/UpdateCallback100.h @@ -0,0 +1,54 @@ +// UpdateCallback100.h + +#ifndef __UPDATE_CALLBACK100_H +#define __UPDATE_CALLBACK100_H + +#include "Common/MyCom.h" + +#include "../../IPassword.h" + +#include "../Agent/IFolderArchive.h" + +#include "ProgressDialog2.h" + +class CUpdateCallback100Imp: + public IFolderArchiveUpdateCallback, + public ICryptoGetTextPassword2, + public ICryptoGetTextPassword, + public IArchiveOpenCallback, + public ICompressProgressInfo, + public CMyUnknownImp +{ + bool _passwordIsDefined; + UString _password; + UInt64 _numFiles; +public: + CProgressDialog *ProgressDialog; + + CUpdateCallback100Imp(): ProgressDialog(0) {} + + MY_UNKNOWN_IMP5( + IFolderArchiveUpdateCallback, + ICryptoGetTextPassword2, + ICryptoGetTextPassword, + IArchiveOpenCallback, + ICompressProgressInfo) + + INTERFACE_IProgress(;) + INTERFACE_IArchiveOpenCallback(;) + INTERFACE_IFolderArchiveUpdateCallback(;) + + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); + + STDMETHOD(CryptoGetTextPassword)(BSTR *password); + STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); + + void Init(bool passwordIsDefined, const UString &password) + { + _passwordIsDefined = passwordIsDefined; + _password = password; + _numFiles = 0; + } +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/ViewSettings.cpp b/CPP/7zip/UI/FileManager/ViewSettings.cpp new file mode 100755 index 0000000..d7a1894 --- /dev/null +++ b/CPP/7zip/UI/FileManager/ViewSettings.cpp @@ -0,0 +1,390 @@ +// ViewSettings.h + +#include "StdAfx.h" + +#include "Common/IntToString.h" +#include "Common/StringConvert.h" + +#include "ViewSettings.h" +#include "Windows/Registry.h" +#include "Windows/Synchronization.h" + +using namespace NWindows; +using namespace NRegistry; + +#define REG_PATH_FM TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-Zip") TEXT(STRING_PATH_SEPARATOR) TEXT("FM") + +static const TCHAR *kCUBasePath = REG_PATH_FM; +static const TCHAR *kCulumnsKeyName = REG_PATH_FM TEXT(STRING_PATH_SEPARATOR) TEXT("Columns"); + +static const TCHAR *kPositionValueName = TEXT("Position"); +static const TCHAR *kPanelsInfoValueName = TEXT("Panels"); +static const TCHAR *kToolbars = TEXT("Toolbars"); + +static const WCHAR *kPanelPathValueName = L"PanelPath"; +static const TCHAR *kListMode = TEXT("ListMode"); +static const TCHAR *kFolderHistoryValueName = TEXT("FolderHistory"); +static const TCHAR *kFastFoldersValueName = TEXT("FolderShortcuts"); +static const TCHAR *kCopyHistoryValueName = TEXT("CopyHistory"); + +/* +class CColumnInfoSpec +{ + UInt32 PropID; + Byte IsVisible; + UInt32 Width; +}; + +struct CColumnHeader +{ + UInt32 Version; + UInt32 SortID; + Byte Ascending; +}; +*/ + +static const UInt32 kColumnInfoSpecHeader = 12; +static const UInt32 kColumnHeaderSize = 12; + +static const UInt32 kColumnInfoVersion = 1; + +static NSynchronization::CCriticalSection g_CS; + +class CTempOutBufferSpec +{ + CByteBuffer Buffer; + UInt32 Size; + UInt32 Pos; +public: + operator const Byte *() const { return (const Byte *)Buffer; } + void Init(UInt32 dataSize) + { + Buffer.SetCapacity(dataSize); + Size = dataSize; + Pos = 0; + } + void WriteByte(Byte value) + { + if (Pos >= Size) + throw "overflow"; + ((Byte *)Buffer)[Pos++] = value; + } + void WriteUInt32(UInt32 value) + { + for (int i = 0; i < 4; i++) + { + WriteByte((Byte)value); + value >>= 8; + } + } + void WriteBool(bool value) + { + WriteUInt32(value ? 1 : 0); + } +}; + +class CTempInBufferSpec +{ +public: + Byte *Buffer; + UInt32 Size; + UInt32 Pos; + Byte ReadByte() + { + if (Pos >= Size) + throw "overflow"; + return Buffer[Pos++]; + } + UInt32 ReadUInt32() + { + UInt32 value = 0; + for (int i = 0; i < 4; i++) + value |= (((UInt32)ReadByte()) << (8 * i)); + return value; + } + bool ReadBool() + { + return (ReadUInt32() != 0); + } +}; + +void SaveListViewInfo(const UString &id, const CListViewInfo &viewInfo) +{ + const CObjectVector &columns = viewInfo.Columns; + CTempOutBufferSpec buffer; + UInt32 dataSize = kColumnHeaderSize + kColumnInfoSpecHeader * columns.Size(); + buffer.Init(dataSize); + + buffer.WriteUInt32(kColumnInfoVersion); + buffer.WriteUInt32(viewInfo.SortID); + buffer.WriteBool(viewInfo.Ascending); + for(int i = 0; i < columns.Size(); i++) + { + const CColumnInfo &column = columns[i]; + buffer.WriteUInt32(column.PropID); + buffer.WriteBool(column.IsVisible); + buffer.WriteUInt32(column.Width); + } + { + NSynchronization::CCriticalSectionLock lock(g_CS); + CKey key; + key.Create(HKEY_CURRENT_USER, kCulumnsKeyName); + key.SetValue(GetSystemString(id), (const Byte *)buffer, dataSize); + } +} + +void ReadListViewInfo(const UString &id, CListViewInfo &viewInfo) +{ + viewInfo.Clear(); + CObjectVector &columns = viewInfo.Columns; + CByteBuffer buffer; + UInt32 size; + { + NSynchronization::CCriticalSectionLock lock(g_CS); + CKey key; + if (key.Open(HKEY_CURRENT_USER, kCulumnsKeyName, KEY_READ) != ERROR_SUCCESS) + return; + if (key.QueryValue(GetSystemString(id), buffer, size) != ERROR_SUCCESS) + return; + } + if (size < kColumnHeaderSize) + return; + CTempInBufferSpec inBuffer; + inBuffer.Size = size; + inBuffer.Buffer = (Byte *)buffer; + inBuffer.Pos = 0; + + + UInt32 version = inBuffer.ReadUInt32(); + if (version != kColumnInfoVersion) + return; + viewInfo.SortID = inBuffer.ReadUInt32(); + viewInfo.Ascending = inBuffer.ReadBool(); + + size -= kColumnHeaderSize; + if (size % kColumnInfoSpecHeader != 0) + return; + int numItems = size / kColumnInfoSpecHeader; + columns.Reserve(numItems); + for(int i = 0; i < numItems; i++) + { + CColumnInfo columnInfo; + columnInfo.PropID = inBuffer.ReadUInt32(); + columnInfo.IsVisible = inBuffer.ReadBool(); + columnInfo.Width = inBuffer.ReadUInt32(); + columns.Add(columnInfo); + } +} + +static const UInt32 kWindowPositionHeaderSize = 5 * 4; +static const UInt32 kPanelsInfoHeaderSize = 3 * 4; + +/* +struct CWindowPosition +{ + RECT Rect; + UInt32 Maximized; +}; + +struct CPanelsInfo +{ + UInt32 NumPanels; + UInt32 CurrentPanel; + UInt32 SplitterPos; +}; +*/ + +void SaveWindowSize(const RECT &rect, bool maximized) +{ + CSysString keyName = kCUBasePath; + NSynchronization::CCriticalSectionLock lock(g_CS); + CKey key; + key.Create(HKEY_CURRENT_USER, keyName); + // CWindowPosition position; + CTempOutBufferSpec buffer; + buffer.Init(kWindowPositionHeaderSize); + buffer.WriteUInt32(rect.left); + buffer.WriteUInt32(rect.top); + buffer.WriteUInt32(rect.right); + buffer.WriteUInt32(rect.bottom); + buffer.WriteBool(maximized); + key.SetValue(kPositionValueName, (const Byte *)buffer, kWindowPositionHeaderSize); +} + +bool ReadWindowSize(RECT &rect, bool &maximized) +{ + CSysString keyName = kCUBasePath; + NSynchronization::CCriticalSectionLock lock(g_CS); + CKey key; + if (key.Open(HKEY_CURRENT_USER, keyName, KEY_READ) != ERROR_SUCCESS) + return false; + CByteBuffer buffer; + UInt32 size; + if (key.QueryValue(kPositionValueName, buffer, size) != ERROR_SUCCESS) + return false; + if (size != kWindowPositionHeaderSize) + return false; + CTempInBufferSpec inBuffer; + inBuffer.Size = size; + inBuffer.Buffer = (Byte *)buffer; + inBuffer.Pos = 0; + rect.left = inBuffer.ReadUInt32(); + rect.top = inBuffer.ReadUInt32(); + rect.right = inBuffer.ReadUInt32(); + rect.bottom = inBuffer.ReadUInt32(); + maximized = inBuffer.ReadBool(); + return true; +} + +void SavePanelsInfo(UInt32 numPanels, UInt32 currentPanel, UInt32 splitterPos) +{ + CSysString keyName = kCUBasePath; + NSynchronization::CCriticalSectionLock lock(g_CS); + CKey key; + key.Create(HKEY_CURRENT_USER, keyName); + + CTempOutBufferSpec buffer; + buffer.Init(kPanelsInfoHeaderSize); + buffer.WriteUInt32(numPanels); + buffer.WriteUInt32(currentPanel); + buffer.WriteUInt32(splitterPos); + key.SetValue(kPanelsInfoValueName, (const Byte *)buffer, kPanelsInfoHeaderSize); +} + +bool ReadPanelsInfo(UInt32 &numPanels, UInt32 ¤tPanel, UInt32 &splitterPos) +{ + CSysString keyName = kCUBasePath; + NSynchronization::CCriticalSectionLock lock(g_CS); + CKey key; + if (key.Open(HKEY_CURRENT_USER, keyName, KEY_READ) != ERROR_SUCCESS) + return false; + CByteBuffer buffer; + UInt32 size; + if (key.QueryValue(kPanelsInfoValueName, buffer, size) != ERROR_SUCCESS) + return false; + if (size != kPanelsInfoHeaderSize) + return false; + CTempInBufferSpec inBuffer; + inBuffer.Size = size; + inBuffer.Buffer = (Byte *)buffer; + inBuffer.Pos = 0; + numPanels = inBuffer.ReadUInt32(); + currentPanel = inBuffer.ReadUInt32(); + splitterPos = inBuffer.ReadUInt32(); + return true; +} + +void SaveToolbarsMask(UInt32 toolbarMask) +{ + CKey key; + key.Create(HKEY_CURRENT_USER, kCUBasePath); + key.SetValue(kToolbars, toolbarMask); +} + +static const UInt32 kDefaultToolbarMask = ((UInt32)1 << 31) | 8 | 4 | 1; + +UInt32 ReadToolbarsMask() +{ + CKey key; + if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS) + return kDefaultToolbarMask; + UInt32 mask; + if (key.QueryValue(kToolbars, mask) != ERROR_SUCCESS) + return kDefaultToolbarMask; + return mask; +} + + +static UString GetPanelPathName(UInt32 panelIndex) +{ + WCHAR panelString[16]; + ConvertUInt32ToString(panelIndex, panelString); + return UString(kPanelPathValueName) + panelString; +} + + +void SavePanelPath(UInt32 panel, const UString &path) +{ + NSynchronization::CCriticalSectionLock lock(g_CS); + CKey key; + key.Create(HKEY_CURRENT_USER, kCUBasePath); + key.SetValue(GetPanelPathName(panel), path); +} + +bool ReadPanelPath(UInt32 panel, UString &path) +{ + NSynchronization::CCriticalSectionLock lock(g_CS); + CKey key; + if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS) + return false; + return (key.QueryValue(GetPanelPathName(panel), path) == ERROR_SUCCESS); +} + +void SaveListMode(const CListMode &listMode) +{ + CKey key; + key.Create(HKEY_CURRENT_USER, kCUBasePath); + UInt32 t = 0; + for (int i = 0; i < 2; i++) + t |= ((listMode.Panels[i]) & 0xFF) << (i * 8); + key.SetValue(kListMode, t); +} + +void ReadListMode(CListMode &listMode) +{ + CKey key; + listMode.Init(); + if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS) + return; + UInt32 t; + if (key.QueryValue(kListMode, t) != ERROR_SUCCESS) + return; + for (int i = 0; i < 2; i++) + { + listMode.Panels[i] = (t & 0xFF); + t >>= 8; + } +} + + +static void SaveStringList(LPCTSTR valueName, const UStringVector &folders) +{ + NSynchronization::CCriticalSectionLock lock(g_CS); + CKey key; + key.Create(HKEY_CURRENT_USER, kCUBasePath); + key.SetValue_Strings(valueName, folders); +} + +static void ReadStringList(LPCTSTR valueName, UStringVector &folders) +{ + folders.Clear(); + NSynchronization::CCriticalSectionLock lock(g_CS); + CKey key; + if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) == ERROR_SUCCESS) + key.GetValue_Strings(valueName, folders); +} + +void SaveFolderHistory(const UStringVector &folders) + { SaveStringList(kFolderHistoryValueName, folders); } +void ReadFolderHistory(UStringVector &folders) + { ReadStringList(kFolderHistoryValueName, folders); } + +void SaveFastFolders(const UStringVector &folders) + { SaveStringList(kFastFoldersValueName, folders); } +void ReadFastFolders(UStringVector &folders) + { ReadStringList(kFastFoldersValueName, folders); } + +void SaveCopyHistory(const UStringVector &folders) + { SaveStringList(kCopyHistoryValueName, folders); } +void ReadCopyHistory(UStringVector &folders) + { ReadStringList(kCopyHistoryValueName, folders); } + +void AddUniqueStringToHeadOfList(UStringVector &list, const UString &s) +{ + for (int i = 0; i < list.Size();) + if (s.CompareNoCase(list[i]) == 0) + list.Delete(i); + else + i++; + list.Insert(0, s); +} diff --git a/CPP/7zip/UI/FileManager/ViewSettings.h b/CPP/7zip/UI/FileManager/ViewSettings.h new file mode 100755 index 0000000..6ba6902 --- /dev/null +++ b/CPP/7zip/UI/FileManager/ViewSettings.h @@ -0,0 +1,98 @@ +// ViewSettings.h + +#ifndef __VIEW_SETTINGS_H +#define __VIEW_SETTINGS_H + +#include "Common/MyString.h" +#include "Common/Types.h" + +struct CColumnInfo +{ + PROPID PropID; + bool IsVisible; + UInt32 Width; +}; + +inline bool operator==(const CColumnInfo &a1, const CColumnInfo &a2) +{ + return (a1.PropID == a2.PropID) && + (a1.IsVisible == a2.IsVisible) && (a1.Width == a2.Width); +} + +inline bool operator!=(const CColumnInfo &a1, const CColumnInfo &a2) +{ + return !(a1 == a2); +} + +struct CListViewInfo +{ + CObjectVector Columns; + PROPID SortID; + bool Ascending; + + void Clear() + { + SortID = 0; + Ascending = true; + Columns.Clear(); + } + + int FindColumnWithID(PROPID propID) const + { + for (int i = 0; i < Columns.Size(); i++) + if (Columns[i].PropID == propID) + return i; + return -1; + } + + bool IsEqual(const CListViewInfo &info) const + { + if (Columns.Size() != info.Columns.Size() || + // SortIndex != info.SortIndex || + SortID != info.SortID || + Ascending != info.Ascending) + return false; + for (int i = 0; i < Columns.Size(); i++) + if (Columns[i] != info.Columns[i]) + return false; + return true; + } +}; + +void SaveListViewInfo(const UString &id, const CListViewInfo &viewInfo); +void ReadListViewInfo(const UString &id, CListViewInfo &viewInfo); + +void SaveWindowSize(const RECT &rect, bool maximized); +bool ReadWindowSize(RECT &rect, bool &maximized); + +void SavePanelsInfo(UInt32 numPanels, UInt32 currentPanel, UInt32 splitterPos); +bool ReadPanelsInfo(UInt32 &numPanels, UInt32 ¤tPanel, UInt32 &splitterPos); + +void SaveToolbarsMask(UInt32 toolbarMask); +UInt32 ReadToolbarsMask(); + +void SavePanelPath(UInt32 panel, const UString &path); +bool ReadPanelPath(UInt32 panel, UString &path); + +struct CListMode +{ + UInt32 Panels[2]; + void Init() { Panels[0] = Panels[1] = 3; } + CListMode() { Init(); } +}; + +void SaveListMode(const CListMode &listMode); +void ReadListMode(CListMode &listMode); + +void SaveFolderHistory(const UStringVector &folders); +void ReadFolderHistory(UStringVector &folders); + +void SaveFastFolders(const UStringVector &folders); +void ReadFastFolders(UStringVector &folders); + +void SaveCopyHistory(const UStringVector &folders); +void ReadCopyHistory(UStringVector &folders); + +void AddUniqueStringToHeadOfList(UStringVector &list, const UString &s); + +#endif diff --git a/CPP/7zip/UI/FileManager/makefile b/CPP/7zip/UI/FileManager/makefile new file mode 100755 index 0000000..45e08a0 --- /dev/null +++ b/CPP/7zip/UI/FileManager/makefile @@ -0,0 +1,223 @@ +PROG = 7zFM.exe +CFLAGS = $(CFLAGS) -I ../../../ \ + -DLANG \ + -DNEW_FOLDER_INTERFACE \ + -DEXTERNAL_CODECS \ + +!IFDEF UNDER_CE +LIBS = $(LIBS) ceshell.lib Commctrl.lib +!ELSE +LIBS = $(LIBS) comctl32.lib htmlhelp.lib comdlg32.lib Mpr.lib Gdi32.lib +CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -DSUPPORT_DEVICE_FILE +!ENDIF + +FM_OBJS = \ + $O\App.obj \ + $O\BrowseDialog.obj \ + $O\ClassDefs.obj \ + $O\EnumFormatEtc.obj \ + $O\ExtractCallback.obj \ + $O\FileFolderPluginOpen.obj \ + $O\FilePlugins.obj \ + $O\FM.obj \ + $O\FoldersPage.obj \ + $O\FormatUtils.obj \ + $O\FSFolder.obj \ + $O\FSFolderCopy.obj \ + $O\HelpUtils.obj \ + $O\LangUtils.obj \ + $O\MenuPage.obj \ + $O\MyLoadMenu.obj \ + $O\OpenCallback.obj \ + $O\OptionsDialog.obj \ + $O\Panel.obj \ + $O\PanelCopy.obj \ + $O\PanelCrc.obj \ + $O\PanelDrag.obj \ + $O\PanelFolderChange.obj \ + $O\PanelItemOpen.obj \ + $O\PanelItems.obj \ + $O\PanelKey.obj \ + $O\PanelListNotify.obj \ + $O\PanelMenu.obj \ + $O\PanelOperations.obj \ + $O\PanelSelect.obj \ + $O\PanelSort.obj \ + $O\PanelSplitFile.obj \ + $O\ProgramLocation.obj \ + $O\PropertyName.obj \ + $O\RegistryAssociations.obj \ + $O\RegistryPlugins.obj \ + $O\RegistryUtils.obj \ + $O\RootFolder.obj \ + $O\SplitUtils.obj \ + $O\StringUtils.obj \ + $O\SysIconUtils.obj \ + $O\TextPairs.obj \ + $O\UpdateCallback100.obj \ + $O\ViewSettings.obj \ + $O\AboutDialog.obj \ + $O\ComboDialog.obj \ + $O\CopyDialog.obj \ + $O\EditPage.obj \ + $O\LangPage.obj \ + $O\ListViewDialog.obj \ + $O\MessagesDialog.obj \ + $O\OverwriteDialog.obj \ + $O\PasswordDialog.obj \ + $O\ProgressDialog2.obj \ + $O\SettingsPage.obj \ + $O\SplitDialog.obj \ + $O\SystemPage.obj \ + +COMMON_OBJS = \ + $O\CRC.obj \ + $O\IntToString.obj \ + $O\Lang.obj \ + $O\MyString.obj \ + $O\MyVector.obj \ + $O\NewHandler.obj \ + $O\Random.obj \ + $O\StringConvert.obj \ + $O\StringToInt.obj \ + $O\TextConfig.obj \ + $O\UTFConvert.obj \ + $O\Wildcard.obj \ + +WIN_OBJS = \ + $O\Clipboard.obj \ + $O\CommonDialog.obj \ + $O\DLL.obj \ + $O\Error.obj \ + $O\FileDir.obj \ + $O\FileFind.obj \ + $O\FileIO.obj \ + $O\FileName.obj \ + $O\Memory.obj \ + $O\MemoryLock.obj \ + $O\Menu.obj \ + $O\Process.obj \ + $O\PropVariant.obj \ + $O\PropVariantConversions.obj \ + $O\Registry.obj \ + $O\ResourceString.obj \ + $O\Shell.obj \ + $O\Synchronization.obj \ + $O\Time.obj \ + $O\Window.obj \ + +!IFNDEF UNDER_CE + +FM_OBJS = $(FM_OBJS) \ + $O\FSDrives.obj \ + $O\NetFolder.obj \ + +WIN_OBJS = $(WIN_OBJS) \ + $O\FileSystem.obj \ + $O\Net.obj \ + $O\Security.obj \ + +!ENDIF + + +WIN_CTRL_OBJS = \ + $O\ComboBox.obj \ + $O\Dialog.obj \ + $O\ListView.obj \ + $O\PropertyPage.obj \ + $O\Window2.obj \ + +7ZIP_COMMON_OBJS = \ + $O\FilePathAutoRename.obj \ + $O\FileStreams.obj \ + $O\ProgressUtils.obj \ + $O\StreamObjects.obj \ + $O\StreamUtils.obj \ + +AR_COMMON_OBJS = \ + $O\OutStreamWithCRC.obj \ + +UI_COMMON_OBJS = \ + $O\ArchiveExtractCallback.obj \ + $O\ArchiveName.obj \ + $O\ArchiveOpenCallback.obj \ + $O\CompressCall.obj \ + $O\DefaultName.obj \ + $O\EnumDirItems.obj \ + $O\ExtractingFilePath.obj \ + $O\LoadCodecs.obj \ + $O\OpenArchive.obj \ + $O\PropIDUtils.obj \ + $O\SortUtils.obj \ + $O\UpdateAction.obj \ + $O\UpdateCallback.obj \ + $O\UpdatePair.obj \ + $O\UpdateProduce.obj \ + $O\WorkDir.obj \ + $O\ZipRegistry.obj \ + +EXPLORER_OBJS = \ + $O\ContextMenu.obj \ + $O\RegistryContextMenu.obj \ + +AGENT_OBJS = \ + $O\Agent.obj \ + $O\AgentOut.obj \ + $O\AgentProxy.obj \ + $O\ArchiveFolder.obj \ + $O\ArchiveFolderOpen.obj \ + $O\ArchiveFolderOut.obj \ + $O\UpdateCallbackAgent.obj \ + +C_OBJS = \ + $O\Alloc.obj \ + $O\CpuArch.obj \ + $O\Sha256.obj \ + $O\Sort.obj \ + $O\Threads.obj \ + +!include "../../Crc.mak" + +OBJS = \ + $O\StdAfx.obj \ + $(FM_OBJS)\ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(WIN_CTRL_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(AR_COMMON_OBJS) \ + $(UI_COMMON_OBJS) \ + $(EXPLORER_OBJS) \ + $(AGENT_OBJS) \ + $O\CopyCoder.obj \ + $(C_OBJS) \ + $(ASM_OBJS) \ + $O\resource.res \ + +!include "../../../Build.mak" + +$(FM_OBJS): $(*B).cpp + $(COMPL) +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +$(WIN_CTRL_OBJS): ../../../Windows/Control/$(*B).cpp + $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) +$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp + $(COMPL) +$(UI_COMMON_OBJS): ../Common/$(*B).cpp + $(COMPL) +$(AGENT_OBJS): ../Agent/$(*B).cpp + $(COMPL) +$(EXPLORER_OBJS): ../Explorer/$(*B).cpp + $(COMPL) + +$O\CopyCoder.obj: ../../Compress/$(*B).cpp + $(COMPL) +$(C_OBJS): ../../../../C/$(*B).c + $(COMPL_O2) + +!include "../../Asm.mak" diff --git a/CPP/7zip/UI/FileManager/resource.h b/CPP/7zip/UI/FileManager/resource.h new file mode 100755 index 0000000..61c6989 --- /dev/null +++ b/CPP/7zip/UI/FileManager/resource.h @@ -0,0 +1,163 @@ +#include "resourceGui.h" + +#define IDR_MENUBAR1 103 +#define IDM_MENU 103 +#define IDR_ACCELERATOR1 209 +#define IDM_FILE_OPEN 210 +#define IDM_FILE_OPEN_INSIDE 211 +#define IDM_FILE_OPEN_OUTSIDE 212 +#define IDM_FILE_VIEW 220 +#define IDM_FILE_EDIT 221 +#define IDM_RENAME 230 +#define IDM_COPY_TO 231 +#define IDM_MOVE_TO 232 +#define IDM_DELETE 233 +#define IDM_FILE_SPLIT 238 +#define IDM_FILE_COMBINE 239 +#define IDM_FILE_PROPERTIES 240 +#define IDM_FILE_COMMENT 241 +#define IDM_FILE_CRC 242 +#define IDM_FILE_DIFF 243 +#define IDM_CREATE_FOLDER 250 +#define IDM_CREATE_FILE 251 +#define IDM_EDIT_CUT 320 +#define IDM_EDIT_COPY 321 +#define IDM_EDIT_PASTE 322 +#define IDM_SELECT_ALL 330 +#define IDM_DESELECT_ALL 331 +#define IDM_INVERT_SELECTION 332 +#define IDM_SELECT 333 +#define IDM_DESELECT 334 +#define IDM_SELECT_BY_TYPE 335 +#define IDM_DESELECT_BY_TYPE 336 +#define IDM_VIEW_LARGE_ICONS 410 +#define IDM_VIEW_SMALL_ICONS 411 +#define IDM_VIEW_LIST 412 +#define IDM_VIEW_DETAILS 413 +#define IDM_VIEW_ARANGE_BY_NAME 420 +#define IDM_VIEW_ARANGE_BY_TYPE 421 +#define IDM_VIEW_ARANGE_BY_DATE 422 +#define IDM_VIEW_ARANGE_BY_SIZE 423 +#define IDM_VIEW_ARANGE_NO_SORT 424 +#define IDM_OPEN_ROOT_FOLDER 430 +#define IDM_OPEN_PARENT_FOLDER 431 +#define IDM_FOLDERS_HISTORY 432 +#define IDM_VIEW_REFRESH 440 +#define IDM_VIEW_FLAT_VIEW 449 +#define IDM_VIEW_TWO_PANELS 450 +#define IDM_VIEW_TOOLBARS 451 +#define IDM_VIEW_STANDARD_TOOLBAR 460 +#define IDM_VIEW_ARCHIVE_TOOLBAR 461 +#define IDM_VIEW_TOOLBARS_LARGE_BUTTONS 462 +#define IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT 463 +#define IDM_OPTIONS 510 +#define IDM_BENCHMARK 511 +#define IDM_HELP_CONTENTS 610 +#define IDM_ABOUT 620 +#define IDS_BOOKMARK 720 +#define IDB_ADD 2002 +#define IDB_EXTRACT 2003 +#define IDB_TEST 2004 +#define IDB_COPY 2010 +#define IDB_MOVE 2011 +#define IDB_DELETE 2012 +#define IDB_INFO 2013 +#define IDB_ADD2 2082 +#define IDB_EXTRACT2 2083 +#define IDB_TEST2 2084 +#define IDB_COPY2 2090 +#define IDB_MOVE2 2091 +#define IDB_DELETE2 2092 +#define IDB_INFO2 2093 +#define IDS_APP_TITLE 2200 +#define IDS_COPY 2201 +#define IDS_MOVE 2202 +#define IDS_COPY_TO 2203 +#define IDS_MOVE_TO 2204 +#define IDS_COPYING 2205 +#define IDS_MOVING 2206 +#define IDS_CANNOT_COPY 2207 +#define IDS_OPERATION_IS_NOT_SUPPORTED 2208 + +#define IDS_CONFIRM_FILE_DELETE 2210 +#define IDS_CONFIRM_FOLDER_DELETE 2211 +#define IDS_CONFIRM_ITEMS_DELETE 2212 +#define IDS_WANT_TO_DELETE_FILE 2213 +#define IDS_WANT_TO_DELETE_FOLDER 2214 +#define IDS_WANT_TO_DELETE_ITEMS 2215 +#define IDS_DELETING 2216 +#define IDS_ERROR_DELETING 2217 +#define IDS_ERROR_LONG_PATH_TO_RECYCLE 2218 + +#define IDS_RENAMING 2220 +#define IDS_ERROR_RENAMING 2221 +#define IDS_CONFIRM_FILE_COPY 2222 +#define IDS_WANT_TO_COPY_FILES 2223 + + +#define IDS_CREATE_FOLDER 2230 +#define IDS_CREATE_FOLDER_NAME 2231 +#define IDS_CREATE_FOLDER_DEFAULT_NAME 2232 +#define IDS_CREATE_FOLDER_ERROR 2233 +#define IDS_CREATE_FILE 2240 +#define IDS_CREATE_FILE_NAME 2241 +#define IDS_CREATE_FOLDER_DEFAULT_FILE_NAME 2242 +#define IDS_CREATE_FILE_DEFAULT_NAME 2242 +#define IDS_CREATE_FILE_ERROR 2243 +#define IDS_SELECT 2250 +#define IDS_DESELECT 2251 +#define IDS_SELECT_MASK 2252 +#define IDS_FOLDERS_HISTORY 2260 +#define IDS_N_SELECTED_ITEMS 2270 + +#define IDS_TOO_MANY_ITEMS 2279 +#define IDS_WANT_UPDATE_MODIFIED_FILE 2280 +#define IDS_CANNOT_UPDATE_FILE 2281 +#define IDS_CANNOT_START_EDITOR 2282 +#define IDS_OPENNING 2283 +#define IDS_VIRUS 2284 +#define IDS_COMPUTER 2300 +#define IDS_NETWORK 2301 +#define IDS_DOCUMENTS 2302 +#define IDS_ADD 2400 +#define IDS_EXTRACT 2401 +#define IDS_TEST 2402 +#define IDS_BUTTON_COPY 2420 +#define IDS_BUTTON_MOVE 2421 +#define IDS_BUTTON_DELETE 2422 +#define IDS_BUTTON_INFO 2423 +#define IDS_PROP_TOTAL_SIZE 3100 +#define IDS_PROP_FREE_SPACE 3101 +#define IDS_PROP_CLUSTER_SIZE 3102 +#define IDS_PROP_VOLUME_NAME 3103 +#define IDS_PROP_LOCAL_NAME 3200 +#define IDS_PROP_PROVIDER 3201 +#define IDS_OPTIONS 4000 +#define IDS_COMMENT 4001 +#define IDS_COMMENT2 4002 +#define IDS_SYSTEM 4010 + +#define IDS_SPLITTING 4020 +#define IDS_SPLIT_CONFIRM_TITLE 4021 +#define IDS_SPLIT_CONFIRM_MESSAGE 4022 +#define IDS_SPLIT_VOL_MUST_BE_SMALLER 4023 + +#define IDS_COMBINE 4030 +#define IDS_COMBINE_TO 4031 +#define IDS_COMBINING 4032 +#define IDS_COMBINE_SELECT_ONE_FILE 4033 +#define IDS_COMBINE_CANT_DETECT_SPLIT_FILE 4034 +#define IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART 4035 + +#define IDS_CHECKSUM_CALCULATING 4040 +#define IDS_CHECKSUM_INFORMATION 4041 +#define IDS_CHECKSUM_CRC_DATA 4042 +#define IDS_CHECKSUM_CRC_DATA_NAMES 4043 + +#define IDS_SCANNING 4050 +#define IDS_PROPERTIES 4060 + +#define IDS_MESSAGE_UNSUPPORTED_OPERATION_FOR_LONG_PATH_FOLDER 4301 +#define IDS_SELECT_ONE_FILE 4302 +#define IDS_SELECT_FILES 4303 +#define IDS_FILE_EXIST 4304 diff --git a/CPP/7zip/UI/FileManager/resource.rc b/CPP/7zip/UI/FileManager/resource.rc new file mode 100755 index 0000000..71144a4 --- /dev/null +++ b/CPP/7zip/UI/FileManager/resource.rc @@ -0,0 +1,248 @@ +#include "../../MyVersionInfo.rc" +#include "../../GuiCommon.rc" +#include "resource.h" + +MY_VERSION_INFO_APP("7-Zip File Manager", "7zFM") + + +IDR_ACCELERATOR1 ACCELERATORS +BEGIN + "N", IDM_CREATE_FILE, VIRTKEY, CONTROL, NOINVERT + VK_F1, IDM_HELP_CONTENTS, VIRTKEY, NOINVERT + VK_F12, IDM_FOLDERS_HISTORY, VIRTKEY, ALT, NOINVERT + VK_F7, IDM_CREATE_FOLDER, VIRTKEY, NOINVERT +END + + +IDM_MENU MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&Open\tEnter", IDM_FILE_OPEN + MENUITEM "Open &Inside\tCtrl+PgDn", IDM_FILE_OPEN_INSIDE + MENUITEM "Open O&utside\tShift+Enter", IDM_FILE_OPEN_OUTSIDE + MENUITEM "&Edit\tF4", IDM_FILE_EDIT + MENUITEM SEPARATOR + MENUITEM "Rena&me\tF2", IDM_RENAME + MENUITEM "&Copy To...\tF5", IDM_COPY_TO + MENUITEM "&Move To...\tF6", IDM_MOVE_TO + MENUITEM "&Delete\tDel", IDM_DELETE + MENUITEM SEPARATOR + MENUITEM "&Split file...", IDM_FILE_SPLIT + MENUITEM "Com&bine files...", IDM_FILE_COMBINE + MENUITEM SEPARATOR + MENUITEM "P&roperties\tAlt+Enter", IDM_FILE_PROPERTIES + MENUITEM "Comme&nt...\tCtrl+Z", IDM_FILE_COMMENT + MENUITEM "Calculate checksum", IDM_FILE_CRC + MENUITEM "Di&ff", IDM_FILE_DIFF + MENUITEM SEPARATOR + MENUITEM "Create Folder\tF7", IDM_CREATE_FOLDER + MENUITEM "Create File\tCtrl+N", IDM_CREATE_FILE + MENUITEM SEPARATOR + MENUITEM "E&xit\tAlt+F4", IDCLOSE + END + POPUP "&Edit" + BEGIN + // MENUITEM "Cu&t\tCtrl+X", IDM_EDIT_CUT, GRAYED + // MENUITEM "&Copy\tCtrl+C", IDM_EDIT_COPY, GRAYED + // MENUITEM "&Paste\tCtrl+V", IDM_EDIT_PASTE, GRAYED + // MENUITEM SEPARATOR + MENUITEM "Select &All\tShift+[Grey +]", IDM_SELECT_ALL + MENUITEM "Deselect All\tShift+[Grey -]", IDM_DESELECT_ALL + MENUITEM "&Invert Selection\tGrey *", IDM_INVERT_SELECTION + MENUITEM "Select...\tGrey +", IDM_SELECT + MENUITEM "Deselect...\tGrey -", IDM_DESELECT + MENUITEM "Select by Type\tAlt+[Grey+]", IDM_SELECT_BY_TYPE + MENUITEM "Deselect by Type\tAlt+[Grey -]", IDM_DESELECT_BY_TYPE + END + POPUP "&View" + BEGIN + MENUITEM "Lar&ge Icons\tCtrl+1", IDM_VIEW_LARGE_ICONS + MENUITEM "S&mall Icons\tCtrl+2", IDM_VIEW_SMALL_ICONS + MENUITEM "&List\tCtrl+3", IDM_VIEW_LIST + MENUITEM "&Details\tCtrl+4", IDM_VIEW_DETAILS, CHECKED + MENUITEM SEPARATOR + MENUITEM "Name\tCtrl+F3", IDM_VIEW_ARANGE_BY_NAME + MENUITEM "Type\tCtrl+F4", IDM_VIEW_ARANGE_BY_TYPE + MENUITEM "Date\tCtrl+F5", IDM_VIEW_ARANGE_BY_DATE + MENUITEM "Size\tCtrl+F6", IDM_VIEW_ARANGE_BY_SIZE + MENUITEM "Unsorted\tCtrl+F7", IDM_VIEW_ARANGE_NO_SORT + MENUITEM SEPARATOR + MENUITEM "Flat View", IDM_VIEW_FLAT_VIEW + MENUITEM "&2 Panels\tF9", IDM_VIEW_TWO_PANELS + POPUP "Toolbars" + BEGIN + MENUITEM "Archive Toolbar", IDM_VIEW_ARCHIVE_TOOLBAR + MENUITEM "Standard Toolbar", IDM_VIEW_STANDARD_TOOLBAR + MENUITEM SEPARATOR + MENUITEM "Large Buttons", IDM_VIEW_TOOLBARS_LARGE_BUTTONS + MENUITEM "Show Buttons Text", IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT + END + MENUITEM "Open Root Folder\t\\", IDM_OPEN_ROOT_FOLDER + MENUITEM "Up One Level\tBackspace", IDM_OPEN_PARENT_FOLDER + MENUITEM "Folders History...\tAlt+F12", IDM_FOLDERS_HISTORY + MENUITEM "&Refresh\tCtrl+R", IDM_VIEW_REFRESH + END + POPUP "F&avorites" + BEGIN + POPUP "&Add folder to Favorites as" + BEGIN + MENUITEM SEPARATOR + END + MENUITEM SEPARATOR + END + POPUP "&Tools" + BEGIN + MENUITEM "&Options...", IDM_OPTIONS + MENUITEM "&Benchmark", IDM_BENCHMARK + #ifndef UNDER_CE + END + POPUP "&Help" + BEGIN + MENUITEM "&Contents...\tF1", IDM_HELP_CONTENTS + #endif + MENUITEM SEPARATOR + MENUITEM "&About 7-Zip...", IDM_ABOUT + END +END + + +IDI_ICON ICON "../../UI/FileManager/FM.ico" + +#ifndef UNDER_CE +1 24 MOVEABLE PURE "../../UI/FileManager/7zFM.exe.manifest" +#endif + +IDB_ADD BITMAP "../../UI/FileManager/Add.bmp" +IDB_EXTRACT BITMAP "../../UI/FileManager/Extract.bmp" +IDB_TEST BITMAP "../../UI/FileManager/Test.bmp" +IDB_COPY BITMAP "../../UI/FileManager/Copy.bmp" +IDB_MOVE BITMAP "../../UI/FileManager/Move.bmp" +IDB_DELETE BITMAP "../../UI/FileManager/Delete.bmp" +IDB_INFO BITMAP "../../UI/FileManager/Info.bmp" +IDB_ADD2 BITMAP "../../UI/FileManager/Add2.bmp" +IDB_EXTRACT2 BITMAP "../../UI/FileManager/Extract2.bmp" +IDB_TEST2 BITMAP "../../UI/FileManager/Test2.bmp" +IDB_COPY2 BITMAP "../../UI/FileManager/Copy2.bmp" +IDB_MOVE2 BITMAP "../../UI/FileManager/Move2.bmp" +IDB_DELETE2 BITMAP "../../UI/FileManager/Delete2.bmp" +IDB_INFO2 BITMAP "../../UI/FileManager/Info2.bmp" + + +STRINGTABLE +BEGIN + IDS_APP_TITLE "7-Zip File Manager" + IDS_COPY "Copy" + IDS_MOVE "Move" + IDS_COPY_TO "Copy to:" + IDS_MOVE_TO "Move to:" + IDS_COPYING "Copying..." + IDS_MOVING "Moving..." + IDS_CANNOT_COPY "You cannot move or copy items for such folders." + IDS_SPLITTING "Splitting..." + IDS_SPLIT_CONFIRM_TITLE "Confirm Splitting" + IDS_SPLIT_CONFIRM_MESSAGE "Are you sure you want to split file into {0} volumes?" + IDS_SPLIT_VOL_MUST_BE_SMALLER "Volume size must be smaller than size of original file" + + IDS_COMBINE "Combine Files" + IDS_COMBINE_TO "&Combine to:" + IDS_COMBINING "Combining..." + IDS_COMBINE_SELECT_ONE_FILE "Select only first part of split file" + IDS_COMBINE_CANT_DETECT_SPLIT_FILE "Can not detect file as split file" + IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART "Can not find more than one part of split file" + + IDS_CHECKSUM_CALCULATING "Checksum calculating..." + IDS_CHECKSUM_INFORMATION "Checksum information" + IDS_CHECKSUM_CRC_DATA "CRC checksum for data:" + IDS_CHECKSUM_CRC_DATA_NAMES "CRC checksum for data and names:" + + IDS_SCANNING "Scanning..." + + IDS_PROPERTIES "Properties" + + IDS_OPERATION_IS_NOT_SUPPORTED "Operation is not supported." + + IDS_CONFIRM_FILE_DELETE "Confirm File Delete" + IDS_CONFIRM_FOLDER_DELETE "Confirm Folder Delete" + IDS_CONFIRM_ITEMS_DELETE "Confirm Multiple File Delete" + IDS_WANT_TO_DELETE_FILE "Are you sure you want to delete '{0}'?" + IDS_WANT_TO_DELETE_FOLDER "Are you sure you want to delete the folder '{0}' and all its contents?" + IDS_WANT_TO_DELETE_ITEMS "Are you sure you want to delete these {0} items?" + IDS_DELETING "Deleting..." + IDS_ERROR_DELETING "Error Deleting File or Folder" + IDS_ERROR_LONG_PATH_TO_RECYCLE "The system cannot move a file with long path to the Recycle Bin" + IDS_RENAMING "Renaming..." + IDS_ERROR_RENAMING "Error Renaming File or Folder" + IDS_CONFIRM_FILE_COPY "Confirm File Copy" + IDS_WANT_TO_COPY_FILES "Are you sure you want to copy files to archive" + + IDS_CREATE_FOLDER "Create Folder" + IDS_CREATE_FOLDER_NAME "Folder name:" + IDS_CREATE_FOLDER_DEFAULT_NAME "New Folder" + IDS_CREATE_FOLDER_ERROR "Error Creating Folder" + IDS_CREATE_FILE "Create File" + IDS_CREATE_FILE_NAME "File Name:" + IDS_CREATE_FILE_DEFAULT_NAME "New File" + IDS_CREATE_FILE_ERROR "Error Creating File" + IDS_SELECT "Select" + IDS_DESELECT "Deselect" + IDS_SELECT_MASK "Mask:" + IDS_FOLDERS_HISTORY "Folders History" + IDS_N_SELECTED_ITEMS "{0} object(s) selected" + + IDS_PROP_TOTAL_SIZE "Total Size" + IDS_PROP_FREE_SPACE "Free Space" + IDS_PROP_CLUSTER_SIZE "Cluster Size" + IDS_PROP_VOLUME_NAME "Label" + IDS_PROP_LOCAL_NAME "Local Name" + IDS_PROP_PROVIDER "Provider" + IDS_OPTIONS "Options" + IDS_COMMENT "Comment" + IDS_COMMENT2 "&Comment:" + IDS_SYSTEM "System" + IDS_TOO_MANY_ITEMS "Too many items" + IDS_WANT_UPDATE_MODIFIED_FILE "File '{0}' was modified.\nDo you want to update it in the archive?" + IDS_CANNOT_UPDATE_FILE "Can not update file\n'{0}'" + IDS_CANNOT_START_EDITOR "Cannot start editor." + IDS_OPENNING "Opening..." + IDS_VIRUS "The file looks like a virus (the file name contains long spaces in name)." + IDS_ADD "Add" + IDS_EXTRACT "Extract" + IDS_TEST "Test" + IDS_BUTTON_COPY "Copy" + IDS_BUTTON_MOVE "Move" + IDS_BUTTON_DELETE "Delete" + IDS_BUTTON_INFO "Info" + IDS_BOOKMARK "Bookmark" + IDS_COMPUTER "Computer" + IDS_NETWORK "Network" + IDS_DOCUMENTS "Documents" + + IDS_MESSAGE_UNSUPPORTED_OPERATION_FOR_LONG_PATH_FOLDER "The operation cannot be called from a folder that has a long path." + IDS_SELECT_ONE_FILE "You must select one file" + IDS_SELECT_FILES "You must select one or more files" + IDS_FILE_EXIST "File {0} is already exist" +END + + +#include "AboutDialog.rc" +#include "BrowseDialog.rc" +#include "ComboDialog.rc" +#include "CopyDialog.rc" +#include "EditPage.rc" +#include "FoldersPage.rc" +#include "LangPage.rc" +#include "ListViewDialog.rc" +#include "MenuPage.rc" +#include "MessagesDialog.rc" +#include "OverwriteDialog.rc" +#include "PasswordDialog.rc" +#include "PluginsPage.rc" +#include "ProgressDialog2.rc" +#include "PropertyName.rc" +#include "SettingsPage.rc" +#include "SplitDialog.rc" +#include "SystemPage.rc" +#include "../GUI/Extract.rc" +#include "../Explorer/resource2.rc" +#include "resourceGui.rc" diff --git a/CPP/7zip/UI/FileManager/resourceGui.h b/CPP/7zip/UI/FileManager/resourceGui.h new file mode 100755 index 0000000..74124ab --- /dev/null +++ b/CPP/7zip/UI/FileManager/resourceGui.h @@ -0,0 +1,10 @@ +#define IDI_ICON 1 + +#define IDS_INCORRECT_VOLUME_SIZE 95 + +#define IDS_FILES_COLON 2274 +#define IDS_FOLDERS_COLON 2275 +#define IDS_SIZE_COLON 2276 + +#define IDS_PROGRESS_TESTING 4100 +#define IDS_MESSAGE_NO_ERRORS 4200 diff --git a/CPP/7zip/UI/FileManager/resourceGui.rc b/CPP/7zip/UI/FileManager/resourceGui.rc new file mode 100755 index 0000000..227ec35 --- /dev/null +++ b/CPP/7zip/UI/FileManager/resourceGui.rc @@ -0,0 +1,13 @@ +#include "resourceGui.h" + +STRINGTABLE +BEGIN + IDS_INCORRECT_VOLUME_SIZE "Incorrect volume size" + + IDS_FILES_COLON "Files:" + IDS_FOLDERS_COLON "Folders:" + IDS_SIZE_COLON "Size:" + + IDS_PROGRESS_TESTING "Testing" + IDS_MESSAGE_NO_ERRORS "There are no errors" +END diff --git a/CPP/7zip/UI/GUI/7zG.exe.manifest b/CPP/7zip/UI/GUI/7zG.exe.manifest new file mode 100755 index 0000000..504328c --- /dev/null +++ b/CPP/7zip/UI/GUI/7zG.exe.manifest @@ -0,0 +1 @@ +7-Zip GUI. diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp new file mode 100755 index 0000000..8d8e7ef --- /dev/null +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp @@ -0,0 +1,581 @@ +// BenchmarkDialog.cpp + +#include "StdAfx.h" + +#include "Common/IntToString.h" +#include "Common/MyException.h" + +#include "Windows/Error.h" +#include "Windows/System.h" +#include "Windows/Thread.h" + +#include "../FileManager/HelpUtils.h" + +#include "BenchmarkDialog.h" + +using namespace NWindows; + +static LPCWSTR kHelpTopic = L"fm/benchmark.htm"; + +static const UINT_PTR kTimerID = 4; +static const UINT kTimerElapse = 1000; + +#ifdef LANG +#include "../FileManager/LangUtils.h" +#endif + +using namespace NWindows; + +UString HResultToMessage(HRESULT errorCode); + +#ifdef LANG +static CIDLangPair kIDLangPairs[] = +{ + { IDC_BENCHMARK_DICTIONARY, 0x02000D0C }, + { IDC_BENCHMARK_MEMORY, 0x03080001 }, + { IDC_BENCHMARK_NUM_THREADS, 0x02000D12 }, + { IDC_BENCHMARK_SPEED_LABEL, 0x03080004 }, + { IDC_BENCHMARK_RATING_LABEL, 0x03080005 }, + { IDC_BENCHMARK_COMPRESSING, 0x03080002 }, + { IDC_BENCHMARK_DECOMPRESSING, 0x03080003 }, + { IDC_BENCHMARK_CURRENT, 0x03080007 }, + { IDC_BENCHMARK_RESULTING, 0x03080008 }, + { IDC_BENCHMARK_CURRENT2, 0x03080007 }, + { IDC_BENCHMARK_RESULTING2, 0x03080008 }, + { IDC_BENCHMARK_TOTAL_RATING, 0x03080006 }, + { IDC_BENCHMARK_ELAPSED, 0x02000C01 }, + { IDC_BENCHMARK_SIZE, 0x02000C03 }, + { IDC_BENCHMARK_PASSES, 0x03080009 }, + // { IDC_BENCHMARK_ERRORS, 0x0308000A }, + { IDC_BENCHMARK_USAGE_LABEL, 0x0308000B }, + { IDC_BENCHMARK_RPU_LABEL, 0x0308000C }, + { IDC_BENCHMARK_COMBO_NUM_THREADS, 0x02000D12}, + + { IDC_BUTTON_STOP, 0x02000714 }, + { IDC_BUTTON_RESTART, 0x02000715 }, + { IDHELP, 0x02000720 }, + { IDCANCEL, 0x02000710 } +}; +#endif + +const LPCTSTR kProcessingString = TEXT("..."); +const LPCTSTR kMB = TEXT(" MB"); +const LPCTSTR kMIPS = TEXT(" MIPS"); +const LPCTSTR kKBs = TEXT(" KB/s"); + +#ifdef UNDER_CE +static const int kMinDicLogSize = 20; +#else +static const int kMinDicLogSize = 21; +#endif +static const UInt32 kMinDicSize = (1 << kMinDicLogSize); +static const UInt32 kMaxDicSize = + #ifdef _WIN64 + (1 << 30); + #else + (1 << 27); + #endif + +bool CBenchmarkDialog::OnInit() +{ + #ifdef LANG + LangSetWindowText(HWND(*this), 0x03080000); + LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + #endif + + Sync.Init(); + + + UInt32 numCPUs = NSystem::GetNumberOfProcessors(); + if (numCPUs < 1) + numCPUs = 1; + numCPUs = MyMin(numCPUs, (UInt32)(1 << 8)); + + if (Sync.NumThreads == (UInt32)-1) + { + Sync.NumThreads = numCPUs; + if (Sync.NumThreads > 1) + Sync.NumThreads &= ~1; + } + m_NumThreads.Attach(GetItem(IDC_BENCHMARK_COMBO_NUM_THREADS)); + int cur = 0; + for (UInt32 num = 1; num <= numCPUs * 2;) + { + TCHAR s[40]; + ConvertUInt64ToString(num, s); + int index = (int)m_NumThreads.AddString(s); + m_NumThreads.SetItemData(index, num); + if (num <= Sync.NumThreads) + cur = index; + if (num > 1) + num++; + num++; + } + m_NumThreads.SetCurSel(cur); + Sync.NumThreads = GetNumberOfThreads(); + + m_Dictionary.Attach(GetItem(IDC_BENCHMARK_COMBO_DICTIONARY)); + cur = 0; + UInt64 ramSize = NSystem::GetRamSize(); + + #ifdef UNDER_CE + const UInt32 kNormalizedCeSize = (16 << 20); + if (ramSize > kNormalizedCeSize && ramSize < (33 << 20)) + ramSize = kNormalizedCeSize; + #endif + + if (Sync.DictionarySize == (UInt32)-1) + { + int dicSizeLog; + for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--) + if (GetBenchMemoryUsage(Sync.NumThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize) + break; + Sync.DictionarySize = (1 << dicSizeLog); + } + if (Sync.DictionarySize < kMinDicSize) + Sync.DictionarySize = kMinDicSize; + if (Sync.DictionarySize > kMaxDicSize) + Sync.DictionarySize = kMaxDicSize; + + for (int i = kMinDicLogSize; i <= 30; i++) + for (int j = 0; j < 2; j++) + { + UInt32 dictionary = (1 << i) + (j << (i - 1)); + if (dictionary > kMaxDicSize) + continue; + TCHAR s[40]; + ConvertUInt64ToString((dictionary >> 20), s); + lstrcat(s, kMB); + int index = (int)m_Dictionary.AddString(s); + m_Dictionary.SetItemData(index, dictionary); + if (dictionary <= Sync.DictionarySize) + cur = index; + } + m_Dictionary.SetCurSel(cur); + + OnChangeSettings(); + + Sync._startEvent.Set(); + _timer = SetTimer(kTimerID, kTimerElapse); + + NormalizePosition(); + return CModalDialog::OnInit(); +} + +UInt32 CBenchmarkDialog::GetNumberOfThreads() +{ + return (UInt32)m_NumThreads.GetItemData(m_NumThreads.GetCurSel()); +} + +UInt32 CBenchmarkDialog::OnChangeDictionary() +{ + UInt32 dictionary = (UInt32)m_Dictionary.GetItemData(m_Dictionary.GetCurSel()); + UInt64 memUsage = GetBenchMemoryUsage(GetNumberOfThreads(), dictionary); + memUsage = (memUsage + (1 << 20) - 1) >> 20; + TCHAR s[40]; + ConvertUInt64ToString(memUsage, s); + lstrcat(s, kMB); + SetItemText(IDC_BENCHMARK_MEMORY_VALUE, s); + return dictionary; +} + +static const UInt32 g_IDs[] = +{ + IDC_BENCHMARK_COMPRESSING_USAGE, + IDC_BENCHMARK_COMPRESSING_USAGE2, + IDC_BENCHMARK_COMPRESSING_SPEED, + IDC_BENCHMARK_COMPRESSING_SPEED2, + IDC_BENCHMARK_COMPRESSING_RATING, + IDC_BENCHMARK_COMPRESSING_RATING2, + IDC_BENCHMARK_COMPRESSING_RPU, + IDC_BENCHMARK_COMPRESSING_RPU2, + + IDC_BENCHMARK_DECOMPRESSING_SPEED, + IDC_BENCHMARK_DECOMPRESSING_SPEED2, + IDC_BENCHMARK_DECOMPRESSING_RATING, + IDC_BENCHMARK_DECOMPRESSING_RATING2, + IDC_BENCHMARK_DECOMPRESSING_USAGE, + IDC_BENCHMARK_DECOMPRESSING_USAGE2, + IDC_BENCHMARK_DECOMPRESSING_RPU, + IDC_BENCHMARK_DECOMPRESSING_RPU2, + + IDC_BENCHMARK_TOTAL_USAGE_VALUE, + IDC_BENCHMARK_TOTAL_RATING_VALUE, + IDC_BENCHMARK_TOTAL_RPU_VALUE +}; + +void CBenchmarkDialog::OnChangeSettings() +{ + EnableItem(IDC_BUTTON_STOP, true); + UInt32 dictionary = OnChangeDictionary(); + TCHAR s[40] = { TEXT('/'), TEXT(' '), 0 }; + ConvertUInt64ToString(NSystem::GetNumberOfProcessors(), s + 2); + SetItemText(IDC_BENCHMARK_HARDWARE_THREADS, s); + for (int i = 0; i < sizeof(g_IDs) / sizeof(g_IDs[0]); i++) + SetItemText(g_IDs[i], kProcessingString); + _startTime = GetTickCount(); + PrintTime(); + NWindows::NSynchronization::CCriticalSectionLock lock(Sync.CS); + Sync.Init(); + Sync.DictionarySize = dictionary; + Sync.Changed = true; + Sync.NumThreads = GetNumberOfThreads(); +} + +void CBenchmarkDialog::OnRestartButton() +{ + OnChangeSettings(); +} + +void CBenchmarkDialog::OnStopButton() +{ + EnableItem(IDC_BUTTON_STOP, false); + Sync.Pause(); +} + +void CBenchmarkDialog::OnHelp() +{ + ShowHelpWindow(NULL, kHelpTopic); +} + +void CBenchmarkDialog::OnCancel() +{ + Sync.Stop(); + KillTimer(_timer); + CModalDialog::OnCancel(); +} + +static void GetTimeString(UInt64 timeValue, TCHAR *s) +{ + wsprintf(s, TEXT("%02d:%02d:%02d"), + UInt32(timeValue / 3600), + UInt32((timeValue / 60) % 60), + UInt32(timeValue % 60)); +} + +void CBenchmarkDialog::PrintTime() +{ + UInt32 curTime = ::GetTickCount(); + UInt32 elapsedTime = (curTime - _startTime); + UInt32 elapsedSec = elapsedTime / 1000; + if (elapsedSec != 0 && Sync.WasPaused()) + return; + TCHAR s[40]; + GetTimeString(elapsedSec, s); + SetItemText(IDC_BENCHMARK_ELAPSED_VALUE, s); +} + +void CBenchmarkDialog::PrintRating(UInt64 rating, UINT controlID) +{ + TCHAR s[40]; + ConvertUInt64ToString(rating / 1000000, s); + lstrcat(s, kMIPS); + SetItemText(controlID, s); +} + +void CBenchmarkDialog::PrintUsage(UInt64 usage, UINT controlID) +{ + TCHAR s[40]; + ConvertUInt64ToString((usage + 5000) / 10000, s); + lstrcat(s, TEXT("%")); + SetItemText(controlID, s); +} + +void CBenchmarkDialog::PrintResults( + UInt32 dictionarySize, + const CBenchInfo2 &info, + UINT usageID, UINT speedID, UINT rpuID, UINT ratingID, + bool decompressMode) +{ + if (info.GlobalTime == 0) + return; + + UInt64 size = info.UnpackSize; + TCHAR s[40]; + { + UInt64 speed = size * info.GlobalFreq / info.GlobalTime; + ConvertUInt64ToString(speed / 1024, s); + lstrcat(s, kKBs); + SetItemText(speedID, s); + } + UInt64 rating; + if (decompressMode) + rating = GetDecompressRating(info.GlobalTime, info.GlobalFreq, size, info.PackSize, 1); + else + rating = GetCompressRating(dictionarySize, info.GlobalTime, info.GlobalFreq, size * info.NumIterations); + + PrintRating(rating, ratingID); + PrintRating(GetRatingPerUsage(info, rating), rpuID); + PrintUsage(GetUsage(info), usageID); +} + +bool CBenchmarkDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */) +{ + PrintTime(); + NWindows::NSynchronization::CCriticalSectionLock lock(Sync.CS); + + TCHAR s[40]; + ConvertUInt64ToString((Sync.ProcessedSize >> 20), s); + lstrcat(s, kMB); + SetItemText(IDC_BENCHMARK_SIZE_VALUE, s); + + ConvertUInt64ToString(Sync.NumPasses, s); + SetItemText(IDC_BENCHMARK_PASSES_VALUE, s); + + /* + ConvertUInt64ToString(Sync.NumErrors, s); + SetItemText(IDC_BENCHMARK_ERRORS_VALUE, s); + */ + + { + UInt32 dicSizeTemp = (UInt32)MyMax(Sync.ProcessedSize, UInt64(1) << 20); + dicSizeTemp = MyMin(dicSizeTemp, Sync.DictionarySize), + PrintResults(dicSizeTemp, + Sync.CompressingInfoTemp, + IDC_BENCHMARK_COMPRESSING_USAGE, + IDC_BENCHMARK_COMPRESSING_SPEED, + IDC_BENCHMARK_COMPRESSING_RPU, + IDC_BENCHMARK_COMPRESSING_RATING); + } + + { + PrintResults( + Sync.DictionarySize, + Sync.CompressingInfo, + IDC_BENCHMARK_COMPRESSING_USAGE2, + IDC_BENCHMARK_COMPRESSING_SPEED2, + IDC_BENCHMARK_COMPRESSING_RPU2, + IDC_BENCHMARK_COMPRESSING_RATING2); + } + + { + PrintResults( + Sync.DictionarySize, + Sync.DecompressingInfoTemp, + IDC_BENCHMARK_DECOMPRESSING_USAGE, + IDC_BENCHMARK_DECOMPRESSING_SPEED, + IDC_BENCHMARK_DECOMPRESSING_RPU, + IDC_BENCHMARK_DECOMPRESSING_RATING, + true); + } + { + PrintResults( + Sync.DictionarySize, + Sync.DecompressingInfo, + IDC_BENCHMARK_DECOMPRESSING_USAGE2, + IDC_BENCHMARK_DECOMPRESSING_SPEED2, + IDC_BENCHMARK_DECOMPRESSING_RPU2, + IDC_BENCHMARK_DECOMPRESSING_RATING2, + true); + if (Sync.DecompressingInfo.GlobalTime > 0 && + Sync.CompressingInfo.GlobalTime > 0) + { + UInt64 comprRating = GetCompressRating(Sync.DictionarySize, + Sync.CompressingInfo.GlobalTime, Sync.CompressingInfo.GlobalFreq, Sync.CompressingInfo.UnpackSize); + UInt64 decomprRating = GetDecompressRating(Sync.DecompressingInfo.GlobalTime, + Sync.DecompressingInfo.GlobalFreq, Sync.DecompressingInfo.UnpackSize, + Sync.DecompressingInfo.PackSize, 1); + PrintRating((comprRating + decomprRating) / 2, IDC_BENCHMARK_TOTAL_RATING_VALUE); + PrintRating(( + GetRatingPerUsage(Sync.CompressingInfo, comprRating) + + GetRatingPerUsage(Sync.DecompressingInfo, decomprRating)) / 2, IDC_BENCHMARK_TOTAL_RPU_VALUE); + PrintUsage((GetUsage(Sync.CompressingInfo) + GetUsage(Sync.DecompressingInfo)) / 2, IDC_BENCHMARK_TOTAL_USAGE_VALUE); + } + } + return true; +} + +bool CBenchmarkDialog::OnCommand(int code, int itemID, LPARAM lParam) +{ + if (code == CBN_SELCHANGE && + (itemID == IDC_BENCHMARK_COMBO_DICTIONARY || + itemID == IDC_BENCHMARK_COMBO_NUM_THREADS)) + { + OnChangeSettings(); + return true; + } + return CModalDialog::OnCommand(code, itemID, lParam); +} + +bool CBenchmarkDialog::OnButtonClicked(int buttonID, HWND buttonHWND) +{ + switch(buttonID) + { + case IDC_BUTTON_RESTART: + OnRestartButton(); + return true; + case IDC_BUTTON_STOP: + OnStopButton(); + return true; + } + return CModalDialog::OnButtonClicked(buttonID, buttonHWND); +} + +struct CThreadBenchmark +{ + CBenchmarkDialog *BenchmarkDialog; + UInt64 _startTime; + DECL_EXTERNAL_CODECS_VARS + // UInt32 dictionarySize; + // UInt32 numThreads; + + HRESULT Process(); + HRESULT Result; + static THREAD_FUNC_DECL MyThreadFunction(void *param) + { + ((CThreadBenchmark *)param)->Result = ((CThreadBenchmark *)param)->Process(); + return 0; + } +}; + +struct CBenchCallback: public IBenchCallback +{ + UInt32 dictionarySize; + CProgressSyncInfo *Sync; + HRESULT SetEncodeResult(const CBenchInfo &info, bool final); + HRESULT SetDecodeResult(const CBenchInfo &info, bool final); +}; + +HRESULT CBenchCallback::SetEncodeResult(const CBenchInfo &info, bool final) +{ + NSynchronization::CCriticalSectionLock lock(Sync->CS); + if (Sync->Changed || Sync->Paused || Sync->Stopped) + return E_ABORT; + Sync->ProcessedSize = info.UnpackSize; + if (final && Sync->CompressingInfo.GlobalTime == 0) + { + (CBenchInfo&)Sync->CompressingInfo = info; + if (Sync->CompressingInfo.GlobalTime == 0) + Sync->CompressingInfo.GlobalTime = 1; + } + else + (CBenchInfo&)Sync->CompressingInfoTemp = info; + + return S_OK; +} + +HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final) +{ + NSynchronization::CCriticalSectionLock lock(Sync->CS); + if (Sync->Changed || Sync->Paused || Sync->Stopped) + return E_ABORT; + CBenchInfo info2 = info; + if (info2.NumIterations == 0) + info2.NumIterations = 1; + + info2.UnpackSize *= info2.NumIterations; + info2.PackSize *= info2.NumIterations; + info2.NumIterations = 1; + + if (final && Sync->DecompressingInfo.GlobalTime == 0) + { + (CBenchInfo&)Sync->DecompressingInfo = info2; + if (Sync->DecompressingInfo.GlobalTime == 0) + Sync->DecompressingInfo.GlobalTime = 1; + } + else + (CBenchInfo&)Sync->DecompressingInfoTemp = info2; + return S_OK; +} + +HRESULT CThreadBenchmark::Process() +{ + CProgressSyncInfo &sync = BenchmarkDialog->Sync; + sync.WaitCreating(); + try + { + for (;;) + { + if (sync.WasStopped()) + return 0; + if (sync.WasPaused()) + { + Sleep(200); + continue; + } + UInt32 dictionarySize; + UInt32 numThreads; + { + NSynchronization::CCriticalSectionLock lock(sync.CS); + if (sync.Stopped || sync.Paused) + continue; + if (sync.Changed) + sync.Init(); + dictionarySize = sync.DictionarySize; + numThreads = sync.NumThreads; + } + + CBenchCallback callback; + callback.dictionarySize = dictionarySize; + callback.Sync = &sync; + HRESULT result; + try + { + result = LzmaBench( + EXTERNAL_CODECS_VARS + numThreads, dictionarySize, &callback); + } + catch(...) + { + result = E_FAIL; + } + + if (result != S_OK) + { + if (result != E_ABORT) + { + // sync.NumErrors++; + { + NSynchronization::CCriticalSectionLock lock(sync.CS); + sync.Pause(); + } + UString message; + if (result == S_FALSE) + message = L"Decoding error"; + else if (result == CLASS_E_CLASSNOTAVAILABLE) + message = L"Can't find 7z.dll"; + else + message = HResultToMessage(result); + BenchmarkDialog->MessageBoxError(message); + } + } + else + { + NSynchronization::CCriticalSectionLock lock(sync.CS); + sync.NumPasses++; + } + } + // return S_OK; + } + catch(CSystemException &e) + { + BenchmarkDialog->MessageBoxError(HResultToMessage(e.ErrorCode)); + return E_FAIL; + } + catch(...) + { + BenchmarkDialog->MessageBoxError(HResultToMessage(E_FAIL)); + return E_FAIL; + } +} + +HRESULT Benchmark( + DECL_EXTERNAL_CODECS_LOC_VARS + UInt32 numThreads, UInt32 dictionarySize, HWND hwndParent) +{ + CThreadBenchmark benchmarker; + #ifdef EXTERNAL_CODECS + benchmarker._codecsInfo = codecsInfo; + benchmarker._externalCodecs = *externalCodecs; + #endif + + CBenchmarkDialog benchmarkDialog; + benchmarkDialog.Sync.DictionarySize = dictionarySize; + benchmarkDialog.Sync.NumThreads = numThreads; + + benchmarker.BenchmarkDialog = &benchmarkDialog; + NWindows::CThread thread; + RINOK(thread.Create(CThreadBenchmark::MyThreadFunction, &benchmarker)); + benchmarkDialog.Create(hwndParent); + return thread.Wait(); +} diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.h b/CPP/7zip/UI/GUI/BenchmarkDialog.h new file mode 100755 index 0000000..6b0d4d2 --- /dev/null +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.h @@ -0,0 +1,135 @@ +// BenchmarkDialog.h + +#ifndef __BENCHMARK_DIALOG_H +#define __BENCHMARK_DIALOG_H + +#include "Windows/Synchronization.h" +#include "Windows/Control/ComboBox.h" + +#include "../Common/Bench.h" + +#include "../FileManager/DialogSize.h" + +#include "BenchmarkDialogRes.h" + +struct CBenchInfo2 : public CBenchInfo +{ + void Init() { GlobalTime = UserTime = 0; } +}; + +class CProgressSyncInfo +{ +public: + bool Stopped; + bool Paused; + bool Changed; + UInt32 DictionarySize; + UInt32 NumThreads; + UInt64 NumPasses; + // UInt64 NumErrors; + NWindows::NSynchronization::CManualResetEvent _startEvent; + NWindows::NSynchronization::CCriticalSection CS; + + CBenchInfo2 CompressingInfoTemp; + CBenchInfo2 CompressingInfo; + UInt64 ProcessedSize; + + CBenchInfo2 DecompressingInfoTemp; + CBenchInfo2 DecompressingInfo; + + CProgressSyncInfo() + { + if (_startEvent.Create() != S_OK) + throw 3986437; + } + void Init() + { + Changed = false; + Stopped = false; + Paused = false; + CompressingInfoTemp.Init(); + CompressingInfo.Init(); + ProcessedSize = 0; + + DecompressingInfoTemp.Init(); + DecompressingInfo.Init(); + + NumPasses = 0; + // NumErrors = 0; + } + void Stop() + { + NWindows::NSynchronization::CCriticalSectionLock lock(CS); + Stopped = true; + } + bool WasStopped() + { + NWindows::NSynchronization::CCriticalSectionLock lock(CS); + return Stopped; + } + void Pause() + { + NWindows::NSynchronization::CCriticalSectionLock lock(CS); + Paused = true; + } + void Start() + { + NWindows::NSynchronization::CCriticalSectionLock lock(CS); + Paused = false; + } + bool WasPaused() + { + NWindows::NSynchronization::CCriticalSectionLock lock(CS); + return Paused; + } + void WaitCreating() { _startEvent.Lock(); } +}; + +class CBenchmarkDialog: + public NWindows::NControl::CModalDialog +{ + NWindows::NControl::CComboBox m_Dictionary; + NWindows::NControl::CComboBox m_NumThreads; + UINT_PTR _timer; + UINT32 _startTime; + + bool OnTimer(WPARAM timerID, LPARAM callback); + virtual bool OnInit(); + void OnRestartButton(); + void OnStopButton(); + void OnHelp(); + virtual void OnCancel(); + bool OnButtonClicked(int buttonID, HWND buttonHWND); + bool OnCommand(int code, int itemID, LPARAM lParam); + + void PrintTime(); + void PrintRating(UInt64 rating, UINT controlID); + void PrintUsage(UInt64 usage, UINT controlID); + void PrintResults( + UINT32 dictionarySize, + const CBenchInfo2 &info, UINT usageID, UINT speedID, UINT rpuID, UINT ratingID, + bool decompressMode = false); + + UInt32 GetNumberOfThreads(); + UInt32 OnChangeDictionary(); + void OnChangeSettings(); +public: + CProgressSyncInfo Sync; + + CBenchmarkDialog(): _timer(0) {} + INT_PTR Create(HWND wndParent = 0) + { + BIG_DIALOG_SIZE(332, 228); + return CModalDialog::Create(SIZED_DIALOG(IDD_DIALOG_BENCHMARK), wndParent); + } + void MessageBoxError(LPCWSTR message) + { + MessageBoxW(*this, message, L"7-Zip", MB_ICONERROR); + } +}; + +HRESULT Benchmark( + DECL_EXTERNAL_CODECS_LOC_VARS + UInt32 numThreads, UInt32 dictionarySize, HWND hwndParent = NULL); + +#endif diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.rc b/CPP/7zip/UI/GUI/BenchmarkDialog.rc new file mode 100755 index 0000000..da30fc3 --- /dev/null +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.rc @@ -0,0 +1,227 @@ +#include "BenchmarkDialogRes.h" +#include "../../GuiCommon.rc" + +#define xc 332 +#define yc 228 + +#undef g0xs +#undef g1x +#undef g1xs +#undef g2xs +#undef g3x +#undef g3xs +#undef g4x + +#define gs 160 +#define gSpace 24 + +#define g0xs 90 +#define g1xs 44 +#define g1x (m + g0xs) +#define gc2x (g1x + g1xs + m) +#define gc2xs 80 + +#define g4x (m + m) + +#define sRating 60 +#define sSpeed 60 +#define sUsage 60 +#define sRpu 60 + +#define xRating (xs - m - m - sRating) +#define xRpu (xRating - sRpu) +#define xUsage (xRpu - sUsage) +#define xSpeed (xUsage - sSpeed) + +#define sLabel (xUsage - g4x) +#define sTotalRating (sUsage + sRpu + sRating + m + m) +#define xTotalRating (xs - m - sTotalRating) + +#define g2xs 58 +#define g3xs 36 +#define g3x (m + g2xs) + + +IDD_DIALOG_BENCHMARK DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE | WS_MINIMIZEBOX +CAPTION "Benchmark" +MY_FONT +BEGIN + PUSHBUTTON "&Restart", IDC_BUTTON_RESTART, bx1, m, bxs, bys + PUSHBUTTON "&Stop", IDC_BUTTON_STOP, bx1, m + bys + 6, bxs, bys + + PUSHBUTTON "&Help", IDHELP, bx2, by, bxs, bys + PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys + + LTEXT "&Dictionary size:", IDC_BENCHMARK_DICTIONARY, m, m + 1, g0xs, 8 + COMBOBOX IDC_BENCHMARK_COMBO_DICTIONARY, g1x, m, g1xs, 140, MY_COMBO + LTEXT "Memory usage:", IDC_BENCHMARK_MEMORY, gc2x, m + 1, gc2xs, 8 + LTEXT "0 MB", IDC_BENCHMARK_MEMORY_VALUE, gc2x + gc2xs, m + 1, 40, 8 + + LTEXT "&Number of CPU threads:", IDC_BENCHMARK_NUM_THREADS, m, 28, g0xs, 8 + COMBOBOX IDC_BENCHMARK_COMBO_NUM_THREADS, g1x, 27, g1xs, 140, MY_COMBO + LTEXT "1", IDC_BENCHMARK_HARDWARE_THREADS, gc2x, 28, 40, 8 + + RTEXT "CPU Usage", IDC_BENCHMARK_USAGE_LABEL, xUsage, 54, sUsage, 8 + RTEXT "Speed", IDC_BENCHMARK_SPEED_LABEL, xSpeed, 54, sSpeed, 8 + RTEXT "Rating / Usage", IDC_BENCHMARK_RPU_LABEL, xRpu, 54, sRpu, 8 + RTEXT "Rating", IDC_BENCHMARK_RATING_LABEL, xRating, 54, sRating, 8 + + GROUPBOX "Compressing", IDC_BENCHMARK_COMPRESSING, m, 64, xc, 40 + + LTEXT "Current", IDC_BENCHMARK_CURRENT, g4x, 76, sLabel, 8 + RTEXT "100%", IDC_BENCHMARK_COMPRESSING_USAGE, xUsage, 76, sUsage, 8 + RTEXT "100 KB/s", IDC_BENCHMARK_COMPRESSING_SPEED, xSpeed, 76, sSpeed, 8 + RTEXT "0", IDC_BENCHMARK_COMPRESSING_RPU, xRpu, 76, sRpu, 8 + RTEXT "0", IDC_BENCHMARK_COMPRESSING_RATING, xRating, 76, sRating, 8 + + LTEXT "Resulting", IDC_BENCHMARK_RESULTING, g4x, 89, sLabel, 8 + RTEXT "100%", IDC_BENCHMARK_COMPRESSING_USAGE2, xUsage, 89, sUsage, 8 + RTEXT "100 KB/s", IDC_BENCHMARK_COMPRESSING_SPEED2, xSpeed, 89, sSpeed, 8 + RTEXT "0", IDC_BENCHMARK_COMPRESSING_RPU2, xRpu, 89, sRpu, 8 + RTEXT "0", IDC_BENCHMARK_COMPRESSING_RATING2, xRating, 89, sRating, 8 + + GROUPBOX "Decompressing", IDC_BENCHMARK_DECOMPRESSING, m, 111, xc, 40 + + LTEXT "Current", IDC_BENCHMARK_CURRENT2, g4x, 123, sLabel, 8 + RTEXT "100%", IDC_BENCHMARK_DECOMPRESSING_USAGE, xUsage, 123, sUsage, 8 + RTEXT "100 KB/s", IDC_BENCHMARK_DECOMPRESSING_SPEED, xSpeed, 123, sSpeed, 8 + RTEXT "0", IDC_BENCHMARK_DECOMPRESSING_RPU, xRpu, 123, sRpu, 8 + RTEXT "0", IDC_BENCHMARK_DECOMPRESSING_RATING, xRating, 123, sRating, 8 + + LTEXT "Resulting", IDC_BENCHMARK_RESULTING2, g4x, 136, sLabel, 8 + RTEXT "100%", IDC_BENCHMARK_DECOMPRESSING_USAGE2, xUsage, 136, sUsage, 8 + RTEXT "100 KB/s", IDC_BENCHMARK_DECOMPRESSING_SPEED2, xSpeed, 136, sSpeed, 8 + RTEXT "0", IDC_BENCHMARK_DECOMPRESSING_RPU2, xRpu, 136, sRpu, 8 + RTEXT "0", IDC_BENCHMARK_DECOMPRESSING_RATING2, xRating, 136, sRating, 8 + + GROUPBOX "Total Rating", IDC_BENCHMARK_TOTAL_RATING, xTotalRating, 163, sTotalRating, 38 + RTEXT "0", IDC_BENCHMARK_TOTAL_USAGE_VALUE, xUsage, 181, sUsage, 8 + RTEXT "0", IDC_BENCHMARK_TOTAL_RPU_VALUE, xRpu, 181, sRpu, 8 + RTEXT "0", IDC_BENCHMARK_TOTAL_RATING_VALUE, xRating, 181, sRating, 8 + + LTEXT "Elapsed time:", IDC_BENCHMARK_ELAPSED, m, 163, g2xs, 8 + LTEXT "Size:", IDC_BENCHMARK_SIZE, m, 176, g2xs, 8 + LTEXT "Passes:", IDC_BENCHMARK_PASSES, m, 189, g2xs, 8 + RTEXT "00:00:00", IDC_BENCHMARK_ELAPSED_VALUE, g3x, 163, g3xs, 8 + RTEXT "0", IDC_BENCHMARK_SIZE_VALUE, g3x, 176, g3xs, 8 + RTEXT "0", IDC_BENCHMARK_PASSES_VALUE, g3x, 189, g3xs, 8 +END + +#ifdef UNDER_CE + +#undef m +#define m 4 + +#undef xc +#undef yc + +#define xc 154 +#define yc 160 + +#undef g0xs +#undef g1x +#undef g1xs +#undef g2xs +#undef g3x +#undef g3xs + +#undef bxs +#undef bys + +#define bxs 60 +#define bys 14 + +#undef gs +#undef gSpace + +#define gs 160 +#define gSpace 24 + +#define g0xs (xc - bxs) +#define g1xs 44 + +#undef g4x +#define g4x (m) + +#undef xRpu +#undef xUsage +#undef xRating +#undef xTotalRating + +#undef sRpu +#undef sRating +#undef sUsage +#undef sLabel +#undef sTotalRating + +#define sRating 40 +#define sUsage 24 +#define sRpu 40 + +#define xRating (xs - m - sRating) +#define xRpu (xRating - sRpu) +#define xUsage (xRpu - sUsage) + +#define sLabel (xUsage - g4x) +#define sTotalRating (sRpu + sRating) +#define xTotalRating (xs - m - sTotalRating) + +#define g3xs 32 +#define g3x (xRpu - g3xs) +#define g2xs (g3x - m) + + +IDD_DIALOG_BENCHMARK_2 DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE | WS_MINIMIZEBOX +CAPTION "Benchmark" +MY_FONT +BEGIN + PUSHBUTTON "&Restart", IDC_BUTTON_RESTART, bx1, m, bxs, bys + PUSHBUTTON "&Stop", IDC_BUTTON_STOP, bx1, m + bys + m, bxs, bys + PUSHBUTTON "Cancel", IDCANCEL, bx1, m + bys + m + bys + m, bxs, bys + + LTEXT "&Dictionary size:", IDC_BENCHMARK_DICTIONARY, m, m, g0xs, 8 + COMBOBOX IDC_BENCHMARK_COMBO_DICTIONARY, m, m + 11, g1xs, 140, MY_COMBO + + LTEXT "&Number of CPU threads:", IDC_BENCHMARK_NUM_THREADS, m, 31, g0xs, 8 + COMBOBOX IDC_BENCHMARK_COMBO_NUM_THREADS, m, 42, g1xs, 140, MY_COMBO + + LTEXT "0 MB", IDC_BENCHMARK_MEMORY_VALUE, m + g1xs + 8, m + 13, xc - bxs - g1xs - 8, 8 + LTEXT "1", IDC_BENCHMARK_HARDWARE_THREADS, m + g1xs + 8, 44, xc - bxs - g1xs - 8, 8 + + LTEXT "Current", IDC_BENCHMARK_CURRENT, g4x, 70, sLabel, 8 + RTEXT "100%", IDC_BENCHMARK_COMPRESSING_USAGE, xUsage, 70, sUsage, 8 + RTEXT "0", IDC_BENCHMARK_COMPRESSING_RPU, xRpu, 70, sRpu, 8 + RTEXT "0", IDC_BENCHMARK_COMPRESSING_RATING, xRating, 70, sRating, 8 + + LTEXT "Resulting", IDC_BENCHMARK_RESULTING, g4x, 80, sLabel, 8 + RTEXT "100%", IDC_BENCHMARK_COMPRESSING_USAGE2, xUsage, 80, sUsage, 8 + RTEXT "0", IDC_BENCHMARK_COMPRESSING_RPU2, xRpu, 80, sRpu, 8 + RTEXT "0", IDC_BENCHMARK_COMPRESSING_RATING2, xRating, 80, sRating, 8 + + LTEXT "Compressing", IDC_BENCHMARK_COMPRESSING, m, 60, xc - bxs, 8 + + LTEXT "Current", IDC_BENCHMARK_CURRENT2, g4x, 104, sLabel, 8 + RTEXT "100%", IDC_BENCHMARK_DECOMPRESSING_USAGE, xUsage, 104, sUsage, 8 + RTEXT "0", IDC_BENCHMARK_DECOMPRESSING_RPU, xRpu, 104, sRpu, 8 + RTEXT "0", IDC_BENCHMARK_DECOMPRESSING_RATING, xRating, 104, sRating, 8 + + LTEXT "Resulting", IDC_BENCHMARK_RESULTING2, g4x, 114, sLabel, 8 + RTEXT "100%", IDC_BENCHMARK_DECOMPRESSING_USAGE2, xUsage, 114, sUsage, 8 + RTEXT "0", IDC_BENCHMARK_DECOMPRESSING_RPU2, xRpu, 114, sRpu, 8 + RTEXT "0", IDC_BENCHMARK_DECOMPRESSING_RATING2, xRating, 114, sRating, 8 + + LTEXT "Decompressing", IDC_BENCHMARK_DECOMPRESSING, m, 94, xc, 8 + + RTEXT "0", IDC_BENCHMARK_TOTAL_RPU_VALUE, xRpu, 140, sRpu, 8 + RTEXT "0", IDC_BENCHMARK_TOTAL_RATING_VALUE, xRating, 140, sRating, 8 + + LTEXT "Elapsed time:", IDC_BENCHMARK_ELAPSED, m, 130, g2xs, 8 + LTEXT "Size:", IDC_BENCHMARK_SIZE, m, 140, g2xs, 8 + LTEXT "Passes:", IDC_BENCHMARK_PASSES, m, 150, g2xs, 8 + + RTEXT "00:00:00", IDC_BENCHMARK_ELAPSED_VALUE, g3x, 130, g3xs, 8 + RTEXT "0", IDC_BENCHMARK_SIZE_VALUE, g3x, 140, g3xs, 8 + RTEXT "0", IDC_BENCHMARK_PASSES_VALUE, g3x, 150, g3xs, 8 +END + +#endif diff --git a/CPP/7zip/UI/GUI/BenchmarkDialogRes.h b/CPP/7zip/UI/GUI/BenchmarkDialogRes.h new file mode 100755 index 0000000..03bd6de --- /dev/null +++ b/CPP/7zip/UI/GUI/BenchmarkDialogRes.h @@ -0,0 +1,55 @@ +#define IDD_DIALOG_BENCHMARK 550 +#define IDD_DIALOG_BENCHMARK_2 650 +#define IDC_BUTTON_STOP 1001 +#define IDC_BUTTON_RESTART 1002 +#define IDC_BENCHMARK_DICTIONARY 1010 +#define IDC_BENCHMARK_COMBO_DICTIONARY 1011 +#define IDC_BENCHMARK_MEMORY 1012 +#define IDC_BENCHMARK_MEMORY_VALUE 1013 +#define IDC_BENCHMARK_NUM_THREADS 1014 +#define IDC_BENCHMARK_COMBO_NUM_THREADS 1015 +#define IDC_BENCHMARK_HARDWARE_THREADS 1016 + +#define IDC_BENCHMARK_SPEED_LABEL 1020 +#define IDC_BENCHMARK_RATING_LABEL 1021 +#define IDC_BENCHMARK_COMPRESSING 1022 +#define IDC_BENCHMARK_DECOMPRESSING 1023 +#define IDC_BENCHMARK_CURRENT 1024 +#define IDC_BENCHMARK_RESULTING 1025 +#define IDC_BENCHMARK_CURRENT2 1026 +#define IDC_BENCHMARK_RESULTING2 1027 +#define IDC_BENCHMARK_USAGE_LABEL 1028 +#define IDC_BENCHMARK_RPU_LABEL 1029 + +#define IDC_BENCHMARK_COMPRESSING_SPEED 1030 +#define IDC_BENCHMARK_COMPRESSING_SPEED2 1031 +#define IDC_BENCHMARK_COMPRESSING_RATING 1032 +#define IDC_BENCHMARK_COMPRESSING_RATING2 1033 +#define IDC_BENCHMARK_COMPRESSING_USAGE 1034 +#define IDC_BENCHMARK_COMPRESSING_USAGE2 1035 +#define IDC_BENCHMARK_COMPRESSING_RPU 1036 +#define IDC_BENCHMARK_COMPRESSING_RPU2 1037 + + +#define IDC_BENCHMARK_DECOMPRESSING_SPEED 1040 +#define IDC_BENCHMARK_DECOMPRESSING_SPEED2 1041 +#define IDC_BENCHMARK_DECOMPRESSING_RATING 1042 +#define IDC_BENCHMARK_DECOMPRESSING_RATING2 1043 +#define IDC_BENCHMARK_DECOMPRESSING_USAGE 1044 +#define IDC_BENCHMARK_DECOMPRESSING_USAGE2 1045 +#define IDC_BENCHMARK_DECOMPRESSING_RPU 1046 +#define IDC_BENCHMARK_DECOMPRESSING_RPU2 1047 + + +#define IDC_BENCHMARK_TOTAL_RATING 1050 + +#define IDC_BENCHMARK_TOTAL_RATING_VALUE 1051 +#define IDC_BENCHMARK_TOTAL_RPU_VALUE 1052 +#define IDC_BENCHMARK_TOTAL_USAGE_VALUE 1053 + +#define IDC_BENCHMARK_ELAPSED 1060 +#define IDC_BENCHMARK_ELAPSED_VALUE 1061 +#define IDC_BENCHMARK_SIZE 1062 +#define IDC_BENCHMARK_SIZE_VALUE 1063 +#define IDC_BENCHMARK_PASSES 1066 +#define IDC_BENCHMARK_PASSES_VALUE 1067 diff --git a/CPP/7zip/UI/GUI/CompressDialog.cpp b/CPP/7zip/UI/GUI/CompressDialog.cpp new file mode 100755 index 0000000..9f3b065 --- /dev/null +++ b/CPP/7zip/UI/GUI/CompressDialog.cpp @@ -0,0 +1,1496 @@ +// CompressDialog.cpp + +#include "StdAfx.h" + +#include "Common/IntToString.h" +#include "Common/StringConvert.h" + +#include "Windows/FileDir.h" +#include "Windows/FileName.h" +#include "Windows/System.h" + +#include "../FileManager/BrowseDialog.h" +#include "../FileManager/FormatUtils.h" +#include "../FileManager/HelpUtils.h" +#include "../FileManager/SplitUtils.h" + +#include "../Explorer/MyMessages.h" + +#include "../Common/ZipRegistry.h" + +#include "CompressDialog.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +#ifdef LANG +#include "../FileManager/LangUtils.h" +#endif + +#include "CompressDialogRes.h" + +#define MY_SIZE_OF_ARRAY(x) (sizeof(x) / sizeof(x[0])) + +#ifdef LANG +static CIDLangPair kIDLangPairs[] = +{ + { IDC_STATIC_COMPRESS_ARCHIVE, 0x02000D01 }, + { IDC_STATIC_COMPRESS_FORMAT, 0x02000D03 }, + { IDC_STATIC_COMPRESS_LEVEL, 0x02000D0B }, + { IDC_STATIC_COMPRESS_METHOD, 0x02000D04 }, + { IDC_STATIC_COMPRESS_DICTIONARY, 0x02000D0C }, + { IDC_STATIC_COMPRESS_ORDER, 0x02000D0D }, + { IDC_STATIC_COMPRESS_MEMORY, 0x02000D0E }, + { IDC_STATIC_COMPRESS_MEMORY_DE, 0x02000D0F }, + { IDC_STATIC_COMPRESS_THREADS, 0x02000D12 }, + { IDC_STATIC_COMPRESS_SOLID, 0x02000D13 }, + { IDC_STATIC_COMPRESS_VOLUME, 0x02000D40 }, + { IDC_STATIC_COMPRESS_PARAMETERS, 0x02000D06 }, + + { IDC_STATIC_COMPRESS_UPDATE_MODE, 0x02000D02 }, + { IDC_STATIC_COMPRESS_OPTIONS, 0x02000D07 }, + { IDC_COMPRESS_SFX, 0x02000D08 }, + { IDC_COMPRESS_SHARED, 0x02000D16 }, + + { IDC_COMPRESS_ENCRYPTION, 0x02000D10 }, + { IDC_STATIC_COMPRESS_PASSWORD1, 0x02000B01 }, + { IDC_STATIC_COMPRESS_PASSWORD2, 0x02000B03 }, + { IDC_COMPRESS_CHECK_SHOW_PASSWORD, 0x02000B02 }, + { IDC_STATIC_COMPRESS_ENCRYPTION_METHOD, 0x02000D11 }, + { IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES, 0x02000D0A }, + + { IDOK, 0x02000702 }, + { IDCANCEL, 0x02000710 }, + { IDHELP, 0x02000720 } +}; +#endif + +using namespace NWindows; +using namespace NFile; +using namespace NName; +using namespace NDirectory; + +static const int kHistorySize = 20; + +static LPCWSTR kExeExt = L".exe"; +static LPCWSTR k7zFormat = L"7z"; + +struct CLevelInfo +{ + UInt32 ResourceID; + UInt32 LangID; +}; + +enum ELevel +{ + kStore = 0, + kFastest = 1, + kFast = 3, + kNormal = 5, + kMaximum = 7, + kUltra = 9 +}; + +static const CLevelInfo g_Levels[] = +{ + { IDS_METHOD_STORE, 0x02000D81 }, + { IDS_METHOD_FASTEST, 0x02000D85 }, + { 0, 0 }, + { IDS_METHOD_FAST, 0x02000D84 }, + { 0, 0 }, + { IDS_METHOD_NORMAL, 0x02000D82 }, + { 0, 0 }, + { IDS_METHOD_MAXIMUM, 0x02000D83 }, + { 0, 0 }, + { IDS_METHOD_ULTRA, 0x02000D86 } +}; + +enum EMethodID +{ + kCopy, + kLZMA, + kLZMA2, + kPPMd, + kBZip2, + kDeflate, + kDeflate64, + kPPMdZip +}; + +static const LPCWSTR kMethodsNames[] = +{ + L"Copy", + L"LZMA", + L"LZMA2", + L"PPMd", + L"BZip2", + L"Deflate", + L"Deflate64", + L"PPMd" +}; + +static const EMethodID g_7zMethods[] = +{ + kLZMA, + kLZMA2, + kPPMd, + kBZip2 +}; + +static const EMethodID g_7zSfxMethods[] = +{ + kCopy, + kLZMA, + kLZMA2, + kPPMd +}; + +static EMethodID g_ZipMethods[] = +{ + kDeflate, + kDeflate64, + kBZip2, + kLZMA, + kPPMdZip +}; + +static EMethodID g_GZipMethods[] = +{ + kDeflate +}; + +static EMethodID g_BZip2Methods[] = +{ + kBZip2 +}; + +static EMethodID g_XzMethods[] = +{ + kLZMA2 +}; + +struct CFormatInfo +{ + LPCWSTR Name; + UInt32 LevelsMask; + const EMethodID *MathodIDs; + int NumMethods; + bool Filter; + bool Solid; + bool MultiThread; + bool SFX; + bool Encrypt; + bool EncryptFileNames; +}; + +#define METHODS_PAIR(x) x, MY_SIZE_OF_ARRAY(x) + +static const CFormatInfo g_Formats[] = +{ + { + L"", + (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), + 0, 0, + false, false, false, false, false, false + }, + { + k7zFormat, + (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), + METHODS_PAIR(g_7zMethods), + true, true, true, true, true, true + }, + { + L"Zip", + (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), + METHODS_PAIR(g_ZipMethods), + false, false, true, false, true, false + }, + { + L"GZip", + (1 << 1) | (1 << 5) | (1 << 7) | (1 << 9), + METHODS_PAIR(g_GZipMethods), + false, false, false, false, false, false + }, + { + L"BZip2", + (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), + METHODS_PAIR(g_BZip2Methods), + false, false, true, false, false, false + }, + { + L"xz", + (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), + METHODS_PAIR(g_XzMethods), + false, false, true, false, false, false + }, + { + L"Tar", + (1 << 0), + 0, 0, + false, false, false, false, false, false + }, + { + L"wim", + (1 << 0), + 0, 0, + false, false, false, false, false, false + } +}; + +static bool IsMethodSupportedBySfx(int methodID) +{ + for (int i = 0; i < MY_SIZE_OF_ARRAY(g_7zSfxMethods); i++) + if (methodID == g_7zSfxMethods[i]) + return true; + return false; +} + +static UInt64 GetMaxRamSizeForProgram() +{ + UInt64 physSize = NSystem::GetRamSize(); + const UInt64 kMinSysSize = (1 << 24); + if (physSize <= kMinSysSize) + physSize = 0; + else + physSize -= kMinSysSize; + const UInt64 kMinUseSize = (1 << 24); + if (physSize < kMinUseSize) + physSize = kMinUseSize; + return physSize; +} + +bool CCompressDialog::OnInit() +{ + #ifdef LANG + LangSetWindowText(HWND(*this), 0x02000D00); + LangSetDlgItemsText(HWND(*this), kIDLangPairs, MY_SIZE_OF_ARRAY(kIDLangPairs) ); + #endif + _password1Control.Attach(GetItem(IDC_COMPRESS_EDIT_PASSWORD1)); + _password2Control.Attach(GetItem(IDC_COMPRESS_EDIT_PASSWORD2)); + _password1Control.SetText(Info.Password); + _password2Control.SetText(Info.Password); + _encryptionMethod.Attach(GetItem(IDC_COMPRESS_COMBO_ENCRYPTION_METHOD)); + + m_ArchivePath.Attach(GetItem(IDC_COMPRESS_COMBO_ARCHIVE)); + m_Format.Attach(GetItem(IDC_COMPRESS_COMBO_FORMAT)); + m_Level.Attach(GetItem(IDC_COMPRESS_COMBO_LEVEL)); + m_Method.Attach(GetItem(IDC_COMPRESS_COMBO_METHOD)); + m_Dictionary.Attach(GetItem(IDC_COMPRESS_COMBO_DICTIONARY)); + m_Order.Attach(GetItem(IDC_COMPRESS_COMBO_ORDER)); + m_Solid.Attach(GetItem(IDC_COMPRESS_COMBO_SOLID)); + m_NumThreads.Attach(GetItem(IDC_COMPRESS_COMBO_THREADS)); + + m_UpdateMode.Attach(GetItem(IDC_COMPRESS_COMBO_UPDATE_MODE)); + m_Volume.Attach(GetItem(IDC_COMPRESS_COMBO_VOLUME)); + m_Params.Attach(GetItem(IDC_COMPRESS_EDIT_PARAMETERS)); + + AddVolumeItems(m_Volume); + + m_RegistryInfo.Load(); + CheckButton(IDC_COMPRESS_CHECK_SHOW_PASSWORD, m_RegistryInfo.ShowPassword); + CheckButton(IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES, m_RegistryInfo.EncryptHeaders); + + UpdatePasswordControl(); + + Info.FormatIndex = -1; + int i; + for (i = 0; i < ArcIndices.Size(); i++) + { + int arcIndex = ArcIndices[i]; + const CArcInfoEx &ai = (*ArcFormats)[arcIndex]; + int index = (int)m_Format.AddString(ai.Name); + m_Format.SetItemData(index, arcIndex); + if (ai.Name.CompareNoCase(m_RegistryInfo.ArcType) == 0 || i == 0) + { + m_Format.SetCurSel(index); + Info.FormatIndex = arcIndex; + } + } + + SetArchiveName(Info.ArchiveName); + SetLevel(); + SetParams(); + + for (i = 0; i < m_RegistryInfo.ArcPaths.Size() && i < kHistorySize; i++) + m_ArchivePath.AddString(m_RegistryInfo.ArcPaths[i]); + + m_UpdateMode.AddString(LangString(IDS_COMPRESS_UPDATE_MODE_ADD, 0x02000DA1)); + m_UpdateMode.AddString(LangString(IDS_COMPRESS_UPDATE_MODE_UPDATE, 0x02000DA2)); + m_UpdateMode.AddString(LangString(IDS_COMPRESS_UPDATE_MODE_FRESH, 0x02000DA3)); + m_UpdateMode.AddString(LangString(IDS_COMPRESS_UPDATE_MODE_SYNCHRONIZE, 0x02000DA4)); + + m_UpdateMode.SetCurSel(0); + + SetSolidBlockSize(); + SetNumThreads(); + + TCHAR s[40] = { TEXT('/'), TEXT(' '), 0 }; + ConvertUInt32ToString(NSystem::GetNumberOfProcessors(), s + 2); + SetItemText(IDC_COMPRESS_HARDWARE_THREADS, s); + + CheckButton(IDC_COMPRESS_SFX, Info.SFXMode); + CheckButton(IDC_COMPRESS_SHARED, Info.OpenShareForWrite); + + CheckControlsEnable(); + + OnButtonSFX(); + + SetEncryptionMethod(); + SetMemoryUsage(); + + NormalizePosition(); + + return CModalDialog::OnInit(); +} + +namespace NCompressDialog +{ + bool CInfo::GetFullPathName(UString &result) const + { + #ifndef UNDER_CE + NDirectory::MySetCurrentDirectory(CurrentDirPrefix); + #endif + return MyGetFullPathName(ArchiveName, result); + } +} + +void CCompressDialog::UpdatePasswordControl() +{ + bool showPassword = IsShowPasswordChecked(); + TCHAR c = showPassword ? 0: TEXT('*'); + _password1Control.SetPasswordChar(c); + _password2Control.SetPasswordChar(c); + UString password; + _password1Control.GetText(password); + _password1Control.SetText(password); + _password2Control.GetText(password); + _password2Control.SetText(password); + + int cmdShow = showPassword ? SW_HIDE : SW_SHOW; + ShowItem(IDC_STATIC_COMPRESS_PASSWORD2, cmdShow); + _password2Control.Show(cmdShow); +} + +bool CCompressDialog::OnButtonClicked(int buttonID, HWND buttonHWND) +{ + switch(buttonID) + { + case IDC_COMPRESS_BUTTON_SET_ARCHIVE: + { + OnButtonSetArchive(); + return true; + } + case IDC_COMPRESS_SFX: + { + OnButtonSFX(); + SetMemoryUsage(); + return true; + } + case IDC_COMPRESS_CHECK_SHOW_PASSWORD: + { + UpdatePasswordControl(); + return true; + } + } + return CModalDialog::OnButtonClicked(buttonID, buttonHWND); +} + +void CCompressDialog::CheckSFXControlsEnable() +{ + const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; + bool enable = fi.SFX; + if (enable) + { + int methodID = GetMethodID(); + enable = (methodID == -1 || IsMethodSupportedBySfx(methodID)); + } + if (!enable) + CheckButton(IDC_COMPRESS_SFX, false); + EnableItem(IDC_COMPRESS_SFX, enable); +} + +void CCompressDialog::CheckVolumeEnable() +{ + bool isSFX = IsSFX(); + m_Volume.Enable(!isSFX); + if (isSFX) + m_Volume.SetText(TEXT("")); +} + +void CCompressDialog::CheckControlsEnable() +{ + const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; + Info.SolidIsSpecified = fi.Solid; + bool multiThreadEnable = fi.MultiThread; + Info.MultiThreadIsAllowed = multiThreadEnable; + Info.EncryptHeadersIsAllowed = fi.EncryptFileNames; + + EnableItem(IDC_COMPRESS_COMBO_SOLID, fi.Solid); + EnableItem(IDC_COMPRESS_COMBO_THREADS, multiThreadEnable); + CheckSFXControlsEnable(); + CheckVolumeEnable(); + + EnableItem(IDC_COMPRESS_ENCRYPTION, fi.Encrypt); + + EnableItem(IDC_STATIC_COMPRESS_PASSWORD1, fi.Encrypt); + EnableItem(IDC_STATIC_COMPRESS_PASSWORD2, fi.Encrypt); + EnableItem(IDC_COMPRESS_EDIT_PASSWORD1, fi.Encrypt); + EnableItem(IDC_COMPRESS_EDIT_PASSWORD2, fi.Encrypt); + EnableItem(IDC_COMPRESS_CHECK_SHOW_PASSWORD, fi.Encrypt); + + EnableItem(IDC_STATIC_COMPRESS_ENCRYPTION_METHOD, fi.Encrypt); + EnableItem(IDC_COMPRESS_COMBO_ENCRYPTION_METHOD, fi.Encrypt); + EnableItem(IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES, fi.EncryptFileNames); + + ShowItem(IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES, fi.EncryptFileNames ? SW_SHOW : SW_HIDE); +} + +bool CCompressDialog::IsSFX() +{ + CWindow sfxButton = GetItem(IDC_COMPRESS_SFX); + return sfxButton.IsEnabled() && IsButtonCheckedBool(IDC_COMPRESS_SFX); +} + +void CCompressDialog::OnButtonSFX() +{ + SetMethod(GetMethodID()); + + UString fileName; + m_ArchivePath.GetText(fileName); + int dotPos = fileName.ReverseFind(L'.'); + int slashPos = fileName.ReverseFind(WCHAR_PATH_SEPARATOR); + if (dotPos < 0 || dotPos <= slashPos) + dotPos = -1; + if (IsSFX()) + { + if (dotPos >= 0) + fileName = fileName.Left(dotPos); + fileName += kExeExt; + m_ArchivePath.SetText(fileName); + } + else + { + if (dotPos >= 0) + { + UString ext = fileName.Mid(dotPos); + if (ext.CompareNoCase(kExeExt) == 0) + { + fileName = fileName.Left(dotPos); + m_ArchivePath.SetText(fileName); + } + } + SetArchiveName2(false); // it's for OnInit + } + + CheckVolumeEnable(); +} + +void CCompressDialog::OnButtonSetArchive() +{ + UString fileName; + m_ArchivePath.GetText(fileName); + fileName.Trim(); + Info.ArchiveName = fileName; + UString fullFileName; + if (!Info.GetFullPathName(fullFileName)) + { + fullFileName = Info.ArchiveName; + return; + } + UString title = LangString(IDS_COMPRESS_SET_ARCHIVE_DIALOG_TITLE, 0x02000D90); + UString s = LangString(IDS_OPEN_TYPE_ALL_FILES, 0x02000DB1); + s += L" (*.*)"; + UString resPath; + if (!MyBrowseForFile(HWND(*this), title, fullFileName, s, resPath)) + return; + m_ArchivePath.SetText(resPath); +} + +// in ExtractDialog.cpp +extern void AddUniqueString(UStringVector &strings, const UString &srcString); + +static bool IsAsciiString(const UString &s) +{ + for (int i = 0; i < s.Length(); i++) + { + wchar_t c = s[i]; + if (c < 0x20 || c > 0x7F) + return false; + } + return true; +} + +void CCompressDialog::OnOK() +{ + _password1Control.GetText(Info.Password); + if (IsZipFormat()) + { + if (!IsAsciiString(Info.Password)) + { + ShowErrorMessageHwndRes(*this, IDS_PASSWORD_USE_ASCII, 0x02000B11); + return; + } + UString method = GetEncryptionMethodSpec(); + method.MakeUpper(); + if (method.Find(L"AES") == 0) + { + if (Info.Password.Length() > 99) + { + ShowErrorMessageHwndRes(*this, IDS_PASSWORD_IS_TOO_LONG, 0x02000B12); + return; + } + } + } + if (!IsShowPasswordChecked()) + { + UString password2; + _password2Control.GetText(password2); + if (password2 != Info.Password) + { + ShowErrorMessageHwndRes(*this, IDS_PASSWORD_PASSWORDS_DO_NOT_MATCH, 0x02000B10); + return; + } + } + + SaveOptionsInMem(); + UString s; + m_ArchivePath.GetText(s); + s.Trim(); + m_RegistryInfo.ArcPaths.Clear(); + AddUniqueString(m_RegistryInfo.ArcPaths, s); + Info.ArchiveName = s; + Info.UpdateMode = NCompressDialog::NUpdateMode::EEnum(m_UpdateMode.GetCurSel()); + + Info.Level = GetLevelSpec(); + Info.Dictionary = GetDictionarySpec(); + Info.Order = GetOrderSpec(); + Info.OrderMode = GetOrderMode(); + Info.NumThreads = GetNumThreadsSpec(); + + UInt32 solidLogSize = GetBlockSizeSpec(); + Info.SolidBlockSize = 0; + if (solidLogSize > 0 && solidLogSize != (UInt32)-1) + Info.SolidBlockSize = (solidLogSize >= 64) ? (UInt64)(Int64)-1 : ((UInt64)1 << solidLogSize); + + Info.Method = GetMethodSpec(); + Info.EncryptionMethod = GetEncryptionMethodSpec(); + Info.FormatIndex = GetFormatIndex(); + Info.SFXMode = IsSFX(); + Info.OpenShareForWrite = IsButtonCheckedBool(IDC_COMPRESS_SHARED); + + m_RegistryInfo.EncryptHeaders = Info.EncryptHeaders = IsButtonCheckedBool(IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES); + + m_Params.GetText(Info.Options); + UString volumeString; + m_Volume.GetText(volumeString); + volumeString.Trim(); + Info.VolumeSizes.Clear(); + if (!volumeString.IsEmpty()) + { + if (!ParseVolumeSizes(volumeString, Info.VolumeSizes)) + { + ShowErrorMessageHwndRes(*this, IDS_COMPRESS_INCORRECT_VOLUME_SIZE, 0x02000D41); + return; + } + if (!Info.VolumeSizes.IsEmpty()) + { + const UInt64 volumeSize = Info.VolumeSizes.Back(); + if (volumeSize < (100 << 10)) + { + wchar_t s[32]; + ConvertUInt64ToString(volumeSize, s); + if (::MessageBoxW(*this, MyFormatNew(IDS_COMPRESS_SPLIT_CONFIRM_MESSAGE, 0x02000D42, s), + L"7-Zip", MB_YESNOCANCEL | MB_ICONQUESTION) != IDYES) + return; + } + } + } + + for (int i = 0; i < m_ArchivePath.GetCount(); i++) + { + UString sTemp; + m_ArchivePath.GetLBText(i, sTemp); + sTemp.Trim(); + AddUniqueString(m_RegistryInfo.ArcPaths, sTemp); + } + if (m_RegistryInfo.ArcPaths.Size() > kHistorySize) + m_RegistryInfo.ArcPaths.DeleteBack(); + + m_RegistryInfo.ArcType = (*ArcFormats)[Info.FormatIndex].Name; + m_RegistryInfo.ShowPassword = IsShowPasswordChecked(); + + m_RegistryInfo.Save(); + + CModalDialog::OnOK(); +} + +static LPCWSTR kHelpTopic = L"fm/plugins/7-zip/add.htm"; + +void CCompressDialog::OnHelp() +{ + ShowHelpWindow(NULL, kHelpTopic); +} + +bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam) +{ + if (code == CBN_SELCHANGE) + { + switch(itemID) + { + case IDC_COMPRESS_COMBO_FORMAT: + { + bool isSFX = IsSFX(); + SaveOptionsInMem(); + SetLevel(); + SetSolidBlockSize(); + SetNumThreads(); + SetParams(); + CheckControlsEnable(); + SetArchiveName2(isSFX); + SetEncryptionMethod(); + SetMemoryUsage(); + return true; + } + case IDC_COMPRESS_COMBO_LEVEL: + { + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + int index = FindRegistryFormatAlways(ai.Name); + NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; + fo.ResetForLevelChange(); + SetMethod(); + SetSolidBlockSize(); + SetNumThreads(); + CheckSFXNameChange(); + SetMemoryUsage(); + return true; + } + case IDC_COMPRESS_COMBO_METHOD: + { + SetDictionary(); + SetOrder(); + SetSolidBlockSize(); + SetNumThreads(); + CheckSFXNameChange(); + SetMemoryUsage(); + return true; + } + case IDC_COMPRESS_COMBO_DICTIONARY: + case IDC_COMPRESS_COMBO_ORDER: + { + SetSolidBlockSize(); + SetMemoryUsage(); + return true; + } + case IDC_COMPRESS_COMBO_THREADS: + { + SetMemoryUsage(); + return true; + } + } + } + return CModalDialog::OnCommand(code, itemID, lParam); +} + +void CCompressDialog::CheckSFXNameChange() +{ + bool isSFX = IsSFX(); + CheckSFXControlsEnable(); + if (isSFX != IsSFX()) + SetArchiveName2(isSFX); +} + +void CCompressDialog::SetArchiveName2(bool prevWasSFX) +{ + UString fileName; + m_ArchivePath.GetText(fileName); + const CArcInfoEx &prevArchiverInfo = (*ArcFormats)[m_PrevFormat]; + if (prevArchiverInfo.KeepName || Info.KeepName) + { + UString prevExtension = prevArchiverInfo.GetMainExt(); + if (prevWasSFX) + prevExtension = kExeExt; + else + prevExtension = UString('.') + prevExtension; + const int prevExtensionLen = prevExtension.Length(); + if (fileName.Length() >= prevExtensionLen) + if (fileName.Right(prevExtensionLen).CompareNoCase(prevExtension) == 0) + fileName = fileName.Left(fileName.Length() - prevExtensionLen); + } + SetArchiveName(fileName); +} + +// if type.KeepName then use OriginalFileName +// else if !KeepName remove extension +// add new extension + +void CCompressDialog::SetArchiveName(const UString &name) +{ + UString fileName = name; + Info.FormatIndex = GetFormatIndex(); + const CArcInfoEx &ai = (*ArcFormats)[Info.FormatIndex]; + m_PrevFormat = Info.FormatIndex; + if (ai.KeepName) + { + fileName = OriginalFileName; + } + else + { + if (!Info.KeepName) + { + int dotPos = fileName.ReverseFind('.'); + int slashPos = MyMax(fileName.ReverseFind(WCHAR_PATH_SEPARATOR), fileName.ReverseFind('/')); + if (dotPos >= 0 && dotPos > slashPos + 1) + fileName = fileName.Left(dotPos); + } + } + + if (IsSFX()) + fileName += kExeExt; + else + { + fileName += L'.'; + fileName += ai.GetMainExt(); + } + m_ArchivePath.SetText(fileName); +} + +int CCompressDialog::FindRegistryFormat(const UString &name) +{ + for (int i = 0; i < m_RegistryInfo.Formats.Size(); i++) + { + const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[i]; + if (name.CompareNoCase(GetUnicodeString(fo.FormatID)) == 0) + return i; + } + return -1; +} + +int CCompressDialog::FindRegistryFormatAlways(const UString &name) +{ + int index = FindRegistryFormat(name); + if (index < 0) + { + NCompression::CFormatOptions fo; + fo.FormatID = GetSystemString(name); + index = m_RegistryInfo.Formats.Add(fo); + } + return index; +} + +int CCompressDialog::GetStaticFormatIndex() +{ + int formatIndex = GetFormatIndex(); + const CArcInfoEx &ai = (*ArcFormats)[formatIndex]; + for (int i = 0; i < MY_SIZE_OF_ARRAY(g_Formats); i++) + if (ai.Name.CompareNoCase(g_Formats[i].Name) == 0) + return i; + return 0; // -1; +} + +void CCompressDialog::SetNearestSelectComboBox(NControl::CComboBox &comboBox, UInt32 value) +{ + for (int i = comboBox.GetCount() - 1; i >= 0; i--) + if ((UInt32)comboBox.GetItemData(i) <= value) + { + comboBox.SetCurSel(i); + return; + } + if (comboBox.GetCount() > 0) + comboBox.SetCurSel(0); +} + +void CCompressDialog::SetLevel() +{ + m_Level.ResetContent(); + const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + int index = FindRegistryFormat(ai.Name); + UInt32 level = kNormal; + if (index >= 0) + { + const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; + if (fo.Level <= kUltra) + level = fo.Level; + else + level = kUltra; + } + int i; + for (i = 0; i <= kUltra; i++) + { + if ((fi.LevelsMask & (1 << i)) != 0) + { + const CLevelInfo &levelInfo = g_Levels[i]; + int index = (int)m_Level.AddString(LangString(levelInfo.ResourceID, levelInfo.LangID)); + m_Level.SetItemData(index, i); + } + } + SetNearestSelectComboBox(m_Level, level); + SetMethod(); +} + +void CCompressDialog::SetMethod(int keepMethodId) +{ + m_Method.ResetContent(); + UInt32 level = GetLevel(); + if (level == 0) + { + SetDictionary(); + SetOrder(); + return; + } + const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + int index = FindRegistryFormat(ai.Name); + UString defaultMethod; + if (index >= 0) + { + const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; + defaultMethod = fo.Method; + } + bool isSfx = IsSFX(); + bool weUseSameMethod = false; + for (int m = 0; m < fi.NumMethods; m++) + { + EMethodID methodID = fi.MathodIDs[m]; + if (isSfx) + if (!IsMethodSupportedBySfx(methodID)) + continue; + const LPCWSTR method = kMethodsNames[methodID]; + int itemIndex = (int)m_Method.AddString(GetSystemString(method)); + m_Method.SetItemData(itemIndex, methodID); + if (keepMethodId == methodID) + { + m_Method.SetCurSel(itemIndex); + weUseSameMethod = true; + continue; + } + if ((defaultMethod.CompareNoCase(method) == 0 || m == 0) && !weUseSameMethod) + m_Method.SetCurSel(itemIndex); + } + if (!weUseSameMethod) + { + SetDictionary(); + SetOrder(); + } +} + +bool CCompressDialog::IsZipFormat() +{ + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + return (ai.Name.CompareNoCase(L"zip") == 0); +} + +void CCompressDialog::SetEncryptionMethod() +{ + _encryptionMethod.ResetContent(); + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + if (ai.Name.CompareNoCase(L"7z") == 0) + { + _encryptionMethod.AddString(TEXT("AES-256")); + _encryptionMethod.SetCurSel(0); + } + else if (ai.Name.CompareNoCase(L"zip") == 0) + { + int index = FindRegistryFormat(ai.Name); + UString encryptionMethod; + if (index >= 0) + { + const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; + encryptionMethod = fo.EncryptionMethod; + } + _encryptionMethod.AddString(TEXT("ZipCrypto")); + _encryptionMethod.AddString(TEXT("AES-256")); + _encryptionMethod.SetCurSel(encryptionMethod.Find(L"AES") == 0 ? 1 : 0); + } +} + +int CCompressDialog::GetMethodID() +{ + if (m_Method.GetCount() <= 0) + return -1; + return (int)(UInt32)m_Method.GetItemData(m_Method.GetCurSel()); +} + +UString CCompressDialog::GetMethodSpec() +{ + if (m_Method.GetCount() <= 1) + return UString(); + return kMethodsNames[GetMethodID()]; +} + +UString CCompressDialog::GetEncryptionMethodSpec() +{ + if (_encryptionMethod.GetCount() <= 1) + return UString(); + if (_encryptionMethod.GetCurSel() <= 0) + return UString(); + UString result; + _encryptionMethod.GetText(result); + result.Replace(L"-", L""); + return result; +} + +int CCompressDialog::AddDictionarySize(UInt32 size, bool kilo, bool maga) +{ + UInt32 sizePrint = size; + if (kilo) + sizePrint >>= 10; + else if (maga) + sizePrint >>= 20; + TCHAR s[40]; + ConvertUInt32ToString(sizePrint, s); + if (kilo) + lstrcat(s, TEXT(" K")); + else if (maga) + lstrcat(s, TEXT(" M")); + else + lstrcat(s, TEXT(" ")); + lstrcat(s, TEXT("B")); + int index = (int)m_Dictionary.AddString(s); + m_Dictionary.SetItemData(index, size); + return index; +} + +int CCompressDialog::AddDictionarySize(UInt32 size) +{ + if (size > 0) + { + if ((size & 0xFFFFF) == 0) + return AddDictionarySize(size, false, true); + if ((size & 0x3FF) == 0) + return AddDictionarySize(size, true, false); + } + return AddDictionarySize(size, false, false); +} + +void CCompressDialog::SetDictionary() +{ + m_Dictionary.ResetContent(); + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + int index = FindRegistryFormat(ai.Name); + UInt32 defaultDictionary = (UInt32)-1; + if (index >= 0) + { + const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; + if (fo.Method.CompareNoCase(GetMethodSpec()) == 0) + defaultDictionary = fo.Dictionary; + } + int methodID = GetMethodID(); + UInt32 level = GetLevel2(); + if (methodID < 0) + return; + const UInt64 maxRamSize = GetMaxRamSizeForProgram(); + switch (methodID) + { + case kLZMA: + case kLZMA2: + { + static const UInt32 kMinDicSize = (1 << 16); + if (defaultDictionary == (UInt32)-1) + { + if (level >= 9) defaultDictionary = (1 << 26); + else if (level >= 7) defaultDictionary = (1 << 25); + else if (level >= 5) defaultDictionary = (1 << 24); + else if (level >= 3) defaultDictionary = (1 << 20); + else defaultDictionary = (kMinDicSize); + } + int i; + AddDictionarySize(kMinDicSize); + m_Dictionary.SetCurSel(0); + for (i = 20; i <= 30; i++) + for (int j = 0; j < 2; j++) + { + if (i == 20 && j > 0) + continue; + UInt32 dictionary = (1 << i) + (j << (i - 1)); + if (dictionary > + #ifdef _WIN64 + (1 << 30) + #else + (1 << 26) + #endif + ) + continue; + AddDictionarySize(dictionary); + UInt64 decomprSize; + UInt64 requiredComprSize = GetMemoryUsage(dictionary, decomprSize); + if (dictionary <= defaultDictionary && requiredComprSize <= maxRamSize) + m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1); + } + + // SetNearestSelectComboBox(m_Dictionary, defaultDictionary); + break; + } + case kPPMd: + { + if (defaultDictionary == (UInt32)-1) + { + if (level >= 9) defaultDictionary = (192 << 20); + else if (level >= 7) defaultDictionary = ( 64 << 20); + else if (level >= 5) defaultDictionary = ( 16 << 20); + else defaultDictionary = ( 4 << 20); + } + int i; + for (i = 20; i < 31; i++) + for (int j = 0; j < 2; j++) + { + if (i == 20 && j > 0) + continue; + UInt32 dictionary = (1 << i) + (j << (i - 1)); + if (dictionary > + #ifdef _WIN64 + (1 << 30) + #else + (1 << 29) + #endif + ) + continue; + AddDictionarySize(dictionary); + UInt64 decomprSize; + UInt64 requiredComprSize = GetMemoryUsage(dictionary, decomprSize); + if (dictionary <= defaultDictionary && requiredComprSize <= maxRamSize || m_Dictionary.GetCount() == 0) + m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1); + } + SetNearestSelectComboBox(m_Dictionary, defaultDictionary); + break; + } + case kDeflate: + { + AddDictionarySize(32 << 10); + m_Dictionary.SetCurSel(0); + break; + } + case kDeflate64: + { + AddDictionarySize(64 << 10); + m_Dictionary.SetCurSel(0); + break; + } + case kBZip2: + { + if (defaultDictionary == (UInt32)-1) + { + if (level >= 5) + defaultDictionary = (900 << 10); + else if (level >= 3) + defaultDictionary = (500 << 10); + else + defaultDictionary = (100 << 10); + } + for (int i = 1; i <= 9; i++) + { + UInt32 dictionary = (i * 100) << 10; + AddDictionarySize(dictionary); + if (dictionary <= defaultDictionary || m_Dictionary.GetCount() == 0) + m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1); + } + break; + } + case kPPMdZip: + { + if (defaultDictionary == (UInt32)-1) + defaultDictionary = (1 << (19 + (level > 8 ? 8 : level))); + for (int i = 20; i <= 28; i++) + { + UInt32 dictionary = (1 << i); + AddDictionarySize(dictionary); + UInt64 decomprSize; + UInt64 requiredComprSize = GetMemoryUsage(dictionary, decomprSize); + if (dictionary <= defaultDictionary && requiredComprSize <= maxRamSize || m_Dictionary.GetCount() == 0) + m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1); + } + SetNearestSelectComboBox(m_Dictionary, defaultDictionary); + break; + } + } +} + +UInt32 CCompressDialog::GetComboValue(NWindows::NControl::CComboBox &c, int defMax) +{ + if (c.GetCount() <= defMax) + return (UInt32)-1; + return (UInt32)c.GetItemData(c.GetCurSel()); +} + +UInt32 CCompressDialog::GetLevel2() +{ + UInt32 level = GetLevel(); + if (level == (UInt32)-1) + level = 5; + return level; +} + +int CCompressDialog::AddOrder(UInt32 size) +{ + TCHAR s[40]; + ConvertUInt32ToString(size, s); + int index = (int)m_Order.AddString(s); + m_Order.SetItemData(index, size); + return index; +} + +void CCompressDialog::SetOrder() +{ + m_Order.ResetContent(); + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + int index = FindRegistryFormat(ai.Name); + UInt32 defaultOrder = (UInt32)-1; + if (index >= 0) + { + const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; + if (fo.Method.CompareNoCase(GetMethodSpec()) == 0) + defaultOrder = fo.Order; + } + int methodID = GetMethodID(); + UInt32 level = GetLevel2(); + if (methodID < 0) + return; + switch (methodID) + { + case kLZMA: + case kLZMA2: + { + if (defaultOrder == (UInt32)-1) + defaultOrder = (level >= 7) ? 64 : 32; + for (int i = 3; i <= 8; i++) + for (int j = 0; j < 2; j++) + { + UInt32 order = (1 << i) + (j << (i - 1)); + if (order <= 256) + AddOrder(order); + } + AddOrder(273); + SetNearestSelectComboBox(m_Order, defaultOrder); + break; + } + case kPPMd: + { + if (defaultOrder == (UInt32)-1) + { + if (level >= 9) + defaultOrder = 32; + else if (level >= 7) + defaultOrder = 16; + else if (level >= 5) + defaultOrder = 6; + else + defaultOrder = 4; + } + int i; + AddOrder(2); + AddOrder(3); + for (i = 2; i < 8; i++) + for (int j = 0; j < 4; j++) + { + UInt32 order = (1 << i) + (j << (i - 2)); + if (order < 32) + AddOrder(order); + } + AddOrder(32); + SetNearestSelectComboBox(m_Order, defaultOrder); + break; + } + case kDeflate: + case kDeflate64: + { + if (defaultOrder == (UInt32)-1) + { + if (level >= 9) + defaultOrder = 128; + else if (level >= 7) + defaultOrder = 64; + else + defaultOrder = 32; + } + int i; + for (i = 3; i <= 8; i++) + for (int j = 0; j < 2; j++) + { + UInt32 order = (1 << i) + (j << (i - 1)); + if (order <= 256) + AddOrder(order); + } + AddOrder(methodID == kDeflate64 ? 257 : 258); + SetNearestSelectComboBox(m_Order, defaultOrder); + break; + } + case kBZip2: + { + break; + } + case kPPMdZip: + { + if (defaultOrder == (UInt32)-1) + defaultOrder = level + 3; + for (int i = 2; i <= 16; i++) + AddOrder(i); + SetNearestSelectComboBox(m_Order, defaultOrder); + break; + } + } +} + +bool CCompressDialog::GetOrderMode() +{ + switch (GetMethodID()) + { + case kPPMd: + return true; + } + return false; +} + +static const UInt32 kNoSolidBlockSize = 0; +static const UInt32 kSolidBlockSize = 64; + +void CCompressDialog::SetSolidBlockSize() +{ + m_Solid.ResetContent(); + const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; + if (!fi.Solid) + return; + + UInt32 level = GetLevel2(); + if (level == 0) + return; + + UInt32 dictionary = GetDictionarySpec(); + if (dictionary == (UInt32)-1) + dictionary = 1; + + UInt32 defaultBlockSize = (UInt32)-1; + + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + int index = FindRegistryFormat(ai.Name); + if (index >= 0) + { + const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; + if (fo.Method.CompareNoCase(GetMethodSpec()) == 0) + defaultBlockSize = fo.BlockLogSize; + } + + index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_NON_SOLID, 0x02000D14)); + m_Solid.SetItemData(index, (UInt32)kNoSolidBlockSize); + m_Solid.SetCurSel(0); + bool needSet = defaultBlockSize == (UInt32)-1; + for (int i = 20; i <= 36; i++) + { + if (needSet && dictionary >= (((UInt64)1 << (i - 7))) && i <= 32) + defaultBlockSize = i; + TCHAR s[40]; + ConvertUInt32ToString(1 << (i % 10), s); + if (i < 30) lstrcat(s, TEXT(" M")); + else lstrcat(s, TEXT(" G")); + lstrcat(s, TEXT("B")); + int index = (int)m_Solid.AddString(s); + m_Solid.SetItemData(index, (UInt32)i); + } + index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_SOLID, 0x02000D15)); + m_Solid.SetItemData(index, kSolidBlockSize); + if (defaultBlockSize == (UInt32)-1) + defaultBlockSize = kSolidBlockSize; + if (defaultBlockSize != kNoSolidBlockSize) + SetNearestSelectComboBox(m_Solid, defaultBlockSize); +} + +void CCompressDialog::SetNumThreads() +{ + m_NumThreads.ResetContent(); + + const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; + if (!fi.MultiThread) + return; + + UInt32 numHardwareThreads = NSystem::GetNumberOfProcessors(); + UInt32 defaultValue = numHardwareThreads; + + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + int index = FindRegistryFormat(ai.Name); + if (index >= 0) + { + const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; + if (fo.Method.CompareNoCase(GetMethodSpec()) == 0 && fo.NumThreads != (UInt32)-1) + defaultValue = fo.NumThreads; + } + + UInt32 numAlgoThreadsMax = 1; + int methodID = GetMethodID(); + switch (methodID) + { + case kLZMA: numAlgoThreadsMax = 2; break; + case kLZMA2: numAlgoThreadsMax = 32; break; + case kBZip2: numAlgoThreadsMax = 32; break; + } + if (IsZipFormat()) + numAlgoThreadsMax = 128; + for (UInt32 i = 1; i <= numHardwareThreads * 2 && i <= numAlgoThreadsMax; i++) + { + TCHAR s[40]; + ConvertUInt32ToString(i, s); + int index = (int)m_NumThreads.AddString(s); + m_NumThreads.SetItemData(index, (UInt32)i); + } + SetNearestSelectComboBox(m_NumThreads, defaultValue); +} + +UInt64 CCompressDialog::GetMemoryUsage(UInt32 dictionary, UInt64 &decompressMemory) +{ + decompressMemory = UInt64(Int64(-1)); + UInt32 level = GetLevel2(); + if (level == 0) + { + decompressMemory = (1 << 20); + return decompressMemory; + } + UInt64 size = 0; + + const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; + if (fi.Filter && level >= 9) + size += (12 << 20) * 2 + (5 << 20); + UInt32 numThreads = GetNumThreads2(); + if (IsZipFormat()) + { + UInt32 numSubThreads = 1; + if (GetMethodID() == kLZMA && numThreads > 1 && level >= 5) + numSubThreads = 2; + UInt32 numMainThreads = numThreads / numSubThreads; + if (numMainThreads > 1) + size += (UInt64)numMainThreads << 25; + } + int methidId = GetMethodID(); + switch (methidId) + { + case kLZMA: + case kLZMA2: + { + 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++; + UInt64 size1 = (UInt64)hs * 4; + size1 += (UInt64)dictionary * 4; + if (level >= 5) + size1 += (UInt64)dictionary * 4; + size1 += (2 << 20); + + UInt32 numThreads1 = 1; + if (numThreads > 1 && level >= 5) + { + size1 += (2 << 20) + (4 << 20); + numThreads1 = 2; + } + UInt32 numBlockThreads = numThreads / numThreads1; + if (methidId == kLZMA || numBlockThreads == 1) + size1 += (UInt64)dictionary * 3 / 2; + else + { + UInt64 chunkSize = (UInt64)dictionary << 2; + chunkSize = MyMax(chunkSize, (UInt64)(1 << 20)); + chunkSize = MyMin(chunkSize, (UInt64)(1 << 28)); + chunkSize = MyMax(chunkSize, (UInt64)dictionary); + size1 += chunkSize * 2; + } + size += size1 * numBlockThreads; + + decompressMemory = dictionary + (2 << 20); + return size; + } + case kPPMd: + { + decompressMemory = dictionary + (2 << 20); + return size + decompressMemory; + } + case kDeflate: + case kDeflate64: + { + UInt32 order = GetOrder(); + if (order == (UInt32)-1) + order = 32; + if (level >= 7) + size += (1 << 20); + size += 3 << 20; + decompressMemory = (2 << 20); + return size; + } + case kBZip2: + { + decompressMemory = (7 << 20); + UInt64 memForOneThread = (10 << 20); + return size + memForOneThread * numThreads; + } + case kPPMdZip: + { + decompressMemory = dictionary + (2 << 20); + return size + (UInt64)decompressMemory * numThreads; + } + } + return (UInt64)(Int64)-1; +} + +UInt64 CCompressDialog::GetMemoryUsage(UInt64 &decompressMemory) +{ + return GetMemoryUsage(GetDictionary(), decompressMemory); +} + +void CCompressDialog::PrintMemUsage(UINT res, UInt64 value) +{ + if (value == (UInt64)(Int64)-1) + { + SetItemText(res, TEXT("?")); + return; + } + value = (value + (1 << 20) - 1) >> 20; + TCHAR s[40]; + ConvertUInt64ToString(value, s); + lstrcat(s, TEXT(" MB")); + SetItemText(res, s); +} + +void CCompressDialog::SetMemoryUsage() +{ + UInt64 decompressMem; + UInt64 memUsage = GetMemoryUsage(decompressMem); + PrintMemUsage(IDC_STATIC_COMPRESS_MEMORY_VALUE, memUsage); + PrintMemUsage(IDC_STATIC_COMPRESS_MEMORY_DE_VALUE, decompressMem); +} + +void CCompressDialog::SetParams() +{ + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + m_Params.SetText(TEXT("")); + int index = FindRegistryFormat(ai.Name); + if (index >= 0) + { + const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; + m_Params.SetText(fo.Options); + } +} + +void CCompressDialog::SaveOptionsInMem() +{ + const CArcInfoEx &ai = (*ArcFormats)[Info.FormatIndex]; + int index = FindRegistryFormatAlways(ai.Name); + m_Params.GetText(Info.Options); + Info.Options.Trim(); + NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; + fo.Options = Info.Options; + fo.Level = GetLevelSpec(); + fo.Dictionary = GetDictionarySpec(); + fo.Order = GetOrderSpec(); + fo.Method = GetMethodSpec(); + fo.EncryptionMethod = GetEncryptionMethodSpec(); + fo.NumThreads = GetNumThreadsSpec(); + fo.BlockLogSize = GetBlockSizeSpec(); +} + +int CCompressDialog::GetFormatIndex() +{ + return (int)m_Format.GetItemData(m_Format.GetCurSel()); +} diff --git a/CPP/7zip/UI/GUI/CompressDialog.h b/CPP/7zip/UI/GUI/CompressDialog.h new file mode 100755 index 0000000..6213dfd --- /dev/null +++ b/CPP/7zip/UI/GUI/CompressDialog.h @@ -0,0 +1,189 @@ +// CompressDialog.h + +#ifndef __COMPRESS_DIALOG_H +#define __COMPRESS_DIALOG_H + +#include "Windows/Control/ComboBox.h" +#include "Windows/Control/Edit.h" + +#include "../Common/LoadCodecs.h" +#include "../Common/ZipRegistry.h" + +#include "../FileManager/DialogSize.h" + +#include "CompressDialogRes.h" + +namespace NCompressDialog +{ + namespace NUpdateMode + { + enum EEnum + { + kAdd, + kUpdate, + kFresh, + kSynchronize + }; + } + struct CInfo + { + NUpdateMode::EEnum UpdateMode; + bool SolidIsSpecified; + bool MultiThreadIsAllowed; + UInt64 SolidBlockSize; + UInt32 NumThreads; + + CRecordVector VolumeSizes; + + UInt32 Level; + UString Method; + UInt32 Dictionary; + bool OrderMode; + UInt32 Order; + UString Options; + + UString EncryptionMethod; + + bool SFXMode; + bool OpenShareForWrite; + + + UString ArchiveName; // in: Relative for ; out: abs + UString CurrentDirPrefix; + bool KeepName; + + bool GetFullPathName(UString &result) const; + + int FormatIndex; + + UString Password; + bool EncryptHeadersIsAllowed; + bool EncryptHeaders; + + void Init() + { + Level = Dictionary = Order = UInt32(-1); + OrderMode = false; + Method.Empty(); + Options.Empty(); + EncryptionMethod.Empty(); + } + CInfo() + { + Init(); + } + }; +} + +class CCompressDialog: public NWindows::NControl::CModalDialog +{ + NWindows::NControl::CComboBox m_ArchivePath; + NWindows::NControl::CComboBox m_Format; + NWindows::NControl::CComboBox m_Level; + NWindows::NControl::CComboBox m_Method; + NWindows::NControl::CComboBox m_Dictionary; + NWindows::NControl::CComboBox m_Order; + NWindows::NControl::CComboBox m_Solid; + NWindows::NControl::CComboBox m_NumThreads; + NWindows::NControl::CComboBox m_UpdateMode; + NWindows::NControl::CComboBox m_Volume; + NWindows::NControl::CDialogChildControl m_Params; + + NWindows::NControl::CEdit _password1Control; + NWindows::NControl::CEdit _password2Control; + NWindows::NControl::CComboBox _encryptionMethod; + + NCompression::CInfo m_RegistryInfo; + + int m_PrevFormat; + void SetArchiveName(const UString &name); + int FindRegistryFormat(const UString &name); + int FindRegistryFormatAlways(const UString &name); + + void CheckSFXNameChange(); + void SetArchiveName2(bool prevWasSFX); + + int GetStaticFormatIndex(); + + void SetNearestSelectComboBox(NWindows::NControl::CComboBox &comboBox, UInt32 value); + + void SetLevel(); + + void SetMethod(int keepMethodId = -1); + int GetMethodID(); + UString GetMethodSpec(); + UString GetEncryptionMethodSpec(); + + bool IsZipFormat(); + + void SetEncryptionMethod(); + + int AddDictionarySize(UInt32 size, bool kilo, bool maga); + int AddDictionarySize(UInt32 size); + + void SetDictionary(); + + UInt32 GetComboValue(NWindows::NControl::CComboBox &c, int defMax = 0); + + UInt32 GetLevel() { return GetComboValue(m_Level); } + UInt32 GetLevelSpec() { return GetComboValue(m_Level, 1); } + UInt32 GetLevel2(); + UInt32 GetDictionary() { return GetComboValue(m_Dictionary); } + UInt32 GetDictionarySpec() { return GetComboValue(m_Dictionary, 1); } + UInt32 GetOrder() { return GetComboValue(m_Order); } + UInt32 GetOrderSpec() { return GetComboValue(m_Order, 1); } + UInt32 GetNumThreadsSpec() { return GetComboValue(m_NumThreads, 1); } + UInt32 GetNumThreads2() { UInt32 num = GetNumThreadsSpec(); if (num == UInt32(-1)) num = 1; return num; } + UInt32 GetBlockSizeSpec() { return GetComboValue(m_Solid, 1); } + + int AddOrder(UInt32 size); + void SetOrder(); + bool GetOrderMode(); + + void SetSolidBlockSize(); + void SetNumThreads(); + + UInt64 GetMemoryUsage(UInt32 dictionary, UInt64 &decompressMemory); + UInt64 GetMemoryUsage(UInt64 &decompressMemory); + void PrintMemUsage(UINT res, UInt64 value); + void SetMemoryUsage(); + void SetParams(); + void SaveOptionsInMem(); + + void UpdatePasswordControl(); + bool IsShowPasswordChecked() const + { return IsButtonChecked(IDC_COMPRESS_CHECK_SHOW_PASSWORD) == BST_CHECKED; } + + int GetFormatIndex(); +public: + CObjectVector *ArcFormats; + CRecordVector ArcIndices; + + NCompressDialog::CInfo Info; + UString OriginalFileName; // for bzip2, gzip2 + + INT_PTR Create(HWND wndParent = 0) + { + BIG_DIALOG_SIZE(400, 304); + return CModalDialog::Create(SIZED_DIALOG(IDD_DIALOG_COMPRESS), wndParent); + } + +protected: + + void CheckSFXControlsEnable(); + void CheckVolumeEnable(); + void CheckControlsEnable(); + + void OnButtonSetArchive(); + bool IsSFX(); + void OnButtonSFX(); + + virtual bool OnInit(); + virtual bool OnCommand(int code, int itemID, LPARAM lParam); + virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); + virtual void OnOK(); + virtual void OnHelp(); + +}; + +#endif diff --git a/CPP/7zip/UI/GUI/CompressDialog.rc b/CPP/7zip/UI/GUI/CompressDialog.rc new file mode 100755 index 0000000..0ca7b70 --- /dev/null +++ b/CPP/7zip/UI/GUI/CompressDialog.rc @@ -0,0 +1,187 @@ +#include "CompressDialogRes.h" +#include "../../GuiCommon.rc" + +#define xc 400 +#define yc 304 + +#undef gSize +#undef gSpace +#undef g0xs +#undef g1x +#undef g1xs +#undef g2xs +#undef g3x +#undef g3xs +#undef g4x +#undef g4x2 +#undef g4xs +#undef g4xs2 + +#define gSize 192 +#define gSpace 24 + +#define g1xs 88 +#define g0xs (gSize - g1xs) +#define g1x (m + g0xs) + +#define g3xs 40 +#define g2xs (gSize - g3xs) +#define g3x (m + g2xs) + +#define g4x (m + gSize + gSpace) +#define g4x2 (g4x + m) +#define g4xs (xc - gSize - gSpace) +#define g4xs2 (g4xs - m - m) + +#define yOpt 72 +#define yPsw 128 + +IDD_DIALOG_COMPRESS MY_DIALOG +CAPTION "Add to Archive" +BEGIN + LTEXT "&Archive:", IDC_STATIC_COMPRESS_ARCHIVE, m, m, xc, 8 + COMBOBOX IDC_COMPRESS_COMBO_ARCHIVE, m, 18, xc - bxsDots - 12, 126, MY_COMBO_WITH_EDIT + PUSHBUTTON "...", IDC_COMPRESS_BUTTON_SET_ARCHIVE, xs - m - bxsDots, 17, bxsDots, bys, WS_GROUP + + LTEXT "Archive &format:", IDC_STATIC_COMPRESS_FORMAT, m, 41, g0xs, 8 + COMBOBOX IDC_COMPRESS_COMBO_FORMAT, g1x, 39, g1xs , 80, MY_COMBO | CBS_SORT + + LTEXT "Compression &level:",IDC_STATIC_COMPRESS_LEVEL, m, 62, g0xs, 8 + COMBOBOX IDC_COMPRESS_COMBO_LEVEL, g1x, 60, g1xs, 80, MY_COMBO + + LTEXT "Compression &method:",IDC_STATIC_COMPRESS_METHOD, m, 83, g0xs, 8 + COMBOBOX IDC_COMPRESS_COMBO_METHOD, g1x, 81, g1xs, 80, MY_COMBO + + LTEXT "&Dictionary size:",IDC_STATIC_COMPRESS_DICTIONARY, m, 104, g0xs, 8 + COMBOBOX IDC_COMPRESS_COMBO_DICTIONARY, g1x, 102, g1xs, 167, MY_COMBO + + LTEXT "&Word size:",IDC_STATIC_COMPRESS_ORDER, m, 125, g0xs, 8 + COMBOBOX IDC_COMPRESS_COMBO_ORDER, g1x, 123, g1xs, 141, MY_COMBO + + LTEXT "&Solid Block size:",IDC_STATIC_COMPRESS_SOLID, m, 146, g0xs, 8 + COMBOBOX IDC_COMPRESS_COMBO_SOLID, g1x, 144, g1xs, 140, MY_COMBO + + LTEXT "&Number of CPU threads:",IDC_STATIC_COMPRESS_THREADS, m, 167, g0xs, 8 + COMBOBOX IDC_COMPRESS_COMBO_THREADS, g1x, 165, g1xs - 35, 140, MY_COMBO + RTEXT "1", IDC_COMPRESS_HARDWARE_THREADS, g1x + g1xs - 35 + 10, 167, 25, 8 + + + LTEXT "Memory usage for Compressing:", IDC_STATIC_COMPRESS_MEMORY, m, 190, g2xs, 8 + RTEXT "0", IDC_STATIC_COMPRESS_MEMORY_VALUE, g3x, 190, g3xs, 8 + + LTEXT "Memory usage for Decompressing:", IDC_STATIC_COMPRESS_MEMORY_DE, m, 206, g2xs, 8 + RTEXT "0",IDC_STATIC_COMPRESS_MEMORY_DE_VALUE, g3x, 206, g3xs, 8 + + + LTEXT "Split to &volumes, bytes:", IDC_STATIC_COMPRESS_VOLUME, m, 225, gSize, 8 + COMBOBOX IDC_COMPRESS_COMBO_VOLUME, m, 237, gSize, 73, MY_COMBO_WITH_EDIT + + LTEXT "&Parameters:",IDC_STATIC_COMPRESS_PARAMETERS, m, 260, xc, 8 + EDITTEXT IDC_COMPRESS_EDIT_PARAMETERS, m, 272, xc, 14, ES_AUTOHSCROLL + + LTEXT "&Update mode:",IDC_STATIC_COMPRESS_UPDATE_MODE, g4x, 39, g4xs, 8 + COMBOBOX IDC_COMPRESS_COMBO_UPDATE_MODE, g4x, 51, g4xs, 80, MY_COMBO + + GROUPBOX "Options",IDC_STATIC_COMPRESS_OPTIONS, g4x, yOpt, g4xs, 48 + CONTROL "Create SF&X archive",IDC_COMPRESS_SFX, MY_CHECKBOX, + g4x2, yOpt + 14, g4xs2, 10 + CONTROL "Compress shared files",IDC_COMPRESS_SHARED, MY_CHECKBOX, + g4x2, yOpt + 30, g4xs2, 10 + + GROUPBOX "Encryption",IDC_COMPRESS_ENCRYPTION, g4x, yPsw, g4xs, 127 + + LTEXT "Enter password:",IDC_STATIC_COMPRESS_PASSWORD1, g4x2, yPsw + 14, g4xs2, 8 + EDITTEXT IDC_COMPRESS_EDIT_PASSWORD1, g4x2, yPsw + 26, g4xs2, 14, ES_PASSWORD | ES_AUTOHSCROLL + LTEXT "Reenter password:",IDC_STATIC_COMPRESS_PASSWORD2, g4x2, yPsw + 46, g4xs2, 8 + EDITTEXT IDC_COMPRESS_EDIT_PASSWORD2, g4x2, yPsw + 58, g4xs2, 14, ES_PASSWORD | ES_AUTOHSCROLL + + CONTROL "Show Password",IDC_COMPRESS_CHECK_SHOW_PASSWORD,MY_CHECKBOX, + g4x2, yPsw + 79, g4xs2, 10 + + LTEXT "&Encryption method:",IDC_STATIC_COMPRESS_ENCRYPTION_METHOD, g4x2, yPsw + 95, 100, 8 + COMBOBOX IDC_COMPRESS_COMBO_ENCRYPTION_METHOD, g4x2 + 100, yPsw + 93, g4xs2 - 100, 198, MY_COMBO + + CONTROL "Encrypt file &names", IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES, MY_CHECKBOX, + g4x2, yPsw + 111, g4xs2, 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 +#undef xc +#undef yc + +#define m 4 +#define xc 152 +#define yc 160 + + +IDD_DIALOG_COMPRESS_2 MY_DIALOG +CAPTION "Add to Archive" +MY_FONT +BEGIN + // LTEXT "&Archive:", IDC_STATIC_COMPRESS_ARCHIVE, m, m + 1, 32, 8 + COMBOBOX IDC_COMPRESS_COMBO_ARCHIVE, m, m, xc - bxsDots - m, 126, MY_COMBO_WITH_EDIT + PUSHBUTTON "...", IDC_COMPRESS_BUTTON_SET_ARCHIVE, xs - m - bxsDots, m, bxsDots, 12, WS_GROUP + + COMBOBOX IDC_COMPRESS_COMBO_FORMAT, m , 22, 32, 80, MY_COMBO | CBS_SORT + COMBOBOX IDC_COMPRESS_COMBO_LEVEL, m + 36, 22, 68, 80, MY_COMBO + COMBOBOX IDC_COMPRESS_COMBO_METHOD, m + 108, 22, 44, 80, MY_COMBO + + COMBOBOX IDC_COMPRESS_COMBO_DICTIONARY, m, 40, 40, 80, MY_COMBO + COMBOBOX IDC_COMPRESS_COMBO_ORDER, m + 44, 40, 32, 80, MY_COMBO + COMBOBOX IDC_COMPRESS_COMBO_SOLID, m + 80, 40, 40, 80, MY_COMBO + COMBOBOX IDC_COMPRESS_COMBO_THREADS, m + 124, 40, 28, 80, MY_COMBO + + LTEXT "Split to &volumes, bytes:", IDC_STATIC_COMPRESS_VOLUME, m, 60, 32, 8 + COMBOBOX IDC_COMPRESS_COMBO_VOLUME, m + 32, 58, 44, 73, MY_COMBO_WITH_EDIT + LTEXT "&Parameters:",IDC_STATIC_COMPRESS_PARAMETERS, m + 80, 60, 48, 8 + EDITTEXT IDC_COMPRESS_EDIT_PARAMETERS, m + 128, 58, 24, 13, ES_AUTOHSCROLL + + COMBOBOX IDC_COMPRESS_COMBO_UPDATE_MODE, m, 76, 88, 80, MY_COMBO + CONTROL "SF&X", IDC_COMPRESS_SFX, MY_CHECKBOX, m + 92, 77, 60, 10 + + CONTROL "Compress shared files", IDC_COMPRESS_SHARED, MY_CHECKBOX, m, 94, xc, 10 + + LTEXT "Enter password:", IDC_STATIC_COMPRESS_PASSWORD1, m, 112, 60, 8 + EDITTEXT IDC_COMPRESS_EDIT_PASSWORD1, m + 60, 110, 44, 13, ES_PASSWORD | ES_AUTOHSCROLL + CONTROL "Show Password", IDC_COMPRESS_CHECK_SHOW_PASSWORD, MY_CHECKBOX, m + 108, 112, 44, 10 + + COMBOBOX IDC_COMPRESS_COMBO_ENCRYPTION_METHOD, m, 128, 48, 198, MY_COMBO + CONTROL "Encrypt file &names", IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES, MY_CHECKBOX, m + 52, 130, 100, 10 + + OK_CANCEL +END + +#endif + +STRINGTABLE +BEGIN + IDS_METHOD_STORE "Store" + IDS_METHOD_NORMAL "Normal" + IDS_METHOD_MAXIMUM "Maximum" + IDS_METHOD_FAST "Fast" + IDS_METHOD_FASTEST "Fastest" + IDS_METHOD_ULTRA "Ultra" + + IDS_COMPRESS_NON_SOLID "Non-solid" + IDS_COMPRESS_SOLID "Solid" + + IDS_COMPRESS_UPDATE_MODE_ADD "Add and replace files" + IDS_COMPRESS_UPDATE_MODE_UPDATE "Update and add files" + IDS_COMPRESS_UPDATE_MODE_FRESH "Freshen existing files" + IDS_COMPRESS_UPDATE_MODE_SYNCHRONIZE "Synchronize files" + IDS_COMPRESS_SET_ARCHIVE_DIALOG_TITLE "Browse" + IDS_COMPRESS_SPLIT_CONFIRM_MESSAGE "Specified volume size: {0} bytes.\nAre you sure you want to split archive into such volumes?" + + IDS_OPEN_TYPE_ALL_FILES "All Files" + + IDS_PASSWORD_USE_ASCII "Use only English letters, numbers and special characters (!, #, $, ...) for password." + IDS_PASSWORD_PASSWORDS_DO_NOT_MATCH "Passwords do not match" + IDS_PASSWORD_IS_TOO_LONG "Password is too long" +END diff --git a/CPP/7zip/UI/GUI/CompressDialogRes.h b/CPP/7zip/UI/GUI/CompressDialogRes.h new file mode 100755 index 0000000..2127d4e --- /dev/null +++ b/CPP/7zip/UI/GUI/CompressDialogRes.h @@ -0,0 +1,81 @@ +#define IDD_DIALOG_COMPRESS 551 +#define IDD_DIALOG_COMPRESS_2 651 +#define IDC_STATIC_COMPRESS_MEMORY 1022 +#define IDC_STATIC_COMPRESS_MEMORY_DE 1023 +#define IDC_STATIC_COMPRESS_MEMORY_VALUE 1027 +#define IDC_STATIC_COMPRESS_MEMORY_DE_VALUE 1028 +#define IDC_COMPRESS_COMBO_ARCHIVE 1072 +#define IDC_COMPRESS_BUTTON_SET_ARCHIVE 1073 +#define IDC_COMPRESS_COMBO_LEVEL 1074 +#define IDC_COMPRESS_COMBO_UPDATE_MODE 1075 +#define IDC_COMPRESS_COMBO_FORMAT 1076 +#define IDC_COMPRESS_COMBO_VOLUME 1077 +#define IDC_COMPRESS_COMBO_METHOD 1078 +#define IDC_COMPRESS_COMBO_DICTIONARY 1079 +#define IDC_COMPRESS_COMBO_ORDER 1080 + +#define IDC_COMPRESS_COMBO_SOLID 1081 +#define IDC_COMPRESS_COMBO_THREADS 1082 +#define IDC_COMPRESS_HARDWARE_THREADS 1083 + +#define IDC_COMPRESS_SFX 1090 +#define IDC_COMPRESS_EDIT_PARAMETERS 1091 + +// #define IDC_COMPRESS_SOLID 1092 +// #define IDC_COMPRESS_MULTI_THREAD 1093 + +#define IDC_STATIC_COMPRESS_ARCHIVE 1097 +#define IDC_STATIC_COMPRESS_FORMAT 1098 +#define IDC_STATIC_COMPRESS_LEVEL 1099 +#define IDC_STATIC_COMPRESS_PARAMETERS 1100 +#define IDC_STATIC_COMPRESS_UPDATE_MODE 1101 +#define IDC_STATIC_COMPRESS_OPTIONS 1102 +#define IDC_STATIC_COMPRESS_VOLUME 1103 +#define IDC_STATIC_COMPRESS_METHOD 1104 +#define IDC_STATIC_COMPRESS_DICTIONARY 1105 +#define IDC_STATIC_COMPRESS_ORDER 1106 + +#define IDC_STATIC_COMPRESS_SOLID 1107 +#define IDC_STATIC_COMPRESS_THREADS 1108 + +#define IDC_COMPRESS_ENCRYPTION 1110 +#define IDC_STATIC_COMPRESS_PASSWORD1 1111 +#define IDC_COMPRESS_EDIT_PASSWORD1 1112 +#define IDC_STATIC_COMPRESS_PASSWORD2 1113 +#define IDC_COMPRESS_EDIT_PASSWORD2 1114 +#define IDC_COMPRESS_CHECK_SHOW_PASSWORD 1115 + +#define IDC_STATIC_COMPRESS_ENCRYPTION_METHOD 1120 +#define IDC_COMPRESS_COMBO_ENCRYPTION_METHOD 1121 + +#define IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES 1122 + +#define IDC_COMPRESS_SHARED 1130 + + +#define IDS_OPEN_TYPE_ALL_FILES 80 + +#define IDS_METHOD_STORE 81 +#define IDS_METHOD_NORMAL 82 +#define IDS_METHOD_MAXIMUM 83 +#define IDS_METHOD_FAST 84 +#define IDS_METHOD_FASTEST 85 +#define IDS_METHOD_ULTRA 86 + +#define IDS_COMPRESS_NON_SOLID 88 +#define IDS_COMPRESS_SOLID 89 + +#define IDS_COMPRESS_UPDATE_MODE_ADD 90 +#define IDS_COMPRESS_UPDATE_MODE_UPDATE 91 +#define IDS_COMPRESS_UPDATE_MODE_FRESH 92 +#define IDS_COMPRESS_UPDATE_MODE_SYNCHRONIZE 93 + +#define IDS_COMPRESS_SPLIT_CONFIRM_MESSAGE 94 + +#define IDS_COMPRESS_SET_ARCHIVE_DIALOG_TITLE 96 + +#define IDS_PASSWORD_USE_ASCII 110 +#define IDS_PASSWORD_PASSWORDS_DO_NOT_MATCH 111 +#define IDS_PASSWORD_IS_TOO_LONG 112 + +#define IDS_COMPRESS_INCORRECT_VOLUME_SIZE 95 diff --git a/CPP/7zip/UI/GUI/Extract.rc b/CPP/7zip/UI/GUI/Extract.rc new file mode 100755 index 0000000..72ebe07 --- /dev/null +++ b/CPP/7zip/UI/GUI/Extract.rc @@ -0,0 +1,33 @@ +#include "ExtractRes.h" + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +STRINGTABLE DISCARDABLE +BEGIN + IDS_UPDATE_NOT_SUPPORTED "Update operations are not supported for this archive." + IDS_CANNOT_CREATE_FOLDER "Cannot create folder '{0}'" + IDS_OPEN_IS_NOT_SUPORTED_ARCHIVE "File is not supported archive." + IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CRC "CRC failed in '{0}'. File is broken." + IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_DATA_ERROR "Data error in '{0}'. File is broken" + IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CRC_ENCRYPTED "CRC failed in encrypted file '{0}'. Wrong password?" + IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED "Data error in encrypted file '{0}'. Wrong password?" + IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_UNSUPPORTED_METHOD "Unsupported compression method for '{0}'." + IDS_EXTRACT_SET_FOLDER "Specify a location for extracted files." + IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CANNOT_OPEN_FILE "Can not open output file '{0}'." + IDS_PROGRESS_EXTRACTING "Extracting" + 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_MEM_ERROR "The system cannot allocate the required amount of memory" + IDS_UNKNOWN_ERROR "Unknown Error" + IDS_UNSUPPORTED_ARCHIVE_TYPE "Unsupported archive type" + + IDC_EXTRACT_RADIO_FULL_PATHNAMES "Full pathnames" + IDC_EXTRACT_RADIO_CURRENT_PATHNAMES "Current pathnames" + IDC_EXTRACT_RADIO_NO_PATHNAMES "No pathnames" + + IDC_EXTRACT_RADIO_ASK_BEFORE_OVERWRITE "Ask before overwrite" + IDC_EXTRACT_RADIO_OVERWRITE_WITHOUT_PROMPT "Overwrite without prompt" + IDC_EXTRACT_RADIO_SKIP_EXISTING_FILES "Skip existing files" + IDC_EXTRACT_RADIO_AUTO_RENAME "Auto rename" + IDC_EXTRACT_RADIO_AUTO_RENAME_EXISTING "Auto rename existing files" +END diff --git a/CPP/7zip/UI/GUI/ExtractDialog.cpp b/CPP/7zip/UI/GUI/ExtractDialog.cpp new file mode 100755 index 0000000..83b4582 --- /dev/null +++ b/CPP/7zip/UI/GUI/ExtractDialog.cpp @@ -0,0 +1,355 @@ +// ExtractDialog.cpp + +#include "StdAfx.h" + +// #include + +#include "ExtractDialog.h" + +#include "Common/StringConvert.h" + +#include "Windows/FileName.h" +#include "Windows/FileDir.h" +#include "Windows/ResourceString.h" + +#ifndef NO_REGISTRY +#include "../FileManager/HelpUtils.h" +#endif + +#include "../Common/ZipRegistry.h" + +#include "../FileManager/BrowseDialog.h" +#include "../FileManager/LangUtils.h" +#include "../FileManager/resourceGui.h" + +#include "ExtractRes.h" +#include "ExtractDialogRes.h" + +using namespace NWindows; +using namespace NFile; +using namespace NName; + +extern HINSTANCE g_hInstance; + +static CIDLangPair kPathMode_Pairs[] = +{ + { IDC_EXTRACT_RADIO_FULL_PATHNAMES, 0x02000811 }, + // { IDC_EXTRACT_RADIO_CURRENT_PATHNAMES, 0x02000812 }, + { IDC_EXTRACT_RADIO_NO_PATHNAMES, 0x02000813 } +}; + +static CIDLangPair kOverwriteMode_Pairs[] = +{ + { IDC_EXTRACT_RADIO_ASK_BEFORE_OVERWRITE, 0x02000821 }, + { IDC_EXTRACT_RADIO_OVERWRITE_WITHOUT_PROMPT, 0x02000822 }, + { IDC_EXTRACT_RADIO_SKIP_EXISTING_FILES, 0x02000823 }, + { IDC_EXTRACT_RADIO_AUTO_RENAME, 0x02000824 }, + { IDC_EXTRACT_RADIO_AUTO_RENAME_EXISTING, 0x02000825 } +}; + +#ifndef _SFX + +static const + // NExtract::NPathMode::EEnum + int + kPathModeButtonsVals[] = +{ + NExtract::NPathMode::kFullPathnames, + // NExtract::NPathMode::kCurrentPathnames, + NExtract::NPathMode::kNoPathnames +}; + +static const int kOverwriteButtons[] = +{ + IDC_EXTRACT_RADIO_ASK_BEFORE_OVERWRITE, + IDC_EXTRACT_RADIO_OVERWRITE_WITHOUT_PROMPT, + IDC_EXTRACT_RADIO_SKIP_EXISTING_FILES, + IDC_EXTRACT_RADIO_AUTO_RENAME, + IDC_EXTRACT_RADIO_AUTO_RENAME_EXISTING, +}; + +static const + int + // NExtract::NOverwriteMode::EEnum + kOverwriteButtonsVals[] = +{ + NExtract::NOverwriteMode::kAskBefore, + NExtract::NOverwriteMode::kWithoutPrompt, + NExtract::NOverwriteMode::kSkipExisting, + NExtract::NOverwriteMode::kAutoRename, + NExtract::NOverwriteMode::kAutoRenameExisting +}; + +static const int kNumOverwriteButtons = sizeof(kOverwriteButtons) / sizeof(kOverwriteButtons[0]); + +/* +static const int kFilesButtons[] = +{ + IDC_EXTRACT_RADIO_SELECTED_FILES, + IDC_EXTRACT_RADIO_ALL_FILES +}; +static const int kNumFilesButtons = sizeof(kFilesButtons) / sizeof(kFilesButtons[0]); +*/ + +/* +int CExtractDialog::GetFilesMode() const +{ + for (int i = 0; i < kNumFilesButtons; i++) + if (IsButtonCheckedBool(kFilesButtons[i])) + return i; + throw 0; +} +*/ + +#endif + +#ifdef LANG +static CIDLangPair kIDLangPairs[] = +{ + { IDC_STATIC_EXTRACT_EXTRACT_TO, 0x02000801 }, + { IDC_EXTRACT_PATH_MODE, 0x02000810 }, + { IDC_EXTRACT_OVERWRITE_MODE, 0x02000820 }, + // { IDC_EXTRACT_FILES, 0x02000830 }, + // { IDC_EXTRACT_RADIO_SELECTED_FILES, 0x02000831 }, + // { IDC_EXTRACT_RADIO_ALL_FILES, 0x02000832 }, + { IDC_EXTRACT_PASSWORD, 0x02000802 }, + { IDC_EXTRACT_CHECK_SHOW_PASSWORD, 0x02000B02 }, + { IDOK, 0x02000702 }, + { IDCANCEL, 0x02000710 }, + { IDHELP, 0x02000720 } + +}; +#endif + +// static const int kWildcardsButtonIndex = 2; + +#ifndef NO_REGISTRY +static const int kHistorySize = 8; +#endif + +#ifndef _SFX +static void AddComboItems(NWindows::NControl::CComboBox &combo, const CIDLangPair *items, int numItems, const int *values, int curVal) +{ + int curSel = 0; + for (int i = 0; i < numItems; i++) + { + UString s = LangString(items[i].ControlID, items[i].LangID); + s.Replace(L"&", L""); + int index = (int)combo.AddString(s); + combo.SetItemData(index, i); + if (values[i] == curVal) + curSel = i; + } + combo.SetCurSel(curSel); +} +#endif + +bool CExtractDialog::OnInit() +{ + #ifdef LANG + LangSetWindowText(HWND(*this), 0x02000800); + LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + #endif + #ifndef _SFX + _passwordControl.Attach(GetItem(IDC_EXTRACT_EDIT_PASSWORD)); + _passwordControl.SetText(Password); + _passwordControl.SetPasswordChar(TEXT('*')); + #endif + + NExtract::CInfo info; + + #ifdef NO_REGISTRY + PathMode = NExtract::NPathMode::kFullPathnames; + OverwriteMode = NExtract::NOverwriteMode::kAskBefore; + // info.Paths = NExtract::NPathMode::kFullPathnames; + #else + info.Load(); + CheckButton(IDC_EXTRACT_CHECK_SHOW_PASSWORD, info.ShowPassword); + UpdatePasswordControl(); + PathMode = info.PathMode; + OverwriteMode = info.OverwriteMode; + #endif + + _path.Attach(GetItem(IDC_EXTRACT_COMBO_PATH)); + + _path.SetText(DirectoryPath); + + #ifndef NO_REGISTRY + for (int 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_COMBO_PATH_MODE)); + AddComboItems(_pathMode, kPathMode_Pairs, sizeof(kPathMode_Pairs) / sizeof(kPathMode_Pairs[0]), + kPathModeButtonsVals, PathMode); + + _overwriteMode.Attach(GetItem(IDC_EXTRACT_COMBO_OVERWRITE_MODE)); + AddComboItems(_overwriteMode, kOverwriteMode_Pairs, sizeof(kOverwriteMode_Pairs) / sizeof(kOverwriteMode_Pairs[0]), + kOverwriteButtonsVals, OverwriteMode); + + /* + CheckRadioButton(kFilesButtons[0], kFilesButtons[kNumFilesButtons - 1], + kFilesButtons[_filesMode]); + */ + + // CWindow selectedFilesWindow = GetItem(IDC_EXTRACT_RADIO_SELECTED_FILES); + // selectedFilesWindow.Enable(_enableSelectedFilesButton); + + + #endif + + HICON icon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ICON)); + SetIcon(ICON_BIG, icon); + + // CWindow filesWindow = GetItem(IDC_EXTRACT_RADIO_FILES); + // filesWindow.Enable(_enableFilesButton); + + // UpdateWildCardState(); + NormalizePosition(); + + return CModalDialog::OnInit(); +} + +#ifndef _SFX +void CExtractDialog::UpdatePasswordControl() +{ + _passwordControl.SetPasswordChar((IsButtonChecked( + IDC_EXTRACT_CHECK_SHOW_PASSWORD) == BST_CHECKED) ? 0: TEXT('*')); + UString password; + _passwordControl.GetText(password); + _passwordControl.SetText(password); +} +#endif + +bool CExtractDialog::OnButtonClicked(int buttonID, HWND buttonHWND) +{ + /* + for (int i = 0; i < kNumFilesButtons; i++) + if (buttonID == kFilesButtons[i]) + { + UpdateWildCardState(); + return true; + } + */ + switch(buttonID) + { + case IDC_EXTRACT_BUTTON_SET_PATH: + OnButtonSetPath(); + return true; + #ifndef _SFX + case IDC_EXTRACT_CHECK_SHOW_PASSWORD: + { + UpdatePasswordControl(); + return true; + } + #endif + } + return CModalDialog::OnButtonClicked(buttonID, buttonHWND); +} + +void CExtractDialog::OnButtonSetPath() +{ + UString currentPath; + _path.GetText(currentPath); + UString title = LangStringSpec(IDS_EXTRACT_SET_FOLDER, 0x02000881); + UString resultPath; + if (!MyBrowseForFolder(HWND(*this), title, currentPath, resultPath)) + return; + #ifndef NO_REGISTRY + _path.SetCurSel(-1); + #endif + _path.SetText(resultPath); +} + +void AddUniqueString(UStringVector &list, const UString &s) +{ + for (int i = 0; i < list.Size(); i++) + if (s.CompareNoCase(list[i]) == 0) + return; + list.Add(s); +} + +void CExtractDialog::OnOK() +{ + #ifndef _SFX + NExtract::NPathMode::EEnum pathMode2 = (NExtract::NPathMode::EEnum)kPathModeButtonsVals[_pathMode.GetItemData(_pathMode.GetCurSel())]; + if (PathMode != NExtract::NPathMode::kCurrentPathnames || + pathMode2 != NExtract::NPathMode::kFullPathnames) + PathMode = pathMode2; + OverwriteMode = (NExtract::NOverwriteMode::EEnum)kOverwriteButtonsVals[_overwriteMode.GetItemData(_overwriteMode.GetCurSel())]; + + // _filesMode = (NExtractionDialog::NFilesMode::EEnum)GetFilesMode(); + + _passwordControl.GetText(Password); + #endif + + NExtract::CInfo info; + info.PathMode = PathMode; + info.OverwriteMode = OverwriteMode; + info.ShowPassword = (IsButtonCheckedBool(IDC_EXTRACT_CHECK_SHOW_PASSWORD)); + + 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(); + #ifndef _SFX + AddUniqueString(info.Paths, s); + #endif + DirectoryPath = s; + #ifndef NO_REGISTRY + 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(); +} + +/* +void CExtractDialog::UpdateWildCardState() +{ + // UpdateData(TRUE); + // m_Wildcards.EnableWindow(BoolToBOOL(m_Files == kWildcardsButtonIndex)); +} +*/ + +#ifndef NO_REGISTRY +static LPCWSTR kHelpTopic = L"fm/plugins/7-zip/extract.htm"; +void CExtractDialog::OnHelp() +{ + ShowHelpWindow(NULL, kHelpTopic); + CModalDialog::OnHelp(); +} +#endif + diff --git a/CPP/7zip/UI/GUI/ExtractDialog.h b/CPP/7zip/UI/GUI/ExtractDialog.h new file mode 100755 index 0000000..37e24df --- /dev/null +++ b/CPP/7zip/UI/GUI/ExtractDialog.h @@ -0,0 +1,83 @@ +// ExtractDialog.h + +#ifndef __EXTRACT_DIALOG_H +#define __EXTRACT_DIALOG_H + +#include "ExtractDialogRes.h" + +#include "Windows/Control/Edit.h" +#include "Windows/Control/ComboBox.h" + +#ifndef NO_REGISTRY +#include "../Common/ZipRegistry.h" +#endif +#include "../Common/ExtractMode.h" + +#include "../FileManager/DialogSize.h" + +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 _passwordControl; + NWindows::NControl::CComboBox _pathMode; + NWindows::NControl::CComboBox _overwriteMode; + #endif + + #ifndef _SFX + // int GetFilesMode() const; + void UpdatePasswordControl(); + #endif + + void OnButtonSetPath(); + + virtual bool OnInit(); + virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); + virtual void OnOK(); + #ifndef NO_REGISTRY + virtual void OnHelp(); + #endif +public: + // bool _enableSelectedFilesButton; + // bool _enableFilesButton; + // NExtractionDialog::NFilesMode::EEnum FilesMode; + + UString DirectoryPath; + #ifndef _SFX + UString Password; + #endif + NExtract::NPathMode::EEnum PathMode; + NExtract::NOverwriteMode::EEnum OverwriteMode; + + 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_DIALOG_EXTRACT), aWndParent); + } +}; + +#endif diff --git a/CPP/7zip/UI/GUI/ExtractDialog.rc b/CPP/7zip/UI/GUI/ExtractDialog.rc new file mode 100755 index 0000000..656b264 --- /dev/null +++ b/CPP/7zip/UI/GUI/ExtractDialog.rc @@ -0,0 +1,83 @@ +#include "ExtractDialogRes.h" +#include "../../GuiCommon.rc" + +#define xc 280 +#define yc 128 + +#undef g1xs +#undef g2x +#undef g2x2 +#undef g2xs +#undef g2xs2 + +#define g1xs 128 + +#define gSpace 24 +#define g2x (m + g1xs + gSpace) +#define g2x2 (g2x + m) +#define g2xs (xc - g1xs - gSpace) +#define g2xs2 (g2xs - m - m) + +IDD_DIALOG_EXTRACT MY_DIALOG +CAPTION "Extract" +BEGIN + LTEXT "E&xtract to:", IDC_STATIC_EXTRACT_EXTRACT_TO, m, m, xc, 8 + COMBOBOX IDC_EXTRACT_COMBO_PATH, m, m + 12, xc - bxsDots - 12, 100, MY_COMBO_WITH_EDIT + PUSHBUTTON "...", IDC_EXTRACT_BUTTON_SET_PATH, xs - m - bxsDots, m + 12 - 2, bxsDots, bys, WS_GROUP + + LTEXT "Path mode:", IDC_EXTRACT_PATH_MODE, m, m + 36, g1xs, 8 + COMBOBOX IDC_EXTRACT_COMBO_PATH_MODE, m, m + 48, g1xs, 140, MY_COMBO + + LTEXT "Overwrite mode:", IDC_EXTRACT_OVERWRITE_MODE, m, m + 68, g1xs, 8 + COMBOBOX IDC_EXTRACT_COMBO_OVERWRITE_MODE, m, m + 80, g1xs, 140, MY_COMBO + + #ifdef UNDER_CE + LTEXT "Password", IDC_EXTRACT_PASSWORD, g2x, m + 36, g2xs, 8 + #else + GROUPBOX "Password", IDC_EXTRACT_PASSWORD, g2x, m + 36, g2xs, 56 + #endif + EDITTEXT IDC_EXTRACT_EDIT_PASSWORD, g2x2, m + 50, g2xs2, 14, ES_PASSWORD | ES_AUTOHSCROLL + CONTROL "Show Password", IDC_EXTRACT_CHECK_SHOW_PASSWORD, MY_CHECKBOX, g2x2, m + 72, g2xs2, 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_DIALOG_EXTRACT_2 MY_DIALOG +CAPTION "Extract" +BEGIN + LTEXT "E&xtract to:", IDC_STATIC_EXTRACT_EXTRACT_TO, m, m, xc - bxsDots - 8, 8 + COMBOBOX IDC_EXTRACT_COMBO_PATH, m, m + 12, xc - bxsDots - 8, 100, MY_COMBO_WITH_EDIT + PUSHBUTTON "...", IDC_EXTRACT_BUTTON_SET_PATH, xs - m - bxsDots, m + 12 - 3, bxsDots, bys, WS_GROUP + + LTEXT "Path mode:", IDC_EXTRACT_PATH_MODE, m, m + 36, g1xs, 8 + COMBOBOX IDC_EXTRACT_COMBO_PATH_MODE, m + g1xs, m + 36, xc - g1xs, 100, MY_COMBO + + LTEXT "Overwrite mode:", IDC_EXTRACT_OVERWRITE_MODE, m, m + 56, g1xs, 8 + COMBOBOX IDC_EXTRACT_COMBO_OVERWRITE_MODE, m + g1xs, m + 56, xc - g1xs, 100, MY_COMBO + + LTEXT "Password", IDC_EXTRACT_PASSWORD, m, m + 76, g1xs, 8 + EDITTEXT IDC_EXTRACT_EDIT_PASSWORD, m + g1xs, m + 76, xc - g1xs, 14, ES_PASSWORD | ES_AUTOHSCROLL + CONTROL "Show Password", IDC_EXTRACT_CHECK_SHOW_PASSWORD, MY_CHECKBOX, m, m + 92, xc, 10 + + OK_CANCEL +END + +#endif diff --git a/CPP/7zip/UI/GUI/ExtractDialogRes.h b/CPP/7zip/UI/GUI/ExtractDialogRes.h new file mode 100755 index 0000000..3039561 --- /dev/null +++ b/CPP/7zip/UI/GUI/ExtractDialogRes.h @@ -0,0 +1,19 @@ +#define IDD_DIALOG_EXTRACT 552 +#define IDD_DIALOG_EXTRACT_2 652 + +#define IDC_STATIC_EXTRACT_EXTRACT_TO 1020 +#define IDC_EXTRACT_COMBO_PATH 1021 +#define IDC_EXTRACT_BUTTON_SET_PATH 1022 + +#define IDC_EXTRACT_COMBO_PATH_MODE 1030 +#define IDC_EXTRACT_COMBO_OVERWRITE_MODE 1031 + +#define IDC_EXTRACT_PATH_MODE 1040 +#define IDC_EXTRACT_OVERWRITE_MODE 1050 + +#define IDC_EXTRACT_FILES 1060 + +#define IDC_EXTRACT_PASSWORD 1100 +#define IDC_EXTRACT_EDIT_PASSWORD 1101 +#define IDC_EXTRACT_CHECK_SHOW_PASSWORD 1102 + diff --git a/CPP/7zip/UI/GUI/ExtractGUI.cpp b/CPP/7zip/UI/GUI/ExtractGUI.cpp new file mode 100755 index 0000000..e9846cc --- /dev/null +++ b/CPP/7zip/UI/GUI/ExtractGUI.cpp @@ -0,0 +1,205 @@ +// ExtractGUI.cpp + +#include "StdAfx.h" + +#include "Common/IntToString.h" +#include "Common/StringConvert.h" + +#include "Windows/Error.h" +#include "Windows/FileDir.h" +#include "Windows/FileFind.h" +#include "Windows/Thread.h" + +#include "../FileManager/ExtractCallback.h" +#include "../FileManager/FormatUtils.h" +#include "../FileManager/LangUtils.h" +#include "../FileManager/resourceGui.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" + +using namespace NWindows; + +static const wchar_t *kIncorrectOutDir = L"Incorrect output directory path"; + +#ifndef _SFX + +static void AddValuePair(UINT resourceID, UInt32 langID, UInt64 value, UString &s) +{ + wchar_t sz[32]; + s += LangString(resourceID, langID); + s += L' '; + ConvertUInt64ToString(value, sz); + s += sz; + s += L'\n'; +} + +static void AddSizePair(UINT resourceID, UInt32 langID, UInt64 value, UString &s) +{ + wchar_t sz[32]; + s += LangString(resourceID, langID); + s += L' '; + ConvertUInt64ToString(value, sz); + s += sz; + ConvertUInt64ToString(value >> 20, sz); + s += L" ("; + s += sz; + s += L" MB)"; + s += L'\n'; +} + +#endif + +class CThreadExtracting: public CProgressThreadVirt +{ + HRESULT ProcessVirt(); +public: + CCodecs *codecs; + CExtractCallbackImp *ExtractCallbackSpec; + CIntVector FormatIndices; + + UStringVector *ArchivePaths; + UStringVector *ArchivePathsFull; + const NWildcard::CCensorNode *WildcardCensor; + const CExtractOptions *Options; + CMyComPtr ExtractCallback; + UString Title; +}; + +HRESULT CThreadExtracting::ProcessVirt() +{ + CDecompressStat Stat; + HRESULT res = DecompressArchives(codecs, FormatIndices, *ArchivePaths, *ArchivePathsFull, + *WildcardCensor, *Options, ExtractCallbackSpec, ExtractCallback, ErrorMessage, Stat); + #ifndef _SFX + if (Options->TestMode && ExtractCallbackSpec->IsOK()) + { + UString s; + AddValuePair(IDS_ARCHIVES_COLON, 0x02000324, Stat.NumArchives, s); + AddValuePair(IDS_FOLDERS_COLON, 0x02000321, Stat.NumFolders, s); + AddValuePair(IDS_FILES_COLON, 0x02000320, Stat.NumFiles, s); + AddSizePair(IDS_SIZE_COLON, 0x02000322, Stat.UnpackSize, s); + AddSizePair(IDS_COMPRESSED_COLON, 0x02000323, Stat.PackSize, s); + + if (Options->CalcCrc) + { + wchar_t temp[16]; + ConvertUInt32ToHex(Stat.CrcSum, temp); + s += L"CRC: "; + s += temp; + s += L'\n'; + } + + s += L'\n'; + s += LangString(IDS_MESSAGE_NO_ERRORS, 0x02000608); + + OkMessageTitle = Title; + OkMessage = s; + } + #endif + return res; +} + +HRESULT ExtractGUI( + CCodecs *codecs, + const CIntVector &formatIndices, + UStringVector &archivePaths, + UStringVector &archivePathsFull, + const NWildcard::CCensorNode &wildcardCensor, + CExtractOptions &options, + bool showDialog, + bool &messageWasDisplayed, + CExtractCallbackImp *extractCallback, + HWND hwndParent) +{ + messageWasDisplayed = false; + + CThreadExtracting extracter; + extracter.codecs = codecs; + extracter.FormatIndices = formatIndices; + + if (!options.TestMode) + { + UString outputDir = options.OutputDir; + #ifndef UNDER_CE + if (outputDir.IsEmpty()) + NFile::NDirectory::MyGetCurrentDirectory(outputDir); + #endif + if (showDialog) + { + CExtractDialog dialog; + if (!NFile::NDirectory::MyGetFullPathName(outputDir, dialog.DirectoryPath)) + { + ShowErrorMessage(kIncorrectOutDir); + messageWasDisplayed = true; + return E_FAIL; + } + NFile::NName::NormalizeDirPathPrefix(dialog.DirectoryPath); + + // dialog.OverwriteMode = options.OverwriteMode; + // dialog.PathMode = options.PathMode; + + if (dialog.Create(hwndParent) != IDOK) + return E_ABORT; + outputDir = dialog.DirectoryPath; + options.OverwriteMode = dialog.OverwriteMode; + options.PathMode = dialog.PathMode; + #ifndef _SFX + extractCallback->Password = dialog.Password; + extractCallback->PasswordIsDefined = !dialog.Password.IsEmpty(); + #endif + } + if (!NFile::NDirectory::MyGetFullPathName(outputDir, options.OutputDir)) + { + ShowErrorMessage(kIncorrectOutDir); + messageWasDisplayed = true; + return E_FAIL; + } + NFile::NName::NormalizeDirPathPrefix(options.OutputDir); + + /* + if(!NFile::NDirectory::CreateComplexDirectory(options.OutputDir)) + { + UString s = GetUnicodeString(NError::MyFormatMessage(GetLastError())); + UString s2 = MyFormatNew(IDS_CANNOT_CREATE_FOLDER, + #ifdef LANG + 0x02000603, + #endif + options.OutputDir); + MyMessageBox(s2 + UString(L'\n') + s); + return E_FAIL; + } + */ + } + + UString title = LangStringSpec(options.TestMode ? IDS_PROGRESS_TESTING : IDS_PROGRESS_EXTRACTING, + options.TestMode ? 0x02000F90: 0x02000890); + + extracter.Title = title; + extracter.ExtractCallbackSpec = extractCallback; + extracter.ExtractCallbackSpec->ProgressDialog = &extracter.ProgressDialog; + extracter.ExtractCallback = extractCallback; + extracter.ExtractCallbackSpec->Init(); + + extracter.ProgressDialog.CompressingMode = false; + + extracter.ArchivePaths = &archivePaths; + extracter.ArchivePathsFull = &archivePathsFull; + extracter.WildcardCensor = &wildcardCensor; + extracter.Options = &options; + + extracter.ProgressDialog.IconID = IDI_ICON; + + RINOK(extracter.Create(title, hwndParent)); + messageWasDisplayed = extracter.ThreadFinishedOK & + extracter.ProgressDialog.MessagesDisplayed; + return extracter.Result; +} diff --git a/CPP/7zip/UI/GUI/ExtractGUI.h b/CPP/7zip/UI/GUI/ExtractGUI.h new file mode 100755 index 0000000..0c34cb0 --- /dev/null +++ b/CPP/7zip/UI/GUI/ExtractGUI.h @@ -0,0 +1,34 @@ +// 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 CIntVector &formatIndices, + UStringVector &archivePaths, + UStringVector &archivePathsFull, + const NWildcard::CCensorNode &wildcardCensor, + CExtractOptions &options, + bool showDialog, + bool &messageWasDisplayed, + CExtractCallbackImp *extractCallback, + HWND hwndParent = NULL); + +#endif diff --git a/CPP/7zip/UI/GUI/ExtractRes.h b/CPP/7zip/UI/GUI/ExtractRes.h new file mode 100755 index 0000000..3c287bb --- /dev/null +++ b/CPP/7zip/UI/GUI/ExtractRes.h @@ -0,0 +1,29 @@ +#define IDS_UPDATE_NOT_SUPPORTED 199 +#define IDS_CANNOT_CREATE_FOLDER 200 +#define IDS_OPEN_IS_NOT_SUPORTED_ARCHIVE 201 + +#define IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CRC 202 +#define IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_DATA_ERROR 203 +#define IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_UNSUPPORTED_METHOD 204 +#define IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CRC_ENCRYPTED 205 +#define IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED 206 + +#define IDS_EXTRACT_SET_FOLDER 207 +#define IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CANNOT_OPEN_FILE 208 +#define IDS_PROGRESS_EXTRACTING 209 + +#define IDS_CANT_OPEN_ARCHIVE 103 +#define IDS_CANT_OPEN_ENCRYPTED_ARCHIVE 104 +#define IDS_MEM_ERROR 105 +#define IDS_UNKNOWN_ERROR 106 +#define IDS_UNSUPPORTED_ARCHIVE_TYPE 107 + +#define IDC_EXTRACT_RADIO_FULL_PATHNAMES 1041 +#define IDC_EXTRACT_RADIO_CURRENT_PATHNAMES 1042 +#define IDC_EXTRACT_RADIO_NO_PATHNAMES 1043 + +#define IDC_EXTRACT_RADIO_ASK_BEFORE_OVERWRITE 1051 +#define IDC_EXTRACT_RADIO_OVERWRITE_WITHOUT_PROMPT 1052 +#define IDC_EXTRACT_RADIO_SKIP_EXISTING_FILES 1053 +#define IDC_EXTRACT_RADIO_AUTO_RENAME 1056 +#define IDC_EXTRACT_RADIO_AUTO_RENAME_EXISTING 1057 diff --git a/CPP/7zip/UI/GUI/FM.ico b/CPP/7zip/UI/GUI/FM.ico new file mode 100755 index 0000000000000000000000000000000000000000..3a0a34da6298bb0a61612a7d60facaf16df8c2c5 GIT binary patch literal 4846 zcmeI0y-Qp{5WvT1AwiO}v65h{v=bHrcEKW@U}J5n{TFOfTxA^y2-{gCAt}=M7hIJh zZmmtMED|J;vlCKGelz>t-Sd1zC7y-2@AhLpcINkH_aP`UA(OJO&=G4tABntR?sSU0 zG$HbAQeEha!6(cPO$2ypSJ!8gb3aVwPzg(C=HA#L+uY|F%&gVyqVC5=ekR++ESG{Av9ul;Wa)M4eeX&C+eew2nv&`1X_=Xsk=fZAq3f*id;VhoZl-d_DXvhd+ME+s|J}6zGwj=(&giT|gJm z1=I2J<`U6I77=|!AJN;kgg&892nl^c&mviVltdM=%Z!3M!|F zj1iUyON7N=8J0-$NTNv42#c2iV`LFwiLiKC;D~TUI3gSo4lflP5rzmuguzM|;fOFq z7&5t((Mw34@*sP8tvXPVJK^P}CU=4X@>rqz0LM8MX{ZCZ8XzaZrN{M>Y;#%#WK*8I}x71|pNt zuK+BWjTxtmBE!OuP8`l8!;-BY&SJO0P5~VZ3WLI+FenTPgI^~YG7JiX!jNGg3>|+M z6b6MsVIVXeJq!wi!k_>s`7^FKGQot??~`MLD}sJ!3X<2&wBUHb-XBA!bY*F=*Z+P$y9 z=pWH`d02*a`>6JA{fF7=6+HFQuJTYAk!q)=%dPo00#)%%?ncLUH?CthZ?cMngGd-;CSp~|a aDxai%qSuvsRtNqM^Dvh>T(@qcet!W-FyKr8 literal 0 HcmV?d00001 diff --git a/CPP/7zip/UI/GUI/GUI.cpp b/CPP/7zip/UI/GUI/GUI.cpp new file mode 100755 index 0000000..ba59ddf --- /dev/null +++ b/CPP/7zip/UI/GUI/GUI.cpp @@ -0,0 +1,283 @@ +// GUI.cpp + +#include "StdAfx.h" + +#include "Common/MyInitGuid.h" + +#include "../../../../C/Alloc.h" + +#include "Common/CommandLineParser.h" +#include "Common/MyException.h" +#include "Common/StringConvert.h" + +#include "Windows/Error.h" +#include "Windows/NtCheck.h" +#ifdef _WIN32 +#include "Windows/MemoryLock.h" +#endif + +#include "../Common/ArchiveCommandLine.h" +#include "../Common/ExitCode.h" + +#include "../FileManager/StringUtils.h" + +#include "BenchmarkDialog.h" +#include "ExtractGUI.h" +#include "UpdateGUI.h" + +#include "ExtractRes.h" + +using namespace NWindows; + +HINSTANCE g_hInstance; +#ifndef _UNICODE +#endif + +#ifdef UNDER_CE +bool g_LVN_ITEMACTIVATE_Support = true; +#endif + +static void ErrorMessage(LPCWSTR message) +{ + MessageBoxW(NULL, message, L"7-Zip", MB_ICONERROR | MB_OK); +} + +static void ErrorLangMessage(UINT resourceID, UInt32 langID) +{ + ErrorMessage(LangString(resourceID, langID)); +} + +static const char *kNoFormats = "7-Zip cannot find the code that works with archives."; + +static int ShowMemErrorMessage() +{ + ErrorLangMessage(IDS_MEM_ERROR, 0x0200060B); + return NExitCode::kMemoryError; +} + +static int ShowSysErrorMessage(DWORD errorCode) +{ + if (errorCode == E_OUTOFMEMORY) + return ShowMemErrorMessage(); + ErrorMessage(HResultToMessage(errorCode)); + return NExitCode::kFatalError; +} + +static int Main2() +{ + UStringVector commandStrings; + NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); + + #ifndef UNDER_CE + if (commandStrings.Size() > 0) + commandStrings.Delete(0); + #endif + if (commandStrings.Size() == 0) + { + MessageBoxW(0, L"Specify command", L"7-Zip", 0); + return 0; + } + + CArchiveCommandLineOptions options; + CArchiveCommandLineParser parser; + + parser.Parse1(commandStrings, options); + parser.Parse2(options); + + #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) + if (options.LargePages) + NSecurity::EnableLockMemoryPrivilege(); + #endif + + CCodecs *codecs = new CCodecs; + CMyComPtr compressCodecsInfo = codecs; + HRESULT result = codecs->Load(); + if (result != S_OK) + throw CSystemException(result); + + bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); + if (codecs->Formats.Size() == 0 && + (isExtractGroupCommand || + options.Command.IsFromUpdateGroup())) + throw kNoFormats; + + CIntVector formatIndices; + if (!codecs->FindFormatForArchiveType(options.ArcType, formatIndices)) + { + ErrorLangMessage(IDS_UNSUPPORTED_ARCHIVE_TYPE, 0x0200060D); + return NExitCode::kFatalError; + } + + if (options.Command.CommandType == NCommandType::kBenchmark) + { + HRESULT res; + #ifdef EXTERNAL_CODECS + CObjectVector externalCodecs; + res = LoadExternalCodecs(codecs, externalCodecs); + if (res != S_OK) + throw CSystemException(res); + #endif + res = Benchmark( + #ifdef EXTERNAL_CODECS + codecs, &externalCodecs, + #endif + options.NumThreads, options.DictionarySize); + if (res != S_OK) + throw CSystemException(res); + } + else if (isExtractGroupCommand) + { + CExtractCallbackImp *ecs = new CExtractCallbackImp; + CMyComPtr extractCallback = ecs; + + #ifndef _NO_CRYPTO + ecs->PasswordIsDefined = options.PasswordEnabled; + ecs->Password = options.Password; + #endif + + ecs->Init(); + + CExtractOptions eo; + eo.StdOutMode = options.StdOutMode; + eo.OutputDir = options.OutputDir; + eo.YesToAll = options.YesToAll; + eo.OverwriteMode = options.OverwriteMode; + eo.PathMode = options.Command.GetPathMode(); + eo.TestMode = options.Command.IsTestMode(); + eo.CalcCrc = options.CalcCrc; + #if !defined(_7ZIP_ST) && !defined(_SFX) + eo.Properties = options.ExtractProperties; + #endif + + bool messageWasDisplayed = false; + HRESULT result = ExtractGUI(codecs, formatIndices, + options.ArchivePathsSorted, + options.ArchivePathsFullSorted, + options.WildcardCensor.Pairs.Front().Head, + eo, options.ShowDialog, messageWasDisplayed, ecs); + if (result != S_OK) + { + if (result != E_ABORT && messageWasDisplayed) + return NExitCode::kFatalError; + throw CSystemException(result); + } + if (!ecs->IsOK()) + return NExitCode::kFatalError; + } + else if (options.Command.IsFromUpdateGroup()) + { + #ifndef _NO_CRYPTO + bool passwordIsDefined = options.PasswordEnabled && !options.Password.IsEmpty(); + #endif + + CUpdateCallbackGUI callback; + // callback.EnablePercents = options.EnablePercents; + + #ifndef _NO_CRYPTO + callback.PasswordIsDefined = passwordIsDefined; + callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty(); + callback.Password = options.Password; + #endif + + // callback.StdOutMode = options.UpdateOptions.StdOutMode; + callback.Init(); + + if (!options.UpdateOptions.Init(codecs, formatIndices, options.ArchiveName)) + { + ErrorLangMessage(IDS_UPDATE_NOT_SUPPORTED, 0x02000601); + return NExitCode::kFatalError; + } + bool messageWasDisplayed = false; + HRESULT result = UpdateGUI( + codecs, + options.WildcardCensor, options.UpdateOptions, + options.ShowDialog, + messageWasDisplayed, &callback); + + if (result != S_OK) + { + if (result != E_ABORT && messageWasDisplayed) + return NExitCode::kFatalError; + throw CSystemException(result); + } + if (callback.FailedFiles.Size() > 0) + { + if (!messageWasDisplayed) + throw CSystemException(E_FAIL); + return NExitCode::kWarning; + } + } + else + { + throw "Unsupported command"; + } + return 0; +} + +#define NT_CHECK_FAIL_ACTION ErrorMessage(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; + #ifdef _WIN32 + NT_CHECK + SetLargePageSize(); + #endif + + InitCommonControls(); + + ReloadLang(); + + // setlocale(LC_COLLATE, ".ACP"); + try + { + return Main2(); + } + catch(const CNewException &) + { + return ShowMemErrorMessage(); + } + catch(const CArchiveCommandLineException &e) + { + ErrorMessage(GetUnicodeString(e)); + return NExitCode::kUserError; + } + catch(const CSystemException &systemError) + { + if (systemError.ErrorCode == E_ABORT) + return NExitCode::kUserBreak; + return ShowSysErrorMessage(systemError.ErrorCode); + } + catch(const UString &s) + { + ErrorMessage(s); + return NExitCode::kFatalError; + } + catch(const AString &s) + { + ErrorMessage(GetUnicodeString(s)); + return NExitCode::kFatalError; + } + catch(const wchar_t *s) + { + ErrorMessage(s); + return NExitCode::kFatalError; + } + catch(const char *s) + { + ErrorMessage(GetUnicodeString(s)); + return NExitCode::kFatalError; + } + catch(...) + { + ErrorLangMessage(IDS_UNKNOWN_ERROR, 0x0200060C); + return NExitCode::kFatalError; + } +} + diff --git a/CPP/7zip/UI/GUI/GUI.dsp b/CPP/7zip/UI/GUI/GUI.dsp new file mode 100755 index 0000000..422b5d4 --- /dev/null +++ b/CPP/7zip/UI/GUI/GUI.dsp @@ -0,0 +1,1018 @@ +# Microsoft Developer Studio Project File - Name="GUI" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=GUI - 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 "GUI.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 "GUI.mak" CFG="GUI - Win32 DebugU" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "GUI - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "GUI - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE "GUI - Win32 ReleaseU" (based on "Win32 (x86) Application") +!MESSAGE "GUI - Win32 DebugU" (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)" == "GUI - 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" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# 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 comctl32.lib htmlhelp.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Program Files\7-Zip\7zg.exe" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "GUI - 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" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# 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 comctl32.lib htmlhelp.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Program Files\7-Zip\7zg.exe" /pdbtype:sept + +!ELSEIF "$(CFG)" == "GUI - 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 "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# 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\7zg.exe" +# 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 comctl32.lib htmlhelp.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Program Files\7-Zip\7zgn.exe" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "GUI - 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 /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# 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 /out:"C:\UTIL\7zg.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 comctl32.lib htmlhelp.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Program Files\7-Zip\7zgn.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "GUI - Win32 Release" +# Name "GUI - Win32 Debug" +# Name "GUI - Win32 ReleaseU" +# Name "GUI - Win32 DebugU" +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\7zG.exe.manifest +# End Source File +# Begin Source File + +SOURCE=.\FM.ico +# End Source File +# 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 "UI Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\Common\ArchiveCommandLine.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ArchiveCommandLine.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ArchiveExtractCallback.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ArchiveExtractCallback.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ArchiveOpenCallback.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ArchiveOpenCallback.h +# End Source File +# Begin Source File + +SOURCE=..\Common\Bench.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\Bench.h +# End Source File +# Begin Source File + +SOURCE=..\Common\DefaultName.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\DefaultName.h +# End Source File +# Begin Source File + +SOURCE=..\Common\DirItem.h +# End Source File +# Begin Source File + +SOURCE=..\Common\EnumDirItems.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\EnumDirItems.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ExitCode.h +# End Source File +# Begin Source File + +SOURCE=..\Common\Extract.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\Extract.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ExtractingFilePath.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ExtractingFilePath.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ExtractMode.h +# End Source File +# Begin Source File + +SOURCE=..\Common\HandlerLoader.h +# End Source File +# Begin Source File + +SOURCE=..\Common\IFileExtractCallback.h +# End Source File +# Begin Source File + +SOURCE=..\Common\LoadCodecs.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\LoadCodecs.h +# End Source File +# Begin Source File + +SOURCE=..\Common\OpenArchive.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\OpenArchive.h +# End Source File +# Begin Source File + +SOURCE=..\Common\Property.h +# End Source File +# Begin Source File + +SOURCE=..\Common\PropIDUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\PropIDUtils.h +# End Source File +# Begin Source File + +SOURCE=..\Common\SetProperties.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\SetProperties.h +# End Source File +# Begin Source File + +SOURCE=..\Common\SortUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\SortUtils.h +# End Source File +# Begin Source File + +SOURCE=..\Common\TempFiles.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\TempFiles.h +# End Source File +# Begin Source File + +SOURCE=..\Common\Update.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\Update.h +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdateAction.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdateAction.h +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdateCallback.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdateCallback.h +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdatePair.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdatePair.h +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdateProduce.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\UpdateProduce.h +# End Source File +# Begin Source File + +SOURCE=..\Common\WorkDir.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\WorkDir.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ZipRegistry.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ZipRegistry.h +# End Source File +# End Group +# Begin Group "Explorer" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\Explorer\MyMessages.cpp +# End Source File +# Begin Source File + +SOURCE=..\Explorer\MyMessages.h +# End Source File +# End Group +# Begin Group "Dialogs" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\BenchmarkDialog.cpp +# End Source File +# Begin Source File + +SOURCE=.\BenchmarkDialog.h +# End Source File +# Begin Source File + +SOURCE=.\CompressDialog.cpp +# End Source File +# Begin Source File + +SOURCE=.\CompressDialog.h +# End Source File +# Begin Source File + +SOURCE=.\ExtractDialog.cpp +# End Source File +# Begin Source File + +SOURCE=.\ExtractDialog.h +# End Source File +# Begin Source File + +SOURCE=..\FileManager\OverwriteDialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\FileManager\OverwriteDialog.h +# End Source File +# Begin Source File + +SOURCE=..\FileManager\PasswordDialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\FileManager\PasswordDialog.h +# End Source File +# Begin Source File + +SOURCE=..\FileManager\ProgressDialog2.cpp +# End Source File +# Begin Source File + +SOURCE=..\FileManager\ProgressDialog2.h +# End Source File +# End Group +# Begin Group "FM Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\FileManager\ExtractCallback.cpp +# End Source File +# Begin Source File + +SOURCE=..\FileManager\ExtractCallback.h +# End Source File +# Begin Source File + +SOURCE=..\FileManager\FolderInterface.h +# End Source File +# Begin Source File + +SOURCE=..\FileManager\FormatUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\FileManager\FormatUtils.h +# End Source File +# Begin Source File + +SOURCE=..\FileManager\HelpUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\FileManager\HelpUtils.h +# End Source File +# Begin Source File + +SOURCE=..\FileManager\LangUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\FileManager\LangUtils.h +# End Source File +# Begin Source File + +SOURCE=..\FileManager\OpenCallback.cpp +# End Source File +# Begin Source File + +SOURCE=..\FileManager\OpenCallback.h +# End Source File +# Begin Source File + +SOURCE=..\FileManager\ProgramLocation.cpp +# End Source File +# Begin Source File + +SOURCE=..\FileManager\ProgramLocation.h +# End Source File +# Begin Source File + +SOURCE=..\FileManager\RegistryUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\FileManager\RegistryUtils.h +# End Source File +# Begin Source File + +SOURCE=..\FileManager\SplitUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\FileManager\SplitUtils.h +# End Source File +# Begin Source File + +SOURCE=..\FileManager\StringUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\FileManager\StringUtils.h +# End Source File +# End Group +# Begin Group "Engine" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\ExtractGUI.cpp +# End Source File +# Begin Source File + +SOURCE=.\ExtractGUI.h +# End Source File +# Begin Source File + +SOURCE=.\GUI.cpp +# End Source File +# Begin Source File + +SOURCE=.\UpdateCallbackGUI.cpp +# End Source File +# Begin Source File + +SOURCE=.\UpdateCallbackGUI.h +# End Source File +# Begin Source File + +SOURCE=.\UpdateGUI.cpp +# End Source File +# Begin Source File + +SOURCE=.\UpdateGUI.h +# End Source File +# End Group +# Begin Group "7-zip 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\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\ProgressUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File +# End Group +# Begin Group "Compress" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\CopyCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\CopyCoder.h +# End Source File +# End Group +# Begin Group "C" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\..\C\7zCrc.c + +!IF "$(CFG)" == "GUI - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "GUI - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "GUI - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "GUI - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\7zCrc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\7zCrcOpt.c + +!IF "$(CFG)" == "GUI - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "GUI - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "GUI - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "GUI - 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\CpuArch.c + +!IF "$(CFG)" == "GUI - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "GUI - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "GUI - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "GUI - 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\Threads.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Threads.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\IntToString.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\IntToString.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Lang.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Lang.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\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\StringToInt.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringToInt.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\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\Edit.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 +# Begin Source File + +SOURCE=..\..\..\Windows\Control\ProgressBar.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\Static.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\..\Windows\COM.h +# End Source File +# 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\Error.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Error.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\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\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\PropVariantConversions.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariantConversions.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Registry.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Registry.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\ResourceString.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\ResourceString.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\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\Time.cpp +# 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 "Archive Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\OutStreamWithCRC.h +# End Source File +# End Group +# End Target +# End Project diff --git a/CPP/7zip/UI/GUI/GUI.dsw b/CPP/7zip/UI/GUI/GUI.dsw new file mode 100755 index 0000000..465622e --- /dev/null +++ b/CPP/7zip/UI/GUI/GUI.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "GUI"=.\GUI.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/CPP/7zip/UI/GUI/StdAfx.cpp b/CPP/7zip/UI/GUI/StdAfx.cpp new file mode 100755 index 0000000..c6d3b1f --- /dev/null +++ b/CPP/7zip/UI/GUI/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/UI/GUI/StdAfx.h b/CPP/7zip/UI/GUI/StdAfx.h new file mode 100755 index 0000000..2dbbc04 --- /dev/null +++ b/CPP/7zip/UI/GUI/StdAfx.h @@ -0,0 +1,13 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include +#include +#include +#include + +#include "Common/NewHandler.h" + +#endif diff --git a/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp b/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp new file mode 100755 index 0000000..25a3c4f --- /dev/null +++ b/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp @@ -0,0 +1,228 @@ +// UpdateCallbackGUI.cpp + +#include "StdAfx.h" + +#include "Common/IntToString.h" +#include "Common/StringConvert.h" + +#include "Windows/Error.h" +#include "Windows/PropVariant.h" + +#include "../FileManager/PasswordDialog.h" + +#include "UpdateCallbackGUI.h" + +using namespace NWindows; + +CUpdateCallbackGUI::~CUpdateCallbackGUI() {} + +void CUpdateCallbackGUI::Init() +{ + FailedFiles.Clear(); + NumFiles = 0; +} + +void CUpdateCallbackGUI::AddErrorMessage(LPCWSTR message) +{ + ProgressDialog->Sync.AddErrorMessage(message); +} + +void CUpdateCallbackGUI::AddErrorMessage(const wchar_t *name, DWORD systemError) +{ + AddErrorMessage( + UString(L"WARNING: ") + + NError::MyFormatMessageW(systemError) + + UString(L": ") + + UString(name)); +} + +HRESULT CUpdateCallbackGUI::OpenResult(const wchar_t *name, HRESULT result) +{ + if (result != S_OK) + { + AddErrorMessage (UString(L"Error: ") + name + UString(L" is not supported archive")); + } + return S_OK; +} + +HRESULT CUpdateCallbackGUI::StartScanning() +{ + return S_OK; +} + +HRESULT CUpdateCallbackGUI::CanNotFindError(const wchar_t *name, DWORD systemError) +{ + FailedFiles.Add(name); + AddErrorMessage(name, systemError); + return S_OK; +} + +HRESULT CUpdateCallbackGUI::FinishScanning() +{ + return S_OK; +} + +HRESULT CUpdateCallbackGUI::StartArchive(const wchar_t *name, bool /* updating */) +{ + ProgressDialog->Sync.SetTitleFileName(name); + return S_OK; +} + +HRESULT CUpdateCallbackGUI::FinishArchive() +{ + return S_OK; +} + +HRESULT CUpdateCallbackGUI::CheckBreak() +{ + return ProgressDialog->Sync.ProcessStopAndPause(); +} + +HRESULT CUpdateCallbackGUI::ScanProgress(UInt64 /* numFolders */, UInt64 numFiles, const wchar_t *path) +{ + ProgressDialog->Sync.SetCurrentFileName(path); + ProgressDialog->Sync.SetNumFilesTotal(numFiles); + return ProgressDialog->Sync.ProcessStopAndPause(); +} + +HRESULT CUpdateCallbackGUI::Finilize() +{ + return S_OK; +} + +HRESULT CUpdateCallbackGUI::SetNumFiles(UInt64 numFiles) +{ + ProgressDialog->Sync.SetNumFilesTotal(numFiles); + return S_OK; +} + +HRESULT CUpdateCallbackGUI::SetTotal(UInt64 total) +{ + ProgressDialog->Sync.SetProgress(total, 0); + return S_OK; +} + +HRESULT CUpdateCallbackGUI::SetCompleted(const UInt64 *completeValue) +{ + RINOK(CheckBreak()); + if (completeValue != NULL) + ProgressDialog->Sync.SetPos(*completeValue); + return S_OK; +} + +HRESULT CUpdateCallbackGUI::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) +{ + RINOK(CheckBreak()); + ProgressDialog->Sync.SetRatioInfo(inSize, outSize); + return S_OK; +} + +HRESULT CUpdateCallbackGUI::GetStream(const wchar_t *name, bool /* isAnti */) +{ + ProgressDialog->Sync.SetCurrentFileName(name); + return S_OK; +} + +HRESULT CUpdateCallbackGUI::OpenFileError(const wchar_t *name, DWORD systemError) +{ + FailedFiles.Add(name); + // if (systemError == ERROR_SHARING_VIOLATION) + { + AddErrorMessage(name, systemError); + return S_FALSE; + } + // return systemError; +} + +HRESULT CUpdateCallbackGUI::SetOperationResult(Int32 /* operationResult */) +{ + NumFiles++; + ProgressDialog->Sync.SetNumFilesCur(NumFiles); + return S_OK; +} + +HRESULT CUpdateCallbackGUI::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) +{ + *password = NULL; + if (!PasswordIsDefined) + { + if (passwordIsDefined == 0 || AskPassword) + { + CPasswordDialog dialog; + ProgressDialog->WaitCreating(); + if (dialog.Create(*ProgressDialog) == IDCANCEL) + return E_ABORT; + Password = dialog.Password; + PasswordIsDefined = true; + } + } + if (passwordIsDefined != 0) + *passwordIsDefined = BoolToInt(PasswordIsDefined); + return StringToBstr(Password, password); +} + +HRESULT CUpdateCallbackGUI::CryptoGetTextPassword(BSTR *password) +{ + return CryptoGetTextPassword2(NULL, password); +} + +/* +It doesn't work, since main stream waits Dialog +HRESULT CUpdateCallbackGUI::CloseProgress() +{ + ProgressDialog->MyClose(); + return S_OK; +} +*/ + + +HRESULT CUpdateCallbackGUI::Open_CheckBreak() +{ + return ProgressDialog->Sync.ProcessStopAndPause(); +} + +HRESULT CUpdateCallbackGUI::Open_SetTotal(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */) +{ + // if (numFiles != NULL) ProgressDialog->Sync.SetNumFilesTotal(*numFiles); + return S_OK; +} + +HRESULT CUpdateCallbackGUI::Open_SetCompleted(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */) +{ + return ProgressDialog->Sync.ProcessStopAndPause(); +} + +#ifndef _NO_CRYPTO + +HRESULT CUpdateCallbackGUI::Open_CryptoGetTextPassword(BSTR *password) +{ + PasswordWasAsked = true; + return CryptoGetTextPassword2(NULL, password); +} + +HRESULT CUpdateCallbackGUI::Open_GetPasswordIfAny(UString &password) +{ + if (PasswordIsDefined) + password = Password; + return S_OK; +} + +bool CUpdateCallbackGUI::Open_WasPasswordAsked() +{ + return PasswordWasAsked; +} + +void CUpdateCallbackGUI::Open_ClearPasswordWasAskedFlag() +{ + PasswordWasAsked = false; +} + +/* +HRESULT CUpdateCallbackGUI::ShowDeleteFile(const wchar_t *name) +{ + ProgressDialog->Sync.SetCurrentFileName(name); + return S_OK; +} +*/ + +#endif diff --git a/CPP/7zip/UI/GUI/UpdateCallbackGUI.h b/CPP/7zip/UI/GUI/UpdateCallbackGUI.h new file mode 100755 index 0000000..ea243d6 --- /dev/null +++ b/CPP/7zip/UI/GUI/UpdateCallbackGUI.h @@ -0,0 +1,41 @@ +// UpdateCallbackGUI.h + +#ifndef __UPDATE_CALLBACK_GUI_H +#define __UPDATE_CALLBACK_GUI_H + +#include "../Common/Update.h" +#include "../Common/ArchiveOpenCallback.h" +#include "../FileManager/ProgressDialog2.h" + +class CUpdateCallbackGUI: + public IOpenCallbackUI, + public IUpdateCallbackUI2 +{ +public: + bool PasswordIsDefined; + UString Password; + bool AskPassword; + bool PasswordWasAsked; + UInt64 NumFiles; + + CUpdateCallbackGUI(): + PasswordIsDefined(false), + PasswordWasAsked(false), + AskPassword(false) + {} + + ~CUpdateCallbackGUI(); + void Init(); + + INTERFACE_IUpdateCallbackUI2(;) + INTERFACE_IOpenCallbackUI(;) + + UStringVector FailedFiles; + + CProgressDialog *ProgressDialog; + + void AddErrorMessage(LPCWSTR message); + void AddErrorMessage(const wchar_t *name, DWORD systemError); +}; + +#endif diff --git a/CPP/7zip/UI/GUI/UpdateGUI.cpp b/CPP/7zip/UI/GUI/UpdateGUI.cpp new file mode 100755 index 0000000..c0eb45a --- /dev/null +++ b/CPP/7zip/UI/GUI/UpdateGUI.cpp @@ -0,0 +1,399 @@ +// UpdateGUI.cpp + +#include "StdAfx.h" + +#include "UpdateGUI.h" + +#include "Common/IntToString.h" +#include "Common/StringConvert.h" +#include "Common/StringToInt.h" + +#include "Windows/Error.h" +#include "Windows/FileDir.h" +#include "Windows/Thread.h" + +#include "../Common/WorkDir.h" + +#include "../Explorer/MyMessages.h" + +#include "../FileManager/LangUtils.h" +#include "../FileManager/ProgramLocation.h" +#include "../FileManager/StringUtils.h" +#include "../FileManager/resourceGui.h" + +#include "CompressDialog.h" +#include "UpdateGUI.h" + +#include "resource2.h" + +using namespace NWindows; +using namespace NFile; + +static const wchar_t *kDefaultSfxModule = L"7z.sfx"; +static const wchar_t *kSFXExtension = L"exe"; + +extern void AddMessageToString(UString &dest, const UString &src); + +UString HResultToMessage(HRESULT errorCode); + +class CThreadUpdating: public CProgressThreadVirt +{ + HRESULT ProcessVirt(); +public: + CCodecs *codecs; + CUpdateCallbackGUI *UpdateCallbackGUI; + const NWildcard::CCensor *WildcardCensor; + CUpdateOptions *Options; +}; + +HRESULT CThreadUpdating::ProcessVirt() +{ + CUpdateErrorInfo ei; + HRESULT res = UpdateArchive(codecs, *WildcardCensor, *Options, + ei, UpdateCallbackGUI, UpdateCallbackGUI); + ErrorMessage = ei.Message; + ErrorPath1 = ei.FileName; + ErrorPath2 = ei.FileName2; + if (ei.SystemError != S_OK && ei.SystemError != E_FAIL && ei.SystemError != E_ABORT) + return ei.SystemError; + return res; +} + +static void AddProp(CObjectVector &properties, const UString &name, const UString &value) +{ + CProperty prop; + prop.Name = name; + prop.Value = value; + properties.Add(prop); +} + +static void AddProp(CObjectVector &properties, const UString &name, UInt32 value) +{ + wchar_t tmp[32]; + ConvertUInt64ToString(value, tmp); + AddProp(properties, name, tmp); +} + +static void AddProp(CObjectVector &properties, const UString &name, bool value) +{ + AddProp(properties, name, value ? UString(L"on"): UString(L"off")); +} + +static bool IsThereMethodOverride(bool is7z, const UString &propertiesString) +{ + UStringVector strings; + SplitString(propertiesString, strings); + for (int i = 0; i < strings.Size(); i++) + { + const UString &s = strings[i]; + if (is7z) + { + const wchar_t *end; + UInt64 n = ConvertStringToUInt64(s, &end); + if (n == 0 && *end == L'=') + return true; + } + else + { + if (s.Length() > 0) + if (s[0] == L'm' && s[1] == L'=') + return true; + } + } + return false; +} + +static void ParseAndAddPropertires(CObjectVector &properties, + const UString &propertiesString) +{ + UStringVector strings; + SplitString(propertiesString, strings); + for (int i = 0; i < strings.Size(); i++) + { + const UString &s = strings[i]; + CProperty property; + int index = s.Find(L'='); + if (index < 0) + property.Name = s; + else + { + property.Name = s.Left(index); + property.Value = s.Mid(index + 1); + } + properties.Add(property); + } +} + +static UString GetNumInBytesString(UInt64 v) +{ + wchar_t s[32]; + ConvertUInt64ToString(v, s); + size_t len = wcslen(s); + s[len++] = L'B'; + s[len] = L'\0'; + return s; +} + +static void SetOutProperties( + CObjectVector &properties, + bool is7z, + UInt32 level, + bool setMethod, + const UString &method, + UInt32 dictionary, + bool orderMode, + UInt32 order, + bool solidIsSpecified, UInt64 solidBlockSize, + bool multiThreadIsAllowed, UInt32 numThreads, + const UString &encryptionMethod, + bool encryptHeadersIsAllowed, bool encryptHeaders, + bool /* sfxMode */) +{ + if (level != (UInt32)(Int32)-1) + AddProp(properties, L"x", (UInt32)level); + if (setMethod) + { + if (!method.IsEmpty()) + AddProp(properties, is7z ? L"0": L"m", method); + if (dictionary != (UInt32)(Int32)-1) + { + UString name; + if (is7z) + name = L"0"; + if (orderMode) + name += L"mem"; + else + name += L"d"; + AddProp(properties, name, GetNumInBytesString(dictionary)); + } + if (order != (UInt32)(Int32)-1) + { + UString name; + if (is7z) + name = L"0"; + if (orderMode) + name += L"o"; + else + name += L"fb"; + AddProp(properties, name, (UInt32)order); + } + } + + if (!encryptionMethod.IsEmpty()) + AddProp(properties, L"em", encryptionMethod); + + if (encryptHeadersIsAllowed) + AddProp(properties, L"he", encryptHeaders); + if (solidIsSpecified) + AddProp(properties, L"s", GetNumInBytesString(solidBlockSize)); + if (multiThreadIsAllowed) + AddProp(properties, L"mt", numThreads); +} + +static HRESULT ShowDialog( + CCodecs *codecs, + const NWildcard::CCensor &censor, + CUpdateOptions &options, CUpdateCallbackGUI *callback, HWND hwndParent) +{ + if (options.Commands.Size() != 1) + throw "It must be one command"; + UString currentDirPrefix; + #ifndef UNDER_CE + { + if (!NDirectory::MyGetCurrentDirectory(currentDirPrefix)) + return E_FAIL; + NName::NormalizeDirPathPrefix(currentDirPrefix); + } + #endif + + bool oneFile = false; + NFind::CFileInfoW fileInfo; + UString name; + if (censor.Pairs.Size() > 0) + { + const NWildcard::CPair &pair = censor.Pairs[0]; + if (pair.Head.IncludeItems.Size() > 0) + { + const NWildcard::CItem &item = pair.Head.IncludeItems[0]; + if (item.ForFile) + { + name = pair.Prefix; + for (int i = 0; i < item.PathParts.Size(); i++) + { + if (i > 0) + name += WCHAR_PATH_SEPARATOR; + name += item.PathParts[i]; + } + if (fileInfo.Find(name)) + { + if (censor.Pairs.Size() == 1 && pair.Head.IncludeItems.Size() == 1) + oneFile = !fileInfo.IsDir(); + } + } + } + } + + CCompressDialog dialog; + NCompressDialog::CInfo &di = dialog.Info; + dialog.ArcFormats = &codecs->Formats; + for (int i = 0; i < codecs->Formats.Size(); i++) + { + const CArcInfoEx &ai = codecs->Formats[i]; + if (ai.Name.CompareNoCase(L"swfc") == 0) + if (!oneFile || name.Right(4).CompareNoCase(L".swf") != 0) + continue; + if (ai.UpdateEnabled && (oneFile || !ai.KeepName)) + dialog.ArcIndices.Add(i); + } + if (dialog.ArcIndices.Size() == 0) + { + ShowErrorMessage(L"No Update Engines"); + return E_FAIL; + } + + // di.ArchiveName = options.ArchivePath.GetFinalPath(); + di.ArchiveName = options.ArchivePath.GetPathWithoutExt(); + dialog.OriginalFileName = options.ArchivePath.Prefix + fileInfo.Name; + + di.CurrentDirPrefix = currentDirPrefix; + di.SFXMode = options.SfxMode; + di.OpenShareForWrite = options.OpenShareForWrite; + + if (callback->PasswordIsDefined) + di.Password = callback->Password; + + di.KeepName = !oneFile; + + if (dialog.Create(hwndParent) != IDOK) + return E_ABORT; + + options.VolumesSizes = di.VolumeSizes; + /* + if (di.VolumeSizeIsDefined) + { + MyMessageBox(L"Splitting to volumes is not supported"); + return E_FAIL; + } + */ + + NUpdateArchive::CActionSet &actionSet = options.Commands.Front().ActionSet; + + switch(di.UpdateMode) + { + case NCompressDialog::NUpdateMode::kAdd: + actionSet = NUpdateArchive::kAddActionSet; + break; + case NCompressDialog::NUpdateMode::kUpdate: + actionSet = NUpdateArchive::kUpdateActionSet; + break; + case NCompressDialog::NUpdateMode::kFresh: + actionSet = NUpdateArchive::kFreshActionSet; + break; + case NCompressDialog::NUpdateMode::kSynchronize: + actionSet = NUpdateArchive::kSynchronizeActionSet; + break; + default: + throw 1091756; + } + const CArcInfoEx &archiverInfo = codecs->Formats[di.FormatIndex]; + callback->PasswordIsDefined = (!di.Password.IsEmpty()); + if (callback->PasswordIsDefined) + callback->Password = di.Password; + + options.MethodMode.Properties.Clear(); + + bool is7z = archiverInfo.Name.CompareNoCase(L"7z") == 0; + bool methodOverride = IsThereMethodOverride(is7z, di.Options); + + SetOutProperties( + options.MethodMode.Properties, + is7z, + di.Level, + !methodOverride, + di.Method, + di.Dictionary, + di.OrderMode, di.Order, + di.SolidIsSpecified, di.SolidBlockSize, + di.MultiThreadIsAllowed, di.NumThreads, + di.EncryptionMethod, + di.EncryptHeadersIsAllowed, di.EncryptHeaders, + di.SFXMode); + + options.OpenShareForWrite = di.OpenShareForWrite; + ParseAndAddPropertires(options.MethodMode.Properties, di.Options); + + if (di.SFXMode) + options.SfxMode = true; + options.MethodMode.FormatIndex = di.FormatIndex; + + options.ArchivePath.VolExtension = archiverInfo.GetMainExt(); + if (di.SFXMode) + options.ArchivePath.BaseExtension = kSFXExtension; + else + options.ArchivePath.BaseExtension = options.ArchivePath.VolExtension; + options.ArchivePath.ParseFromPath(di.ArchiveName); + + NWorkDir::CInfo workDirInfo; + workDirInfo.Load(); + options.WorkingDir.Empty(); + if (workDirInfo.Mode != NWorkDir::NMode::kCurrent) + { + UString fullPath; + NDirectory::MyGetFullPathName(di.ArchiveName, fullPath); + options.WorkingDir = GetWorkDir(workDirInfo, fullPath); + NDirectory::CreateComplexDirectory(options.WorkingDir); + } + return S_OK; +} + +HRESULT UpdateGUI( + CCodecs *codecs, + const NWildcard::CCensor &censor, + CUpdateOptions &options, + bool showDialog, + bool &messageWasDisplayed, + CUpdateCallbackGUI *callback, + HWND hwndParent) +{ + messageWasDisplayed = false; + if (showDialog) + { + RINOK(ShowDialog(codecs, censor, options, callback, hwndParent)); + } + if (options.SfxMode && options.SfxModule.IsEmpty()) + { + UString folder; + if (!GetProgramFolderPath(folder)) + folder.Empty(); + options.SfxModule = folder + kDefaultSfxModule; + } + + CThreadUpdating tu; + + tu.codecs = codecs; + + tu.UpdateCallbackGUI = callback; + tu.UpdateCallbackGUI->ProgressDialog = &tu.ProgressDialog; + tu.UpdateCallbackGUI->Init(); + + UString title = LangString(IDS_PROGRESS_COMPRESSING, 0x02000DC0); + + /* + if (hwndParent != 0) + { + tu.ProgressDialog.MainWindow = hwndParent; + // tu.ProgressDialog.MainTitle = fileName; + tu.ProgressDialog.MainAddTitle = title + L" "; + } + */ + + tu.WildcardCensor = &censor; + tu.Options = &options; + tu.ProgressDialog.IconID = IDI_ICON; + + RINOK(tu.Create(title, hwndParent)); + + messageWasDisplayed = tu.ThreadFinishedOK & + tu.ProgressDialog.MessagesDisplayed; + return tu.Result; +} diff --git a/CPP/7zip/UI/GUI/UpdateGUI.h b/CPP/7zip/UI/GUI/UpdateGUI.h new file mode 100755 index 0000000..12e55a4 --- /dev/null +++ b/CPP/7zip/UI/GUI/UpdateGUI.h @@ -0,0 +1,31 @@ +// GUI/UpdateGUI.h + +#ifndef __UPDATE_GUI_H +#define __UPDATE_GUI_H + +#include "../Common/Update.h" + +#include "UpdateCallbackGUI.h" + +/* + callback->FailedFiles contains names of files for that there were problems. + RESULT can be S_OK, even if there are such warnings!!! + + 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 UpdateGUI( + CCodecs *codecs, + const NWildcard::CCensor &censor, + CUpdateOptions &options, + bool showDialog, + bool &messageWasDisplayed, + CUpdateCallbackGUI *callback, + HWND hwndParent = NULL); + +#endif diff --git a/CPP/7zip/UI/GUI/makefile b/CPP/7zip/UI/GUI/makefile new file mode 100755 index 0000000..bc3c083 --- /dev/null +++ b/CPP/7zip/UI/GUI/makefile @@ -0,0 +1,165 @@ +PROG = 7zG.exe +CFLAGS = $(CFLAGS) -I ../../../ \ + -DLANG \ + -DEXTERNAL_CODECS \ + +!IFDEF UNDER_CE +LIBS = $(LIBS) ceshell.lib Commctrl.lib +!ELSE +LIBS = $(LIBS) comctl32.lib htmlhelp.lib comdlg32.lib +CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -DSUPPORT_DEVICE_FILE -D_7ZIP_LARGE_PAGES +!ENDIF + +GUI_OBJS = \ + $O\BenchmarkDialog.obj \ + $O\CompressDialog.obj \ + $O\ExtractDialog.obj \ + $O\ExtractGUI.obj \ + $O\GUI.obj \ + $O\UpdateCallbackGUI.obj \ + $O\UpdateGUI.obj \ + +COMMON_OBJS = \ + $O\CommandLineParser.obj \ + $O\CRC.obj \ + $O\IntToString.obj \ + $O\Lang.obj \ + $O\ListFileUtils.obj \ + $O\MyString.obj \ + $O\MyVector.obj \ + $O\NewHandler.obj \ + $O\StringConvert.obj \ + $O\StringToInt.obj \ + $O\TextConfig.obj \ + $O\UTFConvert.obj \ + $O\Wildcard.obj \ + +WIN_OBJS = \ + $O\CommonDialog.obj \ + $O\DLL.obj \ + $O\Error.obj \ + $O\FileDir.obj \ + $O\FileFind.obj \ + $O\FileIO.obj \ + $O\FileName.obj \ + $O\MemoryLock.obj \ + $O\PropVariant.obj \ + $O\PropVariantConversions.obj \ + $O\Registry.obj \ + $O\ResourceString.obj \ + $O\Shell.obj \ + $O\Synchronization.obj \ + $O\System.obj \ + $O\Time.obj \ + $O\Window.obj \ + +WIN_CTRL_OBJS = \ + $O\ComboBox.obj \ + $O\Dialog.obj \ + $O\ListView.obj \ + +7ZIP_COMMON_OBJS = \ + $O\CreateCoder.obj \ + $O\FilePathAutoRename.obj \ + $O\FileStreams.obj \ + $O\FilterCoder.obj \ + $O\ProgressUtils.obj \ + $O\StreamUtils.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\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 \ + $O\WorkDir.obj \ + $O\ZipRegistry.obj \ + +AR_COMMON_OBJS = \ + $O\OutStreamWithCRC.obj \ + +FM_OBJS = \ + $O\ExtractCallback.obj \ + $O\FormatUtils.obj \ + $O\HelpUtils.obj \ + $O\LangUtils.obj \ + $O\OpenCallback.obj \ + $O\ProgramLocation.obj \ + $O\RegistryUtils.obj \ + $O\SplitUtils.obj \ + $O\StringUtils.obj \ + $O\OverwriteDialog.obj \ + $O\PasswordDialog.obj \ + $O\ProgressDialog2.obj \ + +!IFDEF UNDER_CE +FM_OBJS = $(FM_OBJS) \ + $O\BrowseDialog.obj \ + $O\SysIconUtils.obj \ +!ENDIF + +C_OBJS = \ + $O\Alloc.obj \ + $O\CpuArch.obj \ + $O\Threads.obj \ + +!include "../../Crc.mak" + +OBJS = \ + $O\StdAfx.obj \ + $(GUI_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(WIN_CTRL_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(UI_COMMON_OBJS) \ + $(AR_COMMON_OBJS) \ + $(FM_OBJS)\ + $O\MyMessages.obj \ + $O\CopyCoder.obj \ + $(LZMA_BENCH_OBJS) \ + $(C_OBJS) \ + $(ASM_OBJS) \ + $O\resource.res + +!include "../../../Build.mak" + +$(GUI_OBJS): $(*B).cpp + $(COMPL) +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +$(WIN_CTRL_OBJS): ../../../Windows/Control/$(*B).cpp + $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) +$(UI_COMMON_OBJS): ../Common/$(*B).cpp + $(COMPL) +$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp + $(COMPL) +$(FM_OBJS): ../FileManager/$(*B).cpp + $(COMPL) +$O\MyMessages.obj: ../Explorer/MyMessages.cpp + $(COMPL) + +$O\CopyCoder.obj: ../../Compress/$(*B).cpp + $(COMPL) +$(C_OBJS): ../../../../C/$(*B).c + $(COMPL_O2) + +!include "../../Asm.mak" diff --git a/CPP/7zip/UI/GUI/resource.rc b/CPP/7zip/UI/GUI/resource.rc new file mode 100755 index 0000000..966b1cf --- /dev/null +++ b/CPP/7zip/UI/GUI/resource.rc @@ -0,0 +1,21 @@ +#include "../../MyVersionInfo.rc" +#include + +#include "resource2.rc" +#include "../FileManager/resourceGui.rc" + +MY_VERSION_INFO_APP("7-Zip GUI", "7zg") + +IDI_ICON ICON "FM.ico" + +#ifndef UNDER_CE +1 24 MOVEABLE PURE "7zG.exe.manifest" +#endif + +#ifdef UNDER_CE +#include "../FileManager/PropertyName.rc" +#endif +#include "../FileManager/OverwriteDialog.rc" +#include "../FileManager/PasswordDialog.rc" +#include "../FileManager/ProgressDialog2.rc" +#include "Extract.rc" diff --git a/CPP/7zip/UI/GUI/resource2.h b/CPP/7zip/UI/GUI/resource2.h new file mode 100755 index 0000000..b9330af --- /dev/null +++ b/CPP/7zip/UI/GUI/resource2.h @@ -0,0 +1,3 @@ +#define IDS_COMPRESSED_COLON 2277 +#define IDS_ARCHIVES_COLON 2278 +#define IDS_PROGRESS_COMPRESSING 98 diff --git a/CPP/7zip/UI/GUI/resource2.rc b/CPP/7zip/UI/GUI/resource2.rc new file mode 100755 index 0000000..58b309b --- /dev/null +++ b/CPP/7zip/UI/GUI/resource2.rc @@ -0,0 +1,11 @@ +#include "ExtractDialog.rc" +#include "CompressDialog.rc" +#include "BenchmarkDialog.rc" +#include "resource2.h" + +STRINGTABLE +BEGIN + IDS_COMPRESSED_COLON "Compressed size:" + IDS_ARCHIVES_COLON "Archives:" + IDS_PROGRESS_COMPRESSING "Compressing" +END diff --git a/CPP/7zip/UI/makefile b/CPP/7zip/UI/makefile new file mode 100755 index 0000000..9d51814 --- /dev/null +++ b/CPP/7zip/UI/makefile @@ -0,0 +1,12 @@ +DIRS = \ + Client7z\~ \ + Console\~ \ + Explorer\~ \ + Far\~ \ + FileManager\~ \ + GUI\~ \ + +all: $(DIRS) + +$(DIRS): +!include "../SubBuild.mak" diff --git a/CPP/7zip/makefile b/CPP/7zip/makefile new file mode 100755 index 0000000..422d2d2 --- /dev/null +++ b/CPP/7zip/makefile @@ -0,0 +1,10 @@ +DIRS = \ + UI\~ \ + Bundles\~ \ + +all: $(DIRS) + +$(DIRS): + cd $(@D) + $(MAKE) -nologo + cd .. diff --git a/CPP/Build.mak b/CPP/Build.mak new file mode 100755 index 0000000..81ac79d --- /dev/null +++ b/CPP/Build.mak @@ -0,0 +1,94 @@ +LIBS = $(LIBS) oleaut32.lib ole32.lib + +!IFDEF CPU +!IFNDEF NO_BUFFEROVERFLOWU +LIBS = $(LIBS) bufferoverflowU.lib +!ENDIF +!ENDIF + + +!IFNDEF O +!IFDEF CPU +O=$(CPU) +!ELSE +O=O +!ENDIF +!ENDIF + +!IF "$(CPU)" == "AMD64" +MY_ML = ml64 -Dx64 +!ELSEIF "$(CPU)" == "ARM" +MY_ML = armasm +!ELSE +MY_ML = ml +!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 +CFLAGS = $(CFLAGS) -Gr +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/ -WX -EHsc -Gy -GR- + +!IFDEF MY_STATIC_LINK +!IFNDEF MY_SINGLE_THREAD +CFLAGS = $(CFLAGS) -MT +!ENDIF +!ELSE +CFLAGS = $(CFLAGS) -MD +!ENDIF + +!IFDEF NEW_COMPILER +CFLAGS = $(CFLAGS) -W4 -GS- -Zc:forScope +!ELSE +CFLAGS = $(CFLAGS) -W3 +!ENDIF + +CFLAGS_O1 = $(CFLAGS) -O1 +CFLAGS_O2 = $(CFLAGS) -O2 + +LFLAGS = $(LFLAGS) -nologo -OPT:REF -OPT:ICF + +!IFDEF DEF_FILE +LFLAGS = $(LFLAGS) -DLL -DEF:$(DEF_FILE) +!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 $** + +all: $(PROGPATH) + +clean: + -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch + +$O: + if not exist "$O" mkdir "$O" + +$(PROGPATH): $O $(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/CPP/Common/AutoPtr.h b/CPP/Common/AutoPtr.h new file mode 100755 index 0000000..e53fb7f --- /dev/null +++ b/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/CPP/Common/Buffer.h b/CPP/Common/Buffer.h new file mode 100755 index 0000000..defe943 --- /dev/null +++ b/CPP/Common/Buffer.h @@ -0,0 +1,77 @@ +// Common/Buffer.h + +#ifndef __COMMON_BUFFER_H +#define __COMMON_BUFFER_H + +#include "Defs.h" + +template class CBuffer +{ +protected: + size_t _capacity; + T *_items; +public: + void Free() + { + delete []_items; + _items = 0; + _capacity = 0; + } + CBuffer(): _capacity(0), _items(0) {}; + CBuffer(const CBuffer &buffer): _capacity(0), _items(0) { *this = buffer; } + CBuffer(size_t size): _items(0), _capacity(0) { SetCapacity(size); } + virtual ~CBuffer() { delete []_items; } + operator T *() { return _items; }; + operator const T *() const { return _items; }; + size_t GetCapacity() const { return _capacity; } + void SetCapacity(size_t newCapacity) + { + if (newCapacity == _capacity) + return; + T *newBuffer; + if (newCapacity > 0) + { + newBuffer = new T[newCapacity]; + if (_capacity > 0) + memmove(newBuffer, _items, MyMin(_capacity, newCapacity) * sizeof(T)); + } + else + newBuffer = 0; + delete []_items; + _items = newBuffer; + _capacity = newCapacity; + } + CBuffer& operator=(const CBuffer &buffer) + { + Free(); + if (buffer._capacity > 0) + { + SetCapacity(buffer._capacity); + memmove(_items, buffer._items, buffer._capacity * sizeof(T)); + } + return *this; + } +}; + +template +bool operator==(const CBuffer& b1, const CBuffer& b2) +{ + if (b1.GetCapacity() != b2.GetCapacity()) + return false; + for (size_t i = 0; i < b1.GetCapacity(); i++) + if (b1[i] != b2[i]) + return false; + return true; +} + +template +bool operator!=(const CBuffer& b1, const CBuffer& b2) +{ + return !(b1 == b2); +} + +typedef CBuffer CCharBuffer; +typedef CBuffer CWCharBuffer; +typedef CBuffer CByteBuffer; + +#endif diff --git a/CPP/Common/CRC.cpp b/CPP/Common/CRC.cpp new file mode 100755 index 0000000..6ac52c4 --- /dev/null +++ b/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/CPP/Common/C_FileIO.cpp b/CPP/Common/C_FileIO.cpp new file mode 100755 index 0000000..0e5647f --- /dev/null +++ b/CPP/Common/C_FileIO.cpp @@ -0,0 +1,88 @@ +// Common/C_FileIO.h + +#include "C_FileIO.h" + +#include +#include + +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/CPP/Common/C_FileIO.h b/CPP/Common/C_FileIO.h new file mode 100755 index 0000000..3f8cbca --- /dev/null +++ b/CPP/Common/C_FileIO.h @@ -0,0 +1,47 @@ +// Common/C_FileIO.h + +#ifndef __COMMON_C_FILEIO_H +#define __COMMON_C_FILEIO_H + +#include +#include + +#include "Types.h" +#include "MyWindows.h" + +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/CPP/Common/ComTry.h b/CPP/Common/ComTry.h new file mode 100755 index 0000000..b2b3029 --- /dev/null +++ b/CPP/Common/ComTry.h @@ -0,0 +1,17 @@ +// 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; } + + // catch(const CNewException &) { return E_OUTOFMEMORY; } + // catch(const CSystemException &e) { return e.ErrorCode; } + // catch(...) { return E_FAIL; } + +#endif diff --git a/CPP/Common/CommandLineParser.cpp b/CPP/Common/CommandLineParser.cpp new file mode 100755 index 0000000..028f4f8 --- /dev/null +++ b/CPP/Common/CommandLineParser.cpp @@ -0,0 +1,229 @@ +// 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; + int i; + for (i = 0; i < src.Length(); i++) + { + wchar_t c = src[i]; + if (c == L' ' && !quoteMode) + { + dest2 = src.Mid(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 wchar_t kSwitchID1 = '-'; +// static const wchar_t kSwitchID2 = '/'; + +static const wchar_t kSwitchMinus = '-'; +static const wchar_t *kStopSwitchParsing = L"--"; + +static bool IsItSwitchChar(wchar_t c) +{ + return (c == kSwitchID1 /*|| c == kSwitchID2 */); +} + +CParser::CParser(int numSwitches): + _numSwitches(numSwitches) +{ + _switches = new CSwitchResult[_numSwitches]; +} + +CParser::~CParser() +{ + delete []_switches; +} + +void CParser::ParseStrings(const CSwitchForm *switchForms, + const UStringVector &commandStrings) +{ + int numCommandStrings = commandStrings.Size(); + bool stopSwitch = false; + for (int i = 0; i < numCommandStrings; i++) + { + const UString &s = commandStrings[i]; + if (stopSwitch) + NonSwitchStrings.Add(s); + else + if (s == kStopSwitchParsing) + stopSwitch = true; + else + if (!ParseString(s, switchForms)) + NonSwitchStrings.Add(s); + } +} + +// if string contains switch then function updates switch structures +// out: (string is a switch) +bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) +{ + int len = s.Length(); + if (len == 0) + return false; + int pos = 0; + if (!IsItSwitchChar(s[pos])) + return false; + while (pos < len) + { + if (IsItSwitchChar(s[pos])) + pos++; + const int kNoLen = -1; + int matchedSwitchIndex = 0; // GCC Warning + int maxLen = kNoLen; + for (int switchIndex = 0; switchIndex < _numSwitches; switchIndex++) + { + int switchLen = MyStringLen(switchForms[switchIndex].IDString); + if (switchLen <= maxLen || pos + switchLen > len) + continue; + + UString temp = s + pos; + temp = temp.Left(switchLen); + if (temp.CompareNoCase(switchForms[switchIndex].IDString) == 0) + // if (_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0) + { + matchedSwitchIndex = switchIndex; + maxLen = switchLen; + } + } + if (maxLen == kNoLen) + throw "maxLen == kNoLen"; + CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex]; + const CSwitchForm &switchForm = switchForms[matchedSwitchIndex]; + if ((!switchForm.Multi) && matchedSwitch.ThereIs) + throw "switch must be single"; + matchedSwitch.ThereIs = true; + pos += maxLen; + int tailSize = len - pos; + NSwitchType::EEnum type = switchForm.Type; + switch(type) + { + case NSwitchType::kPostMinus: + { + if (tailSize == 0) + matchedSwitch.WithMinus = false; + else + { + matchedSwitch.WithMinus = (s[pos] == kSwitchMinus); + if (matchedSwitch.WithMinus) + pos++; + } + break; + } + case NSwitchType::kPostChar: + { + if (tailSize < switchForm.MinLen) + throw "switch is not full"; + UString set = switchForm.PostCharSet; + const int kEmptyCharValue = -1; + if (tailSize == 0) + matchedSwitch.PostCharIndex = kEmptyCharValue; + else + { + int index = set.Find(s[pos]); + if (index < 0) + matchedSwitch.PostCharIndex = kEmptyCharValue; + else + { + matchedSwitch.PostCharIndex = index; + pos++; + } + } + break; + } + case NSwitchType::kLimitedPostString: + case NSwitchType::kUnLimitedPostString: + { + int minLen = switchForm.MinLen; + if (tailSize < minLen) + throw "switch is not full"; + if (type == NSwitchType::kUnLimitedPostString) + { + matchedSwitch.PostStrings.Add(s.Mid(pos)); + return true; + } + int maxLen = switchForm.MaxLen; + UString stringSwitch = s.Mid(pos, minLen); + pos += minLen; + for (int i = minLen; i < maxLen && pos < len; i++, pos++) + { + wchar_t c = s[pos]; + if (IsItSwitchChar(c)) + break; + stringSwitch += c; + } + matchedSwitch.PostStrings.Add(stringSwitch); + break; + } + case NSwitchType::kSimple: + break; + } + } + return true; +} + +const CSwitchResult& CParser::operator[](size_t index) const +{ + return _switches[index]; +} + +///////////////////////////////// +// Command parsing procedures + +int ParseCommand(int numCommandForms, const CCommandForm *commandForms, + const UString &commandString, UString &postString) +{ + for (int i = 0; i < numCommandForms; i++) + { + const UString id = commandForms[i].IDString; + if (commandForms[i].PostStringMode) + { + if (commandString.Find(id) == 0) + { + postString = commandString.Mid(id.Length()); + return i; + } + } + else + if (commandString == id) + { + postString.Empty(); + return i; + } + } + return -1; +} + +} diff --git a/CPP/Common/CommandLineParser.h b/CPP/Common/CommandLineParser.h new file mode 100755 index 0000000..ec079e3 --- /dev/null +++ b/CPP/Common/CommandLineParser.h @@ -0,0 +1,72 @@ +// 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, + kPostMinus, + kLimitedPostString, + kUnLimitedPostString, + kPostChar + }; +} + +struct CSwitchForm +{ + const wchar_t *IDString; + NSwitchType::EEnum Type; + bool Multi; + int MinLen; + int MaxLen; + const wchar_t *PostCharSet; +}; + +struct CSwitchResult +{ + bool ThereIs; + bool WithMinus; + UStringVector PostStrings; + int PostCharIndex; + CSwitchResult(): ThereIs(false) {}; +}; + +class CParser +{ + int _numSwitches; + CSwitchResult *_switches; + bool ParseString(const UString &s, const CSwitchForm *switchForms); +public: + UStringVector NonSwitchStrings; + CParser(int numSwitches); + ~CParser(); + void ParseStrings(const CSwitchForm *switchForms, + const UStringVector &commandStrings); + const CSwitchResult& operator[](size_t index) const; +}; + +///////////////////////////////// +// Command parsing procedures + +struct CCommandForm +{ + const wchar_t *IDString; + bool PostStringMode; +}; + +// Returns: Index of form and postString; -1, if there is no match +int ParseCommand(int numCommandForms, const CCommandForm *commandForms, + const UString &commandString, UString &postString); + +} + +#endif diff --git a/CPP/Common/Defs.h b/CPP/Common/Defs.h new file mode 100755 index 0000000..69b8ece --- /dev/null +++ b/CPP/Common/Defs.h @@ -0,0 +1,20 @@ +// 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 ? -1 : (a == b ? 0 : 1); } + +inline int BoolToInt(bool value) + { return (value ? 1: 0); } + +inline bool IntToBool(int value) + { return (value != 0); } + +#endif diff --git a/CPP/Common/DynamicBuffer.h b/CPP/Common/DynamicBuffer.h new file mode 100755 index 0000000..2bd80ac --- /dev/null +++ b/CPP/Common/DynamicBuffer.h @@ -0,0 +1,50 @@ +// Common/DynamicBuffer.h + +#ifndef __COMMON_DYNAMIC_BUFFER_H +#define __COMMON_DYNAMIC_BUFFER_H + +#include "Buffer.h" + +template class CDynamicBuffer: public CBuffer +{ + void GrowLength(size_t size) + { + size_t delta; + if (this->_capacity > 64) + delta = this->_capacity / 4; + else if (this->_capacity > 8) + delta = 16; + else + delta = 4; + delta = MyMax(delta, size); + size_t newCap = this->_capacity + delta; + if (newCap < delta) + newCap = this->_capacity + size; + SetCapacity(newCap); + } +public: + CDynamicBuffer(): CBuffer() {}; + CDynamicBuffer(const CDynamicBuffer &buffer): CBuffer(buffer) {}; + CDynamicBuffer(size_t size): CBuffer(size) {}; + CDynamicBuffer& operator=(const CDynamicBuffer &buffer) + { + this->Free(); + if (buffer._capacity > 0) + { + SetCapacity(buffer._capacity); + memmove(this->_items, buffer._items, buffer._capacity * sizeof(T)); + } + return *this; + } + void EnsureCapacity(size_t capacity) + { + if (this->_capacity < capacity) + GrowLength(capacity - this->_capacity); + } +}; + +typedef CDynamicBuffer CCharDynamicBuffer; +typedef CDynamicBuffer CWCharDynamicBuffer; +typedef CDynamicBuffer CByteDynamicBuffer; + +#endif diff --git a/CPP/Common/IntToString.cpp b/CPP/Common/IntToString.cpp new file mode 100755 index 0000000..312e9f0 --- /dev/null +++ b/CPP/Common/IntToString.cpp @@ -0,0 +1,77 @@ +// Common/IntToString.cpp + +#include "StdAfx.h" + +#include "IntToString.h" + +void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base) +{ + if (base < 2 || base > 36) + { + *s = '\0'; + return; + } + char temp[72]; + int pos = 0; + do + { + int delta = (int)(value % base); + temp[pos++] = (char)((delta < 10) ? ('0' + delta) : ('a' + (delta - 10))); + value /= base; + } + while (value != 0); + do + *s++ = temp[--pos]; + while (pos > 0); + *s = '\0'; +} + +void ConvertUInt64ToString(UInt64 value, wchar_t *s) +{ + wchar_t temp[32]; + int pos = 0; + do + { + temp[pos++] = (wchar_t)(L'0' + (int)(value % 10)); + value /= 10; + } + while (value != 0); + do + *s++ = temp[--pos]; + while (pos > 0); + *s = L'\0'; +} + +void ConvertUInt32ToString(UInt32 value, char *s) { ConvertUInt64ToString(value, s); } +void ConvertUInt32ToString(UInt32 value, wchar_t *s) { ConvertUInt64ToString(value, s); } + +void ConvertInt64ToString(Int64 value, char *s) +{ + if (value < 0) + { + *s++ = '-'; + value = -value; + } + ConvertUInt64ToString(value, s); +} + +void ConvertInt64ToString(Int64 value, wchar_t *s) +{ + if (value < 0) + { + *s++ = L'-'; + value = -value; + } + ConvertUInt64ToString(value, s); +} + +void ConvertUInt32ToHexWithZeros(UInt32 value, char *s) +{ + for (int i = 0; i < 8; i++) + { + int t = value & 0xF; + value >>= 4; + s[7 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + } + s[8] = '\0'; +} diff --git a/CPP/Common/IntToString.h b/CPP/Common/IntToString.h new file mode 100755 index 0000000..c57fd6a --- /dev/null +++ b/CPP/Common/IntToString.h @@ -0,0 +1,19 @@ +// Common/IntToString.h + +#ifndef __COMMON_INT_TO_STRING_H +#define __COMMON_INT_TO_STRING_H + +#include +#include "Types.h" + +void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base = 10); +void ConvertUInt64ToString(UInt64 value, wchar_t *s); +void ConvertInt64ToString(Int64 value, char *s); +void ConvertInt64ToString(Int64 value, wchar_t *s); + +void ConvertUInt32ToString(UInt32 value, char *s); +void ConvertUInt32ToString(UInt32 value, wchar_t *s); + +void ConvertUInt32ToHexWithZeros(UInt32 value, char *s); + +#endif diff --git a/CPP/Common/Lang.cpp b/CPP/Common/Lang.cpp new file mode 100755 index 0000000..161b30b --- /dev/null +++ b/CPP/Common/Lang.cpp @@ -0,0 +1,130 @@ +// Common/Lang.cpp + +#include "StdAfx.h" + +#include "Lang.h" +#include "TextConfig.h" + +#include "../Windows/FileIO.h" +#include "UTFConvert.h" +#include "Defs.h" + +static bool HexStringToNumber(const UString &s, UInt32 &value) +{ + value = 0; + if (s.IsEmpty()) + return false; + for (int i = 0; i < s.Length(); i++) + { + wchar_t c = s[i]; + int a; + if (c >= L'0' && c <= L'9') + a = c - L'0'; + else if (c >= L'A' && c <= L'F') + a = 10 + c - L'A'; + else if (c >= L'a' && c <= L'f') + a = 10 + c - L'a'; + else + return false; + value *= 0x10; + value += a; + } + return true; +} + + +static bool WaitNextLine(const AString &s, int &pos) +{ + for (; pos < s.Length(); pos++) + if (s[pos] == 0x0A) + return true; + return false; +} + +static int CompareLangItems(void *const *elem1, void *const *elem2, void *) +{ + const CLangPair &langPair1 = *(*((const CLangPair **)elem1)); + const CLangPair &langPair2 = *(*((const CLangPair **)elem2)); + return MyCompare(langPair1.Value, langPair2.Value); +} + +bool CLang::Open(LPCWSTR fileName) +{ + _langPairs.Clear(); + NWindows::NFile::NIO::CInFile file; + if (!file.Open(fileName)) + return false; + UInt64 length; + if (!file.GetLength(length)) + return false; + if (length > (1 << 20)) + return false; + AString s; + char *p = s.GetBuffer((int)length + 1); + UInt32 processed; + if (!file.Read(p, (UInt32)length, processed)) + return false; + p[(UInt32)length] = 0; + s.ReleaseBuffer(); + file.Close(); + int pos = 0; + if (s.Length() >= 3) + { + if (Byte(s[0]) == 0xEF && Byte(s[1]) == 0xBB && Byte(s[2]) == 0xBF) + pos += 3; + } + + ///////////////////// + // read header + + AString stringID = ";!@Lang@!UTF-8!"; + if (s.Mid(pos, stringID.Length()) != stringID) + return false; + pos += stringID.Length(); + + if (!WaitNextLine(s, pos)) + return false; + + CObjectVector pairs; + if (!GetTextConfig(s.Mid(pos), pairs)) + return false; + + _langPairs.Reserve(_langPairs.Size()); + for (int i = 0; i < pairs.Size(); i++) + { + CTextConfigPair textConfigPair = pairs[i]; + CLangPair langPair; + if (!HexStringToNumber(textConfigPair.ID, langPair.Value)) + return false; + langPair.String = textConfigPair.String; + _langPairs.Add(langPair); + } + _langPairs.Sort(CompareLangItems, NULL); + return true; +} + +int CLang::FindItem(UInt32 value) const +{ + int left = 0, right = _langPairs.Size(); + while (left != right) + { + UInt32 mid = (left + right) / 2; + UInt32 midValue = _langPairs[mid].Value; + if (value == midValue) + return mid; + if (value < midValue) + right = mid; + else + left = mid + 1; + } + return -1; +} + +bool CLang::GetMessage(UInt32 value, UString &message) const +{ + int index = FindItem(value); + if (index < 0) + return false; + message = _langPairs[index].String; + return true; +} diff --git a/CPP/Common/Lang.h b/CPP/Common/Lang.h new file mode 100755 index 0000000..ac595c6 --- /dev/null +++ b/CPP/Common/Lang.h @@ -0,0 +1,28 @@ +// Common/Lang.h + +#ifndef __COMMON_LANG_H +#define __COMMON_LANG_H + +#include "MyVector.h" +#include "MyString.h" +#include "Types.h" + +struct CLangPair +{ + UInt32 Value; + UString String; +}; + +class CLang +{ + CObjectVector _langPairs; +public: + bool Open(LPCWSTR fileName); + void Clear() { _langPairs.Clear(); } + int FindItem(UInt32 value) const; + bool GetMessage(UInt32 value, UString &message) const; +}; + +#endif + + diff --git a/CPP/Common/ListFileUtils.cpp b/CPP/Common/ListFileUtils.cpp new file mode 100755 index 0000000..ff61b02 --- /dev/null +++ b/CPP/Common/ListFileUtils.cpp @@ -0,0 +1,75 @@ +// Common/ListFileUtils.cpp + +#include "StdAfx.h" + +#include "MyWindows.h" +#include "../Windows/FileIO.h" + +#include "ListFileUtils.h" +#include "StringConvert.h" +#include "UTFConvert.h" + +static const char kQuoteChar = '\"'; +static void RemoveQuote(UString &s) +{ + if (s.Length() >= 2) + if (s[0] == kQuoteChar && s[s.Length() - 1] == kQuoteChar) + s = s.Mid(1, s.Length() - 2); +} + +bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &resultStrings, UINT codePage) +{ + NWindows::NFile::NIO::CInFile file; + if (!file.Open(fileName)) + return false; + UInt64 length; + if (!file.GetLength(length)) + return false; + if (length > ((UInt32)1 << 31)) + return false; + AString s; + char *p = s.GetBuffer((int)length + 1); + UInt32 processed; + if (!file.Read(p, (UInt32)length, processed)) + return false; + p[(UInt32)length] = 0; + s.ReleaseBuffer(); + file.Close(); + + UString u; + #ifdef CP_UTF8 + if (codePage == CP_UTF8) + { + if (!ConvertUTF8ToUnicode(s, u)) + return false; + } + else + #endif + u = MultiByteToUnicodeString(s, codePage); + if (!u.IsEmpty()) + { + if (u[0] == 0xFEFF) + u.Delete(0); + } + + UString t; + for (int i = 0; i < u.Length(); i++) + { + wchar_t c = u[i]; + if (c == L'\n' || c == 0xD) + { + t.Trim(); + RemoveQuote(t); + if (!t.IsEmpty()) + resultStrings.Add(t); + t.Empty(); + } + else + t += c; + } + t.Trim(); + RemoveQuote(t); + if (!t.IsEmpty()) + resultStrings.Add(t); + return true; +} diff --git a/CPP/Common/ListFileUtils.h b/CPP/Common/ListFileUtils.h new file mode 100755 index 0000000..64f2199 --- /dev/null +++ b/CPP/Common/ListFileUtils.h @@ -0,0 +1,11 @@ +// Common/ListFileUtils.h + +#ifndef __COMMON_LISTFILEUTILS_H +#define __COMMON_LISTFILEUTILS_H + +#include "MyString.h" +#include "Types.h" + +bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP); + +#endif diff --git a/CPP/Common/MyCom.h b/CPP/Common/MyCom.h new file mode 100755 index 0000000..d04fa4c --- /dev/null +++ b/CPP/Common/MyCom.h @@ -0,0 +1,225 @@ +// MyCom.h + +#ifndef __MYCOM_H +#define __MYCOM_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: + // typedef T _PtrClass; + CMyComPtr() { _p = NULL;} + CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); } + CMyComPtr(const CMyComPtr& lp) + { + 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 != 0) + 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; } + // Compare two objects for equivalence + 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 + { + return _p->QueryInterface(iid, (void**)pp); + } +}; + +////////////////////////////////////////////////////////// + +inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr) +{ + *bstr = ::SysAllocString(src); + return (*bstr != 0) ? S_OK : E_OUTOFMEMORY; +} + +class CMyComBSTR +{ +public: + BSTR m_str; + CMyComBSTR(): m_str(NULL) {} + 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() { ::SysFreeString(m_str); } + 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 int Length() const { return ::SysStringLen(m_str); } + operator BSTR() const { return m_str; } + BSTR* operator&() { return &m_str; } + BSTR MyCopy() const + { + int byteLen = ::SysStringByteLen(m_str); + BSTR res = ::SysAllocStringByteLen(NULL, byteLen); + 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; + } + bool operator!() const { return (m_str == NULL); } +}; + +////////////////////////////////////////////////////////// + +class CMyUnknownImp +{ +public: + ULONG __m_RefCount; + CMyUnknownImp(): __m_RefCount(0) {} +}; + +#define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \ + (REFGUID iid, void **outObject) { + +#define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \ + { *outObject = (void *)(i *)this; AddRef(); return S_OK; } + +#define MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) if (iid == IID_IUnknown) \ + { *outObject = (void *)(IUnknown *)(i *)this; AddRef(); return S_OK; } + +#define MY_QUERYINTERFACE_BEGIN2(i) MY_QUERYINTERFACE_BEGIN \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ + MY_QUERYINTERFACE_ENTRY(i) + +#define MY_QUERYINTERFACE_END return E_NOINTERFACE; } + +#define MY_ADDREF_RELEASE \ +STDMETHOD_(ULONG, AddRef)() { 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) \ + ) + +#endif diff --git a/CPP/Common/MyException.h b/CPP/Common/MyException.h new file mode 100755 index 0000000..cd9fe69 --- /dev/null +++ b/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/CPP/Common/MyGuidDef.h b/CPP/Common/MyGuidDef.h new file mode 100755 index 0000000..da73d0a --- /dev/null +++ b/CPP/Common/MyGuidDef.h @@ -0,0 +1,54 @@ +// Common/MyGuidDef.h + +#ifndef GUID_DEFINED +#define GUID_DEFINED + +#include "Types.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/CPP/Common/MyInitGuid.h b/CPP/Common/MyInitGuid.h new file mode 100755 index 0000000..98d1705 --- /dev/null +++ b/CPP/Common/MyInitGuid.h @@ -0,0 +1,22 @@ +// Common/MyInitGuid.h + +#ifndef __COMMON_MY_INITGUID_H +#define __COMMON_MY_INITGUID_H + +#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/CPP/Common/MyMap.cpp b/CPP/Common/MyMap.cpp new file mode 100755 index 0000000..a69c61a --- /dev/null +++ b/CPP/Common/MyMap.cpp @@ -0,0 +1,140 @@ +// MyMap.cpp + +#include "StdAfx.h" + +#include "MyMap.h" + +static const unsigned kNumBitsMax = sizeof(UInt32) * 8; + +static UInt32 GetSubBits(UInt32 value, unsigned startPos, unsigned numBits) +{ + if (startPos == sizeof(value) * 8) + return 0; + value >>= startPos; + if (numBits == sizeof(value) * 8) + return value; + return value & (((UInt32)1 << numBits) - 1); +} + +static inline unsigned GetSubBit(UInt32 v, unsigned n) { return (unsigned)(v >> n) & 1; } + +bool CMap32::Find(UInt32 key, UInt32 &valueRes) const +{ + valueRes = (UInt32)(Int32)-1; + if (Nodes.Size() == 0) + return false; + if (Nodes.Size() == 1) + { + const CNode &n = Nodes[0]; + if (n.Len == kNumBitsMax) + { + valueRes = n.Values[0]; + return (key == n.Key); + } + } + + int cur = 0; + unsigned bitPos = kNumBitsMax; + for (;;) + { + const CNode &n = Nodes[cur]; + bitPos -= n.Len; + if (GetSubBits(key, bitPos, n.Len) != GetSubBits(n.Key, bitPos, n.Len)) + return false; + unsigned bit = GetSubBit(key, --bitPos); + if (n.IsLeaf[bit]) + { + valueRes = n.Values[bit]; + return (key == n.Keys[bit]); + } + cur = (int)n.Keys[bit]; + } +} + +bool CMap32::Set(UInt32 key, UInt32 value) +{ + if (Nodes.Size() == 0) + { + CNode n; + n.Key = n.Keys[0] = n.Keys[1] = key; + n.Values[0] = n.Values[1] = value; + n.IsLeaf[0] = n.IsLeaf[1] = 1; + n.Len = kNumBitsMax; + Nodes.Add(n); + return false; + } + if (Nodes.Size() == 1) + { + CNode &n = Nodes[0]; + if (n.Len == kNumBitsMax) + { + if (key == n.Key) + { + n.Values[0] = n.Values[1] = value; + return true; + } + unsigned i = kNumBitsMax - 1; + for (;GetSubBit(key, i) == GetSubBit(n.Key, i); i--); + n.Len = (UInt16)(kNumBitsMax - (1 + i)); + unsigned newBit = GetSubBit(key, i); + n.Values[newBit] = value; + n.Keys[newBit] = key; + return false; + } + } + + int cur = 0; + unsigned bitPos = kNumBitsMax; + for (;;) + { + CNode &n = Nodes[cur]; + bitPos -= n.Len; + if (GetSubBits(key, bitPos, n.Len) != GetSubBits(n.Key, bitPos, n.Len)) + { + unsigned i = n.Len - 1; + for (; GetSubBit(key, bitPos + i) == GetSubBit(n.Key, bitPos + i); i--); + + CNode e2(n); + e2.Len = (UInt16)i; + + n.Len = (UInt16)(n.Len - (1 + i)); + unsigned newBit = GetSubBit(key, bitPos + i); + n.Values[newBit] = value; + n.IsLeaf[newBit] = 1; + n.IsLeaf[1 - newBit] = 0; + n.Keys[newBit] = key; + n.Keys[1 - newBit] = Nodes.Size(); + Nodes.Add(e2); + return false; + } + unsigned bit = GetSubBit(key, --bitPos); + + if (n.IsLeaf[bit]) + { + if (key == n.Keys[bit]) + { + n.Values[bit] = value; + return true; + } + unsigned i = bitPos - 1; + for (;GetSubBit(key, i) == GetSubBit(n.Keys[bit], i); i--); + + CNode e2; + + unsigned newBit = GetSubBit(key, i); + e2.Values[newBit] = value; + e2.Values[1 - newBit] = n.Values[bit]; + e2.IsLeaf[newBit] = e2.IsLeaf[1 - newBit] = 1; + e2.Keys[newBit] = key; + e2.Keys[1 - newBit] = e2.Key = n.Keys[bit]; + e2.Len = (UInt16)(bitPos - (1 + i)); + + n.IsLeaf[bit] = 0; + n.Keys[bit] = Nodes.Size(); + + Nodes.Add(e2); + return false; + } + cur = (int)n.Keys[bit]; + } +} diff --git a/CPP/Common/MyMap.h b/CPP/Common/MyMap.h new file mode 100755 index 0000000..4545bce --- /dev/null +++ b/CPP/Common/MyMap.h @@ -0,0 +1,28 @@ +// MyMap.h + +#ifndef __COMMON_MYMAP_H +#define __COMMON_MYMAP_H + +#include "MyVector.h" +#include "Types.h" + +class CMap32 +{ + struct CNode + { + UInt32 Key; + UInt32 Keys[2]; + UInt32 Values[2]; + UInt16 Len; + Byte IsLeaf[2]; + }; + CRecordVector Nodes; + +public: + + void Clear() { Nodes.Clear(); } + bool Find(UInt32 key, UInt32 &valueRes) const; + bool Set(UInt32 key, UInt32 value); // returns true, if there is such key already +}; + +#endif diff --git a/CPP/Common/MyString.cpp b/CPP/Common/MyString.cpp new file mode 100755 index 0000000..1a25c9e --- /dev/null +++ b/CPP/Common/MyString.cpp @@ -0,0 +1,200 @@ +// Common/MyString.cpp + +#include "StdAfx.h" + +#ifndef _WIN32 +#include +#endif + +#ifndef _UNICODE +#include "StringConvert.h" +#endif + +#include "MyString.h" + + +#ifdef _WIN32 + +#ifndef _UNICODE + +wchar_t MyCharUpper(wchar_t c) +{ + if (c == 0) + return 0; + wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); + if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return (wchar_t)(unsigned int)(UINT_PTR)res; + const int kBufferSize = 4; + char s[kBufferSize + 1]; + int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); + if (numChars == 0 || numChars > kBufferSize) + return c; + s[numChars] = 0; + ::CharUpperA(s); + ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); + return c; +} + +wchar_t MyCharLower(wchar_t c) +{ + if (c == 0) + return 0; + wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); + if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return (wchar_t)(unsigned int)(UINT_PTR)res; + const int kBufferSize = 4; + char s[kBufferSize + 1]; + int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); + if (numChars == 0 || numChars > kBufferSize) + 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(); + return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); +} + +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(); + return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); +} + +#endif + +/* +inline int ConvertCompareResult(int r) { return r - 2; } + +int MyStringCollate(const wchar_t *s1, const wchar_t *s2) +{ + int res = CompareStringW( + LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1); + #ifdef _UNICODE + return ConvertCompareResult(res); + #else + if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return ConvertCompareResult(res); + return MyStringCollate(UnicodeStringToMultiByte(s1), + UnicodeStringToMultiByte(s2)); + #endif +} + +#ifndef UNDER_CE +int MyStringCollate(const char *s1, const char *s2) +{ + return ConvertCompareResult(CompareStringA( + LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1)); +} + +int MyStringCollateNoCase(const char *s1, const char *s2) +{ + return ConvertCompareResult(CompareStringA( + LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1)); +} +#endif + +int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) +{ + int res = CompareStringW( + LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1); + #ifdef _UNICODE + return ConvertCompareResult(res); + #else + if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return ConvertCompareResult(res); + return MyStringCollateNoCase(UnicodeStringToMultiByte(s1), + UnicodeStringToMultiByte(s2)); + #endif +} +*/ + +#else + +wchar_t MyCharUpper(wchar_t c) +{ + return toupper(c); +} + +/* +int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) +{ + for (;;) + { + wchar_t c1 = *s1++; + wchar_t c2 = *s2++; + wchar_t u1 = MyCharUpper(c1); + wchar_t u2 = MyCharUpper(c2); + + if (u1 < u2) return -1; + if (u1 > u2) return 1; + if (u1 == 0) return 0; + } +} +*/ + +#endif + +int MyStringCompare(const char *s1, const char *s2) +{ + for (;;) + { + unsigned char c1 = (unsigned char)*s1++; + unsigned char c2 = (unsigned char)*s2++; + if (c1 < c2) return -1; + if (c1 > c2) return 1; + if (c1 == 0) return 0; + } +} + +int MyStringCompare(const wchar_t *s1, const wchar_t *s2) +{ + for (;;) + { + wchar_t c1 = *s1++; + wchar_t c2 = *s2++; + if (c1 < c2) return -1; + if (c1 > c2) return 1; + if (c1 == 0) return 0; + } +} + +int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) +{ + 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(const char *s1, const char *s2) +{ + return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2)); +} +*/ diff --git a/CPP/Common/MyString.h b/CPP/Common/MyString.h new file mode 100755 index 0000000..ede2573 --- /dev/null +++ b/CPP/Common/MyString.h @@ -0,0 +1,625 @@ +// Common/String.h + +#ifndef __COMMON_STRING_H +#define __COMMON_STRING_H + +#include + +#include "MyVector.h" + +template +inline int MyStringLen(const T *s) +{ + int i; + for (i = 0; s[i] != '\0'; i++); + return i; +} + +template +inline T * MyStringCopy(T *dest, const T *src) +{ + T *destStart = dest; + while ((*dest++ = *src++) != 0); + return destStart; +} + +inline wchar_t* MyStringGetNextCharPointer(wchar_t *p) + { return (p + 1); } +inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p) + { return (p + 1); } +inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p) + { return (p - 1); } +inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p) + { return (p - 1); } + +#ifdef _WIN32 + +inline const char* MyStringGetNextCharPointer(const char *p) +{ + #ifdef UNDER_CE + return p + 1; + #else + return CharNextA(p); + #endif +} + +inline const char* MyStringGetPrevCharPointer(const char *base, const char *p) + { return CharPrevA(base, p); } + +inline char MyCharUpper(char c) + { return (char)(unsigned int)(UINT_PTR)CharUpperA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); } +#ifdef _UNICODE +inline wchar_t MyCharUpper(wchar_t c) + { return (wchar_t)(unsigned int)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); } +#else +wchar_t MyCharUpper(wchar_t c); +#endif + +#ifdef _UNICODE +inline wchar_t MyCharLower(wchar_t c) + { return (wchar_t)(unsigned int)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); } +#else +wchar_t MyCharLower(wchar_t c); +#endif + +inline char MyCharLower(char c) +#ifdef UNDER_CE + { return (char)MyCharLower((wchar_t)c); } +#else + { return (char)(unsigned int)(UINT_PTR)CharLowerA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); } +#endif + +inline char * MyStringUpper(char *s) { return CharUpperA(s); } +#ifdef _UNICODE +inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); } +#else +wchar_t * MyStringUpper(wchar_t *s); +#endif + +inline char * MyStringLower(char *s) { return CharLowerA(s); } +#ifdef _UNICODE +inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); } +#else +wchar_t * MyStringLower(wchar_t *s); +#endif + +#else // Standard-C +wchar_t MyCharUpper(wchar_t c); +#endif + +////////////////////////////////////// +// Compare + +/* +#ifndef UNDER_CE +int MyStringCollate(const char *s1, const char *s2); +int MyStringCollateNoCase(const char *s1, const char *s2); +#endif +int MyStringCollate(const wchar_t *s1, const wchar_t *s2); +int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2); +*/ + +int MyStringCompare(const char *s1, const char *s2); +int MyStringCompare(const wchar_t *s1, const wchar_t *s2); + +// int MyStringCompareNoCase(const char *s1, const char *s2); +int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2); + +template +class CStringBase +{ + void TrimLeftWithCharSet(const CStringBase &charSet) + { + const T *p = _chars; + while (charSet.Find(*p) >= 0 && (*p != 0)) + p = GetNextCharPointer(p); + Delete(0, (int)(p - _chars)); + } + void TrimRightWithCharSet(const CStringBase &charSet) + { + const T *p = _chars; + const T *pLast = NULL; + while (*p != 0) + { + if (charSet.Find(*p) >= 0) + { + if (pLast == NULL) + pLast = p; + } + else + pLast = NULL; + p = GetNextCharPointer(p); + } + if (pLast != NULL) + { + int i = (int)(pLast - _chars); + Delete(i, _length - i); + } + + } + void MoveItems(int destIndex, int srcIndex) + { + memmove(_chars + destIndex, _chars + srcIndex, + sizeof(T) * (_length - srcIndex + 1)); + } + + void InsertSpace(int &index, int size) + { + CorrectIndex(index); + GrowLength(size); + MoveItems(index + size, index); + } + + static const T *GetNextCharPointer(const T *p) + { return MyStringGetNextCharPointer(p); } + static const T *GetPrevCharPointer(const T *base, const T *p) + { return MyStringGetPrevCharPointer(base, p); } +protected: + T *_chars; + int _length; + int _capacity; + + void SetCapacity(int newCapacity) + { + int realCapacity = newCapacity + 1; + if (realCapacity == _capacity) + return; + /* + const int kMaxStringSize = 0x20000000; + if (newCapacity > kMaxStringSize || newCapacity < _length) + throw 1052337; + */ + T *newBuffer = new T[realCapacity]; + if (_capacity > 0) + { + for (int i = 0; i < _length; i++) + newBuffer[i] = _chars[i]; + delete []_chars; + } + _chars = newBuffer; + _chars[_length] = 0; + _capacity = realCapacity; + } + + void GrowLength(int n) + { + int freeSize = _capacity - _length - 1; + if (n <= freeSize) + return; + int delta; + if (_capacity > 64) + delta = _capacity / 2; + else if (_capacity > 8) + delta = 16; + else + delta = 4; + if (freeSize + delta < n) + delta = n - freeSize; + SetCapacity(_capacity + delta); + } + + void CorrectIndex(int &index) const + { + if (index > _length) + index = _length; + } + +public: + CStringBase(): _chars(0), _length(0), _capacity(0) { SetCapacity(3); } + CStringBase(T c): _chars(0), _length(0), _capacity(0) + { + SetCapacity(1); + _chars[0] = c; + _chars[1] = 0; + _length = 1; + } + CStringBase(const T *chars): _chars(0), _length(0), _capacity(0) + { + int length = MyStringLen(chars); + SetCapacity(length); + MyStringCopy(_chars, chars); // can be optimized by memove() + _length = length; + } + CStringBase(const CStringBase &s): _chars(0), _length(0), _capacity(0) + { + SetCapacity(s._length); + MyStringCopy(_chars, s._chars); + _length = s._length; + } + ~CStringBase() { delete []_chars; } + + operator const T*() const { return _chars;} + + T Back() const { return _chars[_length - 1]; } + + // The minimum size of the character buffer in characters. + // This value does not include space for a null terminator. + T* GetBuffer(int minBufLength) + { + if (minBufLength >= _capacity) + SetCapacity(minBufLength); + return _chars; + } + void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); } + void ReleaseBuffer(int newLength) + { + /* + if (newLength >= _capacity) + throw 282217; + */ + _chars[newLength] = 0; + _length = newLength; + } + + CStringBase& operator=(T c) + { + Empty(); + SetCapacity(1); + _chars[0] = c; + _chars[1] = 0; + _length = 1; + return *this; + } + CStringBase& operator=(const T *chars) + { + Empty(); + int length = MyStringLen(chars); + SetCapacity(length); + MyStringCopy(_chars, chars); + _length = length; + return *this; + } + CStringBase& operator=(const CStringBase& s) + { + if (&s == this) + return *this; + Empty(); + SetCapacity(s._length); + MyStringCopy(_chars, s._chars); + _length = s._length; + return *this; + } + + CStringBase& operator+=(T c) + { + GrowLength(1); + _chars[_length] = c; + _chars[++_length] = 0; + return *this; + } + CStringBase& operator+=(const T *s) + { + int len = MyStringLen(s); + GrowLength(len); + MyStringCopy(_chars + _length, s); + _length += len; + return *this; + } + CStringBase& operator+=(const CStringBase &s) + { + GrowLength(s._length); + MyStringCopy(_chars + _length, s._chars); + _length += s._length; + return *this; + } + void Empty() + { + _length = 0; + _chars[0] = 0; + } + int Length() const { return _length; } + bool IsEmpty() const { return (_length == 0); } + + CStringBase Mid(int startIndex) const + { return Mid(startIndex, _length - startIndex); } + CStringBase Mid(int startIndex, int count) const + { + if (startIndex + count > _length) + count = _length - startIndex; + + if (startIndex == 0 && startIndex + count == _length) + return *this; + + CStringBase result; + result.SetCapacity(count); + // MyStringNCopy(result._chars, _chars + startIndex, count); + for (int i = 0; i < count; i++) + result._chars[i] = _chars[startIndex + i]; + result._chars[count] = 0; + result._length = count; + return result; + } + CStringBase Left(int count) const + { return Mid(0, count); } + CStringBase Right(int count) const + { + if (count > _length) + count = _length; + return Mid(_length - count, count); + } + + void MakeUpper() + { MyStringUpper(_chars); } + void MakeLower() + { MyStringLower(_chars); } + + int Compare(const CStringBase& s) const + { return MyStringCompare(_chars, s._chars); } + + int Compare(const T *s) const + { return MyStringCompare(_chars, s); } + + int CompareNoCase(const CStringBase& s) const + { return MyStringCompareNoCase(_chars, s._chars); } + + int CompareNoCase(const T *s) const + { return MyStringCompareNoCase(_chars, s); } + + /* + int Collate(const CStringBase& s) const + { return MyStringCollate(_chars, s._chars); } + int CollateNoCase(const CStringBase& s) const + { return MyStringCollateNoCase(_chars, s._chars); } + */ + + int Find(T c) const { return Find(c, 0); } + int Find(T c, int startIndex) const + { + const T *p = _chars + startIndex; + for (;;) + { + if (*p == c) + return (int)(p - _chars); + if (*p == 0) + return -1; + p = GetNextCharPointer(p); + } + } + int Find(const CStringBase &s) const { return Find(s, 0); } + int Find(const CStringBase &s, int startIndex) const + { + if (s.IsEmpty()) + return startIndex; + for (; startIndex < _length; startIndex++) + { + int j; + for (j = 0; j < s._length && startIndex + j < _length; j++) + if (_chars[startIndex+j] != s._chars[j]) + break; + if (j == s._length) + return startIndex; + } + return -1; + } + int ReverseFind(T c) const + { + if (_length == 0) + return -1; + const T *p = _chars + _length - 1; + for (;;) + { + if (*p == c) + return (int)(p - _chars); + if (p == _chars) + return -1; + p = GetPrevCharPointer(_chars, p); + } + } + int FindOneOf(const CStringBase &s) const + { + for (int i = 0; i < _length; i++) + if (s.Find(_chars[i]) >= 0) + return i; + return -1; + } + + void TrimLeft(T c) + { + const T *p = _chars; + while (c == *p) + p = GetNextCharPointer(p); + Delete(0, p - _chars); + } + private: + CStringBase GetTrimDefaultCharSet() + { + CStringBase charSet; + charSet += (T)' '; + charSet += (T)'\n'; + charSet += (T)'\t'; + return charSet; + } + public: + + void TrimLeft() + { + TrimLeftWithCharSet(GetTrimDefaultCharSet()); + } + void TrimRight() + { + TrimRightWithCharSet(GetTrimDefaultCharSet()); + } + void TrimRight(T c) + { + const T *p = _chars; + const T *pLast = NULL; + while (*p != 0) + { + if (*p == c) + { + if (pLast == NULL) + pLast = p; + } + else + pLast = NULL; + p = GetNextCharPointer(p); + } + if (pLast != NULL) + { + int i = pLast - _chars; + Delete(i, _length - i); + } + } + void Trim() + { + TrimRight(); + TrimLeft(); + } + + int Insert(int index, T c) + { + InsertSpace(index, 1); + _chars[index] = c; + _length++; + return _length; + } + int Insert(int index, const CStringBase &s) + { + CorrectIndex(index); + if (s.IsEmpty()) + return _length; + int numInsertChars = s.Length(); + InsertSpace(index, numInsertChars); + for (int i = 0; i < numInsertChars; i++) + _chars[index + i] = s[i]; + _length += numInsertChars; + return _length; + } + + // !!!!!!!!!!!!!!! test it if newChar = '\0' + int Replace(T oldChar, T newChar) + { + if (oldChar == newChar) + return 0; + int number = 0; + int pos = 0; + while (pos < Length()) + { + pos = Find(oldChar, pos); + if (pos < 0) + break; + _chars[pos] = newChar; + pos++; + number++; + } + return number; + } + int Replace(const CStringBase &oldString, const CStringBase &newString) + { + if (oldString.IsEmpty()) + return 0; + if (oldString == newString) + return 0; + int oldStringLength = oldString.Length(); + int newStringLength = newString.Length(); + int number = 0; + int pos = 0; + while (pos < _length) + { + pos = Find(oldString, pos); + if (pos < 0) + break; + Delete(pos, oldStringLength); + Insert(pos, newString); + pos += newStringLength; + number++; + } + return number; + } + int Delete(int index, int count = 1) + { + if (index + count > _length) + count = _length - index; + if (count > 0) + { + MoveItems(index, index + count); + _length -= count; + } + return _length; + } + void DeleteBack() { Delete(_length - 1); } +}; + +template +CStringBase operator+(const CStringBase& s1, const CStringBase& s2) +{ + CStringBase result(s1); + result += s2; + return result; +} + +template +CStringBase operator+(const CStringBase& s, T c) +{ + CStringBase result(s); + result += c; + return result; +} + +template +CStringBase operator+(T c, const CStringBase& s) +{ + CStringBase result(c); + result += s; + return result; +} + +template +CStringBase operator+(const CStringBase& s, const T * chars) +{ + CStringBase result(s); + result += chars; + return result; +} + +template +CStringBase operator+(const T * chars, const CStringBase& s) +{ + CStringBase result(chars); + result += s; + return result; +} + +template +bool operator==(const CStringBase& s1, const CStringBase& s2) + { return (s1.Compare(s2) == 0); } + +template +bool operator<(const CStringBase& s1, const CStringBase& s2) + { return (s1.Compare(s2) < 0); } + +template +bool operator==(const T *s1, const CStringBase& s2) + { return (s2.Compare(s1) == 0); } + +template +bool operator==(const CStringBase& s1, const T *s2) + { return (s1.Compare(s2) == 0); } + +template +bool operator!=(const CStringBase& s1, const CStringBase& s2) + { return (s1.Compare(s2) != 0); } + +template +bool operator!=(const T *s1, const CStringBase& s2) + { return (s2.Compare(s1) != 0); } + +template +bool operator!=(const CStringBase& s1, const T *s2) + { return (s1.Compare(s2) != 0); } + +typedef CStringBase AString; +typedef CStringBase UString; + +typedef CObjectVector AStringVector; +typedef CObjectVector UStringVector; + +#ifdef _UNICODE + typedef UString CSysString; +#else + typedef AString CSysString; +#endif + +typedef CObjectVector CSysStringVector; + +#endif diff --git a/CPP/Common/MyUnknown.h b/CPP/Common/MyUnknown.h new file mode 100755 index 0000000..7935124 --- /dev/null +++ b/CPP/Common/MyUnknown.h @@ -0,0 +1,13 @@ +// MyUnknown.h + +#ifndef __MY_UNKNOWN_H +#define __MY_UNKNOWN_H + +#ifdef _WIN32 +#include +#include +#else +#include "MyWindows.h" +#endif + +#endif diff --git a/CPP/Common/MyVector.cpp b/CPP/Common/MyVector.cpp new file mode 100755 index 0000000..054d0aa --- /dev/null +++ b/CPP/Common/MyVector.cpp @@ -0,0 +1,87 @@ +// Common/MyVector.cpp + +#include "StdAfx.h" + +#include + +#include "MyVector.h" + +CBaseRecordVector::~CBaseRecordVector() { ClearAndFree(); } + +void CBaseRecordVector::ClearAndFree() +{ + Clear(); + delete []((unsigned char *)_items); + _capacity = 0; + _size = 0; + _items = 0; +} + +void CBaseRecordVector::Clear() { DeleteFrom(0); } +void CBaseRecordVector::DeleteBack() { Delete(_size - 1); } +void CBaseRecordVector::DeleteFrom(int index) { Delete(index, _size - index); } + +void CBaseRecordVector::ReserveOnePosition() +{ + if (_size != _capacity) + return; + unsigned delta = 1; + if (_capacity >= 64) + delta = (unsigned)_capacity / 4; + else if (_capacity >= 8) + delta = 8; + Reserve(_capacity + (int)delta); +} + +void CBaseRecordVector::Reserve(int newCapacity) +{ + // if (newCapacity <= _capacity) + if (newCapacity == _capacity) + return; + if ((unsigned)newCapacity >= ((unsigned)1 << (sizeof(unsigned) * 8 - 1))) + throw 1052353; + size_t newSize = (size_t)(unsigned)newCapacity * _itemSize; + if (newSize / _itemSize != (size_t)(unsigned)newCapacity) + throw 1052354; + unsigned char *p = NULL; + if (newSize > 0) + { + p = new unsigned char[newSize]; + if (p == 0) + throw 1052355; + int numRecordsToMove = (_size < newCapacity ? _size : newCapacity); + memcpy(p, _items, _itemSize * numRecordsToMove); + } + delete [](unsigned char *)_items; + _items = p; + _capacity = newCapacity; +} + +void CBaseRecordVector::ReserveDown() +{ + Reserve(_size); +} + +void CBaseRecordVector::MoveItems(int destIndex, int srcIndex) +{ + memmove(((unsigned char *)_items) + destIndex * _itemSize, + ((unsigned char *)_items) + srcIndex * _itemSize, + _itemSize * (_size - srcIndex)); +} + +void CBaseRecordVector::InsertOneItem(int index) +{ + ReserveOnePosition(); + MoveItems(index + 1, index); + _size++; +} + +void CBaseRecordVector::Delete(int index, int num) +{ + TestIndexAndCorrectNum(index, num); + if (num > 0) + { + MoveItems(index, index + num); + _size -= num; + } +} diff --git a/CPP/Common/MyVector.h b/CPP/Common/MyVector.h new file mode 100755 index 0000000..24740dc --- /dev/null +++ b/CPP/Common/MyVector.h @@ -0,0 +1,266 @@ +// Common/Vector.h + +#ifndef __COMMON_VECTOR_H +#define __COMMON_VECTOR_H + +#include "Defs.h" + +class CBaseRecordVector +{ + void MoveItems(int destIndex, int srcIndex); +protected: + int _capacity; + int _size; + void *_items; + size_t _itemSize; + + void ReserveOnePosition(); + void InsertOneItem(int index); + void TestIndexAndCorrectNum(int index, int &num) const + { if (index + num > _size) num = _size - index; } +public: + CBaseRecordVector(size_t itemSize): _capacity(0), _size(0), _items(0), _itemSize(itemSize) {} + virtual ~CBaseRecordVector(); + void ClearAndFree(); + int Size() const { return _size; } + bool IsEmpty() const { return (_size == 0); } + void Reserve(int newCapacity); + void ReserveDown(); + virtual void Delete(int index, int num = 1); + void Clear(); + void DeleteFrom(int index); + void DeleteBack(); +}; + +template +class CRecordVector: public CBaseRecordVector +{ +public: + CRecordVector(): CBaseRecordVector(sizeof(T)){}; + CRecordVector(const CRecordVector &v): CBaseRecordVector(sizeof(T)) { *this = v; } + CRecordVector& operator=(const CRecordVector &v) + { + Clear(); + return (*this += v); + } + CRecordVector& operator+=(const CRecordVector &v) + { + int size = v.Size(); + Reserve(Size() + size); + for (int i = 0; i < size; i++) + Add(v[i]); + return *this; + } + int Add(T item) + { + ReserveOnePosition(); + ((T *)_items)[_size] = item; + return _size++; + } + void Insert(int index, T item) + { + InsertOneItem(index); + ((T *)_items)[index] = item; + } + // T* GetPointer() const { return (T*)_items; } + // operator const T *() const { return _items; }; + const T& operator[](int index) const { return ((T *)_items)[index]; } + T& operator[](int index) { return ((T *)_items)[index]; } + const T& Front() const { return operator[](0); } + T& Front() { return operator[](0); } + const T& Back() const { return operator[](_size - 1); } + T& Back() { return operator[](_size - 1); } + + void Swap(int i, int j) + { + T temp = operator[](i); + operator[](i) = operator[](j); + operator[](j) = temp; + } + + int FindInSorted(const T& item, int left, int right) const + { + while (left != right) + { + int mid = (left + right) / 2; + const T& midValue = (*this)[mid]; + if (item == midValue) + return mid; + if (item < midValue) + right = mid; + else + left = mid + 1; + } + return -1; + } + + int FindInSorted(const T& item) const + { + int left = 0, right = Size(); + while (left != right) + { + int mid = (left + right) / 2; + const T& midValue = (*this)[mid]; + if (item == midValue) + return mid; + if (item < midValue) + right = mid; + else + left = mid + 1; + } + return -1; + } + + int AddToUniqueSorted(const T& item) + { + int left = 0, right = Size(); + while (left != right) + { + int mid = (left + right) / 2; + const T& midValue = (*this)[mid]; + if (item == midValue) + return mid; + if (item < midValue) + right = mid; + else + left = mid + 1; + } + Insert(right, item); + return right; + } + + static void SortRefDown(T* p, int k, int size, int (*compare)(const T*, const T*, void *), void *param) + { + T temp = p[k]; + for (;;) + { + int 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) + { + int size = _size; + if (size <= 1) + return; + T* p = (&Front()) - 1; + { + int i = size / 2; + 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); + } +}; + +typedef CRecordVector CIntVector; +typedef CRecordVector CUIntVector; +typedef CRecordVector CBoolVector; +typedef CRecordVector CByteVector; +typedef CRecordVector CPointerVector; + +template +class CObjectVector: public CPointerVector +{ +public: + CObjectVector() {}; + ~CObjectVector() { Clear(); }; + CObjectVector(const CObjectVector &v): CPointerVector() { *this = v; } + CObjectVector& operator=(const CObjectVector &v) + { + Clear(); + return (*this += v); + } + CObjectVector& operator+=(const CObjectVector &v) + { + int size = v.Size(); + Reserve(Size() + size); + for (int i = 0; i < size; i++) + Add(v[i]); + return *this; + } + const T& operator[](int index) const { return *((T *)CPointerVector::operator[](index)); } + T& operator[](int index) { return *((T *)CPointerVector::operator[](index)); } + T& Front() { return operator[](0); } + const T& Front() const { return operator[](0); } + T& Back() { return operator[](_size - 1); } + const T& Back() const { return operator[](_size - 1); } + int Add(const T& item) { return CPointerVector::Add(new T(item)); } + void Insert(int index, const T& item) { CPointerVector::Insert(index, new T(item)); } + virtual void Delete(int index, int num = 1) + { + TestIndexAndCorrectNum(index, num); + for (int i = 0; i < num; i++) + delete (T *)(((void **)_items)[index + i]); + CPointerVector::Delete(index, num); + } + int Find(const T& item) const + { + for (int i = 0; i < Size(); i++) + if (item == (*this)[i]) + return i; + return -1; + } + int FindInSorted(const T& item) const + { + int left = 0, right = Size(); + while (left != right) + { + int mid = (left + right) / 2; + const T& midValue = (*this)[mid]; + if (item == midValue) + return mid; + if (item < midValue) + right = mid; + else + left = mid + 1; + } + return -1; + } + int AddToSorted(const T& item) + { + int left = 0, right = Size(); + while (left != right) + { + int mid = (left + right) / 2; + const T& midValue = (*this)[mid]; + if (item == midValue) + { + right = mid + 1; + break; + } + if (item < midValue) + right = mid; + else + left = mid + 1; + } + Insert(right, item); + return right; + } + + void Sort(int (*compare)(void *const *, void *const *, void *), void *param) + { CPointerVector::Sort(compare, param); } + + static int CompareObjectItems(void *const *a1, void *const *a2, void * /* param */) + { return MyCompare(*(*((const T **)a1)), *(*((const T **)a2))); } + void Sort() { CPointerVector::Sort(CompareObjectItems, 0); } +}; + +#endif diff --git a/CPP/Common/MyWindows.cpp b/CPP/Common/MyWindows.cpp new file mode 100755 index 0000000..9e246af --- /dev/null +++ b/CPP/Common/MyWindows.cpp @@ -0,0 +1,109 @@ +// MyWindows.cpp + +#include "StdAfx.h" + +#ifndef _WIN32 + +#include "MyWindows.h" +#include "Types.h" +#include + +static inline void *AllocateForBSTR(size_t cb) { return ::malloc(cb); } +static inline void FreeForBSTR(void *pv) { ::free(pv);} + +static UINT MyStringLen(const wchar_t *s) +{ + UINT i; + for (i = 0; s[i] != '\0'; i++); + return i; +} + +BSTR SysAllocStringByteLen(LPCSTR psz, UINT len) +{ + int realLen = len + sizeof(UINT) + sizeof(OLECHAR) + sizeof(OLECHAR); + void *p = AllocateForBSTR(realLen); + if (p == 0) + return 0; + *(UINT *)p = len; + BSTR bstr = (BSTR)((UINT *)p + 1); + memmove(bstr, psz, len); + Byte *pb = ((Byte *)bstr) + len; + for (int i = 0; i < sizeof(OLECHAR) * 2; i++) + pb[i] = 0; + return bstr; +} + +BSTR SysAllocString(const OLECHAR *sz) +{ + if (sz == 0) + return 0; + UINT strLen = MyStringLen(sz); + UINT len = (strLen + 1) * sizeof(OLECHAR); + void *p = AllocateForBSTR(len + sizeof(UINT)); + if (p == 0) + return 0; + *(UINT *)p = strLen; + BSTR bstr = (BSTR)((UINT *)p + 1); + memmove(bstr, sz, len); + return bstr; +} + +void SysFreeString(BSTR bstr) +{ + if (bstr != 0) + FreeForBSTR((UINT *)bstr - 1); +} + +UINT SysStringByteLen(BSTR bstr) +{ + if (bstr == 0) + return 0; + return *((UINT *)bstr - 1); +} + +UINT SysStringLen(BSTR bstr) +{ + return SysStringByteLen(bstr) / 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, 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 == 0) + 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/CPP/Common/MyWindows.h b/CPP/Common/MyWindows.h new file mode 100755 index 0000000..5cfded1 --- /dev/null +++ b/CPP/Common/MyWindows.h @@ -0,0 +1,204 @@ +// MyWindows.h + +#ifndef __MYWINDOWS_H +#define __MYWINDOWS_H + +#ifdef _WIN32 + +#include + +#else + +#include // for wchar_t +#include + +#include "MyGuidDef.h" + +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 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 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; + +#ifdef __cplusplus + +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, VARIANTARG *src); + +#endif + +MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, 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 + +typedef enum tagSTREAM_SEEK +{ + STREAM_SEEK_SET = 0, + STREAM_SEEK_CUR = 1, + STREAM_SEEK_END = 2 +} STREAM_SEEK; + +#endif +#endif diff --git a/CPP/Common/MyXml.cpp b/CPP/Common/MyXml.cpp new file mode 100755 index 0000000..ce4c781 --- /dev/null +++ b/CPP/Common/MyXml.cpp @@ -0,0 +1,209 @@ +// MyXml.cpp + +#include "StdAfx.h" + +#include "MyXml.h" + +static bool IsValidChar(char c) +{ + return + c >= 'a' && c <= 'z' || + c >= 'A' && c <= 'Z' || + c >= '0' && c <= '9' || + c == '-'; +} + +static bool IsSpaceChar(char c) +{ + return (c == ' ' || c == '\t' || c == 0x0D || c == 0x0A); +} + +#define SKIP_SPACES(s, pos) while (IsSpaceChar(s[pos])) pos++; + +static bool ReadProperty(const AString &s, int &pos, CXmlProp &prop) +{ + prop.Name.Empty(); + prop.Value.Empty(); + for (; pos < s.Length(); pos++) + { + char c = s[pos]; + if (!IsValidChar(c)) + break; + prop.Name += c; + } + + if (prop.Name.IsEmpty()) + return false; + + SKIP_SPACES(s, pos); + if (s[pos++] != '=') + return false; + + SKIP_SPACES(s, pos); + if (s[pos++] != '\"') + return false; + + while (pos < s.Length()) + { + char c = s[pos++]; + if (c == '\"') + return true; + prop.Value += c; + } + return false; +} + +int CXmlItem::FindProperty(const AString &propName) const +{ + for (int i = 0; i < Props.Size(); i++) + if (Props[i].Name == propName) + return i; + return -1; +} + +AString CXmlItem::GetPropertyValue(const AString &propName) const +{ + int index = FindProperty(propName); + if (index >= 0) + return Props[index].Value; + return AString(); +} + +bool CXmlItem::IsTagged(const AString &tag) const +{ + return (IsTag && Name == tag); +} + +int CXmlItem::FindSubTag(const AString &tag) const +{ + for (int i = 0; i < SubItems.Size(); i++) + if (SubItems[i].IsTagged(tag)) + return i; + return -1; +} + +AString CXmlItem::GetSubString() const +{ + if (SubItems.Size() == 1) + { + const CXmlItem &item = SubItems[0]; + if (!item.IsTag) + return item.Name; + } + return AString(); +} + +AString CXmlItem::GetSubStringForTag(const AString &tag) const +{ + int index = FindSubTag(tag); + if (index >= 0) + return SubItems[index].GetSubString(); + return AString(); +} + +bool CXmlItem::ParseItems(const AString &s, int &pos, int numAllowedLevels) +{ + if (numAllowedLevels == 0) + return false; + SubItems.Clear(); + AString finishString = "'); + } + if (s[pos] == '>') + { + if (!ParseItems(s, ++pos, numAllowedLevels)) + return false; + AString finishString = AString(""); + if (s.Mid(pos, finishString.Length()) != finishString) + return false; + pos += finishString.Length(); + return true; + } + if (posTemp == pos) + return false; + + CXmlProp prop; + if (!ReadProperty(s, pos, prop)) + return false; + Props.Add(prop); + posTemp = pos; + } +} + +static bool SkipHeader(const AString &s, int &pos, const AString &startString, const AString &endString) +{ + SKIP_SPACES(s, pos); + if (s.Mid(pos, startString.Length()) == startString) + { + pos = s.Find(endString, pos); + if (pos < 0) + return false; + pos += endString.Length(); + SKIP_SPACES(s, pos); + } + return true; +} + +bool CXml::Parse(const AString &s) +{ + int pos = 0; + if (!SkipHeader(s, pos, "")) + return false; + if (!SkipHeader(s, pos, "")) + return false; + if (!Root.ParseItem(s, pos, 1000)) + return false; + SKIP_SPACES(s, pos); + return (pos == s.Length() && Root.IsTag); +} diff --git a/CPP/Common/MyXml.h b/CPP/Common/MyXml.h new file mode 100755 index 0000000..52e23d1 --- /dev/null +++ b/CPP/Common/MyXml.h @@ -0,0 +1,40 @@ +// MyXml.h + +#ifndef __MYXML_H +#define __MYXML_H + +#include "MyString.h" + +struct CXmlProp +{ + AString Name; + AString Value; +}; + +class CXmlItem +{ + bool ParseItems(const AString &s, int &pos, int numAllowedLevels); + +public: + AString Name; + bool IsTag; + CObjectVector Props; + CObjectVector SubItems; + + bool ParseItem(const AString &s, int &pos, int numAllowedLevels); + + bool IsTagged(const AString &tag) const; + int FindProperty(const AString &propName) const; + AString GetPropertyValue(const AString &propName) const; + AString GetSubString() const; + int FindSubTag(const AString &tag) const; + AString GetSubStringForTag(const AString &tag) const; +}; + +struct CXml +{ + CXmlItem Root; + bool Parse(const AString &s); +}; + +#endif diff --git a/CPP/Common/NewHandler.cpp b/CPP/Common/NewHandler.cpp new file mode 100755 index 0000000..611bbd8 --- /dev/null +++ b/CPP/Common/NewHandler.cpp @@ -0,0 +1,116 @@ +// NewHandler.cpp + +#include "StdAfx.h" + +#include + +#include "NewHandler.h" + +// #define DEBUG_MEMORY_LEAK + +#ifndef DEBUG_MEMORY_LEAK + +#ifdef _WIN32 +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 + +#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 == 40) + { + int t = 1; + } + if (index < kDebugSize) + { + a[index] = p; + index++; + } + if (p == 0) + throw CNewException(); + printf("Alloc %6d, size = %8d\n", numAllocs, 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/CPP/Common/NewHandler.h b/CPP/Common/NewHandler.h new file mode 100755 index 0000000..6f710cd --- /dev/null +++ b/CPP/Common/NewHandler.h @@ -0,0 +1,16 @@ +// Common/NewHandler.h + +#ifndef __COMMON_NEWHANDLER_H +#define __COMMON_NEWHANDLER_H + +class CNewException {}; + +#ifdef _WIN32 +void +#ifdef _MSC_VER +__cdecl +#endif +operator delete(void *p) throw(); +#endif + +#endif diff --git a/CPP/Common/Random.cpp b/CPP/Common/Random.cpp new file mode 100755 index 0000000..ca0113f --- /dev/null +++ b/CPP/Common/Random.cpp @@ -0,0 +1,26 @@ +// Common/Random.cpp + +#include "StdAfx.h" + +#include + +#ifndef _WIN32 +#include +#endif + +#include "Random.h" + +void CRandom::Init(unsigned int seed) { srand(seed); } + +void CRandom::Init() +{ + Init((unsigned int) + #ifdef _WIN32 + GetTickCount() + #else + time(NULL) + #endif + ); +} + +int CRandom::Generate() const { return rand(); } diff --git a/CPP/Common/Random.h b/CPP/Common/Random.h new file mode 100755 index 0000000..f6fe5c4 --- /dev/null +++ b/CPP/Common/Random.h @@ -0,0 +1,16 @@ +// Common/Random.h + +#ifndef __COMMON_RANDOM_H +#define __COMMON_RANDOM_H + +class CRandom +{ +public: + void Init(); + void Init(unsigned int seed); + int Generate() const; +}; + +#endif + + diff --git a/CPP/Common/StdAfx.h b/CPP/Common/StdAfx.h new file mode 100755 index 0000000..9b43572 --- /dev/null +++ b/CPP/Common/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +// #include "MyWindows.h" +#include "NewHandler.h" + +#endif diff --git a/CPP/Common/StdInStream.cpp b/CPP/Common/StdInStream.cpp new file mode 100755 index 0000000..442191e --- /dev/null +++ b/CPP/Common/StdInStream.cpp @@ -0,0 +1,107 @@ +// Common/StdInStream.cpp + +#include "StdAfx.h" + +#include + +#include "StdInStream.h" +#include "StringConvert.h" +#include "UTFConvert.h" + +#ifdef _MSC_VER +// "was declared deprecated" disabling +#pragma warning(disable : 4996 ) +#endif + +static const char kIllegalChar = '\0'; +static const char kNewLineChar = '\n'; + +static const char *kEOFMessage = "Unexpected end of input stream"; +static const char *kReadErrorMessage ="Error reading input stream"; +static const char *kIllegalCharMessage = "Illegal character in input stream"; + +static LPCTSTR kFileOpenMode = TEXT("r"); + +extern int g_CodePage; + +CStdInStream g_StdIn(stdin); + +bool CStdInStream::Open(LPCTSTR fileName) +{ + Close(); + _stream = _tfopen(fileName, kFileOpenMode); + _streamIsOpen = (_stream != 0); + return _streamIsOpen; +} + +bool CStdInStream::Close() +{ + if (!_streamIsOpen) + return true; + _streamIsOpen = (fclose(_stream) != 0); + return !_streamIsOpen; +} + +CStdInStream::~CStdInStream() +{ + Close(); +} + +AString CStdInStream::ScanStringUntilNewLine(bool allowEOF) +{ + AString s; + for (;;) + { + int intChar = GetChar(); + if (intChar == EOF) + { + if (allowEOF) + break; + throw kEOFMessage; + } + char c = char(intChar); + if (c == kIllegalChar) + throw kIllegalCharMessage; + if (c == kNewLineChar) + break; + s += c; + } + return s; +} + +UString CStdInStream::ScanUStringUntilNewLine() +{ + AString s = ScanStringUntilNewLine(true); + int codePage = g_CodePage; + if (codePage == -1) + codePage = CP_OEMCP; + UString dest; + if (codePage == CP_UTF8) + ConvertUTF8ToUnicode(s, dest); + else + dest = MultiByteToUnicodeString(s, (UINT)codePage); + return dest; +} + +void CStdInStream::ReadToString(AString &resultString) +{ + resultString.Empty(); + int c; + while ((c = GetChar()) != EOF) + resultString += char(c); +} + +bool CStdInStream::Eof() +{ + return (feof(_stream) != 0); +} + +int CStdInStream::GetChar() +{ + int c = fgetc(_stream); // getc() doesn't work in BeOS? + if (c == EOF && !Eof()) + throw kReadErrorMessage; + return c; +} + + diff --git a/CPP/Common/StdInStream.h b/CPP/Common/StdInStream.h new file mode 100755 index 0000000..67ef82b --- /dev/null +++ b/CPP/Common/StdInStream.h @@ -0,0 +1,32 @@ +// Common/StdInStream.h + +#ifndef __COMMON_STDINSTREAM_H +#define __COMMON_STDINSTREAM_H + +#include + +#include "MyString.h" +#include "Types.h" + +class CStdInStream +{ + bool _streamIsOpen; + FILE *_stream; +public: + CStdInStream(): _streamIsOpen(false) {}; + CStdInStream(FILE *stream): _streamIsOpen(false), _stream(stream) {}; + ~CStdInStream(); + bool Open(LPCTSTR fileName); + bool Close(); + + AString ScanStringUntilNewLine(bool allowEOF = false); + void ReadToString(AString &resultString); + UString ScanUStringUntilNewLine(); + + bool Eof(); + int GetChar(); +}; + +extern CStdInStream g_StdIn; + +#endif diff --git a/CPP/Common/StdOutStream.cpp b/CPP/Common/StdOutStream.cpp new file mode 100755 index 0000000..f7ec2a6 --- /dev/null +++ b/CPP/Common/StdOutStream.cpp @@ -0,0 +1,104 @@ +// Common/StdOutStream.cpp + +#include "StdAfx.h" + +#include + +#include "IntToString.h" +#include "StdOutStream.h" +#include "StringConvert.h" +#include "UTFConvert.h" + +#ifdef _MSC_VER +// "was declared deprecated" disabling +#pragma warning(disable : 4996 ) +#endif + +static const char kNewLineChar = '\n'; + +static const char *kFileOpenMode = "wt"; + +extern int g_CodePage; + +CStdOutStream g_StdOut(stdout); +CStdOutStream g_StdErr(stderr); + +bool CStdOutStream::Open(const char *fileName) +{ + Close(); + _stream = fopen(fileName, kFileOpenMode); + _streamIsOpen = (_stream != 0); + return _streamIsOpen; +} + +bool CStdOutStream::Close() +{ + if (!_streamIsOpen) + return true; + if (fclose(_stream) != 0) + return false; + _stream = 0; + _streamIsOpen = false; + return true; +} + +bool CStdOutStream::Flush() +{ + return (fflush(_stream) == 0); +} + +CStdOutStream::~CStdOutStream () +{ + Close(); +} + +CStdOutStream & CStdOutStream::operator<<(CStdOutStream & (*aFunction)(CStdOutStream &)) +{ + (*aFunction)(*this); + return *this; +} + +CStdOutStream & endl(CStdOutStream & outStream) +{ + return outStream << kNewLineChar; +} + +CStdOutStream & CStdOutStream::operator<<(const char *s) +{ + fputs(s, _stream); + return *this; +} + +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 + dest = UnicodeStringToMultiByte(s, (UINT)codePage); + *this << (const char *)dest; + return *this; +} + +CStdOutStream & CStdOutStream::operator<<(char c) +{ + fputc(c, _stream); + return *this; +} + +CStdOutStream & CStdOutStream::operator<<(int number) +{ + char textString[32]; + ConvertInt64ToString(number, textString); + return operator<<(textString); +} + +CStdOutStream & CStdOutStream::operator<<(UInt64 number) +{ + char textString[32]; + ConvertUInt64ToString(number, textString); + return operator<<(textString); +} diff --git a/CPP/Common/StdOutStream.h b/CPP/Common/StdOutStream.h new file mode 100755 index 0000000..c2fcd9d --- /dev/null +++ b/CPP/Common/StdOutStream.h @@ -0,0 +1,35 @@ +// Common/StdOutStream.h + +#ifndef __COMMON_STDOUTSTREAM_H +#define __COMMON_STDOUTSTREAM_H + +#include + +#include "Types.h" + +class CStdOutStream +{ + bool _streamIsOpen; + FILE *_stream; +public: + CStdOutStream (): _streamIsOpen(false), _stream(0) {}; + CStdOutStream (FILE *stream): _streamIsOpen(false), _stream(stream) {}; + ~CStdOutStream (); + operator FILE *() { return _stream; } + bool Open(const char *fileName); + bool Close(); + bool Flush(); + CStdOutStream & operator<<(CStdOutStream & (* aFunction)(CStdOutStream &)); + CStdOutStream & operator<<(const char *string); + CStdOutStream & operator<<(const wchar_t *string); + CStdOutStream & operator<<(char c); + CStdOutStream & operator<<(int number); + CStdOutStream & operator<<(UInt64 number); +}; + +CStdOutStream & endl(CStdOutStream & outStream); + +extern CStdOutStream g_StdOut; +extern CStdOutStream g_StdErr; + +#endif diff --git a/CPP/Common/StringConvert.cpp b/CPP/Common/StringConvert.cpp new file mode 100755 index 0000000..7f9999c --- /dev/null +++ b/CPP/Common/StringConvert.cpp @@ -0,0 +1,97 @@ +// Common/StringConvert.cpp + +#include "StdAfx.h" + +#include "StringConvert.h" + +#ifndef _WIN32 +#include +#endif + +#ifdef _WIN32 +UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) +{ + UString resultString; + if (!srcString.IsEmpty()) + { + int numChars = MultiByteToWideChar(codePage, 0, srcString, + srcString.Length(), resultString.GetBuffer(srcString.Length()), + srcString.Length() + 1); + if (numChars == 0) + throw 282228; + resultString.ReleaseBuffer(numChars); + } + return resultString; +} + +AString UnicodeStringToMultiByte(const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed) +{ + AString dest; + defaultCharWasUsed = false; + if (!s.IsEmpty()) + { + int numRequiredBytes = s.Length() * 2; + BOOL defUsed; + int numChars = WideCharToMultiByte(codePage, 0, s, s.Length(), + dest.GetBuffer(numRequiredBytes), numRequiredBytes + 1, + &defaultChar, &defUsed); + defaultCharWasUsed = (defUsed != FALSE); + if (numChars == 0) + throw 282229; + dest.ReleaseBuffer(numChars); + } + return dest; +} + +AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) +{ + bool defaultCharWasUsed; + return UnicodeStringToMultiByte(srcString, codePage, '_', defaultCharWasUsed); +} + +#ifndef UNDER_CE +AString SystemStringToOemString(const CSysString &srcString) +{ + AString result; + CharToOem(srcString, result.GetBuffer(srcString.Length() * 2)); + result.ReleaseBuffer(); + return result; +} +#endif + +#else + +UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) +{ + UString resultString; + for (int i = 0; i < srcString.Length(); i++) + resultString += wchar_t(srcString[i]); + /* + if (!srcString.IsEmpty()) + { + int numChars = mbstowcs(resultString.GetBuffer(srcString.Length()), srcString, srcString.Length() + 1); + if (numChars < 0) throw "Your environment does not support UNICODE"; + resultString.ReleaseBuffer(numChars); + } + */ + return resultString; +} + +AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) +{ + AString resultString; + for (int i = 0; i < srcString.Length(); i++) + resultString += char(srcString[i]); + /* + if (!srcString.IsEmpty()) + { + int numRequiredBytes = srcString.Length() * 6 + 1; + int numChars = wcstombs(resultString.GetBuffer(numRequiredBytes), srcString, numRequiredBytes); + if (numChars < 0) throw "Your environment does not support UNICODE"; + resultString.ReleaseBuffer(numChars); + } + */ + return resultString; +} + +#endif diff --git a/CPP/Common/StringConvert.h b/CPP/Common/StringConvert.h new file mode 100755 index 0000000..1c7a951 --- /dev/null +++ b/CPP/Common/StringConvert.h @@ -0,0 +1,73 @@ +// Common/StringConvert.h + +#ifndef __COMMON_STRING_CONVERT_H +#define __COMMON_STRING_CONVERT_H + +#include "MyWindows.h" +#include "MyString.h" +#include "Types.h" + +UString MultiByteToUnicodeString(const AString &srcString, UINT codePage = CP_ACP); +AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage, char defaultChar, bool &defaultCharWasUsed); +AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage = CP_ACP); + + +inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString) + { return unicodeString; } +inline const UString& GetUnicodeString(const UString &unicodeString) + { return unicodeString; } +inline UString GetUnicodeString(const AString &ansiString) + { return MultiByteToUnicodeString(ansiString); } +inline UString GetUnicodeString(const AString &multiByteString, UINT codePage) + { return MultiByteToUnicodeString(multiByteString, codePage); } +inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString, UINT) + { return unicodeString; } +inline const UString& GetUnicodeString(const UString &unicodeString, UINT) + { return unicodeString; } + +inline const char* GetAnsiString(const char* ansiString) + { return ansiString; } +inline const AString& GetAnsiString(const AString &ansiString) + { return ansiString; } +inline AString GetAnsiString(const UString &unicodeString) + { return UnicodeStringToMultiByte(unicodeString); } + +inline const char* GetOemString(const char* oemString) + { return oemString; } +inline const AString& GetOemString(const AString &oemString) + { return oemString; } +inline AString GetOemString(const UString &unicodeString) + { return UnicodeStringToMultiByte(unicodeString, CP_OEMCP); } + + +#ifdef _UNICODE + inline const wchar_t* GetSystemString(const wchar_t* unicodeString) + { return unicodeString;} + inline const UString& GetSystemString(const UString &unicodeString) + { return unicodeString;} + inline const wchar_t* GetSystemString(const wchar_t* unicodeString, UINT /* codePage */) + { return unicodeString;} + inline const UString& GetSystemString(const UString &unicodeString, UINT /* codePage */) + { return unicodeString;} + inline UString GetSystemString(const AString &multiByteString, UINT codePage) + { return MultiByteToUnicodeString(multiByteString, codePage);} + inline UString GetSystemString(const AString &multiByteString) + { return MultiByteToUnicodeString(multiByteString);} +#else + inline const char* GetSystemString(const char *ansiString) + { return ansiString; } + inline const AString& GetSystemString(const AString &multiByteString, UINT) + { return multiByteString; } + inline const char * GetSystemString(const char *multiByteString, UINT) + { return multiByteString; } + inline AString GetSystemString(const UString &unicodeString) + { return UnicodeStringToMultiByte(unicodeString); } + inline AString GetSystemString(const UString &unicodeString, UINT codePage) + { return UnicodeStringToMultiByte(unicodeString, codePage); } +#endif + +#ifndef UNDER_CE +AString SystemStringToOemString(const CSysString &srcString); +#endif + +#endif diff --git a/CPP/Common/StringToInt.cpp b/CPP/Common/StringToInt.cpp new file mode 100755 index 0000000..77ce7c5 --- /dev/null +++ b/CPP/Common/StringToInt.cpp @@ -0,0 +1,90 @@ +// Common/StringToInt.cpp + +#include "StdAfx.h" + +#include "StringToInt.h" + +UInt64 ConvertStringToUInt64(const char *s, const char **end) +{ + UInt64 result = 0; + for (;;) + { + char c = *s; + if (c < '0' || c > '9') + { + if (end != NULL) + *end = s; + return result; + } + result *= 10; + result += (c - '0'); + s++; + } +} + +UInt64 ConvertOctStringToUInt64(const char *s, const char **end) +{ + UInt64 result = 0; + for (;;) + { + char c = *s; + if (c < '0' || c > '7') + { + if (end != NULL) + *end = s; + return result; + } + result <<= 3; + result += (c - '0'); + s++; + } +} + +UInt64 ConvertHexStringToUInt64(const char *s, const char **end) +{ + UInt64 result = 0; + for (;;) + { + char c = *s; + UInt32 v; + if (c >= '0' && c <= '9') v = (c - '0'); + else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A'); + else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a'); + else + { + if (end != NULL) + *end = s; + return result; + } + result <<= 4; + result |= v; + s++; + } +} + + +UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) +{ + UInt64 result = 0; + for (;;) + { + wchar_t c = *s; + if (c < '0' || c > '9') + { + if (end != NULL) + *end = s; + return result; + } + result *= 10; + result += (c - '0'); + s++; + } +} + + +Int64 ConvertStringToInt64(const char *s, const char **end) +{ + if (*s == '-') + return -(Int64)ConvertStringToUInt64(s + 1, end); + return ConvertStringToUInt64(s, end); +} diff --git a/CPP/Common/StringToInt.h b/CPP/Common/StringToInt.h new file mode 100755 index 0000000..16a1a4f --- /dev/null +++ b/CPP/Common/StringToInt.h @@ -0,0 +1,18 @@ +// Common/StringToInt.h + +#ifndef __COMMON_STRINGTOINT_H +#define __COMMON_STRINGTOINT_H + +#include +#include "Types.h" + +UInt64 ConvertStringToUInt64(const char *s, const char **end); +UInt64 ConvertOctStringToUInt64(const char *s, const char **end); +UInt64 ConvertHexStringToUInt64(const char *s, const char **end); +UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end); + +Int64 ConvertStringToInt64(const char *s, const char **end); + +#endif + + diff --git a/CPP/Common/TextConfig.cpp b/CPP/Common/TextConfig.cpp new file mode 100755 index 0000000..16c2e7a --- /dev/null +++ b/CPP/Common/TextConfig.cpp @@ -0,0 +1,138 @@ +// Common/TextConfig.cpp + +#include "StdAfx.h" + +#include "TextConfig.h" + +#include "Defs.h" +#include "UTFConvert.h" + +static bool IsDelimitChar(char c) +{ + return (c == ' ' || c == 0x0A || c == 0x0D || + c == '\0' || c == '\t'); +} + +static AString GetIDString(const char *string, int &finishPos) +{ + AString result; + for (finishPos = 0; ; finishPos++) + { + char c = string[finishPos]; + if (IsDelimitChar(c) || c == '=') + break; + result += c; + } + return result; +} + +static bool WaitNextLine(const AString &string, int &pos) +{ + for (;pos < string.Length(); pos++) + if (string[pos] == 0x0A) + return true; + return false; +} + +static bool SkipSpaces(const AString &string, int &pos) +{ + for (;pos < string.Length(); pos++) + { + char c = string[pos]; + if (!IsDelimitChar(c)) + { + if (c != ';') + return true; + if (!WaitNextLine(string, pos)) + return false; + } + } + return false; +} + +bool GetTextConfig(const AString &string, CObjectVector &pairs) +{ + pairs.Clear(); + int pos = 0; + + ///////////////////// + // read strings + + for (;;) + { + if (!SkipSpaces(string, pos)) + break; + CTextConfigPair pair; + int finishPos; + AString temp = GetIDString(((const char *)string) + pos, finishPos); + if (!ConvertUTF8ToUnicode(temp, pair.ID)) + return false; + if (finishPos == 0) + return false; + pos += finishPos; + if (!SkipSpaces(string, pos)) + return false; + if (string[pos] != '=') + return false; + pos++; + if (!SkipSpaces(string, pos)) + return false; + if (string[pos] != '\"') + return false; + pos++; + AString message; + for (;;) + { + if (pos >= string.Length()) + return false; + char c = string[pos++]; + if (c == '\"') + break; + if (c == '\\') + { + char c = string[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 UString &id) +{ + for (int i = 0; i < pairs.Size(); i++) + if (pairs[i].ID.Compare(id) == 0) + return i; + return -1; +} + +UString GetTextConfigValue(const CObjectVector &pairs, const UString &id) +{ + int index = FindTextConfigItem(pairs, id); + if (index < 0) + return UString(); + return pairs[index].String; +} diff --git a/CPP/Common/TextConfig.h b/CPP/Common/TextConfig.h new file mode 100755 index 0000000..d61cf2f --- /dev/null +++ b/CPP/Common/TextConfig.h @@ -0,0 +1,22 @@ +// Common/TextConfig.h + +#ifndef __COMMON_TEXTCONFIG_H +#define __COMMON_TEXTCONFIG_H + +#include "MyVector.h" +#include "MyString.h" + +struct CTextConfigPair +{ + UString ID; + UString String; +}; + +bool GetTextConfig(const AString &text, CObjectVector &pairs); + +int FindTextConfigItem(const CObjectVector &pairs, const UString &id); +UString GetTextConfigValue(const CObjectVector &pairs, const UString &id); + +#endif + + diff --git a/CPP/Common/Types.h b/CPP/Common/Types.h new file mode 100755 index 0000000..fd00237 --- /dev/null +++ b/CPP/Common/Types.h @@ -0,0 +1,11 @@ +// Common/Types.h + +#ifndef __COMMON_TYPES_H +#define __COMMON_TYPES_H + +#include "../../C/Types.h" + +typedef int HRes; + +#endif + diff --git a/CPP/Common/UTFConvert.cpp b/CPP/Common/UTFConvert.cpp new file mode 100755 index 0000000..d3935b1 --- /dev/null +++ b/CPP/Common/UTFConvert.cpp @@ -0,0 +1,145 @@ +// UTFConvert.cpp + +#include "StdAfx.h" + +#include "UTFConvert.h" +#include "Types.h" + +static const Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + +static Bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, size_t srcLen) +{ + size_t destPos = 0, srcPos = 0; + for (;;) + { + Byte c; + int numAdds; + if (srcPos == srcLen) + { + *destLen = destPos; + return True; + } + c = (Byte)src[srcPos++]; + + if (c < 0x80) + { + if (dest) + dest[destPos] = (wchar_t)c; + destPos++; + continue; + } + if (c < 0xC0) + break; + for (numAdds = 1; numAdds < 5; numAdds++) + if (c < kUtf8Limits[numAdds]) + break; + UInt32 value = (c - kUtf8Limits[numAdds - 1]); + + do + { + Byte c2; + if (srcPos == srcLen) + break; + c2 = (Byte)src[srcPos++]; + if (c2 < 0x80 || c2 >= 0xC0) + break; + value <<= 6; + value |= (c2 - 0x80); + } + while (--numAdds != 0); + + if (value < 0x10000) + { + if (dest) + dest[destPos] = (wchar_t)value; + destPos++; + } + else + { + value -= 0x10000; + if (value >= 0x100000) + break; + if (dest) + { + dest[destPos + 0] = (wchar_t)(0xD800 + (value >> 10)); + dest[destPos + 1] = (wchar_t)(0xDC00 + (value & 0x3FF)); + } + destPos += 2; + } + } + *destLen = destPos; + return False; +} + +static Bool Utf16_To_Utf8(char *dest, size_t *destLen, const wchar_t *src, size_t srcLen) +{ + size_t destPos = 0, srcPos = 0; + for (;;) + { + unsigned numAdds; + UInt32 value; + if (srcPos == srcLen) + { + *destLen = destPos; + return True; + } + value = src[srcPos++]; + if (value < 0x80) + { + if (dest) + dest[destPos] = (char)value; + destPos++; + continue; + } + if (value >= 0xD800 && value < 0xE000) + { + UInt32 c2; + if (value >= 0xDC00 || srcPos == srcLen) + break; + c2 = src[srcPos++]; + if (c2 < 0xDC00 || c2 >= 0xE000) + break; + value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000; + } + for (numAdds = 1; numAdds < 5; numAdds++) + if (value < (((UInt32)1) << (numAdds * 5 + 6))) + break; + if (dest) + dest[destPos] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); + destPos++; + do + { + numAdds--; + if (dest) + dest[destPos] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); + destPos++; + } + while (numAdds != 0); + } + *destLen = destPos; + return False; +} + +bool ConvertUTF8ToUnicode(const AString &src, UString &dest) +{ + dest.Empty(); + size_t destLen = 0; + Utf8_To_Utf16(NULL, &destLen, src, src.Length()); + wchar_t *p = dest.GetBuffer((int)destLen); + Bool res = Utf8_To_Utf16(p, &destLen, src, src.Length()); + p[destLen] = 0; + dest.ReleaseBuffer(); + return res ? true : false; +} + +bool ConvertUnicodeToUTF8(const UString &src, AString &dest) +{ + dest.Empty(); + size_t destLen = 0; + Utf16_To_Utf8(NULL, &destLen, src, src.Length()); + char *p = dest.GetBuffer((int)destLen); + Bool res = Utf16_To_Utf8(p, &destLen, src, src.Length()); + p[destLen] = 0; + dest.ReleaseBuffer(); + return res ? true : false; +} diff --git a/CPP/Common/UTFConvert.h b/CPP/Common/UTFConvert.h new file mode 100755 index 0000000..d553101 --- /dev/null +++ b/CPP/Common/UTFConvert.h @@ -0,0 +1,11 @@ +// Common/UTFConvert.h + +#ifndef __COMMON_UTFCONVERT_H +#define __COMMON_UTFCONVERT_H + +#include "MyString.h" + +bool ConvertUTF8ToUnicode(const AString &utfString, UString &resultString); +bool ConvertUnicodeToUTF8(const UString &unicodeString, AString &resultString); + +#endif diff --git a/CPP/Common/Wildcard.cpp b/CPP/Common/Wildcard.cpp new file mode 100755 index 0000000..024d7a5 --- /dev/null +++ b/CPP/Common/Wildcard.cpp @@ -0,0 +1,462 @@ +// Common/Wildcard.cpp + +#include "StdAfx.h" + +#include "../../C/Types.h" + +#include "Wildcard.h" + +bool g_CaseSensitive = + #ifdef _WIN32 + false; + #else + true; + #endif + +static const wchar_t kAnyCharsChar = L'*'; +static const wchar_t kAnyCharChar = L'?'; + +#ifdef _WIN32 +static const wchar_t kDirDelimiter1 = L'\\'; +#endif +static const wchar_t kDirDelimiter2 = L'/'; + +static const UString kWildCardCharSet = L"?*"; + +static const UString kIllegalWildCardFileNameChars= + L"\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA\xB\xC\xD\xE\xF" + L"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" + L"\"/:<>\\|"; + + +static inline bool IsCharDirLimiter(wchar_t c) +{ + return ( + #ifdef _WIN32 + c == kDirDelimiter1 || + #endif + c == kDirDelimiter2); +} + +int CompareFileNames(const UString &s1, const UString &s2) +{ + if (g_CaseSensitive) + return s1.Compare(s2); + return s1.CompareNoCase(s2); +} + +// ----------------------------------------- +// 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 == kAnyCharsChar) + { + if (EnhancedMaskTest(mask + 1, name)) + return true; + if (c == 0) + return false; + } + else + { + if (m == kAnyCharChar) + { + 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(); + UString name; + int len = path.Length(); + if (len == 0) + return; + for (int i = 0; i < len; i++) + { + wchar_t c = path[i]; + if (IsCharDirLimiter(c)) + { + pathParts.Add(name); + name.Empty(); + } + else + name += c; + } + pathParts.Add(name); +} + +void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name) +{ + int i; + for (i = path.Length() - 1; i >= 0; i--) + if (IsCharDirLimiter(path[i])) + break; + dirPrefix = path.Left(i + 1); + name = path.Mid(i + 1); +} + +UString ExtractDirPrefixFromPath(const UString &path) +{ + int i; + for (i = path.Length() - 1; i >= 0; i--) + if (IsCharDirLimiter(path[i])) + break; + return path.Left(i + 1); +} + +UString ExtractFileNameFromPath(const UString &path) +{ + int i; + for (i = path.Length() - 1; i >= 0; i--) + if (IsCharDirLimiter(path[i])) + break; + return path.Mid(i + 1); +} + + +bool CompareWildCardWithName(const UString &mask, const UString &name) +{ + return EnhancedMaskTest(mask, name); +} + +bool DoesNameContainWildCard(const UString &path) +{ + return (path.FindOneOf(kWildCardCharSet) >= 0); +} + + +// ----------------------------------------------------------' +// NWildcard + +namespace NWildcard { + + +/* +M = MaskParts.Size(); +N = TestNameParts.Size(); + + File Dir +ForFile req M<=N [N-M, N) - + nonreq M=N [0, M) - + +ForDir req M 1) + return true; + } + return false; +} + +bool CCensorNode::AreThereIncludeItems() const +{ + if (IncludeItems.Size() > 0) + return true; + for (int i = 0; i < SubNodes.Size(); i++) + 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 (int i = 0; i < items.Size(); i++) + if (items[i].CheckPath(pathParts, isFile)) + return true; + return false; +} + +bool CCensorNode::CheckPath(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].CheckPath(pathParts2, isFile, include)) + return true; + } + return finded; +} + +bool CCensorNode::CheckPath(const UString &path, bool isFile, bool &include) const +{ + UStringVector pathParts; + SplitPathToParts(path, pathParts); + return CheckPath(pathParts, isFile, include); +} + +bool CCensorNode::CheckPath(const UString &path, bool isFile) const +{ + bool include; + if (CheckPath(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) +{ + if (path.IsEmpty()) + return; + bool forFile = true; + bool forFolder = true; + UString path2 = path; + if (IsCharDirLimiter(path[path.Length() - 1])) + { + path2.Delete(path.Length() - 1); + forFile = false; + } + AddItem(include, path2, recursive, forFile, forFolder); +} + +void CCensorNode::ExtendExclude(const CCensorNode &fromNodes) +{ + ExcludeItems += fromNodes.ExcludeItems; + for (int i = 0; i < fromNodes.SubNodes.Size(); i++) + { + 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 (int i = 0; i < Pairs.Size(); i++) + if (CompareFileNames(Pairs[i].Prefix, prefix) == 0) + return i; + return -1; +} + +void CCensor::AddItem(bool include, const UString &path, bool recursive) +{ + UStringVector pathParts; + if (path.IsEmpty()) + throw "Empty file path"; + SplitPathToParts(path, pathParts); + bool forFile = true; + if (pathParts.Back().IsEmpty()) + { + forFile = false; + pathParts.DeleteBack(); + } + const UString &front = pathParts.Front(); + bool isAbs = false; + if (front.IsEmpty()) + isAbs = true; + else if (front.Length() == 2 && front[1] == L':') + isAbs = true; + else + { + for (int i = 0; i < pathParts.Size(); i++) + { + const UString &part = pathParts[i]; + if (part == L".." || part == L".") + { + isAbs = true; + break; + } + } + } + int numAbsParts = 0; + if (isAbs) + if (pathParts.Size() > 1) + numAbsParts = pathParts.Size() - 1; + else + numAbsParts = 1; + UString prefix; + for (int i = 0; i < numAbsParts; i++) + { + const UString &front = pathParts.Front(); + if (DoesNameContainWildCard(front)) + break; + prefix += front; + prefix += WCHAR_PATH_SEPARATOR; + pathParts.Delete(0); + } + int index = FindPrefix(prefix); + if (index < 0) + index = Pairs.Add(CPair(prefix)); + + CItem item; + item.PathParts = pathParts; + item.ForDir = true; + item.ForFile = forFile; + item.Recursive = recursive; + Pairs[index].Head.AddItem(include, item); +} + +bool CCensor::CheckPath(const UString &path, bool isFile) const +{ + bool finded = false; + for (int i = 0; i < Pairs.Size(); i++) + { + bool include; + if (Pairs[i].Head.CheckPath(path, isFile, include)) + { + if (!include) + return false; + finded = true; + } + } + return finded; +} + +void CCensor::ExtendExclude() +{ + int i; + for (i = 0; i < Pairs.Size(); i++) + if (Pairs[i].Prefix.IsEmpty()) + break; + if (i == Pairs.Size()) + return; + int index = i; + for (i = 0; i < Pairs.Size(); i++) + if (index != i) + Pairs[i].Head.ExtendExclude(Pairs[index].Head); +} + +} diff --git a/CPP/Common/Wildcard.h b/CPP/Common/Wildcard.h new file mode 100755 index 0000000..e2a42c8 --- /dev/null +++ b/CPP/Common/Wildcard.h @@ -0,0 +1,80 @@ +// Common/Wildcard.h + +#ifndef __COMMON_WILDCARD_H +#define __COMMON_WILDCARD_H + +#include "MyString.h" + +int CompareFileNames(const UString &s1, const UString &s2); + +void SplitPathToParts(const UString &path, UStringVector &pathParts); +void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name); +UString ExtractDirPrefixFromPath(const UString &path); +UString ExtractFileNameFromPath(const UString &path); +bool DoesNameContainWildCard(const UString &path); +bool CompareWildCardWithName(const UString &mask, const UString &name); + +namespace NWildcard { + +struct CItem +{ + UStringVector PathParts; + bool Recursive; + bool ForFile; + bool ForDir; + 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); + bool CheckPath(UStringVector &pathParts, bool isFile, bool &include) const; +public: + CCensorNode(): Parent(0) { }; + CCensorNode(const UString &name, CCensorNode *parent): Name(name), Parent(parent) { }; + UString Name; + CObjectVector SubNodes; + CObjectVector IncludeItems; + CObjectVector ExcludeItems; + + int FindSubNode(const UString &path) const; + + void AddItem(bool include, CItem &item); + void AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir); + void AddItem2(bool include, const UString &path, bool recursive); + + bool NeedCheckSubDirs() const; + bool AreThereIncludeItems() const; + + bool CheckPath(const UString &path, bool isFile, bool &include) const; + bool CheckPath(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) { }; +}; + +class CCensor +{ + int FindPrefix(const UString &prefix) const; +public: + CObjectVector Pairs; + bool AllAreRelative() const + { return (Pairs.Size() == 1 && Pairs.Front().Prefix.IsEmpty()); } + void AddItem(bool include, const UString &path, bool recursive); + bool CheckPath(const UString &path, bool isFile) const; + void ExtendExclude(); +}; + +} + +#endif diff --git a/CPP/Windows/COM.cpp b/CPP/Windows/COM.cpp new file mode 100755 index 0000000..78a1ac8 --- /dev/null +++ b/CPP/Windows/COM.cpp @@ -0,0 +1,37 @@ +// Windows/COM.cpp + +#include "StdAfx.h" + +#include "Windows/COM.h" +#include "Common/StringConvert.h" + +namespace NWindows { +namespace NCOM { + +// CoInitialize (NULL); must be called! + +UString GUIDToStringW(REFGUID guid) +{ + UString string; + const int kStringSize = 48; + StringFromGUID2(guid, string.GetBuffer(kStringSize), kStringSize); + string.ReleaseBuffer(); + return string; +} + +AString GUIDToStringA(REFGUID guid) +{ + return UnicodeStringToMultiByte(GUIDToStringW(guid)); +} + +HRESULT StringToGUIDW(const wchar_t *string, GUID &classID) +{ + return CLSIDFromString((wchar_t *)string, &classID); +} + +HRESULT StringToGUIDA(const char *string, GUID &classID) +{ + return StringToGUIDW(MultiByteToUnicodeString(string), classID); +} + +}} diff --git a/CPP/Windows/COM.h b/CPP/Windows/COM.h new file mode 100755 index 0000000..c963431 --- /dev/null +++ b/CPP/Windows/COM.h @@ -0,0 +1,69 @@ +// 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/CPP/Windows/Clipboard.cpp b/CPP/Windows/Clipboard.cpp new file mode 100755 index 0000000..01cdeb3 --- /dev/null +++ b/CPP/Windows/Clipboard.cpp @@ -0,0 +1,135 @@ +// Windows/Clipboard.cpp + +#include "StdAfx.h" + +#ifdef UNDER_CE +#include +#endif + +#include "Windows/Clipboard.h" +#include "Windows/Defs.h" +#include "Windows/Memory.h" +#include "Windows/Shell.h" +#include "Windows/Memory.h" + +#include "Common/StringConvert.h" + +namespace NWindows { + +bool CClipboard::Open(HWND wndNewOwner) +{ + m_Open = BOOLToBool(::OpenClipboard(wndNewOwner)); + return m_Open; +} + +CClipboard::~CClipboard() +{ + Close(); +} + +bool CClipboard::Close() +{ + if (!m_Open) + return true; + m_Open = !BOOLToBool(CloseClipboard()); + return !m_Open; +} + +bool ClipboardIsFormatAvailableHDROP() +{ + return BOOLToBool(IsClipboardFormatAvailable(CF_HDROP)); +} + +/* +bool ClipboardGetTextString(AString &s) +{ + s.Empty(); + if (!IsClipboardFormatAvailable(CF_TEXT)) + return false; + CClipboard clipboard; + + if (!clipboard.Open(NULL)) + return false; + + HGLOBAL h = ::GetClipboardData(CF_TEXT); + if (h != NULL) + { + NMemory::CGlobalLock globalLock(h); + const char *p = (const char *)globalLock.GetPointer(); + if (p != NULL) + { + s = p; + return true; + } + } + return false; +} +*/ + +/* +bool ClipboardGetFileNames(UStringVector &names) +{ + names.Clear(); + if (!IsClipboardFormatAvailable(CF_HDROP)) + return false; + CClipboard clipboard; + + if (!clipboard.Open(NULL)) + return false; + + HGLOBAL h = ::GetClipboardData(CF_HDROP); + if (h != NULL) + { + NMemory::CGlobalLock globalLock(h); + void *p = (void *)globalLock.GetPointer(); + if (p != NULL) + { + NShell::CDrop drop(false); + drop.Attach((HDROP)p); + drop.QueryFileNames(names); + return true; + } + } + return false; +} +*/ + +static bool ClipboardSetData(UINT uFormat, const void *data, size_t size) +{ + NMemory::CGlobal global; + if (!global.Alloc(GMEM_DDESHARE | GMEM_MOVEABLE, size)) + return false; + { + NMemory::CGlobalLock globalLock(global); + LPVOID p = globalLock.GetPointer(); + if (p == NULL) + return false; + memcpy(p, data, size); + } + if (::SetClipboardData(uFormat, global) == NULL) + return false; + global.Detach(); + return true; +} + +bool ClipboardSetText(HWND owner, const UString &s) +{ + CClipboard clipboard; + if (!clipboard.Open(owner)) + return false; + if (!::EmptyClipboard()) + return false; + + bool res; + res = ClipboardSetData(CF_UNICODETEXT, (const wchar_t *)s, (s.Length() + 1) * sizeof(wchar_t)); + #ifndef _UNICODE + AString a; + a = UnicodeStringToMultiByte(s, CP_ACP); + res |= ClipboardSetData(CF_TEXT, (const char *)a, (a.Length() + 1) * sizeof(char)); + a = UnicodeStringToMultiByte(s, CP_OEMCP); + res |= ClipboardSetData(CF_OEMTEXT, (const char *)a, (a.Length() + 1) * sizeof(char)); + #endif + return res; +} + +} diff --git a/CPP/Windows/Clipboard.h b/CPP/Windows/Clipboard.h new file mode 100755 index 0000000..c168412 --- /dev/null +++ b/CPP/Windows/Clipboard.h @@ -0,0 +1,28 @@ +// Windows/Clipboard.h + +#ifndef __CLIPBOARD_H +#define __CLIPBOARD_H + +#include "Common/MyString.h" + +namespace NWindows { + +class CClipboard +{ + bool m_Open; +public: + CClipboard(): m_Open(false) {}; + ~CClipboard(); + bool Open(HWND wndNewOwner); + bool Close(); +}; + +bool ClipboardIsFormatAvailableHDROP(); + +// bool ClipboardGetFileNames(UStringVector &names); +// bool ClipboardGetTextString(AString &s); +bool ClipboardSetText(HWND owner, const UString &s); + +} + +#endif diff --git a/CPP/Windows/CommonDialog.cpp b/CPP/Windows/CommonDialog.cpp new file mode 100755 index 0000000..34f4a31 --- /dev/null +++ b/CPP/Windows/CommonDialog.cpp @@ -0,0 +1,184 @@ +// Windows/CommonDialog.cpp + +#include "StdAfx.h" + +#ifdef UNDER_CE +#include +#endif + +#ifndef _UNICODE +#include "Common/StringConvert.h" +#endif +#include "Common/MyCom.h" + +#include "Windows/Defs.h" + +#include "CommonDialog.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows{ + +#ifndef _UNICODE +class CDoubleZeroStringListA +{ + CRecordVector m_Indexes; + AString m_String; +public: + void Add(LPCSTR s); + void SetForBuffer(LPSTR buffer); +}; + +void CDoubleZeroStringListA::Add(LPCSTR s) +{ + m_String += s; + m_Indexes.Add(m_String.Length()); + m_String += ' '; +} + +void CDoubleZeroStringListA::SetForBuffer(LPSTR buffer) +{ + MyStringCopy(buffer, (const char *)m_String); + for (int i = 0; i < m_Indexes.Size(); i++) + buffer[m_Indexes[i]] = '\0'; +} +#endif + +class CDoubleZeroStringListW +{ + CRecordVector m_Indexes; + UString m_String; +public: + void Add(LPCWSTR s); + void SetForBuffer(LPWSTR buffer); +}; + +void CDoubleZeroStringListW::Add(LPCWSTR s) +{ + m_String += s; + m_Indexes.Add(m_String.Length()); + m_String += L' '; +} + +void CDoubleZeroStringListW::SetForBuffer(LPWSTR buffer) +{ + MyStringCopy(buffer, (const wchar_t *)m_String); + for (int i = 0; i < m_Indexes.Size(); i++) + buffer[m_Indexes[i]] = L'\0'; +} + +#define MY_OFN_PROJECT 0x00400000 +#define MY_OFN_SHOW_ALL 0x01000000 + +bool MyGetOpenFileName(HWND hwnd, LPCWSTR title, LPCWSTR fullFileName, + LPCWSTR s, UString &resPath + #ifdef UNDER_CE + , bool openFolder + #endif + ) +{ + const int kBufferSize = MAX_PATH * 2; + #ifndef _UNICODE + if (!g_IsNT) + { + CHAR buffer[kBufferSize]; + MyStringCopy(buffer, (const char *)GetSystemString(fullFileName)); + OPENFILENAME info; + info.lStructSize = sizeof(info); + info.hwndOwner = hwnd; + info.hInstance = 0; + const int kFilterBufferSize = MAX_PATH; + CHAR filterBuffer[kFilterBufferSize]; + CDoubleZeroStringListA doubleZeroStringList; + doubleZeroStringList.Add(GetSystemString(s)); + doubleZeroStringList.Add("*.*"); + doubleZeroStringList.SetForBuffer(filterBuffer); + info.lpstrFilter = filterBuffer; + + info.lpstrCustomFilter = NULL; + info.nMaxCustFilter = 0; + info.nFilterIndex = 0; + + info.lpstrFile = buffer; + info.nMaxFile = kBufferSize; + + info.lpstrFileTitle = NULL; + info.nMaxFileTitle = 0; + + info.lpstrInitialDir= NULL; + + info.lpstrTitle = 0; + AString titleA; + if (title != 0) + { + titleA = GetSystemString(title); + info.lpstrTitle = titleA; + } + + info.Flags = OFN_EXPLORER | OFN_HIDEREADONLY; + info.nFileOffset = 0; + info.nFileExtension = 0; + info.lpstrDefExt = NULL; + + info.lCustData = 0; + info.lpfnHook = NULL; + info.lpTemplateName = NULL; + + bool res = BOOLToBool(::GetOpenFileNameA(&info)); + resPath = GetUnicodeString(buffer); + return res; + } + else + #endif + { + WCHAR buffer[kBufferSize]; + MyStringCopy(buffer, fullFileName); + OPENFILENAMEW info; + info.lStructSize = sizeof(info); + info.hwndOwner = hwnd; + info.hInstance = 0; + const int kFilterBufferSize = MAX_PATH; + WCHAR filterBuffer[kFilterBufferSize]; + CDoubleZeroStringListW doubleZeroStringList; + doubleZeroStringList.Add(s); + doubleZeroStringList.Add(L"*.*"); + doubleZeroStringList.SetForBuffer(filterBuffer); + info.lpstrFilter = filterBuffer; + + info.lpstrCustomFilter = NULL; + info.nMaxCustFilter = 0; + info.nFilterIndex = 0; + + info.lpstrFile = buffer; + info.nMaxFile = kBufferSize; + + info.lpstrFileTitle = NULL; + info.nMaxFileTitle = 0; + + info.lpstrInitialDir= NULL; + + info.lpstrTitle = title; + + info.Flags = OFN_EXPLORER | OFN_HIDEREADONLY + #ifdef UNDER_CE + | (openFolder ? (MY_OFN_PROJECT | MY_OFN_SHOW_ALL) : 0) + #endif + ; + + info.nFileOffset = 0; + info.nFileExtension = 0; + info.lpstrDefExt = NULL; + + info.lCustData = 0; + info.lpfnHook = NULL; + info.lpTemplateName = NULL; + + bool res = BOOLToBool(::GetOpenFileNameW(&info)); + resPath = buffer; + return res; + } +} + +} diff --git a/CPP/Windows/CommonDialog.h b/CPP/Windows/CommonDialog.h new file mode 100755 index 0000000..bf87180 --- /dev/null +++ b/CPP/Windows/CommonDialog.h @@ -0,0 +1,19 @@ +// 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 fullFileName, + LPCWSTR s, UString &resPath + #ifdef UNDER_CE + , bool openFolder = false + #endif +); + +} + +#endif diff --git a/CPP/Windows/Console.cpp b/CPP/Windows/Console.cpp new file mode 100755 index 0000000..fb2830c --- /dev/null +++ b/CPP/Windows/Console.cpp @@ -0,0 +1,10 @@ +// Windows/Console.cpp + +#include "StdAfx.h" + +#include "Windows/Console.h" + +namespace NWindows{ +namespace NConsole{ + +}} diff --git a/CPP/Windows/Console.h b/CPP/Windows/Console.h new file mode 100755 index 0000000..9000471 --- /dev/null +++ b/CPP/Windows/Console.h @@ -0,0 +1,52 @@ +// Windows/Console.h + +#ifndef __WINDOWS_CONSOLE_H +#define __WINDOWS_CONSOLE_H + +#include "Windows/Defs.h" + +namespace NWindows{ +namespace NConsole{ + +class CBase +{ +protected: + HANDLE m_Object; +public: + void Attach(HANDLE aHandle) { m_Object = aHandle; }; + bool GetMode(DWORD &aMode) + { return BOOLToBool(::GetConsoleMode(m_Object, &aMode)); } + bool SetMode(DWORD aMode) + { return BOOLToBool(::SetConsoleMode(m_Object, aMode)); } +}; + +class CIn: public CBase +{ +public: + bool PeekEvents(PINPUT_RECORD anEvents, DWORD aNumEvents, DWORD &aNumEventsRead) + { return BOOLToBool(::PeekConsoleInput(m_Object, anEvents, aNumEvents, &aNumEventsRead)); } + bool PeekEvent(INPUT_RECORD &anEvent, DWORD &aNumEventsRead) + { return PeekEvents(&anEvent, 1, aNumEventsRead); } + bool ReadEvents(PINPUT_RECORD anEvents, DWORD aNumEvents, DWORD &aNumEventsRead) + { return BOOLToBool(::ReadConsoleInput(m_Object, anEvents, aNumEvents, &aNumEventsRead)); } + bool ReadEvent(INPUT_RECORD &anEvent, DWORD &aNumEventsRead) + { return ReadEvents(&anEvent, 1, aNumEventsRead); } + bool GetNumberOfEvents(DWORD &aNumberOfEvents) + { return BOOLToBool(::GetNumberOfConsoleInputEvents(m_Object, &aNumberOfEvents)); } + + bool WriteEvents(const INPUT_RECORD *anEvents, DWORD aNumEvents, DWORD &aNumEventsWritten) + { return BOOLToBool(::WriteConsoleInput(m_Object, anEvents, aNumEvents, &aNumEventsWritten)); } + bool WriteEvent(const INPUT_RECORD &anEvent, DWORD &aNumEventsWritten) + { return WriteEvents(&anEvent, 1, aNumEventsWritten); } + + bool Read(LPVOID aBuffer, DWORD aNumberOfCharsToRead, DWORD &aNumberOfCharsRead) + { return BOOLToBool(::ReadConsole(m_Object, aBuffer, aNumberOfCharsToRead, &aNumberOfCharsRead, NULL)); } + + bool Flush() + { return BOOLToBool(::FlushConsoleInputBuffer(m_Object)); } + +}; + +}} + +#endif diff --git a/CPP/Windows/Control/ComboBox.cpp b/CPP/Windows/Control/ComboBox.cpp new file mode 100755 index 0000000..62ff2a1 --- /dev/null +++ b/CPP/Windows/Control/ComboBox.cpp @@ -0,0 +1,58 @@ +// Windows/Control/ComboBox.cpp + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "Common/StringConvert.h" +#endif + +#include "Windows/Control/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); + if (len == CB_ERR) + return len; + len = GetLBText(index, s.GetBuffer((int)len + 1)); + s.ReleaseBuffer(); + return len; +} + +#ifndef _UNICODE +LRESULT CComboBox::AddString(LPCWSTR s) +{ + if (g_IsNT) + return SendMessageW(CB_ADDSTRING, 0, (LPARAM)s); + return AddString(GetSystemString(s)); +} + +LRESULT CComboBox::GetLBText(int index, UString &s) +{ + s.Empty(); + if (g_IsNT) + { + LRESULT len = SendMessageW(CB_GETLBTEXTLEN, index, 0); + if (len == CB_ERR) + return len; + len = SendMessageW(CB_GETLBTEXT, index, (LPARAM)s.GetBuffer((int)len + 1)); + s.ReleaseBuffer(); + return len; + } + AString sa; + LRESULT len = GetLBText(index, sa); + if (len == CB_ERR) + return len; + s = GetUnicodeString(sa); + return s.Length(); +} +#endif + +}} diff --git a/CPP/Windows/Control/ComboBox.h b/CPP/Windows/Control/ComboBox.h new file mode 100755 index 0000000..10f769f --- /dev/null +++ b/CPP/Windows/Control/ComboBox.h @@ -0,0 +1,61 @@ +// Windows/Control/ComboBox.h + +#ifndef __WINDOWS_CONTROL_COMBOBOX_H +#define __WINDOWS_CONTROL_COMBOBOX_H + +#include + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CComboBox: public CWindow +{ +public: + void ResetContent() { SendMessage(CB_RESETCONTENT, 0, 0); } + LRESULT AddString(LPCTSTR s) { return SendMessage(CB_ADDSTRING, 0, (LPARAM)s); } + #ifndef _UNICODE + LRESULT AddString(LPCWSTR s); + #endif + LRESULT SetCurSel(int index) { return SendMessage(CB_SETCURSEL, index, 0); } + int GetCurSel() { return (int)SendMessage(CB_GETCURSEL, 0, 0); } + int GetCount() { return (int)SendMessage(CB_GETCOUNT, 0, 0); } + + LRESULT GetLBTextLen(int index) { return SendMessage(CB_GETLBTEXTLEN, index, 0); } + LRESULT GetLBText(int index, LPTSTR s) { return SendMessage(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 SendMessage(CB_SETITEMDATA, index, lParam); } + LRESULT GetItemData(int index) { return SendMessage(CB_GETITEMDATA, index, 0); } + + void ShowDropDown(bool show = true) { SendMessage(CB_SHOWDROPDOWN, show ? TRUE : FALSE, 0); } +}; + +#ifndef UNDER_CE + +class CComboBoxEx: public CComboBox +{ +public: + bool SetUnicodeFormat(bool fUnicode) { return LRESULTToBool(SendMessage(CBEM_SETUNICODEFORMAT, BOOLToBool(fUnicode), 0)); } + + LRESULT DeleteItem(int index) { return SendMessage(CBEM_DELETEITEM, index, 0); } + LRESULT InsertItem(COMBOBOXEXITEM *item) { return SendMessage(CBEM_INSERTITEM, 0, (LPARAM)item); } + #ifndef _UNICODE + LRESULT InsertItem(COMBOBOXEXITEMW *item) { return SendMessage(CBEM_INSERTITEMW, 0, (LPARAM)item); } + #endif + + LRESULT SetItem(COMBOBOXEXITEM *item) { return SendMessage(CBEM_SETITEM, 0, (LPARAM)item); } + DWORD SetExtendedStyle(DWORD exMask, DWORD exStyle) { return (DWORD)SendMessage(CBEM_SETEXTENDEDSTYLE, exMask, exStyle); } + HWND GetEditControl() { return (HWND)SendMessage(CBEM_GETEDITCONTROL, 0, 0); } + HIMAGELIST SetImageList(HIMAGELIST imageList) { return (HIMAGELIST)SendMessage(CBEM_SETIMAGELIST, 0, (LPARAM)imageList); } +}; + +#endif + +}} + +#endif diff --git a/CPP/Windows/Control/CommandBar.h b/CPP/Windows/Control/CommandBar.h new file mode 100755 index 0000000..218130a --- /dev/null +++ b/CPP/Windows/Control/CommandBar.h @@ -0,0 +1,48 @@ +// Windows/Control/CommandBar.h + +#ifndef __WINDOWS_CONTROL_COMMANDBAR_H +#define __WINDOWS_CONTROL_COMMANDBAR_H + +#ifdef UNDER_CE + +#include "Windows/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(int iButton, UINT numButtons, LPTBBUTTON buttons) { return BOOLToBool(SendMessage(TB_ADDBUTTONS, (WPARAM)numButtons, (LPARAM)buttons)); } + bool InsertButton(int iButton, LPTBBUTTON button) { return BOOLToBool(SendMessage(TB_INSERTBUTTON, (WPARAM)iButton, (LPARAM)button)); } + BOOL AddToolTips(UINT numToolTips, LPTSTR toolTips) { return BOOLToBool(SendMessage(TB_SETTOOLTIPS, (WPARAM)numToolTips, (LPARAM)toolTips)); } + void AutoSize() { SendMessage(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/CPP/Windows/Control/Dialog.cpp b/CPP/Windows/Control/Dialog.cpp new file mode 100755 index 0000000..f0209f0 --- /dev/null +++ b/CPP/Windows/Control/Dialog.cpp @@ -0,0 +1,201 @@ +// Windows/Control/Dialog.cpp + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "Common/StringConvert.h" +#endif +#include "Windows/Control/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 dialogTmp(dialogHWND); + if (message == WM_INITDIALOG) + dialogTmp.SetUserDataLongPtr(lParam); + CDialog *dialog = (CDialog *)(dialogTmp.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 IDHELP: OnHelp(); break; + default: return false; + } + return true; +} + +static bool GetWorkAreaRect(RECT *rect) +{ + // use another function for multi-monitor. + return BOOLToBool(::SystemParametersInfo(SPI_GETWORKAREA, NULL, rect, NULL)); +} + +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; +} + +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/CPP/Windows/Control/Dialog.h b/CPP/Windows/Control/Dialog.h new file mode 100755 index 0000000..b4c5e4f --- /dev/null +++ b/CPP/Windows/Control/Dialog.h @@ -0,0 +1,205 @@ +// Windows/Control/Dialog.h + +#ifndef __WINDOWS_CONTROL_DIALOG_H +#define __WINDOWS_CONTROL_DIALOG_H + +#include "Windows/Window.h" + +namespace NWindows { +namespace NControl { + +class CDialog: public CWindow +{ +public: + CDialog(HWND wndow = NULL): CWindow(wndow){}; + 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 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 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) + { + 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 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 GetItemSizes(int id, int &x, int &y) + { + RECT rect; + if (!::GetWindowRect(GetItem(id), &rect)) + return false; + x = rect.right - rect.left; + y = rect.bottom - rect.top; + return true; + } + + void GetClientRectOfItem(int id, RECT &rect) + { + ::GetWindowRect(GetItem(id), &rect); + ScreenToClient(&rect); + } + + + bool MoveItem(int id, int x, int y, int width, int height, bool repaint = true) + { return BOOLToBool(::MoveWindow(GetItem(id), x, y, width, height, BoolToBOOL(repaint))); } + + 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(); } +}; + +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); } +}; + +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/CPP/Windows/Control/Edit.h b/CPP/Windows/Control/Edit.h new file mode 100755 index 0000000..fc12b8d --- /dev/null +++ b/CPP/Windows/Control/Edit.h @@ -0,0 +1,19 @@ +// Windows/Control/Edit.h + +#ifndef __WINDOWS_CONTROL_EDIT_H +#define __WINDOWS_CONTROL_EDIT_H + +#include "Windows/Window.h" + +namespace NWindows { +namespace NControl { + +class CEdit: public CWindow +{ +public: + void SetPasswordChar(WPARAM c) { SendMessage(EM_SETPASSWORDCHAR, c); } +}; + +}} + +#endif diff --git a/CPP/Windows/Control/ImageList.cpp b/CPP/Windows/Control/ImageList.cpp new file mode 100755 index 0000000..8aa39c4 --- /dev/null +++ b/CPP/Windows/Control/ImageList.cpp @@ -0,0 +1,11 @@ +// Windows/Control/ImageList.cpp + +#include "StdAfx.h" + +#include "Windows/Control/ImageList.h" + +namespace NWindows { +namespace NControl { + +}} + diff --git a/CPP/Windows/Control/ImageList.h b/CPP/Windows/Control/ImageList.h new file mode 100755 index 0000000..2ac528b --- /dev/null +++ b/CPP/Windows/Control/ImageList.h @@ -0,0 +1,85 @@ +// Windows/Control/ImageList.h + +#ifndef __WINDOWS_CONTROL_IMAGELIST_H +#define __WINDOWS_CONTROL_IMAGELIST_H + +#include "Windows/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/CPP/Windows/Control/ListView.cpp b/CPP/Windows/Control/ListView.cpp new file mode 100755 index 0000000..08af2b1 --- /dev/null +++ b/CPP/Windows/Control/ListView.cpp @@ -0,0 +1,96 @@ +// Windows/Control/ListView.cpp + +#include "StdAfx.h" + +#include "Windows/Control/ListView.h" + +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 + +}} diff --git a/CPP/Windows/Control/ListView.h b/CPP/Windows/Control/ListView.h new file mode 100755 index 0000000..fc0e7de --- /dev/null +++ b/CPP/Windows/Control/ListView.h @@ -0,0 +1,109 @@ +// Windows/Control/ListView.h + +#ifndef __WINDOWS_CONTROL_LISTVIEW_H +#define __WINDOWS_CONTROL_LISTVIEW_H + +#include "Windows/Window.h" + +#include + +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); + + #ifndef UNDER_CE + bool SetUnicodeFormat(bool fUnicode) { return BOOLToBool(ListView_SetUnicodeFormat(_window, BOOLToBool(fUnicode))); } + #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); + 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)SendMessage(LVM_INSERTCOLUMNW, (WPARAM)columnIndex, (LPARAM)columnInfo); } + int InsertColumn(int columnIndex, LPCWSTR text, int width); + int InsertItem(const LV_ITEMW* item) { return (int)SendMessage(LVM_INSERTITEMW, 0, (LPARAM)item); } + int InsertItem(int index, LPCWSTR text); + bool SetItem(const LV_ITEMW* item) { return BOOLToBool((BOOL)SendMessage(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_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 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); } +}; + +}} + +#endif diff --git a/CPP/Windows/Control/ProgressBar.h b/CPP/Windows/Control/ProgressBar.h new file mode 100755 index 0000000..71dc912 --- /dev/null +++ b/CPP/Windows/Control/ProgressBar.h @@ -0,0 +1,31 @@ +// Windows/Control/ProgressBar.h + +#ifndef __WINDOWS_CONTROL_PROGRESSBAR_H +#define __WINDOWS_CONTROL_PROGRESSBAR_H + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CProgressBar: public CWindow +{ +public: + LRESULT SetPos(int pos) { return SendMessage(PBM_SETPOS, pos, 0); } + LRESULT DeltaPos(int increment) { return SendMessage(PBM_DELTAPOS, increment, 0); } + UINT GetPos() { return (UINT)SendMessage(PBM_GETPOS, 0, 0); } + LRESULT SetRange(unsigned short minValue, unsigned short maxValue) { return SendMessage(PBM_SETRANGE, 0, MAKELPARAM(minValue, maxValue)); } + DWORD SetRange32(int minValue, int maxValue) { return (DWORD)SendMessage(PBM_SETRANGE32, minValue, maxValue); } + int SetStep(int step) { return (int)SendMessage(PBM_SETSTEP, step, 0); } + LRESULT StepIt() { return SendMessage(PBM_STEPIT, 0, 0); } + INT GetRange(bool minValue, PPBRANGE range) { return (INT)SendMessage(PBM_GETRANGE, BoolToBOOL(minValue), (LPARAM)range); } + + #ifndef UNDER_CE + COLORREF SetBarColor(COLORREF color) { return (COLORREF)SendMessage(PBM_SETBARCOLOR, 0, color); } + COLORREF SetBackgroundColor(COLORREF color) { return (COLORREF)SendMessage(PBM_SETBKCOLOR, 0, color); } + #endif +}; + +}} + +#endif diff --git a/CPP/Windows/Control/PropertyPage.cpp b/CPP/Windows/Control/PropertyPage.cpp new file mode 100755 index 0000000..d95ed58 --- /dev/null +++ b/CPP/Windows/Control/PropertyPage.cpp @@ -0,0 +1,162 @@ +// Windows/Control/PropertyPage.cpp + +#include "StdAfx.h" + +#include "Windows/Control/PropertyPage.h" +#ifndef _UNICODE +#include "../../Common/StringConvert.h" +#endif + +extern HINSTANCE g_hInstance; +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NControl { + +INT_PTR APIENTRY ProperyPageProcedure(HWND dialogHWND, UINT message, + WPARAM wParam, LPARAM lParam) +{ + CDialog tempDialog(dialogHWND); + if (message == WM_INITDIALOG) + tempDialog.SetUserDataLongPtr(((PROPSHEETPAGE *)lParam)->lParam); + CDialog *dialog = (CDialog *)(tempDialog.GetUserDataLongPtr()); + if (message == WM_INITDIALOG) + dialog->Attach(dialogHWND); + switch (message) + { + case WM_INITDIALOG: + return dialog->OnInit(); + case WM_COMMAND: + return dialog->OnCommand(wParam, lParam); + case WM_NOTIFY: + return dialog->OnNotify((UINT)wParam, (LPNMHDR) lParam); + } + if (dialog == NULL) + return false; + return dialog->OnMessage(message, wParam, lParam); +} + +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; + + int 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::ProperyPageProcedure; + + 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::ProperyPageProcedure; + + 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/CPP/Windows/Control/PropertyPage.h b/CPP/Windows/Control/PropertyPage.h new file mode 100755 index 0000000..4687ed9 --- /dev/null +++ b/CPP/Windows/Control/PropertyPage.h @@ -0,0 +1,46 @@ +// Windows/Control/PropertyPage.h + +#ifndef __WINDOWS_CONTROL_PROPERTYPAGE_H +#define __WINDOWS_CONTROL_PROPERTYPAGE_H + +#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/CPP/Windows/Control/ReBar.h b/CPP/Windows/Control/ReBar.h new file mode 100755 index 0000000..a8f14b8 --- /dev/null +++ b/CPP/Windows/Control/ReBar.h @@ -0,0 +1,35 @@ +// Windows/Control/ReBar.h + +#ifndef __WINDOWS_CONTROL_REBAR_H +#define __WINDOWS_CONTROL_REBAR_H + +#include "Windows/Window.h" +#include "Windows/Defs.h" + +namespace NWindows { +namespace NControl { + +class CReBar: public NWindows::CWindow +{ +public: + bool SetBarInfo(LPREBARINFO barInfo) + { return LRESULTToBool(SendMessage(RB_SETBARINFO, 0, (LPARAM)barInfo)); } + bool InsertBand(int index, LPREBARBANDINFO bandInfo) + { return LRESULTToBool(SendMessage(RB_INSERTBAND, index, (LPARAM)bandInfo)); } + bool SetBandInfo(int index, LPREBARBANDINFO bandInfo) + { return LRESULTToBool(SendMessage(RB_SETBANDINFO, index, (LPARAM)bandInfo)); } + void MaximizeBand(int index, bool ideal) + { SendMessage(RB_MAXIMIZEBAND, index, BoolToBOOL(ideal)); } + bool SizeToRect(LPRECT rect) + { return LRESULTToBool(SendMessage(RB_SIZETORECT, 0, (LPARAM)rect)); } + UINT GetHeight() + { return (UINT)SendMessage(RB_GETBARHEIGHT); } + UINT GetBandCount() + { return (UINT)SendMessage(RB_GETBANDCOUNT); } + bool DeleteBand(UINT index) + { return LRESULTToBool(SendMessage(RB_DELETEBAND, index)); } +}; + +}} + +#endif diff --git a/CPP/Windows/Control/Static.h b/CPP/Windows/Control/Static.h new file mode 100755 index 0000000..355b9e8 --- /dev/null +++ b/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)SendMessage(STM_SETIMAGE, imageType, (LPARAM)handle); } + HANDLE GetImage(WPARAM imageType) { return (HANDLE)SendMessage(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)SendMessage(STM_SETICON, (WPARAM)icon, 0); } + HICON GetIcon() { return (HICON)SendMessage(STM_GETICON, 0, 0); } + #endif +}; + +}} + +#endif diff --git a/CPP/Windows/Control/StatusBar.h b/CPP/Windows/Control/StatusBar.h new file mode 100755 index 0000000..9c88d36 --- /dev/null +++ b/CPP/Windows/Control/StatusBar.h @@ -0,0 +1,43 @@ +// Windows/Control/StatusBar.h + +#ifndef __WINDOWS_CONTROL_STATUSBAR_H +#define __WINDOWS_CONTROL_STATUSBAR_H + +#include "Windows/Window.h" +#include "Windows/Defs.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 SetParts(int numParts, const int *edgePostions) + { return LRESULTToBool(SendMessage(SB_SETPARTS, numParts, (LPARAM)edgePostions)); } + bool SetText(LPCTSTR text) + { return CWindow::SetText(text); } + + bool SetText(int index, LPCTSTR text, UINT type) + { return LRESULTToBool(SendMessage(SB_SETTEXT, index | type, (LPARAM)text)); } + bool SetText(int index, LPCTSTR text) + { return SetText(index, text, 0); } + void Simple(bool simple) + { SendMessage(SB_SIMPLE, BoolToBOOL(simple), 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(int index, LPCWSTR text, UINT type) + { return LRESULTToBool(SendMessage(SB_SETTEXTW, index | type, (LPARAM)text)); } + bool SetText(int index, LPCWSTR text) + { return SetText(index, text, 0); } + #endif +}; + +}} + +#endif diff --git a/CPP/Windows/Control/StdAfx.h b/CPP/Windows/Control/StdAfx.h new file mode 100755 index 0000000..f56e92f --- /dev/null +++ b/CPP/Windows/Control/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../Common/MyWindows.h" +#include "../../Common/NewHandler.h" + +#endif diff --git a/CPP/Windows/Control/ToolBar.h b/CPP/Windows/Control/ToolBar.h new file mode 100755 index 0000000..3aefd9b --- /dev/null +++ b/CPP/Windows/Control/ToolBar.h @@ -0,0 +1,43 @@ +// Windows/Control/ToolBar.h + +#ifndef __WINDOWS_CONTROL_TOOLBAR_H +#define __WINDOWS_CONTROL_TOOLBAR_H + +#include "Windows/Window.h" + +namespace NWindows { +namespace NControl { + +class CToolBar: public NWindows::CWindow +{ +public: + void AutoSize() { SendMessage(TB_AUTOSIZE, 0, 0); } + DWORD GetButtonSize() { return (DWORD)SendMessage(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(SendMessage(TB_GETMAXSIZE, 0, (LPARAM)size)); + } + #endif + + bool EnableButton(UINT buttonID, bool enable) { return LRESULTToBool(SendMessage(TB_ENABLEBUTTON, buttonID, MAKELONG(BoolToBOOL(enable), 0))); } + void ButtonStructSize() { SendMessage(TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON)); } + HIMAGELIST SetImageList(UINT listIndex, HIMAGELIST imageList) { return HIMAGELIST(SendMessage(TB_SETIMAGELIST, listIndex, (LPARAM)imageList)); } + bool AddButton(UINT numButtons, LPTBBUTTON buttons) { return LRESULTToBool(SendMessage(TB_ADDBUTTONS, numButtons, (LPARAM)buttons)); } + #ifndef _UNICODE + bool AddButtonW(UINT numButtons, LPTBBUTTON buttons) { return LRESULTToBool(SendMessage(TB_ADDBUTTONSW, numButtons, (LPARAM)buttons)); } + #endif +}; + +}} + +#endif diff --git a/CPP/Windows/Control/Trackbar.h b/CPP/Windows/Control/Trackbar.h new file mode 100755 index 0000000..6f03a69 --- /dev/null +++ b/CPP/Windows/Control/Trackbar.h @@ -0,0 +1,28 @@ +// Windows/Control/Trackbar.h + +#ifndef __WINDOWS_CONTROL_TRACKBAR_H +#define __WINDOWS_CONTROL_TRACKBAR_H + +#include "Windows/Window.h" +#include "Windows/Defs.h" + +namespace NWindows { +namespace NControl { + +class CTrackbar: public CWindow +{ +public: + void SetRange(int minimum, int maximum, bool redraw = true) + { SendMessage(TBM_SETRANGE, BoolToBOOL(redraw), MAKELONG(minimum, maximum)); } + void SetPos(int pos, bool redraw = true) + { SendMessage(TBM_SETPOS, BoolToBOOL(redraw), pos); } + void SetTicFreq(int freq) + { SendMessage(TBM_SETTICFREQ, freq); } + + int GetPos() + { return (int)SendMessage(TBM_GETPOS); } +}; + +}} + +#endif diff --git a/CPP/Windows/Control/Window2.cpp b/CPP/Windows/Control/Window2.cpp new file mode 100755 index 0000000..7f928b0 --- /dev/null +++ b/CPP/Windows/Control/Window2.cpp @@ -0,0 +1,209 @@ +// Windows/Control/Window2.cpp + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "Common/StringConvert.h" +#endif +#include "Windows/Control/Window2.h" + +// extern HINSTANCE g_hInstance; +#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 windowClass; + if (!::GetClassInfo(instance, className, &windowClass)) + { + // windowClass.style = CS_HREDRAW | CS_VREDRAW; + windowClass.style = 0; + + windowClass.lpfnWndProc = WindowProcedure; + windowClass.cbClsExtra = NULL; + windowClass.cbWndExtra = NULL; + windowClass.hInstance = instance; + windowClass.hIcon = NULL; + windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); + windowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + windowClass.lpszMenuName = NULL; + windowClass.lpszClassName = className; + if (::RegisterClass(&windowClass) == 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 windowClass; + needRegister = ::GetClassInfoW(instance, className, &windowClass) == 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 windowClass; + // windowClass.style = CS_HREDRAW | CS_VREDRAW; + windowClass.style = 0; + windowClass.lpfnWndProc = WindowProcedure; + windowClass.cbClsExtra = NULL; + windowClass.cbWndExtra = NULL; + windowClass.hInstance = instance; + windowClass.hIcon = NULL; + windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); + windowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + windowClass.lpszMenuName = NULL; + windowClass.lpszClassName = className; + if (MyRegisterClass(&windowClass) == 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(aButtonID) + { + case IDOK: + OnOK(); + break; + case IDCANCEL: + OnCancel(); + break; + case IDHELP: + OnHelp(); + break; + default: + return false; + } + return true; +} + +*/ + +}} diff --git a/CPP/Windows/Control/Window2.h b/CPP/Windows/Control/Window2.h new file mode 100755 index 0000000..b0aca17 --- /dev/null +++ b/CPP/Windows/Control/Window2.h @@ -0,0 +1,58 @@ +// Windows/Control/Window2.h + +#ifndef __WINDOWS_CONTROL_WINDOW2_H +#define __WINDOWS_CONTROL_WINDOW2_H + +#include "Windows/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/CPP/Windows/DLL.cpp b/CPP/Windows/DLL.cpp new file mode 100755 index 0000000..6aaedb0 --- /dev/null +++ b/CPP/Windows/DLL.cpp @@ -0,0 +1,110 @@ +// Windows/DLL.cpp + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "../Common/StringConvert.h" +#endif + +#include "DLL.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NDLL { + +bool CLibrary::Free() +{ + if (_module == 0) + return true; + // MessageBox(0, TEXT(""), TEXT("Free"), 0); + // Sleep(5000); + if (!::FreeLibrary(_module)) + return false; + _module = 0; + return true; +} + +bool CLibrary::LoadOperations(HMODULE newModule) +{ + if (newModule == NULL) + return false; + if (!Free()) + return false; + _module = newModule; + return true; +} + +bool CLibrary::LoadEx(LPCTSTR fileName, DWORD flags) +{ + // MessageBox(0, fileName, TEXT("LoadEx"), 0); + return LoadOperations(::LoadLibraryEx(fileName, NULL, flags)); +} + +bool CLibrary::Load(LPCTSTR fileName) +{ + // MessageBox(0, fileName, TEXT("Load"), 0); + // Sleep(5000); + // OutputDebugString(fileName); + // OutputDebugString(TEXT("\n")); + return LoadOperations(::LoadLibrary(fileName)); +} + +#ifndef _UNICODE +static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } +CSysString GetSysPath(LPCWSTR sysPath) + { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } + +bool CLibrary::LoadEx(LPCWSTR fileName, DWORD flags) +{ + if (g_IsNT) + return LoadOperations(::LoadLibraryExW(fileName, NULL, flags)); + return LoadEx(GetSysPath(fileName), flags); +} +bool CLibrary::Load(LPCWSTR fileName) +{ + if (g_IsNT) + return LoadOperations(::LoadLibraryW(fileName)); + return Load(GetSysPath(fileName)); +} +#endif + +bool MyGetModuleFileName(HMODULE hModule, CSysString &result) +{ + result.Empty(); + TCHAR fullPath[MAX_PATH + 2]; + DWORD size = ::GetModuleFileName(hModule, fullPath, MAX_PATH + 1); + if (size <= MAX_PATH && size != 0) + { + result = fullPath; + return true; + } + return false; +} + +#ifndef _UNICODE +bool MyGetModuleFileName(HMODULE hModule, UString &result) +{ + result.Empty(); + if (g_IsNT) + { + wchar_t fullPath[MAX_PATH + 2]; + DWORD size = ::GetModuleFileNameW(hModule, fullPath, MAX_PATH + 1); + if (size <= MAX_PATH && size != 0) + { + result = fullPath; + return true; + } + return false; + } + CSysString resultSys; + if (!MyGetModuleFileName(hModule, resultSys)) + return false; + result = MultiByteToUnicodeString(resultSys, GetCurrentCodePage()); + return true; +} +#endif + +}} diff --git a/CPP/Windows/DLL.h b/CPP/Windows/DLL.h new file mode 100755 index 0000000..7d02887 --- /dev/null +++ b/CPP/Windows/DLL.h @@ -0,0 +1,59 @@ +// 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, proceName) GetProcAddressA(module, proceName) +#else +#define My_GetProcAddress(module, proceName) ::GetProcAddress(module, proceName) +#endif + +class CLibrary +{ + bool LoadOperations(HMODULE newModule); +protected: + HMODULE _module; +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(); + bool LoadEx(LPCTSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); + bool Load(LPCTSTR fileName); + #ifndef _UNICODE + bool LoadEx(LPCWSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); + bool Load(LPCWSTR fileName); + #endif + FARPROC GetProc(LPCSTR procName) const { return My_GetProcAddress(_module, procName); } +}; + +bool MyGetModuleFileName(HMODULE hModule, CSysString &result); +#ifndef _UNICODE +bool MyGetModuleFileName(HMODULE hModule, UString &result); +#endif + +}} + +#endif diff --git a/CPP/Windows/Defs.h b/CPP/Windows/Defs.h new file mode 100755 index 0000000..f3d692f --- /dev/null +++ b/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/CPP/Windows/Error.cpp b/CPP/Windows/Error.cpp new file mode 100755 index 0000000..fcba1e6 --- /dev/null +++ b/CPP/Windows/Error.cpp @@ -0,0 +1,50 @@ +// Windows/Error.h + +#include "StdAfx.h" + +#include "Windows/Error.h" +#ifndef _UNICODE +#include "Common/StringConvert.h" +#endif + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NError { + +bool MyFormatMessage(DWORD messageID, CSysString &message) +{ + LPVOID msgBuf; + if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL,messageID, 0, (LPTSTR) &msgBuf,0, NULL) == 0) + return false; + message = (LPCTSTR)msgBuf; + ::LocalFree(msgBuf); + return true; +} + +#ifndef _UNICODE +bool MyFormatMessage(DWORD messageID, UString &message) +{ + if (g_IsNT) + { + LPVOID msgBuf; + if (::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, messageID, 0, (LPWSTR) &msgBuf, 0, NULL) == 0) + return false; + message = (LPCWSTR)msgBuf; + ::LocalFree(msgBuf); + return true; + } + CSysString messageSys; + bool result = MyFormatMessage(messageID, messageSys); + message = GetUnicodeString(messageSys); + return result; +} +#endif + +}} diff --git a/CPP/Windows/Error.h b/CPP/Windows/Error.h new file mode 100755 index 0000000..d916e8e --- /dev/null +++ b/CPP/Windows/Error.h @@ -0,0 +1,33 @@ +// Windows/Error.h + +#ifndef __WINDOWS_ERROR_H +#define __WINDOWS_ERROR_H + +#include "Common/MyString.h" + +namespace NWindows { +namespace NError { + +bool MyFormatMessage(DWORD messageID, CSysString &message); +inline CSysString MyFormatMessage(DWORD messageID) +{ + CSysString message; + MyFormatMessage(messageID, message); + return message; +} +#ifdef _UNICODE +inline UString MyFormatMessageW(DWORD messageID) + { return MyFormatMessage(messageID); } +#else +bool MyFormatMessage(DWORD messageID, UString &message); +inline UString MyFormatMessageW(DWORD messageID) +{ + UString message; + MyFormatMessage(messageID, message); + return message; +} +#endif + +}} + +#endif diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp new file mode 100755 index 0000000..daec1d3 --- /dev/null +++ b/CPP/Windows/FileDir.cpp @@ -0,0 +1,909 @@ +// 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 + +namespace NWindows { +namespace NFile { + +#if defined(WIN_LONG_PATH) && defined(_UNICODE) +#define WIN_LONG_PATH2 +#endif + +// SetCurrentDirectory doesn't support \\?\ prefix + +#ifdef WIN_LONG_PATH +bool GetLongPathBase(LPCWSTR fileName, UString &res); +bool GetLongPath(LPCWSTR fileName, UString &res); +#endif + +namespace NDirectory { + +#ifndef _UNICODE +static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } +static UString GetUnicodePath(const CSysString &sysPath) + { return MultiByteToUnicodeString(sysPath, GetCurrentCodePage()); } +static CSysString GetSysPath(LPCWSTR sysPath) + { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } +#endif + +#ifndef UNDER_CE + +bool MyGetWindowsDirectory(CSysString &path) +{ + UINT needLength = ::GetWindowsDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); + path.ReleaseBuffer(); + return (needLength > 0 && needLength <= MAX_PATH); +} + +bool MyGetSystemDirectory(CSysString &path) +{ + UINT needLength = ::GetSystemDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); + path.ReleaseBuffer(); + return (needLength > 0 && needLength <= MAX_PATH); +} + +#endif + +#ifndef _UNICODE +bool MyGetWindowsDirectory(UString &path) +{ + if (g_IsNT) + { + UINT needLength = ::GetWindowsDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); + path.ReleaseBuffer(); + return (needLength > 0 && needLength <= MAX_PATH); + } + CSysString sysPath; + if (!MyGetWindowsDirectory(sysPath)) + return false; + path = GetUnicodePath(sysPath); + return true; +} + +bool MyGetSystemDirectory(UString &path) +{ + if (g_IsNT) + { + UINT needLength = ::GetSystemDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); + path.ReleaseBuffer(); + return (needLength > 0 && needLength <= MAX_PATH); + } + CSysString sysPath; + if (!MyGetSystemDirectory(sysPath)) + return false; + path = GetUnicodePath(sysPath); + return true; +} +#endif + +bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return false; + } + #endif + HANDLE hDir = ::CreateFileW(fileName, 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) + { + UString longPath; + if (GetLongPath(fileName, longPath)) + hDir = ::CreateFileW(longPath, 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 MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes) +{ + if (::SetFileAttributes(fileName, fileAttributes)) + return true; + #ifdef WIN_LONG_PATH2 + UString longPath; + if (GetLongPath(fileName, longPath)) + return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); + #endif + return false; +} + +bool MyRemoveDirectory(LPCTSTR pathName) +{ + if (::RemoveDirectory(pathName)) + return true; + #ifdef WIN_LONG_PATH2 + UString longPath; + if (GetLongPath(pathName, longPath)) + return BOOLToBool(::RemoveDirectoryW(longPath)); + #endif + return false; +} + +#ifdef WIN_LONG_PATH +bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2) +{ + if (!GetLongPathBase(s1, d1) || !GetLongPathBase(s2, d2)) + return false; + if (d1.IsEmpty() && d2.IsEmpty()) return false; + if (d1.IsEmpty()) d1 = s1; + if (d2.IsEmpty()) d2 = s2; + return true; +} +#endif + +bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName) +{ + if (::MoveFile(existFileName, newFileName)) + return true; + #ifdef WIN_LONG_PATH2 + UString d1, d2; + if (GetLongPaths(existFileName, newFileName, d1, d2)) + return BOOLToBool(::MoveFileW(d1, d2)); + #endif + return false; +} + +#ifndef _UNICODE +bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes) +{ + if (!g_IsNT) + return MySetFileAttributes(GetSysPath(fileName), fileAttributes); + if (::SetFileAttributesW(fileName, fileAttributes)) + return true; + #ifdef WIN_LONG_PATH + UString longPath; + if (GetLongPath(fileName, longPath)) + return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); + #endif + return false; +} + + +bool MyRemoveDirectory(LPCWSTR pathName) +{ + if (!g_IsNT) + return MyRemoveDirectory(GetSysPath(pathName)); + if (::RemoveDirectoryW(pathName)) + return true; + #ifdef WIN_LONG_PATH + UString longPath; + if (GetLongPath(pathName, longPath)) + return BOOLToBool(::RemoveDirectoryW(longPath)); + #endif + return false; +} + +bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName) +{ + if (!g_IsNT) + return MyMoveFile(GetSysPath(existFileName), GetSysPath(newFileName)); + if (::MoveFileW(existFileName, newFileName)) + return true; + #ifdef WIN_LONG_PATH + UString d1, d2; + if (GetLongPaths(existFileName, newFileName, d1, d2)) + return BOOLToBool(::MoveFileW(d1, d2)); + #endif + return false; +} +#endif + +bool MyCreateDirectory(LPCTSTR pathName) +{ + if (::CreateDirectory(pathName, NULL)) + return true; + #ifdef WIN_LONG_PATH2 + if (::GetLastError() != ERROR_ALREADY_EXISTS) + { + UString longPath; + if (GetLongPath(pathName, longPath)) + return BOOLToBool(::CreateDirectoryW(longPath, NULL)); + } + #endif + return false; +} + +#ifndef _UNICODE +bool MyCreateDirectory(LPCWSTR pathName) +{ + if (!g_IsNT) + return MyCreateDirectory(GetSysPath(pathName)); + if (::CreateDirectoryW(pathName, NULL)) + return true; + #ifdef WIN_LONG_PATH + if (::GetLastError() != ERROR_ALREADY_EXISTS) + { + UString longPath; + if (GetLongPath(pathName, longPath)) + return BOOLToBool(::CreateDirectoryW(longPath, NULL)); + } + #endif + return false; +} +#endif + +/* +bool CreateComplexDirectory(LPCTSTR pathName) +{ + NName::CParsedPath path; + path.ParsePath(pathName); + CSysString fullPath = path.Prefix; + DWORD errorCode = ERROR_SUCCESS; + for (int i = 0; i < path.PathParts.Size(); i++) + { + const CSysString &string = path.PathParts[i]; + if (string.IsEmpty()) + { + if (i != path.PathParts.Size() - 1) + return false; + return true; + } + fullPath += path.PathParts[i]; + if (!MyCreateDirectory(fullPath)) + { + DWORD errorCode = GetLastError(); + if (errorCode != ERROR_ALREADY_EXISTS) + return false; + } + fullPath += NName::kDirDelimiter; + } + return true; +} +*/ + +bool CreateComplexDirectory(LPCTSTR _aPathName) +{ + CSysString pathName = _aPathName; + int pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); + if (pos > 0 && pos == pathName.Length() - 1) + { + if (pathName.Length() == 3 && pathName[1] == ':') + return true; // Disk folder; + pathName.Delete(pos); + } + CSysString pathName2 = pathName; + pos = pathName.Length(); + for (;;) + { + if (MyCreateDirectory(pathName)) + break; + if (::GetLastError() == ERROR_ALREADY_EXISTS) + { + NFind::CFileInfo fileInfo; + if (!fileInfo.Find(pathName)) // For network folders + return true; + if (!fileInfo.IsDir()) + return false; + break; + } + pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); + if (pos < 0 || pos == 0) + return false; + if (pathName[pos - 1] == ':') + return false; + pathName = pathName.Left(pos); + } + pathName = pathName2; + while (pos < pathName.Length()) + { + pos = pathName.Find(TEXT(CHAR_PATH_SEPARATOR), pos + 1); + if (pos < 0) + pos = pathName.Length(); + if (!MyCreateDirectory(pathName.Left(pos))) + return false; + } + return true; +} + +#ifndef _UNICODE + +bool CreateComplexDirectory(LPCWSTR _aPathName) +{ + UString pathName = _aPathName; + int pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); + if (pos > 0 && pos == pathName.Length() - 1) + { + if (pathName.Length() == 3 && pathName[1] == L':') + return true; // Disk folder; + pathName.Delete(pos); + } + UString pathName2 = pathName; + pos = pathName.Length(); + for (;;) + { + if (MyCreateDirectory(pathName)) + break; + if (::GetLastError() == ERROR_ALREADY_EXISTS) + { + NFind::CFileInfoW fileInfo; + if (!fileInfo.Find(pathName)) // For network folders + return true; + if (!fileInfo.IsDir()) + return false; + break; + } + pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); + if (pos < 0 || pos == 0) + return false; + if (pathName[pos - 1] == L':') + return false; + pathName = pathName.Left(pos); + } + pathName = pathName2; + while (pos < pathName.Length()) + { + pos = pathName.Find(WCHAR_PATH_SEPARATOR, pos + 1); + if (pos < 0) + pos = pathName.Length(); + if (!MyCreateDirectory(pathName.Left(pos))) + return false; + } + return true; +} + +#endif + +bool DeleteFileAlways(LPCTSTR name) +{ + if (!MySetFileAttributes(name, 0)) + return false; + if (::DeleteFile(name)) + return true; + #ifdef WIN_LONG_PATH2 + UString longPath; + if (GetLongPath(name, longPath)) + return BOOLToBool(::DeleteFileW(longPath)); + #endif + return false; +} + +#ifndef _UNICODE +bool DeleteFileAlways(LPCWSTR name) +{ + if (!g_IsNT) + return DeleteFileAlways(GetSysPath(name)); + if (!MySetFileAttributes(name, 0)) + return false; + if (::DeleteFileW(name)) + return true; + #ifdef WIN_LONG_PATH + UString longPath; + if (GetLongPath(name, longPath)) + return BOOLToBool(::DeleteFileW(longPath)); + #endif + return false; +} +#endif + +static bool RemoveDirectorySubItems2(const CSysString pathPrefix, const NFind::CFileInfo &fileInfo) +{ + if (fileInfo.IsDir()) + return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); + return DeleteFileAlways(pathPrefix + fileInfo.Name); +} + +bool RemoveDirectoryWithSubItems(const CSysString &path) +{ + NFind::CFileInfo fileInfo; + CSysString pathPrefix = path + NName::kDirDelimiter; + { + NFind::CEnumerator enumerator(pathPrefix + TCHAR(NName::kAnyStringWildcard)); + while (enumerator.Next(fileInfo)) + if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) + return false; + } + if (!MySetFileAttributes(path, 0)) + return false; + return MyRemoveDirectory(path); +} + +#ifndef _UNICODE +static bool RemoveDirectorySubItems2(const UString pathPrefix, const NFind::CFileInfoW &fileInfo) +{ + if (fileInfo.IsDir()) + return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); + return DeleteFileAlways(pathPrefix + fileInfo.Name); +} +bool RemoveDirectoryWithSubItems(const UString &path) +{ + NFind::CFileInfoW fileInfo; + UString pathPrefix = path + UString(NName::kDirDelimiter); + { + NFind::CEnumeratorW enumerator(pathPrefix + UString(NName::kAnyStringWildcard)); + while (enumerator.Next(fileInfo)) + if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) + return false; + } + if (!MySetFileAttributes(path, 0)) + return false; + return MyRemoveDirectory(path); +} +#endif + +bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName) +{ + int index; + if (!MyGetFullPathName(fileName, resultName, index)) + return false; + resultName = resultName.Left(index); + return true; +} + +bool GetOnlyName(LPCTSTR fileName, CSysString &resultName) +{ + int index; + if (!MyGetFullPathName(fileName, resultName, index)) + return false; + resultName = resultName.Mid(index); + return true; +} + +#ifdef UNDER_CE +bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath) +{ + resultPath = fileName; + return true; +} + +bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex) +{ + resultPath = fileName; + // change it + fileNamePartStartIndex = resultPath.ReverseFind(WCHAR_PATH_SEPARATOR); + fileNamePartStartIndex++; + return true; +} + +#else + +bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath) +{ + DWORD needLength = ::GetShortPathName(longPath, shortPath.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); + shortPath.ReleaseBuffer(); + return (needLength > 0 && needLength < MAX_PATH); +} + +#ifdef WIN_LONG_PATH + +static UString GetLastPart(LPCWSTR path) +{ + int i = (int)wcslen(path); + for (; i > 0; i--) + { + WCHAR c = path[i - 1]; + if (c == WCHAR_PATH_SEPARATOR || c == '/') + break; + } + return path + i; +} + +static void AddTrailingDots(LPCWSTR oldPath, UString &newPath) +{ + int len = (int)wcslen(oldPath); + int i; + for (i = len; i > 0 && oldPath[i - 1] == '.'; i--); + if (i == 0 || i == len) + return; + UString oldName = GetLastPart(oldPath); + UString newName = GetLastPart(newPath); + int nonDotsLen = oldName.Length() - (len - i); + if (nonDotsLen == 0 || newName.CompareNoCase(oldName.Left(nonDotsLen)) != 0) + return; + for (; i != len; i++) + newPath += '.'; +} + +#endif + +bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex) +{ + resultPath.Empty(); + LPTSTR fileNamePointer = 0; + LPTSTR buffer = resultPath.GetBuffer(MAX_PATH); + DWORD needLength = ::GetFullPathName(fileName, MAX_PATH + 1, buffer, &fileNamePointer); + resultPath.ReleaseBuffer(); + if (needLength == 0) + return false; + if (needLength >= MAX_PATH) + { + #ifdef WIN_LONG_PATH2 + needLength++; + buffer = resultPath.GetBuffer(needLength + 1); + DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); + resultPath.ReleaseBuffer(); + if (needLength2 == 0 || needLength2 > needLength) + #endif + return false; + } + if (fileNamePointer == 0) + fileNamePartStartIndex = lstrlen(fileName); + else + fileNamePartStartIndex = (int)(fileNamePointer - buffer); + #ifdef _UNICODE + #ifdef WIN_LONG_PATH + AddTrailingDots(fileName, resultPath); + #endif + #endif + return true; +} + +#ifndef _UNICODE +bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex) +{ + resultPath.Empty(); + if (g_IsNT) + { + LPWSTR fileNamePointer = 0; + LPWSTR buffer = resultPath.GetBuffer(MAX_PATH); + DWORD needLength = ::GetFullPathNameW(fileName, MAX_PATH + 1, buffer, &fileNamePointer); + resultPath.ReleaseBuffer(); + if (needLength == 0) + return false; + if (needLength >= MAX_PATH) + { + #ifdef WIN_LONG_PATH + needLength++; + buffer = resultPath.GetBuffer(needLength + 1); + DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); + resultPath.ReleaseBuffer(); + if (needLength2 == 0 || needLength2 > needLength) + #endif + return false; + } + if (fileNamePointer == 0) + fileNamePartStartIndex = MyStringLen(fileName); + else + fileNamePartStartIndex = (int)(fileNamePointer - buffer); + #ifdef WIN_LONG_PATH + AddTrailingDots(fileName, resultPath); + #endif + } + else + { + CSysString sysPath; + if (!MyGetFullPathName(GetSysPath(fileName), sysPath, fileNamePartStartIndex)) + return false; + UString resultPath1 = GetUnicodePath(sysPath.Left(fileNamePartStartIndex)); + UString resultPath2 = GetUnicodePath(sysPath.Mid(fileNamePartStartIndex)); + fileNamePartStartIndex = resultPath1.Length(); + resultPath = resultPath1 + resultPath2; + } + return true; +} +#endif + + +bool MyGetFullPathName(LPCTSTR fileName, CSysString &path) +{ + int index; + return MyGetFullPathName(fileName, path, index); +} + +#ifndef _UNICODE +bool MyGetFullPathName(LPCWSTR fileName, UString &path) +{ + int index; + return MyGetFullPathName(fileName, path, index); +} +#endif + +#ifndef _UNICODE +bool GetOnlyName(LPCWSTR fileName, UString &resultName) +{ + int index; + if (!MyGetFullPathName(fileName, resultName, index)) + return false; + resultName = resultName.Mid(index); + return true; +} +#endif + +#ifndef _UNICODE +bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName) +{ + int index; + if (!MyGetFullPathName(fileName, resultName, index)) + return false; + resultName = resultName.Left(index); + return true; +} +#endif + +bool MyGetCurrentDirectory(CSysString &path) +{ + DWORD needLength = ::GetCurrentDirectory(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); + path.ReleaseBuffer(); + return (needLength > 0 && needLength <= MAX_PATH); +} + +#ifndef _UNICODE +bool MySetCurrentDirectory(LPCWSTR path) +{ + if (g_IsNT) + return BOOLToBool(::SetCurrentDirectoryW(path)); + return MySetCurrentDirectory(GetSysPath(path)); +} +bool MyGetCurrentDirectory(UString &path) +{ + if (g_IsNT) + { + DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); + path.ReleaseBuffer(); + return (needLength > 0 && needLength <= MAX_PATH); + } + CSysString sysPath; + if (!MyGetCurrentDirectory(sysPath)) + return false; + path = GetUnicodePath(sysPath); + return true; +} +#endif + +bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, + CSysString &resultPath, UINT32 &filePart) +{ + LPTSTR filePartPointer; + DWORD value = ::SearchPath(path, fileName, extension, + MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer); + filePart = (UINT32)(filePartPointer - (LPCTSTR)resultPath); + resultPath.ReleaseBuffer(); + return (value > 0 && value <= MAX_PATH); +} +#endif + +#ifndef _UNICODE +bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, + UString &resultPath, UINT32 &filePart) +{ + if (g_IsNT) + { + LPWSTR filePartPointer = 0; + DWORD value = ::SearchPathW(path, fileName, extension, + MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer); + filePart = (UINT32)(filePartPointer - (LPCWSTR)resultPath); + resultPath.ReleaseBuffer(); + return (value > 0 && value <= MAX_PATH); + } + + CSysString sysPath; + if (!MySearchPath( + path != 0 ? (LPCTSTR)GetSysPath(path): 0, + fileName != 0 ? (LPCTSTR)GetSysPath(fileName): 0, + extension != 0 ? (LPCTSTR)GetSysPath(extension): 0, + sysPath, filePart)) + return false; + UString resultPath1 = GetUnicodePath(sysPath.Left(filePart)); + UString resultPath2 = GetUnicodePath(sysPath.Mid(filePart)); + filePart = resultPath1.Length(); + resultPath = resultPath1 + resultPath2; + return true; +} +#endif + +bool MyGetTempPath(CSysString &path) +{ + DWORD needLength = ::GetTempPath(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); + path.ReleaseBuffer(); + return (needLength > 0 && needLength <= MAX_PATH); +} + +#ifndef _UNICODE +bool MyGetTempPath(UString &path) +{ + path.Empty(); + if (g_IsNT) + { + DWORD needLength = ::GetTempPathW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); + path.ReleaseBuffer(); + return (needLength > 0 && needLength <= MAX_PATH); + } + CSysString sysPath; + if (!MyGetTempPath(sysPath)) + return false; + path = GetUnicodePath(sysPath); + return true; +} +#endif + +UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &path) +{ + UINT number = ::GetTempFileName(dirPath, prefix, 0, path.GetBuffer(MAX_PATH + 1)); + path.ReleaseBuffer(); + return number; +} + +#ifndef _UNICODE +UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &path) +{ + if (g_IsNT) + { + UINT number = ::GetTempFileNameW(dirPath, prefix, 0, path.GetBuffer(MAX_PATH)); + path.ReleaseBuffer(); + return number; + } + CSysString sysPath; + UINT number = MyGetTempFileName( + dirPath ? (LPCTSTR)GetSysPath(dirPath): 0, + prefix ? (LPCTSTR)GetSysPath(prefix): 0, + sysPath); + path = GetUnicodePath(sysPath); + return number; +} +#endif + +UINT CTempFile::Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath) +{ + Remove(); + UINT number = MyGetTempFileName(dirPath, prefix, resultPath); + if (number != 0) + { + _fileName = resultPath; + _mustBeDeleted = true; + } + return number; +} + +bool CTempFile::Create(LPCTSTR prefix, CSysString &resultPath) +{ + CSysString tempPath; + if (!MyGetTempPath(tempPath)) + return false; + if (Create(tempPath, prefix, resultPath) != 0) + return true; + #ifdef UNDER_CE + return false; + #else + if (!MyGetWindowsDirectory(tempPath)) + return false; + return (Create(tempPath, prefix, resultPath) != 0); + #endif +} + +bool CTempFile::Remove() +{ + if (!_mustBeDeleted) + return true; + _mustBeDeleted = !DeleteFileAlways(_fileName); + return !_mustBeDeleted; +} + +#ifndef _UNICODE + +UINT CTempFileW::Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath) +{ + Remove(); + UINT number = MyGetTempFileName(dirPath, prefix, resultPath); + if (number != 0) + { + _fileName = resultPath; + _mustBeDeleted = true; + } + return number; +} + +bool CTempFileW::Create(LPCWSTR prefix, UString &resultPath) +{ + UString tempPath; + if (!MyGetTempPath(tempPath)) + return false; + if (Create(tempPath, prefix, resultPath) != 0) + return true; + if (!MyGetWindowsDirectory(tempPath)) + return false; + return (Create(tempPath, prefix, resultPath) != 0); +} + +bool CTempFileW::Remove() +{ + if (!_mustBeDeleted) + return true; + _mustBeDeleted = !DeleteFileAlways(_fileName); + return !_mustBeDeleted; +} + +#endif + +bool CreateTempDirectory(LPCTSTR prefix, CSysString &dirName) +{ + /* + CSysString prefix = tempPath + prefixChars; + CRandom random; + random.Init(); + */ + for (;;) + { + { + CTempFile tempFile; + if (!tempFile.Create(prefix, dirName)) + return false; + if (!tempFile.Remove()) + return false; + } + /* + UINT32 randomNumber = random.Generate(); + TCHAR randomNumberString[32]; + _stprintf(randomNumberString, _T("%04X"), randomNumber); + dirName = prefix + randomNumberString; + */ + if (NFind::DoesFileOrDirExist(dirName)) + continue; + if (MyCreateDirectory(dirName)) + return true; + if (::GetLastError() != ERROR_ALREADY_EXISTS) + return false; + } +} + +bool CTempDirectory::Create(LPCTSTR prefix) +{ + Remove(); + return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); +} + +#ifndef _UNICODE + +bool CreateTempDirectory(LPCWSTR prefix, UString &dirName) +{ + /* + CSysString prefix = tempPath + prefixChars; + CRandom random; + random.Init(); + */ + for (;;) + { + { + CTempFileW tempFile; + if (!tempFile.Create(prefix, dirName)) + return false; + if (!tempFile.Remove()) + return false; + } + /* + UINT32 randomNumber = random.Generate(); + TCHAR randomNumberString[32]; + _stprintf(randomNumberString, _T("%04X"), randomNumber); + dirName = prefix + randomNumberString; + */ + if (NFind::DoesFileOrDirExist(dirName)) + continue; + if (MyCreateDirectory(dirName)) + return true; + if (::GetLastError() != ERROR_ALREADY_EXISTS) + return false; + } +} + +bool CTempDirectoryW::Create(LPCWSTR prefix) +{ + Remove(); + return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); +} + +#endif + +}}} diff --git a/CPP/Windows/FileDir.h b/CPP/Windows/FileDir.h new file mode 100755 index 0000000..2c15071 --- /dev/null +++ b/CPP/Windows/FileDir.h @@ -0,0 +1,177 @@ +// Windows/FileDir.h + +#ifndef __WINDOWS_FILEDIR_H +#define __WINDOWS_FILEDIR_H + +#include "../Common/MyString.h" +#include "Defs.h" + +namespace NWindows { +namespace NFile { +namespace NDirectory { + +#ifdef WIN_LONG_PATH +bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2); +#endif + +bool MyGetWindowsDirectory(CSysString &path); +bool MyGetSystemDirectory(CSysString &path); +#ifndef _UNICODE +bool MyGetWindowsDirectory(UString &path); +bool MyGetSystemDirectory(UString &path); +#endif + +bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); + +bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes); +bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName); +bool MyRemoveDirectory(LPCTSTR pathName); +bool MyCreateDirectory(LPCTSTR pathName); +bool CreateComplexDirectory(LPCTSTR pathName); +bool DeleteFileAlways(LPCTSTR name); +bool RemoveDirectoryWithSubItems(const CSysString &path); + +#ifndef _UNICODE +bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes); +bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName); +bool MyRemoveDirectory(LPCWSTR pathName); +bool MyCreateDirectory(LPCWSTR pathName); +bool CreateComplexDirectory(LPCWSTR pathName); +bool DeleteFileAlways(LPCWSTR name); +bool RemoveDirectoryWithSubItems(const UString &path); +#endif + +bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName); +bool GetOnlyName(LPCTSTR fileName, CSysString &resultName); +#ifdef UNDER_CE +bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath); +bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex); +#else +bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath); + +bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex); +bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath); +#ifndef _UNICODE +bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, + int &fileNamePartStartIndex); +bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath); +bool GetOnlyName(LPCWSTR fileName, UString &resultName); +bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName); +#endif + +inline bool MySetCurrentDirectory(LPCTSTR path) + { return BOOLToBool(::SetCurrentDirectory(path)); } +bool MyGetCurrentDirectory(CSysString &resultPath); +#ifndef _UNICODE +bool MySetCurrentDirectory(LPCWSTR path); +bool MyGetCurrentDirectory(UString &resultPath); +#endif + +bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath, UINT32 &filePart); +#ifndef _UNICODE +bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath, UINT32 &filePart); +#endif + +inline bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath) +{ + UINT32 value; + return MySearchPath(path, fileName, extension, resultPath, value); +} + +#ifndef _UNICODE +inline bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath) +{ + UINT32 value; + return MySearchPath(path, fileName, extension, resultPath, value); +} +#endif + +#endif + +bool MyGetTempPath(CSysString &resultPath); +#ifndef _UNICODE +bool MyGetTempPath(UString &resultPath); +#endif + +UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath); +#ifndef _UNICODE +UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath); +#endif + +class CTempFile +{ + bool _mustBeDeleted; + CSysString _fileName; +public: + CTempFile(): _mustBeDeleted(false) {} + ~CTempFile() { Remove(); } + void DisableDeleting() { _mustBeDeleted = false; } + UINT Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath); + bool Create(LPCTSTR prefix, CSysString &resultPath); + bool Remove(); +}; + +#ifdef _UNICODE +typedef CTempFile CTempFileW; +#else +class CTempFileW +{ + bool _mustBeDeleted; + UString _fileName; +public: + CTempFileW(): _mustBeDeleted(false) {} + ~CTempFileW() { Remove(); } + void DisableDeleting() { _mustBeDeleted = false; } + UINT Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath); + bool Create(LPCWSTR prefix, UString &resultPath); + bool Remove(); +}; +#endif + +bool CreateTempDirectory(LPCTSTR prefixChars, CSysString &dirName); + +class CTempDirectory +{ + bool _mustBeDeleted; + CSysString _tempDir; +public: + const CSysString &GetPath() const { return _tempDir; } + CTempDirectory(): _mustBeDeleted(false) {} + ~CTempDirectory() { Remove(); } + bool Create(LPCTSTR prefix) ; + bool Remove() + { + if (!_mustBeDeleted) + return true; + _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir); + return (!_mustBeDeleted); + } + void DisableDeleting() { _mustBeDeleted = false; } +}; + +#ifdef _UNICODE +typedef CTempDirectory CTempDirectoryW; +#else +class CTempDirectoryW +{ + bool _mustBeDeleted; + UString _tempDir; +public: + const UString &GetPath() const { return _tempDir; } + CTempDirectoryW(): _mustBeDeleted(false) {} + ~CTempDirectoryW() { Remove(); } + bool Create(LPCWSTR prefix) ; + bool Remove() + { + if (!_mustBeDeleted) + return true; + _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir); + return (!_mustBeDeleted); + } + void DisableDeleting() { _mustBeDeleted = false; } +}; +#endif + +}}} + +#endif diff --git a/CPP/Windows/FileFind.cpp b/CPP/Windows/FileFind.cpp new file mode 100755 index 0000000..99fb706 --- /dev/null +++ b/CPP/Windows/FileFind.cpp @@ -0,0 +1,462 @@ +// Windows/FileFind.cpp + +#include "StdAfx.h" + +#include "FileFind.h" +#include "FileIO.h" +#ifndef _UNICODE +#include "../Common/StringConvert.h" +#endif + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NFile { + +#ifdef SUPPORT_DEVICE_FILE +bool IsDeviceName(LPCTSTR n); +#ifndef _UNICODE +bool IsDeviceName(LPCWSTR n); +#endif +#endif + +#if defined(WIN_LONG_PATH) && defined(_UNICODE) +#define WIN_LONG_PATH2 +#endif + +bool GetLongPath(LPCWSTR fileName, UString &res); + +namespace NFind { + +static const TCHAR kDot = TEXT('.'); + +bool CFileInfo::IsDots() const +{ + if (!IsDir() || Name.IsEmpty()) + return false; + if (Name[0] != kDot) + return false; + return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); +} + +#ifndef _UNICODE +bool CFileInfoW::IsDots() const +{ + if (!IsDir() || Name.IsEmpty()) + return false; + if (Name[0] != kDot) + return false; + return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); +} +#endif + +#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.IsDevice = false; + + /* + #ifdef UNDER_CE + fi.ObjectID = fd.dwOID; + #else + fi.ReparseTag = fd.dwReserved0; + #endif + */ + +static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi) +{ + WIN_FD_TO_MY_FI(fi, fd); + fi.Name = fd.cFileName; +} + +#ifndef _UNICODE + +static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } + +static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfoW &fi) +{ + WIN_FD_TO_MY_FI(fi, fd); + fi.Name = fd.cFileName; +} + +static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfoW &fi) +{ + WIN_FD_TO_MY_FI(fi, fd); + fi.Name = GetUnicodeString(fd.cFileName, GetCurrentCodePage()); +} +#endif + +//////////////////////////////// +// CFindFile + +bool CFindFile::Close() +{ + if (_handle == INVALID_HANDLE_VALUE) + return true; + if (!::FindClose(_handle)) + return false; + _handle = INVALID_HANDLE_VALUE; + return true; +} + + +bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fi) +{ + if (!Close()) + return false; + WIN32_FIND_DATA fd; + _handle = ::FindFirstFile(wildcard, &fd); + #ifdef WIN_LONG_PATH2 + if (_handle == INVALID_HANDLE_VALUE) + { + UString longPath; + if (GetLongPath(wildcard, longPath)) + _handle = ::FindFirstFileW(longPath, &fd); + } + #endif + if (_handle == INVALID_HANDLE_VALUE) + return false; + ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); + return true; +} + +#ifndef _UNICODE +bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fi) +{ + if (!Close()) + return false; + if (g_IsNT) + { + WIN32_FIND_DATAW fd; + _handle = ::FindFirstFileW(wildcard, &fd); + #ifdef WIN_LONG_PATH + if (_handle == INVALID_HANDLE_VALUE) + { + UString longPath; + if (GetLongPath(wildcard, longPath)) + _handle = ::FindFirstFileW(longPath, &fd); + } + #endif + if (_handle != INVALID_HANDLE_VALUE) + ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); + } + else + { + WIN32_FIND_DATAA fd; + _handle = ::FindFirstFileA(UnicodeStringToMultiByte(wildcard, + GetCurrentCodePage()), &fd); + if (_handle != INVALID_HANDLE_VALUE) + ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); + } + return (_handle != INVALID_HANDLE_VALUE); +} +#endif + +bool CFindFile::FindNext(CFileInfo &fi) +{ + WIN32_FIND_DATA fd; + bool result = BOOLToBool(::FindNextFile(_handle, &fd)); + if (result) + ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); + return result; +} + +#ifndef _UNICODE +bool CFindFile::FindNext(CFileInfoW &fi) +{ + if (g_IsNT) + { + WIN32_FIND_DATAW fd; + if (!::FindNextFileW(_handle, &fd)) + return false; + ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); + } + else + { + WIN32_FIND_DATAA fd; + if (!::FindNextFileA(_handle, &fd)) + return false; + ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); + } + return true; +} +#endif + +#define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0; + +void CFileInfoBase::Clear() +{ + Size = 0; + MY_CLEAR_FILETIME(CTime); + MY_CLEAR_FILETIME(ATime); + MY_CLEAR_FILETIME(MTime); + Attrib = 0; +} + +bool CFileInfo::Find(LPCTSTR wildcard) +{ + #ifdef SUPPORT_DEVICE_FILE + if (IsDeviceName(wildcard)) + { + Clear(); + IsDevice = true; + NIO::CInFile inFile; + if (!inFile.Open(wildcard)) + return false; + Name = wildcard + 4; + if (inFile.LengthDefined) + Size = inFile.Length; + return true; + } + #endif + CFindFile finder; + return finder.FindFirst(wildcard, *this); +} + + +#ifndef _UNICODE +bool CFileInfoW::Find(LPCWSTR wildcard) +{ + #ifdef SUPPORT_DEVICE_FILE + if (IsDeviceName(wildcard)) + { + Clear(); + IsDevice = true; + NIO::CInFile inFile; + if (!inFile.Open(wildcard)) + return false; + Name = wildcard + 4; + if (inFile.LengthDefined) + Size = inFile.Length; + return true; + } + #endif + CFindFile finder; + return finder.FindFirst(wildcard, *this); +} +#endif + +bool DoesFileExist(LPCTSTR name) +{ + CFileInfo fi; + return fi.Find(name) && !fi.IsDir(); +} + +bool DoesDirExist(LPCTSTR name) +{ + CFileInfo fi; + return fi.Find(name) && fi.IsDir(); +} + +bool DoesFileOrDirExist(LPCTSTR name) +{ + CFileInfo fi; + return fi.Find(name); +} + +#ifndef _UNICODE +bool DoesFileExist(LPCWSTR name) +{ + CFileInfoW fi; + return fi.Find(name) && !fi.IsDir(); +} + +bool DoesDirExist(LPCWSTR name) +{ + CFileInfoW fi; + return fi.Find(name) && fi.IsDir(); +} +bool DoesFileOrDirExist(LPCWSTR name) +{ + CFileInfoW fi; + return fi.Find(name); +} +#endif + +///////////////////////////////////// +// CEnumerator + +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); +} + +#ifndef _UNICODE +bool CEnumeratorW::NextAny(CFileInfoW &fi) +{ + if (_findFile.IsHandleAllocated()) + return _findFile.FindNext(fi); + else + return _findFile.FindFirst(_wildcard, fi); +} + +bool CEnumeratorW::Next(CFileInfoW &fi) +{ + for (;;) + { + if (!NextAny(fi)) + return false; + if (!fi.IsDots()) + return true; + } +} + +bool CEnumeratorW::Next(CFileInfoW &fi, bool &found) +{ + if (Next(fi)) + { + found = true; + return true; + } + found = false; + return (::GetLastError() == ERROR_NO_MORE_FILES); +} + +#endif + +//////////////////////////////// +// CFindChangeNotification +// FindFirstChangeNotification can return 0. MSDN doesn't tell about it. + +bool CFindChangeNotification::Close() +{ + if (!IsHandleAllocated()) + return true; + if (!::FindCloseChangeNotification(_handle)) + return false; + _handle = INVALID_HANDLE_VALUE; + return true; +} + +HANDLE CFindChangeNotification::FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter) +{ + _handle = ::FindFirstChangeNotification(pathName, BoolToBOOL(watchSubtree), notifyFilter); + #ifdef WIN_LONG_PATH2 + if (!IsHandleAllocated()) + { + UString longPath; + if (GetLongPath(pathName, longPath)) + _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); + } + #endif + return _handle; +} + +#ifndef _UNICODE +HANDLE CFindChangeNotification::FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter) +{ + if (!g_IsNT) + return FindFirst(UnicodeStringToMultiByte(pathName, GetCurrentCodePage()), watchSubtree, notifyFilter); + _handle = ::FindFirstChangeNotificationW(pathName, BoolToBOOL(watchSubtree), notifyFilter); + #ifdef WIN_LONG_PATH + if (!IsHandleAllocated()) + { + UString longPath; + if (GetLongPath(pathName, longPath)) + _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); + } + #endif + return _handle; +} +#endif + +#ifndef UNDER_CE +bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings) +{ + driveStrings.Clear(); + UINT32 size = GetLogicalDriveStrings(0, NULL); + if (size == 0) + return false; + CSysString buffer; + UINT32 newSize = GetLogicalDriveStrings(size, buffer.GetBuffer(size)); + if (newSize == 0) + return false; + if (newSize > size) + return false; + CSysString string; + for (UINT32 i = 0; i < newSize; i++) + { + TCHAR c = buffer[i]; + if (c == TEXT('\0')) + { + driveStrings.Add(string); + string.Empty(); + } + else + string += c; + } + if (!string.IsEmpty()) + return false; + return true; +} + +#ifndef _UNICODE +bool MyGetLogicalDriveStrings(UStringVector &driveStrings) +{ + driveStrings.Clear(); + if (g_IsNT) + { + UINT32 size = GetLogicalDriveStringsW(0, NULL); + if (size == 0) + return false; + UString buffer; + UINT32 newSize = GetLogicalDriveStringsW(size, buffer.GetBuffer(size)); + if (newSize == 0) + return false; + if (newSize > size) + return false; + UString string; + for (UINT32 i = 0; i < newSize; i++) + { + WCHAR c = buffer[i]; + if (c == L'\0') + { + driveStrings.Add(string); + string.Empty(); + } + else + string += c; + } + return string.IsEmpty(); + } + CSysStringVector driveStringsA; + bool res = MyGetLogicalDriveStrings(driveStringsA); + for (int i = 0; i < driveStringsA.Size(); i++) + driveStrings.Add(GetUnicodeString(driveStringsA[i])); + return res; +} +#endif + +#endif + +}}} diff --git a/CPP/Windows/FileFind.h b/CPP/Windows/FileFind.h new file mode 100755 index 0000000..5affd83 --- /dev/null +++ b/CPP/Windows/FileFind.h @@ -0,0 +1,161 @@ +// Windows/FileFind.h + +#ifndef __WINDOWS_FILEFIND_H +#define __WINDOWS_FILEFIND_H + +#include "../Common/MyString.h" +#include "../Common/Types.h" +#include "Defs.h" +#include "FileName.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); } +protected: + void Clear(); +public: + UInt64 Size; + FILETIME CTime; + FILETIME ATime; + FILETIME MTime; + DWORD Attrib; + bool IsDevice; + + /* + #ifdef UNDER_CE + DWORD ObjectID; + #else + UINT32 ReparseTag; + #endif + */ + + 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 +{ + CSysString Name; + + bool IsDots() const; + bool Find(LPCTSTR wildcard); +}; + +#ifdef _UNICODE +typedef CFileInfo CFileInfoW; +#else +struct CFileInfoW: public CFileInfoBase +{ + UString Name; + + bool IsDots() const; + bool Find(LPCWSTR wildcard); +}; +#endif + +class CFindFile +{ + friend class CEnumerator; + HANDLE _handle; +public: + bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; } + CFindFile(): _handle(INVALID_HANDLE_VALUE) {} + ~CFindFile() { Close(); } + bool FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo); + bool FindNext(CFileInfo &fileInfo); + #ifndef _UNICODE + bool FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo); + bool FindNext(CFileInfoW &fileInfo); + #endif + bool Close(); +}; + +bool DoesFileExist(LPCTSTR name); +bool DoesDirExist(LPCTSTR name); +bool DoesFileOrDirExist(LPCTSTR name); +#ifndef _UNICODE +bool DoesFileExist(LPCWSTR name); +bool DoesDirExist(LPCWSTR name); +bool DoesFileOrDirExist(LPCWSTR name); +#endif + +class CEnumerator +{ + CFindFile _findFile; + CSysString _wildcard; + bool NextAny(CFileInfo &fileInfo); +public: + CEnumerator(): _wildcard(NName::kAnyStringWildcard) {} + CEnumerator(const CSysString &wildcard): _wildcard(wildcard) {} + bool Next(CFileInfo &fileInfo); + bool Next(CFileInfo &fileInfo, bool &found); +}; + +#ifdef _UNICODE +typedef CEnumerator CEnumeratorW; +#else +class CEnumeratorW +{ + CFindFile _findFile; + UString _wildcard; + bool NextAny(CFileInfoW &fileInfo); +public: + CEnumeratorW(): _wildcard(NName::kAnyStringWildcard) {} + CEnumeratorW(const UString &wildcard): _wildcard(wildcard) {} + bool Next(CFileInfoW &fileInfo); + bool Next(CFileInfoW &fileInfo, bool &found); +}; +#endif + +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(); + HANDLE FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter); + #ifndef _UNICODE + HANDLE FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter); + #endif + bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); } +}; + +#ifndef UNDER_CE +bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings); +#ifndef _UNICODE +bool MyGetLogicalDriveStrings(UStringVector &driveStrings); +#endif +#endif + +}}} + +#endif + diff --git a/CPP/Windows/FileIO.cpp b/CPP/Windows/FileIO.cpp new file mode 100755 index 0000000..a1a1bcc --- /dev/null +++ b/CPP/Windows/FileIO.cpp @@ -0,0 +1,434 @@ +// Windows/FileIO.cpp + +#include "StdAfx.h" + +#include "FileIO.h" + +#if defined(WIN_LONG_PATH) || defined(SUPPORT_DEVICE_FILE) +#include "../Common/MyString.h" +#endif +#ifndef _UNICODE +#include "../Common/StringConvert.h" +#endif + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NFile { + +#ifdef SUPPORT_DEVICE_FILE +bool IsDeviceName(LPCTSTR n) +{ + #ifdef UNDER_CE + int len = (int)MyStringLen(n); + if (len < 5 || len > 5 || memcmp(n, TEXT("DSK"), 3 * sizeof(TCHAR)) != 0) + return false; + if (n[4] != ':') + return false; + // for reading use SG_REQ sg; if (DeviceIoControl(dsk, IOCTL_DISK_READ)); + #else + if (n[0] != '\\' || n[1] != '\\' || n[2] != '.' || n[3] != '\\') + return false; + int len = (int)MyStringLen(n); + if (len == 6 && n[5] == ':') + return true; + if (len < 18 || len > 22 || memcmp(n + 4, TEXT("PhysicalDrive"), 13 * sizeof(TCHAR)) != 0) + return false; + for (int i = 17; i < len; i++) + if (n[i] < '0' || n[i] > '9') + return false; + #endif + return true; +} + +#ifndef _UNICODE +bool IsDeviceName(LPCWSTR n) +{ + if (n[0] != '\\' || n[1] != '\\' || n[2] != '.' || n[3] != '\\') + return false; + int len = (int)wcslen(n); + if (len == 6 && n[5] == ':') + return true; + if (len < 18 || len > 22 || wcsncmp(n + 4, L"PhysicalDrive", 13) != 0) + return false; + for (int i = 17; i < len; i++) + if (n[i] < '0' || n[i] > '9') + return false; + return true; +} +#endif +#endif + +#if defined(WIN_LONG_PATH) && defined(_UNICODE) +#define WIN_LONG_PATH2 +#endif + +#ifdef WIN_LONG_PATH +bool GetLongPathBase(LPCWSTR s, UString &res) +{ + res.Empty(); + int len = MyStringLen(s); + wchar_t c = s[0]; + if (len < 1 || c == L'\\' || c == L'.' && (len == 1 || len == 2 && s[1] == L'.')) + return true; + UString curDir; + bool isAbs = false; + if (len > 3) + isAbs = (s[1] == L':' && s[2] == L'\\' && (c >= L'a' && c <= L'z' || c >= L'A' && c <= L'Z')); + + if (!isAbs) + { + DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, curDir.GetBuffer(MAX_PATH + 1)); + curDir.ReleaseBuffer(); + if (needLength == 0 || needLength > MAX_PATH) + return false; + if (curDir[curDir.Length() - 1] != L'\\') + curDir += L'\\'; + } + res = UString(L"\\\\?\\") + curDir + s; + return true; +} + +bool GetLongPath(LPCWSTR path, UString &longPath) +{ + if (GetLongPathBase(path, longPath)) + return !longPath.IsEmpty(); + return false; +} +#endif + +namespace NIO { + +CFileBase::~CFileBase() { Close(); } + +bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess, + DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) +{ + if (!Close()) + return false; + _handle = ::CreateFile(fileName, desiredAccess, shareMode, + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, + flagsAndAttributes, (HANDLE)NULL); + #ifdef WIN_LONG_PATH2 + if (_handle == INVALID_HANDLE_VALUE) + { + UString longPath; + if (GetLongPath(fileName, longPath)) + _handle = ::CreateFileW(longPath, desiredAccess, shareMode, + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, + flagsAndAttributes, (HANDLE)NULL); + } + #endif + #ifdef SUPPORT_DEVICE_FILE + IsDeviceFile = false; + #endif + return (_handle != INVALID_HANDLE_VALUE); +} + +#ifndef _UNICODE +bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess, + DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) +{ + if (!g_IsNT) + return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP), + desiredAccess, shareMode, creationDisposition, flagsAndAttributes); + if (!Close()) + return false; + _handle = ::CreateFileW(fileName, desiredAccess, shareMode, + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, + flagsAndAttributes, (HANDLE)NULL); + #ifdef WIN_LONG_PATH + if (_handle == INVALID_HANDLE_VALUE) + { + UString longPath; + if (GetLongPath(fileName, longPath)) + _handle = ::CreateFileW(longPath, desiredAccess, shareMode, + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, + flagsAndAttributes, (HANDLE)NULL); + } + #endif + #ifdef SUPPORT_DEVICE_FILE + IsDeviceFile = false; + #endif + return (_handle != INVALID_HANDLE_VALUE); +} +#endif + +bool CFileBase::Close() +{ + if (_handle == INVALID_HANDLE_VALUE) + return true; + if (!::CloseHandle(_handle)) + return false; + _handle = INVALID_HANDLE_VALUE; + return true; +} + +bool CFileBase::GetPosition(UInt64 &position) const +{ + return Seek(0, FILE_CURRENT, position); +} + +bool CFileBase::GetLength(UInt64 &length) const +{ + #ifdef SUPPORT_DEVICE_FILE + if (IsDeviceFile && LengthDefined) + { + length = Length; + 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 +{ + #ifdef SUPPORT_DEVICE_FILE + if (IsDeviceFile && LengthDefined && moveMethod == FILE_END) + { + distanceToMove += Length; + moveMethod = FILE_BEGIN; + } + #endif + + LARGE_INTEGER value; + value.QuadPart = distanceToMove; + value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod); + if (value.LowPart == 0xFFFFFFFF) + if (::GetLastError() != NO_ERROR) + return false; + newPosition = value.QuadPart; + return true; +} + +bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) +{ + return Seek(position, FILE_BEGIN, newPosition); +} + +bool CFileBase::SeekToBegin() +{ + UInt64 newPosition; + return Seek(0, newPosition); +} + +bool CFileBase::SeekToEnd(UInt64 &newPosition) +{ + return Seek(0, FILE_END, newPosition); +} + +bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const +{ + BY_HANDLE_FILE_INFORMATION winFileInfo; + if (!::GetFileInformationByHandle(_handle, &winFileInfo)) + return false; + fileInfo.Attrib = winFileInfo.dwFileAttributes; + fileInfo.CTime = winFileInfo.ftCreationTime; + fileInfo.ATime = winFileInfo.ftLastAccessTime; + fileInfo.MTime = winFileInfo.ftLastWriteTime; + fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes; + fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) + winFileInfo.nFileSizeLow; + fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks; + fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow; + return true; +} + +///////////////////////// +// CInFile + +#ifdef SUPPORT_DEVICE_FILE +void CInFile::GetDeviceLength() +{ + if (_handle != INVALID_HANDLE_VALUE && IsDeviceFile) + { + #ifdef UNDER_CE + LengthDefined = true; + Length = 128 << 20; + + #else + PARTITION_INFORMATION partInfo; + LengthDefined = true; + Length = 0; + + if (GetPartitionInfo(&partInfo)) + Length = partInfo.PartitionLength.QuadPart; + else + { + DISK_GEOMETRY geom; + if (!GetGeometry(&geom)) + if (!GetCdRomGeometry(&geom)) + LengthDefined = false; + if (LengthDefined) + Length = geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector; + } + // SeekToBegin(); + #endif + } +} + +// ((desiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE)) == 0 && + +#define MY_DEVICE_EXTRA_CODE \ + IsDeviceFile = IsDeviceName(fileName); \ + GetDeviceLength(); +#else +#define MY_DEVICE_EXTRA_CODE +#endif + +bool CInFile::Open(LPCTSTR 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(LPCTSTR fileName, bool shareForWrite) +{ return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } + +bool CInFile::Open(LPCTSTR fileName) + { return OpenShared(fileName, false); } + +#ifndef _UNICODE +bool CInFile::Open(LPCWSTR 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(LPCWSTR fileName, bool shareForWrite) +{ return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } + +bool CInFile::Open(LPCWSTR fileName) + { return OpenShared(fileName, false); } +#endif + +// 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) +{ + 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) +{ + if (size > kChunkSizeMax) + size = kChunkSizeMax; + return Read1(data, size, processedSize); +} + +bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) +{ + 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 + +bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) + { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } + +static inline DWORD GetCreationDisposition(bool createAlways) + { return createAlways? CREATE_ALWAYS: CREATE_NEW; } + +bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition) + { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } + +bool COutFile::Create(LPCTSTR fileName, bool createAlways) + { return Open(fileName, GetCreationDisposition(createAlways)); } + +#ifndef _UNICODE + +bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) + { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } + +bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition) + { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } + +bool COutFile::Create(LPCWSTR fileName, bool createAlways) + { return Open(fileName, GetCreationDisposition(createAlways)); } + +#endif + +bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) + { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); } + +bool COutFile::SetMTime(const FILETIME *mTime) { return SetTime(NULL, NULL, mTime); } + +bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) +{ + 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) +{ + 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() { return BOOLToBool(::SetEndOfFile(_handle)); } + +bool COutFile::SetLength(UInt64 length) +{ + UInt64 newPosition; + if (!Seek(length, newPosition)) + return false; + if (newPosition != length) + return false; + return SetEndOfFile(); +} + +}}} diff --git a/CPP/Windows/FileIO.h b/CPP/Windows/FileIO.h new file mode 100755 index 0000000..6f14817 --- /dev/null +++ b/CPP/Windows/FileIO.h @@ -0,0 +1,136 @@ +// Windows/FileIO.h + +#ifndef __WINDOWS_FILEIO_H +#define __WINDOWS_FILEIO_H + +#include "../Common/Types.h" + +#include "Defs.h" + +namespace NWindows { +namespace NFile { +namespace NIO { + +struct CByHandleFileInfo +{ + DWORD Attrib; + FILETIME CTime; + FILETIME ATime; + FILETIME MTime; + DWORD VolumeSerialNumber; + UInt64 Size; + DWORD NumberOfLinks; + UInt64 FileIndex; +}; + +class CFileBase +{ +protected: + HANDLE _handle; + + bool Create(LPCTSTR fileName, DWORD desiredAccess, + DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); + #ifndef _UNICODE + bool Create(LPCWSTR fileName, DWORD desiredAccess, + DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); + #endif + +public: + #ifdef SUPPORT_DEVICE_FILE + bool IsDeviceFile; + bool LengthDefined; + UInt64 Length; + #endif + + CFileBase(): _handle(INVALID_HANDLE_VALUE) {}; + ~CFileBase(); + + bool Close(); + + bool GetPosition(UInt64 &position) const; + bool GetLength(UInt64 &length) const; + + bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const; + bool Seek(UInt64 position, UInt64 &newPosition); + bool SeekToBegin(); + bool SeekToEnd(UInt64 &newPosition); + + bool GetFileInformation(CByHandleFileInfo &fileInfo) const; +}; + +#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) + +class CInFile: public CFileBase +{ + #ifdef SUPPORT_DEVICE_FILE + bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer, DWORD inSize, + LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned, LPOVERLAPPED overlapped) const + { + return BOOLToBool(::DeviceIoControl(_handle, controlCode, inBuffer, inSize, + outBuffer, outSize, bytesReturned, overlapped)); + } + + bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer, + DWORD inSize, LPVOID outBuffer, DWORD outSize) const + { + DWORD ret; + return DeviceIoControl(controlCode, inBuffer, inSize, outBuffer, outSize, &ret, 0); + } + + bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize) const + { return DeviceIoControl(controlCode, NULL, 0, outBuffer, outSize); } + + #ifndef UNDER_CE + bool GetGeometry(DISK_GEOMETRY *res) const + { return DeviceIoControlOut(IOCTL_DISK_GET_DRIVE_GEOMETRY, 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 GetDeviceLength(); + #endif + +public: + bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); + bool OpenShared(LPCTSTR fileName, bool shareForWrite); + bool Open(LPCTSTR fileName); + #ifndef _UNICODE + bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); + bool OpenShared(LPCWSTR fileName, bool shareForWrite); + bool Open(LPCWSTR fileName); + #endif + bool Read1(void *data, UInt32 size, UInt32 &processedSize); + bool ReadPart(void *data, UInt32 size, UInt32 &processedSize); + bool Read(void *data, UInt32 size, UInt32 &processedSize); +}; + +class COutFile: public CFileBase +{ +public: + bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); + bool Open(LPCTSTR fileName, DWORD creationDisposition); + bool Create(LPCTSTR fileName, bool createAlways); + + #ifndef _UNICODE + bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); + bool Open(LPCWSTR fileName, DWORD creationDisposition); + bool Create(LPCWSTR fileName, bool createAlways); + #endif + + bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); + bool SetMTime(const FILETIME *mTime); + bool WritePart(const void *data, UInt32 size, UInt32 &processedSize); + bool Write(const void *data, UInt32 size, UInt32 &processedSize); + bool SetEndOfFile(); + bool SetLength(UInt64 length); +}; + +}}} + +#endif diff --git a/CPP/Windows/FileMapping.cpp b/CPP/Windows/FileMapping.cpp new file mode 100755 index 0000000..857e70d --- /dev/null +++ b/CPP/Windows/FileMapping.cpp @@ -0,0 +1,12 @@ +// Windows/FileMapping.cpp + +#include "StdAfx.h" + +#include "Windows/FileMapping.h" + +namespace NWindows { +namespace NFile { +namespace NMapping { + + +}}} diff --git a/CPP/Windows/FileMapping.h b/CPP/Windows/FileMapping.h new file mode 100755 index 0000000..138a175 --- /dev/null +++ b/CPP/Windows/FileMapping.h @@ -0,0 +1,62 @@ +// Windows/FileMapping.h + +#ifndef __WINDOWS_FILEMAPPING_H +#define __WINDOWS_FILEMAPPING_H + +#include "Common/Types.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 desiredAccess, 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/CPP/Windows/FileName.cpp b/CPP/Windows/FileName.cpp new file mode 100755 index 0000000..4e55a53 --- /dev/null +++ b/CPP/Windows/FileName.cpp @@ -0,0 +1,50 @@ +// Windows/FileName.cpp + +#include "StdAfx.h" + +#include "Windows/FileName.h" +#include "Common/Wildcard.h" + +namespace NWindows { +namespace NFile { +namespace NName { + +void NormalizeDirPathPrefix(CSysString &dirPath) +{ + if (dirPath.IsEmpty()) + return; + if (dirPath.ReverseFind(kDirDelimiter) != dirPath.Length() - 1) + dirPath += kDirDelimiter; +} + +#ifndef _UNICODE +void NormalizeDirPathPrefix(UString &dirPath) +{ + if (dirPath.IsEmpty()) + return; + if (dirPath.ReverseFind(wchar_t(kDirDelimiter)) != dirPath.Length() - 1) + dirPath += wchar_t(kDirDelimiter); +} +#endif + +const wchar_t kExtensionDelimiter = L'.'; + +void SplitNameToPureNameAndExtension(const UString &fullName, + UString &pureName, UString &extensionDelimiter, UString &extension) +{ + int index = fullName.ReverseFind(kExtensionDelimiter); + if (index < 0) + { + pureName = fullName; + extensionDelimiter.Empty(); + extension.Empty(); + } + else + { + pureName = fullName.Left(index); + extensionDelimiter = kExtensionDelimiter; + extension = fullName.Mid(index + 1); + } +} + +}}} diff --git a/CPP/Windows/FileName.h b/CPP/Windows/FileName.h new file mode 100755 index 0000000..b980236 --- /dev/null +++ b/CPP/Windows/FileName.h @@ -0,0 +1,27 @@ +// Windows/FileName.h + +#ifndef __WINDOWS_FILENAME_H +#define __WINDOWS_FILENAME_H + +#include "../../C/Types.h" + +#include "../Common/MyString.h" + +namespace NWindows { +namespace NFile { +namespace NName { + +const TCHAR kDirDelimiter = CHAR_PATH_SEPARATOR; +const TCHAR kAnyStringWildcard = '*'; + +void NormalizeDirPathPrefix(CSysString &dirPath); // ensures that it ended with '\\' +#ifndef _UNICODE +void NormalizeDirPathPrefix(UString &dirPath); // ensures that it ended with '\\' +#endif + +void SplitNameToPureNameAndExtension(const UString &fullName, + UString &pureName, UString &extensionDelimiter, UString &extension); + +}}} + +#endif diff --git a/CPP/Windows/FileSystem.cpp b/CPP/Windows/FileSystem.cpp new file mode 100755 index 0000000..5e2f324 --- /dev/null +++ b/CPP/Windows/FileSystem.cpp @@ -0,0 +1,126 @@ +// Windows/FileSystem.cpp + +#include "StdAfx.h" + +#include "FileSystem.h" +#include "Defs.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NFile { +namespace NSystem { + +bool MyGetVolumeInformation( + LPCTSTR rootPathName, + CSysString &volumeName, + LPDWORD volumeSerialNumber, + LPDWORD maximumComponentLength, + LPDWORD fileSystemFlags, + CSysString &fileSystemName) +{ + bool result = BOOLToBool(GetVolumeInformation( + rootPathName, + volumeName.GetBuffer(MAX_PATH), MAX_PATH, + volumeSerialNumber, + maximumComponentLength, + fileSystemFlags, + fileSystemName.GetBuffer(MAX_PATH), MAX_PATH)); + volumeName.ReleaseBuffer(); + fileSystemName.ReleaseBuffer(); + return result; +} + + +#ifndef _UNICODE +bool MyGetVolumeInformation( + LPCWSTR rootPathName, + UString &volumeName, + LPDWORD volumeSerialNumber, + LPDWORD maximumComponentLength, + LPDWORD fileSystemFlags, + UString &fileSystemName) +{ + if (g_IsNT) + { + bool result = BOOLToBool(GetVolumeInformationW( + rootPathName, + volumeName.GetBuffer(MAX_PATH), MAX_PATH, + volumeSerialNumber, + maximumComponentLength, + fileSystemFlags, + fileSystemName.GetBuffer(MAX_PATH), MAX_PATH)); + volumeName.ReleaseBuffer(); + fileSystemName.ReleaseBuffer(); + return result; + } + AString volumeNameA, fileSystemNameA; + bool result = MyGetVolumeInformation(GetSystemString(rootPathName), volumeNameA, + volumeSerialNumber, maximumComponentLength, fileSystemFlags,fileSystemNameA); + if (result) + { + volumeName = GetUnicodeString(volumeNameA); + fileSystemName = GetUnicodeString(fileSystemNameA); + } + return result; +} +#endif + +typedef BOOL (WINAPI * GetDiskFreeSpaceExPointer)( + LPCTSTR 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(LPCTSTR rootPathName, + UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize) +{ + GetDiskFreeSpaceExPointer pGetDiskFreeSpaceEx = + (GetDiskFreeSpaceExPointer)GetProcAddress( + GetModuleHandle(TEXT("kernel32.dll")), "GetDiskFreeSpaceExA"); + + bool sizeIsDetected = false; + if (pGetDiskFreeSpaceEx) + { + ULARGE_INTEGER i64FreeBytesToCaller, totalSize2, freeSize2; + sizeIsDetected = BOOLToBool(pGetDiskFreeSpaceEx(rootPathName, + &i64FreeBytesToCaller, + &totalSize2, + &freeSize2)); + totalSize = totalSize2.QuadPart; + freeSize = freeSize2.QuadPart; + } + + DWORD numSectorsPerCluster; + DWORD bytesPerSector; + DWORD numberOfFreeClusters; + DWORD totalNumberOfClusters; + + if (!::GetDiskFreeSpace(rootPathName, + &numSectorsPerCluster, + &bytesPerSector, + &numberOfFreeClusters, + &totalNumberOfClusters)) + return false; + + clusterSize = (UInt64)bytesPerSector * (UInt64)numSectorsPerCluster; + if (!sizeIsDetected) + { + totalSize = clusterSize * (UInt64)totalNumberOfClusters; + freeSize = clusterSize * (UInt64)numberOfFreeClusters; + } + return true; +} + +#ifndef _UNICODE +bool MyGetDiskFreeSpace(LPCWSTR rootPathName, + UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize) +{ + return MyGetDiskFreeSpace(GetSystemString(rootPathName), clusterSize, totalSize, freeSize); +} +#endif + +}}} diff --git a/CPP/Windows/FileSystem.h b/CPP/Windows/FileSystem.h new file mode 100755 index 0000000..dfce999 --- /dev/null +++ b/CPP/Windows/FileSystem.h @@ -0,0 +1,51 @@ +// Windows/FileSystem.h + +#ifndef __WINDOWS_FILESYSTEM_H +#define __WINDOWS_FILESYSTEM_H + +#include "../Common/MyString.h" +#include "../Common/Types.h" + +#ifndef _UNICODE +#include "../Common/StringConvert.h" +#endif + +namespace NWindows { +namespace NFile { +namespace NSystem { + +bool MyGetVolumeInformation( + LPCTSTR rootPathName, + CSysString &volumeName, + LPDWORD volumeSerialNumber, + LPDWORD maximumComponentLength, + LPDWORD fileSystemFlags, + CSysString &fileSystemName); + +#ifndef _UNICODE +bool MyGetVolumeInformation( + LPCWSTR rootPathName, + UString &volumeName, + LPDWORD volumeSerialNumber, + LPDWORD maximumComponentLength, + LPDWORD fileSystemFlags, + UString &fileSystemName); +#endif + +inline UINT MyGetDriveType(LPCTSTR pathName) { return GetDriveType(pathName); } +#ifndef _UNICODE +inline UINT MyGetDriveType(LPCWSTR pathName) { return GetDriveType(GetSystemString(pathName)); } +#endif + +bool MyGetDiskFreeSpace(LPCTSTR rootPathName, + UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); + +#ifndef _UNICODE +bool MyGetDiskFreeSpace(LPCWSTR rootPathName, + UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); +#endif + +}}} + +#endif + diff --git a/CPP/Windows/Handle.h b/CPP/Windows/Handle.h new file mode 100755 index 0000000..755eeb8 --- /dev/null +++ b/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/CPP/Windows/Memory.cpp b/CPP/Windows/Memory.cpp new file mode 100755 index 0000000..fd50a59 --- /dev/null +++ b/CPP/Windows/Memory.cpp @@ -0,0 +1,36 @@ +// Windows/Memory.cpp + +#include "StdAfx.h" + +#include "Windows/Memory.h" + +namespace NWindows { +namespace NMemory { + +bool CGlobal::Alloc(UINT flags, SIZE_T size) +{ + HGLOBAL newBlock = ::GlobalAlloc(flags, size); + if (newBlock == NULL) + return false; + m_MemoryHandle = newBlock; + return true; +} + +bool CGlobal::Free() +{ + if (m_MemoryHandle == NULL) + return true; + m_MemoryHandle = ::GlobalFree(m_MemoryHandle); + return (m_MemoryHandle == NULL); +} + +bool CGlobal::ReAlloc(SIZE_T size) +{ + HGLOBAL newBlock = ::GlobalReAlloc(m_MemoryHandle, size, GMEM_MOVEABLE); + if (newBlock == NULL) + return false; + m_MemoryHandle = newBlock; + return true; +} + +}} diff --git a/CPP/Windows/Memory.h b/CPP/Windows/Memory.h new file mode 100755 index 0000000..80b3049 --- /dev/null +++ b/CPP/Windows/Memory.h @@ -0,0 +1,53 @@ +// Windows/Memory.h + +#ifndef __WINDOWS_MEMORY_H +#define __WINDOWS_MEMORY_H + +namespace NWindows { +namespace NMemory { + +class CGlobal +{ + HGLOBAL m_MemoryHandle; +public: + CGlobal(): m_MemoryHandle(NULL){}; + ~CGlobal() { Free(); } + operator HGLOBAL() const { return m_MemoryHandle; }; + void Attach(HGLOBAL hGlobal) + { + Free(); + m_MemoryHandle = hGlobal; + } + HGLOBAL Detach() + { + HGLOBAL h = m_MemoryHandle; + m_MemoryHandle = NULL; + return h; + } + bool Alloc(UINT flags, SIZE_T size); + bool Free(); + LPVOID Lock() const { return GlobalLock(m_MemoryHandle); } + void Unlock() const { GlobalUnlock(m_MemoryHandle); } + bool ReAlloc(SIZE_T size); +}; + +class CGlobalLock +{ + HGLOBAL m_Global; + LPVOID m_Pointer; +public: + LPVOID GetPointer() const { return m_Pointer; } + CGlobalLock(HGLOBAL hGlobal): m_Global(hGlobal) + { + m_Pointer = GlobalLock(hGlobal); + }; + ~CGlobalLock() + { + if (m_Pointer != NULL) + GlobalUnlock(m_Global); + } +}; + +}} + +#endif diff --git a/CPP/Windows/MemoryLock.cpp b/CPP/Windows/MemoryLock.cpp new file mode 100755 index 0000000..9b2ffb8 --- /dev/null +++ b/CPP/Windows/MemoryLock.cpp @@ -0,0 +1,82 @@ +// Common/MemoryLock.cpp + +#include "StdAfx.h" + +namespace NWindows { +namespace NSecurity { + +#ifndef UNDER_CE + +#ifndef _UNICODE +typedef BOOL (WINAPI * OpenProcessTokenP)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle); +typedef BOOL (WINAPI * LookupPrivilegeValueP)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID lpLuid); +typedef BOOL (WINAPI * AdjustTokenPrivilegesP)(HANDLE TokenHandle, BOOL DisableAllPrivileges, + PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState,PDWORD ReturnLength); +#endif + +#ifdef _UNICODE +bool EnableLockMemoryPrivilege( +#else +static bool EnableLockMemoryPrivilege2(HMODULE hModule, +#endif +bool enable) +{ + #ifndef _UNICODE + if (hModule == NULL) + return false; + OpenProcessTokenP openProcessToken = (OpenProcessTokenP)GetProcAddress(hModule, "OpenProcessToken"); + LookupPrivilegeValueP lookupPrivilegeValue = (LookupPrivilegeValueP)GetProcAddress(hModule, "LookupPrivilegeValueA" ); + AdjustTokenPrivilegesP adjustTokenPrivileges = (AdjustTokenPrivilegesP)GetProcAddress(hModule, "AdjustTokenPrivileges"); + if (openProcessToken == NULL || adjustTokenPrivileges == NULL || lookupPrivilegeValue == NULL) + return false; + #endif + + HANDLE token; + if (! + #ifdef _UNICODE + ::OpenProcessToken + #else + openProcessToken + #endif + (::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) + return false; + TOKEN_PRIVILEGES tp; + bool res = false; + if ( + #ifdef _UNICODE + ::LookupPrivilegeValue + #else + lookupPrivilegeValue + #endif + (NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid))) + { + tp.PrivilegeCount = 1; + tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED: 0; + if ( + #ifdef _UNICODE + ::AdjustTokenPrivileges + #else + adjustTokenPrivileges + #endif + (token, FALSE, &tp, 0, NULL, NULL)) + res = (GetLastError() == ERROR_SUCCESS); + } + ::CloseHandle(token); + return res; +} + +#ifndef _UNICODE +bool EnableLockMemoryPrivilege(bool enable) +{ + HMODULE hModule = LoadLibrary(TEXT("Advapi32.dll")); + if (hModule == NULL) + return false; + bool res = EnableLockMemoryPrivilege2(hModule, enable); + ::FreeLibrary(hModule); + return res; +} +#endif + +#endif + +}} diff --git a/CPP/Windows/MemoryLock.h b/CPP/Windows/MemoryLock.h new file mode 100755 index 0000000..f2e574b --- /dev/null +++ b/CPP/Windows/MemoryLock.h @@ -0,0 +1,15 @@ +// Windows/MemoryLock.h + +#ifndef __WINDOWS_MEMORYLOCK_H +#define __WINDOWS_MEMORYLOCK_H + +namespace NWindows { +namespace NSecurity { + +#ifndef UNDER_CE +bool EnableLockMemoryPrivilege(bool enable = true); +#endif + +}} + +#endif diff --git a/CPP/Windows/Menu.cpp b/CPP/Windows/Menu.cpp new file mode 100755 index 0000000..aabfcf6 --- /dev/null +++ b/CPP/Windows/Menu.cpp @@ -0,0 +1,191 @@ +// Windows/Menu.cpp + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "Common/StringConvert.h" +#endif +#include "Windows/Menu.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { + +static void ConvertItemToSysForm(const CMenuItem &item, MENUITEMINFOW &si) +{ + ZeroMemory(&si, sizeof(si)); + si.cbSize = sizeof(si); + si.fMask = item.fMask; + si.fType = item.fType; + si.fState = item.fState; + si.wID = item.wID; + si.hSubMenu = item.hSubMenu; + si.hbmpChecked = item.hbmpChecked; + si.hbmpUnchecked = item.hbmpUnchecked; + si.dwItemData = item.dwItemData; +} + +#ifndef _UNICODE +static void ConvertItemToSysForm(const CMenuItem &item, MENUITEMINFOA &si) +{ + ZeroMemory(&si, sizeof(si)); + si.cbSize = sizeof(si); + si.fMask = item.fMask; + si.fType = item.fType; + si.fState = item.fState; + si.wID = item.wID; + si.hSubMenu = item.hSubMenu; + si.hbmpChecked = item.hbmpChecked; + si.hbmpUnchecked = item.hbmpUnchecked; + si.dwItemData = item.dwItemData; +} +#endif + +static void ConvertItemToMyForm(const MENUITEMINFOW &si, CMenuItem &item) +{ + item.fMask = si.fMask; + item.fType = si.fType; + item.fState = si.fState; + item.wID = si.wID; + item.hSubMenu = si.hSubMenu; + item.hbmpChecked = si.hbmpChecked; + item.hbmpUnchecked = si.hbmpUnchecked; + item.dwItemData = si.dwItemData; +} + +#ifndef _UNICODE +static void ConvertItemToMyForm(const MENUITEMINFOA &si, CMenuItem &item) +{ + item.fMask = si.fMask; + item.fType = si.fType; + item.fState = si.fState; + item.wID = si.wID; + item.hSubMenu = si.hSubMenu; + item.hbmpChecked = si.hbmpChecked; + item.hbmpUnchecked = si.hbmpUnchecked; + item.dwItemData = si.dwItemData; +} +#endif + +bool CMenu::GetItem(UINT itemIndex, bool byPosition, CMenuItem &item) +{ + const UINT kMaxSize = 512; + #ifndef _UNICODE + if (!g_IsNT) + { + CHAR s[kMaxSize + 1]; + MENUITEMINFOA si; + ConvertItemToSysForm(item, si); + if (item.IsString()) + { + si.cch = kMaxSize; + si.dwTypeData = s; + } + if (GetItemInfo(itemIndex, byPosition, &si)) + { + ConvertItemToMyForm(si, item); + if (item.IsString()) + item.StringValue = GetUnicodeString(s); + return true; + } + } + else + #endif + { + wchar_t s[kMaxSize + 1]; + MENUITEMINFOW si; + ConvertItemToSysForm(item, si); + if (item.IsString()) + { + si.cch = kMaxSize; + si.dwTypeData = s; + } + if (GetItemInfo(itemIndex, byPosition, &si)) + { + ConvertItemToMyForm(si, item); + if (item.IsString()) + item.StringValue = s; + return true; + } + } + return false; +} + +bool CMenu::SetItem(UINT itemIndex, bool byPosition, const CMenuItem &item) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + MENUITEMINFOA si; + ConvertItemToSysForm(item, si); + AString s; + if (item.IsString()) + { + s = GetSystemString(item.StringValue); + si.dwTypeData = (LPTSTR)(LPCTSTR)s; + } + return SetItemInfo(itemIndex, byPosition, &si); + } + else + #endif + { + MENUITEMINFOW si; + ConvertItemToSysForm(item, si); + if (item.IsString()) + si.dwTypeData = (LPWSTR)(LPCWSTR)item.StringValue; + return SetItemInfo(itemIndex, byPosition, &si); + } +} + +bool CMenu::InsertItem(UINT itemIndex, bool byPosition, const CMenuItem &item) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + MENUITEMINFOA si; + ConvertItemToSysForm(item, si); + AString s; + if (item.IsString()) + { + s = GetSystemString(item.StringValue); + si.dwTypeData = (LPTSTR)(LPCTSTR)s; + } + return InsertItem(itemIndex, byPosition, &si); + } + else + #endif + { + MENUITEMINFOW si; + ConvertItemToSysForm(item, si); + if (item.IsString()) + si.dwTypeData = (LPWSTR)(LPCWSTR)item.StringValue; + #ifdef UNDER_CE + UINT flags = (item.fType & MFT_SEPARATOR) ? MF_SEPARATOR : MF_STRING; + UINT id = item.wID; + if ((item.fMask & MIIM_SUBMENU) != 0) + { + flags |= MF_POPUP; + id = (UINT)item.hSubMenu; + } + if (!Insert(itemIndex, flags | (byPosition ? MF_BYPOSITION : MF_BYCOMMAND), id, item.StringValue)) + return false; + return SetItemInfo(itemIndex, byPosition, &si); + #else + return InsertItem(itemIndex, byPosition, &si); + #endif + } +} + +#ifndef _UNICODE +bool CMenu::AppendItem(UINT flags, UINT_PTR newItemID, LPCWSTR newItem) +{ + if (g_IsNT) + return BOOLToBool(::AppendMenuW(_menu, flags, newItemID, newItem)); + else + return AppendItem(flags, newItemID, GetSystemString(newItem)); +} +#endif + +} diff --git a/CPP/Windows/Menu.h b/CPP/Windows/Menu.h new file mode 100755 index 0000000..9aca0a2 --- /dev/null +++ b/CPP/Windows/Menu.h @@ -0,0 +1,153 @@ +// Windows/Menu.h + +#ifndef __WINDOWS_MENU_H +#define __WINDOWS_MENU_H + +#include "Common/MyString.h" +#include "Windows/Defs.h" + +namespace NWindows { + +struct CMenuItem +{ + UString StringValue; + UINT fMask; + UINT fType; + UINT fState; + UINT wID; + HMENU hSubMenu; + HBITMAP hbmpChecked; + HBITMAP hbmpUnchecked; + ULONG_PTR dwItemData; + // LPTSTR dwTypeData; + // UINT cch; + // HBITMAP hbmpItem; + bool IsString() const // change it MIIM_STRING + { return ((fMask & MIIM_TYPE) != 0 && (fType == MFT_STRING)); } + bool IsSeparator() const { return (fType == MFT_SEPARATOR); } + CMenuItem(): fMask(0), fType(0), fState(0), wID(0), hSubMenu(0), hbmpChecked(0), + hbmpUnchecked(0), dwItemData(0) {} +}; + +class CMenu +{ + HMENU _menu; +public: + CMenu(): _menu(NULL) {}; + operator HMENU() const { return _menu; } + void Attach(HMENU menu) { _menu = menu; } + + HMENU Detach() + { + HMENU menu = _menu; + _menu = NULL; + return menu; + } + + bool Create() + { + _menu = ::CreateMenu(); + return (_menu != NULL); + } + + bool CreatePopup() + { + _menu = ::CreatePopupMenu(); + return (_menu != NULL); + } + + bool Destroy() + { + if (_menu == NULL) + return false; + return BOOLToBool(::DestroyMenu(Detach())); + } + + int GetItemCount() + { + #ifdef UNDER_CE + for (int i = 0;; i++) + { + CMenuItem item; + item.fMask = MIIM_STATE; + if (!GetItem(i, true, item)) + return i; + } + #else + return GetMenuItemCount(_menu); + #endif + } + + HMENU GetSubMenu(int pos) { return ::GetSubMenu(_menu, pos); } + #ifndef UNDER_CE + bool GetItemString(UINT idItem, UINT flag, CSysString &result) + { + result.Empty(); + int len = ::GetMenuString(_menu, idItem, 0, 0, flag); + len = ::GetMenuString(_menu, idItem, result.GetBuffer(len + 2), len + 1, flag); + result.ReleaseBuffer(); + return (len != 0); + } + UINT GetItemID(int pos) { return ::GetMenuItemID(_menu, pos); } + UINT GetItemState(UINT id, UINT flags) { return ::GetMenuState(_menu, id, flags); } + #endif + + bool GetItemInfo(UINT itemIndex, bool byPosition, LPMENUITEMINFO itemInfo) + { return BOOLToBool(::GetMenuItemInfo(_menu, itemIndex, BoolToBOOL(byPosition), itemInfo)); } + bool SetItemInfo(UINT itemIndex, bool byPosition, LPMENUITEMINFO itemInfo) + { return BOOLToBool(::SetMenuItemInfo(_menu, itemIndex, BoolToBOOL(byPosition), itemInfo)); } + + bool AppendItem(UINT flags, UINT_PTR newItemID, LPCTSTR newItem) + { return BOOLToBool(::AppendMenu(_menu, flags, newItemID, newItem)); } + + bool Insert(UINT position, UINT flags, UINT_PTR idNewItem, LPCTSTR newItem) + { return BOOLToBool(::InsertMenu(_menu, position, flags, idNewItem, newItem)); } + + #ifndef UNDER_CE + bool InsertItem(UINT itemIndex, bool byPosition, LPCMENUITEMINFO itemInfo) + { return BOOLToBool(::InsertMenuItem(_menu, itemIndex, BoolToBOOL(byPosition), itemInfo)); } + #endif + + bool RemoveItem(UINT item, UINT flags) { return BOOLToBool(::RemoveMenu(_menu, item, flags)); } + void RemoveAllItemsFrom(UINT index) { while (RemoveItem(index, MF_BYPOSITION)); } + void RemoveAllItems() { RemoveAllItemsFrom(0); } + + #ifndef _UNICODE + bool GetItemInfo(UINT itemIndex, bool byPosition, LPMENUITEMINFOW itemInfo) + { return BOOLToBool(::GetMenuItemInfoW(_menu, itemIndex, BoolToBOOL(byPosition), itemInfo)); } + bool InsertItem(UINT itemIndex, bool byPosition, LPMENUITEMINFOW itemInfo) + { return BOOLToBool(::InsertMenuItemW(_menu, itemIndex, BoolToBOOL(byPosition), itemInfo)); } + bool SetItemInfo(UINT itemIndex, bool byPosition, LPMENUITEMINFOW itemInfo) + { return BOOLToBool(::SetMenuItemInfoW(_menu, itemIndex, BoolToBOOL(byPosition), itemInfo)); } + bool AppendItem(UINT flags, UINT_PTR newItemID, LPCWSTR newItem); + #endif + + bool GetItem(UINT itemIndex, bool byPosition, CMenuItem &item); + bool SetItem(UINT itemIndex, bool byPosition, const CMenuItem &item); + bool InsertItem(UINT itemIndex, bool byPosition, const CMenuItem &item); + + int Track(UINT flags, int x, int y, HWND hWnd) { return ::TrackPopupMenuEx(_menu, flags, x, y, hWnd, NULL); } + + bool CheckRadioItem(UINT idFirst, UINT idLast, UINT idCheck, UINT flags) + { return BOOLToBool(::CheckMenuRadioItem(_menu, idFirst, idLast, idCheck, flags)); } + + DWORD CheckItem(UINT id, UINT uCheck) { return ::CheckMenuItem(_menu, id, uCheck); } + DWORD CheckItemByID(UINT id, bool check) { return CheckItem(id, MF_BYCOMMAND | (check ? MF_CHECKED : MF_UNCHECKED)); } + + BOOL EnableItem(UINT uIDEnableItem, UINT uEnable) { return EnableMenuItem(_menu, uIDEnableItem, uEnable); } +}; + +class CMenuDestroyer +{ + CMenu *_menu; +public: + CMenuDestroyer(CMenu &menu): _menu(&menu) {} + CMenuDestroyer(): _menu(0) {} + ~CMenuDestroyer() { if (_menu) _menu->Destroy(); } + void Attach(CMenu &menu) { _menu = &menu; } + void Disable() { _menu = 0; } +}; + +} + +#endif diff --git a/CPP/Windows/NationalTime.cpp b/CPP/Windows/NationalTime.cpp new file mode 100755 index 0000000..bbb08d2 --- /dev/null +++ b/CPP/Windows/NationalTime.cpp @@ -0,0 +1,37 @@ +// Windows/NationalTime.cpp + +#include "StdAfx.h" + +#include "Windows/NationalTime.h" + +namespace NWindows { +namespace NNational { +namespace NTime { + +bool MyGetTimeFormat(LCID locale, DWORD flags, CONST SYSTEMTIME *time, + LPCTSTR format, CSysString &resultString) +{ + resultString.Empty(); + int numChars = ::GetTimeFormat(locale, flags, time, format, NULL, 0); + if (numChars == 0) + return false; + numChars = ::GetTimeFormat(locale, flags, time, format, + resultString.GetBuffer(numChars), numChars + 1); + resultString.ReleaseBuffer(); + return (numChars != 0); +} + +bool MyGetDateFormat(LCID locale, DWORD flags, CONST SYSTEMTIME *time, + LPCTSTR format, CSysString &resultString) +{ + resultString.Empty(); + int numChars = ::GetDateFormat(locale, flags, time, format, NULL, 0); + if (numChars == 0) + return false; + numChars = ::GetDateFormat(locale, flags, time, format, + resultString.GetBuffer(numChars), numChars + 1); + resultString.ReleaseBuffer(); + return (numChars != 0); +} + +}}} diff --git a/CPP/Windows/NationalTime.h b/CPP/Windows/NationalTime.h new file mode 100755 index 0000000..d5419c7 --- /dev/null +++ b/CPP/Windows/NationalTime.h @@ -0,0 +1,20 @@ +// Windows/NationalTime.h + +#ifndef __WINDOWS_NATIONALTIME_H +#define __WINDOWS_NATIONALTIME_H + +#include "Common/String.h" + +namespace NWindows { +namespace NNational { +namespace NTime { + +bool MyGetTimeFormat(LCID locale, DWORD flags, CONST SYSTEMTIME *time, + LPCTSTR format, CSysString &resultString); + +bool MyGetDateFormat(LCID locale, DWORD flags, CONST SYSTEMTIME *time, + LPCTSTR format, CSysString &resultString); + +}}} + +#endif diff --git a/CPP/Windows/Net.cpp b/CPP/Windows/Net.cpp new file mode 100755 index 0000000..01a68fb --- /dev/null +++ b/CPP/Windows/Net.cpp @@ -0,0 +1,380 @@ +// Windows/Net.cpp + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "Common/StringConvert.h" +#endif + +#include "Windows/Net.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NNet { + +DWORD CEnum::Open(DWORD scope, DWORD type, DWORD usage, LPNETRESOURCE netResource) +{ + Close(); + DWORD result = ::WNetOpenEnum(scope, type, usage, netResource, &_handle); + _handleAllocated = (result == NO_ERROR); + return result; +} + +#ifndef _UNICODE +DWORD CEnum::Open(DWORD scope, DWORD type, DWORD usage, LPNETRESOURCEW netResource) +{ + Close(); + DWORD result = ::WNetOpenEnumW(scope, type, usage, netResource, &_handle); + _handleAllocated = (result == NO_ERROR); + return result; +} +#endif + +static void SetComplexString(bool &defined, CSysString &destString, LPCTSTR srsString) +{ + defined = (srsString != 0); + if (defined) + destString = srsString; + else + destString.Empty(); +} + +static void ConvertNETRESOURCEToCResource(const NETRESOURCE &netResource, CResource &resource) +{ + resource.Scope = netResource.dwScope; + resource.Type = netResource.dwType; + resource.DisplayType = netResource.dwDisplayType; + resource.Usage = netResource.dwUsage; + SetComplexString(resource.LocalNameIsDefined, resource.LocalName, netResource.lpLocalName); + SetComplexString(resource.RemoteNameIsDefined, resource.RemoteName, netResource.lpRemoteName); + SetComplexString(resource.CommentIsDefined, resource.Comment, netResource.lpComment); + SetComplexString(resource.ProviderIsDefined, resource.Provider, netResource.lpProvider); +} + +static void SetComplexString2(LPTSTR *destString, bool defined, const CSysString &srcString) +{ + if (defined) + *destString = (TCHAR *)(const TCHAR *)srcString; + else + *destString = 0; +} + +static void ConvertCResourceToNETRESOURCE(const CResource &resource, NETRESOURCE &netResource) +{ + netResource.dwScope = resource.Scope; + netResource.dwType = resource.Type; + netResource.dwDisplayType = resource.DisplayType; + netResource.dwUsage = resource.Usage; + SetComplexString2(&netResource.lpLocalName, resource.LocalNameIsDefined, resource.LocalName); + SetComplexString2(&netResource.lpRemoteName, resource.RemoteNameIsDefined, resource.RemoteName); + SetComplexString2(&netResource.lpComment, resource.CommentIsDefined, resource.Comment); + SetComplexString2(&netResource.lpProvider, resource.ProviderIsDefined, resource.Provider); +} + +#ifndef _UNICODE + +static void SetComplexString(bool &defined, UString &destString, LPCWSTR srsString) +{ + defined = (srsString != 0); + if (defined) + destString = srsString; + else + destString.Empty(); +} + +static void ConvertNETRESOURCEToCResource(const NETRESOURCEW &netResource, CResourceW &resource) +{ + resource.Scope = netResource.dwScope; + resource.Type = netResource.dwType; + resource.DisplayType = netResource.dwDisplayType; + resource.Usage = netResource.dwUsage; + SetComplexString(resource.LocalNameIsDefined, resource.LocalName, netResource.lpLocalName); + SetComplexString(resource.RemoteNameIsDefined, resource.RemoteName, netResource.lpRemoteName); + SetComplexString(resource.CommentIsDefined, resource.Comment, netResource.lpComment); + SetComplexString(resource.ProviderIsDefined, resource.Provider, netResource.lpProvider); +} + +static void SetComplexString2(LPWSTR *destString, bool defined, const UString &srcString) +{ + if (defined) + *destString = (WCHAR *)(const WCHAR *)srcString; + else + *destString = 0; +} + +static void ConvertCResourceToNETRESOURCE(const CResourceW &resource, NETRESOURCEW &netResource) +{ + netResource.dwScope = resource.Scope; + netResource.dwType = resource.Type; + netResource.dwDisplayType = resource.DisplayType; + netResource.dwUsage = resource.Usage; + SetComplexString2(&netResource.lpLocalName, resource.LocalNameIsDefined, resource.LocalName); + SetComplexString2(&netResource.lpRemoteName, resource.RemoteNameIsDefined, resource.RemoteName); + SetComplexString2(&netResource.lpComment, resource.CommentIsDefined, resource.Comment); + SetComplexString2(&netResource.lpProvider, resource.ProviderIsDefined, resource.Provider); +} + +static void ConvertResourceWToResource(const CResourceW &resourceW, CResource &resource) +{ + *(CResourceBase *)&resource = *(CResourceBase *)&resourceW; + resource.LocalName = GetSystemString(resourceW.LocalName); + resource.RemoteName = GetSystemString(resourceW.RemoteName); + resource.Comment = GetSystemString(resourceW.Comment); + resource.Provider = GetSystemString(resourceW.Provider); +} + +static void ConvertResourceToResourceW(const CResource &resource, CResourceW &resourceW) +{ + *(CResourceBase *)&resourceW = *(CResourceBase *)&resource; + resourceW.LocalName = GetUnicodeString(resource.LocalName); + resourceW.RemoteName = GetUnicodeString(resource.RemoteName); + resourceW.Comment = GetUnicodeString(resource.Comment); + resourceW.Provider = GetUnicodeString(resource.Provider); +} +#endif + +DWORD CEnum::Open(DWORD scope, DWORD type, DWORD usage, const CResource *resource) +{ + NETRESOURCE netResource; + LPNETRESOURCE pointer; + if (resource == 0) + pointer = 0; + else + { + ConvertCResourceToNETRESOURCE(*resource, netResource); + pointer = &netResource; + } + return Open(scope, type, usage, pointer); +} + +#ifndef _UNICODE +DWORD CEnum::Open(DWORD scope, DWORD type, DWORD usage, const CResourceW *resource) +{ + if (g_IsNT) + { + NETRESOURCEW netResource; + LPNETRESOURCEW pointer; + if (resource == 0) + pointer = 0; + else + { + ConvertCResourceToNETRESOURCE(*resource, netResource); + pointer = &netResource; + } + return Open(scope, type, usage, pointer); + } + CResource *pointer; + CResource resourceA; + if (resource == 0) + pointer = 0; + else + { + ConvertResourceWToResource(*resource, resourceA); + pointer = &resourceA; + } + return Open(scope, type, usage, pointer); +} +#endif + +DWORD CEnum::Close() +{ + if (!_handleAllocated) + return NO_ERROR; + DWORD result = ::WNetCloseEnum(_handle); + _handleAllocated = (result != NO_ERROR); + return result; +} + +DWORD CEnum::Next(LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize) +{ + return ::WNetEnumResource(_handle, lpcCount, lpBuffer, lpBufferSize); +} + +#ifndef _UNICODE +DWORD CEnum::NextW(LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize) +{ + return ::WNetEnumResourceW(_handle, lpcCount, lpBuffer, lpBufferSize); +} +#endif + +DWORD CEnum::Next(CResource &resource) +{ + CByteBuffer byteBuffer; + const DWORD kBufferSize = 16384; + byteBuffer.SetCapacity(kBufferSize); + LPNETRESOURCE lpnrLocal = (LPNETRESOURCE) (BYTE *)(byteBuffer); + ZeroMemory(lpnrLocal, kBufferSize); + DWORD bufferSize = kBufferSize; + DWORD numEntries = 1; + DWORD result = Next(&numEntries, lpnrLocal, &bufferSize); + if (result != NO_ERROR) + return result; + if (numEntries != 1) + return (DWORD)E_FAIL; + ConvertNETRESOURCEToCResource(lpnrLocal[0], resource); + return result; +} + +#ifndef _UNICODE +DWORD CEnum::Next(CResourceW &resource) +{ + if (g_IsNT) + { + CByteBuffer byteBuffer; + const DWORD kBufferSize = 16384; + byteBuffer.SetCapacity(kBufferSize); + LPNETRESOURCEW lpnrLocal = (LPNETRESOURCEW) (BYTE *)(byteBuffer); + ZeroMemory(lpnrLocal, kBufferSize); + DWORD bufferSize = kBufferSize; + DWORD numEntries = 1; + DWORD result = NextW(&numEntries, lpnrLocal, &bufferSize); + if (result != NO_ERROR) + return result; + if (numEntries != 1) + return (DWORD)E_FAIL; + ConvertNETRESOURCEToCResource(lpnrLocal[0], resource); + return result; + } + CResource resourceA; + DWORD result = Next(resourceA); + ConvertResourceToResourceW(resourceA, resource); + return result; +} +#endif + + +DWORD GetResourceParent(const CResource &resource, CResource &parentResource) +{ + CByteBuffer byteBuffer; + const DWORD kBufferSize = 16384; + byteBuffer.SetCapacity(kBufferSize); + LPNETRESOURCE lpnrLocal = (LPNETRESOURCE) (BYTE *)(byteBuffer); + ZeroMemory(lpnrLocal, kBufferSize); + DWORD bufferSize = kBufferSize; + NETRESOURCE netResource; + ConvertCResourceToNETRESOURCE(resource, netResource); + DWORD result = ::WNetGetResourceParent(&netResource, lpnrLocal, &bufferSize); + if (result != NO_ERROR) + return result; + ConvertNETRESOURCEToCResource(lpnrLocal[0], parentResource); + return result; +} + +#ifndef _UNICODE +DWORD GetResourceParent(const CResourceW &resource, CResourceW &parentResource) +{ + if (g_IsNT) + { + CByteBuffer byteBuffer; + const DWORD kBufferSize = 16384; + byteBuffer.SetCapacity(kBufferSize); + LPNETRESOURCEW lpnrLocal = (LPNETRESOURCEW) (BYTE *)(byteBuffer); + ZeroMemory(lpnrLocal, kBufferSize); + DWORD bufferSize = kBufferSize; + NETRESOURCEW netResource; + ConvertCResourceToNETRESOURCE(resource, netResource); + DWORD result = ::WNetGetResourceParentW(&netResource, lpnrLocal, &bufferSize); + if (result != NO_ERROR) + return result; + ConvertNETRESOURCEToCResource(lpnrLocal[0], parentResource); + return result; + } + CResource resourceA, parentResourceA; + ConvertResourceWToResource(resource, resourceA); + DWORD result = GetResourceParent(resourceA, parentResourceA); + ConvertResourceToResourceW(parentResourceA, parentResource); + return result; +} +#endif + +DWORD GetResourceInformation(const CResource &resource, + CResource &destResource, CSysString &systemPathPart) +{ + CByteBuffer byteBuffer; + const DWORD kBufferSize = 16384; + byteBuffer.SetCapacity(kBufferSize); + LPNETRESOURCE lpnrLocal = (LPNETRESOURCE) (BYTE *)(byteBuffer); + ZeroMemory(lpnrLocal, kBufferSize); + DWORD bufferSize = kBufferSize; + NETRESOURCE netResource; + ConvertCResourceToNETRESOURCE(resource, netResource); + LPTSTR lplpSystem; + DWORD result = ::WNetGetResourceInformation(&netResource, + lpnrLocal, &bufferSize, &lplpSystem); + if (result != NO_ERROR) + return result; + if (lplpSystem != 0) + systemPathPart = lplpSystem; + ConvertNETRESOURCEToCResource(lpnrLocal[0], destResource); + return result; +} + +#ifndef _UNICODE +DWORD GetResourceInformation(const CResourceW &resource, + CResourceW &destResource, UString &systemPathPart) +{ + if (g_IsNT) + { + CByteBuffer byteBuffer; + const DWORD kBufferSize = 16384; + byteBuffer.SetCapacity(kBufferSize); + LPNETRESOURCEW lpnrLocal = (LPNETRESOURCEW) (BYTE *)(byteBuffer); + ZeroMemory(lpnrLocal, kBufferSize); + DWORD bufferSize = kBufferSize; + NETRESOURCEW netResource; + ConvertCResourceToNETRESOURCE(resource, netResource); + LPWSTR lplpSystem; + DWORD result = ::WNetGetResourceInformationW(&netResource, + lpnrLocal, &bufferSize, &lplpSystem); + if (result != NO_ERROR) + return result; + if (lplpSystem != 0) + systemPathPart = lplpSystem; + ConvertNETRESOURCEToCResource(lpnrLocal[0], destResource); + return result; + } + CResource resourceA, destResourceA; + ConvertResourceWToResource(resource, resourceA); + AString systemPathPartA; + DWORD result = GetResourceInformation(resourceA, destResourceA, systemPathPartA); + ConvertResourceToResourceW(destResourceA, destResource); + systemPathPart = GetUnicodeString(systemPathPartA); + return result; +} +#endif + +DWORD AddConnection2(const CResource &resource, + LPCTSTR password, LPCTSTR userName, DWORD flags) +{ + NETRESOURCE netResource; + ConvertCResourceToNETRESOURCE(resource, netResource); + return ::WNetAddConnection2(&netResource, + password, userName, flags); +} + +DWORD AddConnection2(const CResource &resource, LPCTSTR password, LPCTSTR userName, DWORD flags); + +#ifndef _UNICODE +DWORD AddConnection2(const CResourceW &resource, LPCWSTR password, LPCWSTR userName, DWORD flags) +{ + if (g_IsNT) + { + NETRESOURCEW netResource; + ConvertCResourceToNETRESOURCE(resource, netResource); + return ::WNetAddConnection2W(&netResource,password, userName, flags); + } + CResource resourceA; + ConvertResourceWToResource(resource, resourceA); + CSysString passwordA = GetSystemString(password); + CSysString userNameA = GetSystemString(userName); + return AddConnection2(resourceA, + password ? (LPCTSTR)passwordA: 0, + userName ? (LPCTSTR)userNameA: 0, + flags); +} +#endif + +}} diff --git a/CPP/Windows/Net.h b/CPP/Windows/Net.h new file mode 100755 index 0000000..5fae43d --- /dev/null +++ b/CPP/Windows/Net.h @@ -0,0 +1,87 @@ +// Windows/Net.h + +#ifndef __WINDOWS_NET_H +#define __WINDOWS_NET_H + +#include "Common/Buffer.h" +#include "Common/MyString.h" + +namespace NWindows { +namespace NNet { + +struct CResourceBase +{ + DWORD Scope; + DWORD Type; + DWORD DisplayType; + DWORD Usage; + bool LocalNameIsDefined; + bool RemoteNameIsDefined; + bool CommentIsDefined; + bool ProviderIsDefined; +}; + +struct CResource: public CResourceBase +{ + CSysString LocalName; + CSysString RemoteName; + CSysString Comment; + CSysString Provider; +}; + +#ifdef _UNICODE +typedef CResource CResourceW; +#else +struct CResourceW: public CResourceBase +{ + UString LocalName; + UString RemoteName; + UString Comment; + UString Provider; +}; +#endif + +class CEnum +{ + HANDLE _handle; + bool _handleAllocated; + DWORD Open(DWORD scope, DWORD type, DWORD usage, LPNETRESOURCE netResource); + DWORD Next(LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize); + #ifndef _UNICODE + DWORD Open(DWORD scope, DWORD type, DWORD usage, LPNETRESOURCEW netResource); + DWORD NextW(LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize); + #endif +protected: + bool IsHandleAllocated() const { return _handleAllocated; } +public: + CEnum(): _handleAllocated(false) {} + ~CEnum() { Close(); } + DWORD Close(); + DWORD Open(DWORD scope, DWORD type, DWORD usage, const CResource *resource); + DWORD Next(CResource &resource); + #ifndef _UNICODE + DWORD Open(DWORD scope, DWORD type, DWORD usage, const CResourceW *resource); + DWORD Next(CResourceW &resource); + #endif +}; + +DWORD GetResourceParent(const CResource &resource, CResource &parentResource); +#ifndef _UNICODE +DWORD GetResourceParent(const CResourceW &resource, CResourceW &parentResource); +#endif + +DWORD GetResourceInformation(const CResource &resource, + CResource &destResource, CSysString &systemPathPart); +#ifndef _UNICODE +DWORD GetResourceInformation(const CResourceW &resource, + CResourceW &destResource, UString &systemPathPart); +#endif + +DWORD AddConnection2(const CResource &resource, LPCTSTR password, LPCTSTR userName, DWORD flags); +#ifndef _UNICODE +DWORD AddConnection2(const CResourceW &resource, LPCWSTR password, LPCWSTR userName, DWORD flags); +#endif + +}} + +#endif diff --git a/CPP/Windows/NtCheck.h b/CPP/Windows/NtCheck.h new file mode 100755 index 0000000..b8fa99b --- /dev/null +++ b/CPP/Windows/NtCheck.h @@ -0,0 +1,44 @@ +// Windows/NtCheck.h + +#ifndef __WINDOWS_NT_CHECK_H +#define __WINDOWS_NT_CHECK_H + +#ifdef _WIN32 + +#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/CPP/Windows/Process.cpp b/CPP/Windows/Process.cpp new file mode 100755 index 0000000..27972cd --- /dev/null +++ b/CPP/Windows/Process.cpp @@ -0,0 +1,81 @@ +// Process.cpp + +#include "StdAfx.h" + +#include "../Common/StringConvert.h" + +#include "Process.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { + +static UString GetQuotedString(const UString &s) +{ + return UString(L'\"') + s + UString(L'\"'); +} + +WRes CProcess::Create(LPCWSTR imageName, const UString ¶ms, LPCWSTR curDir) +{ + Close(); + const UString params2 = + #ifndef UNDER_CE + GetQuotedString(imageName) + L' ' + + #endif + params; + #ifdef UNDER_CE + curDir = 0; + #else + imageName = 0; + #endif + PROCESS_INFORMATION pi; + BOOL result; + #ifndef _UNICODE + if (!g_IsNT) + { + STARTUPINFOA si; + si.cb = sizeof(si); + si.lpReserved = 0; + si.lpDesktop = 0; + si.lpTitle = 0; + si.dwFlags = 0; + si.cbReserved2 = 0; + si.lpReserved2 = 0; + + CSysString curDirA; + if (curDir != 0) + curDirA = GetSystemString(curDir); + result = ::CreateProcessA(NULL, (LPSTR)(LPCSTR)GetSystemString(params2), + NULL, NULL, FALSE, 0, NULL, ((curDir != 0) ? (LPCSTR)curDirA: 0), &si, &pi); + } + else + #endif + { + STARTUPINFOW si; + si.cb = sizeof(si); + si.lpReserved = 0; + si.lpDesktop = 0; + si.lpTitle = 0; + si.dwFlags = 0; + si.cbReserved2 = 0; + si.lpReserved2 = 0; + + result = CreateProcessW(imageName, (LPWSTR)(LPCWSTR)params2, + NULL, NULL, FALSE, 0, NULL, (LPWSTR)curDir, &si, &pi); + } + if (result == 0) + return ::GetLastError(); + ::CloseHandle(pi.hThread); + _handle = pi.hProcess; + return 0; +} + +WRes MyCreateProcess(LPCWSTR imageName, const UString ¶ms) +{ + CProcess process; + return process.Create(imageName, params, 0); +} + +} diff --git a/CPP/Windows/Process.h b/CPP/Windows/Process.h new file mode 100755 index 0000000..1b6b555 --- /dev/null +++ b/CPP/Windows/Process.h @@ -0,0 +1,100 @@ +// Windows/Process.h + +#ifndef __WINDOWS_PROCESS_H +#define __WINDOWS_PROCESS_H + +#include + +#include "../Common/MyString.h" + +#include "Defs.h" +#include "Handle.h" + +namespace NWindows { + +class CProcess: public CHandle +{ +public: + bool Open(DWORD desiredAccess, bool inheritHandle, DWORD processId) + { + _handle = ::OpenProcess(desiredAccess, inheritHandle, processId); + return (_handle != 0); + } + + #ifndef UNDER_CE + + bool GetExitCodeProcess(LPDWORD lpExitCode) { return BOOLToBool(::GetExitCodeProcess(_handle, lpExitCode)); } + bool Terminate(UINT exitCode) { return BOOLToBool(::TerminateProcess(_handle, exitCode)); } + #if(WINVER >= 0x0500) + DWORD GetGuiResources (DWORD uiFlags) { return ::GetGuiResources(_handle, uiFlags); } + #endif + bool SetPriorityClass(DWORD dwPriorityClass) { return BOOLToBool(::SetPriorityClass(_handle, dwPriorityClass)); } + DWORD GetPriorityClass() { return ::GetPriorityClass(_handle); } + bool GetIoCounters(PIO_COUNTERS lpIoCounters ) { return BOOLToBool(::GetProcessIoCounters(_handle, lpIoCounters )); } + + bool GetTimes(LPFILETIME creationTime, LPFILETIME exitTime, LPFILETIME kernelTime, LPFILETIME userTime) + { return BOOLToBool(::GetProcessTimes(_handle, creationTime, exitTime, kernelTime, userTime)); } + + DWORD WaitForInputIdle(DWORD milliseconds) { return ::WaitForInputIdle(_handle, milliseconds); } + + // Debug + + bool ReadMemory(LPCVOID baseAddress, LPVOID buffer, SIZE_T size, SIZE_T* numberOfBytesRead) + { return BOOLToBool(::ReadProcessMemory(_handle, baseAddress, buffer, size, numberOfBytesRead)); } + + bool WriteMemory(LPVOID baseAddress, LPCVOID buffer, SIZE_T size, SIZE_T* numberOfBytesWritten) + { return BOOLToBool(::WriteProcessMemory(_handle, baseAddress, buffer, size, numberOfBytesWritten)); } + + bool FlushInstructionCache(LPCVOID baseAddress = 0, SIZE_T size = 0) + { return BOOLToBool(::FlushInstructionCache(_handle, baseAddress, size)); } + + LPVOID VirtualAlloc(LPVOID address, SIZE_T size, DWORD allocationType, DWORD protect) + { return VirtualAllocEx(_handle, address, size, allocationType, protect); } + + bool VirtualFree(LPVOID address, SIZE_T size, DWORD freeType) + { return BOOLToBool(::VirtualFreeEx(_handle, address, size, freeType)); } + + // Process Status API (PSAPI) + + bool EmptyWorkingSet() + { return BOOLToBool(::EmptyWorkingSet(_handle)); } + bool EnumModules(HMODULE *hModules, DWORD arraySizeInBytes, LPDWORD receivedBytes) + { return BOOLToBool(::EnumProcessModules(_handle, hModules, arraySizeInBytes, receivedBytes)); } + + DWORD MyGetModuleBaseName(HMODULE hModule, LPTSTR baseName, DWORD size) + { return ::GetModuleBaseName(_handle, hModule, baseName, size); } + bool MyGetModuleBaseName(HMODULE hModule, CSysString &name) + { + const int length = 1000; + DWORD resultLen = MyGetModuleBaseName(hModule, name.GetBuffer(length), length); + name.ReleaseBuffer(); + return (resultLen != 0); + } + + DWORD MyGetModuleFileNameEx(HMODULE hModule, LPTSTR baseName, DWORD size) + { return ::GetModuleFileNameEx(_handle, hModule, baseName, size); } + bool MyGetModuleFileNameEx(HMODULE hModule, CSysString &name) + { + const int length = MAX_PATH + 100; + DWORD resultLen = MyGetModuleFileNameEx(hModule, name.GetBuffer(length), length); + name.ReleaseBuffer(); + return (resultLen != 0); + } + + bool GetModuleInformation(HMODULE hModule, LPMODULEINFO moduleInfo) + { return BOOLToBool(::GetModuleInformation(_handle, hModule, moduleInfo, sizeof(MODULEINFO))); } + bool GetMemoryInfo(PPROCESS_MEMORY_COUNTERS memCounters) + { return BOOLToBool(::GetProcessMemoryInfo(_handle, memCounters, sizeof(PROCESS_MEMORY_COUNTERS))); } + + #endif + + WRes Create(LPCWSTR imageName, const UString ¶ms, LPCWSTR curDir); + + DWORD Wait() { return ::WaitForSingleObject(_handle, INFINITE); } +}; + +WRes MyCreateProcess(LPCWSTR imageName, const UString ¶ms); + +} + +#endif diff --git a/CPP/Windows/ProcessMessages.cpp b/CPP/Windows/ProcessMessages.cpp new file mode 100755 index 0000000..439d3fd --- /dev/null +++ b/CPP/Windows/ProcessMessages.cpp @@ -0,0 +1,22 @@ +// Windows/ProcessMessages.cpp + +#include "StdAfx.h" + +#include "ProcessMessages.h" + +namespace NWindows { + +void ProcessMessages(HWND window) +{ + MSG msg; + while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) + { + if (window == (HWND) NULL || !IsDialogMessage(window, &msg)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } +} + +} diff --git a/CPP/Windows/ProcessMessages.h b/CPP/Windows/ProcessMessages.h new file mode 100755 index 0000000..082556a --- /dev/null +++ b/CPP/Windows/ProcessMessages.h @@ -0,0 +1,14 @@ +// Windows/ProcessMessages.h + +#ifndef __WINDOWS_PROCESSMESSAGES_H +#define __WINDOWS_PROCESSMESSAGES_H + +namespace NWindows { + +void ProcessMessages(HWND window); + +} + +#endif + + diff --git a/CPP/Windows/PropVariant.cpp b/CPP/Windows/PropVariant.cpp new file mode 100755 index 0000000..bcd85a5 --- /dev/null +++ b/CPP/Windows/PropVariant.cpp @@ -0,0 +1,243 @@ +// Windows/PropVariant.cpp + +#include "StdAfx.h" + +#include "PropVariant.h" + +#include "../Common/Defs.h" + +namespace NWindows { +namespace NCOM { + +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 *kMemException = "out of memory"; + +CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc) +{ + InternalClear(); + vt = VT_BSTR; + wReserved1 = 0; + bstrVal = ::SysAllocString(lpszSrc); + if (bstrVal == NULL && lpszSrc != NULL) + { + throw kMemException; + // vt = VT_ERROR; + // scode = E_OUTOFMEMORY; + } + return *this; +} + + +CPropVariant& CPropVariant::operator=(const char *s) +{ + InternalClear(); + vt = VT_BSTR; + wReserved1 = 0; + UINT len = (UINT)strlen(s); + bstrVal = ::SysAllocStringByteLen(0, (UINT)len * sizeof(OLECHAR)); + if (bstrVal == NULL) + { + throw kMemException; + // vt = VT_ERROR; + // scode = E_OUTOFMEMORY; + } + else + { + for (UINT i = 0; i <= len; i++) + bstrVal[i] = s[i]; + } + return *this; +} + +CPropVariant& CPropVariant::operator=(bool bSrc) +{ + if (vt != VT_BOOL) + { + InternalClear(); + vt = VT_BOOL; + } + boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE; + return *this; +} + +#define SET_PROP_FUNC(type, id, dest) \ + CPropVariant& CPropVariant::operator=(type value) \ + { 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(const FILETIME &, VT_FILETIME, filetime) + +static HRESULT MyPropVariantClear(PROPVARIANT *prop) +{ + switch(prop->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: + prop->vt = VT_EMPTY; + prop->wReserved1 = 0; + return S_OK; + } + return ::VariantClear((VARIANTARG *)prop); +} + +HRESULT CPropVariant::Clear() +{ + return MyPropVariantClear(this); +} + +HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) +{ + ::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) +{ + 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) +{ + HRESULT hr = MyPropVariantClear(pDest); + if (FAILED(hr)) + return hr; + memcpy(pDest, this, sizeof(PROPVARIANT)); + vt = VT_EMPTY; + return S_OK; +} + +HRESULT CPropVariant::InternalClear() +{ + 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) +{ + 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 + // return MyCompare(aPropVarint.cVal); + default: return 0; + } +} + +}} diff --git a/CPP/Windows/PropVariant.h b/CPP/Windows/PropVariant.h new file mode 100755 index 0000000..1605eec --- /dev/null +++ b/CPP/Windows/PropVariant.h @@ -0,0 +1,56 @@ +// Windows/PropVariant.h + +#ifndef __WINDOWS_PROPVARIANT_H +#define __WINDOWS_PROPVARIANT_H + +#include "../Common/MyWindows.h" +#include "../Common/Types.h" + +namespace NWindows { +namespace NCOM { + +class CPropVariant : public tagPROPVARIANT +{ +public: + CPropVariant() { vt = VT_EMPTY; wReserved1 = 0; } + ~CPropVariant() { 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; } + CPropVariant(Int16 value) { vt = VT_I2; wReserved1 = 0; iVal = value; } + CPropVariant(Int32 value) { vt = VT_I4; wReserved1 = 0; lVal = value; } + CPropVariant(UInt32 value) { vt = VT_UI4; wReserved1 = 0; ulVal = value; } + CPropVariant(UInt64 value) { vt = VT_UI8; wReserved1 = 0; uhVal.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 char *s); + CPropVariant& operator=(bool bSrc); + CPropVariant& operator=(Byte value); + CPropVariant& operator=(Int16 value); + CPropVariant& operator=(Int32 value); + CPropVariant& operator=(UInt32 value); + CPropVariant& operator=(Int64 value); + CPropVariant& operator=(UInt64 value); + CPropVariant& operator=(const FILETIME &value); + + HRESULT Clear(); + HRESULT Copy(const PROPVARIANT *pSrc); + HRESULT Attach(PROPVARIANT *pSrc); + HRESULT Detach(PROPVARIANT *pDest); + + HRESULT InternalClear(); + void InternalCopy(const PROPVARIANT *pSrc); + + int Compare(const CPropVariant &a1); +}; + +}} + +#endif diff --git a/CPP/Windows/PropVariantConversions.cpp b/CPP/Windows/PropVariantConversions.cpp new file mode 100755 index 0000000..9d7c2a2 --- /dev/null +++ b/CPP/Windows/PropVariantConversions.cpp @@ -0,0 +1,105 @@ +// PropVariantConversions.cpp + +#include "StdAfx.h" + +#include "Common/IntToString.h" +#include "Common/StringConvert.h" + +#include "Windows/Defs.h" + +#include "PropVariantConversions.h" + +static UString ConvertUInt64ToString(UInt64 value) +{ + wchar_t buffer[32]; + ConvertUInt64ToString(value, buffer); + return buffer; +} + +static UString ConvertInt64ToString(Int64 value) +{ + wchar_t buffer[32]; + ConvertInt64ToString(value, buffer); + return buffer; +} + +static char *UIntToStringSpec(char c, UInt32 value, char *s, int numPos) +{ + if (c != 0) + *s++ = c; + char temp[16]; + int pos = 0; + do + { + temp[pos++] = (char)('0' + value % 10); + value /= 10; + } + while (value != 0); + int i; + for (i = 0; i < numPos - pos; i++) + *s++ = '0'; + do + *s++ = temp[--pos]; + while (pos > 0); + *s = '\0'; + return s; +} + +bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime, bool includeSeconds) +{ + s[0] = '\0'; + SYSTEMTIME st; + if (!BOOLToBool(FileTimeToSystemTime(&ft, &st))) + return false; + s = UIntToStringSpec(0, st.wYear, s, 4); + s = UIntToStringSpec('-', st.wMonth, s, 2); + s = UIntToStringSpec('-', st.wDay, s, 2); + if (includeTime) + { + s = UIntToStringSpec(' ', st.wHour, s, 2); + s = UIntToStringSpec(':', st.wMinute, s, 2); + if (includeSeconds) + UIntToStringSpec(':', st.wSecond, s, 2); + } + return true; +} + +UString ConvertFileTimeToString(const FILETIME &ft, bool includeTime, bool includeSeconds) +{ + char s[32]; + ConvertFileTimeToString(ft, s, includeTime, includeSeconds); + return GetUnicodeString(s); +} + + +UString ConvertPropVariantToString(const PROPVARIANT &prop) +{ + switch (prop.vt) + { + case VT_EMPTY: return UString(); + case VT_BSTR: return prop.bstrVal; + case VT_UI1: return ConvertUInt64ToString(prop.bVal); + case VT_UI2: return ConvertUInt64ToString(prop.uiVal); + case VT_UI4: return ConvertUInt64ToString(prop.ulVal); + case VT_UI8: return ConvertUInt64ToString(prop.uhVal.QuadPart); + case VT_FILETIME: return ConvertFileTimeToString(prop.filetime, true, true); + // case VT_I1: return ConvertInt64ToString(prop.cVal); + case VT_I2: return ConvertInt64ToString(prop.iVal); + case VT_I4: return ConvertInt64ToString(prop.lVal); + case VT_I8: return ConvertInt64ToString(prop.hVal.QuadPart); + case VT_BOOL: return VARIANT_BOOLToBool(prop.boolVal) ? L"+" : L"-"; + default: throw 150245; + } +} + +UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &prop) +{ + switch (prop.vt) + { + case VT_UI1: return prop.bVal; + case VT_UI2: return prop.uiVal; + case VT_UI4: return prop.ulVal; + case VT_UI8: return (UInt64)prop.uhVal.QuadPart; + default: throw 151199; + } +} diff --git a/CPP/Windows/PropVariantConversions.h b/CPP/Windows/PropVariantConversions.h new file mode 100755 index 0000000..74139a4 --- /dev/null +++ b/CPP/Windows/PropVariantConversions.h @@ -0,0 +1,14 @@ +// Windows/PropVariantConversions.h + +#ifndef __PROP_VARIANT_CONVERSIONS_H +#define __PROP_VARIANT_CONVERSIONS_H + +#include "Common/MyString.h" +#include "Common/Types.h" + +bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime = true, bool includeSeconds = true); +UString ConvertFileTimeToString(const FILETIME &ft, bool includeTime = true, bool includeSeconds = true); +UString ConvertPropVariantToString(const PROPVARIANT &prop); +UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &prop); + +#endif diff --git a/CPP/Windows/PropVariantUtils.cpp b/CPP/Windows/PropVariantUtils.cpp new file mode 100755 index 0000000..a2ebd64 --- /dev/null +++ b/CPP/Windows/PropVariantUtils.cpp @@ -0,0 +1,78 @@ +// PropVariantUtils.cpp + +#include "StdAfx.h" + +#include "PropVariantUtils.h" +#include "Common/StringConvert.h" +#include "Common/IntToString.h" + +using namespace NWindows; + +static AString GetHex(UInt32 v) +{ + char sz[32] = { '0', 'x' }; + ConvertUInt64ToString(v, sz + 2, 16); + return sz; +} + +void StringToProp(const AString &s, NCOM::CPropVariant &prop) +{ + prop = MultiByteToUnicodeString(s); +} + +void PairToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 value, NCOM::CPropVariant &prop) +{ + AString s; + for (unsigned i = 0; i < num; i++) + { + const CUInt32PCharPair &p = pairs[i]; + if (p.Value == value) + s = p.Name; + } + if (s.IsEmpty()) + s = GetHex(value); + StringToProp(s, prop); +} + +AString TypeToString(const char *table[], unsigned num, UInt32 value) +{ + if (value < num) + return table[value]; + return GetHex(value); +} + +void TypeToProp(const char *table[], unsigned num, UInt32 value, NCOM::CPropVariant &prop) +{ + StringToProp(TypeToString(table, num, value), prop); +} + + +AString FlagsToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags) +{ + AString s; + for (unsigned i = 0; i < num; i++) + { + const CUInt32PCharPair &p = pairs[i]; + UInt32 flag = (UInt32)1 << (unsigned)p.Value; + if ((flags & flag) != 0) + { + if (!s.IsEmpty()) + s += ' '; + s += p.Name; + } + flags &= ~flag; + } + if (flags != 0) + { + if (!s.IsEmpty()) + s += ' '; + s += GetHex(flags); + } + return s; +} + +void FlagsToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags, NCOM::CPropVariant &prop) +{ + StringToProp(FlagsToString(pairs, num, flags), prop); +} + diff --git a/CPP/Windows/PropVariantUtils.h b/CPP/Windows/PropVariantUtils.h new file mode 100755 index 0000000..88025c5 --- /dev/null +++ b/CPP/Windows/PropVariantUtils.h @@ -0,0 +1,28 @@ +// Windows/PropVariantUtils.h + +#ifndef __PROP_VARIANT_UTILS_H +#define __PROP_VARIANT_UTILS_H + +#include "Common/MyString.h" +#include "PropVariant.h" + +struct CUInt32PCharPair +{ + UInt32 Value; + const char *Name; +}; + +void StringToProp(const AString &s, NWindows::NCOM::CPropVariant &prop); +void PairToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 value, NWindows::NCOM::CPropVariant &prop); + +AString FlagsToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags); +void FlagsToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags, NWindows::NCOM::CPropVariant &prop); + +AString TypeToString(const char *table[], unsigned num, UInt32 value); +void TypeToProp(const char *table[], unsigned num, UInt32 value, NWindows::NCOM::CPropVariant &prop); + +#define PAIR_TO_PROP(pairs, value, prop) PairToProp(pairs, sizeof(pairs) / sizeof(pairs[0]), value, prop) +#define FLAGS_TO_PROP(pairs, value, prop) FlagsToProp(pairs, sizeof(pairs) / sizeof(pairs[0]), value, prop) +#define TYPE_TO_PROP(table, value, prop) TypeToProp(table, sizeof(table) / sizeof(table[0]), value, prop) + +#endif diff --git a/CPP/Windows/Registry.cpp b/CPP/Windows/Registry.cpp new file mode 100755 index 0000000..3db00ea --- /dev/null +++ b/CPP/Windows/Registry.cpp @@ -0,0 +1,369 @@ +// Windows/Registry.cpp + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "Common/StringConvert.h" +#endif +#include "Windows/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) +{ + 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) +{ + 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() +{ + 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) +{ + MYASSERT(_object != NULL); + return RegDeleteKey(_object, subKeyName); +} + +LONG CKey::RecurseDeleteKey(LPCTSTR subKeyName) +{ + CKey key; + LONG res = key.Open(_object, subKeyName, KEY_READ | KEY_WRITE); + if (res != ERROR_SUCCESS) + return res; + FILETIME fileTime; + const UInt32 kBufferSize = MAX_PATH + 1; // 256 in ATL + DWORD size = kBufferSize; + TCHAR buffer[kBufferSize]; + while (RegEnumKeyEx(key._object, 0, buffer, &size, NULL, NULL, NULL, &fileTime) == ERROR_SUCCESS) + { + res = key.RecurseDeleteKey(buffer); + if (res != ERROR_SUCCESS) + return res; + size = kBufferSize; + } + 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) +{ + 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) +{ + MYASSERT(_object != NULL); + return RegSetValueEx(_object, name, NULL, REG_DWORD, + (BYTE * const)&value, sizeof(UInt32)); +} + +LONG CKey::SetValue(LPCTSTR name, bool value) +{ + return SetValue(name, BoolToUINT32(value)); +} + +LONG CKey::SetValue(LPCTSTR name, LPCTSTR value) +{ + MYASSERT(value != NULL); + MYASSERT(_object != NULL); + return RegSetValueEx(_object, name, NULL, 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.Length() + 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, NULL, 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) +{ + MYASSERT(value != NULL); + MYASSERT(_object != NULL); + return RegSetValueEx(_object, name, NULL, 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) +{ + 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) +{ + DWORD type = NULL; + 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) +{ + UInt32 uintValue = BoolToUINT32(value); + LONG res = QueryValue(name, uintValue); + value = UINT32ToBool(uintValue); + return res; +} + +LONG CKey::GetValue_IfOk(LPCTSTR name, UInt32 &value) +{ + UInt32 newVal; + LONG res = QueryValue(name, newVal); + if (res == ERROR_SUCCESS) + value = newVal; + return res; +} + +LONG CKey::GetValue_IfOk(LPCTSTR name, bool &value) +{ + bool newVal; + LONG res = QueryValue(name, newVal); + if (res == ERROR_SUCCESS) + value = newVal; + return res; +} + +LONG CKey::QueryValue(LPCTSTR name, LPTSTR value, UInt32 &count) +{ + MYASSERT(count != NULL); + DWORD type = NULL; + 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 = NULL; + UInt32 currentSize = 0; + LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)¤tSize); + if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) + return res; + res = QueryValue(name, value.GetBuffer(currentSize), currentSize); + value.ReleaseBuffer(); + return res; +} + +#ifndef _UNICODE +LONG CKey::QueryValue(LPCWSTR name, LPWSTR value, UInt32 &count) +{ + MYASSERT(count != NULL); + DWORD type = NULL; + 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 = NULL; + UInt32 currentSize = 0; + + LONG res; + if (g_IsNT) + { + res = RegQueryValueExW(_object, name, NULL, &type, NULL, (DWORD *)¤tSize); + if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) + return res; + res = QueryValue(name, value.GetBuffer(currentSize), currentSize); + value.ReleaseBuffer(); + } + 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) +{ + DWORD type = NULL; + 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 = NULL; + dataSize = 0; + LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&dataSize); + if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) + return res; + value.SetCapacity(dataSize); + return QueryValue(name, (BYTE *)value, dataSize); +} + +LONG CKey::EnumKeys(CSysStringVector &keyNames) +{ + keyNames.Clear(); + CSysString keyName; + for (UInt32 index = 0; ; index++) + { + const UInt32 kBufferSize = MAX_PATH + 1; // 256 in ATL + FILETIME lastWriteTime; + UInt32 nameSize = kBufferSize; + LONG result = ::RegEnumKeyEx(_object, index, keyName.GetBuffer(kBufferSize), + (DWORD *)&nameSize, NULL, NULL, NULL, &lastWriteTime); + keyName.ReleaseBuffer(); + 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) +{ + UInt32 numChars = 0; + int i; + for (i = 0; i < strings.Size(); i++) + numChars += strings[i].Length() + 1; + CBuffer buffer; + buffer.SetCapacity(numChars); + int pos = 0; + for (i = 0; i < strings.Size(); i++) + { + const UString &s = strings[i]; + MyStringCopy((wchar_t *)buffer + pos, (const wchar_t *)s); + pos += s.Length() + 1; + } + return SetValue(valueName, buffer, numChars * sizeof(wchar_t)); +} + +LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings) +{ + strings.Clear(); + CByteBuffer buffer; + UInt32 dataSize; + LONG res = QueryValue(valueName, buffer, dataSize); + if (res != ERROR_SUCCESS) + return res; + if (dataSize % sizeof(wchar_t) != 0) + return E_FAIL; + const wchar_t *data = (const wchar_t *)(const Byte *)buffer; + int numChars = dataSize / sizeof(wchar_t); + UString s; + for (int i = 0; i < numChars; i++) + { + wchar_t c = data[i]; + if (c == 0) + { + strings.Add(s); + s.Empty(); + } + else + s += c; + } + return res; +} + +}} diff --git a/CPP/Windows/Registry.h b/CPP/Windows/Registry.h new file mode 100755 index 0000000..8f4ede3 --- /dev/null +++ b/CPP/Windows/Registry.h @@ -0,0 +1,85 @@ +// Windows/Registry.h + +#ifndef __WINDOWS_REGISTRY_H +#define __WINDOWS_REGISTRY_H + +#include "Common/Buffer.h" +#include "Common/MyString.h" +#include "Common/Types.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); + LONG Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask = KEY_ALL_ACCESS); + + LONG Close(); + + LONG DeleteSubKey(LPCTSTR subKeyName); + LONG RecurseDeleteKey(LPCTSTR subKeyName); + + LONG DeleteValue(LPCTSTR name); + #ifndef _UNICODE + LONG DeleteValue(LPCWSTR name); + #endif + + LONG SetValue(LPCTSTR valueName, UInt32 value); + LONG SetValue(LPCTSTR valueName, bool value); + LONG SetValue(LPCTSTR valueName, LPCTSTR value); + // 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); + + LONG SetValue_Strings(LPCTSTR valueName, const UStringVector &strings); + LONG GetValue_Strings(LPCTSTR valueName, UStringVector &strings); + + LONG SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value); + + LONG QueryValue(LPCTSTR name, UInt32 &value); + LONG QueryValue(LPCTSTR name, bool &value); + LONG QueryValue(LPCTSTR name, LPTSTR value, UInt32 &dataSize); + LONG QueryValue(LPCTSTR name, CSysString &value); + + LONG GetValue_IfOk(LPCTSTR name, UInt32 &value); + LONG GetValue_IfOk(LPCTSTR name, bool &value); + + #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); + LONG QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize); + + LONG EnumKeys(CSysStringVector &keyNames); +}; + +}} + +#endif diff --git a/CPP/Windows/ResourceString.cpp b/CPP/Windows/ResourceString.cpp new file mode 100755 index 0000000..83b7c23 --- /dev/null +++ b/CPP/Windows/ResourceString.cpp @@ -0,0 +1,64 @@ +// Windows/ResourceString.cpp + +#include "StdAfx.h" + +#include "Windows/ResourceString.h" +#ifndef _UNICODE +#include "Common/StringConvert.h" +#endif + +extern HINSTANCE g_hInstance; +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { + +CSysString MyLoadString(HINSTANCE hInstance, UINT resourceID) +{ + CSysString s; + int size = 256; + int len; + do + { + size += 256; + len = ::LoadString(hInstance, resourceID, s.GetBuffer(size - 1), size); + } + while (size - len <= 1); + s.ReleaseBuffer(); + return s; +} + +CSysString MyLoadString(UINT resourceID) +{ + return MyLoadString(g_hInstance, resourceID); +} + +#ifndef _UNICODE +UString MyLoadStringW(HINSTANCE hInstance, UINT resourceID) +{ + if (g_IsNT) + { + UString s; + int size = 256; + int len; + do + { + size += 256; + len = ::LoadStringW(hInstance, resourceID, s.GetBuffer(size - 1), size); + } + while (size - len <= 1); + s.ReleaseBuffer(); + return s; + } + return GetUnicodeString(MyLoadString(hInstance, resourceID)); +} + +UString MyLoadStringW(UINT resourceID) +{ + return MyLoadStringW(g_hInstance, resourceID); +} + +#endif + +} diff --git a/CPP/Windows/ResourceString.h b/CPP/Windows/ResourceString.h new file mode 100755 index 0000000..fd49286 --- /dev/null +++ b/CPP/Windows/ResourceString.h @@ -0,0 +1,22 @@ +// Windows/ResourceString.h + +#ifndef __WINDOWS_RESOURCESTRING_H +#define __WINDOWS_RESOURCESTRING_H + +#include "Common/MyString.h" + +namespace NWindows { + +CSysString MyLoadString(HINSTANCE hInstance, UINT resourceID); +CSysString MyLoadString(UINT resourceID); +#ifdef _UNICODE +inline UString MyLoadStringW(HINSTANCE hInstance, UINT resourceID) { return MyLoadString(hInstance, resourceID); } +inline UString MyLoadStringW(UINT resourceID) { return MyLoadString(resourceID); } +#else +UString MyLoadStringW(HINSTANCE hInstance, UINT resourceID); +UString MyLoadStringW(UINT resourceID); +#endif + +} + +#endif diff --git a/CPP/Windows/Security.cpp b/CPP/Windows/Security.cpp new file mode 100755 index 0000000..a762f07 --- /dev/null +++ b/CPP/Windows/Security.cpp @@ -0,0 +1,179 @@ +// Windows/Security.cpp + +#include "StdAfx.h" + +#include "Security.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.GetBuffer(0), &accountNameSize, + domainName.GetBuffer(0), &domainNameSize, sidNameUse)) + { + if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) + return false; + } + bool result = BOOLToBool(::LookupAccountSid(systemName, sid, + accountName.GetBuffer(accountNameSize), &accountNameSize, + domainName.GetBuffer(domainNameSize), &domainNameSize, sidNameUse)); + accountName.ReleaseBuffer(); + domainName.ReleaseBuffer(); + 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/CPP/Windows/Security.h b/CPP/Windows/Security.h new file mode 100755 index 0000000..8a88777 --- /dev/null +++ b/CPP/Windows/Security.h @@ -0,0 +1,167 @@ +// Windows/Security.h + +#ifndef __WINDOWS_SECURITY_H +#define __WINDOWS_SECURITY_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/CPP/Windows/Shell.cpp b/CPP/Windows/Shell.cpp new file mode 100755 index 0000000..89b2e7e --- /dev/null +++ b/CPP/Windows/Shell.cpp @@ -0,0 +1,335 @@ +// Windows/Shell.cpp + +#include "StdAfx.h" + +#include "Common/MyCom.h" +#ifndef _UNICODE +#include "Common/StringConvert.h" +#endif + +#include "Windows/COM.h" +#include "Windows/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); + QueryFile(fileIndex, fileNameA.GetBuffer(bufferSize + 2), bufferSize + 1); + fileNameA.ReleaseBuffer(); + fileName = GetUnicodeString(fileNameA); + } + else + #endif + { + UINT bufferSize = QueryFile(fileIndex, (LPWSTR)NULL, 0); + QueryFile(fileIndex, fileName.GetBuffer(bufferSize + 2), bufferSize + 1); + fileName.ReleaseBuffer(); + } + return fileName; +} + +void CDrop::QueryFileNames(UStringVector &fileNames) +{ + fileNames.Clear(); + UINT numFiles = QueryCountOfFiles(); + fileNames.Reserve(numFiles); + for (UINT i = 0; i < numFiles; i++) + fileNames.Add(QueryFileName(i)); +} + + +bool GetPathFromIDList(LPCITEMIDLIST itemIDList, CSysString &path) +{ + bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuffer(MAX_PATH * 2))); + path.ReleaseBuffer(); + 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 = L"all files"; + s += L" (*.*)"; + 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 WinCE SDK!!! + #ifdef UNDER_CE + browseInfo.pszDisplayName = (LPSTR)displayName.GetBuffer(MAX_PATH); + browseInfo.lpszTitle = (LPCSTR)title; + #else + browseInfo.pszDisplayName = displayName.GetBuffer(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; + bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuffer(MAX_PATH * 2))); + path.ReleaseBuffer(); + 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.GetBuffer(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/CPP/Windows/Shell.h b/CPP/Windows/Shell.h new file mode 100755 index 0000000..d8849cd --- /dev/null +++ b/CPP/Windows/Shell.h @@ -0,0 +1,93 @@ +// Windows/Shell.h + +#ifndef __WINDOWS_SHELL_H +#define __WINDOWS_SHELL_H + +#include +#include + +#include "Common/MyString.h" +#include "Windows/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/CPP/Windows/StdAfx.h b/CPP/Windows/StdAfx.h new file mode 100755 index 0000000..5308d63 --- /dev/null +++ b/CPP/Windows/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../Common/MyWindows.h" +#include "../Common/NewHandler.h" + +#endif diff --git a/CPP/Windows/Synchronization.cpp b/CPP/Windows/Synchronization.cpp new file mode 100755 index 0000000..01f1ad9 --- /dev/null +++ b/CPP/Windows/Synchronization.cpp @@ -0,0 +1,10 @@ +// Windows/Synchronization.cpp + +#include "StdAfx.h" + +#include "Synchronization.h" + +namespace NWindows { +namespace NSynchronization { + +}} diff --git a/CPP/Windows/Synchronization.h b/CPP/Windows/Synchronization.h new file mode 100755 index 0000000..786da00 --- /dev/null +++ b/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/CPP/Windows/System.cpp b/CPP/Windows/System.cpp new file mode 100755 index 0000000..545ea0e --- /dev/null +++ b/CPP/Windows/System.cpp @@ -0,0 +1,72 @@ +// Windows/System.cpp + +#include "StdAfx.h" + +#include "../Common/Defs.h" + +#include "System.h" + +namespace NWindows { +namespace NSystem { + +UInt32 GetNumberOfProcessors() +{ + SYSTEM_INFO systemInfo; + GetSystemInfo(&systemInfo); + return (UInt32)systemInfo.dwNumberOfProcessors; +} + +#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 + +UInt64 GetRamSize() +{ + #ifndef UNDER_CE + MY_MEMORYSTATUSEX stat; + stat.dwLength = sizeof(stat); + #endif + #ifdef _WIN64 + if (!::GlobalMemoryStatusEx(&stat)) + return 0; + return MyMin(stat.ullTotalVirtual, stat.ullTotalPhys); + #else + #ifndef UNDER_CE + GlobalMemoryStatusExP globalMemoryStatusEx = (GlobalMemoryStatusExP) + ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GlobalMemoryStatusEx"); + if (globalMemoryStatusEx != 0 && globalMemoryStatusEx(&stat)) + return MyMin(stat.ullTotalVirtual, stat.ullTotalPhys); + #endif + { + MEMORYSTATUS stat; + stat.dwLength = sizeof(stat); + ::GlobalMemoryStatus(&stat); + return MyMin(stat.dwTotalVirtual, stat.dwTotalPhys); + } + #endif +} + +}} diff --git a/CPP/Windows/System.h b/CPP/Windows/System.h new file mode 100755 index 0000000..49a4fe7 --- /dev/null +++ b/CPP/Windows/System.h @@ -0,0 +1,16 @@ +// Windows/System.h + +#ifndef __WINDOWS_SYSTEM_H +#define __WINDOWS_SYSTEM_H + +#include "../Common/Types.h" + +namespace NWindows { +namespace NSystem { + +UInt32 GetNumberOfProcessors(); +UInt64 GetRamSize(); + +}} + +#endif diff --git a/CPP/Windows/Thread.h b/CPP/Windows/Thread.h new file mode 100755 index 0000000..1b5863c --- /dev/null +++ b/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/CPP/Windows/Time.cpp b/CPP/Windows/Time.cpp new file mode 100755 index 0000000..0504cdf --- /dev/null +++ b/CPP/Windows/Time.cpp @@ -0,0 +1,170 @@ +// Windows/Time.cpp + +#include "StdAfx.h" + +#include "Windows/Defs.h" + +#include "Time.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 kUnixTimeStartValue = ((UInt64)kNumTimeQuantumsInSecond) * + 60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear)); + +bool DosTimeToFileTime(UInt32 dosTime, FILETIME &ft) +{ + #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) +{ + #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; +} + +void UnixTimeToFileTime(UInt32 unixTime, FILETIME &ft) +{ + UInt64 v = kUnixTimeStartValue + ((UInt64)unixTime) * kNumTimeQuantumsInSecond; + ft.dwLowDateTime = (DWORD)v; + ft.dwHighDateTime = (DWORD)(v >> 32); +} + +bool FileTimeToUnixTime(const FILETIME &ft, UInt32 &unixTime) +{ + UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; + if (winTime < kUnixTimeStartValue) + { + unixTime = 0; + return false; + } + winTime = (winTime - kUnixTimeStartValue) / kNumTimeQuantumsInSecond; + 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) +{ + 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) +{ + SYSTEMTIME st; + GetSystemTime(&st); + SystemTimeToFileTime(&st, &ft); +} + +}} diff --git a/CPP/Windows/Time.h b/CPP/Windows/Time.h new file mode 100755 index 0000000..7ecb204 --- /dev/null +++ b/CPP/Windows/Time.h @@ -0,0 +1,21 @@ +// Windows/Time.h + +#ifndef __WINDOWS_TIME_H +#define __WINDOWS_TIME_H + +#include "Common/Types.h" + +namespace NWindows { +namespace NTime { + +bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime); +bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime); +void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime); +bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime); +bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, + unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds); +void GetCurUtcFileTime(FILETIME &ft); + +}} + +#endif diff --git a/CPP/Windows/Window.cpp b/CPP/Windows/Window.cpp new file mode 100755 index 0000000..b283686 --- /dev/null +++ b/CPP/Windows/Window.cpp @@ -0,0 +1,169 @@ +// Windows/Window.cpp + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "Common/StringConvert.h" +#endif +#include "Windows/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 length = GetTextLength(); + if (length == 0) + return (::GetLastError() == ERROR_SUCCESS); + length = GetText(s.GetBuffer(length), length + 1); + s.ReleaseBuffer(); + if (length == 0) + return (::GetLastError() != ERROR_SUCCESS); + return true; +} + +#ifndef _UNICODE +bool CWindow::GetText(UString &s) +{ + if (g_IsNT) + { + s.Empty(); + int length = GetWindowTextLengthW(_window); + if (length == 0) + return (::GetLastError() == ERROR_SUCCESS); + length = GetWindowTextW(_window, s.GetBuffer(length), length + 1); + s.ReleaseBuffer(); + if (length == 0) + return (::GetLastError() == ERROR_SUCCESS); + return true; + } + CSysString sysString; + bool result = GetText(sysString); + s = GetUnicodeString(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/CPP/Windows/Window.h b/CPP/Windows/Window.h new file mode 100755 index 0000000..aeb8dd9 --- /dev/null +++ b/CPP/Windows/Window.h @@ -0,0 +1,261 @@ +// Windows/Window.h + +#ifndef __WINDOWS_WINDOW_H +#define __WINDOWS_WINDOW_H + +#include "Defs.h" +#include "Common/MyString.h" + +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)); } + #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) { SendMessage(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 SendMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) + { return ::SendMessage(_window, message, wParam, lParam) ;} + #ifndef _UNICODE + LRESULT SendMessageW(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) + { return ::SendMessageW(_window, message, wParam, lParam) ;} + #endif + + bool PostMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) + { return BOOLToBool(::PostMessage(_window, message, wParam, lParam)) ;} + #ifndef _UNICODE + LRESULT PostMessageW(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) + { return ::PostMessageW(_window, message, wParam, lParam) ;} + #endif + + bool SetText(LPCTSTR s) { return BOOLToBool(::SetWindowText(_window, s)); } + #ifndef _UNICODE + bool CWindow::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)SendMessage(WM_SETICON, sizeType, (LPARAM)icon); } +}; + +#define RECT_SIZE_X(r) ((r).right - (r).left) +#define RECT_SIZE_Y(r) ((r).bottom - (r).top) + +} + +#endif + diff --git a/DOC/7zC.txt b/DOC/7zC.txt new file mode 100755 index 0000000..4ff6325 --- /dev/null +++ b/DOC/7zC.txt @@ -0,0 +1,194 @@ +7z ANSI-C Decoder 4.62 +---------------------- + +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 must download 7-Zip program from www.7-zip.org. + +You can create .7z archive with 7z.exe or 7za.exe: + + 7za.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: + ~~~~~~~~~~~~~ + { + UInt32 i; + for (i = 0; i < db.db.NumFiles; i++) + { + CFileItem *f = db.db.Files + i; + printf("%10d %s\n", (int)f->Size, f->Name); + } + } + + 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/DOC/7zFormat.txt b/DOC/7zFormat.txt new file mode 100755 index 0000000..6b8678f --- /dev/null +++ b/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/DOC/7zip.hhp b/DOC/7zip.hhp new file mode 100755 index 0000000..84667f5 --- /dev/null +++ b/DOC/7zip.hhp @@ -0,0 +1,70 @@ +[OPTIONS] +Compatibility=1.1 or later +Compiled file=7-zip.chm +Contents file=7zip.hhc +Default topic=start.htm +Display compile progress=No +Full-text search=Yes +Index file=7zip.hhk +Language=0x409 English (United States) + + +[FILES] +start.htm +general\thanks.htm +general\faq.htm +general\formats.htm +general\index.htm +general\license.htm +general\performance.htm +general\7z.htm +cmdline\index.htm +cmdline\syntax.htm +cmdline\exit_codes.htm +cmdline\commands\update.htm +cmdline\commands\delete.htm +cmdline\commands\extract.htm +cmdline\commands\extract_full.htm +cmdline\commands\index.htm +cmdline\commands\list.htm +cmdline\commands\test.htm +cmdline\commands\add.htm +cmdline\commands\bench.htm +cmdline\switches\index.htm +cmdline\switches\yes.htm +cmdline\switches\include.htm +cmdline\switches\method.htm +cmdline\switches\ar_include.htm +cmdline\switches\ar_exclude.htm +cmdline\switches\ar_no.htm +cmdline\switches\scc.htm +cmdline\switches\charset.htm +cmdline\switches\email.htm +cmdline\switches\list_tech.htm +cmdline\switches\large_pages.htm +cmdline\switches\output_dir.htm +cmdline\switches\overwrite.htm +cmdline\switches\password.htm +cmdline\switches\recurse.htm +cmdline\switches\sfx.htm +cmdline\switches\shared.htm +cmdline\switches\ssc.htm +cmdline\switches\stdin.htm +cmdline\switches\stdout.htm +cmdline\switches\stop_switch.htm +cmdline\switches\type.htm +cmdline\switches\update.htm +cmdline\switches\working_dir.htm +cmdline\switches\exclude.htm +fm\options.htm +fm\benchmark.htm +fm\index.htm +fm\menu.htm +fm\about.htm +fm\plugins\index.htm +fm\plugins\7-zip\extract.htm +fm\plugins\7-zip\index.htm +fm\plugins\7-zip\add.htm + +[INFOTYPES] + diff --git a/DOC/7zip.inf b/DOC/7zip.inf new file mode 100755 index 0000000..b5758ff --- /dev/null +++ b/DOC/7zip.inf @@ -0,0 +1,55 @@ +[CODE] + +[Version] +Signature = "$Windows NT$" +Provider = "7-zip.org" +CESignature = "$Windows CE$" + +[CEStrings] +AppName = "7-Zip" +InstallDir = %CE1%\%AppName% + +[Strings] +AppVer = "9.20" +AppDate = "2010-11-18" + +[CEDevice] +; ProcessorType = 2577 ; ARM +VersionMin = 3.0 +BuildMin = 0.0 +VersionMax = 1000.0 +BuildMax = 0xE0000000 + +[DefaultInstall] +CopyFiles = CopyFilesSection,CopyFilesSection.Lang +AddReg = RegSettings +CEShortcuts = Shortcuts + +[SourceDisksNames] +1 = ,"Common files",,"." +2 = ,"Lang files",,"Lang" + +[SourceDisksFiles] +7zFM.exe = 1 +7z.sfx = 1 +7zS2.sfx = 1 +ru.txt = 2 + +[DestinationDirs] +DefaultDestDir = ,%InstallDir% +CopyFilesSection = ,%InstallDir% +CopyFilesSection.Lang = ,"%InstallDir%\Lang" +Shortcuts = ,%CE11% + +[CopyFilesSection] +7zFM.exe +7z.sfx +7zS2.sfx + +[CopyFilesSection.Lang] +ru.txt + +[RegSettings] + +[Shortcuts] +7-Zip,0,7zFM.exe diff --git a/DOC/7zip.nsi b/DOC/7zip.nsi new file mode 100755 index 0000000..6ff701d --- /dev/null +++ b/DOC/7zip.nsi @@ -0,0 +1,535 @@ +;-------------------------------- +;Defines + +!define VERSION_MAJOR 9 +!define VERSION_MINOR 20 +!define VERSION_POSTFIX_FULL "" +!ifdef WIN64 +!ifdef IA64 +!define VERSION_SYS_POSTFIX_FULL " for Windows IA-64" +!else +!define VERSION_SYS_POSTFIX_FULL " for Windows x64" +!endif +!else +!define VERSION_SYS_POSTFIX_FULL "" +!endif +!define NAME_FULL "7-Zip ${VERSION_MAJOR}.${VERSION_MINOR}${VERSION_POSTFIX_FULL}${VERSION_SYS_POSTFIX_FULL}" +!define VERSION_POSTFIX "" +!ifdef WIN64 +!ifdef IA64 +!define VERSION_SYS_POSTFIX "-ia64" +!else +!define VERSION_SYS_POSTFIX "-x64" +!endif +!else +!define VERSION_SYS_POSTFIX "" +!endif + + + +!define FM_LINK "7-Zip File Manager.lnk" +!define HELP_LINK "7-Zip Help.lnk" + +!define CLSID_CONTEXT_MENU {23170F69-40C1-278A-1000-000100020000} + +#!define NO_COMPRESSION + + !include "Library.nsh" + !include "MUI.nsh" + +;-------------------------------- +;Configuration + + ;General + Name "${NAME_FULL}" + BrandingText "www.7-zip.org" + OutFile "..\7z${VERSION_MAJOR}${VERSION_MINOR}${VERSION_POSTFIX}${VERSION_SYS_POSTFIX}.exe" + + ;Folder selection page + InstallDir "$PROGRAMFILES\7-Zip" + + ;Get install folder from registry if available + InstallDirRegKey HKLM "Software\7-Zip" "Path" + + ;Compressor +!ifndef NO_COMPRESSION + SetCompressor /solid lzma + ; SetCompressorFilter 1 +!ifdef IA64 + SetCompressorDictSize 8 +!else + SetCompressorDictSize 4 +!endif +!else + SetCompress off +!endif + + +;-------------------------------- +;Variables + +;-------------------------------- +;Interface Settings + + !define MUI_ABORTWARNING + +;-------------------------------- +;Pages + + #!insertmacro MUI_PAGE_LICENSE "License.txt" + !insertmacro MUI_PAGE_DIRECTORY + !insertmacro MUI_PAGE_INSTFILES + !insertmacro MUI_PAGE_FINISH + + !insertmacro MUI_UNPAGE_CONFIRM + !insertmacro MUI_UNPAGE_INSTFILES + !insertmacro MUI_UNPAGE_FINISH + +;-------------------------------- +;Languages + + !insertmacro MUI_LANGUAGE "English" + +;-------------------------------- +;Reserve Files + + ;These files should be inserted before other files in the data block + ;Keep these lines before any File command + ;Only for solid compression (by default, solid compression is enabled for BZIP2 and LZMA) + + !insertmacro MUI_RESERVEFILE_LANGDLL + +;-------------------------------- +;Installer Sections + +Section + !ifndef WIN64 + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\App Paths\7zFMn.exe" + !endif + + # delete old unwanted files + Delete $INSTDIR\7zFMn.exe + Delete $INSTDIR\7zgn.exe + Delete $INSTDIR\7zn.exe + Delete $INSTDIR\7zan.exe + Delete $INSTDIR\7zC.sfx + Delete $INSTDIR\7-zipn.dll + Delete $INSTDIR\7zipDoc.txt + Delete $INSTDIR\file_id.diz + + Delete $INSTDIR\Codecs\7zAES.dll + Delete $INSTDIR\Codecs\AES.dll + Delete $INSTDIR\Codecs\Branch.dll + Delete $INSTDIR\Codecs\BZip2.dll + Delete $INSTDIR\Codecs\Copy.dll + Delete $INSTDIR\Codecs\Deflate.dll + Delete $INSTDIR\Codecs\Implode.dll + Delete $INSTDIR\Codecs\LZMA.dll + Delete $INSTDIR\Codecs\PPMD.dll + Delete $INSTDIR\Codecs\Rar29.dll + Delete $INSTDIR\Codecs\Swap.dll + + RMDir $INSTDIR\Codecs + + Delete $INSTDIR\Formats\7z.dll + Delete $INSTDIR\Formats\arj.dll + Delete $INSTDIR\Formats\bz2.dll + Delete $INSTDIR\Formats\cab.dll + Delete $INSTDIR\Formats\chm.dll + Delete $INSTDIR\Formats\cpio.dll + Delete $INSTDIR\Formats\deb.dll + Delete $INSTDIR\Formats\gz.dll + Delete $INSTDIR\Formats\iso.dll + Delete $INSTDIR\Formats\lzh.dll + Delete $INSTDIR\Formats\nsis.dll + Delete $INSTDIR\Formats\rar.dll + Delete $INSTDIR\Formats\rpm.dll + Delete $INSTDIR\Formats\split.dll + Delete $INSTDIR\Formats\tar.dll + Delete $INSTDIR\Formats\z.dll + Delete $INSTDIR\Formats\zip.dll + + RMDir $INSTDIR\Formats + + Delete $INSTDIR\Lang\no.txt + + # install files + SetOutPath "$INSTDIR" + + File descript.ion + File History.txt + File License.txt + File readme.txt + + # File 7-zip.dll + # File 7-zipn.dll + File 7zFM.exe + File 7z.exe + !ifdef WIN64 + File 7za.exe + !endif + File 7zg.exe + + File 7z.sfx + File 7zCon.sfx + + File 7-zip.chm + + File 7z.dll + + SetOutPath $INSTDIR\Lang + + File en.ttt + File af.txt + File ar.txt + File ast.txt + File az.txt + File ba.txt + File be.txt + File bg.txt + File bn.txt + File br.txt + File ca.txt + File cs.txt + File cy.txt + File da.txt + File de.txt + File el.txt + File eo.txt + File es.txt + File et.txt + File eu.txt + File ext.txt + File fa.txt + File fi.txt + File fr.txt + File fur.txt + File fy.txt + File gl.txt + File gu.txt + File he.txt + File hi.txt + File hr.txt + File hu.txt + File hy.txt + File id.txt + File io.txt + File is.txt + File it.txt + File ja.txt + File ka.txt + File kk.txt + File ko.txt + File ku.txt + File ku-ckb.txt + File lt.txt + File lv.txt + File mk.txt + File mn.txt + File mr.txt + File ms.txt + File ne.txt + File nl.txt + File nb.txt + File nn.txt + File pa-in.txt + File pl.txt + File ps.txt + File pt.txt + File pt-br.txt + File ro.txt + File ru.txt + File sa.txt + File si.txt + File sk.txt + File sl.txt + File sq.txt + File sr-spc.txt + File sr-spl.txt + File sv.txt + File ta.txt + File th.txt + File tr.txt + File tt.txt + File ug.txt + File uk.txt + File uz.txt + File va.txt + File vi.txt + File zh-cn.txt + File zh-tw.txt + + SetOutPath $INSTDIR + + # delete "current user" menu items + + Delete "$SMPROGRAMS\7-Zip\${FM_LINK}" + Delete "$SMPROGRAMS\7-Zip\${HELP_LINK}" + RMDir "$SMPROGRAMS\7-Zip" + + # set "all users" mode + + SetShellVarContext all + + !insertmacro InstallLib DLL NOTSHARED REBOOT_NOTPROTECTED 7-zip.dll $INSTDIR\7-zip.dll $INSTDIR + + ClearErrors + + # create start menu icons + SetOutPath $INSTDIR # working directory + CreateDirectory $SMPROGRAMS\7-Zip + + CreateShortcut "$SMPROGRAMS\7-Zip\${FM_LINK}" $INSTDIR\7zFM.exe + CreateShortcut "$SMPROGRAMS\7-Zip\${HELP_LINK}" $INSTDIR\7-zip.chm + + IfErrors 0 noScErrors + + SetShellVarContext current + + CreateDirectory $SMPROGRAMS\7-Zip + CreateShortcut "$SMPROGRAMS\7-Zip\${FM_LINK}" $INSTDIR\7zFM.exe + CreateShortcut "$SMPROGRAMS\7-Zip\${HELP_LINK}" $INSTDIR\7-zip.chm + + noScErrors: + + # store install folder + WriteRegStr HKLM "Software\7-Zip" "Path" $INSTDIR + WriteRegStr HKCU "Software\7-Zip" "Path" $INSTDIR + + # write reg entries + WriteRegStr HKCR "CLSID\${CLSID_CONTEXT_MENU}" "" "7-Zip Shell Extension" + WriteRegStr HKCR "CLSID\${CLSID_CONTEXT_MENU}\InprocServer32" "" "$INSTDIR\7-zip.dll" + WriteRegStr HKCR "CLSID\${CLSID_CONTEXT_MENU}\InprocServer32" "ThreadingModel" "Apartment" + + + WriteRegStr HKCR "*\shellex\ContextMenuHandlers\7-Zip" "" "${CLSID_CONTEXT_MENU}" + WriteRegStr HKCR "Directory\shellex\ContextMenuHandlers\7-Zip" "" "${CLSID_CONTEXT_MENU}" +; WriteRegStr HKCR "Folder\shellex\ContextMenuHandlers\7-Zip" "" "${CLSID_CONTEXT_MENU}" + + WriteRegStr HKCR "Directory\shellex\DragDropHandlers\7-Zip" "" "${CLSID_CONTEXT_MENU}" + WriteRegStr HKCR "Drive\shellex\DragDropHandlers\7-Zip" "" "${CLSID_CONTEXT_MENU}" + + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved" "${CLSID_CONTEXT_MENU}" "7-Zip Shell Extension" + + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\App Paths\7zFM.exe" "" "$INSTDIR\7zFM.exe" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\App Paths\7zFM.exe" "Path" "$INSTDIR" + + # create uninstaller + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\7-Zip" "DisplayName" "${NAME_FULL}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\7-Zip" "UninstallString" '"$INSTDIR\Uninstall.exe"' + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\7-Zip" "NoModify" 1 + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\7-Zip" "NoRepair" 1 + WriteUninstaller $INSTDIR\Uninstall.exe + + DeleteRegValue HKCR "CLSID\${CLSID_CONTEXT_MENU}\InprocServer32" "InprocServer32" + + !ifdef WIN64 + ExecWait 'regsvr32 /s "$INSTDIR\7-zip.dll"' + !endif + +SectionEnd + + +;-------------------------------- +;Installer Functions + +/* +Function .onInit + + !insertmacro MUI_LANGDLL_DISPLAY + +FunctionEnd +*/ + +;-------------------------------- +;Uninstaller Section + +Section "Uninstall" + + ExecWait 'regsvr32 /u /s "$INSTDIR\7-zip.dll"' + + # delete files + + Delete $INSTDIR\descript.ion + Delete $INSTDIR\History.txt + Delete $INSTDIR\License.txt + Delete $INSTDIR\copying.txt + Delete $INSTDIR\readme.txt + Delete $INSTDIR\7zip_pad.xml + + Delete /REBOOTOK $INSTDIR\7-zip.dll + Delete $INSTDIR\7zFM.exe + Delete $INSTDIR\7z.exe + !ifdef WIN64 + Delete $INSTDIR\7za.exe + !endif + Delete $INSTDIR\7zg.exe + + Delete $INSTDIR\7z.sfx + Delete $INSTDIR\7zCon.sfx + Delete $INSTDIR\7zC.sfx + + Delete $INSTDIR\7-zip.chm + + Delete $INSTDIR\7z.dll + + Delete $INSTDIR\Lang\en.ttt + Delete $INSTDIR\Lang\af.txt + Delete $INSTDIR\Lang\ar.txt + Delete $INSTDIR\Lang\ast.txt + Delete $INSTDIR\Lang\az.txt + Delete $INSTDIR\Lang\ba.txt + Delete $INSTDIR\Lang\be.txt + Delete $INSTDIR\Lang\bg.txt + Delete $INSTDIR\Lang\bn.txt + Delete $INSTDIR\Lang\br.txt + Delete $INSTDIR\Lang\ca.txt + Delete $INSTDIR\Lang\cs.txt + Delete $INSTDIR\Lang\cy.txt + Delete $INSTDIR\Lang\da.txt + Delete $INSTDIR\Lang\de.txt + Delete $INSTDIR\Lang\el.txt + Delete $INSTDIR\Lang\eo.txt + Delete $INSTDIR\Lang\es.txt + Delete $INSTDIR\Lang\et.txt + Delete $INSTDIR\Lang\eu.txt + Delete $INSTDIR\Lang\ext.txt + Delete $INSTDIR\Lang\fa.txt + Delete $INSTDIR\Lang\fi.txt + Delete $INSTDIR\Lang\fr.txt + Delete $INSTDIR\Lang\fur.txt + Delete $INSTDIR\Lang\fy.txt + Delete $INSTDIR\Lang\gl.txt + Delete $INSTDIR\Lang\gu.txt + Delete $INSTDIR\Lang\he.txt + Delete $INSTDIR\Lang\hi.txt + Delete $INSTDIR\Lang\hr.txt + Delete $INSTDIR\Lang\hu.txt + Delete $INSTDIR\Lang\hy.txt + Delete $INSTDIR\Lang\id.txt + Delete $INSTDIR\Lang\io.txt + Delete $INSTDIR\Lang\is.txt + Delete $INSTDIR\Lang\it.txt + Delete $INSTDIR\Lang\ja.txt + Delete $INSTDIR\Lang\ka.txt + Delete $INSTDIR\Lang\kk.txt + Delete $INSTDIR\Lang\ko.txt + Delete $INSTDIR\Lang\ku.txt + Delete $INSTDIR\Lang\ku-ckb.txt + Delete $INSTDIR\Lang\lt.txt + Delete $INSTDIR\Lang\lv.txt + Delete $INSTDIR\Lang\mk.txt + Delete $INSTDIR\Lang\mn.txt + Delete $INSTDIR\Lang\mr.txt + Delete $INSTDIR\Lang\ms.txt + Delete $INSTDIR\Lang\ne.txt + Delete $INSTDIR\Lang\nl.txt + Delete $INSTDIR\Lang\nb.txt + Delete $INSTDIR\Lang\nn.txt + Delete $INSTDIR\Lang\pa-in.txt + Delete $INSTDIR\Lang\pl.txt + Delete $INSTDIR\Lang\ps.txt + Delete $INSTDIR\Lang\pt.txt + Delete $INSTDIR\Lang\pt-br.txt + Delete $INSTDIR\Lang\ro.txt + Delete $INSTDIR\Lang\ru.txt + Delete $INSTDIR\Lang\sa.txt + Delete $INSTDIR\Lang\si.txt + Delete $INSTDIR\Lang\sk.txt + Delete $INSTDIR\Lang\sl.txt + Delete $INSTDIR\Lang\sq.txt + Delete $INSTDIR\Lang\sr.txt + Delete $INSTDIR\Lang\sr-spc.txt + Delete $INSTDIR\Lang\sr-spl.txt + Delete $INSTDIR\Lang\sv.txt + Delete $INSTDIR\Lang\ta.txt + Delete $INSTDIR\Lang\th.txt + Delete $INSTDIR\Lang\tr.txt + Delete $INSTDIR\Lang\tt.txt + Delete $INSTDIR\Lang\ug.txt + Delete $INSTDIR\Lang\uk.txt + Delete $INSTDIR\Lang\uz.txt + Delete $INSTDIR\Lang\va.txt + Delete $INSTDIR\Lang\vi.txt + Delete $INSTDIR\Lang\vr.txt + Delete $INSTDIR\Lang\zh-cn.txt + Delete $INSTDIR\Lang\zh-tw.txt + + RMDir $INSTDIR\Lang + + Delete $INSTDIR\Uninstall.exe + + RMDir $INSTDIR + + # delete start menu entires + + SetShellVarContext all + + # ClearErrors + + Delete "$SMPROGRAMS\7-Zip\${FM_LINK}" + Delete "$SMPROGRAMS\7-Zip\${HELP_LINK}" + RMDir "$SMPROGRAMS\7-Zip" + + # IfErrors 0 noScErrors + + SetShellVarContext current + + Delete "$SMPROGRAMS\7-Zip\${FM_LINK}" + Delete "$SMPROGRAMS\7-Zip\${HELP_LINK}" + RMDir "$SMPROGRAMS\7-Zip" + + # noScErrors: + + + # delete registry entries + + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\7-Zip" + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\App Paths\7zFM.exe" + + DeleteRegKey HKLM "Software\7-Zip" + DeleteRegKey HKCU "Software\7-Zip" + + DeleteRegKey HKCR "CLSID\${CLSID_CONTEXT_MENU}" + + DeleteRegKey HKCR "*\shellex\ContextMenuHandlers\7-Zip" + DeleteRegKey HKCR "Directory\shellex\ContextMenuHandlers\7-Zip" + DeleteRegKey HKCR "Folder\shellex\ContextMenuHandlers\7-Zip" + + DeleteRegKey HKCR "Directory\shellex\DragDropHandlers\7-Zip" + DeleteRegKey HKCR "Folder\shellex\DragDropHandlers\7-Zip" + + DeleteRegValue HKLM "Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved" "${CLSID_CONTEXT_MENU}" + + DeleteRegKey HKCR "7-Zip.001" + DeleteRegKey HKCR "7-Zip.7z" + DeleteRegKey HKCR "7-Zip.arj" + DeleteRegKey HKCR "7-Zip.bz2" + DeleteRegKey HKCR "7-Zip.bzip2" + DeleteRegKey HKCR "7-Zip.tbz" + DeleteRegKey HKCR "7-Zip.tbz2" + DeleteRegKey HKCR "7-Zip.cab" + DeleteRegKey HKCR "7-Zip.cpio" + DeleteRegKey HKCR "7-Zip.deb" + DeleteRegKey HKCR "7-Zip.dmg" + DeleteRegKey HKCR "7-Zip.gz" + DeleteRegKey HKCR "7-Zip.gzip" + DeleteRegKey HKCR "7-Zip.hfs" + DeleteRegKey HKCR "7-Zip.iso" + DeleteRegKey HKCR "7-Zip.lha" + DeleteRegKey HKCR "7-Zip.lzh" + DeleteRegKey HKCR "7-Zip.lzma" + DeleteRegKey HKCR "7-Zip.rar" + DeleteRegKey HKCR "7-Zip.rpm" + DeleteRegKey HKCR "7-Zip.split" + DeleteRegKey HKCR "7-Zip.swm" + DeleteRegKey HKCR "7-Zip.tar" + DeleteRegKey HKCR "7-Zip.taz" + DeleteRegKey HKCR "7-Zip.tgz" + DeleteRegKey HKCR "7-Zip.tpz" + DeleteRegKey HKCR "7-Zip.wim" + DeleteRegKey HKCR "7-Zip.xar" + DeleteRegKey HKCR "7-Zip.z" + DeleteRegKey HKCR "7-Zip.zip" + +SectionEnd diff --git a/DOC/7zip.wxs b/DOC/7zip.wxs new file mode 100755 index 0000000..1d3d0a9 --- /dev/null +++ b/DOC/7zip.wxs @@ -0,0 +1,353 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + + + Privileged + + + + + + + + + + + + + + + + + + + + + + Privileged + + + + + + Privileged + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DOC/License.txt b/DOC/License.txt new file mode 100755 index 0000000..0b7b3d2 --- /dev/null +++ b/DOC/License.txt @@ -0,0 +1,52 @@ + 7-Zip source code + ~~~~~~~~~~~~~~~~~ + License for use and distribution + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + 7-Zip Copyright (C) 1999-2010 Igor Pavlov. + + Licenses for files are: + + 1) CPP/7zip/Compress/Rar* files: GNU LGPL + unRAR restriction + 2) All other files: GNU LGPL + + The GNU LGPL + unRAR restriction means that you must follow both + GNU LGPL rules and unRAR restriction rules. + + + GNU LGPL information + -------------------- + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + unRAR restriction + ----------------- + + The decompression engine for RAR archives was developed using source + code of unRAR program. + All copyrights to original unRAR code are owned by Alexander Roshal. + + The license for original unRAR code has the following restriction: + + The unRAR sources cannot be used to re-create the RAR compression algorithm, + which is proprietary. Distribution of modified unRAR sources in separate form + or as a part of other software is permitted, provided that it is clearly + stated in the documentation and source comments that the code may + not be used to develop a RAR (WinRAR) compatible archiver. + + + -- + Igor Pavlov diff --git a/DOC/Methods.txt b/DOC/Methods.txt new file mode 100755 index 0000000..4c3ec68 --- /dev/null +++ b/DOC/Methods.txt @@ -0,0 +1,152 @@ +7-Zip method IDs (9.18) +----------------------- + +Each compression or crypto method in 7z has unique binary value (ID). +The length of ID in bytes is arbitrary but it can not exceed 63 bits (8 bytes). + +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 only if old codec can not decode data encoded with new version. + + +List of defined IDs +------------------- + +00 - Copy + +03 - Delta +04 - x86 (BCJ) +05 - PPC (Big Endian) +06 - IA64 +07 - ARM (little endian) +08 - ARM Thumb (little endian) +09 - SPARC +21 - LZMA2 + +02.. - Common + 03 Swap + - 2 Swap2 + - 4 Swap4 + +03.. - 7z + 01 - LZMA + 01 - Version + + 03 - Branch + 01 - x86 + 03 - BCJ + 1B - BCJ2 + 02 - PPC + 05 - PPC (Big Endian) + 03 - Alpha + 01 - Alpha + 04 - IA64 + 01 - IA64 + 05 - ARM + 01 - ARM + 06 - M68 + 05 - M68 (Big Endian) + 07 - ARM Thumb + 01 - ARMT + 08 - SPARC + 05 - SPARC + + 04 - PPMD + 01 - Version + + 7F - + 01 - experimental methods. + + +04.. - Misc + 00 - Reserved + 01 - Zip + 00 - Copy (not used). Use {00} instead + 01 - Shrink + 06 - Implode + 08 - Deflate + 09 - Deflate64 + 10 - Imploding + 12 - BZip2 (not used). Use {04 02 02} instead + 14 - LZMA + 60 - Jpeg + 61 - WavPack + 62 - PPMd + 63 - wzAES + 02 - BZip + 02 - BZip2 + 03 - Rar + 01 - Rar15 + 02 - Rar20 + 03 - Rar29 + 04 - Arj + 01 - Arj (1,2,3) + 02 - Arj 4 + 05 - Z + 06 - Lzh + 07 - Reserved for 7z + 08 - Cab + 09 - NSIS + 01 - DeflateNSIS + 02 - BZip2NSIS + + +06.. - Crypto + 00 - + 01 - AES + 0x - AES-128 + 4x - AES-192 + 8x - AES-256 + Cx - AES + + x0 - ECB + x1 - CBC + x2 - CFB + x3 - OFB + + 07 - Reserved + 0F - Reserved + + F0 - Misc Ciphers (Real Ciphers without hashing algo) + + F1 - Misc Ciphers (Combine) + 01 - Zip + 01 - Main Zip crypto algo + 03 - RAR + 02 - + 03 - Rar29 AES-128 + (modified SHA-1) + 07 - 7z + 01 - AES-256 + SHA-256 + +07.. - Hash (subject to change) + 00 - + 01 - CRC + 02 - SHA-1 + 03 - SHA-256 + 04 - SHA-384 + 05 - SHA-512 + + F0 - Misc Hash + + F1 - Misc + 03 - RAR + 03 - Rar29 Password Hashing (modified SHA1) + 07 - 7z + 01 - SHA-256 Password Hashing + + + + +--- +End of document diff --git a/DOC/copying.txt b/DOC/copying.txt new file mode 100755 index 0000000..f3926a6 --- /dev/null +++ b/DOC/copying.txt @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/DOC/history.txt b/DOC/history.txt new file mode 100755 index 0000000..a3ece98 --- /dev/null +++ b/DOC/history.txt @@ -0,0 +1,456 @@ +Sources history of the 7-Zip +---------------------------- + +9.18 2010-11-02 +------------------------- +- New small SFX module for installers (C/Util/SfxSetup). + + +9.17 2010-10-04 +------------------------- +- IStream.h::IOutStream:: + STDMETHOD(SetSize)(Int64 newSize) PURE; + was changed to + STDMETHOD(SetSize)(UInt64 newSize) PURE; + + +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. + + +9.05 2009-07-05 +------------------------- +- FileMapping.h::CFileMapping now returns WRes + + +9.04 2009-05-30 +------------------------- +- ICoder.h: NCoderPropID::EEnum values were changed + + +9.02 2009-04-23 +------------------------- +- Bug was fixed: if swap2 filter was requests at compression, + 7-zip used swap4 filter instead (but id was swap2), so archives were incorrect. + +4.61 2008-11-23 +------------------------- +- Bug in ver. 4.58+ was fixed: + 7-Zip didn't use any -m* switch after -mtc, -mcl or -mcu for .zip archives. +- Bug in .CAB code was fixed. 7-Zip didn't show some empty files, + if .CAB archive contains more than one empty file. + + +4.59 2008-07-27 +------------------------- +- Bug was fixed: + LZMA Encoder in fast compression mode could access memory outside of + allocated range in some rare cases. + + +4.59 alpha 2008-05-30 +------------------------- +- BUGS was fixed: + 7zOut.cpp: 7-Zip incorrectly wrote size of property records in some cases. + 7zIn.cpp: 7-Zip incorrectly work with archive, containg archive properties. + +4.58 alpha 9 2008-04-29 +------------------------- +- BUG was fixed: 7-Zip showed incorrect timestamps in ISO files. + + +4.58 alpha 8 2008-04-15 +------------------------- +- BUG in 4.58 alpha 5/6/7 was fixed: + LZMA encoder worked incorrectly, if lp != 0. +- Unicode (UTF-8) support for filenames in .ZIP archives. Now there are 3 modes: + 1) Default mode: 7-Zip uses UTF-8, if the local code page doesn't contain required symbols. + 2) -mcu switch: 7-Zip uses UTF-8, if there are non-ASCII symbols. + 3) -mcl switch: 7-Zip uses local code page. +- Now it's possible to use -mSW- and -mSW+ switches instead of -mSW=off and -mSW=on + + +4.58 alpha 7 2008-04-08 +------------------------- +- BUG was fixed: BZip2Encoder and BZip2Decoder used CEvent objects without + creating, when BZip2 code was called with one thread (with -mmt1 switch or with + default switches on single thread CPU). +- .lzma support. +- RPM and NSIS support was improved. +- LZMA now stores only (2 << n) or (3 << n) dictionary size value to LZMA properties. + + +4.58 alpha 6 2008-03-27 +------------------------- +- NTFS time extra in ZIP. +- New item property - kpidTimeType - VT_UI4 (0 - NTFS, 1 - Unix, 2 - DOS). +- Static CRC table is not required now for Lzma Encoder (in Lz MatchFinder). + + +4.58 alpha 5 2008-03-19 +------------------------- +- Creation time (-mtc switch) for .7z archives +- LZMA encoder was converted to ANSI-C + + +4.58 alpha 3 2008-02-25 +------------------------- +- Speed optimizations for LZMA decoding. Now it uses C code instead of C++. +- 7-Zip now has 128 MB dictionary limit for 32-bit version: + It's for speed optimization: kNumLogBits = 9 + sizeof(size_t) / 2; +- TAR: 'D' link flag support. +- 7-Zip now can unpack multivolume RAR archives created with + "old style volume names" scheme (-vn switch) and names *.001, *.002, ... +- Fixed bugs: + - 7-Zip FM could not copy / move files to root network folders like \\COMPNAME\FOLDERNAME\ + In case of move it removed original files. + - SFX-WIN: if there are errors, it still could return 0. + - ZIP (.XPS file) isZip64 && thisDiskNumber16 == 0xFFFF. + - ZIP name updating: + If zip file contains extra field and you try to change properties of files, + 7-zip tries to delete all extra fileds (except for WzAES). + And that code could hang. + - 7-Zip GUI didn't suggest BZip2 dictionary size used in previous run. + - If creation time stamp was included in .RAR archive, 7-zip used creation time stamp + as modification time stamp. + +4.58 alpha 2 2007-12-31 +------------------------- +- Small changes in Deflate and LZMA compression. +- Some speed optimizations. + + +4.57 +---- +- Bug was fixed: + Anti item is created for wrong file: + http://sourceforge.net/forum/forum.php?thread_id=1880366&forum_id=45798 + + +4.52 beta 2007-07-32 +------------------------- +- 7-Zip could not decompress some cab files +- "." dir creating at FAT was fixed / long names + + +4.50 beta 2007-07-24 +------------------------- +- 7-Zip now replaces unsupported filenames (like "nul", "com1") during extracting. +- New switch for command line version: + -ssc[-] enables/disables case-sensitive mode. +- 7z.exe l shows archive comment for zip archives +- Some bugs were fixed: long paths names shorter than 4. +- Speed optimizations for AES encryption. + + + +4.56 beta 2007-09-13 +------------------------- +- some fixes in LZ encoder (LZMA and Deflate) code. + size_t was replaces to ptrdiff_t. + size_t version worked incorrectly with some compilers. + + +4.46 beta 2007-05-25 +------------------------- +- CPP Synchronization objects now return HRes (error code) instead of bool. + + +4.45 beta 2007-04-16 +------------------------- +- 7-Zip now uses C version of CRC, so you must call CrcGenerateTable at + stratup code, or you must add CPP/Common/CRC.cpp to your project. +- Method ID in .7z now is 63-bit integer (UInt64). +- Open error messages +- unRar 1.5 fixed +- unShrink fixed +- BUG of 4.43 beta and 4.44 beta was fixed. + 7-Zip compressing to .zip in multi-threading mode didn't work in some cases. + + +4.44 beta 2007-01-20 +------------------------- + +- Bug was fixed: LZMAEncoder.cpp::CEncoder::GetOptimumFast + it was: + data++ + fixed version: + data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1; + It could lead to very small cpmpression ratio decreasing when block needs move. + + +4.30 beta 2005-11-18 +------------------------- +- Security.h::AddLockMemoryPrivilege - installs "Large pages" feature +- MemoryLock.h::EnableLockMemoryPrivilege - enables "Large pages" feature +- Alloc.h::SetLargePageSize - sets optimal LargePageSize size + + +4.27 2005-09-21 +------------------------- +- Some GUIDs/interfaces were changed. + IStream.h: + ISequentialInStream::Read now works as old ReadPart + ISequentialOutStream::Write now works as old WritePart + + +4.26 beta 2005-08-05 +------------------------- +- MyAlloc(0)/BigAlloc(0) now return 0 + + +4.25 beta 2005-07-31 +------------------------- +- More 64-bit compatibilty + + +4.24 beta 2005-07-06 +------------------------- +- Common\NewHandler.h: using throw() for code size optimization. + + +4.23 2005-06-29 +------------------------- +- Bug was fixed: memory leak in Cab decoder. + + +4.19 beta 2005-05-21 +------------------------- +- BZip2 code was rewritten. Now 7-Zip doesn't use original BZip2 code. + Old (original) version was moved to folder 7zip/Compress/BZip2Original/ + + +4.14 beta 2005-01-11 +------------------------- +- STL using was reduced +- 7za now supports Split(001) archves + + +4.10 beta 2004-10-21 +------------------------- +- Codecs now use new interface: ICompressSetDecoderProperties2 + + +4.07 beta 2004-10-03 +------------------------- +- some interfaces were changed slightly to support + -stdin -stdout mode. +- FilterCoder for simple filters +- Wildcard censor class was changed. +- Bug was fixed: when encrypted stream was multiple 16, + it used additional 16 empty bytes. + + +3.11 2003-10-06 +------------------------- + File functions support unicode strings even + on Windows 95/98/ME. + + +3.08.02 2003-09-20 +------------------------- + More compatible with GCC. + + +3.08.02 beta 2003-08-20 +------------------------- + Extracting bug in 7zExtract.cpp was fixed. + + +3.08 beta 2003-08-19 +------------------------- + Big source code reconstruction. + + +2.30 Beta 32 2003-05-15 +------------------------- + Small changes in Deflate decoder. + + +2.30 Beta 31 2003-04-29 +------------------------- + Common/NewHandler.cpp + HeapAlloc in (included to beta 30) was changed to malloc. + HeapAlloc worked slower in Win95/98/Me. + + +2.30 Beta 30 2003-04-21 +------------------------- + new file: Common/String.cpp + Common/NewHandler.* were changed + + +2.30 Beta 29 2003-04-07 +------------------------- + Small changes in LZMA code. + + +2.30 Beta 28 2003-02-16 +------------------------- + Processing anti-files was corrected. + + +2.30 Beta 27 2003-01-24 +------------------------- + Project/Archiver/Format/Common/ArchiveInterface.h: + new IArchiveOpenVolumeCallback interface. + + +2.30 Beta 26 2003-01-12 +------------------------- + SDK/Interface/PropID.h: + kpidComment now is kpidCommented + + +2.30 Beta 25 2003-01-02 +------------------------- + Main archive interfaces were changed. + + +2.30 Beta 24 2002-11-01 +------------------------- + SDK/Windows/Synchronization.h + SDK/Windows/Synchronization.cpp + - some changes. + + +2.30 Beta 23 2002-09-07 +------------------------- + Project/FileManager folder was added. + Notation of some source files was changed. + + +2.30 Beta 22 2002-08-28 +------------------------- + Project/FileManager folder was added. + Notation of some source files was changed. + + + +2.30 Beta 21 2002-07-08 +------------------------- + Project/Compress/LZ/MatchFinder/BinTree/BinTree.h + Project/Compress/LZ/MatchFinder/BinTree/BinTreeMain.h + Project/Compress/LZ/MatchFinder/BinTree/HC.h + Project/Compress/LZ/MatchFinder/BinTree/HCMain.h + - RAM requirements for LZMA (7z) compression were reduced. + + +2.30 Beta 20 2002-07-01 +------------------------- +- SDK/Stream/WindowOut.h + now it uses only required memory (dictionary size). +- Project/Archiver/Resource + contains common resurces + + +2.30 Beta 19 2002-04-11 +------------------------- +- SDK/Archive/Rar/Handler.cpp + supporting RAR29 + +2.30 Beta 18 2002-03-25 +------------------------- +- SDK/Archive/Cab/MSZipDecoder.cpp + SDK/Archive/Cab/LZXDecoder.cpp: + bug with corrupted archives was fixed +- Project/Compress/LZ/MatchFinder/BinTree/BinTree.h +- Project/Compress/LZ/MatchFinder/BinTree/BinTreeMain.h + some speed optimization (using prefetching) + + +2.30 Beta 17 2002-03-03 +------------------------- +- ARJ suppport. + + +2.30 Beta 16 2002-02-24 +------------------------- +- Project/Compress/LZ/LZMA/Decoder.cpp: + Bug was fixed: LZMA could not extract more than 4 GB. +- RPM and CPIO formats. +- Project/Compress/LZ/LZMA/Encoder.* + Project/Archiver/Format/7z/OutHandler.cpp + New fast compression mode for LZMA: -m0a=0. +- New match finders for LZMA: bt4b, hc3, hc4. + + +2.30 Beta 15 2002-02-17 +------------------------- +- Compression ratio in LZMA was slightly improved: + Project/Compress/LZ/LZMA/Encoder.* + Project/Archiver/Format/7z/OutHandler.cpp + + +2.30 Beta 14 2002-02-10 +------------------------- +- Supporting multithreading for LZMA: + Project/Compress/LZ/MatchFinder/MT +- Common/String.h: + CStringBase::Replace function was fixed. + + +2.30 Beta 13 2002-01-27 +------------------------- +- Compress/LZ/MatchFinder/BinTree3.h: + method +- Compress/LZ/MatchFinder/BinTreemain.h: + - one VirtualAlloc array was splitted to + the for 3 arrays. + - Hash-functions were changed. + + + +2.30 Beta 12 2002-01-16 +------------------------- +- Compress/LZ/MatchFinder/BinTreemain.h: + Compress/LZ/MatchFinder/Patricia.h: + Compress/PPM/PPMd/SubAlloc.h: + Beta 11 bugs were fixed: + - VirtualFree was used incorrectly + - checking WIN32 instead _WINDOWS. + Compress/LZ/MatchFinder/Patricia.h: + Beta 11 bug with deleting m_Hash2Descendants was fixed. + + +2.30 Beta 11 2002-01-15 +------------------------- +- Compress/LZ/MatchFinder/BinTreemain.h: + Compress/LZ/MatchFinder/Patricia.h: + Compress/PPM/PPMd/SubAlloc.h: + using VirtualAlloc for memory allocating +- Exlorer/ContextMenu.cpp: + Testing supporting. + CreateProcess instead WinExec +- Format/Common/IArchiveHandler.h: + Exlorer/ProxyHandler.cpp: + FAR/Plugin.cpp: + New properties names: Method, HostOS. +- Exlorer/OverwriteDialog.cpp: + FAR/OverwriteDialog.cpp: + Windows/PropVariantConversions.h + Using National time format was eliminated. + + + +2.30 Beta 10 2002-01-11 +------------------------- +- Exlorer/ContextMenu.cpp: bug with context menu on + Windows NT4 in Unicode version was fixed. +- Format/7z/UpdateArchiveEngine.cpp: bug was fixed - + Updating in Beta 8 and 9 didn't work. +- Exlorer/CCompressDialog.cpp: history growing bug was fixed. + + +2.30 Beta 9 2002-01-08 +------------------------- +- SDK/Common/Vector.h: sopporting sorted object vectors . +- Lang features. +- Two new match finders: pat3h and pat4h. +- SDK/Archive/Zip/InEngine.cpp: bug was fixed. +- SDK/Windows/FileDir.cpp: function CreateComplexDirectory + was changed. + diff --git a/DOC/lzma.txt b/DOC/lzma.txt new file mode 100755 index 0000000..579f2cc --- /dev/null +++ b/DOC/lzma.txt @@ -0,0 +1,598 @@ +LZMA SDK 9.20 +------------- + +LZMA SDK provides the documentation, samples, header files, libraries, +and tools you need to develop applications that use LZMA compression. + +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. + +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. + + + +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) + + +LZMA SDK Contents +----------------- + +LZMA SDK includes: + + - ANSI-C/C++/C#/Java source code for LZMA compressing and decompressing + - Compiled file->file LZMA compressing/decompressing program for Windows system + + +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 + + +Files +--------------------- +lzma.txt - LZMA SDK description (this file) +7zFormat.txt - 7z Format description +7zC.txt - 7z ANSI-C Decoder description +methods.txt - Compression method IDs for .7z +lzma.exe - Compiled file->file LZMA encoder/decoder for Windows +7zr.exe - 7-Zip with 7z/lzma/xz support. +history.txt - history of the LZMA SDK + + +Source code structure +--------------------- + +C/ - C files + 7zCrc*.* - CRC code + Alloc.* - Memory allocation functions + Bra*.* - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code + LzFind.* - Match finder for LZ (LZMA) encoders + LzFindMt.* - Match finder for LZ (LZMA) encoders for multithreading encoding + LzHash.h - Additional file for LZ match finder + LzmaDec.* - LZMA decoding + LzmaEnc.* - LZMA encoding + LzmaLib.* - LZMA Library for DLL calling + Types.h - Basic types for another .c files + Threads.* - The code for multithreading. + + LzmaLib - LZMA Library (.DLL for Windows) + + LzmaUtil - LZMA Utility (file->file LZMA encoder/decoder). + + Archive - files related to archiving + 7z - 7z ANSI-C Decoder + +CPP/ -- CPP files + + Common - common files for C++ projects + Windows - common files for Windows related code + + 7zip - files related to 7-Zip Project + + Common - common files for 7-Zip + + Compress - files related to compression/decompression + + Archive - files related to archiving + + Common - common files for archive handling + 7z - 7z C++ Encoder/Decoder + + Bundles - Modules that are bundles of other modules + + Alone7z - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2 + LzmaCon - lzma.exe: LZMA compression/decompression + Format7zR - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2 + Format7zExtractR - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2. + + UI - User Interface files + + Client7z - Test application for 7za.dll, 7zr.dll, 7zxr.dll + Common - Common UI files + Console - Code for console archiver + + + +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) + + +C/C++ source code of LZMA SDK is part of 7-Zip project. +7-Zip 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 2 GHz Core 2 or AMD Athlon 64 + - 1-2 MB/s on 200 MHz ARM, MIPS, PowerPC or other simple RISC + - 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) Misspredicted 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. + + +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 + Types.h +LzmaUtil/LzmaUtil.c is example application that uses these files. + + +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 + Types.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 + Types.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); + +For full code example, look at C/LzmaUtil/LzmaUtil.c code. + + +How To compress data +-------------------- + +Compile files: LzmaEnc.h + LzmaEnc.c + Types.h + +LzFind.c + LzFind.h + LzFindMt.c + LzFindMt.h + 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 +-------------------------------------- + +Check C/LzmaUtil/LzmaUtil.c as example, + +When to use: file->file decompressing + +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: + +HRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + 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/DOC/readme.txt b/DOC/readme.txt new file mode 100755 index 0000000..14731ee --- /dev/null +++ b/DOC/readme.txt @@ -0,0 +1,181 @@ +7-Zip 9.20 Sources +------------------ + +7-Zip is a file archiver for Windows. + +7-Zip Copyright (C) 1999-2010 Igor Pavlov. + + +License Info +------------ + +7-Zip is free software distributed under the GNU LGPL +(except for unRar code). +read License.txt for more infomation about license. + +Notes about unRAR license: + +Please check main restriction from unRar license: + + 2. The unRAR sources may be used in any software to handle RAR + archives without limitations free of charge, but cannot be used + to re-create the RAR compression algorithm, which is proprietary. + Distribution of modified unRAR sources in separate form or as a + part of other software is permitted, provided that it is clearly + stated in the documentation and source comments that the code may + not be used to develop a RAR (WinRAR) compatible archiver. + +In brief it means: +1) You can compile and use compiled files under GNU LGPL rules, since + unRAR license almost has no restrictions for compiled files. + You can link these compiled files to LGPL programs. +2) You can fix bugs in source code and use compiled fixed version. +3) You can not use unRAR sources to re-create the RAR compression algorithm. + + +LZMA SDK +-------- + +Also this package contains files from LZMA SDK +you can download LZMA SDK from this page: +http://www.7-zip.org/sdk.html +read about addtional licenses for LZMA SDK in file +DOC/lzma.txt + + +How to compile +-------------- +To compile sources you need Visual C++ 6.0. +For compiling some files you also need +new Platform SDK from Microsoft' Site: +http://www.microsoft.com/msdownload/platformsdk/sdkupdate/psdk-full.htm +or +http://www.microsoft.com/msdownload/platformsdk/sdkupdate/XPSP2FULLInstall.htm +or +http://www.microsoft.com/msdownload/platformsdk/sdkupdate/ + +If you use MSVC6, specify SDK directories at top of directories lists: +Tools / Options / Directories + - Include files + - Library files + + +To compile 7-Zip for AMD64 and IA64 you need: + Windows Server 2003 SP1 Platform SDK from microsoft.com + +Also you need Microsoft Macro Assembler: + - ml.exe for x86 + - ml64.exe for AMD64 +You can use ml.exe from Windows SDK for Windows Vista or some other version. + + +Compiling under Unix/Linux +-------------------------- +Check this site for Posix/Linux version: +http://sourceforge.net/projects/p7zip/ + + +Notes: +------ +7-Zip consists of COM modules (DLL files). +But 7-Zip doesn't use standard COM interfaces for creating objects. +Look at +7zip\UI\Client7z folder for example of using DLL files of 7-Zip. +Some DLL files can use other DLL files from 7-Zip. +If you don't like it, you must use standalone version of DLL. +To compile standalone version of DLL you must include all used parts +to project and define some defs. +For example, 7zip\Bundles\Format7z is a standalone version of 7z.dll +that works with 7z format. So you can use such DLL in your project +without additional DLL files. + + +Description of 7-Zip sources package +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +DOC Documentation +--- + 7zFormat.txt - 7z format description + copying.txt - GNU LGPL license + unRarLicense.txt - License for unRAR part of source code + history.txt - Sources history + Methods.txt - Compression method IDs + readme.txt - Readme file + lzma.txt - LZMA SDK description + 7zip.nsi - installer script for NSIS + + +C - Source code in C +CPP - Source code in CPP + +Common Common modules +Windows Win32 wrappers + +7zip +------- + Common Common modules for 7-zip + + Archive 7-Zip Archive Format Plugins + -------- + Common + 7z + Arj + BZip2 + Cab + Cpio + GZip + Rar + Rpm + Split + Tar + Zip + + Bundle Modules that are bundles of other modules + ------ + Alone 7za.exe: Standalone version of 7z + Alone7z 7zr.exe: Standalone version of 7z that supports only 7z/LZMA/BCJ/BCJ2 + SFXCon 7zCon.sfx: Console 7z SFX module + SFXWin 7z.sfx: Windows 7z SFX module + SFXSetup 7zS.sfx: Windows 7z SFX module for Installers + Format7z 7za.dll: .7z support + Format7zExtract 7zxa.dll: .7z support, extracting only + Format7zR 7zr.dll: .7z support, LZMA/BCJ* only + Format7zExtractR 7zxr.dll: .7z support, LZMA/BCJ* only, extracting only + Format7zF 7z.dll: all formats + + UI + -- + Agent Intermediary modules for FAR plugin and Explorer plugin + Console 7z.exe Console version + Explorer Explorer plugin + Resource Resources + Far FAR plugin + Client7z Test application for 7za.dll + + Compress + -------- + BZip2 BZip2 compressor + Branch Branch converter + ByteSwap Byte Swap converter + Copy Copy coder + Deflate + Implode + Arj + LZMA + PPMd Dmitry Shkarin's PPMdH with small changes. + LZ Lempel - Ziv + + Crypto Crypto modules + ------ + 7zAES Cipher for 7z + AES AES Cipher + Rar20 Cipher for Rar 2.0 + RarAES Cipher for Rar 3.0 + Zip Cipher for Zip + + FileManager File Manager + + +--- +Igor Pavlov +http://www.7-zip.org diff --git a/DOC/unRarLicense.txt b/DOC/unRarLicense.txt new file mode 100755 index 0000000..5f78b72 --- /dev/null +++ b/DOC/unRarLicense.txt @@ -0,0 +1,41 @@ + ****** ***** ****** unRAR - free utility for RAR archives + ** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ****** ******* ****** License for use and distribution of + ** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ** ** ** ** ** ** FREE portable version + ~~~~~~~~~~~~~~~~~~~~~ + + The source code of unRAR utility is freeware. This means: + + 1. All copyrights to RAR and the utility unRAR are exclusively + owned by the author - Alexander Roshal. + + 2. The unRAR sources may be used in any software to handle RAR + archives without limitations free of charge, but cannot be used + to re-create the RAR compression algorithm, which is proprietary. + Distribution of modified unRAR sources in separate form or as a + part of other software is permitted, provided that it is clearly + stated in the documentation and source comments that the code may + not be used to develop a RAR (WinRAR) compatible archiver. + + 3. The unRAR utility may be freely distributed. No person or company + may charge a fee for the distribution of unRAR without written + permission from the copyright holder. + + 4. THE RAR ARCHIVER AND THE UNRAR UTILITY ARE DISTRIBUTED "AS IS". + NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. YOU USE AT + YOUR OWN RISK. THE AUTHOR WILL NOT BE LIABLE FOR DATA LOSS, + DAMAGES, LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING + OR MISUSING THIS SOFTWARE. + + 5. Installing and using the unRAR utility signifies acceptance of + these terms and conditions of the license. + + 6. If you don't agree with terms of the license you must remove + unRAR files from your storage devices and cease to use the + utility. + + Thank you for your interest in RAR and unRAR. + + + Alexander L. Roshal \ No newline at end of file -- 2.7.4 From bd45e912c1aa8aff41a67131f1d87f55c9a47070 Mon Sep 17 00:00:00 2001 From: Sunmin Lee Date: Tue, 30 May 2017 17:54:40 +0900 Subject: [PATCH 3/3] Packaging library Apply differences with 7zip codes of TOTA pacakge and packaging codes of 7zip to library which is required in TOTA packages. Change-Id: I1590eacb76665abb180010faca0cc113d471c4f0 Signed-off-by: Sunmin Lee --- C/7zDec.c | 2 +- C/7zDecomp.c | 464 ++++++++++++++++++++++++++++++++++++++++++++++++++++ C/Lzma2Enc.c | 4 +- C/LzmaEnc.c | 2 +- CMakeLists.txt | 52 ++++++ lib7zip.pc.in | 13 ++ packaging/7zip.spec | 48 ++++++ 7 files changed, 581 insertions(+), 4 deletions(-) create mode 100755 C/7zDecomp.c create mode 100755 CMakeLists.txt create mode 100644 lib7zip.pc.in create mode 100644 packaging/7zip.spec diff --git a/C/7zDec.c b/C/7zDec.c index 3386807..a79ed5b 100755 --- a/C/7zDec.c +++ b/C/7zDec.c @@ -3,7 +3,7 @@ #include -/* #define _7ZIP_PPMD_SUPPPORT */ +#define _7ZIP_PPMD_SUPPPORT #include "7z.h" diff --git a/C/7zDecomp.c b/C/7zDecomp.c new file mode 100755 index 0000000..a270c89 --- /dev/null +++ b/C/7zDecomp.c @@ -0,0 +1,464 @@ +/* 7zMain.c - Test application for 7z Decoder +2010-10-28 : Igor Pavlov : Public domain */ + +#include +#include + +#include "7z.h" +#include "7zAlloc.h" +#include "7zCrc.h" +#include "7zFile.h" +#include "7zVersion.h" + +#ifndef USE_WINDOWS_FILE +/* for mkdir */ +#ifdef _WIN32 +#include +#else +#include +#include +#endif +#endif + +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +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 + +static Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + +static Bool Utf16_To_Utf8(Byte *dest, size_t *destLen, const UInt16 *src, size_t srcLen) +{ + size_t destPos = 0, srcPos = 0; + for (;;) + { + unsigned numAdds; + UInt32 value; + if (srcPos == srcLen) + { + *destLen = destPos; + return True; + } + value = src[srcPos++]; + if (value < 0x80) + { + if (dest) + dest[destPos] = (char)value; + destPos++; + continue; + } + if (value >= 0xD800 && value < 0xE000) + { + UInt32 c2; + if (value >= 0xDC00 || srcPos == srcLen) + break; + c2 = src[srcPos++]; + if (c2 < 0xDC00 || c2 >= 0xE000) + break; + value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000; + } + for (numAdds = 1; numAdds < 5; numAdds++) + if (value < (((UInt32)1) << (numAdds * 5 + 6))) + break; + if (dest) + dest[destPos] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); + destPos++; + do + { + numAdds--; + if (dest) + dest[destPos] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); + destPos++; + } + while (numAdds != 0); + } + *destLen = destPos; + return False; +} + +static SRes Utf16_To_Utf8Buf(CBuf *dest, const UInt16 *src, size_t srcLen) +{ + size_t destLen = 0; + Bool res; + Utf16_To_Utf8(NULL, &destLen, src, srcLen); + destLen += 1; + if (!Buf_EnsureSize(dest, destLen)) + return SZ_ERROR_MEM; + res = Utf16_To_Utf8(dest->data, &destLen, src, srcLen); + dest->data[destLen] = 0; + return res ? SZ_OK : SZ_ERROR_FAIL; +} +#endif + +static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s, int fileMode) +{ + int len = 0; + for (len = 0; s[len] != '\0'; len++); + + #ifdef _WIN32 + { + int size = len * 3 + 100; + if (!Buf_EnsureSize(buf, size)) + return SZ_ERROR_MEM; + { + char defaultChar = '_'; + BOOL defUsed; + int numChars = WideCharToMultiByte(fileMode ? + ( + #ifdef UNDER_CE + CP_ACP + #else + AreFileApisANSI() ? CP_ACP : CP_OEMCP + #endif + ) : CP_OEMCP, + 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 + fileMode = fileMode; + return Utf16_To_Utf8Buf(buf, s, len); + #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, 1)); + + res = + #ifdef _WIN32 + _mkdir((const char *)buf.data) + #else + mkdir((const char *)buf.data, 0755) + #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, 1)); + 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, 0); + if (res != SZ_OK) + printf("[%s]\n",(const char *)buf.data); + Buf_Free(&buf, &g_Alloc); + return res; +} + +static void UInt64ToStr(UInt64 value, char *s) +{ + char temp[32]; + int pos = 0; + do + { + temp[pos++] = (char)('0' + (unsigned)(value % 10)); + value /= 10; + } + while (value != 0); + 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; +} + +#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 *ft, char *s) +{ + unsigned year, mon, day, hour, min, sec; + UInt64 v64 = (ft->Low | ((UInt64)ft->High << 32)) / 10000000; + Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + unsigned t; + UInt32 v; + 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 = 1; mon <= 12; mon++) + { + unsigned s = ms[mon - 1]; + if (v < s) + break; + v -= s; + } + day = (unsigned)v + 1; + s = UIntToStr(s, year, 4); *s++ = '-'; + s = UIntToStr(s, mon, 2); *s++ = '-'; + s = UIntToStr(s, day, 2); *s++ = ' '; + s = UIntToStr(s, hour, 2); *s++ = ':'; + s = UIntToStr(s, min, 2); *s++ = ':'; + s = UIntToStr(s, sec, 2); +} + +void PrintError(char *sz) +{ + printf("\nERROR: %s\n", sz); +} + +static void GetAttribString(UInt32 Bool, Byte isDir, char *s) +{ + s[0] = '\0'; +} + +int _7zdecompress(char *path) +{ + CFileInStream archiveStream; + CLookToRead lookStream; + CSzArEx db; + SRes res; + ISzAlloc allocImp; + ISzAlloc allocTempImp; + UInt16 *temp = NULL; + size_t tempSize = 0; + + + allocImp.Alloc = SzAlloc; + allocImp.Free = SzFree; + + allocTempImp.Alloc = SzAllocTemp; + allocTempImp.Free = SzFreeTemp; + + if (InFile_Open(&archiveStream.file, path)) + { + PrintError("can not open input file"); + return 1; + } + + FileInStream_CreateVTable(&archiveStream); + LookToRead_CreateVTable(&lookStream, False); + + lookStream.realStream = &archiveStream.s; + LookToRead_Init(&lookStream); + + CrcGenerateTable(); + + SzArEx_Init(&db); + res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp); + if (res == SZ_OK) + { + int listCommand = 0, testCommand = 0, fullPaths = 0; + + fullPaths = 1; + 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.db.NumFiles; i++) + { + size_t offset = 0; + size_t outSizeProcessed = 0; + const CSzFileItem *f = db.db.Files + i; + size_t len; + if (listCommand == 0 && f->IsDir && !fullPaths) + continue; + len = SzArEx_GetFileNameUtf16(&db, i, NULL); + + if (len > tempSize) + { + SzFree(NULL, temp); + tempSize = len; + temp = (UInt16 *)SzAlloc(NULL, tempSize * sizeof(temp[0])); + if (temp == 0) + { + res = SZ_ERROR_MEM; + break; + } + } + + SzArEx_GetFileNameUtf16(&db, i, temp); + if (listCommand) + { + char attr[8], s[32], t[32]; + + GetAttribString(f->AttribDefined ? f->Attrib : 0, f->IsDir, attr); + + UInt64ToStr(f->Size, s); + if (f->MTimeDefined) + ConvertFileTimeToString(&f->MTime, t); + else + { + size_t j; + for (j = 0; j < 19; j++) + t[j] = ' '; + t[j] = '\0'; + } + + printf("%s %s %10s ", t, attr, s); + res = PrintString(temp); + if (res != SZ_OK) + break; + if (f->IsDir) + printf("/"); + printf("\n"); + continue; + } + fputs(testCommand ? + "Testing ": + "Extracting ", + stdout); + res = PrintString(temp); + if (res != SZ_OK) + break; + if (f->IsDir) + printf("/"); + else + { + res = SzArEx_Extract(&db, &lookStream.s, 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; + } + PrintString(destPath); + if (f->IsDir) + { + MyCreateDir(destPath); + printf("\n"); + continue; + } + else if (OutFile_OpenUtf16(&outFile, destPath)) + { + PrintError("can not open output file"); + PrintString(destPath); + res = SZ_ERROR_FAIL; + break; + } + processedSize = outSizeProcessed; + if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed) + { + PrintError("can not write output file"); + File_Close(&outFile);//wgid: 27067 + res = SZ_ERROR_FAIL; + break; + } + if (File_Close(&outFile)) + { + PrintError("can not close output file"); + res = SZ_ERROR_FAIL; + break; + } + #ifdef USE_WINDOWS_FILE + if (f->AttribDefined) + SetFileAttributesW(destPath, f->Attrib); + #endif + } + printf("\n"); + } + IAlloc_Free(&allocImp, outBuffer); + } + } + SzArEx_Free(&db, &allocImp); + SzFree(NULL, temp); + + File_Close(&archiveStream.file); + if (res == SZ_OK) + { + printf("\nEverything is Ok\n"); + return 0; + } + if (res == SZ_ERROR_UNSUPPORTED) + PrintError("decoder doesn't support this archive"); + else if (res == SZ_ERROR_MEM) + PrintError("can not allocate memory"); + else if (res == SZ_ERROR_CRC) + PrintError("CRC error"); + else + printf("\nERROR #%d\n", res); + return 1; +} diff --git a/C/Lzma2Enc.c b/C/Lzma2Enc.c index 35f6ed7..d52c70a 100755 --- a/C/Lzma2Enc.c +++ b/C/Lzma2Enc.c @@ -4,11 +4,11 @@ /* #include */ #include -/* #define _7ZIP_ST */ + #define _7ZIP_ST #include "Lzma2Enc.h" -#ifndef _7ZIP_ST +#if 0//ndef _7ZIP_ST #include "MtCoder.h" #else #define NUM_MT_CODER_THREADS_MAX 1 diff --git a/C/LzmaEnc.c b/C/LzmaEnc.c index 9e6dbdb..8dbf1ce 100755 --- a/C/LzmaEnc.c +++ b/C/LzmaEnc.c @@ -2,7 +2,7 @@ 2010-04-16 : Igor Pavlov : Public domain */ #include - +#define _7ZIP_ST /* #define SHOW_STAT */ /* #define SHOW_STAT2 */ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 0000000..ca7e3e3 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,52 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(7zip C) + +SET(LIB7ZIP_SRCS + C/7zAlloc.c + C/7zBuf2.c + C/7zBuf.c + C/7zCrc.c + C/7zCrcOpt.c + C/7zDec.c + C/7zFile.c + C/7zIn.c + C/7zStream.c + C/7zDecomp.c + C/Alloc.c + C/Bcj2.c + C/Bra86.c + C/Bra.c + C/CpuArch.c + C/LzFind.c + C/Lzma2Dec.c + C/Lzma2Enc.c + C/LzmaDec.c + C/LzmaEnc.c + C/Ppmd7.c + C/Ppmd7Dec.c +) + +SET(HEADERS + C/Types.h + C/Alloc.h + C/7zFile.h + C/7zVersion.h + C/LzmaDec.h + C/LzmaEnc.h +) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(EXEC_PREFIX "${PREFIX}/bin") +SET(INCLUDEDIR "${PREFIX}/include/${PROJECT_NAME}") +SET(VERSION 0.0.0) + +SET(LIBNAME "lib${PROJECT_NAME}") +CONFIGURE_FILE(${LIBNAME}.pc.in ${LIBNAME}.pc @ONLY) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${LIBNAME}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/C) +INSTALL(FILES ${HEADERS} DESTINATION include/${PROJECT_NAME}) + +ADD_LIBRARY(${PROJECT_NAME} SHARED ${LIB7ZIP_SRCS}) +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${VERSION}) +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR}) diff --git a/lib7zip.pc.in b/lib7zip.pc.in new file mode 100644 index 0000000..a0d2f69 --- /dev/null +++ b/lib7zip.pc.in @@ -0,0 +1,13 @@ +# Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=@EXEC_PREFIX@ +libdir=@LIB_INSTALL_DIR@ +includedir=@INCLUDEDIR@ + +Name: 7zip +Description: 7zip library +Version: @VERSION@ +Requires: +Libs: -L${libdir} -l7zip +Cflags: -I${includedir} diff --git a/packaging/7zip.spec b/packaging/7zip.spec new file mode 100644 index 0000000..894bcc1 --- /dev/null +++ b/packaging/7zip.spec @@ -0,0 +1,48 @@ +Name: 7zip +Url: http://www.7-zip.org/ +Summary: 7zip File Archiver +Version: 9.20 +Release: 1 +Group: System +License: LGPL-2.1+ and unRAR +Source0: %{name}-%{version}.tar.gz + +BuildRequires: cmake + +%description +7-Zip is a file archiver with a high compression ratio. + +%package -n lib7zip +Summary: 7zip library + +%description -n lib7zip +7zip shared library package + +%package -n lib7zip-devel +Summary: 7zip library for (devel) + +%description -n lib7zip-devel +7zip library package for (devel) + +%prep +%setup -q + +%build +%cmake . \ + -DCMAKE_INSTALL_PREFIX=%{_prefix} +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +%make_install + +%files -n lib7zip +%license DOC/copying.txt +%defattr(-,root,root,-) +%{_libdir}/lib7zip.so.* + +%files -n lib7zip-devel +%defattr(-,root,root,-) +%{_includedir}/7zip/*.h +%{_libdir}/lib7zip.so +%{_libdir}/pkgconfig/lib7zip.pc -- 2.7.4