From f08f4dcc3c02464c17753b3feafcfe5243b9e236 Mon Sep 17 00:00:00 2001 From: Igor Pavlov Date: Sun, 23 Nov 2014 00:00:00 +0000 Subject: 9.34 --- Asm/arm/7zCrcOpt.asm | 0 Asm/x86/7zAsm.asm | 28 +- Asm/x86/7zCrcOpt.asm | 0 Asm/x86/AesOpt.asm | 0 Asm/x86/XzCrc64Opt.asm | 205 + C/7z.h | 175 +- C/7zAlloc.c | 2 + C/7zAlloc.h | 0 C/7zArcIn.c | 1839 ++++++ C/7zBuf.c | 6 +- C/7zBuf.h | 12 +- C/7zBuf2.c | 5 +- C/7zCrc.c | 6 +- C/7zCrc.h | 4 +- C/7zCrcOpt.c | 4 +- C/7zDec.c | 109 +- C/7zFile.c | 2 + C/7zFile.h | 4 +- C/7zIn.c | 1402 ----- C/7zStream.c | 6 +- C/7zTypes.h | 256 + C/7zVersion.h | 10 +- C/7zVersion.rc | 0 C/Aes.c | 4 +- C/Aes.h | 4 +- C/AesOpt.c | 4 +- C/Alloc.c | 6 +- C/Alloc.h | 0 C/Bcj2.c | 2 + C/Bcj2.h | 12 +- C/Bra.c | 2 + C/Bra.h | 12 +- C/Bra86.c | 99 +- C/BraIA64.c | 4 +- C/BwtSort.c | 6 +- C/BwtSort.h | 12 +- C/Compiler.h | 28 + C/CpuArch.c | 26 +- C/CpuArch.h | 14 +- C/Delta.c | 2 + C/Delta.h | 12 +- C/HuffEnc.c | 2 + C/HuffEnc.h | 12 +- C/LzFind.c | 2 + C/LzFind.h | 12 +- C/LzFindMt.c | 12 +- C/LzFindMt.h | 10 +- C/LzHash.h | 0 C/Lzma2Dec.c | 2 + C/Lzma2Dec.h | 10 +- C/Lzma2Enc.c | 22 +- C/Lzma2Enc.h | 10 +- C/Lzma86.h | 4 +- C/Lzma86Dec.c | 0 C/Lzma86Enc.c | 2 +- C/LzmaDec.c | 44 +- C/LzmaDec.h | 12 +- C/LzmaEnc.c | 12 +- C/LzmaEnc.h | 6 +- C/LzmaLib.c | 0 C/LzmaLib.h | 12 +- C/MtCoder.c | 2 + C/MtCoder.h | 0 C/Ppmd.h | 3 +- C/Ppmd7.c | 2 + C/Ppmd7.h | 0 C/Ppmd7Dec.c | 2 + C/Ppmd7Enc.c | 2 + C/Ppmd8.c | 25 +- C/Ppmd8.h | 0 C/Ppmd8Dec.c | 2 + C/Ppmd8Enc.c | 2 + C/Precomp.h | 10 + C/RotateDefs.h | 8 +- C/Sha256.c | 2 + C/Sha256.h | 4 +- C/Sort.c | 70 +- C/Sort.h | 18 +- C/Threads.c | 27 +- C/Threads.h | 26 +- C/Types.h | 254 - C/Util/7z/7z.dsp | 33 +- C/Util/7z/7z.dsw | 0 C/Util/7z/7zMain.c | 151 +- C/Util/7z/Precomp.c | 4 + C/Util/7z/Precomp.h | 10 + C/Util/7z/makefile | 10 +- C/Util/7z/makefile.gcc | 10 +- C/Util/Lzma/LzmaUtil.c | 4 +- C/Util/Lzma/LzmaUtil.dsp | 4 +- C/Util/Lzma/LzmaUtil.dsw | 0 C/Util/Lzma/makefile | 0 C/Util/Lzma/makefile.gcc | 0 C/Util/LzmaLib/LzmaLib.def | 0 C/Util/LzmaLib/LzmaLib.dsp | 8 +- C/Util/LzmaLib/LzmaLib.dsw | 0 C/Util/LzmaLib/LzmaLibExports.c | 0 C/Util/LzmaLib/makefile | 0 C/Util/LzmaLib/resource.rc | 0 C/Util/SfxSetup/Precomp.c | 4 + C/Util/SfxSetup/Precomp.h | 10 + C/Util/SfxSetup/SfxSetup.c | 47 +- C/Util/SfxSetup/SfxSetup.dsp | 23 +- C/Util/SfxSetup/SfxSetup.dsw | 0 C/Util/SfxSetup/makefile | 4 +- C/Util/SfxSetup/makefile_con | 5 +- C/Util/SfxSetup/resource.rc | 0 C/Util/SfxSetup/setup.ico | Bin C/Xz.c | 2 + C/Xz.h | 31 +- C/XzCrc64.c | 89 +- C/XzCrc64.h | 4 +- C/XzCrc64Opt.c | 69 + C/XzDec.c | 30 +- C/XzEnc.c | 8 +- C/XzEnc.h | 0 C/XzIn.c | 4 +- CPP/7zip/7zip.mak | 240 + CPP/7zip/Aes.mak | 0 CPP/7zip/Archive/7z/7z.dsp | 16 + CPP/7zip/Archive/7z/7z.dsw | 0 CPP/7zip/Archive/7z/7zCompressionMode.cpp | 0 CPP/7zip/Archive/7z/7zCompressionMode.h | 0 CPP/7zip/Archive/7z/7zDecode.cpp | 123 +- CPP/7zip/Archive/7z/7zDecode.h | 9 +- CPP/7zip/Archive/7z/7zEncode.cpp | 94 +- CPP/7zip/Archive/7z/7zEncode.h | 2 + CPP/7zip/Archive/7z/7zExtract.cpp | 46 +- CPP/7zip/Archive/7z/7zFolderInStream.cpp | 4 +- CPP/7zip/Archive/7z/7zFolderInStream.h | 2 +- CPP/7zip/Archive/7z/7zFolderOutStream.cpp | 2 +- CPP/7zip/Archive/7z/7zFolderOutStream.h | 6 +- CPP/7zip/Archive/7z/7zHandler.cpp | 701 ++- CPP/7zip/Archive/7z/7zHandler.h | 25 +- CPP/7zip/Archive/7z/7zHandlerOut.cpp | 378 +- CPP/7zip/Archive/7z/7zHeader.cpp | 5 + CPP/7zip/Archive/7z/7zHeader.h | 10 +- CPP/7zip/Archive/7z/7zIn.cpp | 1364 +++-- CPP/7zip/Archive/7z/7zIn.h | 333 +- CPP/7zip/Archive/7z/7zItem.h | 208 +- CPP/7zip/Archive/7z/7zOut.cpp | 463 +- CPP/7zip/Archive/7z/7zOut.h | 207 +- CPP/7zip/Archive/7z/7zProperties.cpp | 48 +- CPP/7zip/Archive/7z/7zProperties.h | 0 CPP/7zip/Archive/7z/7zRegister.cpp | 23 +- CPP/7zip/Archive/7z/7zSpecStream.cpp | 10 +- CPP/7zip/Archive/7z/7zSpecStream.h | 0 CPP/7zip/Archive/7z/7zUpdate.cpp | 503 +- CPP/7zip/Archive/7z/7zUpdate.h | 40 +- CPP/7zip/Archive/7z/StdAfx.cpp | 0 CPP/7zip/Archive/7z/StdAfx.h | 3 +- CPP/7zip/Archive/7z/makefile | 43 +- CPP/7zip/Archive/7z/resource.rc | 0 CPP/7zip/Archive/ApmHandler.cpp | 113 +- CPP/7zip/Archive/ArHandler.cpp | 857 +++ CPP/7zip/Archive/Archive.def | 0 CPP/7zip/Archive/Archive2.def | 4 +- CPP/7zip/Archive/ArchiveExports.cpp | 64 +- CPP/7zip/Archive/ArjHandler.cpp | 636 +-- CPP/7zip/Archive/Bz2Handler.cpp | 253 +- CPP/7zip/Archive/Cab/CabBlockInStream.cpp | 191 +- CPP/7zip/Archive/Cab/CabBlockInStream.h | 31 +- CPP/7zip/Archive/Cab/CabHandler.cpp | 512 +- CPP/7zip/Archive/Cab/CabHandler.h | 11 +- CPP/7zip/Archive/Cab/CabHeader.cpp | 0 CPP/7zip/Archive/Cab/CabHeader.h | 23 +- CPP/7zip/Archive/Cab/CabIn.cpp | 446 +- CPP/7zip/Archive/Cab/CabIn.h | 129 +- CPP/7zip/Archive/Cab/CabItem.h | 29 +- CPP/7zip/Archive/Cab/CabRegister.cpp | 14 +- CPP/7zip/Archive/Cab/StdAfx.h | 2 +- CPP/7zip/Archive/Chm/ChmHandler.cpp | 118 +- CPP/7zip/Archive/Chm/ChmHandler.h | 8 +- CPP/7zip/Archive/Chm/ChmHeader.cpp | 24 - CPP/7zip/Archive/Chm/ChmHeader.h | 28 - CPP/7zip/Archive/Chm/ChmIn.cpp | 275 +- CPP/7zip/Archive/Chm/ChmIn.h | 46 +- CPP/7zip/Archive/Chm/ChmRegister.cpp | 13 - CPP/7zip/Archive/Chm/StdAfx.h | 2 +- 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/ComHandler.cpp | 875 +++ CPP/7zip/Archive/Common/CoderMixer.cpp | 0 CPP/7zip/Archive/Common/CoderMixer.h | 0 CPP/7zip/Archive/Common/CoderMixer2.cpp | 70 +- CPP/7zip/Archive/Common/CoderMixer2.h | 19 +- CPP/7zip/Archive/Common/CoderMixer2MT.cpp | 56 +- CPP/7zip/Archive/Common/CoderMixer2MT.h | 12 +- CPP/7zip/Archive/Common/CoderMixer2ST.cpp | 4 +- CPP/7zip/Archive/Common/CoderMixer2ST.h | 0 CPP/7zip/Archive/Common/CoderMixerMT.cpp | 0 CPP/7zip/Archive/Common/CoderMixerMT.h | 0 CPP/7zip/Archive/Common/CrossThreadProgress.cpp | 0 CPP/7zip/Archive/Common/CrossThreadProgress.h | 0 CPP/7zip/Archive/Common/DummyOutStream.cpp | 19 +- CPP/7zip/Archive/Common/DummyOutStream.h | 7 +- CPP/7zip/Archive/Common/FindSignature.cpp | 12 +- CPP/7zip/Archive/Common/FindSignature.h | 0 CPP/7zip/Archive/Common/HandlerOut.cpp | 36 +- CPP/7zip/Archive/Common/HandlerOut.h | 14 +- CPP/7zip/Archive/Common/InStreamWithCRC.cpp | 32 +- CPP/7zip/Archive/Common/InStreamWithCRC.h | 0 CPP/7zip/Archive/Common/ItemNameUtils.cpp | 37 +- CPP/7zip/Archive/Common/ItemNameUtils.h | 7 +- CPP/7zip/Archive/Common/MultiStream.cpp | 43 +- CPP/7zip/Archive/Common/MultiStream.h | 6 +- CPP/7zip/Archive/Common/OutStreamWithCRC.cpp | 0 CPP/7zip/Archive/Common/OutStreamWithCRC.h | 1 + CPP/7zip/Archive/Common/OutStreamWithSha1.cpp | 0 CPP/7zip/Archive/Common/OutStreamWithSha1.h | 0 CPP/7zip/Archive/Common/ParseProperties.cpp | 0 CPP/7zip/Archive/Common/ParseProperties.h | 0 CPP/7zip/Archive/Common/StdAfx.h | 3 +- CPP/7zip/Archive/CpioHandler.cpp | 834 +-- CPP/7zip/Archive/CramfsHandler.cpp | 283 +- CPP/7zip/Archive/DebHandler.cpp | 413 -- CPP/7zip/Archive/DeflateProps.cpp | 0 CPP/7zip/Archive/DeflateProps.h | 0 CPP/7zip/Archive/DllExports.cpp | 2 +- CPP/7zip/Archive/DllExports2.cpp | 26 +- CPP/7zip/Archive/DmgHandler.cpp | 1294 +++-- CPP/7zip/Archive/ElfHandler.cpp | 793 ++- CPP/7zip/Archive/FatHandler.cpp | 120 +- CPP/7zip/Archive/FlvHandler.cpp | 253 +- CPP/7zip/Archive/GzHandler.cpp | 662 ++- 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/HfsHandler.cpp | 1874 ++++++ CPP/7zip/Archive/IArchive.h | 327 +- CPP/7zip/Archive/Icons/7z.ico | Bin CPP/7zip/Archive/Icons/arj.ico | Bin CPP/7zip/Archive/Icons/bz2.ico | Bin CPP/7zip/Archive/Icons/cab.ico | Bin CPP/7zip/Archive/Icons/cpio.ico | Bin CPP/7zip/Archive/Icons/deb.ico | Bin CPP/7zip/Archive/Icons/dmg.ico | Bin CPP/7zip/Archive/Icons/fat.ico | Bin CPP/7zip/Archive/Icons/gz.ico | Bin CPP/7zip/Archive/Icons/hfs.ico | Bin CPP/7zip/Archive/Icons/iso.ico | Bin CPP/7zip/Archive/Icons/lzh.ico | Bin CPP/7zip/Archive/Icons/lzma.ico | Bin CPP/7zip/Archive/Icons/ntfs.ico | Bin CPP/7zip/Archive/Icons/rar.ico | Bin CPP/7zip/Archive/Icons/rpm.ico | Bin CPP/7zip/Archive/Icons/split.ico | Bin CPP/7zip/Archive/Icons/squashfs.ico | Bin CPP/7zip/Archive/Icons/tar.ico | Bin CPP/7zip/Archive/Icons/vhd.ico | Bin CPP/7zip/Archive/Icons/wim.ico | Bin CPP/7zip/Archive/Icons/xar.ico | Bin CPP/7zip/Archive/Icons/xz.ico | Bin CPP/7zip/Archive/Icons/z.ico | Bin CPP/7zip/Archive/Icons/zip.ico | Bin CPP/7zip/Archive/IhexHandler.cpp | 500 ++ CPP/7zip/Archive/Iso/IsoHandler.cpp | 194 +- CPP/7zip/Archive/Iso/IsoHandler.h | 3 +- CPP/7zip/Archive/Iso/IsoHeader.cpp | 12 +- CPP/7zip/Archive/Iso/IsoHeader.h | 9 +- CPP/7zip/Archive/Iso/IsoIn.cpp | 197 +- CPP/7zip/Archive/Iso/IsoIn.h | 88 +- CPP/7zip/Archive/Iso/IsoItem.h | 62 +- CPP/7zip/Archive/Iso/IsoRegister.cpp | 14 +- CPP/7zip/Archive/Iso/StdAfx.h | 3 +- CPP/7zip/Archive/LzhHandler.cpp | 111 +- CPP/7zip/Archive/LzmaHandler.cpp | 323 +- CPP/7zip/Archive/MachoHandler.cpp | 640 ++- CPP/7zip/Archive/MbrHandler.cpp | 36 +- CPP/7zip/Archive/MslzHandler.cpp | 308 +- CPP/7zip/Archive/MubHandler.cpp | 180 +- CPP/7zip/Archive/Nsis/NsisDecode.cpp | 221 +- CPP/7zip/Archive/Nsis/NsisDecode.h | 41 +- CPP/7zip/Archive/Nsis/NsisHandler.cpp | 643 ++- CPP/7zip/Archive/Nsis/NsisHandler.h | 25 +- CPP/7zip/Archive/Nsis/NsisIn.cpp | 6659 ++++++++++++++++++---- CPP/7zip/Archive/Nsis/NsisIn.h | 423 +- CPP/7zip/Archive/Nsis/NsisRegister.cpp | 15 +- CPP/7zip/Archive/Nsis/StdAfx.h | 3 +- CPP/7zip/Archive/NtfsHandler.cpp | 1478 ++++- CPP/7zip/Archive/PeHandler.cpp | 1999 +++++-- CPP/7zip/Archive/PpmdHandler.cpp | 55 +- CPP/7zip/Archive/Rar/RarHandler.cpp | 1287 ++++- CPP/7zip/Archive/Rar/RarHandler.h | 79 +- CPP/7zip/Archive/Rar/RarHeader.cpp | 21 - CPP/7zip/Archive/Rar/RarHeader.h | 69 +- 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 | 40 +- 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 | 0 CPP/7zip/Archive/Rar/StdAfx.h | 2 +- CPP/7zip/Archive/RpmHandler.cpp | 821 ++- CPP/7zip/Archive/SplitHandler.cpp | 275 +- CPP/7zip/Archive/SquashfsHandler.cpp | 240 +- CPP/7zip/Archive/StdAfx.h | 3 +- CPP/7zip/Archive/SwfHandler.cpp | 651 ++- CPP/7zip/Archive/Tar/StdAfx.h | 3 +- CPP/7zip/Archive/Tar/TarHandler.cpp | 388 +- CPP/7zip/Archive/Tar/TarHandler.h | 32 +- CPP/7zip/Archive/Tar/TarHandlerOut.cpp | 71 +- CPP/7zip/Archive/Tar/TarHeader.cpp | 12 +- CPP/7zip/Archive/Tar/TarHeader.h | 65 +- CPP/7zip/Archive/Tar/TarIn.cpp | 239 +- CPP/7zip/Archive/Tar/TarIn.h | 11 +- CPP/7zip/Archive/Tar/TarItem.h | 23 +- CPP/7zip/Archive/Tar/TarOut.cpp | 230 +- CPP/7zip/Archive/Tar/TarOut.h | 18 +- CPP/7zip/Archive/Tar/TarRegister.cpp | 22 +- CPP/7zip/Archive/Tar/TarUpdate.cpp | 129 +- CPP/7zip/Archive/Tar/TarUpdate.h | 1 + CPP/7zip/Archive/Udf/StdAfx.h | 3 +- CPP/7zip/Archive/Udf/UdfHandler.cpp | 170 +- CPP/7zip/Archive/Udf/UdfHandler.h | 11 +- CPP/7zip/Archive/Udf/UdfIn.cpp | 393 +- CPP/7zip/Archive/Udf/UdfIn.h | 54 +- CPP/7zip/Archive/Udf/UdfRegister.cpp | 6 - CPP/7zip/Archive/UefiHandler.cpp | 419 +- CPP/7zip/Archive/VhdHandler.cpp | 517 +- CPP/7zip/Archive/Wim/StdAfx.h | 2 +- CPP/7zip/Archive/Wim/WimHandler.cpp | 817 ++- CPP/7zip/Archive/Wim/WimHandler.h | 99 +- CPP/7zip/Archive/Wim/WimHandlerOut.cpp | 1807 ++++-- CPP/7zip/Archive/Wim/WimIn.cpp | 1099 ++-- CPP/7zip/Archive/Wim/WimIn.h | 355 +- CPP/7zip/Archive/Wim/WimRegister.cpp | 23 +- CPP/7zip/Archive/XarHandler.cpp | 365 +- CPP/7zip/Archive/XzHandler.cpp | 661 ++- CPP/7zip/Archive/ZHandler.cpp | 148 +- CPP/7zip/Archive/Zip/StdAfx.h | 2 +- CPP/7zip/Archive/Zip/ZipAddCommon.cpp | 49 +- CPP/7zip/Archive/Zip/ZipAddCommon.h | 0 CPP/7zip/Archive/Zip/ZipCompressionMode.h | 2 +- CPP/7zip/Archive/Zip/ZipHandler.cpp | 531 +- CPP/7zip/Archive/Zip/ZipHandler.h | 10 +- CPP/7zip/Archive/Zip/ZipHandlerOut.cpp | 151 +- CPP/7zip/Archive/Zip/ZipHeader.cpp | 36 - CPP/7zip/Archive/Zip/ZipHeader.h | 264 +- CPP/7zip/Archive/Zip/ZipIn.cpp | 1323 +++-- CPP/7zip/Archive/Zip/ZipIn.h | 178 +- CPP/7zip/Archive/Zip/ZipItem.cpp | 109 +- CPP/7zip/Archive/Zip/ZipItem.h | 226 +- CPP/7zip/Archive/Zip/ZipItemEx.h | 34 - CPP/7zip/Archive/Zip/ZipOut.cpp | 331 +- CPP/7zip/Archive/Zip/ZipOut.h | 68 +- CPP/7zip/Archive/Zip/ZipRegister.cpp | 27 +- CPP/7zip/Archive/Zip/ZipUpdate.cpp | 296 +- CPP/7zip/Archive/Zip/ZipUpdate.h | 19 +- CPP/7zip/Archive/makefile | 0 CPP/7zip/Asm.mak | 2 + CPP/7zip/Bundles/Alone/Alone.dsp | 121 +- CPP/7zip/Bundles/Alone/Alone.dsw | 0 CPP/7zip/Bundles/Alone/StdAfx.cpp | 0 CPP/7zip/Bundles/Alone/StdAfx.h | 3 +- CPP/7zip/Bundles/Alone/afxres.h | 0 CPP/7zip/Bundles/Alone/makefile | 114 +- CPP/7zip/Bundles/Alone/resource.rc | 0 CPP/7zip/Bundles/Alone7z/StdAfx.cpp | 0 CPP/7zip/Bundles/Alone7z/StdAfx.h | 3 +- CPP/7zip/Bundles/Alone7z/makefile | 104 +- CPP/7zip/Bundles/Alone7z/resource.rc | 0 CPP/7zip/Bundles/Fm/FM.dsp | 126 +- CPP/7zip/Bundles/Fm/FM.dsw | 0 CPP/7zip/Bundles/Fm/StdAfx.cpp | 0 CPP/7zip/Bundles/Fm/StdAfx.h | 15 +- CPP/7zip/Bundles/Fm/makefile | 476 +- CPP/7zip/Bundles/Fm/resource.rc | 0 CPP/7zip/Bundles/Format7z/StdAfx.cpp | 0 CPP/7zip/Bundles/Format7z/StdAfx.h | 3 +- CPP/7zip/Bundles/Format7z/makefile | 53 +- CPP/7zip/Bundles/Format7z/resource.rc | 0 CPP/7zip/Bundles/Format7zExtract/StdAfx.cpp | 0 CPP/7zip/Bundles/Format7zExtract/StdAfx.h | 3 +- CPP/7zip/Bundles/Format7zExtract/makefile | 49 +- CPP/7zip/Bundles/Format7zExtract/resource.rc | 0 CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp | 0 CPP/7zip/Bundles/Format7zExtractR/StdAfx.h | 3 +- CPP/7zip/Bundles/Format7zExtractR/makefile | 43 +- CPP/7zip/Bundles/Format7zExtractR/resource.rc | 0 CPP/7zip/Bundles/Format7zF/Arc.mak | 275 + CPP/7zip/Bundles/Format7zF/Format7z.dsp | 230 +- CPP/7zip/Bundles/Format7zF/Format7z.dsw | 0 CPP/7zip/Bundles/Format7zF/StdAfx.cpp | 0 CPP/7zip/Bundles/Format7zF/StdAfx.h | 3 +- CPP/7zip/Bundles/Format7zF/makefile | 362 +- CPP/7zip/Bundles/Format7zF/resource.rc | 0 CPP/7zip/Bundles/Format7zR/StdAfx.cpp | 0 CPP/7zip/Bundles/Format7zR/StdAfx.h | 3 +- CPP/7zip/Bundles/Format7zR/makefile | 45 +- CPP/7zip/Bundles/Format7zR/resource.rc | 0 CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp | 77 +- CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp | 8 +- CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw | 0 CPP/7zip/Bundles/LzmaCon/StdAfx.cpp | 0 CPP/7zip/Bundles/LzmaCon/StdAfx.h | 2 +- CPP/7zip/Bundles/LzmaCon/makefile | 38 +- CPP/7zip/Bundles/LzmaCon/makefile.gcc | 4 + CPP/7zip/Bundles/LzmaCon/resource.rc | 3 + CPP/7zip/Bundles/SFXCon/7z.ico | Bin CPP/7zip/Bundles/SFXCon/Main.cpp | 447 -- CPP/7zip/Bundles/SFXCon/SFXCon.dsp | 42 +- CPP/7zip/Bundles/SFXCon/SFXCon.dsw | 0 CPP/7zip/Bundles/SFXCon/SfxCon.cpp | 453 ++ CPP/7zip/Bundles/SFXCon/StdAfx.cpp | 0 CPP/7zip/Bundles/SFXCon/StdAfx.h | 3 +- CPP/7zip/Bundles/SFXCon/makefile | 66 +- CPP/7zip/Bundles/SFXCon/resource.rc | 0 CPP/7zip/Bundles/SFXSetup/ExtractCallback.cpp | 237 - CPP/7zip/Bundles/SFXSetup/ExtractCallback.h | 88 - CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp | 238 + CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.h | 86 + CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp | 35 +- CPP/7zip/Bundles/SFXSetup/ExtractEngine.h | 0 CPP/7zip/Bundles/SFXSetup/Main.cpp | 337 -- CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp | 30 +- CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw | 0 CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp | 356 ++ CPP/7zip/Bundles/SFXSetup/StdAfx.cpp | 0 CPP/7zip/Bundles/SFXSetup/StdAfx.h | 7 +- CPP/7zip/Bundles/SFXSetup/makefile | 66 +- CPP/7zip/Bundles/SFXSetup/resource.h | 10 +- CPP/7zip/Bundles/SFXSetup/resource.rc | 8 +- CPP/7zip/Bundles/SFXSetup/setup.ico | Bin CPP/7zip/Bundles/SFXWin/7z.ico | Bin CPP/7zip/Bundles/SFXWin/Main.cpp | 184 - CPP/7zip/Bundles/SFXWin/SFXWin.dsp | 80 +- CPP/7zip/Bundles/SFXWin/SFXWin.dsw | 0 CPP/7zip/Bundles/SFXWin/SfxWin.cpp | 233 + CPP/7zip/Bundles/SFXWin/StdAfx.cpp | 0 CPP/7zip/Bundles/SFXWin/StdAfx.h | 6 +- CPP/7zip/Bundles/SFXWin/makefile | 84 +- CPP/7zip/Bundles/SFXWin/resource.h | 2 +- CPP/7zip/Bundles/SFXWin/resource.rc | 31 +- CPP/7zip/Bundles/makefile | 0 CPP/7zip/Common/CWrappers.cpp | 18 +- CPP/7zip/Common/CWrappers.h | 33 +- CPP/7zip/Common/CreateCoder.cpp | 215 +- CPP/7zip/Common/CreateCoder.h | 41 +- CPP/7zip/Common/FilePathAutoRename.cpp | 10 +- CPP/7zip/Common/FilePathAutoRename.h | 2 +- CPP/7zip/Common/FileStreams.cpp | 157 +- CPP/7zip/Common/FileStreams.h | 28 +- CPP/7zip/Common/FilterCoder.cpp | 20 +- CPP/7zip/Common/FilterCoder.h | 22 +- CPP/7zip/Common/InBuffer.cpp | 120 +- CPP/7zip/Common/InBuffer.h | 99 +- CPP/7zip/Common/InMemStream.cpp | 2 +- CPP/7zip/Common/InMemStream.h | 0 CPP/7zip/Common/InOutTempBuffer.cpp | 4 +- CPP/7zip/Common/InOutTempBuffer.h | 2 +- CPP/7zip/Common/LimitedStreams.cpp | 253 +- CPP/7zip/Common/LimitedStreams.h | 138 +- CPP/7zip/Common/LockedStream.cpp | 0 CPP/7zip/Common/LockedStream.h | 0 CPP/7zip/Common/MemBlocks.cpp | 4 +- CPP/7zip/Common/MemBlocks.h | 4 +- CPP/7zip/Common/MethodId.cpp | 0 CPP/7zip/Common/MethodId.h | 2 +- CPP/7zip/Common/MethodProps.cpp | 131 +- CPP/7zip/Common/MethodProps.h | 5 +- CPP/7zip/Common/OffsetStream.cpp | 12 +- CPP/7zip/Common/OffsetStream.h | 7 +- CPP/7zip/Common/OutBuffer.cpp | 47 +- CPP/7zip/Common/OutBuffer.h | 35 +- CPP/7zip/Common/OutMemStream.cpp | 10 +- CPP/7zip/Common/OutMemStream.h | 9 +- CPP/7zip/Common/ProgressMt.cpp | 0 CPP/7zip/Common/ProgressMt.h | 0 CPP/7zip/Common/ProgressUtils.cpp | 2 +- CPP/7zip/Common/ProgressUtils.h | 0 CPP/7zip/Common/PropId.cpp | 99 + CPP/7zip/Common/RegisterArc.h | 47 +- CPP/7zip/Common/RegisterCodec.h | 26 +- CPP/7zip/Common/StdAfx.h | 3 +- CPP/7zip/Common/StreamBinder.cpp | 0 CPP/7zip/Common/StreamBinder.h | 0 CPP/7zip/Common/StreamObjects.cpp | 61 +- CPP/7zip/Common/StreamObjects.h | 29 +- CPP/7zip/Common/StreamUtils.cpp | 0 CPP/7zip/Common/StreamUtils.h | 12 +- CPP/7zip/Common/UniqBlocks.cpp | 56 + CPP/7zip/Common/UniqBlocks.h | 30 + CPP/7zip/Common/VirtThread.cpp | 0 CPP/7zip/Common/VirtThread.h | 0 CPP/7zip/Compress/ArjDecoder1.cpp | 2 +- CPP/7zip/Compress/ArjDecoder1.h | 7 - CPP/7zip/Compress/ArjDecoder2.cpp | 3 +- CPP/7zip/Compress/ArjDecoder2.h | 7 - CPP/7zip/Compress/BZip2Const.h | 0 CPP/7zip/Compress/BZip2Crc.cpp | 0 CPP/7zip/Compress/BZip2Crc.h | 2 +- CPP/7zip/Compress/BZip2Decoder.cpp | 318 +- CPP/7zip/Compress/BZip2Decoder.h | 87 +- CPP/7zip/Compress/BZip2Encoder.cpp | 38 +- CPP/7zip/Compress/BZip2Encoder.h | 77 +- CPP/7zip/Compress/BZip2Register.cpp | 0 CPP/7zip/Compress/Bcj2Coder.cpp | 172 +- CPP/7zip/Compress/Bcj2Coder.h | 55 +- CPP/7zip/Compress/Bcj2Register.cpp | 0 CPP/7zip/Compress/BcjCoder.cpp | 0 CPP/7zip/Compress/BcjCoder.h | 0 CPP/7zip/Compress/BcjRegister.cpp | 0 CPP/7zip/Compress/BitlDecoder.cpp | 4 +- CPP/7zip/Compress/BitlDecoder.h | 119 +- CPP/7zip/Compress/BitlEncoder.h | 49 +- CPP/7zip/Compress/BitmDecoder.h | 48 +- CPP/7zip/Compress/BitmEncoder.h | 37 +- CPP/7zip/Compress/BranchCoder.cpp | 0 CPP/7zip/Compress/BranchCoder.h | 0 CPP/7zip/Compress/BranchMisc.cpp | 42 +- CPP/7zip/Compress/BranchMisc.h | 0 CPP/7zip/Compress/BranchRegister.cpp | 0 CPP/7zip/Compress/ByteSwap.cpp | 0 CPP/7zip/Compress/Codec.def | 0 CPP/7zip/Compress/CodecExports.cpp | 179 +- CPP/7zip/Compress/CopyCoder.cpp | 21 +- CPP/7zip/Compress/CopyCoder.h | 1 + CPP/7zip/Compress/CopyRegister.cpp | 0 CPP/7zip/Compress/Deflate64Register.cpp | 0 CPP/7zip/Compress/DeflateConst.h | 21 +- CPP/7zip/Compress/DeflateDecoder.cpp | 135 +- CPP/7zip/Compress/DeflateDecoder.h | 56 +- CPP/7zip/Compress/DeflateEncoder.cpp | 60 +- CPP/7zip/Compress/DeflateEncoder.h | 18 +- CPP/7zip/Compress/DeflateRegister.cpp | 0 CPP/7zip/Compress/DeltaFilter.cpp | 0 CPP/7zip/Compress/DllExports.cpp | 45 - CPP/7zip/Compress/DllExports2.cpp | 33 - CPP/7zip/Compress/DllExports2Compress.cpp | 33 + CPP/7zip/Compress/DllExportsCompress.cpp | 53 + CPP/7zip/Compress/HuffmanDecoder.h | 6 +- CPP/7zip/Compress/ImplodeDecoder.cpp | 23 +- CPP/7zip/Compress/ImplodeDecoder.h | 5 +- CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp | 6 +- CPP/7zip/Compress/ImplodeHuffmanDecoder.h | 0 CPP/7zip/Compress/LzOutWindow.cpp | 0 CPP/7zip/Compress/LzOutWindow.h | 30 +- CPP/7zip/Compress/LzhDecoder.cpp | 8 +- CPP/7zip/Compress/LzhDecoder.h | 5 +- CPP/7zip/Compress/Lzma2Decoder.cpp | 0 CPP/7zip/Compress/Lzma2Decoder.h | 0 CPP/7zip/Compress/Lzma2Encoder.cpp | 0 CPP/7zip/Compress/Lzma2Encoder.h | 0 CPP/7zip/Compress/Lzma2Register.cpp | 0 CPP/7zip/Compress/LzmaDecoder.cpp | 16 +- CPP/7zip/Compress/LzmaDecoder.h | 6 +- CPP/7zip/Compress/LzmaEncoder.cpp | 9 +- CPP/7zip/Compress/LzmaEncoder.h | 2 + CPP/7zip/Compress/LzmaRegister.cpp | 0 CPP/7zip/Compress/Lzx.h | 0 CPP/7zip/Compress/Lzx86Converter.cpp | 56 +- CPP/7zip/Compress/Lzx86Converter.h | 25 +- CPP/7zip/Compress/LzxDecoder.cpp | 12 +- CPP/7zip/Compress/LzxDecoder.h | 48 +- CPP/7zip/Compress/Mtf8.h | 16 +- CPP/7zip/Compress/PpmdDecoder.cpp | 0 CPP/7zip/Compress/PpmdDecoder.h | 0 CPP/7zip/Compress/PpmdEncoder.cpp | 0 CPP/7zip/Compress/PpmdEncoder.h | 0 CPP/7zip/Compress/PpmdRegister.cpp | 0 CPP/7zip/Compress/PpmdZip.cpp | 0 CPP/7zip/Compress/PpmdZip.h | 0 CPP/7zip/Compress/QuantumDecoder.cpp | 11 +- CPP/7zip/Compress/QuantumDecoder.h | 23 +- CPP/7zip/Compress/RangeCoder.h | 26 +- CPP/7zip/Compress/RangeCoderBit.h | 16 +- CPP/7zip/Compress/Rar1Decoder.cpp | 10 +- CPP/7zip/Compress/Rar1Decoder.h | 2 + CPP/7zip/Compress/Rar2Decoder.cpp | 8 +- CPP/7zip/Compress/Rar2Decoder.h | 6 +- CPP/7zip/Compress/Rar3Decoder.cpp | 104 +- CPP/7zip/Compress/Rar3Decoder.h | 76 +- CPP/7zip/Compress/Rar3Vm.cpp | 146 +- CPP/7zip/Compress/Rar3Vm.h | 28 +- CPP/7zip/Compress/RarCodecsRegister.cpp | 0 CPP/7zip/Compress/ShrinkDecoder.cpp | 0 CPP/7zip/Compress/ShrinkDecoder.h | 0 CPP/7zip/Compress/StdAfx.h | 2 +- CPP/7zip/Compress/ZDecoder.cpp | 118 +- CPP/7zip/Compress/ZDecoder.h | 26 +- CPP/7zip/Compress/ZlibDecoder.cpp | 25 +- CPP/7zip/Compress/ZlibDecoder.h | 33 +- CPP/7zip/Compress/ZlibEncoder.cpp | 0 CPP/7zip/Compress/ZlibEncoder.h | 0 CPP/7zip/Compress/makefile | 0 CPP/7zip/Crc.mak | 0 CPP/7zip/Crc64.mak | 8 + CPP/7zip/Crypto/7zAes.cpp | 22 +- CPP/7zip/Crypto/7zAes.h | 10 +- CPP/7zip/Crypto/7zAesRegister.cpp | 0 CPP/7zip/Crypto/Codec.def | 0 CPP/7zip/Crypto/HmacSha1.cpp | 0 CPP/7zip/Crypto/HmacSha1.h | 0 CPP/7zip/Crypto/MyAes.cpp | 78 +- CPP/7zip/Crypto/MyAes.h | 26 +- CPP/7zip/Crypto/MyAesReg.cpp | 19 + CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp | 0 CPP/7zip/Crypto/Pbkdf2HmacSha1.h | 3 +- CPP/7zip/Crypto/RandGen.cpp | 10 +- CPP/7zip/Crypto/RandGen.h | 0 CPP/7zip/Crypto/Rar20Crypto.cpp | 0 CPP/7zip/Crypto/Rar20Crypto.h | 2 +- CPP/7zip/Crypto/RarAes.cpp | 16 +- CPP/7zip/Crypto/RarAes.h | 2 +- CPP/7zip/Crypto/Sha1.cpp | 18 +- CPP/7zip/Crypto/Sha1.h | 3 +- CPP/7zip/Crypto/Sha1Reg.cpp | 55 + CPP/7zip/Crypto/StdAfx.h | 2 +- CPP/7zip/Crypto/WzAes.cpp | 13 +- CPP/7zip/Crypto/WzAes.h | 5 +- CPP/7zip/Crypto/ZipCrypto.cpp | 0 CPP/7zip/Crypto/ZipCrypto.h | 2 +- CPP/7zip/Crypto/ZipStrong.cpp | 23 +- CPP/7zip/Crypto/ZipStrong.h | 2 +- CPP/7zip/GuiCommon.rc | 19 +- CPP/7zip/Guid.txt | 26 +- CPP/7zip/ICoder.h | 25 +- CPP/7zip/IDecl.h | 0 CPP/7zip/IPassword.h | 3 +- CPP/7zip/IProgress.h | 2 +- CPP/7zip/IStream.h | 43 +- CPP/7zip/MyVersion.h | 2 +- CPP/7zip/MyVersionInfo.rc | 0 CPP/7zip/PropID.h | 66 +- CPP/7zip/SubBuild.mak | 0 CPP/7zip/UI/Agent/Agent.cpp | 1184 +++- CPP/7zip/UI/Agent/Agent.h | 109 +- CPP/7zip/UI/Agent/AgentOut.cpp | 207 +- CPP/7zip/UI/Agent/AgentProxy.cpp | 565 +- CPP/7zip/UI/Agent/AgentProxy.h | 107 +- CPP/7zip/UI/Agent/ArchiveFolder.cpp | 29 +- CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp | 14 +- CPP/7zip/UI/Agent/ArchiveFolderOut.cpp | 197 +- CPP/7zip/UI/Agent/IFolderArchive.h | 15 +- CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp | 15 +- CPP/7zip/UI/Agent/UpdateCallbackAgent.h | 5 +- CPP/7zip/UI/Client7z/Client7z.cpp | 174 +- CPP/7zip/UI/Client7z/Client7z.dsp | 21 +- CPP/7zip/UI/Client7z/Client7z.dsw | 0 CPP/7zip/UI/Client7z/StdAfx.cpp | 0 CPP/7zip/UI/Client7z/StdAfx.h | 3 +- CPP/7zip/UI/Client7z/makefile | 25 +- CPP/7zip/UI/Client7z/resource.rc | 3 + CPP/7zip/UI/Common/ArchiveCommandLine.cpp | 1065 ++-- CPP/7zip/UI/Common/ArchiveCommandLine.h | 73 +- CPP/7zip/UI/Common/ArchiveExtractCallback.cpp | 965 +++- CPP/7zip/UI/Common/ArchiveExtractCallback.h | 194 +- CPP/7zip/UI/Common/ArchiveName.cpp | 24 +- CPP/7zip/UI/Common/ArchiveName.h | 9 +- CPP/7zip/UI/Common/ArchiveOpenCallback.cpp | 38 +- CPP/7zip/UI/Common/ArchiveOpenCallback.h | 28 +- CPP/7zip/UI/Common/Bench.cpp | 1482 ++++- CPP/7zip/UI/Common/Bench.h | 8 +- CPP/7zip/UI/Common/CompressCall.cpp | 111 +- CPP/7zip/UI/Common/CompressCall.h | 10 +- CPP/7zip/UI/Common/CompressCall2.cpp | 148 +- CPP/7zip/UI/Common/DefaultName.cpp | 6 +- CPP/7zip/UI/Common/DefaultName.h | 6 +- CPP/7zip/UI/Common/DirItem.h | 83 +- CPP/7zip/UI/Common/EnumDirItems.cpp | 624 +- CPP/7zip/UI/Common/EnumDirItems.h | 16 +- CPP/7zip/UI/Common/ExitCode.h | 0 CPP/7zip/UI/Common/Extract.cpp | 362 +- CPP/7zip/UI/Common/Extract.h | 52 +- CPP/7zip/UI/Common/ExtractMode.h | 40 +- CPP/7zip/UI/Common/ExtractingFilePath.cpp | 110 +- CPP/7zip/UI/Common/ExtractingFilePath.h | 12 +- CPP/7zip/UI/Common/HashCalc.cpp | 361 ++ CPP/7zip/UI/Common/HashCalc.h | 107 + CPP/7zip/UI/Common/IFileExtractCallback.h | 32 +- CPP/7zip/UI/Common/LoadCodecs.cpp | 712 ++- CPP/7zip/UI/Common/LoadCodecs.h | 167 +- CPP/7zip/UI/Common/OpenArchive.cpp | 3204 ++++++++++- CPP/7zip/UI/Common/OpenArchive.h | 350 +- CPP/7zip/UI/Common/PropIDUtils.cpp | 547 +- CPP/7zip/UI/Common/PropIDUtils.h | 13 +- CPP/7zip/UI/Common/Property.h | 0 CPP/7zip/UI/Common/SetProperties.cpp | 25 +- CPP/7zip/UI/Common/SetProperties.h | 0 CPP/7zip/UI/Common/SortUtils.cpp | 17 +- CPP/7zip/UI/Common/SortUtils.h | 8 +- CPP/7zip/UI/Common/StdAfx.h | 5 +- CPP/7zip/UI/Common/TempFiles.cpp | 6 +- CPP/7zip/UI/Common/TempFiles.h | 2 +- CPP/7zip/UI/Common/Update.cpp | 998 +++- CPP/7zip/UI/Common/Update.h | 129 +- CPP/7zip/UI/Common/UpdateAction.cpp | 10 +- CPP/7zip/UI/Common/UpdateAction.h | 23 +- CPP/7zip/UI/Common/UpdateCallback.cpp | 448 +- CPP/7zip/UI/Common/UpdateCallback.h | 59 +- CPP/7zip/UI/Common/UpdatePair.cpp | 203 +- CPP/7zip/UI/Common/UpdatePair.h | 4 +- CPP/7zip/UI/Common/UpdateProduce.cpp | 21 +- CPP/7zip/UI/Common/UpdateProduce.h | 15 +- CPP/7zip/UI/Common/WorkDir.cpp | 12 +- CPP/7zip/UI/Common/WorkDir.h | 8 +- CPP/7zip/UI/Common/ZipRegistry.cpp | 97 +- CPP/7zip/UI/Common/ZipRegistry.h | 21 +- CPP/7zip/UI/Console/BenchCon.cpp | 2 +- CPP/7zip/UI/Console/BenchCon.h | 2 +- CPP/7zip/UI/Console/Console.dsp | 157 +- CPP/7zip/UI/Console/Console.dsw | 0 CPP/7zip/UI/Console/Console.mak | 35 + CPP/7zip/UI/Console/ConsoleClose.cpp | 0 CPP/7zip/UI/Console/ConsoleClose.h | 0 CPP/7zip/UI/Console/ExtractCallbackConsole.cpp | 245 +- CPP/7zip/UI/Console/ExtractCallbackConsole.h | 42 +- CPP/7zip/UI/Console/HashCon.cpp | 274 + CPP/7zip/UI/Console/HashCon.h | 26 + CPP/7zip/UI/Console/List.cpp | 1218 ++-- CPP/7zip/UI/Console/List.h | 15 +- CPP/7zip/UI/Console/Main.cpp | 799 ++- CPP/7zip/UI/Console/MainAr.cpp | 17 +- CPP/7zip/UI/Console/OpenCallbackConsole.cpp | 6 +- CPP/7zip/UI/Console/OpenCallbackConsole.h | 7 +- CPP/7zip/UI/Console/PercentPrinter.cpp | 4 +- CPP/7zip/UI/Console/PercentPrinter.h | 2 +- CPP/7zip/UI/Console/StdAfx.cpp | 0 CPP/7zip/UI/Console/StdAfx.h | 3 +- CPP/7zip/UI/Console/UpdateCallbackConsole.cpp | 39 +- CPP/7zip/UI/Console/UpdateCallbackConsole.h | 57 +- CPP/7zip/UI/Console/UserInputUtils.cpp | 41 +- CPP/7zip/UI/Console/UserInputUtils.h | 6 +- CPP/7zip/UI/Console/makefile | 87 +- CPP/7zip/UI/Console/resource.rc | 0 CPP/7zip/UI/Explorer/7-zip.dll.manifest | 0 CPP/7zip/UI/Explorer/ContextMenu.cpp | 532 +- CPP/7zip/UI/Explorer/ContextMenu.h | 17 +- CPP/7zip/UI/Explorer/ContextMenuFlags.h | 2 + CPP/7zip/UI/Explorer/DllExports.cpp | 256 - CPP/7zip/UI/Explorer/DllExportsExplorer.cpp | 256 + CPP/7zip/UI/Explorer/Explorer.def | 0 CPP/7zip/UI/Explorer/Explorer.dsp | 22 +- CPP/7zip/UI/Explorer/Explorer.dsw | 0 CPP/7zip/UI/Explorer/MenuLogo.bmp | Bin 0 -> 114 bytes CPP/7zip/UI/Explorer/MyMessages.cpp | 35 +- CPP/7zip/UI/Explorer/MyMessages.h | 22 +- CPP/7zip/UI/Explorer/OptionsDialog.cpp | 2 +- CPP/7zip/UI/Explorer/OptionsDialog.h | 0 CPP/7zip/UI/Explorer/RegistryContextMenu.cpp | 7 +- CPP/7zip/UI/Explorer/RegistryContextMenu.h | 0 CPP/7zip/UI/Explorer/StdAfx.cpp | 0 CPP/7zip/UI/Explorer/StdAfx.h | 20 +- CPP/7zip/UI/Explorer/makefile | 41 +- CPP/7zip/UI/Explorer/resource.h | 41 +- CPP/7zip/UI/Explorer/resource.rc | 0 CPP/7zip/UI/Explorer/resource2.rc | 19 +- CPP/7zip/UI/Far/ExtractEngine.cpp | 59 +- CPP/7zip/UI/Far/ExtractEngine.h | 8 +- CPP/7zip/UI/Far/Far.cpp | 618 ++ CPP/7zip/UI/Far/Far.def | 0 CPP/7zip/UI/Far/Far.dsp | 112 +- CPP/7zip/UI/Far/Far.dsw | 0 CPP/7zip/UI/Far/FarPlugin.h | 2 +- CPP/7zip/UI/Far/FarUtils.cpp | 40 +- CPP/7zip/UI/Far/FarUtils.h | 13 +- CPP/7zip/UI/Far/Main.cpp | 613 -- CPP/7zip/UI/Far/Messages.h | 94 +- CPP/7zip/UI/Far/OverwriteDialog.cpp | 112 - CPP/7zip/UI/Far/OverwriteDialog.h | 37 - CPP/7zip/UI/Far/OverwriteDialogFar.cpp | 113 + CPP/7zip/UI/Far/OverwriteDialogFar.h | 37 + CPP/7zip/UI/Far/Plugin.cpp | 236 +- CPP/7zip/UI/Far/Plugin.h | 10 +- CPP/7zip/UI/Far/PluginCommon.cpp | 0 CPP/7zip/UI/Far/PluginDelete.cpp | 19 +- CPP/7zip/UI/Far/PluginRead.cpp | 75 +- CPP/7zip/UI/Far/PluginWrite.cpp | 237 +- CPP/7zip/UI/Far/ProgressBox.cpp | 7 +- CPP/7zip/UI/Far/ProgressBox.h | 8 +- CPP/7zip/UI/Far/StdAfx.cpp | 0 CPP/7zip/UI/Far/StdAfx.h | 8 +- CPP/7zip/UI/Far/UpdateCallback100.cpp | 66 - CPP/7zip/UI/Far/UpdateCallback100.h | 43 - CPP/7zip/UI/Far/UpdateCallbackFar.cpp | 65 + CPP/7zip/UI/Far/UpdateCallbackFar.h | 43 + CPP/7zip/UI/Far/makefile | 61 +- CPP/7zip/UI/Far/resource.rc | 0 CPP/7zip/UI/FileManager/7zFM.exe.manifest | 0 CPP/7zip/UI/FileManager/7zipLogo.ico | Bin CPP/7zip/UI/FileManager/AboutDialog.cpp | 46 +- CPP/7zip/UI/FileManager/AboutDialog.h | 7 +- CPP/7zip/UI/FileManager/AboutDialog.rc | 16 +- CPP/7zip/UI/FileManager/AboutDialogRes.h | 14 +- CPP/7zip/UI/FileManager/Add.bmp | Bin CPP/7zip/UI/FileManager/Add2.bmp | Bin CPP/7zip/UI/FileManager/App.cpp | 284 +- CPP/7zip/UI/FileManager/App.h | 55 +- CPP/7zip/UI/FileManager/AppState.h | 41 +- CPP/7zip/UI/FileManager/BrowseDialog.cpp | 968 +++- CPP/7zip/UI/FileManager/BrowseDialog.h | 80 +- CPP/7zip/UI/FileManager/BrowseDialog.rc | 24 +- CPP/7zip/UI/FileManager/BrowseDialogRes.h | 13 +- CPP/7zip/UI/FileManager/ClassDefs.cpp | 3 +- CPP/7zip/UI/FileManager/ComboDialog.cpp | 18 +- CPP/7zip/UI/FileManager/ComboDialog.h | 7 +- CPP/7zip/UI/FileManager/ComboDialog.rc | 9 +- CPP/7zip/UI/FileManager/ComboDialogRes.h | 6 +- CPP/7zip/UI/FileManager/Copy.bmp | Bin CPP/7zip/UI/FileManager/Copy2.bmp | Bin CPP/7zip/UI/FileManager/CopyDialog.cpp | 44 +- CPP/7zip/UI/FileManager/CopyDialog.h | 6 +- CPP/7zip/UI/FileManager/CopyDialog.rc | 13 +- CPP/7zip/UI/FileManager/CopyDialogRes.h | 12 +- CPP/7zip/UI/FileManager/Delete.bmp | Bin CPP/7zip/UI/FileManager/Delete2.bmp | Bin CPP/7zip/UI/FileManager/DialogSize.h | 2 +- CPP/7zip/UI/FileManager/EditPage.cpp | 51 +- CPP/7zip/UI/FileManager/EditPage.h | 5 +- CPP/7zip/UI/FileManager/EditPage.rc | 0 CPP/7zip/UI/FileManager/EditPage2.rc | 17 +- CPP/7zip/UI/FileManager/EditPageRes.h | 21 +- CPP/7zip/UI/FileManager/EnumFormatEtc.cpp | 0 CPP/7zip/UI/FileManager/EnumFormatEtc.h | 0 CPP/7zip/UI/FileManager/Extract.bmp | Bin CPP/7zip/UI/FileManager/Extract2.bmp | Bin CPP/7zip/UI/FileManager/ExtractCallback.cpp | 644 ++- CPP/7zip/UI/FileManager/ExtractCallback.h | 217 +- CPP/7zip/UI/FileManager/FM.cpp | 334 +- CPP/7zip/UI/FileManager/FM.dsp | 263 +- CPP/7zip/UI/FileManager/FM.dsw | 0 CPP/7zip/UI/FileManager/FM.ico | Bin CPP/7zip/UI/FileManager/FM.mak | 81 + CPP/7zip/UI/FileManager/FSDrives.cpp | 172 +- CPP/7zip/UI/FileManager/FSDrives.h | 18 +- CPP/7zip/UI/FileManager/FSFolder.cpp | 901 ++- CPP/7zip/UI/FileManager/FSFolder.h | 138 +- CPP/7zip/UI/FileManager/FSFolderCopy.cpp | 253 +- CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp | 22 +- CPP/7zip/UI/FileManager/FileFolderPluginOpen.h | 0 CPP/7zip/UI/FileManager/FilePlugins.cpp | 8 +- CPP/7zip/UI/FileManager/FilePlugins.h | 0 CPP/7zip/UI/FileManager/FoldersPage.cpp | 40 +- CPP/7zip/UI/FileManager/FoldersPage.h | 2 +- CPP/7zip/UI/FileManager/FoldersPage.rc | 0 CPP/7zip/UI/FileManager/FoldersPage2.rc | 16 +- CPP/7zip/UI/FileManager/FoldersPageRes.h | 21 +- CPP/7zip/UI/FileManager/FormatUtils.cpp | 20 +- CPP/7zip/UI/FileManager/FormatUtils.h | 14 +- CPP/7zip/UI/FileManager/HelpUtils.cpp | 6 +- CPP/7zip/UI/FileManager/HelpUtils.h | 6 +- CPP/7zip/UI/FileManager/IFolder.h | 59 +- CPP/7zip/UI/FileManager/Info.bmp | Bin CPP/7zip/UI/FileManager/Info2.bmp | Bin CPP/7zip/UI/FileManager/LangPage.cpp | 85 +- CPP/7zip/UI/FileManager/LangPage.h | 5 +- CPP/7zip/UI/FileManager/LangPage.rc | 10 +- CPP/7zip/UI/FileManager/LangPageRes.h | 12 +- CPP/7zip/UI/FileManager/LangUtils.cpp | 280 +- CPP/7zip/UI/FileManager/LangUtils.h | 31 +- CPP/7zip/UI/FileManager/LinkDialog.cpp | 342 ++ CPP/7zip/UI/FileManager/LinkDialog.h | 33 + CPP/7zip/UI/FileManager/LinkDialog.rc | 36 + CPP/7zip/UI/FileManager/LinkDialogRes.h | 21 + CPP/7zip/UI/FileManager/ListViewDialog.cpp | 16 +- CPP/7zip/UI/FileManager/ListViewDialog.h | 6 +- CPP/7zip/UI/FileManager/ListViewDialog.rc | 4 +- CPP/7zip/UI/FileManager/ListViewDialogRes.h | 4 +- CPP/7zip/UI/FileManager/MenuPage.cpp | 84 +- CPP/7zip/UI/FileManager/MenuPage.h | 4 +- CPP/7zip/UI/FileManager/MenuPage.rc | 2 +- CPP/7zip/UI/FileManager/MenuPage2.rc | 15 +- CPP/7zip/UI/FileManager/MenuPageRes.h | 14 +- CPP/7zip/UI/FileManager/MessagesDialog.cpp | 46 +- CPP/7zip/UI/FileManager/MessagesDialog.h | 8 +- CPP/7zip/UI/FileManager/MessagesDialog.rc | 4 +- CPP/7zip/UI/FileManager/MessagesDialogRes.h | 6 +- CPP/7zip/UI/FileManager/Move.bmp | Bin CPP/7zip/UI/FileManager/Move2.bmp | Bin CPP/7zip/UI/FileManager/MyCom2.h | 2 +- CPP/7zip/UI/FileManager/MyLoadMenu.cpp | 352 +- CPP/7zip/UI/FileManager/MyLoadMenu.h | 0 CPP/7zip/UI/FileManager/MyWindowsNew.h | 0 CPP/7zip/UI/FileManager/NetFolder.cpp | 21 +- CPP/7zip/UI/FileManager/NetFolder.h | 4 +- CPP/7zip/UI/FileManager/OpenCallback.cpp | 57 +- CPP/7zip/UI/FileManager/OpenCallback.h | 13 +- CPP/7zip/UI/FileManager/OptionsDialog.cpp | 19 +- CPP/7zip/UI/FileManager/OverwriteDialog.cpp | 112 +- CPP/7zip/UI/FileManager/OverwriteDialog.h | 6 +- CPP/7zip/UI/FileManager/OverwriteDialog.rc | 57 +- CPP/7zip/UI/FileManager/OverwriteDialogRes.h | 29 +- CPP/7zip/UI/FileManager/Panel.cpp | 240 +- CPP/7zip/UI/FileManager/Panel.h | 212 +- CPP/7zip/UI/FileManager/PanelCopy.cpp | 199 +- CPP/7zip/UI/FileManager/PanelCrc.cpp | 427 +- CPP/7zip/UI/FileManager/PanelDrag.cpp | 95 +- CPP/7zip/UI/FileManager/PanelFolderChange.cpp | 107 +- CPP/7zip/UI/FileManager/PanelItemOpen.cpp | 431 +- CPP/7zip/UI/FileManager/PanelItems.cpp | 444 +- CPP/7zip/UI/FileManager/PanelKey.cpp | 30 +- CPP/7zip/UI/FileManager/PanelListNotify.cpp | 407 +- CPP/7zip/UI/FileManager/PanelMenu.cpp | 174 +- CPP/7zip/UI/FileManager/PanelOperations.cpp | 265 +- CPP/7zip/UI/FileManager/PanelSelect.cpp | 57 +- CPP/7zip/UI/FileManager/PanelSort.cpp | 147 +- CPP/7zip/UI/FileManager/PanelSplitFile.cpp | 183 +- CPP/7zip/UI/FileManager/PasswordDialog.cpp | 26 +- CPP/7zip/UI/FileManager/PasswordDialog.h | 11 +- CPP/7zip/UI/FileManager/PasswordDialog.rc | 8 +- CPP/7zip/UI/FileManager/PasswordDialogRes.h | 9 +- CPP/7zip/UI/FileManager/PluginInterface.h | 2 +- CPP/7zip/UI/FileManager/PluginLoader.h | 8 +- CPP/7zip/UI/FileManager/PluginsPage.cpp | 22 +- CPP/7zip/UI/FileManager/PluginsPage.h | 0 CPP/7zip/UI/FileManager/PluginsPage.rc | 0 CPP/7zip/UI/FileManager/PluginsPageRes.h | 8 +- CPP/7zip/UI/FileManager/ProgramLocation.cpp | 0 CPP/7zip/UI/FileManager/ProgramLocation.h | 0 CPP/7zip/UI/FileManager/ProgressDialog.cpp | 16 +- CPP/7zip/UI/FileManager/ProgressDialog.h | 12 +- CPP/7zip/UI/FileManager/ProgressDialog.rc | 2 +- CPP/7zip/UI/FileManager/ProgressDialog2.cpp | 995 ++-- CPP/7zip/UI/FileManager/ProgressDialog2.h | 307 +- CPP/7zip/UI/FileManager/ProgressDialog2.rc | 7 +- CPP/7zip/UI/FileManager/ProgressDialog2Res.h | 81 +- CPP/7zip/UI/FileManager/ProgressDialog2a.rc | 80 +- CPP/7zip/UI/FileManager/ProgressDialogRes.h | 4 +- CPP/7zip/UI/FileManager/PropertyName.cpp | 107 +- CPP/7zip/UI/FileManager/PropertyName.h | 6 +- CPP/7zip/UI/FileManager/PropertyName.rc | 135 +- CPP/7zip/UI/FileManager/PropertyNameRes.h | 143 +- CPP/7zip/UI/FileManager/RegistryAssociations.cpp | 20 +- CPP/7zip/UI/FileManager/RegistryAssociations.h | 2 +- CPP/7zip/UI/FileManager/RegistryPlugins.cpp | 8 +- CPP/7zip/UI/FileManager/RegistryPlugins.h | 2 +- CPP/7zip/UI/FileManager/RegistryUtils.cpp | 19 +- CPP/7zip/UI/FileManager/RegistryUtils.h | 17 +- CPP/7zip/UI/FileManager/RootFolder.cpp | 40 +- CPP/7zip/UI/FileManager/RootFolder.h | 2 +- CPP/7zip/UI/FileManager/SettingsPage.cpp | 86 +- CPP/7zip/UI/FileManager/SettingsPage.h | 8 +- CPP/7zip/UI/FileManager/SettingsPage.rc | 0 CPP/7zip/UI/FileManager/SettingsPage2.rc | 31 +- CPP/7zip/UI/FileManager/SettingsPageRes.h | 22 +- CPP/7zip/UI/FileManager/SplitDialog.cpp | 32 +- CPP/7zip/UI/FileManager/SplitDialog.h | 6 +- CPP/7zip/UI/FileManager/SplitDialog.rc | 12 +- CPP/7zip/UI/FileManager/SplitDialogRes.h | 13 +- CPP/7zip/UI/FileManager/SplitUtils.cpp | 87 +- CPP/7zip/UI/FileManager/SplitUtils.h | 14 +- CPP/7zip/UI/FileManager/StdAfx.cpp | 0 CPP/7zip/UI/FileManager/StdAfx.h | 18 +- CPP/7zip/UI/FileManager/StringUtils.cpp | 35 +- CPP/7zip/UI/FileManager/StringUtils.h | 6 +- CPP/7zip/UI/FileManager/SysIconUtils.cpp | 156 +- CPP/7zip/UI/FileManager/SysIconUtils.h | 30 +- CPP/7zip/UI/FileManager/SystemPage.cpp | 41 +- CPP/7zip/UI/FileManager/SystemPage.h | 14 +- CPP/7zip/UI/FileManager/SystemPage.rc | 34 +- CPP/7zip/UI/FileManager/SystemPageRes.h | 18 +- CPP/7zip/UI/FileManager/Test.bmp | Bin CPP/7zip/UI/FileManager/Test2.bmp | Bin CPP/7zip/UI/FileManager/TextPairs.cpp | 29 +- CPP/7zip/UI/FileManager/TextPairs.h | 13 +- CPP/7zip/UI/FileManager/UpdateCallback100.cpp | 25 +- CPP/7zip/UI/FileManager/UpdateCallback100.h | 2 +- CPP/7zip/UI/FileManager/ViewSettings.cpp | 360 +- CPP/7zip/UI/FileManager/ViewSettings.h | 67 +- CPP/7zip/UI/FileManager/makefile | 162 +- CPP/7zip/UI/FileManager/resource.h | 331 +- CPP/7zip/UI/FileManager/resource.rc | 195 +- CPP/7zip/UI/FileManager/resourceGui.h | 17 +- CPP/7zip/UI/FileManager/resourceGui.rc | 18 +- CPP/7zip/UI/GUI/7zG.exe.manifest | 0 CPP/7zip/UI/GUI/BenchmarkDialog.cpp | 313 +- CPP/7zip/UI/GUI/BenchmarkDialog.h | 25 +- CPP/7zip/UI/GUI/BenchmarkDialog.rc | 188 +- CPP/7zip/UI/GUI/BenchmarkDialogRes.h | 121 +- CPP/7zip/UI/GUI/CompressDialog.cpp | 719 ++- CPP/7zip/UI/GUI/CompressDialog.h | 64 +- CPP/7zip/UI/GUI/CompressDialog.rc | 206 +- CPP/7zip/UI/GUI/CompressDialogRes.h | 168 +- CPP/7zip/UI/GUI/Extract.rc | 63 +- CPP/7zip/UI/GUI/ExtractDialog.cpp | 360 +- CPP/7zip/UI/GUI/ExtractDialog.h | 48 +- CPP/7zip/UI/GUI/ExtractDialog.rc | 68 +- CPP/7zip/UI/GUI/ExtractDialogRes.h | 31 +- CPP/7zip/UI/GUI/ExtractGUI.cpp | 158 +- CPP/7zip/UI/GUI/ExtractGUI.h | 6 +- CPP/7zip/UI/GUI/ExtractRes.h | 73 +- CPP/7zip/UI/GUI/FM.ico | Bin CPP/7zip/UI/GUI/GUI.cpp | 229 +- CPP/7zip/UI/GUI/GUI.dsp | 144 +- CPP/7zip/UI/GUI/GUI.dsw | 0 CPP/7zip/UI/GUI/HashGUI.cpp | 278 + CPP/7zip/UI/GUI/HashGUI.h | 16 + CPP/7zip/UI/GUI/StdAfx.cpp | 0 CPP/7zip/UI/GUI/StdAfx.h | 16 +- CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp | 93 +- CPP/7zip/UI/GUI/UpdateCallbackGUI.h | 3 - CPP/7zip/UI/GUI/UpdateGUI.cpp | 219 +- CPP/7zip/UI/GUI/UpdateGUI.h | 4 +- CPP/7zip/UI/GUI/makefile | 73 +- CPP/7zip/UI/GUI/resource.rc | 8 +- CPP/7zip/UI/GUI/resource2.h | 5 +- CPP/7zip/UI/GUI/resource2.rc | 5 +- CPP/7zip/UI/makefile | 0 CPP/7zip/makefile | 0 CPP/Build.mak | 39 +- CPP/Common/AutoPtr.h | 0 CPP/Common/Buffer.h | 77 - CPP/Common/CRC.cpp | 0 CPP/Common/C_FileIO.cpp | 0 CPP/Common/C_FileIO.h | 2 +- CPP/Common/ComTry.h | 0 CPP/Common/CommandLineParser.cpp | 267 +- CPP/Common/CommandLineParser.h | 49 +- CPP/Common/Common.h | 13 + CPP/Common/CrcReg.cpp | 111 + CPP/Common/Defs.h | 0 CPP/Common/DynLimBuf.cpp | 100 + CPP/Common/DynLimBuf.h | 36 + CPP/Common/DynamicBuffer.h | 72 +- CPP/Common/IntToString.cpp | 149 +- CPP/Common/IntToString.h | 23 +- CPP/Common/Lang.cpp | 204 +- CPP/Common/Lang.h | 24 +- CPP/Common/ListFileUtils.cpp | 117 +- CPP/Common/ListFileUtils.h | 5 +- CPP/Common/MyBuffer.h | 237 + CPP/Common/MyCom.h | 63 +- CPP/Common/MyException.h | 0 CPP/Common/MyGuidDef.h | 2 +- CPP/Common/MyInitGuid.h | 0 CPP/Common/MyMap.cpp | 14 +- CPP/Common/MyMap.h | 4 +- CPP/Common/MyString.cpp | 1110 +++- CPP/Common/MyString.h | 842 ++- CPP/Common/MyTypes.h | 30 + CPP/Common/MyUnknown.h | 0 CPP/Common/MyVector.cpp | 84 - CPP/Common/MyVector.h | 575 +- CPP/Common/MyWindows.cpp | 24 +- CPP/Common/MyWindows.h | 15 +- CPP/Common/MyXml.cpp | 265 +- CPP/Common/MyXml.h | 23 +- CPP/Common/NewHandler.cpp | 64 +- CPP/Common/NewHandler.h | 56 +- CPP/Common/Random.cpp | 0 CPP/Common/Random.h | 0 CPP/Common/Sha256Reg.cpp | 52 + CPP/Common/StdAfx.h | 3 +- CPP/Common/StdInStream.cpp | 19 +- CPP/Common/StdInStream.h | 21 +- CPP/Common/StdOutStream.cpp | 58 +- CPP/Common/StdOutStream.h | 41 +- CPP/Common/StringConvert.cpp | 90 +- CPP/Common/StringConvert.h | 10 +- CPP/Common/StringToInt.cpp | 148 +- CPP/Common/StringToInt.h | 19 +- CPP/Common/TextConfig.cpp | 74 +- CPP/Common/TextConfig.h | 7 +- CPP/Common/Types.h | 11 - CPP/Common/UTFConvert.cpp | 59 +- CPP/Common/UTFConvert.h | 5 +- CPP/Common/Wildcard.cpp | 385 +- CPP/Common/Wildcard.h | 101 +- CPP/Common/XzCrc64Reg.cpp | 54 + CPP/Windows/COM.cpp | 0 CPP/Windows/COM.h | 3 +- CPP/Windows/Clipboard.cpp | 24 +- CPP/Windows/Clipboard.h | 8 +- CPP/Windows/CommonDialog.cpp | 239 +- CPP/Windows/CommonDialog.h | 12 +- CPP/Windows/Console.cpp | 0 CPP/Windows/Console.h | 50 +- CPP/Windows/Control/ComboBox.cpp | 6 +- CPP/Windows/Control/ComboBox.h | 2 + CPP/Windows/Control/CommandBar.h | 4 +- CPP/Windows/Control/Dialog.cpp | 52 +- CPP/Windows/Control/Dialog.h | 58 +- CPP/Windows/Control/Edit.h | 2 +- CPP/Windows/Control/ImageList.cpp | 0 CPP/Windows/Control/ImageList.h | 2 +- CPP/Windows/Control/ListView.cpp | 2 +- CPP/Windows/Control/ListView.h | 2 +- CPP/Windows/Control/ProgressBar.h | 0 CPP/Windows/Control/PropertyPage.cpp | 5 +- CPP/Windows/Control/PropertyPage.h | 0 CPP/Windows/Control/ReBar.h | 7 +- CPP/Windows/Control/Static.h | 0 CPP/Windows/Control/StatusBar.h | 21 +- CPP/Windows/Control/StdAfx.h | 3 +- CPP/Windows/Control/ToolBar.h | 2 +- CPP/Windows/Control/Trackbar.h | 6 +- CPP/Windows/Control/Window2.cpp | 101 +- CPP/Windows/Control/Window2.h | 25 +- CPP/Windows/DLL.cpp | 7 +- CPP/Windows/DLL.h | 6 +- CPP/Windows/Defs.h | 0 CPP/Windows/Error.cpp | 60 - CPP/Windows/Error.h | 15 - CPP/Windows/ErrorMsg.cpp | 61 + CPP/Windows/ErrorMsg.h | 15 + CPP/Windows/FileDir.cpp | 352 +- CPP/Windows/FileDir.h | 55 +- CPP/Windows/FileFind.cpp | 317 +- CPP/Windows/FileFind.h | 62 +- CPP/Windows/FileIO.cpp | 293 +- CPP/Windows/FileIO.h | 176 +- CPP/Windows/FileLink.cpp | 426 ++ CPP/Windows/FileMapping.cpp | 0 CPP/Windows/FileMapping.h | 8 +- CPP/Windows/FileName.cpp | 664 ++- CPP/Windows/FileName.h | 57 + CPP/Windows/FileSystem.cpp | 22 +- CPP/Windows/FileSystem.h | 2 +- CPP/Windows/Handle.h | 0 CPP/Windows/Memory.cpp | 36 - CPP/Windows/Memory.h | 53 - CPP/Windows/MemoryGlobal.cpp | 36 + CPP/Windows/MemoryGlobal.h | 53 + CPP/Windows/MemoryLock.cpp | 98 +- CPP/Windows/MemoryLock.h | 27 +- CPP/Windows/Menu.cpp | 29 +- CPP/Windows/Menu.h | 5 +- CPP/Windows/NationalTime.cpp | 0 CPP/Windows/NationalTime.h | 0 CPP/Windows/Net.cpp | 24 +- CPP/Windows/Net.h | 3 +- CPP/Windows/NtCheck.h | 0 CPP/Windows/Process.cpp | 81 - CPP/Windows/Process.h | 100 - CPP/Windows/ProcessMessages.cpp | 0 CPP/Windows/ProcessMessages.h | 0 CPP/Windows/ProcessUtils.cpp | 86 + CPP/Windows/ProcessUtils.h | 100 + CPP/Windows/PropVariant.cpp | 83 +- CPP/Windows/PropVariant.h | 97 +- CPP/Windows/PropVariantConv.cpp | 99 + CPP/Windows/PropVariantConv.h | 30 + CPP/Windows/PropVariantConversions.cpp | 105 - CPP/Windows/PropVariantConversions.h | 14 - CPP/Windows/PropVariantUtils.cpp | 50 +- CPP/Windows/PropVariantUtils.h | 11 +- CPP/Windows/Registry.cpp | 33 +- CPP/Windows/Registry.h | 41 +- CPP/Windows/ResourceString.cpp | 85 +- CPP/Windows/ResourceString.h | 18 +- CPP/Windows/Security.cpp | 179 - CPP/Windows/Security.h | 167 - CPP/Windows/SecurityUtils.cpp | 179 + CPP/Windows/SecurityUtils.h | 167 + CPP/Windows/Shell.cpp | 17 +- CPP/Windows/Shell.h | 5 +- CPP/Windows/StdAfx.h | 3 +- CPP/Windows/Synchronization.cpp | 0 CPP/Windows/Synchronization.h | 0 CPP/Windows/System.cpp | 0 CPP/Windows/System.h | 2 +- CPP/Windows/Thread.h | 0 CPP/Windows/Time.cpp | 203 - CPP/Windows/Time.h | 23 - CPP/Windows/TimeUtils.cpp | 209 + CPP/Windows/TimeUtils.h | 23 + CPP/Windows/Window.cpp | 4 +- CPP/Windows/Window.h | 26 +- DOC/7zC.txt | 13 +- DOC/7zFormat.txt | 0 DOC/7zip.hhp | 17 +- DOC/7zip.inf | 4 +- DOC/7zip.nsi | 203 +- DOC/7zip.wxs | 15 +- DOC/License.txt | 0 DOC/Methods.txt | 46 +- DOC/copying.txt | 0 DOC/history.txt | 12 + DOC/lzma.txt | 20 +- DOC/readme.txt | 4 +- DOC/unRarLicense.txt | 0 1179 files changed, 79402 insertions(+), 38033 deletions(-) mode change 100755 => 100644 Asm/arm/7zCrcOpt.asm mode change 100755 => 100644 Asm/x86/7zAsm.asm mode change 100755 => 100644 Asm/x86/7zCrcOpt.asm mode change 100755 => 100644 Asm/x86/AesOpt.asm create mode 100644 Asm/x86/XzCrc64Opt.asm mode change 100755 => 100644 C/7z.h mode change 100755 => 100644 C/7zAlloc.c mode change 100755 => 100644 C/7zAlloc.h create mode 100644 C/7zArcIn.c mode change 100755 => 100644 C/7zBuf.c mode change 100755 => 100644 C/7zBuf.h mode change 100755 => 100644 C/7zBuf2.c mode change 100755 => 100644 C/7zCrc.c mode change 100755 => 100644 C/7zCrc.h mode change 100755 => 100644 C/7zCrcOpt.c mode change 100755 => 100644 C/7zDec.c mode change 100755 => 100644 C/7zFile.c mode change 100755 => 100644 C/7zFile.h delete mode 100755 C/7zIn.c mode change 100755 => 100644 C/7zStream.c create mode 100644 C/7zTypes.h mode change 100755 => 100644 C/7zVersion.h mode change 100755 => 100644 C/7zVersion.rc mode change 100755 => 100644 C/Aes.c mode change 100755 => 100644 C/Aes.h mode change 100755 => 100644 C/AesOpt.c mode change 100755 => 100644 C/Alloc.c mode change 100755 => 100644 C/Alloc.h mode change 100755 => 100644 C/Bcj2.c mode change 100755 => 100644 C/Bcj2.h mode change 100755 => 100644 C/Bra.c mode change 100755 => 100644 C/Bra.h mode change 100755 => 100644 C/Bra86.c mode change 100755 => 100644 C/BraIA64.c mode change 100755 => 100644 C/BwtSort.c mode change 100755 => 100644 C/BwtSort.h create mode 100644 C/Compiler.h mode change 100755 => 100644 C/CpuArch.c mode change 100755 => 100644 C/CpuArch.h mode change 100755 => 100644 C/Delta.c mode change 100755 => 100644 C/Delta.h mode change 100755 => 100644 C/HuffEnc.c mode change 100755 => 100644 C/HuffEnc.h mode change 100755 => 100644 C/LzFind.c mode change 100755 => 100644 C/LzFind.h mode change 100755 => 100644 C/LzFindMt.c mode change 100755 => 100644 C/LzFindMt.h mode change 100755 => 100644 C/LzHash.h mode change 100755 => 100644 C/Lzma2Dec.c mode change 100755 => 100644 C/Lzma2Dec.h mode change 100755 => 100644 C/Lzma2Enc.c mode change 100755 => 100644 C/Lzma2Enc.h mode change 100755 => 100644 C/Lzma86.h mode change 100755 => 100644 C/Lzma86Dec.c mode change 100755 => 100644 C/Lzma86Enc.c mode change 100755 => 100644 C/LzmaDec.c mode change 100755 => 100644 C/LzmaDec.h mode change 100755 => 100644 C/LzmaEnc.c mode change 100755 => 100644 C/LzmaEnc.h mode change 100755 => 100644 C/LzmaLib.c mode change 100755 => 100644 C/LzmaLib.h mode change 100755 => 100644 C/MtCoder.c mode change 100755 => 100644 C/MtCoder.h mode change 100755 => 100644 C/Ppmd.h mode change 100755 => 100644 C/Ppmd7.c mode change 100755 => 100644 C/Ppmd7.h mode change 100755 => 100644 C/Ppmd7Dec.c mode change 100755 => 100644 C/Ppmd7Enc.c mode change 100755 => 100644 C/Ppmd8.c mode change 100755 => 100644 C/Ppmd8.h mode change 100755 => 100644 C/Ppmd8Dec.c mode change 100755 => 100644 C/Ppmd8Enc.c create mode 100644 C/Precomp.h mode change 100755 => 100644 C/RotateDefs.h mode change 100755 => 100644 C/Sha256.c mode change 100755 => 100644 C/Sha256.h mode change 100755 => 100644 C/Sort.c mode change 100755 => 100644 C/Sort.h mode change 100755 => 100644 C/Threads.c mode change 100755 => 100644 C/Threads.h delete mode 100755 C/Types.h mode change 100755 => 100644 C/Util/7z/7z.dsp mode change 100755 => 100644 C/Util/7z/7z.dsw mode change 100755 => 100644 C/Util/7z/7zMain.c create mode 100644 C/Util/7z/Precomp.c create mode 100644 C/Util/7z/Precomp.h mode change 100755 => 100644 C/Util/7z/makefile mode change 100755 => 100644 C/Util/7z/makefile.gcc mode change 100755 => 100644 C/Util/Lzma/LzmaUtil.c mode change 100755 => 100644 C/Util/Lzma/LzmaUtil.dsp mode change 100755 => 100644 C/Util/Lzma/LzmaUtil.dsw mode change 100755 => 100644 C/Util/Lzma/makefile mode change 100755 => 100644 C/Util/Lzma/makefile.gcc mode change 100755 => 100644 C/Util/LzmaLib/LzmaLib.def mode change 100755 => 100644 C/Util/LzmaLib/LzmaLib.dsp mode change 100755 => 100644 C/Util/LzmaLib/LzmaLib.dsw mode change 100755 => 100644 C/Util/LzmaLib/LzmaLibExports.c mode change 100755 => 100644 C/Util/LzmaLib/makefile mode change 100755 => 100644 C/Util/LzmaLib/resource.rc create mode 100644 C/Util/SfxSetup/Precomp.c create mode 100644 C/Util/SfxSetup/Precomp.h mode change 100755 => 100644 C/Util/SfxSetup/SfxSetup.c mode change 100755 => 100644 C/Util/SfxSetup/SfxSetup.dsp mode change 100755 => 100644 C/Util/SfxSetup/SfxSetup.dsw mode change 100755 => 100644 C/Util/SfxSetup/makefile mode change 100755 => 100644 C/Util/SfxSetup/makefile_con mode change 100755 => 100644 C/Util/SfxSetup/resource.rc mode change 100755 => 100644 C/Util/SfxSetup/setup.ico mode change 100755 => 100644 C/Xz.c mode change 100755 => 100644 C/Xz.h mode change 100755 => 100644 C/XzCrc64.c mode change 100755 => 100644 C/XzCrc64.h create mode 100644 C/XzCrc64Opt.c mode change 100755 => 100644 C/XzDec.c mode change 100755 => 100644 C/XzEnc.c mode change 100755 => 100644 C/XzEnc.h mode change 100755 => 100644 C/XzIn.c create mode 100644 CPP/7zip/7zip.mak mode change 100755 => 100644 CPP/7zip/Aes.mak mode change 100755 => 100644 CPP/7zip/Archive/7z/7z.dsp mode change 100755 => 100644 CPP/7zip/Archive/7z/7z.dsw mode change 100755 => 100644 CPP/7zip/Archive/7z/7zCompressionMode.cpp mode change 100755 => 100644 CPP/7zip/Archive/7z/7zCompressionMode.h mode change 100755 => 100644 CPP/7zip/Archive/7z/7zDecode.cpp mode change 100755 => 100644 CPP/7zip/Archive/7z/7zDecode.h mode change 100755 => 100644 CPP/7zip/Archive/7z/7zEncode.cpp mode change 100755 => 100644 CPP/7zip/Archive/7z/7zEncode.h mode change 100755 => 100644 CPP/7zip/Archive/7z/7zExtract.cpp mode change 100755 => 100644 CPP/7zip/Archive/7z/7zFolderInStream.cpp mode change 100755 => 100644 CPP/7zip/Archive/7z/7zFolderInStream.h mode change 100755 => 100644 CPP/7zip/Archive/7z/7zFolderOutStream.cpp mode change 100755 => 100644 CPP/7zip/Archive/7z/7zFolderOutStream.h mode change 100755 => 100644 CPP/7zip/Archive/7z/7zHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/7z/7zHandler.h mode change 100755 => 100644 CPP/7zip/Archive/7z/7zHandlerOut.cpp mode change 100755 => 100644 CPP/7zip/Archive/7z/7zHeader.cpp mode change 100755 => 100644 CPP/7zip/Archive/7z/7zHeader.h mode change 100755 => 100644 CPP/7zip/Archive/7z/7zIn.cpp mode change 100755 => 100644 CPP/7zip/Archive/7z/7zIn.h mode change 100755 => 100644 CPP/7zip/Archive/7z/7zItem.h mode change 100755 => 100644 CPP/7zip/Archive/7z/7zOut.cpp mode change 100755 => 100644 CPP/7zip/Archive/7z/7zOut.h mode change 100755 => 100644 CPP/7zip/Archive/7z/7zProperties.cpp mode change 100755 => 100644 CPP/7zip/Archive/7z/7zProperties.h mode change 100755 => 100644 CPP/7zip/Archive/7z/7zRegister.cpp mode change 100755 => 100644 CPP/7zip/Archive/7z/7zSpecStream.cpp mode change 100755 => 100644 CPP/7zip/Archive/7z/7zSpecStream.h mode change 100755 => 100644 CPP/7zip/Archive/7z/7zUpdate.cpp mode change 100755 => 100644 CPP/7zip/Archive/7z/7zUpdate.h mode change 100755 => 100644 CPP/7zip/Archive/7z/StdAfx.cpp mode change 100755 => 100644 CPP/7zip/Archive/7z/StdAfx.h mode change 100755 => 100644 CPP/7zip/Archive/7z/makefile mode change 100755 => 100644 CPP/7zip/Archive/7z/resource.rc mode change 100755 => 100644 CPP/7zip/Archive/ApmHandler.cpp create mode 100644 CPP/7zip/Archive/ArHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/Archive.def mode change 100755 => 100644 CPP/7zip/Archive/Archive2.def mode change 100755 => 100644 CPP/7zip/Archive/ArchiveExports.cpp mode change 100755 => 100644 CPP/7zip/Archive/ArjHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/Bz2Handler.cpp mode change 100755 => 100644 CPP/7zip/Archive/Cab/CabBlockInStream.cpp mode change 100755 => 100644 CPP/7zip/Archive/Cab/CabBlockInStream.h mode change 100755 => 100644 CPP/7zip/Archive/Cab/CabHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/Cab/CabHandler.h mode change 100755 => 100644 CPP/7zip/Archive/Cab/CabHeader.cpp mode change 100755 => 100644 CPP/7zip/Archive/Cab/CabHeader.h mode change 100755 => 100644 CPP/7zip/Archive/Cab/CabIn.cpp mode change 100755 => 100644 CPP/7zip/Archive/Cab/CabIn.h mode change 100755 => 100644 CPP/7zip/Archive/Cab/CabItem.h mode change 100755 => 100644 CPP/7zip/Archive/Cab/CabRegister.cpp mode change 100755 => 100644 CPP/7zip/Archive/Cab/StdAfx.h mode change 100755 => 100644 CPP/7zip/Archive/Chm/ChmHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/Chm/ChmHandler.h delete mode 100755 CPP/7zip/Archive/Chm/ChmHeader.cpp delete mode 100755 CPP/7zip/Archive/Chm/ChmHeader.h mode change 100755 => 100644 CPP/7zip/Archive/Chm/ChmIn.cpp mode change 100755 => 100644 CPP/7zip/Archive/Chm/ChmIn.h delete mode 100755 CPP/7zip/Archive/Chm/ChmRegister.cpp mode change 100755 => 100644 CPP/7zip/Archive/Chm/StdAfx.h delete mode 100755 CPP/7zip/Archive/Com/ComHandler.cpp delete mode 100755 CPP/7zip/Archive/Com/ComHandler.h delete mode 100755 CPP/7zip/Archive/Com/ComIn.cpp delete mode 100755 CPP/7zip/Archive/Com/ComIn.h delete mode 100755 CPP/7zip/Archive/Com/ComRegister.cpp create mode 100644 CPP/7zip/Archive/ComHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/Common/CoderMixer.cpp mode change 100755 => 100644 CPP/7zip/Archive/Common/CoderMixer.h mode change 100755 => 100644 CPP/7zip/Archive/Common/CoderMixer2.cpp mode change 100755 => 100644 CPP/7zip/Archive/Common/CoderMixer2.h mode change 100755 => 100644 CPP/7zip/Archive/Common/CoderMixer2MT.cpp mode change 100755 => 100644 CPP/7zip/Archive/Common/CoderMixer2MT.h mode change 100755 => 100644 CPP/7zip/Archive/Common/CoderMixer2ST.cpp mode change 100755 => 100644 CPP/7zip/Archive/Common/CoderMixer2ST.h mode change 100755 => 100644 CPP/7zip/Archive/Common/CoderMixerMT.cpp mode change 100755 => 100644 CPP/7zip/Archive/Common/CoderMixerMT.h mode change 100755 => 100644 CPP/7zip/Archive/Common/CrossThreadProgress.cpp mode change 100755 => 100644 CPP/7zip/Archive/Common/CrossThreadProgress.h mode change 100755 => 100644 CPP/7zip/Archive/Common/DummyOutStream.cpp mode change 100755 => 100644 CPP/7zip/Archive/Common/DummyOutStream.h mode change 100755 => 100644 CPP/7zip/Archive/Common/FindSignature.cpp mode change 100755 => 100644 CPP/7zip/Archive/Common/FindSignature.h mode change 100755 => 100644 CPP/7zip/Archive/Common/HandlerOut.cpp mode change 100755 => 100644 CPP/7zip/Archive/Common/HandlerOut.h mode change 100755 => 100644 CPP/7zip/Archive/Common/InStreamWithCRC.cpp mode change 100755 => 100644 CPP/7zip/Archive/Common/InStreamWithCRC.h mode change 100755 => 100644 CPP/7zip/Archive/Common/ItemNameUtils.cpp mode change 100755 => 100644 CPP/7zip/Archive/Common/ItemNameUtils.h mode change 100755 => 100644 CPP/7zip/Archive/Common/MultiStream.cpp mode change 100755 => 100644 CPP/7zip/Archive/Common/MultiStream.h mode change 100755 => 100644 CPP/7zip/Archive/Common/OutStreamWithCRC.cpp mode change 100755 => 100644 CPP/7zip/Archive/Common/OutStreamWithCRC.h mode change 100755 => 100644 CPP/7zip/Archive/Common/OutStreamWithSha1.cpp mode change 100755 => 100644 CPP/7zip/Archive/Common/OutStreamWithSha1.h mode change 100755 => 100644 CPP/7zip/Archive/Common/ParseProperties.cpp mode change 100755 => 100644 CPP/7zip/Archive/Common/ParseProperties.h mode change 100755 => 100644 CPP/7zip/Archive/Common/StdAfx.h mode change 100755 => 100644 CPP/7zip/Archive/CpioHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/CramfsHandler.cpp delete mode 100755 CPP/7zip/Archive/DebHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/DeflateProps.cpp mode change 100755 => 100644 CPP/7zip/Archive/DeflateProps.h mode change 100755 => 100644 CPP/7zip/Archive/DllExports.cpp mode change 100755 => 100644 CPP/7zip/Archive/DllExports2.cpp mode change 100755 => 100644 CPP/7zip/Archive/DmgHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/ElfHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/FatHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/FlvHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/GzHandler.cpp delete mode 100755 CPP/7zip/Archive/Hfs/HfsHandler.cpp delete mode 100755 CPP/7zip/Archive/Hfs/HfsHandler.h delete mode 100755 CPP/7zip/Archive/Hfs/HfsIn.cpp delete mode 100755 CPP/7zip/Archive/Hfs/HfsIn.h delete mode 100755 CPP/7zip/Archive/Hfs/HfsRegister.cpp create mode 100644 CPP/7zip/Archive/HfsHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/IArchive.h mode change 100755 => 100644 CPP/7zip/Archive/Icons/7z.ico mode change 100755 => 100644 CPP/7zip/Archive/Icons/arj.ico mode change 100755 => 100644 CPP/7zip/Archive/Icons/bz2.ico mode change 100755 => 100644 CPP/7zip/Archive/Icons/cab.ico mode change 100755 => 100644 CPP/7zip/Archive/Icons/cpio.ico mode change 100755 => 100644 CPP/7zip/Archive/Icons/deb.ico mode change 100755 => 100644 CPP/7zip/Archive/Icons/dmg.ico mode change 100755 => 100644 CPP/7zip/Archive/Icons/fat.ico mode change 100755 => 100644 CPP/7zip/Archive/Icons/gz.ico mode change 100755 => 100644 CPP/7zip/Archive/Icons/hfs.ico mode change 100755 => 100644 CPP/7zip/Archive/Icons/iso.ico mode change 100755 => 100644 CPP/7zip/Archive/Icons/lzh.ico mode change 100755 => 100644 CPP/7zip/Archive/Icons/lzma.ico mode change 100755 => 100644 CPP/7zip/Archive/Icons/ntfs.ico mode change 100755 => 100644 CPP/7zip/Archive/Icons/rar.ico mode change 100755 => 100644 CPP/7zip/Archive/Icons/rpm.ico mode change 100755 => 100644 CPP/7zip/Archive/Icons/split.ico mode change 100755 => 100644 CPP/7zip/Archive/Icons/squashfs.ico mode change 100755 => 100644 CPP/7zip/Archive/Icons/tar.ico mode change 100755 => 100644 CPP/7zip/Archive/Icons/vhd.ico mode change 100755 => 100644 CPP/7zip/Archive/Icons/wim.ico mode change 100755 => 100644 CPP/7zip/Archive/Icons/xar.ico mode change 100755 => 100644 CPP/7zip/Archive/Icons/xz.ico mode change 100755 => 100644 CPP/7zip/Archive/Icons/z.ico mode change 100755 => 100644 CPP/7zip/Archive/Icons/zip.ico create mode 100644 CPP/7zip/Archive/IhexHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/Iso/IsoHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/Iso/IsoHandler.h mode change 100755 => 100644 CPP/7zip/Archive/Iso/IsoHeader.cpp mode change 100755 => 100644 CPP/7zip/Archive/Iso/IsoHeader.h mode change 100755 => 100644 CPP/7zip/Archive/Iso/IsoIn.cpp mode change 100755 => 100644 CPP/7zip/Archive/Iso/IsoIn.h mode change 100755 => 100644 CPP/7zip/Archive/Iso/IsoItem.h mode change 100755 => 100644 CPP/7zip/Archive/Iso/IsoRegister.cpp mode change 100755 => 100644 CPP/7zip/Archive/Iso/StdAfx.h mode change 100755 => 100644 CPP/7zip/Archive/LzhHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/LzmaHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/MachoHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/MbrHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/MslzHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/MubHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/Nsis/NsisDecode.cpp mode change 100755 => 100644 CPP/7zip/Archive/Nsis/NsisDecode.h mode change 100755 => 100644 CPP/7zip/Archive/Nsis/NsisHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/Nsis/NsisHandler.h mode change 100755 => 100644 CPP/7zip/Archive/Nsis/NsisIn.cpp mode change 100755 => 100644 CPP/7zip/Archive/Nsis/NsisIn.h mode change 100755 => 100644 CPP/7zip/Archive/Nsis/NsisRegister.cpp mode change 100755 => 100644 CPP/7zip/Archive/Nsis/StdAfx.h mode change 100755 => 100644 CPP/7zip/Archive/NtfsHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/PeHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/PpmdHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/Rar/RarHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/Rar/RarHandler.h delete mode 100755 CPP/7zip/Archive/Rar/RarHeader.cpp mode change 100755 => 100644 CPP/7zip/Archive/Rar/RarHeader.h delete mode 100755 CPP/7zip/Archive/Rar/RarIn.cpp delete mode 100755 CPP/7zip/Archive/Rar/RarIn.h delete mode 100755 CPP/7zip/Archive/Rar/RarItem.cpp mode change 100755 => 100644 CPP/7zip/Archive/Rar/RarItem.h delete mode 100755 CPP/7zip/Archive/Rar/RarRegister.cpp delete mode 100755 CPP/7zip/Archive/Rar/RarVolumeInStream.cpp delete mode 100755 CPP/7zip/Archive/Rar/RarVolumeInStream.h mode change 100755 => 100644 CPP/7zip/Archive/Rar/StdAfx.cpp mode change 100755 => 100644 CPP/7zip/Archive/Rar/StdAfx.h mode change 100755 => 100644 CPP/7zip/Archive/RpmHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/SplitHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/SquashfsHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/StdAfx.h mode change 100755 => 100644 CPP/7zip/Archive/SwfHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/Tar/StdAfx.h mode change 100755 => 100644 CPP/7zip/Archive/Tar/TarHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/Tar/TarHandler.h mode change 100755 => 100644 CPP/7zip/Archive/Tar/TarHandlerOut.cpp mode change 100755 => 100644 CPP/7zip/Archive/Tar/TarHeader.cpp mode change 100755 => 100644 CPP/7zip/Archive/Tar/TarHeader.h mode change 100755 => 100644 CPP/7zip/Archive/Tar/TarIn.cpp mode change 100755 => 100644 CPP/7zip/Archive/Tar/TarIn.h mode change 100755 => 100644 CPP/7zip/Archive/Tar/TarItem.h mode change 100755 => 100644 CPP/7zip/Archive/Tar/TarOut.cpp mode change 100755 => 100644 CPP/7zip/Archive/Tar/TarOut.h mode change 100755 => 100644 CPP/7zip/Archive/Tar/TarRegister.cpp mode change 100755 => 100644 CPP/7zip/Archive/Tar/TarUpdate.cpp mode change 100755 => 100644 CPP/7zip/Archive/Tar/TarUpdate.h mode change 100755 => 100644 CPP/7zip/Archive/Udf/StdAfx.h mode change 100755 => 100644 CPP/7zip/Archive/Udf/UdfHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/Udf/UdfHandler.h mode change 100755 => 100644 CPP/7zip/Archive/Udf/UdfIn.cpp mode change 100755 => 100644 CPP/7zip/Archive/Udf/UdfIn.h mode change 100755 => 100644 CPP/7zip/Archive/Udf/UdfRegister.cpp mode change 100755 => 100644 CPP/7zip/Archive/UefiHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/VhdHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/Wim/StdAfx.h mode change 100755 => 100644 CPP/7zip/Archive/Wim/WimHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/Wim/WimHandler.h mode change 100755 => 100644 CPP/7zip/Archive/Wim/WimHandlerOut.cpp mode change 100755 => 100644 CPP/7zip/Archive/Wim/WimIn.cpp mode change 100755 => 100644 CPP/7zip/Archive/Wim/WimIn.h mode change 100755 => 100644 CPP/7zip/Archive/Wim/WimRegister.cpp mode change 100755 => 100644 CPP/7zip/Archive/XarHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/XzHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/ZHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/Zip/StdAfx.h mode change 100755 => 100644 CPP/7zip/Archive/Zip/ZipAddCommon.cpp mode change 100755 => 100644 CPP/7zip/Archive/Zip/ZipAddCommon.h mode change 100755 => 100644 CPP/7zip/Archive/Zip/ZipCompressionMode.h mode change 100755 => 100644 CPP/7zip/Archive/Zip/ZipHandler.cpp mode change 100755 => 100644 CPP/7zip/Archive/Zip/ZipHandler.h mode change 100755 => 100644 CPP/7zip/Archive/Zip/ZipHandlerOut.cpp delete mode 100755 CPP/7zip/Archive/Zip/ZipHeader.cpp mode change 100755 => 100644 CPP/7zip/Archive/Zip/ZipHeader.h mode change 100755 => 100644 CPP/7zip/Archive/Zip/ZipIn.cpp mode change 100755 => 100644 CPP/7zip/Archive/Zip/ZipIn.h mode change 100755 => 100644 CPP/7zip/Archive/Zip/ZipItem.cpp mode change 100755 => 100644 CPP/7zip/Archive/Zip/ZipItem.h delete mode 100755 CPP/7zip/Archive/Zip/ZipItemEx.h mode change 100755 => 100644 CPP/7zip/Archive/Zip/ZipOut.cpp mode change 100755 => 100644 CPP/7zip/Archive/Zip/ZipOut.h mode change 100755 => 100644 CPP/7zip/Archive/Zip/ZipRegister.cpp mode change 100755 => 100644 CPP/7zip/Archive/Zip/ZipUpdate.cpp mode change 100755 => 100644 CPP/7zip/Archive/Zip/ZipUpdate.h mode change 100755 => 100644 CPP/7zip/Archive/makefile mode change 100755 => 100644 CPP/7zip/Asm.mak mode change 100755 => 100644 CPP/7zip/Bundles/Alone/Alone.dsp mode change 100755 => 100644 CPP/7zip/Bundles/Alone/Alone.dsw mode change 100755 => 100644 CPP/7zip/Bundles/Alone/StdAfx.cpp mode change 100755 => 100644 CPP/7zip/Bundles/Alone/StdAfx.h mode change 100755 => 100644 CPP/7zip/Bundles/Alone/afxres.h mode change 100755 => 100644 CPP/7zip/Bundles/Alone/makefile mode change 100755 => 100644 CPP/7zip/Bundles/Alone/resource.rc mode change 100755 => 100644 CPP/7zip/Bundles/Alone7z/StdAfx.cpp mode change 100755 => 100644 CPP/7zip/Bundles/Alone7z/StdAfx.h mode change 100755 => 100644 CPP/7zip/Bundles/Alone7z/makefile mode change 100755 => 100644 CPP/7zip/Bundles/Alone7z/resource.rc mode change 100755 => 100644 CPP/7zip/Bundles/Fm/FM.dsp mode change 100755 => 100644 CPP/7zip/Bundles/Fm/FM.dsw mode change 100755 => 100644 CPP/7zip/Bundles/Fm/StdAfx.cpp mode change 100755 => 100644 CPP/7zip/Bundles/Fm/StdAfx.h mode change 100755 => 100644 CPP/7zip/Bundles/Fm/makefile mode change 100755 => 100644 CPP/7zip/Bundles/Fm/resource.rc mode change 100755 => 100644 CPP/7zip/Bundles/Format7z/StdAfx.cpp mode change 100755 => 100644 CPP/7zip/Bundles/Format7z/StdAfx.h mode change 100755 => 100644 CPP/7zip/Bundles/Format7z/makefile mode change 100755 => 100644 CPP/7zip/Bundles/Format7z/resource.rc mode change 100755 => 100644 CPP/7zip/Bundles/Format7zExtract/StdAfx.cpp mode change 100755 => 100644 CPP/7zip/Bundles/Format7zExtract/StdAfx.h mode change 100755 => 100644 CPP/7zip/Bundles/Format7zExtract/makefile mode change 100755 => 100644 CPP/7zip/Bundles/Format7zExtract/resource.rc mode change 100755 => 100644 CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp mode change 100755 => 100644 CPP/7zip/Bundles/Format7zExtractR/StdAfx.h mode change 100755 => 100644 CPP/7zip/Bundles/Format7zExtractR/makefile mode change 100755 => 100644 CPP/7zip/Bundles/Format7zExtractR/resource.rc create mode 100644 CPP/7zip/Bundles/Format7zF/Arc.mak mode change 100755 => 100644 CPP/7zip/Bundles/Format7zF/Format7z.dsp mode change 100755 => 100644 CPP/7zip/Bundles/Format7zF/Format7z.dsw mode change 100755 => 100644 CPP/7zip/Bundles/Format7zF/StdAfx.cpp mode change 100755 => 100644 CPP/7zip/Bundles/Format7zF/StdAfx.h mode change 100755 => 100644 CPP/7zip/Bundles/Format7zF/makefile mode change 100755 => 100644 CPP/7zip/Bundles/Format7zF/resource.rc mode change 100755 => 100644 CPP/7zip/Bundles/Format7zR/StdAfx.cpp mode change 100755 => 100644 CPP/7zip/Bundles/Format7zR/StdAfx.h mode change 100755 => 100644 CPP/7zip/Bundles/Format7zR/makefile mode change 100755 => 100644 CPP/7zip/Bundles/Format7zR/resource.rc mode change 100755 => 100644 CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp mode change 100755 => 100644 CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp mode change 100755 => 100644 CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw mode change 100755 => 100644 CPP/7zip/Bundles/LzmaCon/StdAfx.cpp mode change 100755 => 100644 CPP/7zip/Bundles/LzmaCon/StdAfx.h mode change 100755 => 100644 CPP/7zip/Bundles/LzmaCon/makefile mode change 100755 => 100644 CPP/7zip/Bundles/LzmaCon/makefile.gcc create mode 100644 CPP/7zip/Bundles/LzmaCon/resource.rc mode change 100755 => 100644 CPP/7zip/Bundles/SFXCon/7z.ico delete mode 100755 CPP/7zip/Bundles/SFXCon/Main.cpp mode change 100755 => 100644 CPP/7zip/Bundles/SFXCon/SFXCon.dsp mode change 100755 => 100644 CPP/7zip/Bundles/SFXCon/SFXCon.dsw create mode 100644 CPP/7zip/Bundles/SFXCon/SfxCon.cpp mode change 100755 => 100644 CPP/7zip/Bundles/SFXCon/StdAfx.cpp mode change 100755 => 100644 CPP/7zip/Bundles/SFXCon/StdAfx.h mode change 100755 => 100644 CPP/7zip/Bundles/SFXCon/makefile mode change 100755 => 100644 CPP/7zip/Bundles/SFXCon/resource.rc delete mode 100755 CPP/7zip/Bundles/SFXSetup/ExtractCallback.cpp delete mode 100755 CPP/7zip/Bundles/SFXSetup/ExtractCallback.h create mode 100644 CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp create mode 100644 CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.h mode change 100755 => 100644 CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp mode change 100755 => 100644 CPP/7zip/Bundles/SFXSetup/ExtractEngine.h delete mode 100755 CPP/7zip/Bundles/SFXSetup/Main.cpp mode change 100755 => 100644 CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp mode change 100755 => 100644 CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw create mode 100644 CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp mode change 100755 => 100644 CPP/7zip/Bundles/SFXSetup/StdAfx.cpp mode change 100755 => 100644 CPP/7zip/Bundles/SFXSetup/StdAfx.h mode change 100755 => 100644 CPP/7zip/Bundles/SFXSetup/makefile mode change 100755 => 100644 CPP/7zip/Bundles/SFXSetup/resource.h mode change 100755 => 100644 CPP/7zip/Bundles/SFXSetup/resource.rc mode change 100755 => 100644 CPP/7zip/Bundles/SFXSetup/setup.ico mode change 100755 => 100644 CPP/7zip/Bundles/SFXWin/7z.ico delete mode 100755 CPP/7zip/Bundles/SFXWin/Main.cpp mode change 100755 => 100644 CPP/7zip/Bundles/SFXWin/SFXWin.dsp mode change 100755 => 100644 CPP/7zip/Bundles/SFXWin/SFXWin.dsw create mode 100644 CPP/7zip/Bundles/SFXWin/SfxWin.cpp mode change 100755 => 100644 CPP/7zip/Bundles/SFXWin/StdAfx.cpp mode change 100755 => 100644 CPP/7zip/Bundles/SFXWin/StdAfx.h mode change 100755 => 100644 CPP/7zip/Bundles/SFXWin/makefile mode change 100755 => 100644 CPP/7zip/Bundles/SFXWin/resource.h mode change 100755 => 100644 CPP/7zip/Bundles/SFXWin/resource.rc mode change 100755 => 100644 CPP/7zip/Bundles/makefile mode change 100755 => 100644 CPP/7zip/Common/CWrappers.cpp mode change 100755 => 100644 CPP/7zip/Common/CWrappers.h mode change 100755 => 100644 CPP/7zip/Common/CreateCoder.cpp mode change 100755 => 100644 CPP/7zip/Common/CreateCoder.h mode change 100755 => 100644 CPP/7zip/Common/FilePathAutoRename.cpp mode change 100755 => 100644 CPP/7zip/Common/FilePathAutoRename.h mode change 100755 => 100644 CPP/7zip/Common/FileStreams.cpp mode change 100755 => 100644 CPP/7zip/Common/FileStreams.h mode change 100755 => 100644 CPP/7zip/Common/FilterCoder.cpp mode change 100755 => 100644 CPP/7zip/Common/FilterCoder.h mode change 100755 => 100644 CPP/7zip/Common/InBuffer.cpp mode change 100755 => 100644 CPP/7zip/Common/InBuffer.h mode change 100755 => 100644 CPP/7zip/Common/InMemStream.cpp mode change 100755 => 100644 CPP/7zip/Common/InMemStream.h mode change 100755 => 100644 CPP/7zip/Common/InOutTempBuffer.cpp mode change 100755 => 100644 CPP/7zip/Common/InOutTempBuffer.h mode change 100755 => 100644 CPP/7zip/Common/LimitedStreams.cpp mode change 100755 => 100644 CPP/7zip/Common/LimitedStreams.h mode change 100755 => 100644 CPP/7zip/Common/LockedStream.cpp mode change 100755 => 100644 CPP/7zip/Common/LockedStream.h mode change 100755 => 100644 CPP/7zip/Common/MemBlocks.cpp mode change 100755 => 100644 CPP/7zip/Common/MemBlocks.h mode change 100755 => 100644 CPP/7zip/Common/MethodId.cpp mode change 100755 => 100644 CPP/7zip/Common/MethodId.h mode change 100755 => 100644 CPP/7zip/Common/MethodProps.cpp mode change 100755 => 100644 CPP/7zip/Common/MethodProps.h mode change 100755 => 100644 CPP/7zip/Common/OffsetStream.cpp mode change 100755 => 100644 CPP/7zip/Common/OffsetStream.h mode change 100755 => 100644 CPP/7zip/Common/OutBuffer.cpp mode change 100755 => 100644 CPP/7zip/Common/OutBuffer.h mode change 100755 => 100644 CPP/7zip/Common/OutMemStream.cpp mode change 100755 => 100644 CPP/7zip/Common/OutMemStream.h mode change 100755 => 100644 CPP/7zip/Common/ProgressMt.cpp mode change 100755 => 100644 CPP/7zip/Common/ProgressMt.h mode change 100755 => 100644 CPP/7zip/Common/ProgressUtils.cpp mode change 100755 => 100644 CPP/7zip/Common/ProgressUtils.h create mode 100644 CPP/7zip/Common/PropId.cpp mode change 100755 => 100644 CPP/7zip/Common/RegisterArc.h mode change 100755 => 100644 CPP/7zip/Common/RegisterCodec.h mode change 100755 => 100644 CPP/7zip/Common/StdAfx.h mode change 100755 => 100644 CPP/7zip/Common/StreamBinder.cpp mode change 100755 => 100644 CPP/7zip/Common/StreamBinder.h mode change 100755 => 100644 CPP/7zip/Common/StreamObjects.cpp mode change 100755 => 100644 CPP/7zip/Common/StreamObjects.h mode change 100755 => 100644 CPP/7zip/Common/StreamUtils.cpp mode change 100755 => 100644 CPP/7zip/Common/StreamUtils.h create mode 100644 CPP/7zip/Common/UniqBlocks.cpp create mode 100644 CPP/7zip/Common/UniqBlocks.h mode change 100755 => 100644 CPP/7zip/Common/VirtThread.cpp mode change 100755 => 100644 CPP/7zip/Common/VirtThread.h mode change 100755 => 100644 CPP/7zip/Compress/ArjDecoder1.cpp mode change 100755 => 100644 CPP/7zip/Compress/ArjDecoder1.h mode change 100755 => 100644 CPP/7zip/Compress/ArjDecoder2.cpp mode change 100755 => 100644 CPP/7zip/Compress/ArjDecoder2.h mode change 100755 => 100644 CPP/7zip/Compress/BZip2Const.h mode change 100755 => 100644 CPP/7zip/Compress/BZip2Crc.cpp mode change 100755 => 100644 CPP/7zip/Compress/BZip2Crc.h mode change 100755 => 100644 CPP/7zip/Compress/BZip2Decoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/BZip2Decoder.h mode change 100755 => 100644 CPP/7zip/Compress/BZip2Encoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/BZip2Encoder.h mode change 100755 => 100644 CPP/7zip/Compress/BZip2Register.cpp mode change 100755 => 100644 CPP/7zip/Compress/Bcj2Coder.cpp mode change 100755 => 100644 CPP/7zip/Compress/Bcj2Coder.h mode change 100755 => 100644 CPP/7zip/Compress/Bcj2Register.cpp mode change 100755 => 100644 CPP/7zip/Compress/BcjCoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/BcjCoder.h mode change 100755 => 100644 CPP/7zip/Compress/BcjRegister.cpp mode change 100755 => 100644 CPP/7zip/Compress/BitlDecoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/BitlDecoder.h mode change 100755 => 100644 CPP/7zip/Compress/BitlEncoder.h mode change 100755 => 100644 CPP/7zip/Compress/BitmDecoder.h mode change 100755 => 100644 CPP/7zip/Compress/BitmEncoder.h mode change 100755 => 100644 CPP/7zip/Compress/BranchCoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/BranchCoder.h mode change 100755 => 100644 CPP/7zip/Compress/BranchMisc.cpp mode change 100755 => 100644 CPP/7zip/Compress/BranchMisc.h mode change 100755 => 100644 CPP/7zip/Compress/BranchRegister.cpp mode change 100755 => 100644 CPP/7zip/Compress/ByteSwap.cpp mode change 100755 => 100644 CPP/7zip/Compress/Codec.def mode change 100755 => 100644 CPP/7zip/Compress/CodecExports.cpp mode change 100755 => 100644 CPP/7zip/Compress/CopyCoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/CopyCoder.h mode change 100755 => 100644 CPP/7zip/Compress/CopyRegister.cpp mode change 100755 => 100644 CPP/7zip/Compress/Deflate64Register.cpp mode change 100755 => 100644 CPP/7zip/Compress/DeflateConst.h mode change 100755 => 100644 CPP/7zip/Compress/DeflateDecoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/DeflateDecoder.h mode change 100755 => 100644 CPP/7zip/Compress/DeflateEncoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/DeflateEncoder.h mode change 100755 => 100644 CPP/7zip/Compress/DeflateRegister.cpp mode change 100755 => 100644 CPP/7zip/Compress/DeltaFilter.cpp delete mode 100755 CPP/7zip/Compress/DllExports.cpp delete mode 100755 CPP/7zip/Compress/DllExports2.cpp create mode 100644 CPP/7zip/Compress/DllExports2Compress.cpp create mode 100644 CPP/7zip/Compress/DllExportsCompress.cpp mode change 100755 => 100644 CPP/7zip/Compress/HuffmanDecoder.h mode change 100755 => 100644 CPP/7zip/Compress/ImplodeDecoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/ImplodeDecoder.h mode change 100755 => 100644 CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/ImplodeHuffmanDecoder.h mode change 100755 => 100644 CPP/7zip/Compress/LzOutWindow.cpp mode change 100755 => 100644 CPP/7zip/Compress/LzOutWindow.h mode change 100755 => 100644 CPP/7zip/Compress/LzhDecoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/LzhDecoder.h mode change 100755 => 100644 CPP/7zip/Compress/Lzma2Decoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/Lzma2Decoder.h mode change 100755 => 100644 CPP/7zip/Compress/Lzma2Encoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/Lzma2Encoder.h mode change 100755 => 100644 CPP/7zip/Compress/Lzma2Register.cpp mode change 100755 => 100644 CPP/7zip/Compress/LzmaDecoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/LzmaDecoder.h mode change 100755 => 100644 CPP/7zip/Compress/LzmaEncoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/LzmaEncoder.h mode change 100755 => 100644 CPP/7zip/Compress/LzmaRegister.cpp mode change 100755 => 100644 CPP/7zip/Compress/Lzx.h mode change 100755 => 100644 CPP/7zip/Compress/Lzx86Converter.cpp mode change 100755 => 100644 CPP/7zip/Compress/Lzx86Converter.h mode change 100755 => 100644 CPP/7zip/Compress/LzxDecoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/LzxDecoder.h mode change 100755 => 100644 CPP/7zip/Compress/Mtf8.h mode change 100755 => 100644 CPP/7zip/Compress/PpmdDecoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/PpmdDecoder.h mode change 100755 => 100644 CPP/7zip/Compress/PpmdEncoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/PpmdEncoder.h mode change 100755 => 100644 CPP/7zip/Compress/PpmdRegister.cpp mode change 100755 => 100644 CPP/7zip/Compress/PpmdZip.cpp mode change 100755 => 100644 CPP/7zip/Compress/PpmdZip.h mode change 100755 => 100644 CPP/7zip/Compress/QuantumDecoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/QuantumDecoder.h mode change 100755 => 100644 CPP/7zip/Compress/RangeCoder.h mode change 100755 => 100644 CPP/7zip/Compress/RangeCoderBit.h mode change 100755 => 100644 CPP/7zip/Compress/Rar1Decoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/Rar1Decoder.h mode change 100755 => 100644 CPP/7zip/Compress/Rar2Decoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/Rar2Decoder.h mode change 100755 => 100644 CPP/7zip/Compress/Rar3Decoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/Rar3Decoder.h mode change 100755 => 100644 CPP/7zip/Compress/Rar3Vm.cpp mode change 100755 => 100644 CPP/7zip/Compress/Rar3Vm.h mode change 100755 => 100644 CPP/7zip/Compress/RarCodecsRegister.cpp mode change 100755 => 100644 CPP/7zip/Compress/ShrinkDecoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/ShrinkDecoder.h mode change 100755 => 100644 CPP/7zip/Compress/StdAfx.h mode change 100755 => 100644 CPP/7zip/Compress/ZDecoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/ZDecoder.h mode change 100755 => 100644 CPP/7zip/Compress/ZlibDecoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/ZlibDecoder.h mode change 100755 => 100644 CPP/7zip/Compress/ZlibEncoder.cpp mode change 100755 => 100644 CPP/7zip/Compress/ZlibEncoder.h mode change 100755 => 100644 CPP/7zip/Compress/makefile mode change 100755 => 100644 CPP/7zip/Crc.mak create mode 100644 CPP/7zip/Crc64.mak mode change 100755 => 100644 CPP/7zip/Crypto/7zAes.cpp mode change 100755 => 100644 CPP/7zip/Crypto/7zAes.h mode change 100755 => 100644 CPP/7zip/Crypto/7zAesRegister.cpp mode change 100755 => 100644 CPP/7zip/Crypto/Codec.def mode change 100755 => 100644 CPP/7zip/Crypto/HmacSha1.cpp mode change 100755 => 100644 CPP/7zip/Crypto/HmacSha1.h mode change 100755 => 100644 CPP/7zip/Crypto/MyAes.cpp mode change 100755 => 100644 CPP/7zip/Crypto/MyAes.h create mode 100644 CPP/7zip/Crypto/MyAesReg.cpp mode change 100755 => 100644 CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp mode change 100755 => 100644 CPP/7zip/Crypto/Pbkdf2HmacSha1.h mode change 100755 => 100644 CPP/7zip/Crypto/RandGen.cpp mode change 100755 => 100644 CPP/7zip/Crypto/RandGen.h mode change 100755 => 100644 CPP/7zip/Crypto/Rar20Crypto.cpp mode change 100755 => 100644 CPP/7zip/Crypto/Rar20Crypto.h mode change 100755 => 100644 CPP/7zip/Crypto/RarAes.cpp mode change 100755 => 100644 CPP/7zip/Crypto/RarAes.h mode change 100755 => 100644 CPP/7zip/Crypto/Sha1.cpp mode change 100755 => 100644 CPP/7zip/Crypto/Sha1.h create mode 100644 CPP/7zip/Crypto/Sha1Reg.cpp mode change 100755 => 100644 CPP/7zip/Crypto/StdAfx.h mode change 100755 => 100644 CPP/7zip/Crypto/WzAes.cpp mode change 100755 => 100644 CPP/7zip/Crypto/WzAes.h mode change 100755 => 100644 CPP/7zip/Crypto/ZipCrypto.cpp mode change 100755 => 100644 CPP/7zip/Crypto/ZipCrypto.h mode change 100755 => 100644 CPP/7zip/Crypto/ZipStrong.cpp mode change 100755 => 100644 CPP/7zip/Crypto/ZipStrong.h mode change 100755 => 100644 CPP/7zip/GuiCommon.rc mode change 100755 => 100644 CPP/7zip/Guid.txt mode change 100755 => 100644 CPP/7zip/ICoder.h mode change 100755 => 100644 CPP/7zip/IDecl.h mode change 100755 => 100644 CPP/7zip/IPassword.h mode change 100755 => 100644 CPP/7zip/IProgress.h mode change 100755 => 100644 CPP/7zip/IStream.h mode change 100755 => 100644 CPP/7zip/MyVersion.h mode change 100755 => 100644 CPP/7zip/MyVersionInfo.rc mode change 100755 => 100644 CPP/7zip/PropID.h mode change 100755 => 100644 CPP/7zip/SubBuild.mak mode change 100755 => 100644 CPP/7zip/UI/Agent/Agent.cpp mode change 100755 => 100644 CPP/7zip/UI/Agent/Agent.h mode change 100755 => 100644 CPP/7zip/UI/Agent/AgentOut.cpp mode change 100755 => 100644 CPP/7zip/UI/Agent/AgentProxy.cpp mode change 100755 => 100644 CPP/7zip/UI/Agent/AgentProxy.h mode change 100755 => 100644 CPP/7zip/UI/Agent/ArchiveFolder.cpp mode change 100755 => 100644 CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp mode change 100755 => 100644 CPP/7zip/UI/Agent/ArchiveFolderOut.cpp mode change 100755 => 100644 CPP/7zip/UI/Agent/IFolderArchive.h mode change 100755 => 100644 CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp mode change 100755 => 100644 CPP/7zip/UI/Agent/UpdateCallbackAgent.h mode change 100755 => 100644 CPP/7zip/UI/Client7z/Client7z.cpp mode change 100755 => 100644 CPP/7zip/UI/Client7z/Client7z.dsp mode change 100755 => 100644 CPP/7zip/UI/Client7z/Client7z.dsw mode change 100755 => 100644 CPP/7zip/UI/Client7z/StdAfx.cpp mode change 100755 => 100644 CPP/7zip/UI/Client7z/StdAfx.h mode change 100755 => 100644 CPP/7zip/UI/Client7z/makefile create mode 100644 CPP/7zip/UI/Client7z/resource.rc mode change 100755 => 100644 CPP/7zip/UI/Common/ArchiveCommandLine.cpp mode change 100755 => 100644 CPP/7zip/UI/Common/ArchiveCommandLine.h mode change 100755 => 100644 CPP/7zip/UI/Common/ArchiveExtractCallback.cpp mode change 100755 => 100644 CPP/7zip/UI/Common/ArchiveExtractCallback.h mode change 100755 => 100644 CPP/7zip/UI/Common/ArchiveName.cpp mode change 100755 => 100644 CPP/7zip/UI/Common/ArchiveName.h mode change 100755 => 100644 CPP/7zip/UI/Common/ArchiveOpenCallback.cpp mode change 100755 => 100644 CPP/7zip/UI/Common/ArchiveOpenCallback.h mode change 100755 => 100644 CPP/7zip/UI/Common/Bench.cpp mode change 100755 => 100644 CPP/7zip/UI/Common/Bench.h mode change 100755 => 100644 CPP/7zip/UI/Common/CompressCall.cpp mode change 100755 => 100644 CPP/7zip/UI/Common/CompressCall.h mode change 100755 => 100644 CPP/7zip/UI/Common/CompressCall2.cpp mode change 100755 => 100644 CPP/7zip/UI/Common/DefaultName.cpp mode change 100755 => 100644 CPP/7zip/UI/Common/DefaultName.h mode change 100755 => 100644 CPP/7zip/UI/Common/DirItem.h mode change 100755 => 100644 CPP/7zip/UI/Common/EnumDirItems.cpp mode change 100755 => 100644 CPP/7zip/UI/Common/EnumDirItems.h mode change 100755 => 100644 CPP/7zip/UI/Common/ExitCode.h mode change 100755 => 100644 CPP/7zip/UI/Common/Extract.cpp mode change 100755 => 100644 CPP/7zip/UI/Common/Extract.h mode change 100755 => 100644 CPP/7zip/UI/Common/ExtractMode.h mode change 100755 => 100644 CPP/7zip/UI/Common/ExtractingFilePath.cpp mode change 100755 => 100644 CPP/7zip/UI/Common/ExtractingFilePath.h create mode 100644 CPP/7zip/UI/Common/HashCalc.cpp create mode 100644 CPP/7zip/UI/Common/HashCalc.h mode change 100755 => 100644 CPP/7zip/UI/Common/IFileExtractCallback.h mode change 100755 => 100644 CPP/7zip/UI/Common/LoadCodecs.cpp mode change 100755 => 100644 CPP/7zip/UI/Common/LoadCodecs.h mode change 100755 => 100644 CPP/7zip/UI/Common/OpenArchive.cpp mode change 100755 => 100644 CPP/7zip/UI/Common/OpenArchive.h mode change 100755 => 100644 CPP/7zip/UI/Common/PropIDUtils.cpp mode change 100755 => 100644 CPP/7zip/UI/Common/PropIDUtils.h mode change 100755 => 100644 CPP/7zip/UI/Common/Property.h mode change 100755 => 100644 CPP/7zip/UI/Common/SetProperties.cpp mode change 100755 => 100644 CPP/7zip/UI/Common/SetProperties.h mode change 100755 => 100644 CPP/7zip/UI/Common/SortUtils.cpp mode change 100755 => 100644 CPP/7zip/UI/Common/SortUtils.h mode change 100755 => 100644 CPP/7zip/UI/Common/StdAfx.h mode change 100755 => 100644 CPP/7zip/UI/Common/TempFiles.cpp mode change 100755 => 100644 CPP/7zip/UI/Common/TempFiles.h mode change 100755 => 100644 CPP/7zip/UI/Common/Update.cpp mode change 100755 => 100644 CPP/7zip/UI/Common/Update.h mode change 100755 => 100644 CPP/7zip/UI/Common/UpdateAction.cpp mode change 100755 => 100644 CPP/7zip/UI/Common/UpdateAction.h mode change 100755 => 100644 CPP/7zip/UI/Common/UpdateCallback.cpp mode change 100755 => 100644 CPP/7zip/UI/Common/UpdateCallback.h mode change 100755 => 100644 CPP/7zip/UI/Common/UpdatePair.cpp mode change 100755 => 100644 CPP/7zip/UI/Common/UpdatePair.h mode change 100755 => 100644 CPP/7zip/UI/Common/UpdateProduce.cpp mode change 100755 => 100644 CPP/7zip/UI/Common/UpdateProduce.h mode change 100755 => 100644 CPP/7zip/UI/Common/WorkDir.cpp mode change 100755 => 100644 CPP/7zip/UI/Common/WorkDir.h mode change 100755 => 100644 CPP/7zip/UI/Common/ZipRegistry.cpp mode change 100755 => 100644 CPP/7zip/UI/Common/ZipRegistry.h mode change 100755 => 100644 CPP/7zip/UI/Console/BenchCon.cpp mode change 100755 => 100644 CPP/7zip/UI/Console/BenchCon.h mode change 100755 => 100644 CPP/7zip/UI/Console/Console.dsp mode change 100755 => 100644 CPP/7zip/UI/Console/Console.dsw create mode 100644 CPP/7zip/UI/Console/Console.mak mode change 100755 => 100644 CPP/7zip/UI/Console/ConsoleClose.cpp mode change 100755 => 100644 CPP/7zip/UI/Console/ConsoleClose.h mode change 100755 => 100644 CPP/7zip/UI/Console/ExtractCallbackConsole.cpp mode change 100755 => 100644 CPP/7zip/UI/Console/ExtractCallbackConsole.h create mode 100644 CPP/7zip/UI/Console/HashCon.cpp create mode 100644 CPP/7zip/UI/Console/HashCon.h mode change 100755 => 100644 CPP/7zip/UI/Console/List.cpp mode change 100755 => 100644 CPP/7zip/UI/Console/List.h mode change 100755 => 100644 CPP/7zip/UI/Console/Main.cpp mode change 100755 => 100644 CPP/7zip/UI/Console/MainAr.cpp mode change 100755 => 100644 CPP/7zip/UI/Console/OpenCallbackConsole.cpp mode change 100755 => 100644 CPP/7zip/UI/Console/OpenCallbackConsole.h mode change 100755 => 100644 CPP/7zip/UI/Console/PercentPrinter.cpp mode change 100755 => 100644 CPP/7zip/UI/Console/PercentPrinter.h mode change 100755 => 100644 CPP/7zip/UI/Console/StdAfx.cpp mode change 100755 => 100644 CPP/7zip/UI/Console/StdAfx.h mode change 100755 => 100644 CPP/7zip/UI/Console/UpdateCallbackConsole.cpp mode change 100755 => 100644 CPP/7zip/UI/Console/UpdateCallbackConsole.h mode change 100755 => 100644 CPP/7zip/UI/Console/UserInputUtils.cpp mode change 100755 => 100644 CPP/7zip/UI/Console/UserInputUtils.h mode change 100755 => 100644 CPP/7zip/UI/Console/makefile mode change 100755 => 100644 CPP/7zip/UI/Console/resource.rc mode change 100755 => 100644 CPP/7zip/UI/Explorer/7-zip.dll.manifest mode change 100755 => 100644 CPP/7zip/UI/Explorer/ContextMenu.cpp mode change 100755 => 100644 CPP/7zip/UI/Explorer/ContextMenu.h mode change 100755 => 100644 CPP/7zip/UI/Explorer/ContextMenuFlags.h delete mode 100755 CPP/7zip/UI/Explorer/DllExports.cpp create mode 100644 CPP/7zip/UI/Explorer/DllExportsExplorer.cpp mode change 100755 => 100644 CPP/7zip/UI/Explorer/Explorer.def mode change 100755 => 100644 CPP/7zip/UI/Explorer/Explorer.dsp mode change 100755 => 100644 CPP/7zip/UI/Explorer/Explorer.dsw create mode 100644 CPP/7zip/UI/Explorer/MenuLogo.bmp mode change 100755 => 100644 CPP/7zip/UI/Explorer/MyMessages.cpp mode change 100755 => 100644 CPP/7zip/UI/Explorer/MyMessages.h mode change 100755 => 100644 CPP/7zip/UI/Explorer/OptionsDialog.cpp mode change 100755 => 100644 CPP/7zip/UI/Explorer/OptionsDialog.h mode change 100755 => 100644 CPP/7zip/UI/Explorer/RegistryContextMenu.cpp mode change 100755 => 100644 CPP/7zip/UI/Explorer/RegistryContextMenu.h mode change 100755 => 100644 CPP/7zip/UI/Explorer/StdAfx.cpp mode change 100755 => 100644 CPP/7zip/UI/Explorer/StdAfx.h mode change 100755 => 100644 CPP/7zip/UI/Explorer/makefile mode change 100755 => 100644 CPP/7zip/UI/Explorer/resource.h mode change 100755 => 100644 CPP/7zip/UI/Explorer/resource.rc mode change 100755 => 100644 CPP/7zip/UI/Explorer/resource2.rc mode change 100755 => 100644 CPP/7zip/UI/Far/ExtractEngine.cpp mode change 100755 => 100644 CPP/7zip/UI/Far/ExtractEngine.h create mode 100644 CPP/7zip/UI/Far/Far.cpp mode change 100755 => 100644 CPP/7zip/UI/Far/Far.def mode change 100755 => 100644 CPP/7zip/UI/Far/Far.dsp mode change 100755 => 100644 CPP/7zip/UI/Far/Far.dsw mode change 100755 => 100644 CPP/7zip/UI/Far/FarPlugin.h mode change 100755 => 100644 CPP/7zip/UI/Far/FarUtils.cpp mode change 100755 => 100644 CPP/7zip/UI/Far/FarUtils.h delete mode 100755 CPP/7zip/UI/Far/Main.cpp mode change 100755 => 100644 CPP/7zip/UI/Far/Messages.h delete mode 100755 CPP/7zip/UI/Far/OverwriteDialog.cpp delete mode 100755 CPP/7zip/UI/Far/OverwriteDialog.h create mode 100644 CPP/7zip/UI/Far/OverwriteDialogFar.cpp create mode 100644 CPP/7zip/UI/Far/OverwriteDialogFar.h mode change 100755 => 100644 CPP/7zip/UI/Far/Plugin.cpp mode change 100755 => 100644 CPP/7zip/UI/Far/Plugin.h mode change 100755 => 100644 CPP/7zip/UI/Far/PluginCommon.cpp mode change 100755 => 100644 CPP/7zip/UI/Far/PluginDelete.cpp mode change 100755 => 100644 CPP/7zip/UI/Far/PluginRead.cpp mode change 100755 => 100644 CPP/7zip/UI/Far/PluginWrite.cpp mode change 100755 => 100644 CPP/7zip/UI/Far/ProgressBox.cpp mode change 100755 => 100644 CPP/7zip/UI/Far/ProgressBox.h mode change 100755 => 100644 CPP/7zip/UI/Far/StdAfx.cpp mode change 100755 => 100644 CPP/7zip/UI/Far/StdAfx.h delete mode 100755 CPP/7zip/UI/Far/UpdateCallback100.cpp delete mode 100755 CPP/7zip/UI/Far/UpdateCallback100.h create mode 100644 CPP/7zip/UI/Far/UpdateCallbackFar.cpp create mode 100644 CPP/7zip/UI/Far/UpdateCallbackFar.h mode change 100755 => 100644 CPP/7zip/UI/Far/makefile mode change 100755 => 100644 CPP/7zip/UI/Far/resource.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/7zFM.exe.manifest mode change 100755 => 100644 CPP/7zip/UI/FileManager/7zipLogo.ico mode change 100755 => 100644 CPP/7zip/UI/FileManager/AboutDialog.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/AboutDialog.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/AboutDialog.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/AboutDialogRes.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/Add.bmp mode change 100755 => 100644 CPP/7zip/UI/FileManager/Add2.bmp mode change 100755 => 100644 CPP/7zip/UI/FileManager/App.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/App.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/AppState.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/BrowseDialog.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/BrowseDialog.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/BrowseDialog.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/BrowseDialogRes.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/ClassDefs.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/ComboDialog.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/ComboDialog.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/ComboDialog.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/ComboDialogRes.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/Copy.bmp mode change 100755 => 100644 CPP/7zip/UI/FileManager/Copy2.bmp mode change 100755 => 100644 CPP/7zip/UI/FileManager/CopyDialog.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/CopyDialog.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/CopyDialog.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/CopyDialogRes.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/Delete.bmp mode change 100755 => 100644 CPP/7zip/UI/FileManager/Delete2.bmp mode change 100755 => 100644 CPP/7zip/UI/FileManager/DialogSize.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/EditPage.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/EditPage.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/EditPage.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/EditPage2.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/EditPageRes.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/EnumFormatEtc.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/EnumFormatEtc.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/Extract.bmp mode change 100755 => 100644 CPP/7zip/UI/FileManager/Extract2.bmp mode change 100755 => 100644 CPP/7zip/UI/FileManager/ExtractCallback.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/ExtractCallback.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/FM.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/FM.dsp mode change 100755 => 100644 CPP/7zip/UI/FileManager/FM.dsw mode change 100755 => 100644 CPP/7zip/UI/FileManager/FM.ico create mode 100644 CPP/7zip/UI/FileManager/FM.mak mode change 100755 => 100644 CPP/7zip/UI/FileManager/FSDrives.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/FSDrives.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/FSFolder.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/FSFolder.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/FSFolderCopy.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/FileFolderPluginOpen.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/FilePlugins.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/FilePlugins.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/FoldersPage.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/FoldersPage.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/FoldersPage.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/FoldersPage2.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/FoldersPageRes.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/FormatUtils.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/FormatUtils.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/HelpUtils.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/HelpUtils.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/IFolder.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/Info.bmp mode change 100755 => 100644 CPP/7zip/UI/FileManager/Info2.bmp mode change 100755 => 100644 CPP/7zip/UI/FileManager/LangPage.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/LangPage.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/LangPage.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/LangPageRes.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/LangUtils.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/LangUtils.h create mode 100644 CPP/7zip/UI/FileManager/LinkDialog.cpp create mode 100644 CPP/7zip/UI/FileManager/LinkDialog.h create mode 100644 CPP/7zip/UI/FileManager/LinkDialog.rc create mode 100644 CPP/7zip/UI/FileManager/LinkDialogRes.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/ListViewDialog.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/ListViewDialog.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/ListViewDialog.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/ListViewDialogRes.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/MenuPage.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/MenuPage.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/MenuPage.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/MenuPage2.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/MenuPageRes.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/MessagesDialog.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/MessagesDialog.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/MessagesDialog.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/MessagesDialogRes.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/Move.bmp mode change 100755 => 100644 CPP/7zip/UI/FileManager/Move2.bmp mode change 100755 => 100644 CPP/7zip/UI/FileManager/MyCom2.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/MyLoadMenu.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/MyLoadMenu.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/MyWindowsNew.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/NetFolder.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/NetFolder.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/OpenCallback.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/OpenCallback.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/OptionsDialog.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/OverwriteDialog.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/OverwriteDialog.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/OverwriteDialog.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/OverwriteDialogRes.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/Panel.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/Panel.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/PanelCopy.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/PanelCrc.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/PanelDrag.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/PanelFolderChange.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/PanelItemOpen.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/PanelItems.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/PanelKey.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/PanelListNotify.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/PanelMenu.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/PanelOperations.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/PanelSelect.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/PanelSort.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/PanelSplitFile.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/PasswordDialog.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/PasswordDialog.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/PasswordDialog.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/PasswordDialogRes.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/PluginInterface.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/PluginLoader.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/PluginsPage.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/PluginsPage.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/PluginsPage.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/PluginsPageRes.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/ProgramLocation.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/ProgramLocation.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/ProgressDialog.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/ProgressDialog.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/ProgressDialog.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/ProgressDialog2.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/ProgressDialog2.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/ProgressDialog2.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/ProgressDialog2Res.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/ProgressDialog2a.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/ProgressDialogRes.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/PropertyName.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/PropertyName.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/PropertyName.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/PropertyNameRes.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/RegistryAssociations.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/RegistryAssociations.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/RegistryPlugins.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/RegistryPlugins.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/RegistryUtils.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/RegistryUtils.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/RootFolder.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/RootFolder.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/SettingsPage.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/SettingsPage.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/SettingsPage.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/SettingsPage2.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/SettingsPageRes.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/SplitDialog.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/SplitDialog.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/SplitDialog.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/SplitDialogRes.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/SplitUtils.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/SplitUtils.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/StdAfx.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/StdAfx.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/StringUtils.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/StringUtils.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/SysIconUtils.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/SysIconUtils.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/SystemPage.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/SystemPage.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/SystemPage.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/SystemPageRes.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/Test.bmp mode change 100755 => 100644 CPP/7zip/UI/FileManager/Test2.bmp mode change 100755 => 100644 CPP/7zip/UI/FileManager/TextPairs.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/TextPairs.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/UpdateCallback100.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/UpdateCallback100.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/ViewSettings.cpp mode change 100755 => 100644 CPP/7zip/UI/FileManager/ViewSettings.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/makefile mode change 100755 => 100644 CPP/7zip/UI/FileManager/resource.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/resource.rc mode change 100755 => 100644 CPP/7zip/UI/FileManager/resourceGui.h mode change 100755 => 100644 CPP/7zip/UI/FileManager/resourceGui.rc mode change 100755 => 100644 CPP/7zip/UI/GUI/7zG.exe.manifest mode change 100755 => 100644 CPP/7zip/UI/GUI/BenchmarkDialog.cpp mode change 100755 => 100644 CPP/7zip/UI/GUI/BenchmarkDialog.h mode change 100755 => 100644 CPP/7zip/UI/GUI/BenchmarkDialog.rc mode change 100755 => 100644 CPP/7zip/UI/GUI/BenchmarkDialogRes.h mode change 100755 => 100644 CPP/7zip/UI/GUI/CompressDialog.cpp mode change 100755 => 100644 CPP/7zip/UI/GUI/CompressDialog.h mode change 100755 => 100644 CPP/7zip/UI/GUI/CompressDialog.rc mode change 100755 => 100644 CPP/7zip/UI/GUI/CompressDialogRes.h mode change 100755 => 100644 CPP/7zip/UI/GUI/Extract.rc mode change 100755 => 100644 CPP/7zip/UI/GUI/ExtractDialog.cpp mode change 100755 => 100644 CPP/7zip/UI/GUI/ExtractDialog.h mode change 100755 => 100644 CPP/7zip/UI/GUI/ExtractDialog.rc mode change 100755 => 100644 CPP/7zip/UI/GUI/ExtractDialogRes.h mode change 100755 => 100644 CPP/7zip/UI/GUI/ExtractGUI.cpp mode change 100755 => 100644 CPP/7zip/UI/GUI/ExtractGUI.h mode change 100755 => 100644 CPP/7zip/UI/GUI/ExtractRes.h mode change 100755 => 100644 CPP/7zip/UI/GUI/FM.ico mode change 100755 => 100644 CPP/7zip/UI/GUI/GUI.cpp mode change 100755 => 100644 CPP/7zip/UI/GUI/GUI.dsp mode change 100755 => 100644 CPP/7zip/UI/GUI/GUI.dsw create mode 100644 CPP/7zip/UI/GUI/HashGUI.cpp create mode 100644 CPP/7zip/UI/GUI/HashGUI.h mode change 100755 => 100644 CPP/7zip/UI/GUI/StdAfx.cpp mode change 100755 => 100644 CPP/7zip/UI/GUI/StdAfx.h mode change 100755 => 100644 CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp mode change 100755 => 100644 CPP/7zip/UI/GUI/UpdateCallbackGUI.h mode change 100755 => 100644 CPP/7zip/UI/GUI/UpdateGUI.cpp mode change 100755 => 100644 CPP/7zip/UI/GUI/UpdateGUI.h mode change 100755 => 100644 CPP/7zip/UI/GUI/makefile mode change 100755 => 100644 CPP/7zip/UI/GUI/resource.rc mode change 100755 => 100644 CPP/7zip/UI/GUI/resource2.h mode change 100755 => 100644 CPP/7zip/UI/GUI/resource2.rc mode change 100755 => 100644 CPP/7zip/UI/makefile mode change 100755 => 100644 CPP/7zip/makefile mode change 100755 => 100644 CPP/Build.mak mode change 100755 => 100644 CPP/Common/AutoPtr.h delete mode 100755 CPP/Common/Buffer.h mode change 100755 => 100644 CPP/Common/CRC.cpp mode change 100755 => 100644 CPP/Common/C_FileIO.cpp mode change 100755 => 100644 CPP/Common/C_FileIO.h mode change 100755 => 100644 CPP/Common/ComTry.h mode change 100755 => 100644 CPP/Common/CommandLineParser.cpp mode change 100755 => 100644 CPP/Common/CommandLineParser.h create mode 100644 CPP/Common/Common.h create mode 100644 CPP/Common/CrcReg.cpp mode change 100755 => 100644 CPP/Common/Defs.h create mode 100644 CPP/Common/DynLimBuf.cpp create mode 100644 CPP/Common/DynLimBuf.h mode change 100755 => 100644 CPP/Common/DynamicBuffer.h mode change 100755 => 100644 CPP/Common/IntToString.cpp mode change 100755 => 100644 CPP/Common/IntToString.h mode change 100755 => 100644 CPP/Common/Lang.cpp mode change 100755 => 100644 CPP/Common/Lang.h mode change 100755 => 100644 CPP/Common/ListFileUtils.cpp mode change 100755 => 100644 CPP/Common/ListFileUtils.h create mode 100644 CPP/Common/MyBuffer.h mode change 100755 => 100644 CPP/Common/MyCom.h mode change 100755 => 100644 CPP/Common/MyException.h mode change 100755 => 100644 CPP/Common/MyGuidDef.h mode change 100755 => 100644 CPP/Common/MyInitGuid.h mode change 100755 => 100644 CPP/Common/MyMap.cpp mode change 100755 => 100644 CPP/Common/MyMap.h mode change 100755 => 100644 CPP/Common/MyString.cpp mode change 100755 => 100644 CPP/Common/MyString.h create mode 100644 CPP/Common/MyTypes.h mode change 100755 => 100644 CPP/Common/MyUnknown.h mode change 100755 => 100644 CPP/Common/MyVector.cpp mode change 100755 => 100644 CPP/Common/MyVector.h mode change 100755 => 100644 CPP/Common/MyWindows.cpp mode change 100755 => 100644 CPP/Common/MyWindows.h mode change 100755 => 100644 CPP/Common/MyXml.cpp mode change 100755 => 100644 CPP/Common/MyXml.h mode change 100755 => 100644 CPP/Common/NewHandler.cpp mode change 100755 => 100644 CPP/Common/NewHandler.h mode change 100755 => 100644 CPP/Common/Random.cpp mode change 100755 => 100644 CPP/Common/Random.h create mode 100644 CPP/Common/Sha256Reg.cpp mode change 100755 => 100644 CPP/Common/StdAfx.h mode change 100755 => 100644 CPP/Common/StdInStream.cpp mode change 100755 => 100644 CPP/Common/StdInStream.h mode change 100755 => 100644 CPP/Common/StdOutStream.cpp mode change 100755 => 100644 CPP/Common/StdOutStream.h mode change 100755 => 100644 CPP/Common/StringConvert.cpp mode change 100755 => 100644 CPP/Common/StringConvert.h mode change 100755 => 100644 CPP/Common/StringToInt.cpp mode change 100755 => 100644 CPP/Common/StringToInt.h mode change 100755 => 100644 CPP/Common/TextConfig.cpp mode change 100755 => 100644 CPP/Common/TextConfig.h delete mode 100755 CPP/Common/Types.h mode change 100755 => 100644 CPP/Common/UTFConvert.cpp mode change 100755 => 100644 CPP/Common/UTFConvert.h mode change 100755 => 100644 CPP/Common/Wildcard.cpp mode change 100755 => 100644 CPP/Common/Wildcard.h create mode 100644 CPP/Common/XzCrc64Reg.cpp mode change 100755 => 100644 CPP/Windows/COM.cpp mode change 100755 => 100644 CPP/Windows/COM.h mode change 100755 => 100644 CPP/Windows/Clipboard.cpp mode change 100755 => 100644 CPP/Windows/Clipboard.h mode change 100755 => 100644 CPP/Windows/CommonDialog.cpp mode change 100755 => 100644 CPP/Windows/CommonDialog.h mode change 100755 => 100644 CPP/Windows/Console.cpp mode change 100755 => 100644 CPP/Windows/Console.h mode change 100755 => 100644 CPP/Windows/Control/ComboBox.cpp mode change 100755 => 100644 CPP/Windows/Control/ComboBox.h mode change 100755 => 100644 CPP/Windows/Control/CommandBar.h mode change 100755 => 100644 CPP/Windows/Control/Dialog.cpp mode change 100755 => 100644 CPP/Windows/Control/Dialog.h mode change 100755 => 100644 CPP/Windows/Control/Edit.h mode change 100755 => 100644 CPP/Windows/Control/ImageList.cpp mode change 100755 => 100644 CPP/Windows/Control/ImageList.h mode change 100755 => 100644 CPP/Windows/Control/ListView.cpp mode change 100755 => 100644 CPP/Windows/Control/ListView.h mode change 100755 => 100644 CPP/Windows/Control/ProgressBar.h mode change 100755 => 100644 CPP/Windows/Control/PropertyPage.cpp mode change 100755 => 100644 CPP/Windows/Control/PropertyPage.h mode change 100755 => 100644 CPP/Windows/Control/ReBar.h mode change 100755 => 100644 CPP/Windows/Control/Static.h mode change 100755 => 100644 CPP/Windows/Control/StatusBar.h mode change 100755 => 100644 CPP/Windows/Control/StdAfx.h mode change 100755 => 100644 CPP/Windows/Control/ToolBar.h mode change 100755 => 100644 CPP/Windows/Control/Trackbar.h mode change 100755 => 100644 CPP/Windows/Control/Window2.cpp mode change 100755 => 100644 CPP/Windows/Control/Window2.h mode change 100755 => 100644 CPP/Windows/DLL.cpp mode change 100755 => 100644 CPP/Windows/DLL.h mode change 100755 => 100644 CPP/Windows/Defs.h delete mode 100755 CPP/Windows/Error.cpp delete mode 100755 CPP/Windows/Error.h create mode 100644 CPP/Windows/ErrorMsg.cpp create mode 100644 CPP/Windows/ErrorMsg.h mode change 100755 => 100644 CPP/Windows/FileDir.cpp mode change 100755 => 100644 CPP/Windows/FileDir.h mode change 100755 => 100644 CPP/Windows/FileFind.cpp mode change 100755 => 100644 CPP/Windows/FileFind.h mode change 100755 => 100644 CPP/Windows/FileIO.cpp mode change 100755 => 100644 CPP/Windows/FileIO.h create mode 100644 CPP/Windows/FileLink.cpp mode change 100755 => 100644 CPP/Windows/FileMapping.cpp mode change 100755 => 100644 CPP/Windows/FileMapping.h mode change 100755 => 100644 CPP/Windows/FileName.cpp mode change 100755 => 100644 CPP/Windows/FileName.h mode change 100755 => 100644 CPP/Windows/FileSystem.cpp mode change 100755 => 100644 CPP/Windows/FileSystem.h mode change 100755 => 100644 CPP/Windows/Handle.h delete mode 100755 CPP/Windows/Memory.cpp delete mode 100755 CPP/Windows/Memory.h create mode 100644 CPP/Windows/MemoryGlobal.cpp create mode 100644 CPP/Windows/MemoryGlobal.h mode change 100755 => 100644 CPP/Windows/MemoryLock.cpp mode change 100755 => 100644 CPP/Windows/MemoryLock.h mode change 100755 => 100644 CPP/Windows/Menu.cpp mode change 100755 => 100644 CPP/Windows/Menu.h mode change 100755 => 100644 CPP/Windows/NationalTime.cpp mode change 100755 => 100644 CPP/Windows/NationalTime.h mode change 100755 => 100644 CPP/Windows/Net.cpp mode change 100755 => 100644 CPP/Windows/Net.h mode change 100755 => 100644 CPP/Windows/NtCheck.h delete mode 100755 CPP/Windows/Process.cpp delete mode 100755 CPP/Windows/Process.h mode change 100755 => 100644 CPP/Windows/ProcessMessages.cpp mode change 100755 => 100644 CPP/Windows/ProcessMessages.h create mode 100644 CPP/Windows/ProcessUtils.cpp create mode 100644 CPP/Windows/ProcessUtils.h mode change 100755 => 100644 CPP/Windows/PropVariant.cpp mode change 100755 => 100644 CPP/Windows/PropVariant.h create mode 100644 CPP/Windows/PropVariantConv.cpp create mode 100644 CPP/Windows/PropVariantConv.h delete mode 100755 CPP/Windows/PropVariantConversions.cpp delete mode 100755 CPP/Windows/PropVariantConversions.h mode change 100755 => 100644 CPP/Windows/PropVariantUtils.cpp mode change 100755 => 100644 CPP/Windows/PropVariantUtils.h mode change 100755 => 100644 CPP/Windows/Registry.cpp mode change 100755 => 100644 CPP/Windows/Registry.h mode change 100755 => 100644 CPP/Windows/ResourceString.cpp mode change 100755 => 100644 CPP/Windows/ResourceString.h delete mode 100755 CPP/Windows/Security.cpp delete mode 100755 CPP/Windows/Security.h create mode 100644 CPP/Windows/SecurityUtils.cpp create mode 100644 CPP/Windows/SecurityUtils.h mode change 100755 => 100644 CPP/Windows/Shell.cpp mode change 100755 => 100644 CPP/Windows/Shell.h mode change 100755 => 100644 CPP/Windows/StdAfx.h mode change 100755 => 100644 CPP/Windows/Synchronization.cpp mode change 100755 => 100644 CPP/Windows/Synchronization.h mode change 100755 => 100644 CPP/Windows/System.cpp mode change 100755 => 100644 CPP/Windows/System.h mode change 100755 => 100644 CPP/Windows/Thread.h delete mode 100755 CPP/Windows/Time.cpp delete mode 100755 CPP/Windows/Time.h create mode 100644 CPP/Windows/TimeUtils.cpp create mode 100644 CPP/Windows/TimeUtils.h mode change 100755 => 100644 CPP/Windows/Window.cpp mode change 100755 => 100644 CPP/Windows/Window.h mode change 100755 => 100644 DOC/7zC.txt mode change 100755 => 100644 DOC/7zFormat.txt mode change 100755 => 100644 DOC/7zip.hhp mode change 100755 => 100644 DOC/7zip.inf mode change 100755 => 100644 DOC/7zip.nsi mode change 100755 => 100644 DOC/7zip.wxs mode change 100755 => 100644 DOC/License.txt mode change 100755 => 100644 DOC/Methods.txt mode change 100755 => 100644 DOC/copying.txt mode change 100755 => 100644 DOC/history.txt mode change 100755 => 100644 DOC/lzma.txt mode change 100755 => 100644 DOC/readme.txt mode change 100755 => 100644 DOC/unRarLicense.txt diff --git a/Asm/arm/7zCrcOpt.asm b/Asm/arm/7zCrcOpt.asm old mode 100755 new mode 100644 diff --git a/Asm/x86/7zAsm.asm b/Asm/x86/7zAsm.asm old mode 100755 new mode 100644 index 3e42ab45..3707e90c --- a/Asm/x86/7zAsm.asm +++ b/Asm/x86/7zAsm.asm @@ -1,5 +1,5 @@ ; 7zAsm.asm -- ASM macros -; 2009-12-12 : Igor Pavlov : Public domain +; 2012-12-30 : Igor Pavlov : Public domain MY_ASM_START macro ifdef x64 @@ -13,30 +13,34 @@ endm MY_PROC macro name:req, numParams:req align 16 - proc_numParams equ numParams + proc_numParams = 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: + proc_name equ @CatStr(@,name,@, %numParams * 4) endif + proc_name PROC endm MY_ENDP macro ifdef x64 ret - proc_name ENDP else - ret (proc_numParams - 2) * 4 + if proc_numParams LT 3 + ret + else + ret (proc_numParams - 2) * 4 + endif endif + proc_name ENDP endm ifdef x64 REG_SIZE equ 8 + REG_LOGAR_SIZE equ 3 else REG_SIZE equ 4 + REG_LOGAR_SIZE equ 2 endif x0 equ EAX @@ -67,6 +71,14 @@ ifdef x64 r5 equ RBP r6 equ RSI r7 equ RDI + x8 equ r8d + x9 equ r9d + x10 equ r10d + x11 equ r11d + x12 equ r12d + x13 equ r13d + x14 equ r14d + x15 equ r15d else r0 equ x0 r1 equ x1 diff --git a/Asm/x86/7zCrcOpt.asm b/Asm/x86/7zCrcOpt.asm old mode 100755 new mode 100644 diff --git a/Asm/x86/AesOpt.asm b/Asm/x86/AesOpt.asm old mode 100755 new mode 100644 diff --git a/Asm/x86/XzCrc64Opt.asm b/Asm/x86/XzCrc64Opt.asm new file mode 100644 index 00000000..734ca5c4 --- /dev/null +++ b/Asm/x86/XzCrc64Opt.asm @@ -0,0 +1,205 @@ +; XzCrc64Opt.asm -- CRC64 calculation : optimized version +; 2011-06-28 : Igor Pavlov : Public domain + +include 7zAsm.asm + +MY_ASM_START + +ifdef x64 + + rD equ r9 + rN equ r10 + + num_VAR equ r8 + table_VAR equ r9 + + SRCDAT equ rN + rD + +CRC_XOR macro dest:req, src:req, t:req + xor dest, QWORD PTR [r5 + src * 8 + 0800h * t] +endm + +CRC1b macro + movzx x6, BYTE PTR [rD] + inc rD + movzx x3, x0_L + xor x6, x3 + shr r0, 8 + CRC_XOR r0, r6, 0 + dec rN +endm + +MY_PROLOG macro crc_end:req + MY_PUSH_4_REGS + + mov r0, r1 + mov rN, num_VAR + mov r5, table_VAR + mov rD, r2 + test rN, rN + jz crc_end + @@: + test rD, 3 + jz @F + CRC1b + jnz @B + @@: + cmp rN, 8 + jb crc_end + add rN, rD + mov num_VAR, rN + sub rN, 4 + and rN, NOT 3 + sub rD, rN + mov x1, [SRCDAT] + xor r0, r1 + add rN, 4 +endm + +MY_EPILOG macro crc_end:req + sub rN, 4 + mov x1, [SRCDAT] + xor r0, r1 + mov rD, rN + mov rN, num_VAR + sub rN, rD + crc_end: + test rN, rN + jz @F + CRC1b + jmp crc_end + @@: + MY_POP_4_REGS +endm + +MY_PROC XzCrc64UpdateT4, 4 + MY_PROLOG crc_end_4 + align 16 + main_loop_4: + mov x1, [SRCDAT] + movzx x2, x0_L + movzx x3, x0_H + shr r0, 16 + movzx x6, x0_L + movzx x7, x0_H + shr r0, 16 + CRC_XOR r1, r2, 3 + CRC_XOR r0, r3, 2 + CRC_XOR r1, r6, 1 + CRC_XOR r0, r7, 0 + xor r0, r1 + + add rD, 4 + jnz main_loop_4 + + MY_EPILOG crc_end_4 +MY_ENDP + +else + + rD equ r1 + rN equ r7 + + crc_val equ (REG_SIZE * 5) + crc_table equ (8 + crc_val) + table_VAR equ [r4 + crc_table] + num_VAR equ table_VAR + + + SRCDAT equ rN + rD + +CRC macro op0:req, op1:req, dest0:req, dest1:req, src:req, t:req + op0 dest0, DWORD PTR [r5 + src * 8 + 0800h * t] + op1 dest1, DWORD PTR [r5 + src * 8 + 0800h * t + 4] +endm + +CRC_XOR macro dest0:req, dest1:req, src:req, t:req + CRC xor, xor, dest0, dest1, src, t +endm + + +CRC1b macro + movzx x6, BYTE PTR [rD] + inc rD + movzx x3, x0_L + xor x6, x3 + shrd r0, r2, 8 + shr r2, 8 + CRC_XOR r0, r2, r6, 0 + dec rN +endm + +MY_PROLOG macro crc_end:req + MY_PUSH_4_REGS + + mov rN, r2 + + mov x0, [r4 + crc_val] + mov x2, [r4 + crc_val + 4] + mov r5, table_VAR + test rN, rN + jz crc_end + @@: + test rD, 3 + jz @F + CRC1b + jnz @B + @@: + cmp rN, 8 + jb crc_end + add rN, rD + + mov num_VAR, rN + + sub rN, 4 + and rN, NOT 3 + sub rD, rN + xor r0, [SRCDAT] + add rN, 4 +endm + +MY_EPILOG macro crc_end:req + sub rN, 4 + xor r0, [SRCDAT] + + mov rD, rN + mov rN, num_VAR + sub rN, rD + crc_end: + test rN, rN + jz @F + CRC1b + jmp crc_end + @@: + MY_POP_4_REGS +endm + +MY_PROC XzCrc64UpdateT4, 5 + MY_PROLOG crc_end_4 + movzx x6, x0_L + align 16 + main_loop_4: + mov r3, [SRCDAT] + xor r3, r2 + + CRC xor, mov, r3, r2, r6, 3 + movzx x6, x0_H + shr r0, 16 + CRC_XOR r3, r2, r6, 2 + + movzx x6, x0_L + movzx x0, x0_H + CRC_XOR r3, r2, r6, 1 + CRC_XOR r3, r2, r0, 0 + movzx x6, x3_L + mov r0, r3 + + add rD, 4 + jnz main_loop_4 + + MY_EPILOG crc_end_4 +MY_ENDP + +endif + +end diff --git a/C/7z.h b/C/7z.h old mode 100755 new mode 100644 index 01c4cac6..ca4a2233 --- a/C/7z.h +++ b/C/7z.h @@ -1,89 +1,70 @@ /* 7z.h -- 7z interface -2010-03-11 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __7Z_H #define __7Z_H -#include "7zBuf.h" +#include "7zTypes.h" EXTERN_C_BEGIN #define k7zStartHeaderSize 0x20 #define k7zSignatureSize 6 + extern Byte k7zSignature[k7zSignatureSize]; -#define k7zMajorVersion 0 -enum EIdEnum +typedef struct { - 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 -}; + const Byte *Data; + size_t Size; +} CSzData; + +/* CSzCoderInfo & CSzFolder support only default methods */ typedef struct { - UInt32 NumInStreams; - UInt32 NumOutStreams; - UInt64 MethodID; - CBuf Props; + size_t PropsOffset; + UInt32 MethodID; + Byte NumInStreams; + Byte NumOutStreams; + Byte PropsSize; } CSzCoderInfo; -void SzCoderInfo_Init(CSzCoderInfo *p); -void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc); - typedef struct { UInt32 InIndex; UInt32 OutIndex; } CSzBindPair; +#define SZ_NUM_CODERS_IN_FOLDER_MAX 4 +#define SZ_NUM_BINDS_IN_FOLDER_MAX 3 +#define SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX 4 +#define SZ_NUM_CODERS_OUT_STREAMS_IN_FOLDER_MAX 4 + typedef struct { - CSzCoderInfo *Coders; - CSzBindPair *BindPairs; - UInt32 *PackStreams; - UInt64 *UnpackSizes; UInt32 NumCoders; UInt32 NumBindPairs; UInt32 NumPackStreams; - int UnpackCRCDefined; - UInt32 UnpackCRC; - - UInt32 NumUnpackStreams; + UInt32 MainOutStream; + UInt32 PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX]; + CSzBindPair BindPairs[SZ_NUM_BINDS_IN_FOLDER_MAX]; + CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX]; + UInt64 CodersUnpackSizes[SZ_NUM_CODERS_OUT_STREAMS_IN_FOLDER_MAX]; } 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); +/* +typedef struct +{ + size_t CodersDataOffset; + size_t UnpackSizeDataOffset; + // UInt32 StartCoderUnpackSizesIndex; + UInt32 StartPackStreamIndex; + // UInt32 IndexOfMainOutStream; +} CSzFolder2; +*/ -SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes, - ILookInStream *stream, UInt64 startPos, - Byte *outBuffer, size_t outSize, ISzAlloc *allocMain); +SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd, CSzData *sdSizes); typedef struct { @@ -93,35 +74,46 @@ typedef struct 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); + Byte *Defs; /* MSB 0 bit numbering */ + UInt32 *Vals; +} CSzBitUi32s; + +typedef struct +{ + Byte *Defs; /* MSB 0 bit numbering */ + // UInt64 *Vals; + CNtfsFileTime *Vals; +} CSzBitUi64s; + +#define SzBitArray_Check(p, i) (((p)[(i) >> 3] & (0x80 >> ((i) & 7))) != 0) + +#define SzBitWithVals_Check(p, i) ((p)->Defs && ((p)->Defs[(i) >> 3] & (0x80 >> ((i) & 7))) != 0) typedef struct { - UInt64 *PackSizes; - Byte *PackCRCsDefined; - UInt32 *PackCRCs; - CSzFolder *Folders; - CSzFileItem *Files; UInt32 NumPackStreams; UInt32 NumFolders; - UInt32 NumFiles; + + UInt64 *PackPositions; // NumPackStreams + 1 + CSzBitUi32s FolderCRCs; + + size_t *FoCodersOffsets; + size_t *FoSizesOffsets; + // UInt32 StartCoderUnpackSizesIndex; + UInt32 *FoStartPackStreamIndex; + + // CSzFolder2 *Folders; // +1 item for sum values + Byte *CodersData; + Byte *UnpackSizesData; + size_t UnpackSizesDataSize; + // UInt64 *CoderUnpackSizes; } CSzAr; -void SzAr_Init(CSzAr *p); -void SzAr_Free(CSzAr *p, ISzAlloc *alloc); +SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex, + ILookInStream *stream, UInt64 startPos, + Byte *outBuffer, size_t outSize, + ISzAlloc *allocMain); /* SzExtract extracts file from archive @@ -146,19 +138,34 @@ void SzAr_Free(CSzAr *p, ISzAlloc *alloc); typedef struct { CSzAr db; - + UInt64 startPosAfterHeader; UInt64 dataPos; + + UInt32 NumFiles; + + UInt64 *UnpackPositions; + // Byte *IsEmptyFiles; + Byte *IsDirs; + CSzBitUi32s CRCs; - UInt32 *FolderStartPackStreamIndex; - UInt64 *PackStreamStartPositions; - UInt32 *FolderStartFileIndex; + CSzBitUi32s Attribs; + // CSzBitUi32s Parents; + CSzBitUi64s MTime; + CSzBitUi64s CTime; + + // UInt32 *FolderStartPackStreamIndex; + UInt32 *FolderStartFileIndex; // + 1 UInt32 *FileIndexToFolderIndexMap; size_t *FileNameOffsets; /* in 2-byte steps */ - CBuf FileNames; /* UTF-16-LE */ + Byte *FileNames; /* UTF-16-LE */ } CSzArEx; +#define SzArEx_IsDir(p, i) (SzBitArray_Check((p)->IsDirs, i)) + +#define SzArEx_GetFileSize(p, i) ((p)->UnpackPositions[(i) + 1] - (p)->UnpackPositions[i]) + void SzArEx_Init(CSzArEx *p); void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc); UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder); @@ -172,6 +179,11 @@ if dest != NULL, the return value specifies the number of 16-bit characters that size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest); +/* +size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex); +UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest); +*/ + SRes SzArEx_Extract( const CSzArEx *db, ILookInStream *inStream, @@ -196,7 +208,8 @@ SZ_ERROR_INPUT_EOF SZ_ERROR_FAIL */ -SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp); +SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, + ISzAlloc *allocMain, ISzAlloc *allocTemp); EXTERN_C_END diff --git a/C/7zAlloc.c b/C/7zAlloc.c old mode 100755 new mode 100644 index 964b28db..97cea299 --- a/C/7zAlloc.c +++ b/C/7zAlloc.c @@ -1,6 +1,8 @@ /* 7zAlloc.c -- Allocation functions 2010-10-29 : Igor Pavlov : Public domain */ +#include "Precomp.h" + #include "7zAlloc.h" /* #define _SZ_ALLOC_DEBUG */ diff --git a/C/7zAlloc.h b/C/7zAlloc.h old mode 100755 new mode 100644 diff --git a/C/7zArcIn.c b/C/7zArcIn.c new file mode 100644 index 00000000..cdca6564 --- /dev/null +++ b/C/7zArcIn.c @@ -0,0 +1,1839 @@ +/* 7zArcIn.c -- 7z Input functions +2014-06-16 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "7z.h" +#include "7zBuf.h" +#include "7zCrc.h" +#include "CpuArch.h" + +#define MY_ALLOC(T, p, size, alloc) { if ((size) == 0) p = 0; else \ + if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == 0) return SZ_ERROR_MEM; } + +#define k7zMajorVersion 0 + +enum EIdEnum +{ + k7zIdEnd, + k7zIdHeader, + k7zIdArchiveProperties, + k7zIdAdditionalStreamsInfo, + k7zIdMainStreamsInfo, + k7zIdFilesInfo, + k7zIdPackInfo, + k7zIdUnpackInfo, + k7zIdSubStreamsInfo, + k7zIdSize, + k7zIdCRC, + k7zIdFolder, + k7zIdCodersUnpackSize, + k7zIdNumUnpackStream, + k7zIdEmptyStream, + k7zIdEmptyFile, + k7zIdAnti, + k7zIdName, + k7zIdCTime, + k7zIdATime, + k7zIdMTime, + k7zIdWinAttrib, + k7zIdComment, + k7zIdEncodedHeader, + k7zIdStartPos, + k7zIdDummy + // k7zNtSecure, + // k7zParent, + // k7zIsReal +}; + +Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; + +#define NUM_FOLDER_CODERS_MAX 32 +#define NUM_CODER_STREAMS_MAX 32 + +/* +static int SzFolder_FindBindPairForInStream(const CSzFolder *p, UInt32 inStreamIndex) +{ + UInt32 i; + for (i = 0; i < p->NumBindPairs; i++) + if (p->BindPairs[i].InIndex == inStreamIndex) + return i; + return -1; +} +*/ + +#define SzBitUi32s_Init(p) { (p)->Defs = 0; (p)->Vals = 0; } + +static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAlloc *alloc) +{ + MY_ALLOC(Byte, p->Defs, (num + 7) >> 3, alloc); + MY_ALLOC(UInt32, p->Vals, num, alloc); + return SZ_OK; +} + +void SzBitUi32s_Free(CSzBitUi32s *p, ISzAlloc *alloc) +{ + IAlloc_Free(alloc, p->Defs); p->Defs = 0; + IAlloc_Free(alloc, p->Vals); p->Vals = 0; +} + +#define SzBitUi64s_Init(p) { (p)->Defs = 0; (p)->Vals = 0; } + +void SzBitUi64s_Free(CSzBitUi64s *p, ISzAlloc *alloc) +{ + IAlloc_Free(alloc, p->Defs); p->Defs = 0; + IAlloc_Free(alloc, p->Vals); p->Vals = 0; +} + +static void SzAr_Init(CSzAr *p) +{ + p->NumPackStreams = 0; + p->NumFolders = 0; + p->PackPositions = 0; + SzBitUi32s_Init(&p->FolderCRCs); + // p->Folders = 0; + p->FoCodersOffsets = 0; + p->FoSizesOffsets = 0; + p->FoStartPackStreamIndex = 0; + + p->CodersData = 0; + // p->CoderUnpackSizes = 0; + p->UnpackSizesData = 0; +} + +static void SzAr_Free(CSzAr *p, ISzAlloc *alloc) +{ + IAlloc_Free(alloc, p->UnpackSizesData); + IAlloc_Free(alloc, p->CodersData); + // IAlloc_Free(alloc, p->CoderUnpackSizes); + + IAlloc_Free(alloc, p->PackPositions); + + // IAlloc_Free(alloc, p->Folders); + IAlloc_Free(alloc, p->FoCodersOffsets); + IAlloc_Free(alloc, p->FoSizesOffsets); + IAlloc_Free(alloc, p->FoStartPackStreamIndex); + + SzBitUi32s_Free(&p->FolderCRCs, alloc); + + SzAr_Init(p); +} + + +void SzArEx_Init(CSzArEx *p) +{ + SzAr_Init(&p->db); + p->NumFiles = 0; + p->dataPos = 0; + // p->Files = 0; + p->UnpackPositions = 0; + // p->IsEmptyFiles = 0; + p->IsDirs = 0; + // p->FolderStartPackStreamIndex = 0; + // p->PackStreamStartPositions = 0; + p->FolderStartFileIndex = 0; + p->FileIndexToFolderIndexMap = 0; + p->FileNameOffsets = 0; + p->FileNames = 0; + SzBitUi32s_Init(&p->CRCs); + SzBitUi32s_Init(&p->Attribs); + // SzBitUi32s_Init(&p->Parents); + SzBitUi64s_Init(&p->MTime); + SzBitUi64s_Init(&p->CTime); +} + +void SzArEx_Free(CSzArEx *p, 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); + IAlloc_Free(alloc, p->FileNames); + + SzBitUi64s_Free(&p->CTime, alloc); + SzBitUi64s_Free(&p->MTime, alloc); + SzBitUi32s_Free(&p->CRCs, alloc); + // SzBitUi32s_Free(&p->Parents, alloc); + SzBitUi32s_Free(&p->Attribs, alloc); + IAlloc_Free(alloc, p->IsDirs); + // IAlloc_Free(alloc, p->IsEmptyFiles); + IAlloc_Free(alloc, p->UnpackPositions); + // IAlloc_Free(alloc, p->Files); + + SzAr_Free(&p->db, alloc); + SzArEx_Init(p); +} + +static int TestSignatureCandidate(Byte *testBytes) +{ + size_t i; + for (i = 0; i < k7zSignatureSize; i++) + if (testBytes[i] != k7zSignature[i]) + return 0; + return 1; +} + +#define SzData_Clear(p) { (p)->Data = 0; (p)->Size = 0; } + +static SRes SzReadByte(CSzData *sd, Byte *b) +{ + if (sd->Size == 0) + return SZ_ERROR_ARCHIVE; + sd->Size--; + *b = *sd->Data++; + return SZ_OK; +} + +#define SZ_READ_BYTE_SD(_sd_, dest) if ((_sd_)->Size == 0) return SZ_ERROR_ARCHIVE; (_sd_)->Size--; dest = *(_sd_)->Data++; +#define SZ_READ_BYTE(dest) SZ_READ_BYTE_SD(sd, dest) +#define SZ_READ_BYTE_2(dest) if (sd.Size == 0) return SZ_ERROR_ARCHIVE; sd.Size--; dest = *sd.Data++; + +#define SKIP_DATA(sd, size) { sd->Size -= (size_t)(size); sd->Data += (size_t)(size); } +#define SKIP_DATA2(sd, size) { sd.Size -= (size_t)(size); sd.Data += (size_t)(size); } + +#define SZ_READ_32(dest) if (sd.Size < 4) return SZ_ERROR_ARCHIVE; \ + dest = GetUi32(sd.Data); SKIP_DATA2(sd, 4); + +static MY_NO_INLINE SRes ReadNumber(CSzData *sd, UInt64 *value) +{ + Byte firstByte, mask; + unsigned i; + UInt32 v; + + SZ_READ_BYTE(firstByte); + if ((firstByte & 0x80) == 0) + { + *value = firstByte; + return SZ_OK; + } + SZ_READ_BYTE(v); + if ((firstByte & 0x40) == 0) + { + *value = (((UInt32)firstByte & 0x3F) << 8) | v; + return SZ_OK; + } + SZ_READ_BYTE(mask); + *value = v | ((UInt32)mask << 8); + mask = 0x20; + for (i = 2; i < 8; i++) + { + Byte b; + if ((firstByte & mask) == 0) + { + UInt64 highPart = firstByte & (mask - 1); + *value |= (highPart << (8 * i)); + return SZ_OK; + } + SZ_READ_BYTE(b); + *value |= ((UInt64)b << (8 * i)); + mask >>= 1; + } + return SZ_OK; +} + +/* +static MY_NO_INLINE const Byte *SzReadNumbers(const Byte *data, const Byte *dataLim, UInt64 *values, UInt32 num) +{ + for (; num != 0; num--) + { + Byte firstByte; + Byte mask; + + unsigned i; + UInt32 v; + UInt64 value; + + if (data == dataLim) + return NULL; + firstByte = *data++; + + if ((firstByte & 0x80) == 0) + { + *values++ = firstByte; + continue; + } + if (data == dataLim) + return NULL; + v = *data++; + if ((firstByte & 0x40) == 0) + { + *values++ = (((UInt32)firstByte & 0x3F) << 8) | v; + continue; + } + if (data == dataLim) + return NULL; + value = v | ((UInt32)*data++ << 8); + mask = 0x20; + for (i = 2; i < 8; i++) + { + if ((firstByte & mask) == 0) + { + UInt64 highPart = firstByte & (mask - 1); + value |= (highPart << (8 * i)); + break; + } + if (data == dataLim) + return NULL; + value |= ((UInt64)*data++ << (8 * i)); + mask >>= 1; + } + *values++ = value; + } + return data; +} +*/ + +static MY_NO_INLINE SRes SzReadNumber32(CSzData *sd, UInt32 *value) +{ + Byte firstByte; + UInt64 value64; + if (sd->Size == 0) + return SZ_ERROR_ARCHIVE; + firstByte = *sd->Data; + if ((firstByte & 0x80) == 0) + { + *value = firstByte; + sd->Data++; + sd->Size--; + return SZ_OK; + } + RINOK(ReadNumber(sd, &value64)); + if (value64 >= (UInt32)0x80000000 - 1) + return SZ_ERROR_UNSUPPORTED; + if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 4))) + return SZ_ERROR_UNSUPPORTED; + *value = (UInt32)value64; + return SZ_OK; +} + +#define ReadID(sd, value) ReadNumber(sd, value) + +static SRes SkipData(CSzData *sd) +{ + UInt64 size; + RINOK(ReadNumber(sd, &size)); + if (size > sd->Size) + return SZ_ERROR_ARCHIVE; + SKIP_DATA(sd, size); + return SZ_OK; +} + +static SRes WaitId(CSzData *sd, UInt64 id) +{ + for (;;) + { + UInt64 type; + RINOK(ReadID(sd, &type)); + if (type == id) + return SZ_OK; + if (type == k7zIdEnd) + return SZ_ERROR_ARCHIVE; + RINOK(SkipData(sd)); + } +} + +static SRes RememberBitVector(CSzData *sd, UInt32 numItems, const Byte **v) +{ + UInt32 numBytes = (numItems + 7) >> 3; + if (numBytes > sd->Size) + return SZ_ERROR_ARCHIVE; + *v = sd->Data; + SKIP_DATA(sd, numBytes); + return SZ_OK; +} + +static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems) +{ + Byte b = 0; + unsigned m = 0; + UInt32 sum = 0; + for (; numItems != 0; numItems--) + { + if (m == 0) + { + b = *bits++; + m = 8; + } + m--; + sum += ((b >> m) & 1); + } + return sum ; +} + +static MY_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAlloc *alloc) +{ + Byte allAreDefined; + UInt32 i; + Byte *v2; + UInt32 numBytes = (numItems + 7) >> 3; + RINOK(SzReadByte(sd, &allAreDefined)); + if (allAreDefined == 0) + { + if (numBytes > sd->Size) + return SZ_ERROR_ARCHIVE; + MY_ALLOC(Byte, *v, numBytes, alloc); + memcpy(*v, sd->Data, numBytes); + SKIP_DATA(sd, numBytes); + return SZ_OK; + } + MY_ALLOC(Byte, *v, numBytes, alloc); + v2 = *v; + for (i = 0; i < numBytes; i++) + v2[i] = 0xFF; + { + unsigned numBits = (unsigned)numItems & 7; + if (numBits != 0) + v2[numBytes - 1] = (Byte)((((UInt32)1 << numBits) - 1) << (8 - numBits)); + } + return SZ_OK; +} + +static MY_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *crcs, ISzAlloc *alloc) +{ + UInt32 i; + CSzData sd; + UInt32 *vals; + const Byte *defs; + MY_ALLOC(UInt32, crcs->Vals, numItems, alloc); + sd = *sd2; + defs = crcs->Defs; + vals = crcs->Vals; + for (i = 0; i < numItems; i++) + if (SzBitArray_Check(defs, i)) + { + SZ_READ_32(vals[i]); + } + else + vals[i] = 0; + *sd2 = sd; + return SZ_OK; +} + +static SRes ReadBitUi32s(CSzData *sd, UInt32 numItems, CSzBitUi32s *crcs, ISzAlloc *alloc) +{ + SzBitUi32s_Free(crcs, alloc); + RINOK(ReadBitVector(sd, numItems, &crcs->Defs, alloc)); + return ReadUi32s(sd, numItems, crcs, alloc); +} + +static SRes SkipBitUi32s(CSzData *sd, UInt32 numItems) +{ + Byte allAreDefined; + UInt32 numDefined = numItems; + RINOK(SzReadByte(sd, &allAreDefined)); + if (!allAreDefined) + { + size_t numBytes = (numItems + 7) >> 3; + if (numBytes > sd->Size) + return SZ_ERROR_ARCHIVE; + numDefined = CountDefinedBits(sd->Data, numItems); + SKIP_DATA(sd, numBytes); + } + if (numDefined > (sd->Size >> 2)) + return SZ_ERROR_ARCHIVE; + SKIP_DATA(sd, (size_t)numDefined * 4); + return SZ_OK; +} + +static SRes ReadPackInfo(CSzAr *p, CSzData *sd, ISzAlloc *alloc) +{ + RINOK(SzReadNumber32(sd, &p->NumPackStreams)); + + RINOK(WaitId(sd, k7zIdSize)); + MY_ALLOC(UInt64, p->PackPositions, (size_t)p->NumPackStreams + 1, alloc); + { + UInt64 sum = 0; + UInt32 i; + UInt32 numPackStreams = p->NumPackStreams; + for (i = 0; i < numPackStreams; i++) + { + UInt64 packSize; + p->PackPositions[i] = sum; + RINOK(ReadNumber(sd, &packSize)); + sum += packSize; + if (sum < packSize) + return SZ_ERROR_ARCHIVE; + } + p->PackPositions[i] = sum; + } + + for (;;) + { + UInt64 type; + RINOK(ReadID(sd, &type)); + if (type == k7zIdEnd) + return SZ_OK; + if (type == k7zIdCRC) + { + /* CRC of packed streams is unused now */ + RINOK(SkipBitUi32s(sd, p->NumPackStreams)); + continue; + } + RINOK(SkipData(sd)); + } +} + +/* +static SRes SzReadSwitch(CSzData *sd) +{ + Byte external; + RINOK(SzReadByte(sd, &external)); + return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED; +} +*/ + +#define SZ_NUM_IN_STREAMS_IN_FOLDER_MAX 16 + +SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd, CSzData *sdSizes) +{ + UInt32 numCoders, numBindPairs, numPackStreams, i; + UInt32 numInStreams = 0, numOutStreams = 0; + const Byte *dataStart = sd->Data; + Byte inStreamUsed[SZ_NUM_IN_STREAMS_IN_FOLDER_MAX]; + + RINOK(SzReadNumber32(sd, &numCoders)); + if (numCoders > SZ_NUM_CODERS_IN_FOLDER_MAX) + return SZ_ERROR_UNSUPPORTED; + f->NumCoders = numCoders; + + for (i = 0; i < numCoders; i++) + { + Byte mainByte; + CSzCoderInfo *coder = f->Coders + i; + unsigned idSize, j; + UInt64 id; + RINOK(SzReadByte(sd, &mainByte)); + if ((mainByte & 0xC0) != 0) + return SZ_ERROR_UNSUPPORTED; + idSize = (unsigned)(mainByte & 0xF); + if (idSize > sizeof(id)) + return SZ_ERROR_UNSUPPORTED; + if (idSize > sd->Size) + return SZ_ERROR_ARCHIVE; + id = 0; + for (j = 0; j < idSize; j++) + { + id = ((id << 8) | *sd->Data); + sd->Data++; + sd->Size--; + } + if (id > (UInt32)0xFFFFFFFF) + return SZ_ERROR_UNSUPPORTED; + coder->MethodID = (UInt32)id; + + coder->NumInStreams = 1; + coder->NumOutStreams = 1; + coder->PropsOffset = 0; + coder->PropsSize = 0; + + if ((mainByte & 0x10) != 0) + { + UInt32 numStreams; + RINOK(SzReadNumber32(sd, &numStreams)); + if (numStreams > NUM_CODER_STREAMS_MAX) + return SZ_ERROR_UNSUPPORTED; + coder->NumInStreams = (Byte)numStreams; + RINOK(SzReadNumber32(sd, &numStreams)); + if (numStreams > NUM_CODER_STREAMS_MAX) + return SZ_ERROR_UNSUPPORTED; + coder->NumOutStreams = (Byte)numStreams; + } + if ((mainByte & 0x20) != 0) + { + UInt32 propsSize = 0; + RINOK(SzReadNumber32(sd, &propsSize)); + if (propsSize >= 0x40) + return SZ_ERROR_UNSUPPORTED; + if (propsSize > sd->Size) + return SZ_ERROR_ARCHIVE; + coder->PropsOffset = sd->Data - dataStart; + coder->PropsSize = (Byte)propsSize; + sd->Data += (size_t)propsSize; + sd->Size -= (size_t)propsSize; + } + numInStreams += coder->NumInStreams; + numOutStreams += coder->NumOutStreams; + } + + if (numOutStreams == 0) + return SZ_ERROR_UNSUPPORTED; + + f->NumBindPairs = numBindPairs = numOutStreams - 1; + if (numInStreams < numBindPairs) + return SZ_ERROR_ARCHIVE; + if (numInStreams > SZ_NUM_IN_STREAMS_IN_FOLDER_MAX) + return SZ_ERROR_UNSUPPORTED; + f->MainOutStream = 0; + f->NumPackStreams = numPackStreams = numInStreams - numBindPairs; + if (numPackStreams > SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX) + return SZ_ERROR_UNSUPPORTED; + for (i = 0; i < numInStreams; i++) + inStreamUsed[i] = False; + if (numBindPairs != 0) + { + Byte outStreamUsed[SZ_NUM_CODERS_OUT_STREAMS_IN_FOLDER_MAX]; + + if (numBindPairs > SZ_NUM_BINDS_IN_FOLDER_MAX) + return SZ_ERROR_UNSUPPORTED; + + for (i = 0; i < numOutStreams; i++) + outStreamUsed[i] = False; + + for (i = 0; i < numBindPairs; i++) + { + CSzBindPair *bp = f->BindPairs + i; + RINOK(SzReadNumber32(sd, &bp->InIndex)); + if (bp->InIndex >= numInStreams) + return SZ_ERROR_ARCHIVE; + inStreamUsed[bp->InIndex] = True; + RINOK(SzReadNumber32(sd, &bp->OutIndex)); + if (bp->OutIndex >= numInStreams) + return SZ_ERROR_ARCHIVE; + outStreamUsed[bp->OutIndex] = True; + } + for (i = 0; i < numOutStreams; i++) + if (!outStreamUsed[i]) + { + f->MainOutStream = i; + break; + } + if (i == numOutStreams) + return SZ_ERROR_ARCHIVE; + } + + if (numPackStreams == 1) + { + for (i = 0; i < numInStreams; i++) + if (!inStreamUsed[i]) + break; + if (i == numInStreams) + return SZ_ERROR_ARCHIVE; + f->PackStreams[0] = i; + } + else + for (i = 0; i < numPackStreams; i++) + { + RINOK(SzReadNumber32(sd, f->PackStreams + i)); + } + + for (i = 0; i < numOutStreams; i++) + { + RINOK(ReadNumber(sdSizes, f->CodersUnpackSizes + i)); + } + + return SZ_OK; +} + +static MY_NO_INLINE SRes SkipNumbers(CSzData *sd2, UInt32 num) +{ + CSzData sd; + sd = *sd2; + for (; num != 0; num--) + { + Byte firstByte, mask; + unsigned i; + SZ_READ_BYTE_2(firstByte); + if ((firstByte & 0x80) == 0) + continue; + if ((firstByte & 0x40) == 0) + { + if (sd.Size == 0) + return SZ_ERROR_ARCHIVE; + sd.Size--; + sd.Data++; + continue; + } + mask = 0x20; + for (i = 2; i < 8 && (firstByte & mask) != 0; i++) + mask >>= 1; + if (i > sd.Size) + return SZ_ERROR_ARCHIVE; + SKIP_DATA2(sd, i); + } + *sd2 = sd; + return SZ_OK; +} + +#define k_InStreamUsed_MAX 64 +#define k_OutStreamUsed_MAX 64 + +static SRes ReadUnpackInfo(CSzAr *p, + CSzData *sd2, + UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs, + ISzAlloc *alloc) +{ + CSzData sd; + Byte inStreamUsed[k_InStreamUsed_MAX]; + Byte outStreamUsed[k_OutStreamUsed_MAX]; + UInt32 fo, numFolders, numCodersOutStreams, packStreamIndex; + const Byte *startBufPtr; + Byte external; + + RINOK(WaitId(sd2, k7zIdFolder)); + RINOK(SzReadNumber32(sd2, &numFolders)); + if (p->NumFolders > numFoldersMax) + return SZ_ERROR_UNSUPPORTED; + p->NumFolders = numFolders; + + SZ_READ_BYTE_SD(sd2, external); + if (external == 0) + sd = *sd2; + else + { + UInt32 index; + SzReadNumber32(sd2, &index); + if (index >= numTempBufs) + return SZ_ERROR_ARCHIVE; + sd.Data = tempBufs[index].data; + sd.Size = tempBufs[index].size; + } + + MY_ALLOC(size_t, p->FoCodersOffsets, (size_t)numFolders + 1, alloc); + MY_ALLOC(size_t, p->FoSizesOffsets, (size_t)numFolders + 1, alloc); + MY_ALLOC(UInt32, p->FoStartPackStreamIndex, (size_t)numFolders + 1, alloc); + + startBufPtr = sd.Data; + + packStreamIndex = 0; + numCodersOutStreams = 0; + + for (fo = 0; fo < numFolders; fo++) + { + UInt32 numCoders, ci, numInStreams = 0, numOutStreams = 0; + + p->FoCodersOffsets[fo] = sd.Data - startBufPtr; + RINOK(SzReadNumber32(&sd, &numCoders)); + if (numCoders > NUM_FOLDER_CODERS_MAX) + return SZ_ERROR_UNSUPPORTED; + + for (ci = 0; ci < numCoders; ci++) + { + Byte mainByte; + unsigned idSize; + UInt32 coderInStreams, coderOutStreams; + + SZ_READ_BYTE_2(mainByte); + if ((mainByte & 0xC0) != 0) + return SZ_ERROR_UNSUPPORTED; + idSize = (mainByte & 0xF); + if (idSize > 8) + return SZ_ERROR_UNSUPPORTED; + if (idSize > sd.Size) + return SZ_ERROR_ARCHIVE; + SKIP_DATA2(sd, idSize); + + coderInStreams = 1; + coderOutStreams = 1; + if ((mainByte & 0x10) != 0) + { + RINOK(SzReadNumber32(&sd, &coderInStreams)); + RINOK(SzReadNumber32(&sd, &coderOutStreams)); + if (coderInStreams > NUM_CODER_STREAMS_MAX || + coderOutStreams > NUM_CODER_STREAMS_MAX) + return SZ_ERROR_UNSUPPORTED; + } + numInStreams += coderInStreams; + numOutStreams += coderOutStreams; + if ((mainByte & 0x20) != 0) + { + UInt32 propsSize; + RINOK(SzReadNumber32(&sd, &propsSize)); + if (propsSize > sd.Size) + return SZ_ERROR_ARCHIVE; + SKIP_DATA2(sd, propsSize); + } + } + + { + UInt32 indexOfMainStream = 0; + UInt32 numPackStreams = 1; + if (numOutStreams != 1 || numInStreams != 1) + { + UInt32 i; + UInt32 numBindPairs = numOutStreams - 1; + if (numOutStreams == 0 || numInStreams < numBindPairs) + return SZ_ERROR_ARCHIVE; + + if (numInStreams > k_InStreamUsed_MAX || + numOutStreams > k_OutStreamUsed_MAX) + return SZ_ERROR_UNSUPPORTED; + + for (i = 0; i < numInStreams; i++) + inStreamUsed[i] = False; + for (i = 0; i < numOutStreams; i++) + outStreamUsed[i] = False; + + for (i = 0; i < numBindPairs; i++) + { + UInt32 index; + RINOK(SzReadNumber32(&sd, &index)); + if (index >= numInStreams || inStreamUsed[index]) + return SZ_ERROR_ARCHIVE; + inStreamUsed[index] = True; + RINOK(SzReadNumber32(&sd, &index)); + if (index >= numInStreams || outStreamUsed[index]) + return SZ_ERROR_ARCHIVE; + outStreamUsed[index] = True; + } + + numPackStreams = numInStreams - numBindPairs; + + if (numPackStreams != 1) + for (i = 0; i < numPackStreams; i++) + { + UInt32 temp; + RINOK(SzReadNumber32(&sd, &temp)); + if (temp >= numInStreams) + return SZ_ERROR_ARCHIVE; + } + + for (i = 0; i < numOutStreams; i++) + if (!outStreamUsed[i]) + { + indexOfMainStream = i; + break; + } + + if (i == numOutStreams) + return SZ_ERROR_ARCHIVE; + } + p->FoStartPackStreamIndex[fo] = packStreamIndex; + p->FoSizesOffsets[fo] = (numOutStreams << 8) | indexOfMainStream; + numCodersOutStreams += numOutStreams; + if (numCodersOutStreams < numOutStreams) + return SZ_ERROR_UNSUPPORTED; + packStreamIndex += numPackStreams; + if (packStreamIndex < numPackStreams) + return SZ_ERROR_UNSUPPORTED; + if (packStreamIndex > p->NumPackStreams) + return SZ_ERROR_ARCHIVE; + } + } + + { + size_t dataSize = sd.Data - startBufPtr; + p->FoStartPackStreamIndex[fo] = packStreamIndex; + p->FoCodersOffsets[fo] = dataSize; + MY_ALLOC(Byte, p->CodersData, dataSize, alloc); + memcpy(p->CodersData, startBufPtr, dataSize); + } + + if (external != 0) + { + if (sd.Size != 0) + return SZ_ERROR_ARCHIVE; + sd = *sd2; + } + + RINOK(WaitId(&sd, k7zIdCodersUnpackSize)); + + // MY_ALLOC(UInt64, p->CoderUnpackSizes, (size_t)numCodersOutStreams, alloc); + { + size_t dataSize = sd.Size; + /* + UInt32 i; + for (i = 0; i < numCodersOutStreams; i++) + { + RINOK(ReadNumber(&sd, p->CoderUnpackSizes + i)); + } + */ + RINOK(SkipNumbers(&sd, numCodersOutStreams)); + dataSize -= sd.Size; + MY_ALLOC(Byte, p->UnpackSizesData, dataSize, alloc); + memcpy(p->UnpackSizesData, sd.Data - dataSize, dataSize); + p->UnpackSizesDataSize = dataSize; + /* + const Byte *data = SzReadNumbers(sd.Data, sd.Data + sd.Size, p->CoderUnpackSizes, numCodersOutStreams); + if (data == NULL) + return SZ_ERROR_ARCHIVE; + sd.Size = sd.Data + sd.Size - data; + sd.Data = data; + */ + } + + for (;;) + { + UInt64 type; + RINOK(ReadID(&sd, &type)); + if (type == k7zIdEnd) + { + *sd2 = sd; + return SZ_OK; + } + if (type == k7zIdCRC) + { + RINOK(ReadBitUi32s(&sd, numFolders, &p->FolderCRCs, alloc)); + continue; + } + RINOK(SkipData(&sd)); + } +} + +typedef struct +{ + UInt32 NumTotalSubStreams; + UInt32 NumSubDigests; + CSzData sdNumSubStreams; + CSzData sdSizes; + CSzData sdCRCs; +} CSubStreamInfo; + +#define SzUi32IndexMax (((UInt32)1 << 31) - 2) + +static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) +{ + UInt64 type = 0; + UInt32 i; + UInt32 numSubDigests = 0; + UInt32 numFolders = p->NumFolders; + UInt32 numUnpackStreams = numFolders; + UInt32 numUnpackSizesInData = 0; + + for (;;) + { + RINOK(ReadID(sd, &type)); + if (type == k7zIdNumUnpackStream) + { + ssi->sdNumSubStreams.Data = sd->Data; + numUnpackStreams = 0; + numSubDigests = 0; + for (i = 0; i < numFolders; i++) + { + UInt32 numStreams; + RINOK(SzReadNumber32(sd, &numStreams)); + if (numUnpackStreams > numUnpackStreams + numStreams) + return SZ_ERROR_UNSUPPORTED; + numUnpackStreams += numStreams; + if (numStreams != 0) + numUnpackSizesInData += (numStreams - 1); + if (numStreams != 1 || !SzBitWithVals_Check(&p->FolderCRCs, i)) + numSubDigests += numStreams; + } + ssi->sdNumSubStreams.Size = sd->Data - ssi->sdNumSubStreams.Data; + continue; + } + if (type == k7zIdCRC || type == k7zIdSize || type == k7zIdEnd) + break; + RINOK(SkipData(sd)); + } + + if (!ssi->sdNumSubStreams.Data) + { + numSubDigests = numFolders; + if (p->FolderCRCs.Defs) + numSubDigests = numFolders - CountDefinedBits(p->FolderCRCs.Defs, numFolders); + } + + ssi->NumTotalSubStreams = numUnpackStreams; + ssi->NumSubDigests = numSubDigests; + + if (type == k7zIdSize) + { + ssi->sdSizes.Data = sd->Data; + RINOK(SkipNumbers(sd, numUnpackSizesInData)); + ssi->sdSizes.Size = sd->Data - ssi->sdSizes.Data; + RINOK(ReadID(sd, &type)); + } + + for (;;) + { + if (type == k7zIdEnd) + return SZ_OK; + if (type == k7zIdCRC) + { + ssi->sdCRCs.Data = sd->Data; + RINOK(SkipBitUi32s(sd, numSubDigests)); + ssi->sdCRCs.Size = sd->Data - ssi->sdCRCs.Data; + } + else + { + RINOK(SkipData(sd)); + } + RINOK(ReadID(sd, &type)); + } +} + +static SRes SzReadStreamsInfo(CSzAr *p, + CSzData *sd, + UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs, + UInt64 *dataOffset, + CSubStreamInfo *ssi, + ISzAlloc *alloc) +{ + UInt64 type; + + SzData_Clear(&ssi->sdSizes); + SzData_Clear(&ssi->sdCRCs); + SzData_Clear(&ssi->sdNumSubStreams); + + *dataOffset = 0; + RINOK(ReadID(sd, &type)); + if (type == k7zIdPackInfo) + { + RINOK(ReadNumber(sd, dataOffset)); + RINOK(ReadPackInfo(p, sd, alloc)); + RINOK(ReadID(sd, &type)); + } + if (type == k7zIdUnpackInfo) + { + RINOK(ReadUnpackInfo(p, sd, numFoldersMax, tempBufs, numTempBufs, alloc)); + RINOK(ReadID(sd, &type)); + } + if (type == k7zIdSubStreamsInfo) + { + RINOK(ReadSubStreamsInfo(p, sd, ssi)); + RINOK(ReadID(sd, &type)); + } + else + { + ssi->NumTotalSubStreams = p->NumFolders; + // ssi->NumSubDigests = 0; + } + + return (type == k7zIdEnd ? SZ_OK : SZ_ERROR_UNSUPPORTED); +} + +static SRes SzReadAndDecodePackedStreams( + ILookInStream *inStream, + CSzData *sd, + CBuf *tempBufs, + UInt32 numFoldersMax, + UInt64 baseOffset, + CSzAr *p, + ISzAlloc *allocTemp) +{ + UInt64 dataStartPos; + UInt32 fo; + CSubStreamInfo ssi; + CSzData sdCodersUnpSizes; + + RINOK(SzReadStreamsInfo(p, sd, numFoldersMax, NULL, 0, &dataStartPos, &ssi, allocTemp)); + + dataStartPos += baseOffset; + if (p->NumFolders == 0) + return SZ_ERROR_ARCHIVE; + + sdCodersUnpSizes.Data = p->UnpackSizesData; + sdCodersUnpSizes.Size = p->UnpackSizesDataSize; + for (fo = 0; fo < p->NumFolders; fo++) + Buf_Init(tempBufs + fo); + for (fo = 0; fo < p->NumFolders; fo++) + { + CBuf *tempBuf = tempBufs + fo; + // folder = p->Folders; + // unpackSize = SzAr_GetFolderUnpackSize(p, 0); + UInt32 mix = (UInt32)p->FoSizesOffsets[fo]; + UInt32 mainIndex = mix & 0xFF; + UInt32 numOutStreams = mix >> 8; + UInt32 si; + UInt64 unpackSize = 0; + p->FoSizesOffsets[fo] = sdCodersUnpSizes.Data - p->UnpackSizesData; + for (si = 0; si < numOutStreams; si++) + { + UInt64 curSize; + RINOK(ReadNumber(&sdCodersUnpSizes, &curSize)); + if (si == mainIndex) + { + unpackSize = curSize; + break; + } + } + if (si == numOutStreams) + return SZ_ERROR_FAIL; + if ((size_t)unpackSize != unpackSize) + return SZ_ERROR_MEM; + if (!Buf_Create(tempBuf, (size_t)unpackSize, allocTemp)) + return SZ_ERROR_MEM; + } + p->FoSizesOffsets[fo] = sdCodersUnpSizes.Data - p->UnpackSizesData; + + for (fo = 0; fo < p->NumFolders; fo++) + { + const CBuf *tempBuf = tempBufs + fo; + RINOK(LookInStream_SeekTo(inStream, dataStartPos)); + RINOK(SzAr_DecodeFolder(p, fo, inStream, dataStartPos, tempBuf->data, tempBuf->size, allocTemp)); + if (SzBitWithVals_Check(&p->FolderCRCs, fo)) + if (CrcCalc(tempBuf->data, tempBuf->size) != p->FolderCRCs.Vals[fo]) + return SZ_ERROR_CRC; + } + return SZ_OK; +} + +static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size_t *offsets) +{ + size_t pos = 0; + *offsets++ = 0; + if (numFiles == 0) + return (size == 0) ? SZ_OK : SZ_ERROR_ARCHIVE; + if (data[size - 2] != 0 || data[size - 1] != 0) + return SZ_ERROR_ARCHIVE; + do + { + const Byte *p; + if (pos == size) + return SZ_ERROR_ARCHIVE; + for (p = data + pos; + #ifdef _WIN32 + *(const UInt16 *)p != 0 + #else + p[0] != 0 || p[1] != 0 + #endif + ; p += 2); + pos = p - data + 2; + *offsets++ = (pos >> 1); + } + while (--numFiles); + return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE; +} + +static MY_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num, + CSzData *sd2, + const CBuf *tempBufs, UInt32 numTempBufs, + ISzAlloc *alloc) +{ + CSzData sd; + UInt32 i; + CNtfsFileTime *vals; + Byte *defs; + Byte external; + RINOK(ReadBitVector(sd2, num, &p->Defs, alloc)); + RINOK(SzReadByte(sd2, &external)); + if (external == 0) + sd = *sd2; + else + { + UInt32 index; + SzReadNumber32(sd2, &index); + if (index >= numTempBufs) + return SZ_ERROR_ARCHIVE; + sd.Data = tempBufs[index].data; + sd.Size = tempBufs[index].size; + } + MY_ALLOC(CNtfsFileTime, p->Vals, num, alloc); + vals = p->Vals; + defs = p->Defs; + for (i = 0; i < num; i++) + if (SzBitArray_Check(defs, i)) + { + if (sd.Size < 8) + return SZ_ERROR_ARCHIVE; + vals[i].Low = GetUi32(sd.Data); + vals[i].High = GetUi32(sd.Data + 4); + SKIP_DATA2(sd, 8); + } + else + vals[i].High = vals[i].Low = 0; + if (external == 0) + *sd2 = sd; + return SZ_OK; +} + +#define NUM_ADDITIONAL_STREAMS_MAX 8 + +static SRes SzReadHeader2( + CSzArEx *p, /* allocMain */ + CSzData *sd, + // Byte **emptyStreamVector, /* allocTemp */ + // Byte **emptyFileVector, /* allocTemp */ + // Byte **lwtVector, /* allocTemp */ + ILookInStream *inStream, + CBuf *tempBufs, + UInt32 *numTempBufs, + ISzAlloc *allocMain, + ISzAlloc *allocTemp + ) +{ + UInt64 type; + UInt32 numFiles = 0; + UInt32 numEmptyStreams = 0; + UInt32 i; + CSubStreamInfo ssi; + const Byte *emptyStreams = 0; + const Byte *emptyFiles = 0; + + SzData_Clear(&ssi.sdSizes); + SzData_Clear(&ssi.sdCRCs); + SzData_Clear(&ssi.sdNumSubStreams); + + ssi.NumSubDigests = 0; + ssi.NumTotalSubStreams = 0; + + RINOK(ReadID(sd, &type)); + + if (type == k7zIdArchiveProperties) + { + for (;;) + { + UInt64 type; + RINOK(ReadID(sd, &type)); + if (type == k7zIdEnd) + break; + RINOK(SkipData(sd)); + } + RINOK(ReadID(sd, &type)); + } + + // if (type == k7zIdAdditionalStreamsInfo) return SZ_ERROR_UNSUPPORTED; + + if (type == k7zIdAdditionalStreamsInfo) + { + CSzAr tempAr; + SRes res; + UInt32 numTempFolders; + + SzAr_Init(&tempAr); + res = SzReadAndDecodePackedStreams(inStream, sd, tempBufs, NUM_ADDITIONAL_STREAMS_MAX, + p->startPosAfterHeader, &tempAr, allocTemp); + numTempFolders = tempAr.NumFolders; + SzAr_Free(&tempAr, allocTemp); + if (res != SZ_OK) + return res; + *numTempBufs = numTempFolders; + RINOK(ReadID(sd, &type)); + } + + if (type == k7zIdMainStreamsInfo) + { + RINOK(SzReadStreamsInfo(&p->db, sd, (UInt32)1 << 30, tempBufs, *numTempBufs, + &p->dataPos, &ssi, allocMain)); + p->dataPos += p->startPosAfterHeader; + RINOK(ReadID(sd, &type)); + } + + if (type == k7zIdEnd) + { + // *sd2 = sd; + return SZ_OK; + } + if (type != k7zIdFilesInfo) + return SZ_ERROR_ARCHIVE; + + RINOK(SzReadNumber32(sd, &numFiles)); + p->NumFiles = numFiles; + + for (;;) + { + UInt64 type; + UInt64 size; + RINOK(ReadID(sd, &type)); + if (type == k7zIdEnd) + break; + RINOK(ReadNumber(sd, &size)); + if (size > sd->Size) + return SZ_ERROR_ARCHIVE; + if ((UInt64)(int)type != type) + { + SKIP_DATA(sd, size); + } + else switch((int)type) + { + case k7zIdName: + { + size_t namesSize; + const Byte *namesData; + Byte external; + + SZ_READ_BYTE(external); + if (external == 0) + { + namesSize = (size_t)size - 1; + namesData = sd->Data; + } + else + { + UInt32 index; + SzReadNumber32(sd, &index); + if (index >= *numTempBufs) + return SZ_ERROR_ARCHIVE; + namesData = (tempBufs)[index].data; + namesSize = (tempBufs)[index].size; + } + + if ((namesSize & 1) != 0) + return SZ_ERROR_ARCHIVE; + MY_ALLOC(Byte, p->FileNames, namesSize, allocMain); + MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain); + memcpy(p->FileNames, namesData, namesSize); + RINOK(SzReadFileNames(p->FileNames, namesSize, numFiles, p->FileNameOffsets)) + if (external == 0) + { + SKIP_DATA(sd, namesSize); + } + break; + } + case k7zIdEmptyStream: + { + RINOK(RememberBitVector(sd, numFiles, &emptyStreams)); + numEmptyStreams = CountDefinedBits(emptyStreams, numFiles); + break; + } + case k7zIdEmptyFile: + { + RINOK(RememberBitVector(sd, numEmptyStreams, &emptyFiles)); + break; + } + case k7zIdWinAttrib: + { + Byte external; + CSzData sdSwitch; + CSzData *sdPtr; + SzBitUi32s_Free(&p->Attribs, allocMain); + RINOK(ReadBitVector(sd, numFiles, &p->Attribs.Defs, allocMain)); + + SZ_READ_BYTE(external); + if (external == 0) + sdPtr = sd; + else + { + UInt32 index; + SzReadNumber32(sd, &index); + if (index >= *numTempBufs) + return SZ_ERROR_ARCHIVE; + sdSwitch.Data = (tempBufs)[index].data; + sdSwitch.Size = (tempBufs)[index].size; + sdPtr = &sdSwitch; + } + RINOK(ReadUi32s(sdPtr, numFiles, &p->Attribs, allocMain)); + break; + } + /* + case k7zParent: + { + SzBitUi32s_Free(&p->Parents, allocMain); + RINOK(ReadBitVector(sd, numFiles, &p->Parents.Defs, allocMain)); + RINOK(SzReadSwitch(sd)); + RINOK(ReadUi32s(sd, numFiles, &p->Parents, allocMain)); + break; + } + */ + case k7zIdMTime: RINOK(ReadTime(&p->MTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)); break; + case k7zIdCTime: RINOK(ReadTime(&p->CTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)); break; + default: + { + SKIP_DATA(sd, size); + } + } + } + + if (numFiles - numEmptyStreams != ssi.NumTotalSubStreams) + return SZ_ERROR_ARCHIVE; + + for (;;) + { + UInt64 type; + RINOK(ReadID(sd, &type)); + if (type == k7zIdEnd) + break; + RINOK(SkipData(sd)); + } + + { + UInt32 emptyFileIndex = 0; + + UInt32 folderIndex = 0; + UInt32 indexInFolder = 0; + UInt64 unpackPos = 0; + const Byte *digestsDefs = 0; + const Byte *digestsVals = 0; + UInt32 digestsValsIndex = 0; + UInt32 digestIndex; + Byte allDigestsDefined = 0; + UInt32 curNumSubStreams = (UInt32)(Int32)-1; + Byte isDirMask = 0; + Byte crcMask = 0; + Byte mask = 0x80; + // size_t unpSizesOffset = 0; + CSzData sdCodersUnpSizes; + sdCodersUnpSizes.Data = p->db.UnpackSizesData; + sdCodersUnpSizes.Size = p->db.UnpackSizesDataSize; + + MY_ALLOC(UInt32, p->FolderStartFileIndex, p->db.NumFolders + 1, allocMain); + MY_ALLOC(UInt32, p->FileIndexToFolderIndexMap, p->NumFiles, allocMain); + MY_ALLOC(UInt64, p->UnpackPositions, p->NumFiles + 1, allocMain); + MY_ALLOC(Byte, p->IsDirs, (p->NumFiles + 7) >> 3, allocMain); + + RINOK(SzBitUi32s_Alloc(&p->CRCs, p->NumFiles, allocMain)); + + if (ssi.sdCRCs.Size != 0) + { + RINOK(SzReadByte(&ssi.sdCRCs, &allDigestsDefined)); + if (allDigestsDefined) + digestsVals = ssi.sdCRCs.Data; + else + { + size_t numBytes = (ssi.NumSubDigests + 7) >> 3; + digestsDefs = ssi.sdCRCs.Data; + digestsVals = digestsDefs + numBytes; + } + } + + digestIndex = 0; + for (i = 0; i < numFiles; i++, mask >>= 1) + { + if (mask == 0) + { + UInt32 byteIndex = (i - 1) >> 3; + p->IsDirs[byteIndex] = isDirMask; + p->CRCs.Defs[byteIndex] = crcMask; + isDirMask = 0; + crcMask = 0; + mask = 0x80; + } + + p->UnpackPositions[i] = unpackPos; + p->CRCs.Vals[i] = 0; + // p->CRCs.Defs[i] = 0; + if (emptyStreams && SzBitArray_Check(emptyStreams , i)) + { + if (!emptyFiles || !SzBitArray_Check(emptyFiles, emptyFileIndex)) + isDirMask |= mask; + emptyFileIndex++; + if (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 (curNumSubStreams == (UInt32)(Int32)-1); + { + curNumSubStreams = 1; + if (ssi.sdNumSubStreams.Data != 0) + { + RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &curNumSubStreams)); + } + } + if (curNumSubStreams != 0) + break; + curNumSubStreams = (UInt32)(Int32)-1; + folderIndex++; // check it + } + } + p->FileIndexToFolderIndexMap[i] = folderIndex; + if (emptyStreams && SzBitArray_Check(emptyStreams , i)) + continue; + + indexInFolder++; + if (indexInFolder >= curNumSubStreams) + { + UInt64 folderUnpackSize = 0; + UInt64 startFolderUnpackPos; + { + UInt32 mix = (UInt32)p->db.FoSizesOffsets[folderIndex]; + UInt32 mainIndex = mix & 0xFF; + UInt32 numOutStreams = mix >> 8; + UInt32 si; + p->db.FoSizesOffsets[folderIndex] = sdCodersUnpSizes.Data - p->db.UnpackSizesData; + for (si = 0; si < numOutStreams; si++) + { + UInt64 curSize; + RINOK(ReadNumber(&sdCodersUnpSizes, &curSize)); + if (si == mainIndex) + { + folderUnpackSize = curSize; + break; + } + } + if (si == numOutStreams) + return SZ_ERROR_FAIL; + } + + // UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex); + startFolderUnpackPos = p->UnpackPositions[p->FolderStartFileIndex[folderIndex]]; + if (folderUnpackSize < unpackPos - startFolderUnpackPos) + return SZ_ERROR_ARCHIVE; + unpackPos = startFolderUnpackPos + folderUnpackSize; + + if (curNumSubStreams == 1 && SzBitWithVals_Check(&p->db.FolderCRCs, i)) + { + p->CRCs.Vals[i] = p->db.FolderCRCs.Vals[folderIndex]; + crcMask |= mask; + } + else if (allDigestsDefined || (digestsDefs && SzBitArray_Check(digestsDefs, digestIndex))) + { + p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4); + digestsValsIndex++; + crcMask |= mask; + } + folderIndex++; + indexInFolder = 0; + } + else + { + UInt64 v; + RINOK(ReadNumber(&ssi.sdSizes, &v)); + unpackPos += v; + if (allDigestsDefined || (digestsDefs && SzBitArray_Check(digestsDefs, digestIndex))) + { + p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4); + digestsValsIndex++; + crcMask |= mask; + } + } + } + if (mask != 0x80) + { + UInt32 byteIndex = (i - 1) >> 3; + p->IsDirs[byteIndex] = isDirMask; + p->CRCs.Defs[byteIndex] = crcMask; + } + p->UnpackPositions[i] = unpackPos; + p->FolderStartFileIndex[folderIndex] = i; + p->db.FoSizesOffsets[folderIndex] = sdCodersUnpSizes.Data - p->db.UnpackSizesData; + } + return SZ_OK; +} + +static SRes SzReadHeader( + CSzArEx *p, + CSzData *sd, + ILookInStream *inStream, + ISzAlloc *allocMain + ,ISzAlloc *allocTemp + ) +{ + // Byte *emptyStreamVector = 0; + // Byte *emptyFileVector = 0; + // Byte *lwtVector = 0; + UInt32 i; + UInt32 numTempBufs = 0; + SRes res; + CBuf tempBufs[NUM_ADDITIONAL_STREAMS_MAX]; + + for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++) + Buf_Init(tempBufs + i); + // SzBitUi32s_Init(&digests); + + res = SzReadHeader2(p, sd, + // &emptyStreamVector, + // &emptyFileVector, + // &lwtVector, + inStream, + tempBufs, &numTempBufs, + allocMain, allocTemp + ); + + for (i = 0; i < numTempBufs; i++) + Buf_Free(tempBufs + i, allocTemp); + + // IAlloc_Free(allocTemp, emptyStreamVector); + // IAlloc_Free(allocTemp, emptyFileVector); + // IAlloc_Free(allocTemp, lwtVector); + + RINOK(res); + { + if (sd->Size != 0) + return SZ_ERROR_FAIL; + } + + return res; +} + +/* +static UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex) +{ + const CSzFolder2 *f = p->Folders + folderIndex; + + // return p->CoderUnpackSizes[f->StartCoderUnpackSizesIndex + f->IndexOfMainOutStream]; + + UInt32 si; + CSzData sdCodersUnpSizes; + sdCodersUnpSizes.Data = p->UnpackSizesData + f->UnpackSizeDataOffset; + sdCodersUnpSizes.Size = p->UnpackSizesDataSize - f->UnpackSizeDataOffset; + for (si = 0; si < numOutStreams; si++) + { + UInt64 curSize; + ReadNumber(&sdCodersUnpSizes, &curSize); + if (si == mainIndex) + return curSize; + } + return 0; +} +*/ + +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 buf; + 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(&buf, nextHeaderSizeT, allocTemp)) + return SZ_ERROR_MEM; + + res = LookInStream_Read(inStream, buf.data, nextHeaderSizeT); + if (res == SZ_OK) + { + res = SZ_ERROR_ARCHIVE; + if (CrcCalc(buf.data, nextHeaderSizeT) == nextHeaderCRC) + { + CSzData sd; + UInt64 type; + sd.Data = buf.data; + sd.Size = buf.size; + res = ReadID(&sd, &type); + if (res == SZ_OK && type == k7zIdEncodedHeader) + { + CSzAr tempAr; + CBuf tempBuf; + Buf_Init(&tempBuf); + + SzAr_Init(&tempAr); + res = SzReadAndDecodePackedStreams(inStream, &sd, &tempBuf, 1, p->startPosAfterHeader, &tempAr, allocTemp); + SzAr_Free(&tempAr, allocTemp); + + if (res != SZ_OK) + { + Buf_Free(&tempBuf, allocTemp); + } + else + { + Buf_Free(&buf, allocTemp); + buf.data = tempBuf.data; + buf.size = tempBuf.size; + sd.Data = buf.data; + sd.Size = buf.size; + res = ReadID(&sd, &type); + } + } + if (res == SZ_OK) + { + if (type == k7zIdHeader) + { + CSzData sd2; + int ttt; + for (ttt = 0; ttt < 1; ttt++) + // for (ttt = 0; ttt < 40000; ttt++) + { + SzArEx_Free(p, allocMain); + sd2 = sd; + res = SzReadHeader(p, &sd2, inStream, allocMain, allocTemp + ); + if (res != SZ_OK) + break; + } + + // res = SzReadHeader(p, &sd, allocMain, allocTemp); + } + else + res = SZ_ERROR_UNSUPPORTED; + } + } + } + Buf_Free(&buf, allocTemp); + return res; +} + +// #include + +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); + // printf ("\nrrr=%d\n", rrr); + return res; +} + +SRes SzArEx_Extract( + const CSzArEx *p, + ILookInStream *inStream, + UInt32 fileIndex, + UInt32 *blockIndex, + Byte **tempBuf, + size_t *outBufferSize, + size_t *offset, + size_t *outSizeProcessed, + ISzAlloc *allocMain, + ISzAlloc *allocTemp) +{ + UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex]; + SRes res = SZ_OK; + *offset = 0; + *outSizeProcessed = 0; + if (folderIndex == (UInt32)-1) + { + IAlloc_Free(allocMain, *tempBuf); + *blockIndex = folderIndex; + *tempBuf = 0; + *outBufferSize = 0; + return SZ_OK; + } + + if (*tempBuf == 0 || *blockIndex != folderIndex) + { + // UInt64 unpackSizeSpec = SzAr_GetFolderUnpackSize(&p->db, folderIndex); + UInt64 unpackSizeSpec = + p->UnpackPositions[p->FolderStartFileIndex[folderIndex + 1]] - + p->UnpackPositions[p->FolderStartFileIndex[folderIndex]]; + size_t unpackSize = (size_t)unpackSizeSpec; + + if (unpackSize != unpackSizeSpec) + return SZ_ERROR_MEM; + *blockIndex = folderIndex; + IAlloc_Free(allocMain, *tempBuf); + *tempBuf = 0; + + // RINOK(LookInStream_SeekTo(inStream, startOffset)); + + if (res == SZ_OK) + { + *outBufferSize = unpackSize; + if (unpackSize != 0) + { + *tempBuf = (Byte *)IAlloc_Alloc(allocMain, unpackSize); + if (*tempBuf == 0) + res = SZ_ERROR_MEM; + } + if (res == SZ_OK) + { + res = SzAr_DecodeFolder(&p->db, folderIndex, + inStream, + p->dataPos, + *tempBuf, unpackSize, allocTemp); + if (res == SZ_OK) + { + if (SzBitWithVals_Check(&p->db.FolderCRCs, folderIndex)) + { + if (CrcCalc(*tempBuf, unpackSize) != p->db.FolderCRCs.Vals[folderIndex]) + res = SZ_ERROR_CRC; + } + } + } + } + } + if (res == SZ_OK) + { + UInt64 unpackPos = p->UnpackPositions[fileIndex]; + *offset = (size_t)(unpackPos - p->UnpackPositions[p->FolderStartFileIndex[folderIndex]]); + *outSizeProcessed = (size_t)(p->UnpackPositions[fileIndex + 1] - unpackPos); + if (*offset + *outSizeProcessed > *outBufferSize) + return SZ_ERROR_FAIL; + if (SzBitWithVals_Check(&p->CRCs, fileIndex) && CrcCalc(*tempBuf + *offset, *outSizeProcessed) != p->CRCs.Vals[fileIndex]) + res = SZ_ERROR_CRC; + } + return res; +} + + +size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest) +{ + size_t offs = p->FileNameOffsets[fileIndex]; + size_t len = p->FileNameOffsets[fileIndex + 1] - offs; + if (dest != 0) + { + size_t i; + const Byte *src = p->FileNames + offs * 2; + for (i = 0; i < len; i++) + dest[i] = GetUi16(src + i * 2); + } + return len; +} + +/* +size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex) +{ + size_t len; + if (!p->FileNameOffsets) + return 1; + len = 0; + for (;;) + { + UInt32 parent = (UInt32)(Int32)-1; + len += p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex]; + if SzBitWithVals_Check(&p->Parents, fileIndex) + parent = p->Parents.Vals[fileIndex]; + if (parent == (UInt32)(Int32)-1) + return len; + fileIndex = parent; + } +} + +UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest) +{ + Bool needSlash; + if (!p->FileNameOffsets) + { + *(--dest) = 0; + return dest; + } + needSlash = False; + for (;;) + { + UInt32 parent = (UInt32)(Int32)-1; + size_t curLen = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex]; + SzArEx_GetFileNameUtf16(p, fileIndex, dest - curLen); + if (needSlash) + *(dest - 1) = '/'; + needSlash = True; + dest -= curLen; + + if SzBitWithVals_Check(&p->Parents, fileIndex) + parent = p->Parents.Vals[fileIndex]; + if (parent == (UInt32)(Int32)-1) + return dest; + fileIndex = parent; + } +} +*/ diff --git a/C/7zBuf.c b/C/7zBuf.c old mode 100755 new mode 100644 index 14e7f4e2..089a5c4f --- a/C/7zBuf.c +++ b/C/7zBuf.c @@ -1,7 +1,7 @@ /* 7zBuf.c -- Byte Buffer -2008-03-28 -Igor Pavlov -Public domain */ +2013-01-21 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include "7zBuf.h" diff --git a/C/7zBuf.h b/C/7zBuf.h old mode 100755 new mode 100644 index e9f2f316..65f1d7a7 --- a/C/7zBuf.h +++ b/C/7zBuf.h @@ -1,14 +1,12 @@ /* 7zBuf.h -- Byte Buffer -2009-02-07 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __7Z_BUF_H #define __7Z_BUF_H -#include "Types.h" +#include "7zTypes.h" -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN typedef struct { @@ -32,8 +30,6 @@ 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 +EXTERN_C_END #endif diff --git a/C/7zBuf2.c b/C/7zBuf2.c old mode 100755 new mode 100644 index 8d17e0dc..e14e65f4 --- a/C/7zBuf2.c +++ b/C/7zBuf2.c @@ -1,7 +1,10 @@ /* 7zBuf2.c -- Byte Buffer -2008-10-04 : Igor Pavlov : Public domain */ +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include + #include "7zBuf.h" void DynBuf_Construct(CDynBuf *p) diff --git a/C/7zCrc.c b/C/7zCrc.c old mode 100755 new mode 100644 index cd94201b..503e3591 --- a/C/7zCrc.c +++ b/C/7zCrc.c @@ -1,5 +1,7 @@ /* 7zCrc.c -- CRC32 init -2010-12-01 : Igor Pavlov : Public domain */ +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include "7zCrc.h" #include "CpuArch.h" @@ -23,7 +25,7 @@ typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table); -static CRC_FUNC g_CrcUpdate; +CRC_FUNC g_CrcUpdate; UInt32 g_CrcTable[256 * CRC_NUM_TABLES]; UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) diff --git a/C/7zCrc.h b/C/7zCrc.h old mode 100755 new mode 100644 index 38e3e5fb..8fd57958 --- a/C/7zCrc.h +++ b/C/7zCrc.h @@ -1,10 +1,10 @@ /* 7zCrc.h -- CRC32 calculation -2009-11-21 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __7Z_CRC_H #define __7Z_CRC_H -#include "Types.h" +#include "7zTypes.h" EXTERN_C_BEGIN diff --git a/C/7zCrcOpt.c b/C/7zCrcOpt.c old mode 100755 new mode 100644 index a8d42a80..ce132b5d --- a/C/7zCrcOpt.c +++ b/C/7zCrcOpt.c @@ -1,5 +1,7 @@ /* 7zCrcOpt.c -- CRC32 calculation -2010-12-01 : Igor Pavlov : Public domain */ +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include "CpuArch.h" diff --git a/C/7zDec.c b/C/7zDec.c old mode 100755 new mode 100644 index b6d80995..2c7c2cd0 --- a/C/7zDec.c +++ b/C/7zDec.c @@ -1,5 +1,7 @@ /* 7zDec.c -- Decoding from 7z folder -2010-11-02 : Igor Pavlov : Public domain */ +2014-06-16 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include @@ -63,7 +65,7 @@ static Byte ReadByte(void *pp) return 0; } -static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, +static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream, Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) { CPpmd7 ppmd; @@ -77,12 +79,12 @@ static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inSt s.res = SZ_OK; s.processed = 0; - if (coder->Props.size != 5) + if (propsSize != 5) return SZ_ERROR_UNSUPPORTED; { - unsigned order = coder->Props.data[0]; - UInt32 memSize = GetUi32(coder->Props.data + 1); + unsigned order = props[0]; + UInt32 memSize = GetUi32(props + 1); if (order < PPMD7_MIN_ORDER || order > PPMD7_MAX_ORDER || memSize < PPMD7_MIN_MEM_SIZE || @@ -124,14 +126,14 @@ static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inSt #endif -static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, +static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, 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)); + RINOK(LzmaDec_AllocateProbs(&state, props, propsSize, allocMain)); state.dic = outBuffer; state.dicBufSize = outSize; LzmaDec_Init(&state); @@ -172,16 +174,16 @@ static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inSt return res; } -static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, +static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream, Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) { CLzma2Dec state; SRes res = SZ_OK; Lzma2Dec_Construct(&state); - if (coder->Props.size != 1) + if (propsSize != 1) return SZ_ERROR_DATA; - RINOK(Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain)); + RINOK(Lzma2Dec_AllocateProbs(&state, props[0], allocMain)); state.decoder.dic = outBuffer; state.decoder.dicBufSize = outSize; Lzma2Dec_Init(&state); @@ -242,7 +244,7 @@ static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer static Bool IS_MAIN_METHOD(UInt32 m) { - switch(m) + switch (m) { case k_Copy: case k_LZMA: @@ -260,7 +262,7 @@ static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c) return c->NumInStreams == 1 && c->NumOutStreams == 1 && - c->MethodID <= (UInt32)0xFFFFFFFF && + /* c->MethodID <= (UInt32)0xFFFFFFFF && */ IS_MAIN_METHOD((UInt32)c->MethodID); } @@ -280,8 +282,9 @@ static SRes CheckSupportedFolder(const CSzFolder *f) } if (f->NumCoders == 2) { - CSzCoderInfo *c = &f->Coders[1]; - if (c->MethodID > (UInt32)0xFFFFFFFF || + const CSzCoderInfo *c = &f->Coders[1]; + if ( + /* c->MethodID > (UInt32)0xFFFFFFFF || */ c->NumInStreams != 1 || c->NumOutStreams != 1 || f->NumPackStreams != 1 || @@ -321,18 +324,12 @@ static SRes CheckSupportedFolder(const CSzFolder *f) 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, +static SRes SzFolder_Decode2(const CSzFolder *folder, + const Byte *propsData, + const UInt64 *unpackSizes, + const UInt64 *packPositions, ILookInStream *inStream, UInt64 startPos, Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, Byte *tempBuf[]) @@ -346,7 +343,7 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes, for (ci = 0; ci < folder->NumCoders; ci++) { - CSzCoderInfo *coder = &folder->Coders[ci]; + const CSzCoderInfo *coder = &folder->Coders[ci]; if (IS_MAIN_METHOD((UInt32)coder->MethodID)) { @@ -358,7 +355,7 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes, if (folder->NumCoders == 4) { UInt32 indices[] = { 3, 2, 0 }; - UInt64 unpackSize = folder->UnpackSizes[ci]; + UInt64 unpackSize = unpackSizes[ci]; si = indices[ci]; if (ci < 2) { @@ -382,8 +379,8 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes, else return SZ_ERROR_UNSUPPORTED; } - offset = GetSum(packSizes, si); - inSize = packSizes[si]; + offset = packPositions[si]; + inSize = packPositions[si + 1] - offset; RINOK(LookInStream_SeekTo(inStream, startPos + offset)); if (coder->MethodID == k_Copy) @@ -394,16 +391,16 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes, } else if (coder->MethodID == k_LZMA) { - RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); + RINOK(SzDecodeLzma(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); } else if (coder->MethodID == k_LZMA2) { - RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); + RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); } else { #ifdef _7ZIP_PPMD_SUPPPORT - RINOK(SzDecodePpmd(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); + RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); #else return SZ_ERROR_UNSUPPORTED; #endif @@ -411,8 +408,8 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes, } else if (coder->MethodID == k_BCJ2) { - UInt64 offset = GetSum(packSizes, 1); - UInt64 s3Size = packSizes[1]; + UInt64 offset = packPositions[1]; + UInt64 s3Size = packPositions[2] - offset; SRes res; if (ci != 3) return SZ_ERROR_UNSUPPORTED; @@ -438,7 +435,7 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes, { if (ci != 1) return SZ_ERROR_UNSUPPORTED; - switch(coder->MethodID) + switch (coder->MethodID) { case k_BCJ: { @@ -456,15 +453,41 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes, return SZ_OK; } -SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes, +SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex, ILookInStream *inStream, UInt64 startPos, - Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) + 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; + SRes res; + CSzFolder folder; + CSzData sd; + CSzData sdSizes; + + const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex]; + sd.Data = data; + sd.Size = p->FoCodersOffsets[folderIndex + 1] - p->FoCodersOffsets[folderIndex]; + + sdSizes.Data = p->UnpackSizesData + p->FoSizesOffsets[folderIndex]; + sdSizes.Size = + p->FoSizesOffsets[folderIndex + 1] - + p->FoSizesOffsets[folderIndex]; + + res = SzGetNextFolderItem(&folder, &sd, &sdSizes); + + if (res != SZ_OK) + return res; + + if (sd.Size != 0 || outSize != folder.CodersUnpackSizes[folder.MainOutStream]) + return SZ_ERROR_FAIL; + { + int i; + Byte *tempBuf[3] = { 0, 0, 0}; + res = SzFolder_Decode2(&folder, data, folder.CodersUnpackSizes, + p->PackPositions + p->FoStartPackStreamIndex[folderIndex], + 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 old mode 100755 new mode 100644 index a66c9e9d..041e5b15 --- a/C/7zFile.c +++ b/C/7zFile.c @@ -1,6 +1,8 @@ /* 7zFile.c -- File IO 2009-11-24 : Igor Pavlov : Public domain */ +#include "Precomp.h" + #include "7zFile.h" #ifndef USE_WINDOWS_FILE diff --git a/C/7zFile.h b/C/7zFile.h old mode 100755 new mode 100644 index 84538c03..658987ed --- a/C/7zFile.h +++ b/C/7zFile.h @@ -1,5 +1,5 @@ /* 7zFile.h -- File IO -2009-11-24 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __7Z_FILE_H #define __7Z_FILE_H @@ -14,7 +14,7 @@ #include #endif -#include "Types.h" +#include "7zTypes.h" EXTERN_C_BEGIN diff --git a/C/7zIn.c b/C/7zIn.c deleted file mode 100755 index ec93a43f..00000000 --- a/C/7zIn.c +++ /dev/null @@ -1,1402 +0,0 @@ -/* 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 old mode 100755 new mode 100644 index 0ebb7b5f..88f9c42b --- a/C/7zStream.c +++ b/C/7zStream.c @@ -1,9 +1,11 @@ /* 7zStream.c -- 7z Stream functions -2010-03-11 : Igor Pavlov : Public domain */ +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include -#include "Types.h" +#include "7zTypes.h" SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType) { diff --git a/C/7zTypes.h b/C/7zTypes.h new file mode 100644 index 00000000..778413ef --- /dev/null +++ b/C/7zTypes.h @@ -0,0 +1,256 @@ +/* 7zTypes.h -- Basic types +2013-11-12 : Igor Pavlov : Public domain */ + +#ifndef __7Z_TYPES_H +#define __7Z_TYPES_H + +#ifdef _WIN32 +/* #include */ +#endif + +#include + +#ifndef EXTERN_C_BEGIN +#ifdef __cplusplus +#define EXTERN_C_BEGIN extern "C" { +#define EXTERN_C_END } +#else +#define EXTERN_C_BEGIN +#define EXTERN_C_END +#endif +#endif + +EXTERN_C_BEGIN + +#define SZ_OK 0 + +#define SZ_ERROR_DATA 1 +#define SZ_ERROR_MEM 2 +#define SZ_ERROR_CRC 3 +#define SZ_ERROR_UNSUPPORTED 4 +#define SZ_ERROR_PARAM 5 +#define SZ_ERROR_INPUT_EOF 6 +#define SZ_ERROR_OUTPUT_EOF 7 +#define SZ_ERROR_READ 8 +#define SZ_ERROR_WRITE 9 +#define SZ_ERROR_PROGRESS 10 +#define SZ_ERROR_FAIL 11 +#define SZ_ERROR_THREAD 12 + +#define SZ_ERROR_ARCHIVE 16 +#define SZ_ERROR_NO_ARCHIVE 17 + +typedef int SRes; + +#ifdef _WIN32 +/* typedef DWORD WRes; */ +typedef unsigned WRes; +#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_NO_INLINE +#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/7zVersion.h b/C/7zVersion.h old mode 100755 new mode 100644 index 5a83e5f7..e0fa2412 --- a/C/7zVersion.h +++ b/C/7zVersion.h @@ -1,8 +1,10 @@ #define MY_VER_MAJOR 9 -#define MY_VER_MINOR 22 +#define MY_VER_MINOR 34 #define MY_VER_BUILD 00 -#define MY_VERSION "9.22 beta" -#define MY_7ZIP_VERSION "9.22 beta" -#define MY_DATE "2011-04-18" +#define MY_VERSION "9.34 alpha" +// #define MY_7ZIP_VERSION "9.34 alpha" +#define MY_DATE "2014-06-22" +#undef MY_COPYRIGHT +#undef MY_VERSION_COPYRIGHT_DATE #define MY_COPYRIGHT ": Igor Pavlov : Public domain" #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE diff --git a/C/7zVersion.rc b/C/7zVersion.rc old mode 100755 new mode 100644 diff --git a/C/Aes.c b/C/Aes.c old mode 100755 new mode 100644 index e7221cd2..6c49dc98 --- a/C/Aes.c +++ b/C/Aes.c @@ -1,5 +1,7 @@ /* Aes.c -- AES encryption / decryption -2009-11-23 : Igor Pavlov : Public domain */ +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include "Aes.h" #include "CpuArch.h" diff --git a/C/Aes.h b/C/Aes.h old mode 100755 new mode 100644 index c9b0677c..64979b5b --- a/C/Aes.h +++ b/C/Aes.h @@ -1,10 +1,10 @@ /* Aes.h -- AES encryption / decryption -2009-11-23 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __AES_H #define __AES_H -#include "Types.h" +#include "7zTypes.h" EXTERN_C_BEGIN diff --git a/C/AesOpt.c b/C/AesOpt.c old mode 100755 new mode 100644 index 60cfd86d..10a8fb25 --- a/C/AesOpt.c +++ b/C/AesOpt.c @@ -1,5 +1,7 @@ /* AesOpt.c -- Intel's AES -2009-11-23 : Igor Pavlov : Public domain */ +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include "CpuArch.h" diff --git a/C/Alloc.c b/C/Alloc.c old mode 100755 new mode 100644 index 358a7b52..a9a69575 --- a/C/Alloc.c +++ b/C/Alloc.c @@ -1,7 +1,7 @@ /* Alloc.c -- Memory allocation functions -2008-09-24 -Igor Pavlov -Public domain */ +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #ifdef _WIN32 #include diff --git a/C/Alloc.h b/C/Alloc.h old mode 100755 new mode 100644 diff --git a/C/Bcj2.c b/C/Bcj2.c old mode 100755 new mode 100644 index 20199ce5..4e81cdc2 --- a/C/Bcj2.c +++ b/C/Bcj2.c @@ -1,6 +1,8 @@ /* Bcj2.c -- Converter for x86 code (BCJ2) 2008-10-04 : Igor Pavlov : Public domain */ +#include "Precomp.h" + #include "Bcj2.h" #ifdef _LZMA_PROB32 diff --git a/C/Bcj2.h b/C/Bcj2.h old mode 100755 new mode 100644 index dbc05414..1db8ea0a --- a/C/Bcj2.h +++ b/C/Bcj2.h @@ -1,14 +1,12 @@ /* Bcj2.h -- Converter for x86 code (BCJ2) -2009-02-07 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __BCJ2_H #define __BCJ2_H -#include "Types.h" +#include "7zTypes.h" -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN /* Conditions: @@ -31,8 +29,6 @@ int Bcj2_Decode( const Byte *buf3, SizeT size3, Byte *outBuf, SizeT outSize); -#ifdef __cplusplus -} -#endif +EXTERN_C_END #endif diff --git a/C/Bra.c b/C/Bra.c old mode 100755 new mode 100644 index 2e47b141..cdb94569 --- a/C/Bra.c +++ b/C/Bra.c @@ -1,6 +1,8 @@ /* Bra.c -- Converters for RISC code 2010-04-16 : Igor Pavlov : Public domain */ +#include "Precomp.h" + #include "Bra.h" SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) diff --git a/C/Bra.h b/C/Bra.h old mode 100755 new mode 100644 index 5748c1c0..855e37a6 --- a/C/Bra.h +++ b/C/Bra.h @@ -1,14 +1,12 @@ /* Bra.h -- Branch converters for executables -2009-02-07 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __BRA_H #define __BRA_H -#include "Types.h" +#include "7zTypes.h" -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN /* These functions convert relative addresses to absolute addresses @@ -61,8 +59,6 @@ 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 +EXTERN_C_END #endif diff --git a/C/Bra86.c b/C/Bra86.c old mode 100755 new mode 100644 index 1ee0e709..6db15e7e --- a/C/Bra86.c +++ b/C/Bra86.c @@ -1,85 +1,82 @@ /* Bra86.c -- Converter for x86 code (BCJ) -2008-10-04 : Igor Pavlov : Public domain */ +2013-11-12 : Igor Pavlov : Public domain */ -#include "Bra.h" +#include "Precomp.h" -#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) +#include "Bra.h" -const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; -const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; +#define Test86MSByte(b) ((((b) + 1) & 0xFE) == 0) SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) { - SizeT bufferPos = 0, prevPosT; - UInt32 prevMask = *state & 0x7; + SizeT pos = 0; + UInt32 mask = *state & 7; if (size < 5) return 0; + size -= 4; ip += 5; - prevPosT = (SizeT)0 - 1; for (;;) { - Byte *p = data + bufferPos; - Byte *limit = data + size - 4; + Byte *p = data + pos; + const Byte *limit = data + size; 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) + SizeT d = (SizeT)(p - data - pos); + pos = (SizeT)(p - data); + if (p >= limit) { - Byte b = p[4 - kMaskToBitNumber[prevMask]]; - if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b)) + *state = (d > 2 ? 0 : mask >> (unsigned)d); + return pos; + } + if (d > 2) + mask = 0; + else + { + mask >>= (unsigned)d; + if (mask != 0 && (mask > 4 || mask == 3 || Test86MSByte(p[(mask >> 1) + 1]))) { - prevPosT = bufferPos; - prevMask = ((prevMask << 1) & 0x7) | 1; - bufferPos++; + mask = (mask >> 1) | 4; + pos++; 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 (;;) + UInt32 v = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); + UInt32 cur = ip + (UInt32)pos; + pos += 5; + if (encoding) + v += cur; + else + v -= cur; + if (mask != 0) { - 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); + unsigned sh = (mask & 6) << 2; + if (Test86MSByte((Byte)(v >> sh))) + { + v ^= (((UInt32)0x100 << sh) - 1); + if (encoding) + v += cur; + else + v -= cur; + } + mask = 0; } - p[4] = (Byte)(~(((dest >> 24) & 1) - 1)); - p[3] = (Byte)(dest >> 16); - p[2] = (Byte)(dest >> 8); - p[1] = (Byte)dest; - bufferPos += 5; + p[1] = (Byte)v; + p[2] = (Byte)(v >> 8); + p[3] = (Byte)(v >> 16); + p[4] = (Byte)(0 - ((v >> 24) & 1)); } else { - prevMask = ((prevMask << 1) & 0x7) | 1; - bufferPos++; + mask = (mask >> 1) | 4; + pos++; } } - prevPosT = bufferPos - prevPosT; - *state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7)); - return bufferPos; } diff --git a/C/BraIA64.c b/C/BraIA64.c old mode 100755 new mode 100644 index 0b4ee85b..fa60356b --- a/C/BraIA64.c +++ b/C/BraIA64.c @@ -1,5 +1,7 @@ /* BraIA64.c -- Converter for IA-64 code -2008-10-04 : Igor Pavlov : Public domain */ +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include "Bra.h" diff --git a/C/BwtSort.c b/C/BwtSort.c old mode 100755 new mode 100644 index 20730507..f5c61769 --- a/C/BwtSort.c +++ b/C/BwtSort.c @@ -1,7 +1,7 @@ /* BwtSort.c -- BWT block sorting -2008-08-17 -Igor Pavlov -Public domain */ +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include "BwtSort.h" #include "Sort.h" diff --git a/C/BwtSort.h b/C/BwtSort.h old mode 100755 new mode 100644 index ce5598f0..7e989a99 --- a/C/BwtSort.h +++ b/C/BwtSort.h @@ -1,14 +1,12 @@ /* BwtSort.h -- BWT block sorting -2009-02-07 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __BWT_SORT_H #define __BWT_SORT_H -#include "Types.h" +#include "7zTypes.h" -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN /* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize can be > 1M */ /* #define BLOCK_SORT_EXTERNAL_FLAGS */ @@ -23,8 +21,6 @@ extern "C" { UInt32 BlockSort(UInt32 *indices, const Byte *data, UInt32 blockSize); -#ifdef __cplusplus -} -#endif +EXTERN_C_END #endif diff --git a/C/Compiler.h b/C/Compiler.h new file mode 100644 index 00000000..6e964897 --- /dev/null +++ b/C/Compiler.h @@ -0,0 +1,28 @@ +/* Compiler.h -- Compiler ypes +2013-11-12 : Igor Pavlov : Public domain */ + +#ifndef __7Z_COMPILER_H +#define __7Z_COMPILER_H + +#ifdef _MSC_VER + + #ifdef UNDER_CE + #define RPC_NO_WINDOWS_H + /* #pragma warning(disable : 4115) // '_RPC_ASYNC_STATE' : named type definition in parentheses */ + #pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union + #pragma warning(disable : 4214) // nonstandard extension used : bit field types other than int + #endif + + #if _MSC_VER >= 1300 + #pragma warning(disable : 4996) // This function or variable may be unsafe + #else + #pragma warning(disable : 4511) // copy constructor could not be generated + #pragma warning(disable : 4512) // assignment operator could not be generated + #pragma warning(disable : 4702) // unreachable code + #pragma warning(disable : 4710) // not inlined + #pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information + #endif + +#endif + +#endif diff --git a/C/CpuArch.c b/C/CpuArch.c old mode 100755 new mode 100644 index 260cc1f4..d7f8b1d8 --- a/C/CpuArch.c +++ b/C/CpuArch.c @@ -1,5 +1,7 @@ /* CpuArch.c -- CPU specific code -2010-10-26: Igor Pavlov : Public domain */ +2012-05-29: Igor Pavlov : Public domain */ + +#include "Precomp.h" #include "CpuArch.h" @@ -9,6 +11,10 @@ #define USE_ASM #endif +#if !defined(USE_ASM) && _MSC_VER >= 1500 +#include +#endif + #if defined(USE_ASM) && !defined(MY_CPU_AMD64) static UInt32 CheckFlag(UInt32 flag) { @@ -73,9 +79,17 @@ static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) #else __asm__ __volatile__ ( + #if defined(MY_CPU_X86) && defined(__PIC__) + "mov %%ebx, %%edi;" + "cpuid;" + "xchgl %%ebx, %%edi;" + : "=a" (*a) , + "=D" (*b) , + #else "cpuid" : "=a" (*a) , "=b" (*b) , + #endif "=c" (*c) , "=d" (*d) : "0" (function)) ; @@ -135,7 +149,14 @@ Bool CPU_Is_InOrder() firm = x86cpuid_GetFirm(&p); switch (firm) { - case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && model == 0x100C)); + case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && ( + /* Atom CPU */ + model == 0x100C /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */ + || model == 0x2006 /* 45 nm, Z6xx */ + || model == 0x2007 /* 32 nm, Z2460 */ + || model == 0x3005 /* 32 nm, Z2760 */ + || model == 0x3006 /* 32 nm, N2xxx, D2xxx */ + ))); case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA))); case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF)); } @@ -143,6 +164,7 @@ Bool CPU_Is_InOrder() } #if !defined(MY_CPU_AMD64) && defined(_WIN32) +#include static Bool CPU_Sys_Is_SSE_Supported() { OSVERSIONINFO vi; diff --git a/C/CpuArch.h b/C/CpuArch.h old mode 100755 new mode 100644 index e3d7af2e..4fee0093 --- a/C/CpuArch.h +++ b/C/CpuArch.h @@ -1,10 +1,10 @@ /* CpuArch.h -- CPU specific code -2010-12-01: Igor Pavlov : Public domain */ +2013-11-12: Igor Pavlov : Public domain */ #ifndef __CPU_ARCH_H #define __CPU_ARCH_H -#include "Types.h" +#include "7zTypes.h" EXTERN_C_BEGIN @@ -62,9 +62,9 @@ Stop_Compiling_Bad_Endian #ifdef MY_CPU_LE_UNALIGN -#define GetUi16(p) (*(const UInt16 *)(p)) -#define GetUi32(p) (*(const UInt32 *)(p)) -#define GetUi64(p) (*(const UInt64 *)(p)) +#define GetUi16(p) (*(const UInt16 *)(const void *)(p)) +#define GetUi32(p) (*(const UInt32 *)(const void *)(p)) +#define GetUi64(p) (*(const UInt64 *)(const void *)(p)) #define SetUi16(p, d) *(UInt16 *)(p) = (d); #define SetUi32(p, d) *(UInt32 *)(p) = (d); #define SetUi64(p, d) *(UInt64 *)(p) = (d); @@ -99,6 +99,8 @@ Stop_Compiling_Bad_Endian #if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) +#include + #pragma intrinsic(_byteswap_ulong) #pragma intrinsic(_byteswap_uint64) #define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) @@ -116,7 +118,7 @@ Stop_Compiling_Bad_Endian #endif -#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]) +#define GetBe16(p) ((UInt16)(((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1])) #ifdef MY_CPU_X86_OR_AMD64 diff --git a/C/Delta.c b/C/Delta.c old mode 100755 new mode 100644 index 2b327f15..e3edd21e --- a/C/Delta.c +++ b/C/Delta.c @@ -1,6 +1,8 @@ /* Delta.c -- Delta converter 2009-05-26 : Igor Pavlov : Public domain */ +#include "Precomp.h" + #include "Delta.h" void Delta_Init(Byte *state) diff --git a/C/Delta.h b/C/Delta.h old mode 100755 new mode 100644 index 0d4cd627..2fa54ad6 --- a/C/Delta.h +++ b/C/Delta.h @@ -1,14 +1,12 @@ /* Delta.h -- Delta converter -2009-04-15 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __DELTA_H #define __DELTA_H -#include "Types.h" +#include "7zTypes.h" -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN #define DELTA_STATE_SIZE 256 @@ -16,8 +14,6 @@ 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 +EXTERN_C_END #endif diff --git a/C/HuffEnc.c b/C/HuffEnc.c old mode 100755 new mode 100644 index 561c7e5d..db41e8d2 --- a/C/HuffEnc.c +++ b/C/HuffEnc.c @@ -1,6 +1,8 @@ /* HuffEnc.c -- functions for Huffman encoding 2009-09-02 : Igor Pavlov : Public domain */ +#include "Precomp.h" + #include "HuffEnc.h" #include "Sort.h" diff --git a/C/HuffEnc.h b/C/HuffEnc.h old mode 100755 new mode 100644 index 9cf4bfde..92b6878d --- a/C/HuffEnc.h +++ b/C/HuffEnc.h @@ -1,14 +1,12 @@ /* HuffEnc.h -- Huffman encoding -2009-02-07 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __HUFF_ENC_H #define __HUFF_ENC_H -#include "Types.h" +#include "7zTypes.h" -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN /* Conditions: @@ -20,8 +18,6 @@ Conditions: void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 num, UInt32 maxLen); -#ifdef __cplusplus -} -#endif +EXTERN_C_END #endif diff --git a/C/LzFind.c b/C/LzFind.c old mode 100755 new mode 100644 index e3ecb054..262b395b --- a/C/LzFind.c +++ b/C/LzFind.c @@ -1,6 +1,8 @@ /* LzFind.c -- Match finder for LZ algorithms 2009-04-22 : Igor Pavlov : Public domain */ +#include "Precomp.h" + #include #include "LzFind.h" diff --git a/C/LzFind.h b/C/LzFind.h old mode 100755 new mode 100644 index 010c4b92..706143d2 --- a/C/LzFind.h +++ b/C/LzFind.h @@ -1,14 +1,12 @@ /* LzFind.h -- Match finder for LZ algorithms -2009-04-22 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __LZ_FIND_H #define __LZ_FIND_H -#include "Types.h" +#include "7zTypes.h" -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN typedef UInt32 CLzRef; @@ -108,8 +106,6 @@ 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 +EXTERN_C_END #endif diff --git a/C/LzFindMt.c b/C/LzFindMt.c old mode 100755 new mode 100644 index aa41ed98..ea600bb5 --- a/C/LzFindMt.c +++ b/C/LzFindMt.c @@ -1,5 +1,7 @@ /* LzFindMt.c -- multithreaded Match finder for LZ algorithms -2009-09-20 : Igor Pavlov : Public domain */ +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include "LzHash.h" @@ -97,7 +99,7 @@ void MtSync_Destruct(CMtSync *p) #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) +static SRes MtSync_Create2(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks) { if (p->wasCreated) return SZ_OK; @@ -119,7 +121,7 @@ static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void return SZ_OK; } -static SRes MtSync_Create(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks) +static SRes MtSync_Create(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks) { SRes res = MtSync_Create2(p, startAddress, obj, numBlocks); if (res != SZ_OK) @@ -451,8 +453,8 @@ void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *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) +static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } +static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE BtThreadFunc2(void *p) { Byte allocaDummy[0x180]; int i = 0; diff --git a/C/LzFindMt.h b/C/LzFindMt.h old mode 100755 new mode 100644 index b985af5f..6a7095b0 --- a/C/LzFindMt.h +++ b/C/LzFindMt.h @@ -1,5 +1,5 @@ /* LzFindMt.h -- multithreaded Match finder for LZ algorithms -2009-02-07 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __LZ_FIND_MT_H #define __LZ_FIND_MT_H @@ -7,9 +7,7 @@ #include "LzFind.h" #include "Threads.h" -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN #define kMtHashBlockSize (1 << 13) #define kMtHashNumBlocks (1 << 3) @@ -98,8 +96,6 @@ SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddB void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable); void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); -#ifdef __cplusplus -} -#endif +EXTERN_C_END #endif diff --git a/C/LzHash.h b/C/LzHash.h old mode 100755 new mode 100644 diff --git a/C/Lzma2Dec.c b/C/Lzma2Dec.c old mode 100755 new mode 100644 index f3a6b821..502a1588 --- a/C/Lzma2Dec.c +++ b/C/Lzma2Dec.c @@ -3,6 +3,8 @@ /* #define SHOW_DEBUG_INFO */ +#include "Precomp.h" + #ifdef SHOW_DEBUG_INFO #include #endif diff --git a/C/Lzma2Dec.h b/C/Lzma2Dec.h old mode 100755 new mode 100644 index 6bc07bbc..367daf6b --- a/C/Lzma2Dec.h +++ b/C/Lzma2Dec.h @@ -1,14 +1,12 @@ /* Lzma2Dec.h -- LZMA2 Decoder -2009-05-03 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __LZMA2_DEC_H #define __LZMA2_DEC_H #include "LzmaDec.h" -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN /* ---------- State Interface ---------- */ @@ -77,8 +75,6 @@ Returns: SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc); -#ifdef __cplusplus -} -#endif +EXTERN_C_END #endif diff --git a/C/Lzma2Enc.c b/C/Lzma2Enc.c old mode 100755 new mode 100644 index e97597f6..0c8e02e9 --- a/C/Lzma2Enc.c +++ b/C/Lzma2Enc.c @@ -1,5 +1,7 @@ /* Lzma2Enc.c -- LZMA2 Encoder -2010-09-24 : Igor Pavlov : Public domain */ +2012-06-19 : Igor Pavlov : Public domain */ + +#include "Precomp.h" /* #include */ #include @@ -216,8 +218,7 @@ void Lzma2EncProps_Normalize(CLzma2EncProps *p) t3 = t1n * t2; p->lzmaProps.numThreads = t1; - p->numBlockThreads = t2; - p->numTotalThreads = t3; + LzmaEncProps_Normalize(&p->lzmaProps); if (p->blockSize == 0) @@ -231,6 +232,21 @@ void Lzma2EncProps_Normalize(CLzma2EncProps *p) if (blockSize < dictSize) blockSize = dictSize; p->blockSize = (size_t)blockSize; } + if (t2 > 1) + { + UInt64 temp = p->lzmaProps.reduceSize + p->blockSize - 1; + if (temp > p->lzmaProps.reduceSize) + { + UInt64 numBlocks = temp / p->blockSize; + if (numBlocks < t2) + { + t2 = (UInt32)numBlocks; + t3 = t1 * t2; + } + } + } + p->numBlockThreads = t2; + p->numTotalThreads = t3; } static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize) diff --git a/C/Lzma2Enc.h b/C/Lzma2Enc.h old mode 100755 new mode 100644 index 28352558..f409f184 --- a/C/Lzma2Enc.h +++ b/C/Lzma2Enc.h @@ -1,14 +1,12 @@ /* Lzma2Enc.h -- LZMA2 Encoder -2009-02-07 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __LZMA2_ENC_H #define __LZMA2_ENC_H #include "LzmaEnc.h" -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN typedef struct { @@ -59,8 +57,6 @@ SRes Lzma2Encode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); */ -#ifdef __cplusplus -} -#endif +EXTERN_C_END #endif diff --git a/C/Lzma86.h b/C/Lzma86.h old mode 100755 new mode 100644 index 6acbd888..bebed5cb --- a/C/Lzma86.h +++ b/C/Lzma86.h @@ -1,10 +1,10 @@ /* Lzma86.h -- LZMA + x86 (BCJ) Filter -2009-08-14 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __LZMA86_H #define __LZMA86_H -#include "Types.h" +#include "7zTypes.h" EXTERN_C_BEGIN diff --git a/C/Lzma86Dec.c b/C/Lzma86Dec.c old mode 100755 new mode 100644 diff --git a/C/Lzma86Enc.c b/C/Lzma86Enc.c old mode 100755 new mode 100644 index 2ea4ac2d..16467149 --- a/C/Lzma86Enc.c +++ b/C/Lzma86Enc.c @@ -99,7 +99,7 @@ int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, } } } - dest[0] = (bestIsFiltered ? 1 : 0); + dest[0] = (Byte)(bestIsFiltered ? 1 : 0); *destLen = LZMA86_HEADER_SIZE + minSize; } if (useFilter) diff --git a/C/LzmaDec.c b/C/LzmaDec.c old mode 100755 new mode 100644 index 8c1a1486..42c90bdb --- a/C/LzmaDec.c +++ b/C/LzmaDec.c @@ -1,5 +1,7 @@ /* LzmaDec.c -- LZMA Decoder -2010-12-15 : Igor Pavlov : Public domain */ +2011-09-03 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include "LzmaDec.h" @@ -44,6 +46,13 @@ i -= 0x40; } #endif +#define NORMAL_LITER_DEC GET_BIT(prob + symbol, symbol) +#define MATCHED_LITER_DEC \ + matchByte <<= 1; \ + bit = (matchByte & offs); \ + probLit = prob + offs + bit + symbol; \ + GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) + #define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } #define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) @@ -171,7 +180,18 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte { state -= (state < 4) ? state : 3; symbol = 1; - do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); + #ifdef _LZMA_SIZE_OPT + do { NORMAL_LITER_DEC } while (symbol < 0x100); + #else + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + #endif } else { @@ -179,16 +199,28 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte unsigned offs = 0x100; state -= (state < 10) ? 3 : 6; symbol = 1; + #ifdef _LZMA_SIZE_OPT do { unsigned bit; CLzmaProb *probLit; - matchByte <<= 1; - bit = (matchByte & offs); - probLit = prob + offs + bit + symbol; - GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) + MATCHED_LITER_DEC } while (symbol < 0x100); + #else + { + unsigned bit; + CLzmaProb *probLit; + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + } + #endif } dic[dicPos++] = (Byte)symbol; processedPos++; diff --git a/C/LzmaDec.h b/C/LzmaDec.h old mode 100755 new mode 100644 index bf7f084b..cc44daef --- a/C/LzmaDec.h +++ b/C/LzmaDec.h @@ -1,14 +1,12 @@ /* LzmaDec.h -- LZMA Decoder -2009-02-07 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __LZMA_DEC_H #define __LZMA_DEC_H -#include "Types.h" +#include "7zTypes.h" -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN /* #define _LZMA_PROB32 */ /* _LZMA_PROB32 can increase the speed on some CPUs, @@ -224,8 +222,6 @@ 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 +EXTERN_C_END #endif diff --git a/C/LzmaEnc.c b/C/LzmaEnc.c old mode 100755 new mode 100644 index ef26e0cf..fc7d358a --- a/C/LzmaEnc.c +++ b/C/LzmaEnc.c @@ -1,5 +1,7 @@ /* LzmaEnc.c -- LZMA Encoder -2011-01-27 : Igor Pavlov : Public domain */ +2012-11-20 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include @@ -46,7 +48,7 @@ void LzmaEncProps_Init(CLzmaEncProps *p) { p->level = 5; p->dictSize = p->mc = 0; - p->reduceSize = (UInt32)(Int32)-1; + p->reduceSize = (UInt64)(Int64)-1; p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; p->writeEndMark = 0; } @@ -60,10 +62,10 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p) if (p->dictSize > p->reduceSize) { unsigned i; - for (i = 15; i <= 30; i++) + for (i = 11; i <= 30; i++) { - if (p->reduceSize <= ((UInt32)2 << i)) { p->dictSize = ((UInt32)2 << i); break; } - if (p->reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; } + if ((UInt32)p->reduceSize <= ((UInt32)2 << i)) { p->dictSize = ((UInt32)2 << i); break; } + if ((UInt32)p->reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; } } } if (p->lc < 0) p->lc = 3; diff --git a/C/LzmaEnc.h b/C/LzmaEnc.h old mode 100755 new mode 100644 index b8d9ce77..cffe220b --- a/C/LzmaEnc.h +++ b/C/LzmaEnc.h @@ -1,10 +1,10 @@ /* LzmaEnc.h -- LZMA Encoder -2011-01-27 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __LZMA_ENC_H #define __LZMA_ENC_H -#include "Types.h" +#include "7zTypes.h" EXTERN_C_BEGIN @@ -16,7 +16,7 @@ typedef struct _CLzmaEncProps UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version (1 << 12) <= dictSize <= (1 << 30) for 64-bit version default = (1 << 24) */ - UInt32 reduceSize; /* estimated size of data that will be compressed. default = 0xFFFFFFFF. + UInt64 reduceSize; /* estimated size of data that will be compressed. default = 0xFFFFFFFF. Encoder uses this value to reduce dictionary size */ int lc; /* 0 <= lc <= 8, default = 3 */ int lp; /* 0 <= lp <= 4, default = 0 */ diff --git a/C/LzmaLib.c b/C/LzmaLib.c old mode 100755 new mode 100644 diff --git a/C/LzmaLib.h b/C/LzmaLib.h old mode 100755 new mode 100644 index 76c99ce7..88fa87d3 --- a/C/LzmaLib.h +++ b/C/LzmaLib.h @@ -1,14 +1,12 @@ /* LzmaLib.h -- LZMA library interface -2009-04-07 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __LZMA_LIB_H #define __LZMA_LIB_H -#include "Types.h" +#include "7zTypes.h" -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN #define MY_STDAPI int MY_STD_CALL @@ -128,8 +126,6 @@ Returns: 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 +EXTERN_C_END #endif diff --git a/C/MtCoder.c b/C/MtCoder.c old mode 100755 new mode 100644 index 946fbbc7..616f0b41 --- a/C/MtCoder.c +++ b/C/MtCoder.c @@ -1,6 +1,8 @@ /* MtCoder.c -- Multi-thread Coder 2010-09-24 : Igor Pavlov : Public domain */ +#include "Precomp.h" + #include #include "MtCoder.h" diff --git a/C/MtCoder.h b/C/MtCoder.h old mode 100755 new mode 100644 diff --git a/C/Ppmd.h b/C/Ppmd.h old mode 100755 new mode 100644 index 9cbc4664..4356dd1d --- a/C/Ppmd.h +++ b/C/Ppmd.h @@ -1,11 +1,10 @@ /* Ppmd.h -- PPMD codec common code -2011-01-27 : Igor Pavlov : Public domain +2013-01-18 : 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 diff --git a/C/Ppmd7.c b/C/Ppmd7.c old mode 100755 new mode 100644 index 060d86d2..bb5d175e --- a/C/Ppmd7.c +++ b/C/Ppmd7.c @@ -2,6 +2,8 @@ 2010-03-12 : Igor Pavlov : Public domain This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ +#include "Precomp.h" + #include #include "Ppmd7.h" diff --git a/C/Ppmd7.h b/C/Ppmd7.h old mode 100755 new mode 100644 diff --git a/C/Ppmd7Dec.c b/C/Ppmd7Dec.c old mode 100755 new mode 100644 index 68438d5c..04b4b09e --- a/C/Ppmd7Dec.c +++ b/C/Ppmd7Dec.c @@ -2,6 +2,8 @@ 2010-03-12 : Igor Pavlov : Public domain This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ +#include "Precomp.h" + #include "Ppmd7.h" #define kTopValue (1 << 24) diff --git a/C/Ppmd7Enc.c b/C/Ppmd7Enc.c old mode 100755 new mode 100644 index 8247757d..51c19c9f --- a/C/Ppmd7Enc.c +++ b/C/Ppmd7Enc.c @@ -2,6 +2,8 @@ 2010-03-12 : Igor Pavlov : Public domain This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ +#include "Precomp.h" + #include "Ppmd7.h" #define kTopValue (1 << 24) diff --git a/C/Ppmd8.c b/C/Ppmd8.c old mode 100755 new mode 100644 index 9187a88e..ac8a8354 --- a/C/Ppmd8.c +++ b/C/Ppmd8.c @@ -1,7 +1,9 @@ /* Ppmd8.c -- PPMdI codec -2010-03-24 : Igor Pavlov : Public domain +2013-11-12 : Igor Pavlov : Public domain This code is based on PPMd var.I (2002): Dmitry Shkarin : Public domain */ +#include "Precomp.h" + #include #include "Ppmd8.h" @@ -483,10 +485,11 @@ static CPpmd_Void_Ref CutOff(CPpmd8 *p, CTX_PTR ctx, unsigned order) } if (i == 0) { - ctx->Flags = (ctx->Flags & 0x10) + 0x08 * (s->Symbol >= 0x40); + ctx->Flags = (Byte)((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; + /* 9.31: the code was fixed. It's was not BUG, if Freq <= MAX_FREQ = 124 */ + ONE_STATE(ctx)->Freq = (Byte)(((unsigned)ONE_STATE(ctx)->Freq + 11) >> 3); } else Refresh(p, ctx, tmp, ctx->SummFreq > 16 * i); @@ -554,17 +557,17 @@ static void RestoreModel(CPpmd8 *p, CTX_PTR c1 if (--(c->NumStats) == 0) { s = STATS(c); - c->Flags = (c->Flags & 0x10) + 0x08 * (s->Symbol >= 0x40); + c->Flags = (Byte)((c->Flags & 0x10) + 0x08 * (s->Symbol >= 0x40)); *ONE_STATE(c) = *s; SpecialFreeUnit(p, s); - ONE_STATE(c)->Freq = (ONE_STATE(c)->Freq + 11) >> 3; + ONE_STATE(c)->Freq = (Byte)(((unsigned)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; + ONE_STATE(c)->Freq = (Byte)(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); @@ -636,7 +639,7 @@ static CTX_PTR CreateSuccessors(CPpmd8 *p, Bool skip, CPpmd_State *s1, CTX_PTR c else { s = ONE_STATE(c); - s->Freq += (!SUFFIX(c)->NumStats & (s->Freq < 24)); + s->Freq = (Byte)(s->Freq + (!SUFFIX(c)->NumStats & (s->Freq < 24))); } successor = SUCCESSOR(s); if (successor != upBranch) @@ -651,7 +654,7 @@ static CTX_PTR CreateSuccessors(CPpmd8 *p, Bool skip, CPpmd_State *s1, CTX_PTR c upState.Symbol = *(const Byte *)Ppmd8_GetPtr(p, upBranch); SetSuccessor(&upState, upBranch + 1); - flags = 0x10 * (p->FoundState->Symbol >= 0x40) + 0x08 * (upState.Symbol >= 0x40); + flags = (Byte)(0x10 * (p->FoundState->Symbol >= 0x40) + 0x08 * (upState.Symbol >= 0x40)); if (c->NumStats == 0) upState.Freq = ONE_STATE(c)->Freq; @@ -743,7 +746,7 @@ static CTX_PTR ReduceOrder(CPpmd8 *p, CPpmd_State *s1, CTX_PTR c) else { s = ONE_STATE(c); - s->Freq += (s->Freq < 32); + s->Freq = (Byte)(s->Freq + (s->Freq < 32)); } } if (SUCCESSOR(s)) @@ -889,7 +892,7 @@ static void UpdateModel(CPpmd8 *p) #endif s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - fFreq; - flag = 0x08 * (fSymbol >= 0x40); + flag = (Byte)(0x08 * (fSymbol >= 0x40)); for (; c != p->MinContext; c = SUFFIX(c)) { @@ -1012,7 +1015,7 @@ static void Rescale(CPpmd8 *p) 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->MinContext->Flags = (Byte)((p->MinContext->Flags & 0x10) + 0x08 * (tmp.Symbol >= 0x40)); *(p->FoundState = ONE_STATE(p->MinContext)) = tmp; return; } diff --git a/C/Ppmd8.h b/C/Ppmd8.h old mode 100755 new mode 100644 diff --git a/C/Ppmd8Dec.c b/C/Ppmd8Dec.c old mode 100755 new mode 100644 index c54e02ab..317bd651 --- a/C/Ppmd8Dec.c +++ b/C/Ppmd8Dec.c @@ -4,6 +4,8 @@ This code is based on: PPMd var.I (2002): Dmitry Shkarin : Public domain Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ +#include "Precomp.h" + #include "Ppmd8.h" #define kTop (1 << 24) diff --git a/C/Ppmd8Enc.c b/C/Ppmd8Enc.c old mode 100755 new mode 100644 index 8da727eb..5e389be4 --- a/C/Ppmd8Enc.c +++ b/C/Ppmd8Enc.c @@ -4,6 +4,8 @@ This code is based on: PPMd var.I (2002): Dmitry Shkarin : Public domain Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ +#include "Precomp.h" + #include "Ppmd8.h" #define kTop (1 << 24) diff --git a/C/Precomp.h b/C/Precomp.h new file mode 100644 index 00000000..e8ff8b40 --- /dev/null +++ b/C/Precomp.h @@ -0,0 +1,10 @@ +/* Precomp.h -- StdAfx +2013-11-12 : Igor Pavlov : Public domain */ + +#ifndef __7Z_PRECOMP_H +#define __7Z_PRECOMP_H + +#include "Compiler.h" +/* #include "7zTypes.h" */ + +#endif diff --git a/C/RotateDefs.h b/C/RotateDefs.h old mode 100755 new mode 100644 index c3a1385c..1b83e5ea --- a/C/RotateDefs.h +++ b/C/RotateDefs.h @@ -1,5 +1,5 @@ /* RotateDefs.h -- Rotate functions -2009-02-07 : Igor Pavlov : Public domain */ +2013-11-12 : Igor Pavlov : Public domain */ #ifndef __ROTATE_DEFS_H #define __ROTATE_DEFS_H @@ -7,6 +7,12 @@ #ifdef _MSC_VER #include + +// #if (_MSC_VER >= 1200) +#pragma intrinsic(_rotl) +#pragma intrinsic(_rotr) +// #endif + #define rotlFixed(x, n) _rotl((x), (n)) #define rotrFixed(x, n) _rotr((x), (n)) diff --git a/C/Sha256.c b/C/Sha256.c old mode 100755 new mode 100644 index eb4fc61f..db0c7061 --- a/C/Sha256.c +++ b/C/Sha256.c @@ -2,6 +2,8 @@ 2010-06-11 : Igor Pavlov : Public domain This code is based on public domain code from Wei Dai's Crypto++ library. */ +#include "Precomp.h" + #include "RotateDefs.h" #include "Sha256.h" diff --git a/C/Sha256.h b/C/Sha256.h old mode 100755 new mode 100644 index 530f513e..3f455dbc --- a/C/Sha256.h +++ b/C/Sha256.h @@ -1,10 +1,10 @@ /* Sha256.h -- SHA-256 Hash -2010-06-11 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __CRYPTO_SHA256_H #define __CRYPTO_SHA256_H -#include "Types.h" +#include "7zTypes.h" EXTERN_C_BEGIN diff --git a/C/Sort.c b/C/Sort.c old mode 100755 new mode 100644 index 388d2289..e1097e38 --- a/C/Sort.c +++ b/C/Sort.c @@ -1,28 +1,30 @@ /* Sort.c -- Sort functions -2010-09-17 : Igor Pavlov : Public domain */ +2014-04-05 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include "Sort.h" #define HeapSortDown(p, k, size, temp) \ { for (;;) { \ - UInt32 s = (k << 1); \ + size_t s = (k << 1); \ if (s > size) break; \ if (s < size && p[s + 1] > p[s]) s++; \ if (temp >= p[s]) break; \ p[k] = p[s]; k = s; \ } p[k] = temp; } -void HeapSort(UInt32 *p, UInt32 size) +void HeapSort(UInt32 *p, size_t size) { if (size <= 1) return; p--; { - UInt32 i = size / 2; + size_t i = size / 2; do { UInt32 temp = p[i]; - UInt32 k = i; + size_t k = i; HeapSortDown(p, k, size, temp) } while (--i != 0); @@ -30,7 +32,7 @@ void HeapSort(UInt32 *p, UInt32 size) /* do { - UInt32 k = 1; + size_t k = 1; UInt32 temp = p[size]; p[size--] = p[1]; HeapSortDown(p, k, size, temp) @@ -40,7 +42,7 @@ void HeapSort(UInt32 *p, UInt32 size) while (size > 3) { UInt32 temp = p[size]; - UInt32 k = (p[3] > p[2]) ? 3 : 2; + size_t k = (p[3] > p[2]) ? 3 : 2; p[size--] = p[1]; p[1] = p[k]; HeapSortDown(p, k, size, temp) @@ -58,23 +60,69 @@ void HeapSort(UInt32 *p, UInt32 size) } } +void HeapSort64(UInt64 *p, size_t size) +{ + if (size <= 1) + return; + p--; + { + size_t i = size / 2; + do + { + UInt64 temp = p[i]; + size_t k = i; + HeapSortDown(p, k, size, temp) + } + while (--i != 0); + } + /* + do + { + size_t k = 1; + UInt64 temp = p[size]; + p[size--] = p[1]; + HeapSortDown(p, k, size, temp) + } + while (size > 1); + */ + while (size > 3) + { + UInt64 temp = p[size]; + size_t k = (p[3] > p[2]) ? 3 : 2; + p[size--] = p[1]; + p[1] = p[k]; + HeapSortDown(p, k, size, temp) + } + { + UInt64 temp = p[size]; + p[size] = p[1]; + if (size > 2 && p[2] < temp) + { + p[1] = p[2]; + p[2] = temp; + } + else + p[1] = temp; + } +} + /* #define HeapSortRefDown(p, vals, n, size, temp) \ - { UInt32 k = n; UInt32 val = vals[temp]; for (;;) { \ - UInt32 s = (k << 1); \ + { size_t k = n; UInt32 val = vals[temp]; for (;;) { \ + size_t s = (k << 1); \ if (s > size) break; \ if (s < size && vals[p[s + 1]] > vals[p[s]]) s++; \ if (val >= vals[p[s]]) break; \ p[k] = p[s]; k = s; \ } p[k] = temp; } -void HeapSortRef(UInt32 *p, UInt32 *vals, UInt32 size) +void HeapSortRef(UInt32 *p, UInt32 *vals, size_t size) { if (size <= 1) return; p--; { - UInt32 i = size / 2; + size_t i = size / 2; do { UInt32 temp = p[i]; diff --git a/C/Sort.h b/C/Sort.h old mode 100755 new mode 100644 index 65dfc6f6..2e2963a2 --- a/C/Sort.h +++ b/C/Sort.h @@ -1,20 +1,18 @@ /* Sort.h -- Sort functions -2009-02-07 : Igor Pavlov : Public domain */ +2014-04-05 : Igor Pavlov : Public domain */ #ifndef __7Z_SORT_H #define __7Z_SORT_H -#include "Types.h" +#include "7zTypes.h" -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN -void HeapSort(UInt32 *p, UInt32 size); -/* void HeapSortRef(UInt32 *p, UInt32 *vals, UInt32 size); */ +void HeapSort(UInt32 *p, size_t size); +void HeapSort64(UInt64 *p, size_t size); -#ifdef __cplusplus -} -#endif +/* void HeapSortRef(UInt32 *p, UInt32 *vals, size_t size); */ + +EXTERN_C_END #endif diff --git a/C/Threads.c b/C/Threads.c old mode 100755 new mode 100644 index 7af1da2e..d71e13a4 --- a/C/Threads.c +++ b/C/Threads.c @@ -1,5 +1,7 @@ /* Threads.c -- multithreading library -2009-09-20 : Igor Pavlov : Public domain */ +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #ifndef _WIN32_WCE #include @@ -29,14 +31,21 @@ 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. */ + /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ + + #ifdef UNDER_CE + + DWORD threadId; + *p = CreateThread(0, 0, func, param, 0, &threadId); + + #else + + unsigned threadId; + *p = (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId); + + #endif + + /* maybe we must use errno here, but probably GetLastError() is also OK. */ return HandleToWRes(*p); } diff --git a/C/Threads.h b/C/Threads.h old mode 100755 new mode 100644 index d0ddd80e..9b3e1c55 --- a/C/Threads.h +++ b/C/Threads.h @@ -1,15 +1,17 @@ /* Threads.h -- multithreading library -2009-03-27 : Igor Pavlov : Public domain */ +2013-11-12 : Igor Pavlov : Public domain */ #ifndef __7Z_THREADS_H #define __7Z_THREADS_H -#include "Types.h" - -#ifdef __cplusplus -extern "C" { +#ifdef _WIN32 +#include #endif +#include "7zTypes.h" + +EXTERN_C_BEGIN + WRes HandlePtr_Close(HANDLE *h); WRes Handle_WaitObject(HANDLE h); @@ -18,7 +20,15 @@ typedef HANDLE CThread; #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; + +typedef +#ifdef UNDER_CE + DWORD +#else + unsigned +#endif + THREAD_FUNC_RET_TYPE; + #define THREAD_FUNC_CALL_TYPE MY_STD_CALL #define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *); @@ -52,8 +62,6 @@ WRes CriticalSection_Init(CCriticalSection *p); #define CriticalSection_Enter(p) EnterCriticalSection(p) #define CriticalSection_Leave(p) LeaveCriticalSection(p) -#ifdef __cplusplus -} -#endif +EXTERN_C_END #endif diff --git a/C/Types.h b/C/Types.h deleted file mode 100755 index 7732c240..00000000 --- a/C/Types.h +++ /dev/null @@ -1,254 +0,0 @@ -/* 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 old mode 100755 new mode 100644 index 21dd5995..92818667 --- a/C/Util/7z/7z.dsp +++ b/C/Util/7z/7z.dsp @@ -42,7 +42,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /FAs /YX /FD /c +# ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /FAs /Yu"Precomp.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe @@ -50,7 +50,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /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 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\util\7zDec.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "7z - Win32 Debug" @@ -67,7 +67,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /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 CPP /nologo /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_SZ_ALLOC_DEBUG2" /D "_SZ_NO_INT_64_A" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /Yu"Precomp.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe @@ -75,7 +75,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 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 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\util\7zDec.exe" /pdbtype:sept !ENDIF @@ -100,6 +100,10 @@ SOURCE=..\..\7zAlloc.h # End Source File # Begin Source File +SOURCE=..\..\7zArcIn.c +# End Source File +# Begin Source File + SOURCE=..\..\7zBuf.c # End Source File # Begin Source File @@ -133,11 +137,11 @@ SOURCE=..\..\7zFile.h # End Source File # Begin Source File -SOURCE=..\..\7zIn.c +SOURCE=..\..\7zStream.c # End Source File # Begin Source File -SOURCE=..\..\7zStream.c +SOURCE=..\..\7zTypes.h # End Source File # Begin Source File @@ -190,7 +194,6 @@ SOURCE=..\..\Ppmd.h # Begin Source File SOURCE=..\..\Ppmd7.c -# SUBTRACT CPP /YX # End Source File # Begin Source File @@ -199,11 +202,23 @@ SOURCE=..\..\Ppmd7.h # Begin Source File SOURCE=..\..\Ppmd7Dec.c -# SUBTRACT CPP /YX +# End Source File +# End Group +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compiler.h +# End Source File +# Begin Source File + +SOURCE=.\Precomp.c +# ADD CPP /Yc"Precomp.h" # End Source File # Begin Source File -SOURCE=..\..\Types.h +SOURCE=.\Precomp.h # End Source File # End Group # Begin Source File diff --git a/C/Util/7z/7z.dsw b/C/Util/7z/7z.dsw old mode 100755 new mode 100644 diff --git a/C/Util/7z/7zMain.c b/C/Util/7z/7zMain.c old mode 100755 new mode 100644 index 9496dc07..609a578e --- a/C/Util/7z/7zMain.c +++ b/C/Util/7z/7zMain.c @@ -1,11 +1,14 @@ /* 7zMain.c - Test application for 7z Decoder -2010-10-28 : Igor Pavlov : Public domain */ +2014-06-17 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include #include #include "../../7z.h" #include "../../7zAlloc.h" +#include "../../7zBuf.h" #include "../../7zCrc.h" #include "../../7zFile.h" #include "../../7zVersion.h" @@ -95,42 +98,52 @@ static SRes Utf16_To_Utf8Buf(CBuf *dest, const UInt16 *src, size_t 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) +static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s + #ifdef _WIN32 + , UINT codePage + #endif + ) { - int len = 0; - for (len = 0; s[len] != '\0'; len++); + unsigned len = 0; + for (len = 0; s[len] != 0; len++); #ifdef _WIN32 { - int size = len * 3 + 100; + unsigned 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; + buf->data[0] = 0; + if (len != 0) + { + char defaultChar = '_'; + BOOL defUsed; + unsigned numChars = 0; + numChars = WideCharToMultiByte(codePage, 0, s, len, (char *)buf->data, size, &defaultChar, &defUsed); + if (numChars == 0 || numChars >= size) + return SZ_ERROR_FAIL; + buf->data[numChars] = 0; + } return SZ_OK; } } #else - fileMode = fileMode; return Utf16_To_Utf8Buf(buf, s, len); #endif } +#ifdef _WIN32 + #ifndef USE_WINDOWS_FILE + static UINT g_FileCodePage = CP_ACP; + #endif + #define MY_FILE_CODE_PAGE_PARAM ,g_FileCodePage +#else + #define MY_FILE_CODE_PAGE_PARAM +#endif + static WRes MyCreateDir(const UInt16 *name) { #ifdef USE_WINDOWS_FILE @@ -142,7 +155,7 @@ static WRes MyCreateDir(const UInt16 *name) CBuf buf; WRes res; Buf_Init(&buf); - RINOK(Utf16_To_Char(&buf, name, 1)); + RINOK(Utf16_To_Char(&buf, name MY_FILE_CODE_PAGE_PARAM)); res = #ifdef _WIN32 @@ -165,7 +178,7 @@ static WRes OutFile_OpenUtf16(CSzFile *p, const UInt16 *name) CBuf buf; WRes res; Buf_Init(&buf); - RINOK(Utf16_To_Char(&buf, name, 1)); + RINOK(Utf16_To_Char(&buf, name MY_FILE_CODE_PAGE_PARAM)); res = OutFile_Open(p, (const char *)buf.data); Buf_Free(&buf, &g_Alloc); return res; @@ -177,7 +190,11 @@ static SRes PrintString(const UInt16 *s) CBuf buf; SRes res; Buf_Init(&buf); - res = Utf16_To_Char(&buf, s, 0); + res = Utf16_To_Char(&buf, s + #ifdef _WIN32 + , CP_OEMCP + #endif + ); if (res == SZ_OK) fputs((const char *)buf.data, stdout); Buf_Free(&buf, &g_Alloc); @@ -216,17 +233,24 @@ static char *UIntToStr(char *s, unsigned value, int numDigits) return s; } +static void UIntToStr_2(char *s, unsigned value) +{ + s[0] = (char)('0' + (value / 10)); + s[1] = (char)('0' + (value % 10)); +} + #define PERIOD_4 (4 * 365 + 1) #define PERIOD_100 (PERIOD_4 * 25 - 1) #define PERIOD_400 (PERIOD_100 * 4 + 1) -static void ConvertFileTimeToString(const CNtfsFileTime *ft, char *s) +static void ConvertFileTimeToString(const CNtfsFileTime *nt, char *s) { - unsigned year, mon, day, hour, min, sec; - UInt64 v64 = (ft->Low | ((UInt64)ft->High << 32)) / 10000000; + unsigned year, mon, hour, min, sec; Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; unsigned t; UInt32 v; + UInt64 v64 = nt->Low | ((UInt64)nt->High << 32); + v64 /= 10000000; sec = (unsigned)(v64 % 60); v64 /= 60; min = (unsigned)(v64 % 60); v64 /= 60; hour = (unsigned)(v64 % 24); v64 /= 24; @@ -242,20 +266,19 @@ static void ConvertFileTimeToString(const CNtfsFileTime *ft, char *s) if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ms[1] = 29; - for (mon = 1; mon <= 12; mon++) + for (mon = 0;; mon++) { - unsigned s = ms[mon - 1]; + unsigned s = ms[mon]; 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); + UIntToStr_2(s, mon + 1); s[2] = '-'; s += 3; + UIntToStr_2(s, (unsigned)v + 1); s[2] = ' '; s += 3; + UIntToStr_2(s, hour); s[2] = ':'; s += 3; + UIntToStr_2(s, min); s[2] = ':'; s += 3; + UIntToStr_2(s, sec); s[2] = 0; } void PrintError(char *sz) @@ -264,14 +287,13 @@ void PrintError(char *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[0] = (char)(((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : '.'); + s[1] = (char)(((wa & FILE_ATTRIBUTE_READONLY ) != 0) ? 'R': '.'); + s[2] = (char)(((wa & FILE_ATTRIBUTE_HIDDEN ) != 0) ? 'H': '.'); + s[3] = (char)(((wa & FILE_ATTRIBUTE_SYSTEM ) != 0) ? 'S': '.'); + s[4] = (char)(((wa & FILE_ATTRIBUTE_ARCHIVE ) != 0) ? 'A': '.'); s[5] = '\0'; } #else @@ -281,6 +303,8 @@ static void GetAttribString(UInt32, Bool, char *s) } #endif +// #define NUM_PARENTS_MAX 128 + int MY_CDECL main(int numargs, char *args[]) { CFileInStream archiveStream; @@ -291,6 +315,7 @@ int MY_CDECL main(int numargs, char *args[]) ISzAlloc allocTempImp; UInt16 *temp = NULL; size_t tempSize = 0; + // UInt32 parents[NUM_PARENTS_MAX]; printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n\n"); if (numargs == 1) @@ -310,13 +335,21 @@ int MY_CDECL main(int numargs, char *args[]) return 1; } + #if defined(_WIN32) && !defined(USE_WINDOWS_FILE) && !defined(UNDER_CE) + g_FileCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; + #endif + allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; + #ifdef UNDER_CE + if (InFile_OpenW(&archiveStream.file, L"\test.7z")) + #else if (InFile_Open(&archiveStream.file, args[2])) + #endif { PrintError("can not open input file"); return 1; @@ -358,22 +391,24 @@ int MY_CDECL main(int numargs, char *args[]) 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++) + for (i = 0; i < db.NumFiles; i++) { size_t offset = 0; size_t outSizeProcessed = 0; - const CSzFileItem *f = db.db.Files + i; + // const CSzFileItem *f = db.Files + i; size_t len; - if (listCommand == 0 && f->IsDir && !fullPaths) + int isDir = SzArEx_IsDir(&db, i); + if (listCommand == 0 && isDir && !fullPaths) continue; len = SzArEx_GetFileNameUtf16(&db, i, NULL); + // len = SzArEx_GetFullNameLen(&db, i); if (len > tempSize) { SzFree(NULL, temp); tempSize = len; temp = (UInt16 *)SzAlloc(NULL, tempSize * sizeof(temp[0])); - if (temp == 0) + if (!temp) { res = SZ_ERROR_MEM; break; @@ -381,15 +416,25 @@ int MY_CDECL main(int numargs, char *args[]) } SzArEx_GetFileNameUtf16(&db, i, temp); + /* + if (SzArEx_GetFullNameUtf16_Back(&db, i, temp + len) != temp) + { + res = SZ_ERROR_FAIL; + break; + } + */ + if (listCommand) { char attr[8], s[32], t[32]; + UInt64 fileSize; - GetAttribString(f->AttribDefined ? f->Attrib : 0, f->IsDir, attr); + GetAttribString(SzBitWithVals_Check(&db.Attribs, i) ? db.Attribs.Vals[i] : 0, isDir, attr); - UInt64ToStr(f->Size, s); - if (f->MTimeDefined) - ConvertFileTimeToString(&f->MTime, t); + fileSize = SzArEx_GetFileSize(&db, i); + UInt64ToStr(fileSize, s); + if (SzBitWithVals_Check(&db.MTime, i)) + ConvertFileTimeToString(&db.MTime.Vals[i], t); else { size_t j; @@ -402,7 +447,7 @@ int MY_CDECL main(int numargs, char *args[]) res = PrintString(temp); if (res != SZ_OK) break; - if (f->IsDir) + if (isDir) printf("/"); printf("\n"); continue; @@ -414,7 +459,7 @@ int MY_CDECL main(int numargs, char *args[]) res = PrintString(temp); if (res != SZ_OK) break; - if (f->IsDir) + if (isDir) printf("/"); else { @@ -445,7 +490,7 @@ int MY_CDECL main(int numargs, char *args[]) destPath = name + j + 1; } - if (f->IsDir) + if (isDir) { MyCreateDir(destPath); printf("\n"); @@ -471,8 +516,8 @@ int MY_CDECL main(int numargs, char *args[]) break; } #ifdef USE_WINDOWS_FILE - if (f->AttribDefined) - SetFileAttributesW(destPath, f->Attrib); + if (SzBitWithVals_Check(&db.Attribs, i)) + SetFileAttributesW(destPath, db.Attribs.Vals[i]); #endif } printf("\n"); diff --git a/C/Util/7z/Precomp.c b/C/Util/7z/Precomp.c new file mode 100644 index 00000000..01605e3c --- /dev/null +++ b/C/Util/7z/Precomp.c @@ -0,0 +1,4 @@ +/* Precomp.c -- StdAfx +2013-01-21 : Igor Pavlov : Public domain */ + +#include "Precomp.h" diff --git a/C/Util/7z/Precomp.h b/C/Util/7z/Precomp.h new file mode 100644 index 00000000..588a66f7 --- /dev/null +++ b/C/Util/7z/Precomp.h @@ -0,0 +1,10 @@ +/* Precomp.h -- StdAfx +2013-06-16 : Igor Pavlov : Public domain */ + +#ifndef __7Z_PRECOMP_H +#define __7Z_PRECOMP_H + +#include "../../Compiler.h" +#include "../../7zTypes.h" + +#endif diff --git a/C/Util/7z/makefile b/C/Util/7z/makefile old mode 100755 new mode 100644 index 96edda42..9009da83 --- a/C/Util/7z/makefile +++ b/C/Util/7z/makefile @@ -6,12 +6,11 @@ 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\7zArcIn.obj \ $O\7zStream.obj \ $O\Bcj2.obj \ $O\Bra.obj \ @@ -26,12 +25,15 @@ C_OBJS = \ $O\7zMain.obj \ OBJS = \ + $O\Precomp.obj \ $(7Z_OBJS) \ $(C_OBJS) \ !include "../../../CPP/Build.mak" $(7Z_OBJS): $(*B).c - $(COMPL_O1) + $(CCOMPL_USE) $(C_OBJS): ../../$(*B).c - $(COMPL_O2) + $(CCOMPL_USE) +$O\Precomp.obj: Precomp.c + $(CCOMPL_PCH) diff --git a/C/Util/7z/makefile.gcc b/C/Util/7z/makefile.gcc old mode 100755 new mode 100644 index 364c6474..46018201 --- a/C/Util/7z/makefile.gcc +++ b/C/Util/7z/makefile.gcc @@ -4,7 +4,7 @@ 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 +OBJS = 7zMain.o 7zAlloc.o 7zArcIn.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zCrcOpt.o 7zDec.o CpuArch.o LzmaDec.o Lzma2Dec.o Bra.o Bra86.o Bcj2.o Ppmd7.o Ppmd7Dec.o 7zFile.o 7zStream.o all: $(PROG) @@ -14,9 +14,12 @@ $(PROG): $(OBJS) 7zMain.o: 7zMain.c $(CXX) $(CFLAGS) 7zMain.c -7zAlloc.o: 7zAlloc.c +7zAlloc.o: ../../7zAlloc.c $(CXX) $(CFLAGS) ../../7zAlloc.c +7zArcIn.o: ../../7zArcIn.c + $(CXX) $(CFLAGS) ../../7zArcIn.c + 7zBuf.o: ../../7zBuf.c $(CXX) $(CFLAGS) ../../7zBuf.c @@ -32,9 +35,6 @@ $(PROG): $(OBJS) 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 diff --git a/C/Util/Lzma/LzmaUtil.c b/C/Util/Lzma/LzmaUtil.c old mode 100755 new mode 100644 index 09a749af..7c30fdc7 --- a/C/Util/Lzma/LzmaUtil.c +++ b/C/Util/Lzma/LzmaUtil.c @@ -1,7 +1,7 @@ /* LzmaUtil.c -- Test application for LZMA compression -2010-09-20 : Igor Pavlov : Public domain */ +2014-06-17 : Igor Pavlov : Public domain */ -#define _CRT_SECURE_NO_WARNINGS +#include "../../Precomp.h" #include #include diff --git a/C/Util/Lzma/LzmaUtil.dsp b/C/Util/Lzma/LzmaUtil.dsp old mode 100755 new mode 100644 index d10af8b4..43b8e176 --- a/C/Util/Lzma/LzmaUtil.dsp +++ b/C/Util/Lzma/LzmaUtil.dsp @@ -42,7 +42,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c +# ADD CPP /nologo /MT /W4 /WX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" @@ -67,7 +67,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c +# ADD CPP /nologo /MTd /W4 /WX /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" diff --git a/C/Util/Lzma/LzmaUtil.dsw b/C/Util/Lzma/LzmaUtil.dsw old mode 100755 new mode 100644 diff --git a/C/Util/Lzma/makefile b/C/Util/Lzma/makefile old mode 100755 new mode 100644 diff --git a/C/Util/Lzma/makefile.gcc b/C/Util/Lzma/makefile.gcc old mode 100755 new mode 100644 diff --git a/C/Util/LzmaLib/LzmaLib.def b/C/Util/LzmaLib/LzmaLib.def old mode 100755 new mode 100644 diff --git a/C/Util/LzmaLib/LzmaLib.dsp b/C/Util/LzmaLib/LzmaLib.dsp old mode 100755 new mode 100644 index 7d8d386f..3421de83 --- a/C/Util/LzmaLib/LzmaLib.dsp +++ b/C/Util/LzmaLib/LzmaLib.dsp @@ -104,6 +104,10 @@ SOURCE=.\LzmaLibExports.c # End Group # Begin Source File +SOURCE=..\..\7zTypes.h +# End Source File +# Begin Source File + SOURCE=..\..\Alloc.c # End Source File # Begin Source File @@ -170,9 +174,5 @@ SOURCE=..\..\Threads.c 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 old mode 100755 new mode 100644 diff --git a/C/Util/LzmaLib/LzmaLibExports.c b/C/Util/LzmaLib/LzmaLibExports.c old mode 100755 new mode 100644 diff --git a/C/Util/LzmaLib/makefile b/C/Util/LzmaLib/makefile old mode 100755 new mode 100644 diff --git a/C/Util/LzmaLib/resource.rc b/C/Util/LzmaLib/resource.rc old mode 100755 new mode 100644 diff --git a/C/Util/SfxSetup/Precomp.c b/C/Util/SfxSetup/Precomp.c new file mode 100644 index 00000000..01605e3c --- /dev/null +++ b/C/Util/SfxSetup/Precomp.c @@ -0,0 +1,4 @@ +/* Precomp.c -- StdAfx +2013-01-21 : Igor Pavlov : Public domain */ + +#include "Precomp.h" diff --git a/C/Util/SfxSetup/Precomp.h b/C/Util/SfxSetup/Precomp.h new file mode 100644 index 00000000..588a66f7 --- /dev/null +++ b/C/Util/SfxSetup/Precomp.h @@ -0,0 +1,10 @@ +/* Precomp.h -- StdAfx +2013-06-16 : Igor Pavlov : Public domain */ + +#ifndef __7Z_PRECOMP_H +#define __7Z_PRECOMP_H + +#include "../../Compiler.h" +#include "../../7zTypes.h" + +#endif diff --git a/C/Util/SfxSetup/SfxSetup.c b/C/Util/SfxSetup/SfxSetup.c old mode 100755 new mode 100644 index c3c56b1e..32fb56ed --- a/C/Util/SfxSetup/SfxSetup.c +++ b/C/Util/SfxSetup/SfxSetup.c @@ -1,5 +1,7 @@ /* SfxSetup.c - 7z SFX Setup -2010-12-13 : Igor Pavlov : Public domain */ +2014-06-15 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #ifndef UNICODE #define UNICODE @@ -238,6 +240,9 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, ISzAlloc allocTempImp; WCHAR sfxPath[MAX_PATH + 2]; WCHAR path[MAX_PATH * 3 + 2]; + #ifndef UNDER_CE + WCHAR workCurDir[MAX_PATH + 32]; + #endif size_t pathLen; DWORD winRes; const wchar_t *cmdLineParams; @@ -292,6 +297,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, return 1; pathLen = wcslen(path); d = (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId(); + for (i = 0;; i++, d += GetTickCount()) { if (i >= 100) @@ -328,6 +334,10 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, break; } } + + #ifndef UNDER_CE + wcscpy(workCurDir, path); + #endif if (res != SZ_OK) errorMessage = "Can't create temp folder"; } @@ -367,6 +377,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, { res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp); } + if (res == SZ_OK) { UInt32 executeFileIndex = (UInt32)(Int32)-1; @@ -376,11 +387,10 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 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++) + for (i = 0; i < 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); @@ -418,7 +428,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, } } - if (f->IsDir) + if (SzArEx_IsDir(&db, i)) { MyCreateDir(path); continue; @@ -453,6 +463,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, break; } } + processedSize = outSizeProcessed; if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed) { @@ -461,11 +472,12 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, } #ifdef USE_WINDOWS_FILE - if (f->MTimeDefined) + if (SzBitWithVals_Check(&db.MTime, i)) { + const CNtfsFileTime *t = db.MTime.Vals + i; FILETIME mTime; - mTime.dwLowDateTime = f->MTime.Low; - mTime.dwHighDateTime = f->MTime.High; + mTime.dwLowDateTime = t->Low; + mTime.dwHighDateTime = t->High; SetFileTime(outFile.handle, NULL, NULL, &mTime); } #endif @@ -481,8 +493,8 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, } } #ifdef USE_WINDOWS_FILE - if (f->AttribDefined) - SetFileAttributesW(path, f->Attrib); + if (SzBitWithVals_Check(&db.Attribs, i)) + SetFileAttributesW(path, db.Attribs.Vals[i]); #endif } } @@ -513,6 +525,18 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, if (res == SZ_OK) { HANDLE hProcess = 0; + + #ifndef UNDER_CE + WCHAR oldCurDir[MAX_PATH + 2]; + oldCurDir[0] = 0; + { + DWORD needLen = GetCurrentDirectory(MAX_PATH + 1, oldCurDir); + if (needLen == 0 || needLen > MAX_PATH) + oldCurDir[0] = 0; + SetCurrentDirectory(workCurDir); + } + #endif + if (useShellExecute) { SHELLEXECUTEINFO ei; @@ -556,11 +580,16 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, hProcess = pi.hProcess; } } + if (hProcess != 0) { WaitForSingleObject(hProcess, INFINITE); CloseHandle(hProcess); } + + #ifndef UNDER_CE + SetCurrentDirectory(oldCurDir); + #endif } path[pathLen] = L'\0'; diff --git a/C/Util/SfxSetup/SfxSetup.dsp b/C/Util/SfxSetup/SfxSetup.dsp old mode 100755 new mode 100644 index 39f876d4..5ce7195b --- a/C/Util/SfxSetup/SfxSetup.dsp +++ b/C/Util/SfxSetup/SfxSetup.dsp @@ -42,7 +42,7 @@ RSC=rc.exe # 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 CPP /nologo /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /Yu"Precomp.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" @@ -68,7 +68,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /YX /FD /GZ /c +# ADD CPP /nologo /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /Yu"Precomp.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" @@ -103,6 +103,10 @@ SOURCE=..\..\7zAlloc.h # End Source File # Begin Source File +SOURCE=..\..\7zArcIn.c +# End Source File +# Begin Source File + SOURCE=..\..\7zBuf.c # End Source File # Begin Source File @@ -135,11 +139,11 @@ SOURCE=..\..\7zFile.h # End Source File # Begin Source File -SOURCE=..\..\7zIn.c +SOURCE=..\..\7zStream.c # End Source File # Begin Source File -SOURCE=..\..\7zStream.c +SOURCE=..\..\7zTypes.h # End Source File # Begin Source File @@ -185,9 +189,18 @@ SOURCE=..\..\LzmaDec.c SOURCE=..\..\LzmaDec.h # End Source File +# End Group +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\Precomp.c +# ADD CPP /Yc"Precomp.h" +# End Source File # Begin Source File -SOURCE=..\..\Types.h +SOURCE=.\Precomp.h # End Source File # End Group # Begin Source File diff --git a/C/Util/SfxSetup/SfxSetup.dsw b/C/Util/SfxSetup/SfxSetup.dsw old mode 100755 new mode 100644 diff --git a/C/Util/SfxSetup/makefile b/C/Util/SfxSetup/makefile old mode 100755 new mode 100644 index ce1fbc9d..5b519807 --- a/C/Util/SfxSetup/makefile +++ b/C/Util/SfxSetup/makefile @@ -1,16 +1,14 @@ PROG = 7zS2.sfx -LIBS = $(LIBS) -CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE -D_CRT_SECURE_NO_WARNINGS C_OBJS = \ $O\7zAlloc.obj \ + $O\7zArcIn.obj \ $O\7zBuf.obj \ $O\7zBuf2.obj \ $O\7zCrc.obj \ $O\7zCrcOpt.obj \ $O\7zFile.obj \ $O\7zDec.obj \ - $O\7zIn.obj \ $O\7zStream.obj \ $O\Bcj2.obj \ $O\Bra.obj \ diff --git a/C/Util/SfxSetup/makefile_con b/C/Util/SfxSetup/makefile_con old mode 100755 new mode 100644 index 8e1a050d..492191f5 --- a/C/Util/SfxSetup/makefile_con +++ b/C/Util/SfxSetup/makefile_con @@ -1,16 +1,15 @@ PROG = 7zS2con.sfx -LIBS = $(LIBS) -CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE -D_CONSOLE +CFLAGS = $(CFLAGS) -D_CONSOLE C_OBJS = \ $O\7zAlloc.obj \ + $O\7zArcIn.obj \ $O\7zBuf.obj \ $O\7zBuf2.obj \ $O\7zCrc.obj \ $O\7zCrcOpt.obj \ $O\7zFile.obj \ $O\7zDec.obj \ - $O\7zIn.obj \ $O\7zStream.obj \ $O\Bcj2.obj \ $O\Bra.obj \ diff --git a/C/Util/SfxSetup/resource.rc b/C/Util/SfxSetup/resource.rc old mode 100755 new mode 100644 diff --git a/C/Util/SfxSetup/setup.ico b/C/Util/SfxSetup/setup.ico old mode 100755 new mode 100644 diff --git a/C/Xz.c b/C/Xz.c old mode 100755 new mode 100644 index 18caba2c..fbc732a8 --- a/C/Xz.c +++ b/C/Xz.c @@ -1,6 +1,8 @@ /* Xz.c - Xz 2009-04-15 : Igor Pavlov : Public domain */ +#include "Precomp.h" + #include "7zCrc.h" #include "CpuArch.h" #include "Xz.h" diff --git a/C/Xz.h b/C/Xz.h old mode 100755 new mode 100644 index 0f7a822c..a8296730 --- a/C/Xz.h +++ b/C/Xz.h @@ -1,5 +1,5 @@ /* Xz.h - Xz interface -2011-01-09 : Igor Pavlov : Public domain */ +2013-11-19 : Igor Pavlov : Public domain */ #ifndef __XZ_H #define __XZ_H @@ -209,7 +209,9 @@ typedef struct UInt64 indexPos; UInt64 padSize; - UInt64 numStreams; + UInt64 numStartedStreams; + UInt64 numFinishedStreams; + UInt64 numTotalBlocks; UInt32 crc; CMixCoder decoder; @@ -236,10 +238,19 @@ Returns: CODER_STATUS_NOT_FINISHED, CODER_STATUS_NEEDS_MORE_INPUT - maybe there are more xz streams, call XzUnpacker_IsStreamWasFinished to check that current stream was finished - SZ_ERROR_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). + SZ_ERROR_DATA - Data error + SZ_ERROR_UNSUPPORTED - Unsupported method or method properties + SZ_ERROR_CRC - CRC error + // SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). + + SZ_ERROR_NO_ARCHIVE - the error with xz Stream Header with one of the following reasons: + - xz Stream Signature failure + - CRC32 of xz Stream Header is failed + - The size of Stream padding is not multiple of four bytes. + It's possible to get that error, if xz stream was finished and the stream + contains some another data. In that case you can call XzUnpacker_GetExtraSize() + function to get real size of xz stream. */ @@ -249,6 +260,16 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p); +/* +Call XzUnpacker_GetExtraSize after XzUnpacker_Code function to detect real size of +xz stream in two cases: +XzUnpacker_Code() returns: + res == SZ_OK && status == CODER_STATUS_NEEDS_MORE_INPUT + res == SZ_ERROR_NO_ARCHIVE +*/ + +UInt64 XzUnpacker_GetExtraSize(CXzUnpacker *p); + EXTERN_C_END #endif diff --git a/C/XzCrc64.c b/C/XzCrc64.c old mode 100755 new mode 100644 index 0369554b..aa812548 --- a/C/XzCrc64.c +++ b/C/XzCrc64.c @@ -1,33 +1,90 @@ /* XzCrc64.c -- CRC64 calculation -2010-04-16 : Igor Pavlov : Public domain */ +2011-06-28 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include "XzCrc64.h" +#include "CpuArch.h" #define kCrc64Poly UINT64_CONST(0xC96C5795D7870F42) -UInt64 g_Crc64Table[256]; -void MY_FAST_CALL Crc64GenerateTable(void) +#ifdef MY_CPU_LE + #define CRC_NUM_TABLES 4 +#else + #define CRC_NUM_TABLES 5 + #define CRC_UINT64_SWAP(v) \ + ((v >> 56) | \ + ((v >> 40) & ((UInt64)0xFF << 8)) | \ + ((v >> 24) & ((UInt64)0xFF << 16)) | \ + ((v >> 8) & ((UInt64)0xFF << 24)) | \ + ((v << 8) & ((UInt64)0xFF << 32)) | \ + ((v << 24) & ((UInt64)0xFF << 40)) | \ + ((v << 40) & ((UInt64)0xFF << 48)) | \ + (v << 56)) + UInt64 MY_FAST_CALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table); +#endif + +#ifndef MY_CPU_BE + UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table); +#endif + +typedef UInt64 (MY_FAST_CALL *CRC_FUNC)(UInt64 v, const void *data, size_t size, const UInt64 *table); + +static CRC_FUNC g_Crc64Update; +UInt64 g_Crc64Table[256 * CRC_NUM_TABLES]; + +UInt64 MY_FAST_CALL Crc64Update(UInt64 v, const void *data, size_t size) +{ + return g_Crc64Update(v, data, size, g_Crc64Table); +} + +UInt64 MY_FAST_CALL Crc64Calc(const void *data, size_t size) +{ + return g_Crc64Update(CRC64_INIT_VAL, data, size, g_Crc64Table) ^ CRC64_INIT_VAL; +} + +void MY_FAST_CALL Crc64GenerateTable() { UInt32 i; for (i = 0; i < 256; i++) { UInt64 r = i; - int j; + unsigned j; for (j = 0; j < 8; j++) - r = (r >> 1) ^ ((UInt64)kCrc64Poly & ~((r & 1) - 1)); + r = (r >> 1) ^ (kCrc64Poly & ~((r & 1) - 1)); g_Crc64Table[i] = r; } -} + for (; i < 256 * CRC_NUM_TABLES; i++) + { + UInt64 r = g_Crc64Table[i - 256]; + g_Crc64Table[i] = g_Crc64Table[r & 0xFF] ^ (r >> 8); + } + + #ifdef MY_CPU_LE -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; -} + g_Crc64Update = XzCrc64UpdateT4; -UInt64 MY_FAST_CALL Crc64Calc(const void *data, size_t size) -{ - return CRC64_GET_DIGEST(Crc64Update(CRC64_INIT_VAL, data, size)); + + + + + + #else + { + #ifndef MY_CPU_BE + UInt32 k = 1; + if (*(const Byte *)&k == 1) + g_Crc64Update = XzCrc64UpdateT4; + else + #endif + { + for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--) + { + UInt64 x = g_Crc64Table[i - 256]; + g_Crc64Table[i] = CRC_UINT64_SWAP(x); + } + g_Crc64Update = XzCrc64UpdateT1_BeT4; + } + } + #endif } diff --git a/C/XzCrc64.h b/C/XzCrc64.h old mode 100755 new mode 100644 index 0e8efd7e..08dbc330 --- a/C/XzCrc64.h +++ b/C/XzCrc64.h @@ -1,12 +1,12 @@ /* XzCrc64.h -- CRC64 calculation -2010-04-16 : Igor Pavlov : Public domain */ +2013-01-18 : Igor Pavlov : Public domain */ #ifndef __XZ_CRC64_H #define __XZ_CRC64_H #include -#include "Types.h" +#include "7zTypes.h" EXTERN_C_BEGIN diff --git a/C/XzCrc64Opt.c b/C/XzCrc64Opt.c new file mode 100644 index 00000000..dccae1c1 --- /dev/null +++ b/C/XzCrc64Opt.c @@ -0,0 +1,69 @@ +/* XzCrc64Opt.c -- CRC64 calculation +2011-06-28 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "CpuArch.h" + +#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +#ifndef MY_CPU_BE + +UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table) +{ + const Byte *p = (const Byte *)data; + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + for (; size >= 4; size -= 4, p += 4) + { + UInt32 d = (UInt32)v ^ *(const UInt32 *)p; + v = (v >> 32) ^ + table[0x300 + ((d ) & 0xFF)] ^ + table[0x200 + ((d >> 8) & 0xFF)] ^ + table[0x100 + ((d >> 16) & 0xFF)] ^ + table[0x000 + ((d >> 24))]; + } + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + return v; +} + +#endif + + +#ifndef MY_CPU_LE + +#define CRC_UINT64_SWAP(v) \ + ((v >> 56) | \ + ((v >> 40) & ((UInt64)0xFF << 8)) | \ + ((v >> 24) & ((UInt64)0xFF << 16)) | \ + ((v >> 8) & ((UInt64)0xFF << 24)) | \ + ((v << 8) & ((UInt64)0xFF << 32)) | \ + ((v << 24) & ((UInt64)0xFF << 40)) | \ + ((v << 40) & ((UInt64)0xFF << 48)) | \ + (v << 56)) + +UInt64 MY_FAST_CALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table) +{ + const Byte *p = (const Byte *)data; + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + v = CRC_UINT64_SWAP(v); + table += 0x100; + for (; size >= 4; size -= 4, p += 4) + { + UInt32 d = (UInt32)(v >> 32) ^ *(const UInt32 *)p; + v = (v << 32) ^ + table[0x000 + ((d ) & 0xFF)] ^ + table[0x100 + ((d >> 8) & 0xFF)] ^ + table[0x200 + ((d >> 16) & 0xFF)] ^ + table[0x300 + ((d >> 24))]; + } + table -= 0x100; + v = CRC_UINT64_SWAP(v); + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + return v; +} + +#endif diff --git a/C/XzDec.c b/C/XzDec.c old mode 100755 new mode 100644 index 113e2cdf..25e4d0eb --- a/C/XzDec.c +++ b/C/XzDec.c @@ -1,5 +1,7 @@ /* XzDec.c -- Xz Decode -2011-02-07 : Igor Pavlov : Public domain */ +2014-05-09 : Igor Pavlov : Public domain */ + +#include "Precomp.h" /* #define XZ_DUMP */ @@ -305,7 +307,7 @@ static SRes Lzma2State_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *sr { 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); + SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status); srcWasFinished = srcWasFinished; *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK); return res; @@ -347,7 +349,10 @@ void MixCoder_Free(CMixCoder *p) } p->numCoders = 0; if (p->buf) + { p->alloc->Free(p->alloc, p->buf); + p->buf = 0; /* 9.31: the BUG was fixed */ + } } void MixCoder_Init(CMixCoder *p) @@ -601,7 +606,10 @@ void XzUnpacker_Init(CXzUnpacker *p) { p->state = XZ_STATE_STREAM_HEADER; p->pos = 0; - p->numStreams = 0; + p->numStartedStreams = 0; + p->numFinishedStreams = 0; + p->numTotalBlocks = 0; + p->padSize = 0; } void XzUnpacker_Construct(CXzUnpacker *p, ISzAlloc *alloc) @@ -676,7 +684,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, return SZ_OK; } - switch(p->state) + switch (p->state) { case XZ_STATE_STREAM_HEADER: { @@ -690,6 +698,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, else { RINOK(Xz_ParseHeader(&p->streamFlags, p->buf)); + p->numStartedStreams++; p->state = XZ_STATE_BLOCK_HEADER; Sha256_Init(&p->sha); p->indexSize = 0; @@ -730,6 +739,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, else { RINOK(XzBlock_Parse(&p->block, p->buf)); + p->numTotalBlocks++; p->state = XZ_STATE_BLOCK; p->packSize = 0; p->unpackSize = 0; @@ -847,7 +857,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, if (p->pos == XZ_STREAM_FOOTER_SIZE) { p->state = XZ_STATE_STREAM_PADDING; - p->numStreams++; + p->numFinishedStreams++; p->padSize = 0; if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf)) return SZ_ERROR_CRC; @@ -887,3 +897,13 @@ Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p) { return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0); } + +UInt64 XzUnpacker_GetExtraSize(CXzUnpacker *p) +{ + UInt64 num = 0; + if (p->state == XZ_STATE_STREAM_PADDING) + num += p->padSize; + else if (p->state == XZ_STATE_STREAM_HEADER) + num += p->padSize + p->pos; + return num; +} diff --git a/C/XzEnc.c b/C/XzEnc.c old mode 100755 new mode 100644 index 56cfd579..835cb63b --- a/C/XzEnc.c +++ b/C/XzEnc.c @@ -1,5 +1,7 @@ /* XzEnc.c -- Xz Encode -2011-02-07 : Igor Pavlov : Public domain */ +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include #include @@ -218,7 +220,7 @@ static SRes SeqInFilter_Read(void *pp, void *data, size_t *size) CSeqInFilter *p = (CSeqInFilter *)pp; size_t sizeOriginal = *size; if (sizeOriginal == 0) - return S_OK; + return SZ_OK; *size = 0; for (;;) { @@ -274,7 +276,7 @@ static SRes SeqInFilter_Init(CSeqInFilter *p, const CXzFilter *props) RINOK(BraState_SetFromMethod(&p->StateCoder, props->id, 1, &g_Alloc)); RINOK(p->StateCoder.SetProps(p->StateCoder.p, props->props, props->propsSize, &g_Alloc)); p->StateCoder.Init(p->StateCoder.p); - return S_OK; + return SZ_OK; } /* ---------- CSbEncInStream ---------- */ diff --git a/C/XzEnc.h b/C/XzEnc.h old mode 100755 new mode 100644 diff --git a/C/XzIn.c b/C/XzIn.c old mode 100755 new mode 100644 index 4ba87a2c..4f418638 --- a/C/XzIn.c +++ b/C/XzIn.c @@ -1,5 +1,7 @@ /* XzIn.c - Xz input -2011-02-01 : Igor Pavlov : Public domain */ +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" #include diff --git a/CPP/7zip/7zip.mak b/CPP/7zip/7zip.mak new file mode 100644 index 00000000..7fbe2ada --- /dev/null +++ b/CPP/7zip/7zip.mak @@ -0,0 +1,240 @@ +OBJS = \ + $O\StdAfx.obj \ + $(CURRENT_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(WIN_CTRL_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(AR_OBJS) \ + $(AR_COMMON_OBJS) \ + $(UI_COMMON_OBJS) \ + $(AGENT_OBJS) \ + $(CONSOLE_OBJS) \ + $(EXPLORER_OBJS) \ + $(FM_OBJS) \ + $(GUI_OBJS) \ + $(7Z_OBJS) \ + $(CAB_OBJS) \ + $(CHM_OBJS) \ + $(COM_OBJS) \ + $(ISO_OBJS) \ + $(NSIS_OBJS) \ + $(RAR_OBJS) \ + $(TAR_OBJS) \ + $(UDF_OBJS) \ + $(WIM_OBJS) \ + $(ZIP_OBJS) \ + $(COMPRESS_OBJS) \ + $(CRYPTO_OBJS) \ + $(C_OBJS) \ + $(ASM_OBJS) \ + $O\resource.res \ + +!include "../../../Build.mak" + +# MAK_SINGLE_FILE = 1 + +!IFDEF MAK_SINGLE_FILE + +!IFDEF CURRENT_OBJS +$(CURRENT_OBJS): ./$(*B).cpp + $(COMPL) +!ENDIF + + +!IFDEF COMMON_OBJS +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF WIN_OBJS +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF WIN_CTRL_OBJS +$(WIN_CTRL_OBJS): ../../../Windows/Control/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF 7ZIP_COMMON_OBJS +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF AR_OBJS +$(AR_OBJS): ../../Archive/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF AR_COMMON_OBJS +$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF 7Z_OBJS +$(7Z_OBJS): ../../Archive/7z/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF CAB_OBJS +$(CAB_OBJS): ../../Archive/Cab/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF CHM_OBJS +$(CHM_OBJS): ../../Archive/Chm/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF COM_OBJS +$(COM_OBJS): ../../Archive/Com/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF ISO_OBJS +$(ISO_OBJS): ../../Archive/Iso/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF NSIS_OBJS +$(NSIS_OBJS): ../../Archive/Nsis/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF RAR_OBJS +$(RAR_OBJS): ../../Archive/Rar/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF TAR_OBJS +$(TAR_OBJS): ../../Archive/Tar/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF UDF_OBJS +$(UDF_OBJS): ../../Archive/Udf/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF WIM_OBJS +$(WIM_OBJS): ../../Archive/Wim/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF ZIP_OBJS +$(ZIP_OBJS): ../../Archive/Zip/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF COMPRESS_OBJS +$(COMPRESS_OBJS): ../../Compress/$(*B).cpp + $(COMPL_O2) +!ENDIF + +!IFDEF CRYPTO_OBJS +$(CRYPTO_OBJS): ../../Crypto/$(*B).cpp + $(COMPL_O2) +!ENDIF + +!IFDEF UI_COMMON_OBJS +$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF AGENT_OBJS +$(AGENT_OBJS): ../../UI/Agent/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF CONSOLE_OBJS +$(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF EXPLORER_OBJS +$(EXPLORER_OBJS): ../../UI/Explorer/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF FM_OBJS +$(FM_OBJS): ../../UI/FileManager/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF GUI_OBJS +$(GUI_OBJS): ../../UI/GUI/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF C_OBJS +$(C_OBJS): ../../../../C/$(*B).c + $(COMPL_O2) +!ENDIF + + +!ELSE + +{.}.cpp{$O}.obj:: + $(COMPLB) +{../../../Common}.cpp{$O}.obj:: + $(COMPLB) +{../../../Windows}.cpp{$O}.obj:: + $(COMPLB) +{../../../Windows/Control}.cpp{$O}.obj:: + $(COMPLB) +{../../Common}.cpp{$O}.obj:: + $(COMPLB) + +{../../UI/Common}.cpp{$O}.obj:: + $(COMPLB) +{../../UI/Agent}.cpp{$O}.obj:: + $(COMPLB) +{../../UI/Console}.cpp{$O}.obj:: + $(COMPLB) +{../../UI/Explorer}.cpp{$O}.obj:: + $(COMPLB) +{../../UI/FileManager}.cpp{$O}.obj:: + $(COMPLB) +{../../UI/GUI}.cpp{$O}.obj:: + $(COMPLB) + + +{../../Archive}.cpp{$O}.obj:: + $(COMPLB) +{../../Archive/Common}.cpp{$O}.obj:: + $(COMPLB) + +{../../Archive/7z}.cpp{$O}.obj:: + $(COMPLB) +{../../Archive/Cab}.cpp{$O}.obj:: + $(COMPLB) +{../../Archive/Chm}.cpp{$O}.obj:: + $(COMPLB) +{../../Archive/Com}.cpp{$O}.obj:: + $(COMPLB) +{../../Archive/Iso}.cpp{$O}.obj:: + $(COMPLB) +{../../Archive/Nsis}.cpp{$O}.obj:: + $(COMPLB) +{../../Archive/Rar}.cpp{$O}.obj:: + $(COMPLB) +{../../Archive/Tar}.cpp{$O}.obj:: + $(COMPLB) +{../../Archive/Udf}.cpp{$O}.obj:: + $(COMPLB) +{../../Archive/Wim}.cpp{$O}.obj:: + $(COMPLB) +{../../Archive/Zip}.cpp{$O}.obj:: + $(COMPLB) + +{../../Compress}.cpp{$O}.obj:: + $(COMPLB_O2) +{../../Crypto}.cpp{$O}.obj:: + $(COMPLB_O2) +{../../../../C}.c{$O}.obj:: + $(CCOMPLB) + +!ENDIF + +!include "Asm.mak" diff --git a/CPP/7zip/Aes.mak b/CPP/7zip/Aes.mak old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/7z/7z.dsp b/CPP/7zip/Archive/7z/7z.dsp old mode 100755 new mode 100644 index 0484228d..53913f77 --- a/CPP/7zip/Archive/7z/7z.dsp +++ b/CPP/7zip/Archive/7z/7z.dsp @@ -328,6 +328,14 @@ SOURCE=..\..\..\Common\StringToInt.cpp SOURCE=..\..\..\Common\StringToInt.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 "Archive Common" @@ -482,6 +490,10 @@ SOURCE=..\..\Common\ProgressUtils.h # End Source File # Begin Source File +SOURCE=..\..\Common\PropId.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Common\RegisterArc.h # End Source File # Begin Source File @@ -558,6 +570,10 @@ 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 diff --git a/CPP/7zip/Archive/7z/7z.dsw b/CPP/7zip/Archive/7z/7z.dsw old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.cpp b/CPP/7zip/Archive/7z/7zCompressionMode.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.h b/CPP/7zip/Archive/7z/7zCompressionMode.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/7z/7zDecode.cpp b/CPP/7zip/Archive/7z/7zDecode.cpp old mode 100755 new mode 100644 index 425a3415..7f0e45d1 --- a/CPP/7zip/Archive/7z/7zDecode.cpp +++ b/CPP/7zip/Archive/7z/7zDecode.cpp @@ -16,29 +16,33 @@ static void ConvertFolderItemInfoToBindInfo(const CFolder &folder, CBindInfoEx &bindInfo) { bindInfo.Clear(); - int i; + bindInfo.BindPairs.ClearAndSetSize(folder.BindPairs.Size()); + unsigned i; for (i = 0; i < folder.BindPairs.Size(); i++) { - NCoderMixer::CBindPair bindPair; + NCoderMixer::CBindPair &bindPair = bindInfo.BindPairs[i]; bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex; bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex; - bindInfo.BindPairs.Add(bindPair); } + + bindInfo.Coders.ClearAndSetSize(folder.Coders.Size()); + bindInfo.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size()); + UInt32 outStreamIndex = 0; for (i = 0; i < folder.Coders.Size(); i++) { - NCoderMixer::CCoderStreamsInfo coderStreamsInfo; + NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i]; 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); + bindInfo.CoderMethodIDs[i] = coderInfo.MethodID; for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++) if (folder.FindBindPairForOutStream(outStreamIndex) < 0) bindInfo.OutStreams.Add(outStreamIndex); } + bindInfo.InStreams.ClearAndSetSize(folder.PackStreams.Size()); for (i = 0; i < folder.PackStreams.Size(); i++) - bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]); + bindInfo.InStreams[i] = (UInt32)folder.PackStreams[i]; } static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1, @@ -58,7 +62,7 @@ static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2) { if (a1.Coders.Size() != a2.Coders.Size()) return false; - int i; + unsigned i; for (i = 0; i < a1.Coders.Size(); i++) if (!AreCodersEqual(a1.Coders[i], a2.Coders[i])) return false; @@ -90,45 +94,49 @@ HRESULT CDecoder::Decode( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, - const UInt64 *packSizes, - const CFolder &folderInfo, + const CFolders &folders, int folderIndex, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress - #ifndef _NO_CRYPTO - , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined - #endif + _7Z_DECODER_CRYPRO_VARS_DECL #if !defined(_7ZIP_ST) && !defined(_SFX) , bool mtMode, UInt32 numThreads #endif ) { - if (!folderInfo.CheckStructure()) + const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]]; + CFolder folderInfo; + folders.ParseFolderInfo(folderIndex, folderInfo); + + if (!folderInfo.CheckStructure(folders.GetNumFolderUnpackSizes(folderIndex))) return E_NOTIMPL; + + /* + We don't need to init isEncrypted and passwordIsDefined + We must upgrade them only #ifndef _NO_CRYPTO + isEncrypted = false; passwordIsDefined = false; #endif + */ + CObjectVector< CMyComPtr > inStreams; CLockedInStream lockedInStream; lockedInStream.Init(inStream); - for (int j = 0; j < folderInfo.PackStreams.Size(); j++) + for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++) { - CLockedSequentialInStreamImp *lockedStreamImpSpec = new - CLockedSequentialInStreamImp; + CLockedSequentialInStreamImp *lockedStreamImpSpec = new CLockedSequentialInStreamImp; CMyComPtr lockedStreamImp = lockedStreamImpSpec; - lockedStreamImpSpec->Init(&lockedInStream, startPos); - startPos += packSizes[j]; - - CLimitedSequentialInStream *streamSpec = new - CLimitedSequentialInStream; + lockedStreamImpSpec->Init(&lockedInStream, startPos + packPositions[j]); + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr inStream = streamSpec; streamSpec->SetStream(lockedStreamImp); - streamSpec->Init(packSizes[j]); + streamSpec->Init(packPositions[j + 1] - packPositions[j]); inStreams.Add(inStream); } - int numCoders = folderInfo.Coders.Size(); + unsigned numCoders = folderInfo.Coders.Size(); CBindInfoEx bindInfo; ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo); @@ -139,7 +147,7 @@ HRESULT CDecoder::Decode( createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev); if (createNewCoders) { - int i; + unsigned i; _decoders.Clear(); // _decoders2.Clear(); @@ -204,17 +212,19 @@ HRESULT CDecoder::Decode( decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { - RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); + RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs)); } #endif } _bindInfoExPrev = bindInfo; _bindInfoExPrevIsDefined = true; } - int i; + unsigned i; _mixerCoderCommon->ReInit(); - UInt32 packStreamIndex = 0, unpackStreamIndex = 0; + UInt32 packStreamIndex = 0; + UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex]; + UInt32 unpackStreamIndex = unpackStreamIndexStart; UInt32 coderIndex = 0; // UInt32 coder2Index = 0; @@ -229,7 +239,7 @@ HRESULT CDecoder::Decode( if (setDecoderProperties) { const CByteBuffer &props = coderInfo.Props; - size_t size = props.GetCapacity(); + size_t size = props.Size(); if (size > 0xFFFFFFFF) return E_NOTIMPL; // if (size > 0) @@ -257,22 +267,23 @@ HRESULT CDecoder::Decode( decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { - if (getTextPassword == 0) - return E_FAIL; + isEncrypted = true; + if (!getTextPassword) + return E_NOTIMPL; 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++) + size_t len = 0; + if (passwordBSTR) + len = MyStringLen((BSTR)passwordBSTR); + CByteBuffer buffer(len * 2); + for (size_t i = 0; i < len; i++) { - wchar_t c = password[i]; + wchar_t c = passwordBSTR[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } - RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes)); + RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size())); } } #endif @@ -281,32 +292,30 @@ HRESULT CDecoder::Decode( UInt32 numInStreams = (UInt32)coderInfo.NumInStreams; UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams; - CRecordVector packSizesPointers; - CRecordVector unpackSizesPointers; - packSizesPointers.Reserve(numInStreams); - unpackSizesPointers.Reserve(numOutStreams); + CObjArray packSizes(numInStreams); + CObjArray packSizesPointers(numInStreams); + CObjArray unpackSizesPointers(numOutStreams); UInt32 j; + for (j = 0; j < numOutStreams; j++, unpackStreamIndex++) - unpackSizesPointers.Add(&folderInfo.UnpackSizes[unpackStreamIndex]); + unpackSizesPointers[j] = &folders.CoderUnpackSizes[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]); + packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + (UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]; else { int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex); if (index < 0) - return E_FAIL; - packSizesPointers.Add(&packSizes[index]); + return S_FALSE; // check it + packSizes[j] = packPositions[index + 1] - packPositions[index]; + packSizesPointers[j] = &packSizes[j]; } } - _mixerCoderCommon->SetCoderInfo(i, - &packSizesPointers.Front(), - &unpackSizesPointers.Front()); + _mixerCoderCommon->SetCoderInfo(i, packSizesPointers, unpackSizesPointers); } UInt32 mainCoder, temp; bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp); @@ -320,13 +329,15 @@ HRESULT CDecoder::Decode( if (numCoders == 0) return 0; - CRecordVector inStreamPointers; - inStreamPointers.Reserve(inStreams.Size()); - for (i = 0; i < inStreams.Size(); i++) - inStreamPointers.Add(inStreams[i]); + unsigned num = inStreams.Size(); + CObjArray inStreamPointers(num); + for (i = 0; i < num; i++) + inStreamPointers[i] = inStreams[i]; ISequentialOutStream *outStreamPointer = outStream; - return _mixerCoder->Code(&inStreamPointers.Front(), NULL, - inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress); + return _mixerCoder->Code( + inStreamPointers, NULL, num, + &outStreamPointer, NULL, 1, + compressProgress); } }} diff --git a/CPP/7zip/Archive/7z/7zDecode.h b/CPP/7zip/Archive/7z/7zDecode.h old mode 100755 new mode 100644 index d8a424a3..1361772c --- a/CPP/7zip/Archive/7z/7zDecode.h +++ b/CPP/7zip/Archive/7z/7zDecode.h @@ -14,7 +14,7 @@ #include "../../Common/CreateCoder.h" -#include "7zItem.h" +#include "7zIn.h" namespace NArchive { namespace N7z { @@ -50,13 +50,10 @@ public: DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, - const UInt64 *packSizes, - const CFolder &folder, + const CFolders &folders, int folderIndex, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress - #ifndef _NO_CRYPTO - , ICryptoGetTextPassword *getTextPasswordSpec, bool &passwordIsDefined - #endif + _7Z_DECODER_CRYPRO_VARS_DECL #if !defined(_7ZIP_ST) && !defined(_SFX) , bool mtMode, UInt32 numThreads #endif diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp old mode 100755 new mode 100644 index 614f9913..36ff5177 --- a/CPP/7zip/Archive/7z/7zEncode.cpp +++ b/CPP/7zip/Archive/7z/7zEncode.cpp @@ -23,30 +23,30 @@ static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindIn const CRecordVector decompressionMethods, CFolder &folder) { - folder.Coders.Clear(); // bindInfo.CoderMethodIDs.Clear(); // folder.OutStreams.Clear(); - folder.PackStreams.Clear(); - folder.BindPairs.Clear(); - int i; + folder.BindPairs.SetSize(bindInfo.BindPairs.Size()); + unsigned 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); + CBindPair &bp = folder.BindPairs[i]; + const NCoderMixer::CBindPair &mixerBp = bindInfo.BindPairs[i]; + bp.InIndex = mixerBp.InIndex; + bp.OutIndex = mixerBp.OutIndex; } + folder.Coders.SetSize(bindInfo.Coders.Size()); for (i = 0; i < bindInfo.Coders.Size(); i++) { - CCoderInfo coderInfo; + CCoderInfo &coderInfo = folder.Coders[i]; const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i]; coderInfo.NumInStreams = coderStreamsInfo.NumInStreams; coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams; coderInfo.MethodID = decompressionMethods[i]; - folder.Coders.Add(coderInfo); + // coderInfo.Props can be nonFree; } + folder.PackStreams.SetSize(bindInfo.InStreams.Size()); for (i = 0; i < bindInfo.InStreams.Size(); i++) - folder.PackStreams.Add(bindInfo.InStreams[i]); + folder.PackStreams[i] = bindInfo.InStreams[i]; } static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, IUnknown *coder) @@ -65,11 +65,10 @@ HRESULT CEncoder::CreateMixerCoder( _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT; _mixerCoder = _mixerCoderSpec; RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo)); - for (int i = 0; i < _options.Methods.Size(); i++) + FOR_VECTOR (i, _options.Methods) { const CMethodFull &methodFull = _options.Methods[i]; - _codersInfo.Add(CCoderInfo()); - CCoderInfo &encodingInfo = _codersInfo.Back(); + CCoderInfo &encodingInfo = _codersInfo.AddNew(); encodingInfo.MethodID = methodFull.Id; CMyComPtr encoder; CMyComPtr encoder2; @@ -100,7 +99,7 @@ HRESULT CEncoder::CreateMixerCoder( /* CMyComPtr resetSalt; encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt); - if (resetSalt != NULL) + if (resetSalt) { resetSalt->ResetSalt(); } @@ -111,7 +110,7 @@ HRESULT CEncoder::CreateMixerCoder( encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { - RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); + RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs)); } #endif @@ -120,10 +119,9 @@ HRESULT CEncoder::CreateMixerCoder( if (cryptoSetPassword) { - CByteBuffer buffer; - const UInt32 sizeInBytes = _options.Password.Length() * 2; - buffer.SetCapacity(sizeInBytes); - for (int i = 0; i < _options.Password.Length(); i++) + const UInt32 sizeInBytes = _options.Password.Len() * 2; + CByteBuffer buffer(sizeInBytes); + for (unsigned i = 0; i < _options.Password.Len(); i++) { wchar_t c = _options.Password[i]; ((Byte *)buffer)[i * 2] = (Byte)c; @@ -145,13 +143,15 @@ HRESULT CEncoder::Encode( ISequentialInStream *inStream, const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, CFolder &folderItem, + CRecordVector &coderUnpackSizes, + UInt64 &unpackSize, ISequentialOutStream *outStream, CRecordVector &packSizes, ICompressProgressInfo *compressProgress) { RINOK(EncoderConstr()); - if (_mixerCoderSpec == NULL) + if (!_mixerCoderSpec) { RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce)); } @@ -161,13 +161,13 @@ HRESULT CEncoder::Encode( CObjectVector inOutTempBuffers; CObjectVector tempBufferSpecs; CObjectVector > tempBuffers; - int numMethods = _bindInfo.Coders.Size(); - int i; + unsigned numMethods = _bindInfo.Coders.Size(); + unsigned i; for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { - inOutTempBuffers.Add(CInOutTempBuffer()); - inOutTempBuffers.Back().Create(); - inOutTempBuffers.Back().InitWriting(); + CInOutTempBuffer &iotb = inOutTempBuffers.AddNew(); + iotb.Create(); + iotb.InitWriting(); } for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { @@ -186,7 +186,7 @@ HRESULT CEncoder::Encode( UInt32 mainCoderIndex, mainStreamIndex; _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex); - if (inStreamSize != NULL) + if (inStreamSize) { CRecordVector sizePointers; for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++) @@ -203,17 +203,24 @@ HRESULT CEncoder::Encode( CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2; CMyComPtr inStreamSizeCount = inStreamSizeCountSpec; - CSequentialOutStreamSizeCount *outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; - CMyComPtr outStreamSizeCount = outStreamSizeCountSpec; + CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL; + CMyComPtr outStreamSizeCount; inStreamSizeCountSpec->Init(inStream); - outStreamSizeCountSpec->SetStream(outStream); - outStreamSizeCountSpec->Init(); CRecordVector inStreamPointers; CRecordVector outStreamPointers; inStreamPointers.Add(inStreamSizeCount); - outStreamPointers.Add(outStreamSizeCount); + + if (_bindInfo.OutStreams.Size() != 0) + { + outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; + outStreamSizeCount = outStreamSizeCountSpec; + outStreamSizeCountSpec->SetStream(outStream); + outStreamSizeCountSpec->Init(); + outStreamPointers.Add(outStreamSizeCount); + } + for (i = 1; i < _bindInfo.OutStreams.Size(); i++) outStreamPointers.Add(tempBuffers[i - 1]); @@ -223,14 +230,14 @@ HRESULT CEncoder::Encode( CMyComPtr resetInitVector; _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector); - if (resetInitVector != NULL) + if (resetInitVector) { resetInitVector->ResetInitVector(); } CMyComPtr writeCoderProperties; _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); - if (writeCoderProperties != NULL) + if (writeCoderProperties) { CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream; CMyComPtr outStream(outStreamSpec); @@ -256,7 +263,8 @@ HRESULT CEncoder::Encode( ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem); - packSizes.Add(outStreamSizeCountSpec->GetSize()); + if (_bindInfo.OutStreams.Size() != 0) + packSizes.Add(outStreamSizeCountSpec->GetSize()); for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { @@ -264,19 +272,23 @@ HRESULT CEncoder::Encode( RINOK(inOutTempBuffer.WriteToStream(outStream)); packSizes.Add(inOutTempBuffer.GetDataSize()); } - + + unpackSize = 0; for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++) { int binder = _bindInfo.FindBinderForInStream( _bindReverseConverter->DestOutToSrcInMap[i]); UInt64 streamSize; if (binder < 0) + { streamSize = inStreamSizeCountSpec->GetSize(); + unpackSize = streamSize; + } else streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder); - folderItem.UnpackSizes.Add(streamSize); + coderUnpackSizes.Add(streamSize); } - for (i = numMethods - 1; i >= 0; i--) + for (i = 0; i < numMethods; i++) folderItem.Coders[numMethods - 1 - i].Props = _codersInfo[i].Props; return S_OK; } @@ -323,7 +335,7 @@ HRESULT CEncoder::EncoderConstr() { UInt32 numInStreams = 0, numOutStreams = 0; - int i; + unsigned i; for (i = 0; i < _options.Methods.Size(); i++) { const CMethodFull &methodFull = _options.Methods[i]; @@ -339,7 +351,7 @@ HRESULT CEncoder::EncoderConstr() bindPair.OutIndex = numOutStreams; _bindInfo.BindPairs.Add(bindPair); } - else + else if (coderStreamsInfo.NumOutStreams != 0) _bindInfo.OutStreams.Insert(0, numOutStreams); for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++) _bindInfo.OutStreams.Add(numOutStreams + j); @@ -398,7 +410,7 @@ HRESULT CEncoder::EncoderConstr() if (_options.PasswordIsDefined) { - int numCryptoStreams = _bindInfo.OutStreams.Size(); + unsigned numCryptoStreams = _bindInfo.OutStreams.Size(); for (i = 0; i < numCryptoStreams; i++) { diff --git a/CPP/7zip/Archive/7z/7zEncode.h b/CPP/7zip/Archive/7z/7zEncode.h old mode 100755 new mode 100644 index 4909a6e8..8e20bdb5 --- a/CPP/7zip/Archive/7z/7zEncode.h +++ b/CPP/7zip/Archive/7z/7zEncode.h @@ -45,6 +45,8 @@ public: ISequentialInStream *inStream, const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, CFolder &folderItem, + CRecordVector &coderUnpackSizes, + UInt64 &unpackSize, ISequentialOutStream *outStream, CRecordVector &packSizes, ICompressProgressInfo *compressProgress); diff --git a/CPP/7zip/Archive/7z/7zExtract.cpp b/CPP/7zip/Archive/7z/7zExtract.cpp old mode 100755 new mode 100644 index d55f38e1..6d2c5b06 --- a/CPP/7zip/Archive/7z/7zExtract.cpp +++ b/CPP/7zip/Archive/7z/7zExtract.cpp @@ -37,8 +37,8 @@ struct CExtractFolderInfo { if (fileIndex != kNumNoIndex) { - ExtractStatuses.Reserve(1); - ExtractStatuses.Add(true); + ExtractStatuses.ClearAndSetSize(1); + ExtractStatuses[0] = true; } }; }; @@ -51,7 +51,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CMyComPtr extractCallback = extractCallbackSpec; UInt64 importantTotalUnpacked = 0; - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = #ifdef _7Z_VOL @@ -67,7 +67,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if(_volumes.Size() != 1) return E_FAIL; const CVolume &volume = _volumes.Front(); - const CArchiveDatabaseEx &_db = volume.Database; + const CDbEx &_db = volume.Database; IInStream *_inStream = volume.Stream; */ @@ -86,10 +86,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, int volumeIndex = ref.VolumeIndex; const CVolume &volume = _volumes[volumeIndex]; - const CArchiveDatabaseEx &db = volume.Database; + const CDbEx &db = volume.Database; UInt32 fileIndex = ref.ItemIndex; #else - const CArchiveDatabaseEx &db = _db; + const CDbEx &db = _db; UInt32 fileIndex = ref2Index; #endif @@ -115,8 +115,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, volumeIndex, #endif kNumNoIndex, folderIndex)); - const CFolder &folderInfo = db.Folders[folderIndex]; - UInt64 unpackSize = folderInfo.GetUnpackSize(); + UInt64 unpackSize = db.GetFolderUnpackSize(folderIndex); importantTotalUnpacked += unpackSize; extractFolderInfoVector.Back().UnpackSize = unpackSize; } @@ -156,7 +155,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CMyComPtr progress = lps; lps->Init(extractCallback, false); - for (int i = 0;; i++, totalUnpacked += curUnpacked, totalPacked += curPacked) + for (unsigned i = 0;; i++, totalUnpacked += curUnpacked, totalPacked += curPacked) { lps->OutSize = totalUnpacked; lps->InSize = totalPacked; @@ -174,9 +173,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, #ifdef _7Z_VOL const CVolume &volume = _volumes[efi.VolumeIndex]; - const CArchiveDatabaseEx &db = volume.Database; + const CDbEx &db = volume.Database; #else - const CArchiveDatabaseEx &db = _db; + const CDbEx &db = _db; #endif CNum startIndex; @@ -200,13 +199,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, 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) @@ -216,26 +210,24 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, try { #ifndef _NO_CRYPTO - bool passwordIsDefined; + bool isEncrypted = false; + bool passwordIsDefined = false; #endif HRESULT result = decoder.Decode( EXTERNAL_CODECS_VARS #ifdef _7Z_VOL - volume.Stream, + volume.Stream, #else - _inStream, + _inStream, #endif - folderStartPackPos, - &db.PackSizes[packStreamIndex], - folderInfo, + db.ArcInfo.DataStartPosition, + db, folderIndex, outStream, progress - #ifndef _NO_CRYPTO - , getTextPassword, passwordIsDefined - #endif + _7Z_DECODER_CRYPRO_VARS #if !defined(_7ZIP_ST) && !defined(_SFX) - , true, _numThreads + , true, _numThreads #endif ); @@ -246,7 +238,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } if (result == E_NOTIMPL) { - RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kUnSupportedMethod)); + RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kUnsupportedMethod)); continue; } if (result != S_OK) diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.cpp b/CPP/7zip/Archive/7z/7zFolderInStream.cpp old mode 100755 new mode 100644 index edd276bc..3f420a51 --- a/CPP/7zip/Archive/7z/7zFolderInStream.cpp +++ b/CPP/7zip/Archive/7z/7zFolderInStream.cpp @@ -106,8 +106,8 @@ STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSiz STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value) { *value = 0; - int index2 = (int)subStream; - if (index2 < 0 || subStream > Sizes.Size()) + unsigned index2 = (unsigned)subStream; + if (subStream > Sizes.Size()) return E_FAIL; if (index2 < Sizes.Size()) { diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.h b/CPP/7zip/Archive/7z/7zFolderInStream.h old mode 100755 new mode 100644 index 6df3672a..4ed4b2dd --- a/CPP/7zip/Archive/7z/7zFolderInStream.h +++ b/CPP/7zip/Archive/7z/7zFolderInStream.h @@ -47,7 +47,7 @@ public: UInt64 GetFullSize() const { UInt64 size = 0; - for (int i = 0; i < Sizes.Size(); i++) + FOR_VECTOR (i, Sizes) size += Sizes[i]; return size; } diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.cpp b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp old mode 100755 new mode 100644 index 22c4600e..847f65bf --- a/CPP/7zip/Archive/7z/7zFolderOutStream.cpp +++ b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp @@ -14,7 +14,7 @@ CFolderOutStream::CFolderOutStream() } HRESULT CFolderOutStream::Init( - const CArchiveDatabaseEx *db, + const CDbEx *db, UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.h b/CPP/7zip/Archive/7z/7zFolderOutStream.h old mode 100755 new mode 100644 index f9bb1af4..cc2d7734 --- a/CPP/7zip/Archive/7z/7zFolderOutStream.h +++ b/CPP/7zip/Archive/7z/7zFolderOutStream.h @@ -19,12 +19,12 @@ class CFolderOutStream: { COutStreamWithCRC *_crcStreamSpec; CMyComPtr _crcStream; - const CArchiveDatabaseEx *_db; + const CDbEx *_db; const CBoolVector *_extractStatuses; CMyComPtr _extractCallback; UInt32 _ref2Offset; UInt32 _startIndex; - int _currentIndex; + unsigned _currentIndex; bool _testMode; bool _checkCrc; bool _fileIsOpen; @@ -43,7 +43,7 @@ public: STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); HRESULT Init( - const CArchiveDatabaseEx *db, + const CDbEx *db, UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp old mode 100755 new mode 100644 index 93d4f51e..82983419 --- a/CPP/7zip/Archive/7z/7zHandler.cpp +++ b/CPP/7zip/Archive/7z/7zHandler.cpp @@ -23,6 +23,7 @@ #endif using namespace NWindows; +using namespace NCOM; namespace NArchive { namespace N7z { @@ -30,6 +31,7 @@ namespace N7z { CHandler::CHandler() { #ifndef _NO_CRYPTO + _isEncrypted = false; _passwordIsDefined = false; #endif @@ -49,11 +51,12 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) #ifdef _SFX -IMP_IInArchive_ArcProps_NO +IMP_IInArchive_ArcProps_NO_Table -STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */) +STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) { - return E_NOTIMPL; + *numProps = 0; + return S_OK; } STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */, @@ -62,156 +65,473 @@ STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */, return E_NOTIMPL; } - #else -static const STATPROPSTG kArcProps[] = +static const Byte 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} + kpidHeadersSize, + kpidMethod, + kpidSolid, + kpidNumBlocks + // , kpidIsTree }; -static inline wchar_t GetHex(Byte value) +IMP_IInArchive_ArcProps + +static inline char GetHex(unsigned value) { - return (wchar_t)((value < 10) ? ('0' + value) : ('A' + (value - 10))); + return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); } -static UString ConvertMethodIdToString(UInt64 id) +static unsigned ConvertMethodIdToString_Back(char *s, UInt64 id) { - wchar_t s[32]; - int len = 32; - s[--len] = 0; + int len = 0; do { - s[--len] = GetHex((Byte)id & 0xF); id >>= 4; - s[--len] = GetHex((Byte)id & 0xF); id >>= 4; + s[--len] = GetHex((unsigned)id & 0xF); id >>= 4; + s[--len] = GetHex((unsigned)id & 0xF); id >>= 4; } while (id != 0); - return s + len; + return (unsigned)-len; +} + +static void ConvertMethodIdToString(AString &res, UInt64 id) +{ + const unsigned kLen = 32; + char s[kLen]; + unsigned len = kLen - 1; + s[len] = 0; + res += s + len - ConvertMethodIdToString_Back(s + len, id); +} + +static unsigned GetStringForSizeValue(char *s, UInt32 val) +{ + unsigned i; + for (i = 0; i <= 31; i++) + if (((UInt32)1 << i) == val) + { + if (i < 10) + { + s[0] = (char)('0' + i); + s[1] = 0; + return 1; + } + if (i < 20) { s[0] = '1'; s[1] = (char)('0' + i - 10); } + else if (i < 30) { s[0] = '2'; s[1] = (char)('0' + i - 20); } + else { s[0] = '3'; s[1] = (char)('0' + i - 30); } + s[2] = 0; + return 2; + } + char c = 'b'; + if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; } + else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; } + ::ConvertUInt32ToString(val, s); + unsigned pos = MyStringLen(s); + s[pos++] = c; + s[pos] = 0; + return pos; } +/* +static inline void AddHexToString(UString &res, Byte value) +{ + res += GetHex((Byte)(value >> 4)); + res += GetHex((Byte)(value & 0xF)); +} +*/ + +static char *AddProp32(char *s, const char *name, UInt32 v) +{ + *s++ = ':'; + s = MyStpCpy(s, name); + ::ConvertUInt32ToString(v, s); + return s + MyStringLen(s); +} + +void CHandler::AddMethodName(AString &s, UInt64 id) +{ + UString methodName; + FindMethod(EXTERNAL_CODECS_VARS id, methodName); + if (methodName.IsEmpty()) + { + for (unsigned i = 0; i < methodName.Len(); i++) + if (methodName[i] >= 0x80) + { + methodName.Empty(); + break; + } + } + if (methodName.IsEmpty()) + ConvertMethodIdToString(s, id); + else + for (unsigned i = 0; i < methodName.Len(); i++) + s += (char)methodName[i]; +} + +#endif + STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { + #ifndef _SFX COM_TRY_BEGIN + #endif NCOM::CPropVariant prop; - switch(propID) + switch (propID) { + #ifndef _SFX case kpidMethod: { - UString resString; - CRecordVector ids; - int i; - for (i = 0; i < _db.Folders.Size(); i++) + AString s; + const CParsedMethods &pm = _db.ParsedMethods; + FOR_VECTOR (i, pm.IDs) { - 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; + UInt64 id = pm.IDs[i]; + if (!s.IsEmpty()) + s += ' '; + char temp[16]; + if (id == k_LZMA2) + { + s += "LZMA2:"; + if ((pm.Lzma2Prop & 1) == 0) + ConvertUInt32ToString((pm.Lzma2Prop >> 1) + 12, temp); + else + GetStringForSizeValue(temp, 3 << ((pm.Lzma2Prop >> 1) + 11)); + s += temp; + } + else if (id == k_LZMA) + { + s += "LZMA:"; + GetStringForSizeValue(temp, pm.LzmaDic); + s += temp; + } + else + AddMethodName(s, id); } - prop = resString; + prop = s; break; } case kpidSolid: prop = _db.IsSolid(); break; - case kpidNumBlocks: prop = (UInt32)_db.Folders.Size(); break; + case kpidNumBlocks: prop = (UInt32)_db.NumFolders; 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; + case kpidOffset: if (_db.ArcInfo.StartPosition != 0) prop = _db.ArcInfo.StartPosition; break; + /* + case kpidIsTree: if (_db.IsTree) prop = true; break; + case kpidIsAltStream: if (_db.ThereAreAltStreams) prop = true; break; + case kpidIsAux: if (_db.IsTree) prop = true; break; + */ + // case kpidError: if (_db.ThereIsHeaderError) prop = "Header error"; break; + #endif + + case kpidWarningFlags: + { + UInt32 v = 0; + if (_db.StartHeaderWasRecovered) v |= kpv_ErrorFlags_HeadersError; + if (_db.UnsupportedFeatureWarning) v |= kpv_ErrorFlags_UnsupportedFeature; + if (v != 0) + prop = v; + break; + } + + case kpidErrorFlags: + { + UInt32 v = 0; + if (!_db.IsArc) v |= kpv_ErrorFlags_IsNotArc; + if (_db.ThereIsHeaderError) v |= kpv_ErrorFlags_HeadersError; + if (_db.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd; + // if (_db.UnsupportedVersion) v |= kpv_ErrorFlags_Unsupported; + if (_db.UnsupportedFeatureError) v |= kpv_ErrorFlags_UnsupportedFeature; + prop = v; + break; + } } prop.Detach(value); return S_OK; + #ifndef _SFX COM_TRY_END + #endif } -IMP_IInArchive_ArcProps - -#endif - -static void SetPropFromUInt64Def(CUInt64DefVector &v, int index, NCOM::CPropVariant &prop) +static void SetFileTimeProp_From_UInt64Def(PROPVARIANT *prop, const CUInt64DefVector &v, int index) { UInt64 value; if (v.GetItem(index, value)) + PropVarEm_Set_FileTime64(prop, value); +} + +bool CHandler::IsFolderEncrypted(CNum folderIndex) const +{ + if (folderIndex == kNumNoIndex) + return false; + size_t startPos = _db.FoCodersDataOffset[folderIndex]; + const Byte *p = _db.CodersData + startPos; + size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos; + CInByte2 inByte; + inByte.Init(p, size); + + CNum numCoders = inByte.ReadNum(); + for (; numCoders != 0; numCoders--) { - FILETIME ft; - ft.dwLowDateTime = (DWORD)value; - ft.dwHighDateTime = (DWORD)(value >> 32); - prop = ft; + Byte mainByte = inByte.ReadByte(); + unsigned idSize = (mainByte & 0xF); + const Byte *longID = inByte.GetPtr(); + UInt64 id64 = 0; + for (unsigned j = 0; j < idSize; j++) + id64 = ((id64 << 8) | longID[j]); + inByte.SkipDataNoCheck(idSize); + if (id64 == k_AES) + return true; + if ((mainByte & 0x20) != 0) + inByte.SkipDataNoCheck(inByte.ReadNum()); } + return false; } -#ifndef _SFX +STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps) +{ + *numProps = 0; + return S_OK; +} -static UString ConvertUInt32ToString(UInt32 value) +STDMETHODIMP CHandler::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID) { - wchar_t buffer[32]; - ConvertUInt64ToString(value, buffer); - return buffer; + *name = NULL; + *propID = kpidNtSecure; + return S_OK; } -static UString GetStringForSizeValue(UInt32 value) +STDMETHODIMP CHandler::GetParent(UInt32 /* index */, UInt32 *parent, UInt32 *parentType) { - 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) + /* + const CFileItem &file = _db.Files[index]; + *parentType = (file.IsAltStream ? NParentType::kAltStream : NParentType::kDir); + *parent = (UInt32)(Int32)file.Parent; + */ + *parentType = NParentType::kDir; + *parent = (UInt32)(Int32)-1; + return S_OK; +} + +STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) +{ + *data = NULL; + *dataSize = 0; + *propType = 0; + + if (/* _db.IsTree && propID == kpidName || + !_db.IsTree && */ propID == kpidPath) { - result += ConvertUInt32ToString(value >> 10); - result += L"k"; + *data = (void *)_db.GetName(index); + if (*data) + { + *dataSize = (UInt32)((_db.NameOffsets[index + 1] - _db.NameOffsets[index]) * 2); + *propType = NPropDataType::kUtf16z; + } + return S_OK; } - else + /* + if (propID == kpidNtSecure) { - result += ConvertUInt32ToString(value); - result += L"b"; + if (index < (UInt32)_db.SecureIDs.Size()) + { + int id = _db.SecureIDs[index]; + size_t offs = _db.SecureOffsets[id]; + size_t size = _db.SecureOffsets[id + 1] - offs; + if (size >= 0) + { + *data = _db.SecureBuf + offs; + *dataSize = (UInt32)size; + *propType = NPropDataType::kRaw; + } + } } - return result; + */ + return S_OK; } -static inline void AddHexToString(UString &res, Byte value) -{ - res += GetHex((Byte)(value >> 4)); - res += GetHex((Byte)(value & 0xF)); -} +#ifndef _SFX -static void AddProp32(UString &s, const wchar_t *name, UInt32 v) +HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const { - s += name; - s += ConvertUInt32ToString(v); -} + PropVariant_Clear(prop); + if (folderIndex == kNumNoIndex) + return S_OK; + // for (int ttt = 0; ttt < 1; ttt++) { + const unsigned kTempSize = 256; + char temp[kTempSize]; + unsigned pos = kTempSize; + temp[--pos] = 0; -#endif - -bool CHandler::IsEncrypted(UInt32 index2) const -{ - CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; - if (folderIndex != kNumNoIndex) - return _db.Folders[folderIndex].IsEncrypted(); - return false; + size_t startPos = _db.FoCodersDataOffset[folderIndex]; + const Byte *p = _db.CodersData + startPos; + size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos; + CInByte2 inByte; + inByte.Init(p, size); + + // numCoders == 0 ??? + CNum numCoders = inByte.ReadNum(); + bool needSpace = false; + for (; numCoders != 0; numCoders--, needSpace = true) + { + if (pos < 32) // max size of property + break; + Byte mainByte = inByte.ReadByte(); + unsigned idSize = (mainByte & 0xF); + const Byte *longID = inByte.GetPtr(); + UInt64 id64 = 0; + for (unsigned j = 0; j < idSize; j++) + id64 = ((id64 << 8) | longID[j]); + inByte.SkipDataNoCheck(idSize); + CNum propsSize = 0; + const Byte *props = NULL; + if ((mainByte & 0x20) != 0) + { + propsSize = inByte.ReadNum(); + props = inByte.GetPtr(); + inByte.SkipDataNoCheck(propsSize); + } + + const char *name = NULL; + char s[32]; + s[0] = 0; + + if (id64 <= (UInt32)0xFFFFFFFF) + { + UInt32 id = (UInt32)id64; + if (id == k_LZMA) + { + name = "LZMA"; + if (propsSize == 5) + { + UInt32 dicSize = GetUi32((const Byte *)props + 1); + char *dest = s + GetStringForSizeValue(s, dicSize); + UInt32 d = props[0]; + if (d != 0x5D) + { + UInt32 lc = d % 9; + d /= 9; + UInt32 pb = d / 5; + UInt32 lp = d % 5; + if (lc != 3) dest = AddProp32(dest, "lc", lc); + if (lp != 0) dest = AddProp32(dest, "lp", lp); + if (pb != 2) dest = AddProp32(dest, "pb", pb); + } + } + } + else if (id == k_LZMA2) + { + name = "LZMA2"; + if (propsSize == 1) + { + Byte p = props[0]; + if ((p & 1) == 0) + ConvertUInt32ToString((UInt32)((p >> 1) + 12), s); + else + GetStringForSizeValue(s, 3 << ((p >> 1) + 11)); + } + } + else if (id == k_PPMD) + { + name = "PPMD"; + if (propsSize == 5) + { + Byte order = *props; + char *dest = s; + *dest++ = 'o'; + ConvertUInt32ToString(order, dest); + dest += MyStringLen(dest); + dest = MyStpCpy(dest, ":mem"); + GetStringForSizeValue(dest, GetUi32(props + 1)); + } + } + else if (id == k_Delta) + { + name = "Delta"; + if (propsSize == 1) + ConvertUInt32ToString((UInt32)props[0] + 1, s); + } + else if (id == k_BCJ2) name = "BCJ2"; + else if (id == k_BCJ) name = "BCJ"; + else if (id == k_AES) + { + name = "7zAES"; + if (propsSize >= 1) + { + Byte firstByte = props[0]; + UInt32 numCyclesPower = firstByte & 0x3F; + ConvertUInt32ToString(numCyclesPower, s); + } + } + } + + if (name) + { + unsigned nameLen = MyStringLen(name); + unsigned propsLen = MyStringLen(s); + unsigned totalLen = nameLen + propsLen; + if (propsLen != 0) + totalLen++; + if (needSpace) + totalLen++; + if (totalLen + 5 >= pos) + break; + pos -= totalLen; + MyStringCopy(temp + pos, name); + if (propsLen != 0) + { + char *dest = temp + pos + nameLen; + *dest++ = ':'; + MyStringCopy(dest, s); + } + if (needSpace) + temp[pos + totalLen - 1] = ' '; + } + else + { + UString methodName; + FindMethod(EXTERNAL_CODECS_VARS id64, methodName); + if (methodName.IsEmpty()) + { + for (unsigned j = 0; j < methodName.Len(); j++) + if (methodName[j] >= 0x80) + { + methodName.Empty(); + break; + } + } + if (needSpace) + temp[--pos] = ' '; + if (methodName.IsEmpty()) + pos -= ConvertMethodIdToString_Back(temp + pos, id64); + else + { + unsigned len = methodName.Len(); + if (len + 5 > pos) + break; + pos -= len; + for (unsigned i = 0; i < len; i++) + temp[pos + i] = (char)methodName[i]; + } + } + } + if (numCoders != 0 && pos >= 4) + { + temp[--pos] = ' '; + temp[--pos] = '.'; + temp[--pos] = '.'; + temp[--pos] = '.'; + } + return PropVarEm_Set_Str(prop, temp + pos); + // } } -STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +#endif + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { - COM_TRY_BEGIN - NCOM::CPropVariant prop; + PropVariant_Clear(value); + // COM_TRY_BEGIN + // NCOM::CPropVariant prop; /* const CRef2 &ref2 = _refs[index]; @@ -225,14 +545,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va switch(propID) { - case kpidPath: - if (!item.Name.IsEmpty()) - prop = NItemName::GetOSName(item.Name); - break; - case kpidIsDir: prop = item.IsDir; break; + case kpidIsDir: PropVarEm_Set_Bool(value, item.IsDir); break; case kpidSize: { - prop = item.Size; + PropVarEm_Set_UInt64(value, item.Size); // prop = ref2.Size; break; } @@ -244,130 +560,49 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va if (folderIndex != kNumNoIndex) { if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2) - prop = _db.GetFolderFullPackSize(folderIndex); + PropVarEm_Set_UInt64(value, _db.GetFolderFullPackSize(folderIndex)); /* else - prop = (UInt64)0; + PropVarEm_Set_UInt64(value, 0); */ } else - prop = (UInt64)0; + PropVarEm_Set_UInt64(value, 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: + // case kpidIsAux: prop = _db.IsItemAux(index2); break; + case kpidPosition: { UInt64 v; if (_db.StartPos.GetItem(index2, v)) PropVarEm_Set_UInt64(value, v); break; } + case kpidCTime: SetFileTimeProp_From_UInt64Def(value, _db.CTime, index2); break; + case kpidATime: SetFileTimeProp_From_UInt64Def(value, _db.ATime, index2); break; + case kpidMTime: SetFileTimeProp_From_UInt64Def(value, _db.MTime, index2); break; + case kpidAttrib: if (item.AttribDefined) PropVarEm_Set_UInt32(value, item.Attrib); break; + case kpidCRC: if (item.CrcDefined) PropVarEm_Set_UInt32(value, item.Crc); break; + case kpidEncrypted: PropVarEm_Set_Bool(value, IsFolderEncrypted(_db.FileIndexToFolderIndexMap[index2])); break; + case kpidIsAnti: PropVarEm_Set_Bool(value, _db.IsItemAnti(index2)); break; + /* + case kpidIsAltStream: prop = item.IsAltStream; break; + case kpidNtSecure: { - CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; - if (folderIndex != kNumNoIndex) + int id = _db.SecureIDs[index]; + size_t offs = _db.SecureOffsets[id]; + size_t size = _db.SecureOffsets[id + 1] - offs; + if (size >= 0) { - 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); - UInt32 d = coder.Props[0]; - UInt32 lc = d % 9; - d /= 9; - UInt32 pb = d / 5; - UInt32 lp = d % 5; - if (lc != 3) AddProp32(propsString, L":lc", lc); - if (lp != 0) AddProp32(propsString, L":lp", lp); - if (pb != 2) AddProp32(propsString, L":pb", pb); - } - 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; + prop.SetBlob(_db.SecureBuf + offs, (ULONG)size); } + break; } - break; + */ + + case kpidPath: return _db.GetPath(index, value); + #ifndef _SFX + case kpidMethod: return SetMethodToProp(_db.FileIndexToFolderIndexMap[index2], value); case kpidBlock: { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) - prop = (UInt32)folderIndex; + PropVarEm_Set_UInt32(value, (UInt32)folderIndex); } break; case kpidPackedSize0: @@ -376,6 +611,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va case kpidPackedSize3: case kpidPackedSize4: { + /* CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { @@ -390,13 +626,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va } else prop = (UInt64)0; + */ } break; #endif } - prop.Detach(value); + // prop.Detach(value); return S_OK; - COM_TRY_END + // COM_TRY_END } STDMETHODIMP CHandler::Open(IInStream *stream, @@ -408,6 +645,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, #ifndef _SFX _fileInfoPopIDs.Clear(); #endif + try { CMyComPtr openArchiveCallbackTemp = openArchiveCallback; @@ -415,31 +653,30 @@ STDMETHODIMP CHandler::Open(IInStream *stream, #ifndef _NO_CRYPTO CMyComPtr getTextPassword; if (openArchiveCallback) - { - openArchiveCallbackTemp.QueryInterface( - IID_ICryptoGetTextPassword, &getTextPassword); - } + openArchiveCallbackTemp.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); #endif + CInArchive archive; + _db.IsArc = false; RINOK(archive.Open(stream, maxCheckStartPosition)); - #ifndef _NO_CRYPTO - _passwordIsDefined = false; - UString password; - #endif + _db.IsArc = true; + HRESULT result = archive.ReadDatabase( - EXTERNAL_CODECS_VARS - _db - #ifndef _NO_CRYPTO - , getTextPassword, _passwordIsDefined - #endif - ); + EXTERNAL_CODECS_VARS + _db + #ifndef _NO_CRYPTO + , getTextPassword, _isEncrypted, _passwordIsDefined + #endif + ); RINOK(result); - _db.Fill(); + _inStream = stream; } catch(...) { Close(); + // return E_INVALIDARG; + // we must return out_of_memory here return S_FALSE; } // _inStream = stream; @@ -455,6 +692,10 @@ STDMETHODIMP CHandler::Close() COM_TRY_BEGIN _inStream.Release(); _db.Clear(); + #ifndef _NO_CRYPTO + _isEncrypted = false; + _passwordIsDefined = false; + #endif return S_OK; COM_TRY_END } @@ -462,16 +703,16 @@ STDMETHODIMP CHandler::Close() #ifdef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) { COM_TRY_BEGIN const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); _numThreads = numProcessors; - for (int i = 0; i < numProperties; i++) + for (UInt32 i = 0; i < numProps; i++) { UString name = names[i]; - name.MakeUpper(); + name.MakeLower_Ascii(); if (name.IsEmpty()) return E_INVALIDARG; const PROPVARIANT &value = values[i]; @@ -479,9 +720,9 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v int index = ParseStringToUInt32(name, number); if (index == 0) { - if(name.Left(2).CompareNoCase(L"MT") == 0) + if (name.IsPrefixedBy(L"mt")) { - RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); + RINOK(ParseMtProp(name.Ptr(2), value, numProcessors, _numThreads)); continue; } else diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h old mode 100755 new mode 100644 index 247b55f7..dad943e0 --- a/CPP/7zip/Archive/7z/7zHandler.h +++ b/CPP/7zip/Archive/7z/7zHandler.h @@ -58,10 +58,11 @@ public: bool _compressHeaders; bool _encryptHeadersSpecified; bool _encryptHeaders; + // bool _useParents; 9.26 - bool WriteCTime; - bool WriteATime; - bool WriteMTime; + CBoolPair Write_CTime; + CBoolPair Write_ATime; + CBoolPair Write_MTime; bool _volumeMode; @@ -85,10 +86,8 @@ public: #endif class CHandler: - #ifndef EXTRACT_ONLY - public COutHandler, - #endif public IInArchive, + public IArchiveGetRawProps, #ifdef __7Z_SET_PROPERTIES public ISetProperties, #endif @@ -97,9 +96,13 @@ class CHandler: #endif PUBLIC_ISetCompressCodecsInfo public CMyUnknownImp + #ifndef EXTRACT_ONLY + , public COutHandler + #endif { public: MY_QUERYINTERFACE_BEGIN2(IInArchive) + // MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps) #ifdef __7Z_SET_PROPERTIES MY_QUERYINTERFACE_ENTRY(ISetProperties) #endif @@ -111,9 +114,10 @@ public: MY_ADDREF_RELEASE INTERFACE_IInArchive(;) + INTERFACE_IArchiveGetRawProps(;) #ifdef __7Z_SET_PROPERTIES - STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties); + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); #endif #ifndef EXTRACT_ONLY @@ -126,8 +130,9 @@ public: private: CMyComPtr _inStream; - NArchive::N7z::CArchiveDatabaseEx _db; + NArchive::N7z::CDbEx _db; #ifndef _NO_CRYPTO + bool _isEncrypted; bool _passwordIsDefined; #endif @@ -156,11 +161,13 @@ private: #endif - bool IsEncrypted(UInt32 index2) const; + bool IsFolderEncrypted(CNum folderIndex) const; #ifndef _SFX CRecordVector _fileInfoPopIDs; void FillPopIDs(); + void AddMethodName(AString &s, UInt64 id); + HRESULT SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const; #endif diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp old mode 100755 new mode 100644 index dd73ee84..2f6a4c37 --- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp +++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp @@ -4,6 +4,7 @@ #include "../../../Common/ComTry.h" #include "../../../Common/StringToInt.h" +#include "../../../Common/Wildcard.h" #include "../Common/ItemNameUtils.h" #include "../Common/ParseProperties.h" @@ -18,7 +19,7 @@ namespace NArchive { namespace N7z { static const wchar_t *k_LZMA_Name = L"LZMA"; -static const wchar_t *kDefaultMethodName = k_LZMA_Name; +static const wchar_t *kDefaultMethodName = L"LZMA2"; static const wchar_t *k_Copy_Name = L"Copy"; static const wchar_t *k_MatchFinder_ForHeaders = L"BT2"; @@ -67,9 +68,9 @@ HRESULT CHandler::SetHeaderMethod(CCompressionMethodMode &headerMethod) void CHandler::AddDefaultMethod() { - for (int i = 0; i < _methods.Size(); i++) + FOR_VECTOR (i, _methods) { - UString &methodName = _methods[0].MethodName; + UString &methodName = _methods[i].MethodName; if (methodName.IsEmpty()) methodName = kDefaultMethodName; } @@ -95,7 +96,7 @@ HRESULT CHandler::SetMainMethod( const UInt64 kSolidBytes_Max = ((UInt64)1 << 32) - 1; bool needSolid = false; - for (int i = 0; i < methods.Size(); i++) + FOR_VECTOR (i, methods) { COneMethodInfo &oneMethodInfo = methods[i]; SetGlobalLevelAndThreads(oneMethodInfo @@ -139,12 +140,10 @@ HRESULT CHandler::SetMainMethod( return S_OK; } -static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, bool writeTime, PROPID propID, UInt64 &ft, bool &ftDefined) +static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, PROPID propID, UInt64 &ft, bool &ftDefined) { - ft = 0; - ftDefined = false; - if (!writeTime) - return S_OK; + // ft = 0; + // ftDefined = false; NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(index, propID, &prop)); if (prop.vt == VT_FILETIME) @@ -154,15 +153,87 @@ static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, bool w } else if (prop.vt != VT_EMPTY) return E_INVALIDARG; + else + { + ft = 0; + ftDefined = false; + } return S_OK; } +/* + +#ifdef _WIN32 +static const wchar_t kDirDelimiter1 = L'\\'; +#endif +static const wchar_t kDirDelimiter2 = L'/'; + +static inline bool IsCharDirLimiter(wchar_t c) +{ + return ( + #ifdef _WIN32 + c == kDirDelimiter1 || + #endif + c == kDirDelimiter2); +} + +static int FillSortIndex(CObjectVector &treeFolders, int cur, int curSortIndex) +{ + CTreeFolder &tf = treeFolders[cur]; + tf.SortIndex = curSortIndex++; + for (int i = 0; i < tf.SubFolders.Size(); i++) + curSortIndex = FillSortIndex(treeFolders, tf.SubFolders[i], curSortIndex); + tf.SortIndexEnd = curSortIndex; + return curSortIndex; +} + +static int FindSubFolder(const CObjectVector &treeFolders, int cur, const UString &name, int &insertPos) +{ + const CIntVector &subFolders = treeFolders[cur].SubFolders; + int left = 0, right = subFolders.Size(); + insertPos = -1; + for (;;) + { + if (left == right) + { + insertPos = left; + return -1; + } + int mid = (left + right) / 2; + int midFolder = subFolders[mid]; + int compare = CompareFileNames(name, treeFolders[midFolder].Name); + if (compare == 0) + return midFolder; + if (compare < 0) + right = mid; + else + left = mid + 1; + } +} + +static int AddFolder(CObjectVector &treeFolders, int cur, const UString &name) +{ + int insertPos; + int folderIndex = FindSubFolder(treeFolders, cur, name, insertPos); + if (folderIndex < 0) + { + folderIndex = treeFolders.Size(); + CTreeFolder &newFolder = treeFolders.AddNew(); + newFolder.Parent = cur; + newFolder.Name = name; + treeFolders[cur].SubFolders.Insert(insertPos, folderIndex); + } + // else if (treeFolders[folderIndex].IsAltStreamFolder != isAltStreamFolder) throw 1123234234; + return folderIndex; +} +*/ + STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) { COM_TRY_BEGIN - const CArchiveDatabaseEx *db = 0; + const CDbEx *db = 0; #ifdef _7Z_VOL if (_volumes.Size() > 1) return E_FAIL; @@ -177,8 +248,35 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt db = &_db; #endif + /* + CMyComPtr getRawProps; + updateCallback->QueryInterface(IID_IArchiveGetRawProps, (void **)&getRawProps); + + CUniqBlocks secureBlocks; + secureBlocks.AddUniq(NULL, 0); + + CObjectVector treeFolders; + { + CTreeFolder folder; + folder.Parent = -1; + treeFolders.Add(folder); + } + */ + CObjectVector updateItems; - + + bool need_CTime = (Write_CTime.Def && Write_CTime.Val); + bool need_ATime = (Write_ATime.Def && Write_ATime.Val); + bool need_MTime = (Write_MTime.Def && Write_MTime.Val || !Write_MTime.Def); + if (db) + { + if (!Write_CTime.Def) need_CTime = !db->CTime.Defs.IsEmpty(); + if (!Write_ATime.Def) need_ATime = !db->ATime.Defs.IsEmpty(); + if (!Write_MTime.Def) need_MTime = !db->MTime.Defs.IsEmpty(); + } + + UString s; + for (UInt32 i = 0; i < numItems; i++) { Int32 newData, newProps; @@ -194,24 +292,35 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt ui.IsAnti = false; ui.Size = 0; + UString name; + // bool isAltStream = false; if (ui.IndexInArchive != -1) { - if (db == 0 || ui.IndexInArchive >= db->Files.Size()) + if (db == 0 || (unsigned)ui.IndexInArchive >= db->Files.Size()) return E_INVALIDARG; const CFileItem &fi = db->Files[ui.IndexInArchive]; - ui.Name = fi.Name; + if (!ui.NewProps) + { + NCOM::CPropVariant prop; + RINOK(_db.GetPath(ui.IndexInArchive, &prop)); + if (prop.vt == VT_BSTR) + name = prop.bstrVal; + } ui.IsDir = fi.IsDir; ui.Size = fi.Size; + // isAltStream = fi.IsAltStream; 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) + { + 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; @@ -228,21 +337,35 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt } // 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)); + if (need_CTime) RINOK(GetTime(updateCallback, i, kpidCTime, ui.CTime, ui.CTimeDefined)); + if (need_ATime) RINOK(GetTime(updateCallback, i, kpidATime, ui.ATime, ui.ATimeDefined)); + if (need_MTime) RINOK(GetTime(updateCallback, i, kpidMTime, ui.MTime, ui.MTimeDefined)); + + /* + if (getRawProps) + { + const void *data; + UInt32 dataSize; + UInt32 propType; + + getRawProps->GetRawProp(i, kpidNtSecure, &data, &dataSize, &propType); + if (dataSize != 0 && propType != NPropDataType::kRaw) + return E_FAIL; + ui.SecureIndex = secureBlocks.AddUniq((const Byte *)data, dataSize); + } + */ { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidPath, &prop)); if (prop.vt == VT_EMPTY) - nameIsDefined = false; + { + } else if (prop.vt != VT_BSTR) return E_INVALIDARG; else { - ui.Name = NItemName::MakeLegalName(prop.bstrVal); - nameIsDefined = true; + name = NItemName::MakeLegalName(prop.bstrVal); } } { @@ -270,6 +393,19 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt ui.IsAnti = (prop.boolVal != VARIANT_FALSE); } + /* + { + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(i, kpidIsAltStream, &prop)); + if (prop.vt == VT_EMPTY) + isAltStream = false; + else if (prop.vt != VT_BOOL) + return E_INVALIDARG; + else + isAltStream = (prop.boolVal != VARIANT_FALSE); + } + */ + if (ui.IsAnti) { ui.AttribDefined = false; @@ -284,6 +420,80 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (!folderStatusIsDefined && ui.AttribDefined) ui.SetDirStatusFromAttrib(); } + else + { + /* + if (_db.SecureIDs.IsEmpty()) + ui.SecureIndex = secureBlocks.AddUniq(NULL, 0); + else + { + int id = _db.SecureIDs[ui.IndexInArchive]; + size_t offs = _db.SecureOffsets[id]; + size_t size = _db.SecureOffsets[id + 1] - offs; + ui.SecureIndex = secureBlocks.AddUniq(_db.SecureBuf + offs, size); + } + */ + } + + /* + { + int folderIndex = 0; + if (_useParents) + { + int j; + s.Empty(); + for (j = 0; j < name.Len(); j++) + { + wchar_t c = name[j]; + if (IsCharDirLimiter(c)) + { + folderIndex = AddFolder(treeFolders, folderIndex, s); + s.Empty(); + continue; + } + s += c; + } + if (isAltStream) + { + int colonPos = s.Find(':'); + if (colonPos < 0) + { + // isAltStream = false; + return E_INVALIDARG; + } + UString mainName = s.Left(colonPos); + int newFolderIndex = AddFolder(treeFolders, folderIndex, mainName); + if (treeFolders[newFolderIndex].UpdateItemIndex < 0) + { + for (int j = updateItems.Size() - 1; j >= 0; j--) + { + CUpdateItem &ui2 = updateItems[j]; + if (ui2.ParentFolderIndex == folderIndex + && ui2.Name == mainName) + { + ui2.TreeFolderIndex = newFolderIndex; + treeFolders[newFolderIndex].UpdateItemIndex = j; + } + } + } + folderIndex = newFolderIndex; + s.Delete(0, colonPos + 1); + } + ui.Name = s; + } + else + ui.Name = name; + ui.IsAltStream = isAltStream; + ui.ParentFolderIndex = folderIndex; + ui.TreeFolderIndex = -1; + if (ui.IsDir && !s.IsEmpty()) + { + ui.TreeFolderIndex = AddFolder(treeFolders, folderIndex, s); + treeFolders[ui.TreeFolderIndex].UpdateItemIndex = updateItems.Size(); + } + } + */ + ui.Name = name; if (ui.NewData) { @@ -298,6 +508,16 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt updateItems.Add(ui); } + /* + FillSortIndex(treeFolders, 0, 0); + for (i = 0; i < (UInt32)updateItems.Size(); i++) + { + CUpdateItem &ui = updateItems[i]; + ui.ParentSortIndex = treeFolders[ui.ParentFolderIndex].SortIndex; + ui.ParentSortIndexEnd = treeFolders[ui.ParentFolderIndex].SortIndexEnd; + } + */ + CCompressionMethodMode methodMode, headerMethod; HRESULT res = SetMainMethod(methodMode, _methods @@ -317,17 +537,17 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt CMyComPtr getPassword2; updateCallback->QueryInterface(IID_ICryptoGetTextPassword2, (void **)&getPassword2); + methodMode.PasswordIsDefined = false; + methodMode.Password.Empty(); if (getPassword2) { CMyComBSTR password; Int32 passwordIsDefined; RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password)); methodMode.PasswordIsDefined = IntToBool(passwordIsDefined); - if (methodMode.PasswordIsDefined) + if (methodMode.PasswordIsDefined && (BSTR)password) methodMode.Password = password; } - else - methodMode.PasswordIsDefined = false; bool compressMainHeader = _compressHeaders; // check it @@ -360,9 +580,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt options.MaxFilter = level >= 8; options.HeaderOptions.CompressMainHeader = compressMainHeader; - options.HeaderOptions.WriteCTime = WriteCTime; - options.HeaderOptions.WriteATime = WriteATime; - options.HeaderOptions.WriteMTime = WriteMTime; + /* + options.HeaderOptions.WriteCTime = Write_CTime; + options.HeaderOptions.WriteATime = Write_ATime; + options.HeaderOptions.WriteMTime = Write_MTime; + */ options.NumSolidFiles = _numSolidFiles; options.NumSolidBytes = _numSolidBytes; @@ -371,11 +593,23 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt options.VolumeMode = _volumeMode; COutArchive archive; - CArchiveDatabase newDatabase; + CArchiveDatabaseOut newDatabase; CMyComPtr getPassword; updateCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getPassword); + /* + if (secureBlocks.Sorted.Size() > 1) + { + secureBlocks.GetReverseMap(); + for (int i = 0; i < updateItems.Size(); i++) + { + int &secureIndex = updateItems[i].SecureIndex; + secureIndex = secureBlocks.BufIndexToSortedIndex[secureIndex]; + } + } + */ + res = Update( EXTERNAL_CODECS_VARS #ifdef _7Z_VOL @@ -386,6 +620,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt db, #endif updateItems, + // treeFolders, + // secureBlocks, archive, newDatabase, outStream, updateCallback, options #ifndef _NO_CRYPTO , getPassword @@ -409,7 +645,7 @@ static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream if (index == 0) return E_INVALIDARG; srcString.Delete(0, index); - if (srcString[0] == 'S') + if (srcString[0] == 's') { srcString.Delete(0); int index = ParseStringToUInt32(srcString, stream); @@ -428,11 +664,12 @@ void COutHandler::InitProps() _compressHeaders = true; _encryptHeadersSpecified = false; _encryptHeaders = false; + // _useParents = false; - WriteCTime = false; - WriteATime = false; - WriteMTime = true; - + Write_CTime.Init(); + Write_ATime.Init(); + Write_MTime.Init(); + _volumeMode = false; InitSolid(); } @@ -440,24 +677,24 @@ void COutHandler::InitProps() HRESULT COutHandler::SetSolidFromString(const UString &s) { UString s2 = s; - s2.MakeUpper(); - for (int i = 0; i < s2.Length();) + s2.MakeLower_Ascii(); + for (unsigned i = 0; i < s2.Len();) { const wchar_t *start = ((const wchar_t *)s2) + i; const wchar_t *end; UInt64 v = ConvertStringToUInt64(start, &end); if (start == end) { - if (s2[i++] != 'E') + if (s2[i++] != 'e') return E_INVALIDARG; _solidExtension = true; continue; } i += (int)(end - start); - if (i == s2.Length()) + if (i == s2.Len()) return E_INVALIDARG; wchar_t c = s2[i++]; - if (c == 'F') + if (c == 'f') { if (v < 1) v = 1; @@ -468,10 +705,11 @@ HRESULT COutHandler::SetSolidFromString(const UString &s) unsigned numBits; switch (c) { - case 'B': numBits = 0; break; - case 'K': numBits = 10; break; - case 'M': numBits = 20; break; - case 'G': numBits = 30; break; + case 'b': numBits = 0; break; + case 'k': numBits = 10; break; + case 'm': numBits = 20; break; + case 'g': numBits = 30; break; + case 't': numBits = 40; break; default: return E_INVALIDARG; } _numSolidBytes = (v << numBits); @@ -501,14 +739,21 @@ HRESULT COutHandler::SetSolidFromPROPVARIANT(const PROPVARIANT &value) return S_OK; } +static HRESULT PROPVARIANT_to_BoolPair(const PROPVARIANT &prop, CBoolPair &dest) +{ + RINOK(PROPVARIANT_to_bool(prop, dest.Val)); + dest.Def = true; + return S_OK; +} + HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) { UString name = nameSpec; - name.MakeUpper(); + name.MakeLower_Ascii(); if (name.IsEmpty()) return E_INVALIDARG; - if (name[0] == L'S') + if (name[0] == L's') { name.Delete(0); if (name.IsEmpty()) @@ -520,47 +765,52 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val UInt32 number; int index = ParseStringToUInt32(name, number); - UString realName = name.Mid(index); + UString realName = name.Ptr(index); if (index == 0) { - if (name.CompareNoCase(L"RSFX") == 0) return PROPVARIANT_to_bool(value, _removeSfxBlock); - if (name.CompareNoCase(L"HC") == 0) return PROPVARIANT_to_bool(value, _compressHeaders); - if (name.CompareNoCase(L"HCF") == 0) + if (name.IsEqualTo("rsfx")) return PROPVARIANT_to_bool(value, _removeSfxBlock); + if (name.IsEqualTo("hc")) return PROPVARIANT_to_bool(value, _compressHeaders); + // if (name.IsEqualToNoCase(L"HS")) return PROPVARIANT_to_bool(value, _useParents); + + if (name.IsEqualTo("hcf")) { bool compressHeadersFull = true; RINOK(PROPVARIANT_to_bool(value, compressHeadersFull)); return compressHeadersFull ? S_OK: E_INVALIDARG; } - if (name.CompareNoCase(L"HE") == 0) + + if (name.IsEqualTo("he")) { RINOK(PROPVARIANT_to_bool(value, _encryptHeaders)); _encryptHeadersSpecified = true; return S_OK; } - if (name.CompareNoCase(L"TC") == 0) return PROPVARIANT_to_bool(value, WriteCTime); - if (name.CompareNoCase(L"TA") == 0) return PROPVARIANT_to_bool(value, WriteATime); - if (name.CompareNoCase(L"TM") == 0) return PROPVARIANT_to_bool(value, WriteMTime); - if (name.CompareNoCase(L"V") == 0) return PROPVARIANT_to_bool(value, _volumeMode); + + if (name.IsEqualTo("tc")) return PROPVARIANT_to_BoolPair(value, Write_CTime); + if (name.IsEqualTo("ta")) return PROPVARIANT_to_BoolPair(value, Write_ATime); + if (name.IsEqualTo("tm")) return PROPVARIANT_to_BoolPair(value, Write_MTime); + + if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode); } return CMultiMethodProps::SetProperty(name, value); } -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) { COM_TRY_BEGIN _binds.Clear(); InitProps(); - for (int i = 0; i < numProps; i++) + for (UInt32 i = 0; i < numProps; i++) { UString name = names[i]; - name.MakeUpper(); + name.MakeLower_Ascii(); if (name.IsEmpty()) return E_INVALIDARG; const PROPVARIANT &value = values[i]; - if (name[0] == 'B') + if (name[0] == 'b') { if (value.vt != VT_EMPTY) return E_INVALIDARG; @@ -580,10 +830,10 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v RINOK(SetProperty(name, value)); } - int numEmptyMethods = GetNumEmptyMethods(); + unsigned numEmptyMethods = GetNumEmptyMethods(); if (numEmptyMethods > 0) { - int k; + unsigned k; for (k = 0; k < _binds.Size(); k++) { const CBind &bind = _binds[k]; @@ -597,14 +847,14 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v bind.InCoder -= (UInt32)numEmptyMethods; bind.OutCoder -= (UInt32)numEmptyMethods; } - _methods.Delete(0, numEmptyMethods); + _methods.DeleteFrontal(numEmptyMethods); } AddDefaultMethod(); if (!_filterMethod.MethodName.IsEmpty()) { - for (int k = 0; k < _binds.Size(); k++) + FOR_VECTOR (k, _binds) { CBind &bind = _binds[k]; bind.InCoder++; @@ -613,7 +863,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v _methods.Insert(0, _filterMethod); } - for (int k = 0; k < _binds.Size(); k++) + FOR_VECTOR (k, _binds) { const CBind &bind = _binds[k]; if (bind.InCoder >= (UInt32)_methods.Size() || diff --git a/CPP/7zip/Archive/7z/7zHeader.cpp b/CPP/7zip/Archive/7z/7zHeader.cpp old mode 100755 new mode 100644 index 5b5f2fb3..acff2fdd --- a/CPP/7zip/Archive/7z/7zHeader.cpp +++ b/CPP/7zip/Archive/7z/7zHeader.cpp @@ -1,6 +1,7 @@ // 7zHeader.cpp #include "StdAfx.h" + #include "7zHeader.h" namespace NArchive { @@ -11,4 +12,8 @@ Byte kSignature[kSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; Byte kFinishSignature[kSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C + 1}; #endif +// We can change signature. So file doesn't contain correct signature. +// struct SignatureInitializer { SignatureInitializer() { kSignature[0]--; } }; +// static SignatureInitializer g_SignatureInitializer; + }} diff --git a/CPP/7zip/Archive/7z/7zHeader.h b/CPP/7zip/Archive/7z/7zHeader.h old mode 100755 new mode 100644 index 30622b90..d72fdefa --- a/CPP/7zip/Archive/7z/7zHeader.h +++ b/CPP/7zip/Archive/7z/7zHeader.h @@ -3,12 +3,12 @@ #ifndef __7Z_HEADER_H #define __7Z_HEADER_H -#include "../../../Common/Types.h" +#include "../../../Common/MyTypes.h" namespace NArchive { namespace N7z { -const int kSignatureSize = 6; +const unsigned kSignatureSize = 6; extern Byte kSignature[kSignatureSize]; // #define _7Z_VOL @@ -82,13 +82,17 @@ namespace NID kCTime, kATime, kMTime, - kWinAttributes, + kWinAttrib, kComment, kEncodedHeader, kStartPos, kDummy + + // kNtSecure, + // kParent, + // kIsAux }; } diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp old mode 100755 new mode 100644 index fd751a74..d84cf0b0 --- a/CPP/7zip/Archive/7z/7zIn.cpp +++ b/CPP/7zip/Archive/7z/7zIn.cpp @@ -20,15 +20,21 @@ #define FORMAT_7Z_RECOVERY #endif +using namespace NWindows; +using namespace NCOM; + namespace NArchive { namespace N7z { -static void BoolVector_Fill_False(CBoolVector &v, int size) +static const UInt32 k_LZMA2 = 0x21; +static const UInt32 k_LZMA = 0x030101; + +static void BoolVector_Fill_False(CBoolVector &v, unsigned size) { - v.Clear(); - v.Reserve(size); - for (int i = 0; i < size; i++) - v.Add(false); + v.ClearAndSetSize(size); + bool *p = &v[0]; + for (unsigned i = 0; i < size; i++) + p[i] = false; } static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index) @@ -40,11 +46,11 @@ static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index) return res; } -bool CFolder::CheckStructure() const +bool CFolder::CheckStructure(unsigned numUnpackSizes) 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; + const unsigned kNumCodersMax = sizeof(UInt32) * 8; // don't change it + const unsigned kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax + const unsigned kNumBindsMax = 32; if (Coders.Size() > kNumCodersMax || BindPairs.Size() > kNumBindsMax) return false; @@ -53,7 +59,7 @@ bool CFolder::CheckStructure() const CBoolVector v; BoolVector_Fill_False(v, BindPairs.Size() + PackStreams.Size()); - int i; + unsigned i; for (i = 0; i < BindPairs.Size(); i++) if (BoolVector_GetAndSet(v, BindPairs[i].InIndex)) return false; @@ -61,19 +67,19 @@ bool CFolder::CheckStructure() const if (BoolVector_GetAndSet(v, PackStreams[i])) return false; - BoolVector_Fill_False(v, UnpackSizes.Size()); + BoolVector_Fill_False(v, numUnpackSizes); for (i = 0; i < BindPairs.Size(); i++) if (BoolVector_GetAndSet(v, BindPairs[i].OutIndex)) return false; } UInt32 mask[kMaskSize]; - int i; + unsigned i; for (i = 0; i < kMaskSize; i++) mask[i] = 0; { - CIntVector inStreamToCoder, outStreamToCoder; + CUIntVector inStreamToCoder, outStreamToCoder; for (i = 0; i < Coders.Size(); i++) { CNum j; @@ -92,7 +98,7 @@ bool CFolder::CheckStructure() const } for (i = 0; i < kMaskSize; i++) - for (int j = 0; j < kMaskSize; j++) + for (unsigned j = 0; j < kMaskSize; j++) if (((1 << j) & mask[i]) != 0) mask[i] |= mask[j]; @@ -104,43 +110,23 @@ bool CFolder::CheckStructure() const } class CInArchiveException {}; +class CUnsupportedFeatureException: public CInArchiveException {}; static void ThrowException() { throw CInArchiveException(); } static inline void ThrowEndOfData() { ThrowException(); } -static inline void ThrowUnsupported() { ThrowException(); } +static inline void ThrowUnsupported() { throw CUnsupportedFeatureException(); } 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; + bool _needUpdatePos; public: - CStreamSwitch(): _needRemove(false) {} + CStreamSwitch(): _needRemove(false), _needUpdatePos(false) {} ~CStreamSwitch() { Remove(); } void Remove(); - void Set(CInArchive *archive, const Byte *data, size_t size); + void Set(CInArchive *archive, const Byte *data, size_t size, bool needUpdatePos); void Set(CInArchive *archive, const CByteBuffer &byteBuffer); void Set(CInArchive *archive, const CObjectVector *dataVector); }; @@ -149,22 +135,25 @@ void CStreamSwitch::Remove() { if (_needRemove) { - _archive->DeleteByteStream(); + if (_archive->_inByteBack->GetRem() != 0) + _archive->ThereIsHeaderError = true; + _archive->DeleteByteStream(_needUpdatePos); _needRemove = false; } } -void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size) +void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size, bool needUpdatePos) { Remove(); _archive = archive; _archive->AddByteStream(data, size); _needRemove = true; + _needUpdatePos = needUpdatePos; } void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer) { - Set(archive, byteBuffer, byteBuffer.GetCapacity()); + Set(archive, byteBuffer, byteBuffer.Size(), false); } void CStreamSwitch::Set(CInArchive *archive, const CObjectVector *dataVector) @@ -173,13 +162,22 @@ void CStreamSwitch::Set(CInArchive *archive, const CObjectVector *d Byte external = archive->ReadByte(); if (external != 0) { - int dataIndex = (int)archive->ReadNum(); - if (dataIndex < 0 || dataIndex >= dataVector->Size()) + CNum dataIndex = archive->ReadNum(); + if (dataIndex >= dataVector->Size()) ThrowIncorrect(); Set(archive, (*dataVector)[dataIndex]); } } +void CInArchive::AddByteStream(const Byte *buf, size_t size) +{ + if (_numInByteBufs == kNumBufLevelsMax) + ThrowIncorrect(); + _inByteBack = &_inByteVector[_numInByteBufs++]; + _inByteBack->Init(buf, size); +} + + Byte CInByte2::ReadByte() { if (_pos >= _size) @@ -191,8 +189,8 @@ 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++]; + memcpy(data, _buffer + _pos, size); + _pos += size; } void CInByte2::SkipData(UInt64 size) @@ -207,31 +205,75 @@ void CInByte2::SkipData() SkipData(ReadNumber()); } -UInt64 CInByte2::ReadNumber() +static UInt64 ReadNumberSpec(const Byte *p, size_t size, size_t &processed) { - if (_pos >= _size) - ThrowEndOfData(); - Byte firstByte = _buffer[_pos++]; - Byte mask = 0x80; - UInt64 value = 0; - for (int i = 0; i < 8; i++) + if (size == 0) + { + processed = 0; + return 0; + } + Byte firstByte = *p++; + size--; + if ((firstByte & 0x80) == 0) + { + processed = 1; + return firstByte; + } + Byte mask = 0x40; + if (size == 0) + { + processed = 0; + return 0; + } + UInt64 value = (UInt64)*p; + p++; + size--; + for (unsigned i = 1; i < 8; i++) { if ((firstByte & mask) == 0) { UInt64 highPart = firstByte & (mask - 1); value += (highPart << (i * 8)); + processed = i + 1; return value; } - if (_pos >= _size) - ThrowEndOfData(); - value |= ((UInt64)_buffer[_pos++] << (8 * i)); + if (size == 0) + { + processed = 0; + return 0; + } + value |= ((UInt64)*p << (i * 8)); + p++; + size--; mask >>= 1; } + processed = 9; return value; } +UInt64 CInByte2::ReadNumber() +{ + size_t processed; + UInt64 res = ReadNumberSpec(_buffer + _pos, _size - _pos, processed); + if (processed == 0) + ThrowEndOfData(); + _pos += processed; + return res; +} + CNum CInByte2::ReadNum() { + /* + if (_pos < _size) + { + Byte val = _buffer[_pos]; + if ((unsigned)val < 0x80) + { + _pos++; + return (unsigned)val; + } + } + */ UInt64 value = ReadNumber(); if (value > kNumMax) ThrowUnsupported(); @@ -256,48 +298,21 @@ UInt64 CInByte2::ReadUInt64() 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; -} +#define CHECK_SIGNATURE if (p[0] != '7' || p[1] != 'z' || p[2] != 0xBC || p[3] != 0xAF || p[4] != 0x27 || p[5] != 0x1C) return false; static inline bool TestSignature(const Byte *p) { - for (int i = 0; i < kSignatureSize; i++) - if (p[i] != kSignature[i]) - return false; - return CrcCalc(p + 12, 20) == GetUi32(p + 8); + CHECK_SIGNATURE + return CrcCalc(p + 12, 20) == Get32(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)) + CHECK_SIGNATURE; + if (CrcCalc(p + 12, 20) == Get32(p + 8)) return true; - for (i = 8; i < kHeaderSize; i++) + for (unsigned i = 8; i < kHeaderSize; i++) if (p[i] != 0) return false; return (p[6] != 0 || p[7] != 0); @@ -312,39 +327,52 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search if (TestSignature2(_header)) return S_OK; + if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0) + return S_FALSE; - CByteBuffer byteBuffer; - const UInt32 kBufferSize = (1 << 16); - byteBuffer.SetCapacity(kBufferSize); - Byte *buffer = byteBuffer; - memcpy(buffer, _header, kHeaderSize); - UInt64 curTestPos = _arhiveBeginStreamPosition; + const UInt32 kBufSize = 1 << 15; + CByteArr buf(kBufSize); + memcpy(buf, _header, kHeaderSize); + UInt64 offset = 0; + for (;;) { - if (searchHeaderSizeLimit != NULL) - if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit) - break; - UInt32 processedSize; - RINOK(stream->Read(buffer + kHeaderSize, kBufferSize - kHeaderSize, &processedSize)); - if (processedSize == 0) + UInt32 readSize = kBufSize - kHeaderSize; + { + UInt64 rem = *searchHeaderSizeLimit - offset; + if (readSize > rem) + readSize = (UInt32)rem; + if (readSize == 0) + return S_FALSE; + } + UInt32 processed = 0; + RINOK(stream->Read(buf + kHeaderSize, readSize, &processed)); + if (processed == 0) return S_FALSE; - for (UInt32 pos = 1; pos <= processedSize; pos++) + for (UInt32 pos = 0;;) { - for (; buffer[pos] != '7' && pos <= processedSize; pos++); - if (pos > processedSize) + const Byte *p = buf + pos + 1; + const Byte *lim = buf + processed; + for (; p <= lim; p += 4) + { + if (p[0] == '7') break; + if (p[1] == '7') { p += 1; break; } + if (p[2] == '7') { p += 2; break; } + if (p[3] == '7') { p += 3; break; } + }; + if (p > lim) break; - if (TestSignature(buffer + pos)) + pos = (UInt32)(p - buf); + if (TestSignature(p)) { - memcpy(_header, buffer + pos, kHeaderSize); - curTestPos += pos; - _arhiveBeginStreamPosition = curTestPos; - return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL); + memcpy(_header, p, kHeaderSize); + _arhiveBeginStreamPosition += offset + pos; + return stream->Seek(_arhiveBeginStreamPosition + kHeaderSize, STREAM_SEEK_SET, NULL); } } - curTestPos += processedSize; - memmove(buffer, buffer + processedSize, kHeaderSize); + offset += processed; + memmove(buf, buf + processed, kHeaderSize); } - return S_FALSE; } // S_FALSE means that file is not archive @@ -362,7 +390,9 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) void CInArchive::Close() { + _numInByteBufs = 0; _stream.Release(); + ThereIsHeaderError = false; } void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */) @@ -375,30 +405,32 @@ void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */) } } -void CInArchive::GetNextFolderItem(CFolder &folder) +// CFolder &folder can be non empty. So we must set all fields + +void CInByte2::ParseFolder(CFolder &folder) { CNum numCoders = ReadNum(); - folder.Coders.Clear(); - folder.Coders.Reserve((int)numCoders); + folder.Coders.SetSize(numCoders); + CNum numInStreams = 0; CNum numOutStreams = 0; CNum i; for (i = 0; i < numCoders; i++) { - folder.Coders.Add(CCoderInfo()); - CCoderInfo &coder = folder.Coders.Back(); - + CCoderInfo &coder = folder.Coders[i]; { Byte mainByte = ReadByte(); - int idSize = (mainByte & 0xF); - Byte longID[15]; - ReadBytes(longID, idSize); - if (idSize > 8) + if ((mainByte & 0xC0) != 0) ThrowUnsupported(); + unsigned idSize = (mainByte & 0xF); + if (idSize > 8 || idSize > GetRem()) + ThrowUnsupported(); + const Byte *longID = GetPtr(); UInt64 id = 0; - for (int j = 0; j < idSize; j++) - id |= (UInt64)longID[idSize - 1 - j] << (8 * j); + for (unsigned j = 0; j < idSize; j++) + id = ((id << 8) | longID[j]); + SkipDataNoCheck(idSize); coder.MethodID = id; if ((mainByte & 0x10) != 0) @@ -414,53 +446,117 @@ void CInArchive::GetNextFolderItem(CFolder &folder) if ((mainByte & 0x20) != 0) { CNum propsSize = ReadNum(); - coder.Props.SetCapacity((size_t)propsSize); + coder.Props.Alloc((size_t)propsSize); ReadBytes((Byte *)coder.Props, (size_t)propsSize); } - if ((mainByte & 0x80) != 0) - ThrowUnsupported(); + else + coder.Props.Free(); } numInStreams += coder.NumInStreams; numOutStreams += coder.NumOutStreams; } CNum numBindPairs = numOutStreams - 1; - folder.BindPairs.Clear(); - folder.BindPairs.Reserve(numBindPairs); + folder.BindPairs.SetSize(numBindPairs); for (i = 0; i < numBindPairs; i++) { - CBindPair bp; + CBindPair &bp = folder.BindPairs[i]; bp.InIndex = ReadNum(); bp.OutIndex = ReadNum(); - folder.BindPairs.Add(bp); } if (numInStreams < numBindPairs) ThrowUnsupported(); CNum numPackStreams = numInStreams - numBindPairs; - folder.PackStreams.Reserve(numPackStreams); + folder.PackStreams.SetSize(numPackStreams); if (numPackStreams == 1) { for (i = 0; i < numInStreams; i++) if (folder.FindBindPairForInStream(i) < 0) { - folder.PackStreams.Add(i); + folder.PackStreams[0] = i; break; } - if (folder.PackStreams.Size() != 1) + if (i == numInStreams) ThrowUnsupported(); } else for (i = 0; i < numPackStreams; i++) - folder.PackStreams.Add(ReadNum()); + folder.PackStreams[i] = ReadNum(); +} + +void CFolders::ParseFolderInfo(unsigned folderIndex, CFolder &folder) const +{ + size_t startPos = FoCodersDataOffset[folderIndex]; + CInByte2 inByte; + inByte.Init(CodersData + startPos, FoCodersDataOffset[folderIndex + 1] - startPos); + inByte.ParseFolder(folder); + if (inByte.GetRem() != 0) + throw 20120424; } -void CInArchive::WaitAttribute(UInt64 attribute) + +HRESULT CDatabase::GetPath(unsigned index, PROPVARIANT *path) const +{ + PropVariant_Clear(path); + if (!NameOffsets || !NamesBuf) + return S_OK; + + unsigned cur = index; + unsigned size = 0; + + // for (int i = 0;; i++) + { + size_t len = NameOffsets[cur + 1] - NameOffsets[cur]; + size += (unsigned)len; + if (/* i > 256 || */ len > (1 << 12) || size > (1 << 14)) + return PropVarEm_Set_Str(path, "[TOO-LONG]"); + /* + cur = Files[cur].Parent; + if (cur < 0) + break; + */ + } + size--; + + RINOK(PropVarEm_Alloc_Bstr(path, size)); + wchar_t *s = path->bstrVal; + s += size; + *s = 0; + cur = index; + + for (;;) + { + unsigned len = (unsigned)(NameOffsets[cur + 1] - NameOffsets[cur] - 1); + const Byte *p = (const Byte *)NamesBuf + (NameOffsets[cur + 1] * 2) - 2; + do + { + p -= 2; + --s; + wchar_t c = Get16(p); + if (c == '/') + c = WCHAR_PATH_SEPARATOR; + *s = c; + } + while (--len); + /* + const CFileItem &file = Files[cur]; + cur = file.Parent; + if (cur < 0) + */ + return S_OK; + /* + *(--s) = (file.IsAltStream ? ':' : WCHAR_PATH_SEPARATOR); + */ + } +} + +void CInArchive::WaitId(UInt64 id) { for (;;) { UInt64 type = ReadID(); - if (type == attribute) + if (type == id) return; if (type == NID::kEnd) ThrowIncorrect(); @@ -468,90 +564,209 @@ void CInArchive::WaitAttribute(UInt64 attribute) } } -void CInArchive::ReadHashDigests(int numItems, - CBoolVector &digestsDefined, - CRecordVector &digests) +void CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs) { - ReadBoolVector2(numItems, digestsDefined); - digests.Clear(); - digests.Reserve(numItems); - for (int i = 0; i < numItems; i++) + ReadBoolVector2(numItems, crcs.Defs); + crcs.Vals.ClearAndSetSize(numItems); + UInt32 *p = &crcs.Vals[0]; + const bool *defs = &crcs.Defs[0]; + for (unsigned i = 0; i < numItems; i++) { UInt32 crc = 0; - if (digestsDefined[i]) + if (defs[i]) crc = ReadUInt32(); - digests.Add(crc); + p[i] = crc; } } -void CInArchive::ReadPackInfo( - UInt64 &dataOffset, - CRecordVector &packSizes, - CBoolVector &packCRCsDefined, - CRecordVector &packCRCs) +void CInArchive::ReadPackInfo(CFolders &f) { - dataOffset = ReadNumber(); CNum numPackStreams = ReadNum(); - - WaitAttribute(NID::kSize); - packSizes.Clear(); - packSizes.Reserve(numPackStreams); + + WaitId(NID::kSize); + f.PackPositions.Alloc(numPackStreams + 1); + f.NumPackStreams = numPackStreams; + UInt64 sum = 0; for (CNum i = 0; i < numPackStreams; i++) - packSizes.Add(ReadNumber()); + { + f.PackPositions[i] = sum; + UInt64 packSize = ReadNumber(); + sum += packSize; + if (sum < packSize) + ThrowIncorrect(); + } + f.PackPositions[numPackStreams] = sum; UInt64 type; for (;;) { type = ReadID(); if (type == NID::kEnd) - break; + return; if (type == NID::kCRC) { - ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs); + CUInt32DefVector PackCRCs; + ReadHashDigests(numPackStreams, 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) + CFolders &folders) { - WaitAttribute(NID::kFolder); + WaitId(NID::kFolder); CNum numFolders = ReadNum(); + CNum numCodersOutStreams = 0; { CStreamSwitch streamSwitch; streamSwitch.Set(this, dataVector); - folders.Clear(); - folders.Reserve(numFolders); - for (CNum i = 0; i < numFolders; i++) + const Byte *startBufPtr = _inByteBack->GetPtr(); + folders.NumFolders = numFolders; + + folders.FoStartPackStreamIndex.Alloc(numFolders + 1); + folders.FoToMainUnpackSizeIndex.Alloc(numFolders); + folders.FoCodersDataOffset.Alloc(numFolders + 1); + folders.FoToCoderUnpackSizes.Alloc(numFolders + 1); + + CRecordVector InStreamUsed; + CRecordVector OutStreamUsed; + + CNum packStreamIndex = 0; + CNum fo; + CInByte2 *inByte = _inByteBack; + for (fo = 0; fo < numFolders; fo++) { - folders.Add(CFolder()); - GetNextFolderItem(folders.Back()); + UInt32 numOutStreams = 0; + UInt32 indexOfMainStream = 0; + UInt32 numPackStreams = 0; + folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr; + + numOutStreams = 0; + CNum numInStreams = 0; + CNum numCoders = inByte->ReadNum(); + for (CNum ci = 0; ci < numCoders; ci++) + { + Byte mainByte = inByte->ReadByte(); + if ((mainByte & 0xC0) != 0) + ThrowUnsupported(); + unsigned idSize = (mainByte & 0xF); + if (idSize > 8) + ThrowUnsupported(); + if (idSize > inByte->GetRem()) + ThrowEndOfData(); + const Byte *longID = inByte->GetPtr(); + UInt64 id = 0; + for (unsigned j = 0; j < idSize; j++) + id = ((id << 8) | longID[j]); + inByte->SkipDataNoCheck(idSize); + if (folders.ParsedMethods.IDs.Size() < 128) + folders.ParsedMethods.IDs.AddToUniqueSorted(id); + CNum coderInStreams = 1; + CNum coderOutStreams = 1; + if ((mainByte & 0x10) != 0) + { + coderInStreams = inByte->ReadNum(); + coderOutStreams = inByte->ReadNum(); + } + numInStreams += coderInStreams; + if (numInStreams < coderInStreams) + ThrowUnsupported(); + numOutStreams += coderOutStreams; + if (numOutStreams < coderOutStreams) + ThrowUnsupported(); + if ((mainByte & 0x20) != 0) + { + CNum propsSize = inByte->ReadNum(); + if (propsSize > inByte->GetRem()) + ThrowEndOfData(); + if (id == k_LZMA2 && propsSize == 1) + { + Byte v = *_inByteBack->GetPtr(); + if (folders.ParsedMethods.Lzma2Prop < v) + folders.ParsedMethods.Lzma2Prop = v; + } + else if (id == k_LZMA && propsSize == 5) + { + UInt32 dicSize = GetUi32(_inByteBack->GetPtr() + 1); + if (folders.ParsedMethods.LzmaDic < dicSize) + folders.ParsedMethods.LzmaDic = dicSize; + } + inByte->SkipDataNoCheck((size_t)propsSize); + } + } + + if (numOutStreams == 1 && numInStreams == 1) + { + indexOfMainStream = 0; + numPackStreams = 1; + } + else + { + UInt32 i; + if (numOutStreams == 0) + ThrowUnsupported(); + CNum numBindPairs = numOutStreams - 1; + if (numInStreams < numBindPairs) + ThrowUnsupported(); + if (numInStreams >= 256 || numOutStreams >= 256) + ThrowUnsupported(); + + InStreamUsed.ClearAndSetSize(numInStreams); + for (i = 0; i < numInStreams; i++) + InStreamUsed[i] = false; + + OutStreamUsed.ClearAndSetSize(numOutStreams); + for (i = 0; i < numOutStreams; i++) + OutStreamUsed[i] = false; + + for (i = 0; i < numBindPairs; i++) + { + CNum index = ReadNum(); + if (index >= numInStreams || InStreamUsed[index]) + ThrowUnsupported(); + InStreamUsed[index] = true; + index = ReadNum(); + if (index >= numOutStreams || OutStreamUsed[index]) + ThrowUnsupported(); + OutStreamUsed[index] = true; + } + + numPackStreams = numInStreams - numBindPairs; + + if (numPackStreams != 1) + for (i = 0; i < numPackStreams; i++) + inByte->ReadNum(); // PackStreams + + for (i = 0; i < numOutStreams; i++) + if (!OutStreamUsed[i]) + { + indexOfMainStream = i; + break; + } + if (i == numOutStreams) + ThrowUnsupported(); + } + folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams; + numCodersOutStreams += numOutStreams; + folders.FoStartPackStreamIndex[fo] = packStreamIndex; + packStreamIndex += numPackStreams; + folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream; } + size_t dataSize = _inByteBack->GetPtr() - startBufPtr; + folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams; + folders.FoStartPackStreamIndex[fo] = packStreamIndex; + folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr; + folders.CodersData.CopyFrom(startBufPtr, dataSize); } - 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()); - } + WaitId(NID::kCodersUnpackSize); + folders.CoderUnpackSizes.Alloc(numCodersOutStreams); + for (CNum i = 0; i < numCodersOutStreams; i++) + folders.CoderUnpackSizes[i] = ReadNumber(); for (;;) { @@ -560,15 +775,7 @@ void CInArchive::ReadUnpackInfo( 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]; - } + ReadHashDigests(numFolders, folders.FolderCRCs); continue; } SkipData(); @@ -576,170 +783,217 @@ void CInArchive::ReadUnpackInfo( } void CInArchive::ReadSubStreamsInfo( - const CObjectVector &folders, - CRecordVector &numUnpackStreamsInFolders, + CFolders &folders, CRecordVector &unpackSizes, - CBoolVector &digestsDefined, - CRecordVector &digests) + CUInt32DefVector &digests) { - numUnpackStreamsInFolders.Clear(); - numUnpackStreamsInFolders.Reserve(folders.Size()); + folders.NumUnpackStreamsVector.Alloc(folders.NumFolders); + CNum i; + for (i = 0; i < folders.NumFolders; i++) + folders.NumUnpackStreamsVector[i] = 1; + UInt64 type; + for (;;) { type = ReadID(); if (type == NID::kNumUnpackStream) { - for (int i = 0; i < folders.Size(); i++) - numUnpackStreamsInFolders.Add(ReadNum()); + for (i = 0; i < folders.NumFolders; i++) + folders.NumUnpackStreamsVector[i] = ReadNum(); continue; } - if (type == NID::kCRC || type == NID::kSize) - break; - if (type == NID::kEnd) + if (type == NID::kCRC || type == NID::kSize || 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++) + if (type == NID::kSize) { - // 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) + for (i = 0; i < folders.NumFolders; i++) + { + // v3.13 incorrectly worked with empty folders + // v4.07: we check that folder is empty + CNum numSubstreams = folders.NumUnpackStreamsVector[i]; + if (numSubstreams == 0) + continue; + UInt64 sum = 0; + for (CNum j = 1; j < numSubstreams; j++) { UInt64 size = ReadNumber(); unpackSizes.Add(size); sum += size; + if (sum < size) + ThrowIncorrect(); } - unpackSizes.Add(folders[i].GetUnpackSize() - sum); - } - if (type == NID::kSize) + UInt64 folderUnpackSize = folders.GetFolderUnpackSize(i); + if (folderUnpackSize < sum) + ThrowIncorrect(); + unpackSizes.Add(folderUnpackSize - sum); + } type = ReadID(); + } + else + { + for (i = 0; i < folders.NumFolders; i++) + { + /* v9.26 - v9.29 incorrectly worked: + if (folders.NumUnpackStreamsVector[i] == 0), it threw error */ + CNum val = folders.NumUnpackStreamsVector[i]; + if (val > 1) + ThrowIncorrect(); + if (val == 1) + unpackSizes.Add(folders.GetFolderUnpackSize(i)); + } + } - int numDigests = 0; - int numDigestsTotal = 0; - for (i = 0; i < folders.Size(); i++) + unsigned numDigests = 0; + for (i = 0; i < folders.NumFolders; i++) { - CNum numSubstreams = numUnpackStreamsInFolders[i]; - if (numSubstreams != 1 || !folders[i].UnpackCRCDefined) + CNum numSubstreams = folders.NumUnpackStreamsVector[i]; + if (numSubstreams != 1 || !folders.FolderCRCs.ValidAndDefined(i)) numDigests += numSubstreams; - numDigestsTotal += numSubstreams; } for (;;) { + if (type == NID::kEnd) + break; if (type == NID::kCRC) { - CBoolVector digestsDefined2; - CRecordVector digests2; - ReadHashDigests(numDigests, digestsDefined2, digests2); - int digestIndex = 0; - for (i = 0; i < folders.Size(); i++) + // CUInt32DefVector digests2; + // ReadHashDigests(numDigests, digests2); + CBoolVector digests2; + ReadBoolVector2(numDigests, digests2); + + digests.ClearAndSetSize(unpackSizes.Size()); + + unsigned k = 0; + unsigned k2 = 0; + + for (i = 0; i < folders.NumFolders; i++) { - CNum numSubstreams = numUnpackStreamsInFolders[i]; - const CFolder &folder = folders[i]; - if (numSubstreams == 1 && folder.UnpackCRCDefined) + CNum numSubstreams = folders.NumUnpackStreamsVector[i]; + if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i)) { - digestsDefined.Add(true); - digests.Add(folder.UnpackCRC); + digests.Defs[k] = true; + digests.Vals[k] = folders.FolderCRCs.Vals[i]; + k++; + } + else for (CNum j = 0; j < numSubstreams; j++) + { + bool defined = digests2[k2++]; + digests.Defs[k] = defined; + UInt32 crc = 0; + if (defined) + crc = ReadUInt32(); + digests.Vals[k] = crc; + k++; } - else - for (CNum j = 0; j < numSubstreams; j++, digestIndex++) - { - digestsDefined.Add(digestsDefined2[digestIndex]); - digests.Add(digests2[digestIndex]); - } } + // if (k != unpackSizes.Size()) throw 1234567; } - else if (type == NID::kEnd) + else + SkipData(); + + type = ReadID(); + } + + if (digests.Defs.Size() != unpackSizes.Size()) + { + digests.ClearAndSetSize(unpackSizes.Size()); + unsigned k = 0; + for (i = 0; i < folders.NumFolders; i++) { - if (digestsDefined.IsEmpty()) + CNum numSubstreams = folders.NumUnpackStreamsVector[i]; + if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i)) { - BoolVector_Fill_False(digestsDefined, numDigestsTotal); - digests.Clear(); - for (int i = 0; i < numDigestsTotal; i++) - digests.Add(0); + digests.Defs[k] = true; + digests.Vals[k] = folders.FolderCRCs.Vals[i]; + k++; + } + else for (CNum j = 0; j < numSubstreams; j++) + { + digests.Defs[k] = false; + digests.Vals[k] = 0; + k++; } - return; } - else - SkipData(); - type = ReadID(); } } void CInArchive::ReadStreamsInfo( const CObjectVector *dataVector, UInt64 &dataOffset, - CRecordVector &packSizes, - CBoolVector &packCRCsDefined, - CRecordVector &packCRCs, - CObjectVector &folders, - CRecordVector &numUnpackStreamsInFolders, + CFolders &folders, CRecordVector &unpackSizes, - CBoolVector &digestsDefined, - CRecordVector &digests) + CUInt32DefVector &digests) { - for (;;) + UInt64 type = ReadID(); + + if (type == NID::kPackInfo) { - UInt64 type = ReadID(); - if (type > ((UInt32)1 << 30)) - ThrowIncorrect(); - switch((UInt32)type) + dataOffset = ReadNumber(); + ReadPackInfo(folders); + type = ReadID(); + } + + if (type == NID::kUnpackInfo) + { + ReadUnpackInfo(dataVector, folders); + type = ReadID(); + } + + if (folders.NumFolders != 0 && !folders.PackPositions) + { + // if there are folders, we need PackPositions also + folders.PackPositions.Alloc(1); + folders.PackPositions[0] = 0; + } + + if (type == NID::kSubStreamsInfo) + { + ReadSubStreamsInfo(folders, unpackSizes, digests); + type = ReadID(); + } + else + { + folders.NumUnpackStreamsVector.Alloc(folders.NumFolders); + /* If digests.Defs.Size() == 0, it means that there are no crcs. + So we don't need to fill digests with values. */ + // digests.Vals.ClearAndSetSize(folders.NumFolders); + // BoolVector_Fill_False(digests.Defs, folders.NumFolders); + for (CNum i = 0; i < folders.NumFolders; i++) { - 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(); + folders.NumUnpackStreamsVector[i] = 1; + unpackSizes.Add(folders.GetFolderUnpackSize(i)); + // digests.Vals[i] = 0; } } + + if (type != NID::kEnd) + ThrowIncorrect(); } -void CInArchive::ReadBoolVector(int numItems, CBoolVector &v) +void CInArchive::ReadBoolVector(unsigned numItems, CBoolVector &v) { - v.Clear(); - v.Reserve(numItems); + v.ClearAndSetSize(numItems); Byte b = 0; Byte mask = 0; - for (int i = 0; i < numItems; i++) + bool *p = &v[0]; + for (unsigned i = 0; i < numItems; i++) { if (mask == 0) { b = ReadByte(); mask = 0x80; } - v.Add((b & mask) != 0); + p[i] = ((b & mask) != 0); mask >>= 1; } } -void CInArchive::ReadBoolVector2(int numItems, CBoolVector &v) +void CInArchive::ReadBoolVector2(unsigned numItems, CBoolVector &v) { Byte allAreDefined = ReadByte(); if (allAreDefined == 0) @@ -747,27 +1001,30 @@ void CInArchive::ReadBoolVector2(int numItems, CBoolVector &v) ReadBoolVector(numItems, v); return; } - v.Clear(); - v.Reserve(numItems); - for (int i = 0; i < numItems; i++) - v.Add(true); + v.ClearAndSetSize(numItems); + bool *p = &v[0]; + for (unsigned i = 0; i < numItems; i++) + p[i] = true; } void CInArchive::ReadUInt64DefVector(const CObjectVector &dataVector, - CUInt64DefVector &v, int numFiles) + CUInt64DefVector &v, unsigned numItems) { - ReadBoolVector2(numFiles, v.Defined); + ReadBoolVector2(numItems, v.Defs); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); - v.Values.Reserve(numFiles); + + v.Vals.ClearAndSetSize(numItems); + UInt64 *p = &v.Vals[0]; + const bool *defs = &v.Defs[0]; - for (int i = 0; i < numFiles; i++) + for (unsigned i = 0; i < numItems; i++) { UInt64 t = 0; - if (v.Defined[i]) + if (defs[i]) t = ReadUInt64(); - v.Values.Add(t); + p[i] = t; } } @@ -775,35 +1032,19 @@ HRESULT CInArchive::ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset, UInt64 &dataOffset, CObjectVector &dataVector - #ifndef _NO_CRYPTO - , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined - #endif + _7Z_DECODER_CRYPRO_VARS_DECL ) { - CRecordVector packSizes; - CBoolVector packCRCsDefined; - CRecordVector packCRCs; - CObjectVector folders; - - CRecordVector numUnpackStreamsInFolders; + CFolders folders; CRecordVector unpackSizes; - CBoolVector digestsDefined; - CRecordVector digests; + CUInt32DefVector 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 @@ -811,17 +1052,15 @@ HRESULT CInArchive::ReadAndDecodePackedStreams( true #endif ); - UInt64 dataStartPos = baseOffset + dataOffset; - for (int i = 0; i < folders.Size(); i++) + + for (CNum i = 0; i < folders.NumFolders; i++) { - const CFolder &folder = folders[i]; - dataVector.Add(CByteBuffer()); - CByteBuffer &data = dataVector.Back(); - UInt64 unpackSize64 = folder.GetUnpackSize(); + CByteBuffer &data = dataVector.AddNew(); + UInt64 unpackSize64 = folders.GetFolderUnpackSize(i); size_t unpackSize = (size_t)unpackSize64; if (unpackSize != unpackSize64) ThrowUnsupported(); - data.SetCapacity(unpackSize); + data.Alloc(unpackSize); CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream; CMyComPtr outStream = outStreamSpec; @@ -829,43 +1068,35 @@ HRESULT CInArchive::ReadAndDecodePackedStreams( HRESULT result = decoder.Decode( EXTERNAL_CODECS_LOC_VARS - _stream, dataStartPos, - &packSizes[packIndex], folder, outStream, NULL - #ifndef _NO_CRYPTO - , getTextPassword, passwordIsDefined - #endif + _stream, baseOffset + dataOffset, + folders, i, + outStream, NULL + _7Z_DECODER_CRYPRO_VARS #if !defined(_7ZIP_ST) && !defined(_SFX) , false, 1 #endif ); RINOK(result); - if (folder.UnpackCRCDefined) - if (CrcCalc(data, unpackSize) != folder.UnpackCRC) + if (folders.FolderCRCs.ValidAndDefined(i)) + if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i]) ThrowIncorrect(); - for (int j = 0; j < folder.PackStreams.Size(); j++) - { - UInt64 packSize = packSizes[packIndex++]; - dataStartPos += packSize; - HeadersSize += packSize; - } } + HeadersSize += folders.PackPositions[folders.NumPackStreams]; return S_OK; } HRESULT CInArchive::ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS - CArchiveDatabaseEx &db - #ifndef _NO_CRYPTO - , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined - #endif + CDbEx &db + _7Z_DECODER_CRYPRO_VARS_DECL ) { UInt64 type = ReadID(); if (type == NID::kArchiveProperties) { - ReadArchiveProperties(db.ArchiveInfo); + ReadArchiveProperties(db.ArcInfo); type = ReadID(); } @@ -875,70 +1106,53 @@ HRESULT CInArchive::ReadHeader( { HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS - db.ArchiveInfo.StartPositionAfterHeader, - db.ArchiveInfo.DataStartPosition2, + db.ArcInfo.StartPositionAfterHeader, + db.ArcInfo.DataStartPosition2, dataVector - #ifndef _NO_CRYPTO - , getTextPassword, passwordIsDefined - #endif + _7Z_DECODER_CRYPRO_VARS ); RINOK(result); - db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader; + db.ArcInfo.DataStartPosition2 += db.ArcInfo.StartPositionAfterHeader; type = ReadID(); } CRecordVector unpackSizes; - CBoolVector digestsDefined; - CRecordVector digests; + CUInt32DefVector digests; if (type == NID::kMainStreamsInfo) { ReadStreamsInfo(&dataVector, - db.ArchiveInfo.DataStartPosition, - db.PackSizes, - db.PackCRCsDefined, - db.PackCRCs, - db.Folders, - db.NumUnpackStreamsVector, + db.ArcInfo.DataStartPosition, + (CFolders &)db, unpackSizes, - digestsDefined, digests); - db.ArchiveInfo.DataStartPosition += db.ArchiveInfo.StartPositionAfterHeader; + db.ArcInfo.DataStartPosition += db.ArcInfo.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(); + if (type == NID::kFilesInfo) + { CNum numFiles = ReadNum(); + db.Files.ClearAndSetSize(numFiles); + CNum i; + /* 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); + db.ArcInfo.FileInfoPopIDs.Add(NID::kSize); + // if (!db.PackSizes.IsEmpty()) + db.ArcInfo.FileInfoPopIDs.Add(NID::kPackInfo); + if (numFiles > 0 && !digests.Defs.IsEmpty()) + db.ArcInfo.FileInfoPopIDs.Add(NID::kCRC); CBoolVector emptyStreamVector; - BoolVector_Fill_False(emptyStreamVector, (int)numFiles); + BoolVector_Fill_False(emptyStreamVector, (unsigned)numFiles); CBoolVector emptyFileVector; CBoolVector antiFileVector; CNum numEmptyStreams = 0; @@ -949,7 +1163,10 @@ HRESULT CInArchive::ReadHeader( if (type == NID::kEnd) break; UInt64 size = ReadNumber(); - size_t ppp = _inByteBack->_pos; + if (size > _inByteBack->GetRem()) + ThrowIncorrect(); + CStreamSwitch switchProp; + switchProp.Set(this, _inByteBack->GetPtr(), (size_t)size, true); bool addPropIdToList = true; bool isKnownType = true; if (type > ((UInt32)1 << 30)) @@ -960,11 +1177,29 @@ HRESULT CInArchive::ReadHeader( { CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); - for (int i = 0; i < db.Files.Size(); i++) - _inByteBack->ReadString(db.Files[i].Name); + size_t rem = _inByteBack->GetRem(); + db.NamesBuf.Alloc(rem); + ReadBytes(db.NamesBuf, rem); + db.NameOffsets.Alloc(db.Files.Size() + 1); + size_t pos = 0; + unsigned i; + for (i = 0; i < db.Files.Size(); i++) + { + size_t curRem = (rem - pos) / 2; + const UInt16 *buf = (const UInt16 *)(db.NamesBuf + pos); + size_t j; + for (j = 0; j < curRem && buf[j] != 0; j++); + if (j == curRem) + ThrowEndOfData(); + db.NameOffsets[i] = pos / 2; + pos += j * 2 + 2; + } + db.NameOffsets[i] = pos / 2; + if (pos != rem) + ThereIsHeaderError = true; break; } - case NID::kWinAttributes: + case NID::kWinAttrib: { CBoolVector boolVector; ReadBoolVector2(db.Files.Size(), boolVector); @@ -979,9 +1214,40 @@ HRESULT CInArchive::ReadHeader( } break; } + /* + case NID::kIsAux: + { + ReadBoolVector(db.Files.Size(), db.IsAux); + break; + } + case NID::kParent: + { + db.IsTree = true; + // CBoolVector boolVector; + // ReadBoolVector2(db.Files.Size(), boolVector); + // CStreamSwitch streamSwitch; + // streamSwitch.Set(this, &dataVector); + CBoolVector boolVector; + ReadBoolVector2(db.Files.Size(), boolVector); + + db.ThereAreAltStreams = false; + for (i = 0; i < numFiles; i++) + { + CFileItem &file = db.Files[i]; + // file.Parent = -1; + // if (boolVector[i]) + file.Parent = (int)ReadUInt32(); + file.IsAltStream = !boolVector[i]; + if (file.IsAltStream) + db.ThereAreAltStreams = true; + } + break; + } + */ case NID::kEmptyStream: { ReadBoolVector(numFiles, emptyStreamVector); + numEmptyStreams = 0; for (i = 0; i < (CNum)emptyStreamVector.Size(); i++) if (emptyStreamVector[i]) numEmptyStreams++; @@ -993,34 +1259,83 @@ HRESULT CInArchive::ReadHeader( } 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::kStartPos: ReadUInt64DefVector(dataVector, db.StartPos, (unsigned)numFiles); break; + case NID::kCTime: ReadUInt64DefVector(dataVector, db.CTime, (unsigned)numFiles); break; + case NID::kATime: ReadUInt64DefVector(dataVector, db.ATime, (unsigned)numFiles); break; + case NID::kMTime: ReadUInt64DefVector(dataVector, db.MTime, (unsigned)numFiles); break; case NID::kDummy: { for (UInt64 j = 0; j < size; j++) if (ReadByte() != 0) - ThrowIncorrect(); + ThereIsHeaderError = true; addPropIdToList = false; break; } + /* + case NID::kNtSecure: + { + try + { + { + CStreamSwitch streamSwitch; + streamSwitch.Set(this, &dataVector); + UInt32 numDescriptors = ReadUInt32(); + size_t offset = 0; + db.SecureOffsets.Clear(); + for (i = 0; i < numDescriptors; i++) + { + UInt32 size = ReadUInt32(); + db.SecureOffsets.Add(offset); + offset += size; + } + // ThrowIncorrect();; + db.SecureOffsets.Add(offset); + db.SecureBuf.SetCapacity(offset); + for (i = 0; i < numDescriptors; i++) + { + offset = db.SecureOffsets[i]; + ReadBytes(db.SecureBuf + offset, db.SecureOffsets[i + 1] - offset); + } + db.SecureIDs.Clear(); + for (unsigned i = 0; i < db.Files.Size(); i++) + { + db.SecureIDs.Add(ReadNum()); + // db.SecureIDs.Add(ReadUInt32()); + } + // ReadUInt32(); + if (_inByteBack->GetRem() != 0) + ThrowIncorrect();; + } + } + catch(CInArchiveException &) + { + ThereIsHeaderError = true; + addPropIdToList = isKnownType = false; + db.ClearSecure(); + } + break; + } + */ default: addPropIdToList = isKnownType = false; } if (isKnownType) { - if(addPropIdToList) - db.ArchiveInfo.FileInfoPopIDs.Add(type); + if (addPropIdToList) + db.ArcInfo.FileInfoPopIDs.Add(type); } else - SkipData(size); - bool checkRecordsSize = (db.ArchiveInfo.Version.Major > 0 || - db.ArchiveInfo.Version.Minor > 2); - if (checkRecordsSize && _inByteBack->_pos - ppp != size) + { + db.UnsupportedFeatureWarning = true; + _inByteBack->SkipRem(); + } + // SkipData worked incorrectly in some versions before v4.59 (7zVer <= 00.02) + if (_inByteBack->GetRem() != 0) ThrowIncorrect(); } + type = ReadID(); // Read (NID::kEnd) end of headers + CNum emptyFileIndex = 0; CNum sizeIndex = 0; @@ -1034,13 +1349,15 @@ HRESULT CInArchive::ReadHeader( CFileItem &file = db.Files[i]; bool isAnti; file.HasStream = !emptyStreamVector[i]; + file.Crc = 0; if (file.HasStream) { file.IsDir = false; isAnti = false; file.Size = unpackSizes[sizeIndex]; - file.Crc = digests[sizeIndex]; - file.CrcDefined = digestsDefined[sizeIndex]; + file.CrcDefined = digests.ValidAndDefined(sizeIndex); + if (file.CrcDefined) + file.Crc = digests.Vals[sizeIndex]; sizeIndex++; } else @@ -1054,158 +1371,181 @@ HRESULT CInArchive::ReadHeader( 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]; } + db.FillLinks(); + /* + if (type != NID::kEnd) + ThrowIncorrect(); + if (_inByteBack->GetRem() != 0) + ThrowIncorrect(); + */ + return S_OK; } -void CArchiveDatabaseEx::FillFolderStartFileIndex() +void CDbEx::FillLinks() { - FolderStartFileIndex.Clear(); - FolderStartFileIndex.Reserve(Folders.Size()); - FileIndexToFolderIndexMap.Clear(); - FileIndexToFolderIndexMap.Reserve(Files.Size()); + FolderStartFileIndex.ClearAndSetSize(NumFolders); - int folderIndex = 0; + FileIndexToFolderIndexMap.ClearAndSetSize(Files.Size()); + + CNum folderIndex = 0; CNum indexInFolder = 0; - for (int i = 0; i < Files.Size(); i++) + unsigned i; + for (i = 0; i < Files.Size(); i++) { - const CFileItem &file = Files[i]; - bool emptyStream = !file.HasStream; - if (emptyStream && indexInFolder == 0) - { - FileIndexToFolderIndexMap.Add(kNumNoIndex); - continue; - } + bool emptyStream = !Files[i].HasStream; if (indexInFolder == 0) { + if (emptyStream) + { + FileIndexToFolderIndexMap[i] = kNumNoIndex; + continue; + } // v3.13 incorrectly worked with empty folders - // v4.07: Loop for skipping empty folders + // v4.07: we skip empty folders for (;;) { - if (folderIndex >= Folders.Size()) + if (folderIndex >= NumFolders) ThrowIncorrect(); - FolderStartFileIndex.Add(i); // check it + FolderStartFileIndex[folderIndex] = i; if (NumUnpackStreamsVector[folderIndex] != 0) break; folderIndex++; } } - FileIndexToFolderIndexMap.Add(folderIndex); + FileIndexToFolderIndexMap[i] = folderIndex; if (emptyStream) continue; - indexInFolder++; - if (indexInFolder >= NumUnpackStreamsVector[folderIndex]) + if (++indexInFolder >= NumUnpackStreamsVector[folderIndex]) { folderIndex++; indexInFolder = 0; } } + + if (indexInFolder != 0) + folderIndex++; + /* + if (indexInFolder != 0) + ThrowIncorrect(); + */ + for (;;) + { + if (folderIndex >= NumFolders) + return; + FolderStartFileIndex[folderIndex] = i; + /* + if (NumUnpackStreamsVector[folderIndex] != 0) + ThrowIncorrect();; + */ + folderIndex++; + } } HRESULT CInArchive::ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS - CArchiveDatabaseEx &db - #ifndef _NO_CRYPTO - , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined - #endif + CDbEx &db + _7Z_DECODER_CRYPRO_VARS_DECL ) { db.Clear(); - db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; + db.ArcInfo.StartPosition = _arhiveBeginStreamPosition; - db.ArchiveInfo.Version.Major = _header[6]; - db.ArchiveInfo.Version.Minor = _header[7]; + db.ArcInfo.Version.Major = _header[6]; + db.ArcInfo.Version.Minor = _header[7]; - if (db.ArchiveInfo.Version.Major != kMajorVersion) - ThrowUnsupportedVersion(); + if (db.ArcInfo.Version.Major != kMajorVersion) + { + // db.UnsupportedVersion = true; + return S_FALSE; + } - 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); + UInt64 nextHeaderOffset = Get64(_header + 12); + UInt64 nextHeaderSize = Get64(_header + 20); + UInt32 nextHeaderCRC = Get32(_header + 28); #ifdef FORMAT_7Z_RECOVERY - if (crcFromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0) + UInt32 crcFromArc = Get32(_header + 8); + if (crcFromArc == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0) { - UInt64 cur, cur2; + UInt64 cur, fileSize; RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur)); - const int kCheckSize = 500; + const unsigned kCheckSize = 512; 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(_stream->Seek(0, STREAM_SEEK_END, &fileSize)); + UInt64 rem = fileSize - cur; + unsigned checkSize = kCheckSize; + if (rem < kCheckSize) + checkSize = (unsigned)(rem); + if (checkSize < 3) + return S_FALSE; + RINOK(_stream->Seek(fileSize - checkSize, STREAM_SEEK_SET, NULL)); RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize)); - 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) + if (buf[checkSize - 1] != 0) return S_FALSE; + + unsigned i; + for (i = checkSize - 2;; i--) + { + if (buf[i] == NID::kEncodedHeader && buf[i + 1] == NID::kPackInfo || + buf[i] == NID::kHeader && buf[i + 1] == NID::kMainStreamsInfo) + break; + if (i == 0) + return S_FALSE; + } nextHeaderSize = checkSize - i; - nextHeaderOffset = cur2 - cur + i; + nextHeaderOffset = rem - nextHeaderSize; nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize); RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL)); + db.StartHeaderWasRecovered = true; } else #endif { - if (crc != crcFromArchive) - ThrowIncorrect(); + // Crc was tested already at signature check + // if (CrcCalc(_header + 12, 20) != crcFromArchive) ThrowIncorrect(); } - db.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; + db.ArcInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; + db.PhySize = kHeaderSize; + db.IsArc = false; + if ((Int64)nextHeaderOffset < 0 || + nextHeaderSize > ((UInt64)1 << 62)) + return S_FALSE; if (nextHeaderSize == 0) + { + if (nextHeaderOffset != 0) + return S_FALSE; + db.IsArc = true; return S_OK; - - if (nextHeaderSize > (UInt64)(UInt32)0xFFFFFFFF) - return S_FALSE; - - if ((Int64)nextHeaderOffset < 0) - return S_FALSE; - - if (db.ArchiveInfo.StartPositionAfterHeader + nextHeaderOffset > _fileEndPosition) + } + + if (!db.StartHeaderWasRecovered) + db.IsArc = true; + + HeadersSize += kHeaderSize + nextHeaderSize; + db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize; + if (_fileEndPosition - db.ArcInfo.StartPositionAfterHeader < nextHeaderOffset + nextHeaderSize) + { + db.UnexpectedEnd = true; return S_FALSE; + } RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL)); - CByteBuffer buffer2; - buffer2.SetCapacity((size_t)nextHeaderSize); + size_t nextHeaderSize_t = (size_t)nextHeaderSize; + if (nextHeaderSize_t != nextHeaderSize) + return E_OUTOFMEMORY; + CByteBuffer buffer2(nextHeaderSize_t); - RINOK(ReadStream_FALSE(_stream, buffer2, (size_t)nextHeaderSize)); - HeadersSize += kHeaderSize + nextHeaderSize; - db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize; + RINOK(ReadStream_FALSE(_stream, buffer2, nextHeaderSize_t)); - if (CrcCalc(buffer2, (UInt32)nextHeaderSize) != nextHeaderCRC) + if (CrcCalc(buffer2, nextHeaderSize_t) != nextHeaderCRC) ThrowIncorrect(); + + if (!db.StartHeaderWasRecovered) + db.PhySizeWasConfirmed = true; CStreamSwitch streamSwitch; streamSwitch.Set(this, buffer2); @@ -1219,12 +1559,10 @@ HRESULT CInArchive::ReadDatabase2( ThrowIncorrect(); HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS - db.ArchiveInfo.StartPositionAfterHeader, - db.ArchiveInfo.DataStartPosition2, + db.ArcInfo.StartPositionAfterHeader, + db.ArcInfo.DataStartPosition2, dataVector - #ifndef _NO_CRYPTO - , getTextPassword, passwordIsDefined - #endif + _7Z_DECODER_CRYPRO_VARS ); RINOK(result); if (dataVector.Size() == 0) @@ -1237,35 +1575,45 @@ HRESULT CInArchive::ReadDatabase2( ThrowIncorrect(); } + db.IsArc = true; + db.HeadersSize = HeadersSize; return ReadHeader( EXTERNAL_CODECS_LOC_VARS db - #ifndef _NO_CRYPTO - , getTextPassword, passwordIsDefined - #endif + _7Z_DECODER_CRYPRO_VARS ); } HRESULT CInArchive::ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS - CArchiveDatabaseEx &db - #ifndef _NO_CRYPTO - , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined - #endif + CDbEx &db + _7Z_DECODER_CRYPRO_VARS_DECL ) { try { - return ReadDatabase2( + HRESULT res = ReadDatabase2( EXTERNAL_CODECS_LOC_VARS db - #ifndef _NO_CRYPTO - , getTextPassword, passwordIsDefined - #endif + _7Z_DECODER_CRYPRO_VARS ); + if (ThereIsHeaderError) + db.ThereIsHeaderError = true; + if (res == E_NOTIMPL) + ThrowUnsupported(); + return res; + } + catch(CUnsupportedFeatureException &) + { + db.UnsupportedFeatureError = true; + return S_FALSE; + } + catch(CInArchiveException &) + { + db.ThereIsHeaderError = true; + return S_FALSE; } - catch(CInArchiveException &) { return S_FALSE; } } }} diff --git a/CPP/7zip/Archive/7z/7zIn.h b/CPP/7zip/Archive/7z/7zIn.h old mode 100755 new mode 100644 index 4305a8c5..1836a06b --- a/CPP/7zip/Archive/7z/7zIn.h +++ b/CPP/7zip/Archive/7z/7zIn.h @@ -5,6 +5,8 @@ #include "../../../Common/MyCom.h" +#include "../../../Windows/PropVariant.h" + #include "../../IPassword.h" #include "../../IStream.h" @@ -15,7 +17,147 @@ namespace NArchive { namespace N7z { + +/* + We don't need to init isEncrypted and passwordIsDefined + We must upgrade them only */ + +#ifdef _NO_CRYPTO +#define _7Z_DECODER_CRYPRO_VARS_DECL +#define _7Z_DECODER_CRYPRO_VARS +#else +#define _7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined +#define _7Z_DECODER_CRYPRO_VARS , getTextPassword, isEncrypted, passwordIsDefined +#endif + +struct CParsedMethods +{ + Byte Lzma2Prop; + UInt32 LzmaDic; + CRecordVector IDs; + + CParsedMethods(): Lzma2Prop(0), LzmaDic(0) {} +}; + +struct CFolders +{ + CNum NumPackStreams; + CNum NumFolders; + + CObjArray PackPositions; // NumPackStreams + 1 + // CUInt32DefVector PackCRCs; // we don't use PackCRCs now + + CUInt32DefVector FolderCRCs; // NumFolders + CObjArray NumUnpackStreamsVector; // NumFolders + + CObjArray CoderUnpackSizes; // including unpack sizes of bind coders + CObjArray FoToCoderUnpackSizes; // NumFolders + 1 + CObjArray FoStartPackStreamIndex; // NumFolders + 1 + CObjArray FoToMainUnpackSizeIndex; // NumFolders + CObjArray FoCodersDataOffset; // NumFolders + 1 + CByteBuffer CodersData; + + CParsedMethods ParsedMethods; + + void ParseFolderInfo(unsigned folderIndex, CFolder &folder) const; + + unsigned GetNumFolderUnpackSizes(unsigned folderIndex) const + { + return FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex]; + } + + UInt64 GetFolderUnpackSize(unsigned folderIndex) const + { + return CoderUnpackSizes[FoToCoderUnpackSizes[folderIndex] + FoToMainUnpackSizeIndex[folderIndex]]; + } + + UInt64 GetStreamPackSize(unsigned index) const + { + return PackPositions[index + 1] - PackPositions[index]; + } + + void Clear() + { + NumPackStreams = 0; + PackPositions.Free(); + // PackCRCs.Clear(); + + NumFolders = 0; + FolderCRCs.Clear(); + NumUnpackStreamsVector.Free(); + CoderUnpackSizes.Free(); + FoToCoderUnpackSizes.Free(); + FoStartPackStreamIndex.Free(); + FoToMainUnpackSizeIndex.Free(); + FoCodersDataOffset.Free(); + CodersData.Free(); + } +}; + +struct CDatabase: public CFolders +{ + CRecordVector Files; + + CUInt64DefVector CTime; + CUInt64DefVector ATime; + CUInt64DefVector MTime; + CUInt64DefVector StartPos; + CRecordVector IsAnti; + /* + CRecordVector IsAux; + CByteBuffer SecureBuf; + CRecordVector SecureIDs; + */ + + CByteBuffer NamesBuf; + CObjArray NameOffsets; // numFiles + 1, conatins offsets of UINt16 symbols. + + /* + void ClearSecure() + { + SecureBuf.Free(); + SecureIDs.Clear(); + } + */ + + void Clear() + { + CFolders::Clear(); + // ClearSecure(); + + NamesBuf.Free(); + NameOffsets.Free(); + + Files.Clear(); + CTime.Clear(); + ATime.Clear(); + MTime.Clear(); + StartPos.Clear(); + IsAnti.Clear(); + // IsAux.Clear(); + } + + bool IsSolid() const + { + for (CNum i = 0; i < NumFolders; i++) + if (NumUnpackStreamsVector[i] > 1) + return true; + return false; + } + bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); } + // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); } + + const wchar_t * GetName(unsigned index) const + { + if (!NameOffsets || !NamesBuf) + return NULL; + return (const wchar_t *)(const Byte *)NamesBuf + NameOffsets[index]; + }; + + HRESULT GetPath(unsigned index, PROPVARIANT *path) const; +}; + struct CInArchiveInfo { CArchiveVersion Version; @@ -24,29 +166,73 @@ struct CInArchiveInfo UInt64 DataStartPosition; UInt64 DataStartPosition2; CRecordVector FileInfoPopIDs; + void Clear() { + StartPosition = 0; + StartPositionAfterHeader = 0; + DataStartPosition = 0; + DataStartPosition2 = 0; FileInfoPopIDs.Clear(); } }; -struct CArchiveDatabaseEx: public CArchiveDatabase +struct CDbEx: public CDatabase { - CInArchiveInfo ArchiveInfo; - CRecordVector PackStreamStartPositions; - CRecordVector FolderStartPackStreamIndex; + CInArchiveInfo ArcInfo; CRecordVector FolderStartFileIndex; CRecordVector FileIndexToFolderIndexMap; UInt64 HeadersSize; UInt64 PhySize; + /* + CRecordVector SecureOffsets; + bool IsTree; + bool ThereAreAltStreams; + */ + + bool IsArc; + bool PhySizeWasConfirmed; + + bool ThereIsHeaderError; + bool UnexpectedEnd; + // bool UnsupportedVersion; + + bool StartHeaderWasRecovered; + bool UnsupportedFeatureWarning; + bool UnsupportedFeatureError; + + /* + void ClearSecureEx() + { + ClearSecure(); + SecureOffsets.Clear(); + } + */ + void Clear() { - CArchiveDatabase::Clear(); - ArchiveInfo.Clear(); - PackStreamStartPositions.Clear(); - FolderStartPackStreamIndex.Clear(); + IsArc = false; + PhySizeWasConfirmed = false; + + ThereIsHeaderError = false; + UnexpectedEnd = false; + // UnsupportedVersion = false; + + StartHeaderWasRecovered = false; + UnsupportedFeatureError = false; + UnsupportedFeatureWarning = false; + + /* + IsTree = false; + ThereAreAltStreams = false; + */ + + CDatabase::Clear(); + + // SecureOffsets.Clear(); + ArcInfo.Clear(); FolderStartFileIndex.Clear(); FileIndexToFolderIndexMap.Clear(); @@ -54,36 +240,25 @@ struct CArchiveDatabaseEx: public CArchiveDatabase PhySize = 0; } - void FillFolderStartPackStream(); - void FillStartPos(); - void FillFolderStartFileIndex(); - - void Fill() - { - FillFolderStartPackStream(); - FillStartPos(); - FillFolderStartFileIndex(); - } + void FillLinks(); - UInt64 GetFolderStreamPos(int folderIndex, int indexInFolder) const + UInt64 GetFolderStreamPos(unsigned folderIndex, unsigned indexInFolder) const { - return ArchiveInfo.DataStartPosition + - PackStreamStartPositions[FolderStartPackStreamIndex[folderIndex] + indexInFolder]; + return ArcInfo.DataStartPosition + + PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder]; } - UInt64 GetFolderFullPackSize(int folderIndex) const + UInt64 GetFolderFullPackSize(unsigned 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; + return + PackPositions[FoStartPackStreamIndex[folderIndex + 1]] - + PackPositions[FoStartPackStreamIndex[folderIndex]]; } - UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const + UInt64 GetFolderPackStreamSize(unsigned folderIndex, unsigned streamIndex) const { - return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; + unsigned i = FoStartPackStreamIndex[folderIndex] + streamIndex; + return PackPositions[i + 1] - PackPositions[i]; } UInt64 GetFilePackSize(CNum fileIndex) const @@ -96,12 +271,17 @@ struct CArchiveDatabaseEx: public CArchiveDatabase } }; -class CInByte2 +const unsigned kNumBufLevelsMax = 4; + +struct CInByte2 { const Byte *_buffer; - size_t _size; public: + size_t _size; size_t _pos; + + size_t GetRem() const { return _size - _pos; } + const Byte *GetPtr() const { return _buffer + _pos; } void Init(const Byte *buffer, size_t size) { _buffer = buffer; @@ -110,13 +290,17 @@ public: } Byte ReadByte(); void ReadBytes(Byte *data, size_t size); + void SkipDataNoCheck(UInt64 size) { _pos += (size_t)size; } void SkipData(UInt64 size); + void SkipData(); + void SkipRem() { _pos = _size; } UInt64 ReadNumber(); CNum ReadNum(); UInt32 ReadUInt32(); UInt64 ReadUInt64(); - void ReadString(UString &s); + + void ParseFolder(CFolder &folder); }; class CStreamSwitch; @@ -129,8 +313,11 @@ class CInArchive CMyComPtr _stream; - CObjectVector _inByteVector; + unsigned _numInByteBufs; + CInByte2 _inByteVector[kNumBufLevelsMax]; + CInByte2 *_inByteBack; + bool ThereIsHeaderError; UInt64 _arhiveBeginStreamPosition; UInt64 _fileEndPosition; @@ -139,18 +326,17 @@ class CInArchive UInt64 HeadersSize; - void AddByteStream(const Byte *buffer, size_t size) - { - _inByteVector.Add(CInByte2()); - _inByteBack = &_inByteVector.Back(); - _inByteBack->Init(buffer, size); - } + void AddByteStream(const Byte *buffer, size_t size); - void DeleteByteStream() + void DeleteByteStream(bool needUpdatePos) { - _inByteVector.DeleteBack(); - if (!_inByteVector.IsEmpty()) - _inByteBack = &_inByteVector.Back(); + _numInByteBufs--; + if (_numInByteBufs > 0) + { + _inByteBack = &_inByteVector[_numInByteBufs - 1]; + if (needUpdatePos) + _inByteBack->_pos += _inByteVector[_numInByteBufs]._pos; + } } private: @@ -165,79 +351,58 @@ private: UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); } void SkipData(UInt64 size) { _inByteBack->SkipData(size); } void SkipData() { _inByteBack->SkipData(); } - void WaitAttribute(UInt64 attribute); + void WaitId(UInt64 id); void ReadArchiveProperties(CInArchiveInfo &archiveInfo); - void GetNextFolderItem(CFolder &itemInfo); - void ReadHashDigests(int numItems, - CBoolVector &digestsDefined, CRecordVector &digests); + void ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs); - void ReadPackInfo( - UInt64 &dataOffset, - CRecordVector &packSizes, - CBoolVector &packCRCsDefined, - CRecordVector &packCRCs); + void ReadPackInfo(CFolders &f); void ReadUnpackInfo( const CObjectVector *dataVector, - CObjectVector &folders); + CFolders &folders); void ReadSubStreamsInfo( - const CObjectVector &folders, - CRecordVector &numUnpackStreamsInFolders, + CFolders &folders, CRecordVector &unpackSizes, - CBoolVector &digestsDefined, - CRecordVector &digests); + CUInt32DefVector &digests); void ReadStreamsInfo( const CObjectVector *dataVector, UInt64 &dataOffset, - CRecordVector &packSizes, - CBoolVector &packCRCsDefined, - CRecordVector &packCRCs, - CObjectVector &folders, - CRecordVector &numUnpackStreamsInFolders, + CFolders &folders, CRecordVector &unpackSizes, - CBoolVector &digestsDefined, - CRecordVector &digests); - + CUInt32DefVector &digests); - void ReadBoolVector(int numItems, CBoolVector &v); - void ReadBoolVector2(int numItems, CBoolVector &v); + void ReadBoolVector(unsigned numItems, CBoolVector &v); + void ReadBoolVector2(unsigned numItems, CBoolVector &v); void ReadUInt64DefVector(const CObjectVector &dataVector, - CUInt64DefVector &v, int numFiles); + CUInt64DefVector &v, unsigned numItems); HRESULT ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset, UInt64 &dataOffset, CObjectVector &dataVector - #ifndef _NO_CRYPTO - , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined - #endif + _7Z_DECODER_CRYPRO_VARS_DECL ); HRESULT ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS - CArchiveDatabaseEx &db - #ifndef _NO_CRYPTO - ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined - #endif + CDbEx &db + _7Z_DECODER_CRYPRO_VARS_DECL ); HRESULT ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS - CArchiveDatabaseEx &db - #ifndef _NO_CRYPTO - ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined - #endif + CDbEx &db + _7Z_DECODER_CRYPRO_VARS_DECL ); public: + CInArchive(): _numInByteBufs(0) { } 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 + CDbEx &db + _7Z_DECODER_CRYPRO_VARS_DECL ); }; diff --git a/CPP/7zip/Archive/7z/7zItem.h b/CPP/7zip/Archive/7z/7zItem.h old mode 100755 new mode 100644 index 34f10775..02a86196 --- a/CPP/7zip/Archive/7z/7zItem.h +++ b/CPP/7zip/Archive/7z/7zItem.h @@ -3,7 +3,7 @@ #ifndef __7Z_ITEM_H #define __7Z_ITEM_H -#include "../../../Common/Buffer.h" +#include "../../../Common/MyBuffer.h" #include "../../../Common/MyString.h" #include "../../Common/MethodId.h" @@ -25,6 +25,7 @@ struct CCoderInfo CByteBuffer Props; CNum NumInStreams; CNum NumOutStreams; + bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } }; @@ -36,55 +37,48 @@ struct CBindPair 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; - } + CObjArray2 Coders; + CObjArray2 BindPairs; + CObjArray2 PackStreams; CNum GetNumOutStreams() const { CNum result = 0; - for (int i = 0; i < Coders.Size(); i++) + FOR_VECTOR(i, Coders) result += Coders[i].NumOutStreams; return result; } int FindBindPairForInStream(CNum inStreamIndex) const { - for(int i = 0; i < BindPairs.Size(); i++) + FOR_VECTOR(i, BindPairs) if (BindPairs[i].InIndex == inStreamIndex) return i; return -1; } int FindBindPairForOutStream(CNum outStreamIndex) const { - for(int i = 0; i < BindPairs.Size(); i++) + FOR_VECTOR(i, BindPairs) if (BindPairs[i].OutIndex == outStreamIndex) return i; return -1; } int FindPackStreamArrayIndex(CNum inStreamIndex) const { - for(int i = 0; i < PackStreams.Size(); i++) + FOR_VECTOR(i, PackStreams) if (PackStreams[i] == inStreamIndex) return i; return -1; } + int GetIndexOfMainOutStream() const + { + for (int i = (int)GetNumOutStreams() - 1; i >= 0; i--) + if (FindBindPairForOutStream(i) < 0) + return i; + throw 1; + } + bool IsEncrypted() const { for (int i = Coders.Size() - 1; i >= 0; i--) @@ -93,50 +87,66 @@ struct CFolder return false; } - bool CheckStructure() const; + bool CheckStructure(unsigned numUnpackSizes) const; +}; + +struct CUInt32DefVector +{ + CBoolVector Defs; + CRecordVector Vals; + + void ClearAndSetSize(unsigned newSize) + { + Defs.ClearAndSetSize(newSize); + Vals.ClearAndSetSize(newSize); + } + + void Clear() + { + Defs.Clear(); + Vals.Clear(); + } + + void ReserveDown() + { + Defs.ReserveDown(); + Vals.ReserveDown(); + } + + bool ValidAndDefined(unsigned i) const { return i < Defs.Size() && Defs[i]; } }; struct CUInt64DefVector { - CRecordVector Values; - CRecordVector Defined; + CBoolVector Defs; + CRecordVector Vals; void Clear() { - Values.Clear(); - Defined.Clear(); + Defs.Clear(); + Vals.Clear(); } void ReserveDown() { - Values.ReserveDown(); - Values.ReserveDown(); + Defs.ReserveDown(); + Vals.ReserveDown(); } - bool GetItem(int index, UInt64 &value) const + bool GetItem(unsigned index, UInt64 &value) const { - if (index < Defined.Size() && Defined[index]) + if (index < Defs.Size() && Defs[index]) { - value = Values[index]; + value = Vals[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; - } + void SetItem(unsigned index, bool defined, UInt64 value); - bool CheckSize(int size) const { return Defined.Size() == size || Defined.Size() == 0; } + bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; } }; struct CFileItem @@ -144,8 +154,10 @@ struct CFileItem UInt64 Size; UInt32 Attrib; UInt32 Crc; - UString Name; - + /* + int Parent; + bool IsAltStream; + */ bool HasStream; // Test it !!! it means that there is // stream in some folder. It can be empty stream bool IsDir; @@ -153,6 +165,10 @@ struct CFileItem bool AttribDefined; CFileItem(): + /* + Parent(-1), + IsAltStream(false), + */ HasStream(true), IsDir(false), CrcDefined(false), @@ -165,104 +181,6 @@ struct CFileItem } }; -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 old mode 100755 new mode 100644 index 0c8aa7e8..9ff97595 --- a/CPP/7zip/Archive/7z/7zOut.cpp +++ b/CPP/7zip/Archive/7z/7zOut.cpp @@ -10,35 +10,15 @@ #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; + buf[kSignatureSize + 1] = 4; return WriteDirect(buf, 8); } @@ -145,7 +125,9 @@ HRESULT COutArchive::SkipPrefixArchiveHeader() if (_endMarker) return S_OK; #endif - return Stream->Seek(24, STREAM_SEEK_CUR, NULL); + Byte buf[24]; + memset(buf, 0, 24); + return WriteDirect(buf, 24); } UInt64 COutArchive::GetPos() const @@ -271,19 +253,19 @@ UInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props) void COutArchive::WriteFolder(const CFolder &folder) { WriteNumber(folder.Coders.Size()); - int i; + unsigned i; for (i = 0; i < folder.Coders.Size(); i++) { const CCoderInfo &coder = folder.Coders[i]; { - size_t propsSize = coder.Props.GetCapacity(); + size_t propsSize = coder.Props.Size(); UInt64 id = coder.MethodID; int idSize; for (idSize = 1; idSize < sizeof(id); idSize++) if ((id >> (8 * idSize)) == 0) break; - BYTE longID[15]; + Byte longID[15]; for (int t = idSize - 1; t >= 0 ; t--, id >>= 8) longID[t] = (Byte)(id & 0xFF); Byte b; @@ -321,7 +303,7 @@ void COutArchive::WriteBoolVector(const CBoolVector &boolVector) { Byte b = 0; Byte mask = 0x80; - for (int i = 0; i < boolVector.Size(); i++) + FOR_VECTOR (i, boolVector) { if (boolVector[i]) b |= mask; @@ -337,37 +319,42 @@ void COutArchive::WriteBoolVector(const CBoolVector &boolVector) WriteByte(b); } +static inline unsigned Bv_GetSizeInBytes(const CBoolVector &v) { return ((unsigned)v.Size() + 7) / 8; } -void COutArchive::WriteHashDigests( - const CRecordVector &digestsDefined, - const CRecordVector &digests) +void COutArchive::WritePropBoolVector(Byte id, const CBoolVector &boolVector) { - int numDefined = 0; - int i; - for (i = 0; i < digestsDefined.Size(); i++) - if (digestsDefined[i]) + WriteByte(id); + WriteNumber(Bv_GetSizeInBytes(boolVector)); + WriteBoolVector(boolVector); +} + +void COutArchive::WriteHashDigests(const CUInt32DefVector &digests) +{ + unsigned numDefined = 0; + unsigned i; + for (i = 0; i < digests.Defs.Size(); i++) + if (digests.Defs[i]) numDefined++; if (numDefined == 0) return; WriteByte(NID::kCRC); - if (numDefined == digestsDefined.Size()) + if (numDefined == digests.Defs.Size()) WriteByte(1); else { WriteByte(0); - WriteBoolVector(digestsDefined); + WriteBoolVector(digests.Defs); } - for (i = 0; i < digests.Size(); i++) - if (digestsDefined[i]) - WriteUInt32(digests[i]); + for (i = 0; i < digests.Defs.Size(); i++) + if (digests.Defs[i]) + WriteUInt32(digests.Vals[i]); } void COutArchive::WritePackInfo( UInt64 dataOffset, const CRecordVector &packSizes, - const CRecordVector &packCRCsDefined, - const CRecordVector &packCRCs) + const CUInt32DefVector &packCRCs) { if (packSizes.IsEmpty()) return; @@ -375,15 +362,15 @@ void COutArchive::WritePackInfo( WriteNumber(dataOffset); WriteNumber(packSizes.Size()); WriteByte(NID::kSize); - for (int i = 0; i < packSizes.Size(); i++) + FOR_VECTOR (i, packSizes) WriteNumber(packSizes[i]); - WriteHashDigests(packCRCsDefined, packCRCs); + WriteHashDigests(packCRCs); WriteByte(NID::kEnd); } -void COutArchive::WriteUnpackInfo(const CObjectVector &folders) +void COutArchive::WriteUnpackInfo(const CObjectVector &folders, const COutFolders &outFolders) { if (folders.IsEmpty()) return; @@ -394,44 +381,29 @@ void COutArchive::WriteUnpackInfo(const CObjectVector &folders) WriteNumber(folders.Size()); { WriteByte(0); - for (int i = 0; i < folders.Size(); i++) + FOR_VECTOR (i, folders) 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); - + FOR_VECTOR (i, outFolders.CoderUnpackSizes) + WriteNumber(outFolders.CoderUnpackSizes[i]); + + WriteHashDigests(outFolders.FolderUnpackCRCs); + WriteByte(NID::kEnd); } -void COutArchive::WriteSubStreamsInfo( - const CObjectVector &folders, - const CRecordVector &numUnpackStreamsInFolders, +void COutArchive::WriteSubStreamsInfo(const CObjectVector &folders, + const COutFolders &outFolders, const CRecordVector &unpackSizes, - const CRecordVector &digestsDefined, - const CRecordVector &digests) + const CUInt32DefVector &digests) { + const CRecordVector &numUnpackStreamsInFolders = outFolders.NumUnpackStreamsVector; WriteByte(NID::kSubStreamsInfo); - int i; + unsigned i; for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) - { if (numUnpackStreamsInFolders[i] != 1) { WriteByte(NID::kNumUnpackStream); @@ -439,54 +411,50 @@ void COutArchive::WriteSubStreamsInfo( 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 (numUnpackStreamsInFolders[i] > 1) { - if (j + 1 != numUnpackStreamsInFolders[i]) + WriteByte(NID::kSize); + CNum index = 0; + for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) { - if (needFlag) - WriteByte(NID::kSize); - needFlag = false; - WriteNumber(unpackSizes[index]); + CNum num = numUnpackStreamsInFolders[i]; + for (CNum j = 0; j < num; j++) + { + if (j + 1 != num) + WriteNumber(unpackSizes[index]); + index++; + } } - index++; + break; } - CRecordVector digestsDefined2; - CRecordVector digests2; + CUInt32DefVector digests2; - int digestIndex = 0; + unsigned digestIndex = 0; for (i = 0; i < folders.Size(); i++) { - int numSubStreams = (int)numUnpackStreamsInFolders[i]; - if (numSubStreams == 1 && folders[i].UnpackCRCDefined) + unsigned numSubStreams = (unsigned)numUnpackStreamsInFolders[i]; + if (numSubStreams == 1 && outFolders.FolderUnpackCRCs.ValidAndDefined(i)) digestIndex++; else - for (int j = 0; j < numSubStreams; j++, digestIndex++) + for (unsigned j = 0; j < numSubStreams; j++, digestIndex++) { - digestsDefined2.Add(digestsDefined[digestIndex]); - digests2.Add(digests[digestIndex]); + digests2.Defs.Add(digests.Defs[digestIndex]); + digests2.Vals.Add(digests.Vals[digestIndex]); } } - WriteHashDigests(digestsDefined2, digests2); + WriteHashDigests(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. +// 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) { + if (!_useAlign) + return; pos += (unsigned)GetPos(); pos &= (alignSize - 1); if (pos == 0) @@ -500,11 +468,8 @@ void COutArchive::SkipAlign(unsigned pos, unsigned alignSize) 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) +void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSize) { const unsigned bvSize = (numDefined == v.Size()) ? 0 : Bv_GetSizeInBytes(v); const UInt64 dataSize = (UInt64)numDefined * itemSize + bvSize + 2; @@ -524,48 +489,53 @@ void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, B void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type) { - int numDefined = 0; + unsigned numDefined = 0; - int i; - for (i = 0; i < v.Defined.Size(); i++) - if (v.Defined[i]) + unsigned i; + for (i = 0; i < v.Defs.Size(); i++) + if (v.Defs[i]) numDefined++; if (numDefined == 0) return; - WriteAlignedBoolHeader(v.Defined, numDefined, type, 8); + WriteAlignedBoolHeader(v.Defs, numDefined, type, 8); - for (i = 0; i < v.Defined.Size(); i++) - if (v.Defined[i]) - WriteUInt64(v.Values[i]); + for (i = 0; i < v.Defs.Size(); i++) + if (v.Defs[i]) + WriteUInt64(v.Vals[i]); } HRESULT COutArchive::EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const CByteBuffer &data, - CRecordVector &packSizes, CObjectVector &folders) + CRecordVector &packSizes, CObjectVector &folders, COutFolders &outFolders) { 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(); + streamSpec->Init(data, data.Size()); + outFolders.FolderUnpackCRCs.Defs.Add(true); + outFolders.FolderUnpackCRCs.Vals.Add(CrcCalc(data, data.Size())); + // outFolders.NumUnpackStreamsVector.Add(1); + UInt64 dataSize64 = data.Size(); + UInt64 unpackSize; RINOK(encoder.Encode( EXTERNAL_CODECS_LOC_VARS - stream, NULL, &dataSize64, folderItem, SeqStream, packSizes, NULL)) - folders.Add(folderItem); + stream, NULL, &dataSize64, folders.AddNew(), outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL)) return S_OK; } void COutArchive::WriteHeader( - const CArchiveDatabase &db, - const CHeaderOptions &headerOptions, + const CArchiveDatabaseOut &db, + // const CHeaderOptions &headerOptions, UInt64 &headerOffset) { - int i; + /* + bool thereIsSecure = (db.SecureBuf.Size() != 0); + */ + _useAlign = true; + + unsigned i; UInt64 packedSize = 0; for (i = 0; i < db.PackSizes.Size(); i++) @@ -580,31 +550,22 @@ void COutArchive::WriteHeader( if (db.Folders.Size() > 0) { WriteByte(NID::kMainStreamsInfo); - WritePackInfo(0, db.PackSizes, - db.PackCRCsDefined, - db.PackCRCs); - - WriteUnpackInfo(db.Folders); + WritePackInfo(0, db.PackSizes, db.PackCRCs); + WriteUnpackInfo(db.Folders, (const COutFolders &)db); CRecordVector unpackSizes; - CRecordVector digestsDefined; - CRecordVector digests; + CUInt32DefVector 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); + digests.Defs.Add(file.CrcDefined); + digests.Vals.Add(file.Crc); } - WriteSubStreamsInfo( - db.Folders, - db.NumUnpackStreamsVector, - unpackSizes, - digestsDefined, - digests); + WriteSubStreamsInfo(db.Folders, (const COutFolders &)db, unpackSizes, digests); WriteByte(NID::kEnd); } @@ -618,85 +579,75 @@ void COutArchive::WriteHeader( 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; + /* ---------- Empty Streams ---------- */ + CBoolVector emptyStreamVector; + emptyStreamVector.ClearAndSetSize(db.Files.Size()); + unsigned numEmptyStreams = 0; for (i = 0; i < db.Files.Size(); i++) + if (db.Files[i].HasStream) + emptyStreamVector[i] = false; + else + { + emptyStreamVector[i] = true; + numEmptyStreams++; + } + if (numEmptyStreams != 0) { - const CFileItem &file = db.Files[i]; - if (!file.HasStream) + WritePropBoolVector(NID::kEmptyStream, emptyStreamVector); + + CBoolVector emptyFileVector, antiVector; + emptyFileVector.ClearAndSetSize(numEmptyStreams); + antiVector.ClearAndSetSize(numEmptyStreams); + bool thereAreEmptyFiles = false, thereAreAntiItems = false; + unsigned cur = 0; + for (i = 0; i < db.Files.Size(); i++) { - emptyFileVector.Add(!file.IsDir); + const CFileItem &file = db.Files[i]; + if (file.HasStream) + continue; + emptyFileVector[cur] = !file.IsDir; if (!file.IsDir) - numEmptyFiles++; + thereAreEmptyFiles = true; bool isAnti = db.IsItemAnti(i); - antiVector.Add(isAnti); + antiVector[cur] = isAnti; if (isAnti) - numAntiItems++; + thereAreAntiItems = true; + cur++; } + + if (thereAreEmptyFiles) + WritePropBoolVector(NID::kEmptyFile, emptyFileVector); + if (thereAreAntiItems) + WritePropBoolVector(NID::kAnti, antiVector); } - - 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; + unsigned numDefined = 0; size_t namesDataSize = 0; - for (int i = 0; i < db.Files.Size(); i++) + FOR_VECTOR (i, db.Files) { - const UString &name = db.Files[i].Name; + const UString &name = db.Names[i]; if (!name.IsEmpty()) numDefined++; - namesDataSize += (name.Length() + 1) * 2; + namesDataSize += (name.Len() + 1) * 2; } if (numDefined > 0) { namesDataSize++; - SkipAlign(2 + GetBigNumberSize(namesDataSize), 2); + SkipAlign(2 + GetBigNumberSize(namesDataSize), 16); WriteByte(NID::kName); WriteNumber(namesDataSize); WriteByte(0); - for (int i = 0; i < db.Files.Size(); i++) + FOR_VECTOR (i, db.Files) { - const UString &name = db.Files[i].Name; - for (int t = 0; t <= name.Length(); t++) + const UString &name = db.Names[i]; + for (unsigned t = 0; t <= name.Len(); t++) { wchar_t c = name[t]; WriteByte((Byte)c); @@ -706,26 +657,26 @@ void COutArchive::WriteHeader( } } - if (headerOptions.WriteCTime) WriteUInt64DefVector(db.CTime, NID::kCTime); - if (headerOptions.WriteATime) WriteUInt64DefVector(db.ATime, NID::kATime); - if (headerOptions.WriteMTime) WriteUInt64DefVector(db.MTime, NID::kMTime); + /* 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; + boolVector.ClearAndSetSize(db.Files.Size()); + unsigned numDefined = 0; for (i = 0; i < db.Files.Size(); i++) { bool defined = db.Files[i].AttribDefined; - boolVector.Add(defined); + boolVector[i] = defined; if (defined) numDefined++; } - if (numDefined > 0) + if (numDefined != 0) { - WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttributes, 4); + WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttrib, 4); for (i = 0; i < db.Files.Size(); i++) { const CFileItem &file = db.Files[i]; @@ -735,13 +686,95 @@ void COutArchive::WriteHeader( } } + /* + { + // ---------- Write IsAux ---------- + unsigned numAux = 0; + const CBoolVector &isAux = db.IsAux; + for (i = 0; i < isAux.Size(); i++) + if (isAux[i]) + numAux++; + if (numAux > 0) + { + const unsigned bvSize = Bv_GetSizeInBytes(isAux); + WriteByte(NID::kIsAux); + WriteNumber(bvSize); + WriteBoolVector(isAux); + } + } + + { + // ---------- Write Parent ---------- + CBoolVector boolVector; + boolVector.Reserve(db.Files.Size()); + unsigned numIsDir = 0; + unsigned numParentLinks = 0; + for (i = 0; i < db.Files.Size(); i++) + { + const CFileItem &file = db.Files[i]; + bool defined = !file.IsAltStream; + boolVector.Add(defined); + if (defined) + numIsDir++; + if (file.Parent >= 0) + numParentLinks++; + } + if (numParentLinks > 0) + { + // WriteAlignedBoolHeader(boolVector, numDefined, NID::kParent, 4); + const unsigned bvSize = (numIsDir == boolVector.Size()) ? 0 : Bv_GetSizeInBytes(boolVector); + const UInt64 dataSize = (UInt64)db.Files.Size() * 4 + bvSize + 1; + SkipAlign(2 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), 4); + + WriteByte(NID::kParent); + WriteNumber(dataSize); + if (numIsDir == boolVector.Size()) + WriteByte(1); + else + { + WriteByte(0); + WriteBoolVector(boolVector); + } + for (i = 0; i < db.Files.Size(); i++) + { + const CFileItem &file = db.Files[i]; + // if (file.Parent >= 0) + WriteUInt32(file.Parent); + } + } + } + + if (thereIsSecure) + { + UInt64 secureDataSize = 1 + 4 + + db.SecureBuf.Size() + + db.SecureSizes.Size() * 4; + // secureDataSize += db.SecureIDs.Size() * 4; + for (i = 0; i < db.SecureIDs.Size(); i++) + secureDataSize += GetBigNumberSize(db.SecureIDs[i]); + SkipAlign(2 + GetBigNumberSize(secureDataSize), 4); + WriteByte(NID::kNtSecure); + WriteNumber(secureDataSize); + WriteByte(0); + WriteUInt32(db.SecureSizes.Size()); + for (i = 0; i < db.SecureSizes.Size(); i++) + WriteUInt32(db.SecureSizes[i]); + WriteBytes(db.SecureBuf, db.SecureBuf.Size()); + for (i = 0; i < db.SecureIDs.Size(); i++) + { + WriteNumber(db.SecureIDs[i]); + // WriteUInt32(db.SecureIDs[i]); + } + } + */ + WriteByte(NID::kEnd); // for files WriteByte(NID::kEnd); // for headers } HRESULT COutArchive::WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS - const CArchiveDatabase &db, + const CArchiveDatabaseOut &db, const CCompressionMethodMode *options, const CHeaderOptions &headerOptions) { @@ -773,17 +806,16 @@ HRESULT COutArchive::WriteDatabase( _countMode = encodeHeaders; _writeToStream = true; _countSize = 0; - WriteHeader(db, headerOptions, headerOffset); + WriteHeader(db, /* headerOptions, */ headerOffset); if (encodeHeaders) { - CByteBuffer buf; - buf.SetCapacity(_countSize); + CByteBuffer buf(_countSize); _outByte2.Init((Byte *)buf, _countSize); _countMode = false; _writeToStream = false; - WriteHeader(db, headerOptions, headerOffset); + WriteHeader(db, /* headerOptions, */ headerOffset); if (_countSize != _outByte2.GetPos()) return E_FAIL; @@ -794,10 +826,12 @@ HRESULT COutArchive::WriteDatabase( CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions); CRecordVector packSizes; CObjectVector folders; + COutFolders outFolders; + RINOK(EncodeStream( EXTERNAL_CODECS_LOC_VARS encoder, buf, - packSizes, folders)); + packSizes, folders, outFolders)); _writeToStream = true; @@ -805,11 +839,10 @@ HRESULT COutArchive::WriteDatabase( throw 1; WriteID(NID::kEncodedHeader); - WritePackInfo(headerOffset, packSizes, - CRecordVector(), CRecordVector()); - WriteUnpackInfo(folders); + WritePackInfo(headerOffset, packSizes, CUInt32DefVector()); + WriteUnpackInfo(folders, outFolders); WriteByte(NID::kEnd); - for (int i = 0; i < packSizes.Size(); i++) + FOR_VECTOR (i, packSizes) headerOffset += packSizes[i]; } RINOK(_outByte.Flush()); @@ -842,24 +875,28 @@ HRESULT COutArchive::WriteDatabase( } } -void CArchiveDatabase::GetFile(int index, CFileItem &file, CFileItem2 &file2) const +void CUInt64DefVector::SetItem(unsigned index, bool defined, UInt64 value) { - 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); + while (index >= Defs.Size()) + Defs.Add(false); + Defs[index] = defined; + if (!defined) + return; + while (index >= Vals.Size()) + Vals.Add(0); + Vals[index] = value; } -void CArchiveDatabase::AddFile(const CFileItem &file, const CFileItem2 &file2) +void CArchiveDatabaseOut::AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name) { - int index = Files.Size(); + unsigned index = Files.Size(); CTime.SetItem(index, file2.CTimeDefined, file2.CTime); ATime.SetItem(index, file2.ATimeDefined, file2.ATime); MTime.SetItem(index, file2.MTimeDefined, file2.MTime); StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos); - SetItemAnti(index, file2.IsAnti); + SetItem_Anti(index, file2.IsAnti); + // SetItem_Aux(index, file2.IsAux); + Names.Add(name); Files.Add(file); } diff --git a/CPP/7zip/Archive/7z/7zOut.h b/CPP/7zip/Archive/7z/7zOut.h old mode 100755 new mode 100644 index 7b1b528e..cead4bce --- a/CPP/7zip/Archive/7z/7zOut.h +++ b/CPP/7zip/Archive/7z/7zOut.h @@ -9,6 +9,7 @@ #include "7zItem.h" #include "../../Common/OutBuffer.h" +#include "../../Common/StreamUtils.h" namespace NArchive { namespace N7z { @@ -45,27 +46,191 @@ public: struct CHeaderOptions { bool CompressMainHeader; + /* bool WriteCTime; bool WriteATime; bool WriteMTime; + */ CHeaderOptions(): - CompressMainHeader(true), - WriteCTime(false), - WriteATime(false), - WriteMTime(true) + CompressMainHeader(true) + /* + , WriteCTime(false) + , WriteATime(false) + , WriteMTime(true) + */ {} }; + +struct CFileItem2 +{ + UInt64 CTime; + UInt64 ATime; + UInt64 MTime; + UInt64 StartPos; + bool CTimeDefined; + bool ATimeDefined; + bool MTimeDefined; + bool StartPosDefined; + bool IsAnti; + // bool IsAux; + + void Init() + { + CTimeDefined = false; + ATimeDefined = false; + MTimeDefined = false; + StartPosDefined = false; + IsAnti = false; + // IsAux = false; + } +}; + +struct COutFolders +{ + CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only. + + CRecordVector NumUnpackStreamsVector; + CRecordVector CoderUnpackSizes; // including unpack sizes of bind coders + + void OutFoldersClear() + { + FolderUnpackCRCs.Clear(); + NumUnpackStreamsVector.Clear(); + CoderUnpackSizes.Clear(); + } + + void OutFoldersReserveDown() + { + FolderUnpackCRCs.ReserveDown(); + NumUnpackStreamsVector.ReserveDown(); + CoderUnpackSizes.ReserveDown(); + } +}; + +struct CArchiveDatabaseOut: public COutFolders +{ + CRecordVector PackSizes; + CUInt32DefVector PackCRCs; + CObjectVector Folders; + + CRecordVector Files; + UStringVector Names; + CUInt64DefVector CTime; + CUInt64DefVector ATime; + CUInt64DefVector MTime; + CUInt64DefVector StartPos; + CRecordVector IsAnti; + + /* + CRecordVector IsAux; + + CByteBuffer SecureBuf; + CRecordVector SecureSizes; + CRecordVector SecureIDs; + + void ClearSecure() + { + SecureBuf.Free(); + SecureSizes.Clear(); + SecureIDs.Clear(); + } + */ + + void Clear() + { + OutFoldersClear(); + + PackSizes.Clear(); + PackCRCs.Clear(); + Folders.Clear(); + + Files.Clear(); + Names.Clear(); + CTime.Clear(); + ATime.Clear(); + MTime.Clear(); + StartPos.Clear(); + IsAnti.Clear(); + + /* + IsAux.Clear(); + ClearSecure(); + */ + } + + void ReserveDown() + { + OutFoldersReserveDown(); + + PackSizes.ReserveDown(); + PackCRCs.ReserveDown(); + Folders.ReserveDown(); + + Files.ReserveDown(); + Names.ReserveDown(); + CTime.ReserveDown(); + ATime.ReserveDown(); + MTime.ReserveDown(); + StartPos.ReserveDown(); + IsAnti.ReserveDown(); + + /* + IsAux.ReserveDown(); + */ + } + + bool IsEmpty() const + { + return ( + PackSizes.IsEmpty() && + NumUnpackStreamsVector.IsEmpty() && + Folders.IsEmpty() && + Files.IsEmpty()); + } + + bool CheckNumFiles() const + { + unsigned size = Files.Size(); + return ( + CTime.CheckSize(size) && + ATime.CheckSize(size) && + MTime.CheckSize(size) && + StartPos.CheckSize(size) && + (size == IsAnti.Size() || IsAnti.Size() == 0)); + } + + bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); } + // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); } + + void SetItem_Anti(unsigned index, bool isAnti) + { + while (index >= IsAnti.Size()) + IsAnti.Add(false); + IsAnti[index] = isAnti; + } + /* + void SetItem_Aux(unsigned index, bool isAux) + { + while (index >= IsAux.Size()) + IsAux.Add(false); + IsAux[index] = isAux; + } + */ + + void AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name); +}; + class COutArchive { UInt64 _prefixHeaderPos; - HRESULT WriteDirect(const void *data, UInt32 size); + HRESULT WriteDirect(const void *data, UInt32 size) { return WriteStream(SeqStream, data, size); } UInt64 GetPos() const; void WriteBytes(const void *data, size_t size); - void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.GetCapacity()); } + void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.Size()); } void WriteByte(Byte b); void WriteUInt32(UInt32 value); void WriteUInt64(UInt64 value); @@ -75,36 +240,36 @@ class COutArchive void WriteFolder(const CFolder &folder); HRESULT WriteFileHeader(const CFileItem &itemInfo); void WriteBoolVector(const CBoolVector &boolVector); - void WriteHashDigests( - const CRecordVector &digestsDefined, - const CRecordVector &hashDigests); + void WritePropBoolVector(Byte id, const CBoolVector &boolVector); + + void WriteHashDigests(const CUInt32DefVector &digests); void WritePackInfo( UInt64 dataOffset, const CRecordVector &packSizes, - const CRecordVector &packCRCsDefined, - const CRecordVector &packCRCs); + const CUInt32DefVector &packCRCs); - void WriteUnpackInfo(const CObjectVector &folders); + void WriteUnpackInfo( + const CObjectVector &folders, + const COutFolders &outFolders); void WriteSubStreamsInfo( const CObjectVector &folders, - const CRecordVector &numUnpackStreamsInFolders, + const COutFolders &outFolders, const CRecordVector &unpackSizes, - const CRecordVector &digestsDefined, - const CRecordVector &hashDigests); + const CUInt32DefVector &digests); void SkipAlign(unsigned pos, unsigned alignSize); - void WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize); + void WriteAlignedBoolHeader(const CBoolVector &v, unsigned 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); + CRecordVector &packSizes, CObjectVector &folders, COutFolders &outFolders); void WriteHeader( - const CArchiveDatabase &db, - const CHeaderOptions &headerOptions, + const CArchiveDatabaseOut &db, + // const CHeaderOptions &headerOptions, UInt64 &headerOffset); bool _countMode; @@ -118,6 +283,8 @@ class COutArchive bool _endMarker; #endif + bool _useAlign; + HRESULT WriteSignature(); #ifdef _7Z_VOL HRESULT WriteFinishSignature(); @@ -136,7 +303,7 @@ public: HRESULT SkipPrefixArchiveHeader(); HRESULT WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS - const CArchiveDatabase &db, + const CArchiveDatabaseOut &db, const CCompressionMethodMode *options, const CHeaderOptions &headerOptions); diff --git a/CPP/7zip/Archive/7z/7zProperties.cpp b/CPP/7zip/Archive/7z/7zProperties.cpp old mode 100755 new mode 100644 index fd4af49c..5ed36947 --- a/CPP/7zip/Archive/7z/7zProperties.cpp +++ b/CPP/7zip/Archive/7z/7zProperties.cpp @@ -17,7 +17,7 @@ struct CPropMap STATPROPSTG StatPROPSTG; }; -CPropMap kPropMap[] = +static const CPropMap kPropMap[] = { { NID::kName, { NULL, kpidPath, VT_BSTR } }, { NID::kSize, { NULL, kpidSize, VT_UI8 } }, @@ -34,11 +34,12 @@ CPropMap kPropMap[] = { 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::kWinAttrib, { NULL, kpidAttrib, VT_UI4 } }, { NID::kStartPos, { NULL, kpidPosition, VT_UI4 } }, { NID::kCRC, { NULL, kpidCRC, VT_UI4 } }, +// { NID::kIsAux, { NULL, kpidIsAux, VT_BOOL } }, { NID::kAnti, { NULL, kpidIsAnti, VT_BOOL } } #ifndef _SFX @@ -49,11 +50,9 @@ CPropMap kPropMap[] = #endif }; -static const int kPropMapSize = sizeof(kPropMap) / sizeof(kPropMap[0]); - static int FindPropInMap(UInt64 filePropID) { - for (int i = 0; i < kPropMapSize; i++) + for (int i = 0; i < ARRAY_SIZE(kPropMap); i++) if (kPropMap[i].FilePropID == filePropID) return i; return -1; @@ -62,7 +61,7 @@ static int FindPropInMap(UInt64 filePropID) static void CopyOneItem(CRecordVector &src, CRecordVector &dest, UInt32 item) { - for (int i = 0; i < src.Size(); i++) + FOR_VECTOR (i, src) if (src[i] == item) { dest.Add(item); @@ -73,7 +72,7 @@ static void CopyOneItem(CRecordVector &src, static void RemoveOneItem(CRecordVector &src, UInt32 item) { - for (int i = 0; i < src.Size(); i++) + FOR_VECTOR (i, src) if (src[i] == item) { src.Delete(i); @@ -83,7 +82,7 @@ static void RemoveOneItem(CRecordVector &src, UInt32 item) static void InsertToHead(CRecordVector &dest, UInt32 item) { - for (int i = 0; i < dest.Size(); i++) + FOR_VECTOR (i, dest) if (dest[i] == item) { dest.Delete(i); @@ -92,6 +91,8 @@ static void InsertToHead(CRecordVector &dest, UInt32 item) dest.Insert(0, item); } +#define COPY_ONE_ITEM(id) CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::id); + void CHandler::FillPopIDs() { _fileInfoPopIDs.Clear(); @@ -103,21 +104,26 @@ void CHandler::FillPopIDs() const CArchiveDatabaseEx &_db = volume.Database; #endif - CRecordVector fileInfoPopIDs = _db.ArchiveInfo.FileInfoPopIDs; + CRecordVector fileInfoPopIDs = _db.ArcInfo.FileInfoPopIDs; RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream); RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile); + /* + RemoveOneItem(fileInfoPopIDs, NID::kParent); + RemoveOneItem(fileInfoPopIDs, NID::kNtSecure); + */ + + COPY_ONE_ITEM(kName); + COPY_ONE_ITEM(kAnti); + COPY_ONE_ITEM(kSize); + COPY_ONE_ITEM(kPackInfo); + COPY_ONE_ITEM(kCTime); + COPY_ONE_ITEM(kMTime); + COPY_ONE_ITEM(kATime); + COPY_ONE_ITEM(kWinAttrib); + COPY_ONE_ITEM(kCRC); + COPY_ONE_ITEM(kComment); - 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 @@ -141,9 +147,9 @@ void CHandler::FillPopIDs() #endif } -STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) +STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) { - *numProperties = _fileInfoPopIDs.Size(); + *numProps = _fileInfoPopIDs.Size(); return S_OK; } diff --git a/CPP/7zip/Archive/7z/7zProperties.h b/CPP/7zip/Archive/7z/7zProperties.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/7z/7zRegister.cpp b/CPP/7zip/Archive/7z/7zRegister.cpp old mode 100755 new mode 100644 index 6e9bf6b9..37ea29d3 --- a/CPP/7zip/Archive/7z/7zRegister.cpp +++ b/CPP/7zip/Archive/7z/7zRegister.cpp @@ -5,14 +5,21 @@ #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 + +namespace NArchive { +namespace N7z { + +IMP_CreateArcIn +IMP_CreateArcOut static CArcInfo g_ArcInfo = - { L"7z", L"7z", 0, 7, {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}, 6, false, CreateArc, CreateArcOut }; + { "7z", "7z", 0, 7, + 6, {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C}, + 0, + NArcInfoFlags::kFindSignature, + REF_CreateArc_Pair }; + +REGISTER_ARC_DEC_SIG(7z) +// REGISTER_ARC(7z) -REGISTER_ARC(7z) +}} diff --git a/CPP/7zip/Archive/7z/7zSpecStream.cpp b/CPP/7zip/Archive/7z/7zSpecStream.cpp old mode 100755 new mode 100644 index 06969636..8e45d987 --- a/CPP/7zip/Archive/7z/7zSpecStream.cpp +++ b/CPP/7zip/Archive/7z/7zSpecStream.cpp @@ -9,16 +9,14 @@ STDMETHODIMP CSequentialInStreamSizeCount2::Read(void *data, UInt32 size, UInt32 UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; - if (processedSize != 0) + if (processedSize) *processedSize = realProcessedSize; return result; } -STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize( - UInt64 subStream, UInt64 *value) +STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize(UInt64 subStream, UInt64 *value) { - if (_getSubStreamSize == NULL) + if (!_getSubStreamSize) return E_NOTIMPL; - return _getSubStreamSize->GetSubStreamSize(subStream, value); + return _getSubStreamSize->GetSubStreamSize(subStream, value); } - diff --git a/CPP/7zip/Archive/7z/7zSpecStream.h b/CPP/7zip/Archive/7z/7zSpecStream.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp old mode 100755 new mode 100644 index e63b09d2..96befa23 --- a/CPP/7zip/Archive/7z/7zUpdate.cpp +++ b/CPP/7zip/Archive/7z/7zUpdate.cpp @@ -4,10 +4,11 @@ #include "../../../../C/CpuArch.h" -#include "../../Common/LimitedStreams.h" -#include "../../Common/ProgressUtils.h" +#include "../../../Common/Wildcard.h" #include "../../Common/CreateCoder.h" +#include "../../Common/LimitedStreams.h" +#include "../../Common/ProgressUtils.h" #include "../../Compress/CopyCoder.h" @@ -58,19 +59,20 @@ int CUpdateItem::GetExtensionPos() const int slashPos = GetReverseSlashPos(Name); int dotPos = Name.ReverseFind(L'.'); if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0)) - return Name.Length(); + return Name.Len(); return dotPos + 1; } UString CUpdateItem::GetExtension() const { - return Name.Mid(GetExtensionPos()); + return Name.Ptr(GetExtensionPos()); } #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } #define RINOZ_COMP(a, b) RINOZ(MyCompare(a, b)) +/* static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2) { size_t c1 = a1.GetCapacity(); @@ -110,11 +112,12 @@ static int CompareFolders(const CFolder &f1, const CFolder &f2) 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); + return CompareFileNames(f1.Name, f2.Name); } */ @@ -125,15 +128,19 @@ struct CFolderRepack CNum NumCopyFiles; }; -static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void *param) +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; + /* + // In that version we don't want to parse folders here, so we don't compare folders + // probably it must be improved in future + const CDbEx &db = *(const CDbEx *)param; RINOZ(CompareFolders( db.Folders[i1], db.Folders[i2])); + */ return MyCompare(i1, i2); /* RINOZ_COMP( @@ -147,25 +154,31 @@ static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2 */ } -//////////////////////////////////////////////////////////// +/* + we sort empty files and dirs in such order: + - Dir.NonAnti (name sorted) + - File.NonAnti (name sorted) + - File.Anti (name sorted) + - Dir.Anti (reverse name sorted) +*/ static int CompareEmptyItems(const int *p1, const int *p2, void *param) { const CObjectVector &updateItems = *(const CObjectVector *)param; const CUpdateItem &u1 = updateItems[*p1]; const CUpdateItem &u2 = updateItems[*p2]; + // NonAnti < Anti + if (u1.IsAnti != u2.IsAnti) + return (u1.IsAnti ? 1 : -1); if (u1.IsDir != u2.IsDir) - return (u1.IsDir) ? 1 : -1; - if (u1.IsDir) { - if (u1.IsAnti != u2.IsAnti) + // Dir.NonAnti < File < Dir.Anti + if (u1.IsDir) return (u1.IsAnti ? 1 : -1); - int n = MyStringCompareNoCase(u1.Name, u2.Name); - return -n; + return (u2.IsAnti ? -1 : 1); } - if (u1.IsAnti != u2.IsAnti) - return (u1.IsAnti ? 1 : -1); - return MyStringCompareNoCase(u1.Name, u2.Name); + int n = CompareFileNames(u1.Name, u2.Name); + return (u1.IsDir && u1.IsAnti) ? -n : n; } static const char *g_Exts = @@ -198,7 +211,7 @@ static const char *g_Exts = " exe dll ocx vbx sfx sys tlb awx com obj lib out o so " " pdb pch idb ncb opt"; -int GetExtIndex(const char *ext) +static int GetExtIndex(const char *ext) { int extIndex = 1; const char *p = g_Exts; @@ -237,7 +250,9 @@ struct CRefItem UInt32 Index; UInt32 ExtensionPos; UInt32 NamePos; - int ExtensionIndex; + unsigned ExtensionIndex; + + CRefItem() {}; CRefItem(UInt32 index, const CUpdateItem &ui, bool sortByType): UpdateItem(&ui), Index(index), @@ -248,64 +263,134 @@ struct CRefItem if (sortByType) { int slashPos = GetReverseSlashPos(ui.Name); - NamePos = ((slashPos >= 0) ? (slashPos + 1) : 0); + NamePos = slashPos + 1; int dotPos = ui.Name.ReverseFind(L'.'); - if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0)) - ExtensionPos = ui.Name.Length(); + if (dotPos < 0 || dotPos < slashPos) + ExtensionPos = ui.Name.Len(); else { ExtensionPos = dotPos + 1; - UString us = ui.Name.Mid(ExtensionPos); - if (!us.IsEmpty()) + if (ExtensionPos != ui.Name.Len()) { - us.MakeLower(); - int i; AString s; - for (i = 0; i < us.Length(); i++) + for (unsigned pos = ExtensionPos;; pos++) { - wchar_t c = us[i]; + wchar_t c = ui.Name[pos]; if (c >= 0x80) break; - s += (char)c; + if (c == 0) + { + ExtensionIndex = GetExtIndex(s); + break; + } + s += (char)MyCharLower_Ascii((char)c); } - if (i == us.Length()) - ExtensionIndex = GetExtIndex(s); - else - ExtensionIndex = 0; } } } } }; +struct CSortParam +{ + // const CObjectVector *TreeFolders; + bool SortByType; +}; + +/* + we sort files in such order: + - Dir.NonAnti (name sorted) + - alt streams + - Dirs + - Dir.Anti (reverse name sorted) +*/ + + static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param) { const CRefItem &a1 = *p1; const CRefItem &a2 = *p2; const CUpdateItem &u1 = *a1.UpdateItem; const CUpdateItem &u2 = *a2.UpdateItem; - int n; + + /* + if (u1.IsAltStream != u2.IsAltStream) + return u1.IsAltStream ? 1 : -1; + */ + + // Actually there are no dirs that time. They were stored in other steps + // So that code is unused? if (u1.IsDir != u2.IsDir) - return (u1.IsDir) ? 1 : -1; + return u1.IsDir ? 1 : -1; if (u1.IsDir) { if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); - n = MyStringCompareNoCase(u1.Name, u2.Name); + int n = CompareFileNames(u1.Name, u2.Name); return -n; } - bool sortByType = *(bool *)param; + + // bool sortByType = *(bool *)param; + const CSortParam *sortParam = (const CSortParam *)param; + bool sortByType = sortParam->SortByType; 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)); + RINOZ(CompareFileNames(u1.Name.Ptr(a1.ExtensionPos), u2.Name.Ptr(a2.ExtensionPos))); + RINOZ(CompareFileNames(u1.Name.Ptr(a1.NamePos), u2.Name.Ptr(a2.NamePos))); if (!u1.MTimeDefined && u2.MTimeDefined) return 1; if (u1.MTimeDefined && !u2.MTimeDefined) return -1; if (u1.MTimeDefined && u2.MTimeDefined) RINOZ_COMP(u1.MTime, u2.MTime); RINOZ_COMP(u1.Size, u2.Size); } - return MyStringCompareNoCase(u1.Name, u2.Name); + /* + int par1 = a1.UpdateItem->ParentFolderIndex; + int par2 = a2.UpdateItem->ParentFolderIndex; + const CTreeFolder &tf1 = (*sortParam->TreeFolders)[par1]; + const CTreeFolder &tf2 = (*sortParam->TreeFolders)[par2]; + + int b1 = tf1.SortIndex, e1 = tf1.SortIndexEnd; + int b2 = tf2.SortIndex, e2 = tf2.SortIndexEnd; + if (b1 < b2) + { + if (e1 <= b2) + return -1; + // p2 in p1 + int par = par2; + for (;;) + { + const CTreeFolder &tf = (*sortParam->TreeFolders)[par]; + par = tf.Parent; + if (par == par1) + { + RINOZ(CompareFileNames(u1.Name, tf.Name)); + break; + } + } + } + else if (b2 < b1) + { + if (e2 <= b1) + return 1; + // p1 in p2 + int par = par1; + for (;;) + { + const CTreeFolder &tf = (*sortParam->TreeFolders)[par]; + par = tf.Parent; + if (par == par2) + { + RINOZ(CompareFileNames(tf.Name, u2.Name)); + break; + } + } + } + */ + // RINOZ_COMP(a1.UpdateItem->ParentSortIndex, a2.UpdateItem->ParentSortIndex); + RINOK(CompareFileNames(u1.Name, u2.Name)); + RINOZ_COMP(a1.UpdateItem->IndexInClient, a2.UpdateItem->IndexInClient); + RINOZ_COMP(a1.UpdateItem->IndexInArchive, a2.UpdateItem->IndexInArchive); + return 0; } struct CSolidGroup @@ -313,19 +398,19 @@ struct CSolidGroup CRecordVector Indices; }; -static wchar_t *g_ExeExts[] = +static const wchar_t *g_ExeExts[] = { - L"dll", - L"exe", - L"ocx", - L"sfx", - L"sys" + L"dll" + , L"exe" + , L"ocx" + , L"sfx" + , L"sys" }; -static bool IsExeExt(const UString &ext) +static bool IsExeExt(const wchar_t *ext) { - for (int i = 0; i < sizeof(g_ExeExts) / sizeof(g_ExeExts[0]); i++) - if (ext.CompareNoCase(g_ExeExts[i]) == 0) + for (int i = 0; i < ARRAY_SIZE(g_ExeExts); i++) + if (MyStringCompareNoCase(ext, g_ExeExts[i]) == 0) return true; return false; } @@ -402,7 +487,6 @@ static void MakeExeMethod(CCompressionMethodMode &mode, static void FromUpdateItemToFileItem(const CUpdateItem &ui, CFileItem &file, CFileItem2 &file2) { - file.Name = NItemName::MakeLegalName(ui.Name); if (ui.AttribDefined) file.SetAttrib(ui.Attrib); @@ -410,11 +494,13 @@ static void FromUpdateItemToFileItem(const CUpdateItem &ui, file2.ATime = ui.ATime; file2.ATimeDefined = ui.ATimeDefined; file2.MTime = ui.MTime; file2.MTimeDefined = ui.MTimeDefined; file2.IsAnti = ui.IsAnti; + // file2.IsAux = false; file2.StartPosDefined = false; file.Size = ui.Size; file.IsDir = ui.IsDir; file.HasStream = ui.HasStream(); + // file.IsAltStream = ui.IsAltStream; } class CFolderOutStream2: @@ -423,11 +509,11 @@ class CFolderOutStream2: { COutStreamWithCRC *_crcStreamSpec; CMyComPtr _crcStream; - const CArchiveDatabaseEx *_db; + const CDbEx *_db; const CBoolVector *_extractStatuses; CMyComPtr _outStream; UInt32 _startIndex; - int _currentIndex; + unsigned _currentIndex; bool _fileIsOpen; UInt64 _rem; @@ -444,7 +530,7 @@ public: _crcStream = _crcStreamSpec; } - HRESULT Init(const CArchiveDatabaseEx *db, UInt32 startIndex, + HRESULT Init(const CDbEx *db, UInt32 startIndex, const CBoolVector *extractStatuses, ISequentialOutStream *outStream); void ReleaseOutStream(); HRESULT CheckFinishedState() const { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; } @@ -452,7 +538,7 @@ public: STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; -HRESULT CFolderOutStream2::Init(const CArchiveDatabaseEx *db, UInt32 startIndex, +HRESULT CFolderOutStream2::Init(const CDbEx *db, UInt32 startIndex, const CBoolVector *extractStatuses, ISequentialOutStream *outStream) { _db = db; @@ -551,13 +637,13 @@ public: CMyComPtr Fos; UInt64 StartPos; - const UInt64 *PackSizes; - const CFolder *Folder; + const CFolders *Folders; + int FolderIndex; #ifndef _NO_CRYPTO - CMyComPtr GetTextPassword; + CMyComPtr getTextPassword; #endif - DECL_EXTERNAL_CODECS_VARS + DECL_EXTERNAL_CODECS_LOC_VARS2; CDecoder Decoder; #ifndef _7ZIP_ST @@ -585,21 +671,20 @@ void CThreadDecoder::Execute() try { #ifndef _NO_CRYPTO - bool passwordIsDefined; + bool isEncrypted = false; + bool passwordIsDefined = false; #endif + Result = Decoder.Decode( - EXTERNAL_CODECS_VARS + EXTERNAL_CODECS_LOC_VARS InStream, StartPos, - PackSizes, - *Folder, + *Folders, FolderIndex, Fos, NULL - #ifndef _NO_CRYPTO - , GetTextPassword, passwordIsDefined - #endif + _7Z_DECODER_CRYPRO_VARS #ifndef _7ZIP_ST - , MtMode, NumThreads + , MtMode, NumThreads #endif ); } @@ -614,7 +699,7 @@ void CThreadDecoder::Execute() bool static Is86FilteredFolder(const CFolder &f) { - for (int i = 0; i < f.Coders.Size(); i++) + FOR_VECTOR(i, f.Coders) { CMethodId m = f.Coders[i].MethodID; if (m == k_BCJ || m == k_BCJ2) @@ -650,13 +735,26 @@ static bool IsEncryptedGroup(int group) { return (group & 2) != 0; } static int GetGroupIndex(bool encrypted, int bcjFiltered) { return (encrypted ? 2 : 0) + (bcjFiltered ? 1 : 0); } +static void GetFile(const CDatabase &inDb, int index, CFileItem &file, CFileItem2 &file2) +{ + file = inDb.Files[index]; + file2.CTimeDefined = inDb.CTime.GetItem(index, file2.CTime); + file2.ATimeDefined = inDb.ATime.GetItem(index, file2.ATime); + file2.MTimeDefined = inDb.MTime.GetItem(index, file2.MTime); + file2.StartPosDefined = inDb.StartPos.GetItem(index, file2.StartPos); + file2.IsAnti = inDb.IsItemAnti(index); + // file2.IsAux = inDb.IsItemAux(index); +} + HRESULT Update( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, - const CArchiveDatabaseEx *db, + const CDbEx *db, const CObjectVector &updateItems, + // const CObjectVector &treeFolders, + // const CUniqBlocks &secureBlocks, COutArchive &archive, - CArchiveDatabase &newDatabase, + CArchiveDatabaseOut &newDatabase, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options @@ -668,6 +766,9 @@ HRESULT Update( UInt64 numSolidFiles = options.NumSolidFiles; if (numSolidFiles == 0) numSolidFiles = 1; + + // size_t totalSecureDataSize = (size_t)secureBlocks.GetTotalSizeInBytes(); + /* CMyComPtr outStream; RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream)); @@ -675,23 +776,23 @@ HRESULT Update( return E_NOTIMPL; */ - UInt64 startBlockSize = db != 0 ? db->ArchiveInfo.StartPosition: 0; + UInt64 startBlockSize = db != 0 ? db->ArcInfo.StartPosition: 0; if (startBlockSize > 0 && !options.RemoveSfxBlock) { RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL)); } - CRecordVector fileIndexToUpdateIndexMap; + CIntArr fileIndexToUpdateIndexMap; CRecordVector folderRefs; UInt64 complexity = 0; UInt64 inSizeForReduce2 = 0; bool needEncryptedRepack = false; if (db != 0) { - fileIndexToUpdateIndexMap.Reserve(db->Files.Size()); - int i; + fileIndexToUpdateIndexMap.Alloc(db->Files.Size()); + unsigned i; for (i = 0; i < db->Files.Size(); i++) - fileIndexToUpdateIndexMap.Add(-1); + fileIndexToUpdateIndexMap[i] = -1; for (i = 0; i < updateItems.Size(); i++) { @@ -700,7 +801,7 @@ HRESULT Update( fileIndexToUpdateIndexMap[index] = i; } - for (i = 0; i < db->Folders.Size(); i++) + for (i = 0; i < (int)db->NumFolders; i++) { CNum indexInFolder = 0; CNum numCopyItems = 0; @@ -727,7 +828,8 @@ HRESULT Update( CFolderRepack rep; rep.FolderIndex = i; rep.NumCopyFiles = numCopyItems; - const CFolder &f = db->Folders[i]; + CFolder f; + db->ParseFolderInfo(i, f); bool isEncrypted = f.IsEncrypted(); rep.Group = GetGroupIndex(isEncrypted, Is86FilteredFolder(f)); folderRefs.Add(rep); @@ -746,7 +848,7 @@ HRESULT Update( } UInt64 inSizeForReduce = 0; - int i; + unsigned i; for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; @@ -776,18 +878,17 @@ HRESULT Update( if (!folderRefs.IsEmpty()) { #ifdef EXTERNAL_CODECS - threadDecoder._codecsInfo = codecsInfo; - threadDecoder._externalCodecs = *externalCodecs; + threadDecoder.__externalCodecs = __externalCodecs; #endif RINOK(threadDecoder.Create()); } CObjectVector groups; for (i = 0; i < kNumGroupsMax; i++) - groups.Add(CSolidGroup()); + groups.AddNew(); { - // ---------- Split files to 2 groups ---------- + // ---------- Split files to groups ---------- bool useFilters = options.UseFilters; const CCompressionMethodMode &method = *options.Method; @@ -803,7 +904,7 @@ HRESULT Update( { int dotPos = ui.Name.ReverseFind(L'.'); if (dotPos >= 0) - filteredGroup = IsExeExt(ui.Name.Mid(dotPos + 1)); + filteredGroup = IsExeExt(ui.Name.Ptr(dotPos + 1)); } groups[GetGroupIndex(method.PasswordIsDefined, filteredGroup)].Indices.Add(i); } @@ -815,7 +916,7 @@ HRESULT Update( if (needEncryptedRepack) { getPasswordSpec = new CCryptoGetTextPassword; - threadDecoder.GetTextPassword = getPasswordSpec; + threadDecoder.getTextPassword = getPasswordSpec; if (options.Method->PasswordIsDefined) getPasswordSpec->Password = options.Method->Password; @@ -825,18 +926,111 @@ HRESULT Update( return E_NOTIMPL; CMyComBSTR password; RINOK(getDecoderPassword->CryptoGetTextPassword(&password)); - getPasswordSpec->Password = password; + if ((BSTR)password) + getPasswordSpec->Password = password; } } #endif + // ---------- Compress ---------- RINOK(archive.Create(seqOutStream, false)); RINOK(archive.SkipPrefixArchiveHeader()); - int folderRefIndex = 0; + /* + CIntVector treeFolderToArcIndex; + treeFolderToArcIndex.Reserve(treeFolders.Size()); + for (i = 0; i < treeFolders.Size(); i++) + treeFolderToArcIndex.Add(-1); + // ---------- Write Tree (only AUX dirs) ---------- + for (i = 1; i < treeFolders.Size(); i++) + { + const CTreeFolder &treeFolder = treeFolders[i]; + CFileItem file; + CFileItem2 file2; + file2.Init(); + int secureID = 0; + if (treeFolder.UpdateItemIndex < 0) + { + // we can store virtual dir item wuthout attrib, but we want all items have attrib. + file.SetAttrib(FILE_ATTRIBUTE_DIRECTORY); + file2.IsAux = true; + } + else + { + const CUpdateItem &ui = updateItems[treeFolder.UpdateItemIndex]; + // if item is not dir, then it's parent for alt streams. + // we will write such items later + if (!ui.IsDir) + continue; + secureID = ui.SecureIndex; + if (ui.NewProps) + FromUpdateItemToFileItem(ui, file, file2); + else + GetFile(*db, ui.IndexInArchive, file, file2); + } + file.Size = 0; + file.HasStream = false; + file.IsDir = true; + file.Parent = treeFolder.Parent; + + treeFolderToArcIndex[i] = newDatabase.Files.Size(); + newDatabase.AddFile(file, file2, treeFolder.Name); + + if (totalSecureDataSize != 0) + newDatabase.SecureIDs.Add(secureID); + } + */ + + { + /* ---------- Write non-AUX dirs and Empty files ---------- */ + 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; + /* + if (ui.TreeFolderIndex >= 0) + continue; + */ + emptyRefs.Add(i); + } + emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems); + for (i = 0; i < emptyRefs.Size(); i++) + { + const CUpdateItem &ui = updateItems[emptyRefs[i]]; + CFileItem file; + CFileItem2 file2; + UString name; + if (ui.NewProps) + { + FromUpdateItemToFileItem(ui, file, file2); + name = ui.Name; + } + else + { + GetFile(*db, ui.IndexInArchive, file, file2); + name = db->GetName(ui.IndexInArchive); + } + + /* + if (totalSecureDataSize != 0) + newDatabase.SecureIDs.Add(ui.SecureIndex); + file.Parent = ui.ParentFolderIndex; + */ + newDatabase.AddFile(file, file2, name); + } + } + + unsigned folderRefIndex = 0; lps->ProgressOffset = 0; for (int groupIndex = 0; groupIndex < kNumGroupsMax; groupIndex++) @@ -879,15 +1073,20 @@ HRESULT Update( 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++) + CFolder &folder = newDatabase.Folders.AddNew(); + db->ParseFolderInfo(folderIndex, folder); + CNum startIndex = db->FoStartPackStreamIndex[folderIndex]; + for (unsigned j = 0; j < folder.PackStreams.Size(); j++) { - newDatabase.PackSizes.Add(db->PackSizes[startIndex + j]); + newDatabase.PackSizes.Add(db->GetStreamPackSize(startIndex + j)); // newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]); // newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]); } - newDatabase.Folders.Add(folder); + + UInt32 indexStart = db->FoToCoderUnpackSizes[folderIndex]; + UInt32 indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1]; + for (; indexStart < indexEnd; indexStart++) + newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes[indexStart]); } else { @@ -909,8 +1108,8 @@ HRESULT Update( extractStatuses.Add(needExtract); } - int startPackIndex = newDatabase.PackSizes.Size(); - CFolder newFolder; + unsigned startPackIndex = newDatabase.PackSizes.Size(); + UInt64 curUnpackSize; { CMyComPtr sbInStream; { @@ -921,16 +1120,17 @@ HRESULT Update( } threadDecoder.InStream = inStream; - threadDecoder.Folder = &db->Folders[folderIndex]; - threadDecoder.StartPos = db->GetFolderStreamPos(folderIndex, 0); - threadDecoder.PackSizes = &db->PackSizes[db->FolderStartPackStreamIndex[folderIndex]]; + threadDecoder.Folders = (const CFolders *)db; + threadDecoder.FolderIndex = folderIndex; + threadDecoder.StartPos = db->ArcInfo.DataStartPosition; // db->GetFolderStreamPos(folderIndex, 0); threadDecoder.Start(); RINOK(encoder.Encode( - EXTERNAL_CODECS_LOC_VARS - sbInStream, NULL, &inSizeForReduce, newFolder, - archive.SeqStream, newDatabase.PackSizes, progress)); + EXTERNAL_CODECS_LOC_VARS + sbInStream, NULL, &inSizeForReduce, + newDatabase.Folders.AddNew(), newDatabase.CoderUnpackSizes, curUnpackSize, + archive.SeqStream, newDatabase.PackSizes, progress)); threadDecoder.WaitExecuteFinish(); } @@ -939,9 +1139,7 @@ HRESULT Update( for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) lps->OutSize += newDatabase.PackSizes[startPackIndex]; - lps->InSize += newFolder.GetUnpackSize(); - - newDatabase.Folders.Add(newFolder); + lps->InSize += curUnpackSize; } newDatabase.NumUnpackStreamsVector.Add(rep.NumCopyFiles); @@ -953,7 +1151,8 @@ HRESULT Update( { CFileItem file; CFileItem2 file2; - db->GetFile(fi, file, file2); + GetFile(*db, fi, file, file2); + UString name = db->GetName(fi); if (file.HasStream) { indexInFolder++; @@ -972,30 +1171,40 @@ HRESULT Update( uf.CrcDefined = file.CrcDefined; uf.HasStream = file.HasStream; file = uf; + name = ui.Name; } - newDatabase.AddFile(file, file2); + /* + file.Parent = ui.ParentFolderIndex; + if (ui.TreeFolderIndex >= 0) + treeFolderToArcIndex[ui.TreeFolderIndex] = newDatabase.Files.Size(); + if (totalSecureDataSize != 0) + newDatabase.SecureIDs.Add(ui.SecureIndex); + */ + newDatabase.AddFile(file, file2, name); } } } } - int numFiles = group.Indices.Size(); + unsigned numFiles = group.Indices.Size(); if (numFiles == 0) continue; CRecordVector refItems; - refItems.Reserve(numFiles); + refItems.ClearAndSetSize(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); + refItems[i] = CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType); + CSortParam sortParam; + // sortParam.TreeFolders = &treeFolders; + sortParam.SortByType = sortByType; + refItems.Sort(CompareUpdateItems, (void *)&sortParam); - CRecordVector indices; - indices.Reserve(numFiles); + CObjArray indices(numFiles); for (i = 0; i < numFiles; i++) { UInt32 index = refItems[i].Index; - indices.Add(index); + indices[i] = index; /* const CUpdateItem &ui = updateItems[index]; CFileItem file; @@ -1027,7 +1236,7 @@ HRESULT Update( if (numSubFiles == 0) prevExtension = ext; else - if (ext.CompareNoCase(prevExtension) != 0) + if (!ext.IsEqualToNoCase(prevExtension)) break; } } @@ -1038,34 +1247,39 @@ HRESULT Update( CMyComPtr solidInStream(inStreamSpec); inStreamSpec->Init(updateCallback, &indices[i], numSubFiles); - CFolder folderItem; - - int startPackIndex = newDatabase.PackSizes.Size(); + unsigned startPackIndex = newDatabase.PackSizes.Size(); + UInt64 curFolderUnpackSize; RINOK(encoder.Encode( EXTERNAL_CODECS_LOC_VARS - solidInStream, NULL, &inSizeForReduce, folderItem, + solidInStream, NULL, &inSizeForReduce, + newDatabase.Folders.AddNew(), newDatabase.CoderUnpackSizes, curFolderUnpackSize, archive.SeqStream, newDatabase.PackSizes, progress)); for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) lps->OutSize += newDatabase.PackSizes[startPackIndex]; - lps->InSize += folderItem.GetUnpackSize(); + lps->InSize += curFolderUnpackSize; // 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; + UString name; if (ui.NewProps) + { FromUpdateItemToFileItem(ui, file, file2); + name = ui.Name; + } else - db->GetFile(ui.IndexInArchive, file, file2); + { + GetFile(*db, ui.IndexInArchive, file, file2); + name = db->GetName(ui.IndexInArchive); + } if (file2.IsAnti || file.IsDir) return E_FAIL; @@ -1092,7 +1306,14 @@ HRESULT Update( file.CrcDefined = false; file.HasStream = false; } - newDatabase.AddFile(file, file2); + /* + file.Parent = ui.ParentFolderIndex; + if (ui.TreeFolderIndex >= 0) + treeFolderToArcIndex[ui.TreeFolderIndex] = newDatabase.Files.Size(); + if (totalSecureDataSize != 0) + newDatabase.SecureIDs.Add(ui.SecureIndex); + */ + newDatabase.AddFile(file, file2, name); } // numUnpackStreams = 0 is very bad case for locked files // v3.13 doesn't understand it. @@ -1112,36 +1333,28 @@ HRESULT Update( groups.ClearAndFree(); */ + /* + for (i = 0; i < newDatabase.Files.Size(); i++) { - // ---------- 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++) + CFileItem &file = newDatabase.Files[i]; + file.Parent = treeFolderToArcIndex[file.Parent]; + } + + if (totalSecureDataSize != 0) + { + newDatabase.SecureBuf.SetCapacity(totalSecureDataSize); + size_t pos = 0; + newDatabase.SecureSizes.Reserve(secureBlocks.Sorted.Size()); + for (i = 0; i < secureBlocks.Sorted.Size(); i++) { - const 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); + const CByteBuffer &buf = secureBlocks.Bufs[secureBlocks.Sorted[i]]; + size_t size = buf.GetCapacity(); + memcpy(newDatabase.SecureBuf + pos, buf, size); + newDatabase.SecureSizes.Add((UInt32)size); + pos += size; } } - + */ newDatabase.ReserveDown(); return S_OK; } diff --git a/CPP/7zip/Archive/7z/7zUpdate.h b/CPP/7zip/Archive/7z/7zUpdate.h old mode 100755 new mode 100644 index 31e36224..d00276e0 --- a/CPP/7zip/Archive/7z/7zUpdate.h +++ b/CPP/7zip/Archive/7z/7zUpdate.h @@ -3,15 +3,31 @@ #ifndef __7Z_UPDATE_H #define __7Z_UPDATE_H +#include "../IArchive.h" + +// #include "../../Common/UniqBlocks.h" + #include "7zCompressionMode.h" #include "7zIn.h" #include "7zOut.h" -#include "../IArchive.h" - namespace NArchive { namespace N7z { +/* +struct CTreeFolder +{ + UString Name; + int Parent; + CIntVector SubFolders; + int UpdateItemIndex; + int SortIndex; + int SortIndexEnd; + + CTreeFolder(): UpdateItemIndex(-1) {} +}; +*/ + struct CUpdateItem { int IndexInArchive; @@ -23,6 +39,15 @@ struct CUpdateItem UInt64 Size; UString Name; + /* + bool IsAltStream; + int ParentFolderIndex; + int TreeFolderIndex; + */ + + // that code is not used in 9.26 + // int ParentSortIndex; + // int ParentSortIndexEnd; UInt32 Attrib; @@ -37,15 +62,20 @@ struct CUpdateItem bool ATimeDefined; bool MTimeDefined; + // int SecureIndex; // 0 means (no_security) + bool HasStream() const { return !IsDir && !IsAnti && Size != 0; } CUpdateItem(): + // ParentSortIndex(-1), + // IsAltStream(false), IsAnti(false), IsDir(false), AttribDefined(false), CTimeDefined(false), ATimeDefined(false), MTimeDefined(false) + // SecureIndex(0) {} void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); }; @@ -72,10 +102,12 @@ struct CUpdateOptions HRESULT Update( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, - const CArchiveDatabaseEx *db, + const CDbEx *db, const CObjectVector &updateItems, + // const CObjectVector &treeFolders, // treeFolders[0] is root + // const CUniqBlocks &secureBlocks, COutArchive &archive, - CArchiveDatabase &newDatabase, + CArchiveDatabaseOut &newDatabase, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options diff --git a/CPP/7zip/Archive/7z/StdAfx.cpp b/CPP/7zip/Archive/7z/StdAfx.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/7z/StdAfx.h b/CPP/7zip/Archive/7z/StdAfx.h old mode 100755 new mode 100644 index 2e4be10b..2854ff3e --- a/CPP/7zip/Archive/7z/StdAfx.h +++ b/CPP/7zip/Archive/7z/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" -#include "../../../Common/NewHandler.h" +#include "../../../Common/Common.h" #endif diff --git a/CPP/7zip/Archive/7z/makefile b/CPP/7zip/Archive/7z/makefile old mode 100755 new mode 100644 index 0abb3756..19982112 --- a/CPP/7zip/Archive/7z/makefile +++ b/CPP/7zip/Archive/7z/makefile @@ -1,6 +1,6 @@ PROG = 7z.dll -DEF_FILE = ../Archive.def -CFLAGS = $(CFLAGS) -I ../../../ \ +DEF_FILE = ../../Archive/Archive2.def +CFLAGS = $(CFLAGS) \ -DEXTERNAL_CODECS \ AR_OBJS = \ @@ -32,12 +32,14 @@ COMMON_OBJS = \ $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\Synchronization.obj \ $O\System.obj \ @@ -52,6 +54,7 @@ WIN_OBJS = \ $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ + $O\PropId.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ @@ -73,38 +76,4 @@ C_OBJS = \ $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" +!include "../../7zip.mak" diff --git a/CPP/7zip/Archive/7z/resource.rc b/CPP/7zip/Archive/7z/resource.rc old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/ApmHandler.cpp b/CPP/7zip/Archive/ApmHandler.cpp old mode 100755 new mode 100644 index a3b5e19b..04cd06fa --- a/CPP/7zip/Archive/ApmHandler.cpp +++ b/CPP/7zip/Archive/ApmHandler.cpp @@ -4,11 +4,12 @@ #include "../../../C/CpuArch.h" -#include "Common/ComTry.h" -#include "Common/IntToString.h" -#include "Common/MyString.h" +#include "../../Common/ComTry.h" +#include "../../Common/Defs.h" +#include "../../Common/IntToString.h" +#include "../../Common/MyString.h" -#include "Windows/PropVariant.h" +#include "../../Windows/PropVariant.h" #include "../Common/LimitedStreams.h" #include "../Common/ProgressUtils.h" @@ -25,6 +26,9 @@ using namespace NWindows; namespace NArchive { namespace NApm { +static const Byte kSig0 = 'E'; +static const Byte kSig1 = 'R'; + struct CItem { UInt32 StartBlock; @@ -45,13 +49,13 @@ struct CItem 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); + if (p[0] != 0x50 || p[1] != 0x4D || p[2] != 0 || p[3] != 0) + return false; /* DataStartBlock = Get32(p + 0x50); NumDataBlocks = Get32(p + 0x54); @@ -76,42 +80,56 @@ class CHandler: public IInArchiveGetStream, public CMyUnknownImp { - CMyComPtr _stream; CRecordVector _items; - - int _blockSizeLog; + CMyComPtr _stream; + unsigned _blockSizeLog; UInt32 _numBlocks; + UInt64 _phySize; + bool _isArc; HRESULT ReadTables(IInStream *stream); UInt64 BlocksToBytes(UInt32 i) const { return (UInt64)i << _blockSizeLog; } - UInt64 GetItemSize(const CItem &item) { return BlocksToBytes(item.NumBlocks); } + UInt64 GetItemSize(const CItem &item) const { return BlocksToBytes(item.NumBlocks); } public: MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); }; -static inline int GetLog(UInt32 num) +static const UInt32 kSectorSize = 512; + +API_FUNC_static_IsArc IsArc_Apm(const Byte *p, size_t size) { - for (int i = 0; i < 31; i++) - if (((UInt32)1 << i) == num) - return i; - return -1; + if (size < kSectorSize) + return k_IsArc_Res_NEED_MORE; + if (p[0] != kSig0 || p[1] != kSig1) + return k_IsArc_Res_NO; + unsigned i; + for (i = 8; i < 16; i++) + if (p[i] != 0) + return k_IsArc_Res_NO; + UInt32 blockSize = Get16(p + 2); + for (i = 9; ((UInt32)1 << i) != blockSize; i++) + if (i >= 12) + return k_IsArc_Res_NO; + return k_IsArc_Res_YES; } 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) + if (buf[0] != kSig0 || buf[1] != kSig1) return S_FALSE; + UInt32 blockSize = Get16(buf + 2); + unsigned i; + for (i = 9; ((UInt32)1 << i) != blockSize; i++) + if (i >= 12) + return S_FALSE; + _blockSizeLog = i; _numBlocks = Get32(buf + 4); - for (int i = 8; i < 16; i++) + for (i = 8; i < 16; i++) if (buf[i] != 0) return S_FALSE; } @@ -123,13 +141,14 @@ HRESULT CHandler::ReadTables(IInStream *stream) } UInt32 numBlocksInMap = 0; + for (unsigned i = 0;;) { RINOK(ReadStream_FALSE(stream, buf, kSectorSize)); CItem item; - UInt32 numBlocksInMap2; + UInt32 numBlocksInMap2 = 0; if (!item.Parse(buf, numBlocksInMap2)) return S_FALSE; if (i == 0) @@ -154,12 +173,13 @@ HRESULT CHandler::ReadTables(IInStream *stream) if (++i == numBlocksInMap) break; } + + _phySize = BlocksToBytes(_numBlocks); + _isArc = true; return S_OK; } -STDMETHODIMP CHandler::Open(IInStream *stream, - const UInt64 * /* maxCheckStartPosition */, - IArchiveOpenCallback * /* openArchiveCallback */) +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* callback */) { COM_TRY_BEGIN Close(); @@ -171,22 +191,23 @@ STDMETHODIMP CHandler::Open(IInStream *stream, STDMETHODIMP CHandler::Close() { + _isArc = false; + _phySize = 0; _items.Clear(); _stream.Release(); return S_OK; } -STATPROPSTG kProps[] = +static const Byte kProps[] = { - { NULL, kpidPath, VT_BSTR}, - { NULL, kpidSize, VT_UI8}, - { NULL, kpidOffset, VT_UI8} + kpidPath, + kpidSize, + kpidOffset }; -STATPROPSTG kArcProps[] = +static const Byte kArcProps[] = { - { NULL, kpidClusterSize, VT_UI4}, - { NULL, kpidPhySize, VT_UI8} + kpidClusterSize }; IMP_IInArchive_Props @@ -195,7 +216,7 @@ IMP_IInArchive_ArcProps static AString GetString(const char *s) { AString res; - for (int i = 0; i < 32 && s[i] != 0; i++) + for (unsigned i = 0; i < 32 && s[i] != 0; i++) res += s[i]; return res; } @@ -204,12 +225,12 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; - switch(propID) + switch (propID) { case kpidMainSubfile: { int mainIndex = -1; - for (int i = 0; i < _items.Size(); i++) + FOR_VECTOR (i, _items) { AString s = GetString(_items[i].Type); if (s != "Apple_Free" && @@ -228,7 +249,15 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) break; } case kpidClusterSize: prop = (UInt32)1 << _blockSizeLog; break; - case kpidPhySize: prop = BlocksToBytes(_numBlocks); break; + case kpidPhySize: prop = _phySize; break; + + case kpidErrorFlags: + { + UInt32 v = 0; + if (!_isArc) v |= kpv_ErrorFlags_IsNotArc; + prop = v; + break; + } } prop.Detach(value); return S_OK; @@ -246,7 +275,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val COM_TRY_BEGIN NCOM::CPropVariant prop; const CItem &item = _items[index]; - switch(propID) + switch (propID) { case kpidPath: { @@ -283,7 +312,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _items.Size(); if (numItems == 0) @@ -346,10 +375,14 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) COM_TRY_END } -static IInArchive *CreateArc() { return new CHandler; } +IMP_CreateArcIn static CArcInfo g_ArcInfo = - { L"APM", L"", 0, 0xD4, { 0x50, 0x4D, 0, 0, 0, 0, 0 }, 7, false, CreateArc, 0 }; + { "APM", "apm", 0, 0xD4, + 2, { kSig0, kSig1 }, + 0, + 0, + CreateArc, NULL, IsArc_Apm }; REGISTER_ARC(Apm) diff --git a/CPP/7zip/Archive/ArHandler.cpp b/CPP/7zip/Archive/ArHandler.cpp new file mode 100644 index 00000000..b7dcda85 --- /dev/null +++ b/CPP/7zip/Archive/ArHandler.cpp @@ -0,0 +1,857 @@ +// ArHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "../../Common/ComTry.h" +#include "../../Common/IntToString.h" +#include "../../Common/StringConvert.h" +#include "../../Common/StringToInt.h" + +#include "../../Windows/PropVariant.h" +#include "../../Windows/TimeUtils.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 "Common/ItemNameUtils.h" + +using namespace NWindows; +using namespace NTime; + +namespace NArchive { +namespace NAr { + +/* +The end of each file member (including last file in archive) is 2-bytes aligned. +It uses 0xA padding if required. + +File Names: + +GNU/SVR4 variant (.a static library): + / - archive symbol table + // - the list of the long filenames, separated by one or more LF characters. + /N - the reference to name string in long filenames list + name/ - the name + +Microsoft variant (.lib static library): + / - First linker file (archive symbol table) + / - Second linker file + // - the list of the long filenames, null-terminated. Each string begins + immediately after the null byte in the previous string. + /N - the reference to name string in long filenames list + name/ - the name + +BSD (Mac OS X) variant: + "__.SYMDEF" - archive symbol table + or + "__.SYMDEF SORTED" - archive symbol table + #1/N - the real filename of length N is appended to the file header. +*/ + +static const unsigned kSignatureLen = 8; + +#define SIGNATURE { '!', '<', 'a', 'r', 'c', 'h', '>', 0x0A } + +static const Byte kSignature[kSignatureLen] = SIGNATURE; + +static const unsigned kNameSize = 16; +static const unsigned kTimeSize = 12; +static const unsigned kUserSize = 6; +static const unsigned kModeSize = 8; +static const unsigned kSizeSize = 10; + +static const unsigned kHeaderSize = kNameSize + kTimeSize + kUserSize * 2 + kModeSize + kSizeSize + 1 + 1; + +enum EType +{ + kType_Ar, + kType_ALib, + kType_Deb, + kType_Lib +}; + +static const char *k_TypeExtionsions[] = +{ + "ar" + , "a" + , "deb" + , "lib" +}; + +enum ESubType +{ + kSubType_None, + kSubType_BSD +}; + +/* +struct CHeader +{ + char Name[kNameSize]; + char MTime[kTimeSize]; + char User[kUserSize]; + char Group[kUserSize]; + char Mode[kModeSize]; + char Size[kSizeSize]; + char Quote; + char NewLine; +}; +*/ + +struct CItem +{ + AString Name; + UInt64 Size; + UInt32 MTime; + UInt32 User; + UInt32 Group; + UInt32 Mode; + + UInt64 HeaderPos; + UInt64 HeaderSize; + + int TextFileIndex; + int SameNameIndex; + + CItem(): TextFileIndex(-1), SameNameIndex(-1) {} + UInt64 GetDataPos() const { return HeaderPos + HeaderSize; }; +}; + +class CInArchive +{ + CMyComPtr m_Stream; + +public: + UInt64 Position; + ESubType SubType; + + HRESULT GetNextItem(CItem &itemInfo, bool &filled); + HRESULT Open(IInStream *inStream); + HRESULT SkipData(UInt64 dataSize) + { + return m_Stream->Seek(dataSize + (dataSize & 1), STREAM_SEEK_CUR, &Position); + } +}; + +HRESULT CInArchive::Open(IInStream *inStream) +{ + SubType = kSubType_None; + RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &Position)); + char signature[kSignatureLen]; + RINOK(ReadStream_FALSE(inStream, signature, kSignatureLen)); + Position += kSignatureLen; + if (memcmp(signature, kSignature, kSignatureLen) != 0) + return S_FALSE; + m_Stream = inStream; + return S_OK; +} + +static unsigned RemoveTailSpaces(char *dest, const char *s, unsigned size) +{ + memcpy(dest, s, size); + for (; size != 0; size--) + { + if (dest[size - 1] != ' ') + break; + } + dest[size] = 0; + return size; +} + +static bool OctalToNumber32(const char *s, unsigned size, UInt32 &res) +{ + res = 0; + char sz[32]; + size = RemoveTailSpaces(sz, s, size); + if (size == 0) + return true; // some items doesn't contaion any numbers + const char *end; + UInt64 res64 = ConvertOctStringToUInt64(sz, &end); + if ((unsigned)(end - sz) != size) + return false; + res = (UInt32)res64; + return (res64 <= 0xFFFFFFFF); +} + +static bool DecimalToNumber(const char *s, unsigned size, UInt64 &res) +{ + res = 0; + char sz[32]; + size = RemoveTailSpaces(sz, s, size); + if (size == 0) + return true; // some items doesn't contaion any numbers + const char *end; + res = ConvertStringToUInt64(sz, &end); + return ((unsigned)(end - sz) == size); +} + +static bool DecimalToNumber32(const char *s, unsigned 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::GetNextItem(CItem &item, bool &filled) +{ + filled = false; + + char header[kHeaderSize]; + const char *cur = header; + + { + size_t processedSize = sizeof(header); + item.HeaderPos = Position; + item.HeaderSize = kHeaderSize; + RINOK(ReadStream(m_Stream, header, &processedSize)); + if (processedSize != sizeof(header)) + return S_OK; + if (header[kHeaderSize - 2] != 0x60 || + header[kHeaderSize - 1] != 0x0A) + return S_OK; + for (unsigned i = 0; i < kHeaderSize - 2; i++) + // if (header[i] < 0x20) + if (header[i] == 0) + return S_OK; + Position += processedSize; + } + + UInt32 longNameLen = 0; + if (cur[0] == '#' && + cur[1] == '1' && + cur[2] == '/' && + cur[3] != 0) + { + // BSD variant + RIF(DecimalToNumber32(cur + 3, kNameSize - 3 , longNameLen)); + if (longNameLen >= (1 << 12)) + longNameLen = 0; + } + else + { + char tempString[kNameSize + 1]; + RemoveTailSpaces(tempString, cur, kNameSize); + item.Name = tempString; + } + cur += kNameSize; + + RIF(DecimalToNumber32(cur, kTimeSize, item.MTime)); cur += kTimeSize; + RIF(DecimalToNumber32(cur, kUserSize, item.User)); cur += kUserSize; + RIF(DecimalToNumber32(cur, kUserSize, item.Group)); cur += kUserSize; + RIF(OctalToNumber32(cur, kModeSize, item.Mode)); cur += kModeSize; + RIF(DecimalToNumber(cur, kSizeSize, item.Size)); cur += kSizeSize; + + if (longNameLen != 0 && longNameLen <= item.Size) + { + SubType = kSubType_BSD; + size_t processedSize = longNameLen; + char *s = item.Name.GetBuffer(longNameLen); + HRESULT res = ReadStream(m_Stream, s, &processedSize); + s[longNameLen] = 0; + item.Name.ReleaseBuffer(); + RINOK(res); + if (processedSize != longNameLen) + return S_OK; + item.Size -= longNameLen; + item.HeaderSize += longNameLen; + Position += processedSize; + } + + filled = true; + return S_OK; +} + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + CObjectVector _items; + CMyComPtr _stream; + Int32 _mainSubfile; + UInt64 _phySize; + + EType _type; + ESubType _subType; + int _longNames_FileIndex; + AString _libFiles[2]; + unsigned _numLibFiles; + AString _errorMessage; + bool _isArc; + + + void UpdateErrorMessage(const char *s); + + HRESULT ParseLongNames(IInStream *stream); + void ChangeDuplicateNames(); + int FindItem(UInt32 offset) const; + HRESULT AddFunc(UInt32 offset, const Byte *data, size_t size, size_t &pos); + HRESULT ParseLibSymbols(IInStream *stream, unsigned fileIndex); +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +void CHandler::UpdateErrorMessage(const char *s) +{ + if (!_errorMessage.IsEmpty()) + _errorMessage += '\n'; + _errorMessage += s; +} + +static const Byte kArcProps[] = +{ + kpidSubType +}; + +static const Byte kProps[] = +{ + kpidPath, + kpidSize, + kpidMTime, + kpidPosixAttrib, + kpidUser, + kpidGroup +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +HRESULT CHandler::ParseLongNames(IInStream *stream) +{ + unsigned i; + for (i = 0; i < _items.Size(); i++) + if (_items[i].Name == "//") + break; + if (i == _items.Size()) + return S_OK; + + unsigned fileIndex = i; + const CItem &item = _items[fileIndex]; + if (item.Size > ((UInt32)1 << 30)) + return S_FALSE; + RINOK(stream->Seek(item.GetDataPos(), STREAM_SEEK_SET, NULL)); + size_t size = (size_t)item.Size; + + CByteArr p(size); + RINOK(ReadStream_FALSE(stream, p, size)); + for (i = 0; i < _items.Size(); i++) + { + CItem &item = _items[i]; + if (item.Name[0] != '/') + continue; + const char *ptr = item.Name.Ptr(1); + const char *end; + UInt32 pos = ConvertStringToUInt32(ptr, &end); + if (*end != 0 || end == ptr) + continue; + if (pos >= size) + continue; + UInt32 start = pos; + for (;;) + { + if (pos >= size) + return S_FALSE; + char c = p[pos]; + if (c == 0 || c == 0x0A) + break; + pos++; + } + item.Name.SetFrom((const char *)(p + start), pos - start); + } + _longNames_FileIndex = fileIndex; + return S_OK; +} + +void CHandler::ChangeDuplicateNames() +{ + unsigned i; + for (i = 1; i < _items.Size(); i++) + { + CItem &item = _items[i]; + if (item.Name[0] == '/') + continue; + CItem &prev = _items[i - 1]; + if (item.Name == prev.Name) + { + if (prev.SameNameIndex < 0) + prev.SameNameIndex = 0; + item.SameNameIndex = prev.SameNameIndex + 1; + } + } + for (i = 0; i < _items.Size(); i++) + { + CItem &item = _items[i]; + if (item.SameNameIndex < 0) + continue; + char sz[32]; + ConvertUInt32ToString(item.SameNameIndex + 1, sz); + unsigned len = MyStringLen(sz); + sz[len++] = '.'; + sz[len] = 0; + item.Name.Insert(0, sz); + } +} + +int CHandler::FindItem(UInt32 offset) const +{ + unsigned left = 0, right = _items.Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + UInt64 midVal = _items[mid].HeaderPos; + if (offset == midVal) + return mid; + if (offset < midVal) + right = mid; + else + left = mid + 1; + } + return -1; +} + +HRESULT CHandler::AddFunc(UInt32 offset, const Byte *data, size_t size, size_t &pos) +{ + int fileIndex = FindItem(offset); + if (fileIndex < (int)0) + return S_FALSE; + + size_t i = pos; + do + { + if (i >= size) + return S_FALSE; + } + while (data[i++] != 0); + + AString &s = _libFiles[_numLibFiles]; + const AString &name = _items[fileIndex].Name; + s += name; + if (!name.IsEmpty() && name.Back() == '/') + s.DeleteBack(); + s += " "; + s += (const char *)(data + pos); + s += (char)0xD; + s += (char)0xA; + pos = i; + return S_OK; +} + +static UInt32 Get32(const Byte *p, unsigned be) { if (be) return GetBe32(p); return GetUi32(p); } + +HRESULT CHandler::ParseLibSymbols(IInStream *stream, unsigned fileIndex) +{ + CItem &item = _items[fileIndex]; + if (item.Name != "/" && + item.Name != "__.SYMDEF" && + item.Name != "__.SYMDEF SORTED") + return S_OK; + if (item.Size > ((UInt32)1 << 30) || + item.Size < 4) + return S_OK; + RINOK(stream->Seek(item.GetDataPos(), STREAM_SEEK_SET, NULL)); + size_t size = (size_t)item.Size; + CByteArr p(size); + RINOK(ReadStream_FALSE(stream, p, size)); + + size_t pos = 0; + + if (item.Name != "/") + { + // __.SYMDEF parsing (BSD) + unsigned be; + for (be = 0; be < 2; be++) + { + UInt32 tableSize = Get32(p, be); + pos = 4; + if (size - pos < tableSize || (tableSize & 7) != 0) + continue; + size_t namesStart = pos + tableSize; + UInt32 namesSize = Get32(p + namesStart, be); + namesStart += 4; + if (namesStart > size || namesStart + namesSize != size) + continue; + + UInt32 numSymbols = tableSize >> 3; + UInt32 i; + for (i = 0; i < numSymbols; i++, pos += 8) + { + size_t namePos = Get32(p + pos, be); + UInt32 offset = Get32(p + pos + 4, be); + if (AddFunc(offset, p + namesStart, namesSize, namePos) != S_OK) + break; + } + if (i == numSymbols) + { + pos = size; + _type = kType_ALib; + _subType = kSubType_BSD; + break; + } + } + if (be == 2) + return S_FALSE; + } + else if (_numLibFiles == 0) + { + // archive symbol table (GNU) + UInt32 numSymbols = GetBe32(p); + pos = 4; + if (numSymbols > (size - pos) / 4) + return S_FALSE; + pos += 4 * numSymbols; + + for (UInt32 i = 0; i < numSymbols; i++) + { + UInt32 offset = GetBe32(p + 4 + i * 4); + RINOK(AddFunc(offset, p, size, pos)); + } + _type = kType_ALib; + } + else + { + // Second linker file (Microsoft .lib) + UInt32 numMembers = GetUi32(p); + pos = 4; + if (numMembers > (size - pos) / 4) + return S_FALSE; + pos += 4 * numMembers; + + if (size - pos < 4) + return S_FALSE; + UInt32 numSymbols = GetUi32(p + pos); + pos += 4; + if (numSymbols > (size - pos) / 2) + return S_FALSE; + size_t indexStart = pos; + pos += 2 * numSymbols; + + for (UInt32 i = 0; i < numSymbols; i++) + { + // index is 1-based. So 32-bit numSymbols field works as item[0] + UInt32 index = GetUi16(p + indexStart + i * 2); + if (index == 0 || index > numMembers) + return S_FALSE; + UInt32 offset = GetUi32(p + index * 4); + RINOK(AddFunc(offset, p, size, pos)); + } + _type = kType_Lib; + } + // size can be 2-byte aligned in linux files + if (pos != size && pos + (pos & 1) != size) + return S_FALSE; + item.TextFileIndex = _numLibFiles++; + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *stream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + { + Close(); + + UInt64 fileSize = 0; + RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize)); + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + + CInArchive arc; + RINOK(arc.Open(stream)); + + if (callback) + { + RINOK(callback->SetTotal(NULL, &fileSize)); + UInt64 numFiles = _items.Size(); + RINOK(callback->SetCompleted(&numFiles, &arc.Position)); + } + + CItem item; + for (;;) + { + bool filled; + RINOK(arc.GetNextItem(item, filled)); + if (!filled) + break; + _items.Add(item); + arc.SkipData(item.Size); + if (callback && (_items.Size() & 0xFF) == 0) + { + UInt64 numFiles = _items.Size(); + RINOK(callback->SetCompleted(&numFiles, &arc.Position)); + } + } + + if (_items.IsEmpty()) + { + // we don't need false empty archives (8-bytes signature only) + if (arc.Position != fileSize) + return S_FALSE; + } + + _isArc = true; + + _subType = arc.SubType; + + if (ParseLongNames(stream) != S_OK) + UpdateErrorMessage("Long file names parsing error"); + if (_longNames_FileIndex >= 0) + _items.Delete(_longNames_FileIndex); + + if (!_items.IsEmpty() && _items[0].Name == "debian-binary") + { + _type = kType_Deb; + _items.DeleteFrontal(1); + for (unsigned i = 0; i < _items.Size(); i++) + if (_items[i].Name.IsPrefixedBy("data.tar.")) + if (_mainSubfile < 0) + _mainSubfile = i; + else + { + _mainSubfile = -1; + break; + } + } + else + { + ChangeDuplicateNames(); + bool error = false; + for (unsigned li = 0; li < 2 && li < _items.Size(); li++) + if (ParseLibSymbols(stream, li) != S_OK) + error = true; + if (error) + UpdateErrorMessage("Library symbols information error"); + } + + _stream = stream; + _phySize = arc.Position; + + /* + if (fileSize < _phySize) + UpdateErrorMessage("Unexpected end of archive"); + */ + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _isArc = false; + _phySize = 0; + + _errorMessage.Empty(); + _stream.Release(); + _items.Clear(); + + _type = kType_Ar; + _subType = kSubType_None; + _mainSubfile = -1; + _longNames_FileIndex = -1; + + _numLibFiles = 0; + _libFiles[0].Empty(); + _libFiles[1].Empty(); + + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _items.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NCOM::CPropVariant prop; + switch (propID) + { + case kpidPhySize: prop = _phySize; break; + case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break; + case kpidExtension: prop = k_TypeExtionsions[_type]; break; + case kpidShortComment: + case kpidSubType: + { + AString s = k_TypeExtionsions[_type]; + if (_subType == kSubType_BSD) + s += ":BSD"; + prop = s; + break; + } + case kpidErrorFlags: + { + UInt32 v = 0; + if (!_isArc) v |= kpv_ErrorFlags_IsNotArc; + prop = v; + break; + } + case kpidWarning: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break; + case kpidIsNotArcType: if (_type != kType_Deb) prop = true; 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: + if (item.TextFileIndex >= 0) + prop = (item.TextFileIndex == 0) ? "1.txt" : "2.txt"; + else + prop = (const wchar_t *)NItemName::GetOSName2(MultiByteToUnicodeString(item.Name, CP_OEMCP)); + break; + case kpidSize: + case kpidPackSize: + if (item.TextFileIndex >= 0) + prop = (UInt64)_libFiles[item.TextFileIndex].Len(); + else + prop = item.Size; + break; + case kpidMTime: + { + if (item.MTime != 0) + { + FILETIME fileTime; + NTime::UnixTimeToFileTime(item.MTime, fileTime); + prop = fileTime; + } + break; + } + case kpidUser: if (item.User != 0) prop = item.User; break; + case kpidGroup: if (item.Group != 0) prop = item.Group; break; + case kpidPosixAttrib: + if (item.TextFileIndex < 0) + prop = item.Mode; + 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)(Int32)-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]]; + totalSize += + (item.TextFileIndex >= 0) ? + (UInt64)_libFiles[item.TextFileIndex].Len() : 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); + + 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.TextFileIndex >= 0) ? + (UInt64)_libFiles[item.TextFileIndex].Len() : item.Size; + + if (!testMode && !realOutStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + if (testMode) + { + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + bool isOk = true; + if (item.TextFileIndex >= 0) + { + const AString &f = _libFiles[item.TextFileIndex]; + if (realOutStream) + RINOK(WriteStream(realOutStream, f, f.Len())); + } + else + { + RINOK(_stream->Seek(item.GetDataPos(), STREAM_SEEK_SET, NULL)); + streamSpec->Init(item.Size); + RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); + isOk = (copyCoderSpec->TotalSize == item.Size); + } + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(isOk ? + 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]; + if (item.TextFileIndex >= 0) + { + const AString &f = _libFiles[item.TextFileIndex]; + Create_BufInStream_WithNewBuf((const void *)(const char *)f, f.Len(), stream); + return S_OK; + } + else + return CreateLimitedInStream(_stream, item.GetDataPos(), item.Size, stream); + COM_TRY_END +} + +IMP_CreateArcIn + +static CArcInfo g_ArcInfo = + { "Ar", "ar a deb lib", 0, 0xEC, + kSignatureLen, SIGNATURE, + 0, + 0, + CreateArc }; + +REGISTER_ARC(Ar) + +}} diff --git a/CPP/7zip/Archive/Archive.def b/CPP/7zip/Archive/Archive.def old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Archive2.def b/CPP/7zip/Archive/Archive2.def old mode 100755 new mode 100644 index 885d39d1..66feb41d --- a/CPP/7zip/Archive/Archive2.def +++ b/CPP/7zip/Archive/Archive2.def @@ -3,7 +3,9 @@ EXPORTS GetHandlerProperty PRIVATE GetNumberOfFormats PRIVATE GetHandlerProperty2 PRIVATE - CreateObject PRIVATE GetNumberOfMethods PRIVATE GetMethodProperty PRIVATE + GetHashers PRIVATE SetLargePageMode PRIVATE + SetCaseSensitive PRIVATE + GetIsArc PRIVATE \ No newline at end of file diff --git a/CPP/7zip/Archive/ArchiveExports.cpp b/CPP/7zip/Archive/ArchiveExports.cpp old mode 100755 new mode 100644 index c7908b59..c7d6611b --- a/CPP/7zip/Archive/ArchiveExports.cpp +++ b/CPP/7zip/Archive/ArchiveExports.cpp @@ -2,24 +2,28 @@ #include "StdAfx.h" +#include "../../../C/7zVersion.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 unsigned kNumArcsMax = 64; +static unsigned g_NumArcs = 0; +static unsigned g_DefaultArcIndex = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; + void RegisterArc(const CArcInfo *arcInfo) { if (g_NumArcs < kNumArcsMax) { - const wchar_t *p = arcInfo->Name; + const char *p = arcInfo->Name; if (p[0] == '7' && p[1] == 'z' && p[2] == 0) g_DefaultArcIndex = g_NumArcs; - g_Arcs[g_NumArcs++] = arcInfo; + g_Arcs[g_NumArcs] = arcInfo; + g_NumArcs++; } } @@ -28,7 +32,7 @@ DEFINE_GUID(CLSID_CArchiveHandler, #define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5]) -static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value) +static inline HRESULT SetPropString(const char *s, unsigned size, PROPVARIANT *value) { if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0) value->vt = VT_BSTR; @@ -86,37 +90,38 @@ STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject) STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN + NWindows::NCOM::PropVariant_Clear(value); if (formatIndex >= g_NumArcs) return E_INVALIDARG; const CArcInfo &arc = *g_Arcs[formatIndex]; NWindows::NCOM::CPropVariant prop; - switch(propID) + switch (propID) { - case NArchive::kName: - prop = arc.Name; - break; - case NArchive::kClassID: + case NArchive::NHandlerPropID::kName: prop = arc.Name; break; + case NArchive::NHandlerPropID::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); + case NArchive::NHandlerPropID::kExtension: if (arc.Ext) prop = arc.Ext; break; + case NArchive::NHandlerPropID::kAddExtension: if (arc.AddExt) prop = arc.AddExt; break; + case NArchive::NHandlerPropID::kUpdate: prop = (bool)(arc.CreateOutArchive != NULL); break; + case NArchive::NHandlerPropID::kKeepName: prop = ((arc.Flags & NArcInfoFlags::kKeepName) != 0); break; + case NArchive::NHandlerPropID::kAltStreams: prop = ((arc.Flags & NArcInfoFlags::kAltStreams) != 0); break; + case NArchive::NHandlerPropID::kNtSecure: prop = ((arc.Flags & NArcInfoFlags::kNtSecure) != 0); break; + case NArchive::NHandlerPropID::kFlags: prop = (UInt32)arc.Flags; break; + case NArchive::NHandlerPropID::kSignatureOffset: prop = (UInt32)arc.SignatureOffset; break; + // case NArchive::NHandlerPropID::kVersion: prop = (UInt32)MY_VER_MIX; break; + + case NArchive::NHandlerPropID::kSignature: + if (!arc.IsMultiSignature()) + return SetPropString((const char *)arc.Signature, arc.SignatureSize, value); break; - case NArchive::kKeepName: - prop = arc.KeepName; + case NArchive::NHandlerPropID::kMultiSignature: + if (arc.IsMultiSignature()) + return SetPropString((const char *)arc.Signature, arc.SignatureSize, value); break; - case NArchive::kStartSignature: - return SetPropString((const char *)arc.Signature, arc.SignatureSize, value); } prop.Detach(value); return S_OK; @@ -133,3 +138,12 @@ STDAPI GetNumberOfFormats(UINT32 *numFormats) *numFormats = g_NumArcs; return S_OK; } + +STDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc) +{ + *isArc = NULL; + if (formatIndex >= g_NumArcs) + return E_INVALIDARG; + *isArc = g_Arcs[formatIndex]->IsArc; + return S_OK; +} diff --git a/CPP/7zip/Archive/ArjHandler.cpp b/CPP/7zip/Archive/ArjHandler.cpp old mode 100755 new mode 100644 index 4dd686ec..ad44c62a --- a/CPP/7zip/Archive/ArjHandler.cpp +++ b/CPP/7zip/Archive/ArjHandler.cpp @@ -4,11 +4,12 @@ #include "../../../C/CpuArch.h" -#include "Common/ComTry.h" -#include "Common/StringConvert.h" +#include "../../Common/ComTry.h" +#include "../../Common/IntToString.h" +#include "../../Common/StringConvert.h" -#include "Windows/PropVariant.h" -#include "Windows/Time.h" +#include "../../Windows/PropVariant.h" +#include "../../Windows/TimeUtils.h" #include "../Common/LimitedStreams.h" #include "../Common/ProgressUtils.h" @@ -31,74 +32,85 @@ using namespace NWindows; namespace NArchive { namespace NArj { -const int kBlockSizeMin = 30; -const int kBlockSizeMax = 2600; +static const unsigned kBlockSizeMin = 30; +static const unsigned kBlockSizeMax = 2600; -namespace NSignature +static const Byte kSig0 = 0x60; +static const Byte kSig1 = 0xEA; + +namespace NCompressionMethod { - const Byte kSig0 = 0x60; - const Byte kSig1 = 0xEA; + enum + { + kStored = 0, + kCompressed1a = 1, + kCompressed1b = 2, + kCompressed1c = 3, + kCompressed2 = 4, + kNoDataNoCRC = 8, + kNoData = 9 + }; } -namespace NFileHeader +namespace NFileType { - namespace NCompressionMethod + enum { - enum - { - kStored = 0, - kCompressed1a = 1, - kCompressed1b = 2, - kCompressed1c = 3, - kCompressed2 = 4, - kNoDataNoCRC = 8, - kNoData = 9 - }; - } + kBinary = 0, + k7BitText, + kArchiveHeader, + kDirectory, + kVolumeLablel, + kChapterLabel + }; +} - 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 NFlags +{ + const Byte kGarbled = 1 << 0; + const Byte kAnsiPage = 1 << 1; // or (OLD_SECURED_FLAG) obsolete + const Byte kVolume = 1 << 2; + const Byte kExtFile = 1 << 3; + const Byte kPathSym = 1 << 4; + const Byte kBackup = 1 << 5; // obsolete + const Byte kSecured = 1 << 6; + const Byte kDualName = 1 << 7; +} - namespace NHostOS +namespace NHostOS +{ + enum EEnum { - 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 - }; - } + kMSDOS = 0, // MS-DOS, OS/2, Win32, pkarj 2.50 (FAT / VFAT / FAT32) + kPRIMOS, + kUnix, + kAMIGA, + kMac, + kOS_2, + kAPPLE_GS, + kAtari_ST, + kNext, + kVAX_VMS, + kWIN95 + }; } -struct CArchiveHeader +static const char *kHostOS[] = +{ + "MSDOS" + , "PRIMOS" + , "UNIX" + , "AMIGA" + , "MAC" + , "OS/2" + , "APPLE GS" + , "ATARI ST" + , "NEXT" + , "VAX VMS" + , "WIN95" +}; + +struct CArcHeader { // Byte ArchiverVersion; // Byte ExtractVersion; @@ -110,9 +122,9 @@ struct CArchiveHeader UInt32 CTime; UInt32 MTime; UInt32 ArchiveSize; - // UInt32 SecurityEnvelopeFilePosition; - // UInt16 FilespecPositionInFilename; - // UInt16 LengthOfSecurityEnvelopeSata; + // UInt32 SecurPos; + // UInt16 FilespecPosInFilename; + UInt16 SecurSize; // Byte EncryptionVersion; // Byte LastChapter; AString Name; @@ -121,47 +133,71 @@ struct CArchiveHeader HRESULT Parse(const Byte *p, unsigned size); }; +API_FUNC_static_IsArc IsArc_Arj(const Byte *p, size_t size) +{ + if (size < kBlockSizeMin + 4) + return k_IsArc_Res_NEED_MORE; + if (p[0] != kSig0 || p[1] != kSig1) + return k_IsArc_Res_NO; + UInt32 blockSize = Get16(p + 2); + if (blockSize < kBlockSizeMin || + blockSize > kBlockSizeMax) + return k_IsArc_Res_NO; + + p += 4; + size -= 4; + + Byte headerSize = p[0]; + if (headerSize < kBlockSizeMin || + headerSize > blockSize || + p[6] != NFileType::kArchiveHeader || + p[28] > 8) // EncryptionVersion + return k_IsArc_Res_NO; + + if (blockSize + 4 <= size) + if (Get32(p + blockSize) != CrcCalc(p, blockSize)) + return k_IsArc_Res_NO; + + return k_IsArc_Res_YES; +} + 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; + res = (const char *)p; return S_OK; } - s += c; } return S_FALSE; } -HRESULT CArchiveHeader::Parse(const Byte *p, unsigned size) +HRESULT CArcHeader::Parse(const Byte *p, unsigned size) { - if (size < kBlockSizeMin) - return S_FALSE; - Byte firstHeaderSize = p[0]; - if (firstHeaderSize > size) + Byte headerSize = p[0]; + if (headerSize < kBlockSizeMin || headerSize > 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) + if (p[6] != NFileType::kArchiveHeader) return S_FALSE; // Reserved = p[7]; CTime = Get32(p + 8); MTime = Get32(p + 12); - ArchiveSize = Get32(p + 16); - // SecurityEnvelopeFilePosition = Get32(p + 20); + ArchiveSize = Get32(p + 16); // it can be zero. (currently used only for secured archives) + // SecurPos = Get32(p + 20); // UInt16 filespecPositionInFilename = Get16(p + 24); - // LengthOfSecurityEnvelopeSata = Get16(p + 26); + SecurSize = Get16(p + 26); // EncryptionVersion = p[28]; // LastChapter = p[29]; - unsigned pos = firstHeaderSize; + unsigned pos = headerSize; unsigned size1 = size - pos; RINOK(ReadString(p + pos, size1, Name)); pos += size1; @@ -189,32 +225,30 @@ struct CItem Byte Method; Byte FileType; - // UInt16 FilespecPositionInFilename; + // UInt16 FilespecPosInFilename; 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 + bool IsEncrypted() const { return (Flags & NFlags::kGarbled) != 0; } + bool IsDir() const { return (FileType == NFileType::kDirectory); } + bool IsSplitAfter() const { return (Flags & NFlags::kVolume) != 0; } + bool IsSplitBefore() const { return (Flags & NFlags::kExtFile) != 0; } + UInt32 GetWinAttrib() const { - UInt32 winAtrributes; - switch(HostOS) + UInt32 atrrib = 0; + switch (HostOS) { - case NFileHeader::NHostOS::kMSDOS: - case NFileHeader::NHostOS::kWIN95: - winAtrributes = FileAccessMode; + case NHostOS::kMSDOS: + case NHostOS::kWIN95: + atrrib = FileAccessMode; break; - default: - winAtrributes = 0; } if (IsDir()) - winAtrributes |= FILE_ATTRIBUTE_DIRECTORY; - return winAtrributes; + atrrib |= FILE_ATTRIBUTE_DIRECTORY; + return atrrib; } HRESULT Parse(const Byte *p, unsigned size); @@ -222,11 +256,9 @@ struct CItem HRESULT CItem::Parse(const Byte *p, unsigned size) { - if (size < kBlockSizeMin) + Byte headerSize = p[0]; + if (headerSize < kBlockSizeMin || headerSize > size) return S_FALSE; - - Byte firstHeaderSize = p[0]; - Version = p[1]; ExtractVersion = p[2]; HostOS = p[3]; @@ -238,16 +270,16 @@ HRESULT CItem::Parse(const Byte *p, unsigned size) PackSize = Get32(p + 12); Size = Get32(p + 16); FileCRC = Get32(p + 20); - // FilespecPositionInFilename = Get16(p + 24); + // FilespecPosInFilename = Get16(p + 24); FileAccessMode = Get16(p + 26); // FirstChapter = p[28]; // FirstChapter = p[29]; SplitPos = 0; - if (IsSplitBefore() && firstHeaderSize >= 34) + if (IsSplitBefore() && headerSize >= 34) SplitPos = Get32(p + 30); - unsigned pos = firstHeaderSize; + unsigned pos = headerSize; unsigned size1 = size - pos; RINOK(ReadString(p + pos, size1, Name)); pos += size1; @@ -258,180 +290,121 @@ HRESULT CItem::Parse(const Byte *p, unsigned size) return S_OK; } -struct CInArchiveException +enum EErrorType { - enum CCauseType - { - kUnexpectedEndOfArchive = 0, - kCRCError, - kIncorrectArchive - } - Cause; - CInArchiveException(CCauseType cause): Cause(cause) {}; + k_ErrorType_OK, + k_ErrorType_Corrupted, + k_ErrorType_UnexpectedEnd, }; -class CInArchive +class CArc { - 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; - + UInt64 Processed; + EErrorType Error; + bool IsArc; IInStream *Stream; IArchiveOpenCallback *Callback; UInt64 NumFiles; - UInt64 NumBytes; + CArcHeader Header; - 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 (;;) + HRESULT Open(); + HRESULT GetNextItem(CItem &item, bool &filled); + void Close() { - 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); + IsArc = false; + Error = k_ErrorType_OK; } -} +private: + UInt32 _blockSize; + Byte _block[kBlockSizeMax + 4]; -HRESULT CInArchive::SafeReadBytes(void *data, UInt32 size) + HRESULT ReadBlock(bool &filled, bool readSignature); + HRESULT SkipExtendedHeaders(); + HRESULT Read(void *data, size_t *size); +}; + +HRESULT CArc::Read(void *data, size_t *size) { - size_t processed = size; - RINOK(ReadStream(Stream, data, &processed)); - if (processed != size) - throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive); - return S_OK; + HRESULT res = ReadStream(Stream, data, size); + Processed += *size; + return res; } -HRESULT CInArchive::ReadBlock(bool &filled) +#define READ_STREAM(_dest_, _size_) \ + { size_t _processed_ = (_size_); RINOK(Read(_dest_, &_processed_)); \ + if (_processed_ != (_size_)) { Error = k_ErrorType_UnexpectedEnd; return S_OK; } } + +HRESULT CArc::ReadBlock(bool &filled, bool readSignature) { + Error = k_ErrorType_OK; filled = false; - Byte buf[2]; - RINOK(SafeReadBytes(buf, 2)); - _blockSize = Get16(buf); - if (_blockSize == 0) + Byte buf[4]; + unsigned signSize = readSignature ? 2 : 0; + READ_STREAM(buf, signSize + 2) + if (readSignature) + if (buf[0] != kSig0 || buf[1] != kSig1) + { + Error = k_ErrorType_Corrupted; + return S_OK; + } + _blockSize = Get16(buf + signSize); + if (_blockSize == 0) // end of archive + return S_OK; + if (_blockSize < kBlockSizeMin || + _blockSize > kBlockSizeMax) + { + Error = k_ErrorType_Corrupted; return S_OK; - if (_blockSize > kBlockSizeMax) - throw CInArchiveException(CInArchiveException::kIncorrectArchive); - RINOK(SafeReadBytes(_block, _blockSize + 4)); - NumBytes += _blockSize + 6; + } + READ_STREAM(_block, _blockSize + 4); if (Get32(_block + _blockSize) != CrcCalc(_block, _blockSize)) - throw CInArchiveException(CInArchiveException::kCRCError); + { + Error = k_ErrorType_Corrupted; + return S_OK; + } 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() +HRESULT CArc::SkipExtendedHeaders() { for (UInt32 i = 0;; i++) { bool filled; - RINOK(ReadBlock(filled)); + RINOK(ReadBlock(filled, false)); if (!filled) return S_OK; if (Callback && (i & 0xFF) == 0) - RINOK(Callback->SetCompleted(&NumFiles, &NumBytes)); + RINOK(Callback->SetCompleted(&NumFiles, &Processed)); } } -HRESULT CInArchive::Open(const UInt64 *searchHeaderSizeLimit) +HRESULT CArc::Open() { - UInt64 position = 0; - RINOK(FindAndReadMarker(Stream, searchHeaderSizeLimit, position)); - RINOK(Stream->Seek(position, STREAM_SEEK_SET, NULL)); bool filled; - RINOK(ReadSignatureAndBlock(filled)); + RINOK(ReadBlock(filled, true)); if (!filled) return S_FALSE; RINOK(Header.Parse(_block, _blockSize)); + IsArc = true; return SkipExtendedHeaders(); } -HRESULT CInArchive::GetNextItem(bool &filled, CItem &item) +HRESULT CArc::GetNextItem(CItem &item, bool &filled) { - RINOK(ReadSignatureAndBlock(filled)); + RINOK(ReadBlock(filled, true)); if (!filled) return S_OK; filled = false; - RINOK(item.Parse(_block, _blockSize)); + if (item.Parse(_block, _blockSize) != S_OK) + { + Error = k_ErrorType_Corrupted; + return S_OK; + } /* UInt32 extraData; - if ((header.Flags & NFileHeader::NFlags::kExtFile) != 0) + if ((header.Flags & NFlags::kExtFile) != 0) extraData = GetUi32(_block + pos); */ @@ -444,67 +417,47 @@ class CHandler: public IInArchive, public CMyUnknownImp { + CObjectVector _items; + CMyComPtr _stream; + UInt64 _phySize; + CArc _arc; public: MY_UNKNOWN_IMP1(IInArchive) INTERFACE_IInArchive(;) - HRESULT Open2(IInStream *inStream, const UInt64 *maxCheckStartPosition, - IArchiveOpenCallback *callback); -private: - CInArchive _archive; - CObjectVector _items; - CMyComPtr _stream; + HRESULT Open2(IInStream *inStream, IArchiveOpenCallback *callback); }; -const wchar_t *kHostOS[] = +static const Byte kArcProps[] = { - 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" + kpidName, + kpidCTime, + kpidMTime, + kpidHostOS, + kpidComment }; -const wchar_t *kUnknownOS = L"Unknown"; - -const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]); - -STATPROPSTG kArcProps[] = +static const Byte kProps[] = { - { 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} + kpidPath, + kpidIsDir, + kpidSize, + kpidPosition, + kpidPackSize, + kpidMTime, + kpidAttrib, + kpidEncrypted, + kpidCRC, + kpidMethod, + kpidHostOS, + kpidComment }; IMP_IInArchive_Props IMP_IInArchive_ArcProps -static void SetTime(UInt32 dosTime, NWindows::NCOM::CPropVariant &prop) +static void SetTime(UInt32 dosTime, NCOM::CPropVariant &prop) { if (dosTime == 0) return; @@ -519,12 +472,21 @@ static void SetTime(UInt32 dosTime, NWindows::NCOM::CPropVariant &prop) prop = utc; } -static void SetHostOS(Byte hostOS, NWindows::NCOM::CPropVariant &prop) +static void SetHostOS(Byte hostOS, NCOM::CPropVariant &prop) { - prop = hostOS < kNumHostOSes ? kHostOS[hostOS] : kUnknownOS; + char temp[16]; + const char *s = NULL; + if (hostOS < ARRAY_SIZE(kHostOS)) + s = kHostOS[hostOS]; + else + { + ConvertUInt32ToString(hostOS, temp); + s = temp; + } + prop = s; } -static void SetUnicodeString(const AString &s, NWindows::NCOM::CPropVariant &prop) +static void SetUnicodeString(const AString &s, NCOM::CPropVariant &prop) { if (!s.IsEmpty()) prop = MultiByteToUnicodeString(s, CP_OEMCP); @@ -533,14 +495,27 @@ static void SetUnicodeString(const AString &s, NWindows::NCOM::CPropVariant &pro STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; - switch(propID) + 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; + case kpidPhySize: prop = _phySize; break; + case kpidName: SetUnicodeString(_arc.Header.Name, prop); break; + case kpidCTime: SetTime(_arc.Header.CTime, prop); break; + case kpidMTime: SetTime(_arc.Header.MTime, prop); break; + case kpidHostOS: SetHostOS(_arc.Header.HostOS, prop); break; + case kpidComment: SetUnicodeString(_arc.Header.Comment, prop); break; + case kpidErrorFlags: + { + UInt32 v = 0; + if (!_arc.IsArc) v |= kpv_ErrorFlags_IsNotArc; + switch (_arc.Error) + { + case k_ErrorType_UnexpectedEnd: v |= kpv_ErrorFlags_UnexpectedEnd; break; + case k_ErrorType_Corrupted: v |= kpv_ErrorFlags_HeadersError; break; + } + prop = v; + break; + } } prop.Detach(value); return S_OK; @@ -556,16 +531,16 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; + NCOM::CPropVariant prop; const CItem &item = _items[index]; - switch(propID) + 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 kpidAttrib: prop = item.GetWinAttrib(); break; case kpidEncrypted: prop = item.IsEncrypted(); break; case kpidCRC: prop = item.FileCRC; break; case kpidMethod: prop = item.Method; break; @@ -578,75 +553,88 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val COM_TRY_END } -HRESULT CHandler::Open2(IInStream *inStream, const UInt64 *maxCheckStartPosition, - IArchiveOpenCallback *callback) +HRESULT CHandler::Open2(IInStream *inStream, 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)); - } + 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; + _arc.Stream = inStream; + _arc.Callback = callback; + _arc.NumFiles = 0; + _arc.Processed = 0; + + RINOK(_arc.Open()); + + _phySize = _arc.Processed; + if (_arc.Header.ArchiveSize != 0) + _phySize = (UInt64)_arc.Header.ArchiveSize + _arc.Header.SecurSize; - RINOK(_archive.Open(maxCheckStartPosition)); - if (callback != NULL) - RINOK(callback->SetTotal(NULL, &endPos)); for (;;) { CItem item; bool filled; + _arc.Error = k_ErrorType_OK; + RINOK(_arc.GetNextItem(item, filled)); - RINOK(_archive.GetNextItem(filled, item)); - - RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &item.DataPosition)); + if (_arc.Error != k_ErrorType_OK) + break; if (!filled) + { + if (_arc.Error == k_ErrorType_OK) + if (_arc.Header.ArchiveSize == 0) + _phySize = _arc.Processed; break; + } + item.DataPosition = _arc.Processed; _items.Add(item); - if (inStream->Seek(item.PackSize, STREAM_SEEK_CUR, NULL) != S_OK) - throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive); + UInt64 pos = item.DataPosition + item.PackSize; + if (_arc.Header.ArchiveSize == 0) + _phySize = pos; + if (pos > endPos) + { + _arc.Error = k_ErrorType_UnexpectedEnd; + break; + } - _archive.NumFiles = _items.Size(); - _archive.NumBytes = item.DataPosition; + RINOK(inStream->Seek(pos, STREAM_SEEK_SET, NULL)); + _arc.NumFiles = _items.Size(); + _arc.Processed = pos; - if (callback != NULL && _items.Size() % 100 == 0) + if (callback && (_items.Size() & 0xFF) == 0) { - RINOK(callback->SetCompleted(&_archive.NumFiles, &_archive.NumBytes)); + RINOK(callback->SetCompleted(&_arc.NumFiles, &_arc.Processed)); } } return S_OK; } STDMETHODIMP CHandler::Open(IInStream *inStream, - const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback) + const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback *callback) { COM_TRY_BEGIN HRESULT res; - try { - res = Open2(inStream, maxCheckStartPosition, callback); + res = Open2(inStream, 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() { + _arc.Close(); + _phySize = 0; _items.Clear(); _stream.Release(); return S_OK; @@ -657,7 +645,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, { COM_TRY_BEGIN UInt64 totalUnpacked = 0, totalPacked = 0; - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _items.Size(); if (numItems == 0) @@ -736,28 +724,28 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 opRes = NExtract::NOperationResult::kOK; if (item.IsEncrypted()) - opRes = NExtract::NOperationResult::kUnSupportedMethod; + opRes = NExtract::NOperationResult::kUnsupportedMethod; else { - switch(item.Method) + switch (item.Method) { - case NFileHeader::NCompressionMethod::kStored: + case 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: + case NCompressionMethod::kCompressed1a: + case NCompressionMethod::kCompressed1b: + case NCompressionMethod::kCompressed1c: { if (!arj1Decoder) arj1Decoder = new NCompress::NArj::NDecoder1::CCoder; result = arj1Decoder->Code(inStream, outStream, NULL, &curUnpacked, progress); break; } - case NFileHeader::NCompressionMethod::kCompressed2: + case NCompressionMethod::kCompressed2: { if (!arj2Decoder) arj2Decoder = new NCompress::NArj::NDecoder2::CCoder; @@ -765,7 +753,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, break; } default: - opRes = NExtract::NOperationResult::kUnSupportedMethod; + opRes = NExtract::NOperationResult::kUnsupportedMethod; } } if (opRes == NExtract::NOperationResult::kOK) @@ -788,10 +776,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_END } -static IInArchive *CreateArc() { return new CHandler; } +IMP_CreateArcIn static CArcInfo g_ArcInfo = - { L"Arj", L"arj", 0, 4, { 0x60, 0xEA }, 2, false, CreateArc, 0 }; + { "Arj", "arj", 0, 4, + 2, { kSig0, kSig1 }, + 0, + 0, + CreateArc, NULL, IsArc_Arj }; REGISTER_ARC(Arj) diff --git a/CPP/7zip/Archive/Bz2Handler.cpp b/CPP/7zip/Archive/Bz2Handler.cpp old mode 100755 new mode 100644 index 49ae8c79..704cdc73 --- a/CPP/7zip/Archive/Bz2Handler.cpp +++ b/CPP/7zip/Archive/Bz2Handler.cpp @@ -2,7 +2,7 @@ #include "StdAfx.h" -#include "Common/ComTry.h" +#include "../../Common/ComTry.h" #include "../Common/ProgressUtils.h" #include "../Common/RegisterArc.h" @@ -29,37 +29,70 @@ class CHandler: { CMyComPtr _stream; CMyComPtr _seqStream; + + bool _isArc; + bool _needSeekToStart; + bool _dataAfterEnd; + bool _needMoreInput; + + bool _packSize_Defined; + bool _unpackSize_Defined; + bool _numStreams_Defined; + bool _numBlocks_Defined; + UInt64 _packSize; - UInt64 _startPosition; - bool _packSizeDefined; + UInt64 _unpackSize; + UInt64 _numStreams; + UInt64 _numBlocks; CSingleMethodProps _props; public: - MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties) - + 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); + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); CHandler() { } }; -static const STATPROPSTG kProps[] = +static const Byte kProps[] = { - { NULL, kpidPackSize, VT_UI8} + kpidSize, + kpidPackSize +}; + +static const Byte kArcProps[] = +{ + kpidNumStreams, + kpidNumBlocks }; IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO_Table +IMP_IInArchive_ArcProps STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { NCOM::CPropVariant prop; switch (propID) { - case kpidPhySize: if (_packSizeDefined) prop = _packSize; break; + case kpidPhySize: if (_packSize_Defined) prop = _packSize; break; + case kpidUnpackSize: if (_unpackSize_Defined) prop = _unpackSize; break; + case kpidNumStreams: if (_numStreams_Defined) prop = _numStreams; break; + case kpidNumBlocks: if (_numBlocks_Defined) prop = _numBlocks; break; + case kpidErrorFlags: + { + UInt32 v = 0; + if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;; + if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd; + if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd; + prop = v; + } } prop.Detach(value); return S_OK; @@ -71,54 +104,75 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) return S_OK; } -STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) { - NWindows::NCOM::CPropVariant prop; + NCOM::CPropVariant prop; switch (propID) { - case kpidPackSize: if (_packSizeDefined) prop = _packSize; break; + case kpidPackSize: if (_packSize_Defined) prop = _packSize; break; + case kpidSize: if (_unpackSize_Defined) prop = _unpackSize; break; } prop.Detach(value); return S_OK; } -STDMETHODIMP CHandler::Open(IInStream *stream, - const UInt64 * /* maxCheckStartPosition */, - IArchiveOpenCallback * /* openArchiveCallback */) +static const unsigned kSignatureCheckSize = 10; + +API_FUNC_static_IsArc IsArc_BZip2(const Byte *p, size_t size) +{ + if (size < kSignatureCheckSize) + return k_IsArc_Res_NEED_MORE; + if (p[0] != 'B' || p[1] != 'Z' || p[2] != 'h' || p[3] < '1' || p[3] > '9') + return k_IsArc_Res_NO; + p += 4; + if (NCompress::NBZip2::IsBlockSig(p)) + return k_IsArc_Res_YES; + if (NCompress::NBZip2::IsEndSig(p)) + return k_IsArc_Res_YES; + return k_IsArc_Res_NO; +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *) { COM_TRY_BEGIN - try + Close(); { - 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') + Byte buf[kSignatureCheckSize]; + RINOK(ReadStream_FALSE(stream, buf, kSignatureCheckSize)); + if (IsArc_BZip2(buf, kSignatureCheckSize) == k_IsArc_Res_NO) return S_FALSE; - - UInt64 endPosition; - RINOK(stream->Seek(0, STREAM_SEEK_END, &endPosition)); - _packSize = endPosition - _startPosition; - _packSizeDefined = true; + _isArc = true; _stream = stream; _seqStream = stream; + _needSeekToStart = true; } - catch(...) { return S_FALSE; } return S_OK; COM_TRY_END } + STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) { Close(); + _isArc = true; _seqStream = stream; return S_OK; } STDMETHODIMP CHandler::Close() { - _packSizeDefined = false; + _isArc = false; + _needSeekToStart = false; + _dataAfterEnd = false; + _needMoreInput = false; + + _packSize_Defined = false; + _unpackSize_Defined = false; + _numStreams_Defined = false; + _numBlocks_Defined = false; + + _packSize = 0; + _seqStream.Release(); _stream.Release(); return S_OK; @@ -130,13 +184,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_BEGIN if (numItems == 0) return S_OK; - if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0)) + if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) return E_INVALIDARG; - if (_stream) + if (_packSize_Defined) extractCallback->SetTotal(_packSize); - UInt64 currentTotalPacked = 0; - RINOK(extractCallback->SetCompleted(¤tTotalPacked)); + + // RINOK(extractCallback->SetCompleted(&packSize)); + CMyComPtr realOutStream; Int32 askMode = testMode ? NExtract::NAskMode::kTest : @@ -147,14 +202,23 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, extractCallback->PrepareOperation(askMode); - NCompress::NBZip2::CDecoder *decoderSpec = new NCompress::NBZip2::CDecoder; - CMyComPtr decoder = decoderSpec; - if (_stream) + if (_needSeekToStart) { - RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); + if (!_stream) + return E_FAIL; + RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL)); } + else + _needSeekToStart = true; + + Int32 opRes; + + try + { + NCompress::NBZip2::CDecoder *decoderSpec = new NCompress::NBZip2::CDecoder; + CMyComPtr decoder = decoderSpec; decoderSpec->SetInStream(_seqStream); #ifndef _7ZIP_ST @@ -172,43 +236,104 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CMyComPtr progress = lps; lps->Init(extractCallback, true); + UInt64 packSize = 0; + UInt64 unpackedSize = 0; + UInt64 numStreams = 0; + + decoderSpec->InitNumBlocks(); + HRESULT result = S_OK; - bool firstItem = true; for (;;) { - lps->InSize = currentTotalPacked; - lps->OutSize = outStreamSpec->GetSize(); + lps->InSize = packSize; + lps->OutSize = unpackedSize; RINOK(lps->SetCur()); - bool isBz2; - result = decoderSpec->CodeResume(outStream, isBz2, progress); + result = decoderSpec->CodeResume(outStream, progress); - if (result != S_OK) + if (result != S_FALSE && result != S_OK) + return result; + + if (decoderSpec->IsBz) + numStreams++; + else if (numStreams == 0) + { + _isArc = false; + result = S_FALSE; + break; + } + + unpackedSize = outStreamSpec->GetSize(); + UInt64 streamSize = decoderSpec->GetStreamSize(); + + if (streamSize == packSize) + { + // no new bytes in input stream, So it's good end of archive. + result = S_OK; + break; + } + + if (!decoderSpec->IsBz) + { + _dataAfterEnd = true; + result = S_FALSE; break; - if (!isBz2) + } + + if (decoderSpec->Base.BitDecoder.ExtraBitsWereRead()) { - if (firstItem) - result = S_FALSE; + _needMoreInput = true; + packSize = streamSize; + result = S_FALSE; break; } - firstItem = false; - _packSize = currentTotalPacked = decoderSpec->GetInputProcessedSize(); - _packSizeDefined = true; + packSize = decoderSpec->GetInputProcessedSize(); + + if (packSize > streamSize) + return E_FAIL; + + if (result != S_OK) + break; } + + if (numStreams != 0) + { + _packSize = packSize; + _unpackSize = unpackedSize; + _numStreams = numStreams; + _numBlocks = decoderSpec->GetNumBlocks(); + + _packSize_Defined = true; + _unpackSize_Defined = true; + _numStreams_Defined = true; + _numBlocks_Defined = true; + } + decoderSpec->ReleaseInStream(); outStream.Release(); - Int32 retResult; - if (result == S_OK) - retResult = NExtract::NOperationResult::kOK; + if (!_isArc) + opRes = NExtract::NOperationResult::kIsNotArc; + else if (_needMoreInput) + opRes = NExtract::NOperationResult::kUnexpectedEnd; + else if (decoderSpec->CrcError) + opRes = NExtract::NOperationResult::kCRCError; + else if (_dataAfterEnd) + opRes = NExtract::NOperationResult::kDataAfterEnd; else if (result == S_FALSE) - retResult = NExtract::NOperationResult::kDataError; + opRes = NExtract::NOperationResult::kDataError; + else if (result == S_OK) + opRes = NExtract::NOperationResult::kOK; else return result; - return extractCallback->SetOperationResult(retResult); + + } + catch(const CInBufferException &e) { return e.ErrorCode; } + + return extractCallback->SetOperationResult(opRes); COM_TRY_END } @@ -280,24 +405,24 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (indexInArchive != 0) return E_INVALIDARG; if (_stream) - RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); + RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL)); return NCompress::CopyStream(_stream, outStream, NULL); } -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) { return _props.SetProperties(names, values, numProps); } -static IInArchive *CreateArc() { return new CHandler; } -#ifndef EXTRACT_ONLY -static IOutArchive *CreateArcOut() { return new CHandler; } -#else -#define CreateArcOut 0 -#endif +IMP_CreateArcIn +IMP_CreateArcOut static CArcInfo g_ArcInfo = - { L"bzip2", L"bz2 bzip2 tbz2 tbz", L"* * .tar .tar", 2, { 'B', 'Z', 'h' }, 3, true, CreateArc, CreateArcOut }; + { "bzip2", "bz2 bzip2 tbz2 tbz", "* * .tar .tar", 2, + 3, { 'B', 'Z', 'h' }, + 0, + NArcInfoFlags::kKeepName, + REF_CreateArc_Pair, IsArc_BZip2 }; REGISTER_ARC(BZip2) diff --git a/CPP/7zip/Archive/Cab/CabBlockInStream.cpp b/CPP/7zip/Archive/Cab/CabBlockInStream.cpp old mode 100755 new mode 100644 index 12c73eb5..cebec610 --- a/CPP/7zip/Archive/Cab/CabBlockInStream.cpp +++ b/CPP/7zip/Archive/Cab/CabBlockInStream.cpp @@ -3,8 +3,7 @@ #include "StdAfx.h" #include "../../../../C/Alloc.h" - -#include "Common/Defs.h" +#include "../../../../C/CpuArch.h" #include "../../Common/StreamUtils.h" @@ -17,173 +16,73 @@ static const UInt32 kBlockSize = (1 << 16); bool CCabBlockInStream::Create() { - if (!_buffer) - _buffer = (Byte *)::MyAlloc(kBlockSize); - return (_buffer != 0); + if (!_buf) + _buf = (Byte *)::MyAlloc(kBlockSize); + return _buf != 0; } CCabBlockInStream::~CCabBlockInStream() { - MyFree(_buffer); + ::MyFree(_buf); } -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) +static UInt32 CheckSum(const Byte *p, 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 sum = 0; + for (UInt32 i = size >> 2; i != 0; i--) { - UInt32 temp = *dataPointer++; - temp |= ((UInt32)(*dataPointer++)) << 8; - temp |= ((UInt32)(*dataPointer++)) << 16; - temp |= ((UInt32)(*dataPointer++)) << 24; - checkSum ^= temp; + sum ^= GetUi32(p); + p += 4; } - m_Value = checkSum; - size &= 3; - - while (size != 0) - { - m_Hist[m_Pos] = *dataPointer++; - m_Pos = (m_Pos + 1) & 3; - size--; - } + if (size > 2) sum ^= (UInt32)(*p++) << 16; + if (size > 1) sum ^= (UInt32)(*p++) << 8; + if (size > 0) sum ^= (UInt32)(*p++); + return sum; } -static const UInt32 kDataBlockHeaderSize = 8; - -class CTempCabInBuffer2 +HRESULT CCabBlockInStream::PreRead(ISequentialInStream *stream, UInt32 &packSize, UInt32 &unpackSize) { -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) + const UInt32 kHeaderSize = 8; + const UInt32 kReservedMax = 256; + Byte header[kHeaderSize + kReservedMax]; + RINOK(ReadStream_FALSE(stream, header, kHeaderSize + ReservedSize)) + packSize = GetUi16(header + 4); + unpackSize = GetUi16(header + 6); + if (packSize > kBlockSize - _size) + return S_FALSE; + RINOK(ReadStream_FALSE(stream, _buf + _size, packSize)); + + if (MsZip) { - if (packSize < 2) - return S_FALSE; // bad block; - Byte sig[2]; - RINOK(ReadStream_FALSE(_stream, sig, 2)); - if (sig[0] != 0x43 || sig[1] != 0x4B) + if (_size == 0) + { + if (packSize < 2 || _buf[0] != 0x43 || _buf[1] != 0x4B) + return S_FALSE; + _pos = 2; + } + if (_size + packSize > ((UInt32)1 << 15) + 12) /* v9.31 fix. MSZIP specification */ 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) + if (GetUi32(header) != 0) // checkSum + if (CheckSum(header, kHeaderSize + ReservedSize) != CheckSum(_buf + _size, packSize)) 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; + _size += packSize; + return 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 + UInt32 rem = _size - _pos; + if (size > rem) + size = rem; + memcpy(data, _buf + _pos, size); + _pos += size; + if (processedSize) + *processedSize = size; + return S_OK; } }} diff --git a/CPP/7zip/Archive/Cab/CabBlockInStream.h b/CPP/7zip/Archive/Cab/CabBlockInStream.h old mode 100755 new mode 100644 index 1db3835b..b795ed97 --- a/CPP/7zip/Archive/Cab/CabBlockInStream.h +++ b/CPP/7zip/Archive/Cab/CabBlockInStream.h @@ -1,9 +1,9 @@ -// CabBlockInStream.cpp +// CabBlockInStream.h -#ifndef __CABBLOCKINSTREAM_H -#define __CABBLOCKINSTREAM_H +#ifndef __CAB_BLOCK_IN_STREAM_H +#define __CAB_BLOCK_IN_STREAM_H -#include "Common/MyCom.h" +#include "../../../Common/MyCom.h" #include "../../IStream.h" namespace NArchive { @@ -13,30 +13,23 @@ class CCabBlockInStream: public ISequentialInStream, public CMyUnknownImp { - CMyComPtr _stream; - Byte *_buffer; - UInt32 _pos; + Byte *_buf; UInt32 _size; + UInt32 _pos; public: - UInt32 TotalPackSize; - UInt32 ReservedSize; - bool DataError; + UInt32 ReservedSize; // < 256 bool MsZip; - CCabBlockInStream(): _buffer(0), ReservedSize(0), MsZip(false), DataError(false), TotalPackSize(0) {} + MY_UNKNOWN_IMP + + CCabBlockInStream(): _buf(0), ReservedSize(0), MsZip(false) {} ~CCabBlockInStream(); bool Create(); - void SetStream(ISequentialInStream *stream) { _stream = stream; } - - void InitForNewFolder() { TotalPackSize = 0; } - void InitForNewBlock() { _size = 0; } - - MY_UNKNOWN_IMP + void InitForNewBlock() { _size = 0; _pos = 0; } + HRESULT PreRead(ISequentialInStream *stream, UInt32 &packSize, UInt32 &unpackSize); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - - HRESULT PreRead(UInt32 &packSize, UInt32 &unpackSize); }; }} diff --git a/CPP/7zip/Archive/Cab/CabHandler.cpp b/CPP/7zip/Archive/Cab/CabHandler.cpp old mode 100755 new mode 100644 index fd707fe5..22bc93a0 --- a/CPP/7zip/Archive/Cab/CabHandler.cpp +++ b/CPP/7zip/Archive/Cab/CabHandler.cpp @@ -2,15 +2,17 @@ #include "StdAfx.h" +// #include + #include "../../../../C/Alloc.h" -#include "Common/ComTry.h" -#include "Common/IntToString.h" -#include "Common/StringConvert.h" -#include "Common/UTFConvert.h" +#include "../../../Common/ComTry.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/UTFConvert.h" -#include "Windows/PropVariant.h" -#include "Windows/Time.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/TimeUtils.h" #include "../../Common/ProgressUtils.h" #include "../../Common/StreamUtils.h" @@ -39,102 +41,243 @@ enum }; #endif -static STATPROPSTG kProps[] = +static const Byte 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} + kpidPath, + kpidSize, + kpidMTime, + kpidAttrib, + kpidMethod, + kpidBlock #ifdef _CAB_DETAILS , - { L"BlockReal", kpidBlockReal, VT_UI4}, - { NULL, kpidOffset, VT_UI4}, - { NULL, kpidVolume, VT_UI4} + // kpidBlockReal, // L"BlockReal", + kpidOffset, + kpidVolume #endif }; -static const char *kMethods[] = +static const Byte kArcProps[] = { - "None", - "MSZip", - "Quantum", - "LZX" + kpidTotalPhySize, + kpidMethod, + // kpidSolid, + kpidNumBlocks, + kpidNumVolumes, + kpidVolumeIndex, + kpidId }; -static const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]); -static const char *kUnknownMethod = "Unknown"; +IMP_IInArchive_Props +IMP_IInArchive_ArcProps -static STATPROPSTG kArcProps[] = +static const char *kMethods[] = { - { NULL, kpidMethod, VT_BSTR}, - // { NULL, kpidSolid, VT_BOOL}, - { NULL, kpidNumBlocks, VT_UI4}, - { NULL, kpidNumVolumes, VT_UI4} + "None" + , "MSZip" + , "Quantum" + , "LZX" }; -IMP_IInArchive_Props -IMP_IInArchive_ArcProps +static const unsigned kMethodNameBufSize = 32; // "Quantum:255" + +static void SetMethodName(char *s, unsigned method, unsigned param) +{ + if (method < ARRAY_SIZE(kMethods)) + { + s = MyStpCpy(s, kMethods[method]); + if (method != NHeader::NMethod::kLZX && + method != NHeader::NMethod::kQuantum) + return; + *s++ = ':'; + method = param; + } + ConvertUInt32ToString(method, s); +} STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; - switch(propID) + NCOM::CPropVariant prop; + switch (propID) { case kpidMethod: { - AString resString; - CRecordVector ids; - int i; - for (int v = 0; v < m_Database.Volumes.Size(); v++) + UInt32 mask = 0; + UInt32 params[2] = { 0, 0 }; { - const CDatabaseEx &de = m_Database.Volumes[v]; - for (i = 0; i < de.Folders.Size(); i++) - ids.AddToUniqueSorted(de.Folders[i].GetCompressionMethod()); + FOR_VECTOR (v, m_Database.Volumes) + { + const CRecordVector &folders = m_Database.Volumes[v].Folders; + FOR_VECTOR (i, folders) + { + const CFolder &folder = folders[i]; + unsigned method = folder.GetMethod(); + mask |= ((UInt32)1 << method); + if (method == NHeader::NMethod::kLZX || + method == NHeader::NMethod::kQuantum) + { + unsigned di = (method == NHeader::NMethod::kQuantum) ? 0 : 1; + if (params[di] < folder.MethodMinor) + params[di] = folder.MethodMinor; + } + } + } } - for (i = 0; i < ids.Size(); i++) + AString s; + for (unsigned i = 0; i < kNumMethodsMax; i++) { - Byte id = ids[i]; - AString method = (id < kNumMethods) ? kMethods[id] : kUnknownMethod; - if (!resString.IsEmpty()) - resString += ' '; - resString += method; + if ((mask & (1 << i)) == 0) + continue; + if (!s.IsEmpty()) + s += ' '; + char temp[kMethodNameBufSize]; + SetMethodName(temp, i, params[i == NHeader::NMethod::kQuantum ? 0 : 1]); + s += temp; } - prop = resString; + prop = s; break; } // case kpidSolid: prop = _database.IsSolid(); break; case kpidNumBlocks: { UInt32 numFolders = 0; - for (int v = 0; v < m_Database.Volumes.Size(); v++) + FOR_VECTOR (v, m_Database.Volumes) numFolders += m_Database.Volumes[v].Folders.Size(); prop = numFolders; break; } - case kpidNumVolumes: + + case kpidTotalPhySize: { + if (m_Database.Volumes.Size() > 1) + { + UInt64 sum = 0; + FOR_VECTOR (v, m_Database.Volumes) + sum += m_Database.Volumes[v].ArcInfo.Size; + prop = sum; + } + break; + } + + case kpidNumVolumes: prop = (UInt32)m_Database.Volumes.Size(); break; + + case kpidVolumeIndex: + { + if (m_Database.Volumes.Size() == 1) + { + const CDatabaseEx &db = m_Database.Volumes[0]; + const CInArcInfo &ai = db.ArcInfo; + prop = (UInt32)ai.CabinetNumber; + } + break; + } + + case kpidId: + { + if (m_Database.Volumes.Size() != 0) + { + prop = (UInt32)m_Database.Volumes[0].ArcInfo.SetID; + } + break; + } + + case kpidOffset: + /* + if (m_Database.Volumes.Size() == 1) + prop = m_Database.Volumes[0].StartPosition; + */ + prop = _offset; + break; + + case kpidPhySize: + /* + if (m_Database.Volumes.Size() == 1) + prop = (UInt64)m_Database.Volumes[0].ArcInfo.Size; + */ + prop = (UInt64)_phySize; + break; + + case kpidErrorFlags: + { + UInt32 v = 0; + if (!_isArc) v |= kpv_ErrorFlags_IsNotArc; + if (_errorInHeaders) v |= kpv_ErrorFlags_HeadersError; + if (_unexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd; + prop = v; + break; + } + + case kpidError: + if (!_errorMessage.IsEmpty()) + prop = _errorMessage; + break; + + case kpidName: + { + if (m_Database.Volumes.Size() == 1) + { + const CDatabaseEx &db = m_Database.Volumes[0]; + const CInArcInfo &ai = db.ArcInfo; + if (ai.SetID != 0) + { + AString s; + char temp[32]; + ConvertUInt32ToString(ai.SetID, temp); + s += temp; + ConvertUInt32ToString(ai.CabinetNumber + 1, temp); + s += '_'; + s += temp; + s += ".cab"; + prop = s; + } + /* + // that code is incomplete. It gcan give accurate name of volume + char s[32]; + ConvertUInt32ToString(ai.CabinetNumber + 2, s); + unsigned len = MyStringLen(s); + if (ai.IsThereNext()) + { + AString fn = ai.NextArc.FileName; + if (fn.Len() > 4 && StringsAreEqualNoCase_Ascii(fn.RightPtr(4), ".cab")) + fn.DeleteFrom(fn.Len() - 4); + if (len < fn.Len()) + { + if (strcmp(s, fn.RightPtr(len)) == 0) + { + AString s2 = fn; + s2.DeleteFrom(fn.Len() - len); + ConvertUInt32ToString(ai.CabinetNumber + 1, s); + s2 += s; + s2 += ".cab"; + prop = GetUnicodeString(s2); + } + } + } + */ + } + break; } + + // case kpidShortComment: } prop.Detach(value); return S_OK; COM_TRY_END } -STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; + NCOM::CPropVariant prop; const CMvItem &mvItem = m_Database.Items[index]; const CDatabaseEx &db = m_Database.Volumes[mvItem.VolumeIndex]; - int itemIndex = mvItem.ItemIndex; + unsigned itemIndex = mvItem.ItemIndex; const CItem &item = db.Items[itemIndex]; - switch(propID) + switch (propID) { case kpidPath: { @@ -146,9 +289,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va 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 kpidAttrib: prop = item.GetWinAttrib(); break; case kpidMTime: { @@ -168,24 +312,17 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va { 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; + char s[kMethodNameBufSize];; + SetMethodName(s, folder.GetMethod(), folder.MethodMinor); + prop = s; break; } + case kpidBlock: prop = (Int32)m_Database.GetFolderIndex(&mvItem); break; #ifdef _CAB_DETAILS - case kpidBlockReal: prop = (UInt32)item.FolderIndex; break; + // case kpidBlockReal: prop = (UInt32)item.FolderIndex; break; case kpidOffset: prop = (UInt32)item.Offset; break; case kpidVolume: prop = (UInt32)mvItem.VolumeIndex; break; @@ -196,39 +333,13 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va 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); @@ -236,96 +347,169 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, CMyComPtr nextStream = inStream; bool prevChecked = false; UInt64 numItems = 0; - try + unsigned numTempVolumes = 0; + // try { - while (nextStream != 0) + while (nextStream != NULL) { CDatabaseEx db; db.Stream = nextStream; - res = archive.Open(maxCheckStartPosition, db); - if (res == S_OK) + HRESULT res = archive.Open(db, maxCheckStartPosition); + _errorInHeaders |= archive.HeaderError; + _errorInHeaders |= archive.ErrorInNames; + _unexpectedEnd |= archive.UnexpectedEnd; + + if (res == S_OK && !m_Database.Volumes.IsEmpty()) { - if (!m_Database.Volumes.IsEmpty()) + const CArchInfo &lastArc = m_Database.Volumes.Back().ArcInfo; + unsigned cabNumber = db.ArcInfo.CabinetNumber; + if (lastArc.SetID != db.ArcInfo.SetID) + res = S_FALSE; + else if (prevChecked) + { + if (cabNumber != lastArc.CabinetNumber + 1) + res = S_FALSE; + } + else if (cabNumber >= lastArc.CabinetNumber) + res = S_FALSE; + else if (numTempVolumes != 0) { - 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) + const CArchInfo &prevArc = m_Database.Volumes[numTempVolumes - 1].ArcInfo; + if (cabNumber != prevArc.CabinetNumber + 1) res = S_FALSE; } } + + if (archive.IsArc || res == S_OK) + { + _isArc = true; + if (m_Database.Volumes.IsEmpty()) + { + _offset = db.StartPosition; + _phySize = db.ArcInfo.Size; + } + } + if (res == S_OK) - m_Database.Volumes.Insert(prevChecked ? m_Database.Volumes.Size() : 0, db); - else if (res != S_FALSE) - return res; + { + numItems += db.Items.Size(); + m_Database.Volumes.Insert(prevChecked ? m_Database.Volumes.Size() : numTempVolumes, db); + if (!prevChecked && m_Database.Volumes.Size() > 1) + { + numTempVolumes++; + if (db.ArcInfo.CabinetNumber + 1 == m_Database.Volumes[numTempVolumes].ArcInfo.CabinetNumber) + numTempVolumes = 0; + } + } else { + if (res != S_FALSE) + return res; if (m_Database.Volumes.IsEmpty()) return S_FALSE; if (prevChecked) break; prevChecked = true; + if (numTempVolumes != 0) + { + m_Database.Volumes.DeleteFrontal(numTempVolumes); + numTempVolumes = 0; + } } - numItems += db.Items.Size(); RINOK(callback->SetCompleted(&numItems, NULL)); - nextStream = 0; + nextStream = NULL; + for (;;) { - const COtherArchive *otherArchive = 0; + const COtherArc *otherArc = NULL; if (!prevChecked) { - const CInArchiveInfo &ai = m_Database.Volumes.Front().ArchiveInfo; - if (ai.IsTherePrev()) - otherArchive = &ai.PrevArc; + if (numTempVolumes == 0) + { + const CInArcInfo &ai = m_Database.Volumes[0].ArcInfo; + if (ai.IsTherePrev()) + otherArc = &ai.PrevArc; + else + prevChecked = true; + } else - prevChecked = true; + { + const CInArcInfo &ai = m_Database.Volumes[numTempVolumes - 1].ArcInfo; + if (ai.IsThereNext()) + otherArc = &ai.NextArc; + else + { + prevChecked = true; + m_Database.Volumes.DeleteFrontal(numTempVolumes); + numTempVolumes = 0; + } + } } - if (otherArchive == 0) + if (!otherArc) { - const CInArchiveInfo &ai = m_Database.Volumes.Back().ArchiveInfo; + const CInArcInfo &ai = m_Database.Volumes.Back().ArcInfo; if (ai.IsThereNext()) - otherArchive = &ai.NextArc; + otherArc = &ai.NextArc; } - if (!otherArchive) + if (!otherArc) break; - const UString fullName = MultiByteToUnicodeString(otherArchive->FileName, CP_ACP); if (!openVolumeCallback) break; - + // printf("\n%s", otherArc->FileName); + const UString fullName = MultiByteToUnicodeString(otherArc->FileName, CP_ACP); HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream); if (result == S_OK) break; if (result != S_FALSE) return result; + + if (!_errorMessage.IsEmpty()) + _errorMessage += L"\n"; + _errorMessage += L"Can't open volume: "; + _errorMessage += fullName; + if (prevChecked) break; prevChecked = true; + if (numTempVolumes != 0) + { + m_Database.Volumes.DeleteFrontal(numTempVolumes); + numTempVolumes = 0; + } } + + } // read nextStream iteration + + if (numTempVolumes != 0) + { + m_Database.Volumes.DeleteFrontal(numTempVolumes); + numTempVolumes = 0; } - if (res == S_OK) + if (m_Database.Volumes.IsEmpty()) + return S_FALSE; + else { m_Database.FillSortAndShrink(); if (!m_Database.Check()) - res = S_FALSE; + return S_FALSE; } } - catch(...) - { - res = S_FALSE; - } - if (res != S_OK) - { - Close(); - return res; - } COM_TRY_END return S_OK; } STDMETHODIMP CHandler::Close() { + _errorMessage.Empty(); + _isArc = false; + _errorInHeaders = false; + _unexpectedEnd = false; + // _mainVolIndex = -1; + _phySize = 0; + _offset = 0; + m_Database.Clear(); return S_OK; } @@ -348,8 +532,8 @@ private: bool TempBufMode; UInt32 m_BufStartFolderOffset; - int m_StartIndex; - int m_CurrentIndex; + unsigned m_StartIndex; + unsigned m_CurrentIndex; CMyComPtr m_ExtractCallback; bool m_TestMode; @@ -379,7 +563,7 @@ public: void Init( const CMvDatabaseEx *database, const CRecordVector *extractStatuses, - int startIndex, + unsigned startIndex, UInt64 folderSize, IArchiveExtractCallback *extractCallback, bool testMode); @@ -393,7 +577,7 @@ public: void CFolderOutStream::Init( const CMvDatabaseEx *database, const CRecordVector *extractStatuses, - int startIndex, + unsigned startIndex, UInt64 folderSize, IArchiveExtractCallback *extractCallback, bool testMode) @@ -436,7 +620,7 @@ HRESULT CFolderOutStream::OpenFile() const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex]; const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; int numExtractItems = 0; - int curIndex; + unsigned curIndex; for (curIndex = m_CurrentIndex; curIndex < m_ExtractStatuses->Size(); curIndex++) { const CMvItem &mvItem2 = m_Database->Items[m_StartIndex + curIndex]; @@ -559,7 +743,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe if (!TempBuf && TempBufMode && m_RealOutStream) { - RINOK(CloseFileWithResOp(NExtract::NOperationResult::kUnSupportedMethod)); + RINOK(CloseFileWithResOp(NExtract::NOperationResult::kUnsupportedMethod)); } else { @@ -638,7 +822,7 @@ HRESULT CFolderOutStream::Unsupported() if (result != S_FALSE && result != S_OK) return result; m_RealOutStream.Release(); - RINOK(m_ExtractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod)); + RINOK(m_ExtractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod)); m_CurrentIndex++; } return S_OK; @@ -649,7 +833,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testModeSpec, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = m_Database.Items.Size(); if (numItems == 0) @@ -709,7 +893,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, const CMvItem &mvItem = m_Database.Items[index]; const CDatabaseEx &db = m_Database.Volumes[mvItem.VolumeIndex]; - int itemIndex = mvItem.ItemIndex; + unsigned itemIndex = mvItem.ItemIndex; const CItem &item = db.Items[itemIndex]; i++; @@ -747,7 +931,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, extractStatuses.Add(true); startIndex++; UInt64 curUnpack = item.GetEndOffset(); - for(;i < numItems; i++) + for (; i < numItems; i++) { int indexNext = allFilesMode ? i : indices[i]; const CMvItem &mvItem = m_Database.Items[indexNext]; @@ -779,11 +963,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, cabBlockInStreamSpec->MsZip = false; HRESULT res = S_OK; - switch(folder.GetCompressionMethod()) + switch (folder.GetMethod()) { - case NHeader::NCompressionMethodMajor::kNone: + case NHeader::NMethod::kNone: break; - case NHeader::NCompressionMethodMajor::kMSZip: + case NHeader::NMethod::kMSZip: if (!deflateDecoder) { deflateDecoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder; @@ -791,21 +975,21 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } cabBlockInStreamSpec->MsZip = true; break; - case NHeader::NCompressionMethodMajor::kLZX: + case NHeader::NMethod::kLZX: if (!lzxDecoder) { lzxDecoderSpec = new NCompress::NLzx::CDecoder; lzxDecoder = lzxDecoderSpec; } - res = lzxDecoderSpec->SetParams(folder.CompressionTypeMinor); + res = lzxDecoderSpec->SetParams(folder.MethodMinor); break; - case NHeader::NCompressionMethodMajor::kQuantum: + case NHeader::NMethod::kQuantum: if (!quantumDecoder) { quantumDecoderSpec = new NCompress::NQuantum::CDecoder; quantumDecoder = quantumDecoderSpec; } - res = quantumDecoderSpec->SetParams(folder.CompressionTypeMinor); + res = quantumDecoderSpec->SetParams(folder.MethodMinor); break; default: res = E_INVALIDARG; @@ -820,9 +1004,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } RINOK(res); - cabBlockInStreamSpec->InitForNewFolder(); { - int volIndex = mvItem.VolumeIndex; + unsigned volIndex = mvItem.VolumeIndex; int locFolderIndex = item.GetFolderIndex(db.Folders.Size()); bool keepHistory = false; bool keepInputBuffer = false; @@ -838,8 +1021,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, const CFolder &folder = db.Folders[locFolderIndex]; if (f == 0) { - cabBlockInStreamSpec->SetStream(db.Stream); - cabBlockInStreamSpec->ReservedSize = db.ArchiveInfo.GetDataBlockReserveSize(); + cabBlockInStreamSpec->ReservedSize = db.ArcInfo.GetDataBlockReserveSize(); RINOK(db.Stream->Seek(db.StartPosition + folder.DataStart, STREAM_SEEK_SET, NULL)); } if (f == folder.NumDataBlocks) @@ -851,13 +1033,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } f++; - cabBlockInStreamSpec->DataError = false; - if (!keepInputBuffer) cabBlockInStreamSpec->InitForNewBlock(); UInt32 packSize, unpackSize; - res = cabBlockInStreamSpec->PreRead(packSize, unpackSize); + res = cabBlockInStreamSpec->PreRead(db.Stream, packSize, unpackSize); if (res == S_FALSE) break; RINOK(res); @@ -878,22 +1058,36 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (unpackRemain > kBlockSizeMax) unpackRemain = kBlockSizeMax; if (unpackRemain > unpackSize) - unpackRemain = unpackSize; + unpackRemain = unpackSize; - switch(folder.GetCompressionMethod()) + switch (folder.GetMethod()) { - case NHeader::NCompressionMethodMajor::kNone: + case NHeader::NMethod::kNone: res = copyCoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL); break; - case NHeader::NCompressionMethodMajor::kMSZip: - deflateDecoderSpec->SetKeepHistory(keepHistory); + case NHeader::NMethod::kMSZip: + deflateDecoderSpec->Set_KeepHistory(keepHistory); + /* v9.31: now we follow MSZIP specification that requires to finish deflate stream at the end of each block. + But PyCabArc can create CAB archives that doesn't have finish marker at the end of block. + Cabarc probably ignores such errors in cab archives. + Maybe we also should ignore that error? + Or we should extract full file and show the warning? */ + deflateDecoderSpec->Set_NeedFinishInput(true); res = deflateDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL); + if (res == S_OK) + { + if (!deflateDecoderSpec->IsFinished()) + res = S_FALSE; + if (!deflateDecoderSpec->IsFinalBlock()) + res = S_FALSE; + } + break; - case NHeader::NCompressionMethodMajor::kLZX: + case NHeader::NMethod::kLZX: lzxDecoderSpec->SetKeepHistory(keepHistory); res = lzxDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL); break; - case NHeader::NCompressionMethodMajor::kQuantum: + case NHeader::NMethod::kQuantum: quantumDecoderSpec->SetKeepHistory(keepHistory); res = quantumDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL); break; diff --git a/CPP/7zip/Archive/Cab/CabHandler.h b/CPP/7zip/Archive/Cab/CabHandler.h old mode 100755 new mode 100644 index 1edcd11e..6f44b875 --- a/CPP/7zip/Archive/Cab/CabHandler.h +++ b/CPP/7zip/Archive/Cab/CabHandler.h @@ -3,8 +3,10 @@ #ifndef __CAB_HANDLER_H #define __CAB_HANDLER_H -#include "Common/MyCom.h" +#include "../../../Common/MyCom.h" + #include "../IArchive.h" + #include "CabIn.h" namespace NArchive { @@ -21,6 +23,13 @@ public: private: CMvDatabaseEx m_Database; + UString _errorMessage; + bool _isArc; + bool _errorInHeaders; + bool _unexpectedEnd; + // int _mainVolIndex; + UInt32 _phySize; + UInt64 _offset; }; }} diff --git a/CPP/7zip/Archive/Cab/CabHeader.cpp b/CPP/7zip/Archive/Cab/CabHeader.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Cab/CabHeader.h b/CPP/7zip/Archive/Cab/CabHeader.h old mode 100755 new mode 100644 index 0f0d2af3..9ec0760a --- a/CPP/7zip/Archive/Cab/CabHeader.h +++ b/CPP/7zip/Archive/Cab/CabHeader.h @@ -3,7 +3,7 @@ #ifndef __ARCHIVE_CAB_HEADER_H #define __ARCHIVE_CAB_HEADER_H -#include "Common/Types.h" +#include "../../../Common/MyTypes.h" namespace NArchive { namespace NCab { @@ -12,17 +12,14 @@ namespace NHeader { const unsigned kMarkerSize = 8; extern Byte kMarker[kMarkerSize]; -namespace NArchive +namespace NArcFlags { - namespace NFlags - { - const int kPrevCabinet = 0x0001; - const int kNextCabinet = 0x0002; - const int kReservePresent = 0x0004; - } + const unsigned kPrevCabinet = 1; + const unsigned kNextCabinet = 2; + const unsigned kReservePresent = 4; } -namespace NCompressionMethodMajor +namespace NMethod { const Byte kNone = 0; const Byte kMSZip = 1; @@ -30,13 +27,13 @@ namespace NCompressionMethodMajor const Byte kLZX = 3; } -const int kFileNameIsUTFAttributeMask = 0x80; +const unsigned kFileNameIsUtf8_Mask = 0x80; namespace NFolderIndex { - const int kContinuedFromPrev = 0xFFFD; - const int kContinuedToNext = 0xFFFE; - const int kContinuedPrevAndNext = 0xFFFF; + const unsigned kContinuedFromPrev = 0xFFFD; + const unsigned kContinuedToNext = 0xFFFE; + const unsigned kContinuedPrevAndNext = 0xFFFF; } }}} diff --git a/CPP/7zip/Archive/Cab/CabIn.cpp b/CPP/7zip/Archive/Cab/CabIn.cpp old mode 100755 new mode 100644 index c0bffa2d..c499f05f --- a/CPP/7zip/Archive/Cab/CabIn.cpp +++ b/CPP/7zip/Archive/Cab/CabIn.cpp @@ -2,154 +2,353 @@ #include "StdAfx.h" -#include "../Common/FindSignature.h" +// #include + +#include "../../../../C/CpuArch.h" + +#include "../../Common/LimitedStreams.h" +#include "../../Common/StreamUtils.h" #include "CabIn.h" +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) + namespace NArchive { namespace NCab { -Byte CInArchive::Read8() +struct CUnexpectedEndException {}; + +void CInArchive::Skip(unsigned size) { - Byte b; - if (!inBuffer.ReadByte(b)) - throw CInArchiveException(CInArchiveException::kUnsupported); - return b; + if (_inBuffer.Skip(size) != size) + throw CUnexpectedEndException(); } -UInt16 CInArchive::Read16() +void CInArchive::Read(Byte *data, unsigned size) { - UInt16 value = 0; - for (int i = 0; i < 2; i++) - { - Byte b = Read8(); - value |= (UInt16(b) << (8 * i)); - } - return value; + if (_inBuffer.ReadBytes(data, size) != size) + throw CUnexpectedEndException(); } -UInt32 CInArchive::Read32() +void CInArchive::ReadName(AString &s) { - UInt32 value = 0; - for (int i = 0; i < 4; i++) + for (size_t i = 0; i < ((size_t)1 << 13); i++) { - Byte b = Read8(); - value |= (UInt32(b) << (8 * i)); + Byte b; + if (!_inBuffer.ReadByte(b)) + throw CUnexpectedEndException(); + if (b == 0) + { + memcpy(s.GetBuffer((unsigned)i), _tempBuf, i); + s.ReleaseBuffer((unsigned)i); + return; + } + if (_tempBuf.Size() == i) + _tempBuf.ChangeSize_KeepData(i * 2, i); + _tempBuf[i] = b; } - return value; -} - -AString CInArchive::SafeReadName() -{ - AString name; + for (;;) { - Byte b = Read8(); + Byte b; + if (!_inBuffer.ReadByte(b)) + throw CUnexpectedEndException(); if (b == 0) - return name; - name += (char)b; + break; } + + ErrorInNames = true; + s = "[ERROR-LONG-PATH]"; } -void CInArchive::ReadOtherArchive(COtherArchive &oa) +void CInArchive::ReadOtherArc(COtherArc &oa) { - oa.FileName = SafeReadName(); - oa.DiskName = SafeReadName(); + ReadName(oa.FileName); + ReadName(oa.DiskName); } -void CInArchive::Skip(UInt32 size) +struct CSignatureFinder +{ + Byte *Buf; + UInt32 Pos; + UInt32 End; + const Byte *Signature; + UInt32 SignatureSize; + + UInt32 _HeaderSize; + UInt32 _AlignSize; + UInt32 _BufUseCapacity; + + ISequentialInStream *Stream; + UInt64 Processed; // Global offset of start of Buf + + const UInt64 *SearchLimit; + + UInt32 GetTotalCapacity(UInt32 basicSize, UInt32 headerSize) + { + _HeaderSize = headerSize; + for (_AlignSize = (1 << 5); _AlignSize < _HeaderSize; _AlignSize <<= 1); + _BufUseCapacity = basicSize + _AlignSize; + return _BufUseCapacity + 16; + } + + /* + returns: + S_OK - signature found (at Pos) + S_FALSE - signature not found + */ + HRESULT Find(); +}; + +HRESULT CSignatureFinder::Find() { - while (size-- != 0) - Read8(); + for (;;) + { + Buf[End] = Signature[0]; // it's for fast search; + + while (End - Pos >= _HeaderSize) + { + const Byte *p = Buf + Pos; + Byte b = Signature[0]; + for (;;) + { + if (*p == b) break; p++; + if (*p == b) break; p++; + } + Pos = (UInt32)(p - Buf); + if (End - Pos < _HeaderSize) + { + Pos = End - _HeaderSize + 1; + break; + } + UInt32 i; + for (i = 1; i < SignatureSize && p[i] == Signature[i]; i++); + if (i == SignatureSize) + return S_OK; + Pos++; + } + + if (Pos >= _AlignSize) + { + UInt32 num = (Pos & ~(_AlignSize - 1)); + Processed += num; + Pos -= num; + End -= num; + memmove(Buf, Buf + num, End); + } + UInt32 rem = _BufUseCapacity - End; + if (SearchLimit) + { + if (Processed + Pos > *SearchLimit) + return S_FALSE; + UInt64 rem2 = *SearchLimit - (Processed + End) + _HeaderSize; + if (rem > rem2) + rem = (UInt32)rem2; + } + + UInt32 processedSize; + if (Processed == 0 && rem == _BufUseCapacity - _HeaderSize) + rem -= _AlignSize; // to make reads more aligned. + RINOK(Stream->Read(Buf + End, rem, &processedSize)); + if (processedSize == 0) + return S_FALSE; + End += processedSize; + } } -HRESULT CInArchive::Open(const UInt64 *searchHeaderSizeLimit, CDatabaseEx &db) +bool CInArcInfo::Parse(const Byte *p) +{ + if (Get32(p + 0x0C) != 0 || + Get32(p + 0x14) != 0) + return false; + Size = Get32(p + 8); + if (Size < 36) + return false; + Flags = Get16(p + 0x1E); + if (Flags > 7) + return false; + FileHeadersOffset = Get32(p + 0x10); + if (FileHeadersOffset != 0 && FileHeadersOffset > Size) + return false; + VersionMinor = p[0x18]; + VersionMajor = p[0x19]; + NumFolders = Get16(p + 0x1A); + NumFiles = Get16(p + 0x1C); + return true; +} + +HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit) { - IInStream *stream = db.Stream; + IsArc = false; + ErrorInNames = false; + UnexpectedEnd = false; + HeaderError = false; + 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(); + RINOK(db.Stream->Seek(0, STREAM_SEEK_CUR, &db.StartPosition)); + // UInt64 temp = db.StartPosition; - if (ai.ReserveBlockPresent()) + CByteBuffer buffer; + CInArcInfo &ai = db.ArcInfo; + UInt64 startInBuf = 0; + + CLimitedSequentialInStream *limitedStreamSpec = NULL; + CMyComPtr limitedStream; + + // for (int iii = 0; iii < 10000; iii++) { - ai.PerCabinetAreaSize = Read16(); - ai.PerFolderAreaSize = Read8(); - ai.PerDataBlockAreaSize = Read8(); + // db.StartPosition = temp; RINOK(db.Stream->Seek(db.StartPosition, STREAM_SEEK_SET, NULL)); + + const UInt32 kMainHeaderSize = 32; + Byte header[kMainHeaderSize]; + const UInt32 kBufSize = 1 << 15; + RINOK(ReadStream_FALSE(db.Stream, header, kMainHeaderSize)); + if (memcmp(header, NHeader::kMarker, NHeader::kMarkerSize) == 0 && ai.Parse(header)) + { + limitedStreamSpec = new CLimitedSequentialInStream; + limitedStream = limitedStreamSpec; + limitedStreamSpec->SetStream(db.Stream); + limitedStreamSpec->Init(ai.Size - NHeader::kMarkerSize); + buffer.Alloc(kBufSize); + memcpy(buffer, header, kMainHeaderSize); + UInt32 numProcessedBytes; + RINOK(limitedStream->Read(buffer + kMainHeaderSize, kBufSize - kMainHeaderSize, &numProcessedBytes)); + _inBuffer.SetBuf(buffer, (UInt32)kBufSize, kMainHeaderSize + numProcessedBytes, kMainHeaderSize); + } + else + { + if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0) + return S_FALSE; + + CSignatureFinder finder; + + finder.Stream = db.Stream; + finder.Signature = NHeader::kMarker; + finder.SignatureSize = NHeader::kMarkerSize; + finder.SearchLimit = searchHeaderSizeLimit; - Skip(ai.PerCabinetAreaSize); + buffer.Alloc(finder.GetTotalCapacity(kBufSize, kMainHeaderSize)); + finder.Buf = buffer; + + memcpy(buffer, header, kMainHeaderSize); + finder.Processed = db.StartPosition; + finder.End = kMainHeaderSize; + finder.Pos = 1; + + for (;;) + { + RINOK(finder.Find()); + if (ai.Parse(finder.Buf + finder.Pos)) + { + db.StartPosition = finder.Processed + finder.Pos; + limitedStreamSpec = new CLimitedSequentialInStream; + limitedStreamSpec->SetStream(db.Stream); + limitedStream = limitedStreamSpec; + UInt32 remInFinder = finder.End - finder.Pos; + if (ai.Size <= remInFinder) + { + limitedStreamSpec->Init(0); + finder.End = finder.Pos + ai.Size; + } + else + limitedStreamSpec->Init(ai.Size - remInFinder); + + startInBuf = finder.Pos; + _inBuffer.SetBuf(buffer, (UInt32)kBufSize, finder.End, finder.Pos + kMainHeaderSize); + break; + } + finder.Pos++; + } + } } + + IsArc = true; + _inBuffer.SetStream(limitedStream); + if (_tempBuf.Size() == 0) + _tempBuf.Alloc(1 << 12); + + Byte p[16]; + unsigned nextSize = 4 + (ai.ReserveBlockPresent() ? 4 : 0); + Read(p, nextSize); + ai.SetID = Get16(p); + ai.CabinetNumber = Get16(p + 2); + + if (ai.ReserveBlockPresent()) { - if (ai.IsTherePrev()) - ReadOtherArchive(ai.PrevArc); - if (ai.IsThereNext()) - ReadOtherArchive(ai.NextArc); + ai.PerCabinet_AreaSize = Get16(p + 4); + ai.PerFolder_AreaSize = p[6]; + ai.PerDataBlock_AreaSize = p[7]; + Skip(ai.PerCabinet_AreaSize); } + + if (ai.IsTherePrev()) ReadOtherArc(ai.PrevArc); + if (ai.IsThereNext()) ReadOtherArc(ai.NextArc); - int i; + UInt32 i; + db.Folders.ClearAndReserve(ai.NumFolders); for (i = 0; i < ai.NumFolders; i++) { + Read(p, 8); CFolder folder; - - folder.DataStart = Read32(); - folder.NumDataBlocks = Read16(); - folder.CompressionTypeMajor = Read8(); - folder.CompressionTypeMinor = Read8(); - - Skip(ai.PerFolderAreaSize); - db.Folders.Add(folder); + folder.DataStart = Get32(p); + folder.NumDataBlocks = Get16(p + 4); + folder.MethodMajor = p[6]; + folder.MethodMinor = p[7]; + Skip(ai.PerFolder_AreaSize); + db.Folders.AddInReserved(folder); } - RINOK(stream->Seek(db.StartPosition + ai.FileHeadersOffset, STREAM_SEEK_SET, NULL)); + // for (int iii = 0; iii < 10000; iii++) { + + if (_inBuffer.GetProcessedSize() - startInBuf != ai.FileHeadersOffset) + { + // printf("\n!!! Seek Error !!!!\n"); + // fflush(stdout); + RINOK(db.Stream->Seek(db.StartPosition + ai.FileHeadersOffset, STREAM_SEEK_SET, NULL)); + limitedStreamSpec->Init(ai.Size - ai.FileHeadersOffset); + _inBuffer.Init(); + } - inBuffer.SetStream(stream); - inBuffer.Init(); + db.Items.ClearAndReserve(ai.NumFiles); 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()) + Read(p, 16); + CItem &item = db.Items.AddNewInReserved(); + item.Size = Get32(p); + item.Offset = Get32(p + 4); + item.FolderIndex = Get16(p + 8); + UInt16 pureDate = Get16(p + 10); + UInt16 pureTime = Get16(p + 12); + item.Time = (((UInt32)pureDate << 16)) | pureTime; + item.Attributes = Get16(p + 14); + + ReadName(item.Name); + if (item.GetFolderIndex(db.Folders.Size()) >= (int)db.Folders.Size()) + { + HeaderError = true; return S_FALSE; - db.Items.Add(item); + } } + + // } + return S_OK; } +HRESULT CInArchive::Open(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit) +{ + try + { + return Open2(db, searchHeaderSizeLimit); + } + catch(const CInBufferException &e) { return e.ErrorCode; } + catch(CUnexpectedEndException &) { UnexpectedEnd = true; return S_FALSE; } +} + + + #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } static int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param) @@ -161,10 +360,8 @@ static int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param) 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; + if (isDir1 && !isDir2) return -1; + if (isDir2 && !isDir1) return 1; int f1 = mvDb.GetFolderIndex(p1); int f2 = mvDb.GetFolderIndex(p2); RINOZ(MyCompare(f1, f2)); @@ -174,7 +371,7 @@ static int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param) return MyCompare(p1->ItemIndex, p2->ItemIndex); } -bool CMvDatabaseEx::AreItemsEqual(int i1, int i2) +bool CMvDatabaseEx::AreItemsEqual(unsigned i1, unsigned i2) { const CMvItem *p1 = &Items[i1]; const CMvItem *p2 = &Items[i2]; @@ -182,10 +379,10 @@ bool CMvDatabaseEx::AreItemsEqual(int i1, int i2) 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; + return GetFolderIndex(p1) == GetFolderIndex(p2) + && item1.Offset == item2.Offset + && item1.Size == item2.Size + && item1.Name == item2.Name; } void CMvDatabaseEx::FillSortAndShrink() @@ -194,7 +391,7 @@ void CMvDatabaseEx::FillSortAndShrink() StartFolderOfVol.Clear(); FolderStartFileIndex.Clear(); int offset = 0; - for (int v = 0; v < Volumes.Size(); v++) + FOR_VECTOR (v, Volumes) { const CDatabaseEx &db = Volumes[v]; int curOffset = offset; @@ -205,32 +402,35 @@ void CMvDatabaseEx::FillSortAndShrink() CMvItem mvItem; mvItem.VolumeIndex = v; - for (int i = 0 ; i < db.Items.Size(); i++) + FOR_VECTOR (i, db.Items) { 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); + if (Items.Size() > 1) + { + Items.Sort(CompareMvItems, (void *)this); + unsigned j = 1; + unsigned i = 1; + for (; i < Items.Size(); i++) + if (!AreItemsEqual(i, i - 1)) + Items[j++] = Items[i]; + Items.DeleteFrom(j); + } - for (i = 0; i < Items.Size(); i++) + FOR_VECTOR (i, Items) { int folderIndex = GetFolderIndex(&Items[i]); - if (folderIndex >= FolderStartFileIndex.Size()) + if (folderIndex >= (int)FolderStartFileIndex.Size()) FolderStartFileIndex.Add(i); } } bool CMvDatabaseEx::Check() { - for (int v = 1; v < Volumes.Size(); v++) + for (unsigned v = 1; v < Volumes.Size(); v++) { const CDatabaseEx &db1 = Volumes[v]; if (db1.IsTherePrevFolder()) @@ -240,19 +440,19 @@ bool CMvDatabaseEx::Check() return false; const CFolder &f0 = db0.Folders.Back(); const CFolder &f1 = db1.Folders.Front(); - if (f0.CompressionTypeMajor != f1.CompressionTypeMajor || - f0.CompressionTypeMinor != f1.CompressionTypeMinor) + if (f0.MethodMajor != f1.MethodMajor || + f0.MethodMinor != f1.MethodMinor) return false; } } UInt32 beginPos = 0; UInt64 endPos = 0; int prevFolder = -2; - for (int i = 0; i < Items.Size(); i++) + FOR_VECTOR (i, Items) { const CMvItem &mvItem = Items[i]; int fIndex = GetFolderIndex(&mvItem); - if (fIndex >= FolderStartFileIndex.Size()) + if (fIndex >= (int)FolderStartFileIndex.Size()) return false; const CItem &item = Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; if (item.IsDir()) diff --git a/CPP/7zip/Archive/Cab/CabIn.h b/CPP/7zip/Archive/Cab/CabIn.h old mode 100755 new mode 100644 index 1e9b188b..4fdab77b --- a/CPP/7zip/Archive/Cab/CabIn.h +++ b/CPP/7zip/Archive/Cab/CabIn.h @@ -3,96 +3,88 @@ #ifndef __ARCHIVE_CAB_IN_H #define __ARCHIVE_CAB_IN_H -#include "../../IStream.h" +#include "../../../Common/MyBuffer.h" +#include "../../../Common/MyCom.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 +struct COtherArc { AString FileName; AString DiskName; }; -struct CArchiveInfo +struct CArchInfo { - 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() + Byte VersionMinor; // cabinet file format version, minor + Byte VersionMajor; // cabinet file format version, major + UInt32 NumFolders; // number of CFFOLDER entries in this cabinet + UInt32 NumFiles; // number of CFFILE entries in this cabinet + UInt32 Flags; // cabinet file option indicators + UInt32 SetID; // must be the same for all cabinets in a set + UInt32 CabinetNumber; // number of this cabinet file in a set + + UInt16 PerCabinet_AreaSize; // (optional) size of per-cabinet reserved area + Byte PerFolder_AreaSize; // (optional) size of per-folder reserved area + Byte PerDataBlock_AreaSize; // (optional) size of per-datablock reserved area + + COtherArc PrevArc; // prev link can skip some volumes !!! + COtherArc NextArc; + + bool ReserveBlockPresent() const { return (Flags & NHeader::NArcFlags::kReservePresent) != 0; } + bool IsTherePrev() const { return (Flags & NHeader::NArcFlags::kPrevCabinet) != 0; } + bool IsThereNext() const { return (Flags & NHeader::NArcFlags::kNextCabinet) != 0; } + Byte GetDataBlockReserveSize() const { return (Byte)(ReserveBlockPresent() ? PerDataBlock_AreaSize : 0); } + + CArchInfo() { Clear(); } void Clear() { - PerCabinetAreaSize = 0; - PerFolderAreaSize = 0; - PerDataBlockAreaSize = 0; + PerCabinet_AreaSize = 0; + PerFolder_AreaSize = 0; + PerDataBlock_AreaSize = 0; } }; -struct CInArchiveInfo: public CArchiveInfo +struct CInArcInfo: public CArchInfo { - UInt32 Size; /* size of this cabinet file in bytes */ + UInt32 Size; // size of this cabinet file in bytes UInt32 FileHeadersOffset; // offset of the first CFFILE entry + + bool Parse(const Byte *p); }; struct CDatabase { - UInt64 StartPosition; - CInArchiveInfo ArchiveInfo; - CObjectVector Folders; + CRecordVector Folders; CObjectVector Items; + UInt64 StartPosition; + CInArcInfo ArcInfo; void Clear() { - ArchiveInfo.Clear(); + ArcInfo.Clear(); Folders.Clear(); Items.Clear(); } + bool IsTherePrevFolder() const { - for (int i = 0; i < Items.Size(); i++) + FOR_VECTOR (i, Items) if (Items[i].ContinuedFromPrev()) return true; return false; } + int GetNumberOfNewFolders() const { int res = Folders.Size(); @@ -100,8 +92,6 @@ struct CDatabase 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 @@ -111,25 +101,27 @@ struct CDatabaseEx: public CDatabase struct CMvItem { - int VolumeIndex; - int ItemIndex; + unsigned VolumeIndex; + unsigned ItemIndex; }; class CMvDatabaseEx { - bool AreItemsEqual(int i1, int i2); + bool AreItemsEqual(unsigned i1, unsigned i2); + public: CObjectVector Volumes; CRecordVector Items; - CRecordVector StartFolderOfVol; - CRecordVector FolderStartFileIndex; - + CRecordVector StartFolderOfVol; // can be negative + 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(); @@ -137,23 +129,30 @@ public: StartFolderOfVol.Clear(); FolderStartFileIndex.Clear(); } + void FillSortAndShrink(); bool Check(); }; + class CInArchive { - CInBuffer inBuffer; + CInBufferBase _inBuffer; + CByteBuffer _tempBuf; - Byte Read8(); - UInt16 Read16(); - UInt32 Read32(); - AString SafeReadName(); - void Skip(UInt32 size); - void ReadOtherArchive(COtherArchive &oa); + void Skip(unsigned size); + void Read(Byte *data, unsigned size); + void ReadName(AString &s); + void ReadOtherArc(COtherArc &oa); + HRESULT Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit); public: - HRESULT Open(const UInt64 *searchHeaderSizeLimit, CDatabaseEx &db); + bool IsArc; + bool ErrorInNames; + bool UnexpectedEnd; + bool HeaderError; + + HRESULT Open(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit); }; }} diff --git a/CPP/7zip/Archive/Cab/CabItem.h b/CPP/7zip/Archive/Cab/CabItem.h old mode 100755 new mode 100644 index 63a1e856..eda62bda --- a/CPP/7zip/Archive/Cab/CabItem.h +++ b/CPP/7zip/Archive/Cab/CabItem.h @@ -3,20 +3,23 @@ #ifndef __ARCHIVE_CAB_ITEM_H #define __ARCHIVE_CAB_ITEM_H -#include "Common/Types.h" -#include "Common/MyString.h" +#include "../../../Common/MyString.h" + #include "CabHeader.h" namespace NArchive { namespace NCab { +const unsigned kNumMethodsMax = 16; + 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); } + Byte MethodMajor; + Byte MethodMinor; + + Byte GetMethod() const { return (Byte)(MethodMajor & 0xF); } }; struct CItem @@ -25,27 +28,27 @@ struct CItem UInt32 Offset; UInt32 Size; UInt32 Time; - UInt16 FolderIndex; + UInt32 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; } + UInt32 GetWinAttrib() const { return (UInt32)Attributes & ~(UInt32)NHeader::kFileNameIsUtf8_Mask; } + bool IsNameUTF() const { return (Attributes & NHeader::kFileNameIsUtf8_Mask) != 0; } bool IsDir() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; } bool ContinuedFromPrev() const { return - (FolderIndex == NHeader::NFolderIndex::kContinuedFromPrev) || - (FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext); + FolderIndex == NHeader::NFolderIndex::kContinuedFromPrev || + FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext; } bool ContinuedToNext() const { return - (FolderIndex == NHeader::NFolderIndex::kContinuedToNext) || - (FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext); + FolderIndex == NHeader::NFolderIndex::kContinuedToNext || + FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext; } int GetFolderIndex(int numFolders) const @@ -53,7 +56,7 @@ struct CItem if (ContinuedFromPrev()) return 0; if (ContinuedToNext()) - return (numFolders - 1); + return numFolders - 1; return FolderIndex; } }; diff --git a/CPP/7zip/Archive/Cab/CabRegister.cpp b/CPP/7zip/Archive/Cab/CabRegister.cpp old mode 100755 new mode 100644 index 15fe4099..acad4c4a --- a/CPP/7zip/Archive/Cab/CabRegister.cpp +++ b/CPP/7zip/Archive/Cab/CabRegister.cpp @@ -5,9 +5,19 @@ #include "../../Common/RegisterArc.h" #include "CabHandler.h" -static IInArchive *CreateArc() { return new NArchive::NCab::CHandler; } + +namespace NArchive { +namespace NCab { + +IMP_CreateArcIn static CArcInfo g_ArcInfo = - { L"Cab", L"cab", 0, 8, { 0x4D, 0x53, 0x43, 0x46 }, 4, false, CreateArc, 0 }; + { "Cab", "cab", 0, 8, + 8, { 'M', 'S', 'C', 'F', 0, 0, 0, 0 }, + 0, + NArcInfoFlags::kFindSignature, + CreateArc }; REGISTER_ARC(Cab) + +}} diff --git a/CPP/7zip/Archive/Cab/StdAfx.h b/CPP/7zip/Archive/Cab/StdAfx.h old mode 100755 new mode 100644 index e7fb6986..2854ff3e --- a/CPP/7zip/Archive/Cab/StdAfx.h +++ b/CPP/7zip/Archive/Cab/StdAfx.h @@ -3,6 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" +#include "../../../Common/Common.h" #endif diff --git a/CPP/7zip/Archive/Chm/ChmHandler.cpp b/CPP/7zip/Archive/Chm/ChmHandler.cpp old mode 100755 new mode 100644 index a9e334b0..c67ded28 --- a/CPP/7zip/Archive/Chm/ChmHandler.cpp +++ b/CPP/7zip/Archive/Chm/ChmHandler.cpp @@ -2,17 +2,17 @@ #include "StdAfx.h" -#include "Common/ComTry.h" -#include "Common/Defs.h" -#include "Common/StringConvert.h" -#include "Common/UTFConvert.h" +#include "../../../Common/ComTry.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/UTFConvert.h" -#include "Windows/PropVariant.h" -#include "Windows/Time.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/TimeUtils.h" #include "../../Common/LimitedStreams.h" #include "../../Common/ProgressUtils.h" #include "../../Common/StreamUtils.h" +#include "../../Common/RegisterArc.h" #include "../../Compress/CopyCoder.h" #include "../../Compress/LzxDecoder.h" @@ -38,44 +38,45 @@ enum #endif -STATPROPSTG kProps[] = +static const Byte kProps[] = { - { NULL, kpidPath, VT_BSTR}, - { NULL, kpidSize, VT_UI8}, - { NULL, kpidMethod, VT_BSTR}, - { NULL, kpidBlock, VT_UI4} + kpidPath, + kpidSize, + kpidMethod, + kpidBlock #ifdef _CHM_DETAILS , - { L"Section", kpidSection, VT_UI4}, - { NULL, kpidOffset, VT_UI4} + L"Section", kpidSection, + kpidOffset #endif }; -STATPROPSTG kArcProps[] = +/* +static const Byte kArcProps[] = { - { NULL, kpidNumBlocks, VT_UI8} + // kpidNumBlocks, }; +*/ IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO -/* -IMP_IInArchive_ArcProps +IMP_IInArchive_ArcProps_NO_Table STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { - COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; - switch(propID) + // COM_TRY_BEGIN + NCOM::CPropVariant prop; + switch (propID) { + /* case kpidNumBlocks: { UInt64 numBlocks = 0; - for (int i = 0; i < m_Database.Sections.Size(); i++) + FOR_VECTOR(i, m_Database.Sections) { const CSectionInfo &s = m_Database.Sections[i]; - for (int j = 0; j < s.Methods.Size(); j++) + FOR_VECTOR(j, s.Methods) { const CMethodInfo &m = s.Methods[j]; if (m.IsLzx()) @@ -85,23 +86,27 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) prop = numBlocks; break; } + */ + case kpidOffset: prop = m_Database.StartPosition; break; + case kpidPhySize: prop = m_Database.PhySize; break; + + case kpidErrorFlags: prop = m_ErrorFlags; break; } prop.Detach(value); return S_OK; - COM_TRY_END + // COM_TRY_END } -*/ -STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; + NCOM::CPropVariant prop; if (m_Database.NewFormat) { switch(propID) { case kpidSize: - prop = (UInt64)m_Database.NewFormatString.Length(); + prop = (UInt64)m_Database.NewFormatString.Len(); break; } prop.Detach(value); @@ -113,7 +118,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va else entryIndex = m_Database.Indices[index]; const CItem &item = m_Database.Items[entryIndex]; - switch(propID) + switch (propID) { case kpidPath: { @@ -122,7 +127,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va { if (!m_Database.LowLevel) { - if (us.Length() > 1) + if (us.Len() > 1) if (us[0] == L'/') us.Delete(0); } @@ -160,6 +165,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va COM_TRY_END } +/* class CProgressImp: public CProgressVirt { CMyComPtr _callback; @@ -182,18 +188,25 @@ STDMETHODIMP CProgressImp::SetCompleted(const UInt64 *numFiles) return _callback->SetCompleted(numFiles, NULL); return S_OK; } +*/ STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback * /* openArchiveCallback */) { COM_TRY_BEGIN - m_Stream.Release(); + Close(); try { - CInArchive archive; + CInArchive archive(_help2); // CProgressImp progressImp(openArchiveCallback); - RINOK(archive.Open(inStream, maxCheckStartPosition, m_Database)); + HRESULT res = archive.Open(inStream, maxCheckStartPosition, m_Database); + if (!archive.IsArc) m_ErrorFlags |= kpv_ErrorFlags_IsNotArc; + if (archive.HeadersError) m_ErrorFlags |= kpv_ErrorFlags_HeadersError; + if (archive.UnexpectedEnd) m_ErrorFlags |= kpv_ErrorFlags_UnexpectedEnd; + if (archive.UnsupportedFeature) m_ErrorFlags |= kpv_ErrorFlags_UnsupportedFeature; + + RINOK(res); /* if (m_Database.LowLevel) return S_FALSE; @@ -210,6 +223,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, STDMETHODIMP CHandler::Close() { + m_ErrorFlags = 0; m_Database.Clear(); m_Stream.Release(); return S_OK; @@ -402,7 +416,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testModeSpec, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = m_Database.NewFormat ? 1: @@ -432,7 +446,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, UInt64 currentItemSize = 0; UInt64 totalSize = 0; if (m_Database.NewFormat) - totalSize = m_Database.NewFormatString.Length(); + totalSize = m_Database.NewFormatString.Len(); else for (i = 0; i < numItems; i++) totalSize += m_Database.Items[allFilesMode ? i : indices[i]].Size; @@ -460,7 +474,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, continue; if (!testMode) { - UInt32 size = m_Database.NewFormatString.Length(); + UInt32 size = m_Database.NewFormatString.Len(); RINOK(WriteStream(realOutStream, (const char *)m_Database.NewFormatString, size)); } RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); @@ -475,7 +489,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(extractCallback->PrepareOperation(askMode)); if (item.Section != 0) { - RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod)); continue; } @@ -589,7 +603,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (!testMode && !realOutStream) continue; RINOK(extractCallback->PrepareOperation(askMode)); - RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod)); continue; } @@ -718,4 +732,32 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) return S_OK; } +namespace NChm { + +IMP_CreateArcIn_2(CHandler(false)) + +static CArcInfo g_ArcInfo = + { "Chm", "chm chi chq chw", 0, 0xE9, + 12, { 'I', 'T', 'S', 'F', 3, 0, 0, 0, 0x60, 0, 0, 0 }, + 0, + 0, + CreateArc }; + +REGISTER_ARC(Chm) +} + +namespace NHxs { + +IMP_CreateArcIn_2(CHandler(true)) + +static CArcInfo g_ArcInfo = + { "Hxs", "hxs hxi hxr hxq hxw lit", 0, 0xCE, + 16, { 'I', 'T', 'O', 'L', 'I', 'T', 'L', 'S', 1, 0, 0, 0, 0x28, 0, 0, 0 }, + 0, + NArcInfoFlags::kFindSignature, + CreateArc }; + +REGISTER_ARC(Hxs) +} + }} diff --git a/CPP/7zip/Archive/Chm/ChmHandler.h b/CPP/7zip/Archive/Chm/ChmHandler.h old mode 100755 new mode 100644 index 440c50f1..884f391b --- a/CPP/7zip/Archive/Chm/ChmHandler.h +++ b/CPP/7zip/Archive/Chm/ChmHandler.h @@ -3,8 +3,10 @@ #ifndef __ARCHIVE_CHM_HANDLER_H #define __ARCHIVE_CHM_HANDLER_H -#include "Common/MyCom.h" +#include "../../../Common/MyCom.h" + #include "../IArchive.h" + #include "ChmIn.h" namespace NArchive { @@ -19,9 +21,13 @@ public: INTERFACE_IInArchive(;) + bool _help2; + CHandler(bool help2): _help2(help2) {} + private: CFilesDatabase m_Database; CMyComPtr m_Stream; + UInt32 m_ErrorFlags; }; }} diff --git a/CPP/7zip/Archive/Chm/ChmHeader.cpp b/CPP/7zip/Archive/Chm/ChmHeader.cpp deleted file mode 100755 index e8dc9f3e..00000000 --- a/CPP/7zip/Archive/Chm/ChmHeader.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// 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 deleted file mode 100755 index 9f1bd42b..00000000 --- a/CPP/7zip/Archive/Chm/ChmHeader.h +++ /dev/null @@ -1,28 +0,0 @@ -// 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 old mode 100755 new mode 100644 index d52b9ba6..9b0bb199 --- a/CPP/7zip/Archive/Chm/ChmIn.cpp +++ b/CPP/7zip/Archive/Chm/ChmIn.cpp @@ -2,8 +2,10 @@ #include "StdAfx.h" -#include "Common/IntToString.h" -#include "Common/UTFConvert.h" +// #include + +#include "../../../Common/IntToString.h" +#include "../../../Common/UTFConvert.h" #include "../../Common/LimitedStreams.h" @@ -12,6 +14,21 @@ namespace NArchive { namespace NChm { +static const UInt32 kSignature_ITSP = 0x50535449; +static const UInt32 kSignature_PMGL = 0x4C474D50; +static const UInt32 kSignature_LZXC = 0x43585A4C; + +static const UInt32 kSignature_IFCM = 0x4D434649; +static const UInt32 kSignature_AOLL = 0x4C4C4F41; +static const UInt32 kSignature_CAOL = 0x4C4F4143; + +static const UInt32 kSignature_ITSF = 0x46535449; +static const UInt32 kSignature_ITOL = 0x4C4F5449; +static const UInt32 kSignature_ITLS = 0x534C5449; + +struct CEnexpectedEndException {}; +struct CHeaderErrorException {}; + // define CHM_LOW, if you want to see low level items // #define CHM_LOW @@ -31,9 +48,9 @@ static bool AreGuidsEqual(REFGUID g1, REFGUID g2) return true; } -static char GetHex(Byte value) +static char GetHex(unsigned v) { - return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); + return (char)((v < 10) ? ('0' + v) : ('A' + (v - 10))); } static void PrintByte(Byte b, AString &s) @@ -103,10 +120,10 @@ UString CMethodInfo::GetName() const else { s2 = GetGuidString(); - if (ControlData.GetCapacity() > 0) + if (ControlData.Size() > 0) { s2 += ':'; - for (size_t i = 0; i < ControlData.GetCapacity(); i++) + for (size_t i = 0; i < ControlData.Size(); i++) PrintByte(ControlData[i], s2); } } @@ -132,7 +149,7 @@ UString CSectionInfo::GetMethodName() const s += temp; s += L": "; } - for (int i = 0; i < Methods.Size(); i++) + FOR_VECTOR (i, Methods) { if (i != 0) s += L' '; @@ -145,7 +162,7 @@ Byte CInArchive::ReadByte() { Byte b; if (!_inBuffer.ReadByte(b)) - throw 1; + throw CEnexpectedEndException(); return b; } @@ -163,32 +180,32 @@ void CInArchive::ReadBytes(Byte *data, UInt32 size) UInt16 CInArchive::ReadUInt16() { - UInt16 value = 0; + UInt16 val = 0; for (int i = 0; i < 2; i++) - value |= ((UInt16)(ReadByte()) << (8 * i)); - return value; + val |= ((UInt16)(ReadByte()) << (8 * i)); + return val; } UInt32 CInArchive::ReadUInt32() { - UInt32 value = 0; + UInt32 val = 0; for (int i = 0; i < 4; i++) - value |= ((UInt32)(ReadByte()) << (8 * i)); - return value; + val |= ((UInt32)(ReadByte()) << (8 * i)); + return val; } UInt64 CInArchive::ReadUInt64() { - UInt64 value = 0; + UInt64 val = 0; for (int i = 0; i < 8; i++) - value |= ((UInt64)(ReadByte()) << (8 * i)); - return value; + val |= ((UInt64)(ReadByte()) << (8 * i)); + return val; } UInt64 CInArchive::ReadEncInt() { - UInt64 val = 0;; - for (int i = 0; i < 10; i++) + UInt64 val = 0; + for (int i = 0; i < 9; i++) { Byte b = ReadByte(); val |= (b & 0x7F); @@ -196,7 +213,7 @@ UInt64 CInArchive::ReadEncInt() return val; val <<= 7; } - throw 1; + throw CHeaderErrorException(); } void CInArchive::ReadGUID(GUID &g) @@ -207,10 +224,10 @@ void CInArchive::ReadGUID(GUID &g) ReadBytes(g.Data4, 8); } -void CInArchive::ReadString(int size, AString &s) +void CInArchive::ReadString(unsigned size, AString &s) { s.Empty(); - while(size-- != 0) + while (size-- != 0) { char c = (char)ReadByte(); if (c == 0) @@ -222,10 +239,10 @@ void CInArchive::ReadString(int size, AString &s) } } -void CInArchive::ReadUString(int size, UString &s) +void CInArchive::ReadUString(unsigned size, UString &s) { s.Empty(); - while(size-- != 0) + while (size-- != 0) { wchar_t c = ReadUInt16(); if (c == 0) @@ -244,6 +261,7 @@ HRESULT CInArchive::ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size) CMyComPtr limitedStream(streamSpec); streamSpec->SetStream(inStream); streamSpec->Init(size); + m_InStreamRef = limitedStream; _inBuffer.SetStream(limitedStream); _inBuffer.Init(); return S_OK; @@ -252,10 +270,10 @@ HRESULT CInArchive::ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size) HRESULT CInArchive::ReadDirEntry(CDatabase &database) { CItem item; - UInt64 nameLength = ReadEncInt(); - if (nameLength == 0 || nameLength >= 0x10000000) + UInt64 nameLen = ReadEncInt(); + if (nameLen == 0 || nameLen > (1 << 13)) return S_FALSE; - ReadString((int)nameLength, item.Name); + ReadString((unsigned)nameLen, item.Name); item.Section = ReadEncInt(); item.Offset = ReadEncInt(); item.Size = ReadEncInt(); @@ -268,9 +286,14 @@ HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database) UInt32 headerSize = ReadUInt32(); if (headerSize != 0x60) return S_FALSE; + database.PhySize = headerSize; + UInt32 unknown1 = ReadUInt32(); if (unknown1 != 0 && unknown1 != 1) // it's 0 in one .sll file return S_FALSE; + + IsArc = true; + /* UInt32 timeStamp = */ ReadUInt32(); // Considered as a big-endian DWORD, it appears to contain seconds (MSB) and // fractional seconds (second byte). @@ -280,37 +303,39 @@ HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database) GUID g; ReadGUID(g); // {7C01FD10-7BAA-11D0-9E0C-00A0-C922-E6EC} ReadGUID(g); // {7C01FD11-7BAA-11D0-9E0C-00A0-C922-E6EC} - const int kNumSections = 2; + const unsigned kNumSections = 2; UInt64 sectionOffsets[kNumSections]; UInt64 sectionSizes[kNumSections]; - int i; + unsigned i; for (i = 0; i < kNumSections; i++) { sectionOffsets[i] = ReadUInt64(); sectionSizes[i] = ReadUInt64(); + UInt64 end = sectionOffsets[i] + sectionSizes[i]; + database.UpdatePhySize(end); } // if (chmVersion == 3) database.ContentOffset = ReadUInt64(); /* else - database.ContentOffset = _startPosition + 0x58 + database.ContentOffset = database.StartPosition + 0x58 */ - /* // Section 0 ReadChunk(inStream, sectionOffsets[0], sectionSizes[0]); - if (sectionSizes[0] != 0x18) + if (sectionSizes[0] < 0x18) + return S_FALSE; + if (ReadUInt32() != 0x01FE) return S_FALSE; - ReadUInt32(); // unknown: 01FE ReadUInt32(); // unknown: 0 UInt64 fileSize = ReadUInt64(); + database.UpdatePhySize(fileSize); ReadUInt32(); // unknown: 0 ReadUInt32(); // unknown: 0 - */ // Section 1: The Directory Listing ReadChunk(inStream, sectionOffsets[1], sectionSizes[1]); - if (ReadUInt32() != NHeader::kItspSignature) + if (ReadUInt32() != kSignature_ITSP) return S_FALSE; if (ReadUInt32() != 1) // version return S_FALSE; @@ -340,13 +365,13 @@ HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database) for (UInt32 ci = 0; ci < numDirChunks; ci++) { UInt64 chunkPos = _inBuffer.GetProcessedSize(); - if (ReadUInt32() == NHeader::kPmglSignature) + if (ReadUInt32() == kSignature_PMGL) { // 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 + UInt32 quickrefLength = ReadUInt32(); // Len of free space and/or quickref area at end of directory chunk if (quickrefLength > dirChunkSize || quickrefLength < 2) return S_FALSE; ReadUInt32(); // Always 0 @@ -354,7 +379,7 @@ HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database) // 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; + unsigned numItems = 0; for (;;) { UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos; @@ -383,10 +408,13 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database) if (ReadUInt32() != 0x28) // Location of header section table return S_FALSE; UInt32 numHeaderSections = ReadUInt32(); - const int kNumHeaderSectionsMax = 5; + const unsigned kNumHeaderSectionsMax = 5; if (numHeaderSections != kNumHeaderSectionsMax) return S_FALSE; - ReadUInt32(); // Length of post-header table + + IsArc = true; + + ReadUInt32(); // Len of post-header table GUID g; ReadGUID(g); // {0A9007C1-4076-11D3-8789-0000F8105754} @@ -398,6 +426,8 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database) { sectionOffsets[i] = ReadUInt64(); sectionSizes[i] = ReadUInt64(); + UInt64 end = sectionOffsets[i] + sectionSizes[i]; + database.UpdatePhySize(end); } // Post-Header @@ -436,11 +466,11 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database) ReadUInt32(); // $20000 (Same as field following chunk size in directory index) ReadUInt64(); // 0 (unknown) - if (ReadUInt32() != NHeader::kCaolSignature) + if (ReadUInt32() != kSignature_CAOL) 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) + UInt32 caolLength = ReadUInt32(); // $50 (Len of the CAOL section, which includes the ITSF section) if (caolLength >= 0x2C) { /* UInt32 c7 = */ ReadUInt16(); // Unknown. Remains the same when identical files are built. @@ -458,13 +488,15 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database) ReadUInt32(); // 0 (Unknown) if (caolLength == 0x2C) { - database.ContentOffset = 0; + // fprintf(stdout, "\n !!!NewFormat\n"); + // fflush(stdout); + database.ContentOffset = 0; // maybe we must add database.StartPosition here? database.NewFormat = true; } else if (caolLength == 0x50) { ReadUInt32(); // 0 (Unknown) - if (ReadUInt32() != NHeader::kItsfSignature) + if (ReadUInt32() != kSignature_ITSF) return S_FALSE; if (ReadUInt32() != 4) // $4 (Version number -- CHM uses 3) return S_FALSE; @@ -473,7 +505,7 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database) UInt32 unknown = ReadUInt32(); if (unknown != 0 && unknown != 1) // = 0 for some HxW files, 1 in other cases; return S_FALSE; - database.ContentOffset = _startPosition + ReadUInt64(); + database.ContentOffset = database.StartPosition + ReadUInt64(); /* UInt32 timeStamp = */ ReadUInt32(); // A timestamp of some sort. // Considered as a big-endian DWORD, it appears to contain @@ -486,21 +518,21 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database) return S_FALSE; } - /* // Section 0 - ReadChunk(inStream, _startPosition + sectionOffsets[0], sectionSizes[0]); - if (sectionSizes[0] != 0x18) + ReadChunk(inStream, database.StartPosition + sectionOffsets[0], sectionSizes[0]); + if (sectionSizes[0] < 0x18) + return S_FALSE; + if (ReadUInt32() != 0x01FE) return S_FALSE; - ReadUInt32(); // unknown: 01FE ReadUInt32(); // unknown: 0 UInt64 fileSize = ReadUInt64(); + database.UpdatePhySize(fileSize); ReadUInt32(); // unknown: 0 ReadUInt32(); // unknown: 0 - */ // Section 1: The Directory Listing - ReadChunk(inStream, _startPosition + sectionOffsets[1], sectionSizes[1]); - if (ReadUInt32() != NHeader::kIfcmSignature) + ReadChunk(inStream, database.StartPosition + sectionOffsets[1], sectionSizes[1]); + if (ReadUInt32() != kSignature_IFCM) return S_FALSE; if (ReadUInt32() != 1) // (probably a version number) return S_FALSE; @@ -516,9 +548,9 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database) for (UInt32 ci = 0; ci < numDirChunks; ci++) { UInt64 chunkPos = _inBuffer.GetProcessedSize(); - if (ReadUInt32() == NHeader::kAollSignature) + if (ReadUInt32() == kSignature_AOLL) { - UInt32 quickrefLength = ReadUInt32(); // Length of quickref area at end of directory chunk + UInt32 quickrefLength = ReadUInt32(); // Len of quickref area at end of directory chunk if (quickrefLength > dirChunkSize || quickrefLength < 2) return S_FALSE; ReadUInt64(); // Directory chunk number @@ -533,7 +565,7 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database) ReadUInt32(); // 1 (unknown -- other values have also been seen here) ReadUInt32(); // 0 (unknown) - int numItems = 0; + unsigned numItems = 0; for (;;) { UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos; @@ -544,11 +576,11 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database) break; if (database.NewFormat) { - UInt16 nameLength = ReadUInt16(); - if (nameLength == 0) + UInt16 nameLen = ReadUInt16(); + if (nameLen == 0) return S_FALSE; UString name; - ReadUString((int)nameLength, name); + ReadUString((unsigned)nameLen, name); AString s; ConvertUnicodeToUTF8(name, s); Byte b = ReadByte(); @@ -637,10 +669,10 @@ static int CompareFiles(const int *p1, const int *p2, void *param) void CFilesDatabase::SetIndices() { - for (int i = 0; i < Items.Size(); i++) + FOR_VECTOR (i, Items) { const CItem &item = Items[i]; - if (item.IsUserItem() && item.Name.Length() != 1) + if (item.IsUserItem() && item.Name.Len() != 1) Indices.Add(i); } } @@ -654,7 +686,7 @@ bool CFilesDatabase::Check() { UInt64 maxPos = 0; UInt64 prevSection = 0; - for(int i = 0; i < Indices.Size(); i++) + FOR_VECTOR (i, Indices) { const CItem &item = Items[Indices[i]]; if (item.Section == 0 || item.IsDir()) @@ -684,9 +716,9 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database) for (int i = 0; i < numSections; i++) { CSectionInfo section; - UInt16 nameLength = ReadUInt16(); + UInt16 nameLen = ReadUInt16(); UString name; - ReadUString(nameLength, name); + ReadUString(nameLen, name); if (ReadUInt16() != 0) return S_FALSE; if (!ConvertUnicodeToUTF8(name, section.Name)) @@ -695,7 +727,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database) } } - int i; + unsigned i; for (i = 1; i < database.Sections.Size(); i++) { CSectionInfo §ion = database.Sections[i]; @@ -736,7 +768,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database) { // Control Data RINOK(DecompressStream(inStream, database, sectionPrefix + kControlData)); - for (int mi = 0; mi < section.Methods.Size(); mi++) + FOR_VECTOR (mi, section.Methods) { CMethodInfo &method = section.Methods[mi]; UInt32 numDWORDS = ReadUInt32(); @@ -744,7 +776,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database) { if (numDWORDS < 5) return S_FALSE; - if (ReadUInt32() != NHeader::kLzxcSignature) + if (ReadUInt32() != kSignature_LZXC) return S_FALSE; CLzxInfo &li = method.LzxInfo; li.Version = ReadUInt32(); @@ -778,7 +810,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database) else { UInt32 numBytes = numDWORDS * 4; - method.ControlData.SetCapacity(numBytes); + method.ControlData.Alloc(numBytes); ReadBytes(method.ControlData, numBytes); } } @@ -791,7 +823,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database) } // read ResetTable for LZX - for (int mi = 0; mi < section.Methods.Size(); mi++) + FOR_VECTOR (mi, section.Methods) { CMethodInfo &method = section.Methods[mi]; if (method.IsLzx()) @@ -819,16 +851,16 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database) UInt32 numEntries = ReadUInt32(); if (ReadUInt32() != 8) // Size of table entry (bytes) return S_FALSE; - if (ReadUInt32() != 0x28) // Length of table header + if (ReadUInt32() != 0x28) // Len 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); + rt.ResetOffsets.ClearAndReserve(numEntries); for (UInt32 i = 0; i < numEntries; i++) - rt.ResetOffsets.Add(ReadUInt64()); + rt.ResetOffsets.AddInReserved(ReadUInt64()); } } } @@ -843,77 +875,91 @@ HRESULT CInArchive::Open2(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, CFilesDatabase &database) { + IsArc = false; + HeadersError = false; + UnexpectedEnd = false; + UnsupportedFeature = false; + database.Clear(); + database.Help2Format = _help2; + const UInt32 chmVersion = 3; - RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &_startPosition)); + RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &database.StartPosition)); - database.Help2Format = false; - const UInt32 chmVersion = 3; + if (!_inBuffer.Create(1 << 14)) + return E_OUTOFMEMORY; + _inBuffer.SetStream(inStream); + _inBuffer.Init(); + + if (_help2) { - 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 signature = ((UInt64)kSignature_ITLS << 32)| kSignature_ITOL; UInt64 limit = 1 << 18; if (searchHeaderSizeLimit) if (limit > *searchHeaderSizeLimit) limit = *searchHeaderSizeLimit; + UInt64 val = 0; for (;;) { Byte b; if (!_inBuffer.ReadByte(b)) return S_FALSE; - value >>= 8; - value |= ((UInt64)b) << ((kSignatureSize - 1) * 8); + val >>= 8; + val |= ((UInt64)b) << ((kSignatureSize - 1) * 8); if (_inBuffer.GetProcessedSize() >= kSignatureSize) { - if (value == chmSignature) - break; - if (value == hxsSignature) - { - database.Help2Format = true; + if (val == signature) break; - } if (_inBuffer.GetProcessedSize() > limit) return S_FALSE; } } - _startPosition += _inBuffer.GetProcessedSize() - kSignatureSize; - } - - if (database.Help2Format) - { + database.StartPosition += _inBuffer.GetProcessedSize() - kSignatureSize; RINOK(OpenHelp2(inStream, database)); if (database.NewFormat) return S_OK; } else { + if (ReadUInt32() != kSignature_ITSF) + return S_FALSE; + if (ReadUInt32() != chmVersion) + return S_FALSE; RINOK(OpenChm(inStream, database)); } + #ifndef CHM_LOW + try { - HRESULT res = OpenHighLevel(inStream, database); - if (res == S_FALSE) + try + { + HRESULT res = OpenHighLevel(inStream, database); + if (res == S_FALSE) + { + UnsupportedFeature = true; + database.HighLevelClear(); + return S_OK; + } + RINOK(res); + database.LowLevel = false; + } + catch(...) { database.HighLevelClear(); - return S_OK; + throw; } - RINOK(res); - database.LowLevel = false; - } - catch(...) - { - return S_OK; } + // catch(const CInBufferException &e) { return e.ErrorCode; } + catch(CEnexpectedEndException &) { UnexpectedEnd = true; } + catch(CHeaderErrorException &) { HeadersError = true; } + catch(...) { throw; } + #endif + return S_OK; } @@ -923,15 +969,22 @@ HRESULT CInArchive::Open(IInStream *inStream, { try { - HRESULT res = Open2(inStream, searchHeaderSizeLimit, database); - _inBuffer.ReleaseStream(); - return res; - } - catch(...) - { - _inBuffer.ReleaseStream(); - throw; + try + { + HRESULT res = Open2(inStream, searchHeaderSizeLimit, database); + m_InStreamRef.Release(); + return res; + } + catch(...) + { + m_InStreamRef.Release(); + throw; + } } + catch(const CInBufferException &e) { return e.ErrorCode; } + catch(CEnexpectedEndException &) { UnexpectedEnd = true; } + catch(CHeaderErrorException &) { HeadersError = true; } + return S_FALSE; } }} diff --git a/CPP/7zip/Archive/Chm/ChmIn.h b/CPP/7zip/Archive/Chm/ChmIn.h old mode 100755 new mode 100644 index 4b1ac7a6..70764ab9 --- a/CPP/7zip/Archive/Chm/ChmIn.h +++ b/CPP/7zip/Archive/Chm/ChmIn.h @@ -3,13 +3,12 @@ #ifndef __ARCHIVE_CHM_IN_H #define __ARCHIVE_CHM_IN_H -#include "Common/Buffer.h" -#include "Common/MyString.h" +#include "../../../Common/MyBuffer.h" +#include "../../../Common/MyString.h" #include "../../IStream.h" -#include "../../Common/InBuffer.h" -#include "ChmHeader.h" +#include "../../Common/InBuffer.h" namespace NArchive { namespace NChm { @@ -23,21 +22,21 @@ struct CItem bool IsFormatRelatedItem() const { - if (Name.Length() < 2) + if (Name.Len() < 2) return false; return Name[0] == ':' && Name[1] == ':'; } bool IsUserItem() const { - if (Name.Length() < 2) + if (Name.Len() < 2) return false; return Name[0] == '/'; } bool IsDir() const { - if (Name.Length() == 0) + if (Name.Len() == 0) return false; return (Name.Back() == '/'); } @@ -45,15 +44,19 @@ struct CItem struct CDatabase { + UInt64 StartPosition; UInt64 ContentOffset; CObjectVector Items; AString NewFormatString; bool Help2Format; bool NewFormat; + UInt64 PhySize; + + void UpdatePhySize(UInt64 v) { if (PhySize < v) PhySize = v; } int FindItem(const AString &name) const { - for (int i = 0; i < Items.Size(); i++) + FOR_VECTOR (i, Items) if (Items[i].Name == name) return i; return -1; @@ -65,6 +68,8 @@ struct CDatabase NewFormatString.Empty(); Help2Format = false; Items.Clear(); + StartPosition = 0; + PhySize = 0; } }; @@ -74,15 +79,16 @@ struct CResetTable 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]; + UInt64 startPos = ResetOffsets[(unsigned)blockIndex]; if (blockIndex + numBlocks >= ResetOffsets.Size()) size = CompressedSize - startPos; else - size = ResetOffsets[(int)(blockIndex + numBlocks)] - startPos; + size = ResetOffsets[(unsigned)(blockIndex + numBlocks)] - startPos; return true; } bool GetCompressedSizeOfBlock(UInt64 blockIndex, UInt64 &size) const @@ -107,7 +113,7 @@ struct CLzxInfo { if (Version == 2 || Version == 3) { - for (int i = 0; i <= 31; i++) + for (unsigned i = 0; i <= 31; i++) if (((UInt32)1 << i) >= WindowSize) return 15 + i; } @@ -123,7 +129,7 @@ struct CLzxInfo UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex); if (blockIndex >= ResetTable.ResetOffsets.Size()) return false; - offset = ResetTable.ResetOffsets[(int)blockIndex]; + offset = ResetTable.ResetOffsets[(unsigned)blockIndex]; return true; } bool GetCompressedSizeOfFolder(UInt64 folderIndex, UInt64 &size) const @@ -202,18 +208,21 @@ public: bool Check(); }; +/* class CProgressVirt { public: STDMETHOD(SetTotal)(const UInt64 *numFiles) PURE; STDMETHOD(SetCompleted)(const UInt64 *numFiles) PURE; }; +*/ class CInArchive { - UInt64 _startPosition; + CMyComPtr m_InStreamRef; ::CInBuffer _inBuffer; UInt64 _chunkSize; + bool _help2; Byte ReadByte(); void ReadBytes(Byte *data, UInt32 size); @@ -222,8 +231,8 @@ class CInArchive UInt32 ReadUInt32(); UInt64 ReadUInt64(); UInt64 ReadEncInt(); - void ReadString(int size, AString &s); - void ReadUString(int size, UString &s); + void ReadString(unsigned size, AString &s); + void ReadUString(unsigned size, UString &s); void ReadGUID(GUID &g); HRESULT ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size); @@ -232,6 +241,13 @@ class CInArchive HRESULT DecompressStream(IInStream *inStream, const CDatabase &database, const AString &name); public: + bool IsArc; + bool HeadersError; + bool UnexpectedEnd; + bool UnsupportedFeature; + + CInArchive(bool help2) { _help2 = help2; } + HRESULT OpenChm(IInStream *inStream, CDatabase &database); HRESULT OpenHelp2(IInStream *inStream, CDatabase &database); HRESULT OpenHighLevel(IInStream *inStream, CFilesDatabase &database); diff --git a/CPP/7zip/Archive/Chm/ChmRegister.cpp b/CPP/7zip/Archive/Chm/ChmRegister.cpp deleted file mode 100755 index e5f38afa..00000000 --- a/CPP/7zip/Archive/Chm/ChmRegister.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// 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 old mode 100755 new mode 100644 index e7fb6986..2854ff3e --- a/CPP/7zip/Archive/Chm/StdAfx.h +++ b/CPP/7zip/Archive/Chm/StdAfx.h @@ -3,6 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" +#include "../../../Common/Common.h" #endif diff --git a/CPP/7zip/Archive/Com/ComHandler.cpp b/CPP/7zip/Archive/Com/ComHandler.cpp deleted file mode 100755 index 58f76439..00000000 --- a/CPP/7zip/Archive/Com/ComHandler.cpp +++ /dev/null @@ -1,239 +0,0 @@ -// 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 deleted file mode 100755 index f2b7de96..00000000 --- a/CPP/7zip/Archive/Com/ComHandler.h +++ /dev/null @@ -1,28 +0,0 @@ -// 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 deleted file mode 100755 index 2203ca53..00000000 --- a/CPP/7zip/Archive/Com/ComIn.cpp +++ /dev/null @@ -1,389 +0,0 @@ -// 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 deleted file mode 100755 index 429d3796..00000000 --- a/CPP/7zip/Archive/Com/ComIn.h +++ /dev/null @@ -1,119 +0,0 @@ -// 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 deleted file mode 100755 index 6712b890..00000000 --- a/CPP/7zip/Archive/Com/ComRegister.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// 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/ComHandler.cpp b/CPP/7zip/Archive/ComHandler.cpp new file mode 100644 index 00000000..fc686b94 --- /dev/null +++ b/CPP/7zip/Archive/ComHandler.cpp @@ -0,0 +1,875 @@ +// ComHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" +#include "../../../C/CpuArch.h" + +#include "../../Common/IntToString.h" +#include "../../Common/ComTry.h" +#include "../../Common/MyCom.h" +#include "../../Common/MyBuffer.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) GetUi16(p) +#define Get32(p) GetUi32(p) + +namespace NArchive { +namespace NCom { + +#define SIGNATURE { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 } +static const UInt32 kSignatureSize = 8; +static const Byte kSignature[kSignatureSize] = SIGNATURE; + +enum EType +{ + k_Type_Common, + k_Type_Msi, + k_Type_Msp, + k_Type_Doc, + k_Type_Ppt, + k_Type_Xls, +}; + +static const char *kExtensions[] = +{ + "compound" + , "msi" + , "msp" + , "doc" + , "ppt" + , "xls" +}; + +namespace NFatID +{ + static const UInt32 kFree = 0xFFFFFFFF; + static const UInt32 kEndOfChain = 0xFFFFFFFE; + static const UInt32 kFatSector = 0xFFFFFFFD; + static const UInt32 kMatSector = 0xFFFFFFFC; + static const UInt32 kMaxValue = 0xFFFFFFFA; +} + +namespace NItemType +{ + static const Byte kEmpty = 0; + static const Byte kStorage = 1; + static const Byte kStream = 2; + static const Byte kLockBytes = 3; + static const Byte kProperty = 4; + static const Byte kRootStorage = 5; +} + +static 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; + CObjArray MiniSids; + + HRESULT AddNode(int parent, UInt32 did); +public: + + CObjArray Fat; + UInt32 FatSize; + + CObjArray Mat; + UInt32 MatSize; + + CObjectVector Items; + CRecordVector Refs; + + UInt32 LongStreamMinSize; + unsigned SectorSizeBits; + unsigned MiniSectorSizeBits; + + Int32 MainSubfile; + + UInt64 PhySize; + EType Type; + + bool IsNotArcType() const + { + return + Type != k_Type_Msi && + Type != k_Type_Msp; + } + + void UpdatePhySize(UInt64 val) + { + if (PhySize < val) + PhySize = val; + } + HRESULT ReadSector(IInStream *inStream, Byte *buf, unsigned sectorSizeBits, UInt32 sid); + HRESULT ReadIDs(IInStream *inStream, Byte *buf, unsigned sectorSizeBits, UInt32 sid, UInt32 *dest); + + HRESULT Update_PhySize_WithItem(unsigned index); + + 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 + { + unsigned 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); +}; + + +HRESULT CDatabase::ReadSector(IInStream *inStream, Byte *buf, unsigned sectorSizeBits, UInt32 sid) +{ + UpdatePhySize(((UInt64)sid + 2) << sectorSizeBits); + RINOK(inStream->Seek((((UInt64)sid + 1) << sectorSizeBits), STREAM_SEEK_SET, NULL)); + return ReadStream_FALSE(inStream, buf, (UInt32)1 << sectorSizeBits); +} + +HRESULT CDatabase::ReadIDs(IInStream *inStream, Byte *buf, unsigned 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() +{ + PhySize = 0; + + 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 (unsigned i = 0; i < s.Len(); 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 unsigned kMsiNumBits = 6; +static const UInt32 kMsiNumChars = 1 << kMsiNumBits; +static const UInt32 kMsiCharMask = kMsiNumChars - 1; +static const UInt32 kMsiStartUnicodeChar = 0x3800; +static const UInt32 kMsiUnicodeRange = kMsiNumChars * (kMsiNumChars + 1); + +static bool IsMsiName(const Byte *p) +{ + UInt32 c = Get16(p); + return + c >= kMsiStartUnicodeChar && + c <= kMsiStartUnicodeChar + kMsiUnicodeRange; +} + +static bool AreEqualNames(const Byte *rawName, const char *asciiName) +{ + for (unsigned i = 0; i < kNameSizeMax / 2; i++) + { + wchar_t c = Get16(rawName + i * 2); + wchar_t c2 = (Byte)asciiName[i]; + if (c != c2) + return false; + if (c == 0) + return true; + } + return false; +} + +static bool CompoundMsiNameToFileName(const UString &name, UString &resultName) +{ + resultName.Empty(); + for (unsigned i = 0; i < name.Len(); 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 (unsigned i = 0; i < kNameSizeMax; i += 2) + { + wchar_t c = Get16(p + i); + 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.InsertAtFront(WCHAR_PATH_SEPARATOR); + s.Insert(0, ConvertName(item.Name)); + index = ref.Parent; + } + return s; +} + +HRESULT CDatabase::Update_PhySize_WithItem(unsigned index) +{ + const CItem &item = Items[index]; + bool isLargeStream = (index == 0 || IsLargeStream(item.Size)); + if (!isLargeStream) + return S_OK; + unsigned bsLog = isLargeStream ? SectorSizeBits : MiniSectorSizeBits; + // streamSpec->Size = item.Size; + + UInt32 clusterSize = (UInt32)1 << bsLog; + UInt64 numClusters64 = (item.Size + clusterSize - 1) >> bsLog; + if (numClusters64 >= ((UInt32)1 << 31)) + return S_FALSE; + UInt32 sid = item.Sid; + UInt64 size = item.Size; + + if (size != 0) + { + for (;; size -= clusterSize) + { + // if (isLargeStream) + { + if (sid >= FatSize) + return S_FALSE; + UpdatePhySize(((UInt64)sid + 2) << bsLog); + sid = Fat[sid]; + } + if (size <= clusterSize) + break; + } + } + if (sid != NFatID::kEndOfChain) + return S_FALSE; + return S_OK; +} + +// There is name "[!]MsiPatchSequence" in msp files +static const unsigned kMspSequence_Size = 18; +static const Byte kMspSequence[kMspSequence_Size] = + { 0x40, 0x48, 0x96, 0x45, 0x6C, 0x3E, 0xE4, 0x45, + 0xE6, 0x42, 0x16, 0x42, 0x37, 0x41, 0x27, 0x41, + 0x37, 0x41 }; + +HRESULT CDatabase::Open(IInStream *inStream) +{ + MainSubfile = -1; + Type = k_Type_Common; + const UInt32 kHeaderSize = 512; + Byte p[kHeaderSize]; + PhySize = 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) // Little-endian + return S_FALSE; + unsigned sectorSizeBits = Get16(p + 0x1E); + bool mode64bit = (sectorSizeBits >= 12); + unsigned miniSectorSizeBits = Get16(p + 0x20); + SectorSizeBits = sectorSizeBits; + MiniSectorSizeBits = miniSectorSizeBits; + + if (sectorSizeBits > 28 || + sectorSizeBits < 7 || + miniSectorSizeBits > 28 || + miniSectorSizeBits < 2 || + miniSectorSizeBits > sectorSizeBits) + return S_FALSE; + UInt32 numSectorsForFAT = Get32(p + 0x2C); // SAT + LongStreamMinSize = Get32(p + 0x38); + + UInt32 sectSize = (UInt32)1 << sectorSizeBits; + + CByteBuffer sect(sectSize); + + unsigned ssb2 = sectorSizeBits - 2; + UInt32 numSidsInSec = (UInt32)1 << ssb2; + UInt32 numFatItems = numSectorsForFAT << ssb2; + if ((numFatItems >> ssb2) != numSectorsForFAT) + return S_FALSE; + FatSize = numFatItems; + + { + UInt32 numSectorsForBat = Get32(p + 0x48); // master sector allocation table + const UInt32 kNumHeaderBatItems = 109; + UInt32 numBatItems = kNumHeaderBatItems + (numSectorsForBat << ssb2); + if (numBatItems < kNumHeaderBatItems || ((numBatItems - kNumHeaderBatItems) >> ssb2) != numSectorsForBat) + return S_FALSE; + CObjArray bat(numBatItems); + 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; + + Fat.Alloc(numFatItems); + 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)); + } + FatSize = numFatItems = i; + } + + UInt32 numMatItems; + { + UInt32 numSectorsForMat = Get32(p + 0x40); + numMatItems = (UInt32)numSectorsForMat << ssb2; + if ((numMatItems >> ssb2) != numSectorsForMat) + return S_FALSE; + Mat.Alloc(numMatItems); + UInt32 i; + UInt32 sid = Get32(p + 0x3C); // short-sector table SID + 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; + } + + { + CByteBuffer used(numFatItems); + for (UInt32 i = 0; i < numFatItems; i++) + used[i] = 0; + UInt32 sid = Get32(p + 0x30); // directory stream SID + for (;;) + { + if (sid >= numFatItems) + return S_FALSE; + if (used[sid]) + return S_FALSE; + used[sid] = 1; + 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; + } + } + + const 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; + MiniSids.Alloc(numSectorsInMiniStream); + { + 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_VECTOR (i, Refs) + { + const CItem &item = Items[Refs[i].Did]; + if (item.IsDir() || numCabs > 1) + continue; + bool isMsiName; + UString msiName = ConvertName(item.Name, isMsiName); + if (isMsiName && msiName.Len() >= 4 && + MyStringCompareNoCase(msiName.RightPtr(4), L".cab") == 0) + { + numCabs++; + MainSubfile = i; + } + } + if (numCabs > 1) + MainSubfile = -1; + + { + FOR_VECTOR(t, Items) + { + Update_PhySize_WithItem(t); + } + } + { + FOR_VECTOR(t, Items) + { + const CItem &item = Items[t]; + + if (IsMsiName(item.Name)) + { + Type = k_Type_Msi; + if (memcmp(item.Name, kMspSequence, kMspSequence_Size) == 0) + { + Type = k_Type_Msp; + break; + } + continue; + } + if (AreEqualNames(item.Name, "WordDocument")) + { + Type = k_Type_Doc; + break; + } + if (AreEqualNames(item.Name, "PowerPoint Document")) + { + Type = k_Type_Ppt; + break; + } + if (AreEqualNames(item.Name, "Workbook")) + { + Type = k_Type_Xls; + break; + } + } + } + + return S_OK; +} + +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); +}; + +static const Byte kProps[] = +{ + kpidPath, + kpidSize, + kpidPackSize, + kpidCTime, + kpidMTime +}; + +static const Byte kArcProps[] = +{ + kpidExtension, + kpidClusterSize, + kpidSectorSize +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch (propID) + { + case kpidExtension: prop = kExtensions[_db.Type]; break; + case kpidPhySize: prop = _db.PhySize; break; + case kpidClusterSize: prop = (UInt32)1 << _db.SectorSizeBits; break; + case kpidSectorSize: prop = (UInt32)1 << _db.MiniSectorSizeBits; break; + case kpidMainSubfile: if (_db.MainSubfile >= 0) prop = (UInt32)_db.MainSubfile; break; + case kpidIsNotArcType: if (_db.IsNotArcType()) prop = true; 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)(Int32)-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; + UInt32 itemIndex = _db.Refs[index].Did; + const CItem &item = _db.Items[itemIndex]; + CClusterInStream *streamSpec = new CClusterInStream; + CMyComPtr streamTemp = streamSpec; + streamSpec->Stream = _stream; + streamSpec->StartOffset = 0; + + bool isLargeStream = (itemIndex == 0 || _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.ClearAndReserve((unsigned)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.AddInReserved(sid + 1); + sid = _db.Fat[sid]; + } + else + { + UInt64 val = 0; + if (sid >= _db.MatSize || !_db.GetMiniCluster(sid, val) || val >= (UInt64)1 << 32) + return S_FALSE; + streamSpec->Vector.AddInReserved((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 +} + +IMP_CreateArcIn + +static CArcInfo g_ArcInfo = + { "Compound", "msi msp doc xls ppt", 0, 0xE5, + kSignatureSize, SIGNATURE, + 0, + 0, + CreateArc }; + +REGISTER_ARC(Com) + +}} diff --git a/CPP/7zip/Archive/Common/CoderMixer.cpp b/CPP/7zip/Archive/Common/CoderMixer.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Common/CoderMixer.h b/CPP/7zip/Archive/Common/CoderMixer.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Common/CoderMixer2.cpp b/CPP/7zip/Archive/Common/CoderMixer2.cpp old mode 100755 new mode 100644 index 0b06a489..13019d1f --- a/CPP/7zip/Archive/Common/CoderMixer2.cpp +++ b/CPP/7zip/Archive/Common/CoderMixer2.cpp @@ -11,16 +11,23 @@ CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo): { srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams); - UInt32 j; + UInt32 j; + _srcInToDestOutMap.ClearAndSetSize(NumSrcInStreams); + DestOutToSrcInMap.ClearAndSetSize(NumSrcInStreams); + for (j = 0; j < NumSrcInStreams; j++) { - _srcInToDestOutMap.Add(0); - DestOutToSrcInMap.Add(0); + _srcInToDestOutMap[j] = 0; + DestOutToSrcInMap[j] = 0; } + + _srcOutToDestInMap.ClearAndSetSize(_numSrcOutStreams); + _destInToSrcOutMap.ClearAndSetSize(_numSrcOutStreams); + for (j = 0; j < _numSrcOutStreams; j++) { - _srcOutToDestInMap.Add(0); - _destInToSrcOutMap.Add(0); + _srcOutToDestInMap[j] = 0; + _destInToSrcOutMap[j] = 0; } UInt32 destInOffset = 0; @@ -53,66 +60,57 @@ CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo): void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo) { - destBindInfo.Coders.Clear(); - destBindInfo.BindPairs.Clear(); - destBindInfo.InStreams.Clear(); - destBindInfo.OutStreams.Clear(); + destBindInfo.Coders.ClearAndReserve(_srcBindInfo.Coders.Size()); + destBindInfo.BindPairs.ClearAndReserve(_srcBindInfo.BindPairs.Size()); + destBindInfo.InStreams.ClearAndReserve(_srcBindInfo.OutStreams.Size()); + destBindInfo.OutStreams.ClearAndReserve(_srcBindInfo.InStreams.Size()); - int i; - for (i = _srcBindInfo.Coders.Size() - 1; i >= 0; i--) + unsigned i; + for (i = _srcBindInfo.Coders.Size(); i != 0;) { + i--; const CCoderStreamsInfo &srcCoderInfo = _srcBindInfo.Coders[i]; CCoderStreamsInfo destCoderInfo; destCoderInfo.NumInStreams = srcCoderInfo.NumOutStreams; destCoderInfo.NumOutStreams = srcCoderInfo.NumInStreams; - destBindInfo.Coders.Add(destCoderInfo); + destBindInfo.Coders.AddInReserved(destCoderInfo); } - for (i = _srcBindInfo.BindPairs.Size() - 1; i >= 0; i--) + for (i = _srcBindInfo.BindPairs.Size(); 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); + destBindInfo.BindPairs.AddInReserved(destBindPair); } for (i = 0; i < _srcBindInfo.InStreams.Size(); i++) - destBindInfo.OutStreams.Add(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]); + destBindInfo.OutStreams.AddInReserved(_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); + destBindInfo.InStreams.AddInReserved(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]); } -static void SetSizes(const UInt64 **srcSizes, CRecordVector &sizes, +void SetSizes(const UInt64 **srcSizes, CRecordVector &sizes, CRecordVector &sizePointers, UInt32 numItems) { - sizes.Clear(); - sizePointers.Clear(); + sizes.ClearAndSetSize(numItems); + sizePointers.ClearAndSetSize(numItems); for(UInt32 i = 0; i < numItems; i++) { - if (srcSizes == 0 || srcSizes[i] == NULL) + if (!srcSizes || !srcSizes[i]) { - sizes.Add(0); - sizePointers.Add(NULL); + sizes[i] = 0; + sizePointers[i] = NULL; } else { - sizes.Add(*srcSizes[i]); - sizePointers.Add(&sizes.Back()); + sizes[i] = *(srcSizes[i]); + sizePointers[i] = &sizes[i]; } } } -void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes, - const UInt64 **outSizes) +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 old mode 100755 new mode 100644 index a03722d6..50e7077a --- a/CPP/7zip/Archive/Common/CoderMixer2.h +++ b/CPP/7zip/Archive/Common/CoderMixer2.h @@ -3,9 +3,9 @@ #ifndef __CODER_MIXER2_H #define __CODER_MIXER2_H -#include "../../../Common/MyVector.h" -#include "../../../Common/Types.h" #include "../../../Common/MyCom.h" +#include "../../../Common/MyVector.h" + #include "../../ICoder.h" namespace NCoderMixer { @@ -52,7 +52,7 @@ struct CBindInfo { numInStreams = 0; numOutStreams = 0; - for (int i = 0; i < Coders.Size(); i++) + FOR_VECTOR (i, Coders) { const CCoderStreamsInfo &coderStreamsInfo = Coders[i]; numInStreams += coderStreamsInfo.NumInStreams; @@ -62,14 +62,14 @@ struct CBindInfo int FindBinderForInStream(UInt32 inStream) const { - for (int i = 0; i < BindPairs.Size(); i++) + FOR_VECTOR (i, BindPairs) if (BindPairs[i].InIndex == inStream) return i; return -1; } int FindBinderForOutStream(UInt32 outStream) const { - for (int i = 0; i < BindPairs.Size(); i++) + FOR_VECTOR (i, BindPairs) if (BindPairs[i].OutIndex == outStream) return i; return -1; @@ -139,6 +139,9 @@ public: void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo); }; +void SetSizes(const UInt64 **srcSizes, CRecordVector &sizes, + CRecordVector &sizePointers, UInt32 numItems); + struct CCoderInfo2 { CMyComPtr Coder; @@ -151,7 +154,9 @@ struct CCoderInfo2 CRecordVector InSizePointers; CRecordVector OutSizePointers; - CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams); + CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams): + NumInStreams(numInStreams), + NumOutStreams(numOutStreams) {} void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); HRESULT QueryInterface(REFGUID iid, void** pp) const @@ -170,5 +175,5 @@ public: }; } -#endif +#endif diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp old mode 100755 new mode 100644 index 87686e85..5288fbc1 --- a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp +++ b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp @@ -9,30 +9,28 @@ namespace NCoderMixer { CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams): CCoderInfo2(numInStreams, numOutStreams) { - InStreams.Reserve(NumInStreams); - InStreamPointers.Reserve(NumInStreams); - OutStreams.Reserve(NumOutStreams); - OutStreamPointers.Reserve(NumOutStreams); + InStreams.ClearAndReserve(NumInStreams); + OutStreams.ClearAndReserve(NumOutStreams); } void CCoder2::Execute() { Code(NULL); } void CCoder2::Code(ICompressProgressInfo *progress) { - InStreamPointers.Clear(); - OutStreamPointers.Clear(); + InStreamPointers.ClearAndReserve(NumInStreams); + OutStreamPointers.ClearAndReserve(NumOutStreams); UInt32 i; for (i = 0; i < NumInStreams; i++) { - if (InSizePointers[i] != NULL) + if (InSizePointers[i]) InSizePointers[i] = &InSizes[i]; - InStreamPointers.Add((ISequentialInStream *)InStreams[i]); + InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]); } for (i = 0; i < NumOutStreams; i++) { - if (OutSizePointers[i] != NULL) + if (OutSizePointers[i]) OutSizePointers[i] = &OutSizes[i]; - OutStreamPointers.Add((ISequentialOutStream *)OutStreams[i]); + OutStreamPointers.AddInReserved((ISequentialOutStream *)OutStreams[i]); } if (Coder) Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0], @@ -41,7 +39,7 @@ void CCoder2::Code(ICompressProgressInfo *progress) Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams, &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress); { - int i; + unsigned i; for (i = 0; i < InStreams.Size(); i++) InStreams[i].Release(); for (i = 0; i < OutStreams.Size(); i++) @@ -49,32 +47,13 @@ void CCoder2::Code(ICompressProgressInfo *progress) } } -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 @@ -83,10 +62,9 @@ HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo) { _bindInfo = bindInfo; _streamBinders.Clear(); - for (int i = 0; i < _bindInfo.BindPairs.Size(); i++) + FOR_VECTOR (i, _bindInfo.BindPairs) { - _streamBinders.Add(CStreamBinder()); - RINOK(_streamBinders.Back().CreateEvents()); + RINOK(_streamBinders.AddNew().CreateEvents()); } return S_OK; } @@ -113,7 +91,7 @@ void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder) void CCoderMixer2MT::ReInit() { - for (int i = 0; i < _streamBinders.Size(); i++) + FOR_VECTOR (i, _streamBinders) _streamBinders[i].ReInit(); } @@ -124,7 +102,7 @@ HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStre if (_coders.Size() != _bindInfo.Coders.Size()) throw 0; */ - int i; + unsigned i; for (i = 0; i < _coders.Size(); i++) { CCoder2 &coderInfo = _coders[i]; @@ -179,7 +157,7 @@ HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStre HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code) { - for (int i = 0; i < _coders.Size(); i++) + FOR_VECTOR (i, _coders) if (_coders[i].Result == code) return code; return S_OK; @@ -199,7 +177,7 @@ STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams, Init(inStreams, outStreams); - int i; + unsigned i; for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) { diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.h b/CPP/7zip/Archive/Common/CoderMixer2MT.h old mode 100755 new mode 100644 index 81bb3f0b..ba475cec --- a/CPP/7zip/Archive/Common/CoderMixer2MT.h +++ b/CPP/7zip/Archive/Common/CoderMixer2MT.h @@ -12,15 +12,17 @@ namespace NCoderMixer { struct CCoder2: public CCoderInfo2, public CVirtThread { + CRecordVector InStreamPointers; + CRecordVector OutStreamPointers; + +public: HRESULT Result; CObjectVector< CMyComPtr > InStreams; CObjectVector< CMyComPtr > OutStreams; - CRecordVector InStreamPointers; - CRecordVector OutStreamPointers; CCoder2(UInt32 numInStreams, UInt32 numOutStreams); ~CCoder2() { CVirtThread::WaitThreadFinish(); } - void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); + // void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); virtual void Execute(); void Code(ICompressProgressInfo *progress); }; @@ -48,7 +50,7 @@ class CCoderMixer2MT: { CBindInfo _bindInfo; CObjectVector _streamBinders; - int _progressCoderIndex; + unsigned _progressCoderIndex; void AddCoderCommon(); HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams); @@ -68,7 +70,7 @@ public: HRESULT SetBindInfo(const CBindInfo &bindInfo); void AddCoder(ICompressCoder *coder); void AddCoder2(ICompressCoder2 *coder); - void SetProgressCoderIndex(int coderIndex) { _progressCoderIndex = coderIndex; } + void SetProgressCoderIndex(unsigned coderIndex) { _progressCoderIndex = coderIndex; } void ReInit(); void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.cpp b/CPP/7zip/Archive/Common/CoderMixer2ST.cpp old mode 100755 new mode 100644 index a21ca0c0..a94ba115 --- a/CPP/7zip/Archive/Common/CoderMixer2ST.cpp +++ b/CPP/7zip/Archive/Common/CoderMixer2ST.cpp @@ -47,7 +47,7 @@ HRESULT CCoderMixer2ST::GetInStream( { seqInStream = inStreams[i]; *inStreamRes = seqInStream.Detach(); - return S_OK; + return S_OK; } int binderIndex = _bindInfo.FindBinderForInStream(streamIndex); if (binderIndex < 0) @@ -96,7 +96,7 @@ HRESULT CCoderMixer2ST::GetOutStream( { seqOutStream = outStreams[i]; *outStreamRes = seqOutStream.Detach(); - return S_OK; + return S_OK; } int binderIndex = _bindInfo.FindBinderForOutStream(streamIndex); if (binderIndex < 0) diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.h b/CPP/7zip/Archive/Common/CoderMixer2ST.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Common/CoderMixerMT.cpp b/CPP/7zip/Archive/Common/CoderMixerMT.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Common/CoderMixerMT.h b/CPP/7zip/Archive/Common/CoderMixerMT.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Common/CrossThreadProgress.cpp b/CPP/7zip/Archive/Common/CrossThreadProgress.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Common/CrossThreadProgress.h b/CPP/7zip/Archive/Common/CrossThreadProgress.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Common/DummyOutStream.cpp b/CPP/7zip/Archive/Common/DummyOutStream.cpp old mode 100755 new mode 100644 index 54bcfec1..7c4f5487 --- a/CPP/7zip/Archive/Common/DummyOutStream.cpp +++ b/CPP/7zip/Archive/Common/DummyOutStream.cpp @@ -4,19 +4,14 @@ #include "DummyOutStream.h" -STDMETHODIMP CDummyOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +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); + UInt32 realProcessedSize = size; + HRESULT res = S_OK; + if (_stream) + res = _stream->Write(data, size, &realProcessedSize); _size += realProcessedSize; - if(processedSize != NULL) + if (processedSize) *processedSize = realProcessedSize; - return result; + return res; } diff --git a/CPP/7zip/Archive/Common/DummyOutStream.h b/CPP/7zip/Archive/Common/DummyOutStream.h old mode 100755 new mode 100644 index 13d5b62c..b5a51fc0 --- a/CPP/7zip/Archive/Common/DummyOutStream.h +++ b/CPP/7zip/Archive/Common/DummyOutStream.h @@ -1,10 +1,11 @@ // DummyOutStream.h -#ifndef __DUMMYOUTSTREAM_H -#define __DUMMYOUTSTREAM_H +#ifndef __DUMMY_OUT_STREAM_H +#define __DUMMY_OUT_STREAM_H + +#include "../../../Common/MyCom.h" #include "../../IStream.h" -#include "Common/MyCom.h" class CDummyOutStream: public ISequentialOutStream, diff --git a/CPP/7zip/Archive/Common/FindSignature.cpp b/CPP/7zip/Archive/Common/FindSignature.cpp old mode 100755 new mode 100644 index 15aa6cea..e9a0f032 --- a/CPP/7zip/Archive/Common/FindSignature.cpp +++ b/CPP/7zip/Archive/Common/FindSignature.cpp @@ -2,27 +2,25 @@ #include "StdAfx.h" -#include "Common/Buffer.h" - -#include "FindSignature.h" +#include "../../../Common/MyBuffer.h" #include "../../Common/StreamUtils.h" +#include "FindSignature.h" + HRESULT FindSignatureInStream(ISequentialInStream *stream, const Byte *signature, unsigned signatureSize, const UInt64 *limit, UInt64 &resPos) { resPos = 0; - CByteBuffer byteBuffer2; - byteBuffer2.SetCapacity(signatureSize); + CByteBuffer byteBuffer2(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); + CByteBuffer byteBuffer(kBufferSize); Byte *buffer = byteBuffer; UInt32 numPrevBytes = signatureSize - 1; memcpy(buffer, (const Byte *)byteBuffer2 + 1, numPrevBytes); diff --git a/CPP/7zip/Archive/Common/FindSignature.h b/CPP/7zip/Archive/Common/FindSignature.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp old mode 100755 new mode 100644 index 7e6f4602..18ad5580 --- a/CPP/7zip/Archive/Common/HandlerOut.cpp +++ b/CPP/7zip/Archive/Common/HandlerOut.cpp @@ -27,7 +27,7 @@ void CMultiMethodProps::SetGlobalLevelAndThreads(COneMethodInfo &oneMethodInfo ) { UInt32 level = _level; - if (level != (UInt32)(UInt32)-1) + if (level != (UInt32)(Int32)-1) SetMethodProp32(oneMethodInfo, NCoderPropID::kLevel, (UInt32)level); #ifndef _7ZIP_ST SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); @@ -40,7 +40,7 @@ void CMultiMethodProps::Init() _numProcessors = _numThreads = NSystem::GetNumberOfProcessors(); #endif - _level = (UInt32)(UInt32)-1; + _level = (UInt32)(Int32)-1; _autoFilter = true; _crcSize = 4; _filterMethod.Clear(); @@ -50,18 +50,18 @@ void CMultiMethodProps::Init() HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) { UString name = nameSpec; - name.MakeUpper(); + name.MakeLower_Ascii(); if (name.IsEmpty()) return E_INVALIDARG; - if (name[0] == 'X') + if (name[0] == 'x') { name.Delete(0); _level = 9; return ParsePropToUInt32(name, value, _level); } - if (name == L"CRC") + if (name == L"crc") { name.Delete(0, 3); _crcSize = 4; @@ -70,17 +70,17 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN UInt32 number; int index = ParseStringToUInt32(name, number); - UString realName = name.Mid(index); + UString realName = name.Ptr(index); if (index == 0) { - if (name.Left(2).CompareNoCase(L"MT") == 0) + if (name.IsPrefixedBy(L"mt")) { #ifndef _7ZIP_ST - RINOK(ParseMtProp(name.Mid(2), value, _numProcessors, _numThreads)); + RINOK(ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads)); #endif return S_OK; } - if (name.CompareNoCase(L"F") == 0) + if (name.IsEqualTo("f")) { HRESULT res = PROPVARIANT_to_bool(value, _autoFilter); if (res == S_OK) @@ -105,35 +105,35 @@ void CSingleMethodProps::Init() _numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors(); AddNumThreadsProp(_numThreads); #endif - _level = (UInt32)(UInt32)-1; + _level = (UInt32)(Int32)-1; } -HRESULT CSingleMethodProps::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) +HRESULT CSingleMethodProps::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) { Init(); - for (int i = 0; i < numProps; i++) + for (UInt32 i = 0; i < numProps; i++) { UString name = names[i]; - name.MakeUpper(); + name.MakeLower_Ascii(); if (name.IsEmpty()) return E_INVALIDARG; const PROPVARIANT &value = values[i]; - if (name[0] == L'X') + if (name[0] == L'x') { UInt32 a = 9; - RINOK(ParsePropToUInt32(name.Mid(1), value, a)); + RINOK(ParsePropToUInt32(name.Ptr(1), value, a)); _level = a; AddLevelProp(a); } - else if (name.Left(2).CompareNoCase(L"MT") == 0) + else if (name.IsPrefixedBy(L"mt")) { #ifndef _7ZIP_ST - RINOK(ParseMtProp(name.Mid(2), value, _numProcessors, _numThreads)); + RINOK(ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads)); AddNumThreadsProp(_numThreads); #endif } else - return ParseParamsFromPROPVARIANT(name, value); + return ParseMethodFromPROPVARIANT(names[i], value); } return S_OK; } diff --git a/CPP/7zip/Archive/Common/HandlerOut.h b/CPP/7zip/Archive/Common/HandlerOut.h old mode 100755 new mode 100644 index d3c9a237..40a4a698 --- a/CPP/7zip/Archive/Common/HandlerOut.h +++ b/CPP/7zip/Archive/Common/HandlerOut.h @@ -27,16 +27,16 @@ public: #endif ); - int GetNumEmptyMethods() const + unsigned GetNumEmptyMethods() const { - int i; + unsigned i; for (i = 0; i < _methods.Size(); i++) if (!_methods[i].IsEmpty()) break; return i; } - int GetLevel() const { return _level == (UInt32)(UInt32)-1 ? 5 : (int)_level; } + int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; } void Init(); @@ -44,20 +44,20 @@ public: HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); }; -class CSingleMethodProps: public CMethodProps +class CSingleMethodProps: public COneMethodInfo { UInt32 _level; - void Init(); public: #ifndef _7ZIP_ST UInt32 _numThreads; UInt32 _numProcessors; #endif + void Init(); CSingleMethodProps() { Init(); } - int GetLevel() const { return _level == (UInt32)(UInt32)-1 ? 5 : (int)_level; } - HRESULT SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps); + int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; } + HRESULT SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); }; } diff --git a/CPP/7zip/Archive/Common/InStreamWithCRC.cpp b/CPP/7zip/Archive/Common/InStreamWithCRC.cpp old mode 100755 new mode 100644 index 569a56f3..3f4dd3b8 --- a/CPP/7zip/Archive/Common/InStreamWithCRC.cpp +++ b/CPP/7zip/Archive/Common/InStreamWithCRC.cpp @@ -6,29 +6,33 @@ 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) + UInt32 realProcessed = 0; + HRESULT result = S_OK; + if (_stream) + _stream->Read(data, size, &realProcessed); + _size += realProcessed; + if (size > 0 && realProcessed == 0) _wasFinished = true; - _crc = CrcUpdate(_crc, data, realProcessedSize); - if(processedSize != NULL) - *processedSize = realProcessedSize; + _crc = CrcUpdate(_crc, data, realProcessed); + if (processedSize) + *processedSize = realProcessed; return result; } STDMETHODIMP CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) { - UInt32 realProcessedSize; - HRESULT result = _stream->Read(data, size, &realProcessedSize); + UInt32 realProcessed = 0; + HRESULT result = S_OK; + if (_stream) + result = _stream->Read(data, size, &realProcessed); + _size += realProcessed; /* - if (size > 0 && realProcessedSize == 0) + if (size > 0 && realProcessed == 0) _wasFinished = true; */ - _size += realProcessedSize; - _crc = CrcUpdate(_crc, data, realProcessedSize); - if(processedSize != NULL) - *processedSize = realProcessedSize; + _crc = CrcUpdate(_crc, data, realProcessed); + if (processedSize) + *processedSize = realProcessed; return result; } diff --git a/CPP/7zip/Archive/Common/InStreamWithCRC.h b/CPP/7zip/Archive/Common/InStreamWithCRC.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/CPP/7zip/Archive/Common/ItemNameUtils.cpp old mode 100755 new mode 100644 index cc476fad..7cd3037b --- a/CPP/7zip/Archive/Common/ItemNameUtils.cpp +++ b/CPP/7zip/Archive/Common/ItemNameUtils.cpp @@ -2,8 +2,6 @@ #include "StdAfx.h" -#include "../../../../C/Types.h" - #include "ItemNameUtils.h" namespace NArchive { @@ -12,6 +10,21 @@ namespace NItemName { static const wchar_t kOSDirDelimiter = WCHAR_PATH_SEPARATOR; static const wchar_t kDirDelimiter = L'/'; +void ReplaceToOsPathSeparator(wchar_t *s) +{ + #ifdef _WIN32 + for (;;) + { + wchar_t c = *s; + if (c == 0) + break; + if (c == kDirDelimiter) + *s = kOSDirDelimiter; + s++; + } + #endif +} + UString MakeLegalName(const UString &name) { UString zipName = name; @@ -36,15 +49,29 @@ UString GetOSName2(const UString &name) return newName; } -bool HasTailSlash(const AString &name, UINT codePage) +void ConvertToOSName2(UString &name) +{ + if (!name.IsEmpty()) + { + name.Replace(kDirDelimiter, kOSDirDelimiter); + if (name.Back() == kOSDirDelimiter) + name.DeleteBack(); + } +} + +bool HasTailSlash(const AString &name, UINT + #if defined(_WIN32) && !defined(UNDER_CE) + codePage + #endif + ) { if (name.IsEmpty()) return false; LPCSTR prev = #if defined(_WIN32) && !defined(UNDER_CE) - CharPrevExA((WORD)codePage, name, &name[name.Length()], 0); + CharPrevExA((WORD)codePage, name, &name[name.Len()], 0); #else - (LPCSTR)(name) + (name.Length() - 1); + (LPCSTR)(name) + (name.Len() - 1); #endif return (*prev == '/'); } diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.h b/CPP/7zip/Archive/Common/ItemNameUtils.h old mode 100755 new mode 100644 index 5eafacb1..d0dc76a4 --- a/CPP/7zip/Archive/Common/ItemNameUtils.h +++ b/CPP/7zip/Archive/Common/ItemNameUtils.h @@ -1,16 +1,19 @@ // Archive/Common/ItemNameUtils.h -#ifndef __ARCHIVE_ITEMNAMEUTILS_H -#define __ARCHIVE_ITEMNAMEUTILS_H +#ifndef __ARCHIVE_ITEM_NAME_UTILS_H +#define __ARCHIVE_ITEM_NAME_UTILS_H #include "../../../Common/MyString.h" namespace NArchive { namespace NItemName { + void ReplaceToOsPathSeparator(wchar_t *s); + UString MakeLegalName(const UString &name); UString GetOSName(const UString &name); UString GetOSName2(const UString &name); + void ConvertToOSName2(UString &name); bool HasTailSlash(const AString &name, UINT codePage); #ifdef _WIN32 diff --git a/CPP/7zip/Archive/Common/MultiStream.cpp b/CPP/7zip/Archive/Common/MultiStream.cpp old mode 100755 new mode 100644 index 04d11caf..5bf0bef9 --- a/CPP/7zip/Archive/Common/MultiStream.cpp +++ b/CPP/7zip/Archive/Common/MultiStream.cpp @@ -11,10 +11,10 @@ STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize) if (size == 0) return S_OK; if (_pos >= _totalLength) - return (_pos == _totalLength) ? S_OK : E_FAIL; + return S_OK; { - int left = 0, mid = _streamIndex, right = Streams.Size(); + unsigned left = 0, mid = _streamIndex, right = Streams.Size(); for (;;) { CSubStreamInfo &m = Streams[mid]; @@ -51,15 +51,18 @@ STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize) STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - switch(seekOrigin) + 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; + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _pos; break; + case STREAM_SEEK_END: offset += _totalLength; break; default: return STG_E_INVALIDFUNCTION; } - if (newPosition != 0) - *newPosition = _pos; + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _pos = offset; + if (newPosition) + *newPosition = offset; return S_OK; } @@ -69,7 +72,7 @@ class COutVolumeStream: public ISequentialOutStream, public CMyUnknownImp { - int _volIndex; + unsigned _volIndex; UInt64 _volSize; UInt64 _curPos; CMyComPtr _volumeStream; @@ -169,22 +172,20 @@ STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *proce STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - if(seekOrigin >= 3) - return STG_E_INVALIDFUNCTION; - switch(seekOrigin) + switch (seekOrigin) { - case STREAM_SEEK_SET: - _absPos = offset; - break; - case STREAM_SEEK_CUR: - _absPos += offset; - break; - case STREAM_SEEK_END: - _absPos = _length + offset; - break; + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _absPos; break; + case STREAM_SEEK_END: offset += _length; break; + default: return STG_E_INVALIDFUNCTION; } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _absPos = offset; _offsetPos = _absPos; _streamIndex = 0; + if (newPosition) + *newPosition = offset; return S_OK; } */ diff --git a/CPP/7zip/Archive/Common/MultiStream.h b/CPP/7zip/Archive/Common/MultiStream.h old mode 100755 new mode 100644 index 3fceb7cc..2a1a4a43 --- a/CPP/7zip/Archive/Common/MultiStream.h +++ b/CPP/7zip/Archive/Common/MultiStream.h @@ -14,7 +14,7 @@ class CMultiStream: { UInt64 _pos; UInt64 _totalLength; - int _streamIndex; + unsigned _streamIndex; public: struct CSubStreamInfo { @@ -28,7 +28,7 @@ public: HRESULT Init() { UInt64 total = 0; - for (int i = 0; i < Streams.Size(); i++) + FOR_VECTOR (i, Streams) { CSubStreamInfo &s = Streams[i]; s.GlobalOffset = total; @@ -52,7 +52,7 @@ class COutMultiStream: public IOutStream, public CMyUnknownImp { - int _streamIndex; // required stream + unsigned _streamIndex; // required stream UInt64 _offsetPos; // offset from start of _streamIndex index UInt64 _absPos; UInt64 _length; diff --git a/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp b/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Common/OutStreamWithCRC.h b/CPP/7zip/Archive/Common/OutStreamWithCRC.h old mode 100755 new mode 100644 index 115b442a..09b899bb --- a/CPP/7zip/Archive/Common/OutStreamWithCRC.h +++ b/CPP/7zip/Archive/Common/OutStreamWithCRC.h @@ -28,6 +28,7 @@ public: _calculate = calculate; _crc = CRC_INIT_VAL; } + void EnableCalc(bool calculate) { _calculate = calculate; } void InitCRC() { _crc = CRC_INIT_VAL; } UInt64 GetSize() const { return _size; } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.h b/CPP/7zip/Archive/Common/OutStreamWithSha1.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Common/ParseProperties.cpp b/CPP/7zip/Archive/Common/ParseProperties.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Common/ParseProperties.h b/CPP/7zip/Archive/Common/ParseProperties.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Common/StdAfx.h b/CPP/7zip/Archive/Common/StdAfx.h old mode 100755 new mode 100644 index 2e4be10b..2854ff3e --- a/CPP/7zip/Archive/Common/StdAfx.h +++ b/CPP/7zip/Archive/Common/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" -#include "../../../Common/NewHandler.h" +#include "../../../Common/Common.h" #endif diff --git a/CPP/7zip/Archive/CpioHandler.cpp b/CPP/7zip/Archive/CpioHandler.cpp old mode 100755 new mode 100644 index 0f32ef66..9c1271c4 --- a/CPP/7zip/Archive/CpioHandler.cpp +++ b/CPP/7zip/Archive/CpioHandler.cpp @@ -2,12 +2,15 @@ #include "StdAfx.h" -#include "Common/ComTry.h" -#include "Common/StringConvert.h" -#include "Common/StringToInt.h" +#include "../../../C/CpuArch.h" -#include "Windows/PropVariant.h" -#include "Windows/Time.h" +#include "../../Common/ComTry.h" +#include "../../Common/StringConvert.h" +#include "../../Common/StringToInt.h" +#include "../../Common/UTFConvert.h" + +#include "../../Windows/PropVariant.h" +#include "../../Windows/TimeUtils.h" #include "../Common/LimitedStreams.h" #include "../Common/ProgressUtils.h" @@ -18,24 +21,30 @@ #include "Common/ItemNameUtils.h" +using namespace NWindows; + namespace NArchive { namespace NCpio { -namespace NFileHeader -{ - namespace NMagic - { - const char *kMagic1 = "070701"; - const char *kMagic2 = "070702"; - const char *kMagic3 = "070707"; - const char *kEndName = "TRAILER!!!"; +static const Byte kMagicBin0 = 0xC7; +static const Byte kMagicBin1 = 0x71; - const Byte kMagicForRecord2[2] = { 0xC7, 0x71 }; - } +// #define MAGIC_ASCII { '0', '7', '0', '7', '0' } + +static const Byte kMagicHex = '1'; // New ASCII Format +static const Byte kMagicHexCrc = '2'; // New CRC Format +static const Byte kMagicOct = '7'; // Portable ASCII Format + +static const char *kName_TRAILER = "TRAILER!!!"; + +static const unsigned k_BinRecord_Size = 2 + 8 * 2 + 2 * 4; +static const unsigned k_OctRecord_Size = 6 + 8 * 6 + 2 * 11; +static const unsigned k_HexRecord_Size = 6 + 13 * 8; + +static const unsigned k_RecordSize_Max = k_HexRecord_Size; - const UInt32 kRecord2Size = 26; /* - struct CRecord2 + struct CBinRecord { unsigned short c_magic; short c_dev; @@ -49,13 +58,10 @@ namespace NFileHeader unsigned short c_namesize; unsigned short c_filesizes[2]; }; - */ - - const UInt32 kRecordSize = 110; - /* - struct CRecord + + struct CHexRecord { - char Magic[6]; // "070701" for "new" portable format, "070702" for CRC format + char Magic[6]; char inode[8]; char Mode[8]; char UID[8]; @@ -69,15 +75,26 @@ namespace NFileHeader 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; - -} +enum EType +{ + k_Type_BinLe, + k_Type_BinBe, + k_Type_Oct, + k_Type_Hex, + k_Type_HexCrc +}; + +static const char *k_Types[] = +{ + "Binary LE" + , "Binary BE" + , "Portable ASCII" + , "New ASCII" + , "New CRC" +}; struct CItem { @@ -86,12 +103,9 @@ struct CItem UInt32 Mode; UInt32 UID; UInt32 GID; - UInt32 Size; + UInt64 Size; UInt32 MTime; - // char LinkFlag; - // AString LinkName; ????? - char Magic[8]; UInt32 NumLinks; UInt32 DevMajor; UInt32 DevMinor; @@ -100,394 +114,479 @@ struct CItem UInt32 ChkSum; UInt32 Align; + EType Type; + + UInt32 HeaderSize; + UInt64 HeaderPos; + bool IsBin() const { return Type == k_Type_BinLe || Type == k_Type_BinBe; } + bool IsCrcFormat() const { return Type == k_Type_HexCrc; }; bool IsDir() const { return (Mode & 0170000) == 0040000; } + bool IsTrailer() const { return strcmp(Name, kName_TRAILER) == 0; } + UInt64 GetDataPosition() const { return HeaderPos + HeaderSize; }; }; -class CItemEx: public CItem +enum EErrorType { -public: - UInt64 HeaderPosition; - UInt32 HeaderSize; - UInt64 GetDataPosition() const { return HeaderPosition + HeaderSize; }; + k_ErrorType_OK, + k_ErrorType_Corrupted, + k_ErrorType_UnexpectedEnd, }; -const UInt32 kMaxBlockSize = NFileHeader::kRecordSize; - -class CInArchive +struct CInArchive { - CMyComPtr m_Stream; - UInt64 m_Position; - - UInt16 _blockSize; - Byte _block[kMaxBlockSize]; - UInt32 _blockPos; - Byte ReadByte(); - UInt16 ReadUInt16(); - UInt32 ReadUInt32(); + ISequentialInStream *Stream; + UInt64 Processed; - 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 Read(void *data, size_t *size); + HRESULT GetNextItem(CItem &item, EErrorType &errorType); }; -HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize) +HRESULT CInArchive::Read(void *data, size_t *size) { - size_t realProcessedSize = size; - RINOK(ReadStream(m_Stream, data, &realProcessedSize)); - processedSize = (UInt32)realProcessedSize; - m_Position += processedSize; - return S_OK; + HRESULT res = ReadStream(Stream, data, size); + Processed += *size; + return res; } -Byte CInArchive::ReadByte() +static bool ReadHex(const Byte *p, UInt32 &resVal) { - if (_blockPos >= _blockSize) - throw "Incorrect cpio archive"; - return _block[_blockPos++]; + char sz[16]; + memcpy(sz, p, 8); + sz[8] = 0; + const char *end; + resVal = ConvertHexStringToUInt32(sz, &end); + return (unsigned)(end - sz) == 8; } -UInt16 CInArchive::ReadUInt16() +static bool ReadOct6(const Byte *p, UInt32 &resVal) { - UInt16 value = 0; - for (int i = 0; i < 2; i++) - { - Byte b = ReadByte(); - value |= (UInt16(b) << (8 * i)); - } - return value; + char sz[16]; + memcpy(sz, p, 6); + sz[6] = 0; + const char *end; + resVal = ConvertOctStringToUInt32(sz, &end); + return (unsigned)(end - sz) == 6; } -UInt32 CInArchive::ReadUInt32() +static bool ReadOct11(const Byte *p, UInt64 &resVal) { - UInt32 value = 0; - for (int i = 0; i < 4; i++) - { - Byte b = ReadByte(); - value |= (UInt32(b) << (8 * i)); - } - return value; + char sz[16]; + memcpy(sz, p, 11); + sz[11] = 0; + const char *end; + resVal = ConvertOctStringToUInt64(sz, &end); + return (unsigned)(end - sz) == 11; } -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; -} +#define READ_HEX(y) { if (!ReadHex(p2, y)) return S_OK; p2 += 8; } +#define READ_OCT_6(y) { if (!ReadOct6(p2, y)) return S_OK; p2 += 6; } +#define READ_OCT_11(y) { if (!ReadOct11(p2, y)) return S_OK; p2 += 11; } -static bool OctalToNumber(const char *s, UInt64 &res) +static UInt32 GetAlignedSize(UInt32 size, UInt32 align) { - const char *end; - res = ConvertOctStringToUInt64(s, &end); - return (*end == ' ' || *end == 0); + while ((size & (align - 1)) != 0) + size++; + return size; } -static bool OctalToNumber32(const char *s, UInt32 &res) -{ - UInt64 res64; - if (!OctalToNumber(s, res64)) - return false; - res = (UInt32)res64; - return (res64 <= 0xFFFFFFFF); -} +static UInt16 Get16(const Byte *p, bool be) { if (be) return GetBe16(p); return GetUi16(p); } +static UInt32 Get32(const Byte *p, bool be) { return ((UInt32)Get16(p, be) << 16) + Get16(p + 2, be); } -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 G16(offs, v) v = Get16(p + (offs), be) +#define G32(offs, v) v = Get32(p + (offs), be) -#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 const unsigned kNameSizeMax = 1 << 12; -static unsigned short ConvertValue(unsigned short value, bool convert) +API_FUNC_static_IsArc IsArc_Cpio(const Byte *p, size_t size) { - if (!convert) - return value; - return (unsigned short)((((unsigned short)(value & 0xFF)) << 8) | (value >> 8)); -} + if (size < k_BinRecord_Size) + return k_IsArc_Res_NEED_MORE; -static UInt32 GetAlignedSize(UInt32 size, UInt32 align) -{ - while ((size & (align - 1)) != 0) - size++; - return size; + UInt32 nameSize; + UInt32 numLinks; + if (p[0] == '0') + { + if (p[1] != '7' || + p[2] != '0' || + p[3] != '7' || + p[4] != '0') + return k_IsArc_Res_NO; + if (p[5] == '7') + { + if (size < k_OctRecord_Size) + return k_IsArc_Res_NEED_MORE; + for (int i = 6; i < k_OctRecord_Size; i++) + { + char c = p[i]; + if (c < '0' || c > '7') + return k_IsArc_Res_NO; + } + ReadOct6(p + 6 * 6, numLinks); + ReadOct6(p + 8 * 6 + 11, nameSize); + } + else if (p[5] == '1' || p[5] == '2') + { + if (size < k_HexRecord_Size) + return k_IsArc_Res_NEED_MORE; + for (int i = 6; i < k_HexRecord_Size; i++) + { + char c = p[i]; + if ((c < '0' || c > '9') && + (c < 'A' || c > 'F') && + (c < 'a' || c > 'f')) + return k_IsArc_Res_NO; + } + ReadHex(p + 6 + 4 * 8, numLinks); + ReadHex(p + 6 + 11 * 8, nameSize); + } + else + return k_IsArc_Res_NO; + } + else + { + UInt32 rDevMinor; + if (p[0] == kMagicBin0 && p[1] == kMagicBin1) + { + numLinks = GetUi16(p + 12); + rDevMinor = GetUi16(p + 14); + nameSize = GetUi16(p + 20); + } + else if (p[0] == kMagicBin1 && p[1] == kMagicBin0) + { + numLinks = GetBe16(p + 12); + rDevMinor = GetBe16(p + 14); + nameSize = GetBe16(p + 20); + } + else + return k_IsArc_Res_NO; + + if (rDevMinor != 0) + return k_IsArc_Res_NO; + if (nameSize > (1 << 8)) + return k_IsArc_Res_NO; + } + if (numLinks == 0 || numLinks >= (1 << 10)) + return k_IsArc_Res_NO; + if (nameSize == 0 || nameSize > kNameSizeMax) + return k_IsArc_Res_NO; + return k_IsArc_Res_YES; } +#define READ_STREAM(_dest_, _size_) \ + { size_t processed = (_size_); RINOK(Read(_dest_, &processed)); \ +if (processed != (_size_)) { errorType = k_ErrorType_UnexpectedEnd; return S_OK; } } -HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) +HRESULT CInArchive::GetNextItem(CItem &item, EErrorType &errorType) { - filled = false; + errorType = k_ErrorType_Corrupted; - UInt32 processedSize; - item.HeaderPosition = m_Position; + Byte p[k_RecordSize_Max]; - _blockSize = kMaxBlockSize; - RINOK(ReadBytes(_block, 2, processedSize)); - if (processedSize != 2) - return S_FALSE; - _blockPos = 0; + READ_STREAM(p, k_BinRecord_Size) 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) + if (p[0] != '0') { - RINOK(ReadBytes(_block + 2, NFileHeader::kRecord2Size - 2, processedSize)); - if (processedSize != NFileHeader::kRecord2Size - 2) - return S_FALSE; + bool be; + if (p[0] == kMagicBin0 && p[1] == kMagicBin1) { be = false; item.Type = k_Type_BinLe; } + else if (p[0] == kMagicBin1 && p[1] == kMagicBin0) { be = true; item.Type = k_Type_BinBe; } + else 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; + + G16(2, item.DevMinor); + G16(4, item.inode); + G16(6, item.Mode); + G16(8, item.UID); + G16(10, item.GID); + G16(12, item.NumLinks); + G16(14, item.RDevMinor); + G32(16, item.MTime); + G16(20, nameSize); + G32(22, item.Size); + + /* + if (item.RDevMinor != 0) + return S_FALSE; + */ + + item.HeaderSize = GetAlignedSize(nameSize + k_BinRecord_Size, item.Align); + nameSize = item.HeaderSize - k_BinRecord_Size; } else { - RINOK(ReadBytes(_block + 2, 4, processedSize)); - if (processedSize != 4) + if (p[1] != '7' || + p[2] != '0' || + p[3] != '7' || + p[4] != '0') return S_FALSE; - - bool magicOK = - memcmp(_block, NFileHeader::NMagic::kMagic1, 6) == 0 || - memcmp(_block, NFileHeader::NMagic::kMagic2, 6) == 0; - _blockPos = 6; - if (magicOK) + if (p[5] == kMagicOct) { - RINOK(ReadBytes(_block + 6, NFileHeader::kRecordSize - 6, processedSize)); - if (processedSize != NFileHeader::kRecordSize - 6) - return S_FALSE; - item.Align = 4; + item.Type = k_Type_Oct; + READ_STREAM(p + k_BinRecord_Size, k_OctRecord_Size - k_BinRecord_Size) + item.Align = 1; + item.DevMajor = 0; + item.RDevMajor = 0; - 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; + const Byte *p2 = p + 6; + READ_OCT_6(item.DevMinor); + READ_OCT_6(item.inode); + READ_OCT_6(item.Mode); + READ_OCT_6(item.UID); + READ_OCT_6(item.GID); + READ_OCT_6(item.NumLinks); + READ_OCT_6(item.RDevMinor); + { + UInt64 mTime64; + READ_OCT_11(mTime64); + item.MTime = 0; + if (mTime64 < (UInt32)(Int32)-1) + item.MTime = (UInt32)mTime64; + } + READ_OCT_6(nameSize); + READ_OCT_11(item.Size); // ????? + item.HeaderSize = GetAlignedSize(nameSize + k_OctRecord_Size, item.Align); + nameSize = item.HeaderSize - k_OctRecord_Size; } 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) + if (p[5] == kMagicHex) + item.Type = k_Type_Hex; + else if (p[5] == kMagicHexCrc) + item.Type = k_Type_HexCrc; + else 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; + + READ_STREAM(p + k_BinRecord_Size, k_HexRecord_Size - k_BinRecord_Size) + + item.Align = 4; + + const Byte *p2 = p + 6; + READ_HEX(item.inode); + READ_HEX(item.Mode); + READ_HEX(item.UID); + READ_HEX(item.GID); + READ_HEX(item.NumLinks); + READ_HEX(item.MTime); + { + UInt32 size32; + READ_HEX(size32); + item.Size = size32; + } + READ_HEX(item.DevMajor); + READ_HEX(item.DevMinor); + READ_HEX(item.RDevMajor); + READ_HEX(item.RDevMinor); + READ_HEX(nameSize); + READ_HEX(item.ChkSum); + if (nameSize >= kNameSizeMax) + return S_OK; + item.HeaderSize = GetAlignedSize(nameSize + k_HexRecord_Size, item.Align); + nameSize = item.HeaderSize - k_HexRecord_Size; } } - if (nameSize == 0 || nameSize >= (1 << 27)) - return E_FAIL; - RINOK(ReadBytes(item.Name.GetBuffer(nameSize), nameSize, processedSize)); - if (processedSize != nameSize) - return E_FAIL; + if (nameSize > kNameSizeMax) + return S_FALSE; + if (nameSize == 0 || nameSize >= kNameSizeMax) + return S_OK; + char *s = item.Name.GetBuffer(nameSize); + size_t processedSize = nameSize; + RINOK(Read(s, &processedSize)); + s[nameSize] = 0; item.Name.ReleaseBuffer(); - if (strcmp(item.Name, NFileHeader::NMagic::kEndName) == 0) + if (processedSize != nameSize) + { + errorType = k_ErrorType_UnexpectedEnd; 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; + } + errorType = k_ErrorType_OK; 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; + CObjectVector _items; CMyComPtr _stream; + UInt64 _phySize; + EType _Type; + EErrorType _error; + bool _isArc; public: MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); }; -/* -enum +static const Byte kArcProps[] = { - kpidinode = kpidUserDefined, - kpidiChkSum + kpidSubType }; -*/ -STATPROPSTG kProps[] = +static const Byte 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} + kpidPath, + kpidIsDir, + kpidSize, + kpidMTime, + kpidPosixAttrib, + kpidLinks }; IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO +IMP_IInArchive_ArcProps -STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback) +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - // try + NCOM::CPropVariant prop; + switch (propID) { - CInArchive archive; + case kpidSubType: prop = k_Types[_Type]; break; + case kpidPhySize: prop = _phySize; break; + case kpidErrorFlags: + { + UInt32 v = 0; + if (!_isArc) + v |= kpv_ErrorFlags_IsNotArc; + switch (_error) + { + case k_ErrorType_UnexpectedEnd: v |= kpv_ErrorFlags_UnexpectedEnd; break; + case k_ErrorType_Corrupted: v |= kpv_ErrorFlags_HeadersError; break; + } + prop = v; + break; + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + { + Close(); + 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)); + if (callback) { - RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos)); - RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + RINOK(callback->SetTotal(NULL, &endPos)); } - RINOK(archive.Open(stream)); - _items.Clear(); + CInArchive arc; + + arc.Stream = stream; + arc.Processed = 0; for (;;) { - CItemEx item; - bool filled; - HRESULT result = archive.GetNextItem(filled, item); + CItem item; + item.HeaderPos = arc.Processed; + HRESULT result = arc.GetNextItem(item, _error); if (result == S_FALSE) return S_FALSE; if (result != S_OK) return S_FALSE; - if (!filled) + if (_error != k_ErrorType_OK) + { + if (_error == k_ErrorType_Corrupted) + arc.Processed = item.HeaderPos; break; + } + if (_items.IsEmpty()) + _Type = item.Type; + else if (_items.Back().Type != item.Type) + { + _error = k_ErrorType_Corrupted; + arc.Processed = item.HeaderPos; + break; + } + if (item.IsTrailer()) + break; + _items.Add(item); - archive.SkipDataRecords(item.Size, item.Align); - if (callback != NULL) + { - if (needSetTotal) + // archive.SkipDataRecords(item.Size, item.Align); + UInt64 dataSize = item.Size; + UInt32 align = item.Align; + while ((dataSize & (align - 1)) != 0) + dataSize++; + + // _error = k_ErrorType_UnexpectedEnd; break; + + arc.Processed += dataSize; + if (arc.Processed > endPos) { - RINOK(callback->SetTotal(NULL, &endPos)); - needSetTotal = false; + _error = k_ErrorType_UnexpectedEnd; + break; } - if (_items.Size() % 100 == 0) + + UInt64 newPostion; + RINOK(stream->Seek(dataSize, STREAM_SEEK_CUR, &newPostion)); + if (arc.Processed != newPostion) + return E_FAIL; + } + + if (callback && (_items.Size() & 0xFF) == 0) + { + UInt64 numFiles = _items.Size(); + RINOK(callback->SetCompleted(&numFiles, &item.HeaderPos)); + } + } + _phySize = arc.Processed; + if (_error != k_ErrorType_OK) + { + if (_items.Size() == 0) + return S_FALSE; + if (_items.Size() == 1 && _items[0].IsBin()) + { + // probably it's false detected archive. So we return error + return S_FALSE; + } + } + else + { + // Read tailing zeros. + // Most of cpio files use 512-bytes aligned zeros + UInt64 pos = arc.Processed; + const UInt32 kTailSize_MAX = 1 << 9; + Byte buf[kTailSize_MAX]; + + UInt32 rem = (kTailSize_MAX - (UInt32)pos) & (kTailSize_MAX - 1); + if (rem != 0) + { + rem++; // we need to see that it's end of file + size_t processed = rem; + RINOK(ReadStream(stream, buf, &processed)); + if (processed < rem) { - UInt64 numFiles = _items.Size(); - UInt64 numBytes = item.HeaderPosition; - RINOK(callback->SetCompleted(&numFiles, &numBytes)); + unsigned i; + for (i = 0; i < processed && buf[i] == 0; i++); + if (i == processed) + _phySize += processed; } } } - if (_items.Size() == 0) - return S_FALSE; - + + _isArc = true; _stream = stream; } - /* - catch(...) - { - return S_FALSE; - } - */ return S_OK; COM_TRY_END } @@ -496,6 +595,10 @@ STDMETHODIMP CHandler::Close() { _items.Clear(); _stream.Release(); + _phySize = 0; + _Type = k_Type_BinLe; + _isArc = false; + _error = k_ErrorType_OK; return S_OK; } @@ -508,12 +611,24 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; - const CItemEx &item = _items[index]; + NCOM::CPropVariant prop; + const CItem &item = _items[index]; - switch(propID) + switch (propID) { - case kpidPath: prop = NItemName::GetOSName(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break; + case kpidPath: + { + UString res; + bool needConvert = true; + #ifdef _WIN32 + if (ConvertUTF8ToUnicode(item.Name, res)) + needConvert = false; + #endif + if (needConvert) + res = MultiByteToUnicodeString(item.Name, CP_OEMCP); + prop = NItemName::GetOSName(res); + break; + } case kpidIsDir: prop = item.IsDir(); break; case kpidSize: case kpidPackSize: @@ -524,12 +639,13 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val if (item.MTime != 0) { FILETIME utc; - NWindows::NTime::UnixTimeToFileTime(item.MTime, utc); + NTime::UnixTimeToFileTime(item.MTime, utc); prop = utc; } break; } case kpidPosixAttrib: prop = item.Mode; break; + case kpidLinks: prop = item.NumLinks; break; /* case kpidinode: prop = item.inode; break; case kpidiChkSum: prop = item.ChkSum; break; @@ -540,11 +656,53 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val COM_TRY_END } +class COutStreamWithSum: + 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 = 0; + } + void EnableCalc(bool calculate) { _calculate = calculate; } + void InitCRC() { _crc = 0; } + UInt64 GetSize() const { return _size; } + UInt32 GetCRC() const { return _crc; } +}; + +STDMETHODIMP COutStreamWithSum::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + HRESULT result = S_OK; + if (_stream) + result = _stream->Write(data, size, &size); + if (_calculate) + { + UInt32 crc = 0; + for (UInt32 i = 0; i < size; i++) + crc += (UInt32)(((const Byte *)data)[i]); + _crc += crc; + } + if (processedSize) + *processedSize = size; + return result; +} + STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _items.Size(); if (numItems == 0) @@ -568,6 +726,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CMyComPtr inStream(streamSpec); streamSpec->SetStream(_stream); + COutStreamWithSum *outStreamSumSpec = new COutStreamWithSum; + CMyComPtr outStreamSum(outStreamSumSpec); + for (i = 0; i < numItems; i++) { lps->InSize = lps->OutSize = currentTotalSize; @@ -577,7 +738,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, NExtract::NAskMode::kTest : NExtract::NAskMode::kExtract; Int32 index = allFilesMode ? i : indices[i]; - const CItemEx &item = _items[index]; + const CItem &item = _items[index]; RINOK(extractCallback->GetStream(index, &outStream, askMode)); currentTotalSize += item.Size; if (item.IsDir()) @@ -588,19 +749,23 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } if (!testMode && !outStream) continue; + outStreamSumSpec->Init(item.IsCrcFormat()); + outStreamSumSpec->SetStream(outStream); + outStream.Release(); + 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)); + RINOK(copyCoder->Code(inStream, outStreamSum, NULL, NULL, progress)); + outStreamSumSpec->ReleaseStream(); + Int32 res = NExtract::NOperationResult::kDataError; + if (copyCoderSpec->TotalSize == item.Size) + { + res = NExtract::NOperationResult::kOK; + if (item.IsCrcFormat() && item.ChkSum != outStreamSumSpec->GetCRC()) + res = NExtract::NOperationResult::kCRCError; + } + RINOK(extractCallback->SetOperationResult(res)); } return S_OK; COM_TRY_END @@ -609,15 +774,24 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) { COM_TRY_BEGIN - const CItemEx &item = _items[index]; + const CItem &item = _items[index]; return CreateLimitedInStream(_stream, item.GetDataPosition(), item.Size, stream); COM_TRY_END } -static IInArchive *CreateArc() { return new NArchive::NCpio::CHandler; } +IMP_CreateArcIn static CArcInfo g_ArcInfo = - { L"Cpio", L"cpio", 0, 0xED, { 0 }, 0, false, CreateArc, 0 }; + { "Cpio", "cpio", 0, 0xED, + 3 + 5 + 2 + 2, + { + 5, '0', '7', '0', '7', '0', + 2, kMagicBin0, kMagicBin1, + 2, kMagicBin1, kMagicBin0, + }, + 0, + NArcInfoFlags::kMultiSignature, + CreateArc, NULL, IsArc_Cpio }; REGISTER_ARC(Cpio) diff --git a/CPP/7zip/Archive/CramfsHandler.cpp b/CPP/7zip/Archive/CramfsHandler.cpp old mode 100755 new mode 100644 index a55e3743..3764f1af --- a/CPP/7zip/Archive/CramfsHandler.cpp +++ b/CPP/7zip/Archive/CramfsHandler.cpp @@ -3,13 +3,14 @@ #include "StdAfx.h" #include "../../../C/7zCrc.h" -#include "../../../C/CpuArch.h" #include "../../../C/Alloc.h" +#include "../../../C/CpuArch.h" +#include "../../../C/LzmaDec.h" -#include "Common/ComTry.h" -#include "Common/StringConvert.h" +#include "../../Common/ComTry.h" +#include "../../Common/StringConvert.h" -#include "Windows/PropVariantUtils.h" +#include "../../Windows/PropVariantUtils.h" #include "../Common/LimitedStreams.h" #include "../Common/ProgressUtils.h" @@ -38,6 +39,30 @@ static const UInt32 kNodeSize = 12; static const UInt32 kFlag_FsVer2 = (1 << 0); +static const unsigned k_Flags_BlockSize_Shift = 11; +static const unsigned k_Flags_BlockSize_Mask = 7; +static const unsigned k_Flags_Method_Shift = 14; +static const unsigned k_Flags_Method_Mask = 3; + +/* + There is possible collision in flags: + - Original CramFS writes 0 in method field. But it uses ZLIB. + - Modified CramFS writes 0 in method field for "NONE" compression? + How to solve that collision? +*/ + +#define k_Flags_Method_NONE 0 +#define k_Flags_Method_ZLIB 1 +#define k_Flags_Method_LZMA 2 + +static const char *k_Methods[] = +{ + "Copy" + , "ZLIB" + , "LZMA" + , "Unknown" +}; + static const CUInt32PCharPair k_Flags[] = { { 0, "Ver2" }, @@ -48,7 +73,6 @@ static const CUInt32PCharPair k_Flags[] = }; static const unsigned kBlockSizeLog = 12; -static const UInt32 kBlockSize = 1 << kBlockSizeLog; /* struct CNode @@ -141,6 +165,8 @@ struct CHeader } bool IsVer2() const { return (Flags & kFlag_FsVer2) != 0; } + unsigned GetBlockSizeShift() const { return (unsigned)(Flags >> k_Flags_BlockSize_Shift) & k_Flags_BlockSize_Mask; } + unsigned GetMethod() const { return (unsigned)(Flags >> k_Flags_Method_Shift) & k_Flags_Method_Mask; } }; class CHandler: @@ -153,14 +179,21 @@ class CHandler: Byte *_data; UInt32 _size; UInt32 _headersSize; - AString _errorMessage; + + UInt32 _errorFlags; + bool _isArc; + CHeader _h; + UInt32 _phySize; + + unsigned _method; + unsigned _blockSizeLog; // Current file NCompress::NZlib::CDecoder *_zlibDecoderSpec; CMyComPtr _zlibDecoder; - + CBufInStream *_inStreamSpec; CMyComPtr _inStream; @@ -175,6 +208,18 @@ class CHandler: AString GetPath(int index) const; bool GetPackSize(int index, UInt32 &res) const; void Free(); + + UInt32 GetNumBlocks(UInt32 size) const + { + return (size + ((UInt32)1 << _blockSizeLog) - 1) >> _blockSizeLog; + } + + void UpdatePhySize(UInt32 s) + { + if (_phySize < s) + _phySize = s; + } + public: CHandler(): _data(0) {} ~CHandler() { Free(); } @@ -184,25 +229,26 @@ public: HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize); }; -static const STATPROPSTG kProps[] = +static const Byte 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} + kpidPath, + kpidIsDir, + kpidSize, + kpidPackSize, + kpidPosixAttrib + // kpidOffset }; -static const STATPROPSTG kArcProps[] = +static const Byte 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} + kpidVolumeName, + kpidBigEndian, + kpidCharacts, + kpidClusterSize, + kpidMethod, + kpidHeadersSize, + kpidNumSubFiles, + kpidNumBlocks }; IMP_IInArchive_Props @@ -221,10 +267,11 @@ HRESULT CHandler::OpenDir(int parent, UInt32 baseOffset, unsigned level) UInt32 end = offset + size; if (offset < kHeaderSize || end > _size || level > kNumDirLevelsMax) return S_FALSE; + UpdatePhySize(end); if (end > _headersSize) _headersSize = end; - int startIndex = _items.Size(); + unsigned startIndex = _items.Size(); while (size != 0) { @@ -241,8 +288,8 @@ HRESULT CHandler::OpenDir(int parent, UInt32 baseOffset, unsigned level) size -= nodeLen; } - int endIndex = _items.Size(); - for (int i = startIndex; i < endIndex; i++) + unsigned endIndex = _items.Size(); + for (unsigned i = startIndex; i < endIndex; i++) { RINOK(OpenDir(i, _items[i].Offset, level + 1)); } @@ -255,17 +302,26 @@ HRESULT CHandler::Open2(IInStream *inStream) RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize)); if (!_h.Parse(buf)) return S_FALSE; + _method = k_Flags_Method_ZLIB; + _blockSizeLog = kBlockSizeLog; + _phySize = kHeaderSize; if (_h.IsVer2()) { + _method = _h.GetMethod(); + // FIT IT. Now we don't know correct way to work with collision in method field. + if (_method == k_Flags_Method_NONE) + _method = k_Flags_Method_ZLIB; + _blockSizeLog = kBlockSizeLog + _h.GetBlockSizeShift(); if (_h.Size < kHeaderSize || _h.Size > kArcSizeMax || _h.NumFiles > kNumFilesMax) return S_FALSE; + _phySize = _h.Size; } else { UInt64 size; RINOK(inStream->Seek(0, STREAM_SEEK_END, &size)); if (size > kArcSizeMax) - return S_FALSE; + size = kArcSizeMax; _h.Size = (UInt32)size; RINOK(inStream->Seek(kHeaderSize, STREAM_SEEK_SET, NULL)); } @@ -278,18 +334,59 @@ HRESULT CHandler::Open2(IInStream *inStream) if (processed < kNodeSize) return S_FALSE; _size = kHeaderSize + (UInt32)processed; - if (_size != _h.Size) - _errorMessage = "Unexpected end of archive"; - else + if (_h.IsVer2()) { - SetUi32(_data + 0x20, 0); - if (_h.IsVer2()) + if (_size != _h.Size) + _errorFlags = kpv_ErrorFlags_UnexpectedEnd; + else + { + SetUi32(_data + 0x20, 0); if (CrcCalc(_data, _h.Size) != _h.Crc) - _errorMessage = "CRC error"; + { + _errorFlags = kpv_ErrorFlags_HeadersError; + // _errorMessage = "CRC error"; + } + } + if (_h.NumFiles >= 1) + _items.ClearAndReserve(_h.NumFiles - 1); } - if (_h.IsVer2()) - _items.Reserve(_h.NumFiles - 1); - return OpenDir(-1, kHeaderSize, 0); + + RINOK(OpenDir(-1, kHeaderSize, 0)); + + if (!_h.IsVer2()) + { + FOR_VECTOR(i, _items) + { + const CItem &item = _items[i]; + const Byte *p = _data + item.Offset; + bool be = _h.be; + if (IsDir(p, be)) + continue; + UInt32 offset = GetOffset(p, be); + if (offset < kHeaderSize) + continue; + UInt32 numBlocks = GetNumBlocks(GetSize(p, be)); + if (numBlocks == 0) + continue; + UInt32 start = offset + numBlocks * 4; + if (start > _size) + continue; + UInt32 end = Get32(_data + start - 4); + if (end >= start) + UpdatePhySize(end); + } + + // Read tailing zeros. Most cramfs archives use 4096-bytes aligned zeros + const UInt32 kTailSize_MAX = 1 << 12; + UInt32 endPos = (_phySize + kTailSize_MAX - 1) & ~(kTailSize_MAX - 1); + if (endPos > _size) + endPos = _size; + UInt32 pos; + for (pos = _phySize; pos < endPos && _data[pos] == 0; pos++); + if (pos == endPos) + _phySize = endPos; + } + return S_OK; } AString CHandler::GetPath(int index) const @@ -334,13 +431,16 @@ AString CHandler::GetPath(int index) const bool CHandler::GetPackSize(int index, UInt32 &res) const { + res = 0; 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 numBlocks = GetNumBlocks(GetSize(p, be)); + if (numBlocks == 0) + return true; UInt32 start = offset + numBlocks * 4; if (start > _size) return false; @@ -357,6 +457,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb { Close(); RINOK(Open2(stream)); + _isArc = true; _stream = stream; } return S_OK; @@ -371,10 +472,12 @@ void CHandler::Free() STDMETHODIMP CHandler::Close() { + _isArc = false; + _phySize = 0; + _errorFlags = 0; _headersSize = 0; _items.Clear(); _stream.Release(); - _errorMessage.Empty(); Free(); return S_OK; } @@ -389,9 +492,9 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NWindows::NCOM::CPropVariant prop; - switch(propID) + switch (propID) { - case kpidName: + case kpidVolumeName: { char dest[kHeaderNameSize + 4]; memcpy(dest, _h.Name, kHeaderNameSize); @@ -401,11 +504,20 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) } case kpidBigEndian: prop = _h.be; break; case kpidCharacts: FLAGS_TO_PROP(k_Flags, _h.Flags, prop); break; + case kpidMethod: prop = k_Methods[_method]; break; + case kpidClusterSize: prop = (UInt32)1 << _blockSizeLog; 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 kpidPhySize: prop = _phySize; break; case kpidHeadersSize: prop = _headersSize; break; - case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break; + case kpidErrorFlags: + { + UInt32 v = _errorFlags; + if (!_isArc) + v |= kpv_ErrorFlags_IsNotArc; + prop = v; + break; + } } prop.Detach(value); return S_OK; @@ -453,13 +565,60 @@ HRESULT CCramfsInStream::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSi return Handler->ReadBlock(blockIndex, dest, blockSize); } +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } +static void SzFree(void *p, void *address) { p = p; MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) { - if (!_zlibDecoder) + if (_method == k_Flags_Method_ZLIB) { - _zlibDecoderSpec = new NCompress::NZlib::CDecoder(); - _zlibDecoder = _zlibDecoderSpec; + if (!_zlibDecoder) + { + _zlibDecoderSpec = new NCompress::NZlib::CDecoder(); + _zlibDecoder = _zlibDecoderSpec; + } } + else + { + if (_method != k_Flags_Method_LZMA) + { + // probably we must support no-compression archives here. + return E_NOTIMPL; + } + } + + 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; + + if (_method == k_Flags_Method_LZMA) + { + const unsigned kLzmaHeaderSize = LZMA_PROPS_SIZE + 4; + if (inSize < kLzmaHeaderSize) + return S_FALSE; + const Byte *p = _data + start; + UInt32 destSize32 = GetUi32(p + LZMA_PROPS_SIZE); + if (destSize32 > blockSize) + return S_FALSE; + SizeT destLen = destSize32; + SizeT srcLen = inSize - kLzmaHeaderSize; + ELzmaStatus status; + SRes res = LzmaDecode(dest, &destLen, p + kLzmaHeaderSize, &srcLen, + p, LZMA_PROPS_SIZE, LZMA_FINISH_END, &status, &g_Alloc); + if (res != SZ_OK + || (status != LZMA_STATUS_FINISHED_WITH_MARK && + status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) + || destLen != destSize32 + || srcLen != inSize - kLzmaHeaderSize) + return S_FALSE; + return S_OK; + } + if (!_inStream) { _inStreamSpec = new CBufInStream(); @@ -470,17 +629,10 @@ HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) _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 && + return (inSize == _zlibDecoderSpec->GetInputProcessedSize() && _outStreamSpec->GetPos() == blockSize) ? S_OK : S_FALSE; } @@ -488,7 +640,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _items.Size(); if (numItems == 0) @@ -562,19 +714,22 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (hres == E_OUTOFMEMORY) return E_OUTOFMEMORY; if (hres == S_FALSE || !inStream) - res = NExtract::NOperationResult::kUnSupportedMethod; + 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) + if (hres == S_OK) { - RINOK(hres); + if (copyCoderSpec->TotalSize == curSize) + res = NExtract::NOperationResult::kOK; } - if (copyCoderSpec->TotalSize == curSize && hres == S_OK) - res = NExtract::NOperationResult::kOK; + else if (hres == E_NOTIMPL) + res = NExtract::NOperationResult::kUnsupportedMethod; + else if (hres != S_FALSE) + return hres; } } } @@ -596,7 +751,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) return E_FAIL; UInt32 size = GetSize(p, be); - UInt32 numBlocks = (size + kBlockSize - 1) >> kBlockSizeLog; + UInt32 numBlocks = GetNumBlocks(size); UInt32 offset = GetOffset(p, be); if (offset < kHeaderSize) { @@ -625,7 +780,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) _curNumBlocks = numBlocks; _curBlocksOffset = offset; streamSpec->Handler = this; - if (!streamSpec->Alloc(kBlockSizeLog, 21 - kBlockSizeLog)) + if (!streamSpec->Alloc(_blockSizeLog, 21 - _blockSizeLog)) return E_OUTOFMEMORY; streamSpec->Init(size); *stream = streamTemp.Detach(); @@ -634,10 +789,14 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) COM_TRY_END } -static IInArchive *CreateArc() { return new NArchive::NCramfs::CHandler; } +IMP_CreateArcIn static CArcInfo g_ArcInfo = - { L"CramFS", L"cramfs", 0, 0xD3, SIGNATURE, kSignatureSize, false, CreateArc, 0 }; + { "CramFS", "cramfs", 0, 0xD3, + kSignatureSize, SIGNATURE, + 16, + 0, + CreateArc }; REGISTER_ARC(Cramfs) diff --git a/CPP/7zip/Archive/DebHandler.cpp b/CPP/7zip/Archive/DebHandler.cpp deleted file mode 100755 index 82d2cde8..00000000 --- a/CPP/7zip/Archive/DebHandler.cpp +++ /dev/null @@ -1,413 +0,0 @@ -// 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 old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/DeflateProps.h b/CPP/7zip/Archive/DeflateProps.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/DllExports.cpp b/CPP/7zip/Archive/DllExports.cpp old mode 100755 new mode 100644 index 6c72dea7..fa40d024 --- a/CPP/7zip/Archive/DllExports.cpp +++ b/CPP/7zip/Archive/DllExports.cpp @@ -3,8 +3,8 @@ #include "StdAfx.h" #include "../../Common/MyInitGuid.h" + #include "../../Common/ComTry.h" -#include "../../Common/Types.h" #include "../../Windows/NtCheck.h" #include "../../Windows/PropVariant.h" diff --git a/CPP/7zip/Archive/DllExports2.cpp b/CPP/7zip/Archive/DllExports2.cpp old mode 100755 new mode 100644 index ad14ff06..beb758a2 --- a/CPP/7zip/Archive/DllExports2.cpp +++ b/CPP/7zip/Archive/DllExports2.cpp @@ -1,4 +1,4 @@ -// DLLExports.cpp +// DLLExports2.cpp #include "StdAfx.h" @@ -45,23 +45,23 @@ DEFINE_GUID(CLSID_CArchiveHandler, static const UInt16 kDecodeId = 0x2790; DEFINE_GUID(CLSID_CCodec, -0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); +0x23170F69, 0x40C1, kDecodeId, 0, 0, 0, 0, 0, 0, 0, 0); STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject); +STDAPI CreateHasher(const GUID *clsid, IHasher **hasher); STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject); STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) { // COM_TRY_BEGIN *outObject = 0; - if (*iid == IID_ICompressCoder || *iid == IID_ICompressCoder2 || *iid == IID_ICompressFilter) - { + if (*iid == IID_ICompressCoder || + *iid == IID_ICompressCoder2 || + *iid == IID_ICompressFilter) return CreateCoder(clsid, iid, outObject); - } - else - { - return CreateArchiver(clsid, iid, outObject); - } + if (*iid == IID_IHasher) + return CreateHasher(clsid, (IHasher **)outObject); + return CreateArchiver(clsid, iid, outObject); // COM_TRY_END } @@ -72,3 +72,11 @@ STDAPI SetLargePageMode() #endif return S_OK; } + +extern bool g_CaseSensitive; + +STDAPI SetCaseSensitive(Int32 caseSensitive) +{ + g_CaseSensitive = (caseSensitive != 0); + return S_OK; +} diff --git a/CPP/7zip/Archive/DmgHandler.cpp b/CPP/7zip/Archive/DmgHandler.cpp old mode 100755 new mode 100644 index 5040d518..7166f2ce --- a/CPP/7zip/Archive/DmgHandler.cpp +++ b/CPP/7zip/Archive/DmgHandler.cpp @@ -4,85 +4,115 @@ #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 "../../Common/ComTry.h" +#include "../../Common/IntToString.h" +#include "../../Common/MyXml.h" +#include "../../Common/UTFConvert.h" -#include "Windows/PropVariant.h" +#include "../../Windows/PropVariant.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/OutStreamWithCRC.h" + // #define DMG_SHOW_RAW // #include #define PRF(x) // x +#define Get16(p) GetBe16(p) #define Get32(p) GetBe32(p) #define Get64(p) GetBe64(p) -static int Base64ToByte(char c) +static const Byte k_Base64Table[256] = { - 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; -} + 64,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,62,77,64,77,63,52,53,54,55,56,57,58,59,60,61,77,77,77,77,77,77, + 77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,77,77,77,77,77, + 77,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77 +}; -static int Base64ToBin(Byte *dest, const char *src, int srcLen) +static Byte *Base64ToBin(Byte *dest, const char *src) { - int srcPos = 0; - int destPos = 0; - while (srcPos < srcLen) + UInt32 val = 1; + UInt32 c = k_Base64Table[(Byte)(*src++)]; + for (;;) { - Byte buf[4]; - int filled = 0; - while (srcPos < srcLen) + /* + UInt32 c = (Byte)(*src++); + if (c >= 'A') { - int n = Base64ToByte(src[srcPos++]); - if (n >= 0) - { - buf[filled++] = (Byte)n; - if (filled == 4) - break; - } + if (c <= 'Z') c -= 'A'; + else if (c >= 'a' && c <= 'z') c -= 'a' - 26; + else continue; + } + else if (c >= '0') + { + if (c <= '9') c += 52 - '0'; + else if (c == '=') break; + else continue; + } + else if (c == '+') c = 62; + else if (c == '/') c = 63; + else if (c == 0) break; + else continue; + */ + + // UInt32 c = k_Base64Table[(Byte)(*src++)]; + if (c < 64) + { + val = (val << 6) | c; + c = k_Base64Table[(Byte)(*src++)]; + if ((val & ((UInt32)1 << 24)) == 0) + continue; + dest[0] = (Byte)(val >> 16); + dest[1] = (Byte)(val >> 8); + dest[2] = (Byte)(val); + dest += 3; + val = 1; + continue; } - 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++; } + if (c == 64) + break; + c = k_Base64Table[(Byte)(*src++)]; + } + if (val >= ((UInt32)1 << 12)) + { + if (val >= ((UInt32)1 << 18)) + *dest++ = (Byte)(val >> 16); + *dest++ = (Byte)(val); } - return destPos; + return dest; } -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 { +enum +{ + METHOD_ZERO_0 = 0, + METHOD_COPY = 1, + METHOD_ZERO_2 = 2, // without file CRC calculation + METHOD_ADC = 0x80000004, + METHOD_ZLIB = 0x80000005, + METHOD_BZIP2 = 0x80000006, + METHOD_COMMENT = 0x7FFFFFFE, // is used to comment "+beg" and "+end" in extra field. + METHOD_END = 0xFFFFFFFF +}; + struct CBlock { UInt32 Type; @@ -92,176 +122,244 @@ struct CBlock UInt64 PackSize; UInt64 GetNextPackOffset() const { return PackPos + PackSize; } + UInt64 GetNextUnpPos() const { return UnpPos + UnpSize; } + + bool IsZeroMethod() const { return Type == METHOD_ZERO_0 || Type == METHOD_ZERO_2; } + bool ThereAreDataInBlock() const { return Type != METHOD_COMMENT && Type != METHOD_END; } +}; + +static const UInt32 kCheckSumType_CRC = 2; + +static const size_t kChecksumSize_Max = 0x80; + +struct CChecksum +{ + UInt32 Type; + UInt32 NumBits; + Byte Data[kChecksumSize_Max]; + + bool IsCrc32() const { return Type == kCheckSumType_CRC && NumBits == 32; } + UInt32 GetCrc32() const { return Get32(Data); } + void Parse(const Byte *p); +}; + +void CChecksum::Parse(const Byte *p) +{ + Type = Get32(p); + NumBits = Get32(p + 4); + memcpy(Data, p + 8, kChecksumSize_Max); }; struct CFile { - CByteBuffer Raw; + UInt64 Size; + UInt64 PackSize; UInt64 StartPos; + AString Name; 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; - }; + CChecksum Checksum; + bool FullFileChecksum; + + HRESULT Parse(const Byte *p, UInt32 size); +}; +#ifdef DMG_SHOW_RAW +struct CExtraFile +{ + CByteBuffer Data; AString Name; }; +#endif class CHandler: public IInArchive, + public IInArchiveGetStream, public CMyUnknownImp { CMyComPtr _inStream; - - AString _xml; CObjectVector _files; - CRecordVector _fileIndices; + bool _masterCrcError; + + UInt64 _startPos; + UInt64 _phySize; + + #ifdef DMG_SHOW_RAW + CObjectVector _extras; + #endif HRESULT Open2(IInStream *stream); HRESULT Extract(IInStream *stream); public: - MY_UNKNOWN_IMP1(IInArchive) + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); }; 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; + CRecordVector ChecksumTypes; + void Update(const CFile &file); - UString GetString() const; + void GetString(AString &s) 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++; - } + ChecksumTypes.AddToUniqueSorted(file.Checksum.Type); + FOR_VECTOR (i, file.Blocks) + Types.AddToUniqueSorted(file.Blocks[i].Type); } -UString CMethods::GetString() const +void CMethods::GetString(AString &res) const { - UString res; - for (int i = 0; i < Types.Size(); i++) + res.Empty(); + unsigned i; + for (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) + if (type == METHOD_COMMENT || type == METHOD_END) + continue; + char buf[16]; + const char *s; + 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; + case METHOD_ZERO_0: s = "Zero0"; break; + case METHOD_ZERO_2: s = "Zero2"; break; + case METHOD_COPY: s = "Copy"; break; + case METHOD_ADC: s = "ADC"; break; + case METHOD_ZLIB: s = "ZLIB"; break; + case METHOD_BZIP2: s = "BZip2"; break; + default: ConvertUInt32ToString(type, buf); s = buf; } + if (!res.IsEmpty()) + res += ' '; res += s; - if (m.NumBlocks != 1) - { - res += L'['; - ConvertUInt64ToString(m.NumBlocks, buf); - res += buf; - res += L']'; - } - res += L'-'; - res += GetSizeString(m.UnpSize); - if (showPack) + } + for (i = 0; i < ChecksumTypes.Size(); i++) + { + UInt32 type = ChecksumTypes[i]; + char buf[32]; + const char *s; + switch (type) { - res += L'-'; - res += GetSizeString(m.PackSize); + case kCheckSumType_CRC: s = "CRC"; break; + default: + ConvertUInt32ToString(type, MyStpCpy(buf, "Check")); + s = buf; } + if (!res.IsEmpty()) + res += ' '; + res += s; } - return res; } -STATPROPSTG kProps[] = +struct CAppleName +{ + bool IsFs; + const char *Ext; + const char *AppleName; +}; + +static const CAppleName k_Names[] = { - { NULL, kpidPath, VT_BSTR}, - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, - { NULL, kpidComment, VT_BSTR}, - { NULL, kpidMethod, VT_BSTR} + { true, "hfs", "Apple_HFS" }, + { true, "hfsx", "Apple_HFSX" }, + { true, "ufs", "Apple_UFS" }, + { false, "free", "Apple_Free" }, + { false, "ddm", "DDM" }, + { false, NULL, "Apple_partition_map" }, + { false, NULL, " GPT " }, + { false, NULL, "MBR" }, + { false, NULL, "Driver" }, + { false, NULL, "Patches" } +}; + +static const unsigned kNumAppleNames = ARRAY_SIZE(k_Names); + +static const Byte kProps[] = +{ + kpidPath, + kpidSize, + kpidPackSize, + kpidCRC, + kpidComment, + kpidMethod }; IMP_IInArchive_Props -STATPROPSTG kArcProps[] = +static const Byte kArcProps[] = { - { NULL, kpidMethod, VT_BSTR}, - { NULL, kpidNumBlocks, VT_UI4} + kpidMethod, + kpidNumBlocks }; STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NWindows::NCOM::CPropVariant prop; - switch(propID) + switch (propID) { case kpidMethod: { CMethods m; - for (int i = 0; i < _files.Size(); i++) + FOR_VECTOR (i, _files) m.Update(_files[i]); - prop = m.GetString(); + AString s; + m.GetString(s); + if (!s.IsEmpty()) + prop = s; break; } case kpidNumBlocks: { UInt64 numBlocks = 0; - for (int i = 0; i < _files.Size(); i++) + FOR_VECTOR (i, _files) numBlocks += _files[i].Blocks.Size(); prop = numBlocks; break; } + case kpidMainSubfile: + { + int mainIndex = -1; + int numFS = 0; + int numUnknown = 0; + FOR_VECTOR (i, _files) + { + const AString &name = _files[i].Name; + unsigned n; + for (n = 0; n < kNumAppleNames; n++) + { + const CAppleName &appleName = k_Names[n]; + if (name.Find(appleName.AppleName) >= 0) + { + if (appleName.IsFs) + { + numFS++; + mainIndex = i; + } + break; + } + } + if (n == kNumAppleNames) + { + mainIndex = i; + numUnknown++; + } + } + if (numFS + numUnknown == 1) + prop = (UInt32)mainIndex; + break; + } + case kpidWarning: + if (_masterCrcError) + prop = "Master CRC error"; + break; + case kpidOffset: prop = _startPos; break; + case kpidPhySize: prop = _phySize; break; } prop.Detach(value); return S_OK; @@ -270,9 +368,83 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) IMP_IInArchive_ArcProps +HRESULT CFile::Parse(const Byte *p, UInt32 size) +{ + const UInt32 kHeadSize = 0xCC; + if (size < kHeadSize) + return S_FALSE; + if (Get32(p) != 0x6D697368) // "mish" signature + return S_FALSE; + if (Get32(p + 4) != 1) // version + return S_FALSE; + // UInt64 firstSectorNumber = Get64(p + 8); + UInt64 numSectors = Get64(p + 0x10); + + StartPos = Get64(p + 0x18); + + // UInt32 decompressedBufRequested = Get32(p + 0x20); // ??? + // UInt32 blocksDescriptor = Get32(p + 0x24); // number starting from -1? + // char Reserved1[24]; + + Checksum.Parse(p + 0x40); + PRF(printf("\n\nChecksum Type = %2d", Checksum.Type)); + + UInt32 numBlocks = Get32(p + 0xC8); + if (numBlocks > ((UInt32)1 << 28)) + return S_FALSE; + + const UInt32 kRecordSize = 40; + if (numBlocks * kRecordSize + kHeadSize != size) + return S_FALSE; + + PackSize = 0; + Size = 0; + Blocks.ClearAndReserve(numBlocks); + FullFileChecksum = true; + + p += kHeadSize; + UInt32 i; + for (i = 0; i < numBlocks; i++, p += kRecordSize) + { + CBlock b; + b.Type = Get32(p); + b.UnpPos = Get64(p + 0x08) << 9; + b.UnpSize = Get64(p + 0x10) << 9; + b.PackPos = Get64(p + 0x18); + b.PackSize = Get64(p + 0x20); + + // b.PackPos can be 0 for some types. So we don't check it + if (!Blocks.IsEmpty()) + if (b.UnpPos != Blocks.Back().GetNextUnpPos()) + return S_FALSE; + + 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)); + + if (b.Type == METHOD_COMMENT) + continue; + if (b.Type == METHOD_END) + break; + PackSize += b.PackSize; + if (b.UnpSize != 0) + { + if (b.Type == METHOD_ZERO_2) + FullFileChecksum = false; + Blocks.AddInReserved(b); + } + } + if (i != numBlocks - 1) + return S_FALSE; + if (!Blocks.IsEmpty()) + Size = Blocks.Back().GetNextUnpPos(); + if (Size != (numSectors << 9)) + return S_FALSE; + return S_OK; +} + static int FindKeyPair(const CXmlItem &item, const AString &key, const AString &nextTag) { - for (int i = 0; i + 1 < item.SubItems.Size(); i++) + for (unsigned 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)) @@ -281,134 +453,308 @@ static int FindKeyPair(const CXmlItem &item, const AString &key, const AString & return -1; } -static AString GetStringFromKeyPair(const CXmlItem &item, const AString &key, const AString &nextTag) +static const 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(); + return item.SubItems[index].GetSubStringPtr(); + return NULL; +} + +static const unsigned HEADER_SIZE = 0x200; + +static bool IsKoly(const Byte *p) +{ + if (Get32(p) != 0x6B6F6C79) // "koly" signature + return false; + if (Get32(p + 4) != 4) // version + return false; + if (Get32(p + 8) != HEADER_SIZE) + return false; + return true; } HRESULT CHandler::Open2(IInStream *stream) { - const int HEADER_SIZE = 0x1E0; + RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_startPos)); - 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(); + UInt64 headerPos; + if (IsKoly(buf)) + headerPos = _startPos; + else + { + RINOK(stream->Seek(0, STREAM_SEEK_END, &headerPos)); + if (headerPos < HEADER_SIZE) + return S_FALSE; + headerPos -= HEADER_SIZE; + RINOK(stream->Seek(headerPos, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream_FALSE(stream, buf, HEADER_SIZE)); + if (!IsKoly(buf)) + return S_FALSE; + } - CXml xml; - if (!xml.Parse(_xml)) - return S_FALSE; - if (xml.Root.Name != "plist") + // UInt32 flags = Get32(buf + 12); + // UInt64 runningDataForkOffset = Get64(buf + 0x10); + UInt64 dataForkOffset = Get64(buf + 0x18); + UInt64 dataForkLen = Get64(buf + 0x20); + UInt64 rsrcOffset = Get64(buf + 0x28); + UInt64 rsrcLen = Get64(buf + 0x30); + // UInt32 segmentNumber = Get32(buf + 0x38); + // UInt32 segmentCount = Get32(buf + 0x3C); + // Byte segmentGUID[16]; + // CChecksum dataForkChecksum; + // dataForkChecksum.Parse(buf + 0x50); + UInt64 xmlOffset = Get64(buf + 0xD8); + UInt64 xmlLen = Get64(buf + 0xE0); + + UInt64 totalLen = dataForkLen + rsrcLen + xmlLen; + if (totalLen > headerPos) 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) + _startPos = headerPos - totalLen; + _phySize = totalLen + HEADER_SIZE; + headerPos = totalLen; + + if (headerPos < dataForkOffset || + headerPos < dataForkOffset + dataForkLen || + headerPos < rsrcOffset || + headerPos < rsrcOffset + rsrcLen || + headerPos < xmlOffset || + headerPos < xmlOffset + xmlLen) return S_FALSE; - const CXmlItem &arrItem = rfDictItem.SubItems[arrIndex]; + // Byte reserved[0x78] + + CChecksum masterChecksum; + masterChecksum.Parse(buf + 0x160); - int i; - for (i = 0; i < arrItem.SubItems.Size(); i++) + // UInt32 imageVariant = Get32(buf + 0x1E8); + // UInt64 numSectors = Get64(buf + 0x1EC); + // Byte reserved[0x12] + + const UInt32 RSRC_HEAD_SIZE = 0x100; + + // We don't know the size of the field "offset" in rsrc. + // We suppose that it uses 24 bits. So we use Rsrc, only if the rsrcLen < (1 << 24). + bool useRsrc = (rsrcLen > RSRC_HEAD_SIZE && rsrcLen < ((UInt32)1 << 24)); + // useRsrc = false; + + if (useRsrc) { - const CXmlItem &item = arrItem.SubItems[i]; - if (!item.IsTagged("dict")) - continue; + #ifdef DMG_SHOW_RAW + CExtraFile &extra = _extras.AddNew(); + extra.Name = "rsrc.bin"; + CByteBuffer &rsrcBuf = extra.Data; + #else + CByteBuffer rsrcBuf; + #endif + + size_t rsrcLenT = (size_t)rsrcLen; + rsrcBuf.Alloc(rsrcLenT); + RINOK(stream->Seek(_startPos + rsrcOffset, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream_FALSE(stream, rsrcBuf, rsrcLenT)); + + const Byte *p = rsrcBuf; + UInt32 headSize = Get32(p + 0); + UInt32 footerOffset = Get32(p + 4); + UInt32 mainDataSize = Get32(p + 8); + UInt32 footerSize = Get32(p + 12); + if (headSize != RSRC_HEAD_SIZE || + footerOffset >= rsrcLenT || + mainDataSize >= rsrcLenT || + footerOffset + footerSize != rsrcLenT || + footerOffset != headSize + mainDataSize) + return S_FALSE; + if (footerSize < 16) + return S_FALSE; + if (memcmp(p, p + footerOffset, 16) != 0) + return S_FALSE; - CFile file; - file.StartPos = 0; + p += footerOffset; - int destLen; + if ((UInt32)Get16(p + 0x18) != 0x1C) + return S_FALSE; + UInt32 namesOffset = Get16(p + 0x1A); + if (namesOffset > footerSize) + return S_FALSE; + + UInt32 numItems = (UInt32)Get16(p + 0x1C) + 1; + if (numItems * 8 + 0x1E > namesOffset) + return S_FALSE; + + for (UInt32 i = 0; i < numItems; i++) { - 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()); - } + const Byte *p2 = p + 0x1E + i * 8; + + UInt32 typeId = Get32(p2); + if (typeId != 0x626C6B78) // blkx + continue; + + UInt32 numFiles = (UInt32)Get16(p2 + 4) + 1; + UInt32 offs = Get16(p2 + 6); + if (0x1C + offs + 12 * numFiles > namesOffset) + return S_FALSE; - if (destLen > 0xCC && Get32(file.Raw) == 0x6D697368) + for (UInt32 k = 0; k < numFiles; k++) + { + const Byte *p3 = p + 0x1C + offs + k * 12; + // UInt32 id = Get16(p3); + UInt32 namePos = Get16(p3 + 2); + // Byte attributes = p3[4]; // = 0x50 for blkx + // we don't know how many bits we can use. So we use 24 bits only + UInt32 blockOffset = Get32(p3 + 4); + blockOffset &= (((UInt32)1 << 24) - 1); + // UInt32 unknown2 = Get32(p3 + 8); // ??? + if (blockOffset + 4 >= mainDataSize) + return S_FALSE; + const Byte *pBlock = rsrcBuf + headSize + blockOffset; + UInt32 blockSize = Get32(pBlock); + + #ifdef DMG_SHOW_RAW + { + CExtraFile &extra = _extras.AddNew(); + { + char extraName[16]; + ConvertUInt32ToString(_files.Size(), extraName); + extra.Name = extraName; + } + CByteBuffer &rawBuf = extra.Data; + rawBuf.SetCapacity(blockSize); + memcpy(rawBuf, pBlock + 4, blockSize); + } + #endif + + CFile &file = _files.AddNew(); + if (namePos != 0xFFFF) + { + UInt32 namesBlockSize = footerSize - namesOffset; + if (namePos >= namesBlockSize) + return S_FALSE; + const Byte *namePtr = p + namesOffset + namePos; + UInt32 nameLen = *namePtr; + if (namesBlockSize - namePos <= nameLen) + return S_FALSE; + for (UInt32 r = 1; r <= nameLen; r++) + { + char c = namePtr[r]; + if (c < 0x20 || c >= 0x80) + break; + file.Name += c; + } + } + RINOK(file.Parse(pBlock + 4, blockSize)); + } + } + } + else + { + if (xmlLen >= kXmlSizeMax || xmlLen == 0) + return S_FALSE; + RINOK(stream->Seek(_startPos + dataForkLen, STREAM_SEEK_SET, NULL)); + size_t size = (size_t)xmlLen; + + CXml xml; { - PRF(printf("\n\n index = %d", _files.Size())); - const int kRecordSize = 40; - for (int offset = 0xCC; offset + kRecordSize <= destLen; offset += kRecordSize) + AString xmlStr; + char *ss = xmlStr.GetBuffer((int)size + 1); + RINOK(ReadStream_FALSE(stream, ss, size)); + ss[size] = 0; { - 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)); + const char *p = ss; + for (;;) + { + if (*p == 0) break; p++; + if (*p == 0) break; p++; + if (*p == 0) break; p++; + if (*p == 0) break; p++; + } + xmlStr.ReleaseBuffer((int)(p - ss)); } + if (!xml.Parse(xmlStr)) + return S_FALSE; + + #ifdef DMG_SHOW_RAW + CExtraFile &extra = _extras.AddNew(); + extra.Name = "a.xml"; + extra.Data.SetCapacity(size); + memcpy(extra.Data, ss, size); + #endif } - int itemIndex = _files.Add(file); - if (file.Blocks.Size() > 0) + 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]; + + FOR_VECTOR (i, arrItem.SubItems) { - // if (file.Name.Find("HFS") >= 0) - _fileIndices.Add(itemIndex); + const CXmlItem &item = arrItem.SubItems[i]; + if (!item.IsTagged("dict")) + continue; + + CByteBuffer rawBuf; + int destLen = 0; + { + const AString *dataString = GetStringFromKeyPair(item, "Data", "data"); + if (!dataString) + return S_FALSE; + destLen = dataString->Len() / 4 * 3 + 4; + rawBuf.Alloc(destLen); + destLen = (int)(Base64ToBin(rawBuf, *dataString) - rawBuf); + #ifdef DMG_SHOW_RAW + CExtraFile &extra = _extras.AddNew(); + { + char extraName[16]; + ConvertUInt32ToString(_files.Size(), extraName); + extra.Name = extraName; + } + extra.Data.SetCapacity(destLen); + memcpy(extra.Data, rawBuf, destLen); + #endif + } + CFile &file = _files.AddNew(); + { + const AString *name = GetStringFromKeyPair(item, "Name", "string"); + if (!name || name->IsEmpty()) + name = GetStringFromKeyPair(item, "CFName", "string"); + if (name) + file.Name = *name; + } + RINOK(file.Parse(rawBuf, destLen)); } } - - // 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) + if (masterChecksum.IsCrc32()) { + UInt32 crc = CRC_INIT_VAL; + unsigned i; for (i = 0; i < _files.Size(); i++) { - CFile &file = _files[i]; - file.StartPos = startPos; - if (!file.Blocks.IsEmpty()) - startPos += file.Blocks.Back().GetNextPackOffset(); + const CChecksum &cs = _files[i].Checksum; + if ((cs.NumBits & 0x7) != 0) + break; + UInt32 len = cs.NumBits >> 3; + if (len > kChecksumSize_Max) + break; + crc = CrcUpdate(crc, cs.Data, (size_t)len); } + if (i == _files.Size()) + _masterCrcError = (CRC_GET_DIGEST(crc) != masterChecksum.GetCrc32()); } return S_OK; @@ -431,24 +777,27 @@ STDMETHODIMP CHandler::Open(IInStream *stream, STDMETHODIMP CHandler::Close() { + _phySize = 0; _inStream.Release(); - _fileIndices.Clear(); _files.Clear(); - _xml.Empty(); + _masterCrcError = false; + #ifdef DMG_SHOW_RAW + _extras.Clear(); + #endif return S_OK; } STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { - *numItems = _fileIndices.Size() + *numItems = _files.Size() #ifdef DMG_SHOW_RAW - + _files.Size() + 1; + + _extras.Size() #endif ; return S_OK; } -#define RAW_PREFIX L"raw" WSTRING_PATH_SEPARATOR +#define RAW_PREFIX "raw" STRING_PATH_SEPARATOR STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { @@ -456,69 +805,58 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val NWindows::NCOM::CPropVariant prop; #ifdef DMG_SHOW_RAW - if ((int)index == _fileIndices.Size()) + if ((int)index >= _files.Size()) { - switch(propID) + const CExtraFile &extra = _extras[index - _files.Size()]; + switch (propID) { case kpidPath: - prop = RAW_PREFIX L"a.xml"; + prop = (AString)RAW_PREFIX + extra.Name; break; case kpidSize: case kpidPackSize: - prop = (UInt64)_xml.Length(); + prop = (UInt64)extra.Data.Size(); break; } } - else if ((int)index > _fileIndices.Size()) + else + #endif { - int rawIndex = (int)index - (_fileIndices.Size() + 1); - switch(propID) + const CFile &item = _files[index]; + switch (propID) { - case kpidPath: + case kpidSize: prop = item.Size; break; + case kpidPackSize: prop = item.PackSize; break; + case kpidCRC: { - wchar_t s[32] = RAW_PREFIX; - ConvertUInt64ToString(rawIndex, s + MyStringLen(s)); - prop = s; + if (item.Checksum.IsCrc32() && item.FullFileChecksum) + prop = item.Checksum.GetCrc32(); 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; + AString s; + m.GetString(s); + if (!s.IsEmpty()) + prop = s; break; } - // case kpidExtension: prop = L"hfs"; break; - case kpidPath: { - // break; UString name; - wchar_t s[32]; - ConvertUInt64ToString(index, s); + wchar_t s[16]; + ConvertUInt32ToString(index, s); name = s; - int num = 10; - int numDigits; - for (numDigits = 1; num < _fileIndices.Size(); numDigits++) + unsigned num = 10; + unsigned numDigits; + for (numDigits = 1; num < _files.Size(); numDigits++) num *= 10; - while (name.Length() < numDigits) - name = L'0' + name; + while (name.Len() < numDigits) + name.InsertAtFront(L'0'); AString subName; int pos1 = item.Name.Find('('); @@ -528,23 +866,27 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val int pos2 = item.Name.Find(')', pos1); if (pos2 >= 0) { - subName = item.Name.Mid(pos1, pos2 - pos1); + subName.SetFrom(item.Name.Ptr(pos1), pos2 - pos1); pos1 = subName.Find(':'); if (pos1 >= 0) - subName = subName.Left(pos1); + subName.DeleteFrom(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"; + for (unsigned n = 0; n < kNumAppleNames; n++) + { + const CAppleName &appleName = k_Names[n]; + if (appleName.Ext) + { + if (subName == appleName.AppleName) + { + subName = appleName.Ext; + break; + } + } + } UString name2; ConvertUTF8ToUnicode(subName, name2); name += L'.'; @@ -561,6 +903,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val prop = name; break; } + case kpidComment: { UString name; @@ -568,9 +911,6 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val prop = name; break; } - - case kpidSize: prop = item.GetUnpackSize(); break; - case kpidPackSize: prop = item.GetPackSize(); break; } } prop.Detach(value); @@ -585,11 +925,13 @@ class CAdcDecoder: CLzOutWindow m_OutWindowStream; CInBuffer m_InStream; + /* void ReleaseStreams() { m_OutWindowStream.ReleaseStream(); m_InStream.ReleaseStream(); } + */ class CCoderReleaser { @@ -601,7 +943,7 @@ class CAdcDecoder: { if (NeedFlush) m_Coder->m_OutWindowStream.Flush(); - m_Coder->ReleaseStreams(); + // m_Coder->ReleaseStreams(); } }; friend class CCoderReleaser; @@ -711,7 +1053,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _files.Size(); if (numItems == 0) @@ -722,13 +1064,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, { 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(); + if (index >= _files.Size()) + totalSize += _extras[index - _files.Size()].Data.Size(); else #endif - totalSize += _files[_fileIndices[index]].GetUnpackSize(); + totalSize += _files[index].Size; } extractCallback->SetTotal(totalSize); @@ -738,8 +1078,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, UInt64 currentUnpSize = 0; const UInt32 kZeroBufSize = (1 << 14); - CByteBuffer zeroBuf; - zeroBuf.SetCapacity(kZeroBufSize); + CByteBuffer zeroBuf(kZeroBufSize); memset(zeroBuf, 0, kZeroBufSize); NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); @@ -774,52 +1113,55 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, 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)); + + COutStreamWithCRC *outCrcStreamSpec = new COutStreamWithCRC; + CMyComPtr outCrcStream = outCrcStreamSpec; + outCrcStreamSpec->SetStream(realOutStream); + bool needCrc = false; + outCrcStreamSpec->Init(needCrc); + CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream; CMyComPtr outStream(outStreamSpec); - outStreamSpec->SetStream(realOutStream); + outStreamSpec->SetStream(outCrcStream); realOutStream.Release(); Int32 opRes = NExtract::NOperationResult::kOK; #ifdef DMG_SHOW_RAW - if (index > _fileIndices.Size()) + if (index >= _files.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(); + const CByteBuffer &buf = _extras[index - _files.Size()].Data; + outStreamSpec->Init(buf.Size()); + RINOK(WriteStream(outStream, buf, buf.Size())); + currentPackSize = currentUnpSize = buf.Size(); } else #endif { - const CFile &item = _files[_fileIndices[index]]; - currentPackSize = item.GetPackSize(); - currentUnpSize = item.GetUnpackSize(); + const CFile &item = _files[index]; + currentPackSize = item.PackSize; + currentUnpSize = item.Size; + + needCrc = item.Checksum.IsCrc32(); UInt64 unpPos = 0; UInt64 packPos = 0; { - for (int j = 0; j < item.Blocks.Size(); j++) + FOR_VECTOR (j, item.Blocks) { lps->InSize = currentPackTotal + packPos; lps->OutSize = currentUnpTotal + unpPos; RINOK(lps->SetCur()); const CBlock &block = item.Blocks[j]; + if (!block.ThereAreDataInBlock()) + continue; packPos += block.PackSize; if (block.UnpPos != unpPos) @@ -828,26 +1170,28 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, break; } - RINOK(_inStream->Seek(item.StartPos + block.PackPos, STREAM_SEEK_SET, NULL)); + RINOK(_inStream->Seek(_startPos + 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) + outCrcStreamSpec->EnableCalc(needCrc); + + switch (block.Type) { case METHOD_ZERO_0: case METHOD_ZERO_2: realMethod = false; if (block.PackSize != 0) - opRes = NExtract::NOperationResult::kUnSupportedMethod; + opRes = NExtract::NOperationResult::kUnsupportedMethod; + outCrcStreamSpec->EnableCalc(block.Type == METHOD_ZERO_0); break; case METHOD_COPY: if (block.UnpSize != block.PackSize) { - opRes = NExtract::NOperationResult::kUnSupportedMethod; + opRes = NExtract::NOperationResult::kUnsupportedMethod; break; } res = copyCoder->Code(inStream, outStream, NULL, NULL, progress); @@ -862,6 +1206,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, case METHOD_ZLIB: { res = zlibCoder->Code(inStream, outStream, NULL, NULL, progress); + if (res == S_OK) + if (zlibCoderSpec->GetInputProcessedSize() != block.PackSize) + opRes = NExtract::NOperationResult::kDataError; break; } @@ -869,13 +1216,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, { res = bzip2Coder->Code(inStream, outStream, NULL, NULL, progress); if (res == S_OK) - if (streamSpec->GetSize() != block.PackSize) + if (bzip2CoderSpec->GetInputProcessedSize() != block.PackSize) opRes = NExtract::NOperationResult::kDataError; break; } default: - opRes = NExtract::NOperationResult::kUnSupportedMethod; + opRes = NExtract::NOperationResult::kUnsupportedMethod; break; } if (res != S_OK) @@ -900,6 +1247,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } } } + if (needCrc && opRes == NExtract::NOperationResult::kOK) + { + if (outCrcStreamSpec->GetCRC() != item.Checksum.GetCrc32()) + opRes = NExtract::NOperationResult::kCRCError; + } } outStream.Release(); RINOK(extractCallback->SetOperationResult(opRes)); @@ -908,10 +1260,286 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_END } -static IInArchive *CreateArc() { return new CHandler; } +struct CChunk +{ + int BlockIndex; + UInt64 AccessMark; + CByteBuffer Buf; +}; + +class CInStream: + public IInStream, + public CMyUnknownImp +{ + UInt64 _virtPos; + int _latestChunk; + int _latestBlock; + UInt64 _accessMark; + CObjectVector _chunks; + + NCompress::NBZip2::CDecoder *bzip2CoderSpec; + CMyComPtr bzip2Coder; + + NCompress::NZlib::CDecoder *zlibCoderSpec; + CMyComPtr zlibCoder; + + CAdcDecoder *adcCoderSpec; + CMyComPtr adcCoder; + + CBufPtrSeqOutStream *outStreamSpec; + CMyComPtr outStream; + + CLimitedSequentialInStream *limitedStreamSpec; + CMyComPtr inStream; + +public: + CMyComPtr Stream; + UInt64 Size; + const CFile *File; + UInt64 _startPos; + + HRESULT InitAndSeek(UInt64 startPos) + { + _startPos = startPos; + _virtPos = 0; + _latestChunk = -1; + _latestBlock = -1; + _accessMark = 0; + + limitedStreamSpec = new CLimitedSequentialInStream; + inStream = limitedStreamSpec; + limitedStreamSpec->SetStream(Stream); + + outStreamSpec = new CBufPtrSeqOutStream; + outStream = outStreamSpec; + return S_OK; + } + + MY_UNKNOWN_IMP1(IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + + +int FindBlock(const CRecordVector &blocks, UInt64 pos) +{ + int left = 0, right = blocks.Size(); + for (;;) + { + int mid = (left + right) / 2; + if (mid == left) + return left; + if (pos < blocks[mid].UnpPos) + right = mid; + else + left = mid; + } +} + +STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + COM_TRY_BEGIN + + if (processedSize) + *processedSize = 0; + if (size == 0) + return S_OK; + if (_virtPos >= Size) + return S_OK; // (Size == _virtPos) ? S_OK: E_FAIL; + { + UInt64 rem = Size - _virtPos; + if (size > rem) + size = (UInt32)rem; + } + + if (_latestBlock >= 0) + { + const CBlock &block = File->Blocks[_latestBlock]; + if (_virtPos < block.UnpPos || (_virtPos - block.UnpPos) >= block.UnpSize) + _latestBlock = -1; + } + if (_latestBlock < 0) + { + _latestChunk = -1; + int blockIndex = FindBlock(File->Blocks, _virtPos); + const CBlock &block = File->Blocks[blockIndex]; + if (!block.IsZeroMethod() && block.Type != METHOD_COPY) + { + unsigned i; + for (i = 0; i < _chunks.Size(); i++) + if (_chunks[i].BlockIndex == blockIndex) + break; + if (i != _chunks.Size()) + _latestChunk = i; + else + { + const int kNumChunksMax = 128; + int chunkIndex; + if (_chunks.Size() != kNumChunksMax) + chunkIndex = _chunks.Add(CChunk()); + else + { + chunkIndex = 0; + for (i = 0; i < _chunks.Size(); i++) + if (_chunks[i].AccessMark < _chunks[chunkIndex].AccessMark) + chunkIndex = i; + } + CChunk &chunk = _chunks[chunkIndex]; + chunk.BlockIndex = -1; + chunk.AccessMark = 0; + if (chunk.Buf.Size() < block.UnpSize) + { + chunk.Buf.Free(); + if (block.UnpSize > ((UInt32)1 << 31)) + return E_FAIL; + chunk.Buf.Alloc((size_t)block.UnpSize); + } + outStreamSpec->Init(chunk.Buf, (size_t)block.UnpSize); + + RINOK(Stream->Seek(_startPos + File->StartPos + block.PackPos, STREAM_SEEK_SET, NULL)); + + limitedStreamSpec->Init(block.PackSize); + HRESULT res = S_OK; + switch (block.Type) + { + case METHOD_COPY: + if (block.PackSize != block.UnpSize) + return E_FAIL; + res = ReadStream_FAIL(inStream, chunk.Buf, (size_t)block.UnpSize); + break; + + case METHOD_ADC: + if (!adcCoder) + { + adcCoderSpec = new CAdcDecoder(); + adcCoder = adcCoderSpec; + } + res = adcCoder->Code(inStream, outStream, &block.PackSize, &block.UnpSize, NULL); + break; + + case METHOD_ZLIB: + if (!zlibCoder) + { + zlibCoderSpec = new NCompress::NZlib::CDecoder(); + zlibCoder = zlibCoderSpec; + } + res = zlibCoder->Code(inStream, outStream, NULL, NULL, NULL); + if (res == S_OK && zlibCoderSpec->GetInputProcessedSize() != block.PackSize) + res = S_FALSE; + break; + + case METHOD_BZIP2: + if (!bzip2Coder) + { + bzip2CoderSpec = new NCompress::NBZip2::CDecoder(); + bzip2Coder = bzip2CoderSpec; + } + res = bzip2Coder->Code(inStream, outStream, NULL, NULL, NULL); + if (res == S_OK && bzip2CoderSpec->GetInputProcessedSize() != block.PackSize) + res = S_FALSE; + break; + + default: + return E_FAIL; + } + if (res != S_OK) + return res; + if (block.Type != METHOD_COPY && outStreamSpec->GetPos() != block.UnpSize) + return E_FAIL; + chunk.BlockIndex = blockIndex; + _latestChunk = chunkIndex; + } + _chunks[_latestChunk].AccessMark = _accessMark++; + } + _latestBlock = blockIndex; + } + + const CBlock &block = File->Blocks[_latestBlock]; + UInt64 offset = _virtPos - block.UnpPos; + UInt64 rem = block.UnpSize - offset; + if (size > rem) + size = (UInt32)rem; + + HRESULT res = S_OK; + if (block.Type == METHOD_COPY) + { + RINOK(Stream->Seek(_startPos + File->StartPos + block.PackPos + offset, STREAM_SEEK_SET, NULL)); + res = Stream->Read(data, size, &size); + } + else if (block.IsZeroMethod()) + memset(data, 0, size); + else + memcpy(data, _chunks[_latestChunk].Buf + offset, size); + _virtPos += size; + if (processedSize) + *processedSize = size; + return res; + COM_TRY_END +} + +STDMETHODIMP CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: offset += Size; break; + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = offset; + if (newPosition) + *newPosition = offset; + return S_OK; +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + #ifdef DMG_SHOW_RAW + if (index >= (UInt32)_files.Size()) + return S_FALSE; + #endif + CInStream *spec = new CInStream; + CMyComPtr specStream = spec; + spec->File = &_files[index]; + const CFile &file = *spec->File; + FOR_VECTOR (i, file.Blocks) + { + const CBlock &block = file.Blocks[i]; + switch (block.Type) + { + case METHOD_ZERO_0: + case METHOD_ZERO_2: + case METHOD_COPY: + case METHOD_ADC: + case METHOD_ZLIB: + case METHOD_BZIP2: + case METHOD_END: + break; + default: + return S_FALSE; + } + } + spec->Stream = _inStream; + spec->Size = spec->File->Size; + RINOK(spec->InitAndSeek(_startPos)); + *stream = specStream.Detach(); + return S_OK; + COM_TRY_END +} + +IMP_CreateArcIn static CArcInfo g_ArcInfo = - { L"Dmg", L"dmg", 0, 0xE4, { 0 }, 0, false, CreateArc, 0 }; + { "Dmg", "dmg", 0, 0xE4, + 12, { 'k','o','l','y', 0, 0, 0, 4, 0, 0, 2, 0 }, + 0, + NArcInfoFlags::kBackwardOpen | + NArcInfoFlags::kUseGlobalOffset, + CreateArc }; REGISTER_ARC(Dmg) diff --git a/CPP/7zip/Archive/ElfHandler.cpp b/CPP/7zip/Archive/ElfHandler.cpp old mode 100755 new mode 100644 index c4ad78e9..1736219f --- a/CPP/7zip/Archive/ElfHandler.cpp +++ b/CPP/7zip/Archive/ElfHandler.cpp @@ -4,11 +4,11 @@ #include "../../../C/CpuArch.h" -#include "Common/Buffer.h" -#include "Common/ComTry.h" -#include "Common/IntToString.h" +#include "../../Common/ComTry.h" +#include "../../Common/IntToString.h" +#include "../../Common/MyBuffer.h" -#include "Windows/PropVariantUtils.h" +#include "../../Windows/PropVariantUtils.h" #include "../Common/LimitedStreams.h" #include "../Common/ProgressUtils.h" @@ -17,22 +17,44 @@ #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; +static UInt16 Get16(const Byte *p, bool be) { if (be) return GetBe16(p); return GetUi16(p); } +static UInt32 Get32(const Byte *p, bool be) { if (be) return GetBe32(p); return GetUi32(p); } +static UInt64 Get64(const Byte *p, bool be) { if (be) return GetBe64(p); return GetUi64(p); } + +#define G16(offs, v) v = Get16(p + (offs), be) +#define G32(offs, v) v = Get32(p + (offs), be) +#define G64(offs, v) v = Get64(p + (offs), be) + namespace NArchive { namespace NElf { +/* + ELF Structure for most files (real order can be different): + Header + Program (segment) header table (used at runtime) + Segment1 (Section ... Section) + Segment2 + ... + SegmentN + Section header table (the data for linking and relocation) +*/ + #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) +static const UInt32 kHeaderSize32 = 0x34; +static const UInt32 kHeaderSize64 = 0x40; + +static const UInt32 kSegmentSize32 = 0x20; +static const UInt32 kSegmentSize64 = 0x38; + +static const UInt32 kSectionSize32 = 0x28; +static const UInt32 kSectionSize64 = 0x40; struct CHeader { @@ -49,37 +71,30 @@ struct CHeader UInt64 ProgOffset; UInt64 SectOffset; UInt32 Flags; - UInt16 ElfHeaderSize; + UInt16 HeaderSize; UInt16 SegmentEntrySize; UInt16 NumSegments; - UInt16 SectEntrySize; + UInt16 SectionEntrySize; UInt16 NumSections; - // UInt16 SectNameStringTableIndex; + UInt16 NamesSectIndex; 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; } - + UInt64 GetHeadersSize() const { return (UInt64)HeaderSize + + (UInt32)NumSegments * SegmentEntrySize + + (UInt32)NumSections * SectionEntrySize; } }; bool CHeader::Parse(const Byte *p) { - switch(p[4]) + 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]) + switch (p[5]) { case ELF_DATA_2LSB: be = false; break; case ELF_DATA_2MSB: be = true; break; @@ -94,36 +109,72 @@ bool CHeader::Parse(const Byte *p) if (p[i] != 0) return false; - Type = Get16(p + 0x10, be); - Machine = Get16(p + 0x12, be); + G16(0x10, Type); + G16(0x12, Machine); 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); + // G64(0x18, EntryVa); + G64(0x20, ProgOffset); + G64(0x28, SectOffset); p += 0x30; } else { - // EntryVa = Get32(p + 0x18, be); - ProgOffset = Get32(p + 0x1C, be); - SectOffset = Get32(p + 0x20, be); + // G32(0x18, EntryVa); + G32(0x1C, ProgOffset); + G32(0x20, SectOffset); 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(); + G32(0, Flags); + G16(4, HeaderSize); + if (HeaderSize != (Mode64 ? kHeaderSize64 : kHeaderSize32)) + return false; + + G16(6, SegmentEntrySize); + G16(8, NumSegments); + G16(10, SectionEntrySize); + G16(12, NumSections); + G16(14, NamesSectIndex); + + if (ProgOffset < HeaderSize && (ProgOffset != 0 || NumSegments != 0)) return false; + if (SectOffset < HeaderSize && (SectOffset != 0 || NumSections != 0)) return false; + + if (SegmentEntrySize == 0) { if (NumSegments != 0) return false; } + else if (SegmentEntrySize != (Mode64 ? kSegmentSize64 : kSegmentSize32)) return false; + + if (SectionEntrySize == 0) { if (NumSections != 0) return false; } + else if (SectionEntrySize != (Mode64 ? kSectionSize64 : kSectionSize32)) return false; + + return true; } +// The program header table itself. + +#define PT_PHDR 6 + +static const char *g_SegnmentTypes[] = +{ + "Unused", + "Loadable segment", + "Dynamic linking tables", + "Program interpreter path name", + "Note section", + "SHLIB", + "Program header table", + "TLS" +}; + +static const CUInt32PCharPair g_SegmentFlags[] = +{ + { 0, "Execute" }, + { 1, "Write" }, + { 2, "Read" } +}; + struct CSegment { UInt32 Type; @@ -131,14 +182,14 @@ struct CSegment UInt64 Offset; UInt64 Va; // UInt64 Pa; - UInt64 PSize; + UInt64 Size; UInt64 VSize; - // UInt64 Align; + UInt64 Align; void UpdateTotalSize(UInt64 &totalSize) { - UInt64 t = Offset + PSize; - if (t > totalSize) + UInt64 t = Offset + Size; + if (totalSize < t) totalSize = t; } void Parse(const Byte *p, bool mode64, bool be); @@ -146,30 +197,169 @@ struct CSegment void CSegment::Parse(const Byte *p, bool mode64, bool be) { - Type = Get32(p, be); + G32(0, Type); 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); + G32(4, Flags); + G64(8, Offset); + G64(0x10, Va); + // G64(0x18, Pa); + G64(0x20, Size); + G64(0x28, VSize); + G64(0x30, Align); } 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); + G32(4, Offset); + G32(8, Va); + // G32(0x0C, Pa); + G32(0x10, Size); + G32(0x14, VSize); + G32(0x18, Flags); + G32(0x1C, Align); } } -static const CUInt32PCharPair g_MachinePairs[] = +// Section_index = 0 means NO section + +#define SHN_UNDEF 0 + +// Section types + +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_UNKNOWN12 12 +#define SHT_UNKNOWN13 13 +#define SHT_INIT_ARRAY 14 +#define SHT_FINI_ARRAY 15 +#define SHT_PREINIT_ARRAY 16 +#define SHT_GROUP 17 +#define SHT_SYMTAB_SHNDX 18 + + +static const CUInt32PCharPair g_SectTypes[] = +{ + { 0, "NULL" }, + { 1, "PROGBITS" }, + { 2, "SYMTAB" }, + { 3, "STRTAB" }, + { 4, "RELA" }, + { 5, "HASH" }, + { 6, "DYNAMIC" }, + { 7, "NOTE" }, + { 8, "NOBITS" }, + { 9, "REL" }, + { 10, "SHLIB" }, + { 11, "DYNSYM" }, + { 12, "UNKNOWN12" }, + { 13, "UNKNOWN13" }, + { 14, "INIT_ARRAY" }, + { 15, "FINI_ARRAY" }, + { 16, "PREINIT_ARRAY" }, + { 17, "GROUP" }, + { 18, "SYMTAB_SHNDX" }, + { 0x6ffffff5, "GNU_ATTRIBUTES" }, + { 0x6ffffff6, "GNU_HASH" }, + { 0x6ffffffd, "GNU_verdef" }, + { 0x6ffffffe, "GNU_verneed" }, + { 0x6fffffff, "GNU_versym" }, + // { 0x70000001, "X86_64_UNWIND" }, + { 0x70000001, "ARM_EXIDX" }, + { 0x70000002, "ARM_PREEMPTMAP" }, + { 0x70000003, "ARM_ATTRIBUTES" }, + { 0x70000004, "ARM_DEBUGOVERLAY" }, + { 0x70000005, "ARM_OVERLAYSECTION" } +}; + +static const CUInt32PCharPair g_SectionFlags[] = +{ + { 0, "WRITE" }, + { 1, "ALLOC" }, + { 2, "EXECINSTR" }, + + { 4, "MERGE" }, + { 5, "STRINGS" }, + { 6, "INFO_LINK" }, + { 7, "LINK_ORDER" }, + { 8, "OS_NONCONFORMING" }, + { 9, "GROUP" }, + { 10, "TLS" }, + { 11, "CP_SECTION" }, + { 12, "DP_SECTION" }, + { 13, "XCORE_SHF_CP_SECTION" }, + { 28, "64_LARGE" }, +}; + +struct CSection +{ + UInt32 Name; + UInt32 Type; + UInt64 Flags; + UInt64 Va; + UInt64 Offset; + UInt64 VSize; + UInt32 Link; + UInt32 Info; + UInt64 AddrAlign; + UInt64 EntSize; + + UInt64 GetSize() const { return Type == SHT_NOBITS ? 0 : VSize; } + + void UpdateTotalSize(UInt64 &totalSize) + { + UInt64 t = Offset + GetSize(); + if (totalSize < t) + totalSize = t; + } + bool Parse(const Byte *p, bool mode64, bool be); +}; + +bool CSection::Parse(const Byte *p, bool mode64, bool be) +{ + G32(0, Name); + G32(4, Type); + if (mode64) + { + G64(0x08, Flags); + G64(0x10, Va); + G64(0x18, Offset); + G64(0x20, VSize); + G32(0x28, Link); + G32(0x2C, Info); + G64(0x30, AddrAlign); + G64(0x38, EntSize); + } + else + { + G32(0x08, Flags); + G32(0x0C, Va); + G32(0x10, Offset); + G32(0x14, VSize); + G32(0x18, Link); + G32(0x1C, Info); + G32(0x20, AddrAlign); + G32(0x24, EntSize); + } + if (EntSize >= ((UInt32)1 << 31)) + return false; + if (EntSize >= ((UInt32)1 << 10) && + EntSize >= VSize && + VSize != 0) + return false; + return true; +} + +static const CUInt32PCharPair g_Machines[] = { { 0, "None" }, { 1, "AT&T WE 32100" }, @@ -192,6 +382,7 @@ static const CUInt32PCharPair g_MachinePairs[] = { 20, "PowerPC" }, { 21, "PowerPC 64-bit" }, { 22, "IBM S/390" }, + { 23, "SPU" }, { 36, "NEX v800" }, { 37, "Fujitsu FR20" }, @@ -222,6 +413,7 @@ static const CUInt32PCharPair g_MachinePairs[] = { 62, "AMD64" }, { 63, "Sony DSP" }, + { 66, "Siemens FX66" }, { 67, "ST9+" }, { 68, "ST7" }, @@ -251,15 +443,99 @@ static const CUInt32PCharPair g_MachinePairs[] = { 92, "OpenRISC" }, { 93, "ARC Tangent-A5" }, { 94, "Tensilica Xtensa" }, - { 0x9026, "Alpha" } + { 95, "Alphamosaic VideoCore" }, + { 96, "Thompson MM GPP" }, + { 97, "National Semiconductor 32K" }, + { 98, "Tenor Network TPC" }, + { 99, "Trebia SNP 1000" }, + { 100, "ST200" }, + { 101, "Ubicom IP2xxx" }, + { 102, "MAX" }, + { 103, "NS CompactRISC" }, + { 104, "Fujitsu F2MC16" }, + { 105, "TI msp430" }, + { 106, "Blackfin (DSP)" }, + { 107, "SE S1C33" }, + { 108, "Sharp embedded" }, + { 109, "Arca RISC" }, + { 110, "Unicore" }, + { 111, "eXcess" }, + { 112, "DXP" }, + { 113, "Altera Nios II" }, + { 114, "NS CRX" }, + { 115, "Motorola XGATE" }, + { 116, "Infineon C16x/XC16x" }, + { 117, "Renesas M16C" }, + { 118, "Microchip Technology dsPIC30F" }, + { 119, "Freescale CE" }, + { 120, "Renesas M32C" }, + + { 131, "Altium TSK3000" }, + { 132, "Freescale RS08" }, + { 133, "Analog Devices SHARC" }, + { 134, "Cyan Technology eCOG2" }, + { 135, "Sunplus S+core7 RISC" }, + { 136, "NJR 24-bit DSP" }, + { 137, "Broadcom VideoCore III" }, + { 138, "Lattice FPGA" }, + { 139, "SE C17" }, + { 140, "TI TMS320C6000" }, + { 141, "TI TMS320C2000" }, + { 142, "TI TMS320C55x" }, + + { 160, "STM 64bit VLIW Data Signal" }, + { 161, "Cypress M8C" }, + { 162, "Renesas R32C" }, + { 163, "NXP TriMedia" }, + { 164, "Qualcomm Hexagon" }, + { 165, "Intel 8051" }, + { 166, "STMicroelectronics STxP7x" }, + { 167, "Andes" }, + { 168, "Cyan Technology eCOG1X" }, + { 169, "Dallas Semiconductor MAXQ30" }, + { 170, "NJR 16-bit DSP" }, + { 171, "M2000" }, + { 172, "Cray NV2" }, + { 173, "Renesas RX" }, + { 174, "Imagination Technologies META" }, + { 175, "MCST Elbrus" }, + { 176, "Cyan Technology eCOG16" }, + { 177, "National Semiconductor CR16" }, + { 178, "Freescale ETPUnit" }, + { 179, "Infineon SLE9X" }, + { 180, "Intel L10M" }, + { 181, "Intel K10M" }, + + { 183, "ARM64" }, + + { 185, "Atmel AVR32" }, + { 186, "STM8" }, + { 187, "Tilera TILE64" }, + { 188, "Tilera TILEPro" }, + { 189, "Xilinx MicroBlaze" }, + { 190, "NVIDIA CUDA" }, + { 191, "Tilera TILE-Gx" }, + { 192, "CloudShield" }, + { 193, "KIPO-KAIST Core-A 1st" }, + { 194, "KIPO-KAIST Core-A 2nd" }, + { 195, "Synopsys ARCompact V2" }, + { 196, "Open8" }, + { 197, "Renesas RL78" }, + { 198, "Broadcom VideoCore V" }, + { 199, "Renesas 78KOR" }, + { 200, "Freescale 56800EX" }, + + { 47787, "Xilinx MicroBlaze" }, + // { 0x9026, "Alpha" } }; -static const CUInt32PCharPair g_AbiOS[] = +static const CUInt32PCharPair g_OS[] = { { 0, "None" }, { 1, "HP-UX" }, { 2, "NetBSD" }, { 3, "Linux" }, + { 4, "Hurd" }, { 6, "Solaris" }, { 7, "AIX" }, @@ -271,16 +547,18 @@ static const CUInt32PCharPair g_AbiOS[] = { 13, "OpenVMS" }, { 14, "HP NSK" }, { 15, "AROS" }, + { 16, "FenixOS" }, + { 64, "Bare-metal TMS320C6000" }, + { 65, "Linux TMS320C6000" }, { 97, "ARM" }, { 255, "Standalone" } }; -static const CUInt32PCharPair g_SegmentFlags[] = -{ - { 0, "Execute" }, - { 1, "Write" }, - { 2, "Read" } -}; +#define ET_NONE 0 +#define ET_REL 1 +#define ET_EXEC 2 +#define ET_DYN 3 +#define ET_CORE 4 static const char *g_Types[] = { @@ -291,101 +569,119 @@ static const char *g_Types[] = "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 IArchiveAllowTail, public CMyUnknownImp { + CRecordVector _segments; + CRecordVector _sections; + CByteBuffer _namesData; CMyComPtr _inStream; - CObjectVector _sections; - UInt32 _peOffset; - CHeader _header; UInt64 _totalSize; + CHeader _header; + bool _headersError; + bool _allowTail; + + void GetSectionName(UInt32 index, NCOM::CPropVariant &prop, bool showNULL) const; HRESULT Open2(IInStream *stream); - bool Parse(const Byte *buf, UInt32 size); public: - MY_UNKNOWN_IMP1(IInArchive) + MY_UNKNOWN_IMP2(IInArchive, IArchiveAllowTail) INTERFACE_IInArchive(;) -}; + STDMETHOD(AllowTail)(Int32 allowTail); -#define ELF_PT_PHDR 6 + CHandler(): _allowTail(false) {} +}; -bool CHandler::Parse(const Byte *buf, UInt32 size) +void CHandler::GetSectionName(UInt32 index, NCOM::CPropVariant &prop, bool showNULL) const { - 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) + if (index >= _sections.Size()) + return; + const CSection §ion = _sections[index]; + UInt32 offset = section.Name; + if (index == SHN_UNDEF /* && section.Type == SHT_NULL && offset == 0 */) { - CSegment sect; - sect.Parse(p, _header.Mode64, _header.Be); - sect.UpdateTotalSize(_totalSize); - if (sect.Type != ELF_PT_PHDR) - _sections.Add(sect); + if (showNULL) + prop = "NULL"; + return; } - UInt64 total2 = _header.SectOffset + (UInt64)_header.SectEntrySize * _header.NumSections; - if (total2 > _totalSize) - _totalSize = total2; - return true; + const Byte *p = _namesData; + size_t size = _namesData.Size(); + for (size_t i = offset; i < size; i++) + if (p[i] == 0) + { + prop = (const char *)(p + offset); + return; + } } -STATPROPSTG kArcProps[] = +static const Byte kArcProps[] = +{ + kpidCpu, + kpidBit64, + kpidBigEndian, + kpidHostOS, + kpidCharacts, + kpidHeadersSize, + kpidName +}; + +enum { - { 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[] = + kpidLinkSection = kpidUserDefined, + kpidInfoSection +}; + +static const 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} + { NULL, kpidPath, VT_BSTR }, + { NULL, kpidSize, VT_UI8 }, + { NULL, kpidVirtualSize, VT_UI8 }, + { NULL, kpidOffset, VT_UI8 }, + { NULL, kpidVa, VT_UI8 }, + { NULL, kpidType, VT_BSTR }, + { NULL, kpidCharacts, VT_BSTR } + , { L"Link Section", kpidLinkSection, VT_BSTR} + , { L"Info Section", kpidInfoSection, VT_BSTR} }; -IMP_IInArchive_Props +IMP_IInArchive_Props_WITH_NAME IMP_IInArchive_ArcProps STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; - switch(propID) + 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; + 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 kpidShortComment: + case kpidCpu: PAIR_TO_PROP(g_Machines, _header.Machine, prop); break; + case kpidHostOS: PAIR_TO_PROP(g_OS, _header.Os, prop); break; + case kpidCharacts: TYPE_TO_PROP(g_Types, _header.Type, prop); break; + case kpidExtension: + { + const char *s = NULL; + if (_header.Type == ET_DYN) + s = "so"; + else if (_header.Type == ET_REL) + s = "o"; + if (s) + prop = s; + break; + } + // case kpidIsSelfExe: prop = (_header.Type != ET_DYN) && (_header.Type == ET_REL); break; + case kpidErrorFlags: + { + UInt32 flags = 0; + if (_headersError) flags |= kpv_ErrorFlags_HeadersError; + if (flags != 0) + prop = flags; + break; + } } prop.Detach(value); return S_OK; @@ -396,22 +692,45 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { COM_TRY_BEGIN NCOM::CPropVariant prop; - const CSegment &item = _sections[index]; - switch(propID) + if (index < _segments.Size()) { - case kpidPath: + const CSegment &item = _segments[index]; + switch (propID) { - wchar_t sz[32]; - ConvertUInt64ToString(index, sz); - prop = sz; - break; + case kpidPath: + { + char sz[16]; + ConvertUInt32ToString(index, sz); + prop = sz; + break; + } + case kpidOffset: prop = item.Offset; break; + case kpidVa: prop = item.Va; break; + case kpidSize: + case kpidPackSize: prop = (UInt64)item.Size; break; + case kpidVirtualSize: prop = (UInt64)item.VSize; break; + case kpidType: TYPE_TO_PROP(g_SegnmentTypes, item.Type, prop); break; + case kpidCharacts: FLAGS_TO_PROP(g_SegmentFlags, item.Flags, prop); break; + + } + } + else + { + index -= _segments.Size(); + const CSection &item = _sections[index]; + switch (propID) + { + case kpidPath: GetSectionName(index, prop, true); break; + case kpidOffset: prop = item.Offset; break; + case kpidVa: prop = item.Va; break; + case kpidSize: + case kpidPackSize: prop = (UInt64)(item.Type == SHT_NOBITS ? 0 : item.VSize); break; + case kpidVirtualSize: prop = item.GetSize(); break; + case kpidType: PAIR_TO_PROP(g_SectTypes, item.Type, prop); break; + case kpidCharacts: FLAGS_TO_PROP(g_SectionFlags, (UInt32)item.Flags, prop); break; + case kpidLinkSection: GetSectionName(item.Link, prop, false); break; + case kpidInfoSection: GetSectionName(item.Info, prop, false); 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; @@ -420,25 +739,118 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val 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') + const UInt32 kStartSize = kHeaderSize64; + Byte h[kStartSize]; + RINOK(ReadStream_FALSE(stream, h, kStartSize)); + if (h[0] != 0x7F || h[1] != 'E' || h[2] != 'L' || h[3] != 'F') return S_FALSE; - processed = kBufSize - kSigSize; - RINOK(ReadStream(stream, buf + kSigSize, &processed)); - processed += kSigSize; - if (!Parse(buf, (UInt32)processed)) + if (!_header.Parse(h)) return S_FALSE; - UInt64 fileSize; - RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize)); - return (fileSize == _totalSize) ? S_OK : S_FALSE; + + _totalSize = _header.HeaderSize; + + bool addSegments = false; + bool addSections = false; + + if (_header.NumSections > 1) + addSections = true; + else + addSegments = true; + + if (_header.NumSegments != 0) + { + if (_header.ProgOffset > (UInt64)1 << 60) return S_FALSE; + RINOK(stream->Seek(_header.ProgOffset, STREAM_SEEK_SET, NULL)); + size_t size = (size_t)_header.SegmentEntrySize * _header.NumSegments; + + CByteArr buf(size); + + RINOK(ReadStream_FALSE(stream, buf, size)); + + UInt64 total = _header.ProgOffset + size; + if (_totalSize < total) + _totalSize = total; + + const Byte *p = buf; + + if (addSegments) + _segments.ClearAndReserve(_header.NumSegments); + for (unsigned i = 0; i < _header.NumSegments; i++, p += _header.SegmentEntrySize) + { + CSegment seg; + seg.Parse(p, _header.Mode64, _header.Be); + seg.UpdateTotalSize(_totalSize); + if (addSegments) + if (seg.Type != PT_PHDR) + _segments.AddInReserved(seg); + } + } + + if (_header.NumSections != 0) + { + if (_header.SectOffset > (UInt64)1 << 60) return S_FALSE; + RINOK(stream->Seek(_header.SectOffset, STREAM_SEEK_SET, NULL)); + size_t size = (size_t)_header.SectionEntrySize * _header.NumSections; + + CByteArr buf(size); + + RINOK(ReadStream_FALSE(stream, buf, size)); + + UInt64 total = _header.SectOffset + size; + if (_totalSize < total) + _totalSize = total; + + const Byte *p = buf; + + if (addSections) + _sections.ClearAndReserve(_header.NumSections); + for (unsigned i = 0; i < _header.NumSections; i++, p += _header.SectionEntrySize) + { + CSection sect; + if (!sect.Parse(p, _header.Mode64, _header.Be)) + { + _headersError = true; + return S_FALSE; + } + sect.UpdateTotalSize(_totalSize); + if (addSections) + _sections.AddInReserved(sect); + } + } + + if (addSections) + { + if (_header.NamesSectIndex < _sections.Size()) + { + const CSection § = _sections[_header.NamesSectIndex]; + UInt64 size = sect.GetSize(); + if (size != 0 + && size < ((UInt64)1 << 31) + && (Int64)sect.Offset >= 0) + { + _namesData.Alloc((size_t)size); + RINOK(stream->Seek(sect.Offset, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream_FALSE(stream, _namesData, (size_t)size)); + } + } + + /* + // we will not delete NULL sections, since we have links to section via indexes + for (int i = _sections.Size() - 1; i >= 0; i--) + if (_sections[i].Type == SHT_NULL) + _items.Delete(i); + */ + } + + if (!_allowTail) + { + UInt64 fileSize; + RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize)); + if (fileSize > _totalSize) + return S_FALSE; + } + + return S_OK; } STDMETHODIMP CHandler::Open(IInStream *inStream, @@ -455,14 +867,19 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, STDMETHODIMP CHandler::Close() { + _totalSize = 0; + _headersError = false; + _inStream.Release(); + _segments.Clear(); _sections.Clear(); + _namesData.Free(); return S_OK; } STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { - *numItems = _sections.Size(); + *numItems = _segments.Size() + _sections.Size(); return S_OK; } @@ -470,15 +887,20 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) - numItems = _sections.Size(); + numItems = _segments.Size() + _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; + { + UInt32 index = allFilesMode ? i : indices[i]; + totalSize += (index < _segments.Size()) ? + _segments[index].Size : + _sections[index - _segments.Size()].GetSize(); + } extractCallback->SetTotal(totalSize); UInt64 currentTotalSize = 0; @@ -503,8 +925,19 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, NExtract::NAskMode::kTest : NExtract::NAskMode::kExtract; UInt32 index = allFilesMode ? i : indices[i]; - const CSegment &item = _sections[index]; - currentItemSize = item.PSize; + UInt64 offset; + if (index < _segments.Size()) + { + const CSegment &item = _segments[index]; + currentItemSize = item.Size; + offset = item.Offset; + } + else + { + const CSection &item = _sections[index - _segments.Size()]; + currentItemSize = item.GetSize(); + offset = item.Offset; + } CMyComPtr outStream; RINOK(extractCallback->GetStream(index, &outStream, askMode)); @@ -512,7 +945,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, continue; RINOK(extractCallback->PrepareOperation(askMode)); - RINOK(_inStream->Seek(item.Offset, STREAM_SEEK_SET, NULL)); + RINOK(_inStream->Seek(offset, STREAM_SEEK_SET, NULL)); streamSpec->Init(currentItemSize); RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); outStream.Release(); @@ -524,10 +957,20 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_END } -static IInArchive *CreateArc() { return new CHandler; } +STDMETHODIMP CHandler::AllowTail(Int32 allowTail) +{ + _allowTail = IntToBool(allowTail); + return S_OK; +} + +IMP_CreateArcIn static CArcInfo g_ArcInfo = - { L"ELF", L"", 0, 0xDE, { 0 }, 0, false, CreateArc, 0 }; + { "ELF", "elf", 0, 0xDE, + 4, { 0x7F, 'E', 'L', 'F' }, + 0, + NArcInfoFlags::kPreArc, + CreateArc }; REGISTER_ARC(Elf) diff --git a/CPP/7zip/Archive/FatHandler.cpp b/CPP/7zip/Archive/FatHandler.cpp old mode 100755 new mode 100644 index 1c374a44..51064a1a --- a/CPP/7zip/Archive/FatHandler.cpp +++ b/CPP/7zip/Archive/FatHandler.cpp @@ -6,14 +6,14 @@ #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 "../../Common/ComTry.h" +#include "../../Common/IntToString.h" +#include "../../Common/MyBuffer.h" +#include "../../Common/MyCom.h" +#include "../../Common/StringConvert.h" -#include "Windows/PropVariant.h" -#include "Windows/Time.h" +#include "../../Windows/PropVariant.h" +#include "../../Windows/TimeUtils.h" #include "../Common/LimitedStreams.h" #include "../Common/ProgressUtils.h" @@ -109,6 +109,16 @@ static int GetLog(UInt32 num) return -1; } +static const UInt32 kHeaderSize = 512; + +API_FUNC_static_IsArc IsArc_Fat(const Byte *p, size_t size) +{ + if (size < kHeaderSize) + return k_IsArc_Res_NEED_MORE; + CHeader h; + return h.Parse(p) ? k_IsArc_Res_YES : k_IsArc_Res_NO; +} + bool CHeader::Parse(const Byte *p) { if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA) @@ -130,7 +140,7 @@ bool CHeader::Parse(const Byte *p) if (s < 0) return false; SectorsPerClusterLog = (Byte)s; - ClusterSizeLog = SectorSizeLog + SectorsPerClusterLog; + ClusterSizeLog = (Byte)(SectorSizeLog + SectorsPerClusterLog); } NumReservedSectors = Get16(p + 14); @@ -151,7 +161,8 @@ bool CHeader::Parse(const Byte *p) } else { - if (codeOffset < 62) + // Some FAT12s don't contain VolFields + if (codeOffset < 62 - 24) return false; NumFatBits = 0; UInt32 mask = (1 << (SectorSizeLog - 5)) - 1; @@ -174,6 +185,7 @@ bool CHeader::Parse(const Byte *p) // memcpy(OemName, p + 3, 5); + int curOffset = 36; p += 36; if (IsFat32()) { @@ -192,13 +204,23 @@ bool CHeader::Parse(const Byte *p) if (p[i] != 0) return false; p += 28; + curOffset += 28; } // DriveNumber = p[0]; - VolFieldsDefined = (p[2] == 0x29); // ExtendedBootSig - VolId = Get32(p + 3); - // memcpy(VolName, p + 7, 11); - // memcpy(FileSys, p + 18, 8); + VolFieldsDefined = false; + if (codeOffset >= curOffset + 3) + { + VolFieldsDefined = (p[2] == 0x29); // ExtendedBootSig + if (VolFieldsDefined) + { + if (codeOffset < curOffset + 26) + return false; + VolId = Get32(p + 3); + // memcpy(VolName, p + 7, 11); + // memcpy(FileSys, p + 18, 8); + } + } if (NumFatSectors == 0) return false; @@ -214,7 +236,7 @@ bool CHeader::Parse(const Byte *p) { if (NumFatBits == 32) return false; - NumFatBits = (numClusters < 0xFF5) ? 12: 16; + NumFatBits = (Byte)(numClusters < 0xFF5 ? 12 : 16); BadCluster &= ((1 << NumFatBits) - 1); } else if (NumFatBits != 32) @@ -258,7 +280,7 @@ static int CopyAndTrim(char *dest, const char *src, int size, bool toLower) { char c = dest[i]; if (c >= 'A' && c <= 'Z') - dest[i] = c + 0x20; + dest[i] = (char)(c + 0x20); } for (i = size - 1; i >= 0 && dest[i] == ' '; i--); return i + 1; @@ -313,6 +335,8 @@ struct CDatabase CByteBuffer ByteBuf; UInt64 NumCurUsedBytes; + UInt64 PhySize; + CDatabase(): Fat(0) {} ~CDatabase() { ClearAndClose(); } @@ -340,6 +364,7 @@ HRESULT CDatabase::SeekToSector(UInt32 sector) void CDatabase::Clear() { + PhySize = 0; VolItemDefined = false; NumDirClusters = 0; NumCurUsedBytes = 0; @@ -386,7 +411,11 @@ UString CDatabase::GetItemPath(Int32 index) const if (index < 0) return name; item = &Items[index]; - name = item->GetName() + WCHAR_PATH_SEPARATOR + name; + name.InsertAtFront(WCHAR_PATH_SEPARATOR); + if (item->UName.IsEmpty()) + name.Insert(0, item->GetShortName()); + else + name.Insert(0, item->UName); } } @@ -417,7 +446,7 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level) RINOK(SeekToSector(Header.RootDirSector)); } - ByteBuf.SetCapacity(blockSize); + ByteBuf.Alloc(blockSize); UString curName; int checkSum = -1; int numLongRecords = -1; @@ -516,7 +545,7 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level) { Byte sum = 0; for (int i = 0; i < 11; i++) - sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + (Byte)item.DosName[i]; + sum = (Byte)(((sum & 1) ? 0x80 : 0) + (sum >> 1) + (Byte)item.DosName[i]); if (sum == checkSum) item.UName = curName; } @@ -578,7 +607,6 @@ 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)) @@ -618,7 +646,7 @@ HRESULT CDatabase::Open() if (Header.NumFatBits == 32) { const UInt32 kBufSize = (1 << 15); - byteBuf.SetCapacity(kBufSize); + byteBuf.Alloc(kBufSize); for (UInt32 i = 0; i < Header.FatSize;) { UInt32 size = Header.FatSize - i; @@ -656,7 +684,7 @@ HRESULT CDatabase::Open() { const UInt32 kBufSize = (UInt32)Header.CalcFatSizeInSectors() << Header.SectorSizeLog; NumCurUsedBytes += kBufSize; - byteBuf.SetCapacity(kBufSize); + byteBuf.Alloc(kBufSize); Byte *p = byteBuf; RINOK(ReadStream_FALSE(InStream, p, kBufSize)); UInt32 fatSize = Header.FatSize; @@ -682,7 +710,10 @@ HRESULT CDatabase::Open() if ((Fat[0] & 0xFF) != Header.MediaType) return S_FALSE; - return ReadDir(-1, Header.RootCluster, 0); + RINOK(ReadDir(-1, Header.RootCluster, 0)); + + PhySize = Header.GetPhySize(); + return S_OK; } class CHandler: @@ -710,7 +741,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) streamSpec->Size = item.Size; UInt32 numClusters = Header.GetNumClusters(item.Size); - streamSpec->Vector.Reserve(numClusters); + streamSpec->Vector.ClearAndReserve(numClusters); UInt32 cluster = item.Cluster; UInt32 size = item.Size; @@ -726,7 +757,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) { if (!Header.IsValidCluster(cluster)) return S_FALSE; - streamSpec->Vector.Add(cluster - 2); + streamSpec->Vector.AddInReserved(cluster - 2); cluster = Fat[cluster]; if (size <= clusterSize) break; @@ -740,17 +771,17 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) COM_TRY_END } -STATPROPSTG kProps[] = +static const Byte 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} + kpidPath, + kpidIsDir, + kpidSize, + kpidPackSize, + kpidMTime, + kpidCTime, + kpidATime, + kpidAttrib, + kpidShortName }; enum @@ -761,11 +792,10 @@ enum // kpidFileSysType }; -STATPROPSTG kArcProps[] = +static const 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}, @@ -819,16 +849,20 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { case kpidFileSystem: { - wchar_t s[32] = { L'F', L'A', L'T' }; + char s[16]; + s[0] = 'F'; + s[1] = 'A'; + s[2] = 'T'; ConvertUInt32ToString(Header.NumFatBits, s + 3); prop = s; break; } case kpidClusterSize: prop = Header.ClusterSize(); break; - case kpidPhySize: prop = Header.GetPhySize(); break; + case kpidPhySize: prop = PhySize; 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 kpidShortComment: 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; @@ -901,7 +935,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = Items.Size(); if (numItems == 0) @@ -986,10 +1020,14 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) return S_OK; } -static IInArchive *CreateArc() { return new CHandler; } +IMP_CreateArcIn static CArcInfo g_ArcInfo = - { L"FAT", L"fat img", 0, 0xDA, { 0x55, 0xAA }, 2, false, CreateArc, 0 }; + { "FAT", "fat img", 0, 0xDA, + 2, { 0x55, 0xAA }, + 0x1FE, + 0, + CreateArc, NULL, IsArc_Fat }; REGISTER_ARC(Fat) diff --git a/CPP/7zip/Archive/FlvHandler.cpp b/CPP/7zip/Archive/FlvHandler.cpp old mode 100755 new mode 100644 index a22c29e3..3bb4620b --- a/CPP/7zip/Archive/FlvHandler.cpp +++ b/CPP/7zip/Archive/FlvHandler.cpp @@ -4,13 +4,13 @@ #include "../../../C/CpuArch.h" -#include "Common/Buffer.h" -#include "Common/ComTry.h" -// #include "Common/Defs.h" -#include "Common/MyString.h" +#include "../../Common/ComTry.h" +#include "../../Common/MyBuffer.h" +#include "../../Common/MyString.h" -#include "Windows/PropVariant.h" +#include "../../Windows/PropVariant.h" +#include "../Common/InBuffer.h" #include "../Common/ProgressUtils.h" #include "../Common/RegisterArc.h" #include "../Common/StreamObjects.h" @@ -29,9 +29,9 @@ namespace NArchive { namespace NFlv { static const UInt32 kFileSizeMax = (UInt32)1 << 30; -static const int kNumChunksMax = (UInt32)1 << 23; +static const UInt32 kNumChunksMax = (UInt32)1 << 23; -const UInt32 kTagHeaderSize = 11; +static const UInt32 kTagHeaderSize = 11; static const Byte kFlag_Video = 1; static const Byte kFlag_Audio = 4; @@ -39,13 +39,11 @@ 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; +static const unsigned kNumTypes = 19; struct CItem { - UInt32 Offset; - UInt32 Size; - // UInt32 Time; + CByteBuffer Data; Byte Type; }; @@ -55,7 +53,7 @@ struct CItem2 Byte SubType; Byte Props; bool SameSubTypes; - int NumChunks; + unsigned NumChunks; size_t Size; CReferenceBuf *BufSpec; @@ -69,10 +67,12 @@ class CHandler: public IInArchiveGetStream, public CMyUnknownImp { - int _isRaw; CMyComPtr _stream; CObjectVector _items2; // CByteBuffer _metadata; + bool _isRaw; + UInt64 _phySize; + HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); AString GetComment(); public: @@ -81,76 +81,64 @@ public: STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); }; -STATPROPSTG kProps[] = +static const Byte kProps[] = { - { NULL, kpidSize, VT_UI8}, - { NULL, kpidNumBlocks, VT_UI4}, - { NULL, kpidComment, VT_BSTR} + kpidSize, + kpidNumBlocks, + kpidComment }; -/* -STATPROPSTG kArcProps[] = -{ - { NULL, kpidComment, VT_BSTR} -}; -*/ - IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO +IMP_IInArchive_ArcProps_NO_Table static const char *g_AudioTypes[16] = { - "pcm", - "adpcm", - "mp3", - "pcm_le", - "nellymoser16", - "nellymoser8", - "nellymoser", - "g711a", - "g711m", - "audio9", - "aac", - "speex", - "audio12", - "audio13", - "mp3", - "audio15" + "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" + "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" + "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; @@ -170,13 +158,13 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidComment: { char sz[64]; - MyStringCopy(sz, (item.IsAudio() ? g_AudioTypes[item.SubType] : g_VideoTypes[item.SubType]) ); + char *s = MyStpCpy(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"); + *s++ = ' '; + s = MyStpCpy(s, g_Rates[(item.Props >> 2) & 3]); + s = MyStpCpy(s, (item.Props & 2) ? " 16-bit" : " 8-bit"); + s = MyStpCpy(s, (item.Props & 1) ? " stereo" : " mono"); } prop = sz; break; @@ -190,7 +178,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val AString CHandler::GetComment() { const Byte *p = _metadata; - size_t size = _metadata.GetCapacity(); + size_t size = _metadata.Size(); AString res; if (size > 0) { @@ -264,24 +252,25 @@ AString CHandler::GetComment() return res; } +*/ + STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { - COM_TRY_BEGIN + // COM_TRY_BEGIN NWindows::NCOM::CPropVariant prop; switch(propID) { - case kpidComment: prop = GetComment(); break; + // case kpidComment: prop = GetComment(); break; + case kpidPhySize: prop = (UInt64)_phySize; break; + case kpidIsNotArcType: prop = true; break; } prop.Detach(value); return S_OK; - COM_TRY_END + // 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)); @@ -291,69 +280,51 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) header[3] != 1 || (header[4] & 0xFA) != 0) return S_FALSE; - UInt32 offset = Get32(header + 5); + UInt64 offset = Get32(header + 5); if (offset != 9 || Get32(header + 9) != 0) return S_FALSE; - offset += 4; + offset = kHeaderSize; - 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; - } - } + CInBuffer inBuf; + if (!inBuf.Create(1 << 15)) + return E_OUTOFMEMORY; + inBuf.SetStream(stream); + CObjectVector items; int lasts[kNumTypes]; - int i; + unsigned i; for (i = 0; i < kNumTypes; i++) lasts[i] = -1; - while (offset < fileSize) + _phySize = offset; + for (;;) { + Byte buf[kTagHeaderSize]; CItem item; - item.Offset = offset; - const Byte *buf = inBuf + offset; - offset += kTagHeaderSize; - if (offset > fileSize) - return S_FALSE; - + if (inBuf.ReadBytes(buf, kTagHeaderSize) != kTagHeaderSize) + break; item.Type = buf[0]; UInt32 size = Get24(buf + 1); if (size < 1) - return S_FALSE; + break; // item.Time = Get24(buf + 4); // item.Time |= (UInt32)buf[7] << 24; if (Get24(buf + 8) != 0) // streamID - return S_FALSE; + break; 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; + item.Data.Alloc(curSize); + memcpy(item.Data, buf, kTagHeaderSize); + if (inBuf.ReadBytes(item.Data + kTagHeaderSize, size) != size) + break; + if (inBuf.ReadBytes(item.Data + kTagHeaderSize + size, 4) != 4) + break; + if (Get32(item.Data + kTagHeaderSize + size) != kTagHeaderSize + size) + break; + + offset += curSize; + // printf("\noffset = %6X type = %2d time = %6d size = %6d", (UInt32)offset, item.Type, item.Time, item.Size); if (item.Type == kType_Meta) @@ -363,20 +334,20 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) else { if (item.Type != kType_Audio && item.Type != kType_Video) - return S_FALSE; + break; 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; + subType = (Byte)(firstByte >> 4); + props = (Byte)(firstByte & 0xF); } else { - subType = firstByte & 0xF; - props = firstByte >> 4; + subType = (Byte)(firstByte & 0xF); + props = (Byte)(firstByte >> 4); } int last = lasts[item.Type]; if (last < 0) @@ -401,7 +372,14 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) } items.Add(item); } + _phySize = offset; + if (callback && (items.Size() & 0xFF) == 0) + { + RINOK(callback->SetCompleted(NULL, &offset)) + } } + if (items.IsEmpty()) + return S_FALSE; _isRaw = (_items2.Size() == 1); for (i = 0; i < _items2.Size(); i++) @@ -412,12 +390,12 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) { if (!item2.SameSubTypes) return S_FALSE; - itemBuf.SetCapacity((size_t)item2.Size - (kTagHeaderSize + 4 + 1) * item2.NumChunks); + itemBuf.Alloc((size_t)item2.Size - (size_t)(kTagHeaderSize + 4 + 1) * item2.NumChunks); item2.Size = 0; } else { - itemBuf.SetCapacity(kHeaderSize + (size_t)item2.Size); + itemBuf.Alloc(kHeaderSize + (size_t)item2.Size); memcpy(itemBuf, header, kHeaderSize); itemBuf[4] = item2.IsAudio() ? kFlag_Audio : kFlag_Video; item2.Size = kHeaderSize; @@ -428,8 +406,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) { const CItem &item = items[i]; CItem2 &item2 = _items2[lasts[item.Type]]; - size_t size = item.Size; - const Byte *src = inBuf + item.Offset; + size_t size = item.Data.Size(); + const Byte *src = item.Data; if (_isRaw) { src += kTagHeaderSize + 1; @@ -464,6 +442,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCal STDMETHODIMP CHandler::Close() { + _phySize = 0; _stream.Release(); _items2.Clear(); // _metadata.SetCapacity(0); @@ -480,7 +459,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _items2.Size(); if (numItems == 0) @@ -514,7 +493,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(extractCallback->PrepareOperation(askMode)); if (outStream) { - RINOK(WriteStream(outStream, item.BufSpec->Buf, item.BufSpec->Buf.GetCapacity())); + RINOK(WriteStream(outStream, item.BufSpec->Buf, item.BufSpec->Buf.Size())); } RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); } @@ -534,10 +513,14 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) COM_TRY_END } -static IInArchive *CreateArc() { return new CHandler; } +IMP_CreateArcIn static CArcInfo g_ArcInfo = - { L"FLV", L"flv", 0, 0xD6, { 'F', 'L', 'V' }, 3, false, CreateArc, 0 }; + { "FLV", "flv", 0, 0xD6, + 4, { 'F', 'L', 'V', 1, }, + 0, + 0, + CreateArc }; REGISTER_ARC(Flv) diff --git a/CPP/7zip/Archive/GzHandler.cpp b/CPP/7zip/Archive/GzHandler.cpp old mode 100755 new mode 100644 index ede6b01b..69b3c3be --- a/CPP/7zip/Archive/GzHandler.cpp +++ b/CPP/7zip/Archive/GzHandler.cpp @@ -2,13 +2,16 @@ #include "StdAfx.h" +// #include + #include "../../../C/CpuArch.h" -#include "Common/ComTry.h" -#include "Common/StringConvert.h" +#include "../../Common/ComTry.h" +#include "../../Common/Defs.h" +#include "../../Common/StringConvert.h" -#include "Windows/PropVariant.h" -#include "Windows/Time.h" +#include "../../Windows/PropVariant.h" +#include "../../Windows/TimeUtils.h" #include "../Common/ProgressUtils.h" #include "../Common/RegisterArc.h" @@ -26,13 +29,19 @@ using namespace NWindows; +using namespace NCompress; +using namespace NDeflate; + namespace NArchive { namespace NGz { -static const UInt16 kSignature = 0x8B1F; + static const Byte kSignature_0 = 0x1F; + static const Byte kSignature_1 = 0x8B; + static const Byte kSignature_2 = 8; // NCompressionMethod::kDeflate + + // Latest versions of gzip program don't write comment field to gz archive. + // We also don't write comment field to gz archive. -namespace NHeader -{ namespace NFlags { const Byte kIsText = 1 << 0; @@ -40,6 +49,7 @@ namespace NHeader const Byte kExtra = 1 << 2; const Byte kName = 1 << 3; const Byte kComment = 1 << 4; + const Byte kReserved = 0xE0; } namespace NExtraFlags @@ -48,11 +58,6 @@ namespace NHeader const Byte kFastest = 4; } - namespace NCompressionMethod - { - const Byte kDeflate = 8; - } - namespace NHostOS { enum EEnum @@ -79,30 +84,29 @@ namespace NHeader 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" + "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"; @@ -111,7 +115,6 @@ class CItem { bool TestFlag(Byte flag) const { return (Flags & flag) != 0; } public: - Byte Method; Byte Flags; Byte ExtraFlags; Byte HostOS; @@ -123,11 +126,12 @@ public: 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); } + // bool IsText() const { return TestFlag(NFlags::kIsText); } + bool HeaderCrcIsPresent() const { return TestFlag(NFlags::kCrc); } + bool ExtraFieldIsPresent() const { return TestFlag(NFlags::kExtra); } + bool NameIsPresent() const { return TestFlag(NFlags::kName); } + bool CommentIsPresent() const { return TestFlag(NFlags::kComment); } + bool IsSupported() const { return (Flags & NFlags::kReserved) == 0; } void Clear() { @@ -136,48 +140,48 @@ public: // Extra.SetCapacity(0); } - HRESULT ReadHeader(NCompress::NDeflate::NDecoder::CCOMCoder *stream); - HRESULT ReadFooter1(NCompress::NDeflate::NDecoder::CCOMCoder *stream); + HRESULT ReadHeader(NDecoder::CCOMCoder *stream); + HRESULT ReadFooter1(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) +static HRESULT ReadBytes(NDecoder::CCOMCoder *stream, Byte *data, UInt32 size) { for (UInt32 i = 0; i < size; i++) - data[i] = stream->ReadByte(); + data[i] = stream->ReadAlignedByte(); return stream->InputEofError() ? S_FALSE : S_OK; } -static HRESULT SkipBytes(NCompress::NDeflate::NDecoder::CCOMCoder *stream, UInt32 size) +static HRESULT SkipBytes(NDecoder::CCOMCoder *stream, UInt32 size) { for (UInt32 i = 0; i < size; i++) - stream->ReadByte(); + stream->ReadAlignedByte(); return stream->InputEofError() ? S_FALSE : S_OK; } -static HRESULT ReadUInt16(NCompress::NDeflate::NDecoder::CCOMCoder *stream, UInt16 &value /* , UInt32 &crc */) +static HRESULT ReadUInt16(NDecoder::CCOMCoder *stream, UInt32 &value /* , UInt32 &crc */) { value = 0; for (int i = 0; i < 2; i++) { - Byte b = stream->ReadByte(); + Byte b = stream->ReadAlignedByte(); if (stream->InputEofError()) return S_FALSE; // crc = CRC_UPDATE_BYTE(crc, b); - value |= (UInt16(b) << (8 * i)); + value |= ((UInt32)(b) << (8 * i)); } return S_OK; } -static HRESULT ReadString(NCompress::NDeflate::NDecoder::CCOMCoder *stream, AString &s, UInt32 limit /* , UInt32 &crc */) +static HRESULT ReadString(NDecoder::CCOMCoder *stream, AString &s, size_t limit /* , UInt32 &crc */) { s.Empty(); - for (UInt32 i = 0; i < limit; i++) + for (size_t i = 0; i < limit; i++) { - Byte b = stream->ReadByte(); + Byte b = stream->ReadAlignedByte(); if (stream->InputEofError()) return S_FALSE; // crc = CRC_UPDATE_BYTE(crc, b); @@ -188,7 +192,134 @@ static HRESULT ReadString(NCompress::NDeflate::NDecoder::CCOMCoder *stream, AStr return S_FALSE; } -HRESULT CItem::ReadHeader(NCompress::NDeflate::NDecoder::CCOMCoder *stream) +static UInt32 Is_Deflate(const Byte *p, size_t size) +{ + if (size < 1) + return k_IsArc_Res_NEED_MORE; + Byte b = *p; + p++; + size--; + unsigned type = ((unsigned)b >> 1) & 3; + if (type == 3) + return k_IsArc_Res_NO; + if (type == 0) + { + // Stored (uncompreessed data) + if ((b >> 3) != 0) + return k_IsArc_Res_NO; + if (size < 4) + return k_IsArc_Res_NEED_MORE; + if (GetUi16(p) != (UInt16)~GetUi16(p + 2)) + return k_IsArc_Res_NO; + } + else if (type == 2) + { + // Dynamic Huffman + if (size < 1) + return k_IsArc_Res_NEED_MORE; + if ((*p & 0x1F) + 1 > 30) // numDistLevels + return k_IsArc_Res_NO; + } + return k_IsArc_Res_YES; +} + +static unsigned kNameMaxLen = 1 << 12; +static unsigned kCommentMaxLen = 1 << 16; + +API_FUNC_static_IsArc IsArc_Gz(const Byte *p, size_t size) +{ + if (size < 10) + return k_IsArc_Res_NEED_MORE; + if (p[0] != kSignature_0 || + p[1] != kSignature_1 || + p[2] != kSignature_2) + return k_IsArc_Res_NO; + + Byte flags = p[3]; + if ((flags & NFlags::kReserved) != 0) + return k_IsArc_Res_NO; + + Byte extraFlags = p[8]; + // maybe that flag can have another values for some gz archives? + if (extraFlags != 0 && + extraFlags != NExtraFlags::kMaximum && + extraFlags != NExtraFlags::kFastest) + return k_IsArc_Res_NO; + + size -= 10; + p += 10; + + if ((flags & NFlags::kExtra) != 0) + { + if (size < 2) + return k_IsArc_Res_NEED_MORE; + unsigned xlen = GetUi16(p); + size -= 2; + p += 2; + while (xlen != 0) + { + if (xlen < 4) + return k_IsArc_Res_NO; + if (size < 4) + return k_IsArc_Res_NEED_MORE; + unsigned len = GetUi16(p + 2); + size -= 4; + xlen -= 4; + p += 4; + if (len > xlen) + return k_IsArc_Res_NO; + if (len > size) + return k_IsArc_Res_NEED_MORE; + size -= len; + xlen -= len; + p += len; + } + } + + if ((flags & NFlags::kName) != 0) + { + size_t limit = kNameMaxLen; + if (limit > size) + limit = size; + size_t i; + for (i = 0; i < limit && p[i] != 0; i++); + if (i == size) + return k_IsArc_Res_NEED_MORE; + if (i == limit) + return k_IsArc_Res_NO; + i++; + p += i; + size -= i; + } + + if ((flags & NFlags::kComment) != 0) + { + size_t limit = kCommentMaxLen; + if (limit > size) + limit = size; + size_t i; + for (i = 0; i < limit && p[i] != 0; i++); + if (i == size) + return k_IsArc_Res_NEED_MORE; + if (i == limit) + return k_IsArc_Res_NO; + i++; + p += i; + size -= i; + } + + if ((flags & NFlags::kCrc) != 0) + { + if (size < 2) + return k_IsArc_Res_NEED_MORE; + p += 2; + size -= 2; + } + + return Is_Deflate(p, size); +} + +HRESULT CItem::ReadHeader(NDecoder::CCOMCoder *stream) { Clear(); @@ -198,15 +329,15 @@ HRESULT CItem::ReadHeader(NCompress::NDeflate::NDecoder::CCOMCoder *stream) RINOK(ReadBytes(stream, buf, 10)); - if (GetUi16(buf) != kSignature) + if (buf[0] != kSignature_0 || + buf[1] != kSignature_1 || + buf[2] != kSignature_2) return S_FALSE; - Method = buf[2]; - - if (Method != NHeader::NCompressionMethod::kDeflate) + Flags = buf[3]; + if (!IsSupported()) return S_FALSE; - Flags = buf[3]; Time = Get32(buf + 4); ExtraFlags = buf[8]; HostOS = buf[9]; @@ -215,21 +346,21 @@ HRESULT CItem::ReadHeader(NCompress::NDeflate::NDecoder::CCOMCoder *stream) 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); + UInt32 xlen; + RINOK(ReadUInt16(stream, xlen /* , crc */)); + RINOK(SkipBytes(stream, xlen)); + // Extra.SetCapacity(xlen); + // RINOK(ReadStream_FALSE(stream, Extra, xlen)); + // crc = CrcUpdate(crc, Extra, xlen); } if (NameIsPresent()) - RINOK(ReadString(stream, Name, (1 << 10) /* , crc */)); + RINOK(ReadString(stream, Name, kNameMaxLen /* , crc */)); if (CommentIsPresent()) - RINOK(ReadString(stream, Comment, (1 << 16) /* , crc */)); + RINOK(ReadString(stream, Comment, kCommentMaxLen /* , crc */)); if (HeaderCrcIsPresent()) { - UInt16 headerCRC; + UInt32 headerCRC; // UInt32 dummy = 0; RINOK(ReadUInt16(stream, headerCRC /* , dummy */)); /* @@ -240,7 +371,7 @@ HRESULT CItem::ReadHeader(NCompress::NDeflate::NDecoder::CCOMCoder *stream) return stream->InputEofError() ? S_FALSE : S_OK; } -HRESULT CItem::ReadFooter1(NCompress::NDeflate::NDecoder::CCOMCoder *stream) +HRESULT CItem::ReadFooter1(NDecoder::CCOMCoder *stream) { Byte buf[8]; RINOK(ReadBytes(stream, buf, 8)); @@ -261,10 +392,11 @@ HRESULT CItem::ReadFooter2(ISequentialInStream *stream) 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; + buf[0] = kSignature_0; + buf[1] = kSignature_1; + buf[2] = kSignature_2; + buf[3] = (Byte)(Flags & NFlags::kName); + // buf[3] |= NFlags::kCrc; SetUi32(buf + 4, Time); buf[8] = ExtraFlags; buf[9] = HostOS; @@ -272,8 +404,8 @@ HRESULT CItem::WriteHeader(ISequentialOutStream *stream) // 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)); + // crc = CrcUpdate(crc, (const char *)Name, Name.Len() + 1); + RINOK(WriteStream(stream, (const char *)Name, Name.Len() + 1)); } // SetUi16(buf, (UInt16)CRC_GET_DIGEST(crc)); // RINOK(WriteStream(stream, buf, 2)); @@ -296,54 +428,93 @@ class CHandler: public CMyUnknownImp { CItem _item; - UInt64 _startPosition; - UInt64 _headerSize; + + bool _isArc; + bool _needSeekToStart; + bool _dataAfterEnd; + bool _needMoreInput; + + bool _packSize_Defined; + bool _unpackSize_Defined; + bool _numStreams_Defined; + UInt64 _packSize; - bool _packSizeDefined; + UInt64 _unpackSize; // real unpack size (NOT from footer) + UInt64 _numStreams; + UInt64 _headerSize; // only start header (without footer) + CMyComPtr _stream; CMyComPtr _decoder; - NCompress::NDeflate::NDecoder::CCOMCoder *_decoderSpec; + NDecoder::CCOMCoder *_decoderSpec; CSingleMethodProps _props; public: - MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties) + 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); + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); CHandler() { - _decoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder; + _decoderSpec = new NDecoder::CCOMCoder; _decoder = _decoderSpec; } }; -static STATPROPSTG const kProps[] = +static const Byte 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} -} -; + kpidPath, + kpidSize, + kpidPackSize, + kpidMTime, + kpidHostOS, + kpidCRC + // kpidComment +}; + +static const Byte kArcProps[] = +{ + kpidHeadersSize, + kpidNumStreams +}; + IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO_Table +IMP_IInArchive_ArcProps STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { + COM_TRY_BEGIN NCOM::CPropVariant prop; - switch(propID) + switch (propID) { - case kpidPhySize: if (_packSizeDefined) prop = _packSize; break; + case kpidPhySize: if (_packSize_Defined) prop = _packSize; break; + case kpidUnpackSize: if (_unpackSize_Defined) prop = _unpackSize; break; + case kpidNumStreams: if (_numStreams_Defined) prop = _numStreams; break; + case kpidHeadersSize: if (_headerSize != 0) prop = _headerSize; break; + case kpidErrorFlags: + { + UInt32 v = 0; + if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;; + if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd; + if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd; + prop = v; + break; + } + case kpidName: + if (_item.NameIsPresent()) + prop = MultiByteToUnicodeString(_item.Name, CP_ACP) + L".gz"; + break; } prop.Detach(value); return S_OK; + COM_TRY_END } @@ -353,11 +524,11 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) return S_OK; } -STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; - switch(propID) + NCOM::CPropVariant prop; + switch (propID) { case kpidPath: if (_item.NameIsPresent()) @@ -365,7 +536,6 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIA break; // case kpidComment: if (_item.CommentIsPresent()) prop = MultiByteToUnicodeString(_item.Comment, CP_ACP); break; case kpidMTime: - { if (_item.Time != 0) { FILETIME utc; @@ -373,10 +543,21 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIA prop = utc; } break; + case kpidSize: + { + if (_unpackSize_Defined) + prop = _unpackSize; + else if (_stream) + prop = (UInt64)_item.Size32; + 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])) ? + case kpidPackSize: + { + if (_packSize_Defined || _stream) + prop = _packSize; + break; + } + case kpidHostOS: prop = (_item.HostOS < ARRAY_SIZE(kHostOSes)) ? kHostOSes[_item.HostOS] : kUnknownOS; break; case kpidCRC: if (_stream) prop = _item.Crc; break; } @@ -385,56 +566,81 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIA COM_TRY_END } -STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *) +class CCompressProgressInfoImp: + public ICompressProgressInfo, + public CMyUnknownImp { - COM_TRY_BEGIN - HRESULT res; - try + CMyComPtr Callback; +public: + UInt64 Offset; + MY_UNKNOWN_IMP1(ICompressProgressInfo) + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); + void Init(IArchiveOpenCallback *callback) { Callback = callback; } +}; + +STDMETHODIMP CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */) +{ + if (Callback) { - 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; - } - } + UInt64 files = 0; + UInt64 value = Offset + *inSize; + return Callback->SetCompleted(&files, &value); } - catch(...) { res = S_FALSE; } - if (res != S_OK) - Close(); - return res; + return S_OK; +} + +/* +*/ + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *) +{ + COM_TRY_BEGIN + RINOK(OpenSeq(stream)); + _isArc = false; + UInt64 endPos; + RINOK(stream->Seek(-8, STREAM_SEEK_END, &endPos)); + _packSize = endPos + 8; + RINOK(_item.ReadFooter2(stream)); + _stream = stream; + _isArc = true; + _needSeekToStart = true; + return S_OK; 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); + RINOK(_item.ReadHeader(_decoderSpec)); + if (_decoderSpec->InputEofError()) + return S_FALSE; _headerSize = _decoderSpec->GetInputProcessedSize(); + _isArc = true; + return S_OK; } - catch(...) { res = S_FALSE; } - if (res != S_OK) - Close(); - return res; + catch(const CInBufferException &e) { return e.ErrorCode; } COM_TRY_END } STDMETHODIMP CHandler::Close() { - _packSizeDefined = false; + _isArc = false; + _needSeekToStart = false; + _dataAfterEnd = false; + _needMoreInput = false; + + _packSize_Defined = false; + _unpackSize_Defined = false; + _numStreams_Defined = false; + + _packSize = 0; + _headerSize = 0; + _stream.Release(); _decoderSpec->ReleaseInStream(); return S_OK; @@ -446,13 +652,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_BEGIN if (numItems == 0) return S_OK; - if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0)) + if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) return E_INVALIDARG; - if (_stream) - extractCallback->SetTotal(_packSize); - UInt64 currentTotalPacked = 0; - RINOK(extractCallback->SetCompleted(¤tTotalPacked)); + // if (_stream) extractCallback->SetTotal(_packSize); + // UInt64 currentTotalPacked = 0; + // RINOK(extractCallback->SetCompleted(¤tTotalPacked)); CMyComPtr realOutStream; Int32 askMode = testMode ? NExtract::NAskMode::kTest : @@ -473,71 +678,166 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CMyComPtr progress = lps; lps->Init(extractCallback, true); - if (_stream) + bool needReadFirstItem = _needSeekToStart; + + if (_needSeekToStart) { - RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); + if (!_stream) + return E_FAIL; + RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL)); _decoderSpec->InitInStream(true); + // printf("\nSeek"); } + else + _needSeekToStart = true; + bool firstItem = true; - Int32 opRes; + + UInt64 packSize = _decoderSpec->GetInputProcessedSize(); + // printf("\npackSize = %d", (unsigned)packSize); + + UInt64 unpackedSize = 0; + UInt64 numStreams = 0; + + bool crcError = false; + + HRESULT result = S_OK; + + try { + for (;;) { - lps->InSize = _packSize = _decoderSpec->GetInputProcessedSize(); - _packSizeDefined = true; - lps->OutSize = outStreamSpec->GetSize(); + lps->InSize = packSize; + lps->OutSize = unpackedSize; + RINOK(lps->SetCur()); CItem item; - if (!firstItem || _stream) + + if (!firstItem || needReadFirstItem) { - HRESULT result = item.ReadHeader(_decoderSpec); + result = item.ReadHeader(_decoderSpec); + + if (result != S_OK && result != S_FALSE) + return result; + + if (_decoderSpec->InputEofError()) + result = S_FALSE; + + if (result != S_OK && firstItem) + { + _isArc = false; + break; + } + + if (packSize == _decoderSpec->GetStreamSize()) + { + result = S_OK; + break; + } + if (result != S_OK) { - if (result != S_FALSE) - return result; - opRes = firstItem ? - NExtract::NOperationResult::kDataError : - NExtract::NOperationResult::kOK; + _dataAfterEnd = true; break; } } + + numStreams++; firstItem = false; UInt64 startOffset = outStreamSpec->GetSize(); outStreamSpec->InitCRC(); - HRESULT result = _decoderSpec->CodeResume(outStream, NULL, progress); - if (result != S_OK) + result = _decoderSpec->CodeResume(outStream, NULL, progress); + + packSize = _decoderSpec->GetInputProcessedSize(); + unpackedSize = outStreamSpec->GetSize(); + + if (result != S_OK && result != S_FALSE) + return result; + + if (_decoderSpec->InputEofError()) { - if (result != S_FALSE) - return result; - opRes = NExtract::NOperationResult::kDataError; - break; + packSize = _decoderSpec->GetStreamSize(); + _needMoreInput = true; + result = S_FALSE; } + if (result != S_OK) + break; + _decoderSpec->AlignToByte(); - if (item.ReadFooter1(_decoderSpec) != S_OK) + + result = item.ReadFooter1(_decoderSpec); + + packSize = _decoderSpec->GetInputProcessedSize(); + + if (result != S_OK && result != S_FALSE) + return result; + + if (result != S_OK) { - opRes = NExtract::NOperationResult::kDataError; + if (_decoderSpec->InputEofError()) + { + _needMoreInput = true; + result = S_FALSE; + } break; } + if (item.Crc != outStreamSpec->GetCRC() || - item.Size32 != (UInt32)(outStreamSpec->GetSize() - startOffset)) + item.Size32 != (UInt32)(unpackedSize - startOffset)) { - opRes = NExtract::NOperationResult::kCRCError; + crcError = true; + result = S_FALSE; break; } } + + } catch(const CInBufferException &e) { return e.ErrorCode; } + + if (!firstItem) + { + _packSize = packSize; + _unpackSize = unpackedSize; + _numStreams = numStreams; + + _packSize_Defined = true; + _unpackSize_Defined = true; + _numStreams_Defined = true; + } + outStream.Release(); - return extractCallback->SetOperationResult(opRes); + + Int32 retResult = NExtract::NOperationResult::kDataError; + + if (!_isArc) + retResult = NExtract::NOperationResult::kIsNotArc; + else if (_needMoreInput) + retResult = NExtract::NOperationResult::kUnexpectedEnd; + else if (crcError) + retResult = NExtract::NOperationResult::kCRCError; + else if (_dataAfterEnd) + retResult = NExtract::NOperationResult::kDataAfterEnd; + else if (result == S_FALSE) + retResult = NExtract::NOperationResult::kDataError; + else if (result == S_OK) + retResult = NExtract::NOperationResult::kOK; + else + return result; + + return extractCallback->SetOperationResult(retResult); + + COM_TRY_END } static const Byte kHostOS = #ifdef _WIN32 - NHeader::NHostOS::kFAT; + NHostOS::kFAT; #else - NHeader::NHostOS::kUnix; + NHostOS::kUnix; #endif static HRESULT UpdateArchive( @@ -565,16 +865,15 @@ static HRESULT UpdateArchive( lps->Init(updateCallback, true); CItem item = newItem; - item.Method = NHeader::NCompressionMethod::kDeflate; item.ExtraFlags = props.GetLevel() >= 7 ? - NHeader::NExtraFlags::kMaximum : - NHeader::NExtraFlags::kFastest; + NExtraFlags::kMaximum : + NExtraFlags::kFastest; item.HostOS = kHostOS; RINOK(item.WriteHeader(outStream)); - NCompress::NDeflate::NEncoder::CCOMCoder *deflateEncoderSpec = new NCompress::NDeflate::NEncoder::CCOMCoder; + NEncoder::CCOMCoder *deflateEncoderSpec = new NEncoder::CCOMCoder; CMyComPtr deflateEncoder = deflateEncoderSpec; RINOK(props.SetCoderProps(deflateEncoderSpec, NULL)); RINOK(deflateEncoder->Code(crcStream, outStream, NULL, NULL, progress)); @@ -582,7 +881,7 @@ static HRESULT UpdateArchive( item.Crc = inStreamSpec->GetCRC(); item.Size32 = (UInt32)inStreamSpec->GetSize(); RINOK(item.WriteFooter(outStream)); - return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); + return updateCallback->SetOperationResult(NUpdate::NOperationResult::kOK); } STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) @@ -609,13 +908,14 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (IntToBool(newProps)) { { - FILETIME utcTime; NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(0, kpidMTime, &prop)); - if (prop.vt != VT_FILETIME) + if (prop.vt == VT_FILETIME) + NTime::FileTimeToUnixTime(prop.filetime, newItem.Time); + else if (prop.vt == VT_EMPTY) + newItem.Time = 0; + else return E_INVALIDARG; - utcTime = prop.filetime; - NTime::FileTimeToUnixTime(utcTime, newItem.Time); } { NCOM::CPropVariant prop; @@ -623,12 +923,12 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (prop.vt == VT_BSTR) { UString name = prop.bstrVal; - int dirDelimiterPos = name.ReverseFind(CHAR_PATH_SEPARATOR); + int dirDelimiterPos = name.ReverseFind(WCHAR_PATH_SEPARATOR); if (dirDelimiterPos >= 0) - name = name.Mid(dirDelimiterPos + 1); + name = name.Ptr(dirDelimiterPos + 1); newItem.Name = UnicodeStringToMultiByte(name, CP_ACP); if (!newItem.Name.IsEmpty()) - newItem.Flags |= NHeader::NFlags::kName; + newItem.Flags |= NFlags::kName; } else if (prop.vt != VT_EMPTY) return E_INVALIDARG; @@ -665,7 +965,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (!_stream) return E_NOTIMPL; - UInt64 offset = _startPosition; + UInt64 offset = 0; if (IntToBool(newProps)) { newItem.WriteHeader(outStream); @@ -675,20 +975,20 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt return NCompress::CopyStream(_stream, outStream, NULL); } -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) { return _props.SetProperties(names, values, numProps); } -static IInArchive *CreateArc() { return new CHandler; } -#ifndef EXTRACT_ONLY -static IOutArchive *CreateArcOut() { return new CHandler; } -#else -#define CreateArcOut 0 -#endif +IMP_CreateArcIn +IMP_CreateArcOut static CArcInfo g_ArcInfo = - { L"gzip", L"gz gzip tgz tpz", L"* * .tar .tar", 0xEF, { 0x1F, 0x8B, 8 }, 3, true, CreateArc, CreateArcOut }; + { "gzip", "gz gzip tgz tpz", "* * .tar .tar", 0xEF, + 3, { kSignature_0, kSignature_1, kSignature_2 }, + 0, + NArcInfoFlags::kKeepName, + REF_CreateArc_Pair, IsArc_Gz }; REGISTER_ARC(GZip) diff --git a/CPP/7zip/Archive/Hfs/HfsHandler.cpp b/CPP/7zip/Archive/Hfs/HfsHandler.cpp deleted file mode 100755 index f226458d..00000000 --- a/CPP/7zip/Archive/Hfs/HfsHandler.cpp +++ /dev/null @@ -1,243 +0,0 @@ -// 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 deleted file mode 100755 index 269af218..00000000 --- a/CPP/7zip/Archive/Hfs/HfsHandler.h +++ /dev/null @@ -1,26 +0,0 @@ -// 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 deleted file mode 100755 index 8391dd93..00000000 --- a/CPP/7zip/Archive/Hfs/HfsIn.cpp +++ /dev/null @@ -1,480 +0,0 @@ -// 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 deleted file mode 100755 index c1953905..00000000 --- a/CPP/7zip/Archive/Hfs/HfsIn.h +++ /dev/null @@ -1,154 +0,0 @@ -// 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 deleted file mode 100755 index 51c3c2b1..00000000 --- a/CPP/7zip/Archive/Hfs/HfsRegister.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// 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/HfsHandler.cpp b/CPP/7zip/Archive/HfsHandler.cpp new file mode 100644 index 00000000..ca1370d8 --- /dev/null +++ b/CPP/7zip/Archive/HfsHandler.cpp @@ -0,0 +1,1874 @@ +// HfsHandler.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/RegisterArc.h" +#include "../Common/StreamObjects.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/ZlibDecoder.h" + +/* if HFS_SHOW_ALT_STREAMS is defined, the handler will show attribute files + and resource forks. In most cases it looks useless. So we disable it. */ + +// #define HFS_SHOW_ALT_STREAMS + +#define Get16(p) GetBe16(p) +#define Get32(p) GetBe32(p) +#define Get64(p) GetBe64(p) + +namespace NArchive { +namespace NHfs { + +static const wchar_t *kResFileName = L"rsrc"; // L"com.apple.ResourceFork"; + +struct CExtent +{ + UInt32 Pos; + UInt32 NumBlocks; +}; + +struct CIdExtents +{ + UInt32 ID; + UInt32 StartBlock; + CRecordVector Extents; +}; + +struct CFork +{ + UInt64 Size; + UInt32 NumBlocks; + // UInt32 ClumpSize; + CRecordVector Extents; + + CFork(): Size(0), NumBlocks(0) {} + + void Parse(const Byte *p); + + bool IsEmpty() const { return Size == 0 && NumBlocks == 0 && Extents.Size() == 0; } + + UInt32 Calc_NumBlocks_from_Extents() const; + bool Check_NumBlocks() const; + + bool Check_Size_with_NumBlocks(unsigned blockSizeLog) const + { + return Size <= ((UInt64)NumBlocks << blockSizeLog); + } + + bool IsOk(unsigned blockSizeLog) const + { + // we don't check cases with extra (empty) blocks in last extent + return Check_NumBlocks() && Check_Size_with_NumBlocks(blockSizeLog); + } + + bool Upgrade(const CObjectVector &items, UInt32 id); + bool UpgradeAndTest(const CObjectVector &items, UInt32 id, unsigned blockSizeLog) + { + if (!Upgrade(items, id)) + return false; + return IsOk(blockSizeLog); + } +}; + +static const unsigned kNumFixedExtents = 8; + +void CFork::Parse(const Byte *p) +{ + Extents.Clear(); + Size = Get64(p); + // ClumpSize = Get32(p + 8); + NumBlocks = Get32(p + 12); + p += 16; + for (unsigned i = 0; i < kNumFixedExtents; i++, p += 8) + { + CExtent e; + e.Pos = Get32(p); + e.NumBlocks = Get32(p + 4); + if (e.NumBlocks != 0) + Extents.Add(e); + } +} + +UInt32 CFork::Calc_NumBlocks_from_Extents() const +{ + UInt32 num = 0; + FOR_VECTOR (i, Extents) + { + num += Extents[i].NumBlocks; + } + return num; +} + +bool CFork::Check_NumBlocks() const +{ + UInt32 num = 0; + FOR_VECTOR (i, Extents) + { + UInt32 next = num + Extents[i].NumBlocks; + if (next < num) + return false; + num = next; + } + return num == NumBlocks; +} + +struct CIdIndexPair +{ + UInt32 ID; + int Index; + + int Compare(const CIdIndexPair &a) const; +}; + +#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } + +int CIdIndexPair::Compare(const CIdIndexPair &a) const +{ + RINOZ(MyCompare(ID, a.ID)); + return MyCompare(Index, a.Index); +} + +static int FindItemIndex(const CRecordVector &items, UInt32 id) +{ + unsigned left = 0, right = items.Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + UInt32 midVal = items[mid].ID; + if (id == midVal) + return items[mid].Index; + if (id < midVal) + right = mid; + else + left = mid + 1; + } + return -1; +} + +static int Find_in_IdExtents(const CObjectVector &items, UInt32 id) +{ + unsigned left = 0, right = items.Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + UInt32 midVal = items[mid].ID; + if (id == midVal) + return mid; + if (id < midVal) + right = mid; + else + left = mid + 1; + } + return -1; +} + +bool CFork::Upgrade(const CObjectVector &items, UInt32 id) +{ + int index = Find_in_IdExtents(items, id); + if (index < 0) + return true; + const CIdExtents &item = items[index]; + if (Calc_NumBlocks_from_Extents() != item.StartBlock) + return false; + Extents += item.Extents; + return true; +} + + +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; + unsigned BlockSizeLog; + UInt32 NumBlocks; + UInt32 NumFreeBlocks; + + // UInt32 WriteCount; + // UInt32 FinderInfo[8]; + // UInt64 VolID; + + UInt64 GetPhySize() const { return (UInt64)NumBlocks << BlockSizeLog; } + UInt64 GetFreeSize() const { return (UInt64)NumFreeBlocks << BlockSizeLog; } + 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, + RECORD_TYPE_FOLDER_THREAD, + RECORD_TYPE_FILE_THREAD +}; + +struct CItem +{ + UString Name; + + UInt32 ParentID; + + UInt16 Type; + UInt16 FileMode; + // UInt16 Flags; + // UInt32 Valence; + UInt32 ID; + UInt32 CTime; + UInt32 MTime; + // UInt32 AttrMTime; + UInt32 ATime; + // UInt32 BackupDate; + + /* + UInt32 OwnerID; + UInt32 GroupID; + Byte AdminFlags; + Byte OwnerFlags; + union + { + UInt32 iNodeNum; + UInt32 LinkCount; + UInt32 RawDevice; + } special; + + UInt32 FileType; + UInt32 FileCreator; + UInt16 FinderFlags; + UInt16 Point[2]; + */ + + CFork DataFork; + CFork ResourceFork; + + // for compressed attribute + UInt64 UnpackSize; + size_t DataPos; + UInt32 PackSize; + unsigned Method; + bool UseAttr; + bool UseInlineData; + + CItem(): UseAttr(false), UseInlineData(false) {} + bool IsDir() const { return Type == RECORD_TYPE_FOLDER; } + const CFork &GetFork(bool isResource) const { return (CFork & )*(isResource ? &ResourceFork: &DataFork ); } +}; + +struct CAttr +{ + UInt32 ID; + UInt32 Size; + size_t Pos; + UString Name; +}; + +struct CRef +{ + unsigned ItemIndex; + int AttrIndex; + int Parent; + bool IsResource; + + bool IsAltStream() const { return IsResource || AttrIndex >= 0; } + CRef(): AttrIndex(-1), Parent(-1), IsResource(false) {} +}; + +class CDatabase +{ + HRESULT ReadFile(const CFork &fork, CByteBuffer &buf, IInStream *inStream); + HRESULT LoadExtentFile(const CFork &fork, IInStream *inStream, CObjectVector *overflowExtentsArray); + HRESULT LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpenCallback *progress); + HRESULT LoadCatalog(const CFork &fork, const CObjectVector *overflowExtentsArray, IInStream *inStream, IArchiveOpenCallback *progress); + bool Parse_decmpgfs(const CAttr &attr, CItem &item, bool &skip); +public: + CRecordVector Refs; + CObjectVector Items; + CObjectVector Attrs; + + CByteBuffer AttrBuf; + + CVolHeader Header; + bool HeadersError; + bool ThereAreAltStreams; + // bool CaseSensetive; + UString ResFileName; + + UInt64 PhySize; + + void Clear() + { + PhySize = 0; + HeadersError = false; + ThereAreAltStreams = false; + // CaseSensetive = false; + Refs.Clear(); + Items.Clear(); + Attrs.Clear(); + AttrBuf.Free(); + } + + UInt64 Get_UnpackSize_of_Ref(const CRef &ref) const + { + if (ref.AttrIndex >= 0) + return Attrs[ref.AttrIndex].Size; + const CItem &item = Items[ref.ItemIndex]; + if (item.IsDir()) + return 0; + if (item.UseAttr) + return item.UnpackSize; + return item.GetFork(ref.IsResource).Size; + } + + void GetItemPath(unsigned index, NWindows::NCOM::CPropVariant &path) const; + HRESULT Open2(IInStream *inStream, IArchiveOpenCallback *progress); +}; + +enum +{ + kHfsID_Root = 1, + kHfsID_RootFolder = 2, + kHfsID_ExtentsFile = 3, + kHfsID_CatalogFile = 4, + kHfsID_BadBlockFile = 5, + kHfsID_AllocationFile = 6, + kHfsID_StartupFile = 7, + kHfsID_AttributesFile = 8, + kHfsID_RepairCatalogFile = 14, + kHfsID_BogusExtentFile = 15, + kHfsID_FirstUserCatalogNode = 16 +}; + +void CDatabase::GetItemPath(unsigned index, NWindows::NCOM::CPropVariant &path) const +{ + unsigned len = 0; + const unsigned kNumLevelsMax = (1 << 10); + int cur = index; + unsigned i; + + for (i = 0; i < kNumLevelsMax; i++) + { + const CRef &ref = Refs[cur]; + const UString *s; + + if (ref.IsResource) + s = &ResFileName; + else if (ref.AttrIndex >= 0) + s = &Attrs[ref.AttrIndex].Name; + else + s = &Items[ref.ItemIndex].Name; + + len += s->Len(); + len++; + cur = ref.Parent; + if (cur < 0) + break; + } + + len--; + wchar_t *p = path.AllocBstr(len); + p[len] = 0; + cur = index; + + for (;;) + { + const CRef &ref = Refs[cur]; + const UString *s; + wchar_t delimChar = L':'; + + if (ref.IsResource) + s = &ResFileName; + else if (ref.AttrIndex >= 0) + s = &Attrs[ref.AttrIndex].Name; + else + { + delimChar = WCHAR_PATH_SEPARATOR; + s = &Items[ref.ItemIndex].Name; + } + + unsigned curLen = s->Len(); + len -= curLen; + + const wchar_t *src = (const wchar_t *)*s; + wchar_t *dest = p + len; + for (unsigned j = 0; j < curLen; j++) + dest[j] = src[j]; + + if (len == 0) + break; + p[--len] = delimChar; + cur = ref.Parent; + } +} + +// Actually we read all blocks. It can be larger than fork.Size + +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.Alloc(totalSize); + UInt32 curBlock = 0; + FOR_VECTOR (i, fork.Extents) + { + if (curBlock >= fork.NumBlocks) + return S_FALSE; + const CExtent &e = fork.Extents[i]; + if (e.Pos > Header.NumBlocks || + e.NumBlocks > fork.NumBlocks - curBlock || + e.NumBlocks > Header.NumBlocks - e.Pos) + return S_FALSE; + RINOK(inStream->Seek((UInt64)e.Pos << Header.BlockSizeLog, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream_FALSE(inStream, + (Byte *)buf + ((size_t)curBlock << Header.BlockSizeLog), + (size_t)e.NumBlocks << Header.BlockSizeLog)); + curBlock += e.NumBlocks; + } + return S_OK; +} + +static const unsigned kNodeDescriptor_Size = 14; + +struct CNodeDescriptor +{ + UInt32 fLink; + // UInt32 bLink; + Byte Kind; + // Byte Height; + unsigned NumRecords; + + bool CheckNumRecords(unsigned nodeSizeLog) + { + return (kNodeDescriptor_Size + ((UInt32)NumRecords + 1) * 2 <= ((UInt32)1 << nodeSizeLog)); + } + 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; + unsigned 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); + + unsigned 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; +} + + +static const Byte kNodeType_Leaf = 0xFF; +// static const Byte kNodeType_Index = 0; +// static const Byte kNodeType_Header = 1; +// static const Byte kNodeType_Mode = 2; + +static const Byte kExtentForkType_Data = 0; +static const Byte kExtentForkType_Resource = 0xFF; + +/* It loads data extents from Extents Overflow File + Most dmg installers are not fragmented. So there are no extents in Overflow File. */ + +HRESULT CDatabase::LoadExtentFile(const CFork &fork, IInStream *inStream, CObjectVector *overflowExtentsArray) +{ + if (fork.NumBlocks == 0) + return S_OK; + CByteBuffer buf; + RINOK(ReadFile(fork, buf, inStream)); + const Byte *p = (const Byte *)buf; + + // CNodeDescriptor nodeDesc; + // nodeDesc.Parse(p); + CHeaderRec hr; + RINOK(hr.Parse(p + kNodeDescriptor_Size)); + + if ((buf.Size() >> hr.NodeSizeLog) < hr.TotalNodes) + return S_FALSE; + + UInt32 node = hr.FirstLeafNode; + if (node == 0) + return S_OK; + + CByteBuffer usedBuf(hr.TotalNodes); + memset(usedBuf, 0, hr.TotalNodes); + + while (node != 0) + { + if (node >= hr.TotalNodes || usedBuf[node] != 0) + return S_FALSE; + usedBuf[node] = 1; + + size_t nodeOffset = (size_t)node << hr.NodeSizeLog; + CNodeDescriptor desc; + desc.Parse(p + nodeOffset); + if (!desc.CheckNumRecords(hr.NodeSizeLog)) + return S_FALSE; + if (desc.Kind != kNodeType_Leaf) + return S_FALSE; + + UInt32 endBlock = 0; + + for (unsigned i = 0; i < desc.NumRecords; i++) + { + UInt32 nodeSize = (UInt32)1 << hr.NodeSizeLog; + UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2); + UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2); + if (offs > nodeSize || offsNext > nodeSize) + return S_FALSE; + UInt32 recSize = offsNext - offs; + const unsigned kKeyLen = 10; + + if (recSize != 2 + kKeyLen + kNumFixedExtents * 8) + return S_FALSE; + + const Byte *r = p + nodeOffset + offs; + if (Get16(r) != kKeyLen) + return S_FALSE; + + Byte forkType = r[2]; + unsigned forkTypeIndex; + if (forkType == kExtentForkType_Data) + forkTypeIndex = 0; + else if (forkType == kExtentForkType_Resource) + forkTypeIndex = 1; + else + continue; + CObjectVector &overflowExtents = overflowExtentsArray[forkTypeIndex]; + + UInt32 id = Get32(r + 4); + UInt32 startBlock = Get32(r + 8); + r += 2 + kKeyLen; + + bool needNew = true; + + if (overflowExtents.Size() != 0) + { + CIdExtents &e = overflowExtents.Back(); + if (e.ID == id) + { + if (endBlock != startBlock) + return S_FALSE; + needNew = false; + } + } + + if (needNew) + { + CIdExtents &e = overflowExtents.AddNew(); + e.ID = id; + e.StartBlock = startBlock; + endBlock = startBlock; + } + + CIdExtents &e = overflowExtents.Back(); + + for (unsigned k = 0; k < kNumFixedExtents; k++, r += 8) + { + CExtent ee; + ee.Pos = Get32(r); + ee.NumBlocks = Get32(r + 4); + if (ee.NumBlocks != 0) + { + e.Extents.Add(ee); + endBlock += ee.NumBlocks; + } + } + } + + node = desc.fLink; + } + return S_OK; +} + +static void LoadName(const Byte *data, unsigned len, UString &dest) +{ + wchar_t *p = dest.GetBuffer(len); + unsigned i; + for (i = 0; i < len; i++) + p[i] = Get16(data + i * 2); + p[i] = 0; + dest.ReleaseBuffer(); +} + +static bool IsNameEqualTo(const Byte *data, const char *name) +{ + for (unsigned i = 0;; i++) + { + char c = name[i]; + if (c == 0) + return true; + if (Get16(data + i * 2) != (Byte)c) + return false; + } +} + +static const UInt32 kAttrRecordType_Inline = 0x10; +// static const UInt32 kAttrRecordType_Fork = 0x20; +// static const UInt32 kAttrRecordType_Extents = 0x30; + +HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpenCallback *progress) +{ + if (fork.NumBlocks == 0) + return S_OK; + + RINOK(ReadFile(fork, AttrBuf, inStream)); + const Byte *p = (const Byte *)AttrBuf; + + // CNodeDescriptor nodeDesc; + // nodeDesc.Parse(p); + CHeaderRec hr; + RINOK(hr.Parse(p + kNodeDescriptor_Size)); + + // CaseSensetive = (Header.IsHfsX() && hr.KeyCompareType == 0xBC); + + if ((AttrBuf.Size() >> hr.NodeSizeLog) < hr.TotalNodes) + return S_FALSE; + + UInt32 node = hr.FirstLeafNode; + if (node == 0) + return S_OK; + + CByteBuffer usedBuf(hr.TotalNodes); + memset(usedBuf, 0, hr.TotalNodes); + + CFork resFork; + + while (node != 0) + { + if (node >= hr.TotalNodes || usedBuf[node] != 0) + return S_FALSE; + usedBuf[node] = 1; + + size_t nodeOffset = (size_t)node << hr.NodeSizeLog; + CNodeDescriptor desc; + desc.Parse(p + nodeOffset); + if (!desc.CheckNumRecords(hr.NodeSizeLog)) + return S_FALSE; + if (desc.Kind != kNodeType_Leaf) + return S_FALSE; + + for (unsigned 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 (offs >= nodeSize + || offsNext >= nodeSize + || offsNext < offs) + return S_FALSE; + + const unsigned kHeadSize = 14; + if (recSize < kHeadSize) + return S_FALSE; + + const Byte *r = p + nodeOffset + offs; + UInt32 keyLen = Get16(r); + + // UInt16 pad = Get16(r + 2); + UInt32 fileID = Get32(r + 4); + unsigned startBlock = Get32(r + 8); + if (startBlock != 0) + { + // that case is still unsupported + HeadersError = true; + continue; + } + unsigned nameLen = Get16(r + 12); + + if (keyLen + 2 > recSize || + keyLen != kHeadSize - 2 + nameLen * 2) + return S_FALSE; + r += kHeadSize; + recSize -= kHeadSize; + + const Byte *name = r; + r += nameLen * 2; + recSize -= nameLen * 2; + + if (recSize < 4) + return S_FALSE; + + UInt32 recordType = Get32(r); + if (recordType != kAttrRecordType_Inline) + { + // Probably only kAttrRecordType_Inline now is used in real HFS files + HeadersError = true; + continue; + } + + const UInt32 kRecordHeaderSize = 16; + if (recSize < kRecordHeaderSize) + return S_FALSE; + UInt32 dataSize = Get32(r + 12); + + r += kRecordHeaderSize; + recSize -= kRecordHeaderSize; + + if (recSize < dataSize) + return S_FALSE; + + CAttr &attr = Attrs.AddNew(); + attr.ID = fileID; + attr.Pos = nodeOffset + offs + 2 + keyLen + kRecordHeaderSize; + attr.Size = dataSize; + LoadName(name, nameLen, attr.Name); + + if (progress && (i & 0xFFF) == 0) + { + UInt64 numFiles = 0; + RINOK(progress->SetCompleted(&numFiles, NULL)); + } + } + + node = desc.fLink; + } + return S_OK; +} + +static const UInt32 kMethod_Attr = 3; // data stored in attribute file +static const UInt32 kMethod_Resource = 4; // data stored in resource fork + +bool CDatabase::Parse_decmpgfs(const CAttr &attr, CItem &item, bool &skip) +{ + skip = false; + if (attr.Name != L"com.apple.decmpfs") + return true; + if (item.UseAttr || !item.DataFork.IsEmpty()) + return false; + + const UInt32 k_decmpfs_headerSize = 16; + UInt32 dataSize = attr.Size; + if (dataSize < k_decmpfs_headerSize) + return false; + const Byte *r = AttrBuf + attr.Pos; + if (GetUi32(r) != 0x636D7066) // magic == "fpmc" + return false; + item.Method = GetUi32(r + 4); + item.UnpackSize = GetUi64(r + 8); + dataSize -= k_decmpfs_headerSize; + r += k_decmpfs_headerSize; + if (item.Method == kMethod_Resource) + { + if (dataSize != 0) + return false; + item.UseAttr = true; + } + else if (item.Method == kMethod_Attr) + { + if (dataSize == 0) + return false; + Byte b = r[0]; + if ((b & 0xF) == 0xF) + { + dataSize--; + if (item.UnpackSize > dataSize) + return false; + item.DataPos = attr.Pos + k_decmpfs_headerSize + 1; + item.PackSize = dataSize; + item.UseAttr = true; + item.UseInlineData = true; + } + else + { + item.DataPos = attr.Pos + k_decmpfs_headerSize; + item.PackSize = dataSize; + item.UseAttr = true; + } + } + else + return false; + skip = true; + return true; +} + +HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector *overflowExtentsArray, IInStream *inStream, IArchiveOpenCallback *progress) +{ + unsigned reserveSize = (unsigned)(Header.NumFolders + 1 + Header.NumFiles); + Items.ClearAndReserve(reserveSize); + Refs.ClearAndReserve(reserveSize); + + CRecordVector IdToIndexMap; + IdToIndexMap.ClearAndReserve(reserveSize); + + CByteBuffer buf; + RINOK(ReadFile(fork, buf, inStream)); + const Byte *p = (const Byte *)buf; + + // CNodeDescriptor nodeDesc; + // nodeDesc.Parse(p); + CHeaderRec hr; + hr.Parse(p + kNodeDescriptor_Size); + + // CaseSensetive = (Header.IsHfsX() && hr.KeyCompareType == 0xBC); + + if ((buf.Size() >> hr.NodeSizeLog) < hr.TotalNodes) + return S_FALSE; + + CByteBuffer usedBuf(hr.TotalNodes); + memset(usedBuf, 0, hr.TotalNodes); + + CFork resFork; + + UInt32 node = hr.FirstLeafNode; + UInt32 numFiles = 0; + UInt32 numFolders = 0; + + while (node != 0) + { + if (node >= hr.TotalNodes || usedBuf[node] != 0) + return S_FALSE; + usedBuf[node] = 1; + + size_t nodeOffset = (size_t)node << hr.NodeSizeLog; + CNodeDescriptor desc; + desc.Parse(p + nodeOffset); + if (!desc.CheckNumRecords(hr.NodeSizeLog)) + return S_FALSE; + if (desc.Kind != kNodeType_Leaf) + return S_FALSE; + + for (unsigned 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 (offs >= nodeSize + || offs >= nodeSize + || offsNext < offs + || recSize < 6) + return S_FALSE; + + const Byte *r = p + nodeOffset + offs; + UInt32 keyLen = Get16(r); + UInt32 parentID = Get32(r + 2); + if (keyLen < 6 || (keyLen & 1) != 0 || keyLen + 2 > recSize) + return S_FALSE; + r += 6; + recSize -= 6; + keyLen -= 6; + + unsigned nameLen = Get16(r); + if (nameLen * 2 != (unsigned)keyLen) + return S_FALSE; + r += 2; + recSize -= 2; + + r += nameLen * 2; + recSize -= nameLen * 2; + + if (recSize < 2) + return S_FALSE; + UInt16 type = Get16(r); + + if (type != RECORD_TYPE_FOLDER && + type != RECORD_TYPE_FILE) + continue; + + const unsigned kBasicRecSize = 0x58; + if (recSize < kBasicRecSize) + return S_FALSE; + + CItem &item = Items.AddNew(); + item.ParentID = parentID; + item.Type = type; + // item.Flags = Get16(r + 2); + // item.Valence = Get32(r + 4); + item.ID = Get32(r + 8); + { + const Byte *name = r - (nameLen * 2); + LoadName(name, nameLen, item.Name); + if (item.Name.Len() <= 1) + { + if (item.Name.IsEmpty() && nameLen == 21) + { + if (GetUi32(name) == 0 && + GetUi32(name + 4) == 0 && + IsNameEqualTo(name + 8, "HFS+ Private Data")) + { + // it's folder for "Hard Links" files + item.Name = L"[HFS+ Private Data]"; + } + } + + // Some dmg files have ' ' folder item. + if (item.Name.IsEmpty() || item.Name[0] == L' ') + item.Name = L"[]"; + } + } + + 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); // or .linkCount + item.FileType = Get32(r + 0x30); + item.FileCreator = Get32(r + 0x34); + item.FinderFlags = Get16(r + 0x38); + item.Point[0] = Get16(r + 0x3A); // v + item.Point[1] = Get16(r + 0x3C); // h + */ + + // const refIndex = Refs.Size(); + CIdIndexPair pair; + pair.ID = item.ID; + pair.Index = Items.Size() - 1; + IdToIndexMap.Add(pair); + + recSize -= kBasicRecSize; + r += kBasicRecSize; + if (item.IsDir()) + { + numFolders++; + if (recSize != 0) + return S_FALSE; + } + else + { + numFiles++; + const unsigned kForkRecSize = 16 + kNumFixedExtents * 8; + if (recSize != kForkRecSize * 2) + return S_FALSE; + + item.DataFork.Parse(r); + + if (!item.DataFork.UpgradeAndTest(overflowExtentsArray[0], item.ID, Header.BlockSizeLog)) + HeadersError = true; + + item.ResourceFork.Parse(r + kForkRecSize); + if (!item.ResourceFork.IsEmpty()) + { + if (!item.ResourceFork.UpgradeAndTest(overflowExtentsArray[1], item.ID, Header.BlockSizeLog)) + HeadersError = true; + ThereAreAltStreams = true; + } + } + if (progress && (Items.Size() & 0xFFF) == 0) + { + UInt64 numItems = Items.Size(); + RINOK(progress->SetCompleted(&numItems, NULL)); + } + } + node = desc.fLink; + } + + if (Header.NumFiles != numFiles || + Header.NumFolders + 1 != numFolders) + HeadersError = true; + + IdToIndexMap.Sort2(); + { + for (unsigned i = 1; i < IdToIndexMap.Size(); i++) + if (IdToIndexMap[i - 1].ID == IdToIndexMap[i].ID) + return S_FALSE; + } + + + CBoolArr skipAttr(Attrs.Size()); + { + for (unsigned i = 0; i < Attrs.Size(); i++) + skipAttr[i] = false; + } + + { + FOR_VECTOR (i, Attrs) + { + const CAttr &attr = Attrs[i]; + + int itemIndex = FindItemIndex(IdToIndexMap, attr.ID); + if (itemIndex < 0) + { + HeadersError = true; + continue; + } + if (!Parse_decmpgfs(attr, Items[itemIndex], skipAttr[i])) + HeadersError = true; + } + } + + IdToIndexMap.ClearAndReserve(Items.Size()); + + { + FOR_VECTOR (i, Items) + { + const CItem &item = Items[i]; + + CIdIndexPair pair; + pair.ID = item.ID; + pair.Index = Refs.Size(); + IdToIndexMap.Add(pair); + + CRef ref; + ref.ItemIndex = i; + Refs.Add(ref); + + #ifdef HFS_SHOW_ALT_STREAMS + + if (item.ResourceFork.IsEmpty()) + continue; + if (item.UseAttr && item.Method == kMethod_Resource) + continue; + CRef resRef; + resRef.ItemIndex = i; + resRef.IsResource = true; + resRef.Parent = Refs.Size() - 1; + Refs.Add(resRef); + + #endif + } + } + + IdToIndexMap.Sort2(); + + { + FOR_VECTOR (i, Refs) + { + CRef &ref = Refs[i]; + if (ref.IsResource) + continue; + CItem &item = Items[ref.ItemIndex]; + ref.Parent = FindItemIndex(IdToIndexMap, item.ParentID); + if (ref.Parent >= 0) + { + if (!Items[Refs[ref.Parent].ItemIndex].IsDir()) + { + ref.Parent = -1; + HeadersError = true; + } + } + } + } + + #ifdef HFS_SHOW_ALT_STREAMS + { + FOR_VECTOR (i, Attrs) + { + if (skipAttr[i]) + continue; + const CAttr &attr = Attrs[i]; + + int refIndex = FindItemIndex(IdToIndexMap, attr.ID); + if (refIndex < 0) + { + HeadersError = true; + continue; + } + + CRef ref; + ref.AttrIndex = i; + ref.Parent = refIndex; + ref.ItemIndex = Refs[refIndex].ItemIndex; + Refs.Add(ref); + } + } + #endif + + return S_OK; +} + +static const unsigned kHeaderPadSize = (1 << 10); + +HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress) +{ + Clear(); + static const unsigned kHeaderSize = kHeaderPadSize + 512; + Byte buf[kHeaderSize]; + RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize)); + { + for (unsigned i = 0; i < kHeaderPadSize; i++) + if (buf[i] != 0) + return S_FALSE; + } + const Byte *p = buf + kHeaderPadSize; + 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); + + if (h.NumFolders > ((UInt32)1 << 29) || + h.NumFiles > ((UInt32)1 << 30)) + return S_FALSE; + if (progress) + { + UInt64 numFiles = (UInt64)h.NumFiles + h.NumFolders + 1; + RINOK(progress->SetTotal(&numFiles, NULL)); + } + + UInt32 blockSize = Get32(p + 0x28); + + { + unsigned i; + 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.NextCalatlogNodeID = Get32(p + 0x40); + 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; + */ + + ResFileName = kResFileName; + + CFork extentsFork, catalogFork, attrFork; + // allocationFork.Parse(p + 0x70 + 0x50 * 0); + extentsFork.Parse(p + 0x70 + 0x50 * 1); + catalogFork.Parse(p + 0x70 + 0x50 * 2); + attrFork.Parse (p + 0x70 + 0x50 * 3); + // startupFork.Parse(p + 0x70 + 0x50 * 4); + + CObjectVector overflowExtents[2]; + if (!extentsFork.IsOk(Header.BlockSizeLog)) + HeadersError = true; + else + { + HRESULT res = LoadExtentFile(extentsFork, inStream, overflowExtents); + if (res == S_FALSE) + HeadersError = true; + else if (res != S_OK) + return res; + } + + if (!catalogFork.UpgradeAndTest(overflowExtents[0], kHfsID_CatalogFile, Header.BlockSizeLog)) + return S_FALSE; + + if (!attrFork.UpgradeAndTest(overflowExtents[0], kHfsID_AttributesFile, Header.BlockSizeLog)) + HeadersError = true; + else + { + if (attrFork.Size != 0) + RINOK(LoadAttrs(attrFork, inStream, progress)); + } + + RINOK(LoadCatalog(catalogFork, overflowExtents, inStream, progress)); + + PhySize = Header.GetPhySize(); + return S_OK; +} + + + +class CHandler: + public IInArchive, + public IArchiveGetRawProps, + public IInArchiveGetStream, + public CMyUnknownImp, + public CDatabase +{ + CMyComPtr _stream; + + HRESULT GetForkStream(const CFork &fork, ISequentialInStream **stream); + + HRESULT ExtractZlibFile( + ISequentialOutStream *realOutStream, + const CItem &item, + NCompress::NZlib::CDecoder *_zlibDecoderSpec, + CByteBuffer &buf, + UInt64 progressStart, + IArchiveExtractCallback *extractCallback); +public: + MY_UNKNOWN_IMP3(IInArchive, IArchiveGetRawProps, IInArchiveGetStream) + INTERFACE_IInArchive(;) + INTERFACE_IArchiveGetRawProps(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +static const Byte kProps[] = +{ + kpidPath, + kpidIsDir, + kpidSize, + kpidPackSize, + kpidCTime, + kpidMTime, + kpidATime, + kpidPosixAttrib +}; + +static const Byte kArcProps[] = +{ + kpidMethod, + kpidClusterSize, + kpidFreeSpace, + kpidCTime, + kpidMTime +}; + +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 kpidExtension: prop = Header.IsHfsX() ? "hfsx" : "hfs"; break; + case kpidMethod: prop = Header.IsHfsX() ? "HFSX" : "HFS+"; break; + case kpidPhySize: prop = PhySize; break; + case kpidClusterSize: prop = (UInt32)1 << Header.BlockSizeLog; break; + case kpidFreeSpace: prop = (UInt64)Header.GetFreeSize(); break; + case kpidMTime: HfsTimeToProp(Header.MTime, prop); break; + case kpidCTime: + { + FILETIME localFt, ft; + HfsTimeToFileTime(Header.CTime, localFt); + if (LocalFileTimeToFileTime(&localFt, &ft)) + prop = ft; + break; + } + case kpidIsTree: prop = true; break; + case kpidErrorFlags: + { + UInt32 flags = 0; + if (HeadersError) flags |= kpv_ErrorFlags_HeadersError; + if (flags != 0) + prop = flags; + break; + } + case kpidIsAltStream: prop = ThereAreAltStreams; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps) +{ + *numProps = 0; + return S_OK; +} + +STDMETHODIMP CHandler::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID) +{ + *name = NULL; + *propID = 0; + return S_OK; +} + +STDMETHODIMP CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType) +{ + const CRef &ref = Refs[index]; + *parentType = ref.IsAltStream() ? + NParentType::kAltStream : + NParentType::kDir; + *parent = (UInt32)(Int32)ref.Parent; + return S_OK; +} + +STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) +{ + *data = NULL; + *dataSize = 0; + *propType = 0; + #ifdef MY_CPU_LE + if (propID == kpidName) + { + const CRef &ref = Refs[index]; + const UString *s; + if (ref.IsResource) + s = &ResFileName; + else if (ref.AttrIndex >= 0) + s = &Attrs[ref.AttrIndex].Name; + else + s = &Items[ref.ItemIndex].Name; + *data = (const wchar_t *)(*s); + *dataSize = (s->Len() + 1) * sizeof(wchar_t); + *propType = PROP_DATA_TYPE_wchar_t_PTR_Z_LE; + return S_OK; + } + #endif + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + const CRef &ref = Refs[index]; + const CItem &item = Items[ref.ItemIndex]; + switch (propID) + { + case kpidPath: GetItemPath(index, prop); break; + case kpidName: + const UString *s; + if (ref.IsResource) + s = &ResFileName; + else if (ref.AttrIndex >= 0) + s = &Attrs[ref.AttrIndex].Name; + else + s = &item.Name; + prop = *s; + break; + case kpidPackSize: + { + UInt64 size; + if (ref.AttrIndex >= 0) + size = Attrs[ref.AttrIndex].Size; + else if (item.IsDir()) + break; + else if (item.UseAttr) + { + if (item.Method == kMethod_Resource) + size = item.ResourceFork.NumBlocks << Header.BlockSizeLog; + else + size = item.PackSize; + } + else + size = item.GetFork(ref.IsResource).NumBlocks << Header.BlockSizeLog; + prop = size; + break; + } + case kpidSize: + { + UInt64 size; + if (ref.AttrIndex >= 0) + size = Attrs[ref.AttrIndex].Size; + else if (item.IsDir()) + break; + else if (item.UseAttr) + size = item.UnpackSize; + else + size = item.GetFork(ref.IsResource).Size; + prop = size; + break; + } + case kpidIsDir: prop = item.IsDir(); break; + case kpidIsAltStream: prop = ref.IsAltStream(); break; + + case kpidCTime: HfsTimeToProp(item.CTime, prop); break; + case kpidMTime: HfsTimeToProp(item.MTime, prop); break; + case kpidATime: HfsTimeToProp(item.ATime, prop); break; + + case kpidPosixAttrib: if (ref.AttrIndex < 0) prop = (UInt32)item.FileMode; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Open(IInStream *inStream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + Close(); + RINOK(Open2(inStream, callback)); + _stream = inStream; + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _stream.Release(); + Clear(); + return S_OK; +} + +static const UInt32 kCompressionBlockSize = 1 << 16; + +HRESULT CHandler::ExtractZlibFile( + ISequentialOutStream *outStream, + const CItem &item, + NCompress::NZlib::CDecoder *_zlibDecoderSpec, + CByteBuffer &buf, + UInt64 progressStart, + IArchiveExtractCallback *extractCallback) +{ + CMyComPtr inStream; + const CFork &fork = item.ResourceFork; + RINOK(GetForkStream(fork, &inStream)); + const unsigned kHeaderSize = 0x100 + 8; + RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize)); + UInt32 dataPos = Get32(buf); + UInt32 mapPos = Get32(buf + 4); + UInt32 dataSize = Get32(buf + 8); + UInt32 mapSize = Get32(buf + 12); + + const UInt32 kResMapSize = 50; + + if (mapSize != kResMapSize + || dataPos + dataSize != mapPos + || mapPos + mapSize != fork.Size) + return S_FALSE; + + UInt32 dataSize2 = Get32(buf + 0x100); + if (4 + dataSize2 != dataSize || dataSize2 < 8) + return S_FALSE; + + UInt32 numBlocks = GetUi32(buf + 0x100 + 4); + if (((dataSize2 - 4) >> 3) < numBlocks) + return S_FALSE; + if (item.UnpackSize > (UInt64)numBlocks * kCompressionBlockSize) + return S_FALSE; + + if (item.UnpackSize + kCompressionBlockSize < (UInt64)numBlocks * kCompressionBlockSize) + return S_FALSE; + + UInt32 tableSize = (numBlocks << 3); + + CByteBuffer tableBuf(tableSize); + + RINOK(ReadStream_FALSE(inStream, tableBuf, tableSize)); + + UInt32 prev = 4 + tableSize; + + UInt32 i; + for (i = 0; i < numBlocks; i++) + { + UInt32 offset = GetUi32(tableBuf + i * 8); + UInt32 size = GetUi32(tableBuf + i * 8 + 4); + if (size == 0) + return S_FALSE; + if (prev != offset) + return S_FALSE; + if (offset > dataSize2 || + size > dataSize2 - offset) + return S_FALSE; + prev = offset + size; + } + + if (prev != dataSize2) + return S_FALSE; + + CBufInStream *bufInStreamSpec = new CBufInStream; + CMyComPtr bufInStream = bufInStreamSpec; + + UInt64 outPos = 0; + for (i = 0; i < numBlocks; i++) + { + UInt64 rem = item.UnpackSize - outPos; + if (rem == 0) + return S_FALSE; + UInt32 blockSize = kCompressionBlockSize; + if (rem < kCompressionBlockSize) + blockSize = (UInt32)rem; + + UInt32 size = GetUi32(tableBuf + i * 8 + 4); + + RINOK(ReadStream_FALSE(inStream, buf, size)); + + if ((buf[0] & 0xF) == 0xF) + { + // that code was not tested. Are there HFS archives with uncompressed block + if (size - 1 != blockSize) + return S_FALSE; + + if (outStream) + { + RINOK(WriteStream(outStream, buf, blockSize)); + } + } + else + { + UInt64 blockSize64 = blockSize; + bufInStreamSpec->Init(buf, size); + RINOK(_zlibDecoderSpec->Code(bufInStream, outStream, NULL, &blockSize64, NULL)); + if (_zlibDecoderSpec->GetOutputProcessedSize() != blockSize || + _zlibDecoderSpec->GetInputProcessedSize() != size) + return S_FALSE; + } + + outPos += blockSize; + UInt64 progressPos = progressStart + outPos; + RINOK(extractCallback->SetCompleted(&progressPos)); + } + + if (outPos != item.UnpackSize) + return S_FALSE; + + /* We check Resource Map + Are there HFS files with another values in Resource Map ??? */ + + RINOK(ReadStream_FALSE(inStream, buf, mapSize)); + UInt32 types = Get16(buf + 24); + UInt32 names = Get16(buf + 26); + UInt32 numTypes = Get16(buf + 28); + if (numTypes != 0 || types != 28 || names != kResMapSize) + return S_FALSE; + UInt32 resType = Get32(buf + 30); + UInt32 numResources = Get16(buf + 34); + UInt32 resListOffset = Get16(buf + 36); + if (resType != 0x636D7066) // cmpf + return S_FALSE; + if (numResources != 0 || resListOffset != 10) + return S_FALSE; + + UInt32 entryId = Get16(buf + 38); + UInt32 nameOffset = Get16(buf + 40); + // Byte attrib = buf[42]; + UInt32 resourceOffset = Get32(buf + 42) & 0xFFFFFF; + if (entryId != 1 || nameOffset != 0xFFFF || resourceOffset != 0) + return S_FALSE; + + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)(Int32)-1); + if (allFilesMode) + numItems = Refs.Size(); + if (numItems == 0) + return S_OK; + UInt32 i; + UInt64 totalSize = 0; + for (i = 0; i < numItems; i++) + { + const CRef &ref = Refs[allFilesMode ? i : indices[i]]; + totalSize += Get_UnpackSize_of_Ref(ref); + } + RINOK(extractCallback->SetTotal(totalSize)); + + UInt64 currentTotalSize = 0, currentItemSize = 0; + + const size_t kBufSize = kCompressionBlockSize; + CByteBuffer buf(kBufSize + 0x10); // we need 1 additional bytes for uncompressed chunk header + + NCompress::NZlib::CDecoder *_zlibDecoderSpec = NULL; + CMyComPtr _zlibDecoder; + + for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) + { + RINOK(extractCallback->SetCompleted(¤tTotalSize)); + UInt32 index = allFilesMode ? i : indices[i]; + const CRef &ref = Refs[index]; + const CItem &item = Items[ref.ItemIndex]; + currentItemSize = Get_UnpackSize_of_Ref(ref); + + CMyComPtr realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + if (ref.AttrIndex < 0 && 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::kDataError; + if (ref.AttrIndex >= 0) + { + res = NExtract::NOperationResult::kOK; + if (realOutStream) + { + const CAttr &attr = Attrs[ref.AttrIndex]; + RINOK(WriteStream(realOutStream, AttrBuf + attr.Pos, attr.Size)); + } + } + else if (item.UseAttr) + { + if (item.UseInlineData) + { + res = NExtract::NOperationResult::kOK; + if (realOutStream) + { + RINOK(WriteStream(realOutStream, AttrBuf + item.DataPos, (size_t)item.UnpackSize)); + } + } + else + { + if (!_zlibDecoder) + { + _zlibDecoderSpec = new NCompress::NZlib::CDecoder(); + _zlibDecoder = _zlibDecoderSpec; + } + + if (item.Method == kMethod_Attr) + { + CBufInStream *bufInStreamSpec = new CBufInStream; + CMyComPtr bufInStream = bufInStreamSpec; + bufInStreamSpec->Init(AttrBuf + item.DataPos, item.PackSize); + + HRESULT hres = _zlibDecoder->Code(bufInStream, realOutStream, NULL, &item.UnpackSize, NULL); + if (hres != S_FALSE) + { + if (hres != S_OK) + return hres; + if (_zlibDecoderSpec->GetOutputProcessedSize() == item.UnpackSize && + _zlibDecoderSpec->GetInputProcessedSize() == item.PackSize) + res = NExtract::NOperationResult::kOK; + } + } + else + { + HRESULT hres = ExtractZlibFile(realOutStream, item, _zlibDecoderSpec, buf, + currentTotalSize, extractCallback); + if (hres != S_FALSE) + { + if (hres != S_OK) + return hres; + res = NExtract::NOperationResult::kOK; + } + } + } + } + else + { + const CFork &fork = item.GetFork(ref.IsResource); + if (fork.IsOk(Header.BlockSizeLog)) + { + res = NExtract::NOperationResult::kOK; + unsigned extentIndex; + for (extentIndex = 0; extentIndex < fork.Extents.Size(); extentIndex++) + { + if (res != NExtract::NOperationResult::kOK) + break; + if (fork.Size == pos) + break; + const CExtent &e = fork.Extents[extentIndex]; + RINOK(_stream->Seek((UInt64)e.Pos << Header.BlockSizeLog, STREAM_SEEK_SET, NULL)); + UInt64 extentRem = (UInt64)e.NumBlocks << Header.BlockSizeLog; + while (extentRem != 0) + { + UInt64 rem = fork.Size - pos; + if (rem == 0) + { + // Here we check that there are no extra (empty) blocks in last extent. + if (extentRem >= (UInt64)((UInt32)1 << Header.BlockSizeLog)) + res = NExtract::NOperationResult::kDataError; + break; + } + size_t cur = kBufSize; + if (cur > rem) + cur = (size_t)rem; + if (cur > extentRem) + cur = (size_t)extentRem; + RINOK(ReadStream(_stream, buf, &cur)); + if (cur == 0) + { + res = NExtract::NOperationResult::kDataError; + break; + } + if (realOutStream) + { + RINOK(WriteStream(realOutStream, buf, cur)); + } + pos += cur; + extentRem -= cur; + UInt64 processed = currentTotalSize + pos; + RINOK(extractCallback->SetCompleted(&processed)); + } + } + if (extentIndex != fork.Extents.Size() || fork.Size != pos) + res = NExtract::NOperationResult::kDataError; + } + } + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(res)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = Refs.Size(); + return S_OK; +} + +HRESULT CHandler::GetForkStream(const CFork &fork, ISequentialInStream **stream) +{ + *stream = 0; + + if (!fork.IsOk(Header.BlockSizeLog)) + return S_FALSE; + + CExtentsStream *extentStreamSpec = new CExtentsStream(); + CMyComPtr extentStream = extentStreamSpec; + + UInt64 rem = fork.Size; + UInt64 virt = 0; + + FOR_VECTOR (i, fork.Extents) + { + const CExtent &e = fork.Extents[i]; + if (e.NumBlocks == 0) + continue; + UInt64 cur = ((UInt64)e.NumBlocks << Header.BlockSizeLog); + if (cur > rem) + { + cur = rem; + if (i != fork.Extents.Size() - 1) + return S_FALSE; + } + CSeekExtent se; + se.Phy = (UInt64)e.Pos << Header.BlockSizeLog; + se.Virt = virt; + virt += cur; + rem -= cur; + extentStreamSpec->Extents.Add(se); + } + + if (rem != 0) + return S_FALSE; + + CSeekExtent se; + se.Phy = 0; + se.Virt = virt; + extentStreamSpec->Extents.Add(se); + extentStreamSpec->Stream = _stream; + extentStreamSpec->Init(); + *stream = extentStream.Detach(); + return S_OK; +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + *stream = 0; + + const CRef &ref = Refs[index]; + if (ref.AttrIndex >= 0) + return S_FALSE; + const CItem &item = Items[ref.ItemIndex]; + if (item.IsDir() || item.UseAttr) + return S_FALSE; + + return GetForkStream(item.GetFork(ref.IsResource), stream); +} + +IMP_CreateArcIn + +static CArcInfo g_ArcInfo = + { "HFS", "hfs hfsx", 0, 0xE3, + 2 * (4 + 1), + { + 4, 'H', '+', 0, 4, + 4, 'H', 'X', 0, 5, + }, + kHeaderPadSize, + NArcInfoFlags::kMultiSignature, + CreateArc }; + +REGISTER_ARC(Hfs) + +}} diff --git a/CPP/7zip/Archive/IArchive.h b/CPP/7zip/Archive/IArchive.h old mode 100755 new mode 100644 index 85320276..63e16ac3 --- a/CPP/7zip/Archive/IArchive.h +++ b/CPP/7zip/Archive/IArchive.h @@ -20,20 +20,43 @@ namespace NFileTimeType }; } +namespace NArcInfoFlags +{ + const UInt32 kKeepName = 1 << 0; // keep name of file in archive name + const UInt32 kAltStreams = 1 << 1; // the handler supports alt streams + const UInt32 kNtSecure = 1 << 2; // the handler supports NT security + const UInt32 kFindSignature = 1 << 3; // the handler can find start of archive + const UInt32 kMultiSignature = 1 << 4; // there are several signatures + const UInt32 kUseGlobalOffset = 1 << 5; // the seek position of stream must be set as global offset + const UInt32 kStartOpen = 1 << 6; // call handler for each start position + const UInt32 kPureStartOpen = 1 << 7; // call handler only for start of file + const UInt32 kBackwardOpen = 1 << 8; // archive can be open backward + const UInt32 kPreArc = 1 << 9; // such archive can be stored before real archive (like SFX stub) + const UInt32 kSymLinks = 1 << 10; // the handler supports symbolic links + const UInt32 kHardLinks = 1 << 11; // the handler supports hard links +} + namespace NArchive { - enum + namespace NHandlerPropID { - kName = 0, - kClassID, - kExtension, - kAddExtension, - kUpdate, - kKeepName, - kStartSignature, - kFinishSignature, - kAssociate - }; + enum + { + kName = 0, // VT_BSTR + kClassID, // binary GUID in VT_BSTR + kExtension, // VT_BSTR + kAddExtension, // VT_BSTR + kUpdate, // VT_BOOL + kKeepName, // VT_BOOL + kSignature, // binary in VT_BSTR + kMultiSignature, // binary in VT_BSTR + kSignatureOffset, // VT_UI4 + kAltStreams, // VT_BOOL + kNtSecure, // VT_BOOL + kFlags // VT_UI4 + // kVersion // VT_UI4 ((VER_MAJOR << 8) | VER_MINOR) + }; + } namespace NExtract { @@ -46,25 +69,32 @@ namespace NArchive kSkip }; } + namespace NOperationResult { enum { kOK = 0, - kUnSupportedMethod, + kUnsupportedMethod, kDataError, - kCRCError + kCRCError, + kUnavailable, + kUnexpectedEnd, + kDataAfterEnd, + kIsNotArc, + kHeadersError }; } } + namespace NUpdate { namespace NOperationResult { enum { - kOK = 0, - kError + kOK = 0 + , // kError }; } } @@ -79,10 +109,16 @@ ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10) INTERFACE_IArchiveOpenCallback(PURE); }; +/* +IArchiveExtractCallback::GetStream + Result: + (*inStream == NULL) - for directories + (*inStream == NULL) - if link (hard link or symbolic link) was created +*/ #define INTERFACE_IArchiveExtractCallback(x) \ INTERFACE_IProgress(x) \ - STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) x; \ + STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) x; \ STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \ STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) x; \ @@ -115,41 +151,175 @@ ARCHIVE_INTERFACE(IArchiveOpenSetSubArchiveName, 0x50) /* +IInArchive::Open + stream + if (kUseGlobalOffset), stream current position can be non 0. + if (!kUseGlobalOffset), stream current position is 0. + if (maxCheckStartPosition == NULL), the handler can try to search archive start in stream + if (*maxCheckStartPosition == 0), the handler must check only current position as archive start + IInArchive::Extract: indices must be sorted - numItems = 0xFFFFFFFF means "all files" + numItems = (UInt32)(Int32)-1 = 0xFFFFFFFF means "all files" testMode != 0 means "test files without writing to outStream" + +IInArchive::GetArchiveProperty: + kpidOffset - start offset of archive. + VT_EMPTY : means offset = 0. + VT_UI4, VT_UI8, VT_I8 : result offset; negative values is allowed + kpidPhySize - size of archive. VT_EMPTY means unknown size. + kpidPhySize is allowed to be larger than file size. In that case it must show + supposed size. + + kpidIsDeleted: + kpidIsAltStream: + kpidIsAux: + kpidINode: + must return VARIANT_TRUE (VT_BOOL), if archive can support that property in GetProperty. + + +Notes: + Don't call IInArchive functions for same IInArchive object from different threads simultaneously. + Some IInArchive handlers will work incorrectly in that case. */ #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; + STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback) throw() x; \ + STDMETHOD(Close)() throw() x; \ + STDMETHOD(GetNumberOfItems)(UInt32 *numItems) throw() x; \ + STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) throw() x; \ + STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) throw() x; \ + STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) throw() x; \ + STDMETHOD(GetNumberOfProperties)(UInt32 *numProps) throw() x; \ + STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) throw() x; \ + STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProps) throw() x; \ + STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) throw() x; ARCHIVE_INTERFACE(IInArchive, 0x60) { INTERFACE_IInArchive(PURE) }; +namespace NParentType +{ + enum + { + kDir = 0, + kAltStream + }; +}; + +namespace NPropDataType +{ + const UInt32 kMask_ZeroEnd = 1 << 4; + // const UInt32 kMask_BigEndian = 1 << 5; + const UInt32 kMask_Utf = 1 << 6; + // const UInt32 kMask_Utf8 = kMask_Utf | 0; + const UInt32 kMask_Utf16 = kMask_Utf | 1; + // const UInt32 kMask_Utf32 = kMask_Utf | 2; + + const UInt32 kNotDefined = 0; + const UInt32 kRaw = 1; + const UInt32 kUtf16z = kMask_Utf16 | kMask_ZeroEnd; +}; + +// UTF string (pointer to wchar_t) with zero end and little-endian. +#define PROP_DATA_TYPE_wchar_t_PTR_Z_LE ((NPropDataType::kMask_Utf | NPropDataType::kMask_ZeroEnd) + (sizeof(wchar_t) >> 1)) + +/* +GetRawProp: + Result: + S_OK - even if property is not set +*/ + +#define INTERFACE_IArchiveGetRawProps(x) \ + STDMETHOD(GetParent)(UInt32 index, UInt32 *parent, UInt32 *parentType) x; \ + STDMETHOD(GetRawProp)(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) x; \ + STDMETHOD(GetNumRawProps)(UInt32 *numProps) x; \ + STDMETHOD(GetRawPropInfo)(UInt32 index, BSTR *name, PROPID *propID) x; + +ARCHIVE_INTERFACE(IArchiveGetRawProps, 0x70) +{ + INTERFACE_IArchiveGetRawProps(PURE) +}; + +#define INTERFACE_IArchiveGetRootProps(x) \ + STDMETHOD(GetRootProp)(PROPID propID, PROPVARIANT *value) x; \ + STDMETHOD(GetRootRawProp)(PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) x; \ + +ARCHIVE_INTERFACE(IArchiveGetRootProps, 0x71) +{ + INTERFACE_IArchiveGetRootProps(PURE) +}; + ARCHIVE_INTERFACE(IArchiveOpenSeq, 0x61) { STDMETHOD(OpenSeq)(ISequentialInStream *stream) PURE; }; +/* + OpenForSize + Result: + S_FALSE - is not archive + ? - DATA error +*/ + +/* +const UInt32 kOpenFlags_RealPhySize = 1 << 0; +const UInt32 kOpenFlags_NoSeek = 1 << 1; +// const UInt32 kOpenFlags_BeforeExtract = 1 << 2; +*/ + +/* +Flags: + 0 - opens archive with IInStream, if IInStream interface is supported + - if phySize is not available, it doesn't try to make full parse to get phySize + kOpenFlags_NoSeek - ArcOpen2 function doesn't use IInStream interface, even if it's available + kOpenFlags_RealPhySize - the handler will try to get PhySize, even if it requires full decompression for file + + if handler is not allowed to use IInStream and the flag kOpenFlags_RealPhySize is not specified, + the handler can return S_OK, but it doesn't check even Signature. + So next Extract can be called for that sequential stream. +*/ + +/* +ARCHIVE_INTERFACE(IArchiveOpen2, 0x62) +{ + STDMETHOD(ArcOpen2)(ISequentialInStream *stream, UInt32 flags, IArchiveOpenCallback *openCallback) PURE; +}; +*/ + +// ---------- UPDATE ---------- + +/* +GetUpdateItemInfo outs: +*newData *newProps + 0 0 - Copy data and properties from archive + 0 1 - Copy data from archive, request new properties + 1 0 - that combination is unused now + 1 1 - Request new data and new properties. It can be used even for folders + + indexInArchive = -1 if there is no item in archive, or if it doesn't matter. + + +GetStream out: + Result: + S_OK: + (*inStream == NULL) - only for directories + - the bug was fixed in 9.33: (*Stream == NULL) was in case of anti-file + (*inStream != NULL) - for any file, even for empty file or anti-file + S_FALSE - skip that file (don't add item to archive) - (client code can't open stream of that file by some reason) + (*inStream == NULL) + +The order of calling for hard links: + - GetStream() + - GetProperty(kpidHardLink) + +*/ + #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(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProps, UInt32 *indexInArchive) x; \ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) x; \ STDMETHOD(SetOperationResult)(Int32 operationResult) x; \ @@ -169,6 +339,27 @@ ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82) INTERFACE_IArchiveUpdateCallback2(PURE); }; +/* +UpdateItems() +------------- + + outStream: output stream. (the handler) MUST support the case when + Seek position in outStream is not ZERO. + but the caller calls with empty outStream and seek position is ZERO?? + + archives with stub: + + If archive is open and the handler and (Offset > 0), then the handler + knows about stub size. + UpdateItems(): + 1) the handler MUST copy that stub to outStream + 2) the caller MUST NOT copy the stub to outStream, if + "rsfx" property is set with SetProperties + + the handler must support the case where + ISequentialOutStream *outStream +*/ + #define INTERFACE_IOutArchive(x) \ STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \ @@ -182,47 +373,61 @@ ARCHIVE_INTERFACE(IOutArchive, 0xA0) ARCHIVE_INTERFACE(ISetProperties, 0x03) { - STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) PURE; + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) PURE; +}; + +ARCHIVE_INTERFACE(IArchiveKeepModeForNextOpen, 0x04) +{ + STDMETHOD(KeepModeForNextOpen)() PURE; +}; + +/* Exe handler: the handler for executable format (PE, ELF, Mach-O). + SFX archive: executable stub + some tail data. + before 9.31: exe handler didn't parse SFX archives as executable format. + for 9.31+: exe handler parses SFX archives as executable format, only if AllowTail(1) was called */ + +ARCHIVE_INTERFACE(IArchiveAllowTail, 0x05) +{ + STDMETHOD(AllowTail)(Int32 allowTail) PURE; }; #define IMP_IInArchive_GetProp(k) \ (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ - { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ - const STATPROPSTG &srcItem = k[index]; \ - *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } \ + { if (index >= ARRAY_SIZE(k)) return E_INVALIDARG; \ + *propID = k[index]; *varType = k7z_PROPID_To_VARTYPE[(unsigned)*propID]; *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; \ + { if (index >= ARRAY_SIZE(k)) 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::GetNumberOfProperties(UInt32 *numProps) \ + { *numProps = ARRAY_SIZE(kProps); return S_OK; } \ STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp(kProps) #define IMP_IInArchive_Props_WITH_NAME \ - STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \ - { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ + STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) \ + { *numProps = ARRAY_SIZE(kProps); return S_OK; } \ STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kProps) #define IMP_IInArchive_ArcProps \ - STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ - { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \ + STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProps) \ + { *numProps = ARRAY_SIZE(kArcProps); return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp(kArcProps) #define IMP_IInArchive_ArcProps_WITH_NAME \ - STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ - { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \ + STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProps) \ + { *numProps = ARRAY_SIZE(kArcProps); return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kArcProps) #define IMP_IInArchive_ArcProps_NO_Table \ - STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ - { *numProperties = 0; return S_OK; } \ + STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProps) \ + { *numProps = 0; return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *) \ { return E_NOTIMPL; } \ @@ -231,4 +436,32 @@ ARCHIVE_INTERFACE(ISetProperties, 0x03) STDMETHODIMP CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value) \ { value->vt = VT_EMPTY; return S_OK; } + + +#define k_IsArc_Res_NO 0 +#define k_IsArc_Res_YES 1 +#define k_IsArc_Res_NEED_MORE 2 +// #define k_IsArc_Res_YES_LOW_PROB 3 + +#define API_FUNC_IsArc EXTERN_C UInt32 WINAPI +#define API_FUNC_static_IsArc EXTERN_C static UInt32 WINAPI + +extern "C" +{ + typedef HRESULT (WINAPI *Func_CreateObject)(const GUID *clsID, const GUID *iid, void **outObject); + + typedef UInt32 (WINAPI *Func_IsArc)(const Byte *p, size_t size); + typedef HRESULT (WINAPI *Func_GetIsArc)(UInt32 formatIndex, Func_IsArc *isArc); + + typedef HRESULT (WINAPI *Func_GetNumberOfFormats)(UInt32 *numFormats); + typedef HRESULT (WINAPI *Func_GetHandlerProperty)(PROPID propID, PROPVARIANT *value); + typedef HRESULT (WINAPI *Func_GetHandlerProperty2)(UInt32 index, PROPID propID, PROPVARIANT *value); + + typedef HRESULT (WINAPI *Func_SetCaseSensitive)(Int32 caseSensitive); + typedef HRESULT (WINAPI *Func_SetLargePageMode)(); + + typedef IOutArchive * (*Func_CreateOutArchive)(); + typedef IInArchive * (*Func_CreateInArchive)(); +} + #endif diff --git a/CPP/7zip/Archive/Icons/7z.ico b/CPP/7zip/Archive/Icons/7z.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Icons/arj.ico b/CPP/7zip/Archive/Icons/arj.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Icons/bz2.ico b/CPP/7zip/Archive/Icons/bz2.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Icons/cab.ico b/CPP/7zip/Archive/Icons/cab.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Icons/cpio.ico b/CPP/7zip/Archive/Icons/cpio.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Icons/deb.ico b/CPP/7zip/Archive/Icons/deb.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Icons/dmg.ico b/CPP/7zip/Archive/Icons/dmg.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Icons/fat.ico b/CPP/7zip/Archive/Icons/fat.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Icons/gz.ico b/CPP/7zip/Archive/Icons/gz.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Icons/hfs.ico b/CPP/7zip/Archive/Icons/hfs.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Icons/iso.ico b/CPP/7zip/Archive/Icons/iso.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Icons/lzh.ico b/CPP/7zip/Archive/Icons/lzh.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Icons/lzma.ico b/CPP/7zip/Archive/Icons/lzma.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Icons/ntfs.ico b/CPP/7zip/Archive/Icons/ntfs.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Icons/rar.ico b/CPP/7zip/Archive/Icons/rar.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Icons/rpm.ico b/CPP/7zip/Archive/Icons/rpm.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Icons/split.ico b/CPP/7zip/Archive/Icons/split.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Icons/squashfs.ico b/CPP/7zip/Archive/Icons/squashfs.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Icons/tar.ico b/CPP/7zip/Archive/Icons/tar.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Icons/vhd.ico b/CPP/7zip/Archive/Icons/vhd.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Icons/wim.ico b/CPP/7zip/Archive/Icons/wim.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Icons/xar.ico b/CPP/7zip/Archive/Icons/xar.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Icons/xz.ico b/CPP/7zip/Archive/Icons/xz.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Icons/z.ico b/CPP/7zip/Archive/Icons/z.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Icons/zip.ico b/CPP/7zip/Archive/Icons/zip.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/IhexHandler.cpp b/CPP/7zip/Archive/IhexHandler.cpp new file mode 100644 index 00000000..bc468401 --- /dev/null +++ b/CPP/7zip/Archive/IhexHandler.cpp @@ -0,0 +1,500 @@ +// IhexHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "../../Common/ComTry.h" +#include "../../Common/DynamicBuffer.h" +#include "../../Common/IntToString.h" +#include "../../Common/MyVector.h" + +#include "../../Windows/PropVariant.h" + +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" +#include "../Common/InBuffer.h" + +namespace NArchive { +namespace NIhex { + +/* We still don't support files with custom record types: 20, 22: used by Samsung */ + +struct CBlock +{ + CByteDynamicBuffer Data; + UInt32 Offset; +}; + +class CHandler: + public IInArchive, + public CMyUnknownImp +{ + bool _isArc; + bool _needMoreInput; + bool _dataError; + + UInt64 _phySize; + + CObjectVector _blocks; +public: + MY_UNKNOWN_IMP1(IInArchive) + INTERFACE_IInArchive(;) +}; + +static const Byte kProps[] = +{ + kpidPath, + kpidSize, + kpidVa +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO_Table + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _blocks.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NWindows::NCOM::CPropVariant prop; + switch (propID) + { + case kpidPhySize: if (_phySize != 0) prop = _phySize; break; + case kpidErrorFlags: + { + UInt32 v = 0; + if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;; + if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd; + if (_dataError) v |= kpv_ErrorFlags_DataError; + prop = v; + } + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + const CBlock &block = _blocks[index]; + switch (propID) + { + case kpidSize: prop = block.Data.GetPos(); break; + case kpidVa: prop = block.Offset; break; + case kpidPath: + { + if (_blocks.Size() != 1) + { + char s[16]; + ConvertUInt32ToString(index, s); + prop = s; + } + break; + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +static inline int HexToByte(char c) +{ + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'A' && c <= 'F') return c - 'A' + 10; + if (c >= 'a' && c <= 'f') return c - 'a' + 10; + return -1; +} + +static int Parse(const Byte *p) +{ + int c1 = HexToByte(p[0]); if (c1 < 0) return -1; + int c2 = HexToByte(p[1]); if (c2 < 0) return -1; + return (c1 << 4) | c2; +} + +#define kType_Data 0 +#define kType_Eof 1 +#define kType_Seg 2 +#define kType_CsIp 3 +#define kType_High 4 +#define kType_Ip32 5 + +#define kType_MAX 5 + +#define IS_LINE_DELIMITER(c) ((c) == 0 || (c) == 10 || (c) == 13) + +API_FUNC_static_IsArc IsArc_Ihex(const Byte *p, size_t size) +{ + if (size < 1) + return k_IsArc_Res_NEED_MORE; + if (p[0] != ':') + return k_IsArc_Res_NO; + p++; + size--; + + const int kNumLinesToCheck = 3; // 1 line is OK also, but we don't want false detection + + for (int j = 0; j < kNumLinesToCheck; j++) + { + if (size < 4 * 2) + return k_IsArc_Res_NEED_MORE; + + int num = Parse(p); + if (num < 0) + return k_IsArc_Res_NO; + + int type = Parse(p + 6); + if (type < 0 || type > kType_MAX) + return k_IsArc_Res_NO; + + unsigned numChars = ((unsigned)num + 5) * 2; + unsigned sum = 0; + + for (unsigned i = 0; i < numChars; i += 2) + { + if (i + 2 > size) + return k_IsArc_Res_NEED_MORE; + int v = Parse(p + i); + if (v < 0) + return k_IsArc_Res_NO; + sum += (unsigned)v; + } + + if ((sum & 0xFF) != 0) + return k_IsArc_Res_NO; + + if (type == kType_Data) + { + // we don't want to open :0000000000 files + if (num == 0) + return k_IsArc_Res_NO; + } + else + { + if (type == kType_Eof) + { + if (num != 0) + return k_IsArc_Res_NO; + return k_IsArc_Res_YES; + } + if (p[2] != 0 || + p[3] != 0 || + p[4] != 0 || + p[5] != 0) + return k_IsArc_Res_NO; + if (type == kType_Seg || type == kType_High) + { + if (num != 2) + return k_IsArc_Res_NO; + } + else + { + if (num != 4) + return k_IsArc_Res_NO; + } + } + + p += numChars; + size -= numChars; + + for (;;) + { + if (size == 0) + return k_IsArc_Res_NEED_MORE; + char b = *p++; + size--; + if (IS_LINE_DELIMITER(b)) + continue; + if (b == ':') + break; + return k_IsArc_Res_NO; + } + } + + return k_IsArc_Res_YES; +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *) +{ + COM_TRY_BEGIN + { + Close(); + try + { + const unsigned kStartSize = (2 + (256 + 5) + 2) * 2; + Byte temp[kStartSize]; + { + size_t size = kStartSize; + RINOK(ReadStream(stream, temp, &size)); + UInt32 isArcRes = IsArc_Ihex(temp, size); + if (isArcRes == k_IsArc_Res_NO) + return S_FALSE; + if (isArcRes == k_IsArc_Res_NEED_MORE && size != kStartSize) + return S_FALSE; + } + _isArc = true; + + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + CInBuffer s; + if (!s.Create(1 << 15)) + return E_OUTOFMEMORY; + s.SetStream(stream); + s.Init(); + + { + Byte b; + if (!s.ReadByte(b)) + { + _needMoreInput = true; + return S_FALSE; + } + if (b != ':') + { + _dataError = true; + return S_FALSE; + } + } + + UInt32 globalOffset = 0; + + for (;;) + { + if (s.ReadBytes(temp, 2) != 2) + { + _needMoreInput = true; + return S_FALSE; + } + int num = Parse(temp); + if (num < 0) + { + _dataError = true; + return S_FALSE; + } + + { + size_t numPairs = (num + 4); + size_t numBytes = numPairs * 2; + if (s.ReadBytes(temp, numBytes) != numBytes) + { + _needMoreInput = true; + return S_FALSE; + } + + int sum = num; + for (size_t i = 0; i < numPairs; i++) + { + int a = Parse(temp + i * 2); + if (a < 0) + { + _dataError = true; + return S_FALSE; + } + temp[i] = (Byte)a; + sum += a; + } + if ((sum & 0xFF) != 0) + { + _dataError = true; + return S_FALSE; + } + } + + unsigned type = temp[2]; + if (type > kType_MAX) + { + _dataError = true; + return S_FALSE; + } + + UInt32 a = GetBe16(temp); + + if (type == kType_Data) + { + if (num == 0) + { + // we don't want to open :0000000000 files + // maybe it can mean EOF in old-style files? + _dataError = true; + return S_FALSE; + } + // if (num != 0) + { + UInt32 offs = globalOffset + a; + CBlock *block = NULL; + if (!_blocks.IsEmpty()) + { + block = &_blocks.Back(); + if (block->Offset + block->Data.GetPos() != offs) + block = NULL; + } + if (!block) + { + block = &_blocks.AddNew(); + block->Offset = offs; + } + memcpy(block->Data.GetCurPtrAndGrow(num), temp + 3, num); + } + } + else if (type == kType_Eof) + { + _phySize = s.GetProcessedSize(); + { + Byte b; + if (s.ReadByte(b)) + { + if (b == 10) + _phySize++; + else if (b == 13) + { + _phySize++; + if (s.ReadByte(b)) + { + if (b == 10) + _phySize++; + } + } + } + } + return S_OK; + } + else + { + if (a != 0) + { + _dataError = true; + return S_FALSE; + } + if (type == kType_Seg || type == kType_High) + { + if (num != 2) + { + _dataError = true; + return S_FALSE; + } + UInt32 d = GetBe16(temp + 3); + globalOffset = d << (type == kType_Seg ? 4 : 16); + } + else + { + if (num != 4) + { + _dataError = true; + return S_FALSE; + } + } + } + + for (;;) + { + Byte b; + if (!s.ReadByte(b)) + { + _needMoreInput = true; + return S_FALSE; + } + if (IS_LINE_DELIMITER(b)) + continue; + if (b == ':') + break; + _dataError = true; + return S_FALSE; + } + } + } + catch(const CInBufferException &e) { return e.ErrorCode; } + } + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _phySize = 0; + + _isArc = false; + _needMoreInput = false; + _dataError = false; + + _blocks.Clear(); + return S_OK; +} + + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)(Int32)-1); + if (allFilesMode) + numItems = _blocks.Size(); + if (numItems == 0) + return S_OK; + + UInt64 totalSize = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + totalSize += _blocks[allFilesMode ? i : indices[i]].Data.GetPos(); + extractCallback->SetTotal(totalSize); + + UInt64 currentTotalSize = 0; + UInt64 currentItemSize; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) + { + currentItemSize = 0; + lps->InSize = lps->OutSize = currentTotalSize; + RINOK(lps->SetCur()); + + UInt32 index = allFilesMode ? i : indices[i]; + const CByteDynamicBuffer &data = _blocks[index].Data; + currentItemSize = data.GetPos(); + + CMyComPtr realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + if (!testMode && !realOutStream) + continue; + + extractCallback->PrepareOperation(askMode); + + if (realOutStream) + { + RINOK(WriteStream(realOutStream, (const Byte *)data, data.GetPos())); + } + + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + } + + lps->InSize = lps->OutSize = currentTotalSize; + return lps->SetCur(); + + COM_TRY_END +} + +IMP_CreateArcIn + +static CArcInfo g_ArcInfo = + { "IHex", "ihex", 0, 0xCD, + 0, { 0 }, + // 2, { ':', '1' }, + 0, + NArcInfoFlags::kStartOpen, + CreateArc, NULL, IsArc_Ihex }; + +REGISTER_ARC(Z) + +}} diff --git a/CPP/7zip/Archive/Iso/IsoHandler.cpp b/CPP/7zip/Archive/Iso/IsoHandler.cpp old mode 100755 new mode 100644 index f040b033..fc984048 --- a/CPP/7zip/Archive/Iso/IsoHandler.cpp +++ b/CPP/7zip/Archive/Iso/IsoHandler.cpp @@ -2,12 +2,12 @@ #include "StdAfx.h" -#include "Common/ComTry.h" -#include "Common/IntToString.h" -#include "Common/StringConvert.h" +#include "../../../Common/ComTry.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" -#include "Windows/PropVariant.h" -#include "Windows/Time.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/TimeUtils.h" #include "../../Common/LimitedStreams.h" #include "../../Common/ProgressUtils.h" @@ -24,22 +24,21 @@ using namespace NTime; namespace NArchive { namespace NIso { -static const STATPROPSTG kProps[] = +static const Byte kProps[] = { - { NULL, kpidPath, VT_BSTR}, - { NULL, kpidIsDir, VT_BOOL}, - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, - { NULL, kpidMTime, VT_FILETIME} + kpidPath, + kpidIsDir, + kpidSize, + kpidPackSize, + kpidMTime }; -static const STATPROPSTG kArcProps[] = +static const Byte kArcProps[] = { - { NULL, kpidComment, VT_BSTR}, - { NULL, kpidCTime, VT_FILETIME}, - { NULL, kpidMTime, VT_FILETIME} - // { NULL, kpidPhySize, VT_UI8}, - // { NULL, kpidHeadersSize, VT_UI8} + kpidComment, + kpidCTime, + kpidMTime, + // kpidHeadersSize }; IMP_IInArchive_Props @@ -51,13 +50,10 @@ STDMETHODIMP CHandler::Open(IInStream *stream, { COM_TRY_BEGIN Close(); - // try { - if (_archive.Open(stream) != S_OK) - return S_FALSE; + RINOK(_archive.Open(stream)); _stream = stream; } - // catch(...) { return S_FALSE; } return S_OK; COM_TRY_END } @@ -75,9 +71,9 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) return S_OK; } -static void AddString(AString &s, const char *name, const Byte *p, int size) +static void AddString(AString &s, const char *name, const Byte *p, unsigned size) { - int i; + unsigned i; for (i = 0; i < size && p[i]; i++); for (; i > 0 && p[i - 1] == ' '; i--); if (i != 0) @@ -94,12 +90,21 @@ static void AddString(AString &s, const char *name, const Byte *p, int size) #define ADD_STRING(n, v) AddString(s, n, vol. ## v, sizeof(vol. ## v)) +static void AddErrorMessage(AString &s, const char *message) +{ + if (!s.IsEmpty()) + s += ". "; + s += message; +} + STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; + NCOM::CPropVariant prop; + if (_stream) + { const CVolumeDescriptor &vol = _archive.VolDescs[_archive.MainVolDescIndex]; - switch(propID) + switch (propID) { case kpidComment: { @@ -118,9 +123,35 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) } 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; + } + } + + switch (propID) + { + case kpidPhySize: prop = _archive.PhySize; break; + case kpidErrorFlags: + { + UInt32 v = 0; + if (!_archive.IsArc) v |= kpv_ErrorFlags_IsNotArc; + if (_archive.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd; + if (_archive.HeadersError) v |= kpv_ErrorFlags_HeadersError; + prop = v; + break; + } + + case kpidError: + { + AString s; + if (_archive.IncorrectBigEndian) + AddErrorMessage(s, "Incorrect big-endian headers"); + if (_archive.SelfLinkedDirs) + AddErrorMessage(s, "Self-linked directory"); + if (_archive.TooDeepDirs) + AddErrorMessage(s, "Too deep directory levels"); + if (!s.IsEmpty()) + prop = s; + break; + } } prop.Detach(value); return S_OK; @@ -130,22 +161,22 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; + NCOM::CPropVariant prop; if (index >= (UInt32)_archive.Refs.Size()) { index -= _archive.Refs.Size(); const CBootInitialEntry &be = _archive.BootEntries[index]; - switch(propID) + switch (propID) { case kpidPath: { - // wchar_t name[32]; - // ConvertUInt64ToString(index + 1, name); - UString s = L"[BOOT]" WSTRING_PATH_SEPARATOR; + // char name[16]; + // ConvertUInt32ToString(index + 1, name); + AString s = "[BOOT]" STRING_PATH_SEPARATOR; // s += name; - // s += L"-"; + // s += '-'; s += be.GetName(); - prop = (const wchar_t *)s; + prop = s; break; } case kpidIsDir: prop = false; break; @@ -159,7 +190,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { const CRef &ref = _archive.Refs[index]; const CDir &item = ref.Dir->_subItems[ref.Index]; - switch(propID) + switch (propID) { case kpidPath: // if (item.FileId.GetCapacity() >= 0) @@ -171,9 +202,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val s = MultiByteToUnicodeString(item.GetPath(_archive.IsSusp, _archive.SuspSkipSize), CP_OEMCP); int pos = s.ReverseFind(L';'); - if (pos >= 0 && pos == s.Length() - 2) + if (pos >= 0 && pos == (int)s.Len() - 2) if (s.Back() == L'1') - s = s.Left(pos); + s.DeleteFrom(pos); if (!s.IsEmpty()) if (s.Back() == L'.') s.DeleteBack(); @@ -184,7 +215,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidSize: case kpidPackSize: if (!item.IsDir()) - prop = (UInt64)item.DataLength; + prop = (UInt64)ref.TotalSize; break; case kpidMTime: { @@ -204,7 +235,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _archive.Refs.Size(); if (numItems == 0) @@ -219,7 +250,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, const CRef &ref = _archive.Refs[index]; const CDir &item = ref.Dir->_subItems[ref.Index]; if (!item.IsDir()) - totalSize += item.DataLength; + totalSize += ref.TotalSize; } else totalSize += _archive.GetBootItemSize(index - _archive.Refs.Size()); @@ -240,9 +271,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, 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; @@ -267,28 +295,54 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); continue; } - currentItemSize = item.DataLength; + currentItemSize = ref.TotalSize; blockIndex = item.ExtentLocation; } else { - int bootIndex = index - _archive.Refs.Size(); + unsigned 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); + + bool isOK = true; + if (index < (UInt32)_archive.Refs.Size()) + { + const CRef &ref = _archive.Refs[index]; + UInt64 offset = 0; + for (UInt32 e = 0; e < ref.NumExtents; e++) + { + if (e != 0) + lps->InSize = lps->OutSize = currentTotalSize + offset; + const CDir &item2 = ref.Dir->_subItems[ref.Index + e]; + RINOK(_stream->Seek(item2.ExtentLocation * _archive.BlockSize, STREAM_SEEK_SET, NULL)); + streamSpec->Init(item2.Size); + RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); + if (copyCoderSpec->TotalSize != item2.Size) + { + isOK = false; + break; + } + offset += item2.Size; + } + } + else + { + RINOK(_stream->Seek(blockIndex * _archive.BlockSize, STREAM_SEEK_SET, NULL)); + streamSpec->Init(currentItemSize); + RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); + if (copyCoderSpec->TotalSize != currentItemSize) + isOK = false; + } 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() ? + RINOK(extractCallback->SetOperationResult(isOK ? NExtract::NOperationResult::kOK: NExtract::NOperationResult::kDataError)); } @@ -308,12 +362,42 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) const CDir &item = ref.Dir->_subItems[ref.Index]; if (item.IsDir()) return S_FALSE; - currentItemSize = item.DataLength; + + if (ref.NumExtents > 1) + { + CExtentsStream *extentStreamSpec = new CExtentsStream(); + CMyComPtr extentStream = extentStreamSpec; + + extentStreamSpec->Stream = _stream; + + UInt64 virtOffset = 0; + for (UInt32 i = 0; i < ref.NumExtents; i++) + { + const CDir &item = ref.Dir->_subItems[ref.Index + i]; + if (item.Size == 0) + continue; + CSeekExtent se; + se.Phy = (UInt64)item.ExtentLocation * _archive.BlockSize; + se.Virt = virtOffset; + extentStreamSpec->Extents.Add(se); + virtOffset += item.Size; + } + if (virtOffset != ref.TotalSize) + return S_FALSE; + CSeekExtent se; + se.Phy = 0; + se.Virt = virtOffset; + extentStreamSpec->Extents.Add(se); + extentStreamSpec->Init(); + *stream = extentStream.Detach(); + return S_OK; + } + currentItemSize = item.Size; blockIndex = item.ExtentLocation; } else { - int bootIndex = index - _archive.Refs.Size(); + unsigned bootIndex = index - _archive.Refs.Size(); const CBootInitialEntry &be = _archive.BootEntries[bootIndex]; currentItemSize = _archive.GetBootItemSize(bootIndex); blockIndex = be.LoadRBA; diff --git a/CPP/7zip/Archive/Iso/IsoHandler.h b/CPP/7zip/Archive/Iso/IsoHandler.h old mode 100755 new mode 100644 index 1dcade8f..1923784d --- a/CPP/7zip/Archive/Iso/IsoHandler.h +++ b/CPP/7zip/Archive/Iso/IsoHandler.h @@ -3,7 +3,8 @@ #ifndef __ISO_HANDLER_H #define __ISO_HANDLER_H -#include "Common/MyCom.h" +#include "../../../Common/MyCom.h" + #include "../IArchive.h" #include "IsoIn.h" diff --git a/CPP/7zip/Archive/Iso/IsoHeader.cpp b/CPP/7zip/Archive/Iso/IsoHeader.cpp old mode 100755 new mode 100644 index b3e418bb..1cd2516c --- a/CPP/7zip/Archive/Iso/IsoHeader.cpp +++ b/CPP/7zip/Archive/Iso/IsoHeader.cpp @@ -9,13 +9,13 @@ namespace NIso { const char *kElToritoSpec = "EL TORITO SPECIFICATION\0\0\0\0\0\0\0\0\0"; -const wchar_t *kMediaTypes[5] = +const char *kMediaTypes[5] = { - L"NoEmulation", - L"1.2M", - L"1.44M", - L"2.88M", - L"HardDisk" + "NoEmulation" + , "1.2M" + , "1.44M" + , "2.88M" + , "HardDisk" }; }} diff --git a/CPP/7zip/Archive/Iso/IsoHeader.h b/CPP/7zip/Archive/Iso/IsoHeader.h old mode 100755 new mode 100644 index 9702d70a..ce21b0ff --- a/CPP/7zip/Archive/Iso/IsoHeader.h +++ b/CPP/7zip/Archive/Iso/IsoHeader.h @@ -3,7 +3,7 @@ #ifndef __ARCHIVE_ISO_HEADER_H #define __ARCHIVE_ISO_HEADER_H -#include "Common/Types.h" +#include "../../../Common/MyTypes.h" namespace NArchive { namespace NIso { @@ -22,6 +22,7 @@ const Byte kVersion = 1; namespace NFileFlags { const Byte kDirectory = 1 << 1; + const Byte kNonFinalExtent = 1 << 7; } extern const char *kElToritoSpec; @@ -42,7 +43,7 @@ namespace NBootPlatformId const Byte kMac = 2; } -const BYTE kBootMediaTypeMask = 0xF; +const Byte kBootMediaTypeMask = 0xF; namespace NBootMediaType { @@ -53,8 +54,8 @@ namespace NBootMediaType const Byte kHardDisk = 4; } -const int kNumBootMediaTypes = 5; -extern const wchar_t *kMediaTypes[]; +const unsigned kNumBootMediaTypes = 5; +extern const char *kMediaTypes[]; }} diff --git a/CPP/7zip/Archive/Iso/IsoIn.cpp b/CPP/7zip/Archive/Iso/IsoIn.cpp old mode 100755 new mode 100644 index 7ed618d2..ba12acae --- a/CPP/7zip/Archive/Iso/IsoIn.cpp +++ b/CPP/7zip/Archive/Iso/IsoIn.cpp @@ -2,24 +2,34 @@ #include "StdAfx.h" -#include "IsoIn.h" +#include "../../../Common/MyException.h" #include "../../Common/StreamUtils.h" +#include "IsoIn.h" + namespace NArchive { namespace NIso { +struct CUnexpectedEndException {}; +struct CHeaderErrorException {}; +struct CEndianErrorException {}; + 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; + size_t processed = BlockSize; + HRESULT res = ReadStream(_stream, m_Buffer, &processed); + if (res != S_OK) + throw CSystemException(res); + if (processed != BlockSize) + throw CUnexpectedEndException(); + UInt64 end = _position + processed; + if (PhySize < end) + PhySize = end; } Byte b = m_Buffer[m_BufferPos++]; _position++; @@ -44,16 +54,16 @@ void CInArchive::SkipZeros(size_t size) { Byte b = ReadByte(); if (b != 0) - throw 1; + throw CHeaderErrorException(); } } UInt16 CInArchive::ReadUInt16Spec() { - UInt16 value = 0; + UInt16 val = 0; for (int i = 0; i < 2; i++) - value |= ((UInt16)(ReadByte()) << (8 * i)); - return value; + val |= ((UInt16)(ReadByte()) << (8 * i)); + return val; } @@ -61,47 +71,47 @@ UInt16 CInArchive::ReadUInt16() { Byte b[4]; ReadBytes(b, 4); - UInt32 value = 0; + UInt32 val = 0; for (int i = 0; i < 2; i++) { if (b[i] != b[3 - i]) IncorrectBigEndian = true; - value |= ((UInt16)(b[i]) << (8 * i)); + val |= ((UInt16)(b[i]) << (8 * i)); } - return (UInt16)value; + return (UInt16)val; } UInt32 CInArchive::ReadUInt32Le() { - UInt32 value = 0; + UInt32 val = 0; for (int i = 0; i < 4; i++) - value |= ((UInt32)(ReadByte()) << (8 * i)); - return value; + val |= ((UInt32)(ReadByte()) << (8 * i)); + return val; } UInt32 CInArchive::ReadUInt32Be() { - UInt32 value = 0; + UInt32 val = 0; for (int i = 0; i < 4; i++) { - value <<= 8; - value |= ReadByte(); + val <<= 8; + val |= ReadByte(); } - return value; + return val; } UInt32 CInArchive::ReadUInt32() { Byte b[8]; ReadBytes(b, 8); - UInt32 value = 0; + UInt32 val = 0; for (int i = 0; i < 4; i++) { if (b[i] != b[7 - i]) - throw 1; - value |= ((UInt32)(b[i]) << (8 * i)); + throw CEndianErrorException(); + val |= ((UInt32)(b[i]) << (8 * i)); } - return value; + return val; } UInt32 CInArchive::ReadDigits(int numDigits) @@ -115,7 +125,7 @@ UInt32 CInArchive::ReadDigits(int numDigits) if (b == 0) // it's bug in some CD's b = '0'; else - throw 1; + throw CHeaderErrorException(); } UInt32 d = (UInt32)(b - '0'); res *= 10; @@ -158,16 +168,16 @@ void CInArchive::ReadDirRecord2(CDirRecord &r, Byte len) { r.ExtendedAttributeRecordLen = ReadByte(); if (r.ExtendedAttributeRecordLen != 0) - throw 1; + throw CHeaderErrorException(); r.ExtentLocation = ReadUInt32(); - r.DataLength = ReadUInt32(); + r.Size = ReadUInt32(); ReadRecordingDateTime(r.DateTime); r.FileFlags = ReadByte(); r.FileUnitSize = ReadByte(); r.InterleaveGapSize = ReadByte(); r.VolSequenceNumber = ReadUInt16(); Byte idLen = ReadByte(); - r.FileId.SetCapacity(idLen); + r.FileId.Alloc(idLen); ReadBytes((Byte *)r.FileId, idLen); int padSize = 1 - (idLen & 1); @@ -176,9 +186,9 @@ void CInArchive::ReadDirRecord2(CDirRecord &r, Byte len) int curPos = 33 + idLen + padSize; if (curPos > len) - throw 1; + throw CHeaderErrorException(); int rem = len - curPos; - r.SystemUse.SetCapacity(rem); + r.SystemUse.Alloc(rem); ReadBytes((Byte *)r.SystemUse, rem); } @@ -242,15 +252,34 @@ static inline bool CheckSignature(const Byte *sig, const Byte *data) void CInArchive::SeekToBlock(UInt32 blockIndex) { - if (_stream->Seek((UInt64)blockIndex * VolDescs[MainVolDescIndex].LogicalBlockSize, STREAM_SEEK_SET, &_position) != S_OK) - throw 1; + HRESULT res = _stream->Seek((UInt64)blockIndex * VolDescs[MainVolDescIndex].LogicalBlockSize, STREAM_SEEK_SET, &_position); + if (res != S_OK) + throw CSystemException(res); m_BufferPos = 0; } +static const int kNumLevelsMax = 256; + void CInArchive::ReadDir(CDir &d, int level) { if (!d.IsDir()) return; + if (level > kNumLevelsMax) + { + TooDeepDirs = true; + return; + } + + { + FOR_VECTOR (i, UniqStartLocations) + if (UniqStartLocations[i] == d.ExtentLocation) + { + SelfLinkedDirs = true; + return; + } + UniqStartLocations.Add(d.ExtentLocation); + } + SeekToBlock(d.ExtentLocation); UInt64 startPos = _position; @@ -258,7 +287,7 @@ void CInArchive::ReadDir(CDir &d, int level) for (;;) { UInt64 offset = _position - startPos; - if (offset >= d.DataLength) + if (offset >= d.Size) break; Byte len = ReadByte(); if (len == 0) @@ -273,21 +302,44 @@ void CInArchive::ReadDir(CDir &d, int level) firstItem = false; } - for (int i = 0; i < d._subItems.Size(); i++) + FOR_VECTOR (i, d._subItems) ReadDir(d._subItems[i], level + 1); + + UniqStartLocations.DeleteBack(); } void CInArchive::CreateRefs(CDir &d) { if (!d.IsDir()) return; - for (int i = 0; i < d._subItems.Size(); i++) + for (unsigned i = 0; i < d._subItems.Size();) { CRef ref; CDir &subItem = d._subItems[i]; subItem.Parent = &d; ref.Dir = &d; - ref.Index = i; + ref.Index = i++; + ref.NumExtents = 1; + ref.TotalSize = subItem.Size; + if (subItem.IsNonFinalExtent()) + { + for (;;) + { + if (i == d._subItems.Size()) + { + HeadersError = true; + break; + } + const CDir &next = d._subItems[i]; + if (!subItem.AreMultiPartEqualWith(next)) + break; + i++; + ref.NumExtents++; + ref.TotalSize += next.Size; + if (!next.IsNonFinalExtent()) + break; + } + } Refs.Add(ref); CreateRefs(subItem); } @@ -310,13 +362,13 @@ void CInArchive::ReadBootInfo() CBootValidationEntry e; e.PlatformId = ReadByte(); if (ReadUInt16Spec() != 0) - throw 1; + throw CHeaderErrorException(); ReadBytes(e.Id, sizeof(e.Id)); /* UInt16 checkSum = */ ReadUInt16Spec(); if (ReadByte() != 0x55) - throw 1; + throw CHeaderErrorException(); if (ReadByte() != 0xAA) - throw 1; + throw CHeaderErrorException(); } b = ReadByte(); if (b == NBootEntryId::kInitialEntryBootable || b == NBootEntryId::kInitialEntryNotBootable) @@ -327,11 +379,11 @@ void CInArchive::ReadBootInfo() e.LoadSegment = ReadUInt16Spec(); e.SystemType = ReadByte(); if (ReadByte() != 0) - throw 1; + throw CHeaderErrorException(); e.SectorCount = ReadUInt16Spec(); e.LoadRBA = ReadUInt32Le(); if (ReadByte() != 0) - throw 1; + throw CHeaderErrorException(); BootEntries.Add(e); } else @@ -340,16 +392,22 @@ void CInArchive::ReadBootInfo() HRESULT CInArchive::Open2() { - Clear(); - RINOK(_stream->Seek(kStartPos, STREAM_SEEK_CUR, &_position)); + _position = 0; + RINOK(_stream->Seek(0, STREAM_SEEK_END, &_fileSize)); + if (_fileSize < kStartPos) + return S_FALSE; + RINOK(_stream->Seek(kStartPos, STREAM_SEEK_SET, &_position)); + PhySize = _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; @@ -372,9 +430,10 @@ HRESULT CInArchive::Open2() continue; */ } + // version = 2 for ISO 9660:1999? if (ver > 2) - throw S_FALSE; + return S_FALSE; if (sig[0] == NVolDescType::kTerminator) { @@ -382,7 +441,8 @@ HRESULT CInArchive::Open2() // Skip(0x800 - 7); // continue; } - switch(sig[0]) + + switch (sig[0]) { case NVolDescType::kBootRecord: { @@ -408,6 +468,7 @@ HRESULT CInArchive::Open2() break; } } + if (VolDescs.IsEmpty()) return S_FALSE; for (MainVolDescIndex = VolDescs.Size() - 1; MainVolDescIndex > 0; MainVolDescIndex--) @@ -417,30 +478,58 @@ HRESULT CInArchive::Open2() const CVolumeDescriptor &vd = VolDescs[MainVolDescIndex]; if (vd.LogicalBlockSize != kBlockSize) return S_FALSE; + + IsArc = true; + (CDirRecord &)_rootDir = vd.RootDirRecord; ReadDir(_rootDir, 0); CreateRefs(_rootDir); ReadBootInfo(); + + { + FOR_VECTOR(i, Refs) + { + const CRef &ref = Refs[i]; + for (UInt32 j = 0; j < ref.NumExtents; j++) + { + const CDir &item = ref.Dir->_subItems[ref.Index + j]; + if (!item.IsDir()) + UpdatePhySize(item.ExtentLocation, item.Size); + } + } + } + { + FOR_VECTOR(i, BootEntries) + { + const CBootInitialEntry &be = BootEntries[i]; + UpdatePhySize(be.LoadRBA, GetBootItemSize(i)); + } + } return S_OK; } HRESULT CInArchive::Open(IInStream *inStream) { + Clear(); _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; + try { return Open2(); } + catch(const CSystemException &e) { return e.ErrorCode; } + catch(CUnexpectedEndException &) { UnexpectedEnd = true; return S_FALSE; } + catch(CHeaderErrorException &) { HeadersError = true; return S_FALSE; } + catch(CEndianErrorException &) { IncorrectBigEndian = true; return S_FALSE; } } void CInArchive::Clear() { + IsArc = false; + UnexpectedEnd = false; + HeadersError = false; IncorrectBigEndian = false; + TooDeepDirs = false; + SelfLinkedDirs = false; + + UniqStartLocations.Clear(); + Refs.Clear(); _rootDir.Clear(); VolDescs.Clear(); diff --git a/CPP/7zip/Archive/Iso/IsoIn.h b/CPP/7zip/Archive/Iso/IsoIn.h old mode 100755 new mode 100644 index f9c6f640..614b3744 --- a/CPP/7zip/Archive/Iso/IsoIn.h +++ b/CPP/7zip/Archive/Iso/IsoIn.h @@ -3,8 +3,8 @@ #ifndef __ARCHIVE_ISO_IN_H #define __ARCHIVE_ISO_IN_H -#include "Common/IntToString.h" -#include "Common/MyCom.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/MyCom.h" #include "../../IStream.h" @@ -25,37 +25,37 @@ struct CDir: public CDirRecord _subItems.Clear(); } - int GetLength(bool checkSusp, int skipSize) const + unsigned GetLen(bool checkSusp, unsigned skipSize) const { - int len = GetLengthCur(checkSusp, skipSize); + unsigned len = GetLenCur(checkSusp, skipSize); if (Parent != 0) if (Parent->Parent != 0) - len += 1 + Parent->GetLength(checkSusp, skipSize); + len += 1 + Parent->GetLen(checkSusp, skipSize); return len; } - int GetLengthU() const + unsigned GetLenU() const { - int len = (int)(FileId.GetCapacity() / 2); + unsigned len = (unsigned)(FileId.Size() / 2); if (Parent != 0) if (Parent->Parent != 0) - len += 1 + Parent->GetLengthU(); + len += 1 + Parent->GetLenU(); return len; } - AString GetPath(bool checkSusp, int skipSize) const + AString GetPath(bool checkSusp, unsigned skipSize) const { AString s; - int len = GetLength(checkSusp, skipSize); - char *p = s.GetBuffer(len + 1); + unsigned len = GetLen(checkSusp, skipSize); + char *p = s.GetBuffer(len); p += len; *p = 0; const CDir *cur = this; for (;;) { - int curLen = cur->GetLengthCur(checkSusp, skipSize); + unsigned curLen = cur->GetLenCur(checkSusp, skipSize); p -= curLen; - memmove(p, (const char *)(const Byte *)cur->GetNameCur(checkSusp, skipSize), curLen); + memcpy(p, (const char *)(const Byte *)cur->GetNameCur(checkSusp, skipSize), curLen); cur = cur->Parent; if (cur == 0) break; @@ -71,16 +71,16 @@ struct CDir: public CDirRecord UString GetPathU() const { UString s; - int len = GetLengthU(); - wchar_t *p = s.GetBuffer(len + 1); + unsigned len = GetLenU(); + wchar_t *p = s.GetBuffer(len); p += len; *p = 0; const CDir *cur = this; for (;;) { - int curLen = (int)(cur->FileId.GetCapacity() / 2); + unsigned curLen = (unsigned)(cur->FileId.Size() / 2); p -= curLen; - for (int i = 0; i < curLen; i++) + for (unsigned i = 0; i < curLen; i++) { Byte b0 = ((const Byte *)cur->FileId)[i * 2]; Byte b1 = ((const Byte *)cur->FileId)[i * 2 + 1]; @@ -163,23 +163,19 @@ struct CBootInitialEntry return SectorCount * 512; } - UString GetName() const + AString GetName() const { - UString s; - if (Bootable) - s += L"Bootable"; + AString s = (Bootable ? "Bootable" : "NotBootable"); + s += '_'; + if (BootMediaType < kNumBootMediaTypes) + s += kMediaTypes[BootMediaType]; else - s += L"NotBootable"; - s += L"_"; - if (BootMediaType >= kNumBootMediaTypes) { - wchar_t name[16]; + char name[16]; ConvertUInt32ToString(BootMediaType, name); s += name; } - else - s += kMediaTypes[BootMediaType]; - s += L".img"; + s += ".img"; return s; } }; @@ -228,18 +224,19 @@ struct CVolumeDescriptor struct CRef { - CDir *Dir; + const CDir *Dir; UInt32 Index; + UInt32 NumExtents; + UInt64 TotalSize; }; const UInt32 kBlockSize = 1 << 11; class CInArchive { - CMyComPtr _stream; + IInStream *_stream; UInt64 _position; - Byte m_Buffer[kBlockSize]; UInt32 m_BufferPos; CDir _rootDir; @@ -275,15 +272,32 @@ public: HRESULT Open(IInStream *inStream); void Clear(); - UInt64 _archiveSize; + UInt64 _fileSize; + UInt64 PhySize; CRecordVector Refs; CObjectVector VolDescs; int MainVolDescIndex; UInt32 BlockSize; CObjectVector BootEntries; + + bool IsArc; + bool UnexpectedEnd; + bool HeadersError; bool IncorrectBigEndian; + bool TooDeepDirs; + bool SelfLinkedDirs; + CRecordVector UniqStartLocations; + + Byte m_Buffer[kBlockSize]; + void UpdatePhySize(UInt32 blockIndex, UInt64 size) + { + UInt64 alignedSize = (size + BlockSize - 1) & ~((UInt64)BlockSize - 1); + UInt64 end = blockIndex * BlockSize + alignedSize; + if (PhySize < end) + PhySize = end; + } bool IsJoliet() const { return VolDescs[MainVolDescIndex].IsJoliet(); } @@ -297,17 +311,17 @@ public: size = (1440 << 10); else if (be.BootMediaType == NBootMediaType::k2d88Floppy) size = (2880 << 10); - UInt64 startPos = be.LoadRBA * BlockSize; - if (startPos < _archiveSize) + UInt64 startPos = (UInt64)be.LoadRBA * BlockSize; + if (startPos < _fileSize) { - if (_archiveSize - startPos < size) - size = _archiveSize - startPos; + if (_fileSize - startPos < size) + size = _fileSize - startPos; } return size; } bool IsSusp; - int SuspSkipSize; + unsigned SuspSkipSize; }; }} diff --git a/CPP/7zip/Archive/Iso/IsoItem.h b/CPP/7zip/Archive/Iso/IsoItem.h old mode 100755 new mode 100644 index f39c2f5d..b6ae21b7 --- a/CPP/7zip/Archive/Iso/IsoItem.h +++ b/CPP/7zip/Archive/Iso/IsoItem.h @@ -3,11 +3,10 @@ #ifndef __ARCHIVE_ISO_ITEM_H #define __ARCHIVE_ISO_ITEM_H -#include "Common/Types.h" -#include "Common/MyString.h" -#include "Common/Buffer.h" +#include "../../../Common/MyString.h" +#include "../../../Common/MyBuffer.h" -#include "Windows/Time.h" +#include "../../../Windows/TimeUtils.h" #include "IsoHeader.h" @@ -41,62 +40,77 @@ struct CRecordingDateTime struct CDirRecord { - Byte ExtendedAttributeRecordLen; UInt32 ExtentLocation; - UInt32 DataLength; + UInt32 Size; CRecordingDateTime DateTime; Byte FileFlags; Byte FileUnitSize; Byte InterleaveGapSize; + Byte ExtendedAttributeRecordLen; UInt16 VolSequenceNumber; CByteBuffer FileId; CByteBuffer SystemUse; - bool IsDir() const { return (FileFlags & NFileFlags::kDirectory) != 0; } + bool AreMultiPartEqualWith(const CDirRecord &a) const + { + return FileId == a.FileId + && (FileFlags & (~NFileFlags::kNonFinalExtent)) == + (a.FileFlags & (~NFileFlags::kNonFinalExtent)); + } + + bool IsDir() const { return (FileFlags & NFileFlags::kDirectory) != 0; } + bool IsNonFinalExtent() const { return (FileFlags & NFileFlags::kNonFinalExtent) != 0; } + bool IsSystemItem() const { - if (FileId.GetCapacity() != 1) + if (FileId.Size() != 1) return false; Byte b = *(const Byte *)FileId; return (b == 0 || b == 1); } - const Byte* FindSuspName(int skipSize, int &lenRes) const + const Byte* FindSuspName(unsigned skipSize, unsigned &lenRes) const { lenRes = 0; + if (SystemUse.Size() < skipSize) + return 0; const Byte *p = (const Byte *)SystemUse + skipSize; - int length = (int)(SystemUse.GetCapacity() - skipSize); - while (length >= 5) + unsigned rem = (unsigned)(SystemUse.Size() - skipSize); + while (rem >= 5) { - int len = p[2]; + unsigned len = p[2]; + if (len > rem) + return 0; if (p[0] == 'N' && p[1] == 'M' && p[3] == 1) { + if (len < 5) + return 0; // Check it lenRes = len - 5; return p + 5; } p += len; - length -= len; + rem -= len; } return 0; } - int GetLengthCur(bool checkSusp, int skipSize) const + unsigned GetLenCur(bool checkSusp, int skipSize) const { if (checkSusp) { - int len; + unsigned len; const Byte *res = FindSuspName(skipSize, len); if (res != 0) return len; } - return (int)FileId.GetCapacity(); + return (unsigned)FileId.Size(); } const Byte* GetNameCur(bool checkSusp, int skipSize) const { if (checkSusp) { - int len; + unsigned len; const Byte *res = FindSuspName(skipSize, len); if (res != 0) return res; @@ -105,7 +119,7 @@ struct CDirRecord } - bool CheckSusp(const Byte *p, int &startPos) const + bool CheckSusp(const Byte *p, unsigned &startPos) const { if (p[0] == 'S' && p[1] == 'P' && @@ -120,17 +134,17 @@ struct CDirRecord return false; } - bool CheckSusp(int &startPos) const + bool CheckSusp(unsigned &startPos) const { const Byte *p = (const Byte *)SystemUse; - int length = (int)SystemUse.GetCapacity(); - const int kMinLen = 7; - if (length < kMinLen) + unsigned len = (int)SystemUse.Size(); + const unsigned kMinLen = 7; + if (len < kMinLen) return false; if (CheckSusp(p, startPos)) return true; - const int kOffset2 = 14; - if (length < kOffset2 + kMinLen) + const unsigned kOffset2 = 14; + if (len < kOffset2 + kMinLen) return false; return CheckSusp(p + kOffset2, startPos); } diff --git a/CPP/7zip/Archive/Iso/IsoRegister.cpp b/CPP/7zip/Archive/Iso/IsoRegister.cpp old mode 100755 new mode 100644 index 67a09c76..c6f4a521 --- a/CPP/7zip/Archive/Iso/IsoRegister.cpp +++ b/CPP/7zip/Archive/Iso/IsoRegister.cpp @@ -5,9 +5,19 @@ #include "../../Common/RegisterArc.h" #include "IsoHandler.h" -static IInArchive *CreateArc() { return new NArchive::NIso::CHandler; } + +namespace NArchive { +namespace NIso { + +IMP_CreateArcIn static CArcInfo g_ArcInfo = - { L"Iso", L"iso img", 0, 0xE7, { 'C', 'D', '0', '0', '1', 0x1 }, 7, false, CreateArc, 0 }; + { "Iso", "iso img", 0, 0xE7, + 5, { 'C', 'D', '0', '0', '1' }, + NArchive::NIso::kStartPos + 1, + 0, + CreateArc }; REGISTER_ARC(Iso) + +}} diff --git a/CPP/7zip/Archive/Iso/StdAfx.h b/CPP/7zip/Archive/Iso/StdAfx.h old mode 100755 new mode 100644 index 2e4be10b..2854ff3e --- a/CPP/7zip/Archive/Iso/StdAfx.h +++ b/CPP/7zip/Archive/Iso/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" -#include "../../../Common/NewHandler.h" +#include "../../../Common/Common.h" #endif diff --git a/CPP/7zip/Archive/LzhHandler.cpp b/CPP/7zip/Archive/LzhHandler.cpp old mode 100755 new mode 100644 index 194de47e..74f713f6 --- a/CPP/7zip/Archive/LzhHandler.cpp +++ b/CPP/7zip/Archive/LzhHandler.cpp @@ -4,12 +4,12 @@ #include "../../../C/CpuArch.h" -#include "Common/Buffer.h" -#include "Common/ComTry.h" -#include "Common/StringConvert.h" +#include "../../Common/ComTry.h" +#include "../../Common/MyBuffer.h" +#include "../../Common/StringConvert.h" -#include "Windows/PropVariant.h" -#include "Windows/Time.h" +#include "../../Windows/PropVariant.h" +#include "../../Windows/TimeUtils.h" #include "../ICoder.h" @@ -44,10 +44,11 @@ struct CExtension { Byte Type; CByteBuffer Data; + AString GetString() const { AString s; - for (size_t i = 0; i < Data.GetCapacity(); i++) + for (size_t i = 0; i < Data.Size(); i++) { char c = (char)Data[i]; if (c == 0) @@ -58,6 +59,21 @@ struct CExtension } }; +const UInt32 kBasicPartSize = 22; + +API_FUNC_static_IsArc IsArc_Lzh(const Byte *p, size_t size) +{ + if (size < 2 + kBasicPartSize) + return k_IsArc_Res_NEED_MORE; + if (p[2] != '-' || p[3] != 'l' || p[4] != 'h' || p[6] != '-') + return k_IsArc_Res_NO; + Byte n = p[5]; + if (n != 'd') + if (n < '0' || n > '7') + return k_IsArc_Res_NO; + return k_IsArc_Res_YES; +} + struct CItem { AString Name; @@ -85,7 +101,7 @@ struct CItem { if (!IsLhMethod()) return false; - switch(Method[3]) + switch (Method[3]) { case '1': return true; @@ -97,7 +113,7 @@ struct CItem { if (!IsLhMethod()) return false; - switch(Method[3]) + switch (Method[3]) { case '4': case '5': @@ -112,7 +128,7 @@ struct CItem { if (!IsLhMethod()) return 0; - switch(Method[3]) + switch (Method[3]) { case '1': return 12; case '2': return 13; @@ -127,13 +143,14 @@ struct CItem int FindExt(Byte type) const { - for (int i = 0; i < Extensions.Size(); i++) + FOR_VECTOR (i, Extensions) if (Extensions[i].Type == type) return i; return -1; } bool GetUnixTime(UInt32 &value) const { + value = 0; int index = FindExt(kExtIdUnixTime); if (index < 0) { @@ -219,7 +236,6 @@ static HRESULT GetNextItem(ISequentialInStream *stream, bool &filled, CItem &ite return S_OK; Byte header[256]; - const UInt32 kBasicPartSize = 22; processedSize = kBasicPartSize; RINOK(ReadStream(stream, header, &processedSize)); if (processedSize != kBasicPartSize) @@ -281,7 +297,7 @@ static HRESULT GetNextItem(ISequentialInStream *stream, bool &filled, CItem &ite CExtension ext; RINOK(ReadStream_FALSE(stream, &ext.Type, 1)) nextSize -= 3; - ext.Data.SetCapacity(nextSize); + ext.Data.Alloc(nextSize); RINOK(ReadStream_FALSE(stream, (Byte *)ext.Data, nextSize)) item.Extensions.Add(ext); Byte hdr2[2]; @@ -324,28 +340,23 @@ static const char *kUnknownOS = "Unknown"; static const char *GetOS(Byte osId) { - for (int i = 0; i < sizeof(g_OsPairs) / sizeof(g_OsPairs[0]); i++) + for (unsigned i = 0; i < ARRAY_SIZE(g_OsPairs); i++) if (g_OsPairs[i].Id == osId) return g_OsPairs[i].Name; return kUnknownOS; } -static const STATPROPSTG kProps[] = +static const Byte 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} -}; - -static const STATPROPSTG kArcProps[] = -{ - { NULL, kpidPhySize, VT_UI8} + kpidPath, + kpidIsDir, + kpidSize, + kpidPackSize, + kpidMTime, + // kpidAttrib, + kpidCRC, + kpidMethod, + kpidHostOS }; class CCRC @@ -446,7 +457,8 @@ class CHandler: CObjectVector _items; CMyComPtr _stream; UInt64 _phySize; - AString _errorMessage; + UInt32 _errorFlags; + bool _isArc; public: MY_UNKNOWN_IMP1(IInArchive) INTERFACE_IInArchive(;) @@ -454,7 +466,7 @@ public: }; IMP_IInArchive_Props -IMP_IInArchive_ArcProps +IMP_IInArchive_ArcProps_NO_Table CHandler::CHandler() {} @@ -467,21 +479,26 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { NCOM::CPropVariant prop; - switch(propID) + switch (propID) { case kpidPhySize: prop = _phySize; break; - case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break; + + case kpidErrorFlags: + UInt32 v = _errorFlags; + if (!_isArc) v |= kpv_ErrorFlags_IsNotArc; + prop = v; + break; } prop.Detach(value); return S_OK; } -STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; + NCOM::CPropVariant prop; const CItemEx &item = _items[index]; - switch(propID) + switch (propID) { case kpidPath: { @@ -538,6 +555,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback *callback) { COM_TRY_BEGIN + Close(); try { _items.Clear(); @@ -548,7 +566,6 @@ STDMETHODIMP CHandler::Open(IInStream *stream, RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos)); RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); - _phySize = 0; for (;;) { CItemEx item; @@ -557,7 +574,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, RINOK(stream->Seek(0, STREAM_SEEK_CUR, &item.DataPosition)); if (result == S_FALSE) { - _errorMessage = "Incorrect header"; + _errorFlags = kpv_ErrorFlags_HeadersError; break; } @@ -568,12 +585,14 @@ STDMETHODIMP CHandler::Open(IInStream *stream, break; _items.Add(item); + _isArc = true; + UInt64 newPostion; RINOK(stream->Seek(item.PackSize, STREAM_SEEK_CUR, &newPostion)); if (newPostion > endPos) { _phySize = endPos; - _errorMessage = "Unexpected end of archive"; + _errorFlags = kpv_ErrorFlags_UnexpectedEnd; break; } _phySize = newPostion; @@ -607,7 +626,9 @@ STDMETHODIMP CHandler::Open(IInStream *stream, STDMETHODIMP CHandler::Close() { - _errorMessage.Empty(); + _isArc = false; + _phySize = 0; + _errorFlags = 0; _items.Clear(); _stream.Release(); return S_OK; @@ -619,7 +640,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_BEGIN bool testMode = (testModeSpec != 0); UInt64 totalUnPacked = 0, totalPacked = 0; - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _items.Size(); if (numItems == 0) @@ -730,7 +751,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } */ else - opRes = NExtract::NOperationResult::kUnSupportedMethod; + opRes = NExtract::NOperationResult::kUnsupportedMethod; if (opRes == NExtract::NOperationResult::kOK) { @@ -751,10 +772,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_END } -static IInArchive *CreateArc() { return new CHandler; } +IMP_CreateArcIn static CArcInfo g_ArcInfo = - { L"Lzh", L"lzh lha", 0, 6, { '-', 'l' }, 2, false, CreateArc, 0 }; + { "Lzh", "lzh lha", 0, 6, + 3, { '-', 'l', 'h' }, + 2, + 0, + CreateArc, NULL, IsArc_Lzh }; REGISTER_ARC(Lzh) diff --git a/CPP/7zip/Archive/LzmaHandler.cpp b/CPP/7zip/Archive/LzmaHandler.cpp old mode 100755 new mode 100644 index 778c2fd8..d1e19677 --- a/CPP/7zip/Archive/LzmaHandler.cpp +++ b/CPP/7zip/Archive/LzmaHandler.cpp @@ -4,10 +4,10 @@ #include "../../../C/CpuArch.h" -#include "Common/ComTry.h" -#include "Common/IntToString.h" +#include "../../Common/ComTry.h" +#include "../../Common/IntToString.h" -#include "Windows/PropVariant.h" +#include "../../Windows/PropVariant.h" #include "../Common/CreateCoder.h" #include "../Common/ProgressUtils.h" @@ -26,17 +26,24 @@ namespace NLzma { static bool CheckDicSize(const Byte *p) { UInt32 dicSize = GetUi32(p); - for (int i = 1; i <= 30; i++) + if (dicSize == 1) + return true; + for (unsigned i = 0; i <= 30; i++) if (dicSize == ((UInt32)2 << i) || dicSize == ((UInt32)3 << i)) return true; return (dicSize == 0xFFFFFFFF); } -STATPROPSTG kProps[] = +static const Byte kProps[] = { - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, - { NULL, kpidMethod, VT_BSTR} + kpidSize, + kpidPackSize, + kpidMethod +}; + +static const Byte kArcProps[] = +{ + kpidNumStreams }; struct CHeader @@ -62,16 +69,17 @@ bool CHeader::Parse(const Byte *buf, bool isThereFilter) return LzmaProps[0] < 5 * 5 * 9 && FilterID < 2 && - (!HasSize() || Size < ((UInt64)1 << 56)) && - CheckDicSize(LzmaProps + 1); + (!HasSize() || Size < ((UInt64)1 << 56)) + && CheckDicSize(LzmaProps + 1); } class CDecoder { - NCompress::NLzma::CDecoder *_lzmaDecoderSpec; CMyComPtr _lzmaDecoder; CMyComPtr _bcjStream; public: + NCompress::NLzma::CDecoder *_lzmaDecoderSpec; + ~CDecoder(); HRESULT Create(DECL_EXTERNAL_CODECS_LOC_VARS bool filtered, ISequentialInStream *inStream); @@ -86,7 +94,7 @@ public: { return _lzmaDecoderSpec->ReadFromInputStream(data, size, processedSize); } }; -static const UInt64 k_BCJ = 0x03030103; +static const UInt32 k_BCJ = 0x03030103; HRESULT CDecoder::Create( DECL_EXTERNAL_CODECS_LOC_VARS @@ -95,6 +103,7 @@ HRESULT CDecoder::Create( if (!_lzmaDecoder) { _lzmaDecoderSpec = new NCompress::NLzma::CDecoder; + _lzmaDecoderSpec->FinishStream = true; _lzmaDecoder = _lzmaDecoderSpec; } @@ -166,6 +175,10 @@ HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream, } RINOK(res); + if (header.HasSize()) + if (_lzmaDecoderSpec->GetOutputProcessedSize() != header.Size) + return S_FALSE; + return S_OK; } @@ -178,11 +191,24 @@ class CHandler: { CHeader _header; bool _lzma86; - UInt64 _startPosition; - UInt64 _packSize; - bool _packSizeDefined; CMyComPtr _stream; CMyComPtr _seqStream; + + bool _isArc; + bool _needSeekToStart; + bool _dataAfterEnd; + bool _needMoreInput; + + bool _packSize_Defined; + bool _unpackSize_Defined; + bool _numStreams_Defined; + + bool _unsupported; + bool _dataError; + + UInt64 _packSize; + UInt64 _unpackSize; + UInt64 _numStreams; DECL_EXTERNAL_CODECS_VARS DECL_ISetCompressCodecsInfo @@ -204,14 +230,26 @@ public: }; IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO_Table +IMP_IInArchive_ArcProps STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { NCOM::CPropVariant prop; - switch(propID) + switch (propID) { - case kpidPhySize: if (_packSizeDefined) prop = _packSize; break; + case kpidPhySize: if (_packSize_Defined) prop = _packSize; break; + case kpidNumStreams: if (_numStreams_Defined) prop = _numStreams; break; + case kpidUnpackSize: if (_unpackSize_Defined) prop = _unpackSize; break; + case kpidErrorFlags: + { + UInt32 v = 0; + if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;; + if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd; + if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd; + if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod; + if (_dataError) v |= kpv_ErrorFlags_DataError; + prop = v; + } } prop.Detach(value); return S_OK; @@ -226,50 +264,37 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) static void DictSizeToString(UInt32 value, char *s) { for (int i = 0; i <= 31; i++) - if ((UInt32(1) << i) == value) + 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'; - } + 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'; + s += MyStringLen(s); + *s++ = c; + *s = 0; } -static void MyStrCat(char *d, const char *s) -{ - MyStringCopy(d + MyStringLen(d), s); -} - -STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) { NCOM::CPropVariant prop; - switch(propID) + switch (propID) { case kpidSize: if (_stream && _header.HasSize()) prop = _header.Size; break; - case kpidPackSize: if (_packSizeDefined) prop = _packSize; break; + case kpidPackSize: if (_packSize_Defined) prop = _packSize; break; case kpidMethod: if (_stream) { - char s[64]; - s[0] = '\0'; + char sz[64]; + char *s = sz; if (_header.FilterID != 0) - MyStrCat(s, "BCJ "); - MyStrCat(s, "LZMA:"); - DictSizeToString(_header.GetDicSize(), s + MyStringLen(s)); - prop = s; + s = MyStpCpy(s, "BCJ "); + s = MyStpCpy(s, "LZMA:"); + DictSizeToString(_header.GetDicSize(), s); + prop = sz; } break; } @@ -277,11 +302,52 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIA return S_OK; } +API_FUNC_static_IsArc IsArc_Lzma(const Byte *p, size_t size) +{ + const UInt32 kHeaderSize = 1 + 4 + 8; + if (size < kHeaderSize) + return k_IsArc_Res_NEED_MORE; + if (p[0] >= 5 * 5 * 9) + return k_IsArc_Res_NO; + UInt64 unpackSize = GetUi64(p + 1 + 4); + if (unpackSize != (UInt64)(Int64)-1) + { + if (size >= ((UInt64)1 << 56)) + return k_IsArc_Res_NO; + } + if (unpackSize != 0) + { + if (size < kHeaderSize + 2) + return k_IsArc_Res_NEED_MORE; + if (p[kHeaderSize] != 0) + return k_IsArc_Res_NO; + if (unpackSize != (UInt64)(Int64)-1) + { + if ((p[kHeaderSize + 1] & 0x80) != 0) + return k_IsArc_Res_NO; + } + } + if (!CheckDicSize(p + 1)) + // return k_IsArc_Res_YES_LOW_PROB; + return k_IsArc_Res_NO; + return k_IsArc_Res_YES; +} + +API_FUNC_static_IsArc IsArc_Lzma86(const Byte *p, size_t size) +{ + if (size < 1) + return k_IsArc_Res_NEED_MORE; + Byte filterID = p[0]; + if (filterID != 0 && filterID != 1) + return k_IsArc_Res_NO; + return IsArc_Lzma(p + 1, size - 1); +} + STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *) { - RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &_startPosition)); + Close(); - const UInt32 kBufSize = 1 + 5 + 8 + 1; + const UInt32 kBufSize = 1 + 5 + 8 + 2; Byte buf[kBufSize]; RINOK(ReadStream_FALSE(inStream, buf, kBufSize)); @@ -289,35 +355,71 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCal if (!_header.Parse(buf, _lzma86)) return S_FALSE; const Byte *start = buf + GetHeaderSize(); - if (start[0] != 0) + if (start[0] != 0 /* || (start[1] & 0x80) != 0 */ ) // empty stream with EOS is not 0x80 return S_FALSE; - UInt64 endPos; - RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos)); - _packSize = endPos - _startPosition; - _packSizeDefined = true; + RINOK(inStream->Seek(0, STREAM_SEEK_END, &_packSize)); if (_packSize >= 24 && _header.Size == 0 && _header.FilterID == 0 && _header.LzmaProps[0] == 0) return S_FALSE; + _isArc = true; _stream = inStream; _seqStream = inStream; + _needSeekToStart = true; return S_OK; } STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) { Close(); + _isArc = true; _seqStream = stream; return S_OK; } STDMETHODIMP CHandler::Close() { - _packSizeDefined = false; + _isArc = false; + _packSize_Defined = false; + _unpackSize_Defined = false; + _numStreams_Defined = false; + + _dataAfterEnd = false; + _needMoreInput = false; + _unsupported = false; + _dataError = false; + + _packSize = 0; + + _needSeekToStart = false; + _stream.Release(); _seqStream.Release(); return S_OK; } +class CCompressProgressInfoImp: + public ICompressProgressInfo, + public CMyUnknownImp +{ + CMyComPtr Callback; +public: + UInt64 Offset; + + MY_UNKNOWN_IMP1(ICompressProgressInfo) + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); + void Init(IArchiveOpenCallback *callback) { Callback = callback; } +}; + +STDMETHODIMP CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */) +{ + if (Callback) + { + UInt64 files = 0; + UInt64 value = Offset + *inSize; + return Callback->SetCompleted(&files, &value); + } + return S_OK; +} STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) @@ -325,10 +427,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_BEGIN if (numItems == 0) return S_OK; - if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0)) + if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) return E_INVALIDARG; - if (_stream) + if (_packSize_Defined) extractCallback->SetTotal(_packSize); @@ -352,10 +454,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CMyComPtr progress = lps; lps->Init(extractCallback, true); - if (_stream) + if (_needSeekToStart) { - RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); + if (!_stream) + return E_FAIL; + RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL)); } + else + _needSeekToStart = true; CDecoder decoder; HRESULT result = decoder.Create( @@ -363,67 +469,132 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, _lzma86, _seqStream); RINOK(result); - Int32 opRes = NExtract::NOperationResult::kOK; bool firstItem = true; + UInt64 packSize = 0; + UInt64 unpackSize = 0; + UInt64 numStreams = 0; + + bool dataAfterEnd = false; + for (;;) { - lps->OutSize = outStreamSpec->GetSize(); - lps->InSize = _packSize = decoder.GetInputProcessedSize(); - _packSizeDefined = true; + lps->InSize = packSize; + lps->OutSize = unpackSize; 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) + { + if (processed != 0) + dataAfterEnd = true; break; + } + CHeader st; if (!st.Parse(buf, _lzma86)) + { + dataAfterEnd = true; break; + } + numStreams++; firstItem = false; result = decoder.Code(st, outStream, progress); + + packSize = decoder.GetInputProcessedSize(); + unpackSize = outStreamSpec->GetSize(); + if (result == E_NOTIMPL) { - opRes = NExtract::NOperationResult::kUnSupportedMethod; + _unsupported = true; + result = S_FALSE; break; } if (result == S_FALSE) - { - opRes = NExtract::NOperationResult::kDataError; break; - } RINOK(result); } + if (firstItem) - return E_FAIL; + { + _isArc = false; + result = S_FALSE; + } + else if (result == S_OK || result == S_FALSE) + { + if (dataAfterEnd) + _dataAfterEnd = true; + else if (decoder._lzmaDecoderSpec->NeedMoreInput) + _needMoreInput = true; + + _packSize = packSize; + _unpackSize = unpackSize; + _numStreams = numStreams; + + _packSize_Defined = true; + _unpackSize_Defined = true; + _numStreams_Defined = true; + } + + Int32 opResult = NExtract::NOperationResult::kOK; + + if (!_isArc) + opResult = NExtract::NOperationResult::kIsNotArc; + else if (_needMoreInput) + opResult = NExtract::NOperationResult::kUnexpectedEnd; + else if (_unsupported) + opResult = NExtract::NOperationResult::kUnsupportedMethod; + else if (_dataAfterEnd) + opResult = NExtract::NOperationResult::kDataAfterEnd; + else if (result == S_FALSE) + opResult = NExtract::NOperationResult::kDataError; + else if (result == S_OK) + opResult = NExtract::NOperationResult::kOK; + else + return result; + outStream.Release(); - return extractCallback->SetOperationResult(opRes); + return extractCallback->SetOperationResult(opResult); COM_TRY_END } IMPL_ISetCompressCodecsInfo -static IInArchive *CreateArc() { return new CHandler(false); } -static IInArchive *CreateArc86() { return new CHandler(true); } - namespace NLzmaAr { - + +IMP_CreateArcIn_2(CHandler(false)) + static CArcInfo g_ArcInfo = - { L"lzma", L"lzma", 0, 0xA, { 0 }, 0, true, CreateArc, NULL }; + { "lzma", "lzma", 0, 0xA, + 0, { 0 }, + // 2, { 0x5D, 0x00 }, + 0, + NArcInfoFlags::kStartOpen | + NArcInfoFlags::kKeepName, + CreateArc, NULL, + IsArc_Lzma }; + REGISTER_ARC(Lzma) } namespace NLzma86Ar { +IMP_CreateArcIn_2(CHandler(true)) + static CArcInfo g_ArcInfo = - { L"lzma86", L"lzma86", 0, 0xB, { 0 }, 0, true, CreateArc86, NULL }; + { "lzma86", "lzma86", 0, 0xB, + 0, { 0 }, + 0, + NArcInfoFlags::kKeepName, + CreateArc, NULL, + IsArc_Lzma86 }; + REGISTER_ARC(Lzma86) } diff --git a/CPP/7zip/Archive/MachoHandler.cpp b/CPP/7zip/Archive/MachoHandler.cpp old mode 100755 new mode 100644 index a6261f34..11ff9703 --- a/CPP/7zip/Archive/MachoHandler.cpp +++ b/CPP/7zip/Archive/MachoHandler.cpp @@ -4,10 +4,12 @@ #include "../../../C/CpuArch.h" -#include "Common/Buffer.h" -#include "Common/ComTry.h" +#include "../../Common/ComTry.h" +#include "../../Common/MyBuffer.h" +#include "../../Common/StringConvert.h" +#include "../../Common/IntToString.h" -#include "Windows/PropVariantUtils.h" +#include "../../Windows/PropVariantUtils.h" #include "../Common/LimitedStreams.h" #include "../Common/ProgressUtils.h" @@ -16,65 +18,142 @@ #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); } +static UInt32 Get32(const Byte *p, bool be) { if (be) return GetBe32(p); return GetUi32(p); } +static UInt64 Get64(const Byte *p, bool be) { if (be) return GetBe64(p); return GetUi64(p); } using namespace NWindows; +using namespace NCOM; 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 CPU_ARCH_ABI64 (1 << 24) +#define CPU_TYPE_386 7 +#define CPU_TYPE_ARM 12 +#define CPU_TYPE_SPARC 14 +#define CPU_TYPE_PPC 18 -#define MACH_MACHINE_PPC64 (MACH_ARCH_ABI64 | MACH_MACHINE_PPC) -#define MACH_MACHINE_AMD64 (MACH_ARCH_ABI64 | MACH_MACHINE_386) +#define CPU_SUBTYPE_I386_ALL 3 -#define MACH_CMD_SEGMENT_32 1 -#define MACH_CMD_SEGMENT_64 0x19 +#define CPU_TYPE_PPC64 (CPU_ARCH_ABI64 | CPU_TYPE_PPC) +#define CPU_TYPE_AMD64 (CPU_ARCH_ABI64 | CPU_TYPE_386) -#define MACH_SECT_TYPE_MASK 0x000000FF -#define MACH_SECT_ATTR_MASK 0xFFFFFF00 +#define CPU_SUBTYPE_LIB64 (1 << 31) -#define MACH_SECT_ATTR_ZEROFILL 1 +#define CPU_SUBTYPE_POWERPC_970 100 + +static const char *k_PowerPc_SubTypes[] = +{ + NULL + , "601" + , "602" + , "603" + , "603e" + , "603ev" + , "604" + , "604e" + , "620" + , "750" + , "7400" + , "7450" +}; + +static const CUInt32PCharPair g_CpuPairs[] = +{ + { CPU_TYPE_386, "x86" }, + { CPU_TYPE_ARM, "ARM" }, + { CPU_TYPE_SPARC, "SPARC" }, + { CPU_TYPE_PPC, "PowerPC" } +}; + + +#define CMD_SEGMENT_32 1 +#define CMD_SEGMENT_64 0x19 + +#define SECT_TYPE_MASK 0x000000FF +#define SECT_ATTR_MASK 0xFFFFFF00 + +#define 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" + "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" +}; + +enum EFileType +{ + kType_OBJECT = 1, + kType_EXECUTE, + kType_FVMLIB, + kType_CORE, + kType_PRELOAD, + kType_DYLIB, + kType_DYLINKER, + kType_BUNDLE, + kType_DYLIB_STUB, + kType_DSYM }; static const char *g_FileTypes[] = { - "0", - "OBJECT", - "EXECUTE", - "FVMLIB", - "CORE", - "PRELOAD", - "DYLIB", - "DYLINKER", - "BUNDLE", - "DYLIB_STUB", - "DSYM" + "0" + , "OBJECT" + , "EXECUTE" + , "FVMLIB" + , "CORE" + , "PRELOAD" + , "DYLIB" + , "DYLINKER" + , "BUNDLE" + , "DYLIB_STUB" + , "DSYM" }; + +static const char *g_ArcFlags[] = +{ + "NOUNDEFS" + , "INCRLINK" + , "DYLDLINK" + , "BINDATLOAD" + , "PREBOUND" + , "SPLIT_SEGS" + , "LAZY_INIT" + , "TWOLEVEL" + , "FORCE_FLAT" + , "NOMULTIDEFS" + , "NOFIXPREBINDING" + , "PREBINDABLE" + , "ALLMODSBOUND" + , "SUBSECTIONS_VIA_SYMBOLS" + , "CANONICAL" + , "WEAK_DEFINES" + , "BINDS_TO_WEAK" + , "ALLOW_STACK_EXECUTION" + , "ROOT_SAFE" + , "SETUID_SAFE" + , "NO_REEXPORTED_DYLIBS" + , "PIE" + , "DEAD_STRIPPABLE_DYLIB" + , "HAS_TLV_DESCRIPTORS" + , "NO_HEAP_EXECUTION" +}; + + static const CUInt32PCharPair g_Flags[] = { { 31, "PURE_INSTRUCTIONS" }, @@ -89,16 +168,6 @@ static const CUInt32PCharPair g_Flags[] = { 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 @@ -121,209 +190,150 @@ struct CSection bool IsDummy; CSection(): IsDummy(false) {} - // UInt64 GetPackSize() const { return Flags == MACH_SECT_ATTR_ZEROFILL ? 0 : Size; } + // UInt64 GetPackSize() const { return Flags == SECT_ATTR_ZEROFILL ? 0 : Size; } UInt64 GetPackSize() const { return PSize; } }; class CHandler: public IInArchive, + public IArchiveAllowTail, public CMyUnknownImp { CMyComPtr _inStream; CObjectVector _segments; CObjectVector _sections; + bool _allowTail; bool _mode64; bool _be; - UInt32 _machine; + UInt32 _cpuType; + UInt32 _cpuSubType; UInt32 _type; + UInt32 _flags; UInt32 _headersSize; UInt64 _totalSize; + HRESULT Open2(ISequentialInStream *stream); - bool Parse(const Byte *buf, UInt32 size); public: - MY_UNKNOWN_IMP1(IInArchive) + MY_UNKNOWN_IMP2(IInArchive, IArchiveAllowTail) INTERFACE_IInArchive(;) + STDMETHOD(AllowTail)(Int32 allowTail); + CHandler(): _allowTail(false) {} }; -bool CHandler::Parse(const Byte *buf, UInt32 size) +static const Byte kArcProps[] = { - 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; + kpidCpu, + kpidBit64, + kpidBigEndian, + kpidCharacts, + kpidHeadersSize +}; - if (mode64) - { - buf += 4; - size -= 4; - } +static const Byte kProps[] = +{ + kpidPath, + kpidSize, + kpidPackSize, + kpidCharacts, + kpidOffset, + kpidVa +}; - _totalSize = (UInt32)(buf - bufStart); - if (commandsSize < size) - size = commandsSize; +IMP_IInArchive_Props +IMP_IInArchive_ArcProps - for (UInt32 cmdIndex = 0; cmdIndex < numCommands; cmdIndex++) +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + CPropVariant prop; + switch (propID) { - 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) + case kpidShortComment: + case kpidCpu: { - UInt32 offs = (cmd == MACH_CMD_SEGMENT_64) ? 0x48 : 0x38; - if (cmdSize < offs) - break; - - UInt64 vmAddr, vmSize, phAddr, phSize; - + AString s; + char temp[16]; + UInt32 cpu = _cpuType & ~(UInt32)CPU_ARCH_ABI64; + if (_cpuType == CPU_TYPE_AMD64) + s = "x64"; + else { - 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 + const char *n = NULL; + for (unsigned i = 0; i < ARRAY_SIZE(g_CpuPairs); i++) { - vmAddr = Get32(buf + 0x18, be); - vmSize = Get32(buf + 0x1C, be); - phAddr = Get32(buf + 0x20, be); - phSize = Get32(buf + 0x24, be); + const CUInt32PCharPair &pair = g_CpuPairs[i]; + if (pair.Value == cpu) + { + n = pair.Name; + break; + } } + if (!n) { - UInt64 totalSize = phAddr + phSize; - if (totalSize > _totalSize) - _totalSize = totalSize; + ConvertUInt32ToString(cpu, temp); + n = temp; } + s = n; + + if (_cpuType & CPU_ARCH_ABI64) + s += " 64-bit"; + else if (_cpuSubType & CPU_SUBTYPE_LIB64) + s += " 64-bit lib"; } - - 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 + UInt32 t = _cpuSubType & ~(UInt32)CPU_SUBTYPE_LIB64; + if (t != 0 && (t != CPU_SUBTYPE_I386_ALL || cpu != CPU_TYPE_386)) { - 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) + const char *n = NULL; + if (cpu == CPU_TYPE_PPC) { - section.Va = Get64(p + 0x20, be); - section.VSize = Get64(p + 0x28, be); - section.Pa = Get32(p + 0x30, be); - section.Flags = Get32(p + 0x40, be); + if (t == CPU_SUBTYPE_POWERPC_970) + n = "970"; + else if (t < ARRAY_SIZE(k_PowerPc_SubTypes)) + n = k_PowerPc_SubTypes[t]; } - else + if (!n) { - section.Va = Get32(p + 0x20, be); - section.VSize = Get32(p + 0x24, be); - section.Pa = Get32(p + 0x28, be); - section.Flags = Get32(p + 0x38, be); + ConvertUInt32ToString(t, temp); + n = temp; } - 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; + s += ' '; + s += n; } - while (--numSections); - - if (offs != cmdSize) - return false; + prop = s; + break; + } + case kpidCharacts: + { + // TYPE_TO_PROP(g_FileTypes, _type, prop); break; + AString res = TypeToString(g_FileTypes, ARRAY_SIZE(g_FileTypes), _type); + AString s = FlagsToString(g_ArcFlags, ARRAY_SIZE(g_ArcFlags), _flags); + if (!s.IsEmpty()) + { + res += ' '; + res += s; + } + prop = res; + break; } - 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; + case kpidExtension: + { + const char *ext = NULL; + if (_type == kType_OBJECT) + ext = "o"; + else if (_type == kType_BUNDLE) + ext = "bundle"; + else if (_type == kType_DYLIB) + ext = "dylib"; // main shared library usually does not have extension + if (ext) + prop = ext; + break; + } + // case kpidIsSelfExe: prop = (_type == kType_EXECUTE); break; } prop.Detach(value); return S_OK; @@ -340,10 +350,8 @@ static AString GetName(const char *name) 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); + AString res = TypeToString(g_SectTypes, ARRAY_SIZE(g_SectTypes), flags & SECT_TYPE_MASK); + AString s = FlagsToString(g_Flags, ARRAY_SIZE(g_Flags), flags & SECT_ATTR_MASK); if (!s.IsEmpty()) { res += ' '; @@ -355,21 +363,21 @@ static AString SectFlagsToString(UInt32 flags) STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NCOM::CPropVariant prop; + CPropVariant prop; const CSection &item = _sections[index]; - switch(propID) + switch (propID) { case kpidPath: { AString s = GetName(_segments[item.SegmentIndex].Name); if (!item.IsDummy) s += GetName(item.Name); - StringToProp(s, prop); + prop = MultiByteToUnicodeString(s); 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 kpidCharacts: if (!item.IsDummy) prop = SectFlagsToString(item.Flags); break; case kpidOffset: prop = item.Pa; break; case kpidVa: prop = item.Va; break; } @@ -380,18 +388,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val HRESULT CHandler::Open2(ISequentialInStream *stream) { - const UInt32 kBufSize = 1 << 18; - const UInt32 kSigSize = 4; + const UInt32 kStartHeaderSize = 7 * 4; - CByteBuffer buffer; - buffer.SetCapacity(kBufSize); - Byte *buf = buffer; - - size_t processed = kSigSize; - RINOK(ReadStream_FALSE(stream, buf, processed)); - UInt32 sig = GetUi32(buf); + Byte header[kStartHeaderSize]; + RINOK(ReadStream_FALSE(stream, header, kStartHeaderSize)); bool be, mode64; - switch(sig) + switch (GetUi32(header)) { case 0xCEFAEDFE: be = true; mode64 = false; break; case 0xCFFAEDFE: be = true; mode64 = true; break; @@ -399,11 +401,148 @@ HRESULT CHandler::Open2(ISequentialInStream *stream) 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; + + UInt32 numCommands = Get32(header + 0x10, be); + UInt32 commandsSize = Get32(header + 0x14, be); + + if (numCommands == 0) + return S_FALSE; + + if (commandsSize > (1 << 24) || + numCommands > (1 << 21) || + numCommands * 8 > commandsSize) + return S_FALSE; + + _cpuType = Get32(header + 4, be); + _cpuSubType = Get32(header + 8, be); + _type = Get32(header + 0xC, be); + _flags = Get32(header + 0x18, be); + + /* + // Probably the sections are in first commands. So we can reduce the number of commands. + bool reduceCommands = false; + const UInt32 kNumReduceCommands = 16; + if (numCommands > kNumReduceCommands) + { + reduceCommands = true; + numCommands = kNumReduceCommands; + } + */ + + UInt32 startHeaderSize = kStartHeaderSize; + if (mode64) + startHeaderSize += 4; + _headersSize = startHeaderSize + commandsSize; + _totalSize = _headersSize; + CByteArr buffer(_headersSize); + RINOK(ReadStream_FALSE(stream, buffer + kStartHeaderSize, _headersSize - kStartHeaderSize)); + const Byte *buf = buffer + startHeaderSize; + size_t size = _headersSize - startHeaderSize; + for (UInt32 cmdIndex = 0; cmdIndex < numCommands; cmdIndex++) + { + if (size < 8) + return S_FALSE; + UInt32 cmd = Get32(buf, be); + UInt32 cmdSize = Get32(buf + 4, be); + if (cmdSize < 8) + return S_FALSE; + if (size < cmdSize) + return S_FALSE; + if (cmd == CMD_SEGMENT_32 || cmd == CMD_SEGMENT_64) + { + UInt32 offs = (cmd == CMD_SEGMENT_64) ? 0x48 : 0x38; + if (cmdSize < offs) + break; + + UInt64 vmAddr, vmSize, phAddr, phSize; + + { + if (cmd == 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 < phAddr) + return S_FALSE; + 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 S_FALSE; + + if (numSections == 0) + { + CSection § = _sections.AddNew(); + sect.IsDummy = true; + sect.SegmentIndex = _segments.Size() - 1; + sect.Va = vmAddr; + sect.PSize = phSize; + sect.VSize = vmSize; + sect.Pa = phAddr; + sect.Flags = 0; + } + else do + { + UInt32 headSize = (cmd == CMD_SEGMENT_64) ? 0x50 : 0x44; + const Byte *p = buf + offs; + if (cmdSize - offs < headSize) + break; + CSection § = _sections.AddNew(); + unsigned f32Offset; + if (cmd == CMD_SEGMENT_64) + { + sect.Va = Get64(p + 0x20, be); + sect.VSize = Get64(p + 0x28, be); + f32Offset = 0x30; + } + else + { + sect.Va = Get32(p + 0x20, be); + sect.VSize = Get32(p + 0x24, be); + f32Offset = 0x28; + } + sect.Pa = Get32(p + f32Offset, be); + sect.Flags = Get32(p + f32Offset + 10, be); + if (sect.Flags == SECT_ATTR_ZEROFILL) + sect.PSize = 0; + else + sect.PSize = sect.VSize; + memcpy(sect.Name, p, kNameSize); + memcpy(sect.SegName, p + kNameSize, kNameSize); + sect.SegmentIndex = _segments.Size() - 1; + offs += headSize; + } + while (--numSections); + + if (offs != cmdSize) + return S_FALSE; + } + buf += cmdSize; + size -= cmdSize; + } + // return (reduceCommands || (size == 0)) ? S_OK : S_FALSE; + if (size != 0) + return S_FALSE; + + return S_OK; } STDMETHODIMP CHandler::Open(IInStream *inStream, @@ -413,6 +552,13 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, COM_TRY_BEGIN Close(); RINOK(Open2(inStream)); + if (!_allowTail) + { + UInt64 fileSize; + RINOK(inStream->Seek(0, STREAM_SEEK_END, &fileSize)); + if (fileSize > _totalSize) + return S_FALSE; + } _inStream = inStream; return S_OK; COM_TRY_END @@ -420,6 +566,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, STDMETHODIMP CHandler::Close() { + _totalSize = 0; _inStream.Release(); _sections.Clear(); _segments.Clear(); @@ -436,7 +583,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _sections.Size(); if (numItems == 0) @@ -490,10 +637,27 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_END } -static IInArchive *CreateArc() { return new CHandler; } +STDMETHODIMP CHandler::AllowTail(Int32 allowTail) +{ + _allowTail = IntToBool(allowTail); + return S_OK; +} + +IMP_CreateArcIn + +#define k_Signature { \ + 4, 0xCE, 0xFA, 0xED, 0xFE, \ + 4, 0xCF, 0xFA, 0xED, 0xFE, \ + 4, 0xFE, 0xED, 0xFA, 0xCE, \ + 4, 0xFE, 0xED, 0xFA, 0xCF } static CArcInfo g_ArcInfo = - { L"MachO", L"", 0, 0xDF, { 0 }, 0, false, CreateArc, 0 }; + { "MachO", "macho", 0, 0xDF, + 4 * 5, k_Signature, + 0, + NArcInfoFlags::kMultiSignature | + NArcInfoFlags::kPreArc, + CreateArc }; REGISTER_ARC(Macho) diff --git a/CPP/7zip/Archive/MbrHandler.cpp b/CPP/7zip/Archive/MbrHandler.cpp old mode 100755 new mode 100644 index b6d79182..309bc286 --- a/CPP/7zip/Archive/MbrHandler.cpp +++ b/CPP/7zip/Archive/MbrHandler.cpp @@ -10,12 +10,12 @@ #include "../../../C/CpuArch.h" -#include "Common/Buffer.h" -#include "Common/ComTry.h" -#include "Common/IntToString.h" -#include "Common/MyString.h" +#include "../../Common/ComTry.h" +#include "../../Common/IntToString.h" +#include "../../Common/MyBuffer.h" +#include "../../Common/MyString.h" -#include "Windows/PropVariant.h" +#include "../../Windows/PropVariant.h" #include "../Common/LimitedStreams.h" #include "../Common/ProgressUtils.h" @@ -169,7 +169,7 @@ static const CPartType kPartTypes[] = static int FindPartType(UInt32 type) { - for (int i = 0; i < sizeof(kPartTypes) / sizeof(kPartTypes[0]); i++) + for (int i = 0; i < ARRAY_SIZE(kPartTypes); i++) if (kPartTypes[i].Id == type) return i; return -1; @@ -210,7 +210,7 @@ HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int { const UInt32 kSectorSize = 512; - _buffer.SetCapacity(kSectorSize); + _buffer.Alloc(kSectorSize); Byte *buf = _buffer; UInt64 newPos = (UInt64)lba << 9; if (newPos + 512 > _totalSize) @@ -243,7 +243,7 @@ HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int part.Print(); #endif - int numItems = _items.Size(); + unsigned numItems = _items.Size(); UInt32 newLba = lba + part.Lba; if (part.IsExtended()) @@ -323,6 +323,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, STDMETHODIMP CHandler::Close() { + _totalSize = 0; _items.Clear(); _stream.Release(); return S_OK; @@ -335,7 +336,7 @@ enum kpidEndChs }; -STATPROPSTG kProps[] = +static const STATPROPSTG kProps[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidSize, VT_UI8}, @@ -352,12 +353,12 @@ IMP_IInArchive_ArcProps_NO_Table STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { NCOM::CPropVariant prop; - switch(propID) + switch (propID) { case kpidMainSubfile: { int mainIndex = -1; - for (int i = 0; i < _items.Size(); i++) + FOR_VECTOR (i, _items) if (_items[i].IsReal) { if (mainIndex >= 0) @@ -371,6 +372,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) prop = (UInt32)mainIndex; break; } + case kpidPhySize: prop = _totalSize; break; } prop.Detach(value); return S_OK; @@ -435,7 +437,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _items.Size(); if (numItems == 0) @@ -497,10 +499,16 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) COM_TRY_END } -static IInArchive *CreateArc() { return new CHandler; } +IMP_CreateArcIn static CArcInfo g_ArcInfo = - { L"MBR", L"mbr", 0, 0xDB, { 1, 1, 0 }, 3, false, CreateArc, 0 }; + { "MBR", "mbr", 0, 0xDB, + // 3, { 1, 1, 0 }, + // 2, { 0x55, 0x1FF }, + 0, { 0 }, + 0, + NArcInfoFlags::kPureStartOpen, + CreateArc }; REGISTER_ARC(Mbr) diff --git a/CPP/7zip/Archive/MslzHandler.cpp b/CPP/7zip/Archive/MslzHandler.cpp old mode 100755 new mode 100644 index 67495e76..cb124c40 --- a/CPP/7zip/Archive/MslzHandler.cpp +++ b/CPP/7zip/Archive/MslzHandler.cpp @@ -4,10 +4,10 @@ #include "../../../C/CpuArch.h" -#include "Common/ComTry.h" -#include "Common/MyString.h" +#include "../../Common/ComTry.h" +#include "../../Common/MyString.h" -#include "Windows/PropVariant.h" +#include "../../Windows/PropVariant.h" #include "../Common/InBuffer.h" #include "../Common/ProgressUtils.h" @@ -19,28 +19,45 @@ namespace NArchive { namespace NMslz { +static const UInt32 kUnpackSizeMax = 0xFFFFFFE0; + class CHandler: public IInArchive, + public IArchiveOpenSeq, public CMyUnknownImp { - CMyComPtr _stream; - UInt32 _size; + CMyComPtr _inStream; + CMyComPtr _seqStream; + + bool _isArc; + bool _needSeekToStart; + bool _dataAfterEnd; + bool _needMoreInput; + + bool _packSize_Defined; + bool _unpackSize_Defined; + + UInt32 _unpackSize; UInt64 _packSize; + UInt64 _originalFileSize; UString _name; + + void ParseName(Byte replaceByte, IArchiveOpenCallback *callback); public: - MY_UNKNOWN_IMP1(IInArchive) + MY_UNKNOWN_IMP2(IInArchive, IArchiveOpenSeq) INTERFACE_IInArchive(;) + STDMETHOD(OpenSeq)(ISequentialInStream *stream); }; -STATPROPSTG kProps[] = +static const Byte kProps[] = { - { NULL, kpidPath, VT_BSTR}, - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, + kpidPath, + kpidSize, + kpidPackSize, }; IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO +IMP_IInArchive_ArcProps_NO_Table STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { @@ -48,15 +65,39 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) return S_OK; } +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch (propID) + { + case kpidExtension: prop = "mslz"; break; + case kpidIsNotArcType: prop = true; break; + case kpidPhySize: if (_packSize_Defined) prop = _packSize; break; + case kpidErrorFlags: + { + UInt32 v = 0; + if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;; + if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd; + if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd; + prop = v; + } + } + 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; - switch(propID) + switch (propID) { case kpidPath: if (!_name.IsEmpty()) prop = _name; break; - case kpidSize: prop = _size; break; - case kpidPackSize: prop = _packSize; break; + case kpidSize: if (_unpackSize_Defined || _inStream) prop = _unpackSize; break; + case kpidPackSize: if (_packSize_Defined || _inStream) prop = _packSize; break; } prop.Detach(value); return S_OK; @@ -67,69 +108,80 @@ 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 Byte kSignature[kSignatureSize] = MSLZ_SIGNATURE; -static const wchar_t *g_Exts[] = +// we support only 3 chars strings here +static const char *g_Exts[] = { - L"dll", - L"exe", - L"kmd", - L"sys" + "dll" + , "exe" + , "kmd" + , "sys" }; +void CHandler::ParseName(Byte replaceByte, IArchiveOpenCallback *callback) +{ + if (!callback) + return; + CMyComPtr volumeCallback; + callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&volumeCallback); + if (!volumeCallback) + return; + + NWindows::NCOM::CPropVariant prop; + if (volumeCallback->GetProperty(kpidName, &prop) != S_OK || prop.vt != VT_BSTR) + return; + + UString s = prop.bstrVal; + if (s.IsEmpty() || + s.Back() != L'_') + return; + + s.DeleteBack(); + _name = s; + + if (replaceByte == 0) + { + if (s.Len() < 3 || s[s.Len() - 3] != '.') + return; + for (unsigned i = 0; i < ARRAY_SIZE(g_Exts); i++) + { + const char *ext = g_Exts[i]; + if (s[s.Len() - 2] == ext[0] && + s[s.Len() - 1] == ext[1]) + { + replaceByte = ext[2]; + break; + } + } + } + if (replaceByte >= 0x20 && replaceByte < 0x80) + _name += (wchar_t)replaceByte; +} + STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback *callback) { COM_TRY_BEGIN { Close(); + _needSeekToStart = true; Byte buffer[kHeaderSize]; RINOK(ReadStream_FALSE(stream, buffer, kHeaderSize)); - if (memcmp(buffer, signature, kSignatureSize) != 0) + if (memcmp(buffer, kSignature, kSignatureSize) != 0) return S_FALSE; - _size = GetUi32(buffer + 10); - if (_size > 0xFFFFFFE0) + _unpackSize = GetUi32(buffer + 10); + if (_unpackSize > kUnpackSizeMax) return S_FALSE; - RINOK(stream->Seek(0, STREAM_SEEK_END, &_packSize)); + RINOK(stream->Seek(0, STREAM_SEEK_END, &_originalFileSize)); + _packSize = _originalFileSize; - 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; + ParseName(buffer[kSignatureSize], callback); + + _isArc = true; + _unpackSize_Defined = true; + _inStream = stream; + _seqStream = stream; } return S_OK; COM_TRY_END @@ -137,7 +189,20 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * /* maxCheckStartPo STDMETHODIMP CHandler::Close() { - _stream.Release(); + _originalFileSize = 0; + _packSize = 0; + _unpackSize = 0; + + _isArc = false; + _needSeekToStart = false; + _dataAfterEnd = false; + _needMoreInput = false; + + _packSize_Defined = false; + _unpackSize_Defined = false; + + _seqStream.Release(); + _inStream.Release(); _name.Empty(); return S_OK; } @@ -147,12 +212,13 @@ STDMETHODIMP CHandler::Close() // maxLen = 16; MS #define PROGRESS_AND_WRITE \ - if ((dest & kMask) == 0) { RINOK(WriteStream(outStream, buf, kBufSize)); \ + if ((dest & kMask) == 0) { if (outStream) RINOK(WriteStream(outStream, buf, kBufSize)); \ if ((dest & ((1 << 20) - 1)) == 0) \ - { UInt64 inSize = inStream.GetProcessedSize(); UInt64 outSize = dest; \ - RINOK(progress->SetRatioInfo(&inSize, &outSize)); }} + if (progress) \ + { UInt64 inSize = inStream.GetProcessedSize(); UInt64 outSize = dest; \ + RINOK(progress->SetRatioInfo(&inSize, &outSize)); }} -static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UInt32 unpackSize, ICompressProgressInfo *progress) +static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UInt32 unpackSize, bool &needMoreData, ICompressProgressInfo *progress) { const unsigned kBufSize = (1 << 12); const unsigned kMask = kBufSize - 1; @@ -163,11 +229,17 @@ static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UIn { Byte b; if (!inStream.ReadByte(b)) + { + needMoreData = true; return S_FALSE; + } for (unsigned mask = (unsigned)b | 0x100; mask > 1 && dest < unpackSize; mask >>= 1) { if (!inStream.ReadByte(b)) + { + needMoreData = true; return S_FALSE; + } if (mask & 1) { buf[dest++ & kMask] = b; @@ -177,7 +249,10 @@ static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UIn { Byte b1; if (!inStream.ReadByte(b1)) + { + needMoreData = true; 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; @@ -192,7 +267,19 @@ static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UIn } } } - return WriteStream(outStream, buf, dest & kMask); + if (outStream) + RINOK(WriteStream(outStream, buf, dest & kMask)); + return S_OK; +} + +STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) +{ + COM_TRY_BEGIN + Close(); + _isArc = true; + _seqStream = stream; + return S_OK; + COM_TRY_END } STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, @@ -201,10 +288,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_BEGIN if (numItems == 0) return S_OK; - if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0)) + if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) return E_INVALIDARG; - extractCallback->SetTotal(_size); + // extractCallback->SetTotal(_unpackSize); CMyComPtr realOutStream; Int32 askMode = testMode ? @@ -225,32 +312,81 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, 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]; + + if (_needSeekToStart) + { + if (!_inStream) + return E_FAIL; + RINOK(_inStream->Seek(0, STREAM_SEEK_SET, NULL)); + } + else + _needSeekToStart = true; + Int32 opRes = NExtract::NOperationResult::kDataError; - if (s.ReadBytes(buffer, kHeaderSize) == kHeaderSize) + + bool isArc = false; + bool needMoreInput = false; + try { - HRESULT result = MslzDec(s, outStream, _size, progress); - if (result == S_OK) - opRes = NExtract::NOperationResult::kOK; - else if (result != S_FALSE) - return result; + CInBuffer s; + if (!s.Create(1 << 20)) + return E_OUTOFMEMORY; + s.SetStream(_seqStream); + s.Init(); + + Byte buffer[kHeaderSize]; + if (s.ReadBytes(buffer, kHeaderSize) == kHeaderSize) + { + UInt32 unpackSize; + if (memcmp(buffer, kSignature, kSignatureSize) == 0) + { + unpackSize = GetUi32(buffer + 10); + if (unpackSize <= kUnpackSizeMax) + { + HRESULT result = MslzDec(s, outStream, unpackSize, needMoreInput, progress); + if (result == S_OK) + opRes = NExtract::NOperationResult::kOK; + else if (result != S_FALSE) + return result; + _unpackSize = unpackSize; + _unpackSize_Defined = true; + + _packSize = s.GetProcessedSize(); + _packSize_Defined = true; + + if (_inStream && _packSize < _originalFileSize) + _dataAfterEnd = true; + + isArc = true; + } + } + } } + catch (CInBufferException &e) { return e.ErrorCode; } + + _isArc = isArc; + if (isArc) + _needMoreInput = needMoreInput; + if (!_isArc) + opRes = NExtract::NOperationResult::kIsNotArc; + else if (_needMoreInput) + opRes = NExtract::NOperationResult::kUnexpectedEnd; + else if (_dataAfterEnd) + opRes = NExtract::NOperationResult::kDataAfterEnd; + outStream.Release(); return extractCallback->SetOperationResult(opRes); COM_TRY_END } -static IInArchive *CreateArc() { return new CHandler; } +IMP_CreateArcIn static CArcInfo g_ArcInfo = - { L"MsLZ", L"", 0, 0xD5, MSLZ_SIGNATURE, kSignatureSize, false, CreateArc, 0 }; + { "MsLZ", "mslz", 0, 0xD5, + kSignatureSize, MSLZ_SIGNATURE, + 0, + 0, + CreateArc }; REGISTER_ARC(Mslz) diff --git a/CPP/7zip/Archive/MubHandler.cpp b/CPP/7zip/Archive/MubHandler.cpp old mode 100755 new mode 100644 index 5ebda099..39f8de27 --- a/CPP/7zip/Archive/MubHandler.cpp +++ b/CPP/7zip/Archive/MubHandler.cpp @@ -4,9 +4,11 @@ #include "../../../C/CpuArch.h" -#include "Common/ComTry.h" +#include "../../Common/ComTry.h" +#include "../../Common/IntToString.h" +#include "../../Common/MyString.h" -#include "Windows/PropVariant.h" +#include "../../Windows/PropVariant.h" #include "../Common/LimitedStreams.h" #include "../Common/ProgressUtils.h" @@ -15,32 +17,50 @@ #include "../Compress/CopyCoder.h" -static UInt32 Get32(const Byte *p, int be) { if (be) return GetBe32(p); return GetUi32(p); } +static UInt32 Get32(const Byte *p, bool be) { if (be) return GetBe32(p); return GetUi32(p); } + +using namespace NWindows; +using namespace NCOM; namespace NArchive { namespace NMub { +#define MACH_CPU_ARCH_ABI64 (1 << 24) +#define MACH_CPU_TYPE_386 7 +#define MACH_CPU_TYPE_ARM 12 +#define MACH_CPU_TYPE_SPARC 14 +#define MACH_CPU_TYPE_PPC 18 + +#define MACH_CPU_TYPE_PPC64 (MACH_CPU_ARCH_ABI64 | MACH_CPU_TYPE_PPC) +#define MACH_CPU_TYPE_AMD64 (MACH_CPU_ARCH_ABI64 | MACH_CPU_TYPE_386) + +#define MACH_CPU_SUBTYPE_LIB64 (1 << 31) + +#define MACH_CPU_SUBTYPE_I386_ALL 3 + struct CItem { UInt32 Type; UInt32 SubType; - UInt64 Offset; - UInt64 Size; - UInt32 Align; - bool IsTail; + UInt32 Offset; + UInt32 Size; + // UInt32 Align; }; -const UInt32 kNumFilesMax = 10; +static const UInt32 kNumFilesMax = 10; class CHandler: public IInArchive, public IInArchiveGetStream, public CMyUnknownImp { - UInt64 _startPos; CMyComPtr _stream; + // UInt64 _startPos; + UInt64 _phySize; UInt32 _numItems; - CItem _items[kNumFilesMax + 1]; + bool _bigEndian; + CItem _items[kNumFilesMax]; + HRESULT Open2(IInStream *stream); public: MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) @@ -48,65 +68,79 @@ public: STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); }; -STATPROPSTG kProps[] = +static const Byte kArcProps[] = { - { NULL, kpidSize, VT_UI8} + kpidBigEndian }; -IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO +static const Byte kProps[] = +{ + kpidSize +}; -#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 +IMP_IInArchive_Props +IMP_IInArchive_ArcProps -#define MACH_MACHINE_PPC64 (MACH_MACHINE_PPC | MACH_ARCH_ABI64) -#define MACH_MACHINE_AMD64 (MACH_MACHINE_386 | MACH_ARCH_ABI64) +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + PropVariant_Clear(value); + switch (propID) + { + case kpidBigEndian: PropVarEm_Set_Bool(value, _bigEndian); break; + case kpidPhySize: PropVarEm_Set_UInt64(value, _phySize); break; + } + return S_OK; +} STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { - NWindows::NCOM::CPropVariant prop; + PropVariant_Clear(value); const CItem &item = _items[index]; - switch(propID) + switch (propID) { case kpidExtension: { - const wchar_t *ext; - if (item.IsTail) - ext = L"tail"; - else + char temp[32]; + const char *ext = 0; + switch (item.Type) { - 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; - } + case MACH_CPU_TYPE_386: ext = "x86"; break; + case MACH_CPU_TYPE_ARM: ext = "arm"; break; + case MACH_CPU_TYPE_SPARC: ext = "sparc"; break; + case MACH_CPU_TYPE_PPC: ext = "ppc"; break; + case MACH_CPU_TYPE_PPC64: ext = "ppc64"; break; + case MACH_CPU_TYPE_AMD64: ext = "x64"; break; + default: + temp[0] = 'c'; + temp[1] = 'p'; + temp[2] = 'u'; + ConvertUInt32ToString(item.Type, temp + 3); + break; } - prop = ext; - break; + if (ext) + strcpy(temp, ext); + if (item.SubType != 0 && ( + item.Type != MACH_CPU_TYPE_386 && + item.Type != MACH_CPU_TYPE_AMD64 || + (item.SubType & ~(UInt32)MACH_CPU_SUBTYPE_LIB64) != MACH_CPU_SUBTYPE_I386_ALL)) + { + unsigned pos = MyStringLen(temp); + temp[pos++] = '-'; + ConvertUInt32ToString(item.SubType, temp + pos); + } + return PropVarEm_Set_Str(value, temp); } case kpidSize: case kpidPackSize: - prop = (UInt64)item.Size; + PropVarEm_Set_UInt64(value, 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)); + // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_startPos)); const UInt32 kHeaderSize = 8; const UInt32 kRecordSize = 5 * 4; @@ -124,44 +158,37 @@ HRESULT CHandler::Open2(IInStream *stream) case 0xB9FAF10E: be = false; break; default: return S_FALSE; } + _bigEndian = be; UInt32 num = Get32(buf + 4, be); if (num > kNumFilesMax || processed < kHeaderSize + num * kRecordSize) return S_FALSE; + if (num == 0) + 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, be); sb.SubType = Get32(p + 4, be); sb.Offset = Get32(p + 8, be); sb.Size = Get32(p + 12, be); - sb.Align = Get32(p + 16, be); - - if ((sb.Type & ~MACH_TYPE_ABI64) >= 0x100 || - (sb.SubType & ~MACH_SUBTYPE_ABI64) >= 0x100 || - sb.Align > 31) + UInt32 align = Get32(p + 16, be); + if (align > 31) + return S_FALSE; + if (sb.Offset < kHeaderSize + num * kRecordSize) + return S_FALSE; + if ((sb.Type & ~MACH_CPU_ARCH_ABI64) >= 0x100 || + (sb.SubType & ~MACH_CPU_SUBTYPE_LIB64) >= 0x100) return S_FALSE; UInt64 endPos = (UInt64)sb.Offset + sb.Size; - if (endPos > endPosMax) + if (endPosMax < endPos) 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; - } + _phySize = endPosMax; return S_OK; } @@ -186,6 +213,7 @@ STDMETHODIMP CHandler::Close() { _stream.Release(); _numItems = 0; + _phySize = 0; return S_OK; } @@ -199,7 +227,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _numItems; if (numItems == 0) @@ -244,7 +272,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); continue; } - RINOK(_stream->Seek(_startPos + item.Offset, STREAM_SEEK_SET, NULL)); + RINOK(_stream->Seek(/* _startPos + */ item.Offset, STREAM_SEEK_SET, NULL)); streamSpec->Init(item.Size); RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); realOutStream.Release(); @@ -260,15 +288,27 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) { COM_TRY_BEGIN const CItem &item = _items[index]; - return CreateLimitedInStream(_stream, _startPos + item.Offset, item.Size, stream); + return CreateLimitedInStream(_stream, /* _startPos + */ item.Offset, item.Size, stream); COM_TRY_END } -static IInArchive *CreateArc() { return new CHandler; } +IMP_CreateArcIn + +namespace NBe { static CArcInfo g_ArcInfo = - { L"Mub", L"", 0, 0xE2, { 0xCA, 0xFE, 0xBA, 0xBE, 0, 0, 0 }, 7, false, CreateArc, 0 }; + { "Mub", "mub", 0, 0xE2, + 2 + 7 + 4, + { + 7, 0xCA, 0xFE, 0xBA, 0xBE, 0, 0, 0, + 4, 0xB9, 0xFA, 0xF1, 0x0E + }, + 0, + NArcInfoFlags::kMultiSignature, + CreateArc }; REGISTER_ARC(Mub) +} + }} diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.cpp b/CPP/7zip/Archive/Nsis/NsisDecode.cpp old mode 100755 new mode 100644 index 0845f965..bb73d273 --- a/CPP/7zip/Archive/Nsis/NsisDecode.cpp +++ b/CPP/7zip/Archive/Nsis/NsisDecode.cpp @@ -2,66 +2,65 @@ #include "StdAfx.h" -#include "NsisDecode.h" +#include "../../../../C/CpuArch.h" -#include "../../Common/StreamUtils.h" +#include "NsisDecode.h" +#include "../../Common/CreateCoder.h" +#include "../../Common/FilterCoder.h" +#include "../../Common/LimitedStreams.h" #include "../../Common/MethodId.h" +#include "../../Compress/BcjCoder.h" #include "../../Compress/BZip2Decoder.h" #include "../../Compress/DeflateDecoder.h" -#include "../../Compress/LzmaDecoder.h" + +#define Get32(p) GetUi32(p) 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) +HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter) { useFilter = false; - CObjectVector< CMyComPtr > inStreams; if (_decoderInStream) - if (method != _method) + if (Method != _curMethod) Release(); - _method = method; + _curMethod = Method; if (!_codecInStream) { - switch (method) + 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; + case NMethodType::kLZMA: + _lzmaDecoder = new NCompress::NLzma::CDecoder(); + _codecInStream = _lzmaDecoder; + break; default: return E_NOTIMPL; } } - if (thereIsFilterFlag) + if (FilterFlag) { - UInt32 processedSize; - BYTE flag; - RINOK(inStream->Read(&flag, 1, &processedSize)); - if (processedSize != 1) - return E_FAIL; + Byte flag; + RINOK(ReadStream_FALSE(inStream, &flag, 1)); if (flag > 1) return E_NOTIMPL; useFilter = (flag != 0); } - if (useFilter) + if (!useFilter) + _decoderInStream = _codecInStream; + else { if (!_filterInStream) { - CMyComPtr coder; - RINOK(CreateCoder( - EXTERNAL_CODECS_LOC_VARS - k_BCJ_X86, coder, false)); - if (!coder) - return E_NOTIMPL; + CFilterCoder *coderSpec = new CFilterCoder; + CMyComPtr coder = coderSpec; + coderSpec->Filter = new CBCJ_x86_Decoder(); coder.QueryInterface(IID_ISequentialInStream, &_filterInStream); if (!_filterInStream) return E_NOTIMPL; @@ -73,23 +72,13 @@ HRESULT CDecoder::Init( RINOK(setInStream->SetInStream(_codecInStream)); _decoderInStream = _filterInStream; } - else - _decoderInStream = _codecInStream; - if (method == NMethodType::kLZMA) + 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)); - } + const unsigned kPropsSize = LZMA_PROPS_SIZE; + Byte props[kPropsSize]; + RINOK(ReadStream_FALSE(inStream, props, kPropsSize)); + RINOK(_lzmaDecoder->SetDecoderProperties2((const Byte *)props, kPropsSize)); } { @@ -122,9 +111,155 @@ HRESULT CDecoder::Init( return S_OK; } -HRESULT CDecoder::Read(void *data, size_t *processedSize) +static const UInt32 kMask_IsCompressed = (UInt32)1 << 31; + +HRESULT CDecoder::SetToPos(UInt64 pos, ICompressProgressInfo *progress) { - return ReadStream(_decoderInStream, data, processedSize);; + if (StreamPos > pos) + return E_FAIL; + UInt64 inSizeStart = 0; + if (_lzmaDecoder) + inSizeStart = _lzmaDecoder->GetInputProcessedSize(); + UInt64 offset = 0; + while (StreamPos < pos) + { + size_t size = (size_t)MyMin(pos - StreamPos, (UInt64)Buffer.Size()); + RINOK(Read(Buffer, &size)); + if (size == 0) + return S_FALSE; + StreamPos += size; + offset += size; + + UInt64 inSize = 0; + if (_lzmaDecoder) + inSize = _lzmaDecoder->GetInputProcessedSize() - inSizeStart; + RINOK(progress->SetRatioInfo(&inSize, &offset)); + } + return S_OK; +} + +HRESULT CDecoder::Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unpackSize, + ISequentialOutStream *realOutStream, ICompressProgressInfo *progress, + UInt32 &packSizeRes, UInt32 &unpackSizeRes) +{ + CLimitedSequentialInStream *limitedStreamSpec = NULL; + CMyComPtr limitedStream; + packSizeRes = 0; + unpackSizeRes = 0; + + if (Solid) + { + Byte temp[4]; + size_t processedSize = 4; + RINOK(Read(temp, &processedSize)); + if (processedSize != 4) + return S_FALSE; + StreamPos += processedSize; + UInt32 size = Get32(temp); + if (unpackSizeDefined && size != unpackSize) + return S_FALSE; + unpackSize = size; + unpackSizeDefined = true; + } + else + { + Byte temp[4]; + RINOK(ReadStream_FALSE(InputStream, temp, 4)); + StreamPos += 4; + UInt32 size = Get32(temp); + + if ((size & kMask_IsCompressed) == 0) + { + if (unpackSizeDefined && size != unpackSize) + return S_FALSE; + packSizeRes = size; + if (outBuf) + outBuf->Alloc(size); + + UInt64 offset = 0; + + while (size > 0) + { + UInt32 curSize = (UInt32)MyMin((size_t)size, Buffer.Size()); + UInt32 processedSize; + RINOK(InputStream->Read(Buffer, curSize, &processedSize)); + if (processedSize == 0) + return S_FALSE; + if (outBuf) + memcpy((Byte *)*outBuf + (size_t)offset, Buffer, processedSize); + offset += processedSize; + size -= processedSize; + StreamPos += processedSize; + unpackSizeRes += processedSize; + if (realOutStream) + RINOK(WriteStream(realOutStream, Buffer, processedSize)); + RINOK(progress->SetRatioInfo(&offset, &offset)); + } + + return S_OK; + } + + size &= ~kMask_IsCompressed; + packSizeRes = size; + limitedStreamSpec = new CLimitedSequentialInStream; + limitedStream = limitedStreamSpec; + limitedStreamSpec->SetStream(InputStream); + limitedStreamSpec->Init(size); + { + bool useFilter; + RINOK(Init(limitedStream, useFilter)); + } + } + + if (outBuf) + { + if (!unpackSizeDefined) + return S_FALSE; + outBuf->Alloc(unpackSize); + } + + UInt64 inSizeStart = 0; + if (_lzmaDecoder) + inSizeStart = _lzmaDecoder->GetInputProcessedSize(); + + // we don't allow files larger than 4 GB; + if (!unpackSizeDefined) + unpackSize = 0xFFFFFFFF; + UInt32 offset = 0; + + for (;;) + { + size_t rem = unpackSize - offset; + if (rem == 0) + break; + size_t size = Buffer.Size(); + if (size > rem) + size = rem; + RINOK(Read(Buffer, &size)); + if (size == 0) + { + if (unpackSizeDefined) + return S_FALSE; + break; + } + if (outBuf) + memcpy((Byte *)*outBuf + (size_t)offset, Buffer, size); + StreamPos += size; + offset += (UInt32)size; + + UInt64 inSize = 0; // it can be improved: we need inSize for Deflate and BZip2 too. + if (_lzmaDecoder) + inSize = _lzmaDecoder->GetInputProcessedSize() - inSizeStart; + if (Solid) + packSizeRes = (UInt32)inSize; + unpackSizeRes += (UInt32)size; + + UInt64 outSize = offset; + RINOK(progress->SetRatioInfo(&inSize, &outSize)); + if (realOutStream) + RINOK(WriteStream(realOutStream, Buffer, size)); + } + return S_OK; } }} diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.h b/CPP/7zip/Archive/Nsis/NsisDecode.h old mode 100755 new mode 100644 index 36aeb2b1..2ccaaf65 --- a/CPP/7zip/Archive/Nsis/NsisDecode.h +++ b/CPP/7zip/Archive/Nsis/NsisDecode.h @@ -3,9 +3,11 @@ #ifndef __NSIS_DECODE_H #define __NSIS_DECODE_H -#include "../../IStream.h" +#include "../../../Common/MyBuffer.h" -#include "../../Common/CreateCoder.h" +#include "../../Common/StreamUtils.h" + +#include "../../Compress/LzmaDecoder.h" namespace NArchive { namespace NNsis { @@ -21,25 +23,50 @@ namespace NMethodType }; } +/* 7-Zip installers 4.38 - 9.08 used modified version of NSIS that + supported BCJ filter for better compression ratio. + We support such modified NSIS archives. */ + class CDecoder { - NMethodType::EEnum _method; + NMethodType::EEnum _curMethod; // method of created decoder CMyComPtr _filterInStream; CMyComPtr _codecInStream; CMyComPtr _decoderInStream; + NCompress::NLzma::CDecoder *_lzmaDecoder; + public: + CMyComPtr InputStream; // for non-solid + UInt64 StreamPos; // the pos in unpacked for solid, the pos in Packed for non-solid + + NMethodType::EEnum Method; + bool FilterFlag; + bool Solid; + + CByteBuffer Buffer; // temp buf. + void Release() { _filterInStream.Release(); _codecInStream.Release(); _decoderInStream.Release(); + InputStream.Release(); + _lzmaDecoder = NULL; } - HRESULT Init( - DECL_EXTERNAL_CODECS_LOC_VARS - IInStream *inStream, NMethodType::EEnum method, bool thereIsFilterFlag, bool &useFilter); - HRESULT Read(void *data, size_t *processedSize); + + HRESULT Init(ISequentialInStream *inStream, bool &useFilter); + HRESULT Read(void *data, size_t *processedSize) + { + return ReadStream(_decoderInStream, data, processedSize);; + } + + + HRESULT CDecoder::SetToPos(UInt64 pos, ICompressProgressInfo *progress); // for solid + HRESULT Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unpackSize, + ISequentialOutStream *realOutStream, ICompressProgressInfo *progress, + UInt32 &packSizeRes, UInt32 &unpackSizeRes); }; }} diff --git a/CPP/7zip/Archive/Nsis/NsisHandler.cpp b/CPP/7zip/Archive/Nsis/NsisHandler.cpp old mode 100755 new mode 100644 index 4058bd2a..868ca6cb --- a/CPP/7zip/Archive/Nsis/NsisHandler.cpp +++ b/CPP/7zip/Archive/Nsis/NsisHandler.cpp @@ -4,11 +4,12 @@ #include "../../../../C/CpuArch.h" -#include "Common/ComTry.h" -#include "Common/IntToString.h" +#include "../../../Common/ComTry.h" +#include "../../../Common/IntToString.h" -#include "Windows/PropVariant.h" +#include "../../../Windows/PropVariant.h" +#include "../../Common/ProgressUtils.h" #include "../../Common/StreamUtils.h" #include "../Common/ItemNameUtils.h" @@ -27,54 +28,160 @@ static const char *kUnknownMethod = "Unknown"; static const char *kMethods[] = { - "Copy", - "Deflate", - "BZip2", - "LZMA" + "Copy" + , "Deflate" + , "BZip2" + , "LZMA" }; -static const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]); - -static STATPROPSTG kProps[] = +static const Byte 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} + kpidPath, + kpidSize, + kpidPackSize, + kpidMTime, + kpidAttrib, + kpidMethod, + kpidSolid, + kpidOffset }; -static STATPROPSTG kArcProps[] = +static const Byte kArcProps[] = { - { NULL, kpidMethod, VT_BSTR}, - { NULL, kpidSolid, VT_BOOL} + kpidMethod, + kpidSolid, + kpidHeadersSize, + kpidEmbeddedStubSize, + kpidSubType + // kpidCodePage }; IMP_IInArchive_Props IMP_IInArchive_ArcProps + +static AString UInt32ToString(UInt32 val) +{ + char s[16]; + ConvertUInt32ToString(val, s); + return s; +} + +static AString GetStringForSizeValue(UInt32 val) +{ + for (int i = 31; i >= 0; i--) + if (((UInt32)1 << i) == val) + return UInt32ToString(i); + char c = 'b'; + if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; } + else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; } + return UInt32ToString(val) + c; +} + +static AString GetMethod(bool useFilter, NMethodType::EEnum method, UInt32 dict) +{ + AString s; + if (useFilter) + { + s += kBcjMethod; + s += ' '; + } + s += (method < ARRAY_SIZE(kMethods)) ? kMethods[method] : kUnknownMethod; + if (method == NMethodType::kLZMA) + { + s += ':'; + s += GetStringForSizeValue(dict); + } + return s; +} + +/* +AString CHandler::GetMethod(NMethodType::EEnum method, bool useItemFilter, UInt32 dictionary) const +{ + AString s; + if (_archive.IsSolid && _archive.UseFilter || !_archive.IsSolid && useItemFilter) + { + s += kBcjMethod; + s += ' '; + } + s += (method < ARRAY_SIZE(kMethods)) ? kMethods[method] : kUnknownMethod; + if (method == NMethodType::kLZMA) + { + s += ':'; + s += GetStringForSizeValue(_archive.IsSolid ? _archive.DictionarySize: dictionary); + } + return s; +} +*/ + STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; - switch(propID) + NCOM::CPropVariant prop; + switch (propID) { - case kpidMethod: + // case kpidCodePage: if (_archive.IsUnicode) prop = "UTF-16"; break; + case kpidSubType: { - UInt32 dict = 1; - bool filter = false; - for (int i = 0; i < _archive.Items.Size(); i++) + AString s = _archive.GetFormatDescription(); + if (!_archive.IsInstaller) { - const CItem &item = _archive.Items[i]; - filter |= item.UseFilter; - if (item.DictionarySize > dict) - dict = item.DictionarySize; + if (!s.IsEmpty()) + s += ' '; + s += "(Uninstall)"; } - prop = GetMethod(filter, dict); + if (!s.IsEmpty()) + prop = s; break; } + + case kpidMethod: prop = _methodString; break; case kpidSolid: prop = _archive.IsSolid; break; + case kpidOffset: prop = _archive.StartOffset; break; + case kpidPhySize: prop = _archive.ExeStub.Size() + _archive.FirstHeader.ArcSize; break; + case kpidEmbeddedStubSize: prop = _archive.ExeStub.Size(); break; + case kpidHeadersSize: prop = _archive.FirstHeader.HeaderSize; break; + + case kpidErrorFlags: + { + UInt32 v = 0; + if (!_archive.IsArc) v |= kpv_ErrorFlags_IsNotArc; + if (_archive.IsTruncated()) v |= kpv_ErrorFlags_UnexpectedEnd; + prop = v; + break; + } + + case kpidName: + { + AString s; + + #ifdef NSIS_SCRIPT + if (!_archive.Name.IsEmpty()) + s = _archive.Name; + if (!_archive.IsInstaller) + { + if (!s.IsEmpty()) + s += '.'; + s += "Uninstall"; + } + #endif + + if (s.IsEmpty()) + s = _archive.IsInstaller ? "Install" : "Uninstall"; + s += (_archive.ExeStub.Size() == 0) ? ".nsis" : ".exe"; + + prop = _archive.ConvertToUnicode(s); + break; + } + + #ifdef NSIS_SCRIPT + case kpidShortComment: + { + if (!_archive.BrandingText.IsEmpty()) + prop = _archive.ConvertToUnicode(_archive.BrandingText); + break; + } + #endif } prop.Detach(value); return S_OK; @@ -82,16 +189,26 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) } -STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * maxCheckStartPosition, IArchiveOpenCallback * /* openArchiveCallback */) +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback * /* openArchiveCallback */) { COM_TRY_BEGIN Close(); { - if (_archive.Open( - EXTERNAL_CODECS_VARS - stream, maxCheckStartPosition) != S_OK) + if (_archive.Open(stream, maxCheckStartPosition) != S_OK) return S_FALSE; - _inStream = stream; + { + UInt32 dict = _archive.DictionarySize; + if (!_archive.IsSolid) + { + FOR_VECTOR (i, _archive.Items) + { + const CItem &item = _archive.Items[i]; + if (item.DictionarySize > dict) + dict = item.DictionarySize; + } + } + _methodString = GetMethod(_archive.UseFilter, _archive.Method, dict); + } } return S_OK; COM_TRY_END @@ -101,7 +218,6 @@ STDMETHODIMP CHandler::Close() { _archive.Clear(); _archive.Release(); - _inStream.Release(); return S_OK; } @@ -109,74 +225,30 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { *numItems = _archive.Items.Size() #ifdef NSIS_SCRIPT - + 1 + + 1 + _archive.LicenseFiles.Size(); #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) +bool CHandler::GetUncompressedSize(unsigned index, UInt32 &size) const { size = 0; const CItem &item = _archive.Items[index]; - if (item.SizeIsDefined) - size = item.Size; - else if (_archive.IsSolid && item.EstimatedSizeIsDefined) - size = item.EstimatedSize; + if (item.Size_Defined) + size = item.Size; + else if (_archive.IsSolid && item.EstimatedSize_Defined) + size = item.EstimatedSize; else return false; return true; } -bool CHandler::GetCompressedSize(int index, UInt32 &size) +bool CHandler::GetCompressedSize(unsigned index, UInt32 &size) const { size = 0; const CItem &item = _archive.Items[index]; - if (item.CompressedSizeIsDefined) + if (item.CompressedSize_Defined) size = item.CompressedSize; else { @@ -202,27 +274,42 @@ bool CHandler::GetCompressedSize(int index, UInt32 &size) STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; + NCOM::CPropVariant prop; #ifdef NSIS_SCRIPT if (index >= (UInt32)_archive.Items.Size()) { - switch(propID) + if (index == (UInt32)_archive.Items.Size()) { - case kpidPath: prop = L"[NSIS].nsi"; break; - case kpidSize: - case kpidPackSize: prop = (UInt64)_archive.Script.Length(); break; - case kpidSolid: prop = false; break; + switch (propID) + { + case kpidPath: prop = "[NSIS].nsi"; break; + case kpidSize: + case kpidPackSize: prop = (UInt64)_archive.Script.Len(); break; + case kpidSolid: prop = false; break; + } + } + else + { + const CLicenseFile &lic = _archive.LicenseFiles[index - (_archive.Items.Size() + 1)]; + switch (propID) + { + case kpidPath: prop = lic.Name; break; + case kpidSize: + case kpidPackSize: prop = (UInt64)lic.Size; break; + case kpidSolid: prop = false; break; + } } } else #endif { const CItem &item = _archive.Items[index]; - switch(propID) + switch (propID) { + case kpidOffset: prop = item.Pos; break; case kpidPath: { - UString s = NItemName::WinNameToOSName(item.GetReducedName(_archive.IsUnicode)); + UString s = NItemName::WinNameToOSName(_archive.GetReducedName(index)); if (!s.IsEmpty()) prop = (const wchar_t *)s; break; @@ -248,7 +335,21 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val prop = item.MTime; break; } - case kpidMethod: prop = GetMethod(item.UseFilter, item.DictionarySize); break; + case kpidAttrib: + { + if (item.Attrib_Defined) + prop = item.Attrib; + break; + } + + case kpidMethod: + if (_archive.IsSolid) + prop = _methodString; + else + prop = GetMethod(_archive.UseFilter, item.IsCompressed ? _archive.Method : + NMethodType::kCopy, item.DictionarySize); + break; + case kpidSolid: prop = _archive.IsSolid; break; } } @@ -257,24 +358,56 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val COM_TRY_END } + +static bool UninstallerPatch(const Byte *p, size_t size, CByteBuffer &dest) +{ + for (;;) + { + if (size < 4) + return false; + UInt32 len = Get32(p); + if (len == 0) + return size == 4; + if (size < 8) + return false; + UInt32 offs = Get32(p + 4); + p += 8; + size -= 8; + if (size < len || offs > dest.Size() || len > dest.Size() - offs) + return false; + memcpy(dest + offs, p, len); + p += len; + size -= len; + } +} + + STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) GetNumberOfItems(&numItems); if (numItems == 0) return S_OK; + UInt64 totalSize = 0; + UInt64 solidPosMax = 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(); + if (index >= _archive.Items.Size()) + { + if (index == _archive.Items.Size()) + totalSize += _archive.Script.Len(); + else + totalSize += _archive.LicenseFiles[index - (_archive.Items.Size() + 1)].Size; + } else #endif { @@ -282,9 +415,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (_archive.IsSolid) { GetUncompressedSize(index, size); - UInt64 pos = _archive.GetPosOfSolidItem(index); - if (pos > totalSize) - totalSize = pos + size; + UInt64 pos = (UInt64)_archive.GetPosOfSolidItem(index) + size; + if (solidPosMax < pos) + solidPosMax = pos; } else { @@ -293,33 +426,58 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } } } - extractCallback->SetTotal(totalSize); - UInt64 currentTotalSize = 0; - UInt32 currentItemSize = 0; + extractCallback->SetTotal(totalSize + solidPosMax); + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, !_archive.IsSolid); - 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)); + RINOK(_archive.SeekTo_DataStreamOffset()); + RINOK(_archive.InitDecoder()); + _archive.Decoder.StreamPos = 0; } - CByteBuffer byteBuf; - const UInt32 kBufferLength = 1 << 16; - byteBuf.SetCapacity(kBufferLength); - Byte *buffer = byteBuf; + /* We use tempBuf for solid archives, if there is duplicate item. + We don't know uncompressed size for non-solid archives, so we can't + allocate exact buffer. + We use tempBuf also for first part (EXE stub) of unistall.exe + and tempBuf2 is used for second part (NSIS script). */ CByteBuffer tempBuf; - - bool dataError = false; - for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) + CByteBuffer tempBuf2; + + /* tempPos is pos in uncompressed stream of previous item for solid archive, that + was written to tempBuf */ + UInt64 tempPos = (UInt64)(Int64)-1; + + /* prevPos is pos in uncompressed stream of previous item for solid archive. + It's used for test mode (where we don't need to test same file second time */ + UInt64 prevPos = (UInt64)(Int64)-1; + + // if there is error in solid archive, we show error for all subsequent files + bool solidDataError = false; + + UInt64 curTotalPacked = 0, curTotalUnpacked = 0; + UInt32 curPacked = 0; + UInt64 curUnpacked = 0; + + for (i = 0; i < numItems; i++, + curTotalPacked += curPacked, + curTotalUnpacked += curUnpacked) { - currentItemSize = 0; - RINOK(extractCallback->SetCompleted(¤tTotalSize)); + lps->InSize = curTotalPacked; + lps->OutSize = curTotalUnpacked; + if (_archive.IsSolid) + lps->OutSize += _archive.Decoder.StreamPos; + + curPacked = 0; + curUnpacked = 0; + RINOK(lps->SetCur()); + + // RINOK(extractCallback->SetCompleted(¤tTotalSize)); CMyComPtr realOutStream; Int32 askMode = testMode ? NExtract::NAskMode::kTest : @@ -328,169 +486,184 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + bool dataError = false; + #ifdef NSIS_SCRIPT if (index >= (UInt32)_archive.Items.Size()) { - currentItemSize = _archive.Script.Length(); + const void *data; + size_t size; + if (index == (UInt32)_archive.Items.Size()) + { + data = (const Byte *)_archive.Script; + size = _archive.Script.Len(); + } + else + { + CLicenseFile &lic = _archive.LicenseFiles[index - (_archive.Items.Size() + 1)]; + if (lic.Text.Size() != 0) + data = lic.Text; + else + data = _archive._data + lic.Offset; + size = lic.Size; + } + curUnpacked = size; if (!testMode && !realOutStream) continue; RINOK(extractCallback->PrepareOperation(askMode)); - if (!testMode) - RINOK(WriteStream(realOutStream, (const char *)_archive.Script, (UInt32)_archive.Script.Length())); + if (realOutStream) + RINOK(WriteStream(realOutStream, data, size)); } else #endif { const CItem &item = _archive.Items[index]; - if (_archive.IsSolid) - GetUncompressedSize(index, currentItemSize); - else - GetCompressedSize(index, currentItemSize); + if (!_archive.IsSolid) + GetCompressedSize(index, curPacked); if (!testMode && !realOutStream) continue; RINOK(extractCallback->PrepareOperation(askMode)); - if (!dataError) + dataError = solidDataError; + + bool needDecompress = !solidDataError; + if (needDecompress) { - bool needDecompress = false; - bool sizeIsKnown = false; - UInt32 fullSize = 0; + if (testMode && _archive.IsSolid && _archive.GetPosOfSolidItem(index) == prevPos) + needDecompress = false; + } + if (needDecompress) + { bool writeToTemp = false; bool readFromTemp = false; - if (_archive.IsSolid) + if (!_archive.IsSolid) + { + RINOK(_archive.SeekToNonSolidItem(index)); + } + else { UInt64 pos = _archive.GetPosOfSolidItem(index); - while (streamPos < pos) + if (pos < _archive.Decoder.StreamPos) + { + if (pos != tempPos) + solidDataError = dataError = true; + readFromTemp = true; + } + else { - size_t processedSize = (UInt32)MyMin(pos - streamPos, (UInt64)kBufferLength); - HRESULT res = _archive.Decoder.Read(buffer, &processedSize); + HRESULT res = _archive.Decoder.SetToPos(pos, progress); if (res != S_OK) { if (res != S_FALSE) return res; - dataError = true; - break; + solidDataError = dataError = true; } - if (processedSize == 0) + else if (!testMode && i + 1 < numItems) { - dataError = true; - break; + UInt32 next = allFilesMode ? i + 1 : indices[i + 1]; + if (next < _archive.Items.Size()) + { + UInt64 nextPos = _archive.GetPosOfSolidItem(next); + if (nextPos == pos) + { + writeToTemp = true; + tempPos = pos; + } + } } - streamPos += processedSize; } - if (streamPos == pos) + prevPos = pos; + } + + if (!dataError) + { + UInt32 unpackSize = 0; + bool unpackSize_Defined = false; + bool writeToTemp1 = writeToTemp; + if (item.IsUninstaller) { - 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) + unpackSize = item.PatchSize; + unpackSize_Defined = true; + if (!readFromTemp) + writeToTemp = true; + writeToTemp1 = writeToTemp; + if (_archive.ExeStub.Size() == 0) { - UInt64 nextPos = _archive.GetPosOfSolidItem(allFilesMode ? i : indices[i + 1]); - if (nextPos < streamPos + fullSize) - { + if (writeToTemp1 && !readFromTemp) tempBuf.Free(); - tempBuf.SetCapacity(fullSize); - writeToTemp = true; - } + writeToTemp1 = false; } } - else - readFromTemp = true; - } - else - { - RINOK(_inStream->Seek(_archive.GetPosOfNonSolidItem(index) + 4, STREAM_SEEK_SET, NULL)); - if (item.IsCompressed) + + if (readFromTemp) { - 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; + if (realOutStream && !item.IsUninstaller) + RINOK(WriteStream(realOutStream, tempBuf, tempBuf.Size())); } else - fullSize = item.Size; - } - if (!dataError) - { - if (needDecompress) { - UInt64 offset = 0; - while (!sizeIsKnown || fullSize > 0) + UInt32 curUnpacked32 = 0; + HRESULT res = _archive.Decoder.Decode( + writeToTemp1 ? &tempBuf : NULL, + item.IsUninstaller, item.PatchSize, + item.IsUninstaller ? NULL : realOutStream, + progress, + curPacked, curUnpacked32); + curUnpacked = curUnpacked32; + if (_archive.IsSolid) + curUnpacked = 0; + if (res != S_OK) { - 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 (res != S_FALSE) + return res; + dataError = true; if (_archive.IsSolid) - completed = currentTotalSize + offset; - else - completed = streamPos; - RINOK(extractCallback->SetCompleted(&completed)); - if (!testMode) - RINOK(WriteStream(realOutStream, buffer, processedSize)); + solidDataError = true; } } + } + + if (!dataError && item.IsUninstaller) + { + if (_archive.ExeStub.Size() != 0) + { + CByteBuffer destBuf = _archive.ExeStub; + dataError = !UninstallerPatch(tempBuf, tempBuf.Size(), destBuf); + + if (realOutStream) + RINOK(WriteStream(realOutStream, destBuf, destBuf.Size())); + } + + if (readFromTemp) + { + if (realOutStream) + RINOK(WriteStream(realOutStream, tempBuf2, tempBuf2.Size())); + } else { - if (readFromTemp) - { - if (!testMode) - RINOK(WriteStream(realOutStream, tempBuf, tempBuf.GetCapacity())); - } - else - while (fullSize > 0) + UInt32 curPacked2 = 0; + UInt32 curUnpacked2 = 0; + HRESULT res = _archive.Decoder.Decode( + writeToTemp ? &tempBuf2 : NULL, + false, 0, + realOutStream, + progress, + curPacked2, curUnpacked2); + curPacked += curPacked2; + if (!_archive.IsSolid) + curUnpacked += curUnpacked2; + if (res != S_OK) { - 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)); + if (res != S_FALSE) + return res; + dataError = true; + if (_archive.IsSolid) + solidDataError = true; } } } @@ -505,6 +678,4 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_END } -IMPL_ISetCompressCodecsInfo - }} diff --git a/CPP/7zip/Archive/Nsis/NsisHandler.h b/CPP/7zip/Archive/Nsis/NsisHandler.h old mode 100755 new mode 100644 index 6de493df..1eb8b731 --- a/CPP/7zip/Archive/Nsis/NsisHandler.h +++ b/CPP/7zip/Archive/Nsis/NsisHandler.h @@ -3,39 +3,32 @@ #ifndef __NSIS_HANDLER_H #define __NSIS_HANDLER_H -#include "Common/MyCom.h" +#include "../../../Common/MyCom.h" + +#include "../../Common/CreateCoder.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; + AString _methodString; - DECL_EXTERNAL_CODECS_VARS - - bool GetUncompressedSize(int index, UInt32 &size); - bool GetCompressedSize(int index, UInt32 &size); + bool GetUncompressedSize(unsigned index, UInt32 &size) const; + bool GetCompressedSize(unsigned index, UInt32 &size) const; - AString GetMethod(bool useItemFilter, UInt32 dictionary) const; + // AString GetMethod(NMethodType::EEnum method, bool useItemFilter, UInt32 dictionary) const; public: - MY_QUERYINTERFACE_BEGIN2(IInArchive) - QUERY_ENTRY_ISetCompressCodecsInfo - MY_QUERYINTERFACE_END - MY_ADDREF_RELEASE + MY_UNKNOWN_IMP1(IInArchive) INTERFACE_IInArchive(;) - - DECL_ISetCompressCodecsInfo }; }} diff --git a/CPP/7zip/Archive/Nsis/NsisIn.cpp b/CPP/7zip/Archive/Nsis/NsisIn.cpp old mode 100755 new mode 100644 index 40756008..71791c03 --- a/CPP/7zip/Archive/Nsis/NsisIn.cpp +++ b/CPP/7zip/Archive/Nsis/NsisIn.cpp @@ -2,1271 +2,5540 @@ #include "StdAfx.h" -#include "../../../../C/CpuArch.h" - -#include "Common/IntToString.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringToInt.h" +#include "../../Common/LimitedStreams.h" #include "../../Common/StreamUtils.h" #include "NsisIn.h" +#define Get16(p) GetUi16(p) #define Get32(p) GetUi32(p) +// #define NUM_SPEED_TESTS 1000 + namespace NArchive { namespace NNsis { -Byte kSignature[kSignatureSize] = NSIS_SIGNATURE; +static const size_t kInputBufSize = 1 << 20; + +static const Byte kSignature[kSignatureSize] = NSIS_SIGNATURE; +static const UInt32 kMask_IsCompressed = (UInt32)1 << 31; + +static const unsigned kNumCommandParams = 6; +static const unsigned kCmdSize = 4 + kNumCommandParams * 4; #ifdef NSIS_SCRIPT -static const char *kCrLf = "\x0D\x0A"; +#define CR_LF "\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 +static const char *kErrorStr = "$_ERROR_STR_"; -Byte CInArchive::ReadByte() -{ - if (_posInData >= _size) - throw 1; - return _data[_posInData++]; -} +#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } -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(); -} +/* There are several versions of NSIS: + 1) Original NSIS: + NSIS-2 ANSI + NSIS-3 ANSI + NSIS-3 Unicode + 2) NSIS from Jim Park that extends old NSIS-2 to Unicode support: + NSIS-Park-(1,2,3) ANSI + NSIS-Park-(1,2,3) Unicode -#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } + The command IDs layout is slightly different for different versions. + Also there are additional "log" versions of NSIS that support EW_LOG. + We use the layout of "NSIS-3 Unicode" without "log" as main layout. + And we transfer the command IDs to main layout, if another layout is detected. */ -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) +enum { - char sz[32]; - ConvertUInt64ToString(v, sz); - return sz; -} + EW_INVALID_OPCODE, + EW_RET, // Return + EW_NOP, // Nop, Goto + EW_ABORT, // Abort + EW_QUIT, // Quit + EW_CALL, // Call, InitPluginsDir + EW_UPDATETEXT, // DetailPrint + EW_SLEEP, // Sleep + EW_BRINGTOFRONT, // BringToFront + EW_CHDETAILSVIEW, // SetDetailsView + EW_SETFILEATTRIBUTES, // SetFileAttributes + EW_CREATEDIR, // CreateDirectory, SetOutPath + EW_IFFILEEXISTS, // IfFileExists + EW_SETFLAG, // SetRebootFlag, ... + EW_IFFLAG, // IfAbort, IfSilent, IfErrors, IfRebootFlag + EW_GETFLAG, // GetInstDirError, GetErrorLevel + EW_RENAME, // Rename + EW_GETFULLPATHNAME, // GetFullPathName + EW_SEARCHPATH, // SearchPath + EW_GETTEMPFILENAME, // GetTempFileName + EW_EXTRACTFILE, // File + EW_DELETEFILE, // Delete + EW_MESSAGEBOX, // MessageBox + EW_RMDIR, // RMDir + EW_STRLEN, // StrLen + EW_ASSIGNVAR, // StrCpy + EW_STRCMP, // StrCmp + EW_READENVSTR, // ReadEnvStr, ExpandEnvStrings + EW_INTCMP, // IntCmp, IntCmpU + EW_INTOP, // IntOp + EW_INTFMT, // IntFmt + EW_PUSHPOP, // Push/Pop/Exchange + EW_FINDWINDOW, // FindWindow + EW_SENDMESSAGE, // SendMessage + EW_ISWINDOW, // IsWindow + EW_GETDLGITEM, // GetDlgItem + EW_SETCTLCOLORS, // SerCtlColors + EW_SETBRANDINGIMAGE, // SetBrandingImage + EW_CREATEFONT, // CreateFont + EW_SHOWWINDOW, // ShowWindow, EnableWindow, HideWindow + EW_SHELLEXEC, // ExecShell + EW_EXECUTE, // Exec, ExecWait + EW_GETFILETIME, // GetFileTime + EW_GETDLLVERSION, // GetDLLVersion -static AString IntToString(Int32 v) -{ - char sz[32]; - ConvertInt64ToString(v, sz); - return sz; -} + // EW_GETFONTVERSION, // Park : 2.46.2 + // EW_GETFONTNAME, // Park : 2.46.3 + + EW_REGISTERDLL, // RegDLL, UnRegDLL, CallInstDLL + EW_CREATESHORTCUT, // CreateShortCut + EW_COPYFILES, // CopyFiles + EW_REBOOT, // Reboot + EW_WRITEINI, // WriteINIStr, DeleteINISec, DeleteINIStr, FlushINI + EW_READINISTR, // ReadINIStr + EW_DELREG, // DeleteRegValue, DeleteRegKey + EW_WRITEREG, // WriteRegStr, WriteRegExpandStr, WriteRegBin, WriteRegDWORD + EW_READREGSTR, // ReadRegStr, ReadRegDWORD + EW_REGENUM, // EnumRegKey, EnumRegValue + EW_FCLOSE, // FileClose + EW_FOPEN, // FileOpen + EW_FPUTS, // FileWrite, FileWriteByte + EW_FGETS, // FileRead, FileReadByte -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; -} + // Park + // EW_FPUTWS, // FileWriteUTF16LE, FileWriteWord + // EW_FGETWS, // FileReadUTF16LE, FileReadWord + + EW_FSEEK, // FileSeek + EW_FINDCLOSE, // FindClose + EW_FINDNEXT, // FindNext + EW_FINDFIRST, // FindFirst + EW_WRITEUNINSTALLER, // WriteUninstaller + + // Park : since 2.46.3 the log is enabled in main Park version + // EW_LOG, // LogSet, LogText -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; -} + EW_SECTIONSET, // Get*, Set* + EW_INSTTYPESET, // InstTypeSetText, InstTypeGetText, SetCurInstType, GetCurInstType -/* -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; -} -*/ + // instructions not actually implemented in exehead, but used in compiler. + EW_GETLABELADDR, // both of these get converted to EW_ASSIGNVAR + EW_GETFUNCTIONADDR, + + EW_LOCKWINDOW, // LockWindow + + // 2 unicode commands available only in Unicode archive + EW_FPUTWS, // FileWriteUTF16LE, FileWriteWord + EW_FGETWS, // FileReadUTF16LE, FileReadWord -#define SYSREGKEY "Software\\Microsoft\\Windows\\CurrentVersion" + // The following IDs are not IDs in real order. + // We just need some IDs to translate eny extended layout to main layout. -/* -# 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 -*/ + EW_LOG, // LogSet, LogText + + // Park + EW_FINDPROC, // FindProc + + EW_GETFONTVERSION, // GetFontVersion + EW_GETFONTNAME, // GetFontName -struct CCommandPair + kNumCmds +}; + +static const unsigned kNumAdditionalParkCmds = 3; + +struct CCommandInfo { - int NumParams; - const char *Name; + Byte NumParams; }; -enum +static const CCommandInfo k_Commands[kNumCmds] = { - // 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] + { 0 }, // "Invalid" }, + { 0 }, // Return + { 1 }, // Nop, Goto + { 1 }, // "Abort" }, + { 0 }, // "Quit" }, + { 2 }, // Call + { 6 }, // "DetailPrint" }, // 1 param in new versions, 6 in old NSIS versions + { 1 }, // "Sleep" }, + { 0 }, // "BringToFront" }, + { 2 }, // "SetDetailsView" }, + { 2 }, // "SetFileAttributes" }, + { 2 }, // CreateDirectory, SetOutPath + { 3 }, // "IfFileExists" }, + { 3 }, // SetRebootFlag, ... + { 4 }, // "If" }, // IfAbort, IfSilent, IfErrors, IfRebootFlag + { 2 }, // "Get" }, // GetInstDirError, GetErrorLevel + { 4 }, // "Rename" }, + { 3 }, // "GetFullPathName" }, + { 2 }, // "SearchPath" }, + { 2 }, // "GetTempFileName" }, + { 6 }, // "File" + { 2 }, // "Delete" }, + { 6 }, // "MessageBox" }, + { 2 }, // "RMDir" }, + { 2 }, // "StrLen" }, + { 4 }, // StrCpy, GetCurrentAddress + { 5 }, // "StrCmp" }, + { 3 }, // ReadEnvStr, ExpandEnvStrings + { 6 }, // "IntCmp" }, + { 4 }, // "IntOp" }, + { 3 }, // "IntFmt" }, + { 6 }, // Push, Pop, Exch // it must be 3 params. But some multi-command write garbage. + { 5 }, // "FindWindow" }, + { 6 }, // "SendMessage" }, + { 3 }, // "IsWindow" }, + { 3 }, // "GetDlgItem" }, + { 2 }, // "SetCtlColors" }, + { 3 }, // "SetBrandingImage" }, + { 5 }, // "CreateFont" }, + { 4 }, // ShowWindow, EnableWindow, HideWindow + { 6 }, // "ExecShell" }, + { 3 }, // "Exec" }, // Exec, ExecWait + { 3 }, // "GetFileTime" }, + { 3 }, // "GetDLLVersion" }, + { 6 }, // RegDLL, UnRegDLL, CallInstDLL // it must be 5 params. But some multi-command write garbage. + { 6 }, // "CreateShortCut" }, + { 4 }, // "CopyFiles" }, + { 1 }, // "Reboot" }, + { 5 }, // WriteINIStr, DeleteINISec, DeleteINIStr, FlushINI + { 4 }, // "ReadINIStr" }, + { 5 }, // "DeleteReg" }, // DeleteRegKey, DeleteRegValue + { 6 }, // "WriteReg" }, // WriteRegStr, WriteRegExpandStr, WriteRegBin, WriteRegDWORD + { 5 }, // "ReadReg" }, // ReadRegStr, ReadRegDWORD + { 5 }, // "EnumReg" }, // EnumRegKey, EnumRegValue + { 1 }, // "FileClose" }, + { 4 }, // "FileOpen" }, + { 3 }, // "FileWrite" }, // FileWrite, FileWriteByte + { 4 }, // "FileRead" }, // FileRead, FileReadByte + { 4 }, // "FileSeek" }, + { 1 }, // "FindClose" }, + { 2 }, // "FindNext" }, + { 3 }, // "FindFirst" }, + { 4 }, // "WriteUninstaller" }, + { 5 }, // "Section" }, // *** + { 4 }, // InstTypeSetText, InstTypeGetText, SetCurInstType, GetCurInstType + { 6 }, // "GetLabelAddr" }, + { 2 }, // "GetFunctionAddress" }, + { 1 }, // "LockWindow" }, + { 3 }, // "FileWrite" }, // FileWriteUTF16LE, FileWriteWord + { 4 }, // "FileRead" }, // FileReadUTF16LE, FileReadWord - // 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 + { 2 }, // "Log" }, // LogSet, LogText + // Park + { 2 }, // "FindProc" }, + { 2 }, // "GetFontVersion" }, + { 2 }, // "GetFontName" } }; #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" } + +static const char *k_CommandNames[kNumCmds] = +{ + "Invalid" + , NULL // Return + , NULL // Nop, Goto + , "Abort" + , "Quit" + , NULL // Call + , "DetailPrint" // 1 param in new versions, 6 in old NSIS versions + , "Sleep" + , "BringToFront" + , "SetDetailsView" + , "SetFileAttributes" + , NULL // CreateDirectory, SetOutPath + , "IfFileExists" + , NULL // SetRebootFlag, ... + , "If" // IfAbort, IfSilent, IfErrors, IfRebootFlag + , "Get" // GetInstDirError, GetErrorLevel + , "Rename" + , "GetFullPathName" + , "SearchPath" + , "GetTempFileName" + , NULL // File + , "Delete" + , "MessageBox" + , "RMDir" + , "StrLen" + , NULL // StrCpy, GetCurrentAddress + , "StrCmp" + , NULL // ReadEnvStr, ExpandEnvStrings + , "IntCmp" + , "IntOp" + , "IntFmt" + , NULL // Push, Pop, Exch // it must be 3 params. But some multi-command write garbage. + , "FindWindow" + , "SendMessage" + , "IsWindow" + , "GetDlgItem" + , "SetCtlColors" + , "SetBrandingImage" + , "CreateFont" + , NULL // ShowWindow, EnableWindow, HideWindow + , "ExecShell" + , "Exec" // Exec, ExecWait + , "GetFileTime" + , "GetDLLVersion" + , NULL // RegDLL, UnRegDLL, CallInstDLL // it must be 5 params. But some multi-command write garbage. + , "CreateShortCut" + , "CopyFiles" + , "Reboot" + , NULL // WriteINIStr, DeleteINISec, DeleteINIStr, FlushINI + , "ReadINIStr" + , "DeleteReg" // DeleteRegKey, DeleteRegValue + , "WriteReg" // WriteRegStr, WriteRegExpandStr, WriteRegBin, WriteRegDWORD + , "ReadReg" // ReadRegStr, ReadRegDWORD + , "EnumReg" // EnumRegKey, EnumRegValue + , "FileClose" + , "FileOpen" + , "FileWrite" // FileWrite, FileWriteByte + , "FileRead" // FileRead, FileReadByte + , "FileSeek" + , "FindClose" + , "FindNext" + , "FindFirst" + , "WriteUninstaller" + , "Section" // *** + , NULL // InstTypeSetText, InstTypeGetText, SetCurInstType, GetCurInstType + , "GetLabelAddr" + , "GetFunctionAddress" + , "LockWindow" + , "FileWrite" // FileWriteUTF16LE, FileWriteWord + , "FileRead" // FileReadUTF16LE, FileReadWord + + , "Log" // LogSet, LogText + + // Park + , "FindProc" + , "GetFontVersion" + , "GetFontName" }; #endif +/* NSIS can use one name for two CSIDL_*** and CSIDL_COMMON_*** items (CurrentUser / AllUsers) + Some NSIS shell names are not identical to WIN32 CSIDL_* names. + NSIS doesn't use some CSIDL_* values. But we add name for all CSIDL_ (marked with '+'). */ + static const char *kShellStrings[] = { - "", - "", - - "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" + "DESKTOP" // + + , "INTERNET" // + + , "SMPROGRAMS" // CSIDL_PROGRAMS + , "CONTROLS" // + + , "PRINTERS" // + + , "DOCUMENTS" // CSIDL_PERSONAL + , "FAVORITES" // CSIDL_FAVORITES + , "SMSTARTUP" // CSIDL_STARTUP + , "RECENT" // CSIDL_RECENT + , "SENDTO" // CSIDL_SENDTO + , "BITBUCKET" // + + , "STARTMENU" + , NULL // CSIDL_MYDOCUMENTS = CSIDL_PERSONAL + , "MUSIC" // CSIDL_MYMUSIC + , "VIDEOS" // CSIDL_MYVIDEO + , NULL + , "DESKTOP" // CSIDL_DESKTOPDIRECTORY + , "DRIVES" // + + , "NETWORK" // + + , "NETHOOD" + , "FONTS" + , "TEMPLATES" + , "STARTMENU" // CSIDL_COMMON_STARTMENU + , "SMPROGRAMS" // CSIDL_COMMON_PROGRAMS + , "SMSTARTUP" // CSIDL_COMMON_STARTUP + , "DESKTOP" // CSIDL_COMMON_DESKTOPDIRECTORY + , "APPDATA" // CSIDL_APPDATA !!! "QUICKLAUNCH" + , "PRINTHOOD" + , "LOCALAPPDATA" + , "ALTSTARTUP" + , "ALTSTARTUP" // CSIDL_COMMON_ALTSTARTUP + , "FAVORITES" // CSIDL_COMMON_FAVORITES + , "INTERNET_CACHE" + , "COOKIES" + , "HISTORY" + , "APPDATA" // CSIDL_COMMON_APPDATA + , "WINDIR" + , "SYSDIR" + , "PROGRAM_FILES" // + + , "PICTURES" // CSIDL_MYPICTURES + , "PROFILE" + , "SYSTEMX86" // + + , "PROGRAM_FILESX86" // + + , "PROGRAM_FILES_COMMON" // + + , "PROGRAM_FILES_COMMONX8" // + CSIDL_PROGRAM_FILES_COMMONX86 + , "TEMPLATES" // CSIDL_COMMON_TEMPLATES + , "DOCUMENTS" // CSIDL_COMMON_DOCUMENTS + , "ADMINTOOLS" // CSIDL_COMMON_ADMINTOOLS + , "ADMINTOOLS" // CSIDL_ADMINTOOLS + , "CONNECTIONS" // + + , NULL + , NULL + , NULL + , "MUSIC" // CSIDL_COMMON_MUSIC + , "PICTURES" // CSIDL_COMMON_PICTURES + , "VIDEOS" // CSIDL_COMMON_VIDEO + , "RESOURCES" + , "RESOURCES_LOCALIZED" + , "COMMON_OEM_LINKS" // + + , "CDBURN_AREA" + , NULL // unused + , "COMPUTERSNEARME" // + }; -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[] = +static void UIntToString(AString &s, UInt32 v) { - "CMDLINE", - "INSTDIR", - "OUTDIR", - "EXEDIR", - "LANGUAGE", - "TEMP", - "PLUGINSDIR", - "EXEPATH", // test it - "EXEFILE", // test it - "HWNDPARENT", - "_CLICK", - "_OUTDIR" -}; + char sz[16]; + ConvertUInt32ToString(v, sz); + s += sz; +} -static const int kNumVarStrings = sizeof(kVarStrings) / sizeof(kVarStrings[0]); +#ifdef NSIS_SCRIPT +void CInArchive::Add_UInt(UInt32 v) +{ + char sz[16]; + ConvertUInt32ToString(v, sz); + Script += sz; +} -static AString GetVar(UInt32 index) +static void Add_SignedInt(CDynLimBuf &s, Int32 v) { - 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; + char sz[32]; + ConvertInt64ToString(v, sz); + s += sz; } -#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 void Add_Hex(CDynLimBuf &s, UInt32 v) +{ + char sz[16]; + sz[0] = '0'; + sz[1] = 'x'; + ConvertUInt32ToHex(v, sz + 2); + s += sz; +} -static AString GetShellString(int index) +static UInt32 GetUi16Str_Len(const Byte *p) { - 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; + const Byte *pp = p; + for (; *pp != 0 || *(pp + 1) != 0; pp += 2); + return (UInt32)((pp - p) >> 1); } -// Based on Dave Laundon's simplified process_string -AString GetNsisString(const AString &s) +void CInArchive::AddLicense(UInt32 param, Int32 langID) { - AString res; - for (int i = 0; i < s.Length();) + Space(); + if (param >= NumStringChars || + param + 1 >= NumStringChars) { - 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); + Script += kErrorStr; + return; + } + strUsed[param] = 1; - 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"; + UInt32 start = _stringsPos + (IsUnicode ? param * 2 : param); + UInt32 offset = start + (IsUnicode ? 2 : 1); + { + FOR_VECTOR (i, LicenseFiles) + { + const CLicenseFile &lic = LicenseFiles[i]; + if (offset == lic.Offset) + { + Script += lic.Name; + return; + } } - else if (nVarIdx == NS_SKIP_CODE) + } + AString fileName = "[LICENSE]"; + if (langID >= 0) + { + fileName += "\\license-"; + // LangId_To_String(fileName, langID); + UIntToString(fileName, langID); + } + else if (++_numRootLicenses > 1) + { + fileName += '-'; + UIntToString(fileName, _numRootLicenses); + } + const Byte *sz = (_data + start); + unsigned marker = IsUnicode ? Get16(sz) : *sz; + bool isRTF = (marker == 2); + fileName += isRTF ? ".rtf" : ".txt"; // if (*sz == 1) it's text; + Script += fileName; + + CLicenseFile &lic = LicenseFiles.AddNew(); + lic.Name = fileName; + lic.Offset = offset; + if (!IsUnicode) + lic.Size = (UInt32)strlen((const char *)sz + 1); + else + { + sz += 2; + UInt32 len = GetUi16Str_Len(sz); + lic.Size = len * 2; + if (isRTF) { - if (i < s.Length()) - res += s[i++]; + lic.Text.Alloc((size_t)len); + for (UInt32 i = 0; i < len; i++, sz += 2) + { + unsigned c = Get16(sz); + if (c >= 256) + c = '?'; + lic.Text[i] = (Byte)(c); + } + lic.Size = len; + lic.Offset = 0; } - else // Normal char - res += (char)nVarIdx; } - return res; } -UString GetNsisString(const UString &s) +#endif + + +#define kVar_CMDLINE 20 +#define kVar_INSTDIR 21 +#define kVar_OUTDIR 22 +#define kVar_EXEDIR 23 +#define kVar_LANGUAGE 24 +#define kVar_TEMP 25 +#define kVar_PLUGINSDIR 26 +#define kVar_EXEPATH 27 // NSIS 2.26+ +#define kVar_EXEFILE 28 // NSIS 2.26+ + +#define kVar_HWNDPARENT_225 27 +#define kVar_HWNDPARENT 29 + +// #define kVar__CLICK 30 +#define kVar_Spec_OUTDIR_225 29 // NSIS 2.04 - 2.25 +#define kVar_Spec_OUTDIR 31 // NSIS 2.26+ + + +static const char *kVarStrings[] = +{ + "CMDLINE" + , "INSTDIR" + , "OUTDIR" + , "EXEDIR" + , "LANGUAGE" + , "TEMP" + , "PLUGINSDIR" + , "EXEPATH" // NSIS 2.26+ + , "EXEFILE" // NSIS 2.26+ + , "HWNDPARENT" + , "_CLICK" // is set from page->clicknext + , "_OUTDIR" // NSIS 2.04+ +}; + +static const unsigned kNumInternalVars = 20 + ARRAY_SIZE(kVarStrings); + +#define GET_NUM_INTERNAL_VARS (IsNsis200 ? kNumInternalVars - 3 : IsNsis225 ? kNumInternalVars - 2 : kNumInternalVars); + +void CInArchive::GetVar2(AString &res, UInt32 index) { - UString res; - for (int i = 0; i < s.Length();) + if (index < 20) { - wchar_t nVarIdx = s[i++]; - if (nVarIdx > NS_UN_CODES_START && nVarIdx <= NS_UN_CODES_END) + if (index >= 10) { - 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"; + res += 'R'; + index -= 10; } - else if (nVarIdx == NS_UN_SKIP_CODE) + UIntToString(res, index); + } + else + { + unsigned numInternalVars = GET_NUM_INTERNAL_VARS; + if (index < numInternalVars) { - if (i == s.Length()) - break; - res += s[i++]; + if (IsNsis225 && index >= kVar_EXEPATH) + index += 2; + res += kVarStrings[index - 20]; + } + else + { + res += '_'; + UIntToString(res, index - numInternalVars); + res += '_'; } - else // Normal char - res += (char)nVarIdx; } - return res; } -AString CInArchive::ReadString2A(UInt32 pos) const +void CInArchive::GetVar(AString &res, UInt32 index) { - return GetNsisString(ReadStringA(pos)); + res += '$'; + GetVar2(res, index); } -UString CInArchive::ReadString2U(UInt32 pos) const +#ifdef NSIS_SCRIPT + +void CInArchive::Add_Var(UInt32 index) { - return GetNsisString(ReadStringU(pos)); + _tempString_for_GetVar.Empty(); + GetVar(_tempString_for_GetVar, index); + Script += _tempString_for_GetVar; } -AString CInArchive::ReadString2(UInt32 pos) const +void CInArchive::AddParam_Var(UInt32 index) { - if (IsUnicode) - return UnicodeStringToMultiByte(ReadString2U(pos)); - else - return ReadString2A(pos); + Space(); + Add_Var(index); } -AString CInArchive::ReadString2Qw(UInt32 pos) const +void CInArchive::AddParam_UInt(UInt32 value) { - return "\"" + ReadString2(pos) + "\""; + Space(); + Add_UInt(value); } -#define DEL_DIR 1 -#define DEL_RECURSE 2 -#define DEL_REBOOT 4 -// #define DEL_SIMPLE 8 +#endif + + +#define NS_CODE_SKIP 252 +#define NS_CODE_VAR 253 +#define NS_CODE_SHELL 254 +#define NS_CODE_LANG 255 -static const int kNumEntryParams = 6; +#define NS_3_CODE_LANG 1 +#define NS_3_CODE_SHELL 2 +#define NS_3_CODE_VAR 3 +#define NS_3_CODE_SKIP 4 -struct CEntry +#define PARK_CODE_SKIP 0xE000 +#define PARK_CODE_VAR 0xE001 +#define PARK_CODE_SHELL 0xE002 +#define PARK_CODE_LANG 0xE003 + +#define IS_NS_SPEC_CHAR(c) ((c) >= NS_CODE_SKIP) +#define IS_PARK_SPEC_CHAR(c) ((c) >= PARK_CODE_SKIP && (c) <= PARK_CODE_LANG) + +#define DECODE_NUMBER_FROM_2_CHARS(c0, c1) (((c0) & 0x7F) | (((unsigned)((c1) & 0x7F)) << 7)) +#define CONVERT_NUMBER_NS_3_UNICODE(n) n = ((n & 0x7F) | (((n >> 8) & 0x7F) << 7)) +#define CONVERT_NUMBER_PARK(n) n &= 0x7FFF + + +static bool AreStringsEqual_16and8(const Byte *p16, const char *p8) { - UInt32 Which; - UInt32 Params[kNumEntryParams]; - AString GetParamsString(int numParams); - CEntry() + for (;;) { - Which = 0; - for (UInt32 j = 0; j < kNumEntryParams; j++) - Params[j] = 0; + unsigned c16 = Get16(p16); p16 += 2; + unsigned c = (Byte)(*p8++); + if (c16 != c) + return false; + if (c == 0) + return true; } -}; +} -AString CEntry::GetParamsString(int numParams) +void CInArchive::GetShellString(AString &s, unsigned index1, unsigned index2) { - AString s; - for (int i = 0; i < numParams; i++) + // zeros are not allowed here. + // if (index1 == 0 || index2 == 0) throw 333; + + if ((index1 & 0x80) != 0) { - s += " "; - UInt32 v = Params[i]; - if (v > 0xFFF00000) - s += IntToString((Int32)Params[i]); + unsigned offset = (index1 & 0x3F); + + /* NSIS reads registry string: + keyName = HKLM Software\\Microsoft\\Windows\\CurrentVersion + mask = KEY_WOW64_64KEY, If 64-bit flag in index1 is set + valueName = string(offset) + If registry reading is failed, NSIS uses second parameter (index2) + to read string. The recursion is possible in that case in NSIS. + We don't parse index2 string. We only set strUsed status for that + string (but without recursion). */ + + if (offset >= NumStringChars) + { + s += kErrorStr; + return; + } + + #ifdef NSIS_SCRIPT + strUsed[offset] = 1; + if (index2 < NumStringChars) + strUsed[index2] = 1; + #endif + + const Byte *p = (const Byte *)(_data + _stringsPos); + int id = -1; + if (IsUnicode) + { + p += offset * 2; + if (AreStringsEqual_16and8(p, "ProgramFilesDir")) + id = 0; + else if (AreStringsEqual_16and8(p, "CommonFilesDir")) + id = 1; + } else - s += UIntToString(Params[i]); + { + p += offset; + if (strcmp((const char *)p, "ProgramFilesDir") == 0) + id = 0; + else if (strcmp((const char *)p, "CommonFilesDir") == 0) + id = 1; + } + + s += ((id >= 0) ? (id == 0 ? "$PROGRAMFILES" : "$COMMONFILES") : + "$_ERROR_UNSUPPORTED_VALUE_REGISTRY_"); + // s += ((index1 & 0x40) != 0) ? "64" : "32"; + if ((index1 & 0x40) != 0) + s += "64"; + + if (id < 0) + { + s += '('; + if (IsUnicode) + { + for (unsigned i = 0; i < 256; i++) + { + wchar_t c = Get16(p + i * 2); + if (c == 0) + break; + if (c < 0x80) + s += (char)c; + } + } + else + s += (const char *)p; + s += ')'; + } + return; } - return s; + + s += '$'; + if (index1 < ARRAY_SIZE(kShellStrings)) + { + const char *sz = kShellStrings[index1]; + if (sz) + { + s += sz; + return; + } + } + if (index2 < ARRAY_SIZE(kShellStrings)) + { + const char *sz = kShellStrings[index2]; + if (sz) + { + s += sz; + return; + } + } + s += "_ERROR_UNSUPPORTED_SHELL_"; + s += '['; + UIntToString(s, index1); + s += ','; + UIntToString(s, index2); + s += ']'; } #ifdef NSIS_SCRIPT -static AString GetRegRootID(UInt32 val) +void CInArchive::Add_LangStr_Simple(UInt32 id) { - 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; + Script += "LSTR_"; + Add_UInt(id); } #endif -HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) +void CInArchive::Add_LangStr(AString &res, UInt32 id) +{ + #ifdef NSIS_SCRIPT + langStrIDs.Add(id); + #endif + res += "$(LSTR_"; + UIntToString(res, id); + res += ')'; +} + +void CInArchive::GetNsisString_Raw(const Byte *s) { - _posInData = bh.Offset + GetOffset(); - AString prefixA; - UString prefixU; - for (UInt32 i = 0; i < bh.Num; i++) + Raw_AString.Empty(); + + if (NsisType != k_NsisType_Nsis3) { - 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])) + for (;;) { - const CCommandPair &pair = kCommandPairs[e.Which]; - Script += pair.Name; + Byte c = *s++; + if (c == 0) + return; + if (IS_NS_SPEC_CHAR(c)) + { + Byte c0 = *s++; + if (c0 == 0) + return; + if (c != NS_CODE_SKIP) + { + Byte c1 = *s++; + if (c1 == 0) + return; + + if (c == NS_CODE_SHELL) + GetShellString(Raw_AString, c0, c1); + else + { + unsigned n = DECODE_NUMBER_FROM_2_CHARS(c0, c1); + if (c == NS_CODE_VAR) + GetVar(Raw_AString, n); + else // if (c == NS_CODE_LANG) + Add_LangStr(Raw_AString, n); + } + continue; + } + c = c0; + } + Raw_AString += (char)c; } - #endif + } - switch (e.Which) + // NSIS-3 ANSI + for (;;) + { + Byte c = *s++; + if (c <= NS_3_CODE_SKIP) { - case EW_CREATEDIR: + if (c == 0) + return; + Byte c0 = *s++; + if (c0 == 0) + return; + if (c != NS_3_CODE_SKIP) { - if (IsUnicode) - { - prefixU.Empty(); - prefixU = ReadString2U(e.Params[0]); - } + Byte c1 = *s++; + if (c1 == 0) + return; + + if (c == NS_3_CODE_SHELL) + GetShellString(Raw_AString, c0, c1); else { - prefixA.Empty(); - prefixA = ReadString2A(e.Params[0]); + unsigned n = DECODE_NUMBER_FROM_2_CHARS(c0, c1); + if (c == NS_3_CODE_VAR) + GetVar(Raw_AString, n); + else // if (c == NS_3_CODE_LANG) + Add_LangStr(Raw_AString, n); } - #ifdef NSIS_SCRIPT - Script += " "; - if (IsUnicode) - Script += UnicodeStringToMultiByte(prefixU); - else - Script += prefixA; - #endif - break; + continue; } + c = c0; + } + Raw_AString += (char)c; + } +} - case EW_EXTRACTFILE: +#ifdef NSIS_SCRIPT + +void CInArchive::GetNsisString(AString &res, const Byte *s) +{ + for (;;) + { + Byte c = *s++; + if (c == 0) + return; + if (NsisType != k_NsisType_Nsis3) + { + if (IS_NS_SPEC_CHAR(c)) { - CItem item; - item.IsUnicode = IsUnicode; - if (IsUnicode) + Byte c0 = *s++; + if (c0 == 0) + return; + if (c != NS_CODE_SKIP) { - item.PrefixU = prefixU; - item.NameU = ReadString2U(e.Params[1]); - } - else - { - item.PrefixA = prefixA; - item.NameA = ReadString2A(e.Params[1]); + Byte c1 = *s++; + if (c1 == 0) + return; + if (c == NS_CODE_SHELL) + GetShellString(res, c0, c1); + else + { + unsigned n = DECODE_NUMBER_FROM_2_CHARS(c0, c1); + if (c == NS_CODE_VAR) + GetVar(res, n); + else // if (c == NS_CODE_LANG) + Add_LangStr(res, n); + } + continue; } - /* 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) + c = c0; + } + } + else + { + // NSIS-3 ANSI + if (c <= NS_3_CODE_SKIP) + { + Byte c0 = *s++; + if (c0 == 0) + return; + if (c0 == 0) + break; + if (c != NS_3_CODE_SKIP) { - /* - if (item.Pos == Items.Back().Pos) + Byte c1 = *s++; + if (c1 == 0) + return; + if (c == NS_3_CODE_SHELL) + GetShellString(res, c0, c1); + else + { + unsigned n = DECODE_NUMBER_FROM_2_CHARS(c0, c1); + if (c == NS_3_CODE_VAR) + GetVar(res, n); + else // if (c == NS_3_CODE_LANG) + Add_LangStr(res, n); + } + continue; + } + c = c0; + } + } + + { + const char *e; + if (c == 9) e = "$\\t"; + else if (c == 10) e = "$\\n"; + else if (c == 13) e = "$\\r"; + else if (c == '"') e = "$\\\""; + else if (c == '$') e = "$$"; + else + { + res += (char)c; + continue; + } + res += e; + continue; + } + } +} + +#endif + +void CInArchive::GetNsisString_Unicode_Raw(const Byte *p) +{ + Raw_UString.Empty(); + + if (IsPark()) + { + for (;;) + { + unsigned c = Get16(p); + p += 2; + if (c == 0) + break; + if (c < 0x80) + { + Raw_UString += (wchar_t)c; + continue; + } + + if (IS_PARK_SPEC_CHAR(c)) + { + unsigned n = Get16(p); + p += 2; + if (n == 0) + break; + if (c != PARK_CODE_SKIP) + { + Raw_AString.Empty(); + if (c == PARK_CODE_SHELL) + GetShellString(Raw_AString, n & 0xFF, n >> 8); + else + { + CONVERT_NUMBER_PARK(n); + if (c == PARK_CODE_VAR) + GetVar(Raw_AString, n); + else // if (c == PARK_CODE_LANG) + Add_LangStr(Raw_AString, n); + } + for (const Byte *s = (const Byte *)(const char *)Raw_AString; *s != 0; s++) + Raw_UString += *s; + continue; + } + c = n; + } + + Raw_UString += (wchar_t)c; + } + + return; + } + + // NSIS-3 Unicode + for (;;) + { + unsigned c = Get16(p); + p += 2; + if (c > NS_3_CODE_SKIP) + { + Raw_UString += (wchar_t)c; + continue; + } + if (c == 0) + break; + + unsigned n = Get16(p); + p += 2; + if (n == 0) + break; + if (c == NS_3_CODE_SKIP) + { + Raw_UString += (wchar_t)n; + continue; + } + + Raw_AString.Empty(); + if (c == NS_3_CODE_SHELL) + GetShellString(Raw_AString, n & 0xFF, n >> 8); + else + { + CONVERT_NUMBER_NS_3_UNICODE(n); + if (c == NS_3_CODE_VAR) + GetVar(Raw_AString, n); + else // if (c == NS_3_CODE_LANG) + Add_LangStr(Raw_AString, n); + } + for (const Byte *s = (const Byte *)(const char *)Raw_AString; *s != 0; s++) + Raw_UString += (wchar_t)*s; + } +} + +#ifdef NSIS_SCRIPT + +static const Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + +void CInArchive::GetNsisString_Unicode(AString &res, const Byte *p) +{ + for (;;) + { + unsigned c = Get16(p); + p += 2; + if (c == 0) + break; + if (IsPark()) + { + if (IS_PARK_SPEC_CHAR(c)) + { + unsigned n = Get16(p); + p += 2; + if (n == 0) + break; + if (c != PARK_CODE_SKIP) + { + if (c == PARK_CODE_SHELL) + GetShellString(res, n & 0xFF, n >> 8); + else + { + CONVERT_NUMBER_PARK(n); + if (c == PARK_CODE_VAR) + GetVar(res, n); + else // if (c == PARK_CODE_LANG) + Add_LangStr(res, n); + } + continue; + } + c = n; + } + } + else + { + // NSIS-3 Unicode + if (c <= NS_3_CODE_SKIP) + { + unsigned n = Get16(p); + p += 2; + if (n == 0) + break; + if (c != NS_3_CODE_SKIP) + { + if (c == NS_3_CODE_SHELL) + GetShellString(res, n & 0xFF, n >> 8); + else + { + CONVERT_NUMBER_NS_3_UNICODE(n); + if (c == NS_3_CODE_VAR) + GetVar(res, n); + else // if (c == NS_3_CODE_LANG) + Add_LangStr(res, n); + } + continue; + } + c = n; + } + } + + if (c < 0x80) + { + const char *e; + if (c == 9) e = "$\\t"; + else if (c == 10) e = "$\\n"; + else if (c == 13) e = "$\\r"; + else if (c == '"') e = "$\\\""; + else if (c == '$') e = "$$"; + else + { + res += (char)c; + continue; + } + res += e; + continue; + } + + UInt32 value = c; + /* + 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; + } + */ + unsigned numAdds; + for (numAdds = 1; numAdds < 5; numAdds++) + if (value < (((UInt32)1) << (numAdds * 5 + 6))) + break; + res += (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); + do + { + numAdds--; + res += (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); + // destPos++; + } + while (numAdds != 0); + + // AddToUtf8(res, c); + } +} + +#endif + +void CInArchive::ReadString2_Raw(UInt32 pos) +{ + Raw_AString.Empty(); + Raw_UString.Empty(); + if ((Int32)pos < 0) + Add_LangStr(Raw_AString, -((Int32)pos + 1)); + else if (pos >= NumStringChars) + { + Raw_AString += kErrorStr; + // UIntToString(Raw_AString, pos); + } + else + { + if (IsUnicode) + GetNsisString_Unicode_Raw(_data + _stringsPos + pos * 2); + else + GetNsisString_Raw(_data + _stringsPos + pos); + return; + } + for (const char *s = (const char *)Raw_AString; *s != 0; s++) + Raw_UString += *s; +} + +bool CInArchive::IsGoodString(UInt32 param) const +{ + if (param >= NumStringChars) + return false; + if (param == 0) + return true; + const Byte *p = _data + _stringsPos; + if (IsUnicode) + return (Get16(p + param * 2 - 2)) == 0; + return p[param - 1] == 0; +} + +bool CInArchive::AreTwoParamStringsEqual(UInt32 param1, UInt32 param2) const +{ + if (param1 == param2) + return true; + + /* NSIS-3.0a1 probably contains bug, so it can use 2 different strings + with same content. So we check real string also. + Also it's possible to check identical postfix parts of strings. */ + + if (param1 >= NumStringChars || + param2 >= NumStringChars) + return false; + + const Byte *p = _data + _stringsPos; + + if (IsUnicode) + { + const Byte *p1 = p + param1 * 2; + const Byte *p2 = p + param2 * 2; + for (;;) + { + UInt16 c = Get16(p1); + if (c != Get16(p2)) + return false; + if (c == 0) + return true; + p1 += 2; + p2 += 2; + } + } + else + { + const Byte *p1 = p + param1; + const Byte *p2 = p + param2; + for (;;) + { + Byte c = *p1++; + if (c != *p2++) + return false; + if (c == 0) + return true; + } + } +} + +#ifdef NSIS_SCRIPT + +UInt32 CInArchive::GetNumUsedVars() const +{ + UInt32 numUsedVars = 0; + const Byte *data = (const Byte *)_data + _stringsPos; + unsigned npi = 0; + for (UInt32 i = 0; i < NumStringChars;) + { + bool process = true; + if (npi < noParseStringIndexes.Size() && noParseStringIndexes[npi] == i) + { + process = false; + npi++; + } + + if (IsUnicode) + { + if (IsPark()) + { + for (;;) + { + unsigned c = Get16(data + i * 2); + i++; + if (c == 0) + break; + if (IS_PARK_SPEC_CHAR(c)) + { + UInt32 n = Get16(data + i * 2); + i++; + if (n == 0) + break; + if (process && c == PARK_CODE_VAR) + { + CONVERT_NUMBER_PARK(n); + n++; + if (numUsedVars < n) + numUsedVars = n; + } + } + } + } + else // NSIS-3 Unicode + { + for (;;) + { + unsigned c = Get16(data + i * 2); + i++; + if (c == 0) + break; + if (c > NS_3_CODE_SKIP) + continue; + UInt32 n = Get16(data + i * 2); + i++; + if (n == 0) + break; + if (process && c == NS_3_CODE_VAR) + { + CONVERT_NUMBER_NS_3_UNICODE(n); + n++; + if (numUsedVars < n) + numUsedVars = n; + } + } + } + } + else // not Unicode (ANSI) + { + if (NsisType != k_NsisType_Nsis3) + { + for (;;) + { + Byte c = data[i++]; + if (c == 0) + break; + if (IS_NS_SPEC_CHAR(c)) + { + Byte c0 = data[i++]; + if (c0 == 0) + break; + if (c == NS_CODE_SKIP) + continue; + Byte c1 = data[i++]; + if (c1 == 0) + break; + if (process && c == NS_CODE_VAR) + { + UInt32 n = DECODE_NUMBER_FROM_2_CHARS(c0, c1); + n++; + if (numUsedVars < n) + numUsedVars = n; + } + } + } + } + else + { + // NSIS-3 ANSI + for (;;) + { + Byte c = data[i++]; + if (c == 0) + break; + if (c > NS_3_CODE_SKIP) continue; - */ + + Byte c0 = data[i++]; + if (c0 == 0) + break; + if (c == NS_3_CODE_SKIP) + continue; + Byte c1 = data[i++]; + if (c1 == 0) + break; + if (process && c == NS_3_CODE_VAR) + { + UInt32 n = DECODE_NUMBER_FROM_2_CHARS(c0, c1); + n++; + if (numUsedVars < n) + numUsedVars = n; + } + } + } + } + } + return numUsedVars; +} + +void CInArchive::ReadString2(AString &s, UInt32 pos) +{ + if ((Int32)pos < 0) + { + Add_LangStr(s, -((Int32)pos + 1)); + return; + } + + if (pos >= NumStringChars) + { + s += kErrorStr; + // UIntToString(s, pos); + return; + } + + #ifdef NSIS_SCRIPT + strUsed[pos] = 1; + #endif + + if (IsUnicode) + GetNsisString_Unicode(s, _data + _stringsPos + pos * 2); + else + GetNsisString(s, _data + _stringsPos + pos); +} + +#endif + +#ifdef NSIS_SCRIPT + +#define DEL_DIR 1 +#define DEL_RECURSE 2 +#define DEL_REBOOT 4 +// #define DEL_SIMPLE 8 + +void CInArchive::AddRegRoot(UInt32 val) +{ + Space(); + 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: + // Script += " RRRRR "; + // throw 1; + Add_Hex(Script, val); return; + } + Script += s; +} + +static const char *g_WinAttrib[] = +{ + "READONLY" + , "HIDDEN" + , "SYSTEM" + , NULL + , "DIRECTORY" + , "ARCHIVE" + , "DEVICE" + , "NORMAL" + , "TEMPORARY" + , "SPARSE_FILE" + , "REPARSE_POINT" + , "COMPRESSED" + , "OFFLINE" + , "NOT_CONTENT_INDEXED" + , "ENCRYPTED" + , NULL + , "VIRTUAL" +}; + +#define FLAGS_DELIMITER '|' + +static void FlagsToString2(CDynLimBuf &s, const char **table, unsigned num, UInt32 flags) +{ + bool filled = false; + for (unsigned i = 0; i < num; i++) + { + UInt32 f = (UInt32)1 << i; + if ((flags & f) != 0) + { + const char *name = table[i]; + if (name) + { + if (filled) + s += FLAGS_DELIMITER; + filled = true; + s += name; + flags &= ~f; + } + } + } + if (flags != 0) + { + if (filled) + s += FLAGS_DELIMITER; + Add_Hex(s, flags); + } +} + +static bool DoesNeedQuotes(const char *s) +{ + char c = s[0]; + if (c == 0 || c == '#' || c == ';' || (c == '/' && s[1] == '*')) + return true; + for (;;) + { + char c = *s++; + if (c == 0) + return false; + if (c == ' ') + return true; + } +} + +void CInArchive::Add_QuStr(const AString &s) +{ + bool needQuotes = DoesNeedQuotes(s); + if (needQuotes) + Script += '\"'; + Script += s; + if (needQuotes) + Script += '\"'; +} + +void CInArchive::SpaceQuStr(const AString &s) +{ + Space(); + Add_QuStr(s); +} + +void CInArchive::AddParam(UInt32 pos) +{ + _tempString.Empty(); + ReadString2(_tempString, pos); + SpaceQuStr(_tempString); +} + +void CInArchive::AddParams(const UInt32 *params, unsigned num) +{ + for (unsigned i = 0; i < num; i++) + AddParam(params[i]); +} + +void CInArchive::AddOptionalParam(UInt32 pos) +{ + if (pos != 0) + AddParam(pos); +} + +static unsigned GetNumParams(const UInt32 *params, unsigned num) +{ + for (; num > 0 && params[num - 1] == 0; num--); + return num; +} + +void CInArchive::AddOptionalParams(const UInt32 *params, unsigned num) +{ + AddParams(params, GetNumParams(params, num)); +} + + +static const UInt32 CMD_REF_Goto = (1 << 0); +static const UInt32 CMD_REF_Call = (1 << 1); +static const UInt32 CMD_REF_Pre = (1 << 2); +static const UInt32 CMD_REF_Show = (1 << 3); +static const UInt32 CMD_REF_Leave = (1 << 4); +static const UInt32 CMD_REF_OnFunc = (1 << 5); +static const UInt32 CMD_REF_Section = (1 << 6); +static const UInt32 CMD_REF_InitPluginDir = (1 << 7); +// static const UInt32 CMD_REF_Creator = (1 << 5); // _Pre is used instead +static const unsigned CMD_REF_OnFunc_NumShifts = 28; // it uses for onFunc too +static const unsigned CMD_REF_Page_NumShifts = 16; // it uses for onFunc too +static const UInt32 CMD_REF_Page_Mask = 0x0FFF0000; +static const UInt32 CMD_REF_OnFunc_Mask = 0xF0000000; + +inline bool IsPageFunc(UInt32 flag) +{ + return (flag & (CMD_REF_Pre | CMD_REF_Show | CMD_REF_Leave)) != 0; +} + +inline bool IsFunc(UInt32 flag) +{ + // return (flag & (CMD_REF_Pre | CMD_REF_Show | CMD_REF_Leave | CMD_REF_OnFunc)) != 0; + return (flag & (CMD_REF_Call | CMD_REF_Pre | CMD_REF_Show | CMD_REF_Leave | CMD_REF_OnFunc)) != 0; +} + +inline bool IsProbablyEndOfFunc(UInt32 flag) +{ + return (flag != 0 && flag != CMD_REF_Goto); +} + +static const char *kOnFunc[] = +{ + "Init" + , "InstSuccess" + , "InstFailed" + , "UserAbort" + , "GUIInit" + , "GUIEnd" + , "MouseOverSection" + , "VerifyInstDir" + , "SelChange" + , "RebootFailed" +}; + +void CInArchive::Add_FuncName(const UInt32 *labels, UInt32 index) +{ + UInt32 mask = labels[index]; + if (mask & CMD_REF_OnFunc) + { + Script += ".on"; + Script += kOnFunc[labels[index] >> CMD_REF_OnFunc_NumShifts]; + } + else if (mask & CMD_REF_InitPluginDir) + { + /* + if (!IsInstaller) + Script += "un." + */ + Script += "Initialize_____Plugins"; + } + else + { + Script += "func_"; + Add_UInt(index); + } +} + +void CInArchive::AddParam_Func(const UInt32 *labels, UInt32 index) +{ + Space(); + if ((Int32)index >= 0) + Add_FuncName(labels, index); + else + AddQuotes(); +} + + +void CInArchive::Add_LabelName(UInt32 index) +{ + Script += "label_"; + Add_UInt(index); +} + +// param != 0 +void CInArchive::Add_GotoVar(UInt32 param) +{ + Space(); + if ((Int32)param < 0) + Add_Var(-((Int32)param + 1)); + else + Add_LabelName(param - 1); +} + +void CInArchive::Add_GotoVar1(UInt32 param) +{ + if (param == 0) + Script += " 0"; + else + Add_GotoVar(param); +} + +void CInArchive::Add_GotoVars2(const UInt32 *params) +{ + Add_GotoVar1(params[0]); + if (params[1] != 0) + Add_GotoVar(params[1]); +} + +static bool NoLabels(const UInt32 *labels, UInt32 num) +{ + for (UInt32 i = 0; i < num; i++) + if (labels[i] != 0) + return false; + return true; +} + +static const char *k_REBOOTOK = " /REBOOTOK"; + +#define MY__MB_ABORTRETRYIGNORE 2 +#define MY__MB_RETRYCANCEL 5 + +static const char *k_MB_Buttons[] = +{ + "OK" + , "OKCANCEL" + , "ABORTRETRYIGNORE" + , "YESNOCANCEL" + , "YESNO" + , "RETRYCANCEL" + , "CANCELTRYCONTINUE" +}; + +#define MY__MB_ICONSTOP (1 << 4) + +static const char *k_MB_Icons[] = +{ + NULL + , "ICONSTOP" + , "ICONQUESTION" + , "ICONEXCLAMATION" + , "ICONINFORMATION" +}; + +static const char *k_MB_Flags[] = +{ + "HELP" + , "NOFOCUS" + , "SETFOREGROUND" + , "DEFAULT_DESKTOP_ONLY" + , "TOPMOST" + , "RIGHT" + , "RTLREADING" + // , "SERVICE_NOTIFICATION" // unsupported. That bit is used for NSIS purposes +}; + +#define MY__IDCANCEL 2 +#define MY__IDIGNORE 5 + +static const char *k_Button_IDs[] = +{ + "0" + , "IDOK" + , "IDCANCEL" + , "IDABORT" + , "IDRETRY" + , "IDIGNORE" + , "IDYES" + , "IDNO" + , "IDCLOSE" + , "IDHELP" + , "IDTRYAGAIN" + , "IDCONTINUE" +}; + +void CInArchive::Add_ButtonID(UInt32 buttonID) +{ + Space(); + if (buttonID < ARRAY_SIZE(k_Button_IDs)) + Script += k_Button_IDs[buttonID]; + else + { + Script += "Button_"; + Add_UInt(buttonID); + } +} + +bool CInArchive::IsDirectString_Equal(UInt32 offset, const char *s) const +{ + if (offset >= NumStringChars) + return false; + if (IsUnicode) + return AreStringsEqual_16and8(_data + _stringsPos + offset * 2, s); + else + return strcmp((const char *)(const Byte *)_data + _stringsPos + offset, s) == 0; +} + +static UInt32 ConvertHexStringToUInt32(const char *s, const char **end) +{ + UInt32 result = 0; + for (int i = 0; i < 8; i++) + { + char c = *s; + UInt32 v; + if (c >= '0' && c <= '9') v = (c - '0'); + else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A'); + else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a'); + else + { + if (end != NULL) + *end = s; + return result; + } + result <<= 4; + result |= v; + s++; + } + if (end != NULL) + *end = s; + return 0; +} + +static bool StringToUInt32(const char *s, UInt32 &res) +{ + const char *end; + if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) + res = ConvertHexStringToUInt32(s + 2, &end); + else + res = ConvertStringToUInt32(s, &end); + return (*end == 0); +} + +static const unsigned k_CtlColors_Size = 24; + +struct CNsis_CtlColors +{ + UInt32 text; // COLORREF + UInt32 bkc; // COLORREF + UInt32 lbStyle; + UInt32 bkb; // HBRUSH + Int32 bkmode; + Int32 flags; + + void Parse(const Byte *p); +}; + +void CNsis_CtlColors::Parse(const Byte *p) +{ + text = Get32(p); + bkc = Get32(p + 4); + lbStyle = Get32(p + 8); + bkb = Get32(p + 12); + bkmode = (Int32)Get32(p + 16); + flags = (Int32)Get32(p + 20); +} + +// Win32 constants +#define MY__TRANSPARENT 1 +#define MY__OPAQUE 2 + +#define MY__GENERIC_READ (1 << 31) +#define MY__GENERIC_WRITE (1 << 30) +#define MY__GENERIC_EXECUTE (1 << 29) +#define MY__GENERIC_ALL (1 << 28) + +#define MY__CREATE_NEW 1 +#define MY__CREATE_ALWAYS 2 +#define MY__OPEN_EXISTING 3 +#define MY__OPEN_ALWAYS 4 +#define MY__TRUNCATE_EXISTING 5 + +// text/bg colors +#define kColorsFlags_TEXT 1 +#define kColorsFlags_TEXT_SYS 2 +#define kColorsFlags_BK 4 +#define kColorsFlags_BK_SYS 8 +#define kColorsFlags_BKB 16 + +void CInArchive::Add_Color2(UInt32 v) +{ + v = ((v & 0xFF) << 16) | (v & 0xFF00) | ((v >> 16) & 0xFF); + char sz[32]; + for (int i = 5; i >= 0; i--) + { + unsigned t = v & 0xF; + v >>= 4; + sz[i] = (char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))); + } + sz[6] = 0; + Script += sz; +} + +void CInArchive::Add_ColorParam(UInt32 v) +{ + Space(); + Add_Color2(v); +} + +void CInArchive::Add_Color(UInt32 v) +{ + Script += "0x"; + Add_Color2(v); +} + +#define MY__SW_HIDE 0 +#define MY__SW_SHOWNORMAL 1 + +#define MY__SW_SHOWMINIMIZED 2 +#define MY__SW_SHOWMINNOACTIVE 7 +#define MY__SW_SHOWNA 8 + +static const char *kShowWindow_Commands[] = +{ + "HIDE" + , "SHOWNORMAL" // "NORMAL" + , "SHOWMINIMIZED" + , "SHOWMAXIMIZED" // "MAXIMIZE" + , "SHOWNOACTIVATE" + , "SHOW" + , "MINIMIZE" + , "SHOWMINNOACTIVE" + , "SHOWNA" + , "RESTORE" + , "SHOWDEFAULT" + , "FORCEMINIMIZE" // "MAX" +}; + +static void Add_ShowWindow_Cmd_2(AString &s, UInt32 cmd) +{ + if (cmd < ARRAY_SIZE(kShowWindow_Commands)) + { + s += "SW_"; + s += kShowWindow_Commands[cmd]; + } + else + UIntToString(s, cmd); +} + +void CInArchive::Add_ShowWindow_Cmd(UInt32 cmd) +{ + if (cmd < ARRAY_SIZE(kShowWindow_Commands)) + { + Script += "SW_"; + Script += kShowWindow_Commands[cmd]; + } + else + Add_UInt(cmd); +} + +void CInArchive::Add_TypeFromList(const char **table, unsigned tableSize, UInt32 type) +{ + if (type < tableSize) + Script += table[type]; + else + { + Script += '_'; + Add_UInt(type); + } +} + +#define ADD_TYPE_FROM_LIST(table, type) Add_TypeFromList(table, ARRAY_SIZE(table), type) + +enum +{ + k_ExecFlags_AutoClose, + k_ExecFlags_ShellVarContext, + k_ExecFlags_Errors, + k_ExecFlags_Abort, + k_ExecFlags_RebootFlag, + k_ExecFlags_reboot_called, + k_ExecFlags_cur_insttype, + k_ExecFlags_plugin_api_version, + k_ExecFlags_Silent, + k_ExecFlags_InstDirError, + k_ExecFlags_rtl, + k_ExecFlags_ErrorLevel, + k_ExecFlags_RegView, + k_ExecFlags_DetailsPrint = 13, +}; + +// Names for NSIS exec_flags_t structure vars +static const char *kExecFlags_VarsNames[] = +{ + "AutoClose" // autoclose; + , "ShellVarContext" // all_user_var; + , "Errors" // exec_error; + , "Abort" // abort; + , "RebootFlag" // exec_reboot; // NSIS_SUPPORT_REBOOT + , "reboot_called" // reboot_called; // NSIS_SUPPORT_REBOOT + , "cur_insttype" // XXX_cur_insttype; // depreacted + , "plugin_api_version" // plugin_api_version; // see NSISPIAPIVER_CURR + // used to be XXX_insttype_changed + , "Silent" // silent; // NSIS_CONFIG_SILENT_SUPPORT + , "InstDirError" // instdir_error; + , "rtl" // rtl; + , "ErrorLevel" // errlvl; + , "RegView" // alter_reg_view; + , "DetailsPrint" // status_update; +}; + +void CInArchive::Add_ExecFlags(UInt32 flagsType) +{ + ADD_TYPE_FROM_LIST(kExecFlags_VarsNames, flagsType); +} + + +// ---------- Page ---------- + +// page flags +#define PF_CANCEL_ENABLE 4 +#define PF_LICENSE_FORCE_SELECTION 32 +#define PF_LICENSE_NO_FORCE_SELECTION 64 +#define PF_PAGE_EX 512 +#define PF_DIR_NO_BTN_DISABLE 1024 +/* +#define PF_LICENSE_SELECTED 1 +#define PF_NEXT_ENABLE 2 +#define PF_BACK_SHOW 8 +#define PF_LICENSE_STREAM 16 +#define PF_NO_NEXT_FOCUS 128 +#define PF_BACK_ENABLE 256 +*/ + +// page window proc +enum +{ + PWP_LICENSE, + PWP_SELCOM, + PWP_DIR, + PWP_INSTFILES, + PWP_UNINST, + PWP_COMPLETED, + PWP_CUSTOM +}; + +static const char *kPageTypes[] = +{ + "license" + , "components" + , "directory" + , "instfiles" + , "uninstConfirm" + , "COMPLETED" + , "custom" +}; + +#define SET_FUNC_REF(x, flag) if ((Int32)(x) >= 0 && (x) < bh.Num) \ + { labels[x] = (labels[x] & ~CMD_REF_Page_Mask) | ((flag) | (pageIndex << CMD_REF_Page_NumShifts)); } + +// #define IDD_LICENSE 102 +#define IDD_LICENSE_FSRB 108 +#define IDD_LICENSE_FSCB 109 + +void CInArchive::AddPageOption1(UInt32 param, const char *name) +{ + if (param == 0) + return; + TabString(name); + AddParam(param); + NewLine(); +} + +void CInArchive::AddPageOption(const UInt32 *params, unsigned num, const char *name) +{ + num = GetNumParams(params, num); + if (num == 0) + return; + TabString(name); + AddParams(params, num); + NewLine(); +} + +void CInArchive::Separator() +{ + AddLF(); + AddCommentAndString("--------------------"); + AddLF(); +} + +void CInArchive::Space() +{ + Script += ' '; +} + +void CInArchive::Tab() +{ + Script += " "; +} + +void CInArchive::Tab(bool commented) +{ + Script += commented ? " ; " : " "; +} + +void CInArchive::BigSpaceComment() +{ + Script += " ; "; +} + +void CInArchive::SmallSpaceComment() +{ + Script += " ; "; +} + +void CInArchive::AddCommentAndString(const char *s) +{ + Script += "; "; + Script += s; +} + +void CInArchive::AddError(const char *s) +{ + BigSpaceComment(); + Script += "!!! ERROR: "; + Script += s; +} + +void CInArchive::AddErrorLF(const char *s) +{ + AddError(s); + AddLF(); +} + +void CInArchive::CommentOpen() +{ + AddStringLF("/*"); +} + +void CInArchive::CommentClose() +{ + AddStringLF("*/"); +} + +void CInArchive::AddLF() +{ + Script += CR_LF; +} + +void CInArchive::AddQuotes() +{ + Script += "\"\""; +} + +void CInArchive::TabString(const char *s) +{ + Tab(); + Script += s; +} + +void CInArchive::AddStringLF(const char *s) +{ + Script += s; + AddLF(); +} + +// ---------- Section ---------- + +static const char *kSection_VarsNames[] = +{ + "Text" + , "InstTypes" + , "Flags" + , "Code" + , "CodeSize" + , "Size" // size in KB +}; + +void CInArchive::Add_SectOp(UInt32 opType) +{ + ADD_TYPE_FROM_LIST(kSection_VarsNames, opType); +} + +void CSection::Parse(const Byte *p) +{ + Name = Get32(p); + InstallTypes = Get32(p + 4); + Flags = Get32(p + 8); + StartCmdIndex = Get32(p + 12); + NumCommands = Get32(p + 16); + SizeKB = Get32(p + 20); +}; + +// used for section->flags +#define SF_SELECTED (1 << 0) +#define SF_SECGRP (1 << 1) +#define SF_SECGRPEND (1 << 2) +#define SF_BOLD (1 << 3) +#define SF_RO (1 << 4) +#define SF_EXPAND (1 << 5) +#define SF_PSELECTED (1 << 6) +#define SF_TOGGLED (1 << 7) +#define SF_NAMECHG (1 << 8) + +bool CInArchive::PrintSectionBegin(const CSection §, unsigned index) +{ + AString name; + if (sect.Flags & SF_BOLD) + name += '!'; + AString s2; + ReadString2(s2, sect.Name); + if (!IsInstaller) + { + if (!StringsAreEqualNoCase_Ascii(s2, "uninstall")) + name += "un."; + } + name += s2; + + if (sect.Flags & SF_SECGRPEND) + { + AddStringLF("SectionGroupEnd"); + return true; + } + + if (sect.Flags & SF_SECGRP) + { + Script += "SectionGroup"; + if (sect.Flags & SF_EXPAND) + Script += " /e"; + SpaceQuStr(name); + Script += " ; Section"; + AddParam_UInt(index); + NewLine(); + return true; + } + + Script += "Section"; + if ((sect.Flags & SF_SELECTED) == 0) + Script += " /o"; + if (!name.IsEmpty()) + SpaceQuStr(name); + + /* + if (!name.IsEmpty()) + Script += ' '; + else + */ + SmallSpaceComment(); + Script += "Section_"; + Add_UInt(index); + + /* + Script += " ; flags = "; + Add_Hex(Script, sect.Flags); + */ + + NewLine(); + + if (sect.SizeKB != 0) + { + // probably we must show AddSize, only if there is additional size. + Tab(); + AddCommentAndString("AddSize"); + AddParam_UInt(sect.SizeKB); + AddLF(); + } + + bool needSectionIn = + (sect.Name != 0 && sect.InstallTypes != 0) || + (sect.Name == 0 && sect.InstallTypes != 0xFFFFFFFF); + if (needSectionIn || (sect.Flags & SF_RO) != 0) + { + TabString("SectionIn"); + UInt32 instTypes = sect.InstallTypes; + for (int i = 0; i < 32; i++, instTypes >>= 1) + if ((instTypes & 1) != 0) + { + AddParam_UInt(i + 1); + } + if ((sect.Flags & SF_RO) != 0) + Script += " RO"; + AddLF(); + } + return false; +} + +void CInArchive::PrintSectionEnd() +{ + AddStringLF("SectionEnd"); + AddLF(); +} + +// static const unsigned kOnFuncShift = 4; + +void CInArchive::ClearLangComment() +{ + langStrIDs.Clear(); +} + +void CInArchive::PrintNumComment(const char *name, UInt32 value) +{ + // size_t len = Script.Len(); + AddCommentAndString(name); + Script += ": "; + Add_UInt(value); + AddLF(); + /* + len = Script.Len() - len; + char sz[16]; + ConvertUInt32ToString(value, sz); + len += MyStringLen(sz); + for (; len < 20; len++) + Space(); + AddStringLF(sz); + */ +} + + +void CInArchive::NewLine() +{ + if (!langStrIDs.IsEmpty()) + { + BigSpaceComment(); + for (unsigned i = 0; i < langStrIDs.Size() && i < 20; i++) + { + /* + if (i != 0) + Script += ' '; + */ + UInt32 langStr = langStrIDs[i]; + if (langStr >= _numLangStrings) + { + AddError("langStr"); + break; + } + UInt32 param = Get32(_mainLang + langStr * 4); + if (param != 0) + AddParam(param); + } + ClearLangComment(); + } + AddLF(); +} + +static const UInt32 kPageSize = 16 * 4; + +static const char *k_SetOverwrite_Modes[] = +{ + "on" + , "off" + , "try" + , "ifnewer" + , "ifdiff" + // "lastused" +}; + + +void CInArchive::MessageBox_MB_Part(UInt32 param) +{ + { + UInt32 v = param & 0xF; + Script += " MB_"; + if (v < ARRAY_SIZE(k_MB_Buttons)) + Script += k_MB_Buttons[v]; + else + { + Script += "Buttons_"; + Add_UInt(v); + } + } + { + UInt32 icon = (param >> 4) & 0x7; + if (icon != 0) + { + Script += "|MB_"; + if (icon < ARRAY_SIZE(k_MB_Icons) && k_MB_Icons[icon] != 0) + Script += k_MB_Icons[icon]; + else + { + Script += "Icon_"; + Add_UInt(icon); + } + } + } + if ((param & 0x80) != 0) + Script += "|MB_USERICON"; + { + UInt32 defButton = (param >> 8) & 0xF; + if (defButton != 0) + { + Script += "|MB_DEFBUTTON"; + Add_UInt(defButton + 1); + } + } + { + UInt32 modal = (param >> 12) & 0x3; + if (modal == 1) Script += "|MB_SYSTEMMODAL"; + else if (modal == 2) Script += "|MB_TASKMODAL"; + else if (modal == 3) Script += "|0x3000"; + UInt32 flags = (param >> 14); + for (int i = 0; i < ARRAY_SIZE(k_MB_Flags); i++) + if ((flags & (1 << i)) != 0) + { + Script += "|MB_"; + Script += k_MB_Flags[i]; + } + } +} + +#define GET_CMD_PARAM(ppp, index) Get32((ppp) + 4 + (index) * 4) + +static const Byte k_InitPluginDir_Commands[] = + { 13, 26, 31, 13, 19, 21, 11, 14, 25, 31, 1, 22, 4, 1 }; + +bool CInArchive::CompareCommands(const Byte *rawCmds, const Byte *sequence, size_t numCommands) +{ + for (UInt32 kkk = 0; kkk < numCommands; kkk++, rawCmds += kCmdSize) + if (GetCmd(Get32(rawCmds)) != sequence[kkk]) + return false; + return true; +} + +#endif + +static const UInt32 kSectionSize_base = 6 * 4; +static const UInt32 kSectionSize_8bit = kSectionSize_base + 1024; +static const UInt32 kSectionSize_16bit = kSectionSize_base + 1024 * 2; +static const UInt32 kSectionSize_16bit_Big = kSectionSize_base + 8196 * 2; +// 8196 is default string length in NSIS-Unicode since 2.37.3 + + +static void AddString(AString &dest, const char *src) +{ + if (!dest.IsEmpty()) + dest += ' '; + dest += src; +} + +AString CInArchive::GetFormatDescription() const +{ + AString s = "NSIS-"; + char c; + if (IsPark()) + { + s += "Park-"; + c = '1'; + if (NsisType == k_NsisType_Park2) c = '2'; + else if (NsisType == k_NsisType_Park3) c = '3'; + } + else + { + c = '2'; + if (NsisType == k_NsisType_Nsis3) + c = '3'; + } + s += c; + if (IsNsis200) + s += ".00"; + else if (IsNsis225) + s += ".25"; + + if (IsUnicode) + AddString(s, "Unicode"); + if (LogCmdIsEnabled) + AddString(s, "log"); + if (BadCmd >= 0) + { + AddString(s, "BadCmd="); + UIntToString(s, BadCmd); + } + return s; +} + +#ifdef NSIS_SCRIPT + +unsigned CInArchive::GetNumSupportedCommands() const +{ + unsigned numCmds = IsPark() ? kNumCmds : kNumCmds - kNumAdditionalParkCmds; + if (!LogCmdIsEnabled) + numCmds--; + if (!IsUnicode) + numCmds -= 2; + return numCmds; +} + +#endif + +UInt32 CInArchive::GetCmd(UInt32 a) +{ + if (!IsPark()) + { + if (!LogCmdIsEnabled) + return a; + if (a < EW_SECTIONSET) + return a; + if (a == EW_SECTIONSET) + return EW_LOG; + return a - 1; + } + + if (a < EW_REGISTERDLL) + return a; + if (NsisType >= k_NsisType_Park2) + { + if (a == EW_REGISTERDLL) return EW_GETFONTVERSION; + a--; + } + if (NsisType >= k_NsisType_Park3) + { + if (a == EW_REGISTERDLL) return EW_GETFONTNAME; + a--; + } + if (a >= EW_FSEEK) + { + if (IsUnicode) + { + if (a == EW_FSEEK) return EW_FPUTWS; + if (a == EW_FSEEK + 1) return EW_FPUTWS + 1; + a -= 2; + } + + if (a >= EW_SECTIONSET && LogCmdIsEnabled) + { + if (a == EW_SECTIONSET) + return EW_LOG; + return a - 1; + } + if (a == EW_FPUTWS) + return EW_FINDPROC; + // if (a > EW_FPUTWS) return 0; + } + return a; +} + +void CInArchive::FindBadCmd(const CBlockHeader &bh, const Byte *p) +{ + BadCmd = -1; + + for (UInt32 kkk = 0; kkk < bh.Num; kkk++, p += kCmdSize) + { + UInt32 id = GetCmd(Get32(p)); + if (id >= kNumCmds) + continue; + if (BadCmd >= 0 && id >= (unsigned)BadCmd) + continue; + unsigned i; + if (id == EW_GETLABELADDR || + id == EW_GETFUNCTIONADDR) + { + BadCmd = id; + continue; + } + for (i = 6; i != 0; i--) + { + UInt32 param = Get32(p + i * 4); + if (param != 0) + break; + } + if (id == EW_FINDPROC && i == 0) + { + BadCmd = id; + continue; + } + if (k_Commands[id].NumParams < i) + BadCmd = id; + } +} + +/* We calculate the number of parameters in commands to detect + layout of commands. It's not very good way. + If you know simpler and more robust way to detect Version and layout, + please write to 7-Zip forum */ + +void CInArchive::DetectNsisType(const CBlockHeader &bh, const Byte *p) +{ + bool strongPark = false; + bool strongNsis = false; + + { + const Byte *strData = _data + _stringsPos; + if (IsUnicode) + { + UInt32 num = NumStringChars; + for (UInt32 i = 0; i < num; i++) + { + if (Get16(strData + i * 2) == 0) + { + unsigned c2 = Get16(strData + 2 + i * 2); + // if (c2 <= NS_3_CODE_SKIP && c2 != NS_3_CODE_SHELL) + if (c2 == NS_3_CODE_VAR) + { + // it can be TXT/RTF string with marker char (1 or 2). so we must next char + // const wchar_t *p2 = (const wchar_t *)(strData + i * 2 + 2); + // p2 = p2; + if ((Get16(strData + 3 + i * 2) & 0x8000) != 0) + { + NsisType = k_NsisType_Nsis3; + strongNsis = true; + break; + } + } + } + } + if (!strongNsis) + { + NsisType = k_NsisType_Park1; + strongPark = true; + } + } + else + { + UInt32 num = NumStringChars; + for (UInt32 i = 0; i < num; i++) + { + if (strData[i] == 0) + { + Byte c2 = strData[i + 1]; + // it can be TXT/RTF with marker char (1 or 2). so we must check next char + // for marker=1 (txt) + if (c2 == NS_3_CODE_VAR) + // if (c2 <= NS_3_CODE_SKIP && c2 != NS_3_CODE_SHELL && c2 != 1) + { + if ((strData[i+ 2] & 0x80) != 0) + { + // const char *p2 = (const char *)(strData + i + 1); + // p2 = p2; + NsisType = k_NsisType_Nsis3; + strongNsis = true; + break; + } + } + } + } + } + } + + if (NsisType == k_NsisType_Nsis2 && !IsUnicode) + { + const Byte *p2 = p; + + for (UInt32 kkk = 0; kkk < bh.Num; kkk++, p2 += kCmdSize) + { + UInt32 cmd = GetCmd(Get32(p2)); + if (cmd != EW_GETDLGITEM && + cmd != EW_ASSIGNVAR) + continue; + + UInt32 params[kNumCommandParams]; + for (unsigned i = 0; i < kNumCommandParams; i++) + params[i] = Get32(p2 + 4 + 4 * i); + + if (cmd == EW_GETDLGITEM) + { + // we can use also EW_SETCTLCOLORS + if (IsVarStr(params[1], kVar_HWNDPARENT_225)) + { + IsNsis225 = true; + if (params[0] == kVar_Spec_OUTDIR_225) + { + IsNsis200 = true; + break; + } + } + } + else // if (cmd == EW_ASSIGNVAR) + { + if (params[0] == kVar_Spec_OUTDIR_225 && + params[2] == 0 && + params[3] == 0 && + IsVarStr(params[1], kVar_OUTDIR)) + IsNsis225 = true; + } + } + } + + bool parkVer_WasDetected = false; + + if (!strongNsis && !IsNsis225 && !IsNsis200) + { + // it must be before FindBadCmd(bh, p); + unsigned mask = 0; + + unsigned numInsertMax = IsUnicode ? 4 : 2; + + const Byte *p2 = p; + + for (UInt32 kkk = 0; kkk < bh.Num; kkk++, p2 += kCmdSize) + { + UInt32 cmd = Get32(p2); // we use original (not converted) command + + if (cmd < EW_WRITEUNINSTALLER || + cmd > EW_WRITEUNINSTALLER + numInsertMax) + continue; + + UInt32 params[kNumCommandParams]; + for (unsigned i = 0; i < kNumCommandParams; i++) + params[i] = Get32(p2 + 4 + 4 * i); + + if (params[4] != 0 || + params[5] != 0 || + params[0] <= 1 || + params[3] <= 1) + continue; + + UInt32 altParam = params[3]; + if (!IsGoodString(params[0]) || + !IsGoodString(altParam)) + continue; + + UInt32 additional = 0; + if (GetVarIndexFinished(altParam, '\\', additional) != kVar_INSTDIR) + continue; + if (AreTwoParamStringsEqual(altParam + additional, params[0])) + { + unsigned numInserts = cmd - EW_WRITEUNINSTALLER; + mask |= (1 << numInserts); + } + } + + if (mask == 1) + { + parkVer_WasDetected = true; // it can be original NSIS or Park-1 + } + else if (mask != 0) + { + ENsisType newType = NsisType; + if (IsUnicode) + switch (mask) + { + case (1 << 3): newType = k_NsisType_Park2; break; + case (1 << 4): newType = k_NsisType_Park3; break; + } + else + switch (mask) + { + case (1 << 1): newType = k_NsisType_Park2; break; + case (1 << 2): newType = k_NsisType_Park3; break; + } + if (newType != NsisType) + { + parkVer_WasDetected = true; + NsisType = newType; + } + } + } + + FindBadCmd(bh, p); + + /* + if (strongNsis) + return; + */ + + if (BadCmd < EW_REGISTERDLL) + return; + + /* + // in ANSI archive we don't check Park and log version + if (!IsUnicode) + return; + */ + + // We can support Park-ANSI archives, if we remove if (strongPark) check + if (strongPark && !parkVer_WasDetected) + { + if (BadCmd < EW_SECTIONSET) + { + NsisType = k_NsisType_Park3; + LogCmdIsEnabled = true; // version 3 is provided with log enabled + FindBadCmd(bh, p); + if (BadCmd > 0 && BadCmd < EW_SECTIONSET) + { + NsisType = k_NsisType_Park2; + LogCmdIsEnabled = false; + FindBadCmd(bh, p); + if (BadCmd > 0 && BadCmd < EW_SECTIONSET) + { + NsisType = k_NsisType_Park1; + FindBadCmd(bh, p); + } + } + } + } + + if (BadCmd >= EW_SECTIONSET) + { + LogCmdIsEnabled = !LogCmdIsEnabled; + FindBadCmd(bh, p); + if (BadCmd >= EW_SECTIONSET && LogCmdIsEnabled) + { + LogCmdIsEnabled = false; + FindBadCmd(bh, p); + } + } +} + +Int32 CInArchive::GetVarIndex(UInt32 strPos) const +{ + if (strPos >= NumStringChars) + return -1; + + if (IsUnicode) + { + if (NumStringChars - strPos < 3 * 2) + return -1; + const Byte *p = _data + _stringsPos + strPos * 2; + unsigned code = Get16(p); + if (IsPark()) + { + if (code != PARK_CODE_VAR) + return -1; + UInt32 n = Get16(p + 2); + if (n == 0) + return -1; + CONVERT_NUMBER_PARK(n); + return (Int32)n; + } + + // NSIS-3 + { + if (code != NS_3_CODE_VAR) + return -1; + UInt32 n = Get16(p + 2); + if (n == 0) + return -1; + CONVERT_NUMBER_NS_3_UNICODE(n); + return (Int32)n; + } + } + + if (NumStringChars - strPos < 4) + return -1; + + const Byte *p = _data + _stringsPos + strPos; + unsigned c = *p; + if (NsisType == k_NsisType_Nsis3) + { + if (c != NS_3_CODE_VAR) + return -1; + } + else if (c != NS_CODE_VAR) + return -1; + + unsigned c0 = p[1]; + if (c0 == 0) + return -1; + unsigned c1 = p[2]; + if (c1 == 0) + return -1; + return DECODE_NUMBER_FROM_2_CHARS(c0, c1); +} + +Int32 CInArchive::GetVarIndex(UInt32 strPos, UInt32 &resOffset) const +{ + resOffset = 0; + Int32 varIndex = GetVarIndex(strPos); + if (varIndex < 0) + return varIndex; + if (IsUnicode) + { + if (NumStringChars - strPos < 2 * 2) + return -1; + resOffset = 2; + } + else + { + if (NumStringChars - strPos < 3) + return -1; + resOffset = 3; + } + return varIndex; +} + +Int32 CInArchive::GetVarIndexFinished(UInt32 strPos, Byte endChar, UInt32 &resOffset) const +{ + resOffset = 0; + Int32 varIndex = GetVarIndex(strPos); + if (varIndex < 0) + return varIndex; + if (IsUnicode) + { + if (NumStringChars - strPos < 3 * 2) + return -1; + const Byte *p = _data + _stringsPos + strPos * 2; + if (Get16(p + 4) != endChar) + return -1; + resOffset = 3; + } + else + { + if (NumStringChars - strPos < 4) + return -1; + const Byte *p = _data + _stringsPos + strPos; + if (p[3] != endChar) + return -1; + resOffset = 4; + } + return varIndex; +} + +bool CInArchive::IsVarStr(UInt32 strPos, UInt32 varIndex) const +{ + if (varIndex > (UInt32)0x7FFF) + return false; + UInt32 resOffset; + return GetVarIndexFinished(strPos, 0, resOffset) == (Int32)varIndex; +} + +bool CInArchive::IsAbsolutePathVar(UInt32 strPos) const +{ + Int32 varIndex = GetVarIndex(strPos); + if (varIndex < 0) + return false; + switch (varIndex) + { + case kVar_INSTDIR: + case kVar_EXEDIR: + case kVar_TEMP: + case kVar_PLUGINSDIR: + return true; + } + return false; +} + +#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z') + +// We use same check as in NSIS decoder +bool IsDrivePath(const wchar_t *s) { return IS_LETTER_CHAR(s[0]) && s[1] == ':' /* && s[2] == '\\' */ ; } +bool IsDrivePath(const char *s) { return IS_LETTER_CHAR(s[0]) && s[1] == ':' /* && s[2] == '\\' */ ; } + +static bool IsAbsolutePath(const wchar_t *s) +{ + return + s[0] == WCHAR_PATH_SEPARATOR && + s[1] == WCHAR_PATH_SEPARATOR || + IsDrivePath(s); +} + +static bool IsAbsolutePath(const char *s) +{ + return + s[0] == CHAR_PATH_SEPARATOR && + s[1] == CHAR_PATH_SEPARATOR || + IsDrivePath(s); +} + +void CInArchive::SetItemName(CItem &item, UInt32 strPos) +{ + ReadString2_Raw(strPos); + bool isAbs = IsAbsolutePathVar(strPos); + if (IsUnicode) + { + item.NameU = Raw_UString; + if (!isAbs && !IsAbsolutePath(Raw_UString)) + item.Prefix = UPrefixes.Size() - 1; + } + else + { + item.NameA = Raw_AString; + if (!isAbs && !IsAbsolutePath(Raw_AString)) + item.Prefix = APrefixes.Size() - 1; + } +} + +HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) +{ + #ifdef NSIS_SCRIPT + CDynLimBuf &s = Script; + + CObjArray labels; + labels.Alloc(bh.Num); + memset(labels, 0, bh.Num * sizeof(UInt32)); + + { + const Byte *p = _data; + UInt32 i; + for (i = 0; i < numOnFunc; i++) + { + UInt32 func = Get32(p + onFuncOffset + 4 * i); + if (func < bh.Num) + labels[func] = (labels[func] & ~CMD_REF_OnFunc_Mask) | (CMD_REF_OnFunc | (i << CMD_REF_OnFunc_NumShifts)); + } + } + + /* + { + for (int i = 0; i < OnFuncs.Size(); i++) + { + UInt32 address = OnFuncs[i] >> kOnFuncShift; + if (address < bh.Num) + } + } + */ + + if (bhPages.Num != 0) + { + Separator(); + PrintNumComment("PAGES", bhPages.Num); + + if (bhPages.Num > (1 << 12) + || bhPages.Offset > _size + || bhPages.Num * kPageSize > _size - bhPages.Offset) + { + AddErrorLF("Pages error"); + } + else + { + + AddLF(); + const Byte *p = _data + bhPages.Offset; + + for (UInt32 pageIndex = 0; pageIndex < bhPages.Num; pageIndex++, p += kPageSize) + { + UInt32 dlgID = Get32(p); + UInt32 wndProcID = Get32(p + 4); + UInt32 preFunc = Get32(p + 8); + UInt32 showFunc = Get32(p + 12); + UInt32 leaveFunc = Get32(p + 16); + UInt32 flags = Get32(p + 20); + UInt32 caption = Get32(p + 24); + // UInt32 back = Get32(p + 28); + UInt32 next = Get32(p + 32); + // UInt32 clickNext = Get32(p + 36); + // UInt32 cancel = Get32(p + 40); + UInt32 params[5]; + for (int i = 0; i < 5; i++) + params[i] = Get32(p + 44 + 4 * i); + + SET_FUNC_REF(preFunc, CMD_REF_Pre); + SET_FUNC_REF(showFunc, CMD_REF_Show); + SET_FUNC_REF(leaveFunc, CMD_REF_Leave); + + if (wndProcID == PWP_COMPLETED) + CommentOpen(); + + AddCommentAndString("Page "); + Add_UInt(pageIndex); + AddLF(); + + if (flags & PF_PAGE_EX) + { + s += "PageEx "; + if (!IsInstaller) + s += "un."; + } + else + s += IsInstaller ? "Page " : "UninstPage "; + + if (wndProcID < ARRAY_SIZE(kPageTypes)) + s += kPageTypes[wndProcID]; + else + Add_UInt(wndProcID); + + + bool needCallbacks = ( + (Int32)preFunc >= 0 || + (Int32)showFunc >= 0 || + (Int32)leaveFunc >= 0); + + if (flags & PF_PAGE_EX) + { + AddLF(); + if (needCallbacks) + TabString("PageCallbacks"); + } + + if (needCallbacks) + { + AddParam_Func(labels, preFunc); // it's creator_function for PWP_CUSTOM + if (wndProcID != PWP_CUSTOM) + { + AddParam_Func(labels, showFunc); + } + AddParam_Func(labels, leaveFunc); + } + + if ((flags & PF_PAGE_EX) == 0) + { + // AddOptionalParam(caption); + if (flags & PF_CANCEL_ENABLE) + s += " /ENABLECANCEL"; + AddLF(); + } + else + { + AddLF(); + AddPageOption1(caption, "Caption"); + } + + if (wndProcID == PWP_LICENSE) + { + if ((flags & PF_LICENSE_NO_FORCE_SELECTION) != 0 || + (flags & PF_LICENSE_FORCE_SELECTION) != 0) + { + TabString("LicenseForceSelection "); + if (flags & PF_LICENSE_NO_FORCE_SELECTION) + s += "off"; + else + { + if (dlgID == IDD_LICENSE_FSCB) + s += "checkbox"; + else if (dlgID == IDD_LICENSE_FSRB) + s += "radiobuttons"; + else + Add_UInt(dlgID); + AddOptionalParams(params + 2, 2); + } + NewLine(); + } + + if (params[0] != 0 || next != 0) + { + TabString("LicenseText"); + AddParam(params[0]); + AddOptionalParam(next); + NewLine(); + } + if (params[1] != 0) + { + TabString("LicenseData"); + if ((Int32)params[1] < 0) + AddParam(params[1]); + else + AddLicense(params[1], -1); + ClearLangComment(); + NewLine(); + } + } + else if (wndProcID == PWP_SELCOM) + AddPageOption(params, 3, "ComponentsText"); + else if (wndProcID == PWP_DIR) + { + AddPageOption(params, 4, "DirText"); + if (params[4] != 0) + { + TabString("DirVar"); + AddParam_Var(params[4] - 1); + AddLF(); + } + if (flags & PF_DIR_NO_BTN_DISABLE) + { + TabString("DirVerify leave"); + AddLF(); + } + + } + else if (wndProcID == PWP_INSTFILES) + { + AddPageOption1(params[2], "CompletedText"); + AddPageOption1(params[1], "DetailsButtonText"); + } + else if (wndProcID == PWP_UNINST) + { + if (params[4] != 0) + { + TabString("DirVar"); + AddParam_Var(params[4] - 1); + AddLF(); + } + AddPageOption(params, 2, "UninstallText"); + } + + if (flags & PF_PAGE_EX) + { + s += "PageExEnd"; + NewLine(); + } + if (wndProcID == PWP_COMPLETED) + CommentClose(); + NewLine(); + } + } + } + + CObjArray Sections; + + { + Separator(); + PrintNumComment("SECTIONS", bhSections.Num); + PrintNumComment("COMMANDS", bh.Num); + AddLF(); + + if (bhSections.Num > (1 << 15) + // || bhSections.Offset > _size + // || (bhSections.Num * SectionSize > _size - bhSections.Offset) + ) + { + AddErrorLF("Sections error"); + } + else if (bhSections.Num != 0) + { + Sections.Alloc((unsigned)bhSections.Num); + const Byte *p = _data + bhSections.Offset; + for (UInt32 i = 0; i < bhSections.Num; i++, p += SectionSize) + { + CSection §ion = Sections[i]; + section.Parse(p); + if (section.StartCmdIndex < bh.Num) + labels[section.StartCmdIndex] |= CMD_REF_Section; + } + } + } + + #endif + + const Byte *p; + UInt32 kkk; + + #ifdef NSIS_SCRIPT + + p = _data + bh.Offset; + + for (kkk = 0; kkk < bh.Num; kkk++, p += kCmdSize) + { + UInt32 commandId = GetCmd(Get32(p)); + UInt32 mask; + switch (commandId) + { + case EW_NOP: mask = 1 << 0; break; + case EW_IFFILEEXISTS: mask = 3 << 1; break; + case EW_IFFLAG: mask = 3 << 0; break; + case EW_MESSAGEBOX: mask = 5 << 3; break; + case EW_STRCMP: mask = 3 << 2; break; + case EW_INTCMP: mask = 7 << 2; break; + case EW_ISWINDOW: mask = 3 << 1; break; + case EW_CALL: + { + if (Get32(p + 4 + 4) == 1) // it's Call :Label + { + mask = 1 << 0; + break; + } + UInt32 param0 = Get32(p + 4); + if ((Int32)param0 > 0) + labels[param0 - 1] |= CMD_REF_Call; + continue; + } + default: continue; + } + for (int i = 0; mask != 0; i++, mask >>= 1) + if (mask & 1) + { + UInt32 param = Get32(p + 4 + 4 * i); + if ((Int32)param > 0 && (Int32)param <= (Int32)bh.Num) + labels[param - 1] |= CMD_REF_Goto; + } + } + + int InitPluginsDir_Start = -1; + int InitPluginsDir_End = -1; + p = _data + bh.Offset; + for (kkk = 0; kkk < bh.Num; kkk++, p += kCmdSize) + { + UInt32 flg = labels[kkk]; + /* + if (IsFunc(flg)) + { + AddLF(); + for (int i = 0; i < 14; i++) + { + UInt32 commandId = GetCmd(Get32(p + kCmdSize * i)); + s += ", "; + UIntToString(s, commandId); + } + AddLF(); + } + */ + if (IsFunc(flg) + && bh.Num - kkk >= ARRAY_SIZE(k_InitPluginDir_Commands) + && CompareCommands(p, k_InitPluginDir_Commands, ARRAY_SIZE(k_InitPluginDir_Commands))) + { + InitPluginsDir_Start = kkk; + InitPluginsDir_End = kkk + ARRAY_SIZE(k_InitPluginDir_Commands); + labels[kkk] |= CMD_REF_InitPluginDir; + break; + } + } + + #endif + + // AString prefixA_Temp; + // UString prefixU_Temp; + + + // const UInt32 kFindS = 158; + + #ifdef NSIS_SCRIPT + + UInt32 curSectionIndex = 0; + // UInt32 lastSectionEndCmd = 0xFFFFFFFF; + bool sectionIsOpen = false; + // int curOnFunc = 0; + bool onFuncIsOpen = false; + + /* + for (unsigned yyy = 0; yyy + 3 < _data.Size(); yyy++) + { + UInt32 val = Get32(_data + yyy); + if (val == kFindS) + val = val; + } + */ + + UInt32 overwrite_State = 0; // "SetOverwrite on" + Int32 allowSkipFiles_State = -1; // -1: on, -2: off, >=0 : RAW value + UInt32 endCommentIndex = 0; + + unsigned numSupportedCommands = GetNumSupportedCommands(); + + #endif + + p = _data + bh.Offset; + + UString spec_outdir_U; + AString spec_outdir_A; + + UPrefixes.Add(L"$INSTDIR"); + APrefixes.Add("$INSTDIR"); + + p = _data + bh.Offset; + + unsigned spec_outdir_VarIndex = IsNsis225 ? + kVar_Spec_OUTDIR_225 : + kVar_Spec_OUTDIR; + + for (kkk = 0; kkk < bh.Num; kkk++, p += kCmdSize) + { + UInt32 commandId; + UInt32 params[kNumCommandParams]; + commandId = GetCmd(Get32(p)); + { + for (unsigned i = 0; i < kNumCommandParams; i++) + { + params[i] = Get32(p + 4 + 4 * i); + /* + if (params[i] == kFindS) + i = i; + */ + } + } + + #ifdef NSIS_SCRIPT + + bool IsSectionGroup = false; + while (curSectionIndex < bhSections.Num) + { + const CSection § = Sections[curSectionIndex]; + if (sectionIsOpen) + { + if (sect.StartCmdIndex + sect.NumCommands + 1 != kkk) + break; + PrintSectionEnd(); + sectionIsOpen = false; + // lastSectionEndCmd = kkk; + curSectionIndex++; + continue; + } + if (sect.StartCmdIndex != kkk) + break; + if (PrintSectionBegin(sect, curSectionIndex)) + { + IsSectionGroup = true; + curSectionIndex++; + // do we need to flush prefixes in new section? + // FlushOutPathPrefixes(); + } + else + sectionIsOpen = true; + } + + /* + if (curOnFunc < OnFuncs.Size()) + { + if ((OnFuncs[curOnFunc] >> kOnFuncShift) == kkk) + { + s += "Function .on"; + s += kOnFunc[OnFuncs[curOnFunc++] & ((1 << kOnFuncShift) - 1)]; + AddLF(); + onFuncIsOpen = true; + } + } + */ + + if (labels[kkk] != 0 && labels[kkk] != CMD_REF_Section) + { + UInt32 flg = labels[kkk]; + if (IsFunc(flg)) + { + if ((int)kkk == InitPluginsDir_Start) + CommentOpen(); + + onFuncIsOpen = true; + s += "Function "; + Add_FuncName(labels, kkk); + if (IsPageFunc(flg)) + { + BigSpaceComment(); + s += "Page "; + Add_UInt((flg & CMD_REF_Page_Mask) >> CMD_REF_Page_NumShifts); + // if (flg & CMD_REF_Creator) s += ", Creator"; + if (flg & CMD_REF_Leave) s += ", Leave"; + if (flg & CMD_REF_Pre) s += ", Pre"; + if (flg & CMD_REF_Show) s += ", Show"; + } + AddLF(); + } + if (flg & CMD_REF_Goto) + { + Add_LabelName(kkk); + s += ':'; + AddLF(); + } + } + + if (commandId != EW_RET) + { + Tab(kkk < endCommentIndex); + } + + /* + UInt32 originalCmd = Get32(p); + if (originalCmd >= EW_REGISTERDLL) + { + UIntToString(s, originalCmd); + s += ' '; + if (originalCmd != commandId) + { + UIntToString(s, commandId); + s += ' '; + } + } + */ + + unsigned numSkipParams = 0; + + if (commandId < ARRAY_SIZE(k_Commands) && commandId < numSupportedCommands) + { + numSkipParams = k_Commands[commandId].NumParams; + const char *sz = k_CommandNames[commandId]; + if (sz) + s += sz; + } + else + { + s += "Command"; + Add_UInt(commandId); + /* We don't show wrong commands that use overlapped ids. + So we change commandId to big value */ + if (commandId < (1 << 12)) + commandId += (1 << 12); + } + + #endif + + switch (commandId) + { + case EW_CREATEDIR: + { + bool isSetOutPath = (params[1] != 0); + + if (isSetOutPath) + { + UInt32 par0 = params[0]; + + UInt32 resOffset; + Int32 idx = GetVarIndex(par0, resOffset); + if (idx == (Int32)spec_outdir_VarIndex || + idx == kVar_OUTDIR) + par0 += resOffset; + + ReadString2_Raw(par0); + + if (IsUnicode) + { + if (idx == (Int32)spec_outdir_VarIndex) + Raw_UString.Insert(0, spec_outdir_U); + else if (idx == kVar_OUTDIR) + Raw_UString.Insert(0, UPrefixes.Back()); + UPrefixes.Add(Raw_UString); + } + else + { + if (idx == (Int32)spec_outdir_VarIndex) + Raw_AString.Insert(0, spec_outdir_A); + else if (idx == kVar_OUTDIR) + Raw_AString.Insert(0, APrefixes.Back()); + APrefixes.Add(Raw_AString); + } + } + + #ifdef NSIS_SCRIPT + s += isSetOutPath ? "SetOutPath" : "CreateDirectory"; + AddParam(params[0]); + #endif + + break; + } + + + case EW_ASSIGNVAR: + { + if (params[0] == spec_outdir_VarIndex) + { + spec_outdir_U.Empty(); + spec_outdir_A.Empty(); + if (IsVarStr(params[1], kVar_OUTDIR) && + params[2] == 0 && + params[3] == 0) + { + if (IsVarStr(params[1], kVar_OUTDIR)) + { + spec_outdir_U = UPrefixes.Back(); // outdir_U; + spec_outdir_A = APrefixes.Back();// outdir_A; + } + } + } + + #ifdef NSIS_SCRIPT + + if (params[2] == 0 && + params[3] == 0 && + params[4] == 0 && + params[5] == 0 && + params[1] != 0 && + params[1] < NumStringChars) + { + char sz[16]; + ConvertUInt32ToString(kkk + 1, sz); + if (IsDirectString_Equal(params[1], sz)) + { + // we suppose that it's GetCurrentAddress command + // but there is probability that it's StrCpy command + s += "GetCurrentAddress"; + AddParam_Var(params[0]); + SmallSpaceComment(); + } + } + s += "StrCpy"; + AddParam_Var(params[0]); + AddParam(params[1]); + + AddOptionalParams(params + 2, 2); + + #endif + + break; + } + + case EW_EXTRACTFILE: + { + CItem &item = Items.AddNew(); + + UInt32 par1 = params[1]; + + SetItemName(item, par1); + + item.Pos = params[2]; + item.MTime.dwLowDateTime = params[3]; + item.MTime.dwHighDateTime = params[4]; + + #ifdef NSIS_SCRIPT + + { + UInt32 overwrite = params[0] & 0x7; + if (overwrite != overwrite_State) + { + s += "SetOverwrite "; + ADD_TYPE_FROM_LIST(k_SetOverwrite_Modes, overwrite); + overwrite_State = overwrite; + AddLF(); + Tab(kkk < endCommentIndex); + } + } + + { + UInt32 nsisMB = params[0] >> 3; + if ((Int32)nsisMB != allowSkipFiles_State) + { + UInt32 mb = nsisMB & ((1 << 20) - 1); // old/new NSIS + UInt32 b1 = nsisMB >> 21; // NSIS 2.06+ + UInt32 b2 = nsisMB >> 20; // NSIS old + Int32 asf = (Int32)nsisMB; + if (mb == (MY__MB_ABORTRETRYIGNORE | MY__MB_ICONSTOP) && (b1 == MY__IDIGNORE || b2 == MY__IDIGNORE)) + asf = -1; + else if (mb == (MY__MB_RETRYCANCEL | MY__MB_ICONSTOP) && (b1 == MY__IDCANCEL || b2 == MY__IDCANCEL)) + asf = -2; + else + { + AddCommentAndString("AllowSkipFiles [Overwrite]: "); + MessageBox_MB_Part(mb); + if (b1 != 0) + { + s += " /SD"; + Add_ButtonID(b1); + } + } + if (asf != allowSkipFiles_State) + { + if (asf < 0) + { + s += "AllowSkipFiles "; + s += (asf == -1) ? "on" : "off"; + } + AddLF(); + Tab(kkk < endCommentIndex); + } + allowSkipFiles_State = (Int32)nsisMB; + } + } + + s += "File"; + AddParam(params[1]); + + /* params[5] contains link to LangString (negative value) + with NLF_FILE_ERROR or NLF_FILE_ERROR_NOIGNORE message for MessageBox. + We don't need to print it. */ + + #endif + + if (IsVarStr(par1, 10)) // is $R0 + { + // we parse InstallLib macro in 7-Zip installers + unsigned kBackOffset = 28; + if (kkk > 1) + { + // detect old version of InstallLib macro + if (Get32(p - 1 * kCmdSize) == EW_NOP) // goto command + kBackOffset -= 2; + } + + if (kkk > kBackOffset) + { + const Byte *p2 = p - kBackOffset * kCmdSize; + UInt32 cmd = Get32(p2); + if (cmd == EW_ASSIGNVAR) + { + UInt32 pars[6]; + for (int i = 0; i < 6; i++) + pars[i] = Get32(p2 + i * 4 + 4); + if (pars[0] == 10 + 4 && pars[2] == 0 && pars[3] == 0) // 10 + 4 means $R4 + { + ReadString2_Raw(pars[1]); + if (IsUnicode) + { + if (!Raw_UString.IsEmpty()) + item.NameU = Raw_UString; + } + else + { + if (!Raw_AString.IsEmpty()) + item.NameA = Raw_AString; + } + } + } + } + } + /* UInt32 allowIgnore = params[5]; */ + break; + } + + case EW_SETFILEATTRIBUTES: + { + if (kkk > 0 && Get32(p - kCmdSize) == EW_EXTRACTFILE) + { + if (params[0] == Get32(p - kCmdSize + 4 + 4 * 1)) // compare with PrevCmd.Params[1] + { + CItem &item = Items.Back(); + item.Attrib_Defined = true; + item.Attrib = params[1]; + } + } + #ifdef NSIS_SCRIPT + AddParam(params[0]); + Space(); + FlagsToString2(s, g_WinAttrib, ARRAY_SIZE(g_WinAttrib), params[1]); + #endif + break; + } + + case EW_WRITEUNINSTALLER: + { + /* NSIS 2.29+ writes alternative path to params[3] + "$INSTDIR\\" + Str(params[0]) + NSIS installer uses alternative path, if main path + from params[0] is not absolute path */ + + bool pathOk = (params[0] > 0) && IsGoodString(params[0]); + + if (!pathOk) + { + #ifdef NSIS_SCRIPT + AddError("bad path"); + #endif + break; + } + + bool altPathOk = true; + + UInt32 altParam = params[3]; + if (altParam != 0) + { + altPathOk = false; + UInt32 additional = 0; + if (GetVarIndexFinished(altParam, '\\', additional) == kVar_INSTDIR) + altPathOk = AreTwoParamStringsEqual(altParam + additional, params[0]); + } + + + #ifdef NSIS_SCRIPT + + AddParam(params[0]); + + SmallSpaceComment(); + + /* + for (int i = 1; i < 3; i++) + AddParam_UInt(params[i]); + */ + + if (params[3] != 0) + AddParam(params[3]); + + #endif + + if (!altPathOk) + { + #ifdef NSIS_SCRIPT + AddError("alt path error"); + #endif + } + + if (BadCmd >= 0 && BadCmd <= EW_WRITEUNINSTALLER) + { + /* We don't cases with incorrect installer commands. + Such bad installer item can break unpacking for other items. */ + #ifdef NSIS_SCRIPT + AddError("SKIP possible BadCmd"); + #endif + break; + } + + CItem &item = Items.AddNew();; + + SetItemName(item, params[0]); + + item.Pos = params[1]; + item.PatchSize = params[2]; + item.IsUninstaller = true; + + /* + // we can add second time to test the code + CItem item2 = item; + item2.NameU += L'2'; + item2.NameA += '2'; + Items.Add(item2); + */ + + break; + } + + #ifdef NSIS_SCRIPT + + case EW_RET: + { + // bool needComment = false; + if (onFuncIsOpen) + { + if (kkk == bh.Num - 1 || IsProbablyEndOfFunc(labels[kkk + 1])) + { + AddStringLF("FunctionEnd"); + + if ((int)kkk + 1 == InitPluginsDir_End) + CommentClose(); + AddLF(); + onFuncIsOpen = false; + // needComment = true; + break; + } + } + // if (!needComment) + if (IsSectionGroup) + break; + if (sectionIsOpen) + { + const CSection § = Sections[curSectionIndex]; + if (sect.StartCmdIndex + sect.NumCommands == kkk) + { + PrintSectionEnd(); + sectionIsOpen = false; + curSectionIndex++; + break; + } + + // needComment = true; + // break; + } + + /* + if (needComment) + s += " ;"; + */ + TabString("Return"); + AddLF(); + break; + } + + case EW_NOP: + { + if (params[0] == 0) + s += "Nop"; + else + { + s += "Goto"; + Add_GotoVar(params[0]); + } + break; + } + + case EW_ABORT: + { + AddOptionalParam(params[0]); + break; + } + + case EW_CALL: + { + if (kkk + 1 < bh.Num && GetCmd(Get32(p + kCmdSize)) == EW_EXTRACTFILE) + { + UInt32 par1 = GET_CMD_PARAM(p + kCmdSize, 1); + + UInt32 pluginPar = 0; + + if (GetVarIndexFinished(par1, '\\', pluginPar) == kVar_PLUGINSDIR) + { + pluginPar += par1; + UInt32 commandId2 = GetCmd(Get32(p + kCmdSize * 2)); + if (commandId2 == EW_SETFLAG || commandId2 == EW_UPDATETEXT) + { + UInt32 i; + for (i = kkk + 3; i < bh.Num; i++) + { + const Byte *pCmd = p + kCmdSize * (i - kkk); + UInt32 commandId3 = GetCmd(Get32(pCmd)); + if (commandId3 != EW_PUSHPOP + || GET_CMD_PARAM(pCmd, 1) != 0 + || GET_CMD_PARAM(pCmd, 2) != 0) + break; + } + if (i < bh.Num) + { + const Byte *pCmd = p + kCmdSize * (i - kkk); + + // UInt32 callDll_Param = GET_CMD_PARAM(pCmd, 0); + // UInt32 file_Param = GET_CMD_PARAM(p + kCmdSize, 1); + + if (GetCmd(Get32(pCmd)) == EW_REGISTERDLL && + AreTwoParamStringsEqual( + GET_CMD_PARAM(pCmd, 0), + GET_CMD_PARAM(p + kCmdSize, 1))) + { + // params[4] = 1 means GetModuleHandle attempt before default LoadLibraryEx; + /// new versions of NSIS use params[4] = 1 for Plugin command + if (GET_CMD_PARAM(pCmd, 2) == 0 + // && GET_CMD_PARAM(pCmd, 4) != 0 + ) + { + { + AString s2; + ReadString2(s2, pluginPar); + if (s2.Len() >= 4 && + StringsAreEqualNoCase_Ascii(s2.RightPtr(4), ".dll")) + s2.DeleteFrom(s2.Len() - 4); + s2 += "::"; + AString func; + ReadString2(func, GET_CMD_PARAM(pCmd, 1)); + s2 += func; + Add_QuStr(s2); + + if (GET_CMD_PARAM(pCmd, 3) == 1) + s += " /NOUNLOAD"; + + for (UInt32 j = i - 1; j >= kkk + 3; j--) + { + const Byte *pCmd = p - kCmdSize * (kkk - j); + AddParam(GET_CMD_PARAM(pCmd, 0)); + } + NewLine(); + Tab(true); + endCommentIndex = i + 1; + } + } + } + } + } + } + } + { + const Byte *nextCmd = p + kCmdSize; + UInt32 commandId2 = GetCmd(Get32(nextCmd)); + if (commandId2 == EW_SETFLAG + && GET_CMD_PARAM(nextCmd, 0) == k_ExecFlags_DetailsPrint + && GET_CMD_PARAM(nextCmd, 2) != 0) // is "lastused" + // || commandId2 == EW_UPDATETEXT) + { + if ((Int32)params[0] > 0 && labels[params[0] - 1] & CMD_REF_InitPluginDir) + { + s += "InitPluginsDir"; + AddLF(); + Tab(true); + endCommentIndex = kkk + 2; + } + } + } + + s += "Call "; + if ((Int32)params[0] < 0) + Add_Var(-((Int32)params[0] + 1)); + else if (params[0] == 0) + s += '0'; + else + { + UInt32 val = params[0] - 1; + if (params[1] == 1) // it's Call :Label + { + s += ':'; + Add_LabelName(val); + } + else // if (params[1] == 0) // it's Call Func + Add_FuncName(labels, val); + } + break; + } + + case EW_UPDATETEXT: + case EW_SLEEP: + { + AddParam(params[0]); + break; + } + + case EW_CHDETAILSVIEW: + { + if (params[0] == MY__SW_SHOWNA && params[1] == MY__SW_HIDE) s += " show"; + else if (params[1] == MY__SW_SHOWNA && params[0] == MY__SW_HIDE) s += " hide"; + else + for (int i = 0; i < 2; i++) + { + Space(); + Add_ShowWindow_Cmd(params[i]); + } + break; + } + + case EW_IFFILEEXISTS: + { + AddParam(params[0]); + Add_GotoVars2(¶ms[1]); + break; + } + + case EW_SETFLAG: + { + AString temp; + ReadString2(temp, params[1]); + if (params[0] == k_ExecFlags_Errors && params[2] == 0) + { + s += (temp.Len() == 1 && temp[0] == '0') ? "ClearErrors" : "SetErrors"; + break; + } + s += "Set"; + Add_ExecFlags(params[0]); + + if (params[2] != 0) + { + s += " lastused"; + break; + } + UInt32 v; + if (StringToUInt32(temp, v)) + { + const char *s2 = NULL; + switch (params[0]) + { + case k_ExecFlags_AutoClose: + case k_ExecFlags_RebootFlag: + if (v < 2) s2 = (v == 0) ? "false" : "true"; break; + case k_ExecFlags_ShellVarContext: + if (v < 2) s2 = (v == 0) ? "current" : "all"; break; + case k_ExecFlags_Silent: + if (v < 2) s2 = (v == 0) ? "normal" : "silent"; break; + case k_ExecFlags_RegView: + if (v == 0) s2 = "32"; + else if (v == 256) s2 = "64"; + break; + case k_ExecFlags_DetailsPrint: + if (v == 0) s2 = "both"; + else if (v == 2) s2 = "textonly"; + else if (v == 4) s2 = "listonly"; + else if (v == 6) s2 = "none"; + } + if (s2) + { + s += ' '; + s += s2; + break; + } + } + SpaceQuStr(temp); + break; + } + + case EW_IFFLAG: + { + Add_ExecFlags(params[2]); + Add_GotoVars2(¶ms[0]); + /* + static const unsigned kIfErrors = 2; + if (params[2] != kIfErrors && params[3] != 0xFFFFFFFF || + params[2] == kIfErrors && params[3] != 0) + { + s += " # FLAG &= "; + AddParam_UInt(params[3]); + } + */ + break; + } + + case EW_GETFLAG: + { + Add_ExecFlags(params[1]); + AddParam_Var(params[0]); + break; + } + + case EW_RENAME: + { + if (params[2] != 0) + s += k_REBOOTOK; + AddParams(params, 2); + if (params[3] != 0) + { + SmallSpaceComment(); + AddParam(params[3]); // rename comment for log file + } + break; + } + + case EW_GETFULLPATHNAME: + { + if (params[2] == 0) + s += " /SHORT"; + AddParam_Var(params[1]); + AddParam(params[0]); + break; + } + + case EW_SEARCHPATH: + case EW_STRLEN: + { + AddParam_Var(params[0]); + AddParam(params[1]); + break; + } + + case EW_GETTEMPFILENAME: + { + AddParam_Var(params[0]); + AString temp; + ReadString2(temp, params[1]); + if (temp != "$TEMP") + SpaceQuStr(temp); + break; + } + + case EW_DELETEFILE: + { + UInt32 flag = params[1]; + if ((flag & DEL_REBOOT) != 0) + s += k_REBOOTOK; + AddParam(params[0]); + break; + } + + case EW_MESSAGEBOX: + { + MessageBox_MB_Part(params[0]); + AddParam(params[1]); + { + UInt32 buttonID = (params[0] >> 21); // NSIS 2.06+ + if (buttonID != 0) + { + s += " /SD"; + Add_ButtonID(buttonID); + } } - Items.Add(item); - #ifdef NSIS_SCRIPT - Script += " "; + for (int i = 2; i < 6; i += 2) + if (params[i] != 0) + { + Add_ButtonID(params[i]); + Add_GotoVar1(params[i + 1]); + } + break; + } + + case EW_RMDIR: + { + UInt32 flag = params[1]; + if ((flag & DEL_RECURSE) != 0) + s += " /r"; + if ((flag & DEL_REBOOT) != 0) + s += k_REBOOTOK; + AddParam(params[0]); + break; + } + + case EW_STRCMP: + { + if (params[4] != 0) + s += 'S'; + AddParams(params, 2); + Add_GotoVars2(¶ms[2]); + break; + } + + case EW_READENVSTR: + { + s += (params[2] != 0) ? + "ReadEnvStr" : + "ExpandEnvStrings"; + AddParam_Var(params[0]); + AString temp; + ReadString2(temp, params[1]); + if (params[2] != 0 &&temp.Len() >= 2 && temp[0] == '%' && temp.Back() == '%') + { + temp.DeleteBack(); + temp.Delete(0); + } + SpaceQuStr(temp); + break; + } + + case EW_INTCMP: + { + if (params[5] != 0) + s += 'U'; + AddParams(params, 2); + Add_GotoVar1(params[2]); + if (params[3] != 0 || params[4] != 0) + Add_GotoVars2(params + 3); + break; + } + + case EW_INTOP: + { + AddParam_Var(params[0]); + const char *kOps = "+-*/|&^!|&%<>"; // NSIS 2.01+ + // "+-*/|&^!|&%"; // NSIS 2.0b4+ + // "+-*/|&^~!|&%"; // NSIS old + UInt32 opIndex = params[3]; + char c = (opIndex < 13) ? kOps[opIndex] : '?'; + char c2 = (opIndex < 8 || opIndex == 10) ? (char)0 : c; + int numOps = (opIndex == 7) ? 1 : 2; + AddParam(params[1]); + if (numOps == 2 && c == '^' && IsDirectString_Equal(params[2], "0xFFFFFFFF")) + s += " ~ ;"; + Space(); + s += c; + if (numOps != 1) + { + if (c2 != 0) + s += c2; + AddParam(params[2]); + } + break; + } + + case EW_INTFMT: + { + AddParam_Var(params[0]); + AddParams(params + 1, 2); + break; + } - if (IsUnicode) - Script += UnicodeStringToMultiByte(item.NameU); + case EW_PUSHPOP: + { + if (params[2] != 0) + { + s += "Exch"; + if (params[2] != 1) + AddParam_UInt(params[2]); + } + else if (params[1] != 0) + { + s += "Pop"; + AddParam_Var(params[0]); + } else - Script += item.NameA; - #endif + { + if (NoLabels(labels + kkk + 1, 2) + && Get32(p + kCmdSize) == EW_PUSHPOP // Exch" + && GET_CMD_PARAM(p + kCmdSize, 2) == 1 + && Get32(p + kCmdSize * 2) == EW_PUSHPOP // Pop $VAR + && GET_CMD_PARAM(p + kCmdSize * 2, 1) != 0) + { + if (IsVarStr(params[0], GET_CMD_PARAM(p + kCmdSize * 2, 0))) + { + s += "Exch"; + AddParam(params[0]); + NewLine(); + Tab(true); + endCommentIndex = kkk + 3; + } + } + s += "Push"; + AddParam(params[0]); + } break; } + case EW_FINDWINDOW: + { + AddParam_Var(params[0]); + AddParam(params[1]); + AddOptionalParams(params + 2, 3); + break; + } - #ifdef NSIS_SCRIPT - case EW_UPDATETEXT: + case EW_SENDMESSAGE: + { + // SendMessage: 6 [output, hwnd, msg, wparam, lparam, [wparamstring?1:0 | lparamstring?2:0 | timeout<<2] + AddParam(params[1]); + + const char *w = NULL; + AString t; + ReadString2(t, params[2]); + UInt32 wm; + if (StringToUInt32(t, wm)) + { + switch (wm) + { + case 0x0C: w = "SETTEXT"; break; + case 0x10: w = "CLOSE"; break; + case 0x30: w = "SETFONT"; break; + } + } + if (w) + { + s += " ${WM_"; + s += w; + s += '}'; + } + else + SpaceQuStr(t); + + UInt32 spec = params[5]; + for (unsigned i = 0; i < 2; i++) + { + AString s2; + if (spec & ((UInt32)1 << i)) + s2 += "STR:"; + ReadString2(s2, params[3 + i]); + SpaceQuStr(s2); + } + + if ((Int32)params[0] >= 0) + AddParam_Var(params[0]); + + spec >>= 2; + if (spec != 0) + { + s += " /TIMEOUT="; + Add_UInt(spec); + } + break; + } + + case EW_ISWINDOW: + { + AddParam(params[0]); + Add_GotoVars2(¶ms[1]); + break; + } + + case EW_GETDLGITEM: + { + AddParam_Var(params[0]); + AddParams(params + 1, 2); + break; + } + + case EW_SETCTLCOLORS: + { + AddParam(params[0]); + + UInt32 offset = params[1]; + + if (_size < bhCtlColors.Offset + || _size - bhCtlColors.Offset < offset + || _size - bhCtlColors.Offset - offset < k_CtlColors_Size) + { + AddError("bad offset"); + break; + } + + const Byte *p2 = _data + bhCtlColors.Offset + offset; + CNsis_CtlColors colors; + colors.Parse(p2); + + if ((colors.flags & kColorsFlags_BK_SYS) != 0 || + (colors.flags & kColorsFlags_TEXT_SYS) != 0) + s += " /BRANDING"; + + AString bk; + bool bkc = false; + if (colors.bkmode == MY__TRANSPARENT) + bk += " transparent"; + else if (colors.flags & kColorsFlags_BKB) + { + if ((colors.flags & kColorsFlags_BK_SYS) == 0 && + (colors.flags & kColorsFlags_BK) != 0) + bkc = true; + } + if ((colors.flags & kColorsFlags_TEXT) != 0 || !bk.IsEmpty() || bkc) + { + Space(); + if ((colors.flags & kColorsFlags_TEXT_SYS) != 0 || (colors.flags & kColorsFlags_TEXT) == 0) + AddQuotes(); + else + Add_Color(colors.text); + } + s += bk; + if (bkc) + { + Space(); + Add_Color(colors.bkc); + } + + break; + } + + case EW_SETBRANDINGIMAGE: + { + s += " /IMGID="; + Add_UInt(params[1]); + if (params[2] == 1) + s += " /RESIZETOFIT"; + AddParam(params[0]); + break; + } + + case EW_CREATEFONT: + { + AddParam_Var(params[0]); + AddParam(params[1]); + AddOptionalParams(params + 2, 2); + if (params[4] & 1) s += " /ITALIC"; + if (params[4] & 2) s += " /UNDERLINE"; + if (params[4] & 4) s += " /STRIKE"; + break; + } + + case EW_SHOWWINDOW: + { + AString hw, sw; + ReadString2(hw, params[0]); + ReadString2(sw, params[1]); + if (params[3] != 0) + s += "EnableWindow"; + else + { + UInt32 val; + bool valDefined = false; + if (StringToUInt32(sw, val)) + { + if (val < ARRAY_SIZE(kShowWindow_Commands)) + { + sw.Empty(); + sw += "${"; + Add_ShowWindow_Cmd_2(sw, val); + sw += '}'; + valDefined = true; + } + } + bool isHwndParent = IsVarStr(params[0], IsNsis225 ? kVar_HWNDPARENT_225 : kVar_HWNDPARENT); + if (params[2] != 0) + { + if (valDefined && val == 0 && isHwndParent) + { + s += "HideWindow"; + break; + } + } + if (valDefined && val == 5 && isHwndParent && + kkk + 1 < bh.Num && GetCmd(Get32(p + kCmdSize)) == EW_BRINGTOFRONT) + { + s += " ; "; + } + s += "ShowWindow"; + } + SpaceQuStr(hw); + SpaceQuStr(sw); + break; + } + + case EW_SHELLEXEC: + { + AddParams(params, 2); + if (params[2] != 0 || params[3] != MY__SW_SHOWNORMAL) + { + AddParam(params[2]); + if (params[3] != MY__SW_SHOWNORMAL) + { + Space(); + Add_ShowWindow_Cmd(params[3]); + } + } + if (params[5] != 0) + { + s += " ;"; + AddParam(params[5]); // it's tatus text update + } + break; + } + + case EW_EXECUTE: + { + if (params[2] != 0) + s += "Wait"; + AddParam(params[0]); + if (params[2] != 0) + if ((Int32)params[1] >= 0) + AddParam_Var(params[1]); + break; + } + + case EW_GETFILETIME: + case EW_GETDLLVERSION: + { + AddParam(params[2]); + AddParam_Var(params[0]); + AddParam_Var(params[1]); + break; + } + + case EW_REGISTERDLL: + { + AString func; + ReadString2(func, params[1]); + bool printFunc = true; + // params[4] = 1; for plugin command + if (params[2] == 0) + { + s += "CallInstDLL"; + AddParam(params[0]); + if (params[3] == 1) + s += " /NOUNLOAD"; + } + else + { + if (func == "DllUnregisterServer") + { + s += "UnRegDLL"; + printFunc = false; + } + else + { + s += "RegDLL"; + if (func == "DllRegisterServer") + printFunc = false; + } + AddParam(params[0]); + } + if (printFunc) + SpaceQuStr(func); + break; + } + + case EW_CREATESHORTCUT: + { + unsigned numParams; + for (numParams = 6; numParams > 2; numParams--) + if (params[numParams - 1] != 0) + break; + + UInt32 spec = params[4]; + if (spec & 0x8000) // NSIS 3.0b0 + s += " /NoWorkingDir"; + + AddParams(params, numParams > 4 ? 4 : numParams); + if (numParams <= 4) + break; + + UInt32 icon = (spec & 0xFF); + Space(); + if (icon != 0) + Add_UInt(icon); + else + AddQuotes(); + + if ((spec >> 8) == 0 && numParams < 6) + break; + UInt32 sw = (spec >> 8) & 0x7F; + Space(); + // NSIS encoder replaces these names: + if (sw == MY__SW_SHOWMINNOACTIVE) + sw = MY__SW_SHOWMINIMIZED; + if (sw == 0) + AddQuotes(); + else + Add_ShowWindow_Cmd(sw); + + UInt32 modKey = spec >> 24; + UInt32 key = (spec >> 16) & 0xFF; + + if (modKey == 0 && key == 0) + { + if (numParams < 6) + break; + Space(); + AddQuotes(); + } + else + { + Space(); + if (modKey & 1) s += "SHIFT|"; // HOTKEYF_SHIFT + if (modKey & 2) s += "CONTROL|"; + if (modKey & 4) s += "ALT|"; + if (modKey & 8) s += "EXT|"; + + static const unsigned kMy_VK_F1 = 0x70; + if (key >= kMy_VK_F1 && key <= kMy_VK_F1 + 23) + { + s += 'F'; + Add_UInt(key - kMy_VK_F1 + 1); + } + else if (key >= 'A' && key <= 'Z' || key >= '0' && key <= '9') + s += (char)key; + else + { + s += "Char_"; + Add_UInt(key); + } + } + AddOptionalParam(params[5]); // description + break; + } + + case EW_COPYFILES: + { + if (params[2] & 0x04) s += " /SILENT"; // FOF_SILENT + if (params[2] & 0x80) s += " /FILESONLY"; // FOF_FILESONLY + AddParams(params, 2); + if (params[3] != 0) + { + s += " ;"; + AddParam(params[3]); // status text update + } + break; + } + + case EW_REBOOT: + { + if (params[0] != 0xbadf00d) + s += " ; Corrupted ???"; + else if (kkk + 1 < bh.Num && GetCmd(Get32(p + kCmdSize)) == EW_QUIT) + endCommentIndex = kkk + 2; + break; + } + + case EW_WRITEINI: + { + unsigned numAlwaysParams = 0; + if (params[0] == 0) // Section + s += "FlushINI"; + else if (params[4] != 0) + { + s += "WriteINIStr"; + numAlwaysParams = 3; + } + else + { + s += "DeleteINI"; + s += (params[1] == 0) ? "Sec" : "Str"; + numAlwaysParams = 1; + } + AddParam(params[3]); // filename + // Section, EntryName, Value + AddParams(params, numAlwaysParams); + AddOptionalParams(params + numAlwaysParams, 3 - numAlwaysParams); + break; + } + + case EW_READINISTR: + { + AddParam_Var(params[0]); + AddParam(params[3]); // FileName + AddParams(params +1, 2); // Section, EntryName + break; + } + + case EW_DELREG: + { + // NSIS 2.00 used another scheme! + + if (params[4] == 0) + s += "Value"; + else + { + s += "Key"; + if (params[4] & 2) + s += " /ifempty"; + } + AddRegRoot(params[1]); + AddParam(params[2]); + AddOptionalParam(params[3]); + break; + } + + case EW_WRITEREG: + { + const char *s2 = 0; + switch (params[4]) + { + case 1: s2 = "Str"; break; + case 2: s2 = "ExpandStr"; break; // maybe unused + case 3: s2 = "Bin"; break; + case 4: s2 = "DWORD"; break; + default: + s += '?'; + Add_UInt(params[4]); + } + if (params[4] == 1 && params[5] == 2) + s2 = "ExpandStr"; + if (s2) + s += s2; + AddRegRoot(params[0]); + AddParams(params + 1, 2); // keyName, valueName + if (params[4] != 3) + AddParam(params[3]); // value + else + { + // Binary data. + Space(); + UInt32 offset = params[3]; + bool isSupported = false; + if (AfterHeaderSize >= 4 + && bhData.Offset <= AfterHeaderSize - 4 + && offset <= AfterHeaderSize - 4 - bhData.Offset) + { + // we support it for solid archives. + const Byte *p2 = _afterHeader + bhData.Offset + offset; + UInt32 size = Get32(p2); + if (size <= AfterHeaderSize - 4 - bhData.Offset - offset) + { + for (UInt32 i = 0; i < size; i++) + { + Byte b = (p2 + 4)[i]; + unsigned t; + t = (b >> 4); s += (char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))); + t = (b & 15); s += (char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))); + } + isSupported = true; + } + } + if (!isSupported) + { + // we must read from file here; + s += "data["; + Add_UInt(offset); + s += " ... ]"; + s += " ; !!! Unsupported"; + } + } + break; + } + + case EW_READREGSTR: + { + s += (params[4] == 1) ? "DWORD" : "Str"; + AddParam_Var(params[0]); + AddRegRoot(params[1]); + AddParams(params + 2, 2); + break; + } + + case EW_REGENUM: { - Script += " "; - Script += ReadString2(e.Params[0]); - Script += " "; - Script += UIntToString(e.Params[1]); + s += (params[4] != 0) ? "Key" : "Value"; + AddParam_Var(params[0]); + AddRegRoot(params[1]); + AddParams(params + 2, 2); + break; + } + + case EW_FCLOSE: + case EW_FINDCLOSE: + { + AddParam_Var(params[0]); + break; + } + + case EW_FOPEN: + { + AddParam_Var(params[0]); + AddParam(params[3]); + UInt32 acc = params[1]; // dwDesiredAccess + UInt32 creat = params[2]; // dwCreationDisposition + if (acc == 0 && creat == 0) + break; + char cc = 0; + if (acc == MY__GENERIC_READ && creat == OPEN_EXISTING) + cc = 'r'; + else if (creat == CREATE_ALWAYS && acc == MY__GENERIC_WRITE) + cc = 'w'; + else if (creat == OPEN_ALWAYS && (acc == (MY__GENERIC_WRITE | MY__GENERIC_READ))) + cc = 'a'; + // cc = 0; + if (cc != 0) + { + Space(); + s += cc; + break; + } + + if (acc & MY__GENERIC_READ) s += " GENERIC_READ"; + if (acc & MY__GENERIC_WRITE) s += " GENERIC_WRITE"; + if (acc & MY__GENERIC_EXECUTE) s += " GENERIC_EXECUTE"; + if (acc & MY__GENERIC_ALL) s += " GENERIC_ALL"; + + const char *s2 = NULL; + switch (creat) + { + case MY__CREATE_NEW: s2 = "CREATE_NEW"; break; + case MY__CREATE_ALWAYS: s2 = "CREATE_ALWAYS"; break; + case MY__OPEN_EXISTING: s2 = "OPEN_EXISTING"; break; + case MY__OPEN_ALWAYS: s2 = "OPEN_ALWAYS"; break; + case MY__TRUNCATE_EXISTING: s2 = "TRUNCATE_EXISTING"; break; + } + Space(); + if (s2) + s += s2; + else + Add_UInt(creat); break; } - case EW_SETFILEATTRIBUTES: + + case EW_FPUTS: + case EW_FPUTWS: { - Script += " "; - Script += ReadString2(e.Params[0]); - Script += " "; - Script += UIntToString(e.Params[1]); + if (commandId == EW_FPUTWS) + s += (params[2] == 0) ? "UTF16LE" : "Word"; + else if (params[2] != 0) + s += "Byte"; + AddParam_Var(params[0]); + AddParam(params[1]); break; } - case EW_IFFILEEXISTS: + + case EW_FGETS: + case EW_FGETWS: { - Script += " "; - Script += ReadString2(e.Params[0]); - Script += " "; - Script += UIntToString(e.Params[1]); - Script += " "; - Script += UIntToString(e.Params[2]); + if (commandId == EW_FPUTWS) + s += (params[3] == 0) ? "UTF16LE" : "Word"; + if (params[3] != 0) + s += "Byte"; + AddParam_Var(params[0]); + AddParam_Var(params[1]); + AString maxLenStr; + ReadString2(maxLenStr, params[2]); + UInt32 maxLen; + if (StringToUInt32(maxLenStr, maxLen)) + { + if (maxLen == 1 && params[3] != 0) + break; + if (maxLen == 1023 && params[3] == 0) // NSIS_MAX_STRLEN - 1; can be other value!! + break; + } + SpaceQuStr(maxLenStr); break; } - case EW_RENAME: + + case EW_FSEEK: { - Script += " "; - Script += ReadString2(e.Params[0]); - Script += " "; - Script += ReadString2(e.Params[1]); - Script += " "; - Script += UIntToString(e.Params[2]); + AddParam_Var(params[0]); + AddParam(params[2]); + if (params[3] == 1) s += " CUR"; // FILE_CURRENT + if (params[3] == 2) s += " END"; // FILE_END + if ((Int32)params[1] >= 0) + { + if (params[3] == 0) s += " SET"; // FILE_BEGIN + AddParam_Var(params[1]); + } break; } - case EW_GETFULLPATHNAME: + + case EW_FINDNEXT: { - Script += " "; - Script += ReadString2(e.Params[0]); - Script += " "; - Script += ReadString2(e.Params[1]); - Script += " "; - Script += UIntToString(e.Params[2]); + AddParam_Var(params[1]); + AddParam_Var(params[0]); break; } - case EW_SEARCHPATH: + + case EW_FINDFIRST: { - Script += " "; - Script += ReadString2(e.Params[0]); - Script += " "; - Script += ReadString2(e.Params[1]); + AddParam_Var(params[1]); + AddParam_Var(params[0]); + AddParam(params[2]); break; } - case EW_GETTEMPFILENAME: + + case EW_LOG: { - AString s; - Script += " "; - Script += ReadString2(e.Params[0]); - Script += " "; - Script += ReadString2(e.Params[1]); - break; + if (params[0] != 0) + { + s += "Set "; + s += (params[1] == 0) ? "off" : "on"; + } + else + { + s += "Text"; + AddParam(params[1]); + } } - case EW_DELETEFILE: + case EW_SECTIONSET: { - UInt64 flag = e.Params[1]; - if (flag != 0) + if ((Int32)params[2] >= 0) { - Script += " "; - if (flag == DEL_REBOOT) - Script += "/REBOOTOK"; - else - Script += UIntToString(e.Params[1]); + s += "Get"; + Add_SectOp(params[2]); + AddParam(params[0]); + AddParam_Var(params[1]); + } + else + { + s += "Set"; + UInt32 t = -(Int32)params[2] - 1; + Add_SectOp(t); + AddParam(params[0]); + AddParam(params[t == 0 ? 4 : 1]); + + // params[3] != 0 means call SectionFlagsChanged in installer + // used by SECTIONSETFLAGS command } - Script += " "; - Script += ReadString2(e.Params[0]); break; } - case EW_RMDIR: + + case EW_INSTTYPESET: { - UInt64 flag = e.Params[1]; - if (flag != 0) + int numQwParams = 0; + const char *s2; + if (params[3] == 0) + { + if (params[2] == 0) + { + s2 = "InstTypeGetText"; + numQwParams = 1; + } + else + { + s2 = "InstTypeSetText"; + numQwParams = 2; + } + } + else { - if ((flag & DEL_REBOOT) != 0) - Script += " /REBOOTOK"; - if ((flag & DEL_RECURSE) != 0) - Script += " /r"; + if (params[2] == 0) + s2 = "GetCurInstType"; + else + { + s2 = "SetCurInstType"; + numQwParams = 1; + } } - Script += " "; - Script += ReadString2(e.Params[0]); + s += s2; + AddParams(params, numQwParams); + if (params[2] == 0) + AddParam_Var(params[1]); break; } - case EW_STRLEN: + + case EW_LOCKWINDOW: { - Script += " "; - Script += GetVar(e.Params[0]);; - Script += " "; - Script += ReadString2Qw(e.Params[1]); + s += (params[0] == 0) ? " on" : " off"; break; } - case EW_ASSIGNVAR: + + case EW_FINDPROC: { - 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; - } - } + AddParam_Var(params[0]); + AddParam(params[1]); break; } - case EW_STRCMP: + + default: { - Script += " "; + numSkipParams = 0; + } + #endif + } + + #ifdef NSIS_SCRIPT - Script += " "; - Script += ReadString2Qw(e.Params[0]); - - Script += " "; - Script += ReadString2Qw(e.Params[1]); + unsigned numParams = kNumCommandParams; - for (int j = 2; j < 5; j++) - { - Script += " "; - Script += UIntToString(e.Params[j]); - } + for (; numParams > 0; numParams--) + if (params[numParams - 1] != 0) break; + + if (numParams > numSkipParams) + { + s += " ; !!!! Unknown Params: "; + unsigned i; + for (i = 0; i < numParams; i++) + AddParam(params[i]); + + s += " ;"; + + for (i = 0; i < numParams; i++) + { + Space(); + UInt32 v = params[i]; + if (v > 0xFFF00000) + Add_SignedInt(s, (Int32)v); + else + Add_UInt(v); } - case EW_INTCMP: + } + + NewLine(); + + #endif + } + + #ifdef NSIS_SCRIPT + + if (sectionIsOpen) + { + if (curSectionIndex < bhSections.Num) + { + const CSection § = Sections[curSectionIndex]; + if (sect.StartCmdIndex + sect.NumCommands + 1 == kkk) { - if (e.Params[5] != 0) - Script += "U"; + PrintSectionEnd(); + sectionIsOpen = false; + // lastSectionEndCmd = kkk; + curSectionIndex++; + } + } + } + + while (curSectionIndex < bhSections.Num) + { + const CSection § = Sections[curSectionIndex]; + if (sectionIsOpen) + { + if (sect.StartCmdIndex + sect.NumCommands != kkk) + AddErrorLF("SECTION ERROR"); + PrintSectionEnd(); + sectionIsOpen = false; + curSectionIndex++; + } + else + { + if (curSectionIndex == 49) + curSectionIndex = curSectionIndex; + + if (PrintSectionBegin(sect, curSectionIndex)) + curSectionIndex++; + else + sectionIsOpen = true; + } + } + + #endif + + return S_OK; +} + +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)); + const CInArchive *inArchive = (const CInArchive *)param; + if (inArchive->IsUnicode) + { + if (i1.Prefix != i2.Prefix) + { + if (i1.Prefix < 0) return -1; + if (i2.Prefix < 0) return 1; + RINOZ(wcscmp( + inArchive->UPrefixes[i1.Prefix], + inArchive->UPrefixes[i2.Prefix])); + } + RINOZ(wcscmp(i1.NameU, i2.NameU)); + } + else + { + if (i1.Prefix != i2.Prefix) + { + if (i1.Prefix < 0) return -1; + if (i2.Prefix < 0) return 1; + RINOZ(strcmp( + inArchive->APrefixes[i1.Prefix], + inArchive->APrefixes[i2.Prefix])); + } + RINOZ(strcmp(i1.NameA, i2.NameA)); + } + return 0; +} - Script += " "; - Script += ReadString2(e.Params[0]); - Script += " "; - Script += ReadString2(e.Params[1]); +HRESULT CInArchive::SortItems() +{ + { + Items.Sort(CompareItems, (void *)this); + unsigned i; + + for (i = 0; i + 1 < Items.Size(); i++) + { + const CItem &i1 = Items[i]; + const CItem &i2 = Items[i + 1]; + if (i1.Pos != i2.Pos) + continue; - for (int i = 2; i < 5; i++) + if (IsUnicode) + { + if (i1.NameU != i2.NameU) continue; + if (i1.Prefix != i2.Prefix) { - Script += " "; - Script += UIntToString(e.Params[i]); + if (i1.Prefix < 0 || i2.Prefix < 0) continue; + if (UPrefixes[i1.Prefix] != UPrefixes[i2.Prefix]) continue; } - break; } - case EW_INTOP: + else { - 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 + if (i1.NameA != i2.NameA) continue; + if (i1.Prefix != i2.Prefix) { - Script += p1; - Script += " "; - Script += op; - Script += " "; - Script += ReadString2(e.Params[2]); + if (i1.Prefix < 0 || i2.Prefix < 0) continue; + if (APrefixes[i1.Prefix] != APrefixes[i2.Prefix]) continue; } - break; } - - case EW_PUSHPOP: + Items.Delete(i + 1); + i--; + } + + for (i = 0; i < Items.Size(); i++) + { + CItem &item = Items[i]; + UInt32 curPos = item.Pos + 4; + for (unsigned nextIndex = i + 1; nextIndex < Items.Size(); nextIndex++) { - int isPop = (e.Params[1] != 0); - if (isPop) + UInt32 nextPos = Items[nextIndex].Pos; + if (curPos <= nextPos) { - Script += "Pop"; - Script += " "; - Script += GetVar(e.Params[0]);; + item.EstimatedSize_Defined = true; + item.EstimatedSize = nextPos - curPos; + break; } - else + } + } + + 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 + 1 + 4; // size,[flag],prop,dict + BYTE sig[kSigSize]; + size_t processedSize = kSigSize; + RINOK(ReadStream(_stream, sig, &processedSize)); + if (processedSize < 4) + return S_FALSE; + UInt32 size = Get32(sig); + if ((size & kMask_IsCompressed) != 0) { - int isExch = (e.Params[2] != 0); - if (isExch) - { - Script += "Exch"; - } - else + item.IsCompressed = true; + size &= ~kMask_IsCompressed; + if (Method == NMethodType::kLZMA) { - Script += "Push"; - Script += " "; - Script += ReadString2(e.Params[0]); + if (processedSize < 9) + return S_FALSE; + /* + if (FilterFlag) + item.UseFilter = (sig[4] != 0); + */ + item.DictionarySize = Get32(sig + 4 + 1 + (FilterFlag ? 1 : 0)); } } - break; + else + { + item.IsCompressed = false; + item.Size = size; + item.Size_Defined = true; + } + item.CompressedSize = size; + item.CompressedSize_Defined = true; } + } + } + return S_OK; +} - 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]); +// Flags for common_header.flags +#define CH_FLAGS_DETAILS_SHOWDETAILS 1 +#define CH_FLAGS_DETAILS_NEVERSHOW 2 +#define CH_FLAGS_PROGRESS_COLORED 4 +#define CH_FLAGS_SILENT 8 +#define CH_FLAGS_SILENT_LOG 16 +#define CH_FLAGS_AUTO_CLOSE 32 +#define CH_FLAGS_DIR_NO_SHOW 64 // unused now +#define CH_FLAGS_NO_ROOT_DIR 128 +#define CH_FLAGS_COMP_ONLY_ON_CUSTOM 256 +#define CH_FLAGS_NO_CUSTOM 512 + +static const char *k_PostStrings[] = +{ + "install_directory_auto_append" + , "uninstchild" // NSIS 2.25+, used by uninstaller: + , "uninstcmd" // NSIS 2.25+, used by uninstaller: + , "wininit" // NSIS 2.25+, used by move file on reboot +}; + +HRESULT CInArchive::Parse() +{ + // UInt32 offset = ReadUInt32(); + // ???? offset == FirstHeader.HeaderSize + const Byte *p = _data; + + CBlockHeader bhEntries, bhStrings, bhLangTables; + bhEntries.Parse(p + 4 + 8 * 2); + bhStrings.Parse(p + 4 + 8 * 3); + bhLangTables.Parse(p + 4 + 8 * 4); + + #ifdef NSIS_SCRIPT + + CBlockHeader bhFont; + bhPages.Parse(p + 4 + 8 * 0); + bhSections.Parse(p + 4 + 8 * 1); + bhCtlColors.Parse(p + 4 + 8 * 5); + bhFont.Parse(p + 4 + 8 * 6); + bhData.Parse(p + 4 + 8 * 7); + + #endif + + _stringsPos = bhStrings.Offset; + if (_stringsPos > _size) + return S_FALSE; + { + if (bhLangTables.Offset < bhStrings.Offset) + return S_FALSE; + UInt32 stringTableSize = bhLangTables.Offset - bhStrings.Offset; + if (stringTableSize < 2) + return S_FALSE; + const Byte *strData = _data + _stringsPos; + if (strData[stringTableSize - 1] != 0) + return S_FALSE; + IsUnicode = (Get16(strData) == 0); + NumStringChars = stringTableSize; + if (IsUnicode) + { + if ((stringTableSize & 1) != 0) + return S_FALSE; + NumStringChars >>= 1; + if (strData[stringTableSize - 2] != 0) + return S_FALSE; + } + + } + + if (bhEntries.Num > (1 << 25)) + return S_FALSE; + if (bhEntries.Offset > _size) + return S_FALSE; + if (bhEntries.Num * kCmdSize > _size - bhEntries.Offset) + return S_FALSE; + + DetectNsisType(bhEntries, _data + bhEntries.Offset); + + #ifdef NSIS_SCRIPT + + { + AddCommentAndString("NSIS script"); + if (IsUnicode) + Script += " (UTF-8)"; + Space(); + Script += GetFormatDescription(); + AddLF(); + } + { + AddCommentAndString(IsInstaller ? "Install" : "Uninstall"); + AddLF(); + } + + AddLF(); + if (IsUnicode) + AddStringLF("Unicode true"); + + if (Method != NMethodType::kCopy) + { + const char *m = NULL; + switch (Method) + { + case NMethodType::kDeflate: m = "zlib"; break; + case NMethodType::kBZip2: m = "bzip2"; break; + case NMethodType::kLZMA: m = "lzma"; break; + } + Script += "SetCompressor"; + if (IsSolid) + Script += " /SOLID"; + if (m) + { + Space(); + Script += m; + } + AddLF(); + } + if (Method == NMethodType::kLZMA) + { + // if (DictionarySize != (8 << 20)) + { + Script += "SetCompressorDictSize"; + AddParam_UInt(DictionarySize >> 20); + AddLF(); + } + } + + Separator(); + PrintNumComment("HEADER SIZE", FirstHeader.HeaderSize); + // if (bhPages.Offset != 300 && bhPages.Offset != 288) + if (bhPages.Offset != 0) + { + PrintNumComment("START HEADER SIZE", bhPages.Offset); + } + + if (bhSections.Num > 0) + { + if (bhEntries.Offset < bhSections.Offset) + return S_FALSE; + SectionSize = (bhEntries.Offset - bhSections.Offset) / bhSections.Num; + if (bhSections.Offset + bhSections.Num * SectionSize != bhEntries.Offset) + return S_FALSE; + if (SectionSize < kSectionSize_base) + return S_FALSE; + UInt32 maxStringLen = SectionSize - kSectionSize_base; + if (IsUnicode) + { + if ((maxStringLen & 1) != 0) + return S_FALSE; + maxStringLen >>= 1; + } + // if (maxStringLen != 1024) + { + if (maxStringLen == 0) + PrintNumComment("SECTION SIZE", SectionSize); + else + PrintNumComment("MAX STRING LENGTH", maxStringLen); + } + } + + PrintNumComment("STRING CHARS", NumStringChars); + // PrintNumComment("LANG TABLE SIZE", bhCtlColors.Offset - bhLangTables.Offset); + + if (bhCtlColors.Offset > _size) + AddErrorLF("Bad COLORS TABLE"); + // PrintNumComment("COLORS TABLE SIZE", bhFont.Offset - bhCtlColors.Offset); + if (bhCtlColors.Num != 0) + PrintNumComment("COLORS Num", bhCtlColors.Num); + + // bhData uses offset in _afterHeader (not in _data) + // PrintNumComment("FONT TABLE SIZE", bhData.Offset - bhFont.Offset); + if (bhFont.Num != 0) + PrintNumComment("FONTS Num", bhFont.Num); + + // PrintNumComment("DATA SIZE", FirstHeader.HeaderSize - bhData.Offset); + if (bhData.Num != 0) + PrintNumComment("DATA NUM", bhData.Num); + + AddLF(); + + AddStringLF("OutFile [NSIS].exe"); + AddStringLF("!include WinMessages.nsh"); + + AddLF(); + + strUsed.Alloc(NumStringChars); + memset(strUsed, 0, NumStringChars); + + { + UInt32 ehFlags = Get32(p); + UInt32 showDetails = ehFlags & 3;// CH_FLAGS_DETAILS_SHOWDETAILS & CH_FLAGS_DETAILS_NEVERSHOW; + if (showDetails >= 1 && showDetails <= 2) + { + Script += IsInstaller ? "ShowInstDetails" : "ShowUninstDetails"; + Script += (showDetails == 1) ? " show" : " nevershow"; + AddLF(); + } + if (ehFlags & CH_FLAGS_PROGRESS_COLORED) AddStringLF("InstProgressFlags colored" ); + if ((ehFlags & (CH_FLAGS_SILENT | CH_FLAGS_SILENT_LOG)) != 0) + { + Script += IsInstaller ? "SilentInstall " : "SilentUnInstall "; + Script += (ehFlags & CH_FLAGS_SILENT_LOG) ? "silentlog" : "silent"; + AddLF(); + } + if (ehFlags & CH_FLAGS_AUTO_CLOSE) AddStringLF("AutoCloseWindow true"); + if ((ehFlags & CH_FLAGS_NO_ROOT_DIR) == 0) AddStringLF("AllowRootDirInstall true"); + if (ehFlags & CH_FLAGS_NO_CUSTOM) AddStringLF("InstType /NOCUSTOM"); + if (ehFlags & CH_FLAGS_COMP_ONLY_ON_CUSTOM) AddStringLF("InstType /COMPONENTSONLYONCUSTOM"); + } + + // Separator(); + // AddLF(); + + Int32 licenseLangIndex = -1; + { + const Byte *pp = _data + bhPages.Offset; + + for (UInt32 pageIndex = 0; pageIndex < bhPages.Num; pageIndex++, pp += kPageSize) + { + UInt32 wndProcID = Get32(pp + 4); + UInt32 param1 = Get32(pp + 44 + 4 * 1); + if (wndProcID != PWP_LICENSE || param1 == 0) + continue; + if ((Int32)param1 < 0) + licenseLangIndex = - ((Int32)param1 + 1); + else + noParseStringIndexes.AddToUniqueSorted(param1); + } + } - if ((Int32)e.Params[0] >= 0) - { - Script += " "; - Script += GetVar(e.Params[1]); - } + unsigned paramsOffset = 4 + 8 * 8; + if (bhPages.Offset == 276) + paramsOffset -= 8; - spec >>= 2; - if (spec != 0) - { - Script += " /TIMEOUT="; - Script += IntToString(spec); - } - break; - } + const Byte *p2 = p + paramsOffset; - case EW_GETDLGITEM: - { - Script += " "; - Script += GetVar(e.Params[0]);; - Script += " "; - Script += ReadString2(e.Params[1]); - Script += " "; - Script += ReadString2(e.Params[2]); - break; - } + { + UInt32 rootKey = Get32(p2); // (rootKey = -1) in uninstaller by default (the bug in NSIS) + UInt32 subKey = Get32(p2 + 4); + UInt32 value = Get32(p2 + 8); + if ((rootKey != 0 && rootKey != (UInt32)(Int32)-1) || subKey != 0 || value != 0) + { + Script += "InstallDirRegKey"; + AddRegRoot(rootKey); + AddParam(subKey); + AddParam(value); + NewLine(); + } + } - case EW_REGISTERDLL: + { + UInt32 bg_color1 = Get32(p2 + 12); + UInt32 bg_color2 = Get32(p2 + 16); + UInt32 bg_textcolor = Get32(p2 + 20); + if (bg_color1 != (UInt32)(Int32)-1 || bg_color2 != (UInt32)(Int32)-1 || bg_textcolor != (UInt32)(Int32)-1) + { + Script += "BGGradient"; + if (bg_color1 != 0 || bg_color2 != 0xFF0000 || bg_textcolor != (UInt32)(Int32)-1) { - Script += " "; - Script += ReadString2(e.Params[0]); - Script += " "; - Script += ReadString2(e.Params[1]); - Script += " "; - Script += UIntToString(e.Params[2]); - break; + Add_ColorParam(bg_color1); + Add_ColorParam(bg_color2); + if (bg_textcolor != (UInt32)(Int32)-1) + Add_ColorParam(bg_textcolor); } + AddLF(); + } + } - case EW_CREATESHORTCUT: - { - AString s; - - Script += " "; - Script += ReadString2Qw(e.Params[0]); + { + UInt32 lb_bg = Get32(p2 + 24); + UInt32 lb_fg = Get32(p2 + 28); + if ((lb_bg != (UInt32)(Int32)-1 || lb_fg != (UInt32)(Int32)-1) && + (lb_bg != 0 || lb_fg != 0xFF00)) + { + Script += "InstallColors"; + Add_ColorParam(lb_fg); + Add_ColorParam(lb_bg); + AddLF(); + } + } - Script += " "; - Script += ReadString2Qw(e.Params[1]); + UInt32 license_bg = Get32(p2 + 36); + if (license_bg != (UInt32)(Int32)-1 && license_bg != -15) // COLOR_BTNFACE + { + Script += "LicenseBkColor"; + if ((Int32)license_bg == -5) // COLOR_WINDOW + Script += " /windows"; + /* + else if ((Int32)license_bg == -15) + Script += " /grey"; + */ + else + Add_ColorParam(license_bg); + AddLF(); + } - for (int j = 2; j < 5; j++) - { - Script += " "; - Script += UIntToString(e.Params[j]); - } - break; - } + UInt32 langtable_size = Get32(p2 + 32); + if (bhLangTables.Num > 0) + { + UInt32 numStrings = (langtable_size - 10) / 4; + _numLangStrings = numStrings; + AddLF(); + Separator(); + PrintNumComment("LANG TABLES", bhLangTables.Num); + PrintNumComment("LANG STRINGS", numStrings); + AddLF(); - /* - case EW_DELREG: + if (licenseLangIndex >= 0) + { + for (UInt32 i = 0; i < bhLangTables.Num; i++) { - AString keyName, valueName; - keyName = ReadString2(e.Params[1]); - bool isValue = (e.Params[2] != -1); - if (isValue) + const Byte *p = _data + bhLangTables.Offset + langtable_size * i; + LANGID langID = Get16(p); + UInt32 val = Get32(p + 10 + licenseLangIndex * 4); + if (val != 0) { - valueName = ReadString2(e.Params[2]); - Script += "Key"; + Script += "LicenseLangString "; + Add_LangStr_Simple(licenseLangIndex); + AddParam_UInt(langID); + AddLicense(val, langID); + noParseStringIndexes.AddToUniqueSorted(val); + NewLine(); } - 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: + AddLF(); + } + + UInt32 brandingText = 0; + UInt32 caption = 0; + UInt32 name = 0; + UInt32 i; + for (i = 0; i < bhLangTables.Num; i++) + { + const Byte *p = _data + bhLangTables.Offset + langtable_size * i; + LANGID langID = Get16(p); + if (i == 0 || langID == 1033) + _mainLang = p + 10; { - 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; + UInt32 v = Get32(p + 10 + 0 * 4); + if (v != 0 && (langID == 1033 || brandingText == 0)) + brandingText = v; } - - case EW_WRITEUNINSTALLER: { - Script += " "; - Script += ReadString2(e.Params[0]); - for (int j = 1; j < 3; j++) - { - Script += " "; - Script += UIntToString(e.Params[j]); - } - break; + UInt32 v = Get32(p + 10 + 1 * 4); + if (v != 0 && (langID == 1033 || caption == 0)) + caption = v; } - - 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); + UInt32 v = Get32(p + 10 + 2 * 4); + if (v != 0 && (langID == 1033 || name == 0)) + name = v; } - #endif } - #ifdef NSIS_SCRIPT - Script += kCrLf; - #endif - } + + if (name != 0) + { + Script += "Name"; + AddParam(name); + NewLine(); - { - Items.Sort(CompareItems, 0); - int i; - // if (IsSolid) - for (i = 0; i + 1 < Items.Size();) + ReadString2(Name, name); + } + + /* + if (caption != 0) { - 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++; + Script += "Caption"; + AddParam(caption); + NewLine(); } - for (i = 0; i < Items.Size(); i++) + */ + + if (brandingText != 0) { - 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; - } - } + Script += "BrandingText"; + AddParam(brandingText); + NewLine(); + + ReadString2(BrandingText, brandingText); } - if (!IsSolid) + + for (i = 0; i < bhLangTables.Num; i++) { - for (i = 0; i < Items.Size(); i++) + const Byte *p = _data + bhLangTables.Offset + langtable_size * i; + LANGID langID = Get16(p); + + AddLF(); + AddCommentAndString("LANG:"); + AddParam_UInt(langID); + /* + Script += " ("; + LangId_To_String(Script, langID); + Script += ')'; + */ + AddLF(); + // UInt32 dlg_offset = Get32(p + 2); + // UInt32 g_exec_flags_rtl = Get32(p + 6); + + + for (UInt32 j = 0; j < numStrings; j++) { - 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) + UInt32 val = Get32(p + 10 + j * 4); + if (val != 0) { - item.IsCompressed = true; - // is compressed; - size &= ~0x80000000; - if (Method == NMethodType::kLZMA) + if ((Int32)j != licenseLangIndex) { - if (processedSize < 9) - return S_FALSE; - if (FilterFlag) - item.UseFilter = (sig[4] != 0); - item.DictionarySize = Get32(sig + 5 + (FilterFlag ? 1 : 0)); + Script += "LangString "; + Add_LangStr_Simple(j); + AddParam_UInt(langID); + AddParam(val); + AddLF(); } } - else - { - item.IsCompressed = false; - item.Size = size; - item.SizeIsDefined = true; - } - item.CompressedSize = size; - item.CompressedSizeIsDefined = true; } + AddLF(); } + ClearLangComment(); } - 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); + { + unsigned numInternalVars = GET_NUM_INTERNAL_VARS; + UInt32 numUsedVars = GetNumUsedVars(); + if (numUsedVars > numInternalVars) + { + Separator(); + PrintNumComment("VARIABLES", numUsedVars - numInternalVars); + AddLF(); + AString temp; + for (UInt32 i = numInternalVars; i < numUsedVars; i++) + { + Script += "Var "; + temp.Empty(); + GetVar2(temp, i); + AddStringLF(temp); + } + AddLF(); + } + } - _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)); + onFuncOffset = paramsOffset + 40; + numOnFunc = ARRAY_SIZE(kOnFunc); + if (bhPages.Offset == 276) + numOnFunc--; + p2 += 40 + numOnFunc * 4; + + #define NSIS_MAX_INST_TYPES 32 + + AddLF(); - if (c >= NS_UN_CODES_START && c < NS_UN_CODES_END) + UInt32 i; + for (i = 0; i < NSIS_MAX_INST_TYPES + 1; i++, p2 += 4) + { + UInt32 instType = Get32(p2); + if (instType != 0) + { + Script += "InstType"; + AString s2; + if (!IsInstaller) + s2 += "un."; + ReadString2(s2, instType); + SpaceQuStr(s2); + NewLine(); + } + } + + { + UInt32 installDir = Get32(p2); + p2 += 4; + if (installDir != 0) + { + Script += "InstallDir"; + AddParam(installDir); + NewLine(); + } + } + + if (bhPages.Offset >= 288) + for (i = 0; i < 4; i++) { - if (pos >= _size || pos + 1 >= _size) + if (i != 0 && bhPages.Offset < 300) break; - pos += 2; - numZeros1++; + UInt32 param = Get32(p2 + 4 * i); + if (param == 0 || param == (UInt32)(Int32)-1) + continue; + + /* + uninstaller: + UInt32 uninstChild = Get32(p2 + 8); // "$TEMP\\$1u_.exe" + UInt32 uninstCmd = Get32(p2 + 12); // "\"$TEMP\\$1u_.exe\" $0 _?=$INSTDIR\\" + int str_wininit = Get32(p2 + 16); // "$WINDIR\\wininit.ini" + */ + + AddCommentAndString(k_PostStrings[i]); + Script += " ="; + AddParam(param); + NewLine(); } - else + + AddLF(); + + #endif + + RINOK(ReadEntries(bhEntries)); + + #ifdef NSIS_SCRIPT + + Separator(); + AddCommentAndString("UNREFERENCED STRINGS:"); + AddLF(); + AddLF(); + CommentOpen(); + + for (i = 0; i < NumStringChars;) + { + if (!strUsed[i] && i != 0) + // Script += "!!! "; { - if (c0 == 0 && c1 != 0) - numZeros0++; - if (c1 == 0) - numZeros1++; + Add_UInt(i); + AddParam(i); + NewLine(); } - // printf("\nnumZeros0 = %2x %2x", _data[pos + 0], _data[pos + 1]); + if (IsUnicode) + i += GetUi16Str_Len((const Byte *)_data + _stringsPos + i * 2); + else + i += (UInt32)strlen((const char *)(const Byte *)_data + _stringsPos + i); + i++; } - IsUnicode = (numZeros1 > numZeros0 * 3 + kBlockSize / 16); - // printf("\nnumZeros0 = %3d numZeros1 = %3d", numZeros0, numZeros1); - return ReadEntries(bhEntries); + CommentClose(); + #endif + + return SortItems(); } 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); + return (p[0] == 0x5D && + p[1] == 0x00 && p[2] == 0x00 && + p[5] == 0x00 && (p[6] & 0x80) == 0x00); } static bool IsLZMA(const Byte *p, UInt32 &dictionary, bool &thereIsFlag) @@ -1276,7 +5545,7 @@ static bool IsLZMA(const Byte *p, UInt32 &dictionary, bool &thereIsFlag) thereIsFlag = false; return true; } - if (IsLZMA(p + 1, dictionary)) + if (p[0] <= 1 && IsLZMA(p + 1, dictionary)) { thereIsFlag = true; return true; @@ -1289,92 +5558,131 @@ static bool IsBZip2(const Byte *p) return (p[0] == 0x31 && p[1] < 14); } -HRESULT CInArchive::Open2( - DECL_EXTERNAL_CODECS_LOC_VARS2 - ) +HRESULT CInArchive::Open2(const Byte *sig, size_t size) { - 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)); + const UInt32 kSigSize = 4 + 1 + 5 + 2; // size, flag, 5 - lzma props, 2 - lzma first bytes + if (size < kSigSize) + return S_FALSE; _headerIsCompressed = true; IsSolid = true; FilterFlag = false; + UseFilter = false; DictionarySize = 1; + #ifdef NSIS_SCRIPT + AfterHeaderSize = 0; + #endif + UInt32 compressedHeaderSize = Get32(sig); - if (compressedHeaderSize == FirstHeader.HeaderLength) + + /* + XX XX XX XX XX XX XX XX == FirstHeader.HeaderSize, nonsolid, uncompressed + 5D 00 00 dd dd 00 solid LZMA + 00 5D 00 00 dd dd 00 solid LZMA, empty filter (there are no such archives) + 01 5D 00 00 dd dd 00 solid LZMA, BCJ filter (only 7-Zip installer used that format) + + SS SS SS 80 00 5D 00 00 dd dd 00 non-solid LZMA, empty filter + SS SS SS 80 01 5D 00 00 dd dd 00 non-solid LZMA, BCJ filte + SS SS SS 80 01 tt non-solid BZip (tt < 14 + SS SS SS 80 non-solid deflate + + 01 tt solid BZip (tt < 14 + other solid Deflate + */ + + if (compressedHeaderSize == FirstHeader.HeaderSize) { _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)) + if (IsLZMA(sig + 4, DictionarySize, FilterFlag) && sig[3] == 0x80) + Method = NMethodType::kLZMA; + else 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) + if (IsSolid) { - _headerIsCompressed = ((compressedHeaderSize & 0x80000000) != 0); - if (_headerIsCompressed) - compressedHeaderSize &= ~0x80000000; + RINOK(_stream->Seek(DataStreamOffset, STREAM_SEEK_SET, NULL)); + } + else + { + _headerIsCompressed = ((compressedHeaderSize & kMask_IsCompressed) != 0); + compressedHeaderSize &= ~kMask_IsCompressed; _nonSolidStartOffset = compressedHeaderSize; - RINOK(_stream->Seek(StreamOffset + 4, STREAM_SEEK_SET, NULL)); + RINOK(_stream->Seek(DataStreamOffset + 4, STREAM_SEEK_SET, NULL)); } - UInt32 unpackSize = FirstHeader.HeaderLength; + + _data.Alloc(FirstHeader.HeaderSize); + _size = (size_t)FirstHeader.HeaderSize; + + Decoder.Method = Method; + Decoder.FilterFlag = FilterFlag; + Decoder.Solid = IsSolid; + Decoder.InputStream = _stream; + Decoder.Buffer.Alloc(kInputBufSize); + Decoder.StreamPos = 0; + 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.Init(_stream, UseFilter)); + if (IsSolid) + { + size_t processedSize = 4; + Byte buf[4]; + RINOK(Decoder.Read(buf, &processedSize)); + if (processedSize != 4) + return S_FALSE; + if (Get32((const Byte *)buf) != FirstHeader.HeaderSize) + return S_FALSE; + } + size_t processedSize = FirstHeader.HeaderSize; RINOK(Decoder.Read(_data, &processedSize)); - if (processedSize != unpackSize) + if (processedSize != FirstHeader.HeaderSize) return S_FALSE; - _size = processedSize; + + #ifdef NSIS_SCRIPT if (IsSolid) { - UInt32 size2 = ReadUInt32(); - if (size2 < _size) - _size = size2; + /* we need additional bytes for data for WriteRegBin */ + AfterHeaderSize = (1 << 12); + _afterHeader.Alloc(AfterHeaderSize); + size_t processedSize = AfterHeaderSize; + RINOK(Decoder.Read(_afterHeader, &processedSize)); + AfterHeaderSize = (UInt32)processedSize; } + #endif } else { - _data.SetCapacity(unpackSize); - _size = (size_t)unpackSize; - RINOK(ReadStream_FALSE(_stream, (Byte *)_data, unpackSize)); + size_t processedSize = FirstHeader.HeaderSize; + RINOK(ReadStream(_stream, (Byte *)_data, &processedSize)); + if (processedSize < FirstHeader.HeaderSize) + return S_FALSE; + } + + #ifdef NUM_SPEED_TESTS + for (unsigned i = 0; i < NUM_SPEED_TESTS; i++) + { + RINOK(Parse()); + Clear2(); } + #endif + return Parse(); } @@ -1404,57 +5712,212 @@ FirstHeader UInt32 Flags; Byte Signature[16]; // points to the header+sections+entries+stringtable in the datablock - UInt32 HeaderLength; - UInt32 ArchiveSize; + UInt32 HeaderSize; + UInt32 ArcSize; } */ -HRESULT CInArchive::Open( - DECL_EXTERNAL_CODECS_LOC_VARS - IInStream *inStream, const UInt64 *maxCheckStartPosition) + +// ---------- PE (EXE) parsing ---------- + +static const unsigned k_PE_StartSize = 0x40; +static const unsigned k_PE_HeaderSize = 4 + 20; +static const unsigned k_PE_OptHeader32_Size_MIN = 96; + +static inline bool CheckPeOffset(UInt32 pe) +{ + return (pe >= 0x40 && pe <= 0x1000 && (pe & 7) == 0); +} + + +static bool IsArc_Pe(const Byte *p, size_t size) +{ + if (size < 2) + return false; + if (p[0] != 'M' || p[1] != 'Z') + return false; + if (size < k_PE_StartSize) + return false; // k_IsArc_Res_NEED_MORE; + UInt32 pe = Get32(p + 0x3C); + if (!CheckPeOffset(pe)) + return false; + if (pe + k_PE_HeaderSize > size) + return false; // k_IsArc_Res_NEED_MORE; + + p += pe; + if (Get32(p) != 0x00004550) + return false; + return Get16(p + 4 + 16) >= k_PE_OptHeader32_Size_MIN; +} + +HRESULT CInArchive::Open(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(inStream->Seek(0, STREAM_SEEK_CUR, &StartOffset)); + + const UInt32 kStartHeaderSize = 4 * 7; + const unsigned kStep = 512; // nsis start is aligned for 512 + Byte buf[kStep]; + UInt64 pos = StartOffset; + size_t bufSize = 0; + UInt64 pePos = (UInt64)(Int64)-1; + + for (;;) { - RINOK(ReadStream_FALSE(inStream, buffer, kStep)); - if (memcmp(buffer + 4, kSignature, kSignatureSize) == 0) + bufSize = kStep; + RINOK(ReadStream(inStream, buf, &bufSize)); + if (bufSize < kStartHeaderSize) + return S_FALSE; + if (memcmp(buf + 4, kSignature, kSignatureSize) == 0) break; + if (IsArc_Pe(buf, bufSize)) + pePos = pos; + pos += kStep; + UInt64 proc = pos - StartOffset; + if (maxCheckStartPosition && proc > *maxCheckStartPosition) + { + if (pePos == 0) + { + if (proc > (1 << 20)) + return S_FALSE; + } + else + return S_FALSE; + } + } + + if (pePos == (UInt64)(Int64)-1) + { + UInt64 posCur = StartOffset; + for (;;) + { + if (posCur < kStep) + break; + posCur -= kStep; + if (pos - posCur > (1 << 20)) + break; + bufSize = kStep; + RINOK(inStream->Seek(posCur, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream(inStream, buf, &bufSize)); + if (bufSize < kStep) + break; + if (IsArc_Pe(buf, bufSize)) + { + pePos = posCur; + break; + } + } + + // restore buf to nsis header + bufSize = kStep; + RINOK(inStream->Seek(pos, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream(inStream, buf, &bufSize)); + if (bufSize < kStartHeaderSize) + return S_FALSE; } - if (position > maxSize) + + StartOffset = pos; + UInt32 peSize = 0; + + if (pePos != (UInt64)(Int64)-1) + { + UInt64 peSize64 = (pos - pePos); + if (peSize64 < (1 << 20)) + { + peSize = (UInt32)peSize64; + StartOffset = pePos; + } + } + + DataStreamOffset = pos + kStartHeaderSize; + FirstHeader.Flags = Get32(buf); + if ((FirstHeader.Flags & (~kFlagsMask)) != 0) 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) + IsInstaller = (FirstHeader.Flags & NFlags::kUninstall) == 0; + + FirstHeader.HeaderSize = Get32(buf + kSignatureSize + 4); + FirstHeader.ArcSize = Get32(buf + kSignatureSize + 8); + if (FirstHeader.ArcSize <= kStartHeaderSize) return S_FALSE; + + RINOK(inStream->Seek(0, STREAM_SEEK_END, &_fileSize)); + + IsArc = true; + + if (peSize != 0) + { + ExeStub.Alloc(peSize); + RINOK(inStream->Seek(pePos, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream_FALSE(inStream, ExeStub, peSize)); + } + HRESULT res = S_FALSE; try { - _stream = inStream; - HRESULT res = Open2(EXTERNAL_CODECS_LOC_VARS2); - if (res != S_OK) - Clear(); + CLimitedInStream *_limitedStreamSpec = new CLimitedInStream; + _stream = _limitedStreamSpec; + _limitedStreamSpec->SetStream(inStream); + _limitedStreamSpec->InitAndSeek(pos, FirstHeader.ArcSize); + DataStreamOffset -= pos; + res = Open2(buf + kStartHeaderSize, bufSize - kStartHeaderSize); + } + catch(...) + { + _stream.Release(); + throw; + // res = S_FALSE; + } + if (res != S_OK) + { _stream.Release(); - return res; + // Clear(); } - catch(...) { Clear(); return S_FALSE; } + return res; } -void CInArchive::Clear() +UString CInArchive::ConvertToUnicode(const AString &s) const +{ + if (IsUnicode) + { + UString res; + if (ConvertUTF8ToUnicode(s, res)) + return res; + } + return MultiByteToUnicodeString(s); +} + +void CInArchive::Clear2() { + IsUnicode = false; + NsisType = k_NsisType_Nsis2; + IsNsis225 = false; + IsNsis200 = false; + LogCmdIsEnabled = false; + BadCmd = -1; + #ifdef NSIS_SCRIPT + Name.Empty(); + BrandingText.Empty(); Script.Empty(); + LicenseFiles.Clear(); + _numRootLicenses = 0; + langStrIDs.Clear(); + LangComment.Empty(); + noParseStringIndexes.Clear(); #endif + + APrefixes.Clear(); + UPrefixes.Clear(); Items.Clear(); + IsUnicode = false; + ExeStub.Free(); +} + +void CInArchive::Clear() +{ + Clear2(); + IsArc = false; _stream.Release(); } diff --git a/CPP/7zip/Archive/Nsis/NsisIn.h b/CPP/7zip/Archive/Nsis/NsisIn.h old mode 100755 new mode 100644 index 7ca719e4..3acd9ee5 --- a/CPP/7zip/Archive/Nsis/NsisIn.h +++ b/CPP/7zip/Archive/Nsis/NsisIn.h @@ -3,21 +3,28 @@ #ifndef __ARCHIVE_NSIS_IN_H #define __ARCHIVE_NSIS_IN_H -#include "Common/Buffer.h" -#include "Common/MyCom.h" -#include "Common/StringConvert.h" +#include "../../../../C/CpuArch.h" + +#include "../../../Common/DynLimBuf.h" +#include "../../../Common/MyBuffer.h" +#include "../../../Common/MyCom.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/UTFConvert.h" #include "NsisDecode.h" -// #define NSIS_SCRIPT +/* If NSIS_SCRIPT is defined, it will decompile NSIS script to [NSIS].nsi file. + The code is much larger in that case. */ + +#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} +const size_t kScriptSizeLimit = 1 << 27; -extern Byte kSignature[kSignatureSize]; +const unsigned kSignatureSize = 16; +#define NSIS_SIGNATURE { 0xEF, 0xBE, 0xAD, 0xDE, 'N', 'u', 'l', 'l', 's', 'o', 'f', 't', 'I', 'n', 's', 't' } const UInt32 kFlagsMask = 0xF; namespace NFlags @@ -31,18 +38,17 @@ namespace NFlags struct CFirstHeader { UInt32 Flags; - UInt32 HeaderLength; - - UInt32 ArchiveSize; + UInt32 HeaderSize; + UInt32 ArcSize; bool ThereIsCrc() const { - if ((Flags & NFlags::kForceCrc ) != 0) - return true; - return ((Flags & NFlags::kNoCrc) == 0); + return + (Flags & NFlags::kForceCrc) != 0 || + (Flags & NFlags::kNoCrc) == 0; } - UInt32 GetDataSize() const { return ArchiveSize - (ThereIsCrc() ? 4 : 0); } + UInt32 GetDataSize() const { return ArcSize - (ThereIsCrc() ? 4 : 0); } }; @@ -50,123 +56,330 @@ struct CBlockHeader { UInt32 Offset; UInt32 Num; + + void Parse(const Byte *p) + { + Offset = GetUi32(p); + Num = GetUi32(p + 4); + } }; struct CItem { - AString PrefixA; - UString PrefixU; - AString NameA; - UString NameU; - FILETIME MTime; - bool IsUnicode; - bool UseFilter; bool IsCompressed; - bool SizeIsDefined; - bool CompressedSizeIsDefined; - bool EstimatedSizeIsDefined; + bool Size_Defined; + bool CompressedSize_Defined; + bool EstimatedSize_Defined; + bool Attrib_Defined; + bool IsUninstaller; + // bool UseFilter; + + UInt32 Attrib; 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) {} + UInt32 PatchSize; // for Uninstaller.exe + int Prefix; // - 1 means no prefix - bool IsINSTDIR() const + FILETIME MTime; + AString NameA; + UString NameU; + + CItem(): + IsCompressed(true), + Size_Defined(false), + CompressedSize_Defined(false), + EstimatedSize_Defined(false), + Attrib_Defined(false), + IsUninstaller(false), + // UseFilter(false), + Attrib(0), + Pos(0), + Size(0), + CompressedSize(0), + EstimatedSize(0), + DictionarySize(1), + PatchSize(0), + Prefix(-1) { - return (PrefixA.Length() >= 3 || PrefixU.Length() >= 3); + MTime.dwLowDateTime = 0; + MTime.dwHighDateTime = 0; } - UString GetReducedName(bool unicode) const + /* + bool IsINSTDIR() const { - UString s; - if (unicode) - s = PrefixU; - else - s = MultiByteToUnicodeString(PrefixA); - if (s.Length() > 0) - if (s.Back() != 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; + return (PrefixA.Len() >= 3 || PrefixU.Len() >= 3); } + */ }; -class CInArchive +enum ENsisType { - 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(); + k_NsisType_Nsis2, + k_NsisType_Nsis3, + k_NsisType_Park1, // Park 2.46.1- + k_NsisType_Park2, // Park 2.46.2 : GetFontVersion + k_NsisType_Park3 // Park 2.46.3+ : GetFontName +}; + +#ifdef NSIS_SCRIPT +struct CSection +{ + UInt32 InstallTypes; // bits set for each of the different install_types, if any. + UInt32 Flags; // SF_* - defined above + UInt32 StartCmdIndex; // code; + UInt32 NumCommands; // code_size; + UInt32 SizeKB; + UInt32 Name; + + void Parse(const Byte *data); +}; + +struct CLicenseFile +{ + UInt32 Offset; + UInt32 Size; + AString Name; + CByteBuffer Text; +}; + +#endif + +class CInArchive +{ +public: + #ifdef NSIS_SCRIPT + CDynLimBuf Script; + #endif CByteBuffer _data; - UInt64 _size; + CObjectVector Items; + bool IsUnicode; +private: + UInt32 _stringsPos; // relative to _data + UInt32 NumStringChars; + size_t _size; // it's Header Size - size_t _posInData; + AString Raw_AString; + UString Raw_UString; - UInt32 _stringsPos; + ENsisType NsisType; + bool IsNsis200; // NSIS 2.03 and before + bool IsNsis225; // NSIS 2.25 and before + + bool LogCmdIsEnabled; + int BadCmd; // -1: no bad command; in another cases lowest bad command id + bool IsPark() const { return NsisType >= k_NsisType_Park1; } + UInt64 _fileSize; + bool _headerIsCompressed; UInt32 _nonSolidStartOffset; + + #ifdef NSIS_SCRIPT + + CByteBuffer strUsed; + + CBlockHeader bhPages; + CBlockHeader bhSections; + CBlockHeader bhCtlColors; + CBlockHeader bhData; + UInt32 AfterHeaderSize; + CByteBuffer _afterHeader; + + UInt32 SectionSize; + const Byte *_mainLang; + UInt32 _numLangStrings; + AString LangComment; + CRecordVector langStrIDs; + UInt32 numOnFunc; + UInt32 onFuncOffset; + // CRecordVector OnFuncs; + unsigned _numRootLicenses; + CRecordVector noParseStringIndexes; + AString _tempString_for_GetVar; + AString _tempString_for_AddFuncName; + AString _tempString; + + #endif + + public: - HRESULT Open( - DECL_EXTERNAL_CODECS_LOC_VARS - IInStream *inStream, const UInt64 *maxCheckStartPosition); - void Clear(); + CMyComPtr _stream; // it's limited stream that contains only NSIS archive + UInt64 StartOffset; // offset in original stream. + UInt64 DataStreamOffset; // = sizeof(FirstHeader) = offset of Header in _stream + + bool IsArc; - UInt64 StreamOffset; CDecoder Decoder; - CObjectVector Items; + CByteBuffer ExeStub; CFirstHeader FirstHeader; NMethodType::EEnum Method; UInt32 DictionarySize; bool IsSolid; bool UseFilter; bool FilterFlag; - bool IsUnicode; + + bool IsInstaller; + AString Name; + AString BrandingText; + UStringVector UPrefixes; + AStringVector APrefixes; #ifdef NSIS_SCRIPT - AString Script; + CObjectVector LicenseFiles; #endif - UInt32 GetOffset() const { return IsSolid ? 4 : 0; } - UInt64 GetDataPos(int index) + +private: + void GetShellString(AString &s, unsigned index1, unsigned index2); + void GetNsisString_Raw(const Byte *s); + void GetNsisString_Unicode_Raw(const Byte *s); + void ReadString2_Raw(UInt32 pos); + bool IsGoodString(UInt32 param) const; + bool AreTwoParamStringsEqual(UInt32 param1, UInt32 param2) const; + + void Add_LangStr(AString &res, UInt32 id); + + #ifdef NSIS_SCRIPT + + void Add_UInt(UInt32 v); + void AddLicense(UInt32 param, Int32 langID); + + void Add_LangStr_Simple(UInt32 id); + void Add_FuncName(const UInt32 *labels, UInt32 index); + void AddParam_Func(const UInt32 *labels, UInt32 index); + void Add_LabelName(UInt32 index); + + void Add_Color2(UInt32 v); + void Add_ColorParam(UInt32 v); + void Add_Color(UInt32 index); + + void Add_ButtonID(UInt32 buttonID); + + void Add_ShowWindow_Cmd(UInt32 cmd); + void Add_TypeFromList(const char **table, unsigned tableSize, UInt32 type); + void Add_ExecFlags(UInt32 flagsType); + void Add_SectOp(UInt32 opType); + + void Add_Var(UInt32 index); + void AddParam_Var(UInt32 value); + void AddParam_UInt(UInt32 value); + + void Add_GotoVar(UInt32 param); + void Add_GotoVar1(UInt32 param); + void Add_GotoVars2(const UInt32 *params); + + + + bool PrintSectionBegin(const CSection §, unsigned index); + void PrintSectionEnd(); + + void GetNsisString(AString &res, const Byte *s); + void GetNsisString_Unicode(AString &res, const Byte *s); + UInt32 GetNumUsedVars() const; + void ReadString2(AString &s, UInt32 pos); + + void MessageBox_MB_Part(UInt32 param); + void AddParam(UInt32 pos); + void AddOptionalParam(UInt32 pos); + void AddParams(const UInt32 *params, unsigned num); + void AddPageOption1(UInt32 param, const char *name); + void AddPageOption(const UInt32 *params, unsigned num, const char *name); + void AddOptionalParams(const UInt32 *params, unsigned num); + void AddRegRoot(UInt32 value); + + + void ClearLangComment(); + void Separator(); + void Space(); + void Tab(); + void Tab(bool commented); + void BigSpaceComment(); + void SmallSpaceComment(); + void AddCommentAndString(const char *s); + void AddError(const char *s); + void AddErrorLF(const char *s); + void CommentOpen(); + void CommentClose(); + void AddLF(); + void AddQuotes(); + void TabString(const char *s); + void AddStringLF(const char *s); + void NewLine(); + void PrintNumComment(const char *name, UInt32 value); + void Add_QuStr(const AString &s); + void SpaceQuStr(const AString &s); + bool CompareCommands(const Byte *rawCmds, const Byte *sequence, size_t numCommands); + + #endif + + #ifdef NSIS_SCRIPT + unsigned GetNumSupportedCommands() const; + #endif + + UInt32 GetCmd(UInt32 a); + void FindBadCmd(const CBlockHeader &bh, const Byte *); + void DetectNsisType(const CBlockHeader &bh, const Byte *); + + HRESULT ReadEntries(const CBlockHeader &bh); + HRESULT SortItems(); + HRESULT Parse(); + HRESULT Open2(const Byte *data, size_t size); + void Clear2(); + + void GetVar2(AString &res, UInt32 index); + void GetVar(AString &res, UInt32 index); + Int32 GetVarIndex(UInt32 strPos) const; + Int32 GetVarIndex(UInt32 strPos, UInt32 &resOffset) const; + Int32 GetVarIndexFinished(UInt32 strPos, Byte endChar, UInt32 &resOffset) const; + bool IsVarStr(UInt32 strPos, UInt32 varIndex) const; + bool IsAbsolutePathVar(UInt32 strPos) const; + void SetItemName(CItem &item, UInt32 strPos); + +public: + HRESULT Open(IInStream *inStream, const UInt64 *maxCheckStartPosition); + AString GetFormatDescription() const; + HRESULT InitDecoder() + { + bool useFilter; + return Decoder.Init(_stream, useFilter); + } + + HRESULT SeekTo_DataStreamOffset() + { + return _stream->Seek(DataStreamOffset, STREAM_SEEK_SET, NULL); + } + + HRESULT SeekToNonSolidItem(unsigned index) + { + return _stream->Seek(GetPosOfNonSolidItem(index), STREAM_SEEK_SET, NULL); + } + + void Clear(); + + bool IsDirectString_Equal(UInt32 offset, const char *s) const; + /* + UInt64 GetDataPos(unsigned index) { const CItem &item = Items[index]; - return GetOffset() + FirstHeader.HeaderLength + item.Pos; + return GetOffset() + FirstHeader.HeaderSize + item.Pos; } + */ - UInt64 GetPosOfSolidItem(int index) const + UInt64 GetPosOfSolidItem(unsigned index) const { const CItem &item = Items[index]; - return 4 + FirstHeader.HeaderLength + item.Pos; + return 4 + (UInt64)FirstHeader.HeaderSize + item.Pos; } - UInt64 GetPosOfNonSolidItem(int index) const + UInt64 GetPosOfNonSolidItem(unsigned index) const { const CItem &item = Items[index]; - return StreamOffset + _nonSolidStartOffset + 4 + item.Pos; + return DataStreamOffset + _nonSolidStartOffset + 4 + item.Pos; } void Release() @@ -174,6 +387,52 @@ public: Decoder.Release(); } + bool IsTruncated() const { return (_fileSize - StartOffset < FirstHeader.ArcSize); } + + UString GetReducedName(unsigned index) const + { + const CItem &item = Items[index]; + + UString s; + if (item.Prefix >= 0) + { + if (IsUnicode) + s = UPrefixes[item.Prefix]; + else + s = MultiByteToUnicodeString(APrefixes[item.Prefix]); + if (s.Len() > 0) + if (s.Back() != L'\\') + s += L'\\'; + } + + if (IsUnicode) + { + s += item.NameU; + if (item.NameU.IsEmpty()) + s += L"file"; + } + else + { + s += MultiByteToUnicodeString(item.NameA); + if (item.NameA.IsEmpty()) + s += L"file"; + } + + const char *kRemoveStr = "$INSTDIR\\"; + if (s.IsPrefixedBy_Ascii_NoCase(kRemoveStr)) + s.Delete(0, MyStringLen(kRemoveStr)); + if (item.IsUninstaller && ExeStub.Size() == 0) + s += L".nsis"; + return s; + } + + UString ConvertToUnicode(const AString &s) const; + + CInArchive() + #ifdef NSIS_SCRIPT + : Script(kScriptSizeLimit) + #endif + {} }; }} diff --git a/CPP/7zip/Archive/Nsis/NsisRegister.cpp b/CPP/7zip/Archive/Nsis/NsisRegister.cpp old mode 100755 new mode 100644 index 41dedb0d..b363bdec --- a/CPP/7zip/Archive/Nsis/NsisRegister.cpp +++ b/CPP/7zip/Archive/Nsis/NsisRegister.cpp @@ -5,9 +5,20 @@ #include "../../Common/RegisterArc.h" #include "NsisHandler.h" -static IInArchive *CreateArc() { return new NArchive::NNsis::CHandler; } + +namespace NArchive { +namespace NNsis { + +IMP_CreateArcIn static CArcInfo g_ArcInfo = - { L"Nsis", L"", 0, 0x9, NSIS_SIGNATURE, NArchive::NNsis::kSignatureSize, false, CreateArc, 0 }; + { "Nsis", "nsis", 0, 0x9, + NArchive::NNsis::kSignatureSize, NSIS_SIGNATURE, + 4, + NArcInfoFlags::kFindSignature | + NArcInfoFlags::kUseGlobalOffset, + CreateArc }; REGISTER_ARC(Nsis) + +}} diff --git a/CPP/7zip/Archive/Nsis/StdAfx.h b/CPP/7zip/Archive/Nsis/StdAfx.h old mode 100755 new mode 100644 index 2e4be10b..2854ff3e --- a/CPP/7zip/Archive/Nsis/StdAfx.h +++ b/CPP/7zip/Archive/Nsis/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" -#include "../../../Common/NewHandler.h" +#include "../../../Common/Common.h" #endif diff --git a/CPP/7zip/Archive/NtfsHandler.cpp b/CPP/7zip/Archive/NtfsHandler.cpp old mode 100755 new mode 100644 index 505486fc..dfe5eade --- a/CPP/7zip/Archive/NtfsHandler.cpp +++ b/CPP/7zip/Archive/NtfsHandler.cpp @@ -11,15 +11,15 @@ #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 "../../Common/ComTry.h" +#include "../../Common/IntToString.h" +#include "../../Common/MyBuffer.h" +#include "../../Common/MyCom.h" -#include "Windows/PropVariant.h" -#include "Windows/Time.h" +#include "../../Windows/PropVariant.h" +#include "../../Windows/TimeUtils.h" +#include "../Common/MethodProps.h" #include "../Common/ProgressUtils.h" #include "../Common/RegisterArc.h" #include "../Common/StreamUtils.h" @@ -30,8 +30,10 @@ #ifdef SHOW_DEBUG_INFO #define PRF(x) x +#define PRF_UTF16(x) PRF(printf("%S", x)) #else #define PRF(x) +#define PRF_UTF16(x) #endif #ifdef SHOW_DEBUG_INFO2 @@ -48,26 +50,36 @@ #define G32(p, dest) dest = Get32(p); #define G64(p, dest) dest = Get64(p); +using namespace NWindows; + namespace NArchive { namespace Ntfs { -static const UInt32 kNumSysRecs = 16; -static const UInt32 kRecIndex_Volume = 3; -static const UInt32 kRecIndex_BadClus = 8; +static const wchar_t *kVirtualFolder_System = L"[SYSTEM]"; +static const wchar_t *kVirtualFolder_Lost_Normal = L"[LOST]"; +static const wchar_t *kVirtualFolder_Lost_Deleted = L"[UNKNOWN]"; + +static const unsigned kNumSysRecs = 16; + +static const unsigned kRecIndex_Volume = 3; +static const unsigned kRecIndex_BadClus = 8; +static const unsigned kRecIndex_Security = 9; struct CHeader { - Byte SectorSizeLog; - Byte ClusterSizeLog; + unsigned SectorSizeLog; + unsigned ClusterSizeLog; // Byte MediaType; UInt32 NumHiddenSectors; + UInt64 NumSectors; UInt64 NumClusters; UInt64 MftCluster; UInt64 SerialNumber; UInt16 SectorsPerTrack; UInt16 NumHeads; - UInt64 GetPhySize() const { return NumClusters << ClusterSizeLog; } + UInt64 GetPhySize_Clusters() const { return NumClusters << ClusterSizeLog; } + UInt64 GetPhySize_Max() const { return (NumSectors + 1) << SectorSizeLog; } UInt32 ClusterSize() const { return (UInt32)1 << ClusterSizeLog; } bool Parse(const Byte *p); }; @@ -89,35 +101,38 @@ bool CHeader::Parse(const Byte *p) 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; + case 0xEB: if (p[2] != 0x90) return false; codeOffset = 2 + (int)(signed char)p[1]; break; default: return false; } - Byte sectorsPerClusterLog; + unsigned sectorsPerClusterLog; if (memcmp(p + 3, "NTFS ", 8) != 0) return false; { - int s = GetLog(Get16(p + 11)); - if (s < 9 || s > 12) + int t = GetLog(Get16(p + 11)); + if (t < 9 || t > 12) return false; - SectorSizeLog = (Byte)s; - s = GetLog(p[13]); - if (s < 0) + SectorSizeLog = t; + t = GetLog(p[13]); + if (t < 0) return false; - sectorsPerClusterLog = (Byte)s; + sectorsPerClusterLog = t; ClusterSizeLog = SectorSizeLog + sectorsPerClusterLog; + if (ClusterSizeLog > 30) + return false; } for (int i = 14; i < 21; i++) if (p[i] != 0) return false; - // MediaType = p[21]; + if (p[21] != 0xF8) // MediaType = Fixed_Disk + return false; if (Get16(p + 22) != 0) // NumFatSectors return false; - G16(p + 24, SectorsPerTrack); - G16(p + 26, NumHeads); - G32(p + 28, NumHiddenSectors); + G16(p + 24, SectorsPerTrack); // 63 usually + G16(p + 26, NumHeads); // 255 + G32(p + 28, NumHiddenSectors); // 63 (XP) / 2048 (Vista and win7) / (0 on media that are not partitioned ?) if (Get32(p + 32) != 0) // NumSectors32 return false; @@ -132,15 +147,19 @@ bool CHeader::Parse(const Byte *p) return false; if (p[0x27] != 0) // reserved return false; - UInt64 numSectors = Get64(p + 0x28); - NumClusters = numSectors >> sectorsPerClusterLog; + + NumSectors = Get64(p + 0x28); + if (NumSectors >= ((UInt64)1 << (62 - SectorSizeLog))) + return false; + + 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 + 0x40, numClustersInMftRec); // -10 means 2 ^10 = 1024 bytes. G32(p + 0x44, numClustersInIndexBlock); return (numClustersInMftRec < 256 && numClustersInIndexBlock < 256); } @@ -148,6 +167,7 @@ bool CHeader::Parse(const Byte *p) 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; } @@ -178,17 +198,19 @@ enum DEF_ATTR_TYPE(0x1000, FIRST_USER_DEFINED_ATTRIBUTE) }; -static const Byte kFileNameType_Posix = 0; -static const Byte kFileNameType_Win32 = 1; -static const Byte kFileNameType_Dos = 2; -static const Byte kFileNameType_Win32Dos = 3; +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; + + // Probably these timestamps don't contain some useful timestamps. So we don't use them // UInt64 CTime; // UInt64 MTime; - // UInt64 ThisRecMTime; + // UInt64 ThisRecMTime; // xp-64: the time of previous name change (not last name change. why?) // UInt64 ATime; // UInt64 AllocatedSize; // UInt64 DataSize; @@ -201,12 +223,12 @@ struct CFileNameAttr bool Parse(const Byte *p, unsigned size); }; -static void GetString(const Byte *p, unsigned length, UString &res) +static void GetString(const Byte *p, unsigned len, UString &res) { - wchar_t *s = res.GetBuffer(length); - for (unsigned i = 0; i < length; i++) + wchar_t *s = res.GetBuffer(len); + for (unsigned i = 0; i < len; i++) s[i] = Get16(p + i * 2); - s[length] = 0; + s[len] = 0; res.ReleaseBuffer(); } @@ -224,10 +246,10 @@ bool CFileNameAttr::Parse(const Byte *p, unsigned size) G32(p + 0x38, Attrib); // G16(p + 0x3C, PackedEaSize); NameType = p[0x41]; - unsigned length = p[0x40]; - if (0x42 + length > size) + unsigned len = p[0x40]; + if (0x42 + len > size) return false; - GetString(p + 0x42, length, Name); + GetString(p + 0x42, len, Name); return true; } @@ -244,9 +266,9 @@ struct CSiAttr UInt32 Version; UInt32 ClassId; UInt32 OwnerId; - UInt32 SecurityId; - UInt64 QuotaCharged; */ + UInt32 SecurityId; // SecurityId = 0 is possible ? + // UInt64 QuotaCharged; bool Parse(const Byte *p, unsigned size); }; @@ -260,6 +282,9 @@ bool CSiAttr::Parse(const Byte *p, unsigned size) // G64(p + 0x10, ThisRecMTime); G64(p + 0x18, ATime); G32(p + 0x20, Attrib); + SecurityId = 0; + if (size >= 0x38) + G32(p + 0x34, SecurityId); return true; } @@ -295,7 +320,7 @@ bool CVolInfo::Parse(const Byte *p, unsigned size) struct CAttr { UInt32 Type; - // UInt32 Length; + // UInt32 Len; UString Name; // UInt16 Flags; // UInt16 Instance; @@ -317,15 +342,15 @@ struct CAttr 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(); } + bool ParseFileName(CFileNameAttr &a) const { return a.Parse(Data, (unsigned)Data.Size()); } + bool ParseSi(CSiAttr &a) const { return a.Parse(Data, (unsigned)Data.Size()); } + bool ParseVolInfo(CVolInfo &a) const { return a.Parse(Data, (unsigned)Data.Size()); } + bool ParseExtents(CRecordVector &extents, UInt64 numClustersMax, unsigned compressionUnit) const; + UInt64 GetSize() const { return NonResident ? Size : Data.Size(); } UInt64 GetPackSize() const { if (!NonResident) - return Data.GetCapacity(); + return Data.Size(); if (CompressionUnit != 0) return PackSize; return AllocatedSize; @@ -339,7 +364,7 @@ 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)); + RINOZ(wcscmp(a1.Name, a2.Name)); return MyCompare(a1.LowVcn, a2.LowVcn); } @@ -349,25 +374,28 @@ UInt32 CAttr::Parse(const Byte *p, unsigned size) return 0; G32(p, Type); if (Type == 0xFFFFFFFF) - return 4; + return 8; // required size is 4, but attributes are 8 bytes aligned. So we return 8 if (size < 0x18) return 0; PRF(printf(" T=%2X", Type)); - UInt32 length = Get32(p + 0x04); - PRF(printf(" L=%3d", length)); - if (length > size) + UInt32 len = Get32(p + 0x04); + PRF(printf(" L=%3d", len)); + if (len > size) + return 0; + if ((len & 7) != 0) return 0; NonResident = p[0x08]; { - int nameLength = p[9]; + unsigned nameLength = p[9]; UInt32 nameOffset = Get16(p + 0x0A); if (nameLength != 0) { - if (nameOffset + nameLength * 2 > length) + if (nameOffset + nameLength * 2 > len) return 0; GetString(p + nameOffset, nameLength, Name); - PRF(printf(" N=%S", Name)); + PRF(printf(" N=")); + PRF_UTF16(Name); } } @@ -380,7 +408,7 @@ UInt32 CAttr::Parse(const Byte *p, unsigned size) UInt32 offs; if (NonResident) { - if (length < 0x40) + if (len < 0x40) return 0; PRF(printf(" NR")); G64(p + 0x10, LowVcn); @@ -394,7 +422,7 @@ UInt32 CAttr::Parse(const Byte *p, unsigned size) PackSize = Size; if (CompressionUnit != 0) { - if (length < 0x48) + if (len < 0x48) return 0; G64(p + 0x40, PackSize); PRF(printf(" PS=%I64x", PackSize)); @@ -406,12 +434,12 @@ UInt32 CAttr::Parse(const Byte *p, unsigned 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; + PRF(printf(" CU=%d", (unsigned)CompressionUnit)); + dataSize = len - offs; } else { - if (length < 0x18) + if (len < 0x18) return 0; PRF(printf(" RES")); dataSize = Get32(p + 0x10); @@ -420,24 +448,23 @@ UInt32 CAttr::Parse(const Byte *p, unsigned size) // G16(p + 0x16, ResidentFlags); // PRF(printf(" ResFlags=%4X", ResidentFlags)); } - if (offs > length || dataSize > length || length - dataSize < offs) + if (offs > len || dataSize > len || len - dataSize < offs) return 0; - Data.SetCapacity(dataSize); - memcpy(Data, p + offs, dataSize); + Data.CopyFrom(p + offs, dataSize); #ifdef SHOW_DEBUG_INFO PRF(printf(" : ")); - for (unsigned i = 0; i < Data.GetCapacity(); i++) + for (unsigned i = 0; i < Data.Size(); i++) { - PRF(printf(" %02X", (int)Data[i])); + PRF(printf(" %02X", (unsigned)Data[i])); } #endif - return length; + return len; } -bool CAttr::ParseExtents(CRecordVector &extents, UInt64 numClustersMax, int compressionUnit) const +bool CAttr::ParseExtents(CRecordVector &extents, UInt64 numClustersMax, unsigned compressionUnit) const { const Byte *p = Data; - unsigned size = (unsigned)Data.GetCapacity(); + unsigned size = (unsigned)Data.Size(); UInt64 vcn = LowVcn; UInt64 lcn = 0; UInt64 highVcn1 = HighVcn + 1; @@ -504,8 +531,8 @@ bool CAttr::ParseExtents(CRecordVector &extents, UInt64 numClustersMax, static const UInt64 kEmptyTag = (UInt64)(Int64)-1; -static const int kNumCacheChunksLog = 1; -static const UInt32 kNumCacheChunks = (1 << kNumCacheChunksLog); +static const unsigned kNumCacheChunksLog = 1; +static const size_t kNumCacheChunks = (1 << kNumCacheChunksLog); class CInStream: public IInStream, @@ -518,32 +545,32 @@ class CInStream: size_t _compressedPos; UInt64 _tags[kNumCacheChunks]; - int _chunkSizeLog; + unsigned _chunkSizeLog; CByteBuffer _inBuf; CByteBuffer _outBuf; public: CMyComPtr Stream; UInt64 Size; UInt64 InitializedSize; - int BlockSizeLog; - int CompressionUnit; + unsigned BlockSizeLog; + unsigned 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) + HRESULT InitAndSeek(unsigned compressionUnit) { CompressionUnit = compressionUnit; if (compressionUnit != 0) { UInt32 cuSize = GetCuSize(); - _inBuf.SetCapacity(cuSize); + _inBuf.Alloc(cuSize); _chunkSizeLog = BlockSizeLog + CompressionUnit; - _outBuf.SetCapacity(kNumCacheChunks << _chunkSizeLog); + _outBuf.Alloc(kNumCacheChunks << _chunkSizeLog); } - for (int i = 0; i < kNumCacheChunks; i++) + for (size_t i = 0; i < kNumCacheChunks; i++) _tags[i] = kEmptyTag; _sparseMode = false; @@ -683,10 +710,10 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) UInt64 virtBlock = _virtPos >> BlockSizeLog; UInt64 virtBlock2 = virtBlock & ~((UInt64)comprUnitSize - 1); - int left = 0, right = Extents.Size(); + unsigned left = 0, right = Extents.Size(); for (;;) { - int mid = (left + right) / 2; + unsigned mid = (left + right) / 2; if (mid == left) break; if (virtBlock2 < Extents[mid].Virt) @@ -698,7 +725,7 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) bool isCompressed = false; UInt64 virtBlock2End = virtBlock2 + comprUnitSize; if (CompressionUnit != 0) - for (int i = left; i < Extents.Size(); i++) + for (unsigned i = left; i < Extents.Size(); i++) { const CExtent &e = Extents[i]; if (e.Virt >= virtBlock2End) @@ -710,7 +737,7 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) } } - int i; + unsigned i; for (i = left; Extents[i + 1].Virt <= virtBlock; i++); _sparseMode = false; @@ -733,7 +760,7 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) break; } bool thereArePhy = false; - for (int i2 = left; i2 < Extents.Size(); i2++) + for (unsigned i2 = left; i2 < Extents.Size(); i2++) { const CExtent &e = Extents[i2]; if (e.Virt >= virtBlock2End) @@ -812,19 +839,22 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) STDMETHODIMP CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - UInt64 newVirtPos = offset; - switch(seekOrigin) + switch (seekOrigin) { case STREAM_SEEK_SET: break; - case STREAM_SEEK_CUR: newVirtPos += _virtPos; break; - case STREAM_SEEK_END: newVirtPos += Size; break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: offset += Size; break; default: return STG_E_INVALIDFUNCTION; } - if (_virtPos != newVirtPos) + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + if (_virtPos != (UInt64)offset) + { _curRem = 0; - _virtPos = newVirtPos; + _virtPos = offset; + } if (newPosition) - *newPosition = newVirtPos; + *newPosition = offset; return S_OK; } @@ -847,9 +877,9 @@ 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 (_virtPos >= Buf.Size()) + return (_virtPos == Buf.Size()) ? S_OK: E_FAIL; + UInt64 rem = Buf.Size() - _virtPos; if (rem < size) size = (UInt32)rem; memcpy(data, Buf + (size_t)_virtPos, size); @@ -861,20 +891,23 @@ STDMETHODIMP CByteBufStream::Read(void *data, UInt32 size, UInt32 *processedSize STDMETHODIMP CByteBufStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - switch(seekOrigin) + 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; + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: offset += Buf.Size(); break; default: return STG_E_INVALIDFUNCTION; } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = offset; if (newPosition) - *newPosition = _virtPos; + *newPosition = offset; return S_OK; } -static HRESULT DataParseExtents(int clusterSizeLog, const CObjectVector &attrs, - int attrIndex, int attrIndexLim, UInt64 numPhysClusters, CRecordVector &Extents) +static HRESULT DataParseExtents(unsigned clusterSizeLog, const CObjectVector &attrs, + unsigned attrIndex, unsigned attrIndexLim, UInt64 numPhysClusters, CRecordVector &Extents) { CExtent e; e.Virt = 0; @@ -887,12 +920,12 @@ static HRESULT DataParseExtents(int clusterSizeLog, const CObjectVector & (attr0.AllocatedSize & ((1 << clusterSizeLog) - 1)) != 0) return S_FALSE; - for (int i = attrIndex; i < attrIndexLim; i++) + for (unsigned 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++) + FOR_VECTOR (k, Extents) { CExtent &e = Extents[k]; if (!e.IsEmpty()) @@ -916,18 +949,18 @@ static HRESULT DataParseExtents(int clusterSizeLog, const CObjectVector & struct CDataRef { - int Start; - int Num; + unsigned Start; + unsigned Num; }; -static const UInt32 kMagic_FILE = 0x454c4946; +static const UInt32 kMagic_FILE = 0x454C4946; static const UInt32 kMagic_BAAD = 0x44414142; struct CMftRec { UInt32 Magic; // UInt64 Lsn; - UInt16 SeqNumber; + UInt16 SeqNumber; // Number of times this mft record has been reused UInt16 Flags; // UInt16 LinkCount; // UInt16 NextAttrInstance; @@ -938,8 +971,18 @@ struct CMftRec CObjectVector DataAttrs; CObjectVector FileNames; CRecordVector DataRefs; + // CAttr SecurityAttr; CSiAttr SiAttr; + + CByteBuffer ReparseData; + + bool IsAltStream(int dataIndex) const + { + return dataIndex >= 0 && ( + (IsDir() || + !DataAttrs[DataRefs[dataIndex].Start].Name.IsEmpty())); + } void MoveAttrsFrom(CMftRec &src) { @@ -952,12 +995,12 @@ struct CMftRec UInt64 GetPackSize() const { UInt64 res = 0; - for (int i = 0; i < DataRefs.Size(); i++) + FOR_VECTOR (i, DataRefs) res += DataAttrs[DataRefs[i].Start].GetPackSize(); return res; } - bool Parse(Byte *p, int sectorSizeLog, UInt32 numSectors, UInt32 recNumber, CObjectVector *attrs); + bool Parse(Byte *p, unsigned sectorSizeLog, UInt32 numSectors, UInt32 recNumber, CObjectVector *attrs); bool IsEmpty() const { return (Magic <= 2); } bool IsFILE() const { return (Magic == kMagic_FILE); } @@ -968,10 +1011,10 @@ struct CMftRec void ParseDataNames(); HRESULT GetStream(IInStream *mainStream, int dataIndex, - int clusterSizeLog, UInt64 numPhysClusters, IInStream **stream) const; - int GetNumExtents(int dataIndex, int clusterSizeLog, UInt64 numPhysClusters) const; + unsigned clusterSizeLog, UInt64 numPhysClusters, IInStream **stream) const; + unsigned GetNumExtents(int dataIndex, unsigned clusterSizeLog, UInt64 numPhysClusters) const; - UInt64 GetSize(int dataIndex) const { return DataAttrs[DataRefs[dataIndex].Start].GetSize(); } + UInt64 GetSize(unsigned dataIndex) const { return DataAttrs[DataRefs[dataIndex].Start].GetSize(); } CMftRec(): MyNumNameLinks(0) {} }; @@ -981,7 +1024,7 @@ void CMftRec::ParseDataNames() DataRefs.Clear(); DataAttrs.Sort(CompareAttr, 0); - for (int i = 0; i < DataAttrs.Size();) + for (unsigned i = 0; i < DataAttrs.Size();) { CDataRef ref; ref.Start = i; @@ -994,7 +1037,7 @@ void CMftRec::ParseDataNames() } HRESULT CMftRec::GetStream(IInStream *mainStream, int dataIndex, - int clusterSizeLog, UInt64 numPhysClusters, IInStream **destStream) const + unsigned clusterSizeLog, UInt64 numPhysClusters, IInStream **destStream) const { *destStream = 0; CByteBufStream *streamSpec = new CByteBufStream; @@ -1003,11 +1046,11 @@ HRESULT CMftRec::GetStream(IInStream *mainStream, int dataIndex, if (dataIndex < 0) return E_FAIL; - if (dataIndex < DataRefs.Size()) + if ((unsigned)dataIndex < DataRefs.Size()) { const CDataRef &ref = DataRefs[dataIndex]; - int numNonResident = 0; - int i; + unsigned numNonResident = 0; + unsigned i; for (i = ref.Start; i < ref.Start + ref.Num; i++) if (DataAttrs[i].NonResident) numNonResident++; @@ -1037,14 +1080,14 @@ HRESULT CMftRec::GetStream(IInStream *mainStream, int dataIndex, return S_OK; } -int CMftRec::GetNumExtents(int dataIndex, int clusterSizeLog, UInt64 numPhysClusters) const +unsigned CMftRec::GetNumExtents(int dataIndex, unsigned clusterSizeLog, UInt64 numPhysClusters) const { if (dataIndex < 0) return 0; { const CDataRef &ref = DataRefs[dataIndex]; - int numNonResident = 0; - int i; + unsigned numNonResident = 0; + unsigned i; for (i = ref.Start; i < ref.Start + ref.Num; i++) if (DataAttrs[i].NonResident) numNonResident++; @@ -1060,36 +1103,49 @@ int CMftRec::GetNumExtents(int dataIndex, int clusterSizeLog, UInt64 numPhysClus return 0; // error; return extents.Size() - 1; } - // if (attr0.Data.GetCapacity() != 0) + // if (attr0.Data.Size() != 0) // return 1; return 0; } } -bool CMftRec::Parse(Byte *p, int sectorSizeLog, UInt32 numSectors, UInt32 recNumber, +bool CMftRec::Parse(Byte *p, unsigned 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) + UInt32 usaOffset; + UInt32 numUsaItems; + G16(p + 0x04, usaOffset); + G16(p + 0x06, numUsaItems); + + /* NTFS stores (usn) to 2 last bytes in each sector (before writing record to disk). + Original values of these two bytes are stored in table. + So we restore original data from table */ + + if ((usaOffset & 1) != 0 + || usaOffset + numUsaItems * 2 > ((UInt32)1 << sectorSizeLog) - 2 + || numUsaItems == 0 + || numUsaItems - 1 != numSectors) return false; - SetUi16(pp, Get16(p + usaOffset + i * 2)); + + if (usaOffset >= 0x30) // NTFS 3.1+ + if (Get32(p + 0x2C) != recNumber) + 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); @@ -1109,28 +1165,36 @@ bool CMftRec::Parse(Byte *p, int sectorSizeLog, UInt32 numSectors, UInt32 recNum // 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 + if (attrOffs >= limit + || (attrOffs & 7) != 0 + || (bytesInUse & 7) != 0 + || bytesInUse > limit || bytesAlloc != limit) return false; + limit = bytesInUse; - for (UInt32 t = attrOffs; t < limit;) + for (UInt32 t = attrOffs;;) { + if (t >= limit) + return false; + 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) + UInt32 len = attr.Parse(p + t, limit - t); + if (len == 0 || limit - t < len) return false; - t += length; + t += len; if (attr.Type == 0xFFFFFFFF) + { + if (t != limit) + return false; break; - switch(attr.Type) + } + switch (attr.Type) { case ATTR_TYPE_FILE_NAME: { @@ -1138,8 +1202,8 @@ bool CMftRec::Parse(Byte *p, int sectorSizeLog, UInt32 numSectors, UInt32 recNum if (!attr.ParseFileName(fna)) return false; FileNames.Add(fna); - PRF(printf(" flags = %4x", (int)fna.NameType)); - PRF(printf("\n %S", fna.Name)); + PRF(printf(" flags = %4x\n ", (int)fna.NameType)); + PRF_UTF16(fna.Name); break; } case ATTR_TYPE_STANDARD_INFO: @@ -1149,6 +1213,14 @@ bool CMftRec::Parse(Byte *p, int sectorSizeLog, UInt32 numSectors, UInt32 recNum case ATTR_TYPE_DATA: DataAttrs.Add(attr); break; + case ATTR_TYPE_REPARSE_POINT: + ReparseData = attr.Data; + break; + /* + case ATTR_TYPE_SECURITY_DESCRIPTOR: + SecurityAttr = attr; + break; + */ default: if (attrs) attrs->Add(attr); @@ -1161,49 +1233,99 @@ bool CMftRec::Parse(Byte *p, int sectorSizeLog, UInt32 numSectors, UInt32 recNum struct CItem { - int RecIndex; - int DataIndex; - CMftRef ParentRef; - UString Name; - UInt32 Attrib; - - bool IsDir() const { return (DataIndex < 0); } + unsigned RecIndex; // index in Recs array + unsigned NameIndex; // index in CMftRec::FileNames + + int DataIndex; /* index in CMftRec::DataRefs + -1: for folders + -1: for files that have no DATA_ATRIBUTE */ + + int ParentFolder; /* index in Items array + -1: for root items + -2: [LOST] folder + -3: [UNKNOWN] folder (deleted lost) */ + int ParentHost; /* index in Items array, if it's AltStream + -1: if it's not AltStream + -1: if there is no Host item */ + + CItem(): DataIndex(-1), ParentFolder(-1), ParentHost(-1) {} + + bool IsDir() const { return DataIndex < 0; } + // check it !!! + // probably NTFS for empty file still creates empty DATA_ATTRIBUTE + // But it doesn't do it for $Secure:$SDS }; struct CDatabase { - CHeader Header; - CObjectVector Items; + CRecordVector Items; CObjectVector Recs; CMyComPtr InStream; + CHeader Header; + unsigned RecSizeLog; + UInt64 PhySize; + IArchiveOpenCallback *OpenCallback; CByteBuffer ByteBuf; CObjectVector VolAttrs; + CByteBuffer SecurData; + CRecordVector SecurOffsets; + + bool _showSystemFiles; + bool _showDeletedFiles; + UStringVector VirtFolderNames; + int _systemFolderIndex; + int _lostFolderIndex_Normal; + int _lostFolderIndex_Deleted; + + // bool _headerWarning; + + bool ThereAreAltStreams; + + void InitProps() + { + _showSystemFiles = true; + // we show SystemFiles by default since it's difficult to track $Extend\* system files + // it must be fixed later + _showDeletedFiles = false; + } + + CDatabase() { InitProps(); } ~CDatabase() { ClearAndClose(); } void Clear(); void ClearAndClose(); - UString GetItemPath(Int32 index) const; + void GetItemPath(unsigned index, NCOM::CPropVariant &path) const; HRESULT Open(); - HRESULT ReadDir(Int32 parent, UInt32 cluster, int level); HRESULT SeekToCluster(UInt64 cluster); - int FindMtfRec(const CMftRef &ref) const + int FindDirItemForMtfRec(UInt64 recIndex) const { - UInt64 val = ref.GetIndex(); - int left = 0, right = Items.Size(); + if (recIndex >= Recs.Size()) + return -1; + const CMftRec &rec = Recs[(unsigned)recIndex]; + if (!rec.IsDir()) + return -1; + unsigned 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) + unsigned mid = (left + right) / 2; + const CItem &item = Items[mid]; + UInt64 midValue = item.RecIndex; + if (recIndex == midValue) + { + // if (!item.IsAltStream) + // if (!rec.IsAltStream(item.DataIndex)) + if (item.DataIndex < 0) + return mid; + right = mid; + } + else if (recIndex < midValue) right = mid; else left = mid + 1; @@ -1211,6 +1333,19 @@ struct CDatabase return -1; } + bool FindSecurityDescritor(UInt32 id, UInt64 &offset, UInt32 &size) const; + + HRESULT ParseSecuritySDS_2(); + void ParseSecuritySDS() + { + HRESULT res = ParseSecuritySDS_2(); + if (res != S_OK) + { + SecurOffsets.Clear(); + SecurData.Free(); + } + } + }; HRESULT CDatabase::SeekToCluster(UInt64 cluster) @@ -1222,6 +1357,15 @@ void CDatabase::Clear() { Items.Clear(); Recs.Clear(); + SecurOffsets.Clear(); + SecurData.Free(); + VirtFolderNames.Clear(); + _systemFolderIndex = -1; + _lostFolderIndex_Normal = -1; + _lostFolderIndex_Deleted = -1; + ThereAreAltStreams = false; + // _headerWarning = false; + PhySize = 0; } void CDatabase::ClearAndClose() @@ -1232,55 +1376,273 @@ void CDatabase::ClearAndClose() #define MY_DIR_PREFIX(x) L"[" x L"]" WSTRING_PATH_SEPARATOR -UString CDatabase::GetItemPath(Int32 index) const +void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) 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; + unsigned size = 0; + const CMftRec &rec = Recs[item->RecIndex]; + size += rec.FileNames[item->NameIndex].Name.Len(); + + bool isAltStream = rec.IsAltStream(item->DataIndex); + if (isAltStream) + { + const CAttr &data = rec.DataAttrs[rec.DataRefs[item->DataIndex].Start]; + size += data.Name.Len(); + size++; + } + + /* + if (item->ParentHost >= 0) + { + item = &Items[item->ParentHost]; + size += item->Name.Len() + 1; + } + */ + + for (unsigned i = 0;; i++) + { + if (i > 256) + { + path = "[TOO-LONG]"; + return; + } + const wchar_t *servName; + if (item->RecIndex < kNumSysRecs) + servName = kVirtualFolder_System; + else + { + int index2 = item->ParentFolder; + if (index2 >= 0) + { + item = &Items[index2]; + size += Recs[item->RecIndex].FileNames[item->NameIndex].Name.Len() + 1; + continue; + } + if (index2 == -1) + break; + servName = (index2 == -2) ? + kVirtualFolder_Lost_Normal : + kVirtualFolder_Lost_Deleted; + } + size += MyStringLen(servName) + 1; + break; + } + + wchar_t *s = path.AllocBstr(size); + + item = &Items[index]; + + bool needColon = false; + if (isAltStream) + { + const UString &name = rec.DataAttrs[rec.DataRefs[item->DataIndex].Start].Name; + size -= name.Len(); + MyStringCopy(s + size, (const wchar_t *)name); + s[--size] = ':'; + needColon = true; + } + + { + const UString &name = rec.FileNames[item->NameIndex].Name; + unsigned len = name.Len(); + MyStringCopy(s + size - len, (const wchar_t *)name); + if (needColon) + s[size] = ':'; + size -= len; + } + + /* + { + unsigned len = item->Name.Len(); + size -= len; + MyStringCopy(s + size, (const wchar_t *)item->Name); + } + */ + + + /* + if (item->ParentHost >= 0) + { + item = &Items[item->ParentHost]; + unsigned len = item->Name.Len(); + size--; + size -= len; + MyStringCopy(s + size, (const wchar_t *)item->Name); + s[size + len] = ':'; + } + */ + + for (;;) + { + const wchar_t *servName; + if (item->RecIndex < kNumSysRecs) + servName = kVirtualFolder_System; + else + { + int index2 = item->ParentFolder; + if (index2 >= 0) + { + item = &Items[index2]; + const UString &name = Recs[item->RecIndex].FileNames[item->NameIndex].Name; + unsigned len = name.Len(); + size--; + size -= len; + MyStringCopy(s + size, (const wchar_t *)name); + s[size + len] = WCHAR_PATH_SEPARATOR; + continue; + } + if (index2 == -1) + break; + servName = (index2 == -2) ? + kVirtualFolder_Lost_Normal : + kVirtualFolder_Lost_Deleted; + } + MyStringCopy(s, servName); + s[MyStringLen(servName)] = WCHAR_PATH_SEPARATOR; + break; + } +} + +bool CDatabase::FindSecurityDescritor(UInt32 item, UInt64 &offset, UInt32 &size) const +{ + offset = 0; + size = 0; + unsigned left = 0, right = SecurOffsets.Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + size_t offs = SecurOffsets[mid]; + UInt32 midValue = Get32(((const Byte *)SecurData) + offs + 4); + if (item == midValue) + { + offset = Get64((const Byte *)SecurData + offs + 8) + 20; + size = Get32((const Byte *)SecurData + offs + 16) - 20; + return true; + } + if (item < midValue) + right = mid; + else + left = mid + 1; + } + return false; +} + +/* +static int CompareIDs(const size_t *p1, const size_t *p2, void *data) +{ + UInt32 id1 = Get32(((const Byte *)data) + *p1 + 4); + UInt32 id2 = Get32(((const Byte *)data) + *p2 + 4); + return MyCompare(id1, id2); +} +*/ + +// security data contains duplication copy after each 256 KB. +static const unsigned kSecureDuplicateStepBits = 18; + +HRESULT CDatabase::ParseSecuritySDS_2() +{ + const Byte *p = SecurData; + size_t size = SecurData.Size(); + const size_t kDuplicateStep = (size_t)1 << kSecureDuplicateStepBits; + const size_t kDuplicateMask = kDuplicateStep - 1; + size_t lim = MyMin(size, kDuplicateStep); + UInt32 idPrev = 0; + for (size_t pos = 0; pos < size && size - pos >= 20;) + { + UInt32 id = Get32(p + pos + 4); + UInt64 offs = Get64(p + pos + 8); + UInt32 entrySize = Get32(p + pos + 16); + if (offs == pos && entrySize >= 20 && lim - pos >= entrySize) + { + if (id <= idPrev) + return S_FALSE; + idPrev = id; + SecurOffsets.Add(pos); + pos += entrySize; + pos = (pos + 0xF) & ~(size_t)0xF; + if ((pos & kDuplicateMask) != 0) + continue; + } + else + pos = (pos + kDuplicateStep) & ~kDuplicateMask; + pos += kDuplicateStep; + lim = pos + kDuplicateStep; + if (lim >= size) + lim = size; + } + // we checked that IDs are sorted, so we don't need Sort + // SecurOffsets.Sort(CompareIDs, (void *)p); + return S_OK; } HRESULT CDatabase::Open() { Clear(); + + /* NTFS layout: + 1) main part (as specified by NumClusters). Only that part is available, if we open "\\.\c:" + 2) additional empty sectors (as specified by NumSectors) + 3) the copy of first sector (boot sector) + + We support both cases: + - the file with only main part + - full file (as raw data on partition), including the copy + of first sector (boot sector) at the end of data + + We don't support the case, when only the copy of boot sector + at the end was detected as NTFS signature. + */ - 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; - + { + 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)); + PhySize = Header.GetPhySize_Clusters(); + if (fileSize < PhySize) + return S_FALSE; + + UInt64 phySizeMax = Header.GetPhySize_Max(); + if (fileSize >= phySizeMax) + { + RINOK(InStream->Seek(Header.NumSectors << Header.SectorSizeLog, STREAM_SEEK_SET, NULL)); + Byte buf2[kHeaderSize]; + if (ReadStream_FALSE(InStream, buf2, kHeaderSize) == S_OK) + { + if (memcmp(buf, buf2, kHeaderSize) == 0) + PhySize = phySizeMax; + // else _headerWarning = true; + } + } + } + SeekToCluster(Header.MftCluster); CMftRec mftRec; UInt32 numSectorsInRec; - int recSizeLog; + CMyComPtr mftStream; { UInt32 blockSize = 1 << 12; - ByteBuf.SetCapacity(blockSize); + ByteBuf.Alloc(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)) + { + UInt32 allocSize = Get32(ByteBuf + 0x1C); + int t = GetLog(allocSize); + if (t < (int)Header.SectorSizeLog) + return S_FALSE; + RecSizeLog = t; + if (RecSizeLog > 15) + return S_FALSE; + } + + numSectorsInRec = 1 << (RecSizeLog - Header.SectorSizeLog); + if (!mftRec.Parse(ByteBuf, Header.SectorSizeLog, numSectorsInRec, 0, NULL)) return S_FALSE; if (!mftRec.IsFILE()) return S_FALSE; @@ -1292,23 +1654,28 @@ HRESULT CDatabase::Open() return S_FALSE; } + // CObjectVector SecurityAttrs; + UInt64 mftSize = mftRec.DataAttrs[0].Size; - if ((mftSize >> 4) > Header.GetPhySize()) + if ((mftSize >> 4) > Header.GetPhySize_Clusters()) return S_FALSE; - UInt64 numFiles = mftSize >> recSizeLog; + 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)) + + const size_t kBufSize = (1 << 15); + const size_t recSize = ((size_t)1 << RecSizeLog); + if (kBufSize < recSize) return S_FALSE; - ByteBuf.SetCapacity((size_t)kBufSize); - Recs.Reserve((int)numFiles); + ByteBuf.Alloc(kBufSize); + Recs.ClearAndReserve((unsigned)numFiles); + for (UInt64 pos64 = 0;;) { if (OpenCallback) @@ -1319,28 +1686,85 @@ HRESULT CDatabase::Open() RINOK(OpenCallback->SetCompleted(&numFiles, &pos64)); } } - UInt32 readSize = kBufSize; + size_t readSize = kBufSize; UInt64 rem = mftSize - pos64; if (readSize > rem) - readSize = (UInt32)rem; - if (readSize < ((UInt32)1 << recSizeLog)) + readSize = (size_t)rem; + if (readSize < recSize) break; - RINOK(ReadStream_FALSE(mftStream, ByteBuf, (size_t)readSize)); + RINOK(ReadStream_FALSE(mftStream, ByteBuf, readSize)); pos64 += readSize; - for (int i = 0; ((UInt32)(i + 1) << recSizeLog) <= readSize; i++) + + for (size_t i = 0; readSize >= recSize; i += recSize, readSize -= recSize) { PRF(printf("\n---------------------")); PRF(printf("\n%5d:", Recs.Size())); - Byte *p = ByteBuf + ((UInt32)i << recSizeLog); + + Byte *p = ByteBuf + i; CMftRec rec; - if (!rec.Parse(p, Header.SectorSizeLog, numSectorsInRec, (UInt32)Recs.Size(), - (Recs.Size() == kRecIndex_Volume) ? &VolAttrs: NULL)) + + CObjectVector *attrs = NULL; + unsigned recIndex = Recs.Size(); + switch (recIndex) + { + case kRecIndex_Volume: attrs = &VolAttrs; break; + // case kRecIndex_Security: attrs = &SecurityAttrs; break; + } + + if (!rec.Parse(p, Header.SectorSizeLog, numSectorsInRec, (UInt32)Recs.Size(), attrs)) return S_FALSE; Recs.Add(rec); } } - int i; + /* + // that code looks too complex. And we can get security info without index parsing + for (i = 0; i < SecurityAttrs.Size(); i++) + { + const CAttr &attr = SecurityAttrs[i]; + if (attr.Name == L"$SII") + { + if (attr.Type == ATTR_TYPE_INDEX_ROOT) + { + const Byte *data = attr.Data; + size_t size = attr.Data.Size(); + + // Index Root + UInt32 attrType = Get32(data); + UInt32 collationRule = Get32(data + 4); + UInt32 indexAllocationEtrySizeSize = Get32(data + 8); + UInt32 clustersPerIndexRecord = Get32(data + 0xC); + data += 0x10; + + // Index Header + UInt32 firstEntryOffset = Get32(data); + UInt32 totalSize = Get32(data + 4); + UInt32 allocSize = Get32(data + 8); + UInt32 flags = Get32(data + 0xC); + + int num = 0; + for (int j = 0 ; j < num; j++) + { + if (Get32(data) != 0x1414 || // offset and size + Get32(data + 4) != 0 || + Get32(data + 8) != 0x428) // KeySize / EntrySize + break; + UInt32 flags = Get32(data + 12); + UInt32 id = Get32(data + 0x10); + if (id = Get32(data + 0x18)) + break; + UInt32 descriptorOffset = Get64(data + 0x1C); + UInt32 descriptorSize = Get64(data + 0x24); + data += 0x28; + } + // break; + } + } + } + */ + + unsigned i; + for (i = 0; i < Recs.Size(); i++) { CMftRec &rec = Recs[i]; @@ -1349,7 +1773,7 @@ HRESULT CDatabase::Open() UInt64 refIndex = rec.BaseMftRef.GetIndex(); if (refIndex > (UInt32)Recs.Size()) return S_FALSE; - CMftRec &refRec = Recs[(int)refIndex]; + CMftRec &refRec = Recs[(unsigned)refIndex]; bool moveAttrs = (refRec.SeqNumber == rec.BaseMftRef.GetNumber() && refRec.BaseMftRef.IsBaseItself()); if (rec.InUse() && refRec.InUse()) { @@ -1371,81 +1795,357 @@ HRESULT CDatabase::Open() CMftRec &rec = Recs[i]; if (!rec.IsFILE() || !rec.BaseMftRef.IsBaseItself()) continue; - int numNames = 0; + if (i < kNumSysRecs && !_showSystemFiles) + continue; + if (!rec.InUse() && !_showDeletedFiles) + continue; + + unsigned numNames = 0; // printf("\n%4d: ", i); - for (int t = 0; t < rec.FileNames.Size(); t++) + FOR_VECTOR (t, rec.FileNames) { const CFileNameAttr &fna = rec.FileNames[t]; - // printf("%4d %S | ", (int)fna.NameType, fna.Name); + // PRF(printf("%4d ", (int)fna.NameType)); + // PRF_UTF16(fna.Name) + // PRF(printf(" | ")); if (fna.IsDos()) continue; - int numDatas = rec.DataRefs.Size(); + unsigned numDatas = rec.DataRefs.Size(); - // For hard linked files we show substreams only for first Name. + /* + // we can use that code to reduce the number of alt streams + // For hard linked files we show alt streams only for first Name. if (numDatas > 1 && numNames > 0) numDatas = 1; + */ + numNames++; + // here we suppose that first stream is main stream (unnamed stream). + // IS IT SO ???? + int hostIndex = -1; if (rec.IsDir()) { CItem item; - item.Name = fna.Name; + item.NameIndex = t; item.RecIndex = i; - item.DataIndex = -1; - item.ParentRef = fna.ParentDirRef; - item.Attrib = rec.SiAttr.Attrib | 0x10; + // item.ParentRef = fna.ParentDirRef; + // item.Attrib = rec.SiAttr.Attrib | 0x10; // item.Attrib = fna.Attrib; - Items.Add(item); + hostIndex = Items.Add(item); + } + else + { + + // probably NTFS for empty file still creates empty DATA_ATTRIBUTE + // But it doesn't do it for $Secure:$SDS + if (rec.DataRefs.IsEmpty() || + !rec.DataAttrs[rec.DataRefs[0].Start].Name.IsEmpty()) + { + CItem item; + item.NameIndex = t; + item.RecIndex = i; + // item.ParentRef = fna.ParentDirRef; + // item.Attrib = rec.SiAttr.Attrib; + hostIndex = Items.Add(item); + } + } + + { + bool isThereUnNamedStream = false; + for (unsigned di = 0; di < numDatas; di++) + { + const UString &subName = rec.DataAttrs[rec.DataRefs[di].Start].Name; + if (subName.IsEmpty()) + isThereUnNamedStream = true; + } + if (!rec.IsDir() && !isThereUnNamedStream) + { + // return S_FALSE; + } } - for (int di = 0; di < numDatas; di++) + + for (unsigned di = 0; di < numDatas; di++) { CItem item; - item.Name = fna.Name; - item.Attrib = rec.SiAttr.Attrib; + item.NameIndex = t; + // item.FileNameAttr = fna; + // item.Name = fna.Name; + // item.Attrib = rec.SiAttr.Attrib; const UString &subName = rec.DataAttrs[rec.DataRefs[di].Start].Name; - if (!subName.IsEmpty()) + if (subName.IsEmpty()) + { + if (hostIndex >= 0) + continue; + hostIndex = Items.Size(); + } + else { // $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; + if (hostIndex >= 0) + { + // item.Name = subName; + } + else + { + // there is no host file for some streams + // return E_FAIL; + // item.Name += L":"; + // item.Name += subName; + } + // item.Attrib = fna.Attrib; + item.ParentHost = hostIndex; + // item.IsAltStream = true; + ThereAreAltStreams = true; } PRF(printf("\n%3d", i)); - PRF(printf(" attrib=%2x", rec.SiAttr.Attrib)); - PRF(printf(" %S", item.Name)); + PRF(printf(" attrib=%2x ", rec.SiAttr.Attrib)); + // PRF_UTF16(item.Name); item.RecIndex = i; item.DataIndex = di; - item.ParentRef = fna.ParentDirRef; + // item.ParentRef = fna.ParentDirRef; Items.Add(item); rec.MyNumNameLinks++; } } - rec.FileNames.ClearAndFree(); + // rec.FileNames.ClearAndFree(); + } + + if (Recs.Size() > kRecIndex_Security) + { + const CMftRec &rec = Recs[kRecIndex_Security]; + FOR_VECTOR (di, rec.DataRefs) + { + const CAttr &attr = rec.DataAttrs[rec.DataRefs[di].Start]; + if (attr.Name == L"$SDS") + { + CMyComPtr sdsStream; + RINOK(rec.GetStream(InStream, di, Header.ClusterSizeLog, Header.NumClusters, &sdsStream)); + if (sdsStream) + { + UInt64 size64 = attr.GetSize(); + if (size64 < (UInt32)1 << 29) + { + size_t size = (size_t)size64; + if ((((size + 1) >> kSecureDuplicateStepBits) & 1) != 0) + { + size -= (1 << kSecureDuplicateStepBits); + SecurData.Alloc(size); + if (ReadStream_FALSE(sdsStream, SecurData, size) == S_OK) + { + ParseSecuritySDS(); + break; + } + } + } + } + break; + } + } + } + + bool thereAreUnknownFolders_Normal = false; + bool thereAreUnknownFolders_Deleted = false; + + for (i = 0; i < Items.Size(); i++) + { + CItem &item = Items[i]; + const CMftRec &rec = Recs[item.RecIndex]; + const CFileNameAttr &fn = rec.FileNames[item.NameIndex]; + const CMftRef &parentDirRef = fn.ParentDirRef; + UInt64 refIndex = parentDirRef.GetIndex(); + if (refIndex == 5) + item.ParentFolder = -1; + else + { + int index = FindDirItemForMtfRec(refIndex); + if (index < 0 || + Recs[Items[index].RecIndex].SeqNumber != parentDirRef.GetNumber()) + { + if (Recs[item.RecIndex].InUse()) + { + thereAreUnknownFolders_Normal = true; + index = -2; + } + else + { + thereAreUnknownFolders_Deleted = true; + index = -3; + } + } + item.ParentFolder = index; + } } + unsigned virtIndex = Items.Size(); + if (_showSystemFiles) + { + _systemFolderIndex = virtIndex++; + VirtFolderNames.Add(kVirtualFolder_System); + } + if (thereAreUnknownFolders_Normal) + { + _lostFolderIndex_Normal = virtIndex++; + VirtFolderNames.Add(kVirtualFolder_Lost_Normal); + } + if (thereAreUnknownFolders_Deleted) + { + _lostFolderIndex_Deleted = virtIndex++; + VirtFolderNames.Add(kVirtualFolder_Lost_Deleted); + } + return S_OK; } class CHandler: public IInArchive, + public IArchiveGetRawProps, public IInArchiveGetStream, + public ISetProperties, public CMyUnknownImp, CDatabase { public: - MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + MY_UNKNOWN_IMP4( + IInArchive, + IArchiveGetRawProps, + IInArchiveGetStream, + ISetProperties) INTERFACE_IInArchive(;) + INTERFACE_IArchiveGetRawProps(;) STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); }; +STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps) +{ + *numProps = 2; + return S_OK; +} + +STDMETHODIMP CHandler::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID) +{ + *name = NULL; + *propID = index == 0 ? kpidNtReparse : kpidNtSecure; + return S_OK; +} + +STDMETHODIMP CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType) +{ + *parentType = NParentType::kDir; + *parent = (UInt32)(Int32)-1; + + if (index >= Items.Size()) + return S_OK; + const CItem &item = Items[index]; + + if (item.ParentHost >= 0) + { + *parentType = NParentType::kAltStream; + *parent = (UInt32)(Int32)item.ParentHost; + return S_OK; + } + if (item.RecIndex < kNumSysRecs) + { + if (_showSystemFiles) + *parent = _systemFolderIndex; + } + else if (item.ParentFolder >= 0) + *parent = item.ParentFolder; + else if (item.ParentFolder == -2) + *parent = _lostFolderIndex_Normal; + else if (item.ParentFolder == -3) + *parent = _lostFolderIndex_Deleted; + return S_OK; +} + +STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) +{ + *data = NULL; + *dataSize = 0; + *propType = 0; + + if (propID == kpidName) + { + #ifdef MY_CPU_LE + const UString *s; + if (index >= Items.Size()) + s = &VirtFolderNames[index - Items.Size()]; + else + { + const CItem &item = Items[index]; + const CMftRec &rec = Recs[item.RecIndex]; + + // fix it for no HOST case !! + // if (item.IsAltStream && item.DataIndex >= 0) + if (rec.IsAltStream(item.DataIndex)) + { + if (item.ParentHost < 0) + return S_OK; + const CAttr &data = rec.DataAttrs[rec.DataRefs[item.DataIndex].Start]; + s = &data.Name; + } + else + { + s = &rec.FileNames[item.NameIndex].Name; + } + // s = &item.Name; + } + *data = (const wchar_t *)*s; + *dataSize = (s->Len() + 1) * sizeof(wchar_t); + *propType = PROP_DATA_TYPE_wchar_t_PTR_Z_LE; + #endif + return S_OK; + } + + if (propID == kpidNtReparse) + { + if (index >= Items.Size()) + return S_OK; + const CItem &item = Items[index]; + const CMftRec &rec = Recs[item.RecIndex]; + const CByteBuffer &reparse = rec.ReparseData; + + if (reparse.Size() != 0) + { + *dataSize = (UInt32)reparse.Size(); + *propType = NPropDataType::kRaw; + *data = (const Byte *)reparse; + } + } + + if (propID == kpidNtSecure) + { + if (index >= Items.Size()) + return S_OK; + const CItem &item = Items[index]; + const CMftRec &rec = Recs[item.RecIndex]; + if (rec.SiAttr.SecurityId >= 0) + { + UInt64 offset; + UInt32 size; + if (FindSecurityDescritor(rec.SiAttr.SecurityId, offset, size)) + { + *dataSize = size; + *propType = NPropDataType::kRaw; + *data = (const Byte *)SecurData + offset; + } + } + } + return S_OK; +} + STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) { COM_TRY_BEGIN + *stream = 0; + if (index >= Items.Size()) + return S_OK; IInStream *stream2; const CItem &item = Items[index]; const CMftRec &rec = Recs[item.RecIndex]; @@ -1455,18 +2155,66 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) COM_TRY_END } +/* +enum +{ + kpidLink2 = kpidUserDefined, + kpidLinkType, + kpidRecMTime, + kpidRecMTime2, + kpidMTime2, + kpidCTime2, + kpidATime2 +}; + static const STATPROPSTG kProps[] = { { NULL, kpidPath, VT_BSTR}, - { NULL, kpidIsDir, VT_BOOL}, { NULL, kpidSize, VT_UI8}, { NULL, kpidPackSize, VT_UI8}, + + // { NULL, kpidLink, VT_BSTR}, + + // { L"Link 2", kpidLink2, VT_BSTR}, + // { L"Link Type", kpidLinkType, VT_UI2}, + { NULL, kpidINode, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, { NULL, kpidCTime, VT_FILETIME}, { NULL, kpidATime, VT_FILETIME}, + + // { L"Record Modified", kpidRecMTime, VT_FILETIME}, + + // { L"Modified 2", kpidMTime2, VT_FILETIME}, + // { L"Created 2", kpidCTime2, VT_FILETIME}, + // { L"Accessed 2", kpidATime2, VT_FILETIME}, + // { L"Record Modified 2", kpidRecMTime2, VT_FILETIME}, + { NULL, kpidAttrib, VT_UI4}, - { NULL, kpidLinks, VT_UI4}, - { NULL, kpidNumBlocks, VT_UI4} + { NULL, kpidNumBlocks, VT_UI4}, + { NULL, kpidIsDeleted, VT_BOOL}, +}; +*/ + +static const Byte kProps[] = +{ + kpidPath, + kpidIsDir, + kpidSize, + kpidPackSize, + kpidMTime, + kpidCTime, + kpidATime, + kpidAttrib, + kpidLinks, + kpidINode, + kpidNumBlocks, + kpidIsDeleted +}; + +enum +{ + kpidRecordSize = kpidUserDefined }; static const STATPROPSTG kArcProps[] = @@ -1474,21 +2222,34 @@ static const STATPROPSTG kArcProps[] = { NULL, kpidVolumeName, VT_BSTR}, { NULL, kpidFileSystem, VT_BSTR}, { NULL, kpidClusterSize, VT_UI4}, - { NULL, kpidPhySize, VT_UI8}, + { NULL, kpidSectorSize, VT_UI4}, + { L"Record Size", kpidRecordSize, VT_UI4}, { NULL, kpidHeadersSize, VT_UI8}, { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidId, VT_UI8}, +}; - { NULL, kpidSectorSize, VT_UI4}, - { NULL, kpidId, VT_UI8} - // { NULL, kpidSectorsPerTrack, VT_UI4}, - // { NULL, kpidNumHeads, VT_UI4}, - // { NULL, kpidHiddenSectors, VT_UI4} +/* +static const Byte kArcProps[] = +{ + kpidVolumeName, + kpidFileSystem, + kpidClusterSize, + kpidHeadersSize, + kpidCTime, + + kpidSectorSize, + kpidId + // kpidSectorsPerTrack, + // kpidNumHeads, + // kpidHiddenSectors }; +*/ IMP_IInArchive_Props -IMP_IInArchive_ArcProps +IMP_IInArchive_ArcProps_WITH_NAME -static void NtfsTimeToProp(UInt64 t, NWindows::NCOM::CPropVariant &prop) +static void NtfsTimeToProp(UInt64 t, NCOM::CPropVariant &prop) { FILETIME ft; ft.dwLowDateTime = (DWORD)t; @@ -1499,19 +2260,19 @@ static void NtfsTimeToProp(UInt64 t, NWindows::NCOM::CPropVariant &prop) STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; + NCOM::CPropVariant prop; const CMftRec *volRec = (Recs.Size() > kRecIndex_Volume ? &Recs[kRecIndex_Volume] : NULL); - switch(propID) + switch (propID) { case kpidClusterSize: prop = Header.ClusterSize(); break; - case kpidPhySize: prop = Header.GetPhySize(); break; + case kpidPhySize: prop = PhySize; break; /* case kpidHeadersSize: { UInt64 val = 0; - for (int i = 0; i < kNumSysRecs; i++) + for (unsigned i = 0; i < kNumSysRecs; i++) { printf("\n%2d: %8I64d ", i, Recs[i].GetPackSize()); if (i == 8) @@ -1522,16 +2283,18 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) break; } */ - case kpidCTime: if (volRec) NtfsTimeToProp(volRec->SiAttr.CTime, prop); break;break; + case kpidCTime: if (volRec) NtfsTimeToProp(volRec->SiAttr.CTime, prop); break; + case kpidMTime: if (volRec) NtfsTimeToProp(volRec->SiAttr.MTime, prop); break; + case kpidShortComment: case kpidVolumeName: { - for (int i = 0; i < VolAttrs.Size(); i++) + FOR_VECTOR (i, VolAttrs) { const CAttr &attr = VolAttrs[i]; if (attr.Type == ATTR_TYPE_VOLUME_NAME) { UString name; - GetString(attr.Data, (int)attr.Data.GetCapacity() / 2, name); + GetString(attr.Data, (unsigned)attr.Data.Size() / 2, name); prop = name; break; } @@ -1541,7 +2304,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidFileSystem: { AString s = "NTFS"; - for (int i = 0; i < VolAttrs.Size(); i++) + FOR_VECTOR (i, VolAttrs) { const CAttr &attr = VolAttrs[i]; if (attr.Type == ATTR_TYPE_VOLUME_INFO) @@ -1564,7 +2327,31 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) break; } case kpidSectorSize: prop = (UInt32)1 << Header.SectorSizeLog; break; + case kpidRecordSize: prop = (UInt32)1 << RecSizeLog; break; case kpidId: prop = Header.SerialNumber; break; + + case kpidIsTree: prop = true; break; + case kpidIsDeleted: prop = _showDeletedFiles; break; + case kpidIsAltStream: prop = ThereAreAltStreams; break; + case kpidIsAux: prop = true; break; + case kpidINode: prop = true; break; + + case kpidWarning: + if (_lostFolderIndex_Normal >= 0) + prop = "There are lost files"; + + /* + case kpidWarningFlags: + { + UInt32 flags = 0; + if (_headerWarning) + flags |= k_ErrorFlags_HeadersError; + if (flags != 0) + prop = flags; + break; + } + */ + // case kpidMediaType: prop = Header.MediaType; break; // case kpidSectorsPerTrack: prop = Header.SectorsPerTrack; break; // case kpidNumHeads: prop = Header.NumHeads; break; @@ -1578,7 +2365,26 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; + NCOM::CPropVariant prop; + if (index >= Items.Size()) + { + switch (propID) + { + case kpidName: + case kpidPath: + prop = VirtFolderNames[index - Items.Size()]; + break; + case kpidIsDir: prop = true; break; + case kpidIsAux: prop = true; break; + case kpidIsDeleted: + if ((int)index == _lostFolderIndex_Deleted) + prop = true; + break; + } + prop.Detach(value); + return S_OK; + } + const CItem &item = Items[index]; const CMftRec &rec = Recs[item.RecIndex]; @@ -1586,30 +2392,108 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val if (item.DataIndex >= 0) data = &rec.DataAttrs[rec.DataRefs[item.DataIndex].Start]; - switch(propID) + // const CFileNameAttr *fn = &rec.FileNames[item.NameIndex]; + /* + if (rec.FileNames.Size() > 0) + fn = &rec.FileNames[0]; + */ + + switch (propID) { case kpidPath: + GetItemPath(index, prop); + break; + + /* + case kpidLink: + if (!rec.ReparseAttr.SubsName.IsEmpty()) + { + prop = rec.ReparseAttr.SubsName; + } + break; + case kpidLink2: + if (!rec.ReparseAttr.PrintName.IsEmpty()) + { + prop = rec.ReparseAttr.PrintName; + } + break; + + case kpidLinkType: + if (rec.ReparseAttr.Tag != 0) + { + prop = (rec.ReparseAttr.Tag & 0xFFFF); + } + break; + */ + + case kpidINode: { - 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; + // const CMftRec &rec = Recs[item.RecIndex]; + // prop = ((UInt64)rec.SeqNumber << 48) | item.RecIndex; + prop = item.RecIndex; + break; + } + + case kpidName: + { + // prop = item.Name; + const UString *s; + if (rec.IsAltStream(item.DataIndex)) + { + const CAttr &data = rec.DataAttrs[rec.DataRefs[item.DataIndex].Start]; + s = &data.Name; + if (item.ParentHost < 0) + { + UString s2 = rec.FileNames[item.NameIndex].Name; + s2 += L':'; + s2 += *s; + prop = s2; + break; + } + } + else + { + s = &rec.FileNames[item.NameIndex].Name; + } + prop = *s; + break; } case kpidIsDir: prop = item.IsDir(); break; + case kpidIsAltStream: prop = rec.IsAltStream(item.DataIndex); break; + case kpidIsDeleted: prop = !rec.InUse(); break; + case kpidIsAux: prop = false; 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 kpidRecMTime: if (fn) NtfsTimeToProp(rec.SiAttr.ThisRecMTime, prop); break; + + /* + case kpidMTime2: if (fn) NtfsTimeToProp(fn->MTime, prop); break; + case kpidCTime2: if (fn) NtfsTimeToProp(fn->CTime, prop); break; + case kpidATime2: if (fn) NtfsTimeToProp(fn->ATime, prop); break; + case kpidRecMTime2: if (fn) NtfsTimeToProp(fn->ThisRecMTime, prop); break; + */ + case kpidAttrib: - prop = item.Attrib; + { + UInt32 attrib; + /* WinXP-64: The CFileNameAttr::Attrib is not updated after some changes. Why? + CSiAttr:attrib is updated better. So we use CSiAttr:Sttrib */ + /* + if (fn) + attrib = fn->Attrib; + else + */ + attrib = rec.SiAttr.Attrib; + if (item.IsDir()) + attrib |= FILE_ATTRIBUTE_DIRECTORY; + + prop = attrib; break; + } case kpidLinks: prop = rec.MyNumNameLinks; break; case kpidSize: if (data) prop = data->GetSize(); break; case kpidPackSize: if (data) prop = data->GetPackSize(); break; @@ -1654,7 +2538,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = Items.Size(); if (numItems == 0) @@ -1663,9 +2547,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, UInt64 totalSize = 0; for (i = 0; i < numItems; i++) { + UInt32 index = allFilesMode ? i : indices[i]; + if (index >= (UInt32)Items.Size()) + continue; const CItem &item = Items[allFilesMode ? i : indices[i]]; const CMftRec &rec = Recs[item.RecIndex]; - if (!rec.IsDir()) + if (item.DataIndex >= 0) totalSize += rec.GetSize(item.DataIndex); } RINOK(extractCallback->SetTotal(totalSize)); @@ -1673,9 +2560,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, UInt64 totalPackSize; totalSize = totalPackSize = 0; - CByteBuffer buf; UInt32 clusterSize = Header.ClusterSize(); - buf.SetCapacity(clusterSize); + CByteBuffer buf(clusterSize); NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); CMyComPtr copyCoder = copyCoderSpec; @@ -1696,17 +2582,18 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 askMode = testMode ? NExtract::NAskMode::kTest : NExtract::NAskMode::kExtract; - Int32 index = allFilesMode ? i : indices[i]; + UInt32 index = allFilesMode ? i : indices[i]; RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); - const CItem &item = Items[index]; - if (item.IsDir()) + if (index >= (UInt32)Items.Size() || Items[index].IsDir()) { RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); continue; } + const CItem &item = Items[index]; + if (!testMode && !realOutStream) continue; RINOK(extractCallback->PrepareOperation(askMode)); @@ -1723,7 +2610,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CMyComPtr inStream; HRESULT hres = rec.GetStream(InStream, item.DataIndex, Header.ClusterSizeLog, Header.NumClusters, &inStream); if (hres == S_FALSE) - res = NExtract::NOperationResult::kUnSupportedMethod; + res = NExtract::NOperationResult::kUnsupportedMethod; else { RINOK(hres); @@ -1750,15 +2637,46 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { - *numItems = Items.Size(); + *numItems = Items.Size() + VirtFolderNames.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) +{ + InitProps(); + + for (UInt32 i = 0; i < numProps; i++) + { + UString name = names[i]; + name.MakeLower_Ascii(); + if (name.IsEmpty()) + return E_INVALIDARG; + + const PROPVARIANT &prop = values[i]; + + if (name.IsEqualTo("ld")) + { + RINOK(PROPVARIANT_to_bool(prop, _showDeletedFiles)); + } + else if (name.IsEqualTo("ls")) + { + RINOK(PROPVARIANT_to_bool(prop, _showSystemFiles)); + } + else + return E_INVALIDARG; + } return S_OK; } -static IInArchive *CreateArc() { return new CHandler; } +IMP_CreateArcIn static CArcInfo g_ArcInfo = - { L"NTFS", L"ntfs img", 0, 0xD9, { 'N', 'T', 'F', 'S', ' ', ' ', ' ', ' ', 0 }, 9, false, CreateArc, 0 }; + { "NTFS", "ntfs img", 0, 0xD9, + 9, { 'N', 'T', 'F', 'S', ' ', ' ', ' ', ' ', 0 }, + 3, + 0, + CreateArc }; -REGISTER_ARC(Fat) +REGISTER_ARC(Ntfs) }} diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp old mode 100755 new mode 100644 index e5946969..08bcd062 --- a/CPP/7zip/Archive/PeHandler.cpp +++ b/CPP/7zip/Archive/PeHandler.cpp @@ -2,15 +2,17 @@ #include "StdAfx.h" +// #include + #include "../../../C/CpuArch.h" -#include "Common/DynamicBuffer.h" -#include "Common/ComTry.h" -#include "Common/IntToString.h" -#include "Common/StringConvert.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 "../../Windows/PropVariantUtils.h" +#include "../../Windows/TimeUtils.h" #include "../Common/LimitedStreams.h" #include "../Common/ProgressUtils.h" @@ -24,21 +26,69 @@ #define Get32(p) GetUi32(p) #define Get64(p) GetUi64(p) +#define G16(offs, v) v = Get16(p + (offs)) +#define G32(offs, v) v = Get32(p + (offs)) +#define G64(offs, v) v = Get64(p + (offs)) + +#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } + using namespace NWindows; namespace NArchive { namespace NPe { -#define NUM_SCAN_SECTIONS_MAX (1 << 6) +static const UInt32 k_Signature = 0x00004550; + +static HRESULT CalcCheckSum(ISequentialInStream *stream, UInt32 size, UInt32 excludePos, UInt32 &res) +{ + const UInt32 kBufSizeMax = (UInt32)1 << 16; + UInt32 bufSize = MyMin(kBufSizeMax, size); + bufSize += (bufSize & 1); + CByteBuffer buffer(bufSize); + Byte *buf = buffer; + UInt32 sum = 0; + UInt32 pos = 0; + for (;;) + { + UInt32 rem = size - pos; + if (rem > bufSize) + rem = bufSize; + if (rem == 0) + break; + size_t processed = rem; + RINOK(ReadStream(stream, buf, &processed)); + + if ((processed & 1) != 0) + buf[processed] = 0; + + for (unsigned j = 0; j < 4; j++) + { + UInt32 e = excludePos + j; + if (pos <= e) + { + e -= pos; + if (e < processed) + buf[e] = 0; + } + } -#define PE_SIG 0x00004550 -#define PE_OptHeader_Magic_32 0x10B -#define PE_OptHeader_Magic_64 0x20B + 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; + } + res = sum + pos; + return S_OK; +} static AString GetDecString(UInt32 v) { - char sz[32]; - ConvertUInt64ToString(v, sz); + char sz[16]; + ConvertUInt32ToString(v, sz); return sz; } @@ -47,65 +97,80 @@ struct CVersion UInt16 Major; UInt16 Minor; - void Parse(const Byte *buf); - AString GetString() const { return GetDecString(Major) + '.' + GetDecString(Minor); } + void Parse(const Byte *p) + { + G16(0, Major); + G16(2, Minor); + } + void ToProp(NCOM::CPropVariant &prop); }; -void CVersion::Parse(const Byte *p) +void CVersion::ToProp(NCOM::CPropVariant &prop) { - Major = Get16(p); - Minor = Get16(p + 2); + char sz[32]; + ConvertUInt32ToString(Major, sz); + unsigned len = MyStringLen(sz); + sz[len] = '.'; + ConvertUInt32ToString(Minor, sz + len + 1); + prop = sz; } -static const UInt32 kHeaderSize = 4 + 20; +static const unsigned kHeaderSize = 4 + 20; +static const unsigned k_OptHeader32_Size_MIN = 96; +static const unsigned k_OptHeader64_Size_MIN = 112; + +static const UInt32 PE_IMAGE_FILE_DLL = (1 << 13); struct CHeader { + UInt16 Machine; UInt16 NumSections; UInt32 Time; UInt32 PointerToSymbolTable; UInt32 NumSymbols; UInt16 OptHeaderSize; UInt16 Flags; - UInt16 Machine; - bool Parse(const Byte *buf); + bool Parse(const Byte *p); + bool IsDll() const { return (Flags & PE_IMAGE_FILE_DLL) != 0; } }; bool CHeader::Parse(const Byte *p) { - if (Get32(p) != PE_SIG) + if (Get32(p) != k_Signature) 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; + G16( 0, Machine); + G16( 2, NumSections); + G32( 4, Time); + G32( 8, PointerToSymbolTable); + G32(12, NumSymbols); + G16(16, OptHeaderSize); + G16(18, Flags); + return OptHeaderSize >= k_OptHeader32_Size_MIN; } struct CDirLink { UInt32 Va; UInt32 Size; - void Parse(const Byte *p); + + CDirLink(): Va(0), Size(0) {} + void Parse(const Byte *p) + { + G32(0, Va); + G32(4, Size); + } }; -void CDirLink::Parse(const Byte *p) -{ - Va = Get32(p); - Size = Get32(p + 4); -} - enum { kDirLink_Certificate = 4, kDirLink_Debug = 6 }; +static const UInt32 kNumDirItemsMax = 16; + struct CDebugEntry { UInt32 Flags; @@ -116,21 +181,25 @@ struct CDebugEntry UInt32 Va; UInt32 Pa; - void Parse(const Byte *p); + void Parse(const Byte *p) + { + G32(0, Flags); + G32(4, Time); + Ver.Parse(p + 8); + G32(12, Type); + G32(16, Size); + G32(20, Va); + G32(24, Pa); + } }; -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 k_CheckSum_Field_Offset = 64; -static const UInt32 kNumDirItemsMax = 16; +static const UInt32 PE_OptHeader_Magic_32 = 0x10B; +static const UInt32 PE_OptHeader_Magic_64 = 0x20B; + +static const UInt32 k_SubSystems_EFI_First = 10; +static const UInt32 k_SubSystems_EFI_Last = 13; struct COptHeader { @@ -178,10 +247,19 @@ struct COptHeader return i; return -1; } + + bool IsSybSystem_EFI() const + { + return + SubSystem >= k_SubSystems_EFI_First && + SubSystem <= k_SubSystems_EFI_Last; + } }; bool COptHeader::Parse(const Byte *p, UInt32 size) { + if (size < k_OptHeader32_Size_MIN) + return false; Magic = Get16(p); switch (Magic) { @@ -194,19 +272,14 @@ bool COptHeader::Parse(const Byte *p, UInt32 size) LinkerVerMajor = p[2]; LinkerVerMinor = p[3]; - bool hdr64 = Is64Bit(); + G32( 4, CodeSize); + G32( 8, InitDataSize); + G32(12, UninitDataSize); + // G32(16, AddressOfEntryPoint); + // G32(20, BaseOfCode); - 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); + G32(32, SectAlign); + G32(36, FileAlign); OsVer.Parse(p + 40); ImageVer.Parse(p + 44); @@ -214,28 +287,39 @@ bool COptHeader::Parse(const Byte *p, UInt32 size) // reserved = Get32(p + 52); - ImageSize = Get32(p + 56); - HeadersSize = Get32(p + 60); - CheckSum = Get32(p + 64); - SubSystem = Get16(p + 68); - DllCharacts = Get16(p + 70); + G32(56, ImageSize); + G32(60, HeadersSize); + G32(64, CheckSum); + G16(68, SubSystem); + G16(70, DllCharacts); - if (hdr64) + UInt32 pos; + if (Is64Bit()) { - StackReserve = Get64(p + 72); - StackCommit = Get64(p + 80); - HeapReserve = Get64(p + 88); - HeapCommit = Get64(p + 96); + if (size < k_OptHeader64_Size_MIN) + return false; + // BaseOfData32 = 0; + G64(24, ImageBase); + G64(72, StackReserve); + G64(80, StackCommit); + G64(88, HeapReserve); + G64(96, HeapCommit); + pos = 108; } else { - StackReserve = Get32(p + 72); - StackCommit = Get32(p + 76); - HeapReserve = Get32(p + 80); - HeapCommit = Get32(p + 84); + // G32(24, BaseOfData32); + G32(28, ImageBase); + G32(72, StackReserve); + G32(76, StackCommit); + G32(80, HeapReserve); + G32(84, HeapCommit); + pos = 92; } - UInt32 pos = (hdr64 ? 108 : 92); - NumDirItems = Get32(p + pos); + + G32(pos, NumDirItems); + if (NumDirItems > (1 << 16)) + return false; pos += 4; if (pos + 8 * NumDirItems != size) return false; @@ -257,28 +341,31 @@ struct CSection UInt32 Flags; UInt32 Time; // UInt16 NumRelocs; - bool IsDebug; bool IsRealSect; + bool IsDebug; bool IsAdditionalSection; CSection(): IsRealSect(false), IsDebug(false), IsAdditionalSection(false) {} - UInt64 GetPackSize() const { return PSize; } - void UpdateTotalSize(UInt32 &totalSize) + void UpdateTotalSize(UInt32 &totalSize) const { UInt32 t = Pa + PSize; - if (t > totalSize) + if (totalSize < t) totalSize = t; } void Parse(const Byte *p); + + int Compare(const CSection &s) const + { + RINOZ(MyCompare(Pa, s.Pa)); + return MyCompare(PSize, s.PSize); + } }; -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 const unsigned kNameSize = 8; static AString GetName(const Byte *name) { - const int kNameSize = 8; AString res; char *p = res.GetBuffer(kNameSize); memcpy(p, name, kNameSize); @@ -290,12 +377,12 @@ static AString GetName(const Byte *name) 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); + G32( 8, VSize); + G32(12, Va); + G32(16, PSize); + G32(20, Pa); + // G16(32, NumRelocs); + G32(36, Flags); } static const CUInt32PCharPair g_HeaderCharacts[] = @@ -352,6 +439,7 @@ static const CUInt32PCharPair g_SectFlags[] = static const CUInt32PCharPair g_MachinePairs[] = { { 0x014C, "x86" }, + { 0x014D, "I860" }, { 0x0162, "MIPS-R3000" }, { 0x0166, "MIPS-R4000" }, { 0x0168, "MIPS-R10000" }, @@ -364,24 +452,31 @@ static const CUInt32PCharPair g_MachinePairs[] = { 0x01A8, "SH5" }, { 0x01C0, "ARM" }, { 0x01C2, "ARM-Thumb" }, + { 0x01C4, "ARM-NT" }, + { 0x01D3, "AM33" }, { 0x01F0, "PPC" }, { 0x01F1, "PPC-FP" }, { 0x0200, "IA-64" }, + { 0x0266, "MIPS-16" }, { 0x0284, "Alpha-64" }, - { 0x0200, "IA-64" }, - { 0x0366, "MIPSFPU" }, + { 0x0366, "MIPS-FPU" }, + { 0x0466, "MIPS-FPU16" }, + { 0x0520, "TriCore" }, + { 0x0CEF, "CEF" }, + { 0x0EBC, "EFI" }, { 0x8664, "x64" }, - { 0x0EBC, "EFI" } + { 0x9041, "M32R" }, + { 0xC0EE, "CEE" } }; static const CUInt32PCharPair g_SubSystems[] = { - { 0, "Unknown" }, - { 1, "Native" }, - { 2, "Windows GUI" }, - { 3, "Windows CUI" }, - { 7, "Posix" }, - { 9, "Windows CE" }, + { 0, "Unknown" }, + { 1, "Native" }, + { 2, "Windows GUI" }, + { 3, "Windows CUI" }, + { 7, "Posix" }, + { 9, "Windows CE" }, { 10, "EFI" }, { 11, "EFI Boot" }, { 12, "EFI Runtime" }, @@ -391,35 +486,35 @@ static const CUInt32PCharPair g_SubSystems[] = 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" + 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; +static const UInt32 kFlag = (UInt32)1 << 31; +static const UInt32 kMask = ~kFlag; struct CTableItem { @@ -428,8 +523,8 @@ struct CTableItem }; -const UInt32 kBmpHeaderSize = 14; -const UInt32 kIconHeaderSize = 22; +static const UInt32 kBmpHeaderSize = 14; +static const UInt32 kIconHeaderSize = 22; struct CResItem { @@ -450,45 +545,110 @@ struct CResItem bool IsIcon() const { return Type == 3; } bool IsString() const { return Type == 6; } bool IsRcData() const { return Type == 10; } + bool IsVersion() const { return Type == 16; } bool IsRcDataOrUnknown() const { return IsRcData() || Type > 64; } }; -struct CStringItem +struct CTextFile { - UInt32 Lang; - UInt32 Size; CByteDynamicBuffer Buf; + size_t FinalSize() const { return Buf.GetPos(); } + void AddChar(Byte c); void AddWChar(UInt16 c); + void AddWChar_Smart(UInt16 c); + void NewLine(); + void AddString(const char *s); + void AddSpaces(int num); + void AddBytes(const Byte *p, size_t len); + + void OpenBlock(int num) + { + AddSpaces(num); + AddChar('{'); + NewLine(); + } + void CloseBlock(int num) + { + AddSpaces(num); + AddChar('}'); + NewLine(); + } }; -void CStringItem::AddChar(Byte c) +void CTextFile::AddChar(Byte c) +{ + Byte *p = Buf.GetCurPtrAndGrow(2); + p[0] = c; + p[1] = 0; +} + +void CTextFile::AddWChar(UInt16 c) { - Buf.EnsureCapacity(Size + 2); - Buf[Size++] = c; - Buf[Size++] = 0; + Byte *p = Buf.GetCurPtrAndGrow(2); + SetUi16(p, c); } -void CStringItem::AddWChar(UInt16 c) +void CTextFile::AddWChar_Smart(UInt16 c) { if (c == '\n') { AddChar('\\'); c = 'n'; } - Buf.EnsureCapacity(Size + 2); - SetUi16(Buf + Size, c); - Size += 2; + AddWChar(c); +} + +void CTextFile::NewLine() +{ + AddChar(0x0D); + AddChar(0x0A); +} + +void CTextFile::AddString(const char *s) +{ + for (;; s++) + { + char c = *s; + if (c == 0) + return; + AddChar(c); + } +} + +void CTextFile::AddSpaces(int num) +{ + for (int i = 0; i < num; i++) + AddChar(' '); +} + +void CTextFile::AddBytes(const Byte *data, size_t size) +{ + Byte *p = Buf.GetCurPtrAndGrow(size); + memcpy(p, data, size); } +struct CStringItem: public CTextFile +{ + UInt32 Lang; +}; + +struct CByteBuffer_WithLang: public CByteBuffer +{ + UInt32 Lang; +}; + + struct CMixItem { int SectionIndex; int ResourceIndex; int StringIndex; + int VersionIndex; - bool IsSectionItem() const { return ResourceIndex < 0 && StringIndex < 0; }; + CMixItem(): SectionIndex(-1), ResourceIndex(-1), StringIndex(-1), VersionIndex(-1) {} + bool IsSectionItem() const { return ResourceIndex < 0 && StringIndex < 0 && VersionIndex < 0; }; }; struct CUsedBitmap @@ -498,113 +658,95 @@ public: void Alloc(size_t size) { size = (size + 7) / 8; - Buf.SetCapacity(size); + Buf.Alloc(size); memset(Buf, 0, size); } + void Free() { - Buf.SetCapacity(0); + Buf.Free(); } - bool SetRange(size_t from, int size) + + bool SetRange(size_t from, unsigned size) { - for (int i = 0; i < size; i++) + for (unsigned 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; + Buf[pos] = (Byte)(b | mask); } return true; } }; +struct CStringKeyValue +{ + UString Key; + UString Value; +}; class CHandler: public IInArchive, public IInArchiveGetStream, + public IArchiveAllowTail, public CMyUnknownImp { CMyComPtr _stream; CObjectVector _sections; UInt32 _peOffset; CHeader _header; - COptHeader _optHeader; UInt32 _totalSize; - UInt32 _totalSizeLimited; Int32 _mainSubfile; + CRecordVector _mixItems; CRecordVector _items; CObjectVector _strings; + CObjectVector _versionFiles; + UString _versionFullString; + UString _versionShortString; + UString _originalFilename; + CObjectVector _versionKeys; CByteBuffer _buf; bool _oneLang; - UString _resourceFileName; + UString _resourcesPrefix; CUsedBitmap _usedRes; bool _parseResources; + bool _checksumError; - CRecordVector _mixItems; + COptHeader _optHeader; + + bool _allowTail; 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); + void AddLangPrefix(UString &s, UInt32 lang) const; 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); + HRESULT OpenResources(unsigned 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; + return item.Offset >= sect.Va && offset <= _buf.Size() && _buf.Size() - offset >= item.Size; } public: - MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + CHandler(): _allowTail(false) {} + + MY_UNKNOWN_IMP3(IInArchive, IInArchiveGetStream, IArchiveAllowTail) INTERFACE_IInArchive(;) STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); + STDMETHOD(AllowTail)(Int32 allowTail); }; -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 { @@ -633,13 +775,15 @@ enum static const STATPROPSTG kArcProps[] = { + // { NULL, kpidWarning, VT_BSTR}, { 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}, + { NULL, kpidName, VT_BSTR}, + { L"Image Size", kpidImageSize, VT_UI4}, { L"Section Alignment", kpidSectAlign, VT_UI4}, { L"File Alignment", kpidFileAlign, VT_UI4}, @@ -656,31 +800,28 @@ static const STATPROPSTG kArcProps[] = { 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"Image Base", kpidImageBase, VT_UI8}, + { NULL, kpidComment, VT_BSTR}, // { L"Address Of Entry Point", kpidAddressOfEntryPoint, VT_UI8}, // { L"Base Of Code", kpidBaseOfCode, VT_UI8}, // { L"Base Of Data", kpidBaseOfData32, VT_UI8}, }; -static const STATPROPSTG kProps[] = +static const Byte 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} + kpidPath, + kpidSize, + kpidPackSize, + kpidVirtualSize, + kpidCharacts, + kpidOffset, + kpidVa, }; 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) +static void TimeToProp(UInt32 unixTime, NCOM::CPropVariant &prop) { if (unixTime != 0) { @@ -694,20 +835,20 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; - switch(propID) + 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); + v.ToProp(prop); break; } - case kpidOsVer: VerToProp(_optHeader.OsVer, prop); break; - case kpidImageVer: VerToProp(_optHeader.ImageVer, prop); break; - case kpidSubsysVer: VerToProp(_optHeader.SubsysVer, prop); break; + case kpidOsVer: _optHeader.OsVer.ToProp(prop); break; + case kpidImageVer: _optHeader.ImageVer.ToProp(prop); break; + case kpidSubsysVer: _optHeader.SubsysVer.ToProp(prop); break; case kpidCodeSize: prop = _optHeader.CodeSize; break; case kpidInitDataSize: prop = _optHeader.InitDataSize; break; case kpidUnInitDataSize: prop = _optHeader.UninitDataSize; break; @@ -715,7 +856,27 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidPhySize: prop = _totalSize; break; case kpidHeadersSize: prop = _optHeader.HeadersSize; break; case kpidChecksum: prop = _optHeader.CheckSum; break; + case kpidComment: if (!_versionFullString.IsEmpty()) prop = _versionFullString; break; + case kpidShortComment: + if (!_versionShortString.IsEmpty()) + prop = _versionShortString; + else + { + PAIR_TO_PROP(g_MachinePairs, _header.Machine, prop); + } + break; + + case kpidName: if (!_originalFilename.IsEmpty()) prop = _originalFilename; break; + case kpidExtension: + if (_header.IsDll()) + prop = _optHeader.IsSybSystem_EFI() ? "efi" : "dll"; + break; + // case kpidIsSelfExe: prop = !_header.IsDll(); break; + + // case kpidError: + case kpidWarning: if (_checksumError) prop = "Checksum error"; 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; @@ -741,6 +902,32 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) COM_TRY_END } +HRESULT CHandler::ReadString(UInt32 offset, UString &dest) const +{ + if ((offset & 1) != 0 || offset >= _buf.Size()) + return S_FALSE; + size_t rem = _buf.Size() - offset; + if (rem < 2) + return S_FALSE; + unsigned len = Get16(_buf + offset); + if ((rem - 2) / 2 < len) + return S_FALSE; + dest.Empty(); + wchar_t *destBuf = dest.GetBuffer(len); + offset += 2; + const Byte *src = _buf + offset; + unsigned i; + for (i = 0; i < len; i++) + { + wchar_t c = (wchar_t)Get16(src + i * 2); + if (c == 0) + break; + destBuf[i] = c; + } + dest.ReleaseBuffer(i); + return S_OK; +} + void CHandler::AddResNameToString(UString &s, UInt32 id) const { if ((id & kFlag) != 0) @@ -748,32 +935,33 @@ void CHandler::AddResNameToString(UString &s, UInt32 id) const UString name; if (ReadString(id & kMask, name) == S_OK) { - if (name.IsEmpty()) - s += L"[]"; - else + const wchar_t *str = L"[]"; + if (name.Len() > 1 && name[0] == '"' && name.Back() == '"') { - if (name.Length() > 1 && name[0] == '"' && name.Back() == '"') - name = name.Mid(1, name.Length() - 2); - s += name; + if (name.Len() != 2) + { + name.DeleteBack(); + str = name.Ptr(1); + } } + else if (!name.IsEmpty()) + str = name; + s += str; return; } } - wchar_t sz[32]; + wchar_t sz[16]; ConvertUInt32ToString(id, sz); s += sz; } -UString CHandler::GetLangPrefix(UInt32 lang) +void CHandler::AddLangPrefix(UString &s, UInt32 lang) const { - 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) @@ -784,43 +972,53 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val if (mixItem.StringIndex >= 0) { const CStringItem &item = _strings[mixItem.StringIndex]; - switch(propID) + switch (propID) { - case kpidPath: prop = GetLangPrefix(item.Lang) + L"string.txt"; break; + case kpidPath: + { + UString s = _resourcesPrefix; + AddLangPrefix(s, item.Lang); + s += L"string.txt"; + prop = s; + break; + } case kpidSize: case kpidPackSize: - prop = (UInt64)item.Size; break; + prop = (UInt64)item.FinalSize(); break; } } - else if (mixItem.ResourceIndex < 0) + else if (mixItem.VersionIndex >= 0) { - const CSection &item = _sections[mixItem.SectionIndex]; - switch(propID) + const CByteBuffer_WithLang &item = _versionFiles[mixItem.VersionIndex]; + 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; + case kpidPath: + { + UString s = _resourcesPrefix; + AddLangPrefix(s, item.Lang); + s += L"version.txt"; + prop = s; + break; + } + case kpidSize: + case kpidPackSize: + prop = (UInt64)item.Size(); break; } } - else + else if (mixItem.ResourceIndex >= 0) { const CResItem &item = _items[mixItem.ResourceIndex]; - switch(propID) + switch (propID) { case kpidPath: { - UString s = GetLangPrefix(item.Lang); + UString s = _resourcesPrefix; + AddLangPrefix(s, item.Lang); { const wchar_t *p = NULL; - if (item.Type < sizeof(g_ResTypes) / sizeof(g_ResTypes[0])) + if (item.Type < ARRAY_SIZE(g_ResTypes)) p = g_ResTypes[item.Type]; - if (p != 0) + if (p) s += p; else AddResNameToString(s, item.Type); @@ -841,6 +1039,24 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidPackSize: prop = (UInt64)item.Size; break; } } + else + { + const CSection &item = _sections[mixItem.SectionIndex]; + switch (propID) + { + case kpidPath: prop = MultiByteToUnicodeString(item.Name); break; + case kpidSize: prop = (UInt64)MyMin(item.PSize, item.VSize); break; + case kpidPackSize: prop = (UInt64)item.PSize; break; + case kpidVirtualSize: prop = (UInt64)item.VSize; 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; + case kpidZerosTailIsAllowed: if (!item.IsRealSect) prop = true; break; + } + } prop.Detach(value); return S_OK; COM_TRY_END @@ -858,11 +1074,11 @@ HRESULT CHandler::LoadDebugSections(IInStream *stream, bool &thereIsSection) return S_FALSE; UInt64 pa = 0; - int i; + unsigned 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) + if (sect.Va <= debugLink.Va && debugLink.Va + debugLink.Size <= sect.Va + sect.PSize) { pa = sect.Pa + (debugLink.Va - sect.Va); break; @@ -870,19 +1086,18 @@ HRESULT CHandler::LoadDebugSections(IInStream *stream, bool &thereIsSection) } if (i == _sections.Size()) { - return S_OK; // Exe for ARM requires S_OK // return S_FALSE; + return S_OK; } - CByteBuffer buffer; - buffer.SetCapacity(debugLink.Size); + CByteBuffer buffer(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++) + for (i = 0; i < numItems; i++) { CDebugEntry de; de.Parse(buf); @@ -890,20 +1105,19 @@ HRESULT CHandler::LoadDebugSections(IInStream *stream, bool &thereIsSection) 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; + UInt32 totalSize = de.Pa + de.Size; if (totalSize > _totalSize) { _totalSize = totalSize; - _sections.Add(sect); thereIsSection = true; + + CSection § = _sections.AddNew(); + 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; } buf += kEntrySize; } @@ -911,31 +1125,13 @@ HRESULT CHandler::LoadDebugSections(IInStream *stream, bool &thereIsSection) 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()) + if ((offset & 3) != 0 || offset >= _buf.Size()) return S_FALSE; - size_t rem = _buf.GetCapacity() - offset; + size_t rem = _buf.Size() - 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; @@ -944,25 +1140,23 @@ HRESULT CHandler::ReadTable(UInt32 offset, CRecordVector &items) if (!_usedRes.SetRange(offset, 16 + numItems * 8)) return S_FALSE; offset += 16; - _oneLang = true; - unsigned i; - for (i = 0; i < numItems; i++) + items.ClearAndReserve(numItems); + for (unsigned i = 0; i < numItems; i++, offset += 8) { - CTableItem item; const Byte *buf = _buf + offset; - offset += 8; + CTableItem item; item.ID = Get32(buf + 0); - if (((item.ID & kFlag) != 0) != (i < numNameItems)) + if ((bool)((item.ID & kFlag) != 0) != (bool)(i < numNameItems)) return S_FALSE; item.Offset = Get32(buf + 4); - items.Add(item); + items.AddInReserved(item); } return S_OK; } static const UInt32 kFileSizeMax = (UInt32)1 << 30; -static const int kNumResItemsMax = (UInt32)1 << 23; -static const int kNumStringLangsMax = 128; +static const unsigned kNumResItemsMax = (unsigned)1 << 23; +static const unsigned kNumStringLangsMax = 256; // BITMAPINFOHEADER struct CBitmapInfoHeader @@ -984,12 +1178,12 @@ 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); + G32( 4, XSize); + G32( 8, YSize); + G16(12, Planes); + G16(14, BitCount); + G32(16, Compression); + G32(20, SizeImage); return true; } @@ -1089,7 +1283,7 @@ bool CHandler::ParseStringRes(UInt32 id, UInt32 lang, const Byte *src, UInt32 si if ((size & 1) != 0) return false; - int i; + unsigned i; for (i = 0; i < _strings.Size(); i++) if (_strings[i].Lang == lang) break; @@ -1097,10 +1291,8 @@ bool CHandler::ParseStringRes(UInt32 id, UInt32 lang, const Byte *src, UInt32 si { if (_strings.Size() >= kNumStringLangsMax) return false; - CStringItem item; - item.Size = 0; + CStringItem &item = _strings.AddNew(); item.Lang = lang; - i = _strings.Add(item); } CStringItem &item = _strings[i]; @@ -1117,41 +1309,603 @@ bool CHandler::ParseStringRes(UInt32 id, UInt32 lang, const Byte *src, UInt32 si if (size - pos < len * 2) return false; char temp[32]; - ConvertUInt32ToString(id + i, temp); + 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); + item.AddWChar_Smart(Get16(src + pos)); + item.NewLine(); } } - return (size == pos); + if (size == pos) + return true; + + // Some rare case files have additional ZERO. + if (size == pos + 2 && Get16(src + pos) == 0) + return true; + + return false; } -HRESULT CHandler::OpenResources(int sectionIndex, IInStream *stream, IArchiveOpenCallback *callback) + +// ---------- VERSION ---------- + +static const UInt32 kMy_VS_FFI_SIGNATURE = 0xFEEF04BD; + +struct CMy_VS_FIXEDFILEINFO { - 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; + // UInt32 Signature; + // UInt32 StrucVersion; + UInt32 VersionMS; + UInt32 VersionLS; + UInt32 ProductVersionMS; + UInt32 ProductVersionLS; + UInt32 FlagsMask; + UInt32 Flags; + UInt32 OS; + UInt32 Type; + UInt32 Subtype; + UInt32 DateMS; + UInt32 DateLS; + + bool Parse(const Byte *p); + void PrintToTextFile(CTextFile &f, CObjectVector &keys); +}; + +bool CMy_VS_FIXEDFILEINFO::Parse(const Byte *p) +{ + if (Get32(p) != kMy_VS_FFI_SIGNATURE) // signature; + return false; + // G32(0x04, StrucVersion); + G32(0x08, VersionMS); + G32(0x0C, VersionLS); + G32(0x10, ProductVersionMS); + G32(0x14, ProductVersionLS); + G32(0x18, FlagsMask); + G32(0x1C, Flags); + G32(0x20, OS); + G32(0x24, Type); + G32(0x28, Subtype); + G32(0x2C, DateMS); + G32(0x40, DateLS); + return true; +} + +static void PrintUInt32(CTextFile &f, UInt32 v) +{ + char s[16]; + ConvertUInt32ToString(v, s); + f.AddString(s); +} + +static void PrintUInt32(UString &dest, UInt32 v) +{ + wchar_t s[16]; + ConvertUInt32ToString(v, s); + dest += s; +} + +static void PrintHex(CTextFile &f, UInt32 val) +{ + char temp[16]; + temp[0] = '0'; + temp[1] = 'x'; + ConvertUInt32ToHex(val, temp + 2); + f.AddString(temp); +} + +static void PrintVersion(CTextFile &f, UInt32 ms, UInt32 ls) +{ + PrintUInt32(f, HIWORD(ms)); f.AddChar(','); + PrintUInt32(f, LOWORD(ms)); f.AddChar(','); + PrintUInt32(f, HIWORD(ls)); f.AddChar(','); + PrintUInt32(f, LOWORD(ls)); +} + +static void PrintVersion(UString &s, UInt32 ms, UInt32 ls) +{ + PrintUInt32(s, HIWORD(ms)); s += L'.'; + PrintUInt32(s, LOWORD(ms)); s += L'.'; + PrintUInt32(s, HIWORD(ls)); s += L'.'; + PrintUInt32(s, LOWORD(ls)); +} + +static const char *k_VS_FileFlags[] = +{ + "DEBUG" + , "PRERELEASE" + , "PATCHED" + , "PRIVATEBUILD" + , "INFOINFERRED" + , "SPECIALBUILD" +}; + +static const CUInt32PCharPair k_VS_FileOS[] = +{ + { 0x10001, "VOS_DOS_WINDOWS16" }, + { 0x10004, "VOS_DOS_WINDOWS32" }, + { 0x20002, "VOS_OS216_PM16" }, + { 0x30003, "VOS_OS232_PM32" }, + { 0x40004, "VOS_NT_WINDOWS32" } +}; + +static const char *k_VS_FileOS_High[] = +{ + "VOS_UNKNOWN" + , "VOS_DOS" + , "VOS_OS216" + , "VOS_OS232" + , "VOS_NT" + , "VOS_WINCE" +}; + +static const UInt32 kMY_VFT_DRV = 3; +static const UInt32 kMY_VFT_FONT = 4; + +static const char *k_VS_FileOS_Low[] = +{ + "VOS__BASE" + , "VOS__WINDOWS16" + , "VOS__PM16" + , "VOS__PM32" + , "VOS__WINDOWS32" +}; + +static const char *k_VS_FileType[] = +{ + "VFT_UNKNOWN" + , "VFT_APP" + , "VFT_DLL" + , "VFT_DRV" + , "VFT_FONT" + , "VFT_VXD" + , "0x6" + , "VFT_STATIC_LIB" +}; + +// Subtype for VFT_DRV Type +static const char *k_VS_FileSubType_DRV[] = +{ + "0" + , "PRINTER" + , "KEYBOARD" + , "LANGUAGE" + , "DISPLAY" + , "MOUSE" + , "NETWORK" + , "SYSTEM" + , "INSTALLABLE" + , "SOUND" + , "COMM" + , "INPUTMETHOD" + , "VERSIONED_PRINTER" +}; + +// Subtype for VFT_FONT Type +static const char *k_VS_FileSubType_FONT[] = +{ + "0" + , "VFT2_FONT_RASTER" + , "VFT2_FONT_VECTOR" + , "VFT2_FONT_TRUETYPE" +}; + +static int FindKey(CObjectVector &v, const UString &key) +{ + FOR_VECTOR (i, v) + if (v[i].Key == key) + return i; + return -1; +} + +static void AddToUniqueUStringVector(CObjectVector &v, const UString &key, const UString &value) +{ + bool needInsert = false; + unsigned i; + for (i = 0; i < v.Size(); i++) + { + if (v[i].Key == key) + { + if (v[i].Value == value) + return; + needInsert = true; + } + else if (needInsert) + break; + } + CStringKeyValue &pair = v.InsertNew(i); + pair.Key = key; + pair.Value = value; +} + +void CMy_VS_FIXEDFILEINFO::PrintToTextFile(CTextFile &f, CObjectVector &keys) +{ + f.AddString("FILEVERSION "); + PrintVersion(f, VersionMS, VersionLS); + f.NewLine(); + + f.AddString("PRODUCTVERSION "); + PrintVersion(f, ProductVersionMS, ProductVersionLS); + f.NewLine(); + + { + UString s; + PrintVersion(s, VersionMS, VersionLS); + AddToUniqueUStringVector(keys, L"FileVersion", s); + } + { + UString s; + PrintVersion(s, ProductVersionMS, ProductVersionLS); + AddToUniqueUStringVector(keys, L"ProductVersion", s); + } + + f.AddString("FILEFLAGSMASK "); + PrintHex(f, FlagsMask); + f.NewLine(); + + f.AddString("FILEFLAGS "); + { + bool wasPrinted = false; + for (unsigned i = 0; i < ARRAY_SIZE(k_VS_FileFlags); i++) + { + if ((Flags & ((UInt32)1 << i)) != 0) + { + if (wasPrinted) + f.AddString(" | "); + f.AddString("VS_FF_"); + f.AddString(k_VS_FileFlags[i]); + wasPrinted = true; + } + } + UInt32 v = Flags & ~(((UInt32)1 << ARRAY_SIZE(k_VS_FileFlags)) - 1); + if (v != 0 || !wasPrinted) + { + if (wasPrinted) + f.AddString(" | "); + PrintHex(f, v); + } + } + f.NewLine(); + + // OS = 0x111230; + f.AddString("FILEOS "); + unsigned i; + for (i = 0; i < ARRAY_SIZE(k_VS_FileOS); i++) + { + const CUInt32PCharPair &pair = k_VS_FileOS[i]; + if (OS == pair.Value) + { + // continue; + // f.AddString("VOS_"); + f.AddString(pair.Name); + break; + } + } + if (i == ARRAY_SIZE(k_VS_FileOS)) + { + UInt32 high = OS >> 16; + if (high < ARRAY_SIZE(k_VS_FileOS_High)) + f.AddString(k_VS_FileOS_High[high]); + else + PrintHex(f, high << 16); + UInt32 low = OS & 0xFFFF; + if (low != 0) + { + f.AddString(" | "); + if (low < ARRAY_SIZE(k_VS_FileOS_Low)) + f.AddString(k_VS_FileOS_Low[low]); + else + PrintHex(f, low); + } + } + f.NewLine(); + + f.AddString("FILETYPE "); + if (Type < ARRAY_SIZE(k_VS_FileType)) + f.AddString(k_VS_FileType[Type]); + else + PrintHex(f, Type); + f.NewLine(); + + f.AddString("FILESUBTYPE "); + bool needPrintSubType = true; + if (Type == kMY_VFT_DRV) + { + if (Subtype != 0 && Subtype < ARRAY_SIZE(k_VS_FileSubType_DRV)) + { + f.AddString("VFT2_DRV_"); + f.AddString(k_VS_FileSubType_DRV[Subtype]); + needPrintSubType = false; + } + } + else if (Type == kMY_VFT_FONT) + { + if (Subtype != 0 && Subtype < ARRAY_SIZE(k_VS_FileSubType_FONT)) + { + f.AddString(k_VS_FileSubType_FONT[Subtype]); + needPrintSubType = false; + } + } + if (needPrintSubType) + PrintHex(f, Subtype); + f.NewLine(); +} + +static void CopyToUString(const Byte *p, UString &s) +{ + for (;;) + { + wchar_t c = (wchar_t)Get16(p); + p += 2; + if (c == 0) + return; + s += c; + } +} + +static bool CompareWStrStrings(const Byte *p, const char *s) +{ + unsigned pos = 0; + for (;;) + { + Byte c = *s++; + if (Get16(p + pos) != c) + return false; + pos += 2; + if (c == 0) + return true; + } +} + +struct CVersionBlock +{ + UInt32 TotalLen; + UInt32 ValueLen; + bool IsTextValue; + int StrSize; + + bool Parse(const Byte *p, UInt32 size); +}; + +static int Get_Utf16Str_Len_InBytes(const Byte *p, size_t size) +{ + unsigned pos = 0; + for (;;) + { + if (pos + 1 >= size) + return -1; + if (Get16(p + pos) == 0) + return pos; + pos += 2; + } +} + +static const unsigned k_ResoureBlockHeader_Size = 6; + +bool CVersionBlock::Parse(const Byte *p, UInt32 size) +{ + if (size < k_ResoureBlockHeader_Size) + return false; + TotalLen = Get16(p); + ValueLen = Get16(p + 2); + if (TotalLen > size) + return false; + switch (Get16(p + 4)) + { + case 0: IsTextValue = false; break; + case 1: IsTextValue = true; break; + default: return false; + } + StrSize = Get_Utf16Str_Len_InBytes(p + k_ResoureBlockHeader_Size, TotalLen - k_ResoureBlockHeader_Size); + return StrSize >= 0; +} + +static void AddParamString(CTextFile &f, const Byte *p, size_t sLen) +{ + f.AddChar(' '); + f.AddChar('\"'); + f.AddBytes(p, sLen); + f.AddChar('\"'); +} + +static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector &keys) +{ + UInt32 pos; + { + const unsigned k_sizeof_VS_FIXEDFILEINFO = 13 * 4; + + CVersionBlock vb; + if (!vb.Parse(p, size)) + return false; + if (vb.ValueLen != k_sizeof_VS_FIXEDFILEINFO) // maybe 0 is allowed here? + return false; + if (vb.IsTextValue) + return false; + pos = k_ResoureBlockHeader_Size; + if (!CompareWStrStrings(p + pos, "VS_VERSION_INFO")) + return false; + pos += vb.StrSize + 2; + pos += (4 - pos) & 3; + if (pos + vb.ValueLen > vb.TotalLen) + return false; + /* sometimes resource contains zeros in remainder. + So we don't check that size != vb.TotalLen + // if (size != vb.TotalLen) return false; + */ + if (size > vb.TotalLen) + size = vb.TotalLen; + CMy_VS_FIXEDFILEINFO FixedFileInfo; + if (!FixedFileInfo.Parse(p + pos)) + return false; + FixedFileInfo.PrintToTextFile(f, keys); + pos += vb.ValueLen; + } + + f.OpenBlock(0); + + for (;;) + { + pos += (4 - pos) & 3; + if (pos >= size) + break; + + CVersionBlock vb; + if (!vb.Parse(p + pos, size - pos)) + return false; + if (vb.ValueLen != 0) + return false; + UInt32 endPos = pos + vb.TotalLen; + pos += k_ResoureBlockHeader_Size; + + f.AddSpaces(2); + f.AddString("BLOCK"); + AddParamString(f, p + pos, vb.StrSize); + + f.NewLine(); + f.OpenBlock(2); + + if (CompareWStrStrings(p + pos, "VarFileInfo")) + { + pos += vb.StrSize + 2; + for (;;) + { + pos += (4 - pos) & 3; + if (pos >= endPos) + break; + CVersionBlock vb2; + if (!vb2.Parse(p + pos, endPos - pos)) + return false; + UInt32 endPos2 = pos + vb2.TotalLen; + if (vb2.IsTextValue) + return false; + pos += k_ResoureBlockHeader_Size; + f.AddSpaces(4); + f.AddString("VALUE"); + AddParamString(f, p + pos, vb2.StrSize); + if (!CompareWStrStrings(p + pos, "Translation")) + return false; + pos += vb2.StrSize + 2; + pos += (4 - pos) & 3; + if (pos + vb2.ValueLen != endPos2) + return false; + if ((vb2.ValueLen & 3) != 0) + return false; + UInt32 num = (vb2.ValueLen >> 2); + for (; num != 0; num--, pos += 4) + { + UInt32 dw = Get32(p + pos); + UInt32 lang = LOWORD(dw); + UInt32 codePage = HIWORD(dw); + + f.AddString(", "); + PrintHex(f, lang); + f.AddString(", "); + PrintUInt32(f, codePage); + } + f.NewLine(); + } + } + else + { + if (!CompareWStrStrings(p + pos, "StringFileInfo")) + return false; + pos += vb.StrSize + 2; + + for (;;) + { + pos += (4 - pos) & 3; + if (pos >= endPos) + break; + CVersionBlock vb2; + if (!vb2.Parse(p + pos, endPos - pos)) + return false; + UInt32 endPos2 = pos + vb2.TotalLen; + if (vb2.ValueLen != 0) + return false; + pos += k_ResoureBlockHeader_Size; + + f.AddSpaces(4); + f.AddString("BLOCK"); + AddParamString(f, p + pos, vb2.StrSize); + pos += vb2.StrSize + 2; + + f.NewLine(); + f.OpenBlock(4); + + for (;;) + { + pos += (4 - pos) & 3; + if (pos >= endPos2) + break; + + CVersionBlock vb3; + if (!vb3.Parse(p + pos, endPos2 - pos)) + return false; + // ValueLen sometimes is a number of characters (not bytes)? + // So we don't use it. + UInt32 endPos3 = pos + vb3.TotalLen; + pos += k_ResoureBlockHeader_Size; + + // we don't write string if it's not text + if (vb3.IsTextValue) + { + f.AddSpaces(6); + f.AddString("VALUE"); + AddParamString(f, p + pos, vb3.StrSize); + UString key; + UString value; + CopyToUString(p + pos, key); + pos += vb3.StrSize + 2; + + pos += (4 - pos) & 3; + if (vb3.ValueLen > 0 && pos + 2 <= endPos3) + { + f.AddChar(','); + f.AddSpaces((34 - (int)vb3.StrSize) / 2); + int sLen = Get_Utf16Str_Len_InBytes(p + pos, endPos3 - pos); + if (sLen < 0) + return false; + AddParamString(f, p + pos, sLen); + CopyToUString(p + pos, value); + pos += sLen + 2; + } + AddToUniqueUStringVector(keys, key, value); + } + pos = endPos3; + f.NewLine(); + } + f.CloseBlock(4); + } + } + f.CloseBlock(2); + } + f.CloseBlock(0); + return true; +} + +HRESULT CHandler::OpenResources(unsigned 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.Alloc(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 << 22)); + RINOK(ReadStream_FALSE(stream, _buf + pos, rem)); + pos += rem; } } @@ -1162,7 +1916,7 @@ HRESULT CHandler::OpenResources(int sectionIndex, IInStream *stream, IArchiveOpe _oneLang = true; bool stringsOk = true; size_t maxOffset = 0; - for (int i = 0; i < specItems.Size(); i++) + FOR_VECTOR (i, specItems) { const CTableItem &item1 = specItems[i]; if ((item1.Offset & kFlag) == 0) @@ -1171,7 +1925,7 @@ HRESULT CHandler::OpenResources(int sectionIndex, IInStream *stream, IArchiveOpe CRecordVector specItems2; RINOK(ReadTable(item1.Offset & kMask, specItems2)); - for (int j = 0; j < specItems2.Size(); j++) + FOR_VECTOR (j, specItems2) { const CTableItem &item2 = specItems2[j]; if ((item2.Offset & kFlag) == 0) @@ -1184,14 +1938,14 @@ HRESULT CHandler::OpenResources(int sectionIndex, IInStream *stream, IArchiveOpe item.Type = item1.ID; item.ID = item2.ID; - for (int k = 0; k < specItems3.Size(); k++) + FOR_VECTOR (k, specItems3) { 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) + if (item3.Offset >= _buf.Size() || _buf.Size() - item3.Offset < 16) return S_FALSE; const Byte *buf = _buf + item3.Offset; item.Lang = item3.ID; @@ -1225,6 +1979,24 @@ HRESULT CHandler::OpenResources(int sectionIndex, IInStream *stream, IArchiveOpe } } + if (item.IsVersion()) + { + if (offset > _buf.Size() || _buf.Size() - offset < item.Size) + continue; + CTextFile f; + if (ParseVersion((const Byte *)_buf + offset, item.Size, f, _versionKeys)) + { + CMixItem mixItem; + mixItem.VersionIndex = _versionFiles.Size(); + mixItem.SectionIndex = sectionIndex; // check it !!!! + CByteBuffer_WithLang &vf = _versionFiles.AddNew(); + vf.Lang = item.Lang; + vf.CopyFrom(f.Buf, f.Buf.GetPos()); + _mixItems.Add(mixItem); + continue; + } + // PrintError("ver.Parse error"); + } item.Enabled = true; _items.Add(item); } @@ -1233,7 +2005,7 @@ HRESULT CHandler::OpenResources(int sectionIndex, IInStream *stream, IArchiveOpe if (stringsOk && !_strings.IsEmpty()) { - int i; + unsigned i; for (i = 0; i < _items.Size(); i++) { CResItem &item = _items[i]; @@ -1242,10 +2014,9 @@ HRESULT CHandler::OpenResources(int sectionIndex, IInStream *stream, IArchiveOpe } for (i = 0; i < _strings.Size(); i++) { - if (_strings[i].Size == 0) + if (_strings[i].FinalSize() == 0) continue; CMixItem mixItem; - mixItem.ResourceIndex = -1; mixItem.StringIndex = i; mixItem.SectionIndex = sectionIndex; _mixItems.Add(mixItem); @@ -1259,7 +2030,8 @@ HRESULT CHandler::OpenResources(int sectionIndex, IInStream *stream, IArchiveOpe { UInt32 mask = (1 << numBits) - 1; size_t end = ((maxOffset + mask) & ~mask); - if (end < sect.VSize && end <= sect.PSize) + // 9.29: we use only PSize. PSize can be larger than VSize + if (/* end < sect.VSize && */ end <= sect.PSize) { CSection sect2; sect2.Flags = 0; @@ -1274,72 +2046,158 @@ HRESULT CHandler::OpenResources(int sectionIndex, IInStream *stream, IArchiveOpe 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); + + // 9.29: we use sect.PSize instead of sect.VSize to support some CAB-SFX + // the code for .rsrc_2 is commented. + sect2.PSize = sect.PSize - (UInt32)maxOffset; + if (sect2.PSize != 0) + { + 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) +static inline bool CheckPeOffset(UInt32 pe) { - const UInt32 kBufSize = 1 << 18; - const UInt32 kSigSize = 2; + return (pe >= 0x40 && pe <= 0x1000 && (pe & 7) == 0); +} - _mainSubfile = -1; +static const unsigned kStartSize = 0x40; + +API_FUNC_static_IsArc IsArc_Pe(const Byte *p, size_t size) +{ + if (size < 2) + return k_IsArc_Res_NEED_MORE; + if (p[0] != 'M' || p[1] != 'Z') + return k_IsArc_Res_NO; + if (size < kStartSize) + return k_IsArc_Res_NEED_MORE; + UInt32 pe = Get32(p + 0x3C); + if (!CheckPeOffset(pe)) + return k_IsArc_Res_NO; + if (pe + kHeaderSize > size) + return k_IsArc_Res_NEED_MORE; + CHeader header; + if (!header.Parse(p + pe)) + return k_IsArc_Res_NO; + return k_IsArc_Res_YES; +} - CByteBuffer buffer; - buffer.SetCapacity(kBufSize); - Byte *buf = buffer; +HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) +{ + { + Byte h[kStartSize]; + _mainSubfile = -1; + RINOK(ReadStream_FALSE(stream, h, kStartSize)); + if (h[0] != 'M' || h[1] != 'Z') + return S_FALSE; + /* most of PE files contain 0x0090 at offset 2. + But some rare PE files contain another values. So we don't use that check. + if (Get16(h + 2) != 0x90) return false; */ + _peOffset = Get32(h + 0x3C); + if (!CheckPeOffset(_peOffset)) + return S_FALSE; + } + { + Byte h[kHeaderSize]; + RINOK(stream->Seek(_peOffset, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream_FALSE(stream, h, kHeaderSize)); + if (!_header.Parse(h)) + return S_FALSE; + } - 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)) + UInt32 bufSize = _header.OptHeaderSize + (UInt32)_header.NumSections * kSectionSize; + _totalSize = _peOffset + kHeaderSize + bufSize; + CByteBuffer buffer(bufSize); + + RINOK(ReadStream_FALSE(stream, buffer, bufSize)); + if (!_optHeader.Parse(buffer, _header.OptHeaderSize)) return S_FALSE; + + UInt32 pos = _header.OptHeaderSize; + unsigned i; + for (i = 0; i < _header.NumSections; i++, pos += kSectionSize) + { + CSection § = _sections.AddNew(); + sect.Parse(buffer + pos); + sect.IsRealSect = true; + + /* PE pre-file in .hxs file has errors: + PSize of resource is larger tnan real size. + So it overlaps next ".its" section. + We correct it. */ + + if (i > 0) + { + CSection &prev = _sections[i - 1]; + if (prev.Pa < sect.Pa && + prev.Pa + prev.PSize > sect.Pa && + sect.PSize > 0) + { + // printf("\n !!!! Section correction: %s\n ", prev.Name); + // fflush(stdout); + prev.PSize = sect.Pa - prev.Pa; + } + } + /* last ".its" section in hxs file has incorrect sect.PSize. + So we reduce it to real sect.VSize */ + if (sect.VSize == 24 && sect.PSize == 512 && i == (unsigned)_header.NumSections - 1) + sect.PSize = sect.VSize; + } + + for (i = 0; i < _sections.Size(); i++) + _sections[i].UpdateTotalSize(_totalSize); + bool thereISDebug; RINOK(LoadDebugSections(stream, thereISDebug)); const CDirLink &certLink = _optHeader.DirItems[kDirLink_Certificate]; if (certLink.Size != 0) { - CSection sect; + CSection § = _sections.AddNew(); sect.Name = "CERTIFICATE"; sect.Va = 0; sect.Pa = certLink.Va; sect.PSize = sect.VSize = certLink.Size; sect.UpdateTotalSize(_totalSize); - _sections.Add(sect); } if (thereISDebug) { + /* sometime there is some data after debug section. + We don't see any reference in exe file to that data. + But we suppose that it's part of EXE file */ + 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); + buffer.Alloc(kAlign); Byte *buf = buffer; size_t processed = size; RINOK(ReadStream(stream, buf, &processed)); + + /* + if (processed != 0) + { + printf("\ndata after debug %d, %d \n", (int)size, (int)processed); + fflush(stdout); + } + */ + 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) @@ -1351,8 +2209,6 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) { 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]; @@ -1362,38 +2218,31 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) return S_FALSE; size += size2; + CSection § = _sections.AddNew(); + sect.Name = "COFF_SYMBOLS"; 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++) + unsigned num = 0; + FOR_VECTOR(i, sections) { const CSection &s = sections[i]; if (s.Pa > limit) { - CSection s2; + CSection &s2 = _sections.AddNew(); 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; @@ -1404,10 +2253,28 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) } } + + if (_optHeader.CheckSum != 0) + { + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + UInt32 checkSum = 0; + RINOK(CalcCheckSum(stream, _totalSize, _peOffset + kHeaderSize + k_CheckSum_Field_Offset, checkSum)); + _checksumError = (checkSum != _optHeader.CheckSum); + } + + + if (!_allowTail) + { + UInt64 fileSize; + RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize)); + if (fileSize > _totalSize) + return S_FALSE; + } + _parseResources = true; + // _parseResources = false; UInt64 mainSize = 0, mainSize2 = 0; - int i; for (i = 0; i < _sections.Size(); i++) { const CSection § = _sections[i]; @@ -1418,14 +2285,14 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) HRESULT res = OpenResources(i, stream, callback); if (res == S_OK) { - _resourceFileName = GetUnicodeString(sect.Name); - for (int j = 0; j < _items.Size(); j++) + _resourcesPrefix.SetFromAscii(sect.Name); + _resourcesPrefix += WCHAR_PATH_SEPARATOR; + FOR_VECTOR (j, _items) { const CResItem &item = _items[j]; if (item.Enabled) { mixItem.ResourceIndex = j; - mixItem.StringIndex = -1; if (item.IsRcDataOrUnknown()) { if (item.Size >= mainSize) @@ -1440,6 +2307,9 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) _mixItems.Add(mixItem); } } + // 9.29: .rsrc_2 code was commented. + // .rsrc_1 now must include that .rsrc_2 block. + /* if (sect.PSize > sect.VSize) { int numBits = _optHeader.GetNumFileAlignBits(); @@ -1450,7 +2320,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) if (sect.PSize > end) { - CSection sect2; + CSection §2 = _sections.AddNew(); sect2.Flags = 0; sect2.Pa = sect.Pa + end; sect2.Va = sect.Va + end; @@ -1459,18 +2329,16 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) 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) @@ -1498,55 +2366,35 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) } } - 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 (;;) + for (i = 0; i < _versionKeys.Size(); i++) { - 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; - } + if (i != 0) + _versionFullString += L'\n'; + const CStringKeyValue &k = _versionKeys[i]; + _versionFullString += k.Key; + _versionFullString += L": "; + _versionFullString += k.Value; + } - for (size_t i = 0; i < processed; i += 2) + { + int keyIndex = FindKey(_versionKeys, L"OriginalFilename"); + if (keyIndex >= 0) + _originalFilename = _versionKeys[keyIndex].Value; + } + { + int keyIndex = FindKey(_versionKeys, L"FileDescription"); + if (keyIndex >= 0) + _versionShortString = _versionKeys[keyIndex].Value; + } + { + int keyIndex = FindKey(_versionKeys, L"FileVersion"); + if (keyIndex >= 0) { - sum += Get16(buf + i); - sum = (sum + (sum >> 16)) & 0xFFFF; + _versionShortString += L' '; + _versionShortString += _versionKeys[keyIndex].Value; } - pos += (UInt32)processed; - if (rem != processed) - break; } - sum += pos; - res = sum; + return S_OK; } @@ -1565,11 +2413,18 @@ void CHandler::CloseResources() _usedRes.Free(); _items.Clear(); _strings.Clear(); - _buf.SetCapacity(0); + _versionFiles.Clear(); + _buf.Free(); + _versionFullString.Empty(); + _versionShortString.Empty(); + _originalFilename.Empty(); + _versionKeys.Clear(); } STDMETHODIMP CHandler::Close() { + _totalSize = 0; + _checksumError = false; _stream.Release(); _sections.Clear(); _mixItems.Clear(); @@ -1587,7 +2442,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _mixItems.Size(); if (numItems == 0) @@ -1597,12 +2452,16 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, for (i = 0; i < numItems; i++) { const CMixItem &mixItem = _mixItems[allFilesMode ? i : indices[i]]; + UInt64 size; if (mixItem.StringIndex >= 0) - totalSize += _strings[mixItem.StringIndex].Size; - else if (mixItem.ResourceIndex < 0) - totalSize += _sections[mixItem.SectionIndex].GetPackSize(); + size = _strings[mixItem.StringIndex].FinalSize(); + else if (mixItem.VersionIndex >= 0) + size = _versionFiles[mixItem.VersionIndex].Size(); + else if (mixItem.ResourceIndex >= 0) + size = _items[mixItem.ResourceIndex].GetSize(); else - totalSize += _items[mixItem.ResourceIndex].GetSize(); + size = _sections[mixItem.SectionIndex].PSize; + totalSize += size; } extractCallback->SetTotal(totalSize); @@ -1616,15 +2475,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, 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); @@ -1647,27 +2497,26 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (mixItem.StringIndex >= 0) { const CStringItem &item = _strings[mixItem.StringIndex]; - currentItemSize = item.Size; + currentItemSize = item.FinalSize(); if (!testMode && !outStream) continue; RINOK(extractCallback->PrepareOperation(askMode)); if (outStream) - RINOK(WriteStream(outStream, item.Buf, item.Size)); + RINOK(WriteStream(outStream, item.Buf, item.FinalSize())); } - else if (mixItem.ResourceIndex < 0) + else if (mixItem.VersionIndex >= 0) { - currentItemSize = sect.GetPackSize(); + const CByteBuffer &item = _versionFiles[mixItem.VersionIndex]; + currentItemSize = item.Size(); 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); + if (outStream) + RINOK(WriteStream(outStream, item, item.Size())); } - else + else if (mixItem.ResourceIndex >= 0) { const CResItem &item = _items[mixItem.ResourceIndex]; currentItemSize = item.GetSize(); @@ -1685,12 +2534,22 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(WriteStream(outStream, _buf + offset, item.Size)); } } + else + { + currentItemSize = sect.PSize; + 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); + } outStream.Release(); RINOK(extractCallback->SetOperationResult(isOk ? - checkSumOK ? - NExtract::NOperationResult::kOK: - NExtract::NOperationResult::kCRCError: + NExtract::NOperationResult::kOK : NExtract::NOperationResult::kDataError)); } return S_OK; @@ -1714,8 +2573,12 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) if (mixItem.StringIndex >= 0) { const CStringItem &item = _strings[mixItem.StringIndex]; - referenceBuf->Buf.SetCapacity(item.Size); - memcpy(referenceBuf->Buf, item.Buf, item.Size); + referenceBuf->Buf.CopyFrom(item.Buf, item.FinalSize()); + } + else if (mixItem.VersionIndex >= 0) + { + const CByteBuffer &item = _versionFiles[mixItem.VersionIndex]; + referenceBuf->Buf.CopyFrom(item, item.Size()); } else { @@ -1731,7 +2594,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) *stream = streamTemp2.Detach(); return S_OK; } - referenceBuf->Buf.SetCapacity(item.HeaderSize + item.Size); + referenceBuf->Buf.Alloc(item.HeaderSize + item.Size); memcpy(referenceBuf->Buf, item.Header, item.HeaderSize); memcpy(referenceBuf->Buf + item.HeaderSize, _buf + offset, item.Size); } @@ -1742,10 +2605,20 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) COM_TRY_END } -static IInArchive *CreateArc() { return new CHandler; } +STDMETHODIMP CHandler::AllowTail(Int32 allowTail) +{ + _allowTail = IntToBool(allowTail); + return S_OK; +} + +IMP_CreateArcIn static CArcInfo g_ArcInfo = - { L"PE", L"exe dll sys", 0, 0xDD, { 'P', 'E', 0, 0 }, 4, false, CreateArc, 0 }; + { "PE", "exe dll sys", 0, 0xDD, + 2, { 'M', 'Z' }, + 0, + NArcInfoFlags::kPreArc, + CreateArc, NULL, IsArc_Pe }; REGISTER_ARC(Pe) @@ -1758,13 +2631,17 @@ namespace NTe { // Terse Executable (TE) image -/* struct CDataDir { UInt32 Va; UInt32 Size; + + void Parse(const Byte *p) + { + G32(0, Va); + G32(4, Size); + } }; -*/ static const UInt32 kHeaderSize = 40; @@ -1776,8 +2653,10 @@ static bool FindValue(const CUInt32PCharPair *pairs, unsigned num, UInt32 value) return false; } -#define MY_FIND_VALUE(pairs, value) FindValue(pairs, sizeof(pairs) / sizeof(pairs[0]), value) +#define MY_FIND_VALUE(pairs, value) FindValue(pairs, ARRAY_SIZE(pairs), value) +static const UInt32 kNumSection_MAX = 32; + struct CHeader { UInt16 Machine; @@ -1788,41 +2667,65 @@ struct CHeader UInt32 AddressOfEntryPoint; UInt32 BaseOfCode; UInt64 ImageBase; - CDataDir DataDir[2]; // base relocation and debug directory */ + CDataDir DataDir[2]; // base relocation and debug directory - UInt32 ConvertPa(UInt32 pa) const { return pa - StrippedSize + kHeaderSize; } + bool ConvertPa(UInt32 &pa) const + { + if (pa < StrippedSize) + return false; + pa = pa - StrippedSize + kHeaderSize; + return true; + } + bool Parse(const Byte *p); +}; - bool Parse(const Byte *p) +bool CHeader::Parse(const Byte *p) +{ + NumSections = p[4]; + if (NumSections > kNumSection_MAX) + return false; + SubSystem = p[5]; + G16(2, Machine); + G16(6, StrippedSize); + /* + G32(8, AddressOfEntryPoint); + G32(12, BaseOfCode); + G64(16, ImageBase); + */ + for (int i = 0; i < 2; i++) { - if (p[0] != 'V' || p[1] != 'Z') + CDataDir &dd = DataDir[i]; + dd.Parse(p + 24 + i * 8); + if (dd.Size >= ((UInt32)1 << 28)) return false; - Machine = Get16(p + 2); - NumSections = p[4]; - SubSystem = p[5]; - StrippedSize = Get16(p + 6); - /* - AddressOfEntryPoint = Get32(p + 8); - BaseOfCode = Get32(p + 12); - ImageBase = Get64(p + 16); - for (int i = 0; i < 2; i++) - { - const Byte *p2 = p + 24 + i * 8; - DataDir[i].Va = Get32(p2); - DataDir[i].Size = Get32(p2 + 4); - } - */ - return NumSections <= 64 && + } + return MY_FIND_VALUE(NPe::g_MachinePairs, Machine) && MY_FIND_VALUE(NPe::g_SubSystems, SubSystem); - } -}; +} + +API_FUNC_static_IsArc IsArc_Te(const Byte *p, size_t size) +{ + if (size < 2) + return k_IsArc_Res_NEED_MORE; + if (p[0] != 'V' || p[1] != 'Z') + return k_IsArc_Res_NO; + if (size < kHeaderSize) + return k_IsArc_Res_NEED_MORE; + + CHeader h; + if (!h.Parse(p)) + return k_IsArc_Res_NO; + return k_IsArc_Res_YES; +} + struct CSection { - Byte Name[8]; + Byte Name[NPe::kNameSize]; - // UInt32 VSize; + UInt32 VSize; UInt32 Va; UInt32 PSize; UInt32 Pa; @@ -1831,16 +2734,21 @@ struct CSection void Parse(const Byte *p) { - memcpy(Name, p, 8); - // VSize = Get32(p + 8); - Va = Get32(p + 12); - PSize = Get32(p + 16); - Pa = Get32(p + 20); - // NumRelocs = Get16(p + 32); - Flags = Get32(p + 36); + memcpy(Name, p, NPe::kNameSize); + G32(8, VSize); + G32(12, Va); + G32(16, PSize); + G32(20, Pa); + // G32(p + 32, NumRelocs); + G32(36, Flags); } - bool Check() const { return (PSize + Pa > Pa); } + bool Check() const + { + return + Pa <= ((UInt32)1 << 30) && + PSize <= ((UInt32)1 << 30); + } void UpdateTotalSize(UInt32 &totalSize) { @@ -1853,44 +2761,46 @@ struct CSection class CHandler: public IInArchive, public IInArchiveGetStream, + public IArchiveAllowTail, public CMyUnknownImp { - UInt32 _totalSize; + CRecordVector _items; CMyComPtr _stream; - CObjectVector _items; + UInt32 _totalSize; + bool _allowTail; CHeader _h; - UInt64 _fileSize; HRESULT Open2(IInStream *stream); public: - MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + MY_UNKNOWN_IMP3(IInArchive, IInArchiveGetStream, IArchiveAllowTail) INTERFACE_IInArchive(;) STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); + STDMETHOD(AllowTail)(Int32 allowTail); + CHandler(): _allowTail(false) {} }; -static const STATPROPSTG kProps[] = +static const Byte kProps[] = { - { NULL, kpidPath, VT_BSTR}, - { NULL, kpidSize, VT_UI4}, - { NULL, kpidPackSize, VT_UI4}, - { NULL, kpidCharacts, VT_BSTR}, - { NULL, kpidOffset, VT_UI4}, - { NULL, kpidVa, VT_UI8} + kpidPath, + kpidSize, + kpidVirtualSize, + kpidCharacts, + kpidOffset, + kpidVa }; enum { - kpidSubSystem + kpidSubSystem = kpidUserDefined, // , kpidImageBase }; static const STATPROPSTG kArcProps[] = { - { NULL, kpidPhySize, VT_UI4}, - // { NULL, kpidHeadersSize, VT_UI4}, + // { NULL, kpidHeadersSize, VT_UI4 }, { NULL, kpidCpu, VT_BSTR}, - { L"Subsystem", kpidSubSystem, VT_BSTR}, - // { L"Image Base", kpidImageBase, VT_UI8} + { L"Subsystem", kpidSubSystem, VT_BSTR }, + // { L"Image Base", kpidImageBase, VT_UI8 } }; IMP_IInArchive_Props @@ -1900,7 +2810,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; - switch(propID) + switch (propID) { case kpidPhySize: prop = _totalSize; break; case kpidCpu: PAIR_TO_PROP(NPe::g_MachinePairs, _h.Machine, prop); break; @@ -1922,11 +2832,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val NCOM::CPropVariant prop; { const CSection &item = _items[index]; - switch(propID) + switch (propID) { - case kpidPath: StringToProp(NPe::GetName(item.Name), prop); break; + case kpidPath: prop = MultiByteToUnicodeString(NPe::GetName(item.Name)); break; case kpidSize: case kpidPackSize: prop = (UInt64)item.PSize; break; + case kpidVirtualSize: prop = (UInt64)item.VSize; break; case kpidOffset: prop = item.Pa; break; case kpidVa: prop = item.Va; break; case kpidCharacts: FLAGS_TO_PROP(NPe::g_SectFlags, item.Flags, prop); break; @@ -1941,28 +2852,41 @@ HRESULT CHandler::Open2(IInStream *stream) { Byte h[kHeaderSize]; RINOK(ReadStream_FALSE(stream, h, kHeaderSize)); + if (h[0] != 'V' || h[1] != 'Z') + return S_FALSE; if (!_h.Parse(h)) return S_FALSE; - CByteBuffer buf; - UInt32 headerSize = NPe::kSectionSize * _h.NumSections; - buf.SetCapacity(headerSize); + UInt32 headerSize = NPe::kSectionSize * (UInt32)_h.NumSections; + CByteArr buf(headerSize); RINOK(ReadStream_FALSE(stream, buf, headerSize)); + headerSize += kHeaderSize; - _totalSize = kHeaderSize + headerSize; - - for (UInt32 i = 0; i < headerSize; i += NPe::kSectionSize) + _totalSize = headerSize; + _items.ClearAndReserve(_h.NumSections); + for (UInt32 i = 0; i < _h.NumSections; i++) { CSection sect; - sect.Parse(buf + i); - sect.Pa = _h.ConvertPa(sect.Pa); - _items.Add(sect); - sect.UpdateTotalSize(_totalSize); + sect.Parse(buf + i * NPe::kSectionSize); + if (!_h.ConvertPa(sect.Pa)) + return S_FALSE; + if (sect.Pa < headerSize) + return S_FALSE; if (!sect.Check()) return S_FALSE; + _items.AddInReserved(sect); + sect.UpdateTotalSize(_totalSize); } - return stream->Seek(0, STREAM_SEEK_END, &_fileSize); + if (!_allowTail) + { + UInt64 fileSize; + RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize)); + if (fileSize > _totalSize) + return S_FALSE; + } + + return S_OK; } STDMETHODIMP CHandler::Open(IInStream *inStream, @@ -1984,9 +2908,9 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, STDMETHODIMP CHandler::Close() { + _totalSize = 0; _stream.Release(); _items.Clear(); - _totalSize = 0; return S_OK; } @@ -2000,7 +2924,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _items.Size(); if (numItems == 0) @@ -2041,22 +2965,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, continue; RINOK(extractCallback->PrepareOperation(askMode)); int res = NExtract::NOperationResult::kDataError; - if (item.Pa <= _fileSize) - { - if (testMode) - { - if (item.Pa + item.PSize <= _fileSize) - res = NExtract::NOperationResult::kOK; - } - else - { - RINOK(_stream->Seek(item.Pa, STREAM_SEEK_SET, NULL)); - streamSpec->Init(item.PSize); - RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); - if (copyCoderSpec->TotalSize == item.PSize) - res = NExtract::NOperationResult::kOK; - } - } + + RINOK(_stream->Seek(item.Pa, STREAM_SEEK_SET, NULL)); + streamSpec->Init(item.PSize); + RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); + if (copyCoderSpec->TotalSize == item.PSize) + res = NExtract::NOperationResult::kOK; + realOutStream.Release(); RINOK(extractCallback->SetOperationResult(res)); } @@ -2072,10 +2987,20 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) COM_TRY_END } -static IInArchive *CreateArc() { return new CHandler; } +STDMETHODIMP CHandler::AllowTail(Int32 allowTail) +{ + _allowTail = IntToBool(allowTail); + return S_OK; +} + +IMP_CreateArcIn static CArcInfo g_ArcInfo = - { L"TE", L"te", 0, 0xCF, { 'V', 'Z' }, 2, false, CreateArc, 0 }; + { "TE", "te", 0, 0xCF, + 2, { 'V', 'Z' }, + 0, + NArcInfoFlags::kPreArc, + CreateArc, NULL, IsArc_Te }; REGISTER_ARC(TE) diff --git a/CPP/7zip/Archive/PpmdHandler.cpp b/CPP/7zip/Archive/PpmdHandler.cpp old mode 100755 new mode 100644 index 9b2ef048..70e9ffac --- a/CPP/7zip/Archive/PpmdHandler.cpp +++ b/CPP/7zip/Archive/PpmdHandler.cpp @@ -11,12 +11,12 @@ This code is based on: #include "../../../C/Ppmd7.h" #include "../../../C/Ppmd8.h" -#include "Common/ComTry.h" -#include "Common/IntToString.h" -#include "Common/StringConvert.h" +#include "../../Common/ComTry.h" +#include "../../Common/IntToString.h" +#include "../../Common/StringConvert.h" -#include "Windows/PropVariant.h" -#include "Windows/Time.h" +#include "../../Windows/PropVariant.h" +#include "../../Windows/TimeUtils.h" #include "../Common/CWrappers.h" #include "../Common/ProgressUtils.h" @@ -75,11 +75,12 @@ HRESULT CItem::ReadHeader(ISequentialInStream *s, UInt32 &headerSize) 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; + + if (Ver < 6 || Ver > 11) return S_FALSE; UInt32 nameLen = GetUi16(h + 10); Restor = nameLen >> 14; @@ -104,8 +105,8 @@ class CHandler: { CItem _item; UInt32 _headerSize; + bool _packSize_Defined; UInt64 _packSize; - bool _packSizeDefined; CMyComPtr _stream; public: @@ -114,12 +115,12 @@ public: STDMETHOD(OpenSeq)(ISequentialInStream *stream); }; -STATPROPSTG kProps[] = +static const Byte kProps[] = { - { NULL, kpidPath, VT_BSTR}, - { NULL, kpidMTime, VT_FILETIME}, - { NULL, kpidAttrib, VT_UI4}, - { NULL, kpidMethod, VT_BSTR} + kpidPath, + kpidMTime, + kpidAttrib, + kpidMethod }; IMP_IInArchive_Props @@ -128,9 +129,9 @@ IMP_IInArchive_ArcProps_NO_Table STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { NCOM::CPropVariant prop; - switch(propID) + switch (propID) { - case kpidPhySize: if (_packSizeDefined) prop = _packSize; break; + case kpidPhySize: if (_packSize_Defined) prop = _packSize; break; } prop.Detach(value); return S_OK; @@ -151,22 +152,23 @@ static void UIntToString(AString &s, const char *prefix, unsigned value) s += temp; } -STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; - switch(propID) + NCOM::CPropVariant prop; + switch (propID) { case kpidPath: prop = MultiByteToUnicodeString(_item.Name, CP_ACP); break; case kpidMTime: { + // time can be in Unix format ??? 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 kpidPackSize: if (_packSize_Defined) prop = _packSize; break; case kpidMethod: { AString s = "PPMd"; @@ -209,7 +211,8 @@ STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) STDMETHODIMP CHandler::Close() { - _packSizeDefined = false; + _packSize = 0; + _packSize_Defined = false; _stream.Release(); return S_OK; } @@ -356,7 +359,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, { if (numItems == 0) return S_OK; - if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0)) + if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) return E_INVALIDARG; // extractCallback->SetTotal(_packSize); @@ -388,7 +391,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CPpmdCpp ppmd(_item.Ver); if (!ppmd.Alloc(_item.MemInMB)) return E_OUTOFMEMORY; - Int32 opRes = NExtract::NOperationResult::kUnSupportedMethod; + Int32 opRes = NExtract::NOperationResult::kUnsupportedMethod; if (_item.IsSupported()) { opRes = NExtract::NOperationResult::kDataError; @@ -428,7 +431,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, outSize += i; _packSize = _headerSize + inBuf.GetProcessed(); - _packSizeDefined = true; + _packSize_Defined = true; if (realOutStream) { RINOK(WriteStream(realOutStream, outBuf.Buf, i)); @@ -446,10 +449,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, return extractCallback->SetOperationResult(opRes); } -static IInArchive *CreateArc() { return new CHandler; } +IMP_CreateArcIn static CArcInfo g_ArcInfo = - { L"Ppmd", L"pmd", 0, 0xD, { 0x8F, 0xAF, 0xAC, 0x84 }, 4, false, CreateArc, 0 }; + { "Ppmd", "pmd", 0, 0xD, + 4, { 0x8F, 0xAF, 0xAC, 0x84 }, + 0, + 0, + CreateArc }; REGISTER_ARC(Ppmd) diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp old mode 100755 new mode 100644 index 5d072d34..c4adee41 --- a/CPP/7zip/Archive/Rar/RarHandler.cpp +++ b/CPP/7zip/Archive/Rar/RarHandler.cpp @@ -2,50 +2,104 @@ #include "StdAfx.h" -#include "Common/ComTry.h" -#include "Common/IntToString.h" -#include "Common/StringConvert.h" +#include "../../../../C/CpuArch.h" -#include "Windows/PropVariant.h" -#include "Windows/PropVariantUtils.h" -#include "Windows/Time.h" +#include "../../../Common/ComTry.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/UTFConvert.h" + +#include "../../../Windows/PropVariantUtils.h" +#include "../../../Windows/TimeUtils.h" #include "../../IPassword.h" #include "../../Common/CreateCoder.h" #include "../../Common/FilterCoder.h" +#include "../../Common/LimitedStreams.h" #include "../../Common/MethodId.h" #include "../../Common/ProgressUtils.h" +#include "../../Common/RegisterArc.h" +#include "../../Common/StreamUtils.h" #include "../../Compress/CopyCoder.h" #include "../../Crypto/Rar20Crypto.h" #include "../../Crypto/RarAes.h" +#include "../Common/FindSignature.h" #include "../Common/ItemNameUtils.h" #include "../Common/OutStreamWithCRC.h" #include "RarHandler.h" using namespace NWindows; -using namespace NTime; + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) namespace NArchive { namespace NRar { -static const wchar_t *kHostOS[] = +#define SIGNATURE { 0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00 } + +static const Byte kMarker[NHeader::kMarkerSize] = SIGNATURE; + +bool CItem::IgnoreItem() const { - L"MS DOS", - L"OS/2", - L"Win32", - L"Unix", - L"Mac OS", - L"BeOS" -}; + 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; +} -static const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]); +UInt32 CItem::GetWinAttrib() const +{ + UInt32 a; + switch (HostOS) + { + case NHeader::NFile::kHostMSDOS: + case NHeader::NFile::kHostOS2: + case NHeader::NFile::kHostWin32: + a = Attrib; + break; + default: + a = 0; // must be converted from unix value; + } + if (IsDir()) + a |= NHeader::NFile::kWinFileDirectoryAttributeMask; + return a; +} + +static const char *kHostOS[] = +{ + "MS DOS" + , "OS/2" + , "Win32" + , "Unix" + , "Mac OS" + , "BeOS" +}; -static const wchar_t *kUnknownOS = L"Unknown"; +static const char *kUnknownOS = "Unknown"; static const CUInt32PCharPair k_Flags[] = { @@ -61,75 +115,771 @@ static const CUInt32PCharPair k_Flags[] = { 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} +enum EErrorType +{ + k_ErrorType_OK, + k_ErrorType_Corrupted, + k_ErrorType_UnexpectedEnd, + k_ErrorType_DecryptionError }; -static const STATPROPSTG kArcProps[] = +class CInArchive { - { 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} + IInStream *m_Stream; + UInt64 m_StreamStartPosition; + CBuffer _unicodeNameBuffer; + CByteBuffer _comment; + CByteBuffer m_FileHeaderData; + NHeader::NBlock::CBlock m_BlockHeader; + NCrypto::NRar29::CDecoder *m_RarAESSpec; + CMyComPtr m_RarAES; + CBuffer m_DecryptedData; + Byte *m_DecryptedDataAligned; + UInt32 m_DecryptedDataSize; + bool m_CryptoMode; + UInt32 m_CryptoPos; + + + HRESULT ReadBytesSpec(void *data, size_t *size); + bool ReadBytesAndTestSize(void *data, UInt32 size); + void ReadName(const Byte *p, unsigned nameSize, CItem &item); + bool ReadHeaderReal(const Byte *p, unsigned size, CItem &item); + + HRESULT Open2(IInStream *stream, const UInt64 *searchHeaderSizeLimit); + + void AddToSeekValue(UInt64 addValue) + { + m_Position += addValue; + } + + void FinishCryptoBlock() + { + if (m_CryptoMode) + while ((m_CryptoPos & 0xF) != 0) + { + m_CryptoPos++; + m_Position++; + } + } + +public: + UInt64 m_Position; + CInArcInfo ArcInfo; + bool HeaderErrorWarning; + + HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit); + HRESULT GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPassword, + bool &filled, EErrorType &error); +}; + +static bool CheckHeaderCrc(const Byte *header, size_t headerSize) +{ + return Get16(header) == (UInt16)(CrcCalc(header + 2, headerSize - 2) & 0xFFFF); +} + +HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) +{ + HeaderErrorWarning = false; + m_CryptoMode = false; + RINOK(stream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition)); + RINOK(stream->Seek(0, STREAM_SEEK_END, &ArcInfo.FileSize)); + RINOK(stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL)); + m_Position = m_StreamStartPosition; + + UInt64 arcStartPos = m_StreamStartPosition; + { + Byte marker[NHeader::kMarkerSize]; + RINOK(ReadStream_FALSE(stream, marker, NHeader::kMarkerSize)); + if (memcmp(marker, kMarker, NHeader::kMarkerSize) == 0) + m_Position += NHeader::kMarkerSize; + else + { + if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0) + return S_FALSE; + RINOK(stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL)); + RINOK(FindSignatureInStream(stream, 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); + + ArcInfo.EncryptVersion = 0; + ArcInfo.Flags = Get16(buf + 3); + + UInt32 headerSize = NHeader::NArchive::kArchiveHeaderSize; + if (ArcInfo.IsThereEncryptVer()) + { + if (blockSize <= headerSize) + return S_FALSE; + RINOK(ReadStream_FALSE(stream, buf + NHeader::NArchive::kArchiveHeaderSize, 1)); + AddToSeekValue(1); + ArcInfo.EncryptVersion = buf[NHeader::NArchive::kArchiveHeaderSize]; + headerSize += 1; + } + if (blockSize < headerSize + || buf[2] != NHeader::NBlockType::kArchiveHeader + || !CheckHeaderCrc(buf, headerSize)) + return S_FALSE; + + size_t commentSize = blockSize - headerSize; + _comment.Alloc(commentSize); + RINOK(ReadStream_FALSE(stream, _comment, commentSize)); + AddToSeekValue(commentSize); + m_Stream = stream; + ArcInfo.StartPos = arcStartPos; + return S_OK; +} + +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; +} + +static void DecodeUnicodeFileName(const Byte *name, const Byte *encName, + unsigned encSize, wchar_t *unicodeName, unsigned maxDecSize) +{ + unsigned encPos = 0; + unsigned decPos = 0; + unsigned 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: + { + unsigned len = encName[encPos++]; + if (len & 0x80) + { + Byte correction = encName[encPos++]; + for (len = (len & 0x7f) + 2; + len > 0 && decPos < maxDecSize; len--, decPos++) + unicodeName[decPos] = (wchar_t)(((name[decPos] + correction) & 0xff) + (highByte << 8)); + } + else + for (len += 2; len > 0 && decPos < maxDecSize; len--, decPos++) + unicodeName[decPos] = name[decPos]; + } + break; + } + flags <<= 2; + flagBits -= 2; + } + unicodeName[decPos < maxDecSize ? decPos : maxDecSize - 1] = 0; +} + +void CInArchive::ReadName(const Byte *p, unsigned nameSize, CItem &item) +{ + item.UnicodeName.Empty(); + if (nameSize > 0) + { + unsigned i; + for (i = 0; i < nameSize && p[i] != 0; i++); + item.Name.SetFrom((const char *)p, i); + + if (item.HasUnicodeName()) + { + if (i < nameSize) + { + i++; + unsigned uNameSizeMax = MyMin(nameSize, (unsigned)0x400); + _unicodeNameBuffer.AllocAtLeast(uNameSizeMax + 1); + DecodeUnicodeFileName(p, p + i, nameSize - i, _unicodeNameBuffer, uNameSizeMax); + item.UnicodeName = _unicodeNameBuffer; + } + else if (!ConvertUTF8ToUnicode(item.Name, item.UnicodeName)) + item.UnicodeName.Empty(); + } + } + else + item.Name.Empty(); +} + +static int ReadTime(const Byte *p, unsigned size, Byte mask, CRarTime &rarTime) +{ + rarTime.LowSecond = (Byte)(((mask & 4) != 0) ? 1 : 0); + unsigned numDigits = (mask & 3); + rarTime.SubTime[0] = + rarTime.SubTime[1] = + rarTime.SubTime[2] = 0; + if (numDigits > size) + return -1; + for (unsigned i = 0; i < numDigits; i++) + rarTime.SubTime[3 - numDigits + i] = p[i]; + return numDigits; +} + +#define READ_TIME(_mask_, _ttt_) \ + { int size2 = ReadTime(p, size, _mask_, _ttt_); if (size2 < 0) return false; p += size2, size -= size2; } + +#define READ_TIME_2(_mask_, _def_, _ttt_) \ + _def_ = ((_mask_ & 8) != 0); if (_def_) \ + { if (size < 4) return false; \ + _ttt_ ## .DosTime = Get32(p); p += 4; size -= 4; \ + READ_TIME(_mask_, _ttt_); } \ + +bool CInArchive::ReadHeaderReal(const Byte *p, unsigned size, CItem &item) +{ + const Byte *pStart = p; + + item.Clear(); + item.Flags = m_BlockHeader.Flags; + + const unsigned kFileHeaderSize = 25; + + if (size < kFileHeaderSize) + return false; + + item.PackSize = Get32(p); + item.Size = Get32(p + 4); + item.HostOS = p[8]; + item.FileCRC = Get32(p + 9); + item.MTime.DosTime = Get32(p + 13); + item.UnPackVersion = p[17]; + item.Method = p[18]; + unsigned nameSize = Get16(p + 19); + item.Attrib = Get32(p + 21); + + item.MTime.LowSecond = 0; + item.MTime.SubTime[0] = + item.MTime.SubTime[1] = + item.MTime.SubTime[2] = 0; + + p += kFileHeaderSize; + size -= kFileHeaderSize; + if ((item.Flags & NHeader::NFile::kSize64Bits) != 0) + { + if (size < 8) + return false; + item.PackSize |= ((UInt64)Get32(p) << 32); + item.Size |= ((UInt64)Get32(p + 4) << 32); + p += 8; + size -= 8; + } + if (nameSize > size) + return false; + ReadName(p, nameSize, item); + p += nameSize; + size -= nameSize; + + /* + // It was commented, since it's difficult to support alt Streams for solid archives. + if (m_BlockHeader.Type == NHeader::NBlockType::kSubBlock) + { + if (item.HasSalt()) + { + if (size < sizeof(item.Salt)) + return false; + size -= sizeof(item.Salt); + p += sizeof(item.Salt); + } + if (item.Name == "ACL" && size == 0) + { + item.IsAltStream = true; + item.Name.Empty(); + item.UnicodeName = L".ACL"; + } + else if (item.Name == "STM" && size != 0 && (size & 1) == 0) + { + item.IsAltStream = true; + item.Name.Empty(); + for (UInt32 i = 0; i < size; i += 2) + { + wchar_t c = Get16(p + i); + if (c == 0) + return false; + item.UnicodeName += c; + } + } + } + */ + + if (item.HasSalt()) + { + if (size < sizeof(item.Salt)) + return false; + for (unsigned i = 0; i < sizeof(item.Salt); i++) + item.Salt[i] = p[i]; + p += sizeof(item.Salt); + size -= sizeof(item.Salt); + } + + // some rar archives have HasExtTime flag without field. + if (size >= 2 && item.HasExtTime()) + { + Byte aMask = (Byte)(p[0] >> 4); + Byte b = p[1]; + p += 2; + size -= 2; + Byte mMask = (Byte)(b >> 4); + Byte cMask = (Byte)(b & 0xF); + if ((mMask & 8) != 0) + { + READ_TIME(mMask, item.MTime); + } + READ_TIME_2(cMask, item.CTimeDefined, item.CTime); + READ_TIME_2(aMask, item.ATimeDefined, item.ATime); + } + + unsigned fileHeaderWithNameSize = 7 + (unsigned)(p - pStart); + + 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); + + // return (m_BlockHeader.Type != NHeader::NBlockType::kSubBlock || item.IsAltStream); + return true; +} + +HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPassword, bool &filled, EErrorType &error) +{ + filled = false; + error = k_ErrorType_OK; + for (;;) + { + m_Stream->Seek(m_Position, STREAM_SEEK_SET, NULL); + ArcInfo.EndPos = m_Position; + if (!m_CryptoMode && (ArcInfo.Flags & + NHeader::NArchive::kBlockHeadersAreEncrypted) != 0) + { + m_CryptoMode = false; + if (getTextPassword == 0) + { + error = k_ErrorType_DecryptionError; + return S_OK; // return S_FALSE; + } + if (!m_RarAES) + { + m_RarAESSpec = new NCrypto::NRar29::CDecoder; + m_RarAES = m_RarAESSpec; + } + m_RarAESSpec->SetRar350Mode(ArcInfo.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)) + unsigned len = 0; + if (password) + len = MyStringLen((BSTR)password); + CByteBuffer buffer(len * 2); + for (unsigned i = 0; i < len; i++) + { + wchar_t c = password[i]; + ((Byte *)buffer)[i * 2] = (Byte)c; + ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); + } + + RINOK(m_RarAESSpec->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size())); + + const UInt32 kDecryptedBufferSize = (1 << 12); + if (m_DecryptedData.Size() == 0) + { + const UInt32 kAlign = 16; + m_DecryptedData.Alloc(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.AllocAtLeast(7); + size_t processed = 7; + RINOK(ReadBytesSpec((Byte *)m_FileHeaderData, &processed)); + if (processed != 7) + { + if (processed != 0) + error = k_ErrorType_UnexpectedEnd; + ArcInfo.EndPos = m_Position + processed; // test it + return S_OK; + } + + const Byte *p = m_FileHeaderData; + m_BlockHeader.CRC = Get16(p + 0); + m_BlockHeader.Type = p[2]; + m_BlockHeader.Flags = Get16(p + 3); + m_BlockHeader.HeadSize = Get16(p + 5); + + if (m_BlockHeader.HeadSize < 7) + { + error = k_ErrorType_Corrupted; + return S_OK; + // ThrowExceptionWithCode(CInArchiveException::kIncorrectArchive); + } + + if (m_BlockHeader.Type < NHeader::NBlockType::kFileHeader || + m_BlockHeader.Type > NHeader::NBlockType::kEndOfArchive) + { + error = m_CryptoMode ? + k_ErrorType_DecryptionError : + k_ErrorType_Corrupted; + return S_OK; + } + + if (m_BlockHeader.Type == NHeader::NBlockType::kEndOfArchive) + { + bool footerError = false; + + unsigned expectHeadLen = 7; + if (m_BlockHeader.Flags & NHeader::NArchive::kEndOfArc_Flags_DataCRC) + expectHeadLen += 4; + if (m_BlockHeader.Flags & NHeader::NArchive::kEndOfArc_Flags_VolNumber) + expectHeadLen += 2; + if (m_BlockHeader.Flags & NHeader::NArchive::kEndOfArc_Flags_RevSpace) + expectHeadLen += 7; + + // rar 5.0 beta 1 writes incorrect RevSpace and headSize + + if (m_BlockHeader.HeadSize < expectHeadLen) + HeaderErrorWarning = true; + + if (m_BlockHeader.HeadSize > 7) + { + /* We suppose that EndOfArchive header is always small. + It's only 20 bytes for multivolume + Fix the limit, if larger footers are possible */ + if (m_BlockHeader.HeadSize > (1 << 8)) + footerError = true; + else + { + if (m_FileHeaderData.Size() < m_BlockHeader.HeadSize) + m_FileHeaderData.ChangeSize_KeepData(m_BlockHeader.HeadSize, 7); + UInt32 afterSize = m_BlockHeader.HeadSize - 7; + if (ReadBytesAndTestSize(m_FileHeaderData + 7, afterSize)) + processed += afterSize; + else + { + if (!m_CryptoMode) + { + error = k_ErrorType_UnexpectedEnd; + return S_OK; + } + footerError = true; + } + } + } + + if (footerError || !CheckHeaderCrc(m_FileHeaderData, m_BlockHeader.HeadSize)) + { + error = m_CryptoMode ? + k_ErrorType_DecryptionError : + k_ErrorType_Corrupted; + } + else + { + ArcInfo.EndFlags = m_BlockHeader.Flags; + UInt32 offset = 7; + if (m_BlockHeader.Flags & NHeader::NArchive::kEndOfArc_Flags_DataCRC) + { + if (processed < offset + 4) + error = k_ErrorType_Corrupted; + else + ArcInfo.DataCRC = Get32(m_FileHeaderData + offset); + offset += 4; + } + if (m_BlockHeader.Flags & NHeader::NArchive::kEndOfArc_Flags_VolNumber) + { + if (processed < offset + 2) + error = k_ErrorType_Corrupted; + ArcInfo.VolNumber = (UInt32)Get16(m_FileHeaderData + offset); + } + } + m_Position += processed; + FinishCryptoBlock(); + ArcInfo.EndPos = m_Position; + return S_OK; + } + + if (m_BlockHeader.Type == NHeader::NBlockType::kFileHeader + /* || m_BlockHeader.Type == NHeader::NBlockType::kSubBlock */) + { + if (m_FileHeaderData.Size() < m_BlockHeader.HeadSize) + m_FileHeaderData.ChangeSize_KeepData(m_BlockHeader.HeadSize, 7); + // m_CurData = (Byte *)m_FileHeaderData; + // m_PosLimit = m_BlockHeader.HeadSize; + if (!ReadBytesAndTestSize(m_FileHeaderData + 7, m_BlockHeader.HeadSize - 7)) + { + error = k_ErrorType_UnexpectedEnd; + return S_OK; + } + + bool okItem = ReadHeaderReal(m_FileHeaderData + 7, m_BlockHeader.HeadSize - 7, item); + if (okItem) + { + if (!CheckHeaderCrc(m_FileHeaderData, m_BlockHeader.HeadSize - item.CommentSize)) + { + error = k_ErrorType_Corrupted; // ThrowExceptionWithCode(CInArchiveException::kFileHeaderCRCError); + return S_OK; + } + filled = true; + } + + FinishCryptoBlock(); + m_CryptoMode = false; + // Move Position to compressed Data; + m_Stream->Seek(m_Position, STREAM_SEEK_SET, NULL); + AddToSeekValue(item.PackSize); // m_Position points to next header; + // if (okItem) + return S_OK; + /* + else + continue; + */ + } + if (m_CryptoMode && m_BlockHeader.HeadSize > (1 << 10)) + { + error = k_ErrorType_DecryptionError; + return S_OK; + } + if ((m_BlockHeader.Flags & NHeader::NBlock::kLongBlock) != 0) + { + if (m_FileHeaderData.Size() < 7 + 4) + m_FileHeaderData.ChangeSize_KeepData(7 + 4, 7); + if (!ReadBytesAndTestSize(m_FileHeaderData + 7, 4)) + { + error = k_ErrorType_UnexpectedEnd; + return S_OK; + } + UInt32 dataSize = Get32(m_FileHeaderData + 7); + AddToSeekValue(dataSize); + if (m_CryptoMode && dataSize > (1 << 27)) + { + error = k_ErrorType_DecryptionError; + return S_OK; + } + m_CryptoPos = m_BlockHeader.HeadSize; + } + else + m_CryptoPos = 0; + + { + UInt64 newPos = m_Position + m_BlockHeader.HeadSize; + if (newPos > ArcInfo.FileSize) + { + error = k_ErrorType_UnexpectedEnd; + return S_OK; + } + } + AddToSeekValue(m_BlockHeader.HeadSize); + FinishCryptoBlock(); + m_CryptoMode = false; + } +} + + +static const Byte kProps[] = +{ + kpidPath, + kpidIsDir, + kpidSize, + kpidPackSize, + kpidMTime, + kpidCTime, + kpidATime, + kpidAttrib, + + kpidEncrypted, + kpidSolid, + kpidCommented, + kpidSplitBefore, + kpidSplitAfter, + kpidCRC, + kpidHostOS, + kpidMethod, + kpidUnpackVer +}; + +static const Byte kArcProps[] = +{ + kpidTotalPhySize, + kpidCharacts, + kpidSolid, + kpidNumBlocks, + // kpidEncrypted, + kpidIsVolume, + kpidVolumeIndex, + kpidNumVolumes + // kpidCommented }; IMP_IInArchive_Props IMP_IInArchive_ArcProps -UInt64 CHandler::GetPackSize(int refIndex) const +UInt64 CHandler::GetPackSize(unsigned refIndex) const { const CRefItem &refItem = _refItems[refIndex]; UInt64 totalPackSize = 0; - for (int i = 0; i < refItem.NumItems; i++) + for (unsigned i = 0; i < refItem.NumItems; i++) totalPackSize += _items[refItem.ItemIndex + i].PackSize; return totalPackSize; } +bool CHandler::IsSolid(unsigned refIndex) const +{ + const CItem &item = _items[_refItems[refIndex].ItemIndex]; + if (item.UnPackVersion < 20) + { + if (_arcInfo.IsSolid()) + return (refIndex > 0); + return false; + } + return item.IsSolid(); +} + STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; - switch(propID) + 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 kpidVolumeIndex: if (_arcInfo.Is_VolNumber_Defined()) prop = (UInt32)_arcInfo.VolNumber; break; + case kpidSolid: prop = _arcInfo.IsSolid(); break; + case kpidCharacts: + { + AString s = FlagsToString(k_Flags, ARRAY_SIZE(k_Flags), _arcInfo.Flags); + // FLAGS_TO_PROP(k_Flags, _arcInfo.Flags, prop); + if (_arcInfo.Is_DataCRC_Defined()) + { + if (!s.IsEmpty()) + s += ' '; + s += "VolCRC"; + } + prop = s; + break; + } + // case kpidEncrypted: prop = _arcInfo.IsEncrypted(); break; // it's for encrypted names. + case kpidIsVolume: prop = _arcInfo.IsVolume(); break; + case kpidNumVolumes: prop = (UInt32)_arcs.Size(); break; + case kpidOffset: if (_arcs.Size() == 1 && _arcInfo.StartPos != 0) prop = _arcInfo.StartPos; break; + + case kpidTotalPhySize: + { + if (_arcs.Size() > 1) + { + UInt64 sum = 0; + FOR_VECTOR (v, _arcs) + sum += _arcs[v].PhySize; + prop = sum; + } + break; + } + + case kpidPhySize: + { + if (_arcs.Size() != 0) + prop = _arcInfo.GetPhySize(); + break; + } + + // case kpidCommented: prop = _arcInfo.IsCommented(); break; + case kpidNumBlocks: { UInt32 numBlocks = 0; - for (int i = 0; i < _refItems.Size(); i++) + FOR_VECTOR (i, _refItems) if (!IsSolid(i)) numBlocks++; prop = (UInt32)numBlocks; break; } - case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break; + + // case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break; + + case kpidErrorFlags: + { + UInt32 v = _errorFlags; + if (!_isArc) + v |= kpv_ErrorFlags_IsNotArc; + prop = v; + break; + } + + case kpidWarningFlags: + { + if (_warningFlags != 0) + prop = _warningFlags; + break; + } + + case kpidExtension: + if (_arcs.Size() == 1) + { + if (_arcInfo.Is_VolNumber_Defined()) + { + char sz[16]; + ConvertUInt32ToString((UInt32)_arcInfo.VolNumber + 1, sz); + unsigned len = MyStringLen(sz); + AString s = "part"; + for (; len < 2; len++) + s += '0'; + s += sz; + s += ".rar"; + prop = s; + } + } + break; } prop.Detach(value); return S_OK; @@ -144,7 +894,7 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) static bool RarTimeToFileTime(const CRarTime &rarTime, FILETIME &result) { - if (!DosTimeToFileTime(rarTime.DosTime, result)) + if (!NTime::DosTimeToFileTime(rarTime.DosTime, result)) return false; UInt64 value = (((UInt64)result.dwHighDateTime) << 32) + result.dwLowDateTime; value += (UInt64)rarTime.LowSecond * 10000000; @@ -156,7 +906,7 @@ static bool RarTimeToFileTime(const CRarTime &rarTime, FILETIME &result) return true; } -static void RarTimeToProp(const CRarTime &rarTime, NWindows::NCOM::CPropVariant &prop) +static void RarTimeToProp(const CRarTime &rarTime, NCOM::CPropVariant &prop) { FILETIME localFileTime, utcFileTime; if (RarTimeToFileTime(rarTime, localFileTime)) @@ -169,22 +919,28 @@ static void RarTimeToProp(const CRarTime &rarTime, NWindows::NCOM::CPropVariant prop = utcFileTime; } -STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; + NCOM::CPropVariant prop; const CRefItem &refItem = _refItems[index]; - const CItemEx &item = _items[refItem.ItemIndex]; + const CItem &item = _items[refItem.ItemIndex]; + /* + const CItem *mainItem = &item; + if (item.BaseFileIndex >= 0) + mainItem = &_items[_refItems[item.BaseFileIndex].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); + if (item.BaseFileIndex >= 0) + u = mainItem->GetName(); + u += item.GetName(); + */ + prop = (const wchar_t *)NItemName::WinNameToOSName(item.GetName()); break; } case kpidIsDir: prop = item.IsDir(); break; @@ -193,7 +949,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va 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 kpidAttrib: prop = item.GetWinAttrib(); break; case kpidEncrypted: prop = item.IsEncrypted(); break; case kpidSolid: prop = IsSolid(index); break; case kpidCommented: prop = item.IsCommented(); break; @@ -201,43 +957,44 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va case kpidSplitAfter: prop = _items[refItem.ItemIndex + refItem.NumItems - 1].IsSplitAfter(); break; case kpidCRC: { - const CItemEx &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1]; + const CItem &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')) + char temp[16]; + char *s = temp; + if (item.Method >= (Byte)'0' && item.Method <= (Byte)'5') { - method = L"m"; - wchar_t temp[32]; - ConvertUInt64ToString(item.Method - Byte('0'), temp); - method += temp; + *s++ = 'm'; + *s++ = (char)item.Method; if (!item.IsDir()) { - method += L":"; - ConvertUInt64ToString(16 + item.GetDictSize(), temp); - method += temp; + *s++ = ':'; + ConvertUInt32ToString(16 + item.GetDictSize(), s); } } else - { - wchar_t temp[32]; - ConvertUInt64ToString(item.Method, temp); - method += temp; - } - prop = method; + ConvertUInt32ToString(item.Method, s); + s += MyStringLen(s); + *s = 0; + prop = s; break; } - case kpidHostOS: prop = (item.HostOS < kNumHostOSes) ? (kHostOS[item.HostOS]) : kUnknownOS; break; + case kpidHostOS: prop = (item.HostOS < ARRAY_SIZE(kHostOS)) ? kHostOS[item.HostOS] : kUnknownOS; break; } prop.Detach(value); return S_OK; COM_TRY_END } +static bool IsDigit(wchar_t c) +{ + return c >= L'0' && c <= L'9'; +} + class CVolumeName { bool _first; @@ -256,23 +1013,23 @@ public: UString basePart = name; if (dotPos >= 0) { - UString ext = name.Mid(dotPos + 1); - if (ext.CompareNoCase(L"rar") == 0) + UString ext = name.Ptr(dotPos + 1); + if (ext.IsEqualToNoCase(L"rar")) { - _afterPart = name.Mid(dotPos); + _afterPart = name.Ptr(dotPos); basePart = name.Left(dotPos); } - else if (ext.CompareNoCase(L"exe") == 0) + else if (ext.IsEqualToNoCase(L"exe")) { _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) + if (ext.IsEqualToNoCase(L"000") || + ext.IsEqualToNoCase(L"001") || + ext.IsEqualToNoCase(L"r00") || + ext.IsEqualToNoCase(L"r01")) { _afterPart.Empty(); _first = false; @@ -291,46 +1048,49 @@ public: 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 + if (basePart.IsEmpty()) return false; - _unchangedPart = basePart.Left(basePart.Length() - numLetters); - _changedPart = basePart.Right(numLetters); + unsigned i = basePart.Len(); + do + if (!IsDigit(basePart[i - 1])) + break; + while (--i); + _unchangedPart = basePart.Left(i); + _changedPart = basePart.Ptr(i); return true; } + /* + void MakeBeforeFirstName() + { + unsigned len = _changedPart.Len(); + _changedPart.Empty(); + for (unsigned i = 0; i < len; i++) + _changedPart += L'0'; + } + */ + UString GetNextName() { UString newName; if (_newStyle || !_first) { - int i; - int numLetters = _changedPart.Length(); - for (i = numLetters - 1; i >= 0; i--) + for (int i = (int)_changedPart.Len() - 1; i >= 0; i--) { wchar_t c = _changedPart[i]; if (c == L'9') { c = L'0'; - newName = c + newName; + newName.InsertAtFront(c); if (i == 0) - newName = UString(L'1') + newName; + newName.InsertAtFront(L'1'); continue; } c++; newName = UString(c) + newName; i--; for (; i >= 0; i--) - newName = _changedPart[i] + newName; + newName.InsertAtFront(_changedPart[i]); break; } _changedPart = newName; @@ -360,17 +1120,18 @@ HRESULT CHandler::Open2(IInStream *stream, openArchiveCallbackWrap.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); } + CInArchive archive; for (;;) { CMyComPtr inStream; - if (!_archives.IsEmpty()) + if (!_arcs.IsEmpty()) { if (!openVolumeCallback) break; - if (_archives.Size() == 1) + if (_arcs.Size() == 1) { - if (!_archiveInfo.IsVolume()) + if (!_arcInfo.IsVolume()) break; UString baseName; { @@ -380,7 +1141,14 @@ HRESULT CHandler::Open2(IInStream *stream, break; baseName = prop.bstrVal; } - seqName.InitName(baseName, _archiveInfo.HaveNewVolumeName()); + if (!seqName.InitName(baseName, _arcInfo.HaveNewVolumeName())) + break; + /* + if (_arcInfo.HaveNewVolumeName() && !_arcInfo.IsFirstVolume()) + { + seqName.MakeBeforeFirstName(); + } + */ } UString fullName = seqName.GetNextName(); @@ -389,47 +1157,54 @@ HRESULT CHandler::Open2(IInStream *stream, break; if (result != S_OK) return result; - if (!stream) + if (!inStream) break; } else inStream = stream; UInt64 endPos = 0; - RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos)); - RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos)); + RINOK(inStream->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; + _isArc = true; + CItem item; for (;;) { if (archive.m_Position > endPos) { - AddErrorMessage("Unexpected end of archive"); + _errorFlags |= kpv_ErrorFlags_UnexpectedEnd; break; } - bool decryptionError; - AString errorMessageLoc; - HRESULT result = archive.GetNextItem(item, getTextPassword, decryptionError, errorMessageLoc); - if (errorMessageLoc) - AddErrorMessage(errorMessageLoc); - if (result == S_FALSE) + EErrorType error; + // bool decryptionError; + // AString errorMessageLoc; + bool filled; + HRESULT result = archive.GetNextItem(item, getTextPassword, filled, error); + if (error != k_ErrorType_OK) + { + if (error == k_ErrorType_UnexpectedEnd) + _errorFlags |= kpv_ErrorFlags_UnexpectedEnd; + else if (error == k_ErrorType_Corrupted) + _errorFlags |= kpv_ErrorFlags_HeadersError; + else if (error == k_ErrorType_DecryptionError) + _errorFlags |= kpv_ErrorFlags_EncryptedHeadersError; + + // AddErrorMessage(errorMessageLoc); + } + RINOK(result); + if (!filled) { - if (decryptionError && _items.IsEmpty()) + if (error == k_ErrorType_DecryptionError && _items.IsEmpty()) return S_FALSE; break; } - RINOK(result); if (item.IgnoreItem()) continue; @@ -448,7 +1223,7 @@ HRESULT CHandler::Open2(IInStream *stream, CRefItem refItem; refItem.ItemIndex = _items.Size(); refItem.NumItems = 1; - refItem.VolumeIndex = _archives.Size(); + refItem.VolumeIndex = _arcs.Size(); _refItems.Add(refItem); } _items.Add(item); @@ -459,10 +1234,38 @@ HRESULT CHandler::Open2(IInStream *stream, RINOK(openCallback->SetCompleted(&numFiles, &numBytes)); } } + + if (archive.HeaderErrorWarning) + _warningFlags |= kpv_ErrorFlags_HeadersError; + + /* + if (archive.m_Position < endPos) + _warningFlags |= kpv_ErrorFlags_DataAfterEnd; + */ + if (_arcs.IsEmpty()) + _arcInfo = archive.ArcInfo; + // _arcInfo.EndPos = archive.EndPos; + curBytes += endPos; - _archives.Add(archive); + { + CArc &arc = _arcs.AddNew(); + arc.PhySize = archive.ArcInfo.GetPhySize(); + arc.Stream = inStream; + } } } + + /* + int baseFileIndex = -1; + for (int i = 0; i < _refItems.Size(); i++) + { + CItem &item = _items[_refItems[i].ItemIndex]; + if (item.IsAltStream) + item.BaseFileIndex = baseFileIndex; + else + baseFileIndex = i; + } + */ return S_OK; } @@ -472,25 +1275,31 @@ STDMETHODIMP CHandler::Open(IInStream *stream, { COM_TRY_BEGIN Close(); - try + // try { HRESULT res = Open2(stream, maxCheckStartPosition, openCallback); + /* if (res != S_OK) Close(); + */ + return res; } - catch(const CInArchiveException &) { Close(); return S_FALSE; } - catch(...) { Close(); throw; } + // catch(const CInArchiveException &) { Close(); return S_FALSE; } + // catch(...) { Close(); throw; } COM_TRY_END } STDMETHODIMP CHandler::Close() { COM_TRY_BEGIN - _errorMessage.Empty(); + // _errorMessage.Empty(); + _errorFlags = 0; + _warningFlags = 0; + _isArc = false; _refItems.Clear(); _items.Clear(); - _archives.Clear(); + _arcs.Clear(); return S_OK; COM_TRY_END } @@ -502,6 +1311,111 @@ struct CMethodItem }; +class CFolderInStream: + public ISequentialInStream, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + +private: + const CObjectVector *_archives; + const CObjectVector *_items; + CRefItem _refItem; + unsigned _curIndex; + UInt32 _crc; + bool _fileIsOpen; + CMyComPtr _stream; + + HRESULT OpenStream(); + HRESULT CloseStream(); +public: + void Init(const CObjectVector *archives, + const CObjectVector *items, + const CRefItem &refItem); + + CRecordVector CRCs; +}; + + +ISequentialInStream* CArc::CreateLimitedStream(UInt64 offset, UInt64 size) const +{ + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStream(streamSpec); + Stream->Seek(offset, STREAM_SEEK_SET, NULL); + streamSpec->SetStream(Stream); + streamSpec->Init(size); + return inStream.Detach(); +} + +void CFolderInStream::Init( + const 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 CItem &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; +} + STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { @@ -511,23 +1425,23 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, // censoredTotalPacked = 0, importantTotalUnPacked = 0; // importantTotalPacked = 0; - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _refItems.Size(); if (numItems == 0) return S_OK; - int lastIndex = 0; + unsigned lastIndex = 0; CRecordVector importantIndexes; CRecordVector extractStatuses; for (UInt32 t = 0; t < numItems; t++) { - int index = allFilesMode ? t : indices[t]; + unsigned index = allFilesMode ? t : indices[t]; const CRefItem &refItem = _refItems[index]; - const CItemEx &item = _items[refItem.ItemIndex]; + const CItem &item = _items[refItem.ItemIndex]; censoredTotalUnPacked += item.Size; // censoredTotalPacked += item.PackSize; - int j; + unsigned j; for (j = lastIndex; j <= index; j++) // if (!_items[_refItems[j].ItemIndex].IsSolid()) if (!IsSolid(j)) @@ -535,9 +1449,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, for (j = lastIndex; j <= index; j++) { const CRefItem &refItem = _refItems[j]; - const CItemEx &item = _items[refItem.ItemIndex]; + const CItem &item = _items[refItem.ItemIndex]; - // const CItemEx &item = _items[j]; + // const CItem &item = _items[j]; importantTotalUnPacked += item.Size; // importantTotalPacked += item.PackSize; @@ -573,7 +1487,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, lps->Init(extractCallback, false); bool solidStart = true; - for (int i = 0; i < importantIndexes.Size(); i++, + for (unsigned i = 0; i < importantIndexes.Size(); i++, currentImportantTotalUnPacked += currentUnPackSize, currentImportantTotalPacked += currentPackSize) { @@ -593,7 +1507,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, UInt32 index = importantIndexes[i]; const CRefItem &refItem = _refItems[index]; - const CItemEx &item = _items[refItem.ItemIndex]; + const CItem &item = _items[refItem.ItemIndex]; currentUnPackSize = item.Size; @@ -617,7 +1531,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (i < importantIndexes.Size() - 1) { // const CRefItem &nextRefItem = _refItems[importantIndexes[i + 1]]; - // const CItemEx &nextItemInfo = _items[nextRefItem.ItemIndex]; + // const CItem &nextItemInfo = _items[nextRefItem.ItemIndex]; // mustBeProcessedAnywhere = nextItemInfo.IsSolid(); mustBeProcessedAnywhere = IsSolid(importantIndexes[i + 1]); } @@ -637,14 +1551,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, realOutStream.Release(); /* - for (int partIndex = 0; partIndex < 1; partIndex++) + for (unsigned partIndex = 0; partIndex < 1; partIndex++) { CMyComPtr inStream; // item redefinition - const CItemEx &item = _items[refItem.ItemIndex + partIndex]; + const CItem &item = _items[refItem.ItemIndex + partIndex]; - NArchive::NRar::CInArchive &archive = _archives[refItem.VolumeIndex + partIndex]; + CInArchive &archive = _arcs[refItem.VolumeIndex + partIndex]; inStream.Attach(archive.CreateLimitedStream(item.GetDataPosition(), item.PackSize)); @@ -655,7 +1569,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, folderInStream = folderInStreamSpec; } - folderInStreamSpec->Init(&_archives, &_items, refItem); + folderInStreamSpec->Init(&_arcs, &_items, refItem); UInt64 packSize = currentPackSize; @@ -694,7 +1608,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, else { outStream.Release(); - RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod)); continue; } RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, @@ -708,25 +1622,25 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, 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++) + UString unicodePassword; + unsigned len = 0; + if (password) + len = MyStringLen((BSTR)password); + CByteBuffer buffer(len * 2); + for (unsigned i = 0; i < len; i++) { - wchar_t c = unicodePassword[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)); + RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size())); } else { - AString oemPassword = UnicodeStringToMultiByte( - (const wchar_t *)password, CP_OEMCP); - RINOK(cryptoSetPassword->CryptoSetPassword( - (const Byte *)(const char *)oemPassword, oemPassword.Length())); + AString oemPassword; + if (password) + oemPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP); + RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)(const char *)oemPassword, oemPassword.Len())); } } else @@ -754,15 +1668,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, case '4': case '5': { - /* - if (item.UnPackVersion >= 29) - { - outStream.Release(); - RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod)); - continue; - } - */ - int m; + unsigned m; for (m = 0; m < methodItems.Size(); m++) if (methodItems[m].RarUnPackVersion == item.UnPackVersion) break; @@ -772,7 +1678,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, mi.RarUnPackVersion = item.UnPackVersion; mi.Coder.Release(); - if (item.UnPackVersion <= 30) + if (item.UnPackVersion <= 40) { UInt32 methodID = 0x040300; if (item.UnPackVersion < 20) @@ -787,7 +1693,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (mi.Coder == 0) { outStream.Release(); - RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod)); continue; } @@ -814,7 +1720,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } default: outStream.Release(); - RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod)); continue; } HRESULT result = commonCoder->Code(inStream, outStream, &packSize, &item.Size, progress); @@ -834,7 +1740,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, !item.IsSplitBefore() && !item.IsSplitAfter()) */ { - const CItemEx &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1]; + const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1]; bool crcOK = outStreamSpec->GetCRC() == lastItem.FileCRC; outStream.Release(); RINOK(extractCallback->SetOperationResult(crcOK ? @@ -845,9 +1751,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, else { bool crcOK = true; - for (int partIndex = 0; partIndex < refItem.NumItems; partIndex++) + for (unsigned partIndex = 0; partIndex < refItem.NumItems; partIndex++) { - const CItemEx &item = _items[refItem.ItemIndex + partIndex]; + const CItem &item = _items[refItem.ItemIndex + partIndex]; if (item.FileCRC != folderInStreamSpec->CRCs[partIndex]) { crcOK = false; @@ -866,4 +1772,15 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, IMPL_ISetCompressCodecsInfo +IMP_CreateArcIn + +static CArcInfo g_ArcInfo = + { "Rar", "rar r00", 0, 3, + NHeader::kMarkerSize, SIGNATURE, + 0, + NArcInfoFlags::kFindSignature, + CreateArc }; + +REGISTER_ARC(Rar) + }} diff --git a/CPP/7zip/Archive/Rar/RarHandler.h b/CPP/7zip/Archive/Rar/RarHandler.h old mode 100755 new mode 100644 index 79266827..81191be9 --- a/CPP/7zip/Archive/Rar/RarHandler.h +++ b/CPP/7zip/Archive/Rar/RarHandler.h @@ -7,44 +7,85 @@ #include "../../Common/CreateCoder.h" -#include "RarIn.h" -#include "RarVolumeInStream.h" +#include "RarItem.h" namespace NArchive { namespace NRar { +struct CInArcInfo +{ + UInt32 Flags; + Byte EncryptVersion; + + UInt64 StartPos; + UInt64 EndPos; + UInt64 FileSize; + + UInt32 EndFlags; + UInt32 VolNumber; + UInt32 DataCRC; + + CInArcInfo(): EndFlags(0) {} + + UInt64 GetPhySize() const { return EndPos - StartPos; } + + bool IsSolid() const { return (Flags & NHeader::NArchive::kSolid) != 0; } + bool IsCommented() const { return (Flags & NHeader::NArchive::kComment) != 0; } + bool IsVolume() const { return (Flags & NHeader::NArchive::kVolume) != 0; } + bool HaveNewVolumeName() const { return (Flags & NHeader::NArchive::kNewVolName) != 0; } + bool IsFirstVolume() const { return (Flags & NHeader::NArchive::kFirstVolume) != 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); } + + bool Is_VolNumber_Defined() const { return (EndFlags & NHeader::NArchive::kEndOfArc_Flags_VolNumber) != 0; } + bool Is_DataCRC_Defined() const { return (EndFlags & NHeader::NArchive::kEndOfArc_Flags_DataCRC) != 0; } +}; + +struct CArc +{ + CMyComPtr Stream; + UInt64 PhySize; + // CByteBuffer Comment; + + CArc(): PhySize(0) {} + ISequentialInStream *CreateLimitedStream(UInt64 offset, UInt64 size) const; +}; + +struct CRefItem +{ + unsigned VolumeIndex; + unsigned ItemIndex; + unsigned NumItems; +}; + class CHandler: public IInArchive, PUBLIC_ISetCompressCodecsInfo public CMyUnknownImp { CRecordVector _refItems; - CObjectVector _items; - CObjectVector _archives; - NArchive::NRar::CInArchiveInfo _archiveInfo; - AString _errorMessage; + CObjectVector _items; + CObjectVector _arcs; + NArchive::NRar::CInArcInfo _arcInfo; + // AString _errorMessage; + UInt32 _errorFlags; + UInt32 _warningFlags; + bool _isArc; 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(); - } + UInt64 GetPackSize(unsigned refIndex) const; + bool IsSolid(unsigned refIndex) const; + + /* void AddErrorMessage(const AString &s) { if (!_errorMessage.IsEmpty()) _errorMessage += '\n'; _errorMessage += s; } + */ HRESULT Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, diff --git a/CPP/7zip/Archive/Rar/RarHeader.cpp b/CPP/7zip/Archive/Rar/RarHeader.cpp deleted file mode 100755 index 94481e02..00000000 --- a/CPP/7zip/Archive/Rar/RarHeader.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// 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 old mode 100755 new mode 100644 index 5c21a2ac..b518338a --- a/CPP/7zip/Archive/Rar/RarHeader.h +++ b/CPP/7zip/Archive/Rar/RarHeader.h @@ -3,16 +3,15 @@ #ifndef __ARCHIVE_RAR_HEADER_H #define __ARCHIVE_RAR_HEADER_H -#include "Common/Types.h" +#include "../../../Common/MyTypes.h" namespace NArchive { namespace NRar { namespace NHeader { -const int kMarkerSize = 7; -extern Byte kMarker[kMarkerSize]; +const unsigned kMarkerSize = 7; -const int kArchiveSolid = 0x1; +const unsigned kArchiveSolid = 0x1; namespace NBlockType { @@ -44,36 +43,40 @@ namespace NArchive 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 UInt16 kEndOfArc_Flags_NextVol = 1; + const UInt16 kEndOfArc_Flags_DataCRC = 2; + const UInt16 kEndOfArc_Flags_RevSpace = 4; + const UInt16 kEndOfArc_Flags_VolNumber = 8; - const int kBlockHeadersAreEncrypted = 0x80; + const unsigned kHeaderSizeMin = 7; + + const unsigned kArchiveHeaderSize = 13; + const unsigned 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 unsigned kSplitBefore = 1 << 0; + const unsigned kSplitAfter = 1 << 1; + const unsigned kEncrypted = 1 << 2; + const unsigned kComment = 1 << 3; + const unsigned kSolid = 1 << 4; - const int kDictBitStart = 5; - const int kNumDictBits = 3; - const int kDictMask = (1 << kNumDictBits) - 1; - const int kDictDirectoryValue = 0x7; + const unsigned kDictBitStart = 5; + const unsigned kNumDictBits = 3; + const unsigned kDictMask = (1 << kNumDictBits) - 1; + const unsigned 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; + const unsigned kSize64Bits = 1 << 8; + const unsigned kUnicodeName = 1 << 9; + const unsigned kSalt = 1 << 10; + const unsigned kOldVersion = 1 << 11; + const unsigned kExtTime = 1 << 12; + // const unsigned kExtFlags = 1 << 13; + // const unsigned kSkipIfUnknown = 1 << 14; + + const unsigned kLongBlock = 1 << 15; /* struct CBlock @@ -134,17 +137,17 @@ namespace NFile }; */ - const int kLabelFileAttribute = 0x08; - const int kWinFileDirectoryAttributeMask = 0x10; + const unsigned kLabelFileAttribute = 0x08; + const unsigned kWinFileDirectoryAttributeMask = 0x10; enum CHostOS { kHostMSDOS = 0, - kHostOS2 = 1, - kHostWin32 = 2, - kHostUnix = 3, - kHostMacOS = 4, - kHostBeOS = 5 + kHostOS2 = 1, + kHostWin32 = 2, + kHostUnix = 3, + kHostMacOS = 4, + kHostBeOS = 5 }; } diff --git a/CPP/7zip/Archive/Rar/RarIn.cpp b/CPP/7zip/Archive/Rar/RarIn.cpp deleted file mode 100755 index a7d018ff..00000000 --- a/CPP/7zip/Archive/Rar/RarIn.cpp +++ /dev/null @@ -1,478 +0,0 @@ -// 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 deleted file mode 100755 index a6998db2..00000000 --- a/CPP/7zip/Archive/Rar/RarIn.h +++ /dev/null @@ -1,123 +0,0 @@ -// 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 deleted file mode 100755 index 9216ae57..00000000 --- a/CPP/7zip/Archive/Rar/RarItem.cpp +++ /dev/null @@ -1,55 +0,0 @@ -// 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 old mode 100755 new mode 100644 index 4aa4d866..56d25f2c --- a/CPP/7zip/Archive/Rar/RarItem.h +++ b/CPP/7zip/Archive/Rar/RarItem.h @@ -3,13 +3,12 @@ #ifndef __ARCHIVE_RAR_ITEM_H #define __ARCHIVE_RAR_ITEM_H -#include "Common/Types.h" -#include "Common/MyString.h" +#include "../../../Common/StringConvert.h" #include "RarHeader.h" -namespace NArchive{ -namespace NRar{ +namespace NArchive { +namespace NRar { struct CRarTime { @@ -56,18 +55,35 @@ struct CItem 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) {} -}; + UInt32 GetWinAttrib() const; -class CItemEx: public CItem -{ -public: UInt64 Position; - UInt16 MainPartSize; + unsigned MainPartSize; UInt16 CommentSize; UInt16 AlignSize; + + // int BaseFileIndex; + // bool IsAltStream; + + UString GetName() const + { + if (( /* IsAltStream || */ HasUnicodeName()) && !UnicodeName.IsEmpty()) + return UnicodeName; + return MultiByteToUnicodeString(Name, CP_OEMCP); + } + + void Clear() + { + CTimeDefined = false; + ATimeDefined = false; + Name.Empty(); + UnicodeName.Empty(); + // IsAltStream = false; + // BaseFileIndex = -1; + } + + CItem() { Clear(); } + UInt64 GetFullSize() const { return MainPartSize + CommentSize + AlignSize + PackSize; }; // DWORD GetHeaderWithCommentSize() const { return MainPartSize + CommentSize; }; UInt64 GetCommentPosition() const { return Position + MainPartSize; }; diff --git a/CPP/7zip/Archive/Rar/RarRegister.cpp b/CPP/7zip/Archive/Rar/RarRegister.cpp deleted file mode 100755 index 2bcf569e..00000000 --- a/CPP/7zip/Archive/Rar/RarRegister.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// 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 deleted file mode 100755 index 25194f91..00000000 --- a/CPP/7zip/Archive/Rar/RarVolumeInStream.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// 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 deleted file mode 100755 index 78d95b10..00000000 --- a/CPP/7zip/Archive/Rar/RarVolumeInStream.h +++ /dev/null @@ -1,49 +0,0 @@ -// 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 old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Rar/StdAfx.h b/CPP/7zip/Archive/Rar/StdAfx.h old mode 100755 new mode 100644 index e7fb6986..2854ff3e --- a/CPP/7zip/Archive/Rar/StdAfx.h +++ b/CPP/7zip/Archive/Rar/StdAfx.h @@ -3,6 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" +#include "../../../Common/Common.h" #endif diff --git a/CPP/7zip/Archive/RpmHandler.cpp b/CPP/7zip/Archive/RpmHandler.cpp old mode 100755 new mode 100644 index 1d31d451..220bc650 --- a/CPP/7zip/Archive/RpmHandler.cpp +++ b/CPP/7zip/Archive/RpmHandler.cpp @@ -4,10 +4,14 @@ #include "../../../C/CpuArch.h" -#include "Common/ComTry.h" -#include "Common/MyString.h" +#include "../../Common/ComTry.h" +#include "../../Common/IntToString.h" +#include "../../Common/MyString.h" +#include "../../Common/StringConvert.h" +#include "../../Common/UTFConvert.h" -#include "Windows/PropVariant.h" +#include "../../Windows/PropVariant.h" +#include "../../Windows/TimeUtils.h" #include "../Common/LimitedStreams.h" #include "../Common/ProgressUtils.h" @@ -16,6 +20,8 @@ #include "../Compress/CopyCoder.h" +// #define _SHOW_RPM_METADATA + using namespace NWindows; #define Get16(p) GetBe16(p) @@ -24,130 +30,144 @@ using namespace NWindows; 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. */ +static const unsigned kNameSize = 66; +static const unsigned kLeadSize = kNameSize + 30; +static const unsigned k_HeaderSig_Size = 16; +static const unsigned k_Entry_Size = 16; -#define RPMSIG_HEADERSIG 5 /* New Header style signature */ +#define RPMSIG_NONE 0 // Old signature +#define RPMSIG_PGP262_1024 1 // Old signature +#define RPMSIG_HEADERSIG 5 // New signature -const UInt32 kLeadSize = 96; -struct CLead +enum { - 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; }; + kRpmType_Bin = 0, + kRpmType_Src = 1 }; - -const UInt32 kEntryInfoSize = 16; -/* -struct CEntryInfo + +// There are two sets of TAGs: signature tags and header tags + +// ----- Signature TAGs ----- + +#define RPMSIGTAG_SIZE 1000 // Header + Payload size (32bit) + +// ----- Header TAGs ----- + +#define RPMTAG_NAME 1000 +#define RPMTAG_VERSION 1001 +#define RPMTAG_RELEASE 1002 +#define RPMTAG_BUILDTIME 1006 +#define RPMTAG_OS 1021 // string (old version used int?) +#define RPMTAG_ARCH 1022 // string (old version used int?) +#define RPMTAG_PAYLOADFORMAT 1124 +#define RPMTAG_PAYLOADCOMPRESSOR 1125 +// #define RPMTAG_PAYLOADFLAGS 1126 + +enum { - int Tag; - int Type; - int Offset; // Offset from beginning of data segment, only defined on disk - int Count; + k_EntryType_NULL, + k_EntryType_CHAR, + k_EntryType_INT8, + k_EntryType_INT16, + k_EntryType_INT32, + k_EntryType_INT64, + k_EntryType_STRING, + k_EntryType_BIN, + k_EntryType_STRING_ARRAY, + k_EntryType_I18NSTRING }; -*/ -// case: SignatureType == RPMSIG_HEADERSIG -const UInt32 kCSigHeaderSigSize = 16; -struct CSigHeaderSig +static const char *k_CPUs[] = { - 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; }; + "noarch" + , "i386" + , "alpha" + , "sparc" + , "mips" + , "ppc" + , "m68k" + , "sgi" + , "rs6000" + , "ia64" + , "sparc64" // 10 ??? + , "mipsel" + , "arm" + , "m68kmint" + , "s390" + , "s390x" + , "ppc64" + , "sh" + , "xtensa" + , "aarch64" // 19 }; -static HRESULT RedSigHeaderSig(IInStream *inStream, CSigHeaderSig &h) +static const char *k_OS[] = { - 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; -} + "0" + , "Linux" + , "Irix" + , "solaris" + , "SunOS" + , "AmigaOS" // AIX + , "HP-UX" + , "osf" + , "FreeBSD" + , "SCO_SV" + , "Irix64" + , "NextStep" + , "bsdi" + , "machten" + , "cygwin32-NT" + , "cygwin32-95" + , "MP_RAS" + , "MiNT" + , "OS/390" + , "VM/ESA" + , "Linux/390" // "Linux/ESA" + , "Darwin" // "MacOSX" 21 +}; -HRESULT OpenArchive(IInStream *inStream) +struct CLead { - 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; + unsigned char Major; + unsigned char Minor; + UInt16 Type; + UInt16 Cpu; + UInt16 Os; + UInt16 SignatureType; + char Name[kNameSize]; + // char Reserved[16]; - CSigHeaderSig sigHeader, header; - if (lead.SignatureType == RPMSIG_NONE) - { - ; - } - else if (lead.SignatureType == RPMSIG_PGP262_1024) + void Parse(const Byte *p) { - UInt64 pos; - RINOK(inStream->Seek(256, STREAM_SEEK_CUR, &pos)); + Major = p[4]; + Minor = p[5]; + Type = Get16(p + 6); + Cpu= Get16(p + 8); + memcpy(Name, p + 10, kNameSize); + p += 10 + kNameSize; + Os = Get16(p); + SignatureType = Get16(p + 2); } - else if (lead.SignatureType == RPMSIG_HEADERSIG) + + bool IsSupported() const { return Major >= 3 && Type <= 1; } +}; + +struct CEntry +{ + UInt32 Tag; + UInt32 Type; + UInt32 Offset; + UInt32 Count; + + void Parse(const Byte *p) { - 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)); - } + Tag = Get32(p + 0); + Type = Get32(p + 4); + Offset = Get32(p + 8); + Count = Get32(p + 12); } - 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, @@ -155,104 +175,575 @@ class CHandler: public CMyUnknownImp { CMyComPtr _stream; - UInt64 _pos; + + UInt64 _headersSize; // is equal to start offset of payload data + UInt64 _payloadSize; UInt64 _size; - Byte _sig[4]; + // _size = _payloadSize, if (_payloadSize_Defined) + // _size = (fileSize - _headersSize), if (!_payloadSize_Defined) + UInt64 _phySize; // _headersSize + _payloadSize, if (_phySize_Defined) + UInt32 _headerPlusPayload_Size; + UInt32 _buildTime; + + bool _payloadSize_Defined; + bool _phySize_Defined; + bool _headerPlusPayload_Size_Defined; + bool _time_Defined; + + Byte _payloadSig[6]; // start data of payload + + AString _name; // p7zip + AString _version; // 9.20.1 + AString _release; // 8.1.1 + AString _arch; // x86_64 + AString _os; // linux + + AString _format; // cpio + AString _compressor; // xz, gzip, bzip2 + + CLead _lead; + + #ifdef _SHOW_RPM_METADATA + AString _metadata; + #endif + + void SetTime(NCOM::CPropVariant &prop) const + { + if (_time_Defined && _buildTime != 0) + { + FILETIME ft; + if (NTime::UnixTime64ToFileTime(_buildTime, ft)) + prop = ft; + } + } + + void SetStringProp(const AString &s, NCOM::CPropVariant &prop) const + { + UString us; + if (!ConvertUTF8ToUnicode(s, us)) + us = GetUnicodeString(s); + if (!us.IsEmpty()) + prop = us; + } + + void AddCPU(AString &s) const; + AString GetBaseName() const; + void AddSubFileExtension(AString &res) const; + + HRESULT ReadHeader(ISequentialInStream *stream, bool isMainHeader); + HRESULT Open2(ISequentialInStream *stream); public: MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); }; -STATPROPSTG kProps[] = +static const Byte kArcProps[] = { - { NULL, kpidSize, VT_UI8} + kpidHeadersSize, + kpidCpu, + kpidHostOS, + kpidCTime + #ifdef _SHOW_RPM_METADATA + , kpidComment + #endif +}; + +static const Byte kProps[] = +{ + kpidPath, + kpidSize, + kpidCTime }; IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO_Table +IMP_IInArchive_ArcProps -STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +void CHandler::AddCPU(AString &s) const { - NCOM::CPropVariant prop; - switch(propID) { case kpidMainSubfile: prop = (UInt32)0; break; } - prop.Detach(value); - return S_OK; + if (!_arch.IsEmpty()) + s += _arch; + else + { + if (_lead.Type == kRpmType_Bin) + { + char temp[16]; + const char *p; + if (_lead.Cpu < ARRAY_SIZE(k_CPUs)) + p = k_CPUs[_lead.Cpu]; + else + { + ConvertUInt32ToString(_lead.Cpu, temp); + p = temp; + } + s += p; + } + } } -STDMETHODIMP CHandler::Open(IInStream *inStream, - const UInt64 * /* maxCheckStartPosition */, - IArchiveOpenCallback * /* openArchiveCallback */) +AString CHandler::GetBaseName() const { - COM_TRY_BEGIN - try + AString s; + if (!_name.IsEmpty()) { - 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; + s = _name; + if (!_version.IsEmpty()) + { + s += '-'; + s += _version; + } + if (!_release.IsEmpty()) + { + s += '-'; + s += _release; + } } - catch(...) { return S_FALSE; } - COM_TRY_END + else + { + char *p = s.GetBuffer(kNameSize); + memcpy(p, _lead.Name, kNameSize); + p[kNameSize] = 0; + s.ReleaseBuffer(); + } + + s += '.'; + if (_lead.Type == kRpmType_Src) + s += "src"; + else + AddCPU(s); + return s; } -STDMETHODIMP CHandler::Close() +void CHandler::AddSubFileExtension(AString &res) const { - _stream.Release(); - return S_OK; + if (!_format.IsEmpty()) + res += _format; + else + res += "cpio"; + res += '.'; + + const char *s; + + if (!_compressor.IsEmpty()) + { + s = _compressor; + if (_compressor == "bzip2") + s = "bz2"; + else if (_compressor == "gzip") + s = "gz"; + } + else + { + const Byte *p = _payloadSig; + if (p[0] == 0x1F && p[1] == 0x8B) + s = "gz"; + else if (p[0] == 0xFD && p[1] == '7' && p[2] == 'z' && p[3] == 'X' && p[4] == 'Z' && p[5] == 0) + s = "xz"; + else if (p[0] == 'B' && p[1] == 'Z' && p[2] == 'h' && p[3] >= '1' && p[3] <= '9') + s = "bz2"; + else + s = "lzma"; + } + + res += s; } -STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { - *numItems = 1; + COM_TRY_BEGIN + NCOM::CPropVariant prop; + switch (propID) + { + case kpidMainSubfile: prop = (UInt32)0; break; + + case kpidHeadersSize: prop = _headersSize; break; + case kpidPhySize: if (_phySize_Defined) prop = _phySize; break; + + case kpidMTime: + case kpidCTime: + SetTime(prop); + break; + + case kpidCpu: + { + AString s; + AddCPU(s); + /* + if (_lead.Type == kRpmType_Src) + s = "src"; + */ + SetStringProp(s, prop); + break; + } + + case kpidHostOS: + { + if (!_os.IsEmpty()) + SetStringProp(_os, prop); + else + { + char temp[16]; + const char *p; + if (_lead.Os < ARRAY_SIZE(k_OS)) + p = k_OS[_lead.Os]; + else + { + ConvertUInt32ToString(_lead.Os, temp); + p = temp; + } + prop = p; + } + break; + } + + #ifdef _SHOW_RPM_METADATA + case kpidComment: SetStringProp(_metadata, prop); break; + #endif + + case kpidName: + { + AString s = GetBaseName(); + s += ".rpm"; + SetStringProp(s, prop); + break; + } + } + prop.Detach(value); return S_OK; + COM_TRY_END } + STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) { NWindows::NCOM::CPropVariant prop; - switch(propID) + switch (propID) { case kpidSize: case kpidPackSize: prop = _size; break; + + case kpidMTime: + case kpidCTime: + SetTime(prop); + break; + + case kpidPath: + { + AString s = GetBaseName(); + s += '.'; + AddSubFileExtension(s); + SetStringProp(s, prop); + 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; + prop = GetSubFileExtension(); break; } + */ } prop.Detach(value); return S_OK; } +#ifdef _SHOW_RPM_METADATA +static inline char GetHex(unsigned value) +{ + return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); +} +#endif + +HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader) +{ + UInt32 numEntries; + UInt32 dataLen; + { + char buf[k_HeaderSig_Size]; + RINOK(ReadStream_FALSE(stream, buf, k_HeaderSig_Size)); + if (Get32(buf) != 0x8EADE801) // buf[3] = 0x01 - is version + return S_FALSE; + // reserved = Get32(buf + 4); + numEntries = Get32(buf + 8); + dataLen = Get32(buf + 12); + if (numEntries >= 1 << 24) + return S_FALSE; + } + size_t indexSize = (size_t)numEntries * k_Entry_Size; + size_t headerSize = indexSize + dataLen; + if (headerSize < dataLen) + return S_FALSE; + CByteBuffer buffer(headerSize); + RINOK(ReadStream_FALSE(stream, buffer, headerSize)); + + for (UInt32 i = 0; i < numEntries; i++) + { + CEntry entry; + + entry.Parse(buffer + (size_t)i * k_Entry_Size); + if (entry.Offset > dataLen) + return S_FALSE; + + const Byte *p = buffer + indexSize + entry.Offset; + size_t rem = dataLen - entry.Offset; + + if (!isMainHeader) + { + if (entry.Tag == RPMSIGTAG_SIZE && + entry.Type == k_EntryType_INT32) + { + if (rem < 4 || entry.Count != 1) + return S_FALSE; + _headerPlusPayload_Size = Get32(p); + _headerPlusPayload_Size_Defined = true; + } + } + else + { + #ifdef _SHOW_RPM_METADATA + { + char temp[16]; + ConvertUInt32ToString(entry.Tag, temp); + + _metadata += temp; + _metadata += ": "; + } + #endif + + if (entry.Type == k_EntryType_STRING) + { + if (entry.Count != 1) + return S_FALSE; + size_t j; + for (j = 0; j < rem && p[j] != 0; j++); + if (j == rem) + return S_FALSE; + AString s = (const char *)p; + switch (entry.Tag) + { + case RPMTAG_NAME: _name = s; break; + case RPMTAG_VERSION: _version = s; break; + case RPMTAG_RELEASE: _release = s; break; + case RPMTAG_ARCH: _arch = s; break; + case RPMTAG_OS: _os = s; break; + case RPMTAG_PAYLOADFORMAT: _format = s; break; + case RPMTAG_PAYLOADCOMPRESSOR: _compressor = s; break; + } + + #ifdef _SHOW_RPM_METADATA + _metadata += s; + #endif + } + else if (entry.Type == k_EntryType_INT32) + { + if (rem / 4 < entry.Count) + return S_FALSE; + if (entry.Tag == RPMTAG_BUILDTIME) + { + if (entry.Count != 1) + return S_FALSE; + _buildTime = Get32(p); + _time_Defined = true; + } + + #ifdef _SHOW_RPM_METADATA + for (UInt32 t = 0; t < entry.Count; t++) + { + if (t != 0) + _metadata += ' '; + char temp[16]; + ConvertUInt32ToString(Get32(p + t * 4), temp); + _metadata += temp; + } + #endif + } + + #ifdef _SHOW_RPM_METADATA + + else if ( + entry.Type == k_EntryType_STRING_ARRAY || + entry.Type == k_EntryType_I18NSTRING) + { + const Byte *p2 = p; + size_t rem2 = rem; + for (UInt32 t = 0; t < entry.Count; t++) + { + if (rem2 == 0) + return S_FALSE; + if (t != 0) + _metadata += '\n'; + size_t j; + for (j = 0; j < rem2 && p2[j] != 0; j++); + if (j == rem2) + return S_FALSE; + _metadata += (const char *)p2; + j++; + p2 += j; + rem2 -= j; + } + } + else if (entry.Type == k_EntryType_INT16) + { + if (rem / 2 < entry.Count) + return S_FALSE; + for (UInt32 t = 0; t < entry.Count; t++) + { + if (t != 0) + _metadata += ' '; + char temp[16]; + ConvertUInt32ToString(Get16(p + t * 2), temp); + _metadata += temp; + } + } + else if (entry.Type == k_EntryType_BIN) + { + if (rem < entry.Count) + return S_FALSE; + for (UInt32 t = 0; t < entry.Count; t++) + { + const unsigned b = p[t]; + _metadata += GetHex((b >> 4) & 0xF); + _metadata += GetHex(b & 0xF); + } + } + else + { + // p = p; + } + _metadata += '\n'; + #endif + } + } + + headerSize += k_HeaderSig_Size; + _headersSize += headerSize; + if (isMainHeader && _headerPlusPayload_Size_Defined) + { + if (_headerPlusPayload_Size < headerSize) + return S_FALSE; + _payloadSize = _headerPlusPayload_Size - headerSize; + _size = _payloadSize; + _phySize = _headersSize + _payloadSize; + _payloadSize_Defined = true; + _phySize_Defined = true; + } + return S_OK; +} + +HRESULT CHandler::Open2(ISequentialInStream *stream) +{ + { + Byte buf[kLeadSize]; + RINOK(ReadStream_FALSE(stream, buf, kLeadSize)); + if (Get32(buf) != 0xEDABEEDB) + return S_FALSE; + _lead.Parse(buf); + if (!_lead.IsSupported()) + return S_FALSE; + } + + _headersSize = kLeadSize; + + if (_lead.SignatureType == RPMSIG_NONE) + { + ; + } + else if (_lead.SignatureType == RPMSIG_PGP262_1024) + { + Byte temp[256]; + RINOK(ReadStream_FALSE(stream, temp, sizeof(temp))); + } + else if (_lead.SignatureType == RPMSIG_HEADERSIG) + { + RINOK(ReadHeader(stream, false)); + unsigned pos = (unsigned)_headersSize & 7; + if (pos != 0) + { + Byte temp[8]; + unsigned num = 8 - pos; + RINOK(ReadStream_FALSE(stream, temp, num)); + _headersSize += num; + } + } + else + return S_FALSE; + + return ReadHeader(stream, true); +} + + +STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *) +{ + COM_TRY_BEGIN + { + Close(); + RINOK(Open2(inStream)); + + // start of payload is allowed to be unaligned + RINOK(ReadStream_FALSE(inStream, _payloadSig, sizeof(_payloadSig))); + + if (!_payloadSize_Defined) + { + UInt64 endPos; + RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos)); + _size = endPos - _headersSize; + } + _stream = inStream; + return S_OK; + } + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _headersSize = 0; + _payloadSize = 0; + _size = 0; + _phySize = 0; + _headerPlusPayload_Size = 0; + + _payloadSize_Defined = false; + _phySize_Defined = false; + _headerPlusPayload_Size_Defined = false; + _time_Defined = false; + + _name.Empty(); + _version.Empty(); + _release.Empty(); + _arch.Empty(); + _os.Empty(); + + _format.Empty(); + _compressor.Empty(); + + #ifdef _SHOW_RPM_METADATA + _metadata.Empty(); + #endif + + _stream.Release(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = 1; + 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)) + if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) return E_INVALIDARG; RINOK(extractCallback->SetTotal(_size)); + CMyComPtr outStream; Int32 askMode = testMode ? NExtract::NAskMode::kTest : @@ -262,30 +753,38 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, return S_OK; RINOK(extractCallback->PrepareOperation(askMode)); - CMyComPtr copyCoder = new NCompress::CCopyCoder; + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; + CMyComPtr copyCoder = copyCoderSpec; 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)); + RINOK(_stream->Seek(_headersSize, STREAM_SEEK_SET, NULL)); + RINOK(copyCoder->Code(_stream, outStream, NULL, &_size, progress)); outStream.Release(); - return extractCallback->SetOperationResult(NExtract::NOperationResult::kOK); + Int32 opRes = NExtract::NOperationResult::kOK; + if (copyCoderSpec->TotalSize < _size) + opRes = NExtract::NOperationResult::kUnexpectedEnd; + return extractCallback->SetOperationResult(opRes); COM_TRY_END } STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **stream) { COM_TRY_BEGIN - return CreateLimitedInStream(_stream, _pos, _size, stream); + return CreateLimitedInStream(_stream, _headersSize, _size, stream); COM_TRY_END } -static IInArchive *CreateArc() { return new NArchive::NRpm::CHandler; } +IMP_CreateArcIn static CArcInfo g_ArcInfo = - { L"Rpm", L"rpm", 0, 0xEB, { 0xED, 0xAB, 0xEE, 0xDB}, 4, false, CreateArc, 0 }; + { "Rpm", "rpm", 0, 0xEB, + 4, { 0xED, 0xAB, 0xEE, 0xDB}, + 0, + 0, + CreateArc }; REGISTER_ARC(Rpm) diff --git a/CPP/7zip/Archive/SplitHandler.cpp b/CPP/7zip/Archive/SplitHandler.cpp old mode 100755 new mode 100644 index 5d84de4e..19dc1b47 --- a/CPP/7zip/Archive/SplitHandler.cpp +++ b/CPP/7zip/Archive/SplitHandler.cpp @@ -2,10 +2,10 @@ #include "StdAfx.h" -#include "Common/ComTry.h" -#include "Common/MyString.h" +#include "../../Common/ComTry.h" +#include "../../Common/MyString.h" -#include "Windows/PropVariant.h" +#include "../../Windows/PropVariant.h" #include "../Common/ProgressUtils.h" #include "../Common/RegisterArc.h" @@ -19,15 +19,16 @@ using namespace NWindows; namespace NArchive { namespace NSplit { -STATPROPSTG kProps[] = +static const Byte kProps[] = { - { NULL, kpidPath, VT_BSTR}, - { NULL, kpidSize, VT_UI8} + kpidPath, + kpidSize }; -STATPROPSTG kArcProps[] = +static const Byte kArcProps[] = { - { NULL, kpidNumVolumes, VT_UI4} + kpidNumVolumes, + kpidTotalPhySize }; class CHandler: @@ -35,10 +36,12 @@ class CHandler: public IInArchiveGetStream, public CMyUnknownImp { - UString _subName; CObjectVector > _streams; CRecordVector _sizes; + UString _subName; UInt64 _totalSize; + + HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); public: MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) @@ -51,9 +54,11 @@ IMP_IInArchive_ArcProps STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { NCOM::CPropVariant prop; - switch(propID) + switch (propID) { case kpidMainSubfile: prop = (UInt32)0; break; + case kpidPhySize: if (!_sizes.IsEmpty()) prop = _sizes[0]; break; + case kpidTotalPhySize: prop = _totalSize; break; case kpidNumVolumes: prop = (UInt32)_streams.Size(); break; } prop.Detach(value); @@ -72,20 +77,18 @@ struct CSeqName if (_splitStyle) { int i; - int numLetters = _changedPart.Length(); + int numLetters = _changedPart.Len(); for (i = numLetters - 1; i >= 0; i--) { wchar_t c = _changedPart[i]; if (c == 'z') { - c = 'a'; - newName = c + newName; + newName.InsertAtFront('a'); continue; } else if (c == 'Z') { - c = 'A'; - newName = c + newName; + newName.InsertAtFront('A'); continue; } c++; @@ -99,33 +102,32 @@ struct CSeqName newName += newChar; break; } - newName = c + newName; + newName.InsertAtFront(c); i--; for (; i >= 0; i--) - newName = _changedPart[i] + newName; + newName.InsertAtFront(_changedPart[i]); break; } } else { int i; - int numLetters = _changedPart.Length(); + int numLetters = _changedPart.Len(); for (i = numLetters - 1; i >= 0; i--) { wchar_t c = _changedPart[i]; - if (c == L'9') + if (c == '9') { - c = L'0'; - newName = c + newName; + newName.InsertAtFront('0'); if (i == 0) - newName = UString(L'1') + newName; + newName.InsertAtFront('1'); continue; } c++; - newName = c + newName; + newName.InsertAtFront(c); i--; for (; i >= 0; i--) - newName = _changedPart[i] + newName; + newName.InsertAtFront(_changedPart[i]); break; } } @@ -134,142 +136,139 @@ struct CSeqName } }; -STDMETHODIMP CHandler::Open(IInStream *stream, - const UInt64 * /* maxCheckStartPosition */, - IArchiveOpenCallback *openArchiveCallback) +HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) { - COM_TRY_BEGIN Close(); - if (openArchiveCallback == 0) + if (!callback) return S_FALSE; - // try + + CMyComPtr volumeCallback; + callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&volumeCallback); + if (!volumeCallback) + return S_FALSE; + + UString name; { - CMyComPtr openVolumeCallback; - CMyComPtr openArchiveCallbackWrap = openArchiveCallback; - if (openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, - &openVolumeCallback) != S_OK) + NCOM::CPropVariant prop; + RINOK(volumeCallback->GetProperty(kpidName, &prop)); + if (prop.vt != VT_BSTR) 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") + name = prop.bstrVal; + } + + int dotPos = name.ReverseFind('.'); + const UString prefix = name.Left(dotPos + 1); + const UString ext = name.Ptr(dotPos + 1); + UString ext2 = ext; + ext2.MakeLower_Ascii(); + + CSeqName seqName; + + unsigned numLetters = 2; + bool splitStyle = false; + + if (ext2.Len() >= 2 && StringsAreEqual_Ascii(ext2.RightPtr(2), "aa")) + { + splitStyle = true; + while (numLetters < ext2.Len()) { - splitStyle = true; - while (numLetters < extBig.Length()) - { - if (extBig[extBig.Length() - numLetters - 1] != 'A') - break; - numLetters++; - } + if (ext2[ext2.Len() - numLetters - 1] != 'a') + break; + numLetters++; } - else if (ext.Right(2) == L"01") + } + else if (ext.Len() >= 2 && StringsAreEqual_Ascii(ext2.RightPtr(2), "01")) + { + while (numLetters < ext2.Len()) { - while (numLetters < extBig.Length()) - { - if (extBig[extBig.Length() - numLetters - 1] != '0') - break; - numLetters++; - } - if (numLetters != ext.Length()) - return S_FALSE; + if (ext2[ext2.Len() - numLetters - 1] != '0') + break; + numLetters++; } - else + if (numLetters != ext.Len()) 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; + } + else + return S_FALSE; + + seqName._unchangedPart = prefix + ext.Left(ext2.Len() - numLetters); + seqName._changedPart = ext.RightPtr(numLetters); + seqName._splitStyle = splitStyle; + + if (prefix.Len() < 1) + _subName = L"file"; + else + _subName.SetFrom(prefix, prefix.Len() - 1); + + UInt64 size; + { + NCOM::CPropVariant prop; + RINOK(volumeCallback->GetProperty(kpidSize, &prop)); + if (prop.vt != VT_UI8) + return E_INVALIDARG; + size = prop.uhVal.QuadPart; + } + + _totalSize += size; + _sizes.Add(size); + _streams.Add(stream); + + { + UInt64 numFiles = _streams.Size(); + RINOK(callback->SetCompleted(&numFiles, NULL)); + } + + for (;;) + { + const UString fullName = seqName.GetNextName(); + CMyComPtr nextStream; + HRESULT result = volumeCallback->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)); + RINOK(volumeCallback->GetProperty(kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; size = prop.uhVal.QuadPart; } _totalSize += size; _sizes.Add(size); - - if (openArchiveCallback != NULL) + _streams.Add(nextStream); { 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)); - } + RINOK(callback->SetCompleted(&numFiles, NULL)); } } - /* - catch(...) + + if (_streams.Size() == 1) { - return S_FALSE; + if (splitStyle) + return S_FALSE; } - */ return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + HRESULT res = Open2(stream, callback); + if (res != S_OK) + Close(); + return res; COM_TRY_END } STDMETHODIMP CHandler::Close() { - _sizes.Clear(); + _totalSize = 0; + _subName.Empty(); _streams.Clear(); + _sizes.Clear(); return S_OK; } @@ -281,8 +280,8 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) { - NWindows::NCOM::CPropVariant prop; - switch(propID) + NCOM::CPropVariant prop; + switch (propID) { case kpidPath: prop = _subName; break; case kpidSize: @@ -300,7 +299,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_BEGIN if (numItems == 0) return S_OK; - if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0)) + if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) return E_INVALIDARG; UInt64 currentTotalSize = 0; @@ -321,7 +320,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CMyComPtr progress = lps; lps->Init(extractCallback, false); - for (int i = 0; i < _streams.Size(); i++) + FOR_VECTOR (i, _streams) { lps->InSize = lps->OutSize = currentTotalSize; RINOK(lps->SetCur()); @@ -343,7 +342,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) *stream = 0; CMultiStream *streamSpec = new CMultiStream; CMyComPtr streamTemp = streamSpec; - for (int i = 0; i < _streams.Size(); i++) + FOR_VECTOR (i, _streams) { CMultiStream::CSubStreamInfo subStreamInfo; subStreamInfo.Stream = _streams[i]; @@ -356,10 +355,14 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) COM_TRY_END } -static IInArchive *CreateArc() { return new CHandler; } +IMP_CreateArcIn static CArcInfo g_ArcInfo = -{ L"Split", L"001", 0, 0xEA, { 0 }, 0, false, CreateArc, 0 }; + { "Split", "001", 0, 0xEA, + 0, { 0 }, + 0, + 0, + CreateArc }; REGISTER_ARC(Split) diff --git a/CPP/7zip/Archive/SquashfsHandler.cpp b/CPP/7zip/Archive/SquashfsHandler.cpp old mode 100755 new mode 100644 index efaffed1..617a1d66 --- a/CPP/7zip/Archive/SquashfsHandler.cpp +++ b/CPP/7zip/Archive/SquashfsHandler.cpp @@ -7,12 +7,12 @@ #include "../../../C/CpuArch.h" #include "../../../C/Xz.h" -#include "Common/ComTry.h" -#include "Common/IntToString.h" -#include "Common/StringConvert.h" +#include "../../Common/ComTry.h" +#include "../../Common/IntToString.h" +#include "../../Common/StringConvert.h" -#include "Windows/PropVariantUtils.h" -#include "Windows/Time.h" +#include "../../Windows/PropVariantUtils.h" +#include "../../Windows/TimeUtils.h" #include "../Common/CWrappers.h" #include "../Common/LimitedStreams.h" @@ -59,8 +59,6 @@ UInt64 Get64b(const Byte *p, bool be) { return be ? GetBe64(p) : GetUi64(p); } #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; @@ -72,11 +70,11 @@ static const UInt32 kSignature32_LZ = 0x71736873; static const char *k_Methods[] = { - "Unknown", - "ZLIB", - "LZMA", - "LZO", - "XZ" + "Unknown" + , "ZLIB" + , "LZMA" + , "LZO" + , "XZ" }; static const UInt32 kMetadataBlockSizeLog = 13; @@ -315,17 +313,17 @@ UInt32 CNode::Parse1(const Byte *p, UInt32 size, const CHeader &_h) UInt16 t = Get16(p); if (be) { - Type = t >> 12; - Mode = t & 0xFFF; - Uid = p[2] >> 4; - Gid = p[2] & 0xF; + Type = (UInt16)(t >> 12); + Mode = (UInt16)(t & 0xFFF); + Uid = (UInt16)(p[2] >> 4); + Gid = (UInt16)(p[2] & 0xF); } else { - Type = t & 0xF; - Mode = t >> 4; - Uid = p[2] & 0xF; - Gid = p[2] >> 4; + Type = (UInt16)(t & 0xF); + Mode = (UInt16)(t >> 4); + Uid = (UInt16)(p[2] & 0xF); + Gid = (UInt16)(p[2] >> 4); } // Xattr = kXattr_Empty; @@ -339,20 +337,20 @@ UInt32 CNode::Parse1(const Byte *p, UInt32 size, const CHeader &_h) Byte t = p[3]; if (be) { - Type = t >> 4; - Offset = t & 0xF; + Type = (UInt16)(t >> 4); + Offset = (UInt16)(t & 0xF); } else { - Type = t & 0xF; - Offset = t >> 4; + Type = (UInt16)(t & 0xF); + Offset = (UInt16)(t >> 4); } return (Type == kType_FIFO || Type == kType_SOCK) ? 4 : 0; } Type--; - Uid += (Type / 5) * 16; - Type = (Type % 5) + 1; + Uid = (UInt16)(Uid + (Type / 5) * 16); + Type = (UInt16)((Type % 5) + 1); if (Type == kType_FILE) { @@ -418,13 +416,13 @@ UInt32 CNode::Parse2(const Byte *p, UInt32 size, const CHeader &_h) UInt16 t = Get16(p); if (be) { - Type = t >> 12; - Mode = t & 0xFFF; + Type = (UInt16)(t >> 12); + Mode = (UInt16)(t & 0xFFF); } else { - Type = t & 0xF; - Mode = t >> 4; + Type = (UInt16)(t & 0xF); + Mode = (UInt16)(t >> 4); } Uid = p[2]; Gid = p[3]; @@ -548,13 +546,13 @@ UInt32 CNode::Parse3(const Byte *p, UInt32 size, const CHeader &_h) UInt16 t = Get16(p); if (be) { - Type = t >> 12; - Mode = t & 0xFFF; + Type = (UInt16)(t >> 12); + Mode = (UInt16)(t & 0xFFF); } else { - Type = t & 0xF; - Mode = t >> 4; + Type = (UInt16)(t & 0xF); + Mode = (UInt16)(t >> 4); } Uid = p[2]; Gid = p[3]; @@ -841,6 +839,8 @@ class CHandler: // CByteBuffer _uids; // CByteBuffer _gids; CHeader _h; + bool _noPropsLZMA; + bool _needCheckLzma; CMyComPtr _stream; UInt64 _sizeCalculated; @@ -922,31 +922,30 @@ CHandler::CHandler() _dynOutStream = _dynOutStreamSpec; } -static const STATPROPSTG kProps[] = +static const Byte 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} + kpidPath, + kpidIsDir, + kpidSize, + kpidPackSize, + kpidMTime, + kpidPosixAttrib + // kpidUser, + // kpidGroup, + // kpidLinks, + // kpidOffset }; -static const STATPROPSTG kArcProps[] = +static const Byte 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} + kpidHeadersSize, + kpidFileSystem, + kpidMethod, + kpidBlock, + kpidBigEndian, + kpidCTime, + kpidCharacts + // kpidNumBlocks }; IMP_IInArchive_Props @@ -1115,12 +1114,25 @@ HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool UInt32 method = _h.Method; if (_h.SeveralMethods) { - Byte props[1]; - RINOK(ReadStream_FALSE(_stream, props, 1)); - method = (props[0] == 0x5D ? kMethod_LZMA : kMethod_ZLIB); + Byte b; + RINOK(ReadStream_FALSE(_stream, &b, 1)); RINOK(_stream->Seek(-1, STREAM_SEEK_CUR, NULL)); + method = (b == 0x5D ? kMethod_LZMA : kMethod_ZLIB); } + if (method == kMethod_ZLIB && _needCheckLzma) + { + Byte b; + RINOK(ReadStream_FALSE(_stream, &b, 1)); + RINOK(_stream->Seek(-1, STREAM_SEEK_CUR, NULL)); + if (b == 0) + { + _noPropsLZMA = true; + method = _h.Method = kMethod_LZMA; + } + _needCheckLzma = false; + } + if (method == kMethod_ZLIB) { if (!_zlibDecoder) @@ -1140,24 +1152,34 @@ HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool _lzmaDecoderSpec->FinishStream = true; _lzmaDecoder = _lzmaDecoderSpec; } - const UInt32 kPropsSize = 5 + 8; + const UInt32 kPropsSize = LZMA_PROPS_SIZE + 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; + UInt32 propsSize; + UInt64 outSize; + if (_noPropsLZMA) + { + props[0] = 0x5D; + SetUi32(&props[1], _h.BlockSize); + propsSize = 0; + outSize = outSizeMax; + } + else + { + RINOK(ReadStream_FALSE(_limitedInStream, props, kPropsSize)); + propsSize = kPropsSize; + outSize = GetUi64(&props[LZMA_PROPS_SIZE]); + if (outSize > outSizeMax) + return S_FALSE; + } + RINOK(_lzmaDecoderSpec->SetDecoderProperties2(props, LZMA_PROPS_SIZE)); RINOK(_lzmaDecoder->Code(_limitedInStream, outStream, NULL, &outSize, NULL)); - if (inSize != kPropsSize + _lzmaDecoderSpec->GetInputProcessedSize()) + if (inSize != propsSize + _lzmaDecoderSpec->GetInputProcessedSize()) return S_FALSE; } else { - if (_inputBuffer.GetCapacity() < inSize) - { - _inputBuffer.Free(); - _inputBuffer.SetCapacity(inSize); - } + if (_inputBuffer.Size() < inSize) + _inputBuffer.Alloc(inSize); RINOK(ReadStream_FALSE(_stream, _inputBuffer, inSize)); Byte *dest = outBuf; @@ -1287,22 +1309,23 @@ HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned if (blockIndex < 0) return S_FALSE; unpackPos = _dirs.UnpackPos[blockIndex] + n.Offset; - if (unpackPos < n.Offset || unpackPos > _dirs.Data.GetCapacity()) + if (unpackPos < n.Offset || unpackPos > _dirs.Data.Size()) return S_FALSE; - UInt32 rem = (UInt32)_dirs.Data.GetCapacity() - unpackPos; + UInt32 rem = (UInt32)_dirs.Data.Size() - unpackPos; const Byte *p = _dirs.Data + unpackPos; UInt32 fileSize = (UInt32)n.FileSize; - if (fileSize > rem) - return S_FALSE; - rem = fileSize; + // for some squashfs files: fileSize = rem + 3 !!! if (_h.Major >= 3) { - if (rem < 3) + if (fileSize < 3) return S_FALSE; - rem -= 3; + fileSize -= 3; } + if (fileSize > rem) + return S_FALSE; + rem = fileSize; CRecordVector tempItems; while (rem != 0) @@ -1412,7 +1435,7 @@ HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned } int startItemIndex = _items.Size() - tempItems.Size(); - for (int i = 0; i < tempItems.Size(); i++) + FOR_VECTOR (i, tempItems) { const CTempItem &tempItem = tempItems[i]; int index = startItemIndex + i; @@ -1443,9 +1466,11 @@ HRESULT CHandler::Open2(IInStream *inStream) if (!_h.IsSupported()) return E_NOTIMPL; + _noPropsLZMA = false; + _needCheckLzma = false; switch (_h.Method) { - case kMethod_ZLIB: + case kMethod_ZLIB: _needCheckLzma = true; break; case kMethod_LZMA: case kMethod_LZO: case kMethod_XZ: @@ -1461,14 +1486,13 @@ HRESULT CHandler::Open2(IInStream *inStream) { if (_h.NumFrags > kNumFilesMax) return S_FALSE; - _frags.Reserve(_h.NumFrags); - CByteBuffer data; + _frags.ClearAndReserve(_h.NumFrags); 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); + CByteBuffer data(numBlocksBytes); RINOK(inStream->Seek(_h.FragTable, STREAM_SEEK_SET, NULL)); RINOK(ReadStream_FALSE(inStream, data, numBlocksBytes)); bool be = _h.be; @@ -1518,11 +1542,11 @@ HRESULT CHandler::Open2(IInStream *inStream) return S_FALSE; { UInt32 pos = 0; - UInt32 totalSize = (UInt32)_inodesData.Data.GetCapacity(); - _nodesPos.Reserve(_h.NumInodes); - _nodes.Reserve(_h.NumInodes); + UInt32 totalSize = (UInt32)_inodesData.Data.Size(); + _nodesPos.ClearAndReserve(_h.NumInodes); + _nodes.ClearAndReserve(_h.NumInodes); // we use _blockToNode for binary search seed optimizations - _blockToNode.Reserve(_inodesData.GetNumBlocks() + 1); + _blockToNode.ClearAndReserve(_inodesData.GetNumBlocks() + 1); int curBlock = 0; for (UInt32 i = 0; i < _h.NumInodes; i++) { @@ -1544,8 +1568,8 @@ HRESULT CHandler::Open2(IInStream *inStream) _blockToNode.Add(_nodesPos.Size()); curBlock++; } - _nodesPos.Add(pos); - _nodes.Add(n); + _nodesPos.AddInReserved(pos); + _nodes.AddInReserved(n); pos += size; } _blockToNode.Add(_nodesPos.Size()); @@ -1657,7 +1681,6 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb HRESULT res; try { - RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); _openCallback = callback; res = Open2(stream); } @@ -1679,6 +1702,8 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb STDMETHODIMP CHandler::Close() { + _sizeCalculated = 0; + _limitedInStreamSpec->ReleaseStream(); _stream.Release(); @@ -1801,12 +1826,14 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidMethod: { const char *s; - if (_h.SeveralMethods) + if (_noPropsLZMA) + s = "LZMA Spec"; + else if (_h.SeveralMethods) s = "LZMA ZLIB"; else { s = k_Methods[0]; - if (_h.Method < sizeof(k_Methods) / sizeof(k_Methods[0])) + if (_h.Method < ARRAY_SIZE(k_Methods)) s = k_Methods[_h.Method]; } prop = s; @@ -1906,7 +1933,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } case kpidPosixAttrib: { - if (node.Type != 0 && node.Type < sizeof(k_TypeToMode) / sizeof(k_TypeToMode[0])) + if (node.Type != 0 && node.Type < ARRAY_SIZE(k_TypeToMode)) prop = (UInt32)(node.Mode & 0xFFF) | k_TypeToMode[node.Type]; break; } @@ -1914,7 +1941,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidUser: { UInt32 offset = node.Uid * 4; - if (offset < _uids.GetCapacity()) + if (offset < _uids.Size()) prop = (UInt32)Get32(_uids + offset); break; } @@ -1923,13 +1950,13 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val if (_h.Major == 4 || node.Gid == _h.GetSpecGuidIndex()) { UInt32 offset = node.Uid * 4; - if (offset < _uids.GetCapacity()) + if (offset < _uids.Size()) prop = (UInt32)Get32(_uids + offset); } else { UInt32 offset = node.Gid * 4; - if (offset < _gids.GetCapacity()) + if (offset < _gids.Size()) prop = (UInt32)Get32(_gids + offset); } break; @@ -2028,7 +2055,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _items.Size(); if (numItems == 0) @@ -2095,7 +2122,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, { if (hres == E_OUTOFMEMORY) return hres; - res = NExtract::NOperationResult::kUnSupportedMethod; + res = NExtract::NOperationResult::kUnsupportedMethod; } else { @@ -2110,7 +2137,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } else if (hres == E_NOTIMPL) { - res = NExtract::NOperationResult::kUnSupportedMethod; + res = NExtract::NOperationResult::kUnsupportedMethod; } else if(hres != S_FALSE) { @@ -2157,10 +2184,10 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) _nodeIndex = item.Node; size_t cacheSize = _h.BlockSize; - if (_cachedBlock.GetCapacity() != cacheSize) + if (_cachedBlock.Size() != cacheSize) { ClearCache(); - _cachedBlock.SetCapacity(cacheSize); + _cachedBlock.Alloc(cacheSize); } CSquashfsInStream *streamSpec = new CSquashfsInStream; @@ -2179,10 +2206,19 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) COM_TRY_END } -static IInArchive *CreateArc() { return new NArchive::NSquashfs::CHandler; } +IMP_CreateArcIn static CArcInfo g_ArcInfo = - { L"SquashFS", L"squashfs", 0, 0xD2, SIGNATURE, kSignatureSize, false, CreateArc, 0 }; + { "SquashFS", "squashfs", 0, 0xD2, + 3 * (1 + 4), + { + 4, 'h', 's', 'q', 's', + 4, 's', 'q', 's', 'h', + 4, 's', 'h', 's', 'q', + }, + 0, + NArcInfoFlags::kMultiSignature, + CreateArc }; REGISTER_ARC(Cramfs) diff --git a/CPP/7zip/Archive/StdAfx.h b/CPP/7zip/Archive/StdAfx.h old mode 100755 new mode 100644 index ef555ec1..1cbd7fea --- a/CPP/7zip/Archive/StdAfx.h +++ b/CPP/7zip/Archive/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../Common/MyWindows.h" -#include "../../Common/NewHandler.h" +#include "../../Common/Common.h" #endif diff --git a/CPP/7zip/Archive/SwfHandler.cpp b/CPP/7zip/Archive/SwfHandler.cpp old mode 100755 new mode 100644 index d7d9537e..7cfea330 --- a/CPP/7zip/Archive/SwfHandler.cpp +++ b/CPP/7zip/Archive/SwfHandler.cpp @@ -4,19 +4,23 @@ #include "../../../C/CpuArch.h" -#include "Common/Buffer.h" -#include "Common/ComTry.h" -#include "Common/IntToString.h" -#include "Common/MyString.h" +#include "../../Common/ComTry.h" +#include "../../Common/IntToString.h" +#include "../../Common/MyBuffer.h" +#include "../../Common/MyString.h" -#include "Windows/PropVariant.h" +#include "../../Windows/PropVariant.h" #include "../Common/InBuffer.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/LzmaDecoder.h" +#include "../Compress/LzmaEncoder.h" #include "../Compress/ZlibDecoder.h" #include "../Compress/ZlibEncoder.h" @@ -26,33 +30,120 @@ using namespace NWindows; namespace NArchive { + +static const UInt32 kFileSizeMax = (UInt32)1 << 29; + namespace NSwfc { -static const UInt32 kHeaderSize = 8; +static const unsigned kHeaderBaseSize = 8; +static const unsigned kHeaderLzmaSize = 17; static const Byte SWF_UNCOMPRESSED = 'F'; -static const Byte SWF_COMPRESSED = 'C'; -static const Byte SWF_MIN_COMPRESSED_VER = 6; +static const Byte SWF_COMPRESSED_ZLIB = 'C'; +static const Byte SWF_COMPRESSED_LZMA = 'Z'; + +static const Byte SWF_MIN_COMPRESSED_ZLIB_VER = 6; +static const Byte SWF_MIN_COMPRESSED_LZMA_VER = 13; + +static const Byte kVerLim = 20; + +API_FUNC_static_IsArc IsArc_Swf(const Byte *p, size_t size) +{ + if (size < kHeaderBaseSize) + return k_IsArc_Res_NEED_MORE; + if (p[0] != SWF_UNCOMPRESSED || + p[1] != 'W' || + p[2] != 'S' || + p[3] >= kVerLim) + return k_IsArc_Res_NO; + UInt32 uncompressedSize = GetUi32(p + 4); + if (uncompressedSize > kFileSizeMax) + return k_IsArc_Res_NO; + return k_IsArc_Res_YES; +} + +API_FUNC_static_IsArc IsArc_Swfc(const Byte *p, size_t size) +{ + if (size < kHeaderBaseSize + 2 + 1) // 2 + 1 (for zlib check) + return k_IsArc_Res_NEED_MORE; + if ((p[0] != SWF_COMPRESSED_ZLIB && + p[0] != SWF_COMPRESSED_LZMA) || + p[1] != 'W' || + p[2] != 'S' || + p[3] >= kVerLim) + return k_IsArc_Res_NO; + UInt32 uncompressedSize = GetUi32(p + 4); + if (uncompressedSize > kFileSizeMax) + return k_IsArc_Res_NO; + + if (p[0] == SWF_COMPRESSED_ZLIB) + { + if (!NCompress::NZlib::IsZlib_3bytes(p + 8)) + return k_IsArc_Res_NO; + } + else + { + if (size < kHeaderLzmaSize + 2) + return k_IsArc_Res_NEED_MORE; + if (p[kHeaderLzmaSize] != 0 || + (p[kHeaderLzmaSize + 1] & 0x80) != 0) + return k_IsArc_Res_NO; + UInt32 lzmaPackSize = GetUi32(p + 8); + UInt32 lzmaProp = p[12]; + UInt32 lzmaDicSize = GetUi32(p + 13); + if (lzmaProp > 5 * 5 * 9 || + lzmaDicSize > ((UInt32)1 << 28) || + lzmaPackSize < 5 || + lzmaPackSize > ((UInt32)1 << 28)) + return k_IsArc_Res_NO; + } + + return k_IsArc_Res_YES; +} struct CItem { - Byte Buf[kHeaderSize]; + Byte Buf[kHeaderLzmaSize]; + unsigned HeaderSize; 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); } + UInt32 GetLzmaPackSize() const { return GetUi32(Buf + 8); } + UInt32 GetLzmaDicSize() const { return GetUi32(Buf + 13); } - void MakeUncompressed() { Buf[0] = SWF_UNCOMPRESSED; } - void MakeCompressed() + bool IsSwf() const { return (Buf[1] == 'W' && Buf[2] == 'S' && Buf[3] < kVerLim); } + bool IsUncompressed() const { return Buf[0] == SWF_UNCOMPRESSED; } + bool IsZlib() const { return Buf[0] == SWF_COMPRESSED_ZLIB; } + bool IsLzma() const { return Buf[0] == SWF_COMPRESSED_LZMA; } + + void MakeUncompressed() + { + Buf[0] = SWF_UNCOMPRESSED; + HeaderSize = kHeaderBaseSize; + } + void MakeZlib() + { + Buf[0] = SWF_COMPRESSED_ZLIB; + if (Buf[3] < SWF_MIN_COMPRESSED_ZLIB_VER) + Buf[3] = SWF_MIN_COMPRESSED_ZLIB_VER; + } + void MakeLzma(UInt32 packSize) { - Buf[0] = SWF_COMPRESSED; - if (Buf[3] < SWF_MIN_COMPRESSED_VER) - Buf[3] = SWF_MIN_COMPRESSED_VER; + Buf[0] = SWF_COMPRESSED_LZMA; + if (Buf[3] < SWF_MIN_COMPRESSED_LZMA_VER) + Buf[3] = SWF_MIN_COMPRESSED_LZMA_VER; + SetUi32(Buf + 8, packSize); + HeaderSize = kHeaderLzmaSize; } - HRESULT ReadHeader(ISequentialInStream *stream) { return ReadStream_FALSE(stream, Buf, kHeaderSize); } - HRESULT WriteHeader(ISequentialOutStream *stream) { return WriteStream(stream, Buf, kHeaderSize); } + HRESULT ReadHeader(ISequentialInStream *stream) + { + HeaderSize = kHeaderBaseSize; + return ReadStream_FALSE(stream, Buf, kHeaderBaseSize); + } + HRESULT WriteHeader(ISequentialOutStream *stream) + { + return WriteStream(stream, Buf, HeaderSize); + } }; class CHandler: @@ -69,19 +160,22 @@ class CHandler: CMyComPtr _stream; CSingleMethodProps _props; + bool _lzmaMode; public: + CHandler(): _lzmaMode(false) {} 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); + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); }; -STATPROPSTG kProps[] = +static const Byte kProps[] = { - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8} + kpidSize, + kpidPackSize, + kpidMethod }; IMP_IInArchive_Props @@ -90,9 +184,10 @@ IMP_IInArchive_ArcProps_NO_Table STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { NCOM::CPropVariant prop; - switch(propID) + switch (propID) { - case kpidPhySize: if (_packSizeDefined) prop = _packSize; break; + case kpidPhySize: if (_packSizeDefined) prop = _item.HeaderSize + _packSize; break; + case kpidIsNotArcType: prop = true; break; } prop.Detach(value); return S_OK; @@ -104,13 +199,48 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) return S_OK; } +static void DicSizeToString(char *s, UInt32 val) +{ + char c = 0; + unsigned i; + for (i = 0; i <= 31; i++) + if (((UInt32)1 << i) == val) + { + val = i; + break; + } + if (i == 32) + { + c = 'b'; + if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; } + else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; } + } + ::ConvertUInt32ToString(val, s); + int pos = MyStringLen(s); + s[pos++] = c; + s[pos] = 0; +} + STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) { NWindows::NCOM::CPropVariant prop; - switch(propID) + switch (propID) { case kpidSize: prop = (UInt64)_item.GetSize(); break; - case kpidPackSize: if (_packSizeDefined) prop = _packSize; break; + case kpidPackSize: if (_packSizeDefined) prop = _item.HeaderSize + _packSize; break; + case kpidMethod: + { + char s[32]; + if (_item.IsZlib()) + MyStringCopy(s, "zlib"); + else + { + MyStringCopy(s, "LZMA:"); + DicSizeToString(s + 5, _item.GetLzmaDicSize()); + } + prop = s; + break; + } } prop.Detach(value); return S_OK; @@ -126,30 +256,63 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb 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; + RINOK(_item.ReadHeader(stream)); + if (!_item.IsSwf()) + return S_FALSE; + if (_item.IsLzma()) + { + RINOK(ReadStream_FALSE(stream, _item.Buf + kHeaderBaseSize, kHeaderLzmaSize - kHeaderBaseSize)); + _item.HeaderSize = kHeaderLzmaSize; + _packSize = _item.GetLzmaPackSize(); + _packSizeDefined = true; + } + else if (!_item.IsZlib()) + return S_FALSE; + if (_item.GetSize() < _item.HeaderSize) + return S_FALSE; + _seqStream = stream; + return S_OK; } STDMETHODIMP CHandler::Close() { + _packSize = 0; _packSizeDefined = false; _seqStream.Release(); _stream.Release(); return S_OK; } +class CCompressProgressInfoImp: + public ICompressProgressInfo, + public CMyUnknownImp +{ + CMyComPtr Callback; +public: + UInt64 Offset; + MY_UNKNOWN_IMP1(ICompressProgressInfo) + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); + void Init(IArchiveOpenCallback *callback) { Callback = callback; } +}; + +STDMETHODIMP CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */) +{ + if (Callback) + { + UInt64 files = 0; + UInt64 value = Offset + *inSize; + return Callback->SetCompleted(&files, &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)) + if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) return E_INVALIDARG; extractCallback->SetTotal(_item.GetSize()); @@ -163,9 +326,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, extractCallback->PrepareOperation(askMode); - NCompress::NZlib::CDecoder *_decoderSpec = new NCompress::NZlib::CDecoder; - CMyComPtr _decoder = _decoderSpec; - CDummyOutStream *outStreamSpec = new CDummyOutStream; CMyComPtr outStream(outStreamSpec); outStreamSpec->SetStream(realOutStream); @@ -176,24 +336,73 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CMyComPtr progress = lps; lps->Init(extractCallback, false); - lps->InSize = kHeaderSize; + lps->InSize = _item.HeaderSize; 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); + RINOK(_stream->Seek(_item.HeaderSize, STREAM_SEEK_SET, NULL)); + NCompress::NZlib::CDecoder *_decoderZlibSpec = NULL; + NCompress::NLzma::CDecoder *_decoderLzmaSpec = NULL; + CMyComPtr _decoder; + + CMyComPtr inStream2; + + UInt64 unpackSize = _item.GetSize() - (UInt32)8; + if (_item.IsZlib()) + { + _decoderZlibSpec = new NCompress::NZlib::CDecoder; + _decoder = _decoderZlibSpec; + inStream2 = _seqStream; + } + else + { + /* Some .swf files with lzma contain additional 8 bytes at the end + in uncompressed stream. + What does that data mean ??? + We don't decompress these additional 8 bytes */ + + // unpackSize = _item.GetSize(); + // SetUi32(item.Buf + 4, (UInt32)(unpackSize + 8)); + CLimitedSequentialInStream *limitedStreamSpec = new CLimitedSequentialInStream; + inStream2 = limitedStreamSpec; + limitedStreamSpec->SetStream(_seqStream); + limitedStreamSpec->Init(_item.GetLzmaPackSize()); + + _decoderLzmaSpec = new NCompress::NLzma::CDecoder; + _decoder = _decoderLzmaSpec; + // _decoderLzmaSpec->FinishStream = true; + + Byte props[5]; + memcpy(props, _item.Buf + 12, 5); + UInt32 dicSize = _item.GetLzmaDicSize(); + if (dicSize > (UInt32)unpackSize) + { + dicSize = (UInt32)unpackSize; + SetUi32(props + 1, dicSize); + } + RINOK(_decoderLzmaSpec->SetDecoderProperties2(props, 5)); + } + RINOK(item.WriteHeader(outStream)); + HRESULT result = _decoder->Code(inStream2, outStream, NULL, &unpackSize, progress); Int32 opRes = NExtract::NOperationResult::kDataError; if (result == S_OK) { - if (_item.GetSize() == outStreamSpec->GetSize()) + if (item.GetSize() == outStreamSpec->GetSize()) { - _packSizeDefined = true; - _packSize = _decoderSpec->GetInputProcessedSize() + kHeaderSize; - opRes = NExtract::NOperationResult::kOK; + if (_item.IsZlib()) + { + _packSizeDefined = true; + _packSize = _decoderZlibSpec->GetInputProcessedSize(); + opRes = NExtract::NOperationResult::kOK; + } + else + { + // if (_decoderLzmaSpec->GetInputProcessedSize() == _packSize) + opRes = NExtract::NOperationResult::kOK; + } } } else if (result != S_FALSE) @@ -204,8 +413,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_END } -static HRESULT UpdateArchive(ISequentialOutStream *outStream, - UInt64 size, const CSingleMethodProps &props, +static HRESULT UpdateArchive(ISequentialOutStream *outStream, UInt64 size, + bool lzmaMode, const CSingleMethodProps &props, IArchiveUpdateCallback *updateCallback) { UInt64 complexity = 0; @@ -215,27 +424,73 @@ static HRESULT UpdateArchive(ISequentialOutStream *outStream, CMyComPtr fileInStream; RINOK(updateCallback->GetStream(0, &fileInStream)); + /* + CDummyOutStream *outStreamSpec = new CDummyOutStream; + CMyComPtr outStream(outStreamSpec); + outStreamSpec->SetStream(realOutStream); + outStreamSpec->Init(); + realOutStream.Release(); + */ + CItem item; HRESULT res = item.ReadHeader(fileInStream); if (res == S_FALSE) return E_INVALIDARG; RINOK(res); - if (!item.IsUncompressed() || size != item.GetSize()) + if (!item.IsSwf() || !item.IsUncompressed() || size != item.GetSize()) return E_INVALIDARG; - item.MakeCompressed(); - item.WriteHeader(outStream); + NCompress::NZlib::CEncoder *encoderZlibSpec = NULL; + NCompress::NLzma::CEncoder *encoderLzmaSpec = NULL; + CMyComPtr encoder; + CMyComPtr outSeekStream; + if (lzmaMode) + { + outStream->QueryInterface(IID_IOutStream, (void **)&outSeekStream); + if (!outSeekStream) + return E_NOTIMPL; + encoderLzmaSpec = new NCompress::NLzma::CEncoder; + encoder = encoderLzmaSpec; + RINOK(props.SetCoderProps(encoderLzmaSpec, &size)); + item.MakeLzma((UInt32)0xFFFFFFFF); + CBufPtrSeqOutStream *propStreamSpec = new CBufPtrSeqOutStream; + CMyComPtr propStream = propStreamSpec; + propStreamSpec->Init(item.Buf + 12, 5); + RINOK(encoderLzmaSpec->WriteCoderProperties(propStream)); + } + else + { + encoderZlibSpec = new NCompress::NZlib::CEncoder; + encoder = encoderZlibSpec; + encoderZlibSpec->Create(); + RINOK(props.SetCoderProps(encoderZlibSpec->DeflateEncoderSpec, NULL)); + item.MakeZlib(); + } + RINOK(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(props.SetCoderProps(encoderSpec->DeflateEncoderSpec, NULL)); RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, progress)); - if (encoderSpec->GetInputProcessedSize() + kHeaderSize != size) + UInt64 inputProcessed; + if (lzmaMode) + { + UInt64 curPos = 0; + RINOK(outSeekStream->Seek(0, STREAM_SEEK_CUR, &curPos)); + UInt64 packSize = curPos - kHeaderLzmaSize; + if (packSize > (UInt32)0xFFFFFFFF) + return E_INVALIDARG; + item.MakeLzma((UInt32)packSize); + RINOK(outSeekStream->Seek(0, STREAM_SEEK_SET, NULL)); + item.WriteHeader(outStream); + inputProcessed = encoderLzmaSpec->GetInputProcessedSize(); + } + else + { + inputProcessed = encoderZlibSpec->GetInputProcessedSize(); + } + if (inputProcessed + kHeaderBaseSize != size) return E_INVALIDARG; return updateCallback->SetOperationResult(NUpdate::NOperationResult::kOK); } @@ -283,7 +538,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt return E_INVALIDARG; size = prop.uhVal.QuadPart; } - return UpdateArchive(outStream, size, _props, updateCallback); + return UpdateArchive(outStream, size, _lzmaMode, _props, updateCallback); } if (indexInArchive != 0) @@ -301,20 +556,37 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt return NCompress::CopyStream(_seqStream, outStream, NULL); } -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) { - return _props.SetProperties(names, values, numProps); + _lzmaMode = false; + RINOK(_props.SetProperties(names, values, numProps)); + UString m = _props.MethodName; + m.MakeLower_Ascii(); + if (m.IsEqualTo("lzma")) + { + return E_NOTIMPL; + // _lzmaMode = true; + } + else if (m.IsEqualTo("deflate") || m.IsEmpty()) + _lzmaMode = false; + 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 +IMP_CreateArcIn +IMP_CreateArcOut static CArcInfo g_ArcInfo = - { L"SWFc", L"swf", L"~.swf", 0xD8, { 'C', 'W', 'S' }, 3, true, CreateArc, CreateArcOut }; + { "SWFc", "swf", "~.swf", 0xD8, + 2 + 3 + 3, + { + 3, 'C', 'W', 'S', + 3, 'Z', 'W', 'S', + }, + 0, + NArcInfoFlags::kMultiSignature, + REF_CreateArc_Pair, IsArc_Swfc }; REGISTER_ARC(Swfc) @@ -322,8 +594,7 @@ REGISTER_ARC(Swfc) namespace NSwf { -static const UInt32 kFileSizeMax = (UInt32)1 << 30; -static const int kNumTagsMax = (UInt32)1 << 23; +static const unsigned kNumTagsMax = 1 << 23; struct CTag { @@ -338,7 +609,7 @@ class CHandler: { CObjectVector _tags; NSwfc::CItem _item; - UInt64 _packSize; + UInt64 _phySize; HRESULT OpenSeq3(ISequentialInStream *stream, IArchiveOpenCallback *callback); HRESULT OpenSeq2(ISequentialInStream *stream, IArchiveOpenCallback *callback); @@ -349,11 +620,11 @@ public: STDMETHOD(OpenSeq)(ISequentialInStream *stream); }; -STATPROPSTG kProps[] = +static const Byte kProps[] = { - { NULL, kpidPath, VT_BSTR}, - { NULL, kpidSize, VT_UI8}, - { NULL, kpidComment, VT_BSTR} + kpidPath, + kpidSize, + kpidComment, }; IMP_IInArchive_Props @@ -362,9 +633,10 @@ IMP_IInArchive_ArcProps_NO_Table STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { NCOM::CPropVariant prop; - switch(propID) + switch (propID) { - case kpidPhySize: prop = _packSize; break; + case kpidPhySize: prop = _phySize; break; + case kpidIsNotArcType: prop = true; break; } prop.Detach(value); return S_OK; @@ -379,105 +651,105 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) 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" + "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) + switch (propID) { case kpidPath: { @@ -491,9 +763,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } case kpidSize: case kpidPackSize: - prop = (UInt64)tag.Buf.GetCapacity(); break; + prop = (UInt64)tag.Buf.Size(); break; case kpidComment: - if (tag.Type < sizeof(g_TagDesc) / sizeof(g_TagDesc[0])) + if (tag.Type < ARRAY_SIZE(g_TagDesc)) { const char *s = g_TagDesc[tag.Type]; if (s != NULL) @@ -579,8 +851,12 @@ UInt32 CBitReader::ReadBits(unsigned numBits) HRESULT CHandler::OpenSeq3(ISequentialInStream *stream, IArchiveOpenCallback *callback) { RINOK(_item.ReadHeader(stream)) - if (!_item.IsUncompressed()) + if (!_item.IsSwf() || !_item.IsUncompressed()) + return S_FALSE; + UInt32 uncompressedSize = _item.GetSize(); + if (uncompressedSize > kFileSizeMax) return S_FALSE; + CInBuffer s; if (!s.Create(1 << 20)) @@ -610,13 +886,12 @@ HRESULT CHandler::OpenSeq3(ISequentialInStream *stream, IArchiveOpenCallback *ca length = Read32(s); if (type == 0) break; - UInt64 offset = s.GetProcessedSize() + NSwfc::kHeaderSize + length; - if (offset > kFileSizeMax || _tags.Size() >= kNumTagsMax) + UInt64 offset = s.GetProcessedSize() + NSwfc::kHeaderBaseSize + length; + if (offset > uncompressedSize || _tags.Size() >= kNumTagsMax) return S_FALSE; - _tags.Add(CTag()); - CTag &tag = _tags.Back(); + CTag &tag = _tags.AddNew(); tag.Type = type; - tag.Buf.SetCapacity(length); + tag.Buf.Alloc(length); if (s.ReadBytes(tag.Buf, length) != length) return S_FALSE; if (callback && offset >= offsetPrev + (1 << 20)) @@ -626,7 +901,12 @@ HRESULT CHandler::OpenSeq3(ISequentialInStream *stream, IArchiveOpenCallback *ca offsetPrev = offset; } } - _packSize = s.GetProcessedSize() + NSwfc::kHeaderSize; + _phySize = s.GetProcessedSize() + NSwfc::kHeaderBaseSize; + if (_phySize != uncompressedSize) + { + // do we need to support files extracted from SFW-LZMA with additional 8 bytes? + return S_FALSE; + } return S_OK; } @@ -645,6 +925,7 @@ STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) STDMETHODIMP CHandler::Close() { + _phySize = 0; return S_OK; } @@ -652,7 +933,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _tags.Size(); if (numItems == 0) @@ -660,7 +941,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, UInt64 totalSize = 0; UInt32 i; for (i = 0; i < numItems; i++) - totalSize += _tags[allFilesMode ? i : indices[i]].Buf.GetCapacity(); + totalSize += _tags[allFilesMode ? i : indices[i]].Buf.Size(); extractCallback->SetTotal(totalSize); CLocalProgress *lps = new CLocalProgress; @@ -678,7 +959,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, NExtract::NAskMode::kExtract; UInt32 index = allFilesMode ? i : indices[i]; const CByteBuffer &buf = _tags[index].Buf; - totalSize += buf.GetCapacity(); + totalSize += buf.Size(); CMyComPtr outStream; RINOK(extractCallback->GetStream(index, &outStream, askMode)); @@ -687,7 +968,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(extractCallback->PrepareOperation(askMode)); if (outStream) - RINOK(WriteStream(outStream, buf, buf.GetCapacity())); + RINOK(WriteStream(outStream, buf, buf.Size())); outStream.Release(); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); } @@ -695,10 +976,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_END } -static IInArchive *CreateArc() { return new CHandler; } +IMP_CreateArcIn static CArcInfo g_ArcInfo = - { L"SWF", L"swf", 0, 0xD7, { 'F', 'W', 'S' }, 3, true, CreateArc, 0 }; + { "SWF", "swf", 0, 0xD7, + 3, { 'F', 'W', 'S' }, + 0, + NArcInfoFlags::kKeepName, + CreateArc, NULL, NSwfc::IsArc_Swf }; REGISTER_ARC(Swf) diff --git a/CPP/7zip/Archive/Tar/StdAfx.h b/CPP/7zip/Archive/Tar/StdAfx.h old mode 100755 new mode 100644 index 2e4be10b..2854ff3e --- a/CPP/7zip/Archive/Tar/StdAfx.h +++ b/CPP/7zip/Archive/Tar/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" -#include "../../../Common/NewHandler.h" +#include "../../../Common/Common.h" #endif diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp old mode 100755 new mode 100644 index 251afdb7..fc7de5ae --- a/CPP/7zip/Archive/Tar/TarHandler.cpp +++ b/CPP/7zip/Archive/Tar/TarHandler.cpp @@ -2,13 +2,15 @@ #include "StdAfx.h" -#include "Common/ComTry.h" -#include "Common/StringConvert.h" +#include "../../../Common/ComTry.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/UTFConvert.h" -#include "Windows/PropVariant.h" -#include "Windows/Time.h" +#include "../../../Windows/TimeUtils.h" #include "../../Common/LimitedStreams.h" +#include "../../Common/MethodProps.h" #include "../../Common/ProgressUtils.h" #include "../../Common/StreamObjects.h" #include "../../Common/StreamUtils.h" @@ -16,32 +18,34 @@ #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 UINT k_DefaultCodePage = CP_OEMCP; // it uses it if UTF8 check in names shows error -static const STATPROPSTG kProps[] = + +static const Byte 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} + kpidPath, + kpidIsDir, + kpidSize, + kpidPackSize, + kpidMTime, + kpidPosixAttrib, + kpidUser, + kpidGroup, + kpidSymLink, + kpidHardLink, + // kpidLinkType }; -static const STATPROPSTG kArcProps[] = +static const Byte kArcProps[] = { - { NULL, kpidPhySize, VT_UI8}, - { NULL, kpidHeadersSize, VT_UI8} + kpidHeadersSize, + kpidCodePage }; IMP_IInArchive_Props @@ -50,11 +54,42 @@ IMP_IInArchive_ArcProps STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { NCOM::CPropVariant prop; - switch(propID) + switch (propID) { case kpidPhySize: if (_phySizeDefined) prop = _phySize; break; case kpidHeadersSize: if (_phySizeDefined) prop = _headersSize; break; - case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break; + case kpidErrorFlags: + { + UInt32 flags = 0; + if (!_isArc) + flags |= kpv_ErrorFlags_IsNotArc; + else switch (_error) + { + case k_ErrorType_UnexpectedEnd: flags = kpv_ErrorFlags_UnexpectedEnd; break; + case k_ErrorType_Corrupted: flags = kpv_ErrorFlags_HeadersError; break; + } + prop = flags; + break; + } + + case kpidCodePage: + { + const char *name = NULL; + switch (_openCodePage) + { + case CP_OEMCP: name = "OEM"; break; + case CP_UTF8: name = "UTF-8"; break; + } + if (name != NULL) + prop = name; + else + { + char sz[16]; + ConvertUInt32ToString(_openCodePage, sz); + prop = sz; + }; + break; + } } prop.Detach(value); return S_OK; @@ -63,9 +98,16 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) HRESULT CHandler::ReadItem2(ISequentialInStream *stream, bool &filled, CItemEx &item) { item.HeaderPos = _phySize; - RINOK(ReadItem(stream, filled, item, _errorMessage)); - if (filled && item.IsSparse()) - _isSparse = true; + RINOK(ReadItem(stream, filled, item, _error)); + if (filled) + { + /* + if (item.IsSparse()) + _isSparse = true; + */ + if (item.IsPaxExtendedHeader()) + _thereIsPaxExtendedHeader = true; + } _phySize += item.HeaderSize; _headersSize += item.HeaderSize; return S_OK; @@ -80,6 +122,14 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) } _phySizeDefined = true; + + bool utf8_OK = true; + if (!_forceCodePage) + { + if (!utf8_OK) + _curCodePage = k_DefaultCodePage; + } + for (;;) { CItemEx item; @@ -87,12 +137,22 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) RINOK(ReadItem2(stream, filled, item)); if (!filled) break; + + _isArc = true; _items.Add(item); + + if (!_forceCodePage) + { + if (utf8_OK) utf8_OK = CheckUTF8(item.Name); + if (utf8_OK) utf8_OK = CheckUTF8(item.User); + if (utf8_OK) utf8_OK = CheckUTF8(item.Group); + if (utf8_OK) utf8_OK = CheckUTF8(item.LinkName); + } RINOK(stream->Seek(item.GetPackSizeAligned(), STREAM_SEEK_CUR, &_phySize)); if (_phySize > endPos) { - _errorMessage = kUnexpectedEnd; + _error = k_ErrorType_UnexpectedEnd; break; } /* @@ -102,13 +162,13 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) break; } */ - if (callback != NULL) + if (callback) { if (_items.Size() == 1) { RINOK(callback->SetTotal(NULL, &endPos)); } - if (_items.Size() % 100 == 0) + if ((_items.Size() & 0x3FF) == 0) { UInt64 numFiles = _items.Size(); RINOK(callback->SetCompleted(&numFiles, &_phySize)); @@ -116,8 +176,20 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) } } + if (!_forceCodePage) + { + if (!utf8_OK) + _curCodePage = k_DefaultCodePage; + } + _openCodePage = _curCodePage; + if (_items.Size() == 0) { + if (_error != k_ErrorType_OK) + { + _isArc = false; + return S_FALSE; + } CMyComPtr openVolumeCallback; if (!callback) return S_FALSE; @@ -129,11 +201,12 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) 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) + unsigned len = MyStringLen(prop.bstrVal); + if (len < 4 || MyStringCompareNoCase(prop.bstrVal + len - 4, L".tar") != 0) return S_FALSE; } + + _isArc = true; return S_OK; } @@ -158,13 +231,16 @@ STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) STDMETHODIMP CHandler::Close() { - _errorMessage.Empty(); + _isArc = false; + _error = k_ErrorType_OK; + _phySizeDefined = false; _phySize = 0; _headersSize = 0; _curIndex = 0; _latestIsRead = false; - _isSparse = false; + // _isSparse = false; + _thereIsPaxExtendedHeader = false; _items.Clear(); _seqStream.Release(); _stream.Release(); @@ -181,6 +257,8 @@ CHandler::CHandler() { copyCoderSpec = new NCompress::CCopyCoder(); copyCoder = copyCoderSpec; + _openCodePage = CP_UTF8; + Init(); } HRESULT CHandler::SkipTo(UInt32 index) @@ -194,7 +272,7 @@ HRESULT CHandler::SkipTo(UInt32 index) _phySize += copyCoderSpec->TotalSize; if (copyCoderSpec->TotalSize != packSize) { - _errorMessage = kUnexpectedEnd; + _error = k_ErrorType_UnexpectedEnd; return S_FALSE; } _latestIsRead = false; @@ -215,15 +293,29 @@ HRESULT CHandler::SkipTo(UInt32 index) return S_OK; } -static UString TarStringToUnicode(const AString &s) +void CHandler::TarStringToUnicode(const AString &s, NWindows::NCOM::CPropVariant &prop, bool toOs) const { - return MultiByteToUnicodeString(s, CP_OEMCP); + UString dest; + if (_curCodePage == CP_UTF8) + { + if (!ConvertUTF8ToUnicode(s, dest)) + { + prop = "[ERROR-NAME]"; + return; + } + } + else + dest = MultiByteToUnicodeString(s, _curCodePage); + if (toOs) + prop = NItemName::GetOSName2(dest); + else + prop = dest; } STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; + NCOM::CPropVariant prop; const CItemEx *item; if (_stream) @@ -239,9 +331,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } } - switch(propID) + switch (propID) { - case kpidPath: prop = NItemName::GetOSName2(TarStringToUnicode(item->Name)); break; + case kpidPath: TarStringToUnicode(item->Name, prop, true); break; case kpidIsDir: prop = item->IsDir(); break; case kpidSize: prop = item->GetUnpackSize(); break; case kpidPackSize: prop = item->GetPackSizeAligned(); break; @@ -254,9 +346,11 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } 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; + case kpidUser: TarStringToUnicode(item->User, prop); break; + case kpidGroup: TarStringToUnicode(item->Group, prop); break; + case kpidSymLink: if (item->LinkFlag == NFileHeader::NLinkFlag::kSymLink && !item->LinkName.IsEmpty()) TarStringToUnicode(item->LinkName, prop); break; + case kpidHardLink: if (item->LinkFlag == NFileHeader::NLinkFlag::kHardLink && !item->LinkName.IsEmpty()) TarStringToUnicode(item->LinkName, prop); break; + // case kpidLinkType: prop = (int)item->LinkFlag; break; } prop.Detach(value); return S_OK; @@ -272,7 +366,7 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (!seqMode) stream = _stream; - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _items.Size(); if (_stream && numItems == 0) @@ -333,7 +427,18 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (!testMode && !realOutStream) { if (!seqMode) + { + /* + // probably we must show extracting info it callback handler instead + if (item->IsHardLink() || + item->IsSymLink()) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + } + */ continue; + } skipMode = true; askMode = NExtract::NAskMode::kSkip; } @@ -344,13 +449,20 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, outStreamSpec->Init(skipMode ? 0 : unpackSize, true); Int32 opRes = NExtract::NOperationResult::kOK; - if (item->IsSparse()) - opRes = NExtract::NOperationResult::kUnSupportedMethod; + CMyComPtr inStream2; + if (!item->IsSparse()) + inStream2 = inStream; else { - if (item->IsLink()) + GetStream(index, &inStream2); + if (!inStream2) + return E_FAIL; + } + + { + if (item->IsSymLink()) { - RINOK(WriteStream(outStreamSpec, (const char *)item->LinkName, item->LinkName.Length())); + RINOK(WriteStream(outStreamSpec, (const char *)item->LinkName, item->LinkName.Len())); } else { @@ -359,7 +471,7 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(_stream->Seek(item->GetDataPosition(), STREAM_SEEK_SET, NULL)); } streamSpec->Init(item->GetPackSizeAligned()); - RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + RINOK(copyCoder->Code(inStream2, outStream, NULL, NULL, progress)); } if (outStreamSpec->GetRem() != 0) opRes = NExtract::NOperationResult::kDataError; @@ -376,22 +488,198 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_END } +class CSparseStream: + public IInStream, + public CMyUnknownImp +{ + UInt64 _phyPos; + UInt64 _virtPos; + bool _needStartSeek; + +public: + CHandler *Handler; + CMyComPtr HandlerRef; + unsigned ItemIndex; + CRecordVector PhyOffsets; + + MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + + void Init() + { + _virtPos = 0; + _phyPos = 0; + _needStartSeek = true; + } +}; + + +STDMETHODIMP CSparseStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (size == 0) + return S_OK; + const CItemEx &item = Handler->_items[ItemIndex]; + if (_virtPos >= item.Size) + return S_OK; + { + UInt64 rem = item.Size - _virtPos; + if (size > rem) + size = (UInt32)rem; + } + + HRESULT res = S_OK; + + if (item.SparseBlocks.IsEmpty()) + memset(data, 0, size); + else + { + unsigned left = 0, right = item.SparseBlocks.Size(); + for (;;) + { + unsigned mid = (left + right) / 2; + if (mid == left) + break; + if (_virtPos < item.SparseBlocks[mid].Offset) + right = mid; + else + left = mid; + } + + const CSparseBlock &sb = item.SparseBlocks[left]; + UInt64 relat = _virtPos - sb.Offset; + + if (_virtPos >= sb.Offset && relat < sb.Size) + { + UInt64 rem = sb.Size - relat; + if (size > rem) + size = (UInt32)rem; + UInt64 phyPos = PhyOffsets[left] + relat; + if (_needStartSeek || _phyPos != phyPos) + { + RINOK(Handler->_stream->Seek(item.GetDataPosition() + phyPos, STREAM_SEEK_SET, NULL)); + _needStartSeek = false; + _phyPos = phyPos; + } + res = Handler->_stream->Read(data, size, &size); + _phyPos += size; + } + else + { + UInt64 next = item.Size; + if (_virtPos < sb.Offset) + next = sb.Offset; + else if (left + 1 < item.SparseBlocks.Size()) + next = item.SparseBlocks[left + 1].Offset; + UInt64 rem = next - _virtPos; + if (size > rem) + size = (UInt32)rem; + memset(data, 0, size); + } + } + + _virtPos += size; + if (processedSize) + *processedSize = size; + return res; +} + +STDMETHODIMP CSparseStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: offset += Handler->_items[ItemIndex].Size; break; + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = offset; + if (newPosition) + *newPosition = _virtPos; + return S_OK; +} + STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) { COM_TRY_BEGIN + const CItemEx &item = _items[index]; + if (item.IsSparse()) - return E_NOTIMPL; - if (item.IsLink()) + { + CSparseStream *streamSpec = new CSparseStream; + CMyComPtr streamTemp = streamSpec; + streamSpec->Init(); + streamSpec->Handler = this; + streamSpec->HandlerRef = (IInArchive *)this; + streamSpec->ItemIndex = index; + streamSpec->PhyOffsets.Reserve(item.SparseBlocks.Size()); + UInt64 offs = 0; + FOR_VECTOR(i, item.SparseBlocks) + { + const CSparseBlock &sb = item.SparseBlocks[i]; + streamSpec->PhyOffsets.AddInReserved(offs); + offs += sb.Size; + } + *stream = streamTemp.Detach(); + return S_OK; + } + + if (item.IsSymLink()) { CBufInStream *streamSpec = new CBufInStream; CMyComPtr streamTemp = streamSpec; - streamSpec->Init((const Byte *)(const char *)item.LinkName, item.LinkName.Length(), (IInArchive *)this); + streamSpec->Init((const Byte *)(const char *)item.LinkName, item.LinkName.Len(), (IInArchive *)this); *stream = streamTemp.Detach(); return S_OK; } + return CreateLimitedInStream(_stream, item.GetDataPosition(), item.PackSize, stream); + COM_TRY_END } +void CHandler::Init() +{ + _forceCodePage = false; + // _codePage = CP_OEMCP; + _curCodePage = _specifiedCodePage = CP_UTF8; // CP_OEMCP; +} + +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) +{ + Init(); + + for (UInt32 i = 0; i < numProps; i++) + { + UString name = names[i]; + name.MakeLower_Ascii(); + if (name.IsEmpty()) + return E_INVALIDARG; + + const PROPVARIANT &prop = values[i]; + + if (name[0] == L'x') + { + // some clients write 'x' property. So we support it + UInt32 level = 0; + RINOK(ParsePropToUInt32(name.Ptr(1), prop, level)); + } + else if (name.IsEqualTo("cp")) + { + UInt32 cp = CP_OEMCP; + RINOK(ParsePropToUInt32(L"", prop, cp)); + _forceCodePage = true; + _curCodePage = _specifiedCodePage = cp; + } + else + return E_INVALIDARG; + } + return S_OK; +} + }} diff --git a/CPP/7zip/Archive/Tar/TarHandler.h b/CPP/7zip/Archive/Tar/TarHandler.h old mode 100755 new mode 100644 index 9251edf6..23854767 --- a/CPP/7zip/Archive/Tar/TarHandler.h +++ b/CPP/7zip/Archive/Tar/TarHandler.h @@ -3,12 +3,15 @@ #ifndef __TAR_HANDLER_H #define __TAR_HANDLER_H -#include "Common/MyCom.h" -#include "../IArchive.h" +#include "../../../Common/MyCom.h" + +#include "../../../Windows/PropVariant.h" #include "../../Compress/CopyCoder.h" -#include "TarItem.h" +#include "../IArchive.h" + +#include "TarIn.h" namespace NArchive { namespace NTar { @@ -17,13 +20,15 @@ class CHandler: public IInArchive, public IArchiveOpenSeq, public IInArchiveGetStream, + public ISetProperties, public IOutArchive, public CMyUnknownImp { +public: CObjectVector _items; CMyComPtr _stream; CMyComPtr _seqStream; - +private: UInt32 _curIndex; bool _latestIsRead; CItemEx _latestItem; @@ -31,8 +36,16 @@ class CHandler: UInt64 _phySize; UInt64 _headersSize; bool _phySizeDefined; - AString _errorMessage; - bool _isSparse; + EErrorType _error; + bool _isArc; + + // bool _isSparse; + bool _thereIsPaxExtendedHeader; + + bool _forceCodePage; + UInt32 _specifiedCodePage; + UInt32 _curCodePage; + UInt32 _openCodePage; NCompress::CCopyCoder *copyCoderSpec; CMyComPtr copyCoder; @@ -40,12 +53,13 @@ class CHandler: HRESULT ReadItem2(ISequentialInStream *stream, bool &filled, CItemEx &itemInfo); HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); HRESULT SkipTo(UInt32 index); - + void TarStringToUnicode(const AString &s, NWindows::NCOM::CPropVariant &prop, bool toOs = false) const; public: - MY_UNKNOWN_IMP4( + MY_UNKNOWN_IMP5( IInArchive, IArchiveOpenSeq, IInArchiveGetStream, + ISetProperties, IOutArchive ) @@ -53,7 +67,9 @@ public: INTERFACE_IOutArchive(;) STDMETHOD(OpenSeq)(ISequentialInStream *stream); STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); + void Init(); CHandler(); }; diff --git a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp old mode 100755 new mode 100644 index b0ec63d1..b909e96c --- a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp +++ b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp @@ -2,11 +2,13 @@ #include "StdAfx.h" -#include "Common/ComTry.h" -#include "Common/StringConvert.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 "../../../Windows/PropVariant.h" +#include "../../../Windows/TimeUtils.h" #include "TarHandler.h" #include "TarUpdate.h" @@ -22,24 +24,54 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) return S_OK; } -static HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, AString &res) +HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, + AString &res, UINT codePage, bool convertSlash = false) { NCOM::CPropVariant prop; RINOK(callback->GetProperty(index, propId, &prop)); if (prop.vt == VT_BSTR) - res = UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP); + { + UString s = prop.bstrVal; + if (convertSlash) + s = NItemName::MakeLegalName(s); + if (codePage == CP_UTF8) + { + if (!ConvertUnicodeToUTF8(s, res)) + return E_INVALIDARG; + } + else + UnicodeStringToMultiByte2(res, s, codePage); + } else if (prop.vt != VT_EMPTY) return E_INVALIDARG; return S_OK; } +// sort old files with original order. + +static int CompareUpdateItems(void *const *p1, void *const *p2, void *) +{ + const CUpdateItem &u1 = *(*((const CUpdateItem **)p1)); + const CUpdateItem &u2 = *(*((const CUpdateItem **)p2)); + if (!u1.NewProps) + { + if (u2.NewProps) + return -1; + return MyCompare(u1.IndexInArchive, u2.IndexInArchive); + } + if (!u2.NewProps) + return 1; + return MyCompare(u1.IndexInClient, u2.IndexInClient); +} + STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *callback) { COM_TRY_BEGIN - if ((_stream && (!_errorMessage.IsEmpty() || _isSparse)) || _seqStream) + if ((_stream && (_error != k_ErrorType_OK /* || _isSparse */)) || _seqStream) return E_NOTIMPL; CObjectVector updateItems; + UINT codePage = (_forceCodePage ? _specifiedCodePage : _openCodePage); for (UInt32 i = 0; i < numItems; i++) { CUpdateItem ui; @@ -87,19 +119,13 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt else ui.MTime = NTime::FileTimeToUnixTime64(prop.filetime); } - { - 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)); + RINOK(GetPropString(callback, i, kpidPath, ui.Name, codePage, true)); + if (ui.IsDir && !ui.Name.IsEmpty() && ui.Name.Back() != '/') + ui.Name += '/'; + RINOK(GetPropString(callback, i, kpidUser, ui.User, codePage)); + RINOK(GetPropString(callback, i, kpidGroup, ui.Group, codePage)); } + if (IntToBool(newData)) { NCOM::CPropVariant prop; @@ -115,7 +141,12 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt } updateItems.Add(ui); } - return UpdateArchive(_stream, outStream, _items, updateItems, callback); + if (_thereIsPaxExtendedHeader) + { + // we restore original order of files, if there is pax header block + updateItems.Sort(CompareUpdateItems, NULL); + } + return UpdateArchive(_stream, outStream, _items, updateItems, codePage, callback); COM_TRY_END } diff --git a/CPP/7zip/Archive/Tar/TarHeader.cpp b/CPP/7zip/Archive/Tar/TarHeader.cpp old mode 100755 new mode 100644 index 3275b284..70be09f3 --- a/CPP/7zip/Archive/Tar/TarHeader.cpp +++ b/CPP/7zip/Archive/Tar/TarHeader.cpp @@ -1,4 +1,4 @@ -// Archive/Tar/Header.h +// Archive/TarHeader.cpp #include "StdAfx.h" @@ -8,18 +8,16 @@ 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 + // 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"; + const char kUsTar_00[8] = { 'u', 's', 't', 'a', 'r', 0, '0', '0' } ; } }}} diff --git a/CPP/7zip/Archive/Tar/TarHeader.h b/CPP/7zip/Archive/Tar/TarHeader.h old mode 100755 new mode 100644 index a212ae03..df594d81 --- a/CPP/7zip/Archive/Tar/TarHeader.h +++ b/CPP/7zip/Archive/Tar/TarHeader.h @@ -1,20 +1,22 @@ -// Archive/Tar/Header.h +// Archive/TarHeader.h #ifndef __ARCHIVE_TAR_HEADER_H #define __ARCHIVE_TAR_HEADER_H -#include "Common/Types.h" +#include "../../../Common/MyTypes.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; + const unsigned kRecordSize = 512; + const unsigned kNameSize = 100; + const unsigned kUserNameSize = 32; + const unsigned kGroupNameSize = 32; + const unsigned kPrefixSize = 155; + + const unsigned kUstarMagic_Offset = 257; /* struct CHeader @@ -42,66 +44,39 @@ namespace NFileHeader }; */ - 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 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 kHardLink = '1'; // Link to previously dumped file + const char kSymLink = '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. + const char kGnu_LongLink = 'K'; + const char kGnu_LongName = 'L'; + const char kSparse = 'S'; + 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. */ - - const char kSparse = 'S'; } - // 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 + // extern const char *kUsTar; // = "ustar"; // 5 chars + // extern const char *kGNUTar; // = "GNUtar "; // 7 chars and a null + // extern const char *kEmpty; // = "\0\0\0\0\0\0\0\0" + extern const char kUsTar_00[]; } - } }} diff --git a/CPP/7zip/Archive/Tar/TarIn.cpp b/CPP/7zip/Archive/Tar/TarIn.cpp old mode 100755 new mode 100644 index b6e5e0f5..1584a520 --- a/CPP/7zip/Archive/Tar/TarIn.cpp +++ b/CPP/7zip/Archive/Tar/TarIn.cpp @@ -4,18 +4,20 @@ #include "../../../../C/CpuArch.h" -#include "Common/StringToInt.h" +#include "../../../Common/StringToInt.h" #include "../../Common/StreamUtils.h" +#include "../IArchive.h" + #include "TarIn.h" namespace NArchive { namespace NTar { -static void MyStrNCpy(char *dest, const char *src, int size) +static void MyStrNCpy(char *dest, const char *src, unsigned size) { - for (int i = 0; i < size; i++) + for (unsigned i = 0; i < size; i++) { char c = src[i]; dest[i] = c; @@ -24,19 +26,21 @@ static void MyStrNCpy(char *dest, const char *src, int size) } } -static bool OctalToNumber(const char *srcString, int size, UInt64 &res) +static bool OctalToNumber(const char *srcString, unsigned size, UInt64 &res) { char sz[32]; MyStrNCpy(sz, srcString, size); sz[size] = 0; const char *end; - int i; + unsigned i; for (i = 0; sz[i] == ' '; i++); res = ConvertOctStringToUInt64(sz + i, &end); + if (end == sz + i) + return false; return (*end == ' ' || *end == 0); } -static bool OctalToNumber32(const char *srcString, int size, UInt32 &res) +static bool OctalToNumber32(const char *srcString, unsigned size, UInt32 &res) { UInt64 res64; if (!OctalToNumber(srcString, size, res64)) @@ -45,17 +49,27 @@ static bool OctalToNumber32(const char *srcString, int size, UInt32 &res) return (res64 <= 0xFFFFFFFF); } -#define RIF(x) { if (!(x)) return S_FALSE; } +#define RIF(x) { if (!(x)) return S_OK; } + +/* +static bool IsEmptyData(const char *buf, size_t size) +{ + for (unsigned i = 0; i < size; i++) + if (buf[i] != 0) + return false; + return true; +} +*/ static bool IsRecordLast(const char *buf) { - for (int i = 0; i < NFileHeader::kRecordSize; i++) + for (unsigned i = 0; i < NFileHeader::kRecordSize; i++) if (buf[i] != 0) return false; return true; } -static void ReadString(const char *s, int size, AString &result) +static void ReadString(const char *s, unsigned size, AString &result) { char temp[NFileHeader::kRecordSize + 1]; MyStrNCpy(temp, s, size); @@ -88,12 +102,39 @@ static bool ParseSize(const char *p, UInt64 &val) return OctalToNumber(p, 12, val); } -static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemEx &item, AString &error) +#define CHECK(x) { if (!(x)) return k_IsArc_Res_NO; } + +API_FUNC_IsArc IsArc_Tar(const Byte *p2, size_t size) +{ + if (size < NFileHeader::kRecordSize) + return k_IsArc_Res_NEED_MORE; + + const char *p = (const char *)p2; + p += NFileHeader::kNameSize; + + UInt32 mode; + CHECK(OctalToNumber32(p, 8, 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; + + UInt64 packSize; + Int64 time; + UInt32 checkSum; + CHECK(ParseSize(p, packSize)); p += 12; + CHECK(ParseInt64(p, time)); p += 12; + CHECK(OctalToNumber32(p, 8, checkSum)); + return k_IsArc_Res_YES; +} + +static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemEx &item, EErrorType &error) { char buf[NFileHeader::kRecordSize]; char *p = buf; - error.Empty(); + error = k_ErrorType_OK; filled = false; bool thereAreEmptyRecords = false; @@ -103,26 +144,41 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE RINOK(ReadStream(stream, buf, &processedSize)); if (processedSize == 0) { - if (!thereAreEmptyRecords ) - error = "There are no trailing zero-filled records"; + if (!thereAreEmptyRecords) + error = k_ErrorType_UnexpectedEnd; // "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"; + if (!thereAreEmptyRecords) + error = k_ErrorType_UnexpectedEnd; // error = "There is no correct record at the end of archive"; + else + { + /* + if (IsEmptyData(buf, processedSize)) + error = k_ErrorType_UnexpectedEnd; + else + { + // extraReadSize = processedSize; + // error = k_ErrorType_Corrupted; // some data after the end tail zeros + } + */ + } + return S_OK; } - item.HeaderSize += NFileHeader::kRecordSize; if (!IsRecordLast(buf)) break; + item.HeaderSize += NFileHeader::kRecordSize; thereAreEmptyRecords = true; } if (thereAreEmptyRecords) { - error = "There are data after end of archive"; + // error = "There are data after end of archive"; return S_OK; } + error = k_ErrorType_Corrupted; ReadString(p, NFileHeader::kNameSize, item.Name); p += NFileHeader::kNameSize; RIF(OctalToNumber32(p, 8, item.Mode)); p += 8; @@ -137,7 +193,7 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE UInt32 checkSum; RIF(OctalToNumber32(p, 8, checkSum)); - memcpy(p, NFileHeader::kCheckSumBlanks, 8); p += 8; + memset(p, ' ', 8); p += 8; item.LinkFlag = *p++; @@ -148,93 +204,170 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE 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; + item.DeviceMajorDefined = (p[0] != 0); if (item.DeviceMajorDefined) { RIF(OctalToNumber32(p, 8, item.DeviceMajor)); } p += 8; + item.DeviceMinorDefined = (p[0] != 0); if (item.DeviceMinorDefined) { RIF(OctalToNumber32(p, 8, item.DeviceMinor)); } p += 8; AString prefix; ReadString(p, NFileHeader::kPrefixSize, prefix); p += NFileHeader::kPrefixSize; - if (!prefix.IsEmpty() && item.IsMagic() && + if (!prefix.IsEmpty() && item.IsUstarMagic() && (item.LinkFlag != 'L' /* || prefix != "00000000000" */ )) item.Name = prefix + AString('/') + item.Name; - if (item.LinkFlag == NFileHeader::NLinkFlag::kLink) + if (item.LinkFlag == NFileHeader::NLinkFlag::kHardLink) { item.PackSize = 0; item.Size = 0; } - else if (item.LinkFlag == NFileHeader::NLinkFlag::kSparse) + /* + TAR standard requires sum of unsigned byte values. + But some TAR programs use sum of signed byte values. + So we check both values. + */ + UInt32 checkSumReal = 0; + Int32 checkSumReal_Signed = 0; + for (unsigned i = 0; i < NFileHeader::kRecordSize; i++) + { + char c = buf[i]; + checkSumReal_Signed += (signed char)c; + checkSumReal += (Byte)buf[i]; + } + + if (checkSumReal != checkSum) + { + if ((UInt32)checkSumReal_Signed != checkSum) + return S_OK; + } + + item.HeaderSize += NFileHeader::kRecordSize; + + if (item.LinkFlag == NFileHeader::NLinkFlag::kSparse) { - if (buf[482] != 0) - return S_FALSE; + Byte isExtended = buf[482]; + if (isExtended != 0 && isExtended != 1) + return S_OK; RIF(ParseSize(buf + 483, item.Size)); - p = buf + 386; UInt64 min = 0; - for (int i = 0; i < 4; i++, p += 24) + for (unsigned i = 0; i < 4; i++) { + p = buf + 386 + 24 * i; if (GetBe32(p) == 0) + { + if (isExtended != 0) + return S_OK; break; + } CSparseBlock sb; RIF(ParseSize(p, sb.Offset)); RIF(ParseSize(p + 12, sb.Size)); item.SparseBlocks.Add(sb); if (sb.Offset < min || sb.Offset > item.Size) - return S_FALSE; + return S_OK; if ((sb.Offset & 0x1FF) != 0 || (sb.Size & 0x1FF) != 0) - return S_FALSE; + return S_OK; min = sb.Offset + sb.Size; if (min < sb.Offset) - return S_FALSE; + return S_OK; + } + if (min > item.Size) + return S_OK; + + while (isExtended != 0) + { + size_t processedSize = NFileHeader::kRecordSize; + RINOK(ReadStream(stream, buf, &processedSize)); + if (processedSize != NFileHeader::kRecordSize) + { + error = k_ErrorType_UnexpectedEnd; + return S_OK; + } + + item.HeaderSize += NFileHeader::kRecordSize; + isExtended = buf[21 * 24]; + if (isExtended != 0 && isExtended != 1) + return S_OK; + for (unsigned i = 0; i < 21; i++) + { + p = buf + 24 * i; + if (GetBe32(p) == 0) + { + if (isExtended != 0) + return S_OK; + break; + } + CSparseBlock sb; + RIF(ParseSize(p, sb.Offset)); + RIF(ParseSize(p + 12, sb.Size)); + item.SparseBlocks.Add(sb); + if (sb.Offset < min || sb.Offset > item.Size) + return S_OK; + if ((sb.Offset & 0x1FF) != 0 || (sb.Size & 0x1FF) != 0) + return S_OK; + min = sb.Offset + sb.Size; + if (min < sb.Offset) + return S_OK; + } } if (min > item.Size) - return S_FALSE; + return S_OK; } - UInt32 checkSumReal = 0; - for (int i = 0; i < NFileHeader::kRecordSize; i++) - checkSumReal += (Byte)buf[i]; - - if (checkSumReal != checkSum) - return S_FALSE; - filled = true; + error = k_ErrorType_OK; return S_OK; } -HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, AString &error) +HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, EErrorType &error) { item.HeaderSize = 0; bool flagL = false; bool flagK = false; AString nameL; AString nameK; + for (;;) { RINOK(GetNextItemReal(stream, filled, item, error)); if (!filled) + { + if (error == k_ErrorType_OK && (flagL || flagK)) + error = k_ErrorType_Corrupted; + return S_OK; + } + + if (error != k_ErrorType_OK) return S_OK; - if (item.LinkFlag == 'L' || // NEXT file has a long name - item.LinkFlag == 'K') // NEXT file has a long linkname + + if (item.LinkFlag == NFileHeader::NLinkFlag::kGnu_LongName || // file contains a long name + item.LinkFlag == NFileHeader::NLinkFlag::kGnu_LongLink) // file contains a long linkname { AString *name; - if (item.LinkFlag == 'L') - { if (flagL) return S_FALSE; flagL = true; name = &nameL; } + if (item.LinkFlag == NFileHeader::NLinkFlag::kGnu_LongName) + { if (flagL) return S_OK; flagL = true; name = &nameL; } else - { if (flagK) return S_FALSE; flagK = true; name = &nameK; } + { if (flagK) return S_OK; flagK = true; name = &nameK; } - if (item.Name.Compare(NFileHeader::kLongLink) != 0 && - item.Name.Compare(NFileHeader::kLongLink2) != 0) - return S_FALSE; + if (item.Name != NFileHeader::kLongLink && + item.Name != NFileHeader::kLongLink2) + return S_OK; if (item.PackSize > (1 << 14)) - return S_FALSE; - int packSize = (int)item.GetPackSizeAligned(); + return S_OK; + unsigned packSize = (unsigned)item.GetPackSizeAligned(); char *buf = name->GetBuffer(packSize); - RINOK(ReadStream_FALSE(stream, buf, packSize)); - item.HeaderSize += packSize; - buf[(size_t)item.PackSize] = '\0'; + size_t processedSize = packSize; + HRESULT res = ReadStream(stream, buf, &processedSize); + item.HeaderSize += (unsigned)processedSize; + buf[(size_t)item.PackSize] = 0; name->ReleaseBuffer(); + RINOK(res); + if (processedSize != packSize) + { + error = k_ErrorType_UnexpectedEnd; + return S_OK; + } continue; } + switch (item.LinkFlag) { case 'g': @@ -256,10 +389,12 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, AStri } default: if (item.LinkFlag > '7' || (item.LinkFlag < '0' && item.LinkFlag != 0)) - return S_FALSE; + return S_OK; } + if (flagL) item.Name = nameL; if (flagK) item.LinkName = nameK; + error = k_ErrorType_OK; return S_OK; } } diff --git a/CPP/7zip/Archive/Tar/TarIn.h b/CPP/7zip/Archive/Tar/TarIn.h old mode 100755 new mode 100644 index a5491ebe..a67b1dbd --- a/CPP/7zip/Archive/Tar/TarIn.h +++ b/CPP/7zip/Archive/Tar/TarIn.h @@ -10,7 +10,16 @@ namespace NArchive { namespace NTar { -HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &itemInfo, AString &error); +enum EErrorType +{ + k_ErrorType_OK, + k_ErrorType_Corrupted, + k_ErrorType_UnexpectedEnd, +}; + +HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &itemInfo, EErrorType &error); + +API_FUNC_IsArc IsArc_Tar(const Byte *p, size_t size); }} diff --git a/CPP/7zip/Archive/Tar/TarItem.h b/CPP/7zip/Archive/Tar/TarItem.h old mode 100755 new mode 100644 index 3584a7ce..805a2e7c --- a/CPP/7zip/Archive/Tar/TarItem.h +++ b/CPP/7zip/Archive/Tar/TarItem.h @@ -40,28 +40,41 @@ struct CItem CRecordVector SparseBlocks; - bool IsLink() const { return LinkFlag == NFileHeader::NLinkFlag::kSymbolicLink && (Size == 0); } + bool IsSymLink() const { return LinkFlag == NFileHeader::NLinkFlag::kSymLink && (Size == 0); } + bool IsHardLink() const { return LinkFlag == NFileHeader::NLinkFlag::kHardLink; } bool IsSparse() const { return LinkFlag == NFileHeader::NLinkFlag::kSparse; } - UInt64 GetUnpackSize() const { return IsLink() ? LinkName.Length() : Size; } + UInt64 GetUnpackSize() const { return IsSymLink() ? LinkName.Len() : Size; } + bool IsPaxExtendedHeader() const + { + switch (LinkFlag) + { + case 'g': + case 'x': + case 'X': // Check it + return true; + } + return false; + } bool IsDir() const { - switch(LinkFlag) + switch (LinkFlag) { case NFileHeader::NLinkFlag::kDirectory: case NFileHeader::NLinkFlag::kDumpDir: return true; case NFileHeader::NLinkFlag::kOldNormal: case NFileHeader::NLinkFlag::kNormal: + case NFileHeader::NLinkFlag::kSymLink: return NItemName::HasTailSlash(Name, CP_OEMCP); } return false; } - bool IsMagic() const + bool IsUstarMagic() const { for (int i = 0; i < 5; i++) - if (Magic[i] != NFileHeader::NMagic::kUsTar[i]) + if (Magic[i] != NFileHeader::NMagic::kUsTar_00[i]) return false; return true; } diff --git a/CPP/7zip/Archive/Tar/TarOut.cpp b/CPP/7zip/Archive/Tar/TarOut.cpp old mode 100755 new mode 100644 index 6e699e28..51081e8b --- a/CPP/7zip/Archive/Tar/TarOut.cpp +++ b/CPP/7zip/Archive/Tar/TarOut.cpp @@ -2,8 +2,6 @@ #include "StdAfx.h" -#include "Common/IntToString.h" - #include "../../Common/StreamUtils.h" #include "TarOut.h" @@ -11,26 +9,15 @@ 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) +HRESULT COutArchive::WriteBytes(const void *data, unsigned size) { - char s[32]; - ConvertUInt64ToString(value, s, 8); - return AString(s) + ' '; + Pos += size; + return WriteStream(m_Stream, data, size); } -static void MyStrNCpy(char *dest, const char *src, int size) +static void MyStrNCpy(char *dest, const char *src, unsigned size) { - for (int i = 0; i < size; i++) + for (unsigned i = 0; i < size; i++) { char c = src[i]; dest[i] = c; @@ -39,54 +26,53 @@ static void MyStrNCpy(char *dest, const char *src, int size) } } -static bool MakeOctalString8(char *s, UInt32 value) +static bool WriteOctal_8(char *s, UInt32 val) { - AString tempString = MakeOctalString(value); - - const int kMaxSize = 8; - if (tempString.Length() >= kMaxSize) + const unsigned kNumDigits = 8 - 1; + if (val >= ((UInt32)1 << (kNumDigits * 3))) return false; - int numSpaces = kMaxSize - (tempString.Length() + 1); - for (int i = 0; i < numSpaces; i++) - s[i] = ' '; - MyStringCopy(s + numSpaces, (const char *)tempString); + for (unsigned i = 0; i < kNumDigits; i++) + { + s[kNumDigits - 1 - i] = (char)('0' + (val & 7)); + val >>= 3; + } return true; } -static void MakeOctalString12(char *s, UInt64 value) +static void WriteOctal_12(char *s, UInt64 val) { - AString tempString = MakeOctalString(value); - const int kMaxSize = 12; - if (tempString.Length() > kMaxSize) + const unsigned kNumDigits = 12 - 1; + if (val >= ((UInt64)1 << (kNumDigits * 3))) { // 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); + for (unsigned i = 0; i < 8; i++, val <<= 8) + s[4 + i] = (char)(val >> 56); return; } - int numSpaces = kMaxSize - tempString.Length(); - for (int i = 0; i < numSpaces; i++) - s[i] = ' '; - memmove(s + numSpaces, (const char *)tempString, tempString.Length()); + for (unsigned i = 0; i < kNumDigits; i++) + { + s[kNumDigits - 1 - i] = (char)('0' + (val & 7)); + val >>= 3; + } } -static void MakeOctalString12_From_Int64(char *s, Int64 value) +static void WriteOctal_12_Signed(char *s, Int64 val) { - if (value >= 0) + if (val >= 0) { - MakeOctalString12(s, value); + WriteOctal_12(s, val); return; } s[0] = s[1] = s[2] = s[3] = (char)(Byte)0xFF; - for (int i = 0; i < 8; i++, value <<= 8) - s[4 + i] = (char)(value >> 56); + for (unsigned i = 0; i < 8; i++, val <<= 8) + s[4 + i] = (char)(val >> 56); } -static bool CopyString(char *dest, const AString &src, int maxSize) +static bool CopyString(char *dest, const AString &src, unsigned maxSize) { - if (src.Length() >= maxSize) + if (src.Len() >= maxSize) return false; MyStringCopy(dest, (const char *)src); return true; @@ -97,25 +83,22 @@ static bool CopyString(char *dest, const AString &src, int maxSize) HRESULT COutArchive::WriteHeaderReal(const CItem &item) { char record[NFileHeader::kRecordSize]; + memset(record, 0, 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) + if (item.Name.Len() > 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; + RETURN_IF_NOT_TRUE(WriteOctal_8(cur, item.Mode)); cur += 8; + RETURN_IF_NOT_TRUE(WriteOctal_8(cur, item.UID)); cur += 8; + RETURN_IF_NOT_TRUE(WriteOctal_8(cur, item.GID)); cur += 8; - MakeOctalString12(cur, item.PackSize); cur += 12; - MakeOctalString12_From_Int64(cur, item.MTime); cur += 12; + WriteOctal_12(cur, item.PackSize); cur += 12; + WriteOctal_12_Signed(cur, item.MTime); cur += 12; - memmove(cur, NFileHeader::kCheckSumBlanks, 8); + memset(cur, ' ', 8); cur += 8; *cur++ = item.LinkFlag; @@ -123,7 +106,7 @@ HRESULT COutArchive::WriteHeaderReal(const CItem &item) RETURN_IF_NOT_TRUE(CopyString(cur, item.LinkName, NFileHeader::kNameSize)); cur += NFileHeader::kNameSize; - memmove(cur, item.Magic, 8); + memcpy(cur, item.Magic, 8); cur += 8; RETURN_IF_NOT_TRUE(CopyString(cur, item.User, NFileHeader::kUserNameSize)); @@ -132,64 +115,127 @@ HRESULT COutArchive::WriteHeaderReal(const CItem &item) cur += NFileHeader::kGroupNameSize; - if (item.DeviceMajorDefined) - RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.DeviceMajor)); - cur += 8; + if (item.DeviceMajorDefined) RETURN_IF_NOT_TRUE(WriteOctal_8(cur, item.DeviceMajor)); cur += 8; + if (item.DeviceMinorDefined) RETURN_IF_NOT_TRUE(WriteOctal_8(cur, item.DeviceMinor)); cur += 8; - if (item.DeviceMinorDefined) - RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.DeviceMinor)); - cur += 8; + if (item.IsSparse()) + { + record[482] = (char)(item.SparseBlocks.Size() > 4 ? 1 : 0); + WriteOctal_12(record + 483, item.Size); + for (unsigned i = 0; i < item.SparseBlocks.Size() && i < 4; i++) + { + const CSparseBlock &sb = item.SparseBlocks[i]; + char *p = record + 386 + 24 * i; + WriteOctal_12(p, sb.Offset); + WriteOctal_12(p + 12, sb.Size); + } + } + { + UInt32 checkSum = 0; + { + for (unsigned i = 0; i < NFileHeader::kRecordSize; i++) + checkSum += (Byte)record[i]; + } + /* we use GNU TAR scheme: + checksum field is formatted differently from the + other fields: it has [6] digits, a null, then a space. */ + // RETURN_IF_NOT_TRUE(WriteOctal_8(record + 148, checkSum)); + const unsigned kNumDigits = 6; + for (unsigned i = 0; i < kNumDigits; i++) + { + record[148 + kNumDigits - 1 - i] = (char)('0' + (checkSum & 7)); + checkSum >>= 3; + } + record[148 + 6] = 0; + } - UInt32 checkSumReal = 0; - for (i = 0; i < NFileHeader::kRecordSize; i++) - checkSumReal += Byte(record[i]); + RINOK(WriteBytes(record, NFileHeader::kRecordSize)); - RETURN_IF_NOT_TRUE(MakeOctalString8(record + 148, checkSumReal)); + if (item.IsSparse()) + { + for (unsigned i = 4; i < item.SparseBlocks.Size();) + { + memset(record, 0, NFileHeader::kRecordSize); + for (unsigned t = 0; t < 21 && i < item.SparseBlocks.Size(); t++, i++) + { + const CSparseBlock &sb = item.SparseBlocks[i]; + char *p = record + 24 * t; + WriteOctal_12(p, sb.Offset); + WriteOctal_12(p + 12, sb.Size); + } + record[21 * 24] = (char)(i < item.SparseBlocks.Size() ? 1 : 0); + RINOK(WriteBytes(record, NFileHeader::kRecordSize)); + } + } - return WriteBytes(record, NFileHeader::kRecordSize); + return S_OK; } HRESULT COutArchive::WriteHeader(const CItem &item) { - int nameSize = item.Name.Length(); - if (nameSize < NFileHeader::kNameSize) + unsigned nameSize = item.Name.Len(); + unsigned linkSize = item.LinkName.Len(); + + /* There two versions of GNU tar: + OLDGNU_FORMAT: it writes short name and zero at the end + GNU_FORMAT: it writes only short name without zero at the end + we write it as OLDGNU_FORMAT with zero at the end */ + + if (nameSize < NFileHeader::kNameSize && + linkSize < NFileHeader::kNameSize) return WriteHeaderReal(item); - CItem modifiedItem = item; - int nameStreamSize = nameSize + 1; - modifiedItem.PackSize = 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); + CItem mi = item; + mi.Name = NFileHeader::kLongLink; + mi.LinkName.Empty(); + for (int i = 0; i < 2; i++) + { + const AString *name; + // We suppose that GNU tar also writes item for long link before item for LongName? + if (i == 0) + { + mi.LinkFlag = NFileHeader::NLinkFlag::kGnu_LongLink; + name = &item.LinkName; + } + else + { + mi.LinkFlag = NFileHeader::NLinkFlag::kGnu_LongName; + name = &item.Name; + } + if (name->Len() < NFileHeader::kNameSize) + continue; + unsigned nameStreamSize = name->Len() + 1; + mi.PackSize = nameStreamSize; + RINOK(WriteHeaderReal(mi)); + RINOK(WriteBytes((const char *)*name, nameStreamSize)); + RINOK(FillDataResidual(nameStreamSize)); + } + + mi = item; + if (mi.Name.Len() >= NFileHeader::kNameSize) + mi.Name.SetFrom(item.Name, NFileHeader::kNameSize - 1); + if (mi.LinkName.Len() >= NFileHeader::kNameSize) + mi.LinkName.SetFrom(item.LinkName, NFileHeader::kNameSize - 1); + return WriteHeaderReal(mi); } HRESULT COutArchive::FillDataResidual(UInt64 dataSize) { - UInt32 lastRecordSize = UInt32(dataSize & (NFileHeader::kRecordSize - 1)); + unsigned lastRecordSize = ((unsigned)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); + unsigned rem = NFileHeader::kRecordSize - lastRecordSize; + Byte buf[NFileHeader::kRecordSize]; + memset(buf, 0, rem); + return WriteBytes(buf, rem); } 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++) + memset(record, 0, NFileHeader::kRecordSize); + for (unsigned i = 0; i < 2; i++) { RINOK(WriteBytes(record, NFileHeader::kRecordSize)); } diff --git a/CPP/7zip/Archive/Tar/TarOut.h b/CPP/7zip/Archive/Tar/TarOut.h old mode 100755 new mode 100644 index ef837869..ee9b965e --- a/CPP/7zip/Archive/Tar/TarOut.h +++ b/CPP/7zip/Archive/Tar/TarOut.h @@ -3,21 +3,29 @@ #ifndef __ARCHIVE_TAR_OUT_H #define __ARCHIVE_TAR_OUT_H -#include "TarItem.h" +#include "../../../Common/MyCom.h" -#include "Common/MyCom.h" #include "../../IStream.h" +#include "TarItem.h" + namespace NArchive { namespace NTar { class COutArchive { CMyComPtr m_Stream; - HRESULT WriteBytes(const void *buffer, UInt32 size); -public: - void Create(ISequentialOutStream *outStream); + + HRESULT WriteBytes(const void *data, unsigned size); HRESULT WriteHeaderReal(const CItem &item); +public: + UInt64 Pos; + + void Create(ISequentialOutStream *outStream) + { + m_Stream = outStream; + } + HRESULT WriteHeader(const CItem &item); HRESULT FillDataResidual(UInt64 dataSize); HRESULT WriteFinishHeader(); diff --git a/CPP/7zip/Archive/Tar/TarRegister.cpp b/CPP/7zip/Archive/Tar/TarRegister.cpp old mode 100755 new mode 100644 index e21c0aac..9e0f6f21 --- a/CPP/7zip/Archive/Tar/TarRegister.cpp +++ b/CPP/7zip/Archive/Tar/TarRegister.cpp @@ -5,14 +5,22 @@ #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 + +namespace NArchive { +namespace NTar { + +IMP_CreateArcIn +IMP_CreateArcOut static CArcInfo g_ArcInfo = -{ L"tar", L"tar", 0, 0xEE, { 'u', 's', 't', 'a', 'r' }, 5, false, CreateArc, CreateArcOut }; + { "tar", "tar", 0, 0xEE, + 5, { 'u', 's', 't', 'a', 'r' }, + NFileHeader::kUstarMagic_Offset, + NArcInfoFlags::kStartOpen | + NArcInfoFlags::kSymLinks | + NArcInfoFlags::kHardLinks, + REF_CreateArc_Pair, IsArc_Tar }; REGISTER_ARC(Tar) + +}} diff --git a/CPP/7zip/Archive/Tar/TarUpdate.cpp b/CPP/7zip/Archive/Tar/TarUpdate.cpp old mode 100755 new mode 100644 index fb123169..fdbce395 --- a/CPP/7zip/Archive/Tar/TarUpdate.cpp +++ b/CPP/7zip/Archive/Tar/TarUpdate.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../../Windows/TimeUtils.h" + #include "../../Common/LimitedStreams.h" #include "../../Common/ProgressUtils.h" @@ -13,18 +15,26 @@ namespace NArchive { namespace NTar { +HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, + AString &res, UINT codePage, bool convertSlash = false); + HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, const CObjectVector &inputItems, const CObjectVector &updateItems, + UINT codePage, IArchiveUpdateCallback *updateCallback) { COutArchive outArchive; outArchive.Create(outStream); + outArchive.Pos = 0; + + CMyComPtr outSeekStream; + outStream->QueryInterface(IID_IOutStream, (void **)&outSeekStream); UInt64 complexity = 0; - int i; - for(i = 0; i < updateItems.Size(); i++) + unsigned i; + for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (ui.NewData) @@ -76,37 +86,101 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, item.DeviceMinorDefined = false; item.UID = 0; item.GID = 0; - memmove(item.Magic, NFileHeader::NMagic::kEmpty, 8); + memcpy(item.Magic, NFileHeader::NMagic::kUsTar_00, 8); } else item = inputItems[ui.IndexInArchive]; + AString symLink; + if (ui.NewData || ui.NewProps) + { + RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidSymLink, symLink, codePage, true)); + if (!symLink.IsEmpty()) + { + item.LinkFlag = NFileHeader::NLinkFlag::kSymLink; + item.LinkName = symLink; + } + } + if (ui.NewData) { + item.SparseBlocks.Clear(); item.PackSize = ui.Size; + item.Size = ui.Size; if (ui.Size == (UInt64)(Int64)-1) return E_INVALIDARG; - } - else - item.PackSize = inputItems[ui.IndexInArchive].PackSize; - - if (ui.NewData) - { + CMyComPtr fileInStream; - HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream); - if (res != S_FALSE) + + bool needWrite = true; + if (!symLink.IsEmpty()) { - RINOK(res); + item.PackSize = 0; + item.Size = 0; + } + else + { + HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream); + if (res == S_FALSE) + needWrite = false; + else + { + RINOK(res); + + if (fileInStream) + { + CMyComPtr getProps; + fileInStream->QueryInterface(IID_IStreamGetProps, (void **)&getProps); + if (getProps) + { + FILETIME mTime; + UInt64 size2; + if (getProps->GetProps(&size2, NULL, NULL, &mTime, NULL) == S_OK) + { + item.PackSize = size2; + item.MTime = NWindows::NTime::FileTimeToUnixTime64(mTime);; + } + } + } + { + AString hardLink; + RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidHardLink, hardLink, codePage, true)); + if (!hardLink.IsEmpty()) + { + item.LinkFlag = NFileHeader::NLinkFlag::kHardLink; + item.LinkName = hardLink; + item.PackSize = 0; + item.Size = 0; + fileInStream.Release(); + } + } + } + } + + if (needWrite) + { + UInt64 fileHeaderStartPos = outArchive.Pos; RINOK(outArchive.WriteHeader(item)); - if (!ui.IsDir) + if (fileInStream) { RINOK(copyCoder->Code(fileInStream, outStream, NULL, NULL, progress)); + outArchive.Pos += copyCoderSpec->TotalSize; if (copyCoderSpec->TotalSize != item.PackSize) - return E_FAIL; + { + if (!outSeekStream) + return E_FAIL; + UInt64 backOffset = outArchive.Pos - fileHeaderStartPos; + RINOK(outSeekStream->Seek(-(Int64)backOffset, STREAM_SEEK_CUR, NULL)); + outArchive.Pos = fileHeaderStartPos; + item.PackSize = copyCoderSpec->TotalSize; + RINOK(outArchive.WriteHeader(item)); + RINOK(outSeekStream->Seek(item.PackSize, STREAM_SEEK_CUR, NULL)); + outArchive.Pos += item.PackSize; + } RINOK(outArchive.FillDataResidual(item.PackSize)); } } - complexity += ui.Size; + complexity += item.PackSize; RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); } else @@ -115,6 +189,30 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, UInt64 size; if (ui.NewProps) { + // memcpy(item.Magic, NFileHeader::NMagic::kEmpty, 8); + + if (!symLink.IsEmpty()) + { + item.PackSize = 0; + item.Size = 0; + } + else + { + if (ui.IsDir == existItem.IsDir()) + item.LinkFlag = existItem.LinkFlag; + + item.SparseBlocks = existItem.SparseBlocks; + item.Size = existItem.Size; + item.PackSize = existItem.PackSize; + } + + item.DeviceMajorDefined = existItem.DeviceMajorDefined; + item.DeviceMinorDefined = existItem.DeviceMinorDefined; + item.DeviceMajor = existItem.DeviceMajor; + item.DeviceMinor = existItem.DeviceMinor; + item.UID = existItem.UID; + item.GID = existItem.GID; + RINOK(outArchive.WriteHeader(item)); RINOK(inStream->Seek(existItem.GetDataPosition(), STREAM_SEEK_SET, NULL)); size = existItem.PackSize; @@ -129,6 +227,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)); if (copyCoderSpec->TotalSize != size) return E_FAIL; + outArchive.Pos += size; RINOK(outArchive.FillDataResidual(existItem.PackSize)); complexity += size; } diff --git a/CPP/7zip/Archive/Tar/TarUpdate.h b/CPP/7zip/Archive/Tar/TarUpdate.h old mode 100755 new mode 100644 index 3f889739..c2393416 --- a/CPP/7zip/Archive/Tar/TarUpdate.h +++ b/CPP/7zip/Archive/Tar/TarUpdate.h @@ -27,6 +27,7 @@ struct CUpdateItem HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, const CObjectVector &inputItems, const CObjectVector &updateItems, + UINT codePage, IArchiveUpdateCallback *updateCallback); }} diff --git a/CPP/7zip/Archive/Udf/StdAfx.h b/CPP/7zip/Archive/Udf/StdAfx.h old mode 100755 new mode 100644 index 2e4be10b..2854ff3e --- a/CPP/7zip/Archive/Udf/StdAfx.h +++ b/CPP/7zip/Archive/Udf/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" -#include "../../../Common/NewHandler.h" +#include "../../../Common/Common.h" #endif diff --git a/CPP/7zip/Archive/Udf/UdfHandler.cpp b/CPP/7zip/Archive/Udf/UdfHandler.cpp old mode 100755 new mode 100644 index c7085272..6aa53ea9 --- a/CPP/7zip/Archive/Udf/UdfHandler.cpp +++ b/CPP/7zip/Archive/Udf/UdfHandler.cpp @@ -2,13 +2,14 @@ #include "StdAfx.h" -#include "Common/ComTry.h" +#include "../../../Common/ComTry.h" -#include "Windows/PropVariant.h" -#include "Windows/Time.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/TimeUtils.h" #include "../../Common/LimitedStreams.h" #include "../../Common/ProgressUtils.h" +#include "../../Common/RegisterArc.h" #include "../../Common/StreamObjects.h" #include "../../Compress/CopyCoder.h" @@ -18,7 +19,7 @@ namespace NArchive { namespace NUdf { -void UdfTimeToFileTime(const CTime &t, NWindows::NCOM::CPropVariant &prop) +static void UdfTimeToFileTime(const CTime &t, NWindows::NCOM::CPropVariant &prop) { UInt64 numSecs; const Byte *d = t.Data; @@ -33,21 +34,21 @@ void UdfTimeToFileTime(const CTime &t, NWindows::NCOM::CPropVariant &prop) prop = ft; } -static STATPROPSTG kProps[] = +static const Byte 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} + kpidPath, + kpidIsDir, + kpidSize, + kpidPackSize, + kpidMTime, + kpidATime }; -static STATPROPSTG kArcProps[] = +static const Byte kArcProps[] = { - { NULL, kpidComment, VT_BSTR}, - { NULL, kpidClusterSize, VT_UI4}, - { NULL, kpidCTime, VT_FILETIME} + kpidComment, + kpidClusterSize, + kpidCTime }; IMP_IInArchive_Props @@ -59,6 +60,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) NWindows::NCOM::CPropVariant prop; switch(propID) { + case kpidPhySize: prop = _archive.PhySize; break; + case kpidComment: { UString comment = _archive.GetComment(); @@ -71,7 +74,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) if (_archive.LogVols.Size() > 0) { UInt32 blockSize = _archive.LogVols[0].BlockSize; - int i; + unsigned i; for (i = 1; i < _archive.LogVols.Size(); i++) if (_archive.LogVols[i].BlockSize != blockSize) break; @@ -88,6 +91,16 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) UdfTimeToFileTime(vol.FileSets[0].RecodringTime, prop); } break; + + case kpidErrorFlags: + { + UInt32 v = 0; + if (!_archive.IsArc) v |= kpv_ErrorFlags_IsNotArc; + if (_archive.Unsupported) v |= kpv_ErrorFlags_UnsupportedFeature; + if (_archive.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd; + prop = v; + break; + } } prop.Detach(value); return S_OK; @@ -127,9 +140,7 @@ HRESULT CProgressImp::SetCompleted() return S_OK; } -STDMETHODIMP CHandler::Open(IInStream *stream, - const UInt64 * /* maxCheckStartPosition */, - IArchiveOpenCallback *callback) +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback) { COM_TRY_BEGIN { @@ -137,14 +148,14 @@ STDMETHODIMP CHandler::Open(IInStream *stream, CProgressImp progressImp(callback); RINOK(_archive.Open(stream, &progressImp)); bool showVolName = (_archive.LogVols.Size() > 1); - for (int volIndex = 0; volIndex < _archive.LogVols.Size(); volIndex++) + FOR_VECTOR (volIndex, _archive.LogVols) { const CLogVol &vol = _archive.LogVols[volIndex]; bool showFileSetName = (vol.FileSets.Size() > 1); - for (int fsIndex = 0; fsIndex < vol.FileSets.Size(); fsIndex++) + FOR_VECTOR (fsIndex, vol.FileSets) { const CFileSet &fs = vol.FileSets[fsIndex]; - for (int i = ((showVolName || showFileSetName) ? 0 : 1); i < fs.Refs.Size(); i++) + for (unsigned i = ((showVolName || showFileSetName) ? 0 : 1); i < fs.Refs.Size(); i++) { CRef2 ref2; ref2.Vol = volIndex; @@ -184,7 +195,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val 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) + switch (propID) { case kpidPath: prop = _archive.GetItemPath(ref2.Vol, ref2.Fs, ref2.Ref, _archive.LogVols.Size() > 1, vol.FileSets.Size() > 1); break; @@ -200,99 +211,6 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val 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; @@ -325,7 +243,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) extentStreamSpec->Stream = _inStream; UInt64 virtOffset = 0; - for (int extentIndex = 0; extentIndex < item.Extents.Size(); extentIndex++) + FOR_VECTOR (extentIndex, item.Extents) { const CMyExtent &extent = item.Extents[extentIndex]; UInt32 len = extent.GetLen(); @@ -363,7 +281,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _refs2.Size(); if (numItems == 0) @@ -431,7 +349,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CMyComPtr udfInStream; HRESULT res = GetStream(index, &udfInStream); if (res == E_NOTIMPL) - opRes = NExtract::NOperationResult::kUnSupportedMethod; + opRes = NExtract::NOperationResult::kUnsupportedMethod; else if (res != S_OK) opRes = NExtract::NOperationResult::kDataError; else @@ -448,4 +366,18 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_END } +IMP_CreateArcIn + +static const UInt32 kIsoStartPos = 0x8000; + +static CArcInfo g_ArcInfo = + { "Udf", "udf iso img", 0, 0xE0, + // 5, { 0, 'N', 'S', 'R', '0' }, + 6, { 1, 'C', 'D', '0', '0', '1' }, + kIsoStartPos, + NArcInfoFlags::kStartOpen, + CreateArc, NULL, IsArc_Udf }; + +REGISTER_ARC(Udf) + }} diff --git a/CPP/7zip/Archive/Udf/UdfHandler.h b/CPP/7zip/Archive/Udf/UdfHandler.h old mode 100755 new mode 100644 index f513727d..da44b232 --- a/CPP/7zip/Archive/Udf/UdfHandler.h +++ b/CPP/7zip/Archive/Udf/UdfHandler.h @@ -1,9 +1,10 @@ -// Udf/Handler.h +// UdfHandler.h #ifndef __UDF_HANDLER_H #define __UDF_HANDLER_H -#include "Common/MyCom.h" +#include "../../../Common/MyCom.h" + #include "../IArchive.h" #include "UdfIn.h" @@ -13,9 +14,9 @@ namespace NUdf { struct CRef2 { - int Vol; - int Fs; - int Ref; + unsigned Vol; + unsigned Fs; + unsigned Ref; }; class CHandler: diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp old mode 100755 new mode 100644 index d2a2884f..3053a0c1 --- a/CPP/7zip/Archive/Udf/UdfIn.cpp +++ b/CPP/7zip/Archive/Udf/UdfIn.cpp @@ -2,12 +2,25 @@ #include "StdAfx.h" +// #define SHOW_DEBUG_INFO + +#ifdef SHOW_DEBUG_INFO +#include +#endif + #include "../../../../C/CpuArch.h" +#include "../../Common/RegisterArc.h" #include "../../Common/StreamUtils.h" #include "UdfIn.h" +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif + #define Get16(p) GetUi16(p) #define Get32(p) GetUi32(p) #define Get64(p) GetUi64(p) @@ -15,24 +28,22 @@ 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); +static const unsigned kNumPartitionsMax = 64; +static const unsigned kNumLogVolumesMax = 64; +static const unsigned kNumRecursionLevelsMax = 1 << 10; +static const unsigned kNumItemsMax = 1 << 27; +static const unsigned kNumFilesMax = 1 << 28; +static const unsigned kNumRefsMax = 1 << 28; +static const UInt32 kNumExtentsMax = (UInt32)1 << 30; +static const UInt64 kFileNameLengthTotalMax = (UInt64)1 << 33; +static const UInt64 kInlineExtentsSizeMax = (UInt64)1 << 33; #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 CRC16_UPDATE_BYTE(crc, b) ((UInt16)(g_Crc16Table[(((crc) >> 8) ^ (b)) & 0xFF] ^ ((crc) << 8))) #define kCrc16Poly 0x1021 -UInt16 g_Crc16Table[256]; +static UInt16 g_Crc16Table[256]; void MY_FAST_CALL Crc16GenerateTable(void) { @@ -61,15 +72,14 @@ UInt16 MY_FAST_CALL Crc16Calc(const void *data, size_t 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); + Data.CopyFrom(p, size); } -static UString ParseDString(const Byte *data, int size) +static UString ParseDString(const Byte *data, unsigned size) { UString res; wchar_t *p; @@ -78,8 +88,8 @@ static UString ParseDString(const Byte *data, int size) Byte type = data[0]; if (type == 8) { - p = res.GetBuffer((int)size + 1); - for (int i = 1; i < size; i++) + p = res.GetBuffer(size); + for (unsigned i = 1; i < size; i++) { wchar_t c = data[i]; if (c == 0) @@ -89,10 +99,10 @@ static UString ParseDString(const Byte *data, int size) } else if (type == 16) { - p = res.GetBuffer((int)size / 2 + 1); - for (int i = 1; i + 2 <= size; i += 2) + p = res.GetBuffer(size / 2); + for (unsigned i = 1; i + 2 <= size; i += 2) { - wchar_t c = ((wchar_t)data[i] << 8) | data[i + 1]; + wchar_t c = GetBe16(data + i); if (c == 0) break; *p++ = c; @@ -106,13 +116,14 @@ static UString ParseDString(const Byte *data, int size) 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))); + unsigned size = Data[sizeof(Data) - 1]; + return ParseDString(Data, MyMin(size, (unsigned)(sizeof(Data) - 1))); } +UString CDString::GetString() const { return ParseDString(Data, (unsigned)Data.Size()); } + void CTime::Parse(const Byte *buf) { memcpy(Data, buf, sizeof(Data)); } /* @@ -161,8 +172,8 @@ HRESULT CTag::Parse(const Byte *buf, size_t size) 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]; + for (i = 0; i < 4; i++) sum = (Byte)(sum + buf[i]); + for (i = 5; i < 16; i++) sum = (Byte)(sum + buf[i]); if (sum != buf[4] || buf[5] != 0) return S_FALSE; Id = Get16(buf); @@ -182,27 +193,27 @@ HRESULT CTag::Parse(const Byte *buf, size_t size) 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_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 + 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 }; @@ -237,6 +248,8 @@ void CLongAllocDesc::Parse(const Byte *buf) bool CInArchive::CheckExtent(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len) const { const CLogVol &vol = LogVols[volIndex]; + if (partitionRef >= (int)vol.PartitionMaps.Size()) + return false; 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); @@ -244,7 +257,7 @@ bool CInArchive::CheckExtent(int volIndex, int partitionRef, UInt32 blockPos, UI bool CInArchive::CheckItemExtents(int volIndex, const CItem &item) const { - for (int i = 0; i < item.Extents.Size(); i++) + FOR_VECTOR (i, item.Extents) { const CMyExtent &e = item.Extents[i]; if (!CheckExtent(volIndex, e.PartitionRef, e.Pos, e.GetLen())) @@ -259,9 +272,14 @@ HRESULT CInArchive::Read(int volIndex, int partitionRef, UInt32 blockPos, UInt32 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); + UInt64 offset = ((UInt64)partition.Pos << SecLogSize) + (UInt64)blockPos * vol.BlockSize; + RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL)); + HRESULT res = ReadStream_FALSE(_stream, buf, len); + if (res == S_FALSE && offset + len > FileSize) + UnexpectedEnd = true; + RINOK(res); + UpdatePhySize(offset + len); + return S_OK; } HRESULT CInArchive::Read(int volIndex, const CLongAllocDesc &lad, Byte *buf) @@ -278,9 +296,9 @@ HRESULT CInArchive::ReadFromFile(int volIndex, const CItem &item, CByteBuffer &b buf = item.InlineData; return S_OK; } - buf.SetCapacity((size_t)item.Size); + buf.Alloc((size_t)item.Size); size_t pos = 0; - for (int i = 0; i < item.Extents.Size(); i++) + FOR_VECTOR (i, item.Extents) { const CMyExtent &e = item.Extents[i]; UInt32 len = e.GetLen(); @@ -407,9 +425,8 @@ HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &la if (lad.GetLen() != vol.BlockSize) return S_FALSE; - CByteBuffer buf; size_t size = lad.GetLen(); - buf.SetCapacity(size); + CByteBuffer buf(size); RINOK(Read(volIndex, lad, buf)); CTag tag; @@ -456,8 +473,7 @@ HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &la if (desctType == ICB_DESC_TYPE_INLINE) { item.IsInline = true; - item.InlineData.SetCapacity(allocDescriptorsLen); - memcpy(item.InlineData, p + pos, allocDescriptorsLen); + item.InlineData.CopyFrom(p + pos, allocDescriptorsLen); } else { @@ -504,7 +520,7 @@ HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &la item.InlineData.Free(); const Byte *p = buf; - size = buf.GetCapacity(); + size = buf.Size(); size_t processedTotal = 0; for (; processedTotal < size;) { @@ -519,7 +535,7 @@ HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &la // file.ImplUse = fileId.ImplUse; file.Id = fileId.Id; - _fileNameLengthTotal += file.Id.Data.GetCapacity(); + _fileNameLengthTotal += file.Id.Data.Size(); if (_fileNameLengthTotal > kFileNameLengthTotalMax) return S_FALSE; @@ -538,9 +554,9 @@ HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &la return S_FALSE; _numExtents += item.Extents.Size(); - if (item.InlineData.GetCapacity() > kInlineExtentsSizeMax - _inlineExtentsSize) + if (item.InlineData.Size() > kInlineExtentsSizeMax - _inlineExtentsSize) return S_FALSE; - _inlineExtentsSize += item.InlineData.GetCapacity(); + _inlineExtentsSize += item.InlineData.Size(); } return S_OK; @@ -548,7 +564,7 @@ HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &la HRESULT CInArchive::FillRefs(CFileSet &fs, int fileIndex, int parent, int numRecurseAllowed) { - if (_numRefs % 10000 == 0) + if ((_numRefs & 0xFFF) == 0) { RINOK(_progress->SetCompleted()); } @@ -563,23 +579,47 @@ HRESULT CInArchive::FillRefs(CFileSet &fs, int fileIndex, int parent, int numRec parent = fs.Refs.Size(); fs.Refs.Add(ref); const CItem &item = Items[Files[fileIndex].ItemIndex]; - for (int i = 0; i < item.SubFiles.Size(); i++) + FOR_VECTOR (i, item.SubFiles) { RINOK(FillRefs(fs, item.SubFiles[i], parent, numRecurseAllowed)); } return S_OK; } +API_FUNC_IsArc IsArc_Udf(const Byte *p, size_t size) +{ + UInt32 res = k_IsArc_Res_NO; + unsigned SecLogSize; + for (SecLogSize = 11;; SecLogSize -= 3) + { + if (SecLogSize < 8) + return res; + UInt32 offset = (UInt32)256 << SecLogSize; + size_t bufSize = 1 << SecLogSize; + if (offset + bufSize > size) + res = k_IsArc_Res_NEED_MORE; + else + { + CTag tag; + if (tag.Parse(p + offset, bufSize) == S_OK) + if (tag.Id == DESC_TYPE_AnchorVolPtr) + return k_IsArc_Res_YES; + } + } +} + HRESULT CInArchive::Open2() { Clear(); + UInt64 fileSize; + RINOK(_stream->Seek(0, STREAM_SEEK_END, &fileSize)); + FileSize = fileSize; // Some UDFs contain additional pad zeros (2 KB). // Seek to STREAM_SEEK_END for direct DVD reading can return 8 KB more, so we check last 16 KB. // And when we read last block, result read size can be smaller than required size. - UInt64 fileSize; - RINOK(_stream->Seek(0, STREAM_SEEK_END, &fileSize)); + /* const size_t kBufSize = 1 << 14; Byte buf[kBufSize]; size_t readSize = (fileSize < kBufSize) ? (size_t)fileSize : kBufSize; @@ -598,22 +638,69 @@ HRESULT CInArchive::Open2() if (tag.Id == DESC_TYPE_AnchorVolPtr) break; } - + PhySize = fileSize; CExtent extentVDS; extentVDS.Parse(buf + i + 16); + */ + const size_t kBufSize = 1 << 11; + Byte buf[kBufSize]; + for (SecLogSize = 11;; SecLogSize -= 3) + { + if (SecLogSize < 8) + return S_FALSE; + UInt32 offset = (UInt32)256 << SecLogSize; + if (offset >= fileSize) + continue; + RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL)); + size_t bufSize = 1 << SecLogSize; + size_t readSize = bufSize; + RINOK(ReadStream(_stream, buf, &readSize)); + if (readSize == bufSize) + { + CTag tag; + if (tag.Parse(buf, readSize) == S_OK) + if (tag.Id == DESC_TYPE_AnchorVolPtr) + break; + } + } + PhySize = (UInt32)(256 + 1) << SecLogSize; + IsArc = true; - for (UInt32 location = extentVDS.Pos; ; location++) + CExtent extentVDS; + extentVDS.Parse(buf + 16); + { + CExtent extentVDS2; + extentVDS2.Parse(buf + 24); + UpdatePhySize(((UInt64)extentVDS.Pos << SecLogSize) + extentVDS.Len); + UpdatePhySize(((UInt64)extentVDS2.Pos << SecLogSize) + extentVDS2.Len); + } + + for (UInt32 location = 0; ; 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)); + if (((UInt64)(location + 1) << SecLogSize) > extentVDS.Len) + return S_FALSE; + + UInt64 offs = (UInt64)(extentVDS.Pos + location) << SecLogSize; + RINOK(_stream->Seek(offs, STREAM_SEEK_SET, NULL)); + HRESULT res = ReadStream_FALSE(_stream, buf, bufSize); + if (res == S_FALSE && offs + bufSize > FileSize) + UnexpectedEnd = true; + RINOK(res); + + CTag tag; RINOK(tag.Parse(buf + pos, bufSize - pos)); if (tag.Id == DESC_TYPE_Terminating) break; + if (tag.Id == DESC_TYPE_Partition) { + // Partition Descriptor + // ECMA 167 3/10.5 + // UDF / 2.2.14 + if (Partitions.Size() >= kNumPartitionsMax) return S_FALSE; CPartition partition; @@ -631,10 +718,15 @@ HRESULT CInArchive::Open2() // partition.ImplId.Parse(buf + 196); // memcpy(partition.ImplUse, buf + 228, sizeof(partition.ImplUse)); + PRF(printf("\nPartition number = %2d pos = %d len = %d", partition.Number, partition.Pos, partition.Len)); Partitions.Add(partition); } else if (tag.Id == DESC_TYPE_LogicalVol) { + /* Logical Volume Descriptor + ECMA 3/10.6 + UDF 2.60 2.2.4 */ + if (LogVols.Size() >= kNumLogVolumesMax) return S_FALSE; CLogVol vol; @@ -647,6 +739,8 @@ HRESULT CInArchive::Open2() // memcpy(vol.ContentsUse, buf + 248, sizeof(vol.ContentsUse)); vol.FileSetLocation.Parse(buf + 248); + /* the extent in which the first File Set Descriptor Sequence + of the logical volume is recorded */ // UInt32 mapTableLength = Get32(buf + 264); UInt32 numPartitionMaps = Get32(buf + 268); @@ -654,6 +748,8 @@ HRESULT CInArchive::Open2() return S_FALSE; // vol.ImplId.Parse(buf + 272); // memcpy(vol.ImplUse, buf + 128, sizeof(vol.ImplUse)); + + PRF(printf("\nLogicalVol numPartitionMaps = %2d", numPartitionMaps)); size_t pos = 440; for (UInt32 i = 0; i < numPartitionMaps; i++) { @@ -670,10 +766,33 @@ HRESULT CInArchive::Open2() // memcpy(pm.Data, buf + pos + 2, pm.Length - 2); if (pm.Type == 1) { - if (pos + 6 > bufSize) + if (len != 6) // < 6 return S_FALSE; // pm.VolSeqNumber = Get16(buf + pos + 2); pm.PartitionNumber = Get16(buf + pos + 4); + PRF(printf("\nPartitionMap type 1 PartitionNumber = %2d", pm.PartitionNumber)); + } + else if (pm.Type == 2) + { + if (len != 64) + return S_FALSE; + /* ECMA 10.7.3 / Type 2 Partition Map + 62 bytes: Partition Identifier. */ + + /* UDF 2.6 + 2.2.8 Virtual Partition Map + This is an extension of ECMA 167 to expand its scope to include + sequentially written media (eg. CD-R). This extension is for a + Partition Map entry to describe a virtual space. */ + + // It's not implemented still. + if (Get16(buf + pos + 2) != 0) + return S_FALSE; + // pm.VolSeqNumber = Get16(buf + pos + 36); + pm.PartitionNumber = Get16(buf + pos + 38); + PRF(printf("\nPartitionMap type 2 PartitionNumber = %2d", pm.PartitionNumber)); + // Unsupported = true; + return S_FALSE; } else return S_FALSE; @@ -686,21 +805,26 @@ HRESULT CInArchive::Open2() UInt64 totalSize = 0; - int volIndex; + unsigned volIndex; for (volIndex = 0; volIndex < LogVols.Size(); volIndex++) { CLogVol &vol = LogVols[volIndex]; - for (int pmIndex = 0; pmIndex < vol.PartitionMaps.Size(); pmIndex++) + FOR_VECTOR (pmIndex, vol.PartitionMaps) { CPartitionMap &pm = vol.PartitionMaps[pmIndex]; - int i; + unsigned i; for (i = 0; i < Partitions.Size(); i++) { CPartition &part = Partitions[i]; if (part.Number == pm.PartitionNumber) { if (part.VolIndex >= 0) - return S_FALSE; + { + // it's for 2.60. Fix it + if (part.VolIndex != (int)volIndex) + return S_FALSE; + // return S_FALSE; + } pm.PartitionIndex = i; part.VolIndex = volIndex; @@ -715,27 +839,39 @@ HRESULT CInArchive::Open2() RINOK(_progress->SetTotal(totalSize)); + PRF(printf("\n Read files")); + for (volIndex = 0; volIndex < LogVols.Size(); volIndex++) { CLogVol &vol = LogVols[volIndex]; + PRF(printf("\nLogVol %2d", 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()); + CByteBuffer buf(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_ExtendedFile) + { + // ECMA 4 / 14.17 + // 2.60 ?? + return S_FALSE; + } + if (tag.Id != DESC_TYPE_FileSet) return S_FALSE; + PRF(printf("\n FileSet", volIndex)); CFileSet fs; fs.RecodringTime.Parse(p + 16); // fs.InterchangeLevel = Get16(p + 18); @@ -757,16 +893,76 @@ HRESULT CInArchive::Open2() // nextExtent.Parse(p + 448); } - for (int fsIndex = 0; fsIndex < vol.FileSets.Size(); fsIndex++) + FOR_VECTOR (fsIndex, vol.FileSets) { 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)); + unsigned fileIndex = Files.Size(); + Files.AddNew(); + RINOK(ReadFileItem(volIndex, fsIndex, fs.RootDirICB, kNumRecursionLevelsMax)); + RINOK(FillRefs(fs, fileIndex, -1, kNumRecursionLevelsMax)); + } + } + + + for (volIndex = 0; volIndex < LogVols.Size(); volIndex++) + { + const CLogVol &vol = LogVols[volIndex]; + // bool showFileSetName = (vol.FileSets.Size() > 1); + FOR_VECTOR (fsIndex, vol.FileSets) + { + const CFileSet &fs = vol.FileSets[fsIndex]; + for (unsigned i = + // ((showVolName || showFileSetName) ? 0 : 1) + 0; i < fs.Refs.Size(); i++) + { + const CRef &ref = vol.FileSets[fsIndex].Refs[i]; + const CFile &file = Files[ref.FileIndex]; + const CItem &item = Items[file.ItemIndex]; + UInt64 size = item.Size; + + if (!item.IsRecAndAlloc() || !item.CheckChunkSizes() || !CheckItemExtents(volIndex, item)) + continue; + + FOR_VECTOR (extentIndex, item.Extents) + { + const CMyExtent &extent = item.Extents[extentIndex]; + UInt32 len = extent.GetLen(); + if (len == 0) + continue; + if (size < len) + break; + + int partitionIndex = vol.PartitionMaps[extent.PartitionRef].PartitionIndex; + UInt32 logBlockNumber = extent.Pos; + const CPartition &partition = Partitions[partitionIndex]; + UInt64 offset = ((UInt64)partition.Pos << SecLogSize) + + (UInt64)logBlockNumber * vol.BlockSize; + UpdatePhySize(offset + len); + } + } } } + { + UInt32 secMask = ((UInt32)1 << SecLogSize) - 1; + PhySize = (PhySize + secMask) & ~(UInt64)secMask; + } + if (PhySize < fileSize) + { + RINOK(_stream->Seek(PhySize, STREAM_SEEK_SET, NULL)); + size_t bufSize = 1 << SecLogSize; + size_t readSize = bufSize; + RINOK(ReadStream(_stream, buf, &readSize)); + if (readSize == bufSize) + { + CTag tag; + if (tag.Parse(buf, readSize) == S_OK) + if (tag.Id == DESC_TYPE_AnchorVolPtr) + { + PhySize += bufSize; + } + } + } return S_OK; } @@ -774,15 +970,38 @@ HRESULT CInArchive::Open(IInStream *inStream, CProgressVirt *progress) { _progress = progress; _stream = inStream; + HRESULT res = Open2(); + if (res == S_FALSE && IsArc && !UnexpectedEnd) + Unsupported = true; + return res; + + /* HRESULT res; - try { res = Open2(); } - catch(...) { Clear(); res = S_FALSE; } + try + { + res = Open2(); + } + catch(...) + { + // Clear(); + // res = S_FALSE; + _stream.Release(); + throw; + } _stream.Release(); return res; + */ } void CInArchive::Clear() { + IsArc = false; + Unsupported = false; + UnexpectedEnd = false; + + PhySize = 0; + FileSize = 0; + Partitions.Clear(); LogVols.Clear(); Items.Clear(); @@ -797,7 +1016,7 @@ void CInArchive::Clear() UString CInArchive::GetComment() const { UString res; - for (int i = 0; i < LogVols.Size(); i++) + FOR_VECTOR (i, LogVols) { if (i > 0) res += L" "; @@ -827,7 +1046,7 @@ static void UpdateWithName(UString &res, const UString &addString) if (res.IsEmpty()) res = addString; else - res = addString + WCHAR_PATH_SEPARATOR + res; + res.Insert(0, addString + WCHAR_PATH_SEPARATOR); } UString CInArchive::GetItemPath(int volIndex, int fsIndex, int refIndex, @@ -851,7 +1070,7 @@ UString CInArchive::GetItemPath(int volIndex, int fsIndex, int refIndex, if (showFsName) { wchar_t s[32]; - ConvertUInt64ToString(fsIndex, s); + ConvertUInt32ToString(fsIndex, s); UString newName = L"File Set "; newName += s; UpdateWithName(name, newName); @@ -860,7 +1079,7 @@ UString CInArchive::GetItemPath(int volIndex, int fsIndex, int refIndex, if (showVolName) { wchar_t s[32]; - ConvertUInt64ToString(volIndex, s); + ConvertUInt32ToString(volIndex, s); UString newName = s; UString newName2 = vol.GetName(); if (newName2.IsEmpty()) diff --git a/CPP/7zip/Archive/Udf/UdfIn.h b/CPP/7zip/Archive/Udf/UdfIn.h old mode 100755 new mode 100644 index 46b9a7e8..23693a71 --- a/CPP/7zip/Archive/Udf/UdfIn.h +++ b/CPP/7zip/Archive/Udf/UdfIn.h @@ -3,11 +3,11 @@ #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 "../../../Common/IntToString.h" +#include "../../../Common/MyBuffer.h" +#include "../../../Common/MyCom.h" +#include "../../../Common/MyMap.h" +#include "../../../Common/MyString.h" #include "../../IStream.h" @@ -22,6 +22,7 @@ namespace NUdf { struct CDString32 { Byte Data[32]; + void Parse(const Byte *buf); // UString GetString() const; }; @@ -30,13 +31,15 @@ struct CDString32 struct CDString128 { Byte Data[128]; - void Parse(const Byte *buf); + + void Parse(const Byte *buf) { memcpy(Data, buf, sizeof(Data)); } UString GetString() const; }; struct CDString { CByteBuffer Data; + void Parse(const Byte *p, unsigned size); UString GetString() const; }; @@ -52,12 +55,12 @@ struct CTime bool IsLocal() const { return GetType() == 1; } int GetMinutesOffset() const { - int t = (Data[0] | ((UInt16)Data[1] << 8)) & 0xFFF; + int t = (Data[0] | ((unsigned)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)); } + unsigned GetYear() const { return (Data[2] | ((unsigned)Data[3] << 8)); } void Parse(const Byte *buf); }; @@ -208,8 +211,9 @@ struct CFile // CByteBuffer ImplUse; CDString Id; - CFile(): /* FileVersion(0), FileCharacteristics(0), */ ItemIndex(-1) {} int ItemIndex; + + CFile(): /* FileVersion(0), FileCharacteristics(0), */ ItemIndex(-1) {} UString GetName() const { return Id.GetString(); } }; @@ -217,7 +221,7 @@ struct CMyExtent { UInt32 Pos; UInt32 Len; - int PartitionRef; + unsigned PartitionRef; UInt32 GetLen() const { return Len & 0x3FFFFFFF; } UInt32 GetType() const { return Len >> 30; } @@ -254,7 +258,7 @@ struct CItem bool IsRecAndAlloc() const { - for (int i = 0; i < Extents.Size(); i++) + FOR_VECTOR (i, Extents) if (!Extents[i].IsRecAndAlloc()) return false; return true; @@ -263,9 +267,9 @@ struct CItem UInt64 GetChunksSumSize() const { if (IsInline) - return InlineData.GetCapacity(); + return InlineData.Size(); UInt64 size = 0; - for (int i = 0; i < Extents.Size(); i++) + FOR_VECTOR (i, Extents) size += Extents[i].GetLen(); return size; } @@ -331,7 +335,7 @@ struct CProgressVirt class CInArchive { - CMyComPtr _stream; + IInStream *_stream; CProgressVirt *_progress; HRESULT Read(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len, Byte *buf); @@ -351,17 +355,29 @@ class CInArchive UInt32 _numExtents; UInt64 _inlineExtentsSize; bool CheckExtent(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len) const; -public: - HRESULT Open(IInStream *inStream, CProgressVirt *progress); - void Clear(); +public: CObjectVector Partitions; CObjectVector LogVols; CObjectVector Items; CObjectVector Files; - int SecLogSize; + unsigned SecLogSize; + UInt64 PhySize; + UInt64 FileSize; + + bool IsArc; + bool Unsupported; + bool UnexpectedEnd; + + void UpdatePhySize(UInt64 val) + { + if (PhySize < val) + PhySize = val; + } + HRESULT Open(IInStream *inStream, CProgressVirt *progress); + void Clear(); UString GetComment() const; UString GetItemPath(int volIndex, int fsIndex, int refIndex, @@ -370,6 +386,8 @@ public: bool CheckItemExtents(int volIndex, const CItem &item) const; }; +API_FUNC_IsArc IsArc_Udf(const Byte *p, size_t size); + }} #endif diff --git a/CPP/7zip/Archive/Udf/UdfRegister.cpp b/CPP/7zip/Archive/Udf/UdfRegister.cpp old mode 100755 new mode 100644 index 1b08d120..ed32f12e --- a/CPP/7zip/Archive/Udf/UdfRegister.cpp +++ b/CPP/7zip/Archive/Udf/UdfRegister.cpp @@ -5,9 +5,3 @@ #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/UefiHandler.cpp b/CPP/7zip/Archive/UefiHandler.cpp old mode 100755 new mode 100644 index 88739d8f..2aaf7d8f --- a/CPP/7zip/Archive/UefiHandler.cpp +++ b/CPP/7zip/Archive/UefiHandler.cpp @@ -4,8 +4,6 @@ // #define SHOW_DEBUG_INFO -// #include - #ifdef SHOW_DEBUG_INFO #include #endif @@ -15,13 +13,12 @@ #include "../../../C/CpuArch.h" #include "../../../C/LzmaDec.h" -#include "Common/Buffer.h" -#include "Common/ComTry.h" -#include "Common/IntToString.h" -#include "Common/StringConvert.h" +#include "../../Common/ComTry.h" +#include "../../Common/IntToString.h" +#include "../../Common/MyBuffer.h" +#include "../../Common/StringConvert.h" -#include "Windows/PropVariant.h" -#include "Windows/PropVariantUtils.h" +#include "../../Windows/PropVariantUtils.h" #include "../Common/ProgressUtils.h" #include "../Common/RegisterArc.h" @@ -30,8 +27,6 @@ #include "../Compress/CopyCoder.h" -#include "./Common/FindSignature.h" - #ifdef SHOW_DEBUG_INFO #define PRF(x) x #else @@ -43,8 +38,6 @@ #define Get64(p) GetUi64(p) #define Get24(p) (Get32(p) & 0xFFFFFF) -#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) - namespace NArchive { namespace NUefi { @@ -71,7 +64,7 @@ static const Byte k_FFS_Guid[kGuidSize] = FFS_SIGNATURE; static const Byte k_MacFS_Guid[kGuidSize] = { 0xAD,0xEE,0xAD,0x04,0xFF,0x61,0x31,0x4D,0xB6,0xBA,0x64,0xF8,0xBF,0x90,0x1F,0x5A }; -static const UInt32 kFvSignature = 0x4856465F; +static const UInt32 kFvSignature = 0x4856465F; // "_FVH" static const Byte kGuids[][kGuidSize] = { @@ -93,19 +86,19 @@ static const Byte kGuids[][kGuidSize] = static const char *kGuidNames[] = { - "CRC", - "VolumeTopFile", - "ACPI", - "ACPI2", - "Main", - "Intel32", - "Intel64", - "Intel32c", - "Intel64c", - "MacVolume", - "MacUpdate.txt", - "MacName", - "Insyde" + "CRC" + , "VolumeTopFile" + , "ACPI" + , "ACPI2" + , "Main" + , "Intel32" + , "Intel64" + , "Intel32c" + , "Intel64c" + , "MacVolume" + , "MacUpdate.txt" + , "MacName" + , "Insyde" }; enum @@ -237,18 +230,18 @@ enum static const char *g_FileTypes[] = { - "ALL", - "RAW", - "FREEFORM", - "SECURITY_CORE", - "PEI_CORE", - "DXE_CORE", - "PEIM", - "DRIVER", - "COMBINED_PEIM_DRIVER", - "APPLICATION", - "0xA", - "VOLUME" + "ALL" + , "RAW" + , "FREEFORM" + , "SECURITY_CORE" + , "PEI_CORE" + , "DXE_CORE" + , "PEIM" + , "DRIVER" + , "COMBINED_PEIM_DRIVER" + , "APPLICATION" + , "0xA" + , "VOLUME" }; // typedef Byte FFS_FILE_ATTRIBUTES; @@ -334,9 +327,9 @@ static const CUInt32PCharPair g_SECTION_TYPE[] = static const char *g_Methods[] = { - "COPY", - "LZH", - "LZMA" + "COPY" + , "LZH" + , "LZMA" }; static AString UInt32ToString(UInt32 val) @@ -446,7 +439,7 @@ class CFfsFileHeader Byte Attrib; Byte State; - UInt16 GetTailReference() const { return CheckHeader | ((UInt16)CheckFile << 8); } + UInt16 GetTailReference() const { return (UInt16)(CheckHeader | ((UInt16)CheckFile << 8)); } UInt32 GetTailSize() const { return IsThereTail() ? 2 : 0; } bool IsThereFileChecksum() const { return (Attrib & FFS_ATTRIB_CHECKSUM) != 0; } bool IsThereTail() const { return (Attrib & FFS_ATTRIB_TAIL_PRESENT) != 0; } @@ -474,6 +467,7 @@ public: } UInt32 GetDataSize() const { return Size - kFileHeaderSize - GetTailSize(); } + UInt32 GetDataSize2(UInt32 rem) const { return rem - kFileHeaderSize - GetTailSize(); } bool Check(const Byte *p, UInt32 size) { @@ -544,8 +538,7 @@ public: } }; -#define GET_32(offs, dest) dest = Get32(p + (offs)); -#define GET_64(offs, dest) dest = Get64(p + (offs)); +#define G32(_offs_, dest) dest = Get32(p + (_offs_)); struct CCapsuleHeader { @@ -567,18 +560,18 @@ struct CCapsuleHeader void Parse(const Byte *p) { - GET_32(0x10, HeaderSize); - GET_32(0x14, Flags); - GET_32(0x18, CapsuleImageSize); - GET_32(0x1C, SequenceNumber); - GET_32(0x30, OffsetToSplitInformation); - GET_32(0x34, OffsetToCapsuleBody); - GET_32(0x38, OffsetToOemDefinedHeader); - GET_32(0x3C, OffsetToAuthorInformation); - GET_32(0x40, OffsetToRevisionInformation); - GET_32(0x44, OffsetToShortDescription); - GET_32(0x48, OffsetToLongDescription); - GET_32(0x4C, OffsetToApplicableDevices); + G32(0x10, HeaderSize); + G32(0x14, Flags); + G32(0x18, CapsuleImageSize); + G32(0x1C, SequenceNumber); + G32(0x30, OffsetToSplitInformation); + G32(0x34, OffsetToCapsuleBody); + G32(0x38, OffsetToOemDefinedHeader); + G32(0x3C, OffsetToAuthorInformation); + G32(0x40, OffsetToRevisionInformation); + G32(0x44, OffsetToShortDescription); + G32(0x48, OffsetToLongDescription); + G32(0x4C, OffsetToApplicableDevices); } }; @@ -655,6 +648,7 @@ class CHandler: UInt32 _totalBufsSize; CCapsuleHeader _h; + UInt64 _phySize; void AddCommentString(const wchar_t *name, UInt32 pos); int AddItem(const CItem &item); @@ -663,7 +657,9 @@ class CHandler: int AddBuf(UInt32 size); HRESULT ParseSections(int bufIndex, UInt32 pos, UInt32 size, int parent, int method, int level); - HRESULT ParseVolume(int bufIndex, UInt32 posBase, UInt32 size, int parent, int method, int level); + HRESULT ParseVolume(int bufIndex, UInt32 posBase, + UInt32 exactSize, UInt32 limitSize, + int parent, int method, int level); HRESULT OpenCapsule(IInStream *stream); HRESULT OpenFv(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback); HRESULT Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback); @@ -674,21 +670,20 @@ public: STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); }; -static const STATPROPSTG kProps[] = +static const Byte kProps[] = { - { NULL, kpidPath, VT_BSTR}, - { NULL, kpidIsDir, VT_BOOL}, - { NULL, kpidSize, VT_UI8}, - { NULL, kpidMethod, VT_BSTR}, - { NULL, kpidCharacts, VT_BSTR} + kpidPath, + kpidIsDir, + kpidSize, + kpidMethod, + kpidCharacts }; -static const STATPROPSTG kArcProps[] = +static const Byte kArcProps[] = { - { NULL, kpidComment, VT_BSTR}, - { NULL, kpidMethod, VT_BSTR}, - { NULL, kpidPhySize, VT_UI8}, - { NULL, kpidCharacts, VT_BSTR} + kpidComment, + kpidMethod, + kpidCharacts }; IMP_IInArchive_Props @@ -733,7 +728,7 @@ void CHandler::AddCommentString(const wchar_t *name, UInt32 pos) return; for (UInt32 i = pos;; i += 2) { - if (s.Length() > (1 << 16) || i >= _h.OffsetToCapsuleBody) + if (s.Len() > (1 << 16) || i >= _h.OffsetToCapsuleBody) return; wchar_t c = Get16(buf + i); if (c == 0) @@ -773,7 +768,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) break; } case kpidComment: if (!_comment.IsEmpty()) prop = _comment; break; - case kpidPhySize: prop = (UInt64)_h.CapsuleImageSize; break; + case kpidPhySize: prop = (UInt64)_phySize; break; } prop.Detach(value); return S_OK; @@ -1037,7 +1032,7 @@ static HRESULT LzhDecode(Byte *dest, UInt32 destSize, const Byte *src, UInt32 sr { UInt32 c = extraHuff.DecodeSymbol(&bitDec); if (c > 2) - lens[i++] = (Byte)c - 2; + lens[i++] = (Byte)(c - 2); else { UInt32 numZeros; @@ -1163,8 +1158,8 @@ int CHandler::AddBuf(UInt32 size) if (size > kBufTotalSizeMax - _totalBufsSize) throw 1; _totalBufsSize += size; - int index = _bufs.Add(CByteBuffer()); - _bufs[index].SetCapacity(size); + int index = _bufs.Size(); + _bufs.AddNew().Alloc(size); return index; } @@ -1272,7 +1267,9 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p pStart, 5, LZMA_FINISH_END, &status, &g_Alloc); if (res != 0) return S_FALSE; - if (srcLen != srcLen2 || destLen != lzmaUncompressedSize || status != LZMA_STATUS_FINISHED_WITH_MARK) + if (srcLen != srcLen2 || destLen != lzmaUncompressedSize || ( + status != LZMA_STATUS_FINISHED_WITH_MARK && + status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)) return S_FALSE; RINOK(ParseSections(newBufIndex, 0, (UInt32)lzmaUncompressedSize, parent, compressionType, level)); } @@ -1323,7 +1320,10 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p { item.KeepName = false; int newParent = AddDirItem(item); - RINOK(ParseVolume(bufIndex, posBase + pos + 4, sectSize - 4, newParent, method, level)); + RINOK(ParseVolume(bufIndex, posBase + pos + 4, + sectSize - 4, + sectSize - 4, + newParent, method, level)); } else { @@ -1341,7 +1341,10 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p needAdd = false; item.Name = "vol"; int newParent = AddDirItem(item); - RINOK(ParseVolume(bufIndex, posBase + pos + 4 + kInsydeOffset, sectDataSize - kInsydeOffset, newParent, method, level)); + RINOK(ParseVolume(bufIndex, posBase + pos + 4 + kInsydeOffset, + sectDataSize - kInsydeOffset, + sectDataSize - kInsydeOffset, + newParent, method, level)); } if (needAdd) @@ -1359,19 +1362,20 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p AString s; if (ParseDepedencyExpression(p + 4, sectDataSize, s)) { - if (s.Length() < (1 << 9)) + if (s.Len() < (1 << 9)) { - s = '[' + s + ']'; + s.InsertAtFront('['); + s += ']'; AddSpaceAndString(_items[item.Parent].Characts, s); needAdd = false; } else { - item.BufIndex = AddBuf(s.Length()); + item.BufIndex = AddBuf(s.Len()); CByteBuffer &buf0 = _bufs[item.BufIndex]; - memcpy(buf0, s, s.Length()); + memcpy(buf0, s, s.Len()); item.Offset = 0; - item.Size = s.Length(); + item.Size = s.Len(); } } break; @@ -1383,7 +1387,11 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p AString s; if (ParseUtf16zString2(p + 6, sectDataSize - 2, s)) { - AddSpaceAndString(_items[item.Parent].Characts, (AString)"ver:" + UInt32ToString(Get16(p + 4)) + ' ' + s); + AString s2 = "ver:"; + s2 += UInt32ToString(Get16(p + 4)); + s2 += ' '; + s2 += s; + AddSpaceAndString(_items[item.Parent].Characts, s2); needAdd = false; } } @@ -1430,13 +1438,39 @@ static bool Is_FF_Stream(const Byte *p, UInt32 size) return (Count_FF_Bytes(p, size) == size); } -HRESULT CHandler::ParseVolume(int bufIndex, UInt32 posBase, UInt32 size, int parent, int method, int level) +struct CVolFfsHeader +{ + UInt32 HeaderLen; + UInt64 VolSize; + + bool Parse(const Byte *p); +}; + +bool CVolFfsHeader::Parse(const Byte *p) +{ + if (Get32(p + 0x28) != kFvSignature) + return false; + + UInt32 attribs = Get32(p + 0x2C); + if ((attribs & FVB_ERASE_POLARITY) == 0) + return false; + VolSize = Get64(p + 0x20); + HeaderLen = Get16(p + 0x30); + if (HeaderLen < kFvHeaderSize || (HeaderLen & 0x7) != 0 || VolSize < HeaderLen) + return false; + return true; +}; + +HRESULT CHandler::ParseVolume( + int bufIndex, UInt32 posBase, + UInt32 exactSize, UInt32 limitSize, + int parent, int method, int level) { if (level > kLevelMax) return S_FALSE; MyPrint(posBase, size, level, "Volume"); level++; - if (size < kFvHeaderSize) + if (exactSize < kFvHeaderSize) return S_FALSE; const Byte *p = _bufs[bufIndex] + posBase; // first 16 bytes must be zeros, but they are not zeros sometimes. @@ -1448,28 +1482,27 @@ HRESULT CHandler::ParseVolume(int bufIndex, UInt32 posBase, UInt32 size, int par item.BufIndex = bufIndex; item.Parent = parent; item.Offset = posBase; - item.Size = size; + item.Size = exactSize; item.SetGuid(p + kFfsGuidOffset); item.Name += " [VOLUME]"; AddItem(item); return S_OK; } - if (Get32(p + 0x28) != kFvSignature) - return S_FALSE; - UInt32 attribs = Get32(p + 0x2C); - if ((attribs & FVB_ERASE_POLARITY) == 0) + CVolFfsHeader ffsHeader; + if (!ffsHeader.Parse(p)) return S_FALSE; // if (parent >= 0) AddSpaceAndString(_items[parent].Characts, FLAGS_TO_STRING(g_FV_Attribs, attribs)); - UInt64 fvLen = Get64(p + 0x20); - UInt32 headerLen = Get16(p + 0x30); - if (headerLen > size || headerLen < kFvHeaderSize || (headerLen & 0x7) != 0 || - fvLen > size || fvLen < headerLen) + + // VolSize > exactSize (fh.Size) for some UEFI archives (is it correct UEFI?) + // so we check VolSize for limitSize instead. + + if (ffsHeader.HeaderLen > limitSize || ffsHeader.VolSize > limitSize) return S_FALSE; { UInt32 checkCalc = 0; - for (UInt32 i = 0; i < headerLen; i += 2) + for (UInt32 i = 0; i < ffsHeader.HeaderLen; i += 2) checkCalc += Get16(p + i); if ((checkCalc & 0xFFFF) != 0) return S_FALSE; @@ -1482,7 +1515,7 @@ HRESULT CHandler::ParseVolume(int bufIndex, UInt32 posBase, UInt32 size, int par UInt32 pos = kFvHeaderSize; for (;;) { - if (pos >= headerLen) + if (pos >= ffsHeader.HeaderLen) return S_FALSE; UInt32 numBlocks = Get32(p + pos); UInt32 length = Get32(p + pos + 4); @@ -1490,18 +1523,18 @@ HRESULT CHandler::ParseVolume(int bufIndex, UInt32 posBase, UInt32 size, int par if (numBlocks == 0 && length == 0) break; } - if (pos != headerLen) + if (pos != ffsHeader.HeaderLen) return S_FALSE; CRecordVector guidsVector; for (;;) { - UInt32 rem = (UInt32)fvLen - pos; + UInt32 rem = (UInt32)ffsHeader.VolSize - pos; if (rem < kFileHeaderSize) break; pos = (pos + 7) & ~7; - rem = (UInt32)fvLen - pos; + rem = (UInt32)ffsHeader.VolSize - pos; if (rem < kFileHeaderSize) break; @@ -1565,7 +1598,10 @@ HRESULT CHandler::ParseVolume(int bufIndex, UInt32 posBase, UInt32 size, int par if (isVolume) { int newParent = AddDirItem(item); - RINOK(ParseVolume(bufIndex, offset, sectSize, newParent, method, level)); + UInt32 limSize = fh.GetDataSize2(rem); + // volume.VolSize > fh.Size for some UEFI archives (is it correct UEFI?) + // so we will check VolSize for limitSize instead. + RINOK(ParseVolume(bufIndex, offset, sectSize, limSize, newParent, method, level)); } else AddItem(item); @@ -1590,6 +1626,7 @@ HRESULT CHandler::OpenCapsule(IInStream *stream) _h.OffsetToCapsuleBody < kHeaderSize || _h.OffsetToCapsuleBody > _h.CapsuleImageSize) return S_FALSE; + _phySize = _h.CapsuleImageSize; if (_h.SequenceNumber != 0 || _h.OffsetToSplitInformation != 0 ) @@ -1605,112 +1642,29 @@ HRESULT CHandler::OpenCapsule(IInStream *stream) AddCommentString(L"Short Description", _h.OffsetToShortDescription); AddCommentString(L"Long Description", _h.OffsetToLongDescription); - return ParseVolume(bufIndex, _h.OffsetToCapsuleBody, _h.CapsuleImageSize - _h.OffsetToCapsuleBody, -1, -1, 0); + return ParseVolume(bufIndex, _h.OffsetToCapsuleBody, + _h.CapsuleImageSize - _h.OffsetToCapsuleBody, + _h.CapsuleImageSize - _h.OffsetToCapsuleBody, + -1, -1, 0); } -HRESULT CHandler::OpenFv(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback) +HRESULT CHandler::OpenFv(IInStream *stream, const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback * /* callback */) { - UInt64 fileSize; - RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize)); - if (fileSize > (1 << 27)) + Byte buf[kFvHeaderSize]; + RINOK(ReadStream_FALSE(stream, buf, kFvHeaderSize)); + if (!IsFfs(buf)) return S_FALSE; - - UInt32 volIndex = 0; - UInt32 pos = 0, prevEnd = 0; - if (callback) - { - RINOK(callback->SetTotal(NULL, &fileSize)); - } - - for (;;) - { - UInt64 limit = 0; - UInt64 *limitPtr = NULL; - if (maxCheckStartPosition) - { - UInt32 directSize = pos - prevEnd; - if (directSize >= *maxCheckStartPosition) - break; - limit = *maxCheckStartPosition - directSize; - limitPtr = &limit; - } - - UInt64 resPos; - RINOK(stream->Seek(pos + kFfsGuidOffset, STREAM_SEEK_SET, NULL)); - if (FindSignatureInStream(stream, k_FFS_Guid, kGuidSize, limitPtr, resPos) == S_FALSE) - break; - - pos += (UInt32)resPos; - UInt64 fvSize; - { - UInt32 rem = (UInt32)fileSize - pos; - if (rem < kFvHeaderSize) - break; - RINOK(stream->Seek(pos, STREAM_SEEK_SET, NULL)); - Byte buf[kFvHeaderSize]; - RINOK(ReadStream_FALSE(stream, buf, kFvHeaderSize)); - fvSize = Get64(buf + 0x20); - if (!IsFfs(buf) || fvSize > rem) - { - pos++; - continue; - } - } - - RINOK(stream->Seek(prevEnd, STREAM_SEEK_SET, NULL)); - - if (pos != prevEnd) - { - CItem item; - item.Offset = 0; - item.Size = pos - prevEnd; - item.BufIndex = AddBuf(item.Size); - CByteBuffer &buf0 = _bufs[item.BufIndex]; - RINOK(ReadStream_FALSE(stream, buf0, item.Size)); - item.Name = UInt32ToString(volIndex++); - AddItem(item); - } - - prevEnd = pos; - RINOK(stream->Seek(pos, STREAM_SEEK_SET, NULL)); - UInt32 fvSize32 = (UInt32)fvSize; - CItem item; - item.BufIndex = AddBuf(fvSize32); - CByteBuffer &buf0 = _bufs[item.BufIndex]; - item.Name = UInt32ToString(volIndex++); - int parent = AddDirItem(item); - ReadStream_FALSE(stream, buf0, fvSize32); - RINOK(ParseVolume(item.BufIndex, 0, fvSize32, parent, -1, 0)); - pos += fvSize32; - prevEnd = pos; - - if (callback) - { - UInt64 pos64 = pos; - RINOK(callback->SetCompleted(NULL, &pos64)); - } - } - if (_items.Size() == 0) + CVolFfsHeader ffsHeader; + if (!ffsHeader.Parse(buf)) return S_FALSE; - - if (pos <= fileSize) - { - pos = (UInt32)fileSize; - if (prevEnd < pos) - { - CItem item; - item.Offset = 0; - item.Size = pos - prevEnd; - item.BufIndex = AddBuf(item.Size); - CByteBuffer &buf0 = _bufs[item.BufIndex]; - RINOK(stream->Seek(prevEnd, STREAM_SEEK_SET, NULL)); - RINOK(ReadStream_FALSE(stream, buf0, item.Size)); - item.Name = UInt32ToString(volIndex++); - AddItem(item); - } - } - _h.CapsuleImageSize = pos; - return S_OK; + if (ffsHeader.VolSize > ((UInt32)1 << 30)) + return S_FALSE; + _phySize = ffsHeader.VolSize; + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + UInt32 fvSize32 = (UInt32)ffsHeader.VolSize; + int bufIndex = AddBuf(fvSize32); + RINOK(ReadStream_FALSE(stream, _bufs[bufIndex], fvSize32)); + return ParseVolume(bufIndex, 0, fvSize32, fvSize32, -1, -1, 0); } HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback) @@ -1724,20 +1678,21 @@ HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, RINOK(OpenFv(stream, maxCheckStartPosition, callback)); } - CIntVector numChilds; - numChilds.Reserve(_items.Size()); - int i; - for (i = 0; i < _items.Size(); i++) + unsigned num = _items.Size(); + CIntArr numChilds(num); + unsigned i; + for (i = 0; i < num; i++) + numChilds[i] = 0; + for (i = 0; i < num; i++) { - numChilds.Add(0); int parent = _items[i].Parent; if (parent >= 0) numChilds[parent]++; } - for (i = 0; i < _items.Size(); i++) + for (i = 0; i < num; i++) { - CItem &item = _items[i]; + const CItem &item = _items[i]; int parent = item.Parent; if (parent >= 0) { @@ -1748,7 +1703,7 @@ HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, } } - CIntVector mainToReduced; + CUIntVector mainToReduced; for (i = 0; i < _items.Size(); i++) { mainToReduced.Add(_items2.Size()); @@ -1807,18 +1762,18 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, { COM_TRY_BEGIN Close(); - try { - if (Open2(inStream, maxCheckStartPosition, callback) != S_OK) - return S_FALSE; + HRESULT res = Open2(inStream, maxCheckStartPosition, callback); + if (res == E_NOTIMPL) + res = S_FALSE; + return res; } - catch(...) { return S_FALSE; } - return S_OK; COM_TRY_END } STDMETHODIMP CHandler::Close() { + _phySize = 0; _totalBufsSize = 0; _methodsMask = 0; _items.Clear(); @@ -1839,7 +1794,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _items2.Size(); if (numItems == 0) @@ -1916,20 +1871,32 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) } -namespace UEFIc -{ - static IInArchive *CreateArc() { return new CHandler(true); } - static CArcInfo g_ArcInfo = - { L"UEFIc", L"scap", 0, 0xD0, CAPSULE_SIGNATURE, kCapsuleSigSize, false, CreateArc, 0 }; - REGISTER_ARC(UEFIc) +namespace UEFIc { + +IMP_CreateArcIn_2(CHandler(true)) + +static CArcInfo g_ArcInfo = + { "UEFIc", "scap", 0, 0xD0, + kCapsuleSigSize, CAPSULE_SIGNATURE, + 0, + NArcInfoFlags::kFindSignature, + CreateArc }; + +REGISTER_ARC(UEFIc) } -namespace UEFIs -{ - static IInArchive *CreateArc() { return new CHandler(false); } - static CArcInfo g_ArcInfo = - { L"UEFIs", L"", 0, 0xD1, FFS_SIGNATURE, kGuidSize, false, CreateArc, 0 }; - REGISTER_ARC(UEFIs) +namespace UEFIf { + +IMP_CreateArcIn_2(CHandler(false)) + +static CArcInfo g_ArcInfo = + { "UEFIf", "uefif", 0, 0xD1, + kGuidSize, FFS_SIGNATURE, + kFfsGuidOffset, + NArcInfoFlags::kFindSignature, + CreateArc }; + +REGISTER_ARC(UEFIf) } }} diff --git a/CPP/7zip/Archive/VhdHandler.cpp b/CPP/7zip/Archive/VhdHandler.cpp old mode 100755 new mode 100644 index 9d1c928e..5268bd0b --- a/CPP/7zip/Archive/VhdHandler.cpp +++ b/CPP/7zip/Archive/VhdHandler.cpp @@ -4,12 +4,12 @@ #include "../../../C/CpuArch.h" -#include "Common/Buffer.h" -#include "Common/ComTry.h" -#include "Common/IntToString.h" -#include "Common/MyString.h" +#include "../../Common/ComTry.h" +#include "../../Common/IntToString.h" +#include "../../Common/MyBuffer.h" +#include "../../Common/MyString.h" -#include "Windows/PropVariant.h" +#include "../../Windows/PropVariant.h" #include "../Common/LimitedStreams.h" #include "../Common/ProgressUtils.h" @@ -22,14 +22,19 @@ #define Get32(p) GetBe32(p) #define Get64(p) GetBe64(p) -#define G32(p, dest) dest = Get32(p); -#define G64(p, dest) dest = Get64(p); +#define G32(_offs_, dest) dest = Get32(p + (_offs_)); +#define G64(_offs_, dest) dest = Get64(p + (_offs_)); using namespace NWindows; namespace NArchive { namespace NVhd { +#define SIGNATURE { 'c', 'o', 'n', 'e', 'c', 't', 'i', 'x', 0, 0 } + +static const unsigned kSignatureSize = 10; +static const Byte kSignature[kSignatureSize] = SIGNATURE; + static const UInt32 kUnusedBlock = 0xFFFFFFFF; static const UInt32 kDiskType_Fixed = 2; @@ -38,11 +43,11 @@ static const UInt32 kDiskType_Diff = 4; static const char *kDiskTypes[] = { - "0", - "1", - "Fixed", - "Dynamic", - "Differencing" + "0" + , "1" + , "Fixed" + , "Dynamic" + , "Differencing" }; struct CFooter @@ -73,7 +78,7 @@ struct CFooter AString CFooter::GetTypeString() const { - if (Type < sizeof(kDiskTypes) / sizeof(kDiskTypes[0])) + if (Type < ARRAY_SIZE(kDiskTypes)) return kDiskTypes[Type]; char s[16]; ConvertUInt32ToString(Type, s); @@ -96,27 +101,35 @@ static bool CheckBlock(const Byte *p, unsigned size, unsigned checkSumOffset, un return true; } +static const unsigned kSectorSize_Log = 9; +static const unsigned kSectorSize = 1 << kSectorSize_Log; +static const unsigned kHeaderSize = 512; + bool CFooter::Parse(const Byte *p) { - if (memcmp(p, "conectix", 8) != 0) + if (memcmp(p, kSignature, kSignatureSize) != 0) + return false; + // G32(0x08, Features); + // G32(0x0C, FormatVersion); + G64(0x10, DataOffset); + G32(0x18, CTime); + G32(0x1C, CreatorApp); + G32(0x20, CreatorVersion); + G32(0x24, CreatorHostOS); + // G64(0x28, OriginalSize); + G64(0x30, CurrentSize); + G32(0x38, DiskGeometry); + G32(0x3C, Type); + if (Type < kDiskType_Fixed || + Type > kDiskType_Diff) 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); + // if (DataOffset > ((UInt64)1 << 62)) return false; + // if (CurrentSize > ((UInt64)1 << 62)) return false; + return CheckBlock(p, kHeaderSize, 0x40, 0x55); } -/* struct CParentLocatorEntry { UInt32 Code; @@ -124,17 +137,15 @@ struct CParentLocatorEntry UInt32 DataLen; UInt64 DataOffset; - bool Parse(const Byte *p); + bool Parse(const Byte *p) + { + G32(0x00, Code); + G32(0x04, DataSpace); + G32(0x08, DataLen); + G64(0x10, DataOffset); + return Get32(p + 0x0C) == 0; // Reserved + } }; -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 { @@ -142,56 +153,63 @@ struct CDynHeader UInt64 TableOffset; // UInt32 HeaderVersion; UInt32 NumBlocks; - int BlockSizeLog; + unsigned BlockSizeLog; UInt32 ParentTime; Byte ParentId[16]; + bool RelativeNameWasUsed; UString ParentName; - // CParentLocatorEntry ParentLocators[8]; + UString RelativeParentNameFromLocator; + CParentLocatorEntry ParentLocators[8]; bool Parse(const Byte *p); UInt32 NumBitMapSectors() const { - UInt32 numSectorsInBlock = (1 << (BlockSizeLog - 9)); - return (numSectorsInBlock + 512 * 8 - 1) / (512 * 8); + UInt32 numSectorsInBlock = (1 << (BlockSizeLog - kSectorSize_Log)); + return (numSectorsInBlock + kSectorSize * 8 - 1) / (kSectorSize * 8); + } + void Clear() + { + RelativeNameWasUsed = false; + ParentName.Empty(); + RelativeParentNameFromLocator.Empty(); } }; -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); + // G64(0x08, DataOffset); + G64(0x10, TableOffset); + // G32(0x18, HeaderVersion); + G32(0x1C, NumBlocks); + { + UInt32 blockSize = Get32(p + 0x20); + unsigned i; + for (i = kSectorSize_Log;; i++) + { + if (i > 31) + return false; + if (((UInt32)1 << i) == blockSize) + break; + } + BlockSizeLog = i; + } + G32(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++) + const unsigned kNameLen = 256; + wchar_t *s = ParentName.GetBuffer(kNameLen); + for (unsigned i = 0; i < kNameLen; i++) s[i] = Get16(p + 0x40 + i * 2); - s[kNameLength] = 0; + s[kNameLen] = 0; ParentName.ReleaseBuffer(); } - /* - for (int i = 0; i < 8; i++) + for (unsigned i = 0; i < 8; i++) if (!ParentLocators[i].Parse(p + 0x240 + i * 24)) return false; - */ return CheckBlock(p, 1024, 0x24, 0x240 + 8 * 24); } @@ -202,8 +220,10 @@ class CHandler: public CMyUnknownImp { UInt64 _virtPos; - UInt64 _phyPos; - UInt64 _phyLimit; + UInt64 _posInArc; + UInt64 _posInArcLimit; + UInt64 _startOffset; + UInt64 _phySize; CFooter Footer; CDynHeader Dyn; @@ -214,7 +234,22 @@ class CHandler: CMyComPtr Stream; CMyComPtr ParentStream; CHandler *Parent; + UString _errorMessage; + // bool _unexpectedEnd; + void AddErrorMessage(const wchar_t *s) + { + if (!_errorMessage.IsEmpty()) + _errorMessage += L'\n'; + _errorMessage += s; + } + void UpdatePhySize(UInt64 value) + { + if (_phySize < value) + _phySize = value; + } + + void Reset_PosInArc() { _posInArc = (UInt64)0 - 1; } HRESULT Seek(UInt64 offset); HRESULT InitAndSeek(); HRESULT ReadPhy(UInt64 offset, void *data, UInt32 size); @@ -223,7 +258,7 @@ class CHandler: UInt64 GetPackSize() const { return Footer.ThereIsDynamic() ? ((UInt64)NumUsedBlocks << Dyn.BlockSizeLog) : Footer.CurrentSize; } - UString GetParentName() const + UString GetParentSequence() const { const CHandler *p = this; UString res; @@ -231,26 +266,45 @@ class CHandler: { if (!res.IsEmpty()) res += L" -> "; - res += p->Dyn.ParentName; + UString mainName; + UString anotherName; + if (Dyn.RelativeNameWasUsed) + { + mainName = p->Dyn.RelativeParentNameFromLocator; + anotherName = p->Dyn.ParentName; + } + else + { + mainName = p->Dyn.ParentName; + anotherName = p->Dyn.RelativeParentNameFromLocator; + } + res += mainName; + if (mainName != anotherName && !anotherName.IsEmpty()) + { + res += L' '; + res += L'('; + res += anotherName; + res += L')'; + } p = p->Parent; } return res; } - bool IsOK() const + bool AreParentsOK() const { const CHandler *p = this; while (p->NeedParent()) { p = p->Parent; - if (p == 0) + if (!p) return false; } return true; } HRESULT Open3(); - HRESULT Open2(IInStream *stream, CHandler *child, IArchiveOpenCallback *openArchiveCallback, int level); + HRESULT Open2(IInStream *stream, CHandler *child, IArchiveOpenCallback *openArchiveCallback, unsigned level); public: MY_UNKNOWN_IMP3(IInArchive, IInArchiveGetStream, IInStream) @@ -261,7 +315,7 @@ public: STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; -HRESULT CHandler::Seek(UInt64 offset) { return Stream->Seek(offset, STREAM_SEEK_SET, NULL); } +HRESULT CHandler::Seek(UInt64 offset) { return Stream->Seek(_startOffset + offset, STREAM_SEEK_SET, NULL); } HRESULT CHandler::InitAndSeek() { @@ -269,50 +323,122 @@ HRESULT CHandler::InitAndSeek() { RINOK(Parent->InitAndSeek()); } - _virtPos = _phyPos = 0; + _virtPos = _posInArc = 0; BitMapTag = kUnusedBlock; - BitMap.SetCapacity(Dyn.NumBitMapSectors() << 9); + BitMap.Alloc(Dyn.NumBitMapSectors() << kSectorSize_Log); return Seek(0); } HRESULT CHandler::ReadPhy(UInt64 offset, void *data, UInt32 size) { - if (offset + size > _phyLimit) + if (offset + size > _posInArcLimit) return S_FALSE; - if (offset != _phyPos) + if (offset != _posInArc) { - _phyPos = offset; + _posInArc = offset; RINOK(Seek(offset)); } HRESULT res = ReadStream_FALSE(Stream, data, size); - _phyPos += size; + if (res == S_OK) + _posInArc += size; + else + Reset_PosInArc(); return res; } HRESULT CHandler::Open3() { - RINOK(Stream->Seek(0, STREAM_SEEK_END, &_phyPos)); - if (_phyPos < 512) + // Fixed archive uses only footer + + UInt64 startPos; + RINOK(Stream->Seek(0, STREAM_SEEK_CUR, &startPos)); + _startOffset = startPos; + Byte header[kHeaderSize]; + RINOK(ReadStream_FALSE(Stream, header, kHeaderSize)); + bool headerIsOK = Footer.Parse(header); + + if (headerIsOK && !Footer.ThereIsDynamic()) + { + // fixed archive + if (startPos < Footer.CurrentSize) + return S_FALSE; + _posInArcLimit = Footer.CurrentSize; + _phySize = Footer.CurrentSize + kHeaderSize; + _startOffset = startPos - Footer.CurrentSize; + _posInArc = _phySize; + return S_OK; + } + + UInt64 fileSize; + RINOK(Stream->Seek(0, STREAM_SEEK_END, &fileSize)); + if (fileSize < kHeaderSize) 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; + RINOK(Stream->Seek(fileSize - kHeaderSize, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream_FALSE(Stream, buf, kHeaderSize)); - if (!Footer.ThereIsDynamic()) + if (!headerIsOK) + { + if (!Footer.Parse(buf)) + return S_FALSE; + if (Footer.ThereIsDynamic()) + return S_FALSE; // we can't open Dynamic Archive backward. + _posInArcLimit = Footer.CurrentSize; + _phySize = Footer.CurrentSize + kHeaderSize; + _startOffset = fileSize - kHeaderSize - Footer.CurrentSize; + _posInArc = _phySize; return S_OK; + } - RINOK(ReadPhy(0, buf + 512, 512)); - if (memcmp(buf, buf + 512, 512) != 0) - return S_FALSE; + _phySize = kHeaderSize; + _posInArc = fileSize - startPos; + _posInArcLimit = _posInArc - kHeaderSize; + + bool headerAndFooterAreEqual = false; + if (memcmp(header, buf, kHeaderSize) == 0) + { + headerAndFooterAreEqual = true; + _phySize = fileSize - _startOffset; + } RINOK(ReadPhy(Footer.DataOffset, buf, kDynSize)); if (!Dyn.Parse(buf)) return S_FALSE; + + UpdatePhySize(Footer.DataOffset + kDynSize); + + for (int i = 0; i < 8; i++) + { + const CParentLocatorEntry &locator = Dyn.ParentLocators[i]; + const UInt32 kNameBufSizeMax = 1024; + if (locator.DataLen < kNameBufSizeMax && + locator.DataOffset < _posInArcLimit && + locator.DataOffset + locator.DataLen <= _posInArcLimit) + { + if (locator.Code == 0x57327275 && (locator.DataLen & 1) == 0) + { + // "W2ru" locator + // Path is encoded as little-endian UTF-16 + Byte nameBuf[kNameBufSizeMax]; + UString tempString; + unsigned len = (locator.DataLen >> 1); + wchar_t *s = tempString.GetBuffer(len); + RINOK(ReadPhy(locator.DataOffset, nameBuf, locator.DataLen)); + for (unsigned j = 0; j < len; j++) + s[j] = GetUi16(nameBuf + j * 2); + s[len] = 0; + tempString.ReleaseBuffer(); + if (tempString[0] == L'.' && tempString[1] == L'\\') + tempString.DeleteFrontal(2); + Dyn.RelativeParentNameFromLocator = tempString; + } + } + if (locator.DataLen != 0) + UpdatePhySize(locator.DataOffset + locator.DataLen); + } if (Dyn.NumBlocks >= (UInt32)1 << 31) return S_FALSE; @@ -324,20 +450,69 @@ HRESULT CHandler::Open3() else if (((Footer.CurrentSize - 1) >> Dyn.BlockSizeLog) + 1 != Dyn.NumBlocks) return S_FALSE; - Bat.Reserve(Dyn.NumBlocks); + Bat.ClearAndReserve(Dyn.NumBlocks); + + UInt32 bitmapSize = Dyn.NumBitMapSectors() << kSectorSize_Log; + while ((UInt32)Bat.Size() < Dyn.NumBlocks) { - RINOK(ReadPhy(Dyn.TableOffset + (UInt64)Bat.Size() * 4, buf, 512)); - for (UInt32 j = 0; j < 512; j += 4) + RINOK(ReadPhy(Dyn.TableOffset + (UInt64)Bat.Size() * 4, buf, kSectorSize)); + UpdatePhySize(Dyn.TableOffset + kSectorSize); + for (UInt32 j = 0; j < kSectorSize; j += 4) { UInt32 v = Get32(buf + j); if (v != kUnusedBlock) + { + UInt32 blockSize = (UInt32)1 << Dyn.BlockSizeLog; + UpdatePhySize(((UInt64)v << kSectorSize_Log) + bitmapSize + blockSize); NumUsedBlocks++; - Bat.Add(v); + } + Bat.AddInReserved(v); if ((UInt32)Bat.Size() >= Dyn.NumBlocks) break; } } + + if (headerAndFooterAreEqual) + return S_OK; + + if (_startOffset + _phySize + kHeaderSize > fileSize) + { + // _unexpectedEnd = true; + _posInArcLimit = _phySize; + _phySize += kHeaderSize; + return S_OK; + } + + RINOK(ReadPhy(_phySize, buf, kHeaderSize)); + if (memcmp(header, buf, kHeaderSize) == 0) + { + _posInArcLimit = _phySize; + _phySize += kHeaderSize; + return S_OK; + } + + if (_phySize == 0x800) + { + /* WHY does empty archive contain additional empty sector? + We skip that sector and check footer again. */ + unsigned i; + for (i = 0; i < kSectorSize && buf[i] == 0; i++); + if (i == kSectorSize) + { + RINOK(ReadPhy(_phySize + kSectorSize, buf, kHeaderSize)); + if (memcmp(header, buf, kHeaderSize) == 0) + { + _phySize += kSectorSize; + _posInArcLimit = _phySize; + _phySize += kHeaderSize; + return S_OK; + } + } + } + _posInArcLimit = _phySize; + _phySize += kHeaderSize; + AddErrorMessage(L"Can't find footer"); return S_OK; } @@ -371,17 +546,17 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) } else { - UInt64 newPos = (UInt64)blockSectIndex << 9; + UInt64 newPos = (UInt64)blockSectIndex << kSectorSize_Log; if (BitMapTag != blockIndex) { - RINOK(ReadPhy(newPos, BitMap, (UInt32)BitMap.GetCapacity())); + RINOK(ReadPhy(newPos, BitMap, (UInt32)BitMap.Size())); BitMapTag = blockIndex; } - RINOK(ReadPhy(newPos + BitMap.GetCapacity() + offsetInBlock, data, size)); + RINOK(ReadPhy(newPos + BitMap.Size() + offsetInBlock, data, size)); for (UInt32 cur = 0; cur < size;) { UInt32 rem = MyMin(0x200 - (offsetInBlock & 0x1FF), size - cur); - UInt32 bmi = offsetInBlock >> 9; + UInt32 bmi = offsetInBlock >> kSectorSize_Log; if (((BitMap[bmi >> 3] >> (7 - (bmi & 7))) & 1) == 0) { if (ParentStream) @@ -409,15 +584,18 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) STDMETHODIMP CHandler::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - switch(seekOrigin) + 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; + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: offset += Footer.CurrentSize; break; default: return STG_E_INVALIDFUNCTION; } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = offset; if (newPosition) - *newPosition = _virtPos; + *newPosition = offset; return S_OK; } @@ -427,9 +605,10 @@ enum kpidSavedState }; -STATPROPSTG kArcProps[] = +static const STATPROPSTG kArcProps[] = { { NULL, kpidSize, VT_UI8}, + { NULL, kpidOffset, VT_UI8}, { NULL, kpidCTime, VT_FILETIME}, { NULL, kpidClusterSize, VT_UI8}, { NULL, kpidMethod, VT_BSTR}, @@ -440,16 +619,16 @@ STATPROPSTG kArcProps[] = { NULL, kpidId, VT_BSTR} }; -STATPROPSTG kProps[] = +static const Byte kProps[] = { - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, - { NULL, kpidCTime, VT_FILETIME} + kpidSize, + kpidPackSize, + kpidCTime /* - { NULL, kpidNumCyls, VT_UI4}, - { NULL, kpidNumHeads, VT_UI4}, - { NULL, kpidSectorsPerTrack, VT_UI4} + { kpidNumCyls, VT_UI4}, + { kpidNumHeads, VT_UI4}, + { kpidSectorsPerTrack, VT_UI4} */ }; @@ -470,11 +649,11 @@ static void VhdTimeToFileTime(UInt32 vhdTime, NCOM::CPropVariant &prop) prop = utc; } -static void StringToAString(char *dest, UInt32 s) +static void StringToAString(char *dest, UInt32 val) { for (int i = 24; i >= 0; i -= 8) { - Byte b = (Byte)((s >> i) & 0xFF); + Byte b = (Byte)((val >> i) & 0xFF); if (b < 0x20 || b > 0x7F) break; *dest++ = b; @@ -496,11 +675,12 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; - switch(propID) + 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 kpidShortComment: case kpidMethod: { AString s = Footer.GetTypeString(); @@ -535,7 +715,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) } case kpidHostOS: { - if (Footer.CreatorHostOS == 0x5769326b) + if (Footer.CreatorHostOS == 0x5769326B) prop = "Windows"; else { @@ -555,18 +735,32 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) break; } case kpidSavedState: prop = Footer.SavedState ? true : false; break; - case kpidParent: if (NeedParent()) prop = GetParentName(); break; + case kpidParent: if (NeedParent()) prop = GetParentSequence(); break; + case kpidOffset: prop = _startOffset; break; + case kpidPhySize: prop = _phySize; break; + /* + case kpidErrorFlags: + { + UInt32 flags = 0; + if (_unexpectedEnd) + flags |= kpv_ErrorFlags_UnexpectedEndOfArc; + if (flags != 0) + prop = flags; + break; + } + */ + case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break; } prop.Detach(value); return S_OK; COM_TRY_END } -HRESULT CHandler::Open2(IInStream *stream, CHandler *child, IArchiveOpenCallback *openArchiveCallback, int level) +HRESULT CHandler::Open2(IInStream *stream, CHandler *child, IArchiveOpenCallback *openArchiveCallback, unsigned level) { Close(); Stream = stream; - if (level > 32) + if (level > (1 << 12)) // Maybe we need to increase that limit return S_FALSE; RINOK(Open3()); if (child && memcmp(child->Dyn.ParentId, Footer.Id, 16) != 0) @@ -575,16 +769,65 @@ HRESULT CHandler::Open2(IInStream *stream, CHandler *child, IArchiveOpenCallback return S_OK; CMyComPtr openVolumeCallback; if (openArchiveCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback) != S_OK) - return S_FALSE; + { + // 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); + bool useRelative; + UString name; + if (!Dyn.RelativeParentNameFromLocator.IsEmpty()) + { + useRelative = true; + name = Dyn.RelativeParentNameFromLocator; + } + else + { + useRelative = false; + name = Dyn.ParentName; + } + Dyn.RelativeNameWasUsed = useRelative; + + if (openVolumeCallback) + { + HRESULT res = openVolumeCallback->GetStream(name, &nextStream); + if (res == S_FALSE) + { + if (useRelative && Dyn.ParentName != Dyn.RelativeParentNameFromLocator) + { + res = openVolumeCallback->GetStream(Dyn.ParentName, &nextStream); + if (res == S_OK) + Dyn.RelativeNameWasUsed = false; + } + if (res == S_FALSE) + return S_OK; + } + RINOK(res); + + Parent = new CHandler; + ParentStream = Parent; + + res = Parent->Open2(nextStream, this, openArchiveCallback, level + 1); + if (res == S_FALSE) + { + Parent = NULL; + ParentStream.Release(); + } + } + { + const CHandler *p = this; + while (p->NeedParent()) + { + p = p->Parent; + if (p == 0) + { + AddErrorMessage(L"Can't open parent VHD file:"); + AddErrorMessage(Dyn.ParentName); + break; + } + } + } + return S_OK; } STDMETHODIMP CHandler::Open(IInStream *stream, @@ -613,11 +856,15 @@ STDMETHODIMP CHandler::Open(IInStream *stream, STDMETHODIMP CHandler::Close() { + _phySize = 0; Bat.Clear(); NumUsedBlocks = 0; Parent = 0; Stream.Release(); ParentStream.Release(); + Dyn.Clear(); + _errorMessage.Empty(); + // _unexpectedEnd = false; return S_OK; } @@ -629,8 +876,8 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) { - COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; + // COM_TRY_BEGIN + NCOM::CPropVariant prop; switch(propID) { @@ -645,7 +892,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN } prop.Detach(value); return S_OK; - COM_TRY_END + // COM_TRY_END } STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, @@ -654,7 +901,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_BEGIN if (numItems == 0) return S_OK; - if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0)) + if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) return E_INVALIDARG; RINOK(extractCallback->SetTotal(Footer.CurrentSize)); @@ -678,7 +925,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CMyComPtr inStream; HRESULT hres = GetStream(0, &inStream); if (hres == S_FALSE) - res = NExtract::NOperationResult::kUnSupportedMethod; + res = NExtract::NOperationResult::kUnsupportedMethod; else { RINOK(hres); @@ -715,7 +962,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **strea *stream = streamTemp.Detach(); return S_OK; } - if (!Footer.ThereIsDynamic() || !IsOK()) + if (!Footer.ThereIsDynamic() || !AreParentsOK()) return S_FALSE; CMyComPtr streamTemp = this; RINOK(InitAndSeek()); @@ -724,10 +971,14 @@ STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **strea COM_TRY_END } -static IInArchive *CreateArc() { return new CHandler; } +IMP_CreateArcIn 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 }; + { "VHD", "vhd", ".mbr", 0xDC, + kSignatureSize, SIGNATURE, + 0, + NArcInfoFlags::kUseGlobalOffset, + CreateArc }; REGISTER_ARC(Vhd) diff --git a/CPP/7zip/Archive/Wim/StdAfx.h b/CPP/7zip/Archive/Wim/StdAfx.h old mode 100755 new mode 100644 index e7fb6986..2854ff3e --- a/CPP/7zip/Archive/Wim/StdAfx.h +++ b/CPP/7zip/Archive/Wim/StdAfx.h @@ -3,6 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" +#include "../../../Common/Common.h" #endif diff --git a/CPP/7zip/Archive/Wim/WimHandler.cpp b/CPP/7zip/Archive/Wim/WimHandler.cpp old mode 100755 new mode 100644 index eaad1e7c..6f0b10e2 --- a/CPP/7zip/Archive/Wim/WimHandler.cpp +++ b/CPP/7zip/Archive/Wim/WimHandler.cpp @@ -4,13 +4,10 @@ #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/ComTry.h" +#include "../../../Common/IntToString.h" +#include "../../Common/MethodProps.h" #include "../../Common/ProgressUtils.h" #include "../../Common/StreamUtils.h" @@ -25,29 +22,36 @@ using namespace NWindows; namespace NArchive { namespace NWim { -#define WIM_DETAILS +// #define WIM_DETAILS -static STATPROPSTG kProps[] = +static const Byte 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} + kpidPath, + kpidIsDir, + kpidSize, + kpidPackSize, + kpidMTime, + kpidCTime, + kpidATime, + kpidAttrib, + kpidMethod, + kpidShortName, + kpidINode, + kpidLinks #ifdef WIM_DETAILS - , { NULL, kpidVolume, VT_UI4} - , { NULL, kpidOffset, VT_UI8} - , { NULL, kpidLinks, VT_UI4} + , kpidVolume + , kpidOffset #endif }; -static STATPROPSTG kArcProps[] = +enum +{ + kpidNumImages = kpidUserDefined, + kpidBootImage +}; + +static const STATPROPSTG kArcProps[] = { { NULL, kpidSize, VT_UI8}, { NULL, kpidPackSize, VT_UI8}, @@ -58,133 +62,60 @@ static STATPROPSTG kArcProps[] = { NULL, kpidUnpackVer, VT_BSTR}, { NULL, kpidIsVolume, VT_BOOL}, { NULL, kpidVolume, VT_UI4}, - { NULL, kpidNumVolumes, VT_UI4} + { NULL, kpidNumVolumes, VT_UI4}, + { L"Images", kpidNumImages, VT_UI4}, + { L"Boot Image", kpidBootImage, 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; -} +static const char *kMethodLZX = "LZX"; +static const char *kMethodXpress = "XPress"; +static const char *kMethodCopy = "Copy"; -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); -} +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_WITH_NAME -void CXml::ToUnicode(UString &s) +static void AddErrorMessage(AString &s, const char *message) { - 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(); + if (!s.IsEmpty()) + s += ". "; + s += message; } -void CXml::Parse() +static void ConvertByteToHex(unsigned value, char *s) { - 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++) + for (int i = 0; i < 2; i++) { - const CXmlItem &item = xml.Root.SubItems[i]; - if (item.IsTagged("IMAGE")) - { - CImageInfo imageInfo; - imageInfo.Parse(item); - Images.Add(imageInfo); - } + unsigned t = value & 0xF; + value >>= 4; + s[1 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); } } -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; + NCOM::CPropVariant prop; const CImageInfo *image = NULL; if (_xmls.Size() == 1) { - const CXml &xml = _xmls[0]; + const CWimXml &xml = _xmls[0]; if (xml.Images.Size() == 1) image = &xml.Images[0]; } - switch(propID) + switch (propID) { + case kpidPhySize: prop = _phySize; break; case kpidSize: prop = _db.GetUnpackSize(); break; case kpidPackSize: prop = _db.GetPackSize(); break; case kpidCTime: if (_xmls.Size() == 1) { - const CXml &xml = _xmls[0]; + const CWimXml &xml = _xmls[0]; int index = -1; - for (int i = 0; i < xml.Images.Size(); i++) + FOR_VECTOR (i, xml.Images) { const CImageInfo &image = xml.Images[i]; if (image.CTimeDefined) @@ -199,9 +130,9 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidMTime: if (_xmls.Size() == 1) { - const CXml &xml = _xmls[0]; + const CWimXml &xml = _xmls[0]; int index = -1; - for (int i = 0; i < xml.Images.Size(); i++) + FOR_VECTOR (i, xml.Images) { const CImageInfo &image = xml.Images[i]; if (image.MTimeDefined) @@ -266,10 +197,63 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) } break; case kpidNumVolumes: if (_volumes.Size() > 0) prop = (UInt32)(_volumes.Size() - 1); break; + + case kpidName: + if (_firstVolumeIndex >= 0) + { + const CHeader &h = _volumes[_firstVolumeIndex].Header; + if (GetUi32(h.Guid) != 0) + { + char temp[16 * 2 + 4]; + int i; + for (i = 0; i < 4; i++) + ConvertByteToHex(h.Guid[i], temp + i * 2); + temp[i * 2] = 0; + AString s = temp; + const char *ext = ".wim"; + if (h.NumParts != 1) + { + s += '_'; + if (h.PartNumber != 1) + { + char sz[16]; + ConvertUInt32ToString(h.PartNumber, sz); + s += sz; + } + ext = ".swm"; + } + s += ext; + prop = s; + } + } + break; + + case kpidExtension: + if (_firstVolumeIndex >= 0) + { + const CHeader &h = _volumes[_firstVolumeIndex].Header; + if (h.NumParts > 1) + { + AString s; + if (h.PartNumber != 1) + { + char sz[16]; + ConvertUInt32ToString(h.PartNumber, sz); + s = sz; + s += '.'; + } + s += "swm"; + prop = s; + } + } + break; + + case kpidNumImages: prop = (UInt32)_db.Images.Size(); break; + case kpidBootImage: if (_bootIndex != 0) prop = (UInt32)_bootIndex; break; case kpidMethod: { bool lzx = false, xpress = false, copy = false; - for (int i = 0; i < _xmls.Size(); i++) + FOR_VECTOR (i, _xmls) { const CHeader &header = _volumes[_xmls[i].VolIndex].Header; if (header.IsCompressed()) @@ -296,6 +280,34 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) res += kMethodCopy; } prop = res; + break; + } + case kpidIsTree: prop = true; break; + case kpidIsAltStream: prop = _db.ThereAreAltStreams; break; + case kpidIsAux: prop = true; break; + // WIM uses special prefix to represent deleted items + // case kpidIsDeleted: prop = _db.ThereAreDeletedStreams; break; + case kpidINode: prop = true; break; + + case kpidErrorFlags: + { + UInt32 flags = 0; + if (!_isArc) flags |= kpv_ErrorFlags_IsNotArc; + // if (HeadersError) flags |= kpv_ErrorFlags_HeadersError; + // if (UnexpectedEnd) flags |= kpv_ErrorFlags_UnexpectedEndOfArc; + prop = flags; + break; + } + + case kpidWarning: + { + AString s; + if (_xmlError) + AddErrorMessage(s, "XML error"); + if (_db.RefCountError) + AddErrorMessage(s, "Some files have incorrect reference count"); + if (!s.IsEmpty()) + prop = s; } } prop.Detach(value); @@ -303,104 +315,404 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) COM_TRY_END } +void GetFileTime(const Byte *p, NCOM::CPropVariant &prop) +{ + prop.vt = VT_FILETIME; + prop.filetime.dwLowDateTime = Get32(p); + prop.filetime.dwHighDateTime = Get32(p + 4); +} + +#define FILES_DIR_NAME "[Files]" + STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; - if (index < (UInt32)_db.SortedItems.Size()) + NCOM::CPropVariant prop; + + if (index < _db.SortedItems.Size()) { - int realIndex = _db.SortedItems[index]; + unsigned 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]; + si = &_db.DataStreams[item.StreamIndex]; vol = &_volumes[si->PartNumber]; } - switch(propID) + const CItem *mainItem = &item; + if (item.IsAltStream) + mainItem = &_db.Items[item.Parent]; + const Byte *metadata = NULL; + if (mainItem->ImageIndex >= 0) + metadata = _db.Images[mainItem->ImageIndex].Meta + mainItem->Offset; + + switch (propID) { case kpidPath: - if (item.HasMetadata) - prop = _db.GetItemPath(realIndex); + if (item.ImageIndex >= 0) + _db.GetItemPath(realIndex, _showImageNumber, prop); else { char sz[16]; ConvertUInt32ToString(item.StreamIndex, sz); AString s = sz; - while (s.Length() < _nameLenForStreams) + /* + while (s.Len() < _nameLenForStreams) s = '0' + s; + */ /* if (si->Resource.IsFree()) - prefix = "[Free]"; + s = (AString)("[Free]" STRING_PATH_SEPARATOR) + sz; + else */ - s = "[Files]" STRING_PATH_SEPARATOR + s; + s = (AString)(FILES_DIR_NAME STRING_PATH_SEPARATOR) + sz; 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 kpidName: + if (item.ImageIndex >= 0) + _db.GetItemName(realIndex, prop); + else + { + char sz[16]; + ConvertUInt32ToString(item.StreamIndex, sz); + /* + AString s = sz; + while (s.Len() < _nameLenForStreams) + s = '0' + s; + */ + prop = sz; + } + break; + + case kpidShortName: + if (item.ImageIndex >= 0 && !item.IsAltStream) + _db.GetShortName(realIndex, prop); + break; + + case kpidPackSize: prop = (UInt64)(si ? si->Resource.PackSize : 0); break; + case kpidSize: prop = (UInt64)(si ? si->Resource.UnpackSize : 0); break; + case kpidIsDir: prop = item.IsDir; break; + case kpidIsAltStream: prop = item.IsAltStream; break; + case kpidAttrib: + if (!item.IsAltStream && mainItem->ImageIndex >= 0) + { + /* + if (fileNameLen == 0 && isDir && !item.HasStream()) + item.Attrib = 0x10; // some swm archives have system/hidden attributes for root + */ + prop = (UInt32)Get32(metadata + 8); + } + break; + case kpidCTime: if (mainItem->HasMetadata()) GetFileTime(metadata + (_db.IsOldVersion ? 0x18: 0x28), prop); break; + case kpidATime: if (mainItem->HasMetadata()) GetFileTime(metadata + (_db.IsOldVersion ? 0x20: 0x30), prop); break; + case kpidMTime: if (mainItem->HasMetadata()) GetFileTime(metadata + (_db.IsOldVersion ? 0x28: 0x38), prop); break; + + case kpidINode: + if (mainItem->HasMetadata() && !_isOldVersion) + { + UInt32 attrib = (UInt32)Get32(metadata + 8); + if ((attrib & FILE_ATTRIBUTE_REPARSE_POINT) == 0) + { + // we don't know about that field in OLD WIM format + unsigned offset = 0x58; // (_db.IsOldVersion ? 0x30: 0x58); + UInt64 val = Get64(metadata + offset); + if (val != 0) + prop = val; + } + } + break; + + case kpidStreamId: + if (item.StreamIndex >= 0) + prop = (UInt32)item.StreamIndex; + break; + case kpidMethod: if (si) prop = si->Resource.IsCompressed() ? (vol->Header.IsLzxMode() ? kMethodLZX : kMethodXpress) : kMethodCopy; break; + case kpidLinks: if (si) prop = (UInt32)si->RefCount; 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(); + if (index < _numXmlItems) { - switch(propID) + switch (propID) { case kpidPath: - { - char sz[16]; - ConvertUInt32ToString(_xmls[index].VolIndex, sz); - prop = (AString)"[" + (AString)sz + "].xml"; - break; - } + case kpidName: prop = _xmls[index].FileName; break; case kpidIsDir: prop = false; break; case kpidPackSize: - case kpidSize: prop = (UInt64)_xmls[index].Data.GetCapacity(); break; + case kpidSize: prop = (UInt64)_xmls[index].Data.Size(); break; case kpidMethod: prop = kMethodCopy; break; } } + else + { + index -= _numXmlItems; + switch (propID) + { + case kpidPath: + case kpidName: + if (index < (UInt32)_db.VirtualRoots.Size()) + prop = _db.Images[_db.VirtualRoots[index]].RootName; + else + prop = FILES_DIR_NAME; + break; + case kpidIsDir: prop = true; break; + case kpidIsAux: prop = true; break; + } + } } prop.Detach(value); return S_OK; COM_TRY_END } +STDMETHODIMP CHandler::GetRootProp(PROPID propID, PROPVARIANT *value) +{ + // COM_TRY_BEGIN + NCOM::CPropVariant prop; + if (_db.Images.Size() != 0 && _db.NumExludededItems != 0) + { + const CImage &image = _db.Images[_db.IndexOfUserImage]; + const CItem &item = _db.Items[image.StartItem]; + if (!item.IsDir || item.ImageIndex != _db.IndexOfUserImage) + return E_FAIL; + const Byte *metadata = image.Meta + item.Offset; + + switch (propID) + { + case kpidIsDir: prop = true; break; + case kpidAttrib: prop = (UInt32)Get32(metadata + 8); break; + case kpidCTime: GetFileTime(metadata + (_db.IsOldVersion ? 0x18: 0x28), prop); break; + case kpidATime: GetFileTime(metadata + (_db.IsOldVersion ? 0x20: 0x30), prop); break; + case kpidMTime: GetFileTime(metadata + (_db.IsOldVersion ? 0x28: 0x38), prop); break; + } + } + prop.Detach(value); + return S_OK; + // COM_TRY_END +} + +HRESULT CHandler::GetSecurity(UInt32 realIndex, const void **data, UInt32 *dataSize, UInt32 *propType) +{ + const CItem &item = _db.Items[realIndex]; + if (item.IsAltStream || item.ImageIndex < 0) + return S_OK; + const CImage &image = _db.Images[item.ImageIndex]; + const Byte *metadata = image.Meta + item.Offset; + UInt32 securityId = Get32(metadata + 0xC); + if (securityId == (UInt32)(Int32)-1) + return S_OK; + if (securityId >= (UInt32)image.SecurOffsets.Size()) + return E_FAIL; + UInt32 offs = image.SecurOffsets[securityId]; + UInt32 len = image.SecurOffsets[securityId + 1] - offs; + const CByteBuffer &buf = image.Meta; + if (offs <= buf.Size() && buf.Size() - offs >= len) + { + *data = buf + offs; + *dataSize = len; + *propType = NPropDataType::kRaw; + } + return S_OK; +} + +STDMETHODIMP CHandler::GetRootRawProp(PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) +{ + *data = 0; + *dataSize = 0; + *propType = 0; + if (propID == kpidNtSecure && _db.Images.Size() != 0 && _db.NumExludededItems != 0) + { + const CImage &image = _db.Images[_db.IndexOfUserImage]; + const CItem &item = _db.Items[image.StartItem]; + if (!item.IsDir || item.ImageIndex != _db.IndexOfUserImage) + return E_FAIL; + return GetSecurity(image.StartItem, data, dataSize, propType); + } + return S_OK; +} + +static const Byte kRawProps[] = +{ + kpidSha1, + kpidNtReparse, + kpidNtSecure +}; + + +STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps) +{ + *numProps = ARRAY_SIZE(kRawProps); + return S_OK; +} + +STDMETHODIMP CHandler::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID) +{ + *propID = kRawProps[index]; + *name = 0; + return S_OK; +} + +STDMETHODIMP CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType) +{ + *parentType = NParentType::kDir; + *parent = (UInt32)(Int32)-1; + if (index >= _db.SortedItems.Size()) + return S_OK; + + const CItem &item = _db.Items[_db.SortedItems[index]]; + + if (item.ImageIndex >= 0) + { + *parentType = item.IsAltStream ? NParentType::kAltStream : NParentType::kDir; + if (item.Parent >= 0) + { + if (_db.ExludedItem != item.Parent) + *parent = _db.Items[item.Parent].IndexInSorted; + } + else + { + CImage &image = _db.Images[item.ImageIndex]; + if (image.VirtualRootIndex >= 0) + *parent = _db.SortedItems.Size() + _numXmlItems + image.VirtualRootIndex; + } + } + else + *parent = _db.SortedItems.Size() + _numXmlItems + _db.VirtualRoots.Size(); + return S_OK; +} + +static bool IsEmptySha(const Byte *data) +{ + for (int i = 0; i < kHashSize; i++) + if (data[i] != 0) + return false; + return true; +} + +STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) +{ + *data = NULL; + *dataSize = 0; + *propType = 0; + + if (propID == kpidName) + { + if (index < _db.SortedItems.Size()) + { + const CItem &item = _db.Items[_db.SortedItems[index]]; + if (item.ImageIndex < 0) + return S_OK; + const CImage &image = _db.Images[item.ImageIndex]; + *propType = NPropDataType::kUtf16z; + if (image.NumEmptyRootItems != 0 && item.Parent < 0) + { + const CByteBuffer &buf = _db.Images[item.ImageIndex].RootNameBuf; + *data = (void *)(const Byte *)buf; + *dataSize = (UInt32)buf.Size(); + return S_OK; + } + const Byte *meta = image.Meta + item.Offset + + (item.IsAltStream ? + (_isOldVersion ? 0x10 : 0x24) : + (_isOldVersion ? kDirRecordSizeOld - 2 : kDirRecordSize - 2)); + *data = (const void *)(meta + 2); + *dataSize = (UInt32)Get16(meta) + 2; + return S_OK; + } + { + index -= _db.SortedItems.Size(); + if (index < _numXmlItems) + return S_OK; + index -= _numXmlItems; + if (index >= (UInt32)_db.VirtualRoots.Size()) + return S_OK; + const CByteBuffer &buf = _db.Images[_db.VirtualRoots[index]].RootNameBuf; + *data = (void *)(const Byte *)buf; + *dataSize = (UInt32)buf.Size(); + *propType = NPropDataType::kUtf16z; + return S_OK; + } + } + + if (index >= _db.SortedItems.Size()) + return S_OK; + + unsigned index2 = _db.SortedItems[index]; + + if (propID == kpidNtSecure) + { + return GetSecurity(index2, data, dataSize, propType); + } + + const CItem &item = _db.Items[index2]; + if (propID == kpidSha1) + { + if (item.StreamIndex >= 0) + *data = _db.DataStreams[item.StreamIndex].Hash; + else + { + if (_isOldVersion) + return S_OK; + const Byte *sha1 = _db.Images[item.ImageIndex].Meta + item.Offset + (item.IsAltStream ? 0x10 : 0x40); + if (IsEmptySha(sha1)) + return S_OK; + *data = sha1; + } + *dataSize = kHashSize; + *propType = NPropDataType::kRaw; + return S_OK; + } + + if (propID == kpidNtReparse && !_isOldVersion) + { + // we don't know about Reparse field in OLD WIM format + + if (item.StreamIndex < 0) + return S_OK; + if (index2 >= _db.ItemToReparse.Size()) + return S_OK; + int reparseIndex = _db.ItemToReparse[index2]; + if (reparseIndex < 0) + return S_OK; + const CByteBuffer &buf = _db.ReparseItems[reparseIndex]; + if (buf.Size() == 0) + return S_OK; + *data = buf; + *dataSize = (UInt32)buf.Size(); + *propType = NPropDataType::kRaw; + return S_OK; + } + + return S_OK; +} + 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(); + dotPos = name.Len(); _before = name.Left(dotPos); - _after = name.Mid(dotPos); + _after = name.Ptr(dotPos); } - UString GetNextName(UInt32 index) + UString GetNextName(UInt32 index) const { wchar_t s[16]; ConvertUInt32ToString(index, s); @@ -408,25 +720,26 @@ public: } }; -STDMETHODIMP CHandler::Open(IInStream *inStream, - const UInt64 * /* maxCheckStartPosition */, - IArchiveOpenCallback *openArchiveCallback) +STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback) { COM_TRY_BEGIN + Close(); { CMyComPtr openVolumeCallback; CVolumeName seqName; - if (openArchiveCallback != NULL) - openArchiveCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback); + if (callback) + callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback); UInt32 numVolumes = 1; - int firstVolumeIndex = -1; + for (UInt32 i = 1; i <= numVolumes; i++) { CMyComPtr curStream; - if (i != 1) + if (i == 1) + curStream = inStream; + else { UString fullName = seqName.GetNextName(i); HRESULT result = openVolumeCallback->GetStream(fullName, &curStream); @@ -437,52 +750,59 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, if (!curStream) break; } - else - curStream = inStream; CHeader header; - HRESULT res = NWim::ReadHeader(curStream, header); + HRESULT res = NWim::ReadHeader(curStream, header, _phySize); if (res != S_OK) { - if (i == 1) - return res; - if (res == S_FALSE) + if (i != 1 && res == S_FALSE) continue; return res; } + _isArc = true; + _bootIndex = header.BootIndex; _version = header.Version; _isOldVersion = header.IsOldVersion(); - if (firstVolumeIndex >= 0) - if (!header.AreFromOnArchive(_volumes[firstVolumeIndex].Header)) + if (_firstVolumeIndex >= 0) + if (!header.AreFromOnArchive(_volumes[_firstVolumeIndex].Header)) break; if (_volumes.Size() > header.PartNumber && _volumes[header.PartNumber].Stream) break; - CXml xml; + CWimXml xml; xml.VolIndex = header.PartNumber; - res = _db.Open(curStream, header, xml.Data, openArchiveCallback); + res = _db.OpenXml(curStream, header, xml.Data); + if (res == S_OK) + { + if (!xml.Parse()) + _xmlError = true; + + UInt64 totalFiles = xml.GetTotalFilesAndDirs() + xml.Images.Size(); + totalFiles += 16 + xml.Images.Size() * 4; // we reserve some additional items + if (totalFiles >= ((UInt32)1 << 30)) + totalFiles = 0; + res = _db.Open(curStream, header, (unsigned)totalFiles, callback); + } if (res != S_OK) { - if (i == 1) - return res; - if (res == S_FALSE) + if (i != 1 && res == S_FALSE) continue; return res; } while (_volumes.Size() <= header.PartNumber) - _volumes.Add(CVolume()); + _volumes.AddNew(); CVolume &volume = _volumes[header.PartNumber]; volume.Header = header; volume.Stream = curStream; - firstVolumeIndex = header.PartNumber; + _firstVolumeIndex = header.PartNumber; - bool needAddXml = true; - if (_xmls.Size() != 0) - if (xml.Data == _xmls[0].Data) - needAddXml = false; - if (needAddXml) + if (_xmls.IsEmpty() || xml.Data != _xmls[0].Data) { - xml.Parse(); + wchar_t sz[16]; + ConvertUInt32ToString(xml.VolIndex, sz); + xml.FileName = L'['; + xml.FileName += sz; + xml.FileName += L"].xml"; _xmls.Add(xml); } @@ -503,14 +823,30 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, } } - _db.DetectPathMode(); - RINOK(_db.Sort(_db.SkipRoot)); + RINOK(_db.FillAndCheck()); + int defaultImageIndex = (int)_defaultImageNumber - 1; + + bool showImageNumber = (_db.Images.Size() != 1 && defaultImageIndex < 0); + if (!showImageNumber && _set_use_ShowImageNumber) + showImageNumber = _set_showImageNumber; + if (!showImageNumber && _keepMode_ShowImageNumber) + showImageNumber = true; + + _showImageNumber = showImageNumber; + + RINOK(_db.GenerateSortedItems(defaultImageIndex, showImageNumber)); + RINOK(_db.ExtractReparseStreams(_volumes, callback)); + + /* wchar_t sz[16]; - ConvertUInt32ToString(_db.Streams.Size(), sz); + ConvertUInt32ToString(_db.DataStreams.Size(), sz); _nameLenForStreams = MyStringLen(sz); + */ - _xmlInComments = (_xmls.Size() == 1 && !_db.ShowImageNumber); + _xmlInComments = !_showImageNumber; + _numXmlItems = (_xmlInComments ? 0 : _xmls.Size()); + _numIgnoreItems = _db.ThereAreDeletedStreams ? 1 : 0; } return S_OK; COM_TRY_END @@ -518,10 +854,17 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, STDMETHODIMP CHandler::Close() { + _firstVolumeIndex = -1; + _phySize = 0; _db.Clear(); _volumes.Clear(); _xmls.Clear(); - _nameLenForStreams = 0; + // _nameLenForStreams = 0; + _xmlInComments = false; + _numXmlItems = 0; + _numIgnoreItems = 0; + _xmlError = false; + _isArc = false; return S_OK; } @@ -529,10 +872,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) - numItems = _db.SortedItems.Size() + _xmls.Size(); + numItems = _db.SortedItems.Size() + _numXmlItems + _db.VirtualRoots.Size() + _numIgnoreItems; if (numItems == 0) return S_OK; @@ -541,17 +884,21 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, for (i = 0; i < numItems; i++) { UInt32 index = allFilesMode ? i : indices[i]; - if (index < (UInt32)_db.SortedItems.Size()) + if (index < _db.SortedItems.Size()) { int streamIndex = _db.Items[_db.SortedItems[index]].StreamIndex; if (streamIndex >= 0) { - const CStreamInfo &si = _db.Streams[streamIndex]; + const CStreamInfo &si = _db.DataStreams[streamIndex]; totalSize += si.Resource.UnpackSize; } } else - totalSize += _xmls[index - (UInt32)_db.SortedItems.Size()].Data.GetCapacity(); + { + index -= _db.SortedItems.Size(); + if (index < (UInt32)_numXmlItems) + totalSize += _xmls[index].Data.Size(); + } } RINOK(extractCallback->SetTotal(totalSize)); @@ -586,17 +933,21 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CMyComPtr realOutStream; RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); - if (index >= (UInt32)_db.SortedItems.Size()) + if (index >= _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) + index -= _db.SortedItems.Size(); + if (index < (UInt32)_numXmlItems) { - RINOK(WriteStream(realOutStream, (const Byte *)data, data.GetCapacity())); - realOutStream.Release(); + const CByteBuffer &data = _xmls[index].Data; + currentItemUnPacked = data.Size(); + if (realOutStream) + { + RINOK(WriteStream(realOutStream, (const Byte *)data, data.Size())); + realOutStream.Release(); + } } RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); continue; @@ -610,13 +961,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, continue; RINOK(extractCallback->PrepareOperation(askMode)); realOutStream.Release(); - RINOK(extractCallback->SetOperationResult(item.HasStream() ? - NExtract::NOperationResult::kDataError : - NExtract::NOperationResult::kOK)); + RINOK(extractCallback->SetOperationResult(_db.ItemHasStream(item) ? + NExtract::NOperationResult::kDataError : + NExtract::NOperationResult::kOK)); continue; } - const CStreamInfo &si = _db.Streams[streamIndex]; + const CStreamInfo &si = _db.DataStreams[streamIndex]; currentItemUnPacked = si.Resource.UnpackSize; currentItemPacked = si.Resource.PackSize; @@ -626,7 +977,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 opRes = NExtract::NOperationResult::kOK; if (streamIndex != prevSuccessStreamIndex || realOutStream) { - Byte digest[20]; + Byte digest[kHashSize]; const CVolume &vol = _volumes[si.PartNumber]; HRESULT res = unpacker.Unpack(vol.Stream, si.Resource, vol.Header.IsLzxMode(), realOutStream, progress, digest); @@ -651,9 +1002,59 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { - *numItems = _db.SortedItems.Size(); - if (!_xmlInComments) - *numItems += _xmls.Size(); + *numItems = _db.SortedItems.Size() + + _numXmlItems + + _db.VirtualRoots.Size() + + _numIgnoreItems; + return S_OK; +} + +CHandler::CHandler() +{ + _keepMode_ShowImageNumber = false; + InitDefaults(); + _xmlError = false; +} + +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) +{ + InitDefaults(); + + for (UInt32 i = 0; i < numProps; i++) + { + UString name = names[i]; + name.MakeLower_Ascii(); + if (name.IsEmpty()) + return E_INVALIDARG; + + const PROPVARIANT &prop = values[i]; + + if (name[0] == L'x') + { + // some clients write 'x' property. So we support it + UInt32 level = 0; + RINOK(ParsePropToUInt32(name.Ptr(1), prop, level)); + } + else if (name.IsEqualTo("is")) + { + RINOK(PROPVARIANT_to_bool(prop, _set_showImageNumber)); + _set_use_ShowImageNumber = true; + } + else if (name.IsEqualTo("im")) + { + UInt32 image = 9; + RINOK(ParsePropToUInt32(L"", prop, image)); + _defaultImageNumber = image; + } + else + return E_INVALIDARG; + } + return S_OK; +} + +STDMETHODIMP CHandler::KeepModeForNextOpen() +{ + _keepMode_ShowImageNumber = _showImageNumber; return S_OK; } diff --git a/CPP/7zip/Archive/Wim/WimHandler.h b/CPP/7zip/Archive/Wim/WimHandler.h old mode 100755 new mode 100644 index aa92069a..416e11ca --- a/CPP/7zip/Archive/Wim/WimHandler.h +++ b/CPP/7zip/Archive/Wim/WimHandler.h @@ -3,72 +3,75 @@ #ifndef __ARCHIVE_WIM_HANDLER_H #define __ARCHIVE_WIM_HANDLER_H -#include "Common/MyCom.h" -#include "Common/MyXml.h" +#include "../../../Common/MyCom.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 IArchiveGetRawProps, + public IArchiveGetRootProps, + public IArchiveKeepModeForNextOpen, + public ISetProperties, + public IOutArchive, public CMyUnknownImp { CDatabase _db; UInt32 _version; bool _isOldVersion; + UInt32 _bootIndex; + CObjectVector _volumes; - CObjectVector _xmls; - int _nameLenForStreams; + CObjectVector _xmls; + // unsigned _nameLenForStreams; bool _xmlInComments; + + unsigned _numXmlItems; + unsigned _numIgnoreItems; -public: - MY_UNKNOWN_IMP1(IInArchive) - INTERFACE_IInArchive(;) -}; + bool _xmlError; + bool _isArc; -class COutHandler: - public IOutArchive, - public CMyUnknownImp -{ + bool _set_use_ShowImageNumber; + bool _set_showImageNumber; + int _defaultImageNumber; + + bool _showImageNumber; + + bool _keepMode_ShowImageNumber; + + UInt64 _phySize; + int _firstVolumeIndex; + + void InitDefaults() + { + _set_use_ShowImageNumber = false; + _set_showImageNumber = false; + _defaultImageNumber = -1; + } + + bool ThereIsError() const { return _xmlError || _db.ThereIsError(); } + HRESULT GetSecurity(UInt32 realIndex, const void **data, UInt32 *dataSize, UInt32 *propType); + + HRESULT GetOutProperty(IArchiveUpdateCallback *callback, UInt32 callbackIndex, Int32 arcIndex, PROPID propID, PROPVARIANT *value); + HRESULT GetTime(IArchiveUpdateCallback *callback, UInt32 callbackIndex, Int32 arcIndex, PROPID propID, FILETIME &ft); public: - MY_UNKNOWN_IMP1(IOutArchive) + CHandler(); + MY_UNKNOWN_IMP6( + IInArchive, + IArchiveGetRawProps, + IArchiveGetRootProps, + IArchiveKeepModeForNextOpen, + ISetProperties, + IOutArchive) + INTERFACE_IInArchive(;) + INTERFACE_IArchiveGetRawProps(;) + INTERFACE_IArchiveGetRootProps(;) + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); + STDMETHOD(KeepModeForNextOpen)(); INTERFACE_IOutArchive(;) }; diff --git a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp old mode 100755 new mode 100644 index 85f0771c..149989d1 --- a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp +++ b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp @@ -2,17 +2,23 @@ #include "StdAfx.h" +// #include + #include "../../../../C/CpuArch.h" -#include "Common/ComTry.h" -#include "Common/IntToString.h" +#include "../../../Common/ComTry.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringToInt.h" +#include "../../../Common/UTFConvert.h" +#include "../../../Common/Wildcard.h" -#include "Windows/PropVariant.h" -#include "Windows/Time.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/TimeUtils.h" #include "../../Common/LimitedStreams.h" #include "../../Common/ProgressUtils.h" #include "../../Common/StreamUtils.h" +#include "../../Common/UniqBlocks.h" #include "../../Crypto/RandGen.h" #include "../../Crypto/Sha1.h" @@ -24,125 +30,218 @@ using namespace NWindows; namespace NArchive { namespace NWim { +static const Int32 kNumImagesMax = (1 << 10); + struct CSha1Hash { Byte Hash[kHashSize]; }; -struct CHashList +class CHashList { + CUIntVector Sorted; +public: CRecordVector Digests; - CIntVector Sorted; - int AddUnique(const CSha1Hash &h); + int AddUniq(const Byte *h); }; -int CHashList::AddUnique(const CSha1Hash &h) +// returns -1 : if it's new HASH + +int CHashList::AddUniq(const Byte *h) { - int left = 0, right = Sorted.Size(); + unsigned left = 0, right = Sorted.Size(); while (left != right) { - int mid = (left + right) / 2; - int index = Sorted[mid]; - UInt32 i; + unsigned mid = (left + right) / 2; + unsigned index = Sorted[mid]; const Byte *hash2 = Digests[index].Hash; + unsigned i; for (i = 0; i < kHashSize; i++) - if (h.Hash[i] != hash2[i]) + if (h[i] != hash2[i]) break; if (i == kHashSize) return index; - if (h.Hash[i] < hash2[i]) + if (h[i] < hash2[i]) right = mid; else left = mid + 1; } - Sorted.Insert(left, Digests.Add(h)); + CSha1Hash h2; + memcpy(h2.Hash, h, kHashSize); + Sorted.Insert(left, Digests.Add(h2)); return -1; } -struct CUpdateItem +struct CAltStream { + int UpdateIndex; + int HashIndex; + UInt64 Size; UString Name; + bool Skip; + + CAltStream(): UpdateIndex(-1), HashIndex(-1), Skip(false) {} +}; + +struct CMetaItem +{ + int UpdateIndex; + int HashIndex; + UInt64 Size; FILETIME CTime; FILETIME ATime; FILETIME MTime; UInt32 Attrib; + UInt64 FileID; + UInt64 VolID; + + UString Name; + UString ShortName; + + int SecurityId; // -1: means no secutity ID bool IsDir; - int HashIndex; + bool Skip; + unsigned NumSkipAltStreams; + CObjectVector AltStreams; + + CByteBuffer Reparse; + + unsigned GetNumAltStreams() const { return AltStreams.Size() - NumSkipAltStreams; } + CMetaItem(): UpdateIndex(-1), HashIndex(-1), SecurityId(-1), + FileID(0), VolID(0), + Skip(false), NumSkipAltStreams(0) {} +}; + +static int Compare_HardLink_MetaItems(const CMetaItem &a1, const CMetaItem &a2) +{ + if (a1.VolID < a2.VolID) return -1; + if (a1.VolID > a2.VolID) return 1; + if (a1.FileID < a2.FileID) return -1; + if (a1.FileID > a2.FileID) return 1; + if (a1.Size < a2.Size) return -1; + if (a1.Size > a2.Size) return 1; + return ::CompareFileTime(&a1.MTime, &a2.MTime); +} + +static int AddToHardLinkList(const CObjectVector &metaItems, unsigned indexOfItem, CUIntVector &indexes) +{ + const CMetaItem &mi = metaItems[indexOfItem]; + unsigned left = 0, right = indexes.Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + unsigned index = indexes[mid]; + int comp = Compare_HardLink_MetaItems(mi, metaItems[index]); + if (comp == 0) + return index; + if (comp < 0) + right = mid; + else + left = mid + 1; + } + indexes.Insert(left, indexOfItem); + return -1; +} - CUpdateItem(): HashIndex(-1) {} +struct CUpdateItem +{ + unsigned CallbackIndex; // index in callback + + int MetaIndex; // index in in MetaItems[] + + int AltStreamIndex; // index in CMetaItem::AltStreams vector + // -1: if not alt stream? + + int InArcIndex; // >= 0, if we use OLD Data + // -1, if we use NEW Data + + CUpdateItem(): MetaIndex(-1), AltStreamIndex(-1), InArcIndex(-1) {} }; struct CDir { - int Index; - UString Name; + int MetaIndex; 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); + CUIntVector Files; // indexes in MetaItems[] + + CDir(): MetaIndex(-1) {} + unsigned GetNumDirs() const; + unsigned GetNumFiles() const; + UInt64 GetTotalSize(const CObjectVector &metaItems) const; + bool FindDir(const CObjectVector &items, const UString &name, unsigned &index); }; -UInt64 CDir::GetNumDirs() const +/* imagex counts Junctions as files (not as dirs). + We suppose that it's not correct */ + +unsigned CDir::GetNumDirs() const { - UInt64 num = Dirs.Size(); - for (int i = 0; i < Dirs.Size(); i++) + unsigned num = Dirs.Size(); + FOR_VECTOR (i, Dirs) num += Dirs[i].GetNumDirs(); return num; } -UInt64 CDir::GetNumFiles() const +unsigned CDir::GetNumFiles() const { - UInt64 num = Files.Size(); - for (int i = 0; i < Dirs.Size(); i++) + unsigned num = Files.Size(); + FOR_VECTOR (i, Dirs) num += Dirs[i].GetNumFiles(); return num; } -CDir* CDir::AddDir(CObjectVector &items, const UString &name, int index) +UInt64 CDir::GetTotalSize(const CObjectVector &metaItems) const +{ + UInt64 sum = 0; + unsigned i; + for (i = 0; i < Files.Size(); i++) + sum += metaItems[Files[i]].Size; + for (i = 0; i < Dirs.Size(); i++) + sum += Dirs[i].GetTotalSize(metaItems); + return sum; +} + +bool CDir::FindDir(const CObjectVector &items, const UString &name, unsigned &index) { - int left = 0, right = Dirs.Size(); + unsigned 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) + unsigned mid = (left + right) / 2; + int comp = CompareFileNames(name, items[Dirs[mid].MetaIndex].Name); + if (comp == 0) { - if (index >= 0) - d.Index = index; - return &d; + index = mid; + return true; } - if (compare < 0) + if (comp < 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; + index = left; + return false; } - -STDMETHODIMP COutHandler::GetFileTimeType(UInt32 *type) +STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) { *type = NFileTimeType::kWindows; return S_OK; } -static HRESULT GetTime(IArchiveUpdateCallback *callback, int index, PROPID propID, FILETIME &ft) +HRESULT CHandler::GetOutProperty(IArchiveUpdateCallback *callback, UInt32 callbackIndex, Int32 arcIndex, PROPID propID, PROPVARIANT *value) +{ + if (arcIndex >= 0) + return GetProperty(arcIndex, propID, value); + return callback->GetProperty(callbackIndex, propID, value); +} + +HRESULT CHandler::GetTime(IArchiveUpdateCallback *callback, UInt32 callbackIndex, Int32 arcIndex, PROPID propID, FILETIME &ft) { ft.dwLowDateTime = ft.dwHighDateTime = 0; NCOM::CPropVariant prop; - RINOK(callback->GetProperty(index, propID, &prop)); + RINOK(GetOutProperty(callback, callbackIndex, arcIndex, propID, &prop)); if (prop.vt == VT_FILETIME) ft = prop.filetime; else if (prop.vt != VT_EMPTY) @@ -150,6 +249,37 @@ static HRESULT GetTime(IArchiveUpdateCallback *callback, int index, PROPID propI return S_OK; } +static HRESULT GetRootTime( + IArchiveGetRootProps *callback, + IArchiveGetRootProps *arcRoot, + PROPID propID, FILETIME &ft) +{ + NCOM::CPropVariant prop; + if (callback) + { + RINOK(callback->GetRootProp(propID, &prop)); + if (prop.vt == VT_FILETIME) + { + ft = prop.filetime; + return S_OK; + } + if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + } + if (arcRoot) + { + RINOK(arcRoot->GetRootProp(propID, &prop)); + if (prop.vt == VT_FILETIME) + { + ft = prop.filetime; + return S_OK; + } + 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) @@ -217,7 +347,7 @@ STDMETHODIMP CInStreamWithSha1::Read(void *data, UInt32 size, UInt32 *processedS HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; _sha.Update((const Byte *)data, realProcessedSize); - if (processedSize != NULL) + if (processedSize) *processedSize = realProcessedSize; return result; } @@ -228,116 +358,301 @@ static void SetFileTimeToMem(Byte *p, const FILETIME &ft) Set32(p + 4, ft.dwHighDateTime); } -static size_t WriteItem(const CUpdateItem &item, Byte *p, const Byte *hash) +static size_t WriteItem_Dummy(const CMetaItem &item) { - int fileNameLen = item.Name.Length() * 2; - int fileNameLen2 = (fileNameLen == 0 ? fileNameLen : fileNameLen + 2); + if (item.Skip) + return 0; + unsigned fileNameLen = item.Name.Len() * 2; + // we write fileNameLen + 2 + 2 to be same as original WIM. + unsigned fileNameLen2 = (fileNameLen == 0 ? 0 : fileNameLen + 2); - size_t totalLen = ((kDirRecordSize + fileNameLen2 + 6) & ~7); - if (p) + unsigned shortNameLen = item.ShortName.Len() * 2; + unsigned shortNameLen2 = (shortNameLen == 0 ? 2 : shortNameLen + 4); + + size_t totalLen = ((kDirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7); + if (item.GetNumAltStreams() != 0) { - 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]); + if (!item.IsDir) + { + UInt32 curLen = (((0x26 + 0) + 6) & ~7); + totalLen += curLen; + } + FOR_VECTOR (i, item.AltStreams) + { + const CAltStream &ss = item.AltStreams[i]; + if (ss.Skip) + continue; + fileNameLen = ss.Name.Len() * 2; + fileNameLen2 = (fileNameLen == 0 ? 0 : fileNameLen + 2 + 2); + UInt32 curLen = (((0x26 + fileNameLen2) + 6) & ~7); + totalLen += curLen; + } } return totalLen; } -static void WriteTree(const CDir &tree, CRecordVector &digests, - CUpdateItem &defaultDirItem, - CObjectVector &updateItems, Byte *dest, size_t &pos) +static size_t WriteItem(const CRecordVector &digests, const CMetaItem &item, Byte *p) { - int i; - for (i = 0; i < tree.Files.Size(); i++) + if (item.Skip) + return 0; + unsigned fileNameLen = item.Name.Len() * 2; + unsigned fileNameLen2 = (fileNameLen == 0 ? 0 : fileNameLen + 2); + unsigned shortNameLen = item.ShortName.Len() * 2; + unsigned shortNameLen2 = (shortNameLen == 0 ? 2 : shortNameLen + 4); + + size_t totalLen = ((kDirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7); + + memset(p, 0, totalLen); + Set64(p, totalLen); + Set64(p + 8, item.Attrib); + Set32(p + 0xC, (Int32)item.SecurityId); + SetFileTimeToMem(p + 0x28, item.CTime); + SetFileTimeToMem(p + 0x30, item.ATime); + SetFileTimeToMem(p + 0x38, item.MTime); + + /* WIM format probably doesn't support hard links to symbolic links. + In these cases it just stores symbolic links (REPARSE TAGS). + Check it in new versions of WIM software form MS !!! + We also follow that scheme */ + + if (item.Reparse.Size() != 0) + { + UInt32 tag = GetUi32(item.Reparse); + Set32(p + 0x58, tag); + // Set32(p + 0x5C, 0); // probably it's always ZERO + } + else if (item.FileID != 0) + { + Set64(p + 0x58, item.FileID); + } + + Set16(p + 0x62, (UInt16)shortNameLen); + Set16(p + 0x64, (UInt16)fileNameLen); + unsigned i; + for (i = 0; i * 2 < fileNameLen; i++) + Set16(p + kDirRecordSize + i * 2, item.Name[i]); + for (i = 0; i * 2 < shortNameLen; i++) + Set16(p + kDirRecordSize + fileNameLen2 + i * 2, item.ShortName[i]); + + if (item.GetNumAltStreams() == 0) + { + if (item.HashIndex >= 0) + memcpy(p + 0x40, digests[item.HashIndex].Hash, kHashSize); + } + else { - const CUpdateItem &ui = updateItems[tree.Files[i]]; - pos += WriteItem(ui, dest ? dest + pos : NULL, - ui.HashIndex >= 0 ? digests[ui.HashIndex].Hash : NULL); + Set16(p + 0x60, (UInt16)(item.GetNumAltStreams() + (item.IsDir ? 0 : 1))); + p += totalLen; + + if (!item.IsDir) + { + UInt32 curLen = (((0x26 + 0) + 6) & ~7); + memset(p, 0, curLen); + Set64(p, curLen); + if (item.HashIndex >= 0) + memcpy(p + 0x10, digests[item.HashIndex].Hash, kHashSize); + totalLen += curLen; + p += curLen; + } + + FOR_VECTOR (si, item.AltStreams) + { + const CAltStream &ss = item.AltStreams[si]; + if (ss.Skip) + continue; + + fileNameLen = ss.Name.Len() * 2; + fileNameLen2 = (fileNameLen == 0 ? 0 : fileNameLen + 2 + 2); + UInt32 curLen = (((0x26 + fileNameLen2) + 6) & ~7); + memset(p, 0, curLen); + + Set64(p, curLen); + if (ss.HashIndex >= 0) + memcpy(p + 0x10, digests[ss.HashIndex].Hash, kHashSize); + Set16(p + 0x24, (UInt16)fileNameLen); + for (i = 0; i * 2 < fileNameLen; i++) + Set16(p + 0x26 + i * 2, ss.Name[i]); + totalLen += curLen; + p += curLen; + } } + + return totalLen; +} - size_t posStart = pos; +struct CDb +{ + CMetaItem DefaultDirItem; + const CRecordVector *Hashes; + CObjectVector MetaItems; + CRecordVector UpdateItems; + CUIntVector UpdateIndexes; /* indexes in UpdateItems in order of writing data streams + to disk (the order of tree items). */ + + size_t WriteTree_Dummy(const CDir &tree) const; + void WriteTree(const CDir &tree, Byte *dest, size_t &pos) const; + void WriteOrderList(const CDir &tree); +}; + +size_t CDb::WriteTree_Dummy(const CDir &tree) const +{ + unsigned i; + size_t pos = 0; + for (i = 0; i < tree.Files.Size(); i++) + pos += WriteItem_Dummy(MetaItems[tree.Files[i]]); 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); + const CDir &subDir = tree.Dirs[i]; + pos += WriteItem_Dummy(MetaItems[subDir.MetaIndex]); + pos += WriteTree_Dummy(subDir); } + return pos + 8; +} + +void CDb::WriteTree(const CDir &tree, Byte *dest, size_t &pos) const +{ + unsigned i; + for (i = 0; i < tree.Files.Size(); i++) + pos += WriteItem(*Hashes, MetaItems[tree.Files[i]], dest + pos); - if (dest) - Set64(dest + pos, 0); + size_t posStart = pos; + for (i = 0; i < tree.Dirs.Size(); i++) + pos += WriteItem_Dummy(MetaItems[tree.Dirs[i].MetaIndex]); + + Set64(dest + pos, 0); pos += 8; for (i = 0; i < tree.Dirs.Size(); i++) { - const CDir &subfolder = tree.Dirs[i]; - if (dest) + const CDir &subDir = tree.Dirs[i]; + const CMetaItem &metaItem = MetaItems[subDir.MetaIndex]; + bool needCreateTree = (metaItem.Reparse.Size() == 0) + || !subDir.Files.IsEmpty() + || !subDir.Dirs.IsEmpty(); + size_t len = WriteItem(*Hashes, metaItem, dest + posStart); + posStart += len; + if (needCreateTree) { - 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; + Set64(dest + posStart - len + 0x10, pos); // subdirOffset + WriteTree(subDir, dest, pos); } - WriteTree(subfolder, digests, defaultDirItem, updateItems, dest, pos); } } -static void AddTag(AString &s, const char *name, const AString &value) +void CDb::WriteOrderList(const CDir &tree) +{ + if (tree.MetaIndex >= 0) + { + const CMetaItem &mi = MetaItems[tree.MetaIndex]; + if (mi.UpdateIndex >= 0) + UpdateIndexes.Add(mi.UpdateIndex); + FOR_VECTOR (si, mi.AltStreams) + UpdateIndexes.Add(mi.AltStreams[si].UpdateIndex); + } + + unsigned i; + for (i = 0; i < tree.Files.Size(); i++) + { + const CMetaItem &mi = MetaItems[tree.Files[i]]; + UpdateIndexes.Add(mi.UpdateIndex); + FOR_VECTOR (si, mi.AltStreams) + UpdateIndexes.Add(mi.AltStreams[si].UpdateIndex); + } + + for (i = 0; i < tree.Dirs.Size(); i++) + WriteOrderList(tree.Dirs[i]); +} + +static void AddTag_ToString(AString &s, const char *name, const char *value) { - s += "<"; + s += '<'; s += name; - s += ">"; + s += '>'; s += value; - s += ""; + s += '>'; +} + +static void AddTagUInt64_ToString(AString &s, const char *name, UInt64 value) +{ + char temp[32]; + ConvertUInt64ToString(value, temp); + AddTag_ToString(s, name, temp); +} + +static CXmlItem &AddUniqueTag(CXmlItem &parentItem, const char *name) +{ + int index = parentItem.FindSubTag(name); + if (index < 0) + { + CXmlItem &subItem = parentItem.SubItems.AddNew(); + subItem.IsTag = true; + subItem.Name = name; + return subItem; + } + CXmlItem &subItem = parentItem.SubItems[index]; + subItem.SubItems.Clear(); + return subItem; } -static void AddTagUInt64(AString &s, const char *name, UInt64 value) +static void AddTag_UInt64_2(CXmlItem &item, UInt64 value) { + CXmlItem &subItem = item.SubItems.AddNew(); + subItem.IsTag = false; char temp[32]; ConvertUInt64ToString(value, temp); - AddTag(s, name, temp); + subItem.Name = temp; +} + +static void AddTag_UInt64(CXmlItem &parentItem, const char *name, UInt64 value) +{ + AddTag_UInt64_2(AddUniqueTag(parentItem, name), value); +} + +static void AddTag_Hex(CXmlItem &item, const char *name, UInt32 value) +{ + item.IsTag = true; + item.Name = name; + char temp[16]; + temp[0] = '0'; + temp[1] = 'x'; + ConvertUInt32ToHex8Digits(value, temp + 2); + CXmlItem &subItem = item.SubItems.AddNew(); + subItem.IsTag = false; + subItem.Name = temp; } -static AString TimeToXml(FILETIME &ft) +static void AddTag_Time_2(CXmlItem &item, const 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; + AddTag_Hex(item.SubItems.AddNew(), "HIGHPART", ft.dwHighDateTime); + AddTag_Hex(item.SubItems.AddNew(), "LOWPART", ft.dwLowDateTime); +} + +static void AddTag_Time(CXmlItem &parentItem, const char *name, const FILETIME &ft) +{ + AddTag_Time_2(AddUniqueTag(parentItem, name), ft); +} + +static void AddTag_String_IfEmpty(CXmlItem &parentItem, const char *name, const char *value) +{ + int index = parentItem.FindSubTag(name); + if (index >= 0) + return; + CXmlItem &tag = parentItem.SubItems.AddNew(); + tag.IsTag = true; + tag.Name = name; + CXmlItem &subItem = tag.SubItems.AddNew(); + subItem.IsTag = false; + subItem.Name = value; } void CHeader::SetDefaultFields(bool useLZX) { Version = kWimVersion; - Flags = NHeaderFlags::kRpFix; + Flags = NHeaderFlags::kReparsePointFixup; ChunkSize = 0; if (useLZX) { @@ -355,285 +670,1097 @@ void CHeader::SetDefaultFields(bool useLZX) IntegrityResource.Clear(); } -static HRESULT UpdateArchive(ISequentialOutStream *seqOutStream, - CDir &rootFolder, - CObjectVector &updateItems, - IArchiveUpdateCallback *callback) +static void AddTrees(CObjectVector &trees, CObjectVector &metaItems, const CMetaItem &ri, int curTreeIndex) { - 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; + while (curTreeIndex >= (int)trees.Size()) + trees.AddNew().Dirs.AddNew().MetaIndex = metaItems.Add(ri); +} - RINOK(callback->SetTotal(complexity)); +STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 numItems, IArchiveUpdateCallback *callback) +{ + COM_TRY_BEGIN - NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; - CMyComPtr copyCoder = copyCoderSpec; + if (ThereIsError()) + return E_NOTIMPL; - CLocalProgress *lps = new CLocalProgress; - CMyComPtr progress = lps; - lps->Init(callback, true); + bool isUpdate = (_volumes.Size() != 0); + int defaultImageIndex = _defaultImageNumber - 1; + bool showImageNumber; - complexity = 0; + if (isUpdate) + { + showImageNumber = _showImageNumber; + if (_version != kWimVersion) + return E_NOTIMPL; + if (_volumes.Size() != 2 || _volumes[0].Stream) + return E_NOTIMPL; + if (!showImageNumber) + defaultImageIndex = _db.IndexOfUserImage; + if (_db.Images.Size() > kNumImagesMax) + return E_NOTIMPL; + } + else + { + showImageNumber = (_set_use_ShowImageNumber && _set_showImageNumber); + if (!showImageNumber) + defaultImageIndex = 0; + } - bool useCompression = false; + if (defaultImageIndex >= kNumImagesMax) + return E_NOTIMPL; - CHeader header; - header.SetDefaultFields(useCompression); - Byte buf[kHeaderSizeMax]; - header.WriteTo(buf); - RINOK(WriteStream(outStream, buf, kHeaderSizeMax)); + CMyComPtr outStream; + RINOK(outSeqStream->QueryInterface(IID_IOutStream, (void **)&outStream)); + if (!outStream) + return E_NOTIMPL; + if (!callback) + return E_FAIL; - CHashList hashes; - CObjectVector streams; + CDb db; + CObjectVector trees; - UInt64 curPos = kHeaderSizeMax; - UInt64 unpackTotalSize = 0; - for (i = 0; i < updateItems.Size(); i++) - { - lps->InSize = lps->OutSize = complexity; - RINOK(lps->SetCur()); + CMetaItem ri; // default DIR item + FILETIME ftCur; + NTime::GetCurUtcFileTime(ftCur); + ri.MTime = ri.ATime = ri.CTime = ftCur; + ri.Attrib = FILE_ATTRIBUTE_DIRECTORY; + ri.IsDir = true; - CUpdateItem &ui = updateItems[i]; - if (ui.IsDir || ui.Size == 0) - continue; - CInStreamWithSha1 *inShaStreamSpec = new CInStreamWithSha1; - CMyComPtr inShaStream = inShaStreamSpec; + // ---------- Detect changed images ---------- + unsigned i; + CBoolVector isChangedImage; + { + CUIntVector numUnchangedItemsInImage; + for (i = 0; i < _db.Images.Size(); i++) { - CMyComPtr fileInStream; - HRESULT res = callback->GetStream(i, &fileInStream); - if (res != S_FALSE) + numUnchangedItemsInImage.Add(0); + isChangedImage.Add(false); + } + + for (i = 0; i < numItems; i++) + { + UInt32 indexInArchive; + Int32 newData, newProps; + RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive)); + if (newProps == 0) { - 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) + if (indexInArchive >= _db.SortedItems.Size()) + continue; + const CItem &item = _db.Items[_db.SortedItems[indexInArchive]]; + if (newData == 0) { - ui.HashIndex = index; - streams[index].RefCount++; - outStream->Seek(-(Int64)packSize, STREAM_SEEK_CUR, &curPos); - outStream->SetSize(curPos); + if (item.ImageIndex >= 0) + numUnchangedItemsInImage[item.ImageIndex]++; } 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; + // oldProps & newData. Current version of 7-Zip doesn't use it + if (item.ImageIndex >= 0) + isChangedImage[item.ImageIndex] = true; } } - fileInStream.Release(); - complexity += ui.Size; - RINOK(callback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); + else if (!showImageNumber) + { + if (defaultImageIndex >= 0 && defaultImageIndex < (int)isChangedImage.Size()) + isChangedImage[defaultImageIndex] = true; + } + else + { + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(i, kpidPath, &prop)); + + if (prop.vt != VT_BSTR) + return E_INVALIDARG; + const wchar_t *path = prop.bstrVal; + if (!path) + return E_INVALIDARG; + + const wchar_t *end; + UInt64 val = ConvertStringToUInt64(path, &end); + if (end == path) + return E_INVALIDARG; + if (val == 0 || val > kNumImagesMax) + return E_INVALIDARG; + wchar_t c = *end; + if (c != 0 && c != ':' && c != L'/' && c != WCHAR_PATH_SEPARATOR) + return E_INVALIDARG; + unsigned imageIndex = (unsigned)val - 1; + if (imageIndex < _db.Images.Size()) + isChangedImage[imageIndex] = true; + if (_defaultImageNumber > 0 && val != _defaultImageNumber) + return E_INVALIDARG; + } } + + for (i = 0; i < _db.Images.Size(); i++) + if (!isChangedImage[i]) + isChangedImage[i] = _db.GetNumUserItemsInImage(i) != numUnchangedItemsInImage[i]; } - lps->InSize = lps->OutSize = complexity; - RINOK(lps->SetCur()); - - 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); + if (defaultImageIndex >= 0) { - 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; + for (i = 0; i < _db.Images.Size(); i++) + if ((int)i != defaultImageIndex) + isChangedImage[i] = false; } + CMyComPtr getRawProps; + callback->QueryInterface(IID_IArchiveGetRawProps, (void **)&getRawProps); - header.OffsetResource.UnpackSize = header.OffsetResource.PackSize = (UInt64)streams.Size() * kStreamInfoSize; - header.OffsetResource.Offset = curPos; - header.OffsetResource.Flags = NResourceFlags::kMetadata; + CMyComPtr getRootProps; + callback->QueryInterface(IID_IArchiveGetRootProps, (void **)&getRootProps); - for (i = 0; i < streams.Size(); i++) + CObjectVector secureBlocks; + + if (!showImageNumber && (getRootProps || isUpdate) && + ( + defaultImageIndex >= (int)isChangedImage.Size() + || defaultImageIndex < 0 // test it + || isChangedImage[defaultImageIndex] + )) { - Byte buf[kStreamInfoSize]; - streams[i].WriteTo(buf); - RINOK(WriteStream(outStream, buf, kStreamInfoSize)); - curPos += kStreamInfoSize; + // Fill Root Item: Metadata and security + CMetaItem rootItem = ri; + { + const void *data = NULL; + UInt32 dataSize = 0; + UInt32 propType = 0; + if (getRootProps) + { + RINOK(getRootProps->GetRootRawProp(kpidNtSecure, &data, &dataSize, &propType)); + } + if (dataSize == 0 && isUpdate) + { + RINOK(GetRootRawProp(kpidNtSecure, &data, &dataSize, &propType)); + } + if (dataSize != 0) + { + if (propType != NPropDataType::kRaw) + return E_FAIL; + while (defaultImageIndex >= (int)secureBlocks.Size()) + secureBlocks.AddNew(); + CUniqBlocks &secUniqBlocks = secureBlocks[defaultImageIndex]; + rootItem.SecurityId = secUniqBlocks.AddUniq((const Byte *)data, dataSize); + } + } + + IArchiveGetRootProps *thisGetRoot = isUpdate ? this : NULL; + + RINOK(GetRootTime(getRootProps, thisGetRoot, kpidCTime, rootItem.CTime)); + RINOK(GetRootTime(getRootProps, thisGetRoot, kpidATime, rootItem.ATime)); + RINOK(GetRootTime(getRootProps, thisGetRoot, kpidMTime, rootItem.MTime)); + + { + NCOM::CPropVariant prop; + if (getRootProps) + { + RINOK(getRootProps->GetRootProp(kpidAttrib, &prop)); + if (prop.vt == VT_UI4) + rootItem.Attrib = prop.ulVal; + else if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + } + if (prop.vt == VT_EMPTY && thisGetRoot) + { + RINOK(GetRootProp(kpidAttrib, &prop)); + if (prop.vt == VT_UI4) + rootItem.Attrib = prop.ulVal; + else if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + } + rootItem.Attrib |= FILE_ATTRIBUTE_DIRECTORY; + } + + AddTrees(trees, db.MetaItems, ri, defaultImageIndex); + db.MetaItems[trees[defaultImageIndex].Dirs[0].MetaIndex] = rootItem; } - 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; + // ---------- Request Metadata for changed items ---------- - 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++) + UString fileName; + + for (i = 0; i < numItems; i++) { CUpdateItem ui; - Int32 newData, newProps; UInt32 indexInArchive; - if (!callback) - return E_FAIL; + Int32 newData, newProps; RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive)); + if (newData == 0 || newProps == 0) + { + if (indexInArchive >= _db.SortedItems.Size()) + continue; + + const CItem &item = _db.Items[_db.SortedItems[indexInArchive]]; + + if (item.ImageIndex >= 0) + { + if (!isChangedImage[item.ImageIndex]) + { + if (newData == 0 && newProps == 0) + continue; + return E_FAIL; + } + } + else + { + // if deleted item was not renamed, we just skip it + if (newProps == 0) + continue; + } + if (newData == 0) + ui.InArcIndex = indexInArchive; + } + + // we set arcIndex only if we must use old props + Int32 arcIndex = (newProps ? -1 : indexInArchive); + bool isDir = false; { NCOM::CPropVariant prop; - RINOK(callback->GetProperty(i, kpidIsDir, &prop)); - if (prop.vt == VT_EMPTY) - ui.IsDir = false; - else if (prop.vt != VT_BOOL) + RINOK(GetOutProperty(callback, i, arcIndex, kpidIsDir, &prop)); + if (prop.vt == VT_BOOL) + isDir = (prop.boolVal != VARIANT_FALSE); + else if (prop.vt != VT_EMPTY) return E_INVALIDARG; - else - ui.IsDir = (prop.boolVal != VARIANT_FALSE); } - + + bool isAltStream = 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) + RINOK(GetOutProperty(callback, i, arcIndex, kpidIsAltStream, &prop)); + if (prop.vt == VT_BOOL) + isAltStream = (prop.boolVal != VARIANT_FALSE); + else if (prop.vt != VT_EMPTY) 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)); + if (isDir && isAltStream) + return E_INVALIDARG; + + UInt64 size = 0; + UInt64 iNode = 0; + + if (!isDir) { + if (!newData) + { + NCOM::CPropVariant prop; + GetProperty(indexInArchive, kpidINode, &prop); + if (prop.vt == VT_UI8) + iNode = prop.uhVal.QuadPart; + } + NCOM::CPropVariant prop; - RINOK(callback->GetProperty(i, kpidSize, &prop)); - if (prop.vt != VT_UI8) + if (newData) + { + RINOK(callback->GetProperty(i, kpidSize, &prop)); + } + else + { + RINOK(GetProperty(indexInArchive, kpidSize, &prop)); + } + if (prop.vt == VT_UI8) + size = prop.uhVal.QuadPart; + else if (prop.vt != VT_EMPTY) 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) + { + NCOM::CPropVariant propPath; + const wchar_t *path = NULL; + RINOK(GetOutProperty(callback, i, arcIndex, kpidPath, &propPath)); + if (propPath.vt == VT_BSTR) + path = propPath.bstrVal; + else if (propPath.vt != VT_EMPTY) + return E_INVALIDARG; + + if (!path) return E_INVALIDARG; - CDir *curItem = &rootFolder; - int len = path.Length(); - UString fileName; - for (int j = 0; j < len; j++) + CDir *curItem = NULL; + bool isRootImageDir = false; + fileName.Empty(); + + int imageIndex; + + if (!showImageNumber) { - wchar_t c = path[j]; - if (c == WCHAR_PATH_SEPARATOR || c == L'/') + imageIndex = defaultImageIndex; + AddTrees(trees, db.MetaItems, ri, imageIndex); + curItem = &trees[imageIndex].Dirs[0]; + } + else + { + const wchar_t *end; + UInt64 val = ConvertStringToUInt64(path, &end); + if (end == path) + return E_INVALIDARG; + if (val == 0 || val > kNumImagesMax) + return E_INVALIDARG; + + imageIndex = (int)val - 1; + if (imageIndex < (int)isChangedImage.Size()) + if (!isChangedImage[imageIndex]) + return E_FAIL; + + AddTrees(trees, db.MetaItems, ri, imageIndex); + curItem = &trees[imageIndex].Dirs[0]; + wchar_t c = *end; + + if (c == 0) + { + if (!isDir || isAltStream) + return E_INVALIDARG; + ui.MetaIndex = curItem->MetaIndex; + isRootImageDir = true; + } + else if (c == ':') { - curItem = curItem->AddDir(updateItems, fileName, -1); - fileName.Empty(); + if (isDir || !isAltStream) + return E_INVALIDARG; + ui.MetaIndex = curItem->MetaIndex; + CAltStream ss; + ss.Size = size; + ss.Name = end + 1; + ss.UpdateIndex = db.UpdateItems.Size(); + ui.AltStreamIndex = db.MetaItems[ui.MetaIndex].AltStreams.Add(ss); + } + else if (c == WCHAR_PATH_SEPARATOR || c == L'/') + { + path = end + 1; + if (*path == 0) + return E_INVALIDARG; } else - fileName += c; + return E_INVALIDARG; } + + if (ui.MetaIndex < 0) + { + for (;;) + { + wchar_t c = *path++; + if (c == 0) + break; + if (c == WCHAR_PATH_SEPARATOR || c == L'/') + { + unsigned indexOfDir; + if (!curItem->FindDir(db.MetaItems, fileName, indexOfDir)) + { + CDir &dir = curItem->Dirs.InsertNew(indexOfDir); + dir.MetaIndex = db.MetaItems.Add(ri); + db.MetaItems.Back().Name = fileName; + } + curItem = &curItem->Dirs[indexOfDir]; + fileName.Empty(); + } + else + fileName += c; + } - ui.Name = fileName; - updateItems.Add(ui); - if (ui.IsDir) - curItem->AddDir(updateItems, fileName, (int)i); + if (isAltStream) + { + int colonPos = fileName.Find(L':'); + if (colonPos < 0) + return E_INVALIDARG; + const UString mainName = fileName.Left(colonPos); + unsigned indexOfDir; + if (curItem->FindDir(db.MetaItems, mainName, indexOfDir)) + ui.MetaIndex = curItem->Dirs[indexOfDir].MetaIndex; + else + { + for (int j = (int)curItem->Files.Size() - 1; j >= 0; j--) + { + int metaIndex = curItem->Files[j]; + const CMetaItem &mi = db.MetaItems[metaIndex]; + if (CompareFileNames(mainName, mi.Name) == 0) + { + ui.MetaIndex = metaIndex; + break; + } + } + } + if (ui.MetaIndex >= 0) + { + CAltStream ss; + ss.Size = size; + ss.Name = fileName.Ptr(colonPos + 1); + ss.UpdateIndex = db.UpdateItems.Size(); + ui.AltStreamIndex = db.MetaItems[ui.MetaIndex].AltStreams.Add(ss); + } + } + } + + + if (ui.MetaIndex < 0 || isRootImageDir) + { + if (!isRootImageDir) + { + ui.MetaIndex = db.MetaItems.Size(); + db.MetaItems.AddNew(); + } + CMetaItem &mi = db.MetaItems[ui.MetaIndex]; + mi.Size = size; + mi.IsDir = isDir; + mi.Name = fileName; + mi.UpdateIndex = db.UpdateItems.Size(); + { + NCOM::CPropVariant prop; + RINOK(GetOutProperty(callback, i, arcIndex, kpidAttrib, &prop)); + if (prop.vt == VT_EMPTY) + mi.Attrib = 0; + else if (prop.vt == VT_UI4) + mi.Attrib = prop.ulVal; + else + return E_INVALIDARG; + if (isDir) + mi.Attrib |= FILE_ATTRIBUTE_DIRECTORY; + } + RINOK(GetTime(callback, i, arcIndex, kpidCTime, mi.CTime)); + RINOK(GetTime(callback, i, arcIndex, kpidATime, mi.ATime)); + RINOK(GetTime(callback, i, arcIndex, kpidMTime, mi.MTime)); + + { + NCOM::CPropVariant prop; + RINOK(GetOutProperty(callback, i, arcIndex, kpidShortName, &prop)); + if (prop.vt == VT_BSTR) + mi.ShortName = prop.bstrVal; + else if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + } + + while (imageIndex >= (int)secureBlocks.Size()) + secureBlocks.AddNew(); + + if (!isAltStream && (getRawProps || arcIndex >= 0)) + { + CUniqBlocks &secUniqBlocks = secureBlocks[imageIndex]; + const void *data; + UInt32 dataSize; + UInt32 propType; + + data = NULL; + dataSize = 0; + propType = 0; + + if (arcIndex >= 0) + { + GetRawProp(arcIndex, kpidNtSecure, &data, &dataSize, &propType); + } + else + { + getRawProps->GetRawProp(i, kpidNtSecure, &data, &dataSize, &propType); + } + if (dataSize != 0) + { + if (propType != NPropDataType::kRaw) + return E_FAIL; + mi.SecurityId = secUniqBlocks.AddUniq((const Byte *)data, dataSize); + } + + data = NULL; + dataSize = 0; + propType = 0; + if (arcIndex >= 0) + { + GetRawProp(arcIndex, kpidNtReparse, &data, &dataSize, &propType); + } + else + { + getRawProps->GetRawProp(i, kpidNtReparse, &data, &dataSize, &propType); + } + if (dataSize != 0) + { + if (propType != NPropDataType::kRaw) + return E_FAIL; + mi.Reparse.CopyFrom((const Byte *)data, dataSize); + } + } + + if (!isRootImageDir) + { + if (isDir) + { + unsigned indexOfDir; + if (curItem->FindDir(db.MetaItems, fileName, indexOfDir)) + curItem->Dirs[indexOfDir].MetaIndex = ui.MetaIndex; + else + curItem->Dirs.InsertNew(indexOfDir).MetaIndex = ui.MetaIndex; + } + else + curItem->Files.Add(ui.MetaIndex); + } + } + + } + + if (iNode != 0 && ui.MetaIndex >= 0 && ui.AltStreamIndex < 0) + db.MetaItems[ui.MetaIndex].FileID = iNode; + + ui.CallbackIndex = i; + db.UpdateItems.Add(ui); + } + + unsigned numNewImages = trees.Size(); + for (i = numNewImages; i < isChangedImage.Size(); i++) + if (!isChangedImage[i]) + numNewImages = i + 1; + + AddTrees(trees, db.MetaItems, ri, numNewImages - 1); + + for (i = 0; i < trees.Size(); i++) + if (i >= isChangedImage.Size() || isChangedImage[i]) + db.WriteOrderList(trees[i]); + + + UInt64 complexity = 0; + + unsigned numDataStreams = _db.DataStreams.Size(); + CIntArr streamsRefs(numDataStreams); + for (i = 0; i < numDataStreams; i++) + streamsRefs[i] = 0; + + // ---------- Calculate Streams Refs Counts in unchanged images + + for (i = 0; i < _db.Images.Size(); i++) + { + if (isChangedImage[i]) + continue; + complexity += _db.MetaStreams[i].Resource.PackSize; + const CImage &image = _db.Images[i]; + unsigned endItem = image.StartItem + image.NumItems; + for (unsigned k = image.StartItem; k < endItem; k++) + { + const CItem &item = _db.Items[k]; + if (item.StreamIndex >= 0) + streamsRefs[item.StreamIndex]++; + } + } + + // ---------- Update Streams Refs Counts in changed images + + for (i = 0; i < db.UpdateIndexes.Size(); i++) + { + const CUpdateItem &ui = db.UpdateItems[db.UpdateIndexes[i]]; + if (ui.InArcIndex >= 0) + { + if ((unsigned)ui.InArcIndex >= _db.SortedItems.Size()) + continue; + const CItem &item = _db.Items[_db.SortedItems[ui.InArcIndex]]; + if (item.StreamIndex >= 0) + streamsRefs[item.StreamIndex]++; + } else - curItem->Files.Add(i); + { + const CMetaItem &mi = db.MetaItems[ui.MetaIndex]; + UInt64 size; + if (ui.AltStreamIndex < 0) + size = mi.Size; + else + size = mi.AltStreams[ui.AltStreamIndex].Size; + complexity += size; + } } - return UpdateArchive(outStream, tree, updateItems, callback); + + for (i = 0; i < _db.DataStreams.Size(); i++) + if (streamsRefs[i] != 0) + complexity += _db.DataStreams[i].Resource.PackSize; + + 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 useResourceCompression = false; + // use useResourceCompression only if CHeader::Flags compression is also set + + CHeader header; + header.SetDefaultFields(false); + + if (isUpdate) + { + const CHeader &srcHeader = _volumes[1].Header; + header.Flags = srcHeader.Flags; + header.ChunkSize = srcHeader.ChunkSize; + } + + Byte buf[kHeaderSizeMax]; + header.WriteTo(buf); + RINOK(WriteStream(outStream, buf, kHeaderSizeMax)); + + UInt64 curPos = kHeaderSizeMax; + + CInStreamWithSha1 *inShaStreamSpec = new CInStreamWithSha1; + CMyComPtr inShaStream = inShaStreamSpec; + + CLimitedSequentialInStream *inStreamLimitedSpec = NULL; + CMyComPtr inStreamLimited; + if (_volumes.Size() == 2) + { + inStreamLimitedSpec = new CLimitedSequentialInStream; + inStreamLimited = inStreamLimitedSpec; + inStreamLimitedSpec->SetStream(_volumes[1].Stream); + } + + + // these two lists have same sizes and same hashes in same order. + CHashList hashes; + CObjectVector streams; + + + // ---------- Copy unchanged data streams ---------- + + for (i = 0; i < _db.DataStreams.Size(); i++) + { + if (streamsRefs[i] == 0) + continue; + + lps->InSize = lps->OutSize = complexity; + RINOK(lps->SetCur()); + + const CStreamInfo &siOld = _db.DataStreams[i]; + if (hashes.AddUniq(siOld.Hash) >= 0) + return E_FAIL; // two streams with same SHA-1 + + RINOK(_volumes[siOld.PartNumber].Stream->Seek(siOld.Resource.Offset, STREAM_SEEK_SET, NULL)); + inStreamLimitedSpec->Init(siOld.Resource.PackSize); + RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)); + if (copyCoderSpec->TotalSize != siOld.Resource.PackSize) + return E_FAIL; + + CStreamInfo &s = streams.AddNew(); + s.Resource = siOld.Resource; + s.Resource.Offset = curPos; + s.PartNumber = 1; + s.RefCount = streamsRefs[i]; + memcpy(s.Hash, siOld.Hash, kHashSize); + + curPos += s.Resource.PackSize; + lps->ProgressOffset += s.Resource.PackSize; + } + + + // ---------- Write new items ---------- + + CUIntVector hlIndexes; // sorted indexes for hard link items + + for (i = 0; i < db.UpdateIndexes.Size(); i++) + { + lps->InSize = lps->OutSize = complexity; + RINOK(lps->SetCur()); + + const CUpdateItem &ui = db.UpdateItems[db.UpdateIndexes[i]]; + CMetaItem &mi = db.MetaItems[ui.MetaIndex]; + UInt64 size = 0; + + if (ui.AltStreamIndex >= 0) + { + if (mi.Skip) + continue; + size = mi.AltStreams[ui.AltStreamIndex].Size; + } + else + { + size = mi.Size; + if (mi.IsDir) + { + // we support LINK files here + if (mi.Reparse.Size() == 0) + continue; + } + } + + if (ui.InArcIndex >= 0) + { + // data streams with OLD Data were written already + // we just need to find HashIndex in hashes. + + if ((unsigned)ui.InArcIndex >= _db.SortedItems.Size()) + return E_FAIL; + const CItem &item = _db.Items[_db.SortedItems[ui.InArcIndex]]; + if (item.StreamIndex < 0) + { + if (size == 0) + continue; + // if (_db.ItemHasStream(item)) + return E_FAIL; + } + + // We support empty file (size = 0, but with stream and SHA-1) from old archive + + const CStreamInfo &siOld = _db.DataStreams[item.StreamIndex]; + // we must have written that stream already + int index = hashes.AddUniq(siOld.Hash); + if (index < 0) + return E_FAIL; + if (ui.AltStreamIndex < 0) + mi.HashIndex = index; + else + mi.AltStreams[ui.AltStreamIndex].HashIndex = index; + continue; + } + + CMyComPtr fileInStream; + HRESULT res = callback->GetStream(ui.CallbackIndex, &fileInStream); + if (res == S_FALSE) + { + if (ui.AltStreamIndex >= 0) + { + mi.NumSkipAltStreams++; + mi.AltStreams[ui.AltStreamIndex].Skip = true; + } + else + mi.Skip = true; + } + else + { + RINOK(res); + + int miIndex = -1; + + if (!fileInStream) + { + if (!mi.IsDir) + return E_INVALIDARG; + } + else if (ui.AltStreamIndex < 0) + { + CMyComPtr getProps2; + fileInStream->QueryInterface(IID_IStreamGetProps2, (void **)&getProps2); + if (getProps2) + { + CStreamFileProps props; + if (getProps2->GetProps2(&props) == S_OK) + { + mi.Attrib = props.Attrib; + mi.Size = props.Size; + size = props.Size; + mi.CTime = props.CTime; + mi.ATime = props.ATime; + mi.MTime = props.MTime; + mi.FileID = props.FileID_Low; + if (props.NumLinks <= 1) + mi.FileID = 0; + mi.VolID = props.VolID; + if (mi.FileID != 0) + miIndex = AddToHardLinkList(db.MetaItems, ui.MetaIndex, hlIndexes); + } + } + } + + if (miIndex >= 0) + { + mi.HashIndex = db.MetaItems[miIndex].HashIndex; + if (mi.HashIndex >= 0) + streams[mi.HashIndex].RefCount++; + // fix for future: maybe we need to check also that real size is equal to size from IStreamGetProps2 + } + else if (ui.AltStreamIndex < 0 && mi.Reparse.Size() != 0) + { + if (mi.Reparse.Size() < 8) + return E_FAIL; + NCrypto::NSha1::CContext sha1; + sha1.Init(); + size_t packSize = mi.Reparse.Size() - 8; + sha1.Update((const Byte *)mi.Reparse + 8, packSize); + Byte hash[kHashSize]; + sha1.Final(hash); + int index = hashes.AddUniq(hash); + if (index >= 0) + streams[index].RefCount++; + else + { + RINOK(WriteStream(outStream, (const Byte *)mi.Reparse + 8, packSize)); + index = streams.Size(); + CStreamInfo &s = streams.AddNew(); + s.Resource.PackSize = packSize; + s.Resource.Offset = curPos; + s.Resource.UnpackSize = packSize; + s.Resource.Flags = 0; // check it + /* + if (useResourceCompression) + s.Resource.Flags = NResourceFlags::Compressed; + */ + s.PartNumber = 1; + s.RefCount = 1; + memcpy(s.Hash, hash, kHashSize); + curPos += packSize; + } + mi.HashIndex = index; + } + else + { + inShaStreamSpec->SetStream(fileInStream); + fileInStream.Release(); + inShaStreamSpec->Init(); + UInt64 offsetBlockSize = 0; + /* + if (useResourceCompression) + { + for (UInt64 t = kChunkSize; t < 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)); + size = copyCoderSpec->TotalSize; + + if (size != 0) + { + Byte hash[kHashSize]; + UInt64 packSize = offsetBlockSize + size; + inShaStreamSpec->Final(hash); + int index = hashes.AddUniq(hash); + + if (index >= 0) + { + streams[index].RefCount++; + outStream->Seek(-(Int64)packSize, STREAM_SEEK_CUR, &curPos); + outStream->SetSize(curPos); + } + else + { + index = streams.Size(); + CStreamInfo &s = streams.AddNew(); + s.Resource.PackSize = packSize; + s.Resource.Offset = curPos; + s.Resource.UnpackSize = size; + s.Resource.Flags = 0; + /* + if (useResourceCompression) + s.Resource.Flags = NResourceFlags::Compressed; + */ + s.PartNumber = 1; + s.RefCount = 1; + memcpy(s.Hash, hash, kHashSize); + curPos += packSize; + } + + if (ui.AltStreamIndex < 0) + mi.HashIndex = index; + else + mi.AltStreams[ui.AltStreamIndex].HashIndex = index; + } + } + } + fileInStream.Release(); + complexity += size; + RINOK(callback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); + } + + while (secureBlocks.Size() < numNewImages) + secureBlocks.AddNew(); + + + + // ---------- Write Images ---------- + + for (i = 0; i < numNewImages; i++) + { + lps->InSize = lps->OutSize = complexity; + RINOK(lps->SetCur()); + if (i < isChangedImage.Size() && !isChangedImage[i]) + { + CStreamInfo s = _db.MetaStreams[i]; + + RINOK(_volumes[1].Stream->Seek(s.Resource.Offset, STREAM_SEEK_SET, NULL)); + inStreamLimitedSpec->Init(s.Resource.PackSize); + RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)); + if (copyCoderSpec->TotalSize != s.Resource.PackSize) + return E_FAIL; + + s.Resource.Offset = curPos; + s.PartNumber = 1; + s.RefCount = 1; + streams.Add(s); + + if (_bootIndex != 0 && _bootIndex == (UInt32)i + 1) + { + header.MetadataResource = s.Resource; + header.BootIndex = _bootIndex; + } + + lps->ProgressOffset += s.Resource.PackSize; + curPos += s.Resource.PackSize; + // printf("\nWrite old image %x\n", i + 1); + continue; + } + + const CDir &tree = trees[i]; + const UInt32 kSecuritySize = 8; + + size_t pos = kSecuritySize; + + const CUniqBlocks &secUniqBlocks = secureBlocks[i]; + const CObjectVector &secBufs = secUniqBlocks.Bufs; + pos += (size_t)secUniqBlocks.GetTotalSizeInBytes(); + pos += secBufs.Size() * 8; + pos = (pos + 7) & ~(size_t)7; + + db.DefaultDirItem = ri; + pos += db.WriteTree_Dummy(tree); + + CByteBuffer meta(pos); + + Set32((Byte *)meta + 4, secBufs.Size()); // num security entries + pos = kSecuritySize; + + if (secBufs.Size() == 0) + { + // 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, 0); + } + else + { + unsigned i; + for (i = 0; i < secBufs.Size(); i++, pos += 8) + { + Set64(meta + pos, secBufs[i].Size()); + } + for (i = 0; i < secBufs.Size(); i++) + { + const CByteBuffer &buf = secBufs[i]; + size_t size = buf.Size(); + memcpy(meta + pos, buf, size); + pos += size; + } + while ((pos & 7) != 0) + meta[pos++] = 0; + Set32((Byte *)meta, (UInt32)pos); // size of security data + } + + db.Hashes = &hashes.Digests; + db.WriteTree(tree, (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); + + if (_bootIndex != 0 && _bootIndex == (UInt32)i + 1) + { + header.MetadataResource = s.Resource; + header.BootIndex = _bootIndex; + } + + RINOK(WriteStream(outStream, (const Byte *)meta, pos)); + meta.Free(); + curPos += pos; + } + } + + lps->InSize = lps->OutSize = complexity; + RINOK(lps->SetCur()); + + header.OffsetResource.UnpackSize = header.OffsetResource.PackSize = (UInt64)streams.Size() * kStreamInfoSize; + header.OffsetResource.Offset = curPos; + header.OffsetResource.Flags = NResourceFlags::kMetadata; + + + + // ---------- Write Streams Info Tables ---------- + + for (i = 0; i < streams.Size(); i++) + { + Byte buf[kStreamInfoSize]; + streams[i].WriteTo(buf); + RINOK(WriteStream(outStream, buf, kStreamInfoSize)); + curPos += kStreamInfoSize; + } + + AString xml = ""; + AddTagUInt64_ToString(xml, "TOTALBYTES", curPos); + for (i = 0; i < trees.Size(); i++) + { + CDir &tree = trees[i]; + + CXmlItem item; + if (_xmls.Size() == 1) + { + const CWimXml &_oldXml = _xmls[0]; + if ((int)i < _oldXml.Images.Size()) + { + // int ttt = _oldXml.Images[i].ItemIndexInXml; + item = _oldXml.Xml.Root.SubItems[_oldXml.Images[i].ItemIndexInXml]; + } + } + if (i >= isChangedImage.Size() || isChangedImage[i]) + { + char temp[16]; + if (item.Name.IsEmpty()) + { + ConvertUInt32ToString(i + 1, temp); + item.Name = "IMAGE"; + item.IsTag = true; + CXmlProp &prop = item.Props.AddNew(); + prop.Name = "INDEX"; + prop.Value = temp; + } + + AddTag_String_IfEmpty(item, "NAME", temp); + AddTag_UInt64(item, "DIRCOUNT", tree.GetNumDirs() - 1); + AddTag_UInt64(item, "FILECOUNT", tree.GetNumFiles()); + AddTag_UInt64(item, "TOTALBYTES", tree.GetTotalSize(db.MetaItems)); + + AddTag_Time(item, "CREATIONTIME", ftCur); + AddTag_Time(item, "LASTMODIFICATIONTIME", ftCur); + } + + item.AppendTo(xml); + } + xml += ""; + + size_t xmlSize; + { + UString utf16String; + if (!ConvertUTF8ToUnicode(xml, utf16String)) + return S_FALSE; + xmlSize = (utf16String.Len() + 1) * 2; + + CByteBuffer xmlBuf(xmlSize); + Set16((Byte *)xmlBuf, 0xFEFF); + for (i = 0; i < (unsigned)utf16String.Len(); i++) + Set16((Byte *)xmlBuf + 2 + i * 2, utf16String[i]); + RINOK(WriteStream(outStream, (const Byte *)xmlBuf, xmlSize)); + } + + header.XmlResource.UnpackSize = header.XmlResource.PackSize = xmlSize; + header.XmlResource.Offset = curPos; + header.XmlResource.Flags = NResourceFlags::kMetadata; + + outStream->Seek(0, STREAM_SEEK_SET, NULL); + header.NumImages = trees.Size(); + header.WriteTo(buf); + return WriteStream(outStream, buf, kHeaderSizeMax); + COM_TRY_END } diff --git a/CPP/7zip/Archive/Wim/WimIn.cpp b/CPP/7zip/Archive/Wim/WimIn.cpp old mode 100755 new mode 100644 index c210804d..cec037cc --- a/CPP/7zip/Archive/Wim/WimIn.cpp +++ b/CPP/7zip/Archive/Wim/WimIn.cpp @@ -2,13 +2,17 @@ #include "StdAfx.h" +// #include + #include "../../../../C/CpuArch.h" -#include "Common/IntToString.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringToInt.h" +#include "../../../Common/UTFConvert.h" -#include "../../Common/StreamUtils.h" -#include "../../Common/StreamObjects.h" #include "../../Common/LimitedStreams.h" +#include "../../Common/StreamObjects.h" +#include "../../Common/StreamUtils.h" #include "../Common/OutStreamWithSha1.h" @@ -33,7 +37,6 @@ public: { if (NeedFlush) m_Decoder->Flush(); - m_Decoder->ReleaseStreams(); } }; @@ -44,8 +47,8 @@ HRESULT CDecoder::CodeSpec(UInt32 outSize) for (unsigned i = 0; i < kMainTableSize; i += 2) { Byte b = m_InBitStream.DirectReadByte(); - levels[i] = b & 0xF; - levels[i + 1] = b >> 4; + levels[i] = (Byte)(b & 0xF); + levels[i + 1] = (Byte)(b >> 4); } if (!m_MainDecoder.SetCodeLengths(levels)) return S_FALSE; @@ -154,11 +157,7 @@ HRESULT CUnpacker::Unpack(IInStream *inStream, const CResource &resource, bool l size_t sizesBufSize = (size_t)sizesBufSize64; if (sizesBufSize != sizesBufSize64) return E_OUTOFMEMORY; - if (sizesBufSize > sizesBuf.GetCapacity()) - { - sizesBuf.Free(); - sizesBuf.SetCapacity(sizesBufSize); - } + sizesBuf.AllocAtLeast(sizesBufSize); RINOK(ReadStream_FALSE(inStream, (Byte *)sizesBuf, sizesBufSize)); const Byte *p = (const Byte *)sizesBuf; @@ -237,8 +236,7 @@ static HRESULT UnpackData(IInStream *inStream, const CResource &resource, bool l size_t size = (size_t)resource.UnpackSize; if (size != resource.UnpackSize) return E_OUTOFMEMORY; - buf.Free(); - buf.SetCapacity(size); + buf.Alloc(size); CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream(); CMyComPtr outStream = outStreamSpec; @@ -256,7 +254,7 @@ void CResource::Parse(const Byte *p) UnpackSize = Get64(p + 16); } -#define GetResource(p, res) res.Parse(p) +#define GET_RESOURCE(_p_, res) res.ParseAndUpdatePhySize(_p_, phySize) static void GetStream(bool oldVersion, const Byte *p, CStreamInfo &s) { @@ -265,111 +263,151 @@ static void GetStream(bool oldVersion, const Byte *p, CStreamInfo &s) { s.PartNumber = 1; s.Id = Get32(p + 24); - s.RefCount = Get32(p + 28); - memcpy(s.Hash, p + 32, kHashSize); + // printf("\n%d", s.Id); + p += 28; } else { s.PartNumber = Get16(p + 24); - s.RefCount = Get32(p + 26); - memcpy(s.Hash, p + 30, kHashSize); + p += 26; } + s.RefCount = Get32(p); + memcpy(s.Hash, p + 4, kHashSize); } -static const wchar_t *kLongPath = L"[LongPath]"; -UString CDatabase::GetItemPath(const int index1) const +static const char *kLongPath = "[LongPath]"; + +void CDatabase::GetShortName(unsigned index, NWindows::NCOM::CPropVariant &name) const { - int size = 0; + const CItem &item = Items[index]; + const CImage &image = Images[item.ImageIndex]; + if (item.Parent < 0 && image.NumEmptyRootItems != 0) + { + name.Clear(); + return; + } + const Byte *meta = image.Meta + item.Offset + + (IsOldVersion ? kDirRecordSizeOld : kDirRecordSize); + UInt32 fileNameLen = Get16(meta - 2); + UInt32 shortLen = Get16(meta - 4) / 2; + wchar_t *s = name.AllocBstr(shortLen); + if (fileNameLen != 0) + meta += fileNameLen + 2; + for (UInt32 i = 0; i < shortLen; i++) + s[i] = Get16(meta + i * 2); + s[shortLen] = 0; + // empty shortName has no ZERO at the end ? +} + +void CDatabase::GetItemName(unsigned index, NWindows::NCOM::CPropVariant &name) const +{ + const CItem &item = Items[index]; + const CImage &image = Images[item.ImageIndex]; + if (item.Parent < 0 && image.NumEmptyRootItems != 0) + { + name = image.RootName; + return; + } + const Byte *meta = image.Meta + item.Offset + + (item.IsAltStream ? + (IsOldVersion ? 0x10 : 0x24) : + (IsOldVersion ? kDirRecordSizeOld - 2 : kDirRecordSize - 2)); + UInt32 len = Get16(meta) / 2; + wchar_t *s = name.AllocBstr(len); + meta += 2; + len++; + for (UInt32 i = 0; i < len; i++) + s[i] = Get16(meta + i * 2); +} + +void CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCOM::CPropVariant &path) const +{ + unsigned size = 0; int index = index1; - int newLevel; - for (newLevel = 0;; newLevel = 1) + unsigned newLevel; + int imageIndex = Items[index].ImageIndex; + const CImage &image = Images[imageIndex]; + for (newLevel = 0;;) { const CItem &item = Items[index]; index = item.Parent; - if (index >= 0 || !SkipRoot) - size += item.Name.Length() + newLevel; + if (index >= 0 || image.NumEmptyRootItems == 0) + { + const Byte *meta = image.Meta + item.Offset; + meta += item.IsAltStream ? + (IsOldVersion ? 0x10 : 0x24) : + (IsOldVersion ? kDirRecordSizeOld - 2 : kDirRecordSize - 2); + size += Get16(meta) / 2; + size += newLevel; + newLevel = 1; + if ((UInt32)size >= ((UInt32)1 << 15)) + { + path = kLongPath; + return; + } + } if (index < 0) break; - if ((UInt32)size >= ((UInt32)1 << 16)) - return kLongPath; } - wchar_t temp[16]; - int imageLen = 0; - if (ShowImageNumber) + if (showImageNumber) { - ConvertUInt32ToString(-1 - index, temp); - imageLen = MyStringLen(temp); - size += imageLen + 1; + size += image.RootName.Len(); + size += newLevel; } - if ((UInt32)size >= ((UInt32)1 << 16)) - return kLongPath; - UString path; - wchar_t *s = path.GetBuffer(size); + wchar_t *s = path.AllocBstr(size); s[size] = 0; - if (ShowImageNumber) + + if (showImageNumber) { - memcpy(s, temp, imageLen * sizeof(wchar_t)); - s[imageLen] = WCHAR_PATH_SEPARATOR; + MyStringCopy(s, (const wchar_t *)image.RootName); + if (newLevel) + s[image.RootName.Len()] = WCHAR_PATH_SEPARATOR; } index = index1; - - for (newLevel = 0;; newLevel = 1) + wchar_t separator = 0; + for (;;) { const CItem &item = Items[index]; index = item.Parent; - if (index >= 0 || !SkipRoot) + if (index >= 0 || image.NumEmptyRootItems == 0) { - if (newLevel) - s[--size] = WCHAR_PATH_SEPARATOR; - size -= item.Name.Length(); - memcpy(s + size, item.Name, sizeof(wchar_t) * item.Name.Length()); + if (separator) + s[--size] = separator; + const Byte *meta = image.Meta + item.Offset; + meta += (item.IsAltStream) ? + (IsOldVersion ? 0x10: 0x24) : + (IsOldVersion ? kDirRecordSizeOld - 2 : kDirRecordSize - 2); + UInt32 len = Get16(meta) / 2; + size -= len; + wchar_t *dest = s + size; + meta += 2; + for (UInt32 i = 0; i < len; i++) + dest[i] = Get16(meta + i * 2); } if (index < 0) - { - path.ReleaseBuffer(); - return path; - } + return; + separator = item.IsAltStream ? L':' : WCHAR_PATH_SEPARATOR; } } -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; -} +// Root folders in OLD archives (ver = 1.10) conatin real items. +// Root folders in NEW archives (ver > 1.11) contain only one folder with empty name. HRESULT CDatabase::ParseDirItem(size_t pos, int parent) { if ((pos & 7) != 0) return S_FALSE; - - int prevIndex = -1; - for (int numItems = 0;; numItems++) + + for (unsigned numItems = 0;; numItems++) { - if (OpenCallback) + if (OpenCallback && (Items.Size() & 0xFFFF) == 0) { UInt64 numFiles = Items.Size(); - if ((numFiles & 0x3FF) == 0) - { - RINOK(OpenCallback->SetCompleted(&numFiles, NULL)); - } + RINOK(OpenCallback->SetCompleted(&numFiles, NULL)); } size_t rem = DirSize - pos; if (pos < DirStartOffset || pos > DirSize || rem < 8) @@ -379,32 +417,93 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent) if (len == 0) { if (parent < 0 && numItems != 1) - SkipRoot = false; + Images.Back().NumEmptyRootItems = 0; 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) + + UInt32 dirRecordSize = IsOldVersion ? kDirRecordSizeOld : kDirRecordSize; + if (len < dirRecordSize) + return S_FALSE; + + CItem item; + UInt32 attrib = Get32(p + 8); + item.IsDir = ((attrib & 0x10) != 0); + UInt64 subdirOffset = Get64(p + 0x10); + UInt32 numAltStreams = 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; + { - if (len < 0x40 || (/* Get32(p + 12) == 0 && */ Get32(p + 0x14) != 0)) - { - extraOffset = 0x10; - } + if (*(const UInt16 *)(p + fileNameLen) != 0) + return S_FALSE; + for (UInt32 j = 0; j < fileNameLen; j += 2) + if (*(const UInt16 *)(p + j) == 0) + return S_FALSE; + } + if (shortNameLen != 0) + { + // empty shortName has no ZERO at the end ? + const Byte *p2 = p + fileNameLen2; + if (*(const UInt16 *)(p2 + shortNameLen) != 0) + return S_FALSE; + for (UInt32 j = 0; j < shortNameLen; j += 2) + if (*(const UInt16 *)(p2 + j) == 0) + return S_FALSE; } - else if (Get64(p + 8) == 0) - extraOffset = 0x24; - if (extraOffset) + + item.Offset = pos; + item.Parent = parent; + item.ImageIndex = Images.Size() - 1; + unsigned prevIndex = Items.Add(item); + + pos += (size_t)len; + + for (UInt32 i = 0; i < numAltStreams; i++) { - if (prevIndex == -1) + 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) + return S_FALSE; + if ((len & 7) != 0 || rem < len) + return S_FALSE; + if (IsOldVersion) + { + if (len < 0x18) + return S_FALSE; + } + else + if (len < 0x28) + return S_FALSE; + DirProcessed += (size_t)len; + if (DirProcessed > DirSize) + return S_FALSE; + + unsigned extraOffset = 0; + if (IsOldVersion) + extraOffset = 0x10; + else + { + if (Get64(p + 8) != 0) + return S_FALSE; + extraOffset = 0x24; + } UInt32 fileNameLen = Get16(p + extraOffset); if ((fileNameLen & 1) != 0) return S_FALSE; @@ -414,188 +513,137 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent) if (((extraOffset + 2 + fileNameLen2 + 6) & ~7) > len) return S_FALSE; - UString name; - RINOK(ReadName(p + extraOffset + 2, fileNameLen, name)); + { + const Byte *p2 = p + extraOffset + 2; + if (*(const UInt16 *)(p2 + fileNameLen) != 0) + return S_FALSE; + for (UInt32 j = 0; j < fileNameLen; j += 2) + if (*(const UInt16 *)(p2 + j) == 0) + return S_FALSE; + } - CItem &prevItem = Items[prevIndex]; - if (name.IsEmpty() && !prevItem.HasStream()) + if (fileNameLen == 0) { + Byte *prevMeta = DirData + item.Offset; if (IsOldVersion) - prevItem.Id = Get32(p + 8); + memcpy(prevMeta + 0x10, p + 8, 4); // It's 32-bit Id else - memcpy(prevItem.Hash, p + 0x10, kHashSize); + memcpy(prevMeta + 0x40, 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); + ThereAreAltStreams = true; + CItem item2; + item2.Offset = pos; + item2.IsAltStream = true; + item2.Parent = prevIndex; + item2.ImageIndex = Images.Size() - 1; + Items.Add(item2); } 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) + if (parent < 0 && numItems == 0 && shortNameLen == 0 && fileNameLen == 0 && item.IsDir) { - UString s = GetItemPath(parent) + L"\\" + item.Name; - printf("\n%s %8x %S", item.IsDir() ? "D" : " ", (int)subdirOffset, (const wchar_t *)s); + CImage &image = Images.Back(); + image.NumEmptyRootItems = Items.Size() - image.StartItem; } - */ - - 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) + 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) +HRESULT CDatabase::ParseImageDirs(CByteBuffer &buf, int parent) { DirData = buf; - DirSize = buf.GetCapacity(); - - size_t pos = 0; + DirSize = buf.Size(); if (DirSize < 8) return S_FALSE; const Byte *p = DirData; - UInt32 totalLength = Get32(p); + size_t pos = 0; + CImage &image = Images.Back(); + if (IsOldVersion) { - for (pos = 4;; pos += 8) + // there is no specification about that code + UInt32 sum = 0; + image.SecurOffsets.Add(0); + for (;;) { - 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) + UInt32 len = Get32(p + pos); + if (len > DirSize - sum) return S_FALSE; + sum += len; + image.SecurOffsets.Add(sum); + UInt32 n = Get32(p + pos + 4); // what does this field mean? + pos += 8; + if (n == 0) + break; } - pos += totalLength + 4; - pos = (pos + 7) & ~(size_t)7; - if (pos > DirSize) + if (sum > DirSize - pos) return S_FALSE; + FOR_VECTOR (i, image.SecurOffsets) + image.SecurOffsets[i] += (UInt32)pos; + pos += sum; + pos = (pos + 7) & ~(size_t)7; } else { - - // UInt32 numEntries = Get32(p + 4); - pos += 8; - { - /* - CRecordVector entryLens; - UInt64 sum = 0; - for (UInt32 i = 0; i < numEntries; i++) + UInt32 totalLen = Get32(p); + if (totalLen == 0) + pos = 8; + else { - if (pos + 8 > DirSize) + if (totalLen < 8) 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) + UInt32 numEntries = Get32(p + 4); pos = 8; - else if (totalLength < 8) - return S_FALSE; - else - pos = totalLength; - } + if (totalLen > DirSize || numEntries > ((totalLen - 8) >> 3)) + return S_FALSE; + UInt32 sum = (UInt32)pos + numEntries * 8; + image.SecurOffsets.ClearAndReserve(numEntries + 1); + image.SecurOffsets.AddInReserved(sum); + for (UInt32 i = 0; i < numEntries; i++, pos += 8) + { + UInt64 len = Get64(p + pos); + if (len > totalLen - sum) + return S_FALSE; + sum += (UInt32)len; + image.SecurOffsets.AddInReserved(sum); + } + pos = sum; + pos = (pos + 7) & ~(size_t)7; + if (pos != (((size_t)totalLen + 7) & ~(size_t)7)) + return S_FALSE; + } } + + if (pos > DirSize) + return S_FALSE; DirStartOffset = DirProcessed = pos; + image.StartItem = Items.Size(); RINOK(ParseDirItem(pos, parent)); + image.NumItems = Items.Size() - image.StartItem; 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) + /* Original program writes additional 8 bytes (END_OF_ROOT_FOLDER), + but the reference to that folder is empty */ + + // we can't use DirProcessed - DirStartOffset == 112 check if there is alt stream in root + if (DirProcessed == DirSize - 8 && Get64(p + DirSize - 8) == 0) return S_OK; return S_FALSE; } -HRESULT CHeader::Parse(const Byte *p) +HRESULT CHeader::Parse(const Byte *p, UInt64 &phySize) { UInt32 headerSize = Get32(p + 8); + phySize = headerSize; Version = Get32(p + 0x0C); Flags = Get32(p + 0x10); if (!IsSupported()) @@ -603,7 +651,7 @@ HRESULT CHeader::Parse(const Byte *p) ChunkSize = Get32(p + 0x14); if (ChunkSize != kChunkSize && ChunkSize != 0) return S_FALSE; - int offset; + unsigned offset; if (IsOldVersion()) { if (headerSize != 0x60) @@ -627,124 +675,190 @@ HRESULT CHeader::Parse(const Byte *p) offset += 4; } } - GetResource(p + offset, OffsetResource); - GetResource(p + offset + 0x18, XmlResource); - GetResource(p + offset + 0x30, MetadataResource); + GET_RESOURCE(p + offset , OffsetResource); + GET_RESOURCE(p + offset + 0x18, XmlResource); + GET_RESOURCE(p + offset + 0x30, MetadataResource); + BootIndex = 0; if (IsNewVersion()) { if (headerSize < 0xD0) return S_FALSE; - BootIndex = Get32(p + 0x48); - IntegrityResource.Parse(p + offset + 0x4C); + BootIndex = Get32(p + offset + 0x48); + GET_RESOURCE(p + offset + 0x4C, IntegrityResource); } + return S_OK; } const Byte kSignature[kSignatureSize] = { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 }; -HRESULT ReadHeader(IInStream *inStream, CHeader &h) +HRESULT ReadHeader(IInStream *inStream, CHeader &h, UInt64 &phySize) { Byte p[kHeaderSizeMax]; RINOK(ReadStream_FALSE(inStream, p, kHeaderSizeMax)); if (memcmp(p, kSignature, kSignatureSize) != 0) return S_FALSE; - return h.Parse(p); + return h.Parse(p, phySize); } -static HRESULT ReadStreams(bool oldVersion, IInStream *inStream, const CHeader &h, CDatabase &db) +static HRESULT ReadStreams(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) + size_t streamInfoSize = h.IsOldVersion() ? kStreamInfoSize + 2 : kStreamInfoSize; + for (i = 0; offsetBuf.Size() - i >= streamInfoSize; i += streamInfoSize) { CStreamInfo s; - GetStream(oldVersion, (const Byte *)offsetBuf + i, s); + GetStream(h.IsOldVersion(), (const Byte *)offsetBuf + i, s); if (s.PartNumber == h.PartNumber) - db.Streams.Add(s); + { + if (s.Resource.IsMetadata()) + { + if (s.RefCount == 0) + return S_FALSE; + if (s.RefCount > 1) + { + s.RefCount--; + db.DataStreams.Add(s); + } + s.RefCount = 1; + db.MetaStreams.Add(s); + } + else + db.DataStreams.Add(s); + } } - return (i == offsetBuf.GetCapacity()) ? S_OK : S_FALSE; + return (i == offsetBuf.Size()) ? S_OK : S_FALSE; } static bool IsEmptySha(const Byte *data) { - for (int i = 0; i < kHashSize; i++) + for (unsigned 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) +HRESULT CDatabase::OpenXml(IInStream *inStream, const CHeader &h, CByteBuffer &xml) +{ + return UnpackData(inStream, h.XmlResource, h.IsLzxMode(), xml, NULL); +} + +static void SetRootNames(CImage &image, unsigned value) +{ + wchar_t temp[16]; + ConvertUInt32ToString(value, temp); + image.RootName = temp; + image.RootNameBuf.Alloc(image.RootName.Len() * 2 + 2); + Byte *p = image.RootNameBuf; + unsigned len = image.RootName.Len() + 1; + for (unsigned k = 0; k < len; k++) + { + p[k * 2] = (Byte)temp[k]; + p[k * 2 + 1] = 0; + } +} + +HRESULT CDatabase::Open(IInStream *inStream, const CHeader &h, unsigned numItemsReserve, IArchiveOpenCallback *openCallback) { OpenCallback = openCallback; IsOldVersion = h.IsOldVersion(); - RINOK(UnpackData(inStream, h.XmlResource, h.IsLzxMode(), xml, NULL)); - RINOK(ReadStreams(h.IsOldVersion(), inStream, h, *this)); + RINOK(ReadStreams(inStream, h, *this)); + + // printf("\nh.PartNumber = %02d", (unsigned)h.PartNumber); bool needBootMetadata = !h.MetadataResource.IsEmpty(); - Order = 0; - if (h.PartNumber == 1) + + FOR_VECTOR (i, MetaStreams) { - int imageIndex = 1; - for (int i = 0; i < Streams.Size(); i++) + const CStreamInfo &si = MetaStreams[i]; + /* + printf("\ni = %5d" + " Refs = %3d" + " Part = %1d" + " Offs = %7X" + " PackSize = %7X" + " Size = %7X" + " Flags = %d " + , + i, + si.RefCount, + (unsigned)si.PartNumber, + (unsigned)si.Resource.Offset, + (unsigned)si.Resource.PackSize, + (unsigned)si.Resource.UnpackSize, + (unsigned)si.Resource.Flags + ); + for (unsigned y = 0; y < 2; y++) + printf("%02X", (unsigned)si.Hash[y]); + */ + + if (h.PartNumber != 1 || si.PartNumber != h.PartNumber) + continue; + + Byte hash[kHashSize]; + CImage &image = Images.AddNew(); + SetRootNames(image, Images.Size()); + CByteBuffer &metadata = image.Meta; + RINOK(UnpackData(inStream, si.Resource, h.IsLzxMode(), metadata, hash)); + if (memcmp(hash, si.Hash, kHashSize) != 0 && + !(h.IsOldVersion() && IsEmptySha(si.Hash))) + return S_FALSE; + image.NumEmptyRootItems = 0; + if (Items.IsEmpty()) + Items.ClearAndReserve(numItemsReserve); + RINOK(ParseImageDirs(metadata, -1)); + if (needBootMetadata) { - // 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; + bool sameRes = (h.MetadataResource.Offset == si.Resource.Offset); + if (sameRes) + needBootMetadata = false; + bool isBootIndex = (h.BootIndex == (UInt32)Images.Size()); + if (h.IsNewVersion()) + { + if (sameRes && !isBootIndex) + return S_FALSE; + if (isBootIndex && !sameRes) + return S_FALSE; + } } } if (needBootMetadata) - { - CByteBuffer metadata; - RINOK(UnpackData(inStream, h.MetadataResource, h.IsLzxMode(), metadata, NULL)); - RINOK(ParseImageDirs(metadata, -1)); - NumImages++; - } + return S_FALSE; return S_OK; } +#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } + 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); + RINOZ(MyCompare(p1->PartNumber, p2->PartNumber)); + RINOZ(MyCompare(p1->Resource.Offset, p2->Resource.Offset)); + return MyCompare(p1->Resource.PackSize, p2->Resource.PackSize); } -static int CompareIDs(const int *p1, const int *p2, void *param) +static int CompareIDs(const unsigned *p1, const unsigned *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) +static int CompareHashRefs(const unsigned *p1, const unsigned *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) + const CUIntVector &sortedByHash, UInt32 id) { - int left = 0, right = streams.Size(); + unsigned left = 0, right = streams.Size(); while (left != right) { - int mid = (left + right) / 2; - int streamIndex = sortedByHash[mid]; + unsigned mid = (left + right) / 2; + unsigned streamIndex = sortedByHash[mid]; UInt32 id2 = streams[streamIndex].Id; if (id == id2) return streamIndex; @@ -757,15 +871,15 @@ static int FindId(const CRecordVector &streams, } static int FindHash(const CRecordVector &streams, - const CIntVector &sortedByHash, const Byte *hash) + const CUIntVector &sortedByHash, const Byte *hash) { - int left = 0, right = streams.Size(); + unsigned left = 0, right = streams.Size(); while (left != right) { - int mid = (left + right) / 2; - int streamIndex = sortedByHash[mid]; - UInt32 i; + unsigned mid = (left + right) / 2; + unsigned streamIndex = sortedByHash[mid]; const Byte *hash2 = streams[streamIndex].Hash; + unsigned i; for (i = 0; i < kHashSize; i++) if (hash[i] != hash2[i]) break; @@ -779,77 +893,424 @@ static int FindHash(const CRecordVector &streams, return -1; } -static int CompareItems(const int *a1, const int *a2, void *param) +bool CDatabase::ItemHasStream(const CItem &item) const { - const CObjectVector &items = ((CDatabase *)param)->Items; + if (item.ImageIndex < 0) + return true; + const Byte *meta = Images[item.ImageIndex].Meta + item.Offset; + if (IsOldVersion) + { + // old wim use same field for file_id and dir_offset; + if (item.IsDir) + return false; + meta += (item.IsAltStream ? 0x8 : 0x10); + UInt32 id = GetUi32(meta); + return id != 0; + } + meta += (item.IsAltStream ? 0x10 : 0x40); + for (unsigned i = 0; i < kHashSize; i++) + if (meta[i] != 0) + return true; + return false; +} + +static int CompareItems(const unsigned *a1, const unsigned *a2, void *param) +{ + const CRecordVector &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); + if (i1.IsDir != i2.IsDir) + return i1.IsDir ? -1 : 1; + if (i1.IsAltStream != i2.IsAltStream) + return i1.IsAltStream ? 1 : -1; + RINOZ(MyCompare(i1.StreamIndex, i2.StreamIndex)); + RINOZ(MyCompare(i1.ImageIndex, i2.ImageIndex)); + return MyCompare(i1.Offset, i2.Offset); } -HRESULT CDatabase::Sort(bool skipRootDir) +HRESULT CDatabase::FillAndCheck() { - Streams.Sort(CompareStreamsByPos, NULL); - { - CIntVector sortedByHash; + DataStreams.Sort(CompareStreamsByPos, NULL); + for (unsigned i = 1; i < DataStreams.Size(); i++) + { + const CStreamInfo &s0 = DataStreams[i - 1]; + const CStreamInfo &s1 = DataStreams[i]; + if (s0.PartNumber == s1.PartNumber) + if (s0.Resource.GetEndLimit() > s1.Resource.Offset) + return S_FALSE; + } + } + + { + CUIntVector sortedByHash; { - for (int i = 0; i < Streams.Size(); i++) - sortedByHash.Add(i); + unsigned num = DataStreams.Size(); + sortedByHash.ClearAndSetSize(num); + unsigned *vals = &sortedByHash[0]; + for (unsigned i = 0; i < num; i++) + vals[i] = i; if (IsOldVersion) - sortedByHash.Sort(CompareIDs, &Streams); + sortedByHash.Sort(CompareIDs, &DataStreams); else - sortedByHash.Sort(CompareHashRefs, &Streams); + sortedByHash.Sort(CompareHashRefs, &DataStreams); } - for (int i = 0; i < Items.Size(); i++) + FOR_VECTOR (i, Items) { 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); + const Byte *hash = Images[item.ImageIndex].Meta + item.Offset; + if (IsOldVersion) + { + if (!item.IsDir) + { + hash += (item.IsAltStream ? 0x8 : 0x10); + UInt32 id = GetUi32(hash); + if (id != 0) + item.StreamIndex = FindId(DataStreams, sortedByHash, id); + } + } + /* + else if (item.IsDir) + { + // reparse points can have dirs some dir + } + */ + else + { + hash += (item.IsAltStream ? 0x10 : 0x40); + unsigned hi; + for (hi = 0; hi < kHashSize; hi++) + if (hash[hi] != 0) + break; + if (hi != kHashSize) + { + item.StreamIndex = FindHash(DataStreams, sortedByHash, hash); + } + } } } - { - CRecordVector used; - int i; - for (i = 0; i < Streams.Size(); i++) + CUIntVector refCounts; + refCounts.ClearAndSetSize(DataStreams.Size()); + unsigned i; + + for (i = 0; i < DataStreams.Size(); i++) { - const CStreamInfo &s = Streams[i]; - used.Add(s.Resource.IsMetadata() && s.PartNumber == 1); - // used.Add(false); + UInt32 startVal = 0; + // const CStreamInfo &s = DataStreams[i]; + /* + if (s.Resource.IsMetadata() && s.PartNumber == 1) + startVal = 1; + */ + refCounts[i] = startVal; } + for (i = 0; i < Items.Size(); i++) { - CItem &item = Items[i]; - if (item.StreamIndex >= 0) - used[item.StreamIndex] = true; + int streamIndex = Items[i].StreamIndex; + if (streamIndex >= 0) + refCounts[streamIndex]++; } - for (i = 0; i < Streams.Size(); i++) - if (!used[i]) + + for (i = 0; i < DataStreams.Size(); i++) + { + const CStreamInfo &s = DataStreams[i]; + if (s.RefCount != refCounts[i]) + { + /* + printf("\ni = %5d si.Refcount = %d realRefs = %d size = %6d offset = %6x id = %4d ", + i, s.RefCount, refCounts[i], (unsigned)s.Resource.UnpackSize, (unsigned)s.Resource.Offset, s.Id); + */ + // return S_FALSE; + RefCountError = true; + } + if (refCounts[i] == 0) { CItem item; + item.Offset = 0; item.StreamIndex = i; - item.HasMetadata = false; + item.ImageIndex = -1; + ThereAreDeletedStreams = true; Items.Add(item); } + } } + return S_OK; +} + +HRESULT CDatabase::GenerateSortedItems(int imageIndex, bool showImageNumber) +{ + SortedItems.Clear(); + VirtualRoots.Clear(); + IndexOfUserImage = imageIndex; + NumExludededItems = 0; + ExludedItem = -1; + + if (Images.Size() != 1 && imageIndex < 0) + showImageNumber = true; + + unsigned startItem = 0; + unsigned endItem = 0; + if (imageIndex < 0) + { + endItem = Items.Size(); + if (Images.Size() == 1) + { + IndexOfUserImage = 0; + const CImage &image = Images[0]; + if (!showImageNumber) + NumExludededItems = image.NumEmptyRootItems; + } + } + else if ((unsigned)imageIndex < Images.Size()) + { + const CImage &image = Images[imageIndex]; + startItem = image.StartItem; + endItem = startItem + image.NumItems; + if (!showImageNumber) + NumExludededItems = image.NumEmptyRootItems; + } + if (NumExludededItems != 0) + { + ExludedItem = startItem; + startItem += NumExludededItems; + } + + unsigned num = endItem - startItem; + SortedItems.ClearAndSetSize(num); + unsigned i; + for (i = 0; i < num; i++) + SortedItems[i] = startItem + i; - SortedItems.Reserve(Items.Size()); - for (int i = (skipRootDir ? 1 : 0); i < Items.Size(); i++) - SortedItems.Add(i); SortedItems.Sort(CompareItems, this); + for (i = 0; i < SortedItems.Size(); i++) + Items[SortedItems[i]].IndexInSorted = i; + + if (showImageNumber) + for (i = 0; i < Images.Size(); i++) + { + CImage &image = Images[i]; + if (image.NumEmptyRootItems != 0) + continue; + image.VirtualRootIndex = VirtualRoots.Size(); + VirtualRoots.Add(i); + } + return S_OK; +} + +static void IntVector_SetMinusOne_IfNeed(CIntVector &v, unsigned size) +{ + if (v.Size() == size) + return; + v.ClearAndSetSize(size); + int *vals = &v[0]; + for (unsigned i = 0; i < size; i++) + vals[i] = -1; +} + +HRESULT CDatabase::ExtractReparseStreams(const CObjectVector &volumes, IArchiveOpenCallback *openCallback) +{ + ItemToReparse.Clear(); + ReparseItems.Clear(); + + // we don't know about Reparse field for OLD WIM format + if (IsOldVersion) + return S_OK; + + CIntVector streamToReparse; + + FOR_VECTOR(i, Items) + { + // maybe it's better to use sorted items for faster access? + const CItem &item = Items[i]; + + if (!item.HasMetadata() || item.IsAltStream) + continue; + + if (item.ImageIndex < 0) + continue; + + const Byte *metadata = Images[item.ImageIndex].Meta + item.Offset; + + const UInt32 attrib = Get32(metadata + 8); + if ((attrib & FILE_ATTRIBUTE_REPARSE_POINT) == 0) + continue; + + if (item.StreamIndex < 0) + continue; // it's ERROR + + const CStreamInfo &si = DataStreams[item.StreamIndex]; + if (si.Resource.UnpackSize >= (1 << 16)) + continue; // reparse data can not be larger than 64 KB + + IntVector_SetMinusOne_IfNeed(streamToReparse, DataStreams.Size()); + IntVector_SetMinusOne_IfNeed(ItemToReparse, Items.Size()); + + const unsigned offset = 0x58; // we don't know about Reparse field for OLD WIM format + UInt32 tag = Get32(metadata + offset); + int reparseIndex = streamToReparse[item.StreamIndex]; + CByteBuffer buf; + + if (openCallback && (i & 0xFFFF) == 0) + { + UInt64 numFiles = Items.Size(); + RINOK(openCallback->SetCompleted(&numFiles, NULL)); + } + + if (reparseIndex >= 0) + { + const CByteBuffer &reparse = ReparseItems[reparseIndex]; + if (tag == Get32(reparse)) + { + ItemToReparse[i] = reparseIndex; + continue; + } + buf = reparse; + // we support that strange and unusual situation with different tags and same reparse data. + } + else + { + /* + if (si.PartNumber >= volumes.Size()) + continue; + */ + const CVolume &vol = volumes[si.PartNumber]; + /* + if (!vol.Stream) + continue; + */ + + Byte digest[kHashSize]; + HRESULT res = UnpackData(vol.Stream, si.Resource, vol.Header.IsLzxMode(), buf, digest); + + if (res == S_FALSE) + continue; + + RINOK(res); + + if (memcmp(digest, si.Hash, kHashSize) != 0 + // && !(h.IsOldVersion() && IsEmptySha(si.Hash)) + ) + { + // setErrorStatus; + continue; + } + } + + CByteBuffer &reparse = ReparseItems.AddNew(); + reparse.Alloc(8 + buf.Size()); + Byte *dest = (Byte *)reparse; + SetUi32(dest, tag); + SetUi32(dest + 4, (UInt32)buf.Size()); + memcpy(dest + 8, buf, buf.Size()); + ItemToReparse[i] = ReparseItems.Size() - 1; + } + return S_OK; } + + +static bool ParseNumber64(const AString &s, UInt64 &res) +{ + const char *end; + if (s.IsPrefixedBy("0x")) + { + if (s.Len() == 2) + return false; + res = ConvertHexStringToUInt64(s.Ptr(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; +} + +static 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); + + ParseNumber64(item.GetSubStringForTag("DIRCOUNT"), DirCount); + ParseNumber64(item.GetSubStringForTag("FILECOUNT"), FileCount); + IndexDefined = ParseNumber32(item.GetPropVal("INDEX"), Index); +} + +void CWimXml::ToUnicode(UString &s) +{ + size_t size = Data.Size(); + if (size < 2 || (size & 1) != 0 || size > (1 << 24)) + return; + const Byte *p = Data; + if (Get16(p) != 0xFEFF) + return; + wchar_t *chars = s.GetBuffer((unsigned)size / 2); + for (size_t i = 2; i < size; i += 2) + *chars++ = (wchar_t)Get16(p + i); + *chars = 0; + s.ReleaseBuffer(); +} + +bool CWimXml::Parse() +{ + UString s; + ToUnicode(s); + AString utf; + if (!ConvertUnicodeToUTF8(s, utf)) + return false; + if (!Xml.Parse(utf)) + return false; + if (Xml.Root.Name != "WIM") + return false; + + FOR_VECTOR (i, Xml.Root.SubItems) + { + const CXmlItem &item = Xml.Root.SubItems[i]; + if (item.IsTagged("IMAGE")) + { + CImageInfo imageInfo; + imageInfo.Parse(item); + if (!imageInfo.IndexDefined || imageInfo.Index != (UInt32)Images.Size() + 1) + return false; + imageInfo.ItemIndexInXml = i; + Images.Add(imageInfo); + } + } + return true; +} + }} diff --git a/CPP/7zip/Archive/Wim/WimIn.h b/CPP/7zip/Archive/Wim/WimIn.h old mode 100755 new mode 100644 index da3e28a5..4b7c6d95 --- a/CPP/7zip/Archive/Wim/WimIn.h +++ b/CPP/7zip/Archive/Wim/WimIn.h @@ -3,8 +3,10 @@ #ifndef __ARCHIVE_WIM_IN_H #define __ARCHIVE_WIM_IN_H -#include "Common/Buffer.h" -#include "Common/MyString.h" +#include "../../../Common/MyBuffer.h" +#include "../../../Common/MyXml.h" + +#include "../../../Windows/PropVariant.h" #include "../../Compress/CopyCoder.h" #include "../../Compress/LzxDecoder.h" @@ -14,6 +16,104 @@ namespace NArchive { namespace NWim { +const UInt32 kDirRecordSizeOld = 62; +const UInt32 kDirRecordSize = 102; + +/* + There is error in WIM specification about dwReparseTag, dwReparseReserved and liHardLink fields. + + Correct DIRENTRY structure: + { + hex offset + 0 UInt64 Len; + 8 UInt32 Attrib; + C UInt32 SecurityId; + + 10 UInt64 SubdirOffset; // = 0 for files + + 18 UInt64 unused1; // = 0? + 20 UInt64 unused2; // = 0? + + 28 UInt64 CTime; + 30 UInt64 ATime; + 38 UInt64 MTime; + + 40 Byte Sha1[20]; + + 54 UInt32 Unknown1; // is it 0 always? + + + union + { + 58 UInt64 NtNodeId; + { + 58 UInt32 ReparseTag; + 5C UInt32 ReparseFlags; // is it 0 always? Check with new imagex. + } + } + + 60 UInt16 Streams; + + 62 UInt16 ShortNameLen; + 64 UInt16 FileNameLen; + + 66 UInt16 Name[]; + UInt16 ShortName[]; + } + + // DIRENTRY for WIM_VERSION <= 1.10 + DIRENTRY_OLD structure: + { + hex offset + 0 UInt64 Len; + 8 UInt32 Attrib; + C UInt32 SecurityId; + + union + { + 10 UInt64 SubdirOffset; // + + 10 UInt32 OldWimFileId; // used for files in old WIMs + 14 UInt32 OldWimFileId_Reserved; // = 0 + } + + 18 UInt64 CTime; + 20 UInt64 ATime; + 28 UInt64 MTime; + + 30 UInt64 Unknown; // NtNodeId ? + + 38 UInt16 Streams; + 3A UInt16 ShortNameLen; + 3C UInt16 FileNameLen; + 3E UInt16 FileName[]; + UInt16 ShortName[]; + } + + ALT_STREAM structure: + { + hex offset + 0 UInt64 Len; + 8 UInt64 Unused; + 10 Byte Sha1[20]; + 24 UInt16 FileNameLen; + 26 UInt16 FileName[]; + } + + ALT_STREAM_OLD structure: + { + hex offset + 0 UInt64 Len; + 8 UInt64 StreamId; // 32-bit value + 10 UInt16 FileNameLen; + 12 UInt16 FileName[]; + } + + If item is file (not Directory) and there are alternative streams, + there is additional ALT_STREAM item of main "unnamed" stream in Streams array. + +*/ + namespace NXpress { class CBitStream @@ -24,7 +124,6 @@ class CBitStream 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; } @@ -74,11 +173,6 @@ class CDecoder 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); }; @@ -90,7 +184,7 @@ namespace NResourceFlags const Byte kFree = 1; const Byte kMetadata = 2; const Byte Compressed = 4; - const Byte Spanned = 4; + // const Byte Spanned = 4; } struct CResource @@ -107,7 +201,16 @@ struct CResource UnpackSize = 0; Flags = 0; } + UInt64 GetEndLimit() const { return Offset + PackSize; } void Parse(const Byte *p); + void ParseAndUpdatePhySize(const Byte *p, UInt64 &phySize) + { + Parse(p); + UInt64 v = GetEndLimit(); + if (phySize < v) + phySize = v; + } + void WriteTo(Byte *p) const; bool IsFree() const { return (Flags & NResourceFlags::kFree) != 0; } bool IsMetadata() const { return (Flags & NResourceFlags::kMetadata) != 0; } @@ -117,16 +220,21 @@ struct CResource namespace NHeaderFlags { - const UInt32 kCompression = 2; - const UInt32 kSpanned = 8; - const UInt32 kRpFix = 0x80; - const UInt32 kXPRESS = 0x20000; - const UInt32 kLZX = 0x40000; + const UInt32 kCompression = 2; + const UInt32 kReadOnly = 4; + const UInt32 kSpanned = 8; + const UInt32 kResourceOnly = 0x10; + const UInt32 kMetadataOnly = 0x20; + const UInt32 kWriteInProgress = 0x40; + const UInt32 kReparsePointFixup = 0x80; + const UInt32 kXPRESS = 0x20000; + const UInt32 kLZX = 0x40000; } const UInt32 kWimVersion = 0x010D00; -const UInt32 kHeaderSizeMax = 0xD0; -const UInt32 kSignatureSize = 8; + +const unsigned kHeaderSizeMax = 0xD0; +const unsigned kSignatureSize = 8; extern const Byte kSignature[kSignatureSize]; const unsigned kChunkSizeBits = 15; const UInt32 kChunkSize = (1 << kChunkSizeBits); @@ -150,7 +258,7 @@ struct CHeader void SetDefaultFields(bool useLZX); void WriteTo(Byte *p) const; - HRESULT Parse(const Byte *p); + HRESULT Parse(const Byte *p, UInt64 &phySize); 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; } @@ -164,115 +272,217 @@ struct CHeader } }; -const UInt32 kHashSize = 20; -const UInt32 kStreamInfoSize = 24 + 2 + 4 + kHashSize; +const unsigned kHashSize = 20; +const unsigned kStreamInfoSize = 24 + 2 + 4 + kHashSize; struct CStreamInfo { CResource Resource; - UInt16 PartNumber; + UInt16 PartNumber; // for NEW WIM format, we set it to 1 for OLD WIM format UInt32 RefCount; - UInt32 Id; - BYTE Hash[kHashSize]; + UInt32 Id; // for OLD WIM format + 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; + size_t Offset; + int IndexInSorted; 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 + int ImageIndex; // -1 means that file is unreferenced in Images (deleted item?) + bool IsDir; + bool IsAltStream; + + bool HasMetadata() const { return ImageIndex >= 0; } + + CItem(): + IndexInSorted(-1), + StreamIndex(-1), + Parent(-1), + IsDir(false), + IsAltStream(false) + {} +}; + +struct CImage +{ + CByteBuffer Meta; + CRecordVector SecurOffsets; + unsigned StartItem; + unsigned NumItems; + unsigned NumEmptyRootItems; + int VirtualRootIndex; // index in CDatabase::VirtualRoots[] + UString RootName; + CByteBuffer RootNameBuf; + + CImage(): VirtualRootIndex(-1) {} +}; + +struct CImageInfo +{ + bool CTimeDefined; + bool MTimeDefined; + bool NameDefined; + bool IndexDefined; + + FILETIME CTime; + FILETIME MTime; + UString Name; + + UInt64 DirCount; + UInt64 FileCount; + UInt32 Index; + + int ItemIndexInXml; + + UInt64 GetTotalFilesAndDirs() const { return DirCount + FileCount; } + + CImageInfo(): CTimeDefined(false), MTimeDefined(false), NameDefined(false), + IndexDefined(false), ItemIndexInXml(-1) {} + void Parse(const CXmlItem &item); +}; + +struct CWimXml +{ + CByteBuffer Data; + CXml Xml; + + UInt16 VolIndex; + CObjectVector Images; + + UString FileName; + + UInt64 GetTotalFilesAndDirs() const { - for (unsigned i = 0; i < kHashSize; i++) - if (Hash[i] != 0) - return true; - return Id != 0; + UInt64 sum = 0; + FOR_VECTOR (i, Images) + sum += Images[i].GetTotalFilesAndDirs(); + return sum; } + + void ToUnicode(UString &s); + bool Parse(); +}; + +struct CVolume +{ + CHeader Header; + CMyComPtr Stream; }; class CDatabase { - const Byte *DirData; + 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); + HRESULT ParseImageDirs(CByteBuffer &buf, int parent); public: - CRecordVector Streams; - CObjectVector Items; - CIntVector SortedItems; - int NumImages; - bool SkipRoot; - bool ShowImageNumber; + CRecordVector DataStreams; + + CRecordVector MetaStreams; + + CRecordVector Items; + CObjectVector ReparseItems; + CIntVector ItemToReparse; // from index_in_Items to index_in_ReparseItems + // -1 means no reparse; + + CObjectVector Images; + bool IsOldVersion; + bool ThereAreDeletedStreams; + bool ThereAreAltStreams; + bool RefCountError; + + // User Items can contain all images or just one image from all. + CUIntVector SortedItems; + int IndexOfUserImage; // -1 : if more than one images was filled to Sorted Items + + unsigned NumExludededItems; + int ExludedItem; // -1 : if there are no exclude items + CUIntVector VirtualRoots; // we use them for old 1.10 WIM archives + + bool ThereIsError() const { return RefCountError; } + + unsigned GetNumUserItemsInImage(unsigned imageIndex) const + { + if (IndexOfUserImage >= 0 && imageIndex != (unsigned)IndexOfUserImage) + return 0; + if (imageIndex >= Images.Size()) + return 0; + return Images[imageIndex].NumItems - NumExludededItems; + } + + bool ItemHasStream(const CItem &item) const; UInt64 GetUnpackSize() const { UInt64 res = 0; - for (int i = 0; i < Streams.Size(); i++) - res += Streams[i].Resource.UnpackSize; + FOR_VECTOR (i, DataStreams) + res += DataStreams[i].Resource.UnpackSize; return res; } UInt64 GetPackSize() const { UInt64 res = 0; - for (int i = 0; i < Streams.Size(); i++) - res += Streams[i].Resource.PackSize; + FOR_VECTOR (i, DataStreams) + res += DataStreams[i].Resource.PackSize; return res; } void Clear() { - Streams.Clear(); + DataStreams.Clear(); + + MetaStreams.Clear(); + Items.Clear(); + ReparseItems.Clear(); + ItemToReparse.Clear(); + SortedItems.Clear(); - NumImages = 0; + + Images.Clear(); + VirtualRoots.Clear(); - SkipRoot = true; - ShowImageNumber = true; IsOldVersion = false; + ThereAreDeletedStreams = false; + ThereAreAltStreams = false; + RefCountError = false; } - UString GetItemPath(int index) const; + CDatabase(): RefCountError(false) {} - HRESULT Open(IInStream *inStream, const CHeader &h, CByteBuffer &xml, IArchiveOpenCallback *openCallback); + void GetShortName(unsigned index, NWindows::NCOM::CPropVariant &res) const; + void GetItemName(unsigned index1, NWindows::NCOM::CPropVariant &res) const; + void GetItemPath(unsigned index, bool showImageNumber, NWindows::NCOM::CPropVariant &res) const; - void DetectPathMode() - { - ShowImageNumber = (NumImages != 1); - } + HRESULT OpenXml(IInStream *inStream, const CHeader &h, CByteBuffer &xml); + HRESULT Open(IInStream *inStream, const CHeader &h, unsigned numItemsReserve, IArchiveOpenCallback *openCallback); + HRESULT FillAndCheck(); - HRESULT Sort(bool skipRootDir); + /* + imageIndex showImageNumber NumImages + * true * Show Image_Number + -1 * >1 Show Image_Number + -1 false 1 Don't show Image_Number + N false * Don't show Image_Number + */ + HRESULT GenerateSortedItems(int imageIndex, bool showImageNumber); + + HRESULT ExtractReparseStreams(const CObjectVector &volumes, IArchiveOpenCallback *openCallback); }; -HRESULT ReadHeader(IInStream *inStream, CHeader &header); +HRESULT ReadHeader(IInStream *inStream, CHeader &header, UInt64 &phySize); class CUnpacker { @@ -285,6 +495,7 @@ class CUnpacker NXpress::CDecoder xpressDecoder; CByteBuffer sizesBuf; + HRESULT Unpack(IInStream *inStream, const CResource &res, bool lzxMode, ISequentialOutStream *outStream, ICompressProgressInfo *progress); public: diff --git a/CPP/7zip/Archive/Wim/WimRegister.cpp b/CPP/7zip/Archive/Wim/WimRegister.cpp old mode 100755 new mode 100644 index 8da91436..35d78314 --- a/CPP/7zip/Archive/Wim/WimRegister.cpp +++ b/CPP/7zip/Archive/Wim/WimRegister.cpp @@ -5,14 +5,23 @@ #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 + +namespace NArchive { +namespace NWim { + +IMP_CreateArcIn +IMP_CreateArcOut static CArcInfo g_ArcInfo = - { L"wim", L"wim swm", 0, 0xE6, { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 }, 8, false, CreateArc, CreateArcOut }; + { "wim", "wim swm", 0, 0xE6, + 8, { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 }, + 0, + NArcInfoFlags::kAltStreams | + NArcInfoFlags::kNtSecure | + NArcInfoFlags::kSymLinks | + NArcInfoFlags::kHardLinks + , REF_CreateArc_Pair }; REGISTER_ARC(Wim) + +}} diff --git a/CPP/7zip/Archive/XarHandler.cpp b/CPP/7zip/Archive/XarHandler.cpp old mode 100755 new mode 100644 index e7d88b6c..918ef736 --- a/CPP/7zip/Archive/XarHandler.cpp +++ b/CPP/7zip/Archive/XarHandler.cpp @@ -4,13 +4,13 @@ #include "../../../C/CpuArch.h" -#include "Common/ComTry.h" -#include "Common/MyXml.h" -#include "Common/StringToInt.h" -#include "Common/UTFConvert.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 "../../Windows/PropVariant.h" +#include "../../Windows/TimeUtils.h" #include "../Common/LimitedStreams.h" #include "../Common/ProgressUtils.h" @@ -24,6 +24,8 @@ #include "Common/OutStreamWithSha1.h" +using namespace NWindows; + #define XAR_SHOW_RAW #define Get16(p) GetBe16(p) @@ -33,6 +35,25 @@ namespace NArchive { namespace NXar { +static const UInt32 kXmlSizeMax = ((UInt32)1 << 30) - (1 << 14); +static const UInt32 kXmlPackSizeMax = kXmlSizeMax; + +/* +#define XAR_CKSUM_NONE 0 +#define XAR_CKSUM_SHA1 1 +#define XAR_CKSUM_MD5 2 + +static const char *k_ChecksumAlgos[] = +{ + "None" + , "SHA-1" + , "MD5" +}; +*/ + +#define METHOD_NAME_ZLIB "zlib" + + struct CFile { AString Name; @@ -41,125 +62,153 @@ struct CFile UInt64 PackSize; UInt64 Offset; - // UInt32 mode; UInt64 CTime; UInt64 MTime; UInt64 ATime; + UInt32 Mode; + + AString User; + AString Group; bool IsDir; bool HasData; - + bool ModeDefined; bool Sha1IsDefined; - Byte Sha1[20]; // bool packSha1IsDefined; - // Byte packSha1[20]; + + Byte Sha1[NCrypto::NSha1::kDigestSize]; + // Byte packSha1[NCrypto::NSha1::kDigestSize]; int Parent; - CFile(): IsDir(false), HasData(false), Sha1IsDefined(false), - /* packSha1IsDefined(false), */ - Parent(-1), Size(0), PackSize(0), CTime(0), MTime(0), ATime(0) {} + CFile(): IsDir(false), HasData(false), ModeDefined(false), Sha1IsDefined(false), + /* packSha1IsDefined(false), */ + Parent(-1), + Size(0), PackSize(0), Offset(0), + CTime(0), MTime(0), ATime(0), Mode(0) {} + + bool IsCopyMethod() const + { + return Method.IsEmpty() || Method == "octet-stream"; + } + + void UpdateTotalPackSize(UInt64 &totalSize) const + { + UInt64 t = Offset + PackSize; + if (totalSize < t) + totalSize = t; + } }; class CHandler: public IInArchive, + public IInArchiveGetStream, public CMyUnknownImp { UInt64 _dataStartPos; CMyComPtr _inStream; AString _xml; CObjectVector _files; + // UInt32 _checkSumAlgo; + UInt64 _phySize; + Int32 _mainSubfile; + bool _is_pkg; HRESULT Open2(IInStream *stream); HRESULT Extract(IInStream *stream); public: - MY_UNKNOWN_IMP1(IInArchive) + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); }; -const UInt32 kXmlSizeMax = ((UInt32)1 << 30) - (1 << 14); +static const Byte kArcProps[] = +{ + kpidSubType, + kpidHeadersSize +}; -STATPROPSTG kProps[] = +static const Byte 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} + kpidPath, + kpidSize, + kpidPackSize, + kpidMTime, + kpidCTime, + kpidATime, + kpidPosixAttrib, + kpidUser, + kpidGroup, + kpidMethod }; IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO +IMP_IInArchive_ArcProps -static bool ParseNumber(const char *s, int size, UInt32 &res) -{ - const char *end; - res = (UInt32)ConvertStringToUInt64(s, &end); - return (end - s == size); -} +#define PARSE_NUM(_num_, _dest_) \ + { const char *end; _dest_ = ConvertStringToUInt32(p, &end); \ + if ((unsigned)(end - p) != _num_) return 0; p += _num_ + 1; } static bool ParseUInt64(const CXmlItem &item, const char *name, UInt64 &res) { - AString s = item.GetSubStringForTag(name); + const AString s = item.GetSubStringForTag(name); + if (s.IsEmpty()) + return false; const char *end; res = ConvertStringToUInt64(s, &end); - return (end - (const char *)s == s.Length()); + return *end == 0; } static UInt64 ParseTime(const CXmlItem &item, const char *name) { - AString s = item.GetSubStringForTag(name); - if (s.Length() < 20) + const AString s = item.GetSubStringForTag(name); + if (s.Len() < 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; + PARSE_NUM(4, year) + PARSE_NUM(2, month) + PARSE_NUM(2, day) + PARSE_NUM(2, hour) + PARSE_NUM(2, min) + PARSE_NUM(2, sec) UInt64 numSecs; - if (!NWindows::NTime::GetSecondsSince1601(year, month, day, hour, min, sec, numSecs)) + if (!NTime::GetSecondsSince1601(year, month, day, hour, min, sec, numSecs)) return 0; return numSecs * 10000000; } -static bool HexToByte(char c, Byte &res) +static int HexToByte(char c) { - 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; + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'A' && c <= 'F') return c - 'A' + 10; + if (c >= 'a' && c <= 'f') return c - 'a' + 10; + return -1; } -#define METHOD_NAME_ZLIB "zlib" - static bool ParseSha1(const CXmlItem &item, const char *name, Byte *digest) { int index = item.FindSubTag(name); - if (index < 0) + if (index < 0) return false; const CXmlItem &checkItem = item.SubItems[index]; - AString style = checkItem.GetPropertyValue("style"); + const AString style = checkItem.GetPropVal("style"); if (style == "SHA1") { - AString s = checkItem.GetSubString(); - if (s.Length() != 40) + const AString s = checkItem.GetSubString(); + if (s.Len() != NCrypto::NSha1::kDigestSize * 2) return false; - for (int i = 0; i < s.Length(); i += 2) + for (unsigned i = 0; i < s.Len(); i += 2) { - Byte b0, b1; - if (!HexToByte(s[i], b0) || !HexToByte(s[i + 1], b1)) + int b0 = HexToByte(s[i]); + int b1 = HexToByte(s[i + 1]); + if (b0 < 0 || b1 < 0) return false; - digest[i / 2] = (b0 << 4) | b1; + digest[i / 2] = (Byte)((b0 << 4) | b1); } return true; } @@ -203,17 +252,17 @@ static bool AddItem(const CXmlItem &item, CObjectVector &files, int paren const CXmlItem &encodingItem = dataItem.SubItems[encodingIndex]; if (encodingItem.IsTag) { - AString s = encodingItem.GetPropertyValue("style"); - if (s.Length() >= 0) + AString s = encodingItem.GetPropVal("style"); + if (s.Len() >= 0) { AString appl = "application/"; - if (s.Left(appl.Length()) == appl) + if (s.IsPrefixedBy(appl)) { - s = s.Mid(appl.Length()); + s.DeleteFrontal(appl.Len()); AString xx = "x-"; - if (s.Left(xx.Length()) == xx) + if (s.IsPrefixedBy(xx)) { - s = s.Mid(xx.Length()); + s.DeleteFrontal(xx.Len()); if (s == "gzip") s = METHOD_NAME_ZLIB; } @@ -227,9 +276,23 @@ static bool AddItem(const CXmlItem &item, CObjectVector &files, int paren file.CTime = ParseTime(item, "ctime"); file.MTime = ParseTime(item, "mtime"); file.ATime = ParseTime(item, "atime"); + + { + const AString s = item.GetSubStringForTag("mode"); + if (s[0] == '0') + { + const char *end; + file.Mode = ConvertOctStringToUInt32(s, &end); + file.ModeDefined = (*end == 0); + } + } + + file.User = item.GetSubStringForTag("user"); + file.Group = item.GetSubStringForTag("group"); + files.Add(file); } - for (int i = 0; i < item.SubItems.Size(); i++) + FOR_VECTOR (i, item.SubItems) if (!AddItem(item.SubItems[i], files, parent)) return false; return true; @@ -237,28 +300,28 @@ static bool AddItem(const CXmlItem &item, CObjectVector &files, int paren 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 + // UInt32 ver = Get16(buf + 6); // == 1 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) + // _checkSumAlgo = Get32(buf + 0x18); + + if (packSize >= kXmlPackSizeMax || + unpackSize >= kXmlSizeMax) return S_FALSE; - _dataStartPos = archiveStartPos + kHeaderSize + packSize; + _dataStartPos = kHeaderSize + packSize; + _phySize = _dataStartPos; - char *ss = _xml.GetBuffer((int)unpackSize + 1); + char *ss = _xml.GetBuffer((unsigned)unpackSize); NCompress::NZlib::CDecoder *zlibCoderSpec = new NCompress::NZlib::CDecoder(); CMyComPtr zlibCoder = zlibCoderSpec; @@ -291,6 +354,19 @@ HRESULT CHandler::Open2(IInStream *stream) return S_FALSE; if (!AddItem(toc, _files, -1)) return S_FALSE; + + UInt64 totalPackSize = 0; + FOR_VECTOR(i, _files) + { + const CFile &file = _files[i]; + file.UpdateTotalPackSize(totalPackSize); + if (file.Name == "Payload") + _mainSubfile = i; + if (file.Name == "PackageInfo") + _is_pkg = true; + } + _phySize = _dataStartPos + totalPackSize; + return S_OK; } @@ -311,9 +387,12 @@ STDMETHODIMP CHandler::Open(IInStream *stream, STDMETHODIMP CHandler::Close() { + _phySize = 0; _inStream.Release(); _files.Clear(); _xml.Empty(); + _mainSubfile = -1; + _is_pkg = false; return S_OK; } @@ -327,7 +406,7 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) return S_OK; } -static void TimeToProp(UInt64 t, NWindows::NCOM::CPropVariant &prop) +static void TimeToProp(UInt64 t, NCOM::CPropVariant &prop) { if (t != 0) { @@ -338,34 +417,56 @@ static void TimeToProp(UInt64 t, NWindows::NCOM::CPropVariant &prop) } } +static void Utf8StringToProp(const AString &s, NCOM::CPropVariant &prop) +{ + if (!s.IsEmpty()) + { + UString us; + if (ConvertUTF8ToUnicode(s, us)) + prop = us; + } +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NCOM::CPropVariant prop; + switch (propID) + { + case kpidHeadersSize: prop = _dataStartPos; break; + case kpidPhySize: prop = _phySize; break; + case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break; + case kpidSubType: if (_is_pkg) prop = "pkg"; break; + case kpidExtension: prop = _is_pkg ? "pkg" : "xar"; 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; + NCOM::CPropVariant prop; #ifdef XAR_SHOW_RAW - if ((int)index == _files.Size()) + if (index == _files.Size()) { - switch(propID) + switch (propID) { - case kpidPath: prop = L"[TOC].xml"; break; + case kpidPath: prop = "[TOC].xml"; break; case kpidSize: - case kpidPackSize: prop = (UInt64)_xml.Length(); break; + case kpidPackSize: prop = (UInt64)_xml.Len(); break; } } else #endif { const CFile &item = _files[index]; - switch(propID) + switch (propID) { - case kpidMethod: - { - UString name; - if (!item.Method.IsEmpty() && ConvertUTF8ToUnicode(item.Method, name)) - prop = name; - break; - } + case kpidMethod: Utf8StringToProp(item.Method, prop); break; + case kpidPath: { AString path; @@ -373,30 +474,40 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val do { const CFile &item = _files[cur]; - AString s = item.Name; - if (s.IsEmpty()) - s = "unknown"; - if (path.IsEmpty()) - path = s; + if (!path.IsEmpty()) + path.InsertAtFront(CHAR_PATH_SEPARATOR); + if (item.Name.IsEmpty()) + path.Insert(0, "unknown"); else - path = s + CHAR_PATH_SEPARATOR + path; + path.Insert(0, item.Name); cur = item.Parent; } while (cur >= 0); - UString name; - if (ConvertUTF8ToUnicode(path, name)) - prop = name; + Utf8StringToProp(path, prop); 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 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; + case kpidMTime: TimeToProp(item.MTime, prop); break; + case kpidCTime: TimeToProp(item.CTime, prop); break; + case kpidATime: TimeToProp(item.ATime, prop); break; + case kpidPosixAttrib: + if (item.ModeDefined) + { + UInt32 mode = item.Mode; + const UInt32 k_PosixAttrib_Dir = (1 << 14); + const UInt32 k_PosixAttrib_RegFile = (1 << 15); + if ((mode & 0xF000) == 0) + mode |= (item.IsDir ? k_PosixAttrib_Dir : k_PosixAttrib_RegFile); + prop = mode; + } + break; + case kpidUser: Utf8StringToProp(item.User, prop); break; + case kpidGroup: Utf8StringToProp(item.Group, prop); break; } } prop.Detach(value); @@ -408,7 +519,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _files.Size(); if (numItems == 0) @@ -417,10 +528,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, UInt32 i; for (i = 0; i < numItems; i++) { - int index = (int)(allFilesMode ? i : indices[i]); + UInt32 index = (allFilesMode ? i : indices[i]); #ifdef XAR_SHOW_RAW if (index == _files.Size()) - totalSize += _xml.Length(); + totalSize += _xml.Len(); else #endif totalSize += _files[index].Size; @@ -433,8 +544,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, UInt64 currentUnpSize = 0; const UInt32 kZeroBufSize = (1 << 14); - CByteBuffer zeroBuf; - zeroBuf.SetCapacity(kZeroBufSize); + CByteBuffer zeroBuf(kZeroBufSize); memset(zeroBuf, 0, kZeroBufSize); NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); @@ -478,7 +588,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 askMode = testMode ? NExtract::NAskMode::kTest : NExtract::NAskMode::kExtract; - Int32 index = allFilesMode ? i : indices[i]; + UInt32 index = allFilesMode ? i : indices[i]; RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); if (index < _files.Size()) @@ -504,9 +614,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (index == _files.Size()) { outStreamSha1Spec->Init(false); - outStreamLimSpec->Init(_xml.Length()); - RINOK(WriteStream(outStream, (const char *)_xml, _xml.Length())); - currentPackSize = currentUnpSize = _xml.Length(); + outStreamLimSpec->Init(_xml.Len()); + RINOK(WriteStream(outStream, (const char *)_xml, _xml.Len())); + currentPackSize = currentUnpSize = _xml.Len(); } else #endif @@ -524,17 +634,17 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, HRESULT res = S_OK; ICompressCoder *coder = NULL; - if (item.Method.IsEmpty() || item.Method == "octet-stream") + if (item.IsCopyMethod()) if (item.PackSize == item.Size) coder = copyCoder; else - opRes = NExtract::NOperationResult::kUnSupportedMethod; + 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; + opRes = NExtract::NOperationResult::kUnsupportedMethod; if (coder) res = coder->Code(inStream, outStream, NULL, NULL, progress); @@ -578,10 +688,35 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_END } -static IInArchive *CreateArc() { return new NArchive::NXar::CHandler; } +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + *stream = NULL; + COM_TRY_BEGIN + #ifdef XAR_SHOW_RAW + if (index == _files.Size()) + { + Create_BufInStream_WithNewBuf((const void *)(const char *)_xml, _xml.Len(), stream); + return S_OK; + } + else + #endif + { + const CFile &item = _files[index]; + if (item.HasData && item.IsCopyMethod() && item.PackSize == item.Size) + return CreateLimitedInStream(_inStream, _dataStartPos + item.Offset, item.Size, stream); + } + return S_FALSE; + COM_TRY_END +} + +IMP_CreateArcIn static CArcInfo g_ArcInfo = - { L"Xar", L"xar", 0, 0xE1, { 'x', 'a', 'r', '!', 0, 0x1C }, 6, false, CreateArc, 0 }; + { "Xar", "xar pkg", 0, 0xE1, + 6, { 'x', 'a', 'r', '!', 0, 0x1C }, + 0, + 0, + CreateArc }; REGISTER_ARC(Xar) diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp old mode 100755 new mode 100644 index 8383488b..0de58a44 --- a/CPP/7zip/Archive/XzHandler.cpp +++ b/CPP/7zip/Archive/XzHandler.cpp @@ -7,8 +7,8 @@ #include "../../../C/XzEnc.h" #include "../../Common/ComTry.h" +#include "../../Common/Defs.h" #include "../../Common/IntToString.h" -#include "../../Common/StringConvert.h" #include "../ICoder.h" @@ -43,6 +43,81 @@ struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit; static const wchar_t *k_LZMA2_Name = L"LZMA2"; +struct CStatInfo +{ + UInt64 InSize; + UInt64 OutSize; + UInt64 PhySize; + + UInt64 NumStreams; + UInt64 NumBlocks; + + bool UnpackSize_Defined; + + bool NumStreams_Defined; + bool NumBlocks_Defined; + + bool IsArc; + bool UnexpectedEnd; + bool DataAfterEnd; + bool Unsupported; + bool HeadersError; + bool DataError; + bool CrcError; + + CStatInfo() { Clear(); } + + void Clear() + { + InSize = 0; + OutSize = 0; + PhySize = 0; + + NumStreams = 0; + NumBlocks = 0; + + UnpackSize_Defined = false; + + NumStreams_Defined = false; + NumBlocks_Defined = false; + + UnexpectedEnd = false; + DataAfterEnd = false; + Unsupported = false; + HeadersError = false; + DataError = false; + CrcError = false; + IsArc = false; + } + +}; + +struct IDecodeState: public CStatInfo +{ + SRes DecodeRes; + + IDecodeState(): DecodeRes(SZ_OK) {} + virtual HRESULT Progress() = 0; + + HRESULT Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream); +}; + +struct CVirtProgress_To_LocalProgress: public IDecodeState +{ + CLocalProgress *lps; + CMyComPtr progress; + + HRESULT Progress(); +}; + +HRESULT CVirtProgress_To_LocalProgress::Progress() +{ + lps->InSize = InSize; + lps->OutSize = OutSize; + return lps->SetCur(); +} + + class CHandler: public IInArchive, public IArchiveOpenSeq, @@ -53,19 +128,17 @@ class CHandler: #endif public CMyUnknownImp { - Int64 _startPosition; - UInt64 _packSize; - UInt64 _unpackSize; - UInt64 _numBlocks; - AString _methodsString; - bool _useSeq; - UInt64 _unpackSizeDefined; - UInt64 _packSizeDefined; + CStatInfo _stat; + + bool _isArc; + bool _needSeekToStart; + bool _phySize_Defined; CMyComPtr _stream; CMyComPtr _seqStream; UInt32 _filterId; + AString _methodsString; void Init() { @@ -73,7 +146,15 @@ class CHandler: CMultiMethodProps::Init(); } - HRESULT Open2(IInStream *inStream, IArchiveOpenCallback *callback); + HRESULT Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback); + + HRESULT Decode2(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, IDecodeState &progress) + { + RINOK(progress.Decode(seqInStream, outStream)); + _stat = progress; + _phySize_Defined = true; + return S_OK; + } public: MY_QUERYINTERFACE_BEGIN2(IInArchive) @@ -90,7 +171,7 @@ public: #ifndef EXTRACT_ONLY INTERFACE_IOutArchive(;) - STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps); + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); #endif CHandler(); @@ -101,60 +182,60 @@ CHandler::CHandler() Init(); } -static STATPROPSTG const kProps[] = +static const Byte kProps[] = { - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, - { NULL, kpidMethod, VT_BSTR} + kpidSize, + kpidPackSize, + kpidMethod }; -static STATPROPSTG const kArcProps[] = +static const Byte kArcProps[] = { - { NULL, kpidMethod, VT_BSTR}, - { NULL, kpidNumBlocks, VT_UI4} + kpidMethod, + kpidNumStreams, + kpidNumBlocks }; IMP_IInArchive_Props IMP_IInArchive_ArcProps -static char GetHex(Byte value) +static inline char GetHex(unsigned value) { return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); } -static inline void AddHexToString(AString &res, Byte value) +static inline void AddHexToString(AString &s, Byte value) { - res += GetHex((Byte)(value >> 4)); - res += GetHex((Byte)(value & 0xF)); + s += GetHex(value >> 4); + s += GetHex(value & 0xF); } -static AString ConvertUInt32ToString(UInt32 value) +static void AddUInt32ToString(AString &s, UInt32 value) { - char temp[32]; - ::ConvertUInt32ToString(value, temp); - return temp; + char temp[16]; + ConvertUInt32ToString(value, temp); + s += temp; } -static AString Lzma2PropToString(int prop) +static void Lzma2PropToString(AString &s, unsigned prop) { + char c = 0; + UInt32 size; 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'; - } + size = prop / 2 + 12; else { - res = ConvertUInt32ToString(size); c = 'k'; + size = (UInt32)(2 | (prop & 1)) << (prop / 2 + 1); + if (prop > 17) + { + size >>= 10; + c = 'm'; + } } - return res + c; + AddUInt32ToString(s, size); + if (c != 0) + s += c; } struct CMethodNamePair @@ -178,25 +259,29 @@ static const CMethodNamePair g_NamePairs[] = static AString GetMethodString(const CXzFilter &f) { - AString s; - - for (int i = 0; i < sizeof(g_NamePairs) / sizeof(g_NamePairs[i]); i++) + const char *p = NULL; + for (unsigned i = 0; i < ARRAY_SIZE(g_NamePairs); i++) if (g_NamePairs[i].Id == f.id) - s = g_NamePairs[i].Name; - if (s.IsEmpty()) + { + p = g_NamePairs[i].Name; + break; + } + char temp[32]; + if (!p) { - char temp[32]; ::ConvertUInt64ToString(f.id, temp); - s = temp; + p = temp; } + AString s = p; + if (f.propsSize > 0) { s += ':'; if (f.id == XZ_ID_LZMA2 && f.propsSize == 1) - s += Lzma2PropToString(f.props[0]); + Lzma2PropToString(s, f.props[0]); else if (f.id == XZ_ID_Delta && f.propsSize == 1) - s += ConvertUInt32ToString((UInt32)f.props[0] + 1); + AddUInt32ToString(s, (UInt32)f.props[0] + 1); else { s += '['; @@ -217,22 +302,22 @@ static void AddString(AString &dest, const AString &src) static const char *kChecks[] = { - "NoCheck", - "CRC32", - NULL, - NULL, - "CRC64", - NULL, - NULL, - NULL, - NULL, - NULL, - "SHA256", - NULL, - NULL, - NULL, - NULL, - NULL + "NoCheck" + , "CRC32" + , NULL + , NULL + , "CRC64" + , NULL + , NULL + , NULL + , NULL + , NULL + , "SHA256" + , NULL + , NULL + , NULL + , NULL + , NULL }; static AString GetCheckString(const CXzs &xzs) @@ -249,7 +334,10 @@ static AString GetCheckString(const CXzs &xzs) if (kChecks[i]) s2 = kChecks[i]; else - s2 = "Check-" + ConvertUInt32ToString((UInt32)i); + { + s2 = "Check-"; + AddUInt32ToString(s2, (UInt32)i); + } AddString(s, s2); } return s; @@ -258,12 +346,26 @@ static AString GetCheckString(const CXzs &xzs) STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; - switch(propID) + NCOM::CPropVariant prop; + switch (propID) { - case kpidNumBlocks: if (!_useSeq) prop = _numBlocks; break; - case kpidPhySize: if (_packSizeDefined) prop = _packSize; break; + case kpidPhySize: if (_phySize_Defined) prop = _stat.PhySize; break; + case kpidNumStreams: if (_stat.NumStreams_Defined) prop = _stat.NumStreams; break; + case kpidNumBlocks: if (_stat.NumBlocks_Defined) prop = _stat.NumBlocks; break; + case kpidUnpackSize: if (_stat.UnpackSize_Defined) prop = _stat.OutSize; break; case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break; + case kpidErrorFlags: + { + UInt32 v = 0; + if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;; + if (_stat.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd; + if (_stat.DataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd; + if (_stat.HeadersError) v |= kpv_ErrorFlags_HeadersError; + if (_stat.Unsupported) v |= kpv_ErrorFlags_UnsupportedMethod; + if (_stat.DataError) v |= kpv_ErrorFlags_DataError; + if (_stat.CrcError) v |= kpv_ErrorFlags_CrcError; + prop = v; + } } prop.Detach(value); return S_OK; @@ -276,14 +378,14 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) return S_OK; } -STDMETHODIMP CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value) +STDMETHODIMP CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; - switch(propID) + NCOM::CPropVariant prop; + switch (propID) { - case kpidSize: if (_unpackSizeDefined) prop = _unpackSize; break; - case kpidPackSize: if (_packSizeDefined) prop = _packSize; break; + case kpidSize: if (_stat.UnpackSize_Defined) prop = _stat.OutSize; break; + case kpidPackSize: if (_phySize_Defined) prop = _stat.PhySize; break; case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break; } prop.Detach(value); @@ -321,82 +423,124 @@ struct CXzsCPP ~CXzsCPP() { Xzs_Free(&p, &g_Alloc); } }; -HRESULT CHandler::Open2(IInStream *inStream, IArchiveOpenCallback *callback) + +struct CVirtProgress_To_OpenProgress: public IDecodeState { - CSeekInStreamWrap inStreamImp(inStream); + IArchiveOpenCallback *Callback; + UInt64 Offset; - CLookToRead lookStream; - LookToRead_CreateVTable(&lookStream, True); - lookStream.realStream = &inStreamImp.p; - LookToRead_Init(&lookStream); + HRESULT Progress(); +}; - COpenCallbackWrap openWrap(callback); - RINOK(inStream->Seek(0, STREAM_SEEK_END, &_packSize)); - RINOK(callback->SetTotal(NULL, &_packSize)); +HRESULT CVirtProgress_To_OpenProgress::Progress() +{ + if (Callback) + { + UInt64 files = 0; + UInt64 value = Offset + InSize; + return Callback->SetCompleted(&files, &value); + } + return S_OK; +} - 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) +static HRESULT SRes_to_Open_HRESULT(SRes res) +{ + switch (res) { - _packSize -= _startPosition; - _unpackSize = Xzs_GetUnpackSize(&xzs.p); - _unpackSizeDefined = _packSizeDefined = true; - _numBlocks = (UInt64)Xzs_GetNumBlocks(&xzs.p); + case SZ_OK: return S_OK; + case SZ_ERROR_MEM: return E_OUTOFMEMORY; + case SZ_ERROR_PROGRESS: return E_ABORT; + /* + case SZ_ERROR_UNSUPPORTED: + case SZ_ERROR_CRC: + case SZ_ERROR_DATA: + case SZ_ERROR_ARCHIVE: + case SZ_ERROR_NO_ARCHIVE: + return S_FALSE; + */ + } + return S_FALSE; +} - RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); +HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback) +{ + _needSeekToStart = true; + + { CXzStreamFlags st; CSeqInStreamWrap inStreamWrap(inStream); - SRes res2 = Xz_ReadHeader(&st, &inStreamWrap.p); + SRes res = Xz_ReadHeader(&st, &inStreamWrap.p); + if (res != SZ_OK) + return SRes_to_Open_HRESULT(res); - if (res2 == SZ_OK) { CXzBlock block; Bool isIndex; UInt32 headerSizeRes; - res2 = XzBlock_ReadHeader(&block, &inStreamWrap.p, &isIndex, &headerSizeRes); + SRes 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++) + unsigned numFilters = XzBlock_GetNumFilters(&block); + for (unsigned 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_END, &_stat.PhySize)); + RINOK(callback->SetTotal(NULL, &_stat.PhySize)); + + CSeekInStreamWrap inStreamImp(inStream); + + CLookToRead lookStream; + LookToRead_CreateVTable(&lookStream, True); + lookStream.realStream = &inStreamImp.p; + LookToRead_Init(&lookStream); + + COpenCallbackWrap openWrap(callback); + + CXzsCPP xzs; + Int64 startPosition; + SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.s, &startPosition, &openWrap.p, &g_Alloc); + if (res == SZ_ERROR_PROGRESS) + return (openWrap.Res == S_OK) ? E_FAIL : openWrap.Res; + /* + if (res == SZ_ERROR_NO_ARCHIVE && xzs.p.num > 0) + res = SZ_OK; + */ + if (res == SZ_OK && startPosition == 0) { - 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; - } + _phySize_Defined = true; + + _stat.OutSize = Xzs_GetUnpackSize(&xzs.p); + _stat.UnpackSize_Defined = true; + + _stat.NumStreams = xzs.p.num; + _stat.NumStreams_Defined = true; + + _stat.NumBlocks = Xzs_GetNumBlocks(&xzs.p); + _stat.NumBlocks_Defined = true; + + AddString(_methodsString, GetCheckString(xzs.p)); + } + else + { + res = SZ_OK; } - if (res == SZ_ERROR_NO_ARCHIVE) - return S_FALSE; - RINOK(SResToHRESULT(res)); + RINOK(SRes_to_Open_HRESULT(res)); _stream = inStream; _seqStream = inStream; + _isArc = true; return S_OK; } STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback) { COM_TRY_BEGIN - try { Close(); - return Open2(inStream, callback); + return Open2(inStream, /* 0, */ callback); } - catch(...) { return S_FALSE; } COM_TRY_END } @@ -404,15 +548,21 @@ STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) { Close(); _seqStream = stream; + _isArc = true; + _needSeekToStart = false; return S_OK; } STDMETHODIMP CHandler::Close() { - _numBlocks = 0; - _useSeq = true; - _unpackSizeDefined = _packSizeDefined = false; - _methodsString.Empty(); + _stat.Clear(); + + _isArc = false; + _needSeekToStart = false; + + _phySize_Defined = false; + + _methodsString.Empty(); _stream.Release(); _seqStream.Release(); return S_OK; @@ -442,6 +592,7 @@ struct CXzUnpackerCPP Byte *InBuf; Byte *OutBuf; CXzUnpacker p; + CXzUnpackerCPP(): InBuf(0), OutBuf(0) { XzUnpacker_Construct(&p, &g_Alloc); @@ -454,129 +605,193 @@ struct CXzUnpackerCPP } }; -STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, - Int32 testMode, IArchiveExtractCallback *extractCallback) +HRESULT IDecodeState::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream) { - 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); + const size_t kInBufSize = 1 << 15; + const size_t kOutBufSize = 1 << 21; - SRes res = S_OK; + DecodeRes = SZ_OK; - const UInt32 kInBufSize = 1 << 15; - const UInt32 kOutBufSize = 1 << 21; - - UInt32 inPos = 0; - UInt32 inSize = 0; - UInt32 outPos = 0; CXzUnpackerCPP xzu; XzUnpacker_Init(&xzu.p); - { - 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) + xzu.InBuf = (Byte *)MyAlloc(kInBufSize); + xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize); + if (!xzu.InBuf || !xzu.OutBuf) + return E_OUTOFMEMORY; + + UInt32 inSize = 0; + SizeT inPos = 0; + SizeT outPos = 0; + for (;;) { if (inPos == inSize) { inPos = inSize = 0; - RINOK(_seqStream->Read(xzu.InBuf, kInBufSize, &inSize)); + RINOK(seqInStream->Read(xzu.InBuf, kInBufSize, &inSize)); } SizeT inLen = inSize - inPos; SizeT outLen = kOutBufSize - outPos; ECoderStatus status; - res = XzUnpacker_Code(&xzu.p, + + SRes 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 += inLen; + outPos += outLen; + + InSize += inLen; + OutSize += outLen; - inPos += (UInt32)inLen; - outPos += (UInt32)outLen; - lps->InSize += inLen; - lps->OutSize += outLen; + DecodeRes = res; - bool finished = (((inLen == 0) && (outLen == 0)) || res != SZ_OK); + bool finished = ((inLen == 0 && outLen == 0) || res != SZ_OK); - if (outPos == kOutBufSize || finished) + if (outStream) { - if (realOutStream && outPos > 0) + if (outPos == kOutBufSize || finished) { - RINOK(WriteStream(realOutStream, xzu.OutBuf, outPos)); + if (outPos != 0) + { + RINOK(WriteStream(outStream, xzu.OutBuf, outPos)); + outPos = 0; + } } - outPos = 0; } - RINOK(lps->SetCur()); + else + outPos = 0; + + RINOK(Progress()); + if (finished) { - _packSize = lps->InSize; - _unpackSize = lps->OutSize; - _packSizeDefined = _unpackSizeDefined = true; + PhySize = InSize; + NumStreams = xzu.p.numStartedStreams; + if (NumStreams > 0) + IsArc = true; + NumBlocks = xzu.p.numTotalBlocks; + + UnpackSize_Defined = true; + NumStreams_Defined = true; + NumBlocks_Defined = true; + + UInt64 extraSize = XzUnpacker_GetExtraSize(&xzu.p); + if (res == SZ_OK) { if (status == CODER_STATUS_NEEDS_MORE_INPUT) { - if (XzUnpacker_IsStreamWasFinished(&xzu.p)) - _packSize -= xzu.p.padSize; - else + extraSize = 0; + if (!XzUnpacker_IsStreamWasFinished(&xzu.p)) + { + // finished at padding bytes, but padding is not aligned for 4 + UnexpectedEnd = true; res = SZ_ERROR_DATA; + } } - else + else // status == CODER_STATUS_NOT_FINISHED res = SZ_ERROR_DATA; } + else if (res == SZ_ERROR_NO_ARCHIVE) + { + if (InSize == extraSize) + IsArc = false; + else + { + if (extraSize != 0 || inPos != inSize) + { + DataAfterEnd = true; + res = SZ_OK; + } + } + } + + DecodeRes = res; + PhySize -= extraSize; + + switch (res) + { + case SZ_OK: break; + case SZ_ERROR_NO_ARCHIVE: IsArc = false; break; + case SZ_ERROR_ARCHIVE: HeadersError = true; break; + case SZ_ERROR_UNSUPPORTED: Unsupported = true; break; + case SZ_ERROR_CRC: CrcError = true; break; + case SZ_ERROR_DATA: DataError = true; break; + default: DataError = true; break; + } + break; } } - Int32 opRes; - switch(res) + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + if (numItems == 0) + return S_OK; + if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) + return E_INVALIDARG; + + extractCallback->SetTotal(_stat.PhySize); + 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); + + CVirtProgress_To_LocalProgress vp; + vp.lps = new CLocalProgress; + vp.progress = vp.lps; + vp.lps->Init(extractCallback, true); + + + if (_needSeekToStart) { - 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); + if (!_stream) + return E_FAIL; + RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL)); } + else + _needSeekToStart = true; + + RINOK(Decode2(_seqStream, realOutStream, vp)); + + Int32 opRes; + + if (!vp.IsArc) + opRes = NExtract::NOperationResult::kIsNotArc; + else if (vp.UnexpectedEnd) + opRes = NExtract::NOperationResult::kUnexpectedEnd; + else if (vp.DataAfterEnd) + opRes = NExtract::NOperationResult::kDataAfterEnd; + else if (vp.CrcError) + opRes = NExtract::NOperationResult::kCRCError; + else if (vp.Unsupported) + opRes = NExtract::NOperationResult::kUnsupportedMethod; + else if (vp.HeadersError) + opRes = NExtract::NOperationResult::kDataError; + else if (vp.DataError) + opRes = NExtract::NOperationResult::kDataError; + else if (vp.DecodeRes != SZ_OK) + opRes = NExtract::NOperationResult::kDataError; + else + opRes = NExtract::NOperationResult::kOK; + realOutStream.Release(); return extractCallback->SetOperationResult(opRes); COM_TRY_END @@ -648,7 +863,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt RINOK(NCompress::NLzma2::SetLzma2Prop(NCoderPropID::kReduceSize, prop, lzma2Props)); } - for (int i = 0; i < _methods.Size(); i++) + FOR_VECTOR (i, _methods) { COneMethodInfo &m = _methods[i]; SetGlobalLevelAndThreads(m @@ -657,7 +872,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt #endif ); { - for (int j = 0; j < m.Props.Size(); j++) + FOR_VECTOR (j, m.Props) { const CProp &prop = m.Props[j]; RINOK(NCompress::NLzma2::SetLzma2Prop(prop.Id, prop.Value, lzma2Props)); @@ -692,7 +907,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (_filterId == XZ_ID_Delta) { bool deltaDefined = false; - for (int j = 0; j < _filterMethod.Props.Size(); j++) + FOR_VECTOR (j, _filterMethod.Props) { const CProp &prop = _filterMethod.Props[j]; if (prop.Id == NCoderPropID::kDefaultProp && prop.Value.vt == VT_UI4) @@ -715,29 +930,26 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (indexInArchive != 0) return E_INVALIDARG; if (_stream) - RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); - return NCompress::CopyStream(_stream, outStream, 0); + RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL)); + return NCompress::CopyStream(_stream, outStream, NULL); } -#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) - -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) { COM_TRY_BEGIN Init(); - for (int i = 0; i < numProps; i++) + for (UInt32 i = 0; i < numProps; i++) { RINOK(SetProperty(names[i], values[i])); } if (!_filterMethod.MethodName.IsEmpty()) { - int k; + unsigned k; for (k = 0; k < ARRAY_SIZE(g_NamePairs); k++) { const CMethodNamePair &pair = g_NamePairs[k]; - UString m = GetUnicodeString(pair.Name); - if (_filterMethod.MethodName.CompareNoCase(m) == 0) + if (StringsAreEqualNoCase_Ascii(_filterMethod.MethodName, pair.Name)) { _filterId = pair.Id; break; @@ -747,8 +959,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v return E_INVALIDARG; } - int numEmptyMethods = GetNumEmptyMethods(); - _methods.Delete(0, numEmptyMethods); + _methods.DeleteFrontal(GetNumEmptyMethods()); if (_methods.Size() > 1) return E_INVALIDARG; if (_methods.Size() == 1) @@ -756,7 +967,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v UString &methodName = _methods[0].MethodName; if (methodName.IsEmpty()) methodName = k_LZMA2_Name; - else if (methodName.CompareNoCase(k_LZMA2_Name) != 0) + else if (!methodName.IsEqualToNoCase(k_LZMA2_Name)) return E_INVALIDARG; } return S_OK; @@ -765,15 +976,15 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v #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 +IMP_CreateArcIn +IMP_CreateArcOut static CArcInfo g_ArcInfo = - { L"xz", L"xz txz", L"* .tar", 0xC, {0xFD, '7' , 'z', 'X', 'Z', '\0'}, 6, true, CreateArc, CreateArcOut }; + { "xz", "xz txz", "* .tar", 0xC, + 6, { 0xFD, '7' , 'z', 'X', 'Z', 0 }, + 0, + NArcInfoFlags::kKeepName, + REF_CreateArc_Pair }; REGISTER_ARC(xz) diff --git a/CPP/7zip/Archive/ZHandler.cpp b/CPP/7zip/Archive/ZHandler.cpp old mode 100755 new mode 100644 index 49b76a11..459f3e35 --- a/CPP/7zip/Archive/ZHandler.cpp +++ b/CPP/7zip/Archive/ZHandler.cpp @@ -2,9 +2,9 @@ #include "StdAfx.h" -#include "Common/ComTry.h" +#include "../../Common/ComTry.h" -#include "Windows/PropVariant.h" +#include "../../Windows/PropVariant.h" #include "../Common/ProgressUtils.h" #include "../Common/RegisterArc.h" @@ -22,21 +22,21 @@ class CHandler: public CMyUnknownImp { CMyComPtr _stream; - UInt64 _streamStartPosition; UInt64 _packSize; - Byte _properties; + // UInt64 _unpackSize; + // bool _unpackSize_Defined; public: MY_UNKNOWN_IMP1(IInArchive) INTERFACE_IInArchive(;) }; -STATPROPSTG kProps[] = +static const Byte kProps[] = { - { NULL, kpidPackSize, VT_UI8} + kpidPackSize }; IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO +IMP_IInArchive_ArcProps_NO_Table STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { @@ -44,36 +44,110 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) return S_OK; } -STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { NWindows::NCOM::CPropVariant prop; - switch(propID) + switch (propID) { + case kpidPhySizeCantBeDetected: prop = true; break; + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +{ + NWindows::NCOM::CPropVariant prop; + switch (propID) + { + // case kpidSize: if (_unpackSize_Defined) prop = _unpackSize; break; case kpidPackSize: prop = _packSize; break; } prop.Detach(value); return S_OK; } -static const int kSignatureSize = 3; +/* +class CCompressProgressInfoImp: + public ICompressProgressInfo, + public CMyUnknownImp +{ + CMyComPtr Callback; +public: + MY_UNKNOWN_IMP1(ICompressProgressInfo) + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); + void Init(IArchiveOpenCallback *callback) { Callback = callback; } +}; + +STDMETHODIMP CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) +{ + if (Callback) + { + UInt64 files = 1; + return Callback->SetCompleted(&files, inSize); + } + return S_OK; +} +*/ + +API_FUNC_static_IsArc IsArc_Z(const Byte *p, size_t size) +{ + if (size < 3) + return k_IsArc_Res_NEED_MORE; + if (size > NCompress::NZ::kRecommendedCheckSize) + size = NCompress::NZ::kRecommendedCheckSize; + if (!NCompress::NZ::CheckStream(p, size)) + return k_IsArc_Res_NO; + return k_IsArc_Res_YES; +} STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * /* maxCheckStartPosition */, - IArchiveOpenCallback * /* openArchiveCallback */) + IArchiveOpenCallback * /* openCallback */) { 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) + // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_streamStartPosition)); + Byte buffer[NCompress::NZ::kRecommendedCheckSize]; + // Byte buffer[1500]; + size_t size = NCompress::NZ::kRecommendedCheckSize; + // size = 700; + RINOK(ReadStream(stream, buffer, &size)); + if (!NCompress::NZ::CheckStream(buffer, size)) return S_FALSE; - _properties = buffer[2]; - UInt64 endPosition; - RINOK(stream->Seek(0, STREAM_SEEK_END, &endPosition)); - _packSize = endPosition - _streamStartPosition - kSignatureSize; - + UInt64 endPos; + RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos)); + _packSize = endPos; + + /* + bool fullCheck = false; + if (fullCheck) + { + CCompressProgressInfoImp *compressProgressSpec = new CCompressProgressInfoImp; + CMyComPtr compressProgress = compressProgressSpec; + compressProgressSpec->Init(openCallback); + + NCompress::NZ::CDecoder *decoderSpec = new NCompress::NZ::CDecoder; + CMyComPtr decoder = decoderSpec; + + CDummyOutStream *outStreamSpec = new CDummyOutStream; + CMyComPtr outStream(outStreamSpec); + outStreamSpec->SetStream(NULL); + outStreamSpec->Init(); + decoderSpec->SetProp(_prop); + if (openCallback) + { + UInt64 files = 1; + RINOK(openCallback->SetTotal(&files, &endPos)); + } + RINOK(stream->Seek(_streamStartPosition + kSignatureSize, STREAM_SEEK_SET, NULL)); + HRESULT res = decoder->Code(stream, outStream, NULL, NULL, openCallback ? compressProgress : NULL); + if (res != S_OK) + return S_FALSE; + _packSize = decoderSpec->PackSize; + } + */ _stream = stream; } return S_OK; @@ -82,6 +156,8 @@ STDMETHODIMP CHandler::Open(IInStream *stream, STDMETHODIMP CHandler::Close() { + _packSize = 0; + // _unpackSize_Defined = false; _stream.Release(); return S_OK; } @@ -93,7 +169,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_BEGIN if (numItems == 0) return S_OK; - if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0)) + if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) return E_INVALIDARG; extractCallback->SetTotal(_packSize); @@ -124,37 +200,37 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CMyComPtr progress = lps; lps->Init(extractCallback, true); - RINOK(_stream->Seek(_streamStartPosition + kSignatureSize, STREAM_SEEK_SET, NULL)); + RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL)); - CMyComPtr decoder; NCompress::NZ::CDecoder *decoderSpec = new NCompress::NZ::CDecoder; - decoder = decoderSpec; - - HRESULT result = decoderSpec->SetDecoderProperties2(&_properties, 1); + CMyComPtr decoder = decoderSpec; - int opResult; - if (result != S_OK) - opResult = NExtract::NOperationResult::kUnSupportedMethod; - else + int opRes; { - result = decoder->Code(_stream, outStream, NULL, NULL, progress); + HRESULT result = decoder->Code(_stream, outStream, NULL, NULL, progress); if (result == S_FALSE) - opResult = NExtract::NOperationResult::kDataError; + opRes = NExtract::NOperationResult::kDataError; else { RINOK(result); - opResult = NExtract::NOperationResult::kOK; + opRes = NExtract::NOperationResult::kOK; } } + // _unpackSize = outStreamSpec->GetSize(); + // _unpackSize_Defined = true; outStream.Release(); - return extractCallback->SetOperationResult(opResult); + return extractCallback->SetOperationResult(opRes); COM_TRY_END } -static IInArchive *CreateArc() { return new CHandler; } +IMP_CreateArcIn static CArcInfo g_ArcInfo = - { L"Z", L"z taz", L"* .tar", 5, { 0x1F, 0x9D }, 2, false, CreateArc, 0 }; + { "Z", "z taz", "* .tar", 5, + 2, { 0x1F, 0x9D }, + 0, + 0, + CreateArc, NULL, IsArc_Z }; REGISTER_ARC(Z) diff --git a/CPP/7zip/Archive/Zip/StdAfx.h b/CPP/7zip/Archive/Zip/StdAfx.h old mode 100755 new mode 100644 index e7fb6986..2854ff3e --- a/CPP/7zip/Archive/Zip/StdAfx.h +++ b/CPP/7zip/Archive/Zip/StdAfx.h @@ -3,6 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" +#include "../../../Common/Common.h" #endif diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp old mode 100755 new mode 100644 index f77e4f23..9a0d7515 --- a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp +++ b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp @@ -4,7 +4,7 @@ #include "../../../../C/7zCrc.h" -#include "Windows/PropVariant.h" +#include "../../../Windows/PropVariant.h" #include "../../ICoder.h" #include "../../IPassword.h" @@ -85,18 +85,18 @@ CAddCommon::CAddCommon(const CCompressionMethodMode &options): static HRESULT GetStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC) { UInt32 crc = CRC_INIT_VAL; - const UInt32 kBufferSize = (1 << 14); - Byte buffer[kBufferSize]; + const UInt32 kBufSize = (1 << 14); + Byte buf[kBufSize]; for (;;) { - UInt32 realProcessedSize; - RINOK(inStream->Read(buffer, kBufferSize, &realProcessedSize)); - if (realProcessedSize == 0) + UInt32 processed; + RINOK(inStream->Read(buf, kBufSize, &processed)); + if (processed == 0) { resultCRC = CRC_GET_DIGEST(crc); return S_OK; } - crc = CrcUpdate(crc, buffer, (size_t)realProcessedSize); + crc = CrcUpdate(crc, buf, (size_t)processed); } } @@ -105,8 +105,14 @@ HRESULT CAddCommon::Compress( ISequentialInStream *inStream, IOutStream *outStream, ICompressProgressInfo *progress, CCompressingResult &opRes) { - CSequentialInStreamWithCRC *inSecCrcStreamSpec = 0; - CInStreamWithCRC *inCrcStreamSpec = 0; + if (!inStream) + { + // We can create empty stream here. But it was already implemented in caller code in 9.33+ + return E_INVALIDARG; + } + + CSequentialInStreamWithCRC *inSecCrcStreamSpec = NULL; + CInStreamWithCRC *inCrcStreamSpec = NULL; CMyComPtr inCrcStream; { CMyComPtr inStream2; @@ -128,26 +134,30 @@ HRESULT CAddCommon::Compress( } } - int numTestMethods = _options.MethodSequence.Size(); + unsigned numTestMethods = _options.MethodSequence.Size(); + if (numTestMethods > 1 || _options.PasswordIsDefined) { - if (inCrcStreamSpec == 0) + if (!inCrcStreamSpec) { 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++) + + for (unsigned i = 0; i < numTestMethods; i++) { opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Default; - if (inCrcStreamSpec != 0) + if (inCrcStreamSpec) 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; @@ -157,6 +167,7 @@ HRESULT CAddCommon::Compress( _cryptoStreamSpec = new CFilterCoder; _cryptoStream = _cryptoStreamSpec; } + if (_options.IsAesMode) { opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Aes; @@ -164,7 +175,7 @@ HRESULT CAddCommon::Compress( { _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->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Len())); } RINOK(_filterAesSpec->WriteHeader(outStream)); } @@ -173,19 +184,21 @@ HRESULT CAddCommon::Compress( if (!_cryptoStreamSpec->Filter) { _cryptoStreamSpec->Filter = _filterSpec = new NCrypto::NZip::CEncoder; - _filterSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Length()); + _filterSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Len()); } UInt32 crc = 0; RINOK(GetStreamCRC(inStream, crc)); RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL)); RINOK(_filterSpec->WriteHeader(outStream, crc)); } + RINOK(_cryptoStreamSpec->SetOutStream(outStream)); outStreamReleaser.FilterCoder = _cryptoStreamSpec; } method = _options.MethodSequence[i]; - switch(method) + + switch (method) { case NFileHeader::NCompressionMethod::kStored: { @@ -202,6 +215,7 @@ HRESULT CAddCommon::Compress( RINOK(_copyCoder->Code(inCrcStream, outStreamNew, NULL, NULL, progress)); break; } + default: { if (!_compressEncoder) @@ -272,7 +286,7 @@ HRESULT CAddCommon::Compress( RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &opRes.PackSize)); - if (inCrcStreamSpec != 0) + if (inCrcStreamSpec) { opRes.CRC = inCrcStreamSpec->GetCRC(); opRes.UnpackSize = inCrcStreamSpec->GetSize(); @@ -292,6 +306,7 @@ HRESULT CAddCommon::Compress( else if (opRes.PackSize < opRes.UnpackSize) break; } + if (_options.PasswordIsDefined && _options.IsAesMode) { RINOK(_filterAesSpec->WriteFooter(outStream)); diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.h b/CPP/7zip/Archive/Zip/ZipAddCommon.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Archive/Zip/ZipCompressionMode.h b/CPP/7zip/Archive/Zip/ZipCompressionMode.h old mode 100755 new mode 100644 index 893daaab..86548d95 --- a/CPP/7zip/Archive/Zip/ZipCompressionMode.h +++ b/CPP/7zip/Archive/Zip/ZipCompressionMode.h @@ -3,7 +3,7 @@ #ifndef __ZIP_COMPRESSION_MODE_H #define __ZIP_COMPRESSION_MODE_H -#include "Common/MyString.h" +#include "../../../Common/MyString.h" #ifndef _7ZIP_ST #include "../../../Windows/System.h" diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp old mode 100755 new mode 100644 index 2281ed5b..f556068c --- a/CPP/7zip/Archive/Zip/ZipHandler.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp @@ -2,11 +2,11 @@ #include "StdAfx.h" -#include "Common/ComTry.h" -#include "Common/IntToString.h" +#include "../../../Common/ComTry.h" +#include "../../../Common/IntToString.h" -#include "Windows/PropVariant.h" -#include "Windows/Time.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/TimeUtils.h" #include "../../IPassword.h" @@ -40,98 +40,112 @@ 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" + "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" + "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 const char *kMethod_AES = "AES"; +static const char *kMethod_ZipCrypto = "ZipCrypto"; +static const char *kMethod_StrongCrypto = "StrongCrypto"; -static struct CStrongCryptoPair +struct CIdToNamePair { - UInt16 Id; + unsigned Id; const char *Name; -} g_StrongCryptoPairs[] = +}; + +static const CIdToNamePair k_MethodIdNamePairs[] = +{ + { NFileHeader::NCompressionMethod::kBZip2, "BZip2" }, + { NFileHeader::NCompressionMethod::kLZMA, "LZMA" }, + { NFileHeader::NCompressionMethod::kJpeg, "Jpeg" }, + { NFileHeader::NCompressionMethod::kWavPack, "WavPack" }, + { NFileHeader::NCompressionMethod::kPPMd, "PPMd" } +}; + +static const CIdToNamePair k_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" } + { NStrongCrypto_AlgId::kDES, "DES" }, + { NStrongCrypto_AlgId::kRC2old, "RC2a" }, + { NStrongCrypto_AlgId::k3DES168, "3DES-168" }, + { NStrongCrypto_AlgId::k3DES112, "3DES-112" }, + { NStrongCrypto_AlgId::kAES128, "pkAES-128" }, + { NStrongCrypto_AlgId::kAES192, "pkAES-192" }, + { NStrongCrypto_AlgId::kAES256, "pkAES-256" }, + { NStrongCrypto_AlgId::kRC2, "RC2" }, + { NStrongCrypto_AlgId::kBlowfish, "Blowfish" }, + { NStrongCrypto_AlgId::kTwofish, "Twofish" }, + { NStrongCrypto_AlgId::kRC4, "RC4" } }; -static const STATPROPSTG kProps[] = +const char *FindNameForId(const CIdToNamePair *pairs, unsigned num, unsigned id) +{ + for (unsigned i = 0; i < num; i++) + { + const CIdToNamePair &pair = pairs[i]; + if (id == pair.Id) + return pair.Name; + } + return NULL; +} + +static const Byte 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, kpidPosixAttrib, 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} + kpidPath, + kpidIsDir, + kpidSize, + kpidPackSize, + kpidMTime, + kpidCTime, + kpidATime, + kpidAttrib, + // kpidPosixAttrib, + kpidEncrypted, + kpidComment, + kpidCRC, + kpidMethod, + kpidHostOS, + kpidUnpackVer }; -static const STATPROPSTG kArcProps[] = +static const Byte kArcProps[] = { - { NULL, kpidBit64, VT_BOOL}, - { NULL, kpidComment, VT_BSTR}, - { NULL, kpidPhySize, VT_UI8}, - { NULL, kpidOffset, VT_UI8} + kpidEmbeddedStubSize, + kpidBit64, + kpidComment }; CHandler::CHandler() @@ -142,12 +156,12 @@ CHandler::CHandler() static AString BytesToString(const CByteBuffer &data) { AString s; - int size = (int)data.GetCapacity(); + unsigned size = (unsigned)data.Size(); if (size > 0) { - char *p = s.GetBuffer(size + 1); + char *p = s.GetBuffer(size); memcpy(p, (const Byte *)data, size); - p[size] = '\0'; + p[size] = 0; s.ReleaseBuffer(); } return s; @@ -160,13 +174,52 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NWindows::NCOM::CPropVariant prop; - switch(propID) + 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 kpidComment: if (m_Archive.ArcInfo.Comment.Size() != 0) 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; - case kpidError: if (!m_Archive.IsOkHeaders) prop = "Incorrect headers"; break; + case kpidOffset: /* if (m_Archive.ArcInfo.Base != 0) */ + prop = m_Archive.ArcInfo.Base; break; + + case kpidEmbeddedStubSize: + { + UInt64 stubSize = m_Archive.ArcInfo.GetEmbeddedStubSize(); + if (stubSize != 0) + prop = stubSize; + break; + } + + case kpidWarningFlags: + { + UInt32 v = 0; + // if (m_Archive.ExtraMinorError) v |= kpv_ErrorFlags_HeadersError; + if (m_Archive.HeadersWarning) v |= kpv_ErrorFlags_HeadersError; + if (v != 0) + prop = v; + break; + } + + case kpidErrorFlags: + { + UInt32 v = 0; + if (!m_Archive.IsArc) v |= kpv_ErrorFlags_IsNotArc; + if (m_Archive.HeadersError) v |= kpv_ErrorFlags_HeadersError; + if (m_Archive.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd; + if (m_Archive.ArcInfo.Base < 0) + { + /* We try to support case when we have sfx-zip with embedded stub, + but the stream has access only to zip part. + In that case we ignore UnavailableStart error. + maybe we must show warning in that case. */ + UInt64 stubSize = m_Archive.ArcInfo.GetEmbeddedStubSize(); + if (stubSize < (UInt64)-m_Archive.ArcInfo.Base) + v |= kpv_ErrorFlags_UnavailableStart; + } + if (m_Archive.NoCentralDir) v |= kpv_ErrorFlags_UnconfirmedStart; + prop = v; + break; + } } prop.Detach(value); COM_TRY_END @@ -184,24 +237,36 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val COM_TRY_BEGIN NWindows::NCOM::CPropVariant prop; const CItemEx &item = m_Items[index]; - switch(propID) + switch (propID) { - case kpidPath: prop = NItemName::GetOSName2(item.GetUnicodeString(item.Name)); break; + case kpidPath: + { + UString res; + item.GetUnicodeString(item.Name, res, _forceCodePage, _specifiedCodePage); + NItemName::ConvertToOSName2(res); + prop = res; + break; + } + case kpidIsDir: prop = item.IsDir(); break; - case kpidSize: prop = item.UnPackSize; break; + case kpidSize: prop = item.Size; break; case kpidPackSize: prop = item.PackSize; break; + case kpidTimeType: { FILETIME ft; UInt32 unixTime; + UInt32 type; if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, ft)) - prop = (UInt32)NFileTimeType::kWindows; + type = NFileTimeType::kWindows; else if (item.CentralExtra.GetUnixTime(true, NFileHeader::NUnixTime::kMTime, unixTime)) - prop = (UInt32)NFileTimeType::kUnix; + type = NFileTimeType::kUnix; else - prop = (UInt32)NFileTimeType::kDOS; + type = NFileTimeType::kDOS; + prop = type; break; } + case kpidCTime: { FILETIME ft; @@ -209,6 +274,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val prop = ft; break; } + case kpidATime: { FILETIME ft; @@ -216,26 +282,33 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val prop = ft; break; } + case kpidMTime: { FILETIME utc; + bool defined = true; if (!item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, utc)) { - UInt32 unixTime; + UInt32 unixTime = 0; if (item.CentralExtra.GetUnixTime(true, NFileHeader::NUnixTime::kMTime, unixTime)) NTime::UnixTimeToFileTime(unixTime, utc); else { FILETIME localFileTime; - if (!NTime::DosTimeToFileTime(item.Time, localFileTime) || + if (item.Time == 0) + defined = false; + else if (!NTime::DosTimeToFileTime(item.Time, localFileTime) || !LocalFileTimeToFileTime(&localFileTime, &utc)) utc.dwHighDateTime = utc.dwLowDateTime = 0; } } - prop = utc; + if (defined) + prop = utc; break; } + case kpidAttrib: prop = item.GetWinAttrib(); break; + case kpidPosixAttrib: { UInt32 attrib; @@ -243,83 +316,107 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val prop = attrib; 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 kpidComment: + { + if (item.Comment.Size() != 0) + { + UString res; + item.GetUnicodeString(BytesToString(item.Comment), res, _forceCodePage, _specifiedCodePage); + prop = res; + } + break; + } + + case kpidCRC: if (item.IsThereCrc()) prop = item.Crc; break; + case kpidMethod: { - UInt16 methodId = item.CompressionMethod; - AString method; + UInt16 methodId = item.Method; + AString m; + if (item.IsEncrypted()) { if (methodId == NFileHeader::NCompressionMethod::kWzAES) { - method = kAESMethod; - CWzAesExtraField aesField; - if (item.CentralExtra.GetWzAesField(aesField)) + m += kMethod_AES; + CWzAesExtra aesField; + if (item.CentralExtra.GetWzAes(aesField)) { - method += '-'; - char s[32]; - ConvertUInt64ToString((aesField.Strength + 1) * 64 , s); - method += s; - method += ' '; + char s[16]; + s[0] = '-'; + ConvertUInt32ToString(((unsigned)aesField.Strength + 1) * 64 , s + 1); + m += s; methodId = aesField.Method; } } - else + else if (item.IsStrongEncrypted()) { - if (item.IsStrongEncrypted()) + CStrongCryptoExtra f; + f.AlgId = 0; + if (item.CentralExtra.GetStrongCrypto(f)) { - CStrongCryptoField f; - bool finded = false; - if (item.CentralExtra.GetStrongCryptoField(f)) + const char *s = FindNameForId(k_StrongCryptoPairs, ARRAY_SIZE(k_StrongCryptoPairs), f.AlgId); + if (s) + m += s; + else { - 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; - } - } + m += kMethod_StrongCrypto; + char temp[16]; + temp[0] = ':'; + ConvertUInt32ToString(f.AlgId, temp + 1); + m += temp; } - if (!finded) - method += kStrongCryptoMethod; } else - method += kZipCryptoMethod; - method += ' '; + m += kMethod_StrongCrypto; } + else + m += kMethod_ZipCrypto; + m += ' '; } - 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 temp[16]; + const char *s = NULL; + if (methodId < ARRAY_SIZE(kMethods)) + s = kMethods[methodId]; + else { - char s[32]; - ConvertUInt64ToString(methodId, s); - method += s; + s = FindNameForId(k_MethodIdNamePairs, ARRAY_SIZE(k_MethodIdNamePairs), methodId); + if (!s) + { + ConvertUInt32ToString(methodId, temp); + s = temp; + } } + m += s; + if (methodId == NFileHeader::NCompressionMethod::kLZMA && item.IsLzmaEOS()) + m += ":EOS"; } - prop = method; + + prop = m; break; } + case kpidHostOS: - prop = (item.MadeByVersion.HostOS < sizeof(kHostOS) / sizeof(kHostOS[0])) ? - (kHostOS[item.MadeByVersion.HostOS]) : kUnknownOS; + { + Byte hostOS = item.GetHostOS(); + char temp[16]; + const char *s = NULL; + if (hostOS < ARRAY_SIZE(kHostOS)) + s = kHostOS[hostOS]; + else + { + ConvertUInt32ToString(hostOS, temp); + s = temp; + } + prop = s; break; + } + case kpidUnpackVer: prop = (UInt32)item.ExtractVersion.Version; break; @@ -333,23 +430,25 @@ class CProgressImp: public CProgressVirt { CMyComPtr _callback; public: - STDMETHOD(SetTotal)(UInt64 numFiles); - STDMETHOD(SetCompleted)(UInt64 numFiles); + virtual HRESULT SetCompletedLocal(UInt64 numFiles, UInt64 numBytes); + virtual HRESULT SetTotalCD(UInt64 numFiles); + virtual HRESULT SetCompletedCD(UInt64 numFiles); CProgressImp(IArchiveOpenCallback *callback): _callback(callback) {} }; -STDMETHODIMP CProgressImp::SetTotal(UInt64 numFiles) +HRESULT CProgressImp::SetCompletedLocal(UInt64 numFiles, UInt64 numBytes) { - if (_callback) - return _callback->SetTotal(&numFiles, NULL); - return S_OK; + return _callback->SetCompleted(&numFiles, &numBytes); } -STDMETHODIMP CProgressImp::SetCompleted(UInt64 numFiles) +HRESULT CProgressImp::SetTotalCD(UInt64 numFiles) { - if (_callback) - return _callback->SetCompleted(&numFiles, NULL); - return S_OK; + return _callback->SetTotal(&numFiles, NULL); +} + +HRESULT CProgressImp::SetCompletedCD(UInt64 numFiles) +{ + return _callback->SetCompleted(&numFiles, NULL); } STDMETHODIMP CHandler::Open(IInStream *inStream, @@ -359,12 +458,10 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, 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); + return m_Archive.ReadHeaders(m_Items, callback ? &progressImp : NULL); } - catch(const CInArchiveException &) { Close(); return S_FALSE; } catch(...) { Close(); throw; } COM_TRY_END } @@ -467,26 +564,26 @@ HRESULT CZipDecoder::Decode( bool needCRC = true; bool wzAesMode = false; bool pkAesMode = false; - UInt16 methodId = item.CompressionMethod; + UInt16 methodId = item.Method; if (item.IsEncrypted()) { if (item.IsStrongEncrypted()) { - CStrongCryptoField f; - if (item.CentralExtra.GetStrongCryptoField(f)) + CStrongCryptoExtra f; + if (item.CentralExtra.GetStrongCrypto(f)) { pkAesMode = true; } if (!pkAesMode) { - res = NExtract::NOperationResult::kUnSupportedMethod; + res = NExtract::NOperationResult::kUnsupportedMethod; return S_OK; } } - if (methodId == NFileHeader::NCompressionMethod::kWzAES) + if (!pkAesMode && methodId == NFileHeader::NCompressionMethod::kWzAES) { - CWzAesExtraField aesField; - if (item.CentralExtra.GetWzAesField(aesField)) + CWzAesExtra aesField; + if (item.CentralExtra.GetWzAes(aesField)) { wzAesMode = true; needCRC = aesField.NeedCrc(); @@ -520,8 +617,8 @@ HRESULT CZipDecoder::Decode( { if (wzAesMode) { - CWzAesExtraField aesField; - if (!item.CentralExtra.GetWzAesField(aesField)) + CWzAesExtra aesField; + if (!item.CentralExtra.GetWzAes(aesField)) return S_OK; methodId = aesField.Method; if (!_wzAesDecoder) @@ -562,31 +659,35 @@ HRESULT CZipDecoder::Decode( CMyComBSTR password; RINOK(getTextPassword->CryptoGetTextPassword(&password)); AString charPassword; - if (wzAesMode || pkAesMode) + if (password) { - charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_ACP); - /* - for (int i = 0;; i++) + if (wzAesMode || pkAesMode) { - wchar_t c = password[i]; - if (c == 0) - break; - if (c >= 0x80) + charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_ACP); + /* + for (unsigned i = 0;; i++) { - res = NExtract::NOperationResult::kDataError; - return S_OK; + wchar_t c = password[i]; + if (c == 0) + break; + if (c >= 0x80) + { + res = NExtract::NOperationResult::kDataError; + return S_OK; + } + charPassword += (char)c; } - charPassword += (char)c; + */ + } + else + { + /* pkzip25 / WinZip / Windows probably use ANSI for some files + We use OEM for compatibility with previous versions of 7-Zip? */ + charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP); } - */ - } - 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()); + (const Byte *)(const char *)charPassword, charPassword.Len()); if (result != S_OK) return S_OK; } @@ -596,7 +697,7 @@ HRESULT CZipDecoder::Decode( } } - int m; + unsigned m; for (m = 0; m < methodItems.Size(); m++) if (methodItems[m].ZipMethod == methodId) break; @@ -624,7 +725,7 @@ HRESULT CZipDecoder::Decode( { if (methodId > 0xFF) { - res = NExtract::NOperationResult::kUnSupportedMethod; + res = NExtract::NOperationResult::kUnsupportedMethod; return S_OK; } szMethodID = kMethodId_ZipBase + (Byte)methodId; @@ -634,7 +735,7 @@ HRESULT CZipDecoder::Decode( if (mi.Coder == 0) { - res = NExtract::NOperationResult::kUnSupportedMethod; + res = NExtract::NOperationResult::kUnsupportedMethod; return S_OK; } } @@ -680,7 +781,7 @@ HRESULT CZipDecoder::Decode( } else if (pkAesMode) { - result =_pkAesDecoderSpec->ReadHeader(inStream, item.FileCRC, item.UnPackSize); + result =_pkAesDecoderSpec->ReadHeader(inStream, item.Crc, item.Size); if (result == S_OK) { bool passwOK; @@ -696,7 +797,16 @@ HRESULT CZipDecoder::Decode( if (result == S_OK) { - RINOK(filterStreamSpec->SetInStream(inStream)); + if (pkAesMode) + { + /* 9.31: The BUG in 9.24-9.30 was fixed. pkAes archives didn't work. + We don't need to call CAesCbcCoder::Init() to reset IV for data. */ + filterStreamSpec->SetInStream_NoSubFilterInit(inStream); + } + else + { + RINOK(filterStreamSpec->SetInStream(inStream)); + } inStreamReleaser.FilterCoder = filterStreamSpec; inStreamNew = filterStream; if (wzAesMode) @@ -709,12 +819,12 @@ HRESULT CZipDecoder::Decode( else inStreamNew = inStream; if (result == S_OK) - result = coder->Code(inStreamNew, outStream, NULL, &item.UnPackSize, compressProgress); + result = coder->Code(inStreamNew, outStream, NULL, &item.Size, compressProgress); if (result == S_FALSE) return S_OK; if (result == E_NOTIMPL) { - res = NExtract::NOperationResult::kUnSupportedMethod; + res = NExtract::NOperationResult::kUnsupportedMethod; return S_OK; } @@ -723,7 +833,7 @@ HRESULT CZipDecoder::Decode( bool crcOK = true; bool authOk = true; if (needCRC) - crcOK = (outStreamSpec->GetCRC() == item.FileCRC); + crcOK = (outStreamSpec->GetCRC() == item.Crc); if (wzAesMode) { inStream.Attach(archive.CreateLimitedStream(authenticationPos, NCrypto::NWzAes::kMacSize)); @@ -744,7 +854,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_BEGIN CZipDecoder myDecoder; UInt64 totalUnPacked = 0, totalPacked = 0; - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = m_Items.Size(); if(numItems == 0) @@ -753,7 +863,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, for (i = 0; i < numItems; i++) { const CItemEx &item = m_Items[allFilesMode ? i : indices[i]]; - totalUnPacked += item.UnPackSize; + totalUnPacked += item.Size; totalPacked += item.PackSize; } RINOK(extractCallback->SetTotal(totalUnPacked)); @@ -765,7 +875,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CMyComPtr progress = lps; lps->Init(extractCallback, false); - for (i = 0; i < numItems; i++, currentTotalUnPacked += currentItemUnPacked, + for (i = 0; i < numItems; i++, + currentTotalUnPacked += currentItemUnPacked, currentTotalPacked += currentItemPacked) { currentItemUnPacked = 0; @@ -779,11 +890,26 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 askMode = testMode ? NExtract::NAskMode::kTest : NExtract::NAskMode::kExtract; - Int32 index = allFilesMode ? i : indices[i]; + UInt32 index = allFilesMode ? i : indices[i]; + + CItemEx item = m_Items[index]; + bool isLocalOffsetOK = m_Archive.IsLocalOffsetOK(item); + bool skip = !isLocalOffsetOK && !item.IsDir(); + if (skip) + askMode = NExtract::NAskMode::kSkip; + + currentItemUnPacked = item.Size; + currentItemPacked = item.PackSize; RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); - CItemEx item = m_Items[index]; + if (!isLocalOffsetOK) + { + RINOK(extractCallback->PrepareOperation(askMode)); + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnavailable)); + continue; + } if (!item.FromLocal) { HRESULT res = m_Archive.ReadLocalItemAfterCdItem(item); @@ -793,14 +919,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, { RINOK(extractCallback->PrepareOperation(askMode)); realOutStream.Release(); - RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kHeadersError)); } continue; } RINOK(res); } - if (item.IsDir() || item.IgnoreItem()) + if (item.IsDir()) { // if (!testMode) { @@ -811,9 +937,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, continue; } - currentItemUnPacked = item.UnPackSize; - currentItemPacked = item.PackSize; - if (!testMode && !realOutStream) continue; diff --git a/CPP/7zip/Archive/Zip/ZipHandler.h b/CPP/7zip/Archive/Zip/ZipHandler.h old mode 100755 new mode 100644 index 33cf6fdc..7f1d2eba --- a/CPP/7zip/Archive/Zip/ZipHandler.h +++ b/CPP/7zip/Archive/Zip/ZipHandler.h @@ -3,7 +3,7 @@ #ifndef __ZIP_HANDLER_H #define __ZIP_HANDLER_H -#include "Common/DynamicBuffer.h" +#include "../../../Common/DynamicBuffer.h" #include "../../ICoder.h" #include "../IArchive.h" @@ -33,7 +33,7 @@ public: INTERFACE_IInArchive(;) INTERFACE_IOutArchive(;) - STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties); + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); DECL_ISetCompressCodecsInfo @@ -47,8 +47,11 @@ private: int m_MainMethod; bool m_ForceAesMode; bool m_WriteNtfsTimeExtra; + bool _removeSfxBlock; bool m_ForceLocal; bool m_ForceUtf8; + bool _forceCodePage; + UInt32 _specifiedCodePage; DECL_EXTERNAL_CODECS_VARS @@ -58,8 +61,11 @@ private: m_MainMethod = -1; m_ForceAesMode = false; m_WriteNtfsTimeExtra = true; + _removeSfxBlock = false; m_ForceLocal = false; m_ForceUtf8 = false; + _forceCodePage = false; + _specifiedCodePage = CP_OEMCP; } }; diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp old mode 100755 new mode 100644 index dd1ca136..ae58cbe2 --- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp @@ -2,12 +2,12 @@ #include "StdAfx.h" -#include "Common/ComTry.h" -#include "Common/StringConvert.h" -#include "Common/StringToInt.h" +#include "../../../Common/ComTry.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/StringToInt.h" -#include "Windows/PropVariant.h" -#include "Windows/Time.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/TimeUtils.h" #include "../../IPassword.h" @@ -36,7 +36,7 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) static bool IsAsciiString(const UString &s) { - for (int i = 0; i < s.Length(); i++) + for (unsigned i = 0; i < s.Len(); i++) { wchar_t c = s[i]; if (c < 0x20 || c > 0x7F) @@ -66,40 +66,48 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt IArchiveUpdateCallback *callback) { COM_TRY_BEGIN2 + + if (m_Archive.IsOpen()) + { + if (!m_Archive.CanUpdate()) + return E_NOTIMPL; + } + CObjectVector updateItems; bool thereAreAesUpdates = false; UInt64 largestSize = 0; bool largestSizeDefined = false; + for (UInt32 i = 0; i < numItems; i++) { CUpdateItem ui; Int32 newData; - Int32 newProperties; + Int32 newProps; UInt32 indexInArchive; if (!callback) return E_FAIL; - RINOK(callback->GetUpdateItemInfo(i, &newData, &newProperties, &indexInArchive)); - ui.NewProperties = IntToBool(newProperties); + RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive)); + ui.NewProps = IntToBool(newProps); ui.NewData = IntToBool(newData); - ui.IndexInArchive = indexInArchive; + ui.IndexInArc = indexInArchive; ui.IndexInClient = i; - bool existInArchive = (indexInArchive != (UInt32)-1); + bool existInArchive = (indexInArchive != (UInt32)(Int32)-1); if (existInArchive && newData) if (m_Items[indexInArchive].IsAesEncrypted()) thereAreAesUpdates = true; - if (IntToBool(newProperties)) + if (IntToBool(newProps)) { UString name; { NCOM::CPropVariant prop; RINOK(callback->GetProperty(i, kpidAttrib, &prop)); if (prop.vt == VT_EMPTY) - ui.Attributes = 0; + ui.Attrib = 0; else if (prop.vt != VT_UI4) return E_INVALIDARG; else - ui.Attributes = prop.ulVal; + ui.Attrib = prop.ulVal; } { @@ -131,15 +139,15 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt 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)); + RINOK(GetTime(callback, i, kpidMTime, ui.Ntfs_MTime)); + RINOK(GetTime(callback, i, kpidATime, ui.Ntfs_ATime)); + RINOK(GetTime(callback, i, kpidCTime, ui.Ntfs_CTime)); { FILETIME localFileTime = { 0, 0 }; - if (ui.NtfsMTime.dwHighDateTime != 0 || - ui.NtfsMTime.dwLowDateTime != 0) - if (!FileTimeToLocalFileTime(&ui.NtfsMTime, &localFileTime)) + if (ui.Ntfs_MTime.dwHighDateTime != 0 || + ui.Ntfs_MTime.dwLowDateTime != 0) + if (!FileTimeToLocalFileTime(&ui.Ntfs_MTime, &localFileTime)) return E_INVALIDARG; FileTimeToDosTime(localFileTime, ui.Time); } @@ -159,25 +167,27 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (needSlash) name += kSlash; + UINT codePage = _forceCodePage ? _specifiedCodePage : CP_OEMCP; + bool tryUtf8 = true; - if (m_ForceLocal || !m_ForceUtf8) + if ((m_ForceLocal || !m_ForceUtf8) && codePage != CP_UTF8) { bool defaultCharWasUsed; - ui.Name = UnicodeStringToMultiByte(name, CP_OEMCP, '_', defaultCharWasUsed); + ui.Name = UnicodeStringToMultiByte(name, codePage, '_', defaultCharWasUsed); tryUtf8 = (!m_ForceLocal && (defaultCharWasUsed || - MultiByteToUnicodeString(ui.Name, CP_OEMCP) != name)); + MultiByteToUnicodeString(ui.Name, codePage) != name)); } if (tryUtf8) { - int i; - for (i = 0; i < name.Length() && (unsigned)name[i] < 0x80; i++); - ui.IsUtf8 = (i != name.Length()); + unsigned i; + for (i = 0; i < name.Len() && (unsigned)name[i] < 0x80; i++); + ui.IsUtf8 = (i != name.Len()); if (!ConvertUnicodeToUTF8(name, ui.Name)) return E_INVALIDARG; } - if (ui.Name.Length() >= (1 << 16)) + if (ui.Name.Len() >= (1 << 16)) return E_INVALIDARG; ui.IndexInClient = i; @@ -211,6 +221,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt largestSizeDefined = true; } ui.Size = size; + // ui.Size -= ui.Size / 2; } updateItems.Add(ui); } @@ -225,6 +236,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt options._dataSizeReduce = largestSize; options._dataSizeReduceDefined = largestSizeDefined; + options.PasswordIsDefined = false; + options.Password.Empty(); if (getTextPassword) { CMyComBSTR password; @@ -236,18 +249,17 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (!m_ForceAesMode) options.IsAesMode = thereAreAesUpdates; - if (!IsAsciiString((const wchar_t *)password)) + if (!IsAsciiString((BSTR)password)) return E_INVALIDARG; + if (password) + options.Password = UnicodeStringToMultiByte((BSTR)password, CP_OEMCP); if (options.IsAesMode) { - if (options.Password.Length() > NCrypto::NWzAes::kPasswordSizeMax) + if (options.Password.Len() > NCrypto::NWzAes::kPasswordSizeMax) return E_INVALIDARG; } - options.Password = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP); } } - else - options.PasswordIsDefined = false; Byte mainMethod; if (m_MainMethod < 0) @@ -263,68 +275,68 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt return Update( EXTERNAL_CODECS_VARS m_Items, updateItems, outStream, - m_Archive.IsOpen() ? &m_Archive : NULL, &options, callback); + m_Archive.IsOpen() ? &m_Archive : NULL, _removeSfxBlock, + &options, callback); + COM_TRY_END2 } struct CMethodIndexToName { unsigned Method; - const wchar_t *Name; + const char *Name; }; static const CMethodIndexToName k_SupportedMethods[] = { - { NFileHeader::NCompressionMethod::kStored, L"COPY" }, - { NFileHeader::NCompressionMethod::kDeflated, L"DEFLATE" }, - { NFileHeader::NCompressionMethod::kDeflated64, L"DEFLATE64" }, - { NFileHeader::NCompressionMethod::kBZip2, L"BZIP2" }, - { NFileHeader::NCompressionMethod::kLZMA, L"LZMA" }, - { NFileHeader::NCompressionMethod::kPPMd, L"PPMD" } + { NFileHeader::NCompressionMethod::kStored, "copy" }, + { NFileHeader::NCompressionMethod::kDeflated, "deflate" }, + { NFileHeader::NCompressionMethod::kDeflated64, "deflate64" }, + { NFileHeader::NCompressionMethod::kBZip2, "bzip2" }, + { NFileHeader::NCompressionMethod::kLZMA, "lzma" }, + { NFileHeader::NCompressionMethod::kPPMd, "ppmd" } }; -#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) - -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) { InitMethodProps(); #ifndef _7ZIP_ST const UInt32 numProcessors = _props.NumThreads; #endif - for (int i = 0; i < numProps; i++) + for (UInt32 i = 0; i < numProps; i++) { UString name = names[i]; - name.MakeUpper(); + name.MakeLower_Ascii(); if (name.IsEmpty()) return E_INVALIDARG; const PROPVARIANT &prop = values[i]; - if (name[0] == L'X') + if (name[0] == L'x') { UInt32 level = 9; - RINOK(ParsePropToUInt32(name.Mid(1), prop, level)); + RINOK(ParsePropToUInt32(name.Ptr(1), prop, level)); _props.Level = level; _props.MethodInfo.AddLevelProp(level); } - else if (name == L"M") + else if (name == L"m") { if (prop.vt == VT_BSTR) { UString m = prop.bstrVal, m2; - m.MakeUpper(); + m.MakeLower_Ascii(); int colonPos = m.Find(L':'); if (colonPos >= 0) { - m2 = m.Mid(colonPos + 1); - m = m.Left(colonPos); + m2 = m.Ptr(colonPos + 1); + m.DeleteFrom(colonPos); } - int k; + unsigned k; for (k = 0; k < ARRAY_SIZE(k_SupportedMethods); k++) { const CMethodIndexToName &pair = k_SupportedMethods[k]; - if (m == pair.Name) + if (m.IsEqualTo(pair.Name)) { if (!m2.IsEmpty()) { @@ -339,7 +351,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v } else if (prop.vt == VT_UI4) { - int k; + unsigned k; for (k = 0; k < ARRAY_SIZE(k_SupportedMethods); k++) { unsigned method = k_SupportedMethods[k].Method; @@ -355,16 +367,16 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v else return E_INVALIDARG; } - else if (name.Left(2) == L"EM") + else if (name.IsPrefixedBy(L"em")) { if (prop.vt != VT_BSTR) return E_INVALIDARG; { UString m = prop.bstrVal; - m.MakeUpper(); - if (m.Left(3) == L"AES") + m.MakeLower_Ascii(); + if (m.IsPrefixedBy(L"aes")) { - m = m.Mid(3); + m.DeleteFrontal(3); if (m == L"128") _props.AesKeyMode = 1; else if (m == L"192") @@ -376,7 +388,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v _props.IsAesMode = true; m_ForceAesMode = true; } - else if (m == L"ZIPCRYPTO") + else if (m == L"zipcrypto") { _props.IsAesMode = false; m_ForceAesMode = true; @@ -385,29 +397,40 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v return E_INVALIDARG; } } - else if (name.Left(2) == L"MT") + else if (name.IsPrefixedBy(L"mt")) { #ifndef _7ZIP_ST - RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _props.NumThreads)); + RINOK(ParseMtProp(name.Ptr(2), prop, numProcessors, _props.NumThreads)); _props.NumThreadsWasChanged = true; #endif } - else if (name.CompareNoCase(L"TC") == 0) + else if (name.IsEqualTo("tc")) { RINOK(PROPVARIANT_to_bool(prop, m_WriteNtfsTimeExtra)); } - else if (name.CompareNoCase(L"CL") == 0) + else if (name.IsEqualTo("cl")) { RINOK(PROPVARIANT_to_bool(prop, m_ForceLocal)); if (m_ForceLocal) m_ForceUtf8 = false; } - else if (name.CompareNoCase(L"CU") == 0) + else if (name.IsEqualTo("cu")) { RINOK(PROPVARIANT_to_bool(prop, m_ForceUtf8)); if (m_ForceUtf8) m_ForceLocal = false; } + else if (name.IsEqualTo("cp")) + { + UInt32 cp = CP_OEMCP; + RINOK(ParsePropToUInt32(L"", prop, cp)); + _forceCodePage = true; + _specifiedCodePage = cp; + } + else if (name.IsEqualTo("rsfx")) + { + RINOK(PROPVARIANT_to_bool(prop, _removeSfxBlock)); + } else { RINOK(_props.MethodInfo.ParseParamsFromPROPVARIANT(name, prop)); diff --git a/CPP/7zip/Archive/Zip/ZipHeader.cpp b/CPP/7zip/Archive/Zip/ZipHeader.cpp deleted file mode 100755 index 582187b5..00000000 --- a/CPP/7zip/Archive/Zip/ZipHeader.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// 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 old mode 100755 new mode 100644 index ce8c1e4f..1391cdf4 --- a/CPP/7zip/Archive/Zip/ZipHeader.h +++ b/CPP/7zip/Archive/Zip/ZipHeader.h @@ -1,57 +1,39 @@ -// Archive/Zip/Header.h +// ZipHeader.h #ifndef __ARCHIVE_ZIP_HEADER_H #define __ARCHIVE_ZIP_HEADER_H -#include "Common/Types.h" +#include "../../../Common/MyTypes.h" namespace NArchive { namespace NZip { +const unsigned kMarkerSize = 4; + 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 kLocalFileHeader = 0x04034B50; + const UInt32 kDataDescriptor = 0x08074B50; + const UInt32 kCentralFileHeader = 0x02014B50; + const UInt32 kEcd = 0x06054B50; + const UInt32 kEcd64 = 0x06064B50; + const UInt32 kEcd64Locator = 0x07064B50; + + // const UInt32 kSpan = 0x08074B50; + const UInt32 kNoSpan = 0x30304b50; // PK00, replaces kSpan, if there is only 1 segment } -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; -}; +const unsigned kLocalHeaderSize = 4 + 26; // including signature +const unsigned kDataDescriptorSize = 4 + 12; // including signature +const unsigned kCentralHeaderSize = 4 + 42; // including signature -struct CEndOfCentralDirectoryRecordFull -{ - UInt32 Signature; - CEndOfCentralDirectoryRecord Header; -}; -*/ +const unsigned kEcdSize = 22; // including signature +const unsigned kEcd64_MainSize = 44; +const unsigned kEcd64_FullSize = 12 + kEcd64_MainSize; +const unsigned kEcd64Locator_Size = 20; namespace NFileHeader { - /* - struct CVersion - { - Byte Version; - Byte HostOS; - }; - */ - namespace NCompressionMethod { enum EType @@ -77,7 +59,7 @@ namespace NFileHeader kPPMd = 0x62, kWzAES = 0x63 }; - const int kNumCompressionMethods = 11; + const Byte kMadeByProgramVersion = 63; const Byte kExtractVersion_Default = 10; @@ -90,8 +72,6 @@ namespace NFileHeader const Byte kExtractVersion_Aes = 51; const Byte kExtractVersion_LZMA = 63; const Byte kExtractVersion_PPMd = 63; - - // const Byte kSupportedVersion = 20; } namespace NExtraID @@ -127,155 +107,93 @@ namespace NFileHeader }; } - 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 unsigned kEncrypted = 1 << 0; + const unsigned kLzmaEOS = 1 << 1; + const unsigned kDescriptorUsedMask = 1 << 3; + const unsigned kStrongEncrypted = 1 << 6; + const unsigned kUtf8 = 1 << 11; + + const unsigned kImplodeDictionarySizeMask = 1 << 1; + const unsigned kImplodeLiteralsOnMask = 1 << 2; - const int kDeflateTypeBitStart = 1; - const int kNumDeflateTypeBits = 2; - const int kNumDeflateTypes = (1 << kNumDeflateTypeBits); - const int kDeflateTypeMask = (1 << kNumDeflateTypeBits) - 1; + const unsigned kDeflateTypeBitStart = 1; + const unsigned kNumDeflateTypeBits = 2; + const unsigned kNumDeflateTypes = (1 << kNumDeflateTypeBits); + const unsigned 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 + 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 + + namespace NUnixAttrib { - const UInt32 kIFMT = 0170000; /* Unix file type mask */ + const UInt32 kIFMT = 0170000; // 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 kIFDIR = 0040000; // directory + const UInt32 kIFREG = 0100000; // regular file + const UInt32 kIFSOCK = 0140000; // socket (BSD, not SysV or Amiga) + const UInt32 kIFLNK = 0120000; // symbolic link (not SysV, Amiga) + const UInt32 kIFBLK = 0060000; // block special (not Amiga) + const UInt32 kIFCHR = 0020000; // character special (not Amiga) + const UInt32 kIFIFO = 0010000; // 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 */ + const UInt32 kISUID = 04000; // set user id on execution + const UInt32 kISGID = 02000; // set group id on execution + const UInt32 kISVTX = 01000; // directory permissions control + const UInt32 kENFMT = kISGID; // record locking enforcement flag + const UInt32 kIRWXU = 00700; // read, write, execute: owner + const UInt32 kIRUSR = 00400; // read permission: owner + const UInt32 kIWUSR = 00200; // write permission: owner + const UInt32 kIXUSR = 00100; // execute permission: owner + const UInt32 kIRWXG = 00070; // read, write, execute: group + const UInt32 kIRGRP = 00040; // read permission: group + const UInt32 kIWGRP = 00020; // write permission: group + const UInt32 kIXGRP = 00010; // execute permission: group + const UInt32 kIRWXO = 00007; // read, write, execute: other + const UInt32 kIROTH = 00004; // read permission: other + const UInt32 kIWOTH = 00002; // write permission: other + const UInt32 kIXOTH = 00001; // execute permission: other } - namespace NAmigaAttribute + namespace NAmigaAttrib { - 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 */ + 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 } } diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp old mode 100755 new mode 100644 index e930488f..345fbf56 --- a/CPP/7zip/Archive/Zip/ZipIn.cpp +++ b/CPP/7zip/Archive/Zip/ZipIn.cpp @@ -2,13 +2,15 @@ #include "StdAfx.h" -#include "../../../../C/CpuArch.h" +// #include -#include "Common/DynamicBuffer.h" +#include "../../../Common/DynamicBuffer.h" #include "../../Common/LimitedStreams.h" #include "../../Common/StreamUtils.h" +#include "../IArchive.h" + #include "ZipIn.h" #define Get16(p) GetUi16(p) @@ -17,100 +19,342 @@ namespace NArchive { namespace NZip { - + +struct CEcd +{ + UInt16 thisDiskNumber; + UInt16 startCDDiskNumber; + UInt16 numEntriesInCDOnThisDisk; + UInt16 numEntriesInCD; + UInt32 cdSize; + UInt32 cdStartOffset; + UInt16 commentSize; + + void Parse(const Byte *p); + + bool IsEmptyArc() + { + return thisDiskNumber == 0 && startCDDiskNumber == 0 && + numEntriesInCDOnThisDisk == 0 && numEntriesInCD == 0 && cdSize == 0 + && cdStartOffset == 0 // test it + ; + } +}; + +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); +} + 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(stream->Seek(0, STREAM_SEEK_CUR, &m_Position)); + RINOK(stream->Seek(0, STREAM_SEEK_END, &ArcInfo.FileEndPos)); + RINOK(stream->Seek(m_Position, STREAM_SEEK_SET, NULL)); + + // printf("\nOpen offset = %d", (int)m_Position); RINOK(FindAndReadMarker(stream, searchHeaderSizeLimit)); RINOK(stream->Seek(m_Position, STREAM_SEEK_SET, NULL)); - m_Stream = stream; + Stream = stream; return S_OK; } void CInArchive::Close() { - _inBuffer.ReleaseStream(); - m_Stream.Release(); + IsArc = false; + HeadersError = false; + HeadersWarning = false; + ExtraMinorError = false; + UnexpectedEnd = false; + NoCentralDir = false; + IsZip64 = false; + Stream.Release(); } HRESULT CInArchive::Seek(UInt64 offset) { - return m_Stream->Seek(offset, STREAM_SEEK_SET, NULL); + return Stream->Seek(offset, STREAM_SEEK_SET, NULL); } -////////////////////////////////////// -// Markers +static bool CheckDosTime(UInt32 dosTime) +{ + if (dosTime == 0) + return true; + unsigned month = (dosTime >> 21) & 0xF; + unsigned day = (dosTime >> 16) & 0x1F; + unsigned hour = (dosTime >> 11) & 0x1F; + unsigned min = (dosTime >> 5) & 0x3F; + unsigned sec = (dosTime & 0x1F) * 2; + if (month < 1 || month > 12 || day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59) + return false; + return true; +} -static inline bool TestMarkerCandidate(const Byte *p, UInt32 &value) +API_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size) { + if (size < 8) + return k_IsArc_Res_NEED_MORE; + if (p[0] != 'P') + return k_IsArc_Res_NO; + + UInt32 value = Get32(p); + + if (value == NSignature::kNoSpan) + { + p += 4; + size -= 4; + } + value = Get32(p); - return - (value == NSignature::kLocalFileHeader) || - (value == NSignature::kEndOfCentralDir); + + if (value == NSignature::kEcd) + { + if (size < kEcdSize) + return k_IsArc_Res_NEED_MORE; + CEcd ecd; + ecd.Parse(p + 4); + // if (ecd.cdSize != 0) + if (!ecd.IsEmptyArc()) + return k_IsArc_Res_NO; + return k_IsArc_Res_YES; // k_IsArc_Res_YES_2; + } + + if (value != NSignature::kLocalFileHeader) + return k_IsArc_Res_NO; + + if (size < kLocalHeaderSize) + return k_IsArc_Res_NEED_MORE; + + p += 4; + + { + const unsigned kPureHeaderSize = kLocalHeaderSize - 4; + unsigned i; + for (i = 0; i < kPureHeaderSize && p[i] == 0; i++); + if (i == kPureHeaderSize) + return k_IsArc_Res_NEED_MORE; + } + + /* + if (p[0] >= 128) // ExtractVersion.Version; + return k_IsArc_Res_NO; + */ + + // ExtractVersion.Version = p[0]; + // ExtractVersion.HostOS = p[1]; + // Flags = Get16(p + 2); + // Method = Get16(p + 4); + /* + // 9.33: some zip archives contain incorrect value in timestamp. So we don't check it now + UInt32 dosTime = Get32(p + 6); + if (!CheckDosTime(dosTime)) + return k_IsArc_Res_NO; + */ + // Crc = Get32(p + 10); + // PackSize = Get32(p + 14); + // Size = Get32(p + 18); + unsigned nameSize = Get16(p + 22); + unsigned extraSize = Get16(p + 24); + UInt32 extraOffset = kLocalHeaderSize + (UInt32)nameSize; + if (extraOffset + extraSize > (1 << 16)) + return k_IsArc_Res_NO; + + p -= 4; + + { + size_t rem = size - kLocalHeaderSize; + if (rem > nameSize) + rem = nameSize; + const Byte *p2 = p + kLocalHeaderSize; + for (size_t i = 0; i < rem; i++) + if (p2[i] == 0) + return k_IsArc_Res_NO; + } + + if (size < extraOffset) + return k_IsArc_Res_NEED_MORE; + + if (extraSize > 0) + { + p += extraOffset; + size -= extraOffset; + while (extraSize != 0) + { + if (extraSize < 4) + { + // 7-Zip before 9.31 created incorrect WsAES Extra in folder's local headers. + // so we return k_IsArc_Res_YES to support such archives. + // return k_IsArc_Res_NO; // do we need to support such extra ? + return k_IsArc_Res_YES; + } + if (size < 4) + return k_IsArc_Res_NEED_MORE; + unsigned dataSize = Get16(p + 2); + size -= 4; + extraSize -= 4; + p += 4; + if (dataSize > extraSize) + return k_IsArc_Res_NO; + if (dataSize > size) + return k_IsArc_Res_NEED_MORE; + size -= dataSize; + extraSize -= dataSize; + p += dataSize; + } + } + + return k_IsArc_Res_YES; } -static const UInt32 kNumMarkerAddtionalBytes = 2; -static inline bool TestMarkerCandidate2(const Byte *p, UInt32 &value) +static UInt32 IsArc_Zip_2(const Byte *p, size_t size, bool isFinal) { - value = Get32(p); - if (value == NSignature::kEndOfCentralDir) - return (Get16(p + 4) == 0); - return (value == NSignature::kLocalFileHeader && p[4] < 128); + UInt32 res = IsArc_Zip(p, size); + if (res == k_IsArc_Res_NEED_MORE && isFinal) + return k_IsArc_Res_NO; + return res; } -HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit) +HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchLimit) { ArcInfo.Clear(); - m_Position = m_StreamStartPosition; + ArcInfo.MarkerPos = m_Position; + ArcInfo.MarkerPos2 = m_Position; - Byte marker[NSignature::kMarkerSize]; - RINOK(ReadStream_FALSE(stream, marker, NSignature::kMarkerSize)); - m_Position += NSignature::kMarkerSize; - if (TestMarkerCandidate(marker, m_Signature)) - return S_OK; + if (searchLimit && *searchLimit == 0) + { + const unsigned kStartBufSize = kMarkerSize; + Byte startBuf[kStartBufSize]; + size_t processed = kStartBufSize; + RINOK(ReadStream(stream, startBuf, &processed)); + m_Position += processed; + if (processed < kMarkerSize) + return S_FALSE; + m_Signature = Get32(startBuf); + if (m_Signature != NSignature::kEcd && + m_Signature != NSignature::kLocalFileHeader) + { + if (m_Signature != NSignature::kNoSpan) + return S_FALSE; + size_t processed = kStartBufSize; + RINOK(ReadStream(stream, startBuf, &processed)); + m_Position += processed; + if (processed < kMarkerSize) + return S_FALSE; + m_Signature = Get32(startBuf); + if (m_Signature != NSignature::kEcd && + m_Signature != NSignature::kLocalFileHeader) + return S_FALSE; + ArcInfo.MarkerPos2 += 4; + } + + // we use weak test in case of *searchLimit == 0) + // since error will be detected later in Open function + // m_Position = ArcInfo.MarkerPos2 + 4; + return S_OK; // maybe we need to search backward. + } + + const size_t kBufSize = (size_t)1 << 18; // must be larger than kCheckSize + const size_t kCheckSize = (size_t)1 << 16; // must be smaller than kBufSize + CByteArr buffer(kBufSize); + + size_t numBytesInBuffer = 0; + UInt64 curScanPos = 0; - 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)); + size_t numReadBytes = kBufSize - numBytesInBuffer; + RINOK(ReadStream(stream, buffer + numBytesInBuffer, &numReadBytes)); m_Position += numReadBytes; - UInt32 numBytesInBuffer = numBytesPrev + (UInt32)numReadBytes; - const UInt32 kMarker2Size = NSignature::kMarkerSize + kNumMarkerAddtionalBytes; - if (numBytesInBuffer < kMarker2Size) + numBytesInBuffer += numReadBytes; + bool isFinished = (numBytesInBuffer != kBufSize); + + size_t limit = (isFinished ? numBytesInBuffer : numBytesInBuffer - kCheckSize); + + if (searchLimit && curScanPos + limit > *searchLimit) + limit = (size_t)(*searchLimit - curScanPos + 1); + + if (limit < 1) break; - UInt32 numTests = numBytesInBuffer - kMarker2Size + 1; - for (UInt32 pos = 0; pos < numTests; pos++) + + const Byte *buf = buffer; + for (size_t pos = 0; pos < limit; pos++) { - if (buffer[pos] != 0x50) + if (buf[pos] != 0x50) + continue; + if (buf[pos + 1] != 0x4B) continue; - if (TestMarkerCandidate2(buffer + pos, m_Signature)) + size_t rem = numBytesInBuffer - pos; + UInt32 res = IsArc_Zip_2(buf + pos, rem, isFinished); + if (res != k_IsArc_Res_NO) { - curTestPos += pos; - ArcInfo.StartPosition = curTestPos; - m_Position = curTestPos + NSignature::kMarkerSize; + if (rem < kMarkerSize) + return S_FALSE; + m_Signature = Get32(buf + pos); + ArcInfo.MarkerPos += curScanPos + pos; + ArcInfo.MarkerPos2 = ArcInfo.MarkerPos; + if (m_Signature == NSignature::kNoSpan) + { + m_Signature = Get32(buf + pos + 4); + ArcInfo.MarkerPos2 += 4; + } + m_Position = ArcInfo.MarkerPos2 + kMarkerSize; return S_OK; } } - curTestPos += numTests; - numBytesPrev = numBytesInBuffer - numTests; - memmove(buffer, buffer + numTests, numBytesPrev); + + if (isFinished) + break; + + curScanPos += limit; + numBytesInBuffer -= limit; + memmove(buffer, buffer + limit, numBytesInBuffer); } + return S_FALSE; } +HRESULT CInArchive::IncreaseRealPosition(UInt64 addValue) +{ + return Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position); +} + +class CUnexpectEnd {}; + HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize) { size_t realProcessedSize = size; @@ -121,42 +365,35 @@ HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize) catch (const CInBufferException &e) { return e.ErrorCode; } } else - result = ReadStream(m_Stream, data, &realProcessedSize); - if (processedSize != NULL) + result = ReadStream(Stream, data, &realProcessedSize); + if (processedSize) *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) +void CInArchive::SafeReadBytes(void *data, unsigned size) { - if (!ReadBytesAndTestSize(data, size)) - throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive); + size_t processed = size; + if (_inBufMode) + { + processed = _inBuffer.ReadBytes((Byte *)data, size); + m_Position += processed; + } + else + { + HRESULT result = ReadStream(Stream, data, &processed); + m_Position += processed; + if (result != S_OK) + throw CSystemException(result); + } + if (processed != size) + throw CUnexpectEnd(); } -void CInArchive::ReadBuffer(CByteBuffer &buffer, UInt32 size) +void CInArchive::ReadBuffer(CByteBuffer &buffer, unsigned size) { - buffer.SetCapacity(size); + buffer.Alloc(size); if (size > 0) SafeReadBytes(buffer, size); } @@ -168,65 +405,73 @@ Byte CInArchive::ReadByte() return b; } -UInt16 CInArchive::ReadUInt16() -{ - Byte buf[2]; - SafeReadBytes(buf, 2); - return Get16(buf); -} +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); } -UInt32 CInArchive::ReadUInt32() +void CInArchive::Skip(unsigned num) { - Byte buf[4]; - SafeReadBytes(buf, 4); - return Get32(buf); + if (_inBufMode) + { + size_t skip = _inBuffer.Skip(num); + m_Position += skip; + if (skip != num) + throw CUnexpectEnd(); + } + else + { + for (unsigned i = 0; i < num; i++) + ReadByte(); + } } -UInt64 CInArchive::ReadUInt64() +void CInArchive::Skip64(UInt64 num) { - Byte buf[8]; - SafeReadBytes(buf, 8); - return Get64(buf); + for (UInt64 i = 0; i < num; i++) + ReadByte(); } -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) +void CInArchive::ReadFileName(unsigned size, AString &s) { - if (nameSize == 0) - dest.Empty(); - char *p = dest.GetBuffer((int)nameSize); - SafeReadBytes(p, nameSize); - p[nameSize] = 0; - dest.ReleaseBuffer(); + if (size == 0) + { + s.Empty(); + return; + } + char *p = s.GetBuffer(size); + SafeReadBytes(p, size); + p[size] = 0; + s.ReleaseBuffer(); } -void CInArchive::ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock, +bool CInArchive::ReadExtra(unsigned extraSize, CExtraBlock &extraBlock, UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber) { extraBlock.Clear(); UInt32 remain = extraSize; - while(remain >= 4) + while (remain >= 4) { CExtraSubBlock subBlock; subBlock.ID = ReadUInt16(); - UInt32 dataSize = ReadUInt16(); + unsigned dataSize = ReadUInt16(); remain -= 4; if (dataSize > remain) // it's bug - dataSize = remain; + { + HeadersWarning = true; + Skip(remain); + return false; + } if (subBlock.ID == NFileHeader::NExtraID::kZip64) { if (unpackSize == 0xFFFFFFFF) { if (dataSize < 8) - break; + { + HeadersWarning = true; + Skip(remain); + return false; + } unpackSize = ReadUInt64(); remain -= 8; dataSize -= 8; @@ -255,8 +500,7 @@ void CInArchive::ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock, remain -= 4; dataSize -= 4; } - for (UInt32 i = 0; i < dataSize; i++) - ReadByte(); + Skip(dataSize); } else { @@ -265,88 +509,125 @@ void CInArchive::ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock, } remain -= dataSize; } + if (remain != 0) + { + ExtraMinorError = true; + // 7-Zip before 9.31 created incorrect WsAES Extra in folder's local headers. + // so we don't return false, but just set warning flag + // return false; + } Skip(remain); + return true; } -HRESULT CInArchive::ReadLocalItem(CItemEx &item) +bool CInArchive::ReadLocalItem(CItemEx &item) { - const int kBufSize = 26; - Byte p[kBufSize]; - SafeReadBytes(p, kBufSize); + const unsigned kPureHeaderSize = kLocalHeaderSize - 4; + Byte p[kPureHeaderSize]; + SafeReadBytes(p, kPureHeaderSize); + { + unsigned i; + for (i = 0; i < kPureHeaderSize && p[i] == 0; i++); + if (i == kPureHeaderSize) + return false; + } item.ExtractVersion.Version = p[0]; item.ExtractVersion.HostOS = p[1]; item.Flags = Get16(p + 2); - item.CompressionMethod = Get16(p + 4); + item.Method = Get16(p + 4); item.Time = Get32(p + 6); - item.FileCRC = Get32(p + 10); + item.Crc = 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) + item.Size = Get32(p + 18); + unsigned nameSize = Get16(p + 22); + unsigned extraSize = Get16(p + 24); + ReadFileName(nameSize, item.Name); + item.LocalFullHeaderSize = kLocalHeaderSize + (UInt32)nameSize + extraSize; + + /* + if (item.IsDir()) + item.Size = 0; // check It + */ + + if (extraSize > 0) { UInt64 localHeaderOffset = 0; UInt32 diskStartNumber = 0; - ReadExtra(item.LocalExtraSize, item.LocalExtra, item.UnPackSize, item.PackSize, - localHeaderOffset, diskStartNumber); + if (!ReadExtra(extraSize, item.LocalExtra, item.Size, item.PackSize, + localHeaderOffset, diskStartNumber)) + return false; } - /* - if (item.IsDir()) - item.UnPackSize = 0; // check It - */ - return S_OK; + if (!CheckDosTime(item.Time)) + { + HeadersWarning = true; + // return false; + } + if (item.Name.Len() != nameSize) + return false; + return item.LocalFullHeaderSize <= ((UInt32)1 << 16); } -static bool FlagsAreSame(CItem &i1, CItem &i2) +static bool FlagsAreSame(const CItem &i1, const CItem &i2) { - if (i1.CompressionMethod != i2.CompressionMethod) + if (i1.Method != i2.Method) return false; - // i1.Time - if (i1.Flags == i2.Flags) return true; UInt32 mask = 0xFFFF; - switch(i1.CompressionMethod) + switch(i1.Method) { case NFileHeader::NCompressionMethod::kDeflated: mask = 0x7FF9; break; default: - if (i1.CompressionMethod <= NFileHeader::NCompressionMethod::kImploded) + if (i1.Method <= NFileHeader::NCompressionMethod::kImploded) mask = 0x7FFF; } return ((i1.Flags & mask) == (i2.Flags & mask)); } +static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem) +{ + if (!FlagsAreSame(cdItem, localItem)) + return false; + if (!localItem.HasDescriptor()) + { + if (cdItem.Crc != localItem.Crc || + cdItem.PackSize != localItem.PackSize || + cdItem.Size != localItem.Size) + return false; + } + /* pkzip 2.50 creates incorrect archives. It uses + - WIN encoding for name in local header + - OEM encoding for name in central header + We don't support these strange items. */ + + /* if (cdItem.Name.Len() != localItem.Name.Len()) + return false; + */ + if (cdItem.Name != localItem.Name) + return false; + return true; +} + HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item) { if (item.FromLocal) return S_OK; try { - RINOK(Seek(ArcInfo.Base + item.LocalHeaderPosition)); + UInt64 offset = ArcInfo.Base + item.LocalHeaderPos; + if (ArcInfo.Base < 0 && (Int64)offset < 0) + return S_FALSE; + RINOK(Seek(offset)); CItemEx localItem; if (ReadUInt32() != NSignature::kLocalFileHeader) return S_FALSE; - RINOK(ReadLocalItem(localItem)); - if (!FlagsAreSame(item, localItem)) + ReadLocalItem(localItem); + if (!AreItemsEqual(localItem, item)) 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.LocalFullHeaderSize = localItem.LocalFullHeaderSize; item.LocalExtra = localItem.LocalExtra; item.FromLocal = true; } @@ -356,53 +637,45 @@ HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item) HRESULT CInArchive::ReadLocalItemDescriptor(CItemEx &item) { - if (item.HasDescriptor()) + const unsigned kBufSize = (1 << 12); + Byte buf[kBufSize]; + + UInt32 numBytesInBuffer = 0; + UInt32 packedSize = 0; + + for (;;) { - const int kBufferSize = (1 << 12); - Byte buffer[kBufferSize]; - - UInt32 numBytesInBuffer = 0; - UInt32 packedSize = 0; - - bool descriptorWasFound = false; - for (;;) + UInt32 processedSize; + RINOK(ReadBytes(buf + numBytesInBuffer, kBufSize - numBytesInBuffer, &processedSize)); + numBytesInBuffer += processedSize; + if (numBytesInBuffer < kDataDescriptorSize) + return S_FALSE; + UInt32 i; + for (i = 0; i <= numBytesInBuffer - kDataDescriptorSize; i++) { - 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++) + // descriptor signature field is Info-ZIP's extension to pkware Zip specification. + // New ZIP specification also allows descriptorSignature. + if (buf[i] != 0x50) + continue; + // !!!! It must be fixed for Zip64 archives + if (Get32(buf + i) == NSignature::kDataDescriptor) { - // 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) + UInt32 descriptorPackSize = Get32(buf + i + 8); + if (descriptorPackSize == packedSize + i) { - descriptorWasFound = true; - item.FileCRC = Get32(buffer + i + 4); + item.Crc = Get32(buf + i + 4); item.PackSize = descriptorPackSize; - item.UnPackSize = Get32(buffer + i + 12); - IncreaseRealPosition(Int64(Int32(0 - (numBytesInBuffer - i - NFileHeader::kDataDescriptorSize)))); - break; + item.Size = Get32(buf + i + 12); + return IncreaseRealPosition(Int64(Int32(0 - (numBytesInBuffer - i - kDataDescriptorSize)))); } } - if (descriptorWasFound) - break; - packedSize += i; - int j; - for (j = 0; i < numBytesInBuffer; i++, j++) - buffer[j] = buffer[i]; - numBytesInBuffer = j; } + packedSize += i; + unsigned j; + for (j = 0; i < numBytesInBuffer; i++, j++) + buf[j] = buf[i]; + numBytesInBuffer = j; } - else - IncreaseRealPosition(item.PackSize); - return S_OK; } HRESULT CInArchive::ReadLocalItemAfterCdItemFull(CItemEx &item) @@ -433,7 +706,7 @@ HRESULT CInArchive::ReadLocalItemAfterCdItemFull(CItemEx &item) unpackSize = ReadUInt32(); } - if (crc != item.FileCRC || item.PackSize != packSize || item.UnPackSize != unpackSize) + if (crc != item.Crc || item.PackSize != packSize || item.Size != unpackSize) return S_FALSE; } } @@ -444,106 +717,161 @@ HRESULT CInArchive::ReadLocalItemAfterCdItemFull(CItemEx &item) HRESULT CInArchive::ReadCdItem(CItemEx &item) { item.FromCentral = true; - const int kBufSize = 42; - Byte p[kBufSize]; - SafeReadBytes(p, kBufSize); + Byte p[kCentralHeaderSize - 4]; + SafeReadBytes(p, kCentralHeaderSize - 4); + 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.Method = Get16(p + 6); item.Time = Get32(p + 8); - item.FileCRC = Get32(p + 12); + item.Crc = 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); + item.Size = Get32(p + 20); + unsigned nameSize = Get16(p + 24); + UInt16 extraSize = Get16(p + 26); + UInt16 commentSize = Get16(p + 28); + UInt32 diskNumberStart = Get16(p + 30); + item.InternalAttrib = Get16(p + 32); + item.ExternalAttrib = Get32(p + 34); + item.LocalHeaderPos = Get32(p + 38); + ReadFileName(nameSize, item.Name); - if (headerExtraSize > 0) + if (extraSize > 0) { - ReadExtra(headerExtraSize, item.CentralExtra, item.UnPackSize, item.PackSize, - item.LocalHeaderPosition, headerDiskNumberStart); + ReadExtra(extraSize, item.CentralExtra, item.Size, item.PackSize, + item.LocalHeaderPos, diskNumberStart); } - if (headerDiskNumberStart != 0) - throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported); + if (diskNumberStart != 0) + return E_NOTIMPL; // May be these strings must be deleted /* if (item.IsDir()) - item.UnPackSize = 0; + item.Size = 0; */ - ReadBuffer(item.Comment, headerCommentSize); + ReadBuffer(item.Comment, commentSize); return S_OK; } +void CCdInfo::ParseEcd(const Byte *p) +{ + NumEntries = Get16(p + 10); + Size = Get32(p + 12); + Offset = Get32(p + 16); +} + +void CCdInfo::ParseEcd64(const Byte *p) +{ + NumEntries = Get64(p + 24); + Size = Get64(p + 40); + Offset = Get64(p + 48); +} + HRESULT CInArchive::TryEcd64(UInt64 offset, CCdInfo &cdInfo) { + if (offset >= ((UInt64)1 << 63)) + return S_FALSE; RINOK(Seek(offset)); - const UInt32 kEcd64Size = 56; - Byte buf[kEcd64Size]; - if (!ReadBytesAndTestSize(buf, kEcd64Size)) + Byte buf[kEcd64_FullSize]; + + RINOK(ReadStream_FALSE(Stream, buf, kEcd64_FullSize)); + + if (Get32(buf) != NSignature::kEcd64) return S_FALSE; - if (Get32(buf) != NSignature::kZip64EndOfCentralDir) + UInt64 mainSize = Get64(buf + 4); + if (mainSize < kEcd64_MainSize || mainSize > ((UInt64)1 << 32)) return S_FALSE; - // cdInfo.NumEntries = Get64(buf + 24); - cdInfo.Size = Get64(buf + 40); - cdInfo.Offset = Get64(buf + 48); + cdInfo.ParseEcd64(buf); 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; + RINOK(Stream->Seek(0, STREAM_SEEK_END, &endPosition)); + + const UInt32 kBufSizeMax = ((UInt32)1 << 16) + kEcdSize + kEcd64Locator_Size + kEcd64_FullSize; UInt32 bufSize = (endPosition < kBufSizeMax) ? (UInt32)endPosition : kBufSizeMax; if (bufSize < kEcdSize) return S_FALSE; + CByteArr byteBuffer(bufSize); + UInt64 startPosition = endPosition - bufSize; - RINOK(m_Stream->Seek(startPosition, STREAM_SEEK_SET, &m_Position)); + RINOK(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--) + + RINOK(ReadStream_FALSE(Stream, byteBuffer, bufSize)); + + const Byte *buf = byteBuffer; + for (UInt32 i = bufSize - kEcdSize;; i--) { - if (Get32(buf + i) == NSignature::kEndOfCentralDir) + if (buf[i] != 0x50) { - if (i >= kZip64EcdLocatorSize) + if (i == 0) return S_FALSE; + i--; + if (buf[i] != 0x50) { - const Byte *locator = buf + i - kZip64EcdLocatorSize; - if (Get32(locator) == NSignature::kZip64EndOfCentralDirLocator) + if (i == 0) return S_FALSE; + continue; + } + } + if (Get32(buf + i) == NSignature::kEcd) + { + if (i >= kEcd64_FullSize + kEcd64Locator_Size) + { + const Byte *locator = buf + i - kEcd64Locator_Size; + if (Get32(locator) == NSignature::kEcd64Locator && + Get32(locator + 4) == 0) // number of the disk with the start of the zip64 ECD { + // Most of the zip64 use fixed size Zip64 ECD + UInt64 ecd64Offset = Get64(locator + 8); - if (TryEcd64(ecd64Offset, cdInfo) == S_OK) - return S_OK; - if (TryEcd64(ArcInfo.StartPosition + ecd64Offset, cdInfo) == S_OK) + UInt64 absEcd64 = endPosition - bufSize + i - (kEcd64Locator_Size + kEcd64_FullSize); + { + const Byte *ecd64 = locator - kEcd64_FullSize; + if (Get32(ecd64) == NSignature::kEcd64 && + Get64(ecd64 + 4) == kEcd64_MainSize) + { + cdInfo.ParseEcd64(ecd64); + ArcInfo.Base = absEcd64 - ecd64Offset; + return S_OK; + } + } + + // some zip64 use variable size Zip64 ECD. + // we try to find it + if (absEcd64 != ecd64Offset) + { + if (TryEcd64(ecd64Offset, cdInfo) == S_OK) + { + ArcInfo.Base = 0; + return S_OK; + } + } + if (ArcInfo.MarkerPos != 0 && + ArcInfo.MarkerPos + ecd64Offset != absEcd64) { - ArcInfo.Base = ArcInfo.StartPosition; - return S_OK; + if (TryEcd64(ArcInfo.MarkerPos + ecd64Offset, cdInfo) == S_OK) + { + ArcInfo.Base = ArcInfo.MarkerPos; + return S_OK; + } } } } - if (Get32(buf + i + 4) == 0) + if (Get32(buf + i + 4) == 0) // ThisDiskNumber, StartCentralDirectoryDiskNumber; { - // cdInfo.NumEntries = GetUInt16(buf + i + 10); - cdInfo.Size = Get32(buf + i + 12); - cdInfo.Offset = Get32(buf + i + 16); - UInt64 curPos = endPosition - bufSize + i; + cdInfo.ParseEcd(buf + i); + UInt64 absEcdPos = endPosition - bufSize + i; UInt64 cdEnd = cdInfo.Size + cdInfo.Offset; - if (curPos != cdEnd) + ArcInfo.Base = 0; + if (absEcdPos != cdEnd) { /* if (cdInfo.Offset <= 16 && cdInfo.Size != 0) @@ -553,290 +881,301 @@ HRESULT CInArchive::FindCd(CCdInfo &cdInfo) } else */ - ArcInfo.Base = curPos - cdEnd; + ArcInfo.Base = absEcdPos - cdEnd; } return S_OK; } } + if (i == 0) + return S_FALSE; } - 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)); + RINOK(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) + 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())); + if (progress && items.Size() % 1 == 0) + RINOK(progress->SetCompletedCD(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; + if (progress) + progress->SetTotalCD(cdInfo.NumEntries); res = TryReadCd(items, ArcInfo.Base + cdOffset, cdSize, progress); if (res == S_FALSE && ArcInfo.Base == 0) { - res = TryReadCd(items, cdInfo.Offset + ArcInfo.StartPosition, cdSize, progress); + res = TryReadCd(items, ArcInfo.MarkerPos + cdOffset, cdSize, progress); if (res == S_OK) - ArcInfo.Base = ArcInfo.StartPosition; + ArcInfo.Base = ArcInfo.MarkerPos; } - if (!ReadUInt32(m_Signature)) - return S_FALSE; return res; } -HRESULT CInArchive::ReadLocalsAndCd(CObjectVector &items, CProgressVirt *progress, UInt64 &cdOffset, int &numCdItems) +static HRESULT FindItem(const CObjectVector &items, UInt64 offset) { - items.Clear(); - numCdItems = 0; - while (m_Signature == NSignature::kLocalFileHeader) + unsigned left = 0, right = items.Size(); + for (;;) { - // 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; + if (left >= right) + return -1; + unsigned index = (left + right) / 2; + UInt64 position = items[index].LocalHeaderPos; + if (offset == position) + return index; + if (offset < position) + right = index; + else + left = index + 1; } - 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)); +bool IsStrangeItem(const CItem &item) +{ + return item.Name.Len() > (1 << 14) || item.Method > (1 << 8); +} - if (i == 0) +HRESULT CInArchive::ReadLocals( + CObjectVector &items, CProgressVirt *progress) +{ + items.Clear(); + while (m_Signature == NSignature::kLocalFileHeader) + { + CItemEx item; + item.LocalHeaderPos = m_Position - 4 - ArcInfo.MarkerPos; + // we write ralative LocalHeaderPos here. Later we can correct it to real Base. + try { - int j; - for (j = 0; j < items.Size(); j++) + ReadLocalItem(item); + item.FromLocal = true; + if (item.HasDescriptor()) + ReadLocalItemDescriptor(item); + else { - CItemEx &item = items[j]; - if (item.Name == cdItem.Name) - { - ArcInfo.Base = item.LocalHeaderPosition - cdItem.LocalHeaderPosition; - break; - } + RINOK(IncreaseRealPosition(item.PackSize)); } - if (j == items.Size()) - return S_FALSE; + items.Add(item); + m_Signature = ReadUInt32(); } - - int index; - int left = 0, right = items.Size(); - for (;;) + catch (CUnexpectEnd &) { - if (left >= right) + if (items.IsEmpty() || items.Size() == 1 && IsStrangeItem(items[0])) 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; + throw; } - 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 (progress && items.Size() % 1 == 0) + RINOK(progress->SetCompletedLocal(items.Size(), item.LocalHeaderPos)); + } - 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)) + if (items.Size() == 1 && m_Signature != NSignature::kCentralFileHeader) + if (IsStrangeItem(items[0])) 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) +HRESULT CInArchive::ReadHeaders2(CObjectVector &items, CProgressVirt *progress) { - IsOkHeaders = true; - // m_Signature must be kLocalFileHeaderSignature or - // kEndOfCentralDirSignature + items.Clear(); + + // m_Signature must be kLocalFileHeader or kEcd // m_Position points to next byte after signature + RINOK(Stream->Seek(m_Position, STREAM_SEEK_SET, NULL)); - IsZip64 = false; - items.Clear(); + if (!_inBuffer.Create(1 << 15)) + return E_OUTOFMEMORY; + _inBuffer.SetStream(Stream); - UInt64 cdSize, cdStartOffset; - HRESULT res; - try + bool needReadCd = true; + bool localsWereRead = false; + if (m_Signature == NSignature::kEcd) { - res = ReadCd(items, cdStartOffset, cdSize, progress); + // It must be empty archive or backware archive + // we don't support backware archive still + + const unsigned kBufSize = kEcdSize - 4; + Byte buf[kBufSize]; + SafeReadBytes(buf, kBufSize); + CEcd ecd; + ecd.Parse(buf); + // if (ecd.cdSize != 0) + // Do we need also to support the case where empty zip archive with PK00 uses cdOffset = 4 ?? + if (!ecd.IsEmptyArc()) + return S_FALSE; + + ArcInfo.Base = ArcInfo.MarkerPos; + needReadCd = false; + IsArc = true; // check it: we need more tests? + RINOK(Stream->Seek(ArcInfo.MarkerPos2 + 4, STREAM_SEEK_SET, &m_Position)); } - catch(CInArchiveException &) + + UInt64 cdSize = 0, cdRelatOffset = 0, cdAbsOffset = 0; + HRESULT res = S_OK; + + if (needReadCd) { - res = S_FALSE; + CItemEx firstItem; + // try + { + try + { + if (!ReadLocalItem(firstItem)) + return S_FALSE; + } + catch(CUnexpectEnd &) + { + return S_FALSE; + } + + IsArc = true; + res = ReadCd(items, cdRelatOffset, cdSize, progress); + if (res == S_OK) + m_Signature = ReadUInt32(); + } + // catch() { res = S_FALSE; } + if (res != S_FALSE && res != S_OK) + return res; + + if (res == S_OK && items.Size() == 0) + res = S_FALSE; + + if (res == S_OK) + { + // we can't read local items here to keep _inBufMode state + firstItem.LocalHeaderPos = ArcInfo.MarkerPos2 - ArcInfo.Base; + int index = FindItem(items, firstItem.LocalHeaderPos); + if (index == -1) + res = S_FALSE; + else if (!AreItemsEqual(firstItem, items[index])) + res = S_FALSE; + ArcInfo.CdWasRead = true; + ArcInfo.FirstItemRelatOffset = items[0].LocalHeaderPos; + } } - if (res != S_FALSE && res != S_OK) - return res; - /* - if (res != S_OK) - return res; - res = S_FALSE; - */ + CObjectVector cdItems; - int numCdItems = items.Size(); + bool needSetBase = false; + unsigned numCdItems = items.Size(); + if (res == S_FALSE) { + // CD doesn't match firstItem so we clear items and read Locals. + items.Clear(); + localsWereRead = true; _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; + ArcInfo.Base = ArcInfo.MarkerPos; + RINOK(Stream->Seek(ArcInfo.MarkerPos2, STREAM_SEEK_SET, &m_Position)); + m_Signature = ReadUInt32(); + + RINOK(ReadLocals(items, progress)); + + if (m_Signature != NSignature::kCentralFileHeader) + { + m_Position -= 4; + NoCentralDir = true; + HeadersError = true; + return S_OK; + } + _inBufMode = true; + _inBuffer.Init(); + cdAbsOffset = m_Position - 4; + for (;;) + { + CItemEx cdItem; + RINOK(ReadCdItem(cdItem)); + cdItems.Add(cdItem); + if (progress && cdItems.Size() % 1 == 0) + RINOK(progress->SetCompletedCD(items.Size())); + m_Signature = ReadUInt32(); + if (m_Signature != NSignature::kCentralFileHeader) + break; + } + + cdSize = (m_Position - 4) - cdAbsOffset; + needSetBase = true; + numCdItems = cdItems.Size(); + + if (!cdItems.IsEmpty()) + { + ArcInfo.CdWasRead = true; + ArcInfo.FirstItemRelatOffset = cdItems[0].LocalHeaderPos; + } } CEcd64 ecd64; bool isZip64 = false; - UInt64 zip64EcdStartOffset = m_Position - 4 - ArcInfo.Base; - if (m_Signature == NSignature::kZip64EndOfCentralDir) + UInt64 ecd64AbsOffset = m_Position - 4; + if (m_Signature == NSignature::kEcd64) { IsZip64 = isZip64 = true; UInt64 recordSize = ReadUInt64(); - const int kBufSize = kZip64EcdSize; + const unsigned kBufSize = kEcd64_MainSize; Byte buf[kBufSize]; SafeReadBytes(buf, kBufSize); ecd64.Parse(buf); - Skip(recordSize - kZip64EcdSize); - if (!ReadUInt32(m_Signature)) - return S_FALSE; + Skip64(recordSize - kEcd64_MainSize); + m_Signature = ReadUInt32(); + if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0) - throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported); + return E_NOTIMPL; + + if (needSetBase) + { + ArcInfo.Base = cdAbsOffset - ecd64.cdStartOffset; + cdRelatOffset = ecd64.cdStartOffset; + needSetBase = false; + } + if (ecd64.numEntriesInCDOnThisDisk != numCdItems || ecd64.numEntriesInCD != numCdItems || ecd64.cdSize != cdSize || - (ecd64.cdStartOffset != cdStartOffset && + (ecd64.cdStartOffset != cdRelatOffset && (!items.IsEmpty()))) return S_FALSE; } - if (m_Signature == NSignature::kZip64EndOfCentralDirLocator) + if (m_Signature == NSignature::kEcd64Locator) { + if (!isZip64) + return S_FALSE; /* UInt32 startEndCDDiskNumber = */ ReadUInt32(); - UInt64 endCDStartOffset = ReadUInt64(); + UInt64 ecd64RelatOffset = ReadUInt64(); /* UInt32 numberOfDisks = */ ReadUInt32(); - if (zip64EcdStartOffset != endCDStartOffset) - return S_FALSE; - if (!ReadUInt32(m_Signature)) + if (ecd64AbsOffset != ArcInfo.Base + ecd64RelatOffset) return S_FALSE; + m_Signature = ReadUInt32(); } - if (m_Signature != NSignature::kEndOfCentralDir) + if (m_Signature != NSignature::kEcd) return S_FALSE; - const int kBufSize = kEcdSize - 4; + const unsigned kBufSize = kEcdSize - 4; Byte buf[kBufSize]; SafeReadBytes(buf, kBufSize); CEcd ecd; @@ -849,47 +1188,119 @@ HRESULT CInArchive::ReadHeaders(CObjectVector &items, CProgressVirt *pr COPY_ECD_ITEM_32(cdSize); COPY_ECD_ITEM_32(cdStartOffset); - ReadBuffer(ArcInfo.Comment, ecd.commentSize); + if (needSetBase) + { + ArcInfo.Base = cdAbsOffset - ecd64.cdStartOffset; + cdRelatOffset = ecd64.cdStartOffset; + needSetBase = false; + } + + if (localsWereRead && (UInt64)ArcInfo.Base != ArcInfo.MarkerPos) + { + UInt64 delta = ArcInfo.MarkerPos - ArcInfo.Base; + for (unsigned i = 0; i < items.Size(); i++) + items[i].LocalHeaderPos += delta; + } + + + // ---------- merge Central Directory Items ---------- + + if (!cdItems.IsEmpty()) + { + for (unsigned i = 0; i < cdItems.Size(); i++) + { + const CItemEx &cdItem = cdItems[i]; + int index = FindItem(items, cdItem.LocalHeaderPos); + if (index == -1) + { + items.Add(cdItem); + continue; + } + CItemEx &item = items[index]; + if (item.Name != cdItem.Name + // || item.Name.Len() != cdItem.Name.Len() + || item.PackSize != cdItem.PackSize + || item.Size != cdItem.Size + // item.ExtractVersion != cdItem.ExtractVersion + || !FlagsAreSame(item, cdItem) + || item.Crc != cdItem.Crc) + continue; + + // item.LocalHeaderPos = cdItem.LocalHeaderPos; + // item.Name = cdItem.Name; + item.MadeByVersion = cdItem.MadeByVersion; + item.CentralExtra = cdItem.CentralExtra; + item.InternalAttrib = cdItem.InternalAttrib; + item.ExternalAttrib = cdItem.ExternalAttrib; + item.Comment = cdItem.Comment; + item.FromCentral = cdItem.FromCentral; + } + } if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0) - throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported); - if (numCdItems != items.Size()) - IsOkHeaders = false; - if ((UInt16)ecd64.numEntriesInCDOnThisDisk != ((UInt16)numCdItems) || + return E_NOTIMPL; + + if (isZip64) + { + if (ecd64.numEntriesInCDOnThisDisk != items.Size()) + HeadersError = true; + } + else + { + // old 7-zip could store 32-bit number of CD items to 16-bit field. + if ((UInt16)ecd64.numEntriesInCDOnThisDisk != (UInt16)numCdItems || + (UInt16)ecd64.numEntriesInCDOnThisDisk != (UInt16)items.Size()) + HeadersError = true; + } + + ReadBuffer(ArcInfo.Comment, ecd.commentSize); + _inBufMode = false; + _inBuffer.Free(); + + if ( (UInt16)ecd64.numEntriesInCD != ((UInt16)numCdItems) || (UInt32)ecd64.cdSize != (UInt32)cdSize || - ((UInt32)(ecd64.cdStartOffset) != (UInt32)cdStartOffset && + ((UInt32)(ecd64.cdStartOffset) != (UInt32)cdRelatOffset && (!items.IsEmpty()))) return S_FALSE; - _inBufMode = false; - _inBuffer.Free(); - ArcInfo.FinishPosition = m_Position; + // printf("\nOpen OK"); return S_OK; } +HRESULT CInArchive::ReadHeaders(CObjectVector &items, CProgressVirt *progress) +{ + HRESULT res; + try + { + res = ReadHeaders2(items, progress); + } + catch (const CInBufferException &e) { res = e.ErrorCode; } + catch (const CUnexpectEnd &) + { + if (items.IsEmpty()) + return S_FALSE; + UnexpectedEnd = true; + res = S_OK; + } + catch (...) + { + _inBufMode = false; + throw; + } + ArcInfo.FinishPos = m_Position; + _inBufMode = false; + return res; +} + ISequentialInStream* CInArchive::CreateLimitedStream(UInt64 position, UInt64 size) { CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr stream(streamSpec); - SeekInArchive(ArcInfo.Base + position); - streamSpec->SetStream(m_Stream); + Stream->Seek(ArcInfo.Base + position, STREAM_SEEK_SET, NULL); + streamSpec->SetStream(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 old mode 100755 new mode 100644 index 0565339a..f6b349b1 --- a/CPP/7zip/Archive/Zip/ZipIn.h +++ b/CPP/7zip/Archive/Zip/ZipIn.h @@ -3,121 +3,187 @@ #ifndef __ZIP_IN_H #define __ZIP_IN_H -#include "Common/MyCom.h" +#include "../../../Common/MyCom.h" #include "../../IStream.h" #include "../../Common/InBuffer.h" #include "ZipHeader.h" -#include "ZipItemEx.h" +#include "ZipItem.h" + +API_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size); namespace NArchive { namespace NZip { -class CInArchiveException +class CItemEx: public CItem { public: - enum ECauseType - { - kUnexpectedEndOfArchive = 0, - kArchiceHeaderCRCError, - kFileHeaderCRCError, - kIncorrectArchive, - kDataDescroptorsAreNotSupported, - kMultiVolumeArchiveAreNotSupported, - kReadStreamError, - kSeekStreamError - } - Cause; - CInArchiveException(ECauseType cause): Cause(cause) {} + UInt32 LocalFullHeaderSize; // including Name and Extra + + UInt64 GetLocalFullSize() const + { return LocalFullHeaderSize + PackSize + (HasDescriptor() ? kDataDescriptorSize : 0); } + UInt64 GetDataPosition() const + { return LocalHeaderPos + LocalFullHeaderSize; }; }; -class CInArchiveInfo +struct CInArchiveInfo { -public: - UInt64 Base; - UInt64 StartPosition; - UInt64 FinishPosition; + Int64 Base; /* Base offset of start of archive in stream. + Offsets in headers must be calculated from that Base. + Base is equal to MarkerPos for normal ZIPs. + Base can point to PE stub for some ZIP SFXs. + if CentralDir was read, + Base can be negative, if start of data is not available, + if CentralDirs was not read, + Base = ArcInfo.MarkerPos; */ + + /* The following *Pos variables contain absolute offsets in Stream */ + UInt64 MarkerPos; /* Pos of first signature, it can point to PK00 signature + = MarkerPos2 in most archives + = MarkerPos2 - 4 if there is PK00 signature */ + UInt64 MarkerPos2; // Pos of first local item signature in stream + UInt64 FinishPos; // Finish pos of archive data + UInt64 FileEndPos; // Finish pos of stream + + UInt64 FirstItemRelatOffset; /* Relative offset of first local (read from cd) (relative to Base). + = 0 in most archives + = size of stub for some SFXs */ + bool CdWasRead; + CByteBuffer Comment; - CInArchiveInfo(): Base(0), StartPosition(0) {} - UInt64 GetPhySize() const { return FinishPosition - StartPosition; } + CInArchiveInfo(): Base(0), MarkerPos(0), MarkerPos2(0), FinishPos(0), FileEndPos(0), + FirstItemRelatOffset(0), CdWasRead(false) {} + + UInt64 GetPhySize() const { return FinishPos - Base; } + UInt64 GetEmbeddedStubSize() const + { + if (CdWasRead) + return FirstItemRelatOffset; + return MarkerPos2 - Base; + } + bool ThereIsTail() const { return FileEndPos > FinishPos; } + void Clear() { Base = 0; - StartPosition = 0; - Comment.SetCapacity(0); + MarkerPos = 0; + MarkerPos2 = 0; + FinishPos = 0; + FileEndPos = 0; + + FirstItemRelatOffset = 0; + CdWasRead = false; + + Comment.Free(); } }; -class CProgressVirt +struct CProgressVirt { -public: - STDMETHOD(SetTotal)(UInt64 numFiles) PURE; - STDMETHOD(SetCompleted)(UInt64 numFiles) PURE; + virtual HRESULT SetCompletedLocal(UInt64 numFiles, UInt64 numBytes) = 0; + virtual HRESULT SetTotalCD(UInt64 numFiles) = 0; + virtual HRESULT SetCompletedCD(UInt64 numFiles) = 0; }; struct CCdInfo { - // UInt64 NumEntries; + UInt64 NumEntries; UInt64 Size; UInt64 Offset; + + void ParseEcd(const Byte *p); + void ParseEcd64(const Byte *p); }; class CInArchive { - CMyComPtr m_Stream; + CInBuffer _inBuffer; + bool _inBufMode; 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 IncreaseRealPosition(UInt64 addValue); + 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); + void SafeReadBytes(void *data, unsigned size); + void ReadBuffer(CByteBuffer &buffer, unsigned 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, + void Skip(unsigned num); + void Skip64(UInt64 num); + void ReadFileName(unsigned nameSize, AString &dest); + + bool ReadExtra(unsigned extraSize, CExtraBlock &extraBlock, UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber); - HRESULT ReadLocalItem(CItemEx &item); + bool 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); + HRESULT ReadLocals(CObjectVector &localItems, CProgressVirt *progress); + + HRESULT ReadHeaders2(CObjectVector &items, CProgressVirt *progress); public: CInArchiveInfo ArcInfo; + + bool IsArc; bool IsZip64; - bool IsOkHeaders; - + bool HeadersError; + bool HeadersWarning; + bool ExtraMinorError; + bool UnexpectedEnd; + bool NoCentralDir; + + CMyComPtr Stream; + + void Close(); + HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); HRESULT ReadHeaders(CObjectVector &items, CProgressVirt *progress); + + bool IsOpen() const { return Stream != NULL; } + bool AreThereErrors() const { return HeadersError || UnexpectedEnd; } + + bool IsLocalOffsetOK(const CItemEx &item) const + { + if (item.FromLocal) + return true; + return /* ArcInfo.Base >= 0 || */ ArcInfo.Base + (Int64)item.LocalHeaderPos >= 0; + } + 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; } + UInt64 GetOffsetInStream(UInt64 offsetFromArc) const { return ArcInfo.Base + offsetFromArc; } + + bool CanUpdate() const + { + if (AreThereErrors()) + return false; + if (ArcInfo.Base < 0) + return false; + if ((Int64)ArcInfo.MarkerPos2 < ArcInfo.Base) + return false; + + // 7-zip probably can update archives with embedded stubs. + // we just disable that feature for more safety. + if (ArcInfo.GetEmbeddedStubSize() != 0) + return false; + + if (ArcInfo.ThereIsTail()) + return false; + return true; + } }; }} diff --git a/CPP/7zip/Archive/Zip/ZipItem.cpp b/CPP/7zip/Archive/Zip/ZipItem.cpp old mode 100755 new mode 100644 index ad89f558..ae88944d --- a/CPP/7zip/Archive/Zip/ZipItem.cpp +++ b/CPP/7zip/Archive/Zip/ZipItem.cpp @@ -10,21 +10,13 @@ namespace NArchive { namespace NZip { -bool operator==(const CVersion &v1, const CVersion &v2) -{ - return (v1.Version == v2.Version) && (v1.HostOS == v2.HostOS); -} +using namespace NFileHeader; -bool operator!=(const CVersion &v1, const CVersion &v2) -{ - return !(v1 == v2); -} - -bool CExtraSubBlock::ExtractNtfsTime(int index, FILETIME &ft) const +bool CExtraSubBlock::ExtractNtfsTime(unsigned index, FILETIME &ft) const { ft.dwHighDateTime = ft.dwLowDateTime = 0; - UInt32 size = (UInt32)Data.GetCapacity(); - if (ID != NFileHeader::NExtraID::kNTFS || size < 32) + UInt32 size = (UInt32)Data.Size(); + if (ID != NExtraID::kNTFS || size < 32) return false; const Byte *p = (const Byte *)Data; p += 4; // for reserved @@ -32,13 +24,13 @@ bool CExtraSubBlock::ExtractNtfsTime(int index, FILETIME &ft) const while (size > 4) { UInt16 tag = GetUi16(p); - UInt32 attrSize = GetUi16(p + 2); + unsigned attrSize = GetUi16(p + 2); p += 4; size -= 4; if (attrSize > size) attrSize = size; - if (tag == NFileHeader::NNtfsExtra::kTagTime && attrSize >= 24) + if (tag == NNtfsExtra::kTagTime && attrSize >= 24) { p += 8 * index; ft.dwLowDateTime = GetUi32(p); @@ -51,25 +43,25 @@ bool CExtraSubBlock::ExtractNtfsTime(int index, FILETIME &ft) const return false; } -bool CExtraSubBlock::ExtractUnixTime(bool isCentral, int index, UInt32 &res) const +bool CExtraSubBlock::ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res) const { res = 0; - UInt32 size = (UInt32)Data.GetCapacity(); - if (ID != NFileHeader::NExtraID::kUnixTime || size < 5) + UInt32 size = (UInt32)Data.Size(); + if (ID != NExtraID::kUnixTime || size < 5) return false; const Byte *p = (const Byte *)Data; Byte flags = *p++; size--; if (isCentral) { - if (index != NFileHeader::NUnixTime::kMTime || - (flags & (1 << NFileHeader::NUnixTime::kMTime)) == 0 || + if (index != NUnixTime::kMTime || + (flags & (1 << NUnixTime::kMTime)) == 0 || size < 4) return false; res = GetUi32(p); return true; } - for (int i = 0; i < 3; i++) + for (unsigned i = 0; i < 3; i++) if ((flags & (1 << i)) != 0) { if (size < 4) @@ -96,30 +88,33 @@ bool CItem::IsDir() const return true; if (!FromCentral) return false; - WORD highAttributes = WORD((ExternalAttributes >> 16 ) & 0xFFFF); - switch (MadeByVersion.HostOS) + + UInt16 highAttrib = (UInt16)((ExternalAttrib >> 16 ) & 0xFFFF); + + Byte hostOS = GetHostOS(); + switch (hostOS) { - case NFileHeader::NHostOS::kAMIGA: - switch (highAttributes & NFileHeader::NAmigaAttribute::kIFMT) + case NHostOS::kAMIGA: + switch (highAttrib & NAmigaAttrib::kIFMT) { - case NFileHeader::NAmigaAttribute::kIFDIR: return true; - case NFileHeader::NAmigaAttribute::kIFREG: return false; + case NAmigaAttrib::kIFDIR: return true; + case NAmigaAttrib::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: + case NHostOS::kFAT: + case NHostOS::kNTFS: + case NHostOS::kHPFS: + case NHostOS::kVFAT: + return ((ExternalAttrib & FILE_ATTRIBUTE_DIRECTORY) != 0); + case NHostOS::kAtari: + case NHostOS::kMac: + case NHostOS::kVMS: + case NHostOS::kVM_CMS: + case NHostOS::kAcorn: + case NHostOS::kMVS: return false; // change it throw kUnknownAttributes; - case NFileHeader::NHostOS::kUnix: - return (highAttributes & NFileHeader::NUnixAttribute::kIFDIR) != 0; + case NHostOS::kUnix: + return (highAttrib & NUnixAttrib::kIFDIR) != 0; default: return false; } @@ -127,13 +122,13 @@ bool CItem::IsDir() const UInt32 CItem::GetWinAttrib() const { - DWORD winAttrib = 0; - switch (MadeByVersion.HostOS) + UInt32 winAttrib = 0; + switch (GetHostOS()) { - case NFileHeader::NHostOS::kFAT: - case NFileHeader::NHostOS::kNTFS: + case NHostOS::kFAT: + case NHostOS::kNTFS: if (FromCentral) - winAttrib = ExternalAttributes; + winAttrib = ExternalAttrib; break; } if (IsDir()) // test it; @@ -144,35 +139,15 @@ UInt32 CItem::GetWinAttrib() const bool CItem::GetPosixAttrib(UInt32 &attrib) const { // some archivers can store PosixAttrib in high 16 bits even with HostOS=FAT. - if (FromCentral && MadeByVersion.HostOS == NFileHeader::NHostOS::kUnix) + if (FromCentral && GetHostOS() == NHostOS::kUnix) { - attrib = ExternalAttributes >> 16; + attrib = ExternalAttrib >> 16; return (attrib != 0); } attrib = 0; if (IsDir()) - attrib = NFileHeader::NUnixAttribute::kIFDIR; + attrib = NUnixAttrib::kIFDIR; return false; } -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 old mode 100755 new mode 100644 index 5efd433a..d50c3ae9 --- a/CPP/7zip/Archive/Zip/ZipItem.h +++ b/CPP/7zip/Archive/Zip/ZipItem.h @@ -3,10 +3,12 @@ #ifndef __ARCHIVE_ZIP_ITEM_H #define __ARCHIVE_ZIP_ITEM_H -#include "Common/MyString.h" -#include "Common/Buffer.h" -#include "Common/UTFConvert.h" -#include "Common/StringConvert.h" +#include "../../../../C/CpuArch.h" + +#include "../../../Common/MyBuffer.h" +#include "../../../Common/MyString.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/UTFConvert.h" #include "ZipHeader.h" @@ -19,25 +21,25 @@ struct CVersion 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(bool isCentral, int index, UInt32 &res) const; + + bool ExtractNtfsTime(unsigned index, FILETIME &ft) const; + bool ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res) const; }; -struct CWzAesExtraField +const unsigned k_WzAesExtra_Size = 7; + +struct CWzAesExtra { - UInt16 VendorVersion; // 0x0001 - AE-1, 0x0002 - AE-2, - // UInt16 VendorId; // "AE" - Byte Strength; // 1 - 128-bit , 2 - 192-bit , 3 - 256-bit + UInt16 VendorVersion; // 1: AE-1, 2: AE-2, + // UInt16 VendorId; // 'A' 'E' + Byte Strength; // 1: 128-bit, 2: 192-bit, 3: 256-bit UInt16 Method; - CWzAesExtraField(): VendorVersion(2), Strength(3), Method(0) {} + CWzAesExtra(): VendorVersion(2), Strength(3), Method(0) {} bool NeedCrc() const { return (VendorVersion == 1); } @@ -45,19 +47,21 @@ struct CWzAesExtraField { if (sb.ID != NFileHeader::NExtraID::kWzAES) return false; - if (sb.Data.GetCapacity() < 7) + if (sb.Data.Size() < k_WzAesExtra_Size) return false; const Byte *p = (const Byte *)sb.Data; - VendorVersion = (((UInt16)p[1]) << 8) | p[0]; + VendorVersion = GetUi16(p); if (p[2] != 'A' || p[3] != 'E') return false; Strength = p[4]; - Method = (((UInt16)p[6]) << 16) | p[5]; + // 9.31: The BUG was fixed: + Method = GetUi16(p + 5); return true; } + void SetSubBlock(CExtraSubBlock &sb) const { - sb.Data.SetCapacity(7); + sb.Data.Alloc(k_WzAesExtra_Size); sb.ID = NFileHeader::NExtraID::kWzAES; Byte *p = (Byte *)sb.Data; p[0] = (Byte)VendorVersion; @@ -70,7 +74,7 @@ struct CWzAesExtraField } }; -namespace NStrongCryptoFlags +namespace NStrongCrypto_AlgId { const UInt16 kDES = 0x6601; const UInt16 kRC2old = 0x6602; @@ -85,7 +89,7 @@ namespace NStrongCryptoFlags const UInt16 kRC4 = 0x6801; } -struct CStrongCryptoField +struct CStrongCryptoExtra { UInt16 Format; UInt16 AlgId; @@ -97,12 +101,12 @@ struct CStrongCryptoField if (sb.ID != NFileHeader::NExtraID::kStrongEncrypt) return false; const Byte *p = (const Byte *)sb.Data; - if (sb.Data.GetCapacity() < 8) + if (sb.Data.Size() < 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]; + Format = GetUi16(p + 0); + AlgId = GetUi16(p + 2); + BitLen = GetUi16(p + 4); + Flags = GetUi16(p + 6); return (Format == 2); } }; @@ -110,39 +114,50 @@ struct CStrongCryptoField 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; + FOR_VECTOR (i, SubBlocks) + res += SubBlocks[i].Data.Size() + 2 + 2; return res; } - bool GetWzAesField(CWzAesExtraField &aesField) const + + bool GetWzAes(CWzAesExtra &e) const { - for (int i = 0; i < SubBlocks.Size(); i++) - if (aesField.ParseFromSubBlock(SubBlocks[i])) + FOR_VECTOR (i, SubBlocks) + if (e.ParseFromSubBlock(SubBlocks[i])) return true; return false; } - bool GetStrongCryptoField(CStrongCryptoField &f) const + bool HasWzAes() const + { + CWzAesExtra e; + return GetWzAes(e); + } + + bool GetStrongCrypto(CStrongCryptoExtra &e) const { - for (int i = 0; i < SubBlocks.Size(); i++) - if (f.ParseFromSubBlock(SubBlocks[i])) + FOR_VECTOR (i, SubBlocks) + if (e.ParseFromSubBlock(SubBlocks[i])) return true; return false; } - bool HasWzAesField() const + /* + bool HasStrongCrypto() const { - CWzAesExtraField aesField; - return GetWzAesField(aesField); + CStrongCryptoExtra e; + return GetStrongCrypto(e); } + */ - bool GetNtfsTime(int index, FILETIME &ft) const + bool GetNtfsTime(unsigned index, FILETIME &ft) const { - for (int i = 0; i < SubBlocks.Size(); i++) + FOR_VECTOR (i, SubBlocks) { const CExtraSubBlock &sb = SubBlocks[i]; if (sb.ID == NFileHeader::NExtraID::kNTFS) @@ -151,9 +166,9 @@ struct CExtraBlock return false; } - bool GetUnixTime(bool isCentral, int index, UInt32 &res) const + bool GetUnixTime(bool isCentral, unsigned index, UInt32 &res) const { - for (int i = 0; i < SubBlocks.Size(); i++) + FOR_VECTOR (i, SubBlocks) { const CExtraSubBlock &sb = SubBlocks[i]; if (sb.ID == NFileHeader::NExtraID::kUnixTime) @@ -162,14 +177,6 @@ struct CExtraBlock return false; } - /* - bool HasStrongCryptoField() const - { - CStrongCryptoField f; - return GetStrongCryptoField(f); - } - */ - void RemoveUnknownSubBlocks() { for (int i = SubBlocks.Size() - 1; i >= 0; i--) @@ -182,95 +189,134 @@ struct CExtraBlock class CLocalItem { public: - CVersion ExtractVersion; UInt16 Flags; - UInt16 CompressionMethod; - UInt32 Time; - UInt32 FileCRC; + UInt16 Method; + CVersion ExtractVersion; + + UInt64 Size; UInt64 PackSize; - UInt64 UnPackSize; + UInt32 Time; + UInt32 Crc; 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 IsAesEncrypted() const { return IsEncrypted() && (IsStrongEncrypted() || Method == NFileHeader::NCompressionMethod::kWzAES); }; bool IsLzmaEOS() const { return (Flags & NFileHeader::NFlags::kLzmaEOS) != 0; } + bool HasDescriptor() const { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; } bool IsDir() const; - bool IgnoreItem() const { return false; } - - bool HasDescriptor() const { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; } - UString GetUnicodeString(const AString &s) const + /* + void GetUnicodeString(const AString &s, UString &res) const { - UString res; - if (IsUtf8()) - if (!ConvertUTF8ToUnicode(s, res)) - res.Empty(); - if (res.IsEmpty()) - res = MultiByteToUnicodeString(s, GetCodePage()); - return res; + bool isUtf8 = IsUtf8(); + if (isUtf8) + if (ConvertUTF8ToUnicode(s, res)) + return; + MultiByteToUnicodeString2(res, s, GetCodePage()); } - + */ + private: - void SetFlagBits(int startBitNumber, int numBits, int value); - void SetBitMask(int bitMask, bool enable); + + void SetFlag(unsigned bitMask, bool enable) + { + if (enable) + Flags |= bitMask; + else + Flags &= ~bitMask; + } + public: + void ClearFlags() { Flags = 0; } - void SetEncrypted(bool encrypted); - void SetUtf8(bool isUtf8); + void SetEncrypted(bool encrypted) { SetFlag(NFileHeader::NFlags::kEncrypted, encrypted); } + void SetUtf8(bool isUtf8) { SetFlag(NFileHeader::NFlags::kUtf8, isUtf8); } - WORD GetCodePage() const { return CP_OEMCP; } + UINT GetCodePage() const { return CP_OEMCP; } }; + class CItem: public CLocalItem { public: CVersion MadeByVersion; - UInt16 InternalAttributes; - UInt32 ExternalAttributes; + UInt16 InternalAttrib; + UInt32 ExternalAttrib; - UInt64 LocalHeaderPosition; + UInt64 LocalHeaderPos; - FILETIME NtfsMTime; - FILETIME NtfsATime; - FILETIME NtfsCTime; - CExtraBlock CentralExtra; CByteBuffer Comment; bool FromLocal; bool FromCentral; - bool NtfsTimeIsDefined; + // CItem can be used as CLocalItem. So we must clear unused fields + CItem(): + InternalAttrib(0), + ExternalAttrib(0), + FromLocal(false), + FromCentral(false) + { + MadeByVersion.Version = 0; + MadeByVersion.HostOS = 0; + } + bool IsDir() const; UInt32 GetWinAttrib() const; bool GetPosixAttrib(UInt32 &attrib) const; + Byte GetHostOS() const { return FromCentral ? MadeByVersion.HostOS : ExtractVersion.HostOS; } + + void GetUnicodeString(const AString &s, UString &res, bool useSpecifiedCodePage, UINT codePage) const + { + bool isUtf8 = IsUtf8(); + + #ifdef _WIN32 + if (!isUtf8) + { + if (useSpecifiedCodePage) + isUtf8 = (codePage == CP_UTF8); + else if (GetHostOS() == NFileHeader::NHostOS::kUnix) + { + /* Some ZIP archives in Unix use UTF-8 encoding without Utf8 flag in header. + We try to get name as UTF-8. + Do we need to do it in POSIX version also? */ + isUtf8 = true; + } + } + #endif + + if (isUtf8) + if (ConvertUTF8ToUnicode(s, res)) + return; + MultiByteToUnicodeString2(res, s, useSpecifiedCodePage ? codePage : GetCodePage()); + } + bool IsThereCrc() const { - if (CompressionMethod == NFileHeader::NCompressionMethod::kWzAES) + if (Method == NFileHeader::NCompressionMethod::kWzAES) { - CWzAesExtraField aesField; - if (CentralExtra.GetWzAesField(aesField)) + CWzAesExtra aesField; + if (CentralExtra.GetWzAes(aesField)) return aesField.NeedCrc(); } - return (FileCRC != 0 || !IsDir()); + return (Crc != 0 || !IsDir()); } - WORD GetCodePage() const + UINT GetCodePage() const { - return (WORD)((MadeByVersion.HostOS == NFileHeader::NHostOS::kFAT - || MadeByVersion.HostOS == NFileHeader::NHostOS::kNTFS - ) ? CP_OEMCP : CP_ACP); + Byte hostOS = GetHostOS(); + return (UINT)(( + hostOS == NFileHeader::NHostOS::kFAT || + hostOS == NFileHeader::NHostOS::kNTFS) ? CP_OEMCP : CP_ACP); } - CItem() : FromLocal(false), FromCentral(false), NtfsTimeIsDefined(false) {} }; }} diff --git a/CPP/7zip/Archive/Zip/ZipItemEx.h b/CPP/7zip/Archive/Zip/ZipItemEx.h deleted file mode 100755 index ab62cdbb..00000000 --- a/CPP/7zip/Archive/Zip/ZipItemEx.h +++ /dev/null @@ -1,34 +0,0 @@ -// 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 old mode 100755 new mode 100644 index aa82143e..2a1ba2c4 --- a/CPP/7zip/Archive/Zip/ZipOut.cpp +++ b/CPP/7zip/Archive/Zip/ZipOut.cpp @@ -9,80 +9,93 @@ namespace NArchive { namespace NZip { -void COutArchive::Create(IOutStream *outStream) +HRESULT COutArchive::Create(IOutStream *outStream) { + m_CurPos = 0; if (!m_OutBuffer.Create(1 << 16)) - throw CSystemException(E_OUTOFMEMORY); + return E_OUTOFMEMORY; m_Stream = outStream; m_OutBuffer.SetStream(outStream); m_OutBuffer.Init(); - m_BasePosition = 0; + + return m_Stream->Seek(0, STREAM_SEEK_CUR, &m_Base); +} + +void COutArchive::MoveCurPos(UInt64 distanceToMove) +{ + m_CurPos += distanceToMove; // test overflow } -void COutArchive::MoveBasePosition(UInt64 distanceToMove) +void COutArchive::SeekToRelatPos(UInt64 offset) { - m_BasePosition += distanceToMove; // test overflow + HRESULT res = m_Stream->Seek(m_Base + offset, STREAM_SEEK_SET, NULL); + if (res != S_OK) + throw CSystemException(res); } -void COutArchive::PrepareWriteCompressedDataZip64(UInt16 fileNameLength, bool isZip64, bool aesEncryption) +void COutArchive::PrepareWriteCompressedDataZip64(unsigned fileNameLen, 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; + m_ExtraSize += 4 + k_WzAesExtra_Size; + m_LocalFileHeaderSize = kLocalHeaderSize + fileNameLen + m_ExtraSize; } -void COutArchive::PrepareWriteCompressedData(UInt16 fileNameLength, UInt64 unPackSize, bool aesEncryption) +void COutArchive::PrepareWriteCompressedData(unsigned fileNameLen, 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); + // We use Zip64, if unPackSize size is larger than 0xF8000000 to support + // cases when compressed size can be about 3% larger than uncompressed size + + PrepareWriteCompressedDataZip64(fileNameLen, unPackSize >= (UInt32)0xF8000000, aesEncryption); } -void COutArchive::PrepareWriteCompressedData2(UInt16 fileNameLength, UInt64 unPackSize, UInt64 packSize, bool aesEncryption) +#define DOES_NEED_ZIP64(v) (v >= (UInt32)0xFFFFFFFF) + +void COutArchive::PrepareWriteCompressedData2(unsigned fileNameLen, UInt64 unPackSize, UInt64 packSize, bool aesEncryption) { - bool isUnPack64 = unPackSize >= 0xFFFFFFFF; - bool isPack64 = packSize >= 0xFFFFFFFF; - bool isZip64 = isPack64 || isUnPack64; - PrepareWriteCompressedDataZip64(fileNameLength, isZip64, aesEncryption); + bool isZip64 = + DOES_NEED_ZIP64(unPackSize) || + DOES_NEED_ZIP64(packSize); + PrepareWriteCompressedDataZip64(fileNameLen, isZip64, aesEncryption); } void COutArchive::WriteBytes(const void *buffer, UInt32 size) { m_OutBuffer.WriteBytes(buffer, size); - m_BasePosition += size; + m_CurPos += size; } -void COutArchive::WriteByte(Byte b) +void COutArchive::Write8(Byte b) { - WriteBytes(&b, 1); + m_OutBuffer.WriteByte(b); + m_CurPos++; } -void COutArchive::WriteUInt16(UInt16 value) +void COutArchive::Write16(UInt16 val) { for (int i = 0; i < 2; i++) { - WriteByte((Byte)value); - value >>= 8; + Write8((Byte)val); + val >>= 8; } } -void COutArchive::WriteUInt32(UInt32 value) +void COutArchive::Write32(UInt32 val) { for (int i = 0; i < 4; i++) { - WriteByte((Byte)value); - value >>= 8; + Write8((Byte)val); + val >>= 8; } } -void COutArchive::WriteUInt64(UInt64 value) +void COutArchive::Write64(UInt64 val) { for (int i = 0; i < 8; i++) { - WriteByte((Byte)value); - value >>= 8; + Write8((Byte)val); + val >>= 8; } } @@ -90,178 +103,181 @@ void COutArchive::WriteExtra(const CExtraBlock &extra) { if (extra.SubBlocks.Size() != 0) { - for (int i = 0; i < extra.SubBlocks.Size(); i++) + FOR_VECTOR (i, extra.SubBlocks) { const CExtraSubBlock &subBlock = extra.SubBlocks[i]; - WriteUInt16(subBlock.ID); - WriteUInt16((UInt16)subBlock.Data.GetCapacity()); - WriteBytes(subBlock.Data, (UInt32)subBlock.Data.GetCapacity()); + Write16(subBlock.ID); + Write16((UInt16)subBlock.Data.Size()); + WriteBytes(subBlock.Data, (UInt32)subBlock.Data.Size()); } } } -void COutArchive::SeekTo(UInt64 offset) +void COutArchive::WriteCommonItemInfo(const CLocalItem &item, bool isZip64) { - HRESULT res = m_Stream->Seek(offset, STREAM_SEEK_SET, NULL); - if (res != S_OK) - throw CSystemException(res); + { + Byte ver = item.ExtractVersion.Version; + if (isZip64 && ver < NFileHeader::NCompressionMethod::kExtractVersion_Zip64) + ver = NFileHeader::NCompressionMethod::kExtractVersion_Zip64; + Write8(ver); + } + Write8(item.ExtractVersion.HostOS); + Write16(item.Flags); + Write16(item.Method); + Write32(item.Time); + Write32(item.Crc); } +#define WRITE_32_VAL_SPEC(__v, __isZip64) Write32((__isZip64) ? 0xFFFFFFFF : (UInt32)(__v)); + void COutArchive::WriteLocalHeader(const CLocalItem &item) { - SeekTo(m_BasePosition); + SeekToCurPos(); - bool isZip64 = m_IsZip64 || item.PackSize >= 0xFFFFFFFF || item.UnPackSize >= 0xFFFFFFFF; + bool isZip64 = m_IsZip64 || + DOES_NEED_ZIP64(item.PackSize) || + DOES_NEED_ZIP64(item.Size); - 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()); + Write32(NSignature::kLocalFileHeader); + WriteCommonItemInfo(item, isZip64); + + WRITE_32_VAL_SPEC(item.PackSize, isZip64); + WRITE_32_VAL_SPEC(item.Size, isZip64); + + Write16((UInt16)item.Name.Len()); { - UInt16 localExtraSize = (UInt16)((isZip64 ? (4 + 16): 0) + item.LocalExtra.GetSize()); - if (localExtraSize > m_ExtraSize) + UInt16 localExtraSize = (UInt16)((isZip64 ? (4 + 8 + 8): 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()); + Write16((UInt16)m_ExtraSize); + WriteBytes((const char *)item.Name, item.Name.Len()); - UInt32 extraPos = 0; if (isZip64) { - extraPos += 4 + 16; - WriteUInt16(NFileHeader::NExtraID::kZip64); - WriteUInt16(16); - WriteUInt64(item.UnPackSize); - WriteUInt64(item.PackSize); + Write16(NFileHeader::NExtraID::kZip64); + Write16(8 + 8); + Write64(item.Size); + Write64(item.PackSize); } WriteExtra(item.LocalExtra); - extraPos += (UInt32)item.LocalExtra.GetSize(); - for (; extraPos < m_ExtraSize; extraPos++) - WriteByte(0); + + // Why don't we write NTFS timestamps to local header? + // Probably we want to reduce size of archive? m_OutBuffer.FlushWithCheck(); - MoveBasePosition(item.PackSize); - SeekTo(m_BasePosition); + MoveCurPos(item.PackSize); } -void COutArchive::WriteCentralHeader(const CItem &item) +void COutArchive::WriteCentralHeader(const CItemOut &item) { - bool isUnPack64 = item.UnPackSize >= 0xFFFFFFFF; - bool isPack64 = item.PackSize >= 0xFFFFFFFF; - bool isPosition64 = item.LocalHeaderPosition >= 0xFFFFFFFF; - bool isZip64 = isPack64 || isUnPack64 || isPosition64; + bool isUnPack64 = DOES_NEED_ZIP64(item.Size); + bool isPack64 = DOES_NEED_ZIP64(item.PackSize); + bool isPosition64 = DOES_NEED_ZIP64(item.LocalHeaderPos); + 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)); + Write32(NSignature::kCentralFileHeader); + Write8(item.MadeByVersion.Version); + Write8(item.MadeByVersion.HostOS); + + WriteCommonItemInfo(item, isZip64); + + WRITE_32_VAL_SPEC(item.PackSize, isPack64); + WRITE_32_VAL_SPEC(item.Size, isUnPack64); + + Write16((UInt16)item.Name.Len()); + + 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()); + const UInt16 centralExtraSize = (UInt16)( + (isZip64 ? 4 + zip64ExtraSize : 0) + + (item.NtfsTimeIsDefined ? 4 + kNtfsExtraSize : 0) + + item.CentralExtra.GetSize()); + + Write16(centralExtraSize); // test it; + Write16((UInt16)item.Comment.Size()); + Write16(0); // DiskNumberStart; + Write16(item.InternalAttrib); + Write32(item.ExternalAttrib); + WRITE_32_VAL_SPEC(item.LocalHeaderPos, isPosition64); + WriteBytes((const char *)item.Name, item.Name.Len()); + if (isZip64) { - WriteUInt16(NFileHeader::NExtraID::kZip64); - WriteUInt16(zip64ExtraSize); - if(isUnPack64) - WriteUInt64(item.UnPackSize); - if(isPack64) - WriteUInt64(item.PackSize); - if(isPosition64) - WriteUInt64(item.LocalHeaderPosition); + Write16(NFileHeader::NExtraID::kZip64); + Write16(zip64ExtraSize); + if (isUnPack64) + Write64(item.Size); + if (isPack64) + Write64(item.PackSize); + if (isPosition64) + Write64(item.LocalHeaderPos); } + 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); + Write16(NFileHeader::NExtraID::kNTFS); + Write16(kNtfsExtraSize); + Write32(0); // reserved + Write16(NFileHeader::NNtfsExtra::kTagTime); + Write16(8 * 3); + WriteNtfsTime(item.Ntfs_MTime); + WriteNtfsTime(item.Ntfs_ATime); + WriteNtfsTime(item.Ntfs_CTime); } + WriteExtra(item.CentralExtra); - if (item.Comment.GetCapacity() > 0) - WriteBytes(item.Comment, (UInt32)item.Comment.GetCapacity()); + if (item.Comment.Size() > 0) + WriteBytes(item.Comment, (UInt32)item.Comment.Size()); } -void COutArchive::WriteCentralDir(const CObjectVector &items, const CByteBuffer *comment) +void COutArchive::WriteCentralDir(const CObjectVector &items, const CByteBuffer *comment) { - SeekTo(m_BasePosition); + SeekToCurPos(); - UInt64 cdOffset = GetCurrentPosition(); - for(int i = 0; i < items.Size(); i++) + UInt64 cdOffset = GetCurPos(); + FOR_VECTOR (i, items) WriteCentralHeader(items[i]); - UInt64 cd64EndOffset = GetCurrentPosition(); + UInt64 cd64EndOffset = GetCurPos(); UInt64 cdSize = cd64EndOffset - cdOffset; - bool cdOffset64 = cdOffset >= 0xFFFFFFFF; - bool cdSize64 = cdSize >= 0xFFFFFFFF; + bool cdOffset64 = DOES_NEED_ZIP64(cdOffset); + bool cdSize64 = DOES_NEED_ZIP64(cdSize); bool items64 = items.Size() >= 0xFFFF; bool isZip64 = (cdOffset64 || cdSize64 || items64); + + // isZip64 = true; // to test Zip64 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 + Write32(NSignature::kEcd64); + Write64(kEcd64_MainSize); + Write16(45); // made by version + Write16(45); // extract version + Write32(0); // ThisDiskNumber = 0; + Write32(0); // StartCentralDirectoryDiskNumber;; + Write64((UInt64)items.Size()); + Write64((UInt64)items.Size()); + Write64((UInt64)cdSize); + Write64((UInt64)cdOffset); + + Write32(NSignature::kEcd64Locator); + Write32(0); // number of the disk with the start of the zip64 end of central directory + Write64(cd64EndOffset); + Write32(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); + + Write32(NSignature::kEcd); + Write16(0); // ThisDiskNumber = 0; + Write16(0); // StartCentralDirectoryDiskNumber; + Write16((UInt16)(items64 ? 0xFFFF: items.Size())); + Write16((UInt16)(items64 ? 0xFFFF: items.Size())); + + WRITE_32_VAL_SPEC(cdSize, cdSize64); + WRITE_32_VAL_SPEC(cdOffset, cdOffset64); + + UInt32 commentSize = (UInt32)(comment ? comment->Size() : 0); + Write16((UInt16)commentSize); if (commentSize > 0) WriteBytes((const Byte *)*comment, commentSize); m_OutBuffer.FlushWithCheck(); @@ -271,14 +287,21 @@ void COutArchive::CreateStreamForCompressing(IOutStream **outStream) { COffsetOutStream *streamSpec = new COffsetOutStream; CMyComPtr tempStream(streamSpec); - streamSpec->Init(m_Stream, m_BasePosition + m_LocalFileHeaderSize); + streamSpec->Init(m_Stream, m_Base + m_CurPos + m_LocalFileHeaderSize); *outStream = tempStream.Detach(); } +/* void COutArchive::SeekToPackedDataPosition() { SeekTo(m_BasePosition + m_LocalFileHeaderSize); } +*/ + +void COutArchive::SeekToCurPos() +{ + SeekToRelatPos(m_CurPos); +} void COutArchive::CreateStreamForCopying(ISequentialOutStream **outStream) { diff --git a/CPP/7zip/Archive/Zip/ZipOut.h b/CPP/7zip/Archive/Zip/ZipOut.h old mode 100755 new mode 100644 index 2f6349e5..eaaa0320 --- a/CPP/7zip/Archive/Zip/ZipOut.h +++ b/CPP/7zip/Archive/Zip/ZipOut.h @@ -3,7 +3,7 @@ #ifndef __ZIP_OUT_H #define __ZIP_OUT_H -#include "Common/MyCom.h" +#include "../../../Common/MyCom.h" #include "../../IStream.h" #include "../../Common/OutBuffer.h" @@ -14,41 +14,73 @@ namespace NArchive { namespace NZip { // can throw CSystemException and COutBufferException - + +class CItemOut: public CItem +{ +public: + FILETIME Ntfs_MTime; + FILETIME Ntfs_ATime; + FILETIME Ntfs_CTime; + bool NtfsTimeIsDefined; + + // It's possible that NtfsTime is not defined, but there is NtfsTime in Extra. + + CItemOut(): NtfsTimeIsDefined(false) {} +}; + class COutArchive { CMyComPtr m_Stream; COutBuffer m_OutBuffer; - UInt64 m_BasePosition; + UInt64 m_Base; // Base of arc (offset in output Stream) + UInt64 m_CurPos; // Curent position in archive (relative from m_Base) + UInt32 m_LocalFileHeaderSize; UInt32 m_ExtraSize; bool m_IsZip64; + void SeekToRelatPos(UInt64 offset); + void WriteBytes(const void *buffer, UInt32 size); - void WriteByte(Byte b); - void WriteUInt16(UInt16 value); - void WriteUInt32(UInt32 value); - void WriteUInt64(UInt64 value); + void Write8(Byte b); + void Write16(UInt16 val); + void Write32(UInt32 val); + void Write64(UInt64 val); + void WriteNtfsTime(const FILETIME &ft) + { + Write32(ft.dwLowDateTime); + Write32(ft.dwHighDateTime); + } - void WriteExtraHeader(const CItem &item); - void WriteCentralHeader(const CItem &item); void WriteExtra(const CExtraBlock &extra); - void SeekTo(UInt64 offset); + void WriteCommonItemInfo(const CLocalItem &item, bool isZip64); + void WriteCentralHeader(const CItemOut &item); + + void PrepareWriteCompressedDataZip64(unsigned fileNameLen, bool isZip64, bool aesEncryption); + 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); + HRESULT Create(IOutStream *outStream); + + void MoveCurPos(UInt64 distanceToMove); + UInt64 GetCurPos() const { return m_CurPos; }; + + void SeekToCurPos(); + + void PrepareWriteCompressedData(unsigned fileNameLen, UInt64 unPackSize, bool aesEncryption); + void PrepareWriteCompressedData2(unsigned fileNameLen, UInt64 unPackSize, UInt64 packSize, bool aesEncryption); void WriteLocalHeader(const CLocalItem &item); - void WriteCentralDir(const CObjectVector &items, const CByteBuffer *comment); + void WriteLocalHeader_And_SeekToNextFile(const CLocalItem &item) + { + WriteLocalHeader(item); + SeekToCurPos(); + } + + void WriteCentralDir(const CObjectVector &items, const CByteBuffer *comment); void CreateStreamForCompressing(IOutStream **outStream); void CreateStreamForCopying(ISequentialOutStream **outStream); - void SeekToPackedDataPosition(); }; }} diff --git a/CPP/7zip/Archive/Zip/ZipRegister.cpp b/CPP/7zip/Archive/Zip/ZipRegister.cpp old mode 100755 new mode 100644 index 3e7aade8..545e76c6 --- a/CPP/7zip/Archive/Zip/ZipRegister.cpp +++ b/CPP/7zip/Archive/Zip/ZipRegister.cpp @@ -5,14 +5,27 @@ #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 + +namespace NArchive { +namespace NZip { + +IMP_CreateArcIn +IMP_CreateArcOut static CArcInfo g_ArcInfo = - { L"zip", L"zip jar xpi odt ods docx xlsx", 0, 1, { 0x50, 0x4B, 0x03, 0x04 }, 4, false, CreateArc, CreateArcOut }; + { "zip", "zip zipx jar xpi odt ods docx xlsx epub", 0, 1, + 3 + 4 + 4 + 6, + { + 4, 0x50, 0x4B, 0x03, 0x04, + 4, 0x50, 0x4B, 0x05, 0x06, + 6, 0x50, 0x4B, 0x30, 0x30, 0x50, 0x4B, + }, + 0, + NArcInfoFlags::kFindSignature | + NArcInfoFlags::kMultiSignature | + NArcInfoFlags::kUseGlobalOffset, + REF_CreateArc_Pair, IsArc_Zip }; REGISTER_ARC(Zip) + +}} diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp old mode 100755 new mode 100644 index a91364be..2978e387 --- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp +++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp @@ -4,12 +4,12 @@ #include "../../../../C/Alloc.h" -#include "Common/AutoPtr.h" -#include "Common/Defs.h" -#include "Common/StringConvert.h" +#include "../../../Common/AutoPtr.h" +#include "../../../Common/Defs.h" +#include "../../../Common/StringConvert.h" -#include "Windows/Defs.h" -#include "Windows/Thread.h" +#include "../../../Windows/Defs.h" +#include "../../../Windows/Thread.h" #include "../../Common/CreateCoder.h" #include "../../Common/LimitedStreams.h" @@ -44,12 +44,12 @@ static const Byte kExtractHostOS = kHostOS; static const Byte kMethodForDirectory = NFileHeader::NCompressionMethod::kStored; -static HRESULT CopyBlockToArchive(ISequentialInStream *inStream, +static HRESULT CopyBlockToArchive(ISequentialInStream *inStream, UInt64 size, COutArchive &outArchive, ICompressProgressInfo *progress) { CMyComPtr outStream; outArchive.CreateStreamForCopying(&outStream); - return NCompress::CopyStream(inStream, outStream, progress); + return NCompress::CopyStream_ExactSize(inStream, outStream, size, progress); } static HRESULT WriteRange(IInStream *inStream, COutArchive &outArchive, @@ -57,13 +57,7 @@ static HRESULT WriteRange(IInStream *inStream, COutArchive &outArchive, { 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)); + RINOK(CopyBlockToArchive(inStream, range.Size, outArchive, progress)); return progress->SetRatioInfo(&range.Size, &range.Size); } @@ -71,42 +65,42 @@ static void SetFileHeader( COutArchive &archive, const CCompressionMethodMode &options, const CUpdateItem &ui, - CItem &item) + CItemOut &item) { - item.UnPackSize = ui.Size; + item.Size = ui.Size; bool isDir; item.ClearFlags(); - if (ui.NewProperties) + if (ui.NewProps) { isDir = ui.IsDir; item.Name = ui.Name; item.SetUtf8(ui.IsUtf8); - item.ExternalAttributes = ui.Attributes; + item.ExternalAttrib = ui.Attrib; item.Time = ui.Time; - item.NtfsMTime = ui.NtfsMTime; - item.NtfsATime = ui.NtfsATime; - item.NtfsCTime = ui.NtfsCTime; + item.Ntfs_MTime = ui.Ntfs_MTime; + item.Ntfs_ATime = ui.Ntfs_ATime; + item.Ntfs_CTime = ui.Ntfs_CTime; item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined; } else isDir = item.IsDir(); - item.LocalHeaderPosition = archive.GetCurrentPosition(); + item.LocalHeaderPos = archive.GetCurPos(); item.MadeByVersion.HostOS = kMadeByHostOS; item.MadeByVersion.Version = NFileHeader::NCompressionMethod::kMadeByProgramVersion; item.ExtractVersion.HostOS = kExtractHostOS; - item.InternalAttributes = 0; // test it + item.InternalAttrib = 0; // test it item.SetEncrypted(!isDir && options.PasswordIsDefined); if (isDir) { item.ExtractVersion.Version = NFileHeader::NCompressionMethod::kExtractVersion_Dir; - item.CompressionMethod = kMethodForDirectory; + item.Method = kMethodForDirectory; item.PackSize = 0; - item.FileCRC = 0; // test it + item.Crc = 0; // test it } } @@ -114,9 +108,9 @@ static void SetItemInfoFromCompressingResult(const CCompressingResult &compressi bool isAesMode, Byte aesKeyMode, CItem &item) { item.ExtractVersion.Version = compressingResult.ExtractVersion; - item.CompressionMethod = compressingResult.Method; - item.FileCRC = compressingResult.CRC; - item.UnPackSize = compressingResult.UnpackSize; + item.Method = compressingResult.Method; + item.Crc = compressingResult.CRC; + item.Size = compressingResult.UnpackSize; item.PackSize = compressingResult.PackSize; item.LocalExtra.Clear(); @@ -124,11 +118,11 @@ static void SetItemInfoFromCompressingResult(const CCompressingResult &compressi if (isAesMode) { - CWzAesExtraField wzAesField; + CWzAesExtra wzAesField; wzAesField.Strength = aesKeyMode; wzAesField.Method = compressingResult.Method; - item.CompressionMethod = NFileHeader::NCompressionMethod::kWzAES; - item.FileCRC = 0; + item.Method = NFileHeader::NCompressionMethod::kWzAES; + item.Crc = 0; CExtraSubBlock sb; wzAesField.SetSubBlock(sb); item.LocalExtra.SubBlocks.Add(sb); @@ -142,10 +136,7 @@ static THREAD_FUNC_DECL CoderThread(void *threadCoderInfo); struct CThreadInfo { - #ifdef EXTERNAL_CODECS - CMyComPtr _codecsInfo; - const CObjectVector *_externalCodecs; - #endif + DECL_EXTERNAL_CODECS_LOC_VARS2; NWindows::CThread Thread; NWindows::NSynchronization::CAutoResetEvent CompressEvent; @@ -202,9 +193,7 @@ void CThreadInfo::WaitAndCode() if (ExitThread) return; Result = Coder.Compress( - #ifdef EXTERNAL_CODECS - _codecsInfo, _externalCodecs, - #endif + EXTERNAL_CODECS_LOC_VARS InStream, OutStream, Progress, CompressingResult); if (Result == S_OK && Progress) Result = Progress->SetRatioInfo(&CompressingResult.UnpackSize, &CompressingResult.PackSize); @@ -224,7 +213,7 @@ public: CObjectVector Threads; ~CThreads() { - for (int i = 0; i < Threads.Size(); i++) + FOR_VECTOR (i, Threads) Threads[i].StopWaitClose(); } }; @@ -245,7 +234,7 @@ public: CMemRefs(CMemBlockManagerMt *manager): Manager(manager) {} ; ~CMemRefs() { - for (int i = 0; i < Refs.Size(); i++) + FOR_VECTOR (i, Refs) Refs[i].FreeOpt(Manager); } }; @@ -335,69 +324,74 @@ STDMETHODIMP CMtProgressMixer::SetRatioInfo(const UInt64 *inSize, const UInt64 * #endif -static HRESULT UpdateItemOldData(COutArchive &archive, - IInStream *inStream, - const CUpdateItem &ui, CItemEx &item, +static HRESULT UpdateItemOldData( + COutArchive &archive, + CInArchive *inArchive, + const CItemEx &itemEx, + const CUpdateItem &ui, + CItemOut &item, /* bool izZip64, */ ICompressProgressInfo *progress, UInt64 &complexity) { - if (ui.NewProperties) + if (ui.NewProps) { if (item.HasDescriptor()) return E_NOTIMPL; // use old name size. // CUpdateRange range(item.GetLocalExtraPosition(), item.LocalExtraSize + item.PackSize); - CUpdateRange range(item.GetDataPosition(), item.PackSize); + CUpdateRange range(inArchive->GetOffsetInStream(itemEx.GetDataPosition()), itemEx.PackSize); - // item.ExternalAttributes = ui.Attributes; - // Test it + // we keep ExternalAttrib and some another properties from old archive + // item.ExternalAttrib = ui.Attrib; + 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.Ntfs_MTime = ui.Ntfs_MTime; + item.Ntfs_ATime = ui.Ntfs_ATime; + item.Ntfs_CTime = ui.Ntfs_CTime; 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; + item.LocalHeaderPos = archive.GetCurPos(); + + archive.PrepareWriteCompressedData2(item.Name.Len(), item.Size, item.PackSize, item.LocalExtra.HasWzAes()); archive.WriteLocalHeader(item); + RINOK(WriteRange(inArchive->Stream, archive, range, progress)); + complexity += range.Size; } else { - CUpdateRange range(item.LocalHeaderPosition, item.GetLocalFullSize()); + CUpdateRange range(inArchive->GetOffsetInStream(itemEx.LocalHeaderPos), itemEx.GetLocalFullSize()); // set new header position - item.LocalHeaderPosition = archive.GetCurrentPosition(); + item.LocalHeaderPos = archive.GetCurPos(); - RINOK(WriteRange(inStream, archive, range, progress)); + RINOK(WriteRange(inArchive->Stream, archive, range, progress)); complexity += range.Size; - archive.MoveBasePosition(range.Size); + archive.MoveCurPos(range.Size); } return S_OK; } static void WriteDirHeader(COutArchive &archive, const CCompressionMethodMode *options, - const CUpdateItem &ui, CItemEx &item) + const CUpdateItem &ui, CItemOut &item) { SetFileHeader(archive, *options, ui, item); - archive.PrepareWriteCompressedData((UInt16)item.Name.Length(), ui.Size, options->IsRealAesMode()); - archive.WriteLocalHeader(item); + archive.PrepareWriteCompressedData(item.Name.Len(), ui.Size, + // options->IsRealAesMode() + false // fixed 9.31 + ); + archive.WriteLocalHeader_And_SeekToNextFile(item); } static HRESULT Update2St( DECL_EXTERNAL_CODECS_LOC_VARS COutArchive &archive, CInArchive *inArchive, - IInStream *inStream, const CObjectVector &inputItems, const CObjectVector &updateItems, const CCompressionMethodMode *options, @@ -410,26 +404,29 @@ static HRESULT Update2St( CAddCommon compressor(*options); - CObjectVector items; + CObjectVector items; UInt64 unpackSizeTotal = 0, packSizeTotal = 0; - for (int itemIndex = 0; itemIndex < updateItems.Size(); itemIndex++) + FOR_VECTOR (itemIndex, updateItems) { lps->InSize = unpackSizeTotal; lps->OutSize = packSizeTotal; RINOK(lps->SetCur()); const CUpdateItem &ui = updateItems[itemIndex]; - CItemEx item; - if (!ui.NewProperties || !ui.NewData) + CItemEx itemEx; + CItemOut item; + + if (!ui.NewProps || !ui.NewData) { - item = inputItems[ui.IndexInArchive]; - if (inArchive->ReadLocalItemAfterCdItemFull(item) != S_OK) + itemEx = inputItems[ui.IndexInArc]; + if (inArchive->ReadLocalItemAfterCdItemFull(itemEx) != S_OK) return E_NOTIMPL; + (CItem &)item = itemEx; } if (ui.NewData) { - bool isDir = ((ui.NewProperties) ? ui.IsDir : item.IsDir()); + bool isDir = ((ui.NewProps) ? ui.IsDir : item.IsDir()); if (isDir) { WriteDirHeader(archive, options, ui, item); @@ -445,10 +442,12 @@ static HRESULT Update2St( continue; } RINOK(res); + if (!fileInStream) + return E_INVALIDARG; // file Size can be 64-bit !!! SetFileHeader(archive, *options, ui, item); - archive.PrepareWriteCompressedData((UInt16)item.Name.Length(), ui.Size, options->IsRealAesMode()); + archive.PrepareWriteCompressedData(item.Name.Len(), ui.Size, options->IsRealAesMode()); CCompressingResult compressingResult; CMyComPtr outStream; archive.CreateStreamForCompressing(&outStream); @@ -456,9 +455,9 @@ static HRESULT Update2St( EXTERNAL_CODECS_LOC_VARS fileInStream, outStream, progress, compressingResult)); SetItemInfoFromCompressingResult(compressingResult, options->IsRealAesMode(), options->AesKeyMode, item); - archive.WriteLocalHeader(item); + archive.WriteLocalHeader_And_SeekToNextFile(item); RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); - unpackSizeTotal += item.UnPackSize; + unpackSizeTotal += item.Size; packSizeTotal += item.PackSize; } } @@ -466,12 +465,12 @@ static HRESULT Update2St( { UInt64 complexity = 0; lps->SendRatio = false; - RINOK(UpdateItemOldData(archive, inStream, ui, item, progress, complexity)); + RINOK(UpdateItemOldData(archive, inArchive, itemEx, ui, item, progress, complexity)); lps->SendRatio = true; lps->ProgressOffset += complexity; } items.Add(item); - lps->ProgressOffset += NFileHeader::kLocalBlockSize; + lps->ProgressOffset += kLocalHeaderSize; } lps->InSize = unpackSizeTotal; lps->OutSize = packSizeTotal; @@ -484,7 +483,6 @@ static HRESULT Update2( DECL_EXTERNAL_CODECS_LOC_VARS COutArchive &archive, CInArchive *inArchive, - IInStream *inStream, const CObjectVector &inputItems, const CObjectVector &updateItems, const CCompressionMethodMode *options, @@ -495,7 +493,7 @@ static HRESULT Update2( UInt64 numFilesToCompress = 0; UInt64 numBytesToCompress = 0; - int i; + unsigned i; for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; @@ -511,18 +509,18 @@ static HRESULT Update2( } else { - CItemEx inputItem = inputItems[ui.IndexInArchive]; + CItemEx inputItem = inputItems[ui.IndexInArc]; if (inArchive->ReadLocalItemAfterCdItemFull(inputItem) != S_OK) return E_NOTIMPL; complexity += inputItem.GetLocalFullSize(); // complexity += inputItem.GetCentralExtraPlusCommentSize(); } - complexity += NFileHeader::kLocalBlockSize; - complexity += NFileHeader::kCentralBlockSize; + complexity += kLocalHeaderSize; + complexity += kCentralHeaderSize; } if (comment) - complexity += comment->GetCapacity(); + complexity += comment->Size(); complexity++; // end of central updateCallback->SetTotal(complexity); @@ -540,6 +538,9 @@ static HRESULT Update2( UInt32 numThreads = options->NumThreads; if (numThreads > kNumMaxThreads) numThreads = kNumMaxThreads; + if (numThreads < 1) + numThreads = 1; + const size_t kMemPerThread = (1 << 25); const size_t kBlockSize = 1 << 16; @@ -549,16 +550,18 @@ static HRESULT Update2( if (numFilesToCompress <= 1) mtMode = false; + Byte method = options->MethodSequence.Front(); if (!mtMode) { - if (numThreads < 2) - if (options2.MethodInfo.FindProp(NCoderPropID::kNumThreads) < 0 && - options2.NumThreadsWasChanged) - options2.MethodInfo.AddNumThreadsProp(1); + if (options2.MethodInfo.FindProp(NCoderPropID::kNumThreads) < 0) + { + // fixed for 9.31. bzip2 default is just one thread. + if (options2.NumThreadsWasChanged || method == NFileHeader::NCompressionMethod::kBZip2) + options2.MethodInfo.AddNumThreadsProp(numThreads); + } } else { - Byte method = options->MethodSequence.Front(); if (method == NFileHeader::NCompressionMethod::kStored && !options->PasswordIsDefined) numThreads = 1; if (method == NFileHeader::NCompressionMethod::kBZip2) @@ -594,13 +597,13 @@ static HRESULT Update2( #endif return Update2St( EXTERNAL_CODECS_LOC_VARS - archive, inArchive, inStream, + archive, inArchive, inputItems, updateItems, &options2, comment, updateCallback); #ifndef _7ZIP_ST - CObjectVector items; + CObjectVector items; CMtProgressMixer *mtProgressMixerSpec = new CMtProgressMixer; CMyComPtr progress = mtProgressMixerSpec; @@ -629,8 +632,7 @@ static HRESULT Update2( { CThreadInfo &threadInfo = threads.Threads[i]; #ifdef EXTERNAL_CODECS - threadInfo._codecsInfo = codecsInfo; - threadInfo._externalCodecs = externalCodecs; + threadInfo.__externalCodecs = __externalCodecs; #endif RINOK(threadInfo.CreateEvents()); threadInfo.OutStreamSpec = new COutMemStream(&memManager); @@ -643,9 +645,9 @@ static HRESULT Update2( RINOK(threadInfo.CreateThread()); } } - int mtItemIndex = 0; + unsigned mtItemIndex = 0; - int itemIndex = 0; + unsigned itemIndex = 0; int lastRealStreamItemIndex = -1; while (itemIndex < updateItems.Size()) @@ -655,17 +657,19 @@ static HRESULT Update2( const CUpdateItem &ui = updateItems[mtItemIndex++]; if (!ui.NewData) continue; - CItemEx item; - if (ui.NewProperties) + CItemEx itemEx; + CItemOut item; + if (ui.NewProps) { if (ui.IsDir) continue; } else { - item = inputItems[ui.IndexInArchive]; - if (inArchive->ReadLocalItemAfterCdItemFull(item) != S_OK) + itemEx = inputItems[ui.IndexInArc]; + if (inArchive->ReadLocalItemAfterCdItemFull(itemEx) != S_OK) return E_NOTIMPL; + (CItem &)item = itemEx; if (item.IsDir()) continue; } @@ -676,13 +680,15 @@ static HRESULT Update2( if (res == S_FALSE) { complexity += ui.Size; - complexity += NFileHeader::kLocalBlockSize; + complexity += kLocalHeaderSize; mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity); RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); refs.Refs[mtItemIndex - 1].Skip = true; continue; } RINOK(res); + if (!fileInStream) + return E_INVALIDARG; RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); } @@ -719,29 +725,31 @@ static HRESULT Update2( const CUpdateItem &ui = updateItems[itemIndex]; - CItemEx item; - if (!ui.NewProperties || !ui.NewData) + CItemEx itemEx; + CItemOut item; + if (!ui.NewProps || !ui.NewData) { - item = inputItems[ui.IndexInArchive]; - if (inArchive->ReadLocalItemAfterCdItemFull(item) != S_OK) + itemEx = inputItems[ui.IndexInArc]; + if (inArchive->ReadLocalItemAfterCdItemFull(itemEx) != S_OK) return E_NOTIMPL; + (CItem &)item = itemEx; } if (ui.NewData) { - bool isDir = ((ui.NewProperties) ? ui.IsDir : item.IsDir()); + bool isDir = ((ui.NewProps) ? ui.IsDir : item.IsDir()); if (isDir) { WriteDirHeader(archive, options, ui, item); } else { - if (lastRealStreamItemIndex < itemIndex) + if (lastRealStreamItemIndex < (int)itemIndex) { lastRealStreamItemIndex = itemIndex; SetFileHeader(archive, *options, ui, item); // file Size can be 64-bit !!! - archive.PrepareWriteCompressedData((UInt16)item.Name.Length(), ui.Size, options->IsRealAesMode()); + archive.PrepareWriteCompressedData(item.Name.Len(), ui.Size, options->IsRealAesMode()); } CMemBlocks2 &memRef = refs.Refs[itemIndex]; @@ -750,10 +758,13 @@ static HRESULT Update2( CMyComPtr outStream; archive.CreateStreamForCompressing(&outStream); memRef.WriteToStream(memManager.GetBlockSize(), outStream); + SetFileHeader(archive, *options, ui, item); + // the BUG was fixed in 9.26: + // SetItemInfoFromCompressingResult must be after SetFileHeader + // to write correct Size. SetItemInfoFromCompressingResult(memRef.CompressingResult, options->IsRealAesMode(), options->AesKeyMode, item); - SetFileHeader(archive, *options, ui, item); - archive.WriteLocalHeader(item); + archive.WriteLocalHeader_And_SeekToNextFile(item); // RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); memRef.FreeOpt(&memManager); } @@ -783,10 +794,10 @@ static HRESULT Update2( { RINOK(threadInfo.OutStreamSpec->WriteToRealStream()); threadInfo.OutStreamSpec->ReleaseOutStream(); + SetFileHeader(archive, *options, ui, item); SetItemInfoFromCompressingResult(threadInfo.CompressingResult, options->IsRealAesMode(), options->AesKeyMode, item); - SetFileHeader(archive, *options, ui, item); - archive.WriteLocalHeader(item); + archive.WriteLocalHeader_And_SeekToNextFile(item); } else { @@ -801,10 +812,10 @@ static HRESULT Update2( } else { - RINOK(UpdateItemOldData(archive, inStream, ui, item, progress, complexity)); + RINOK(UpdateItemOldData(archive, inArchive, itemEx, ui, item, progress, complexity)); } items.Add(item); - complexity += NFileHeader::kLocalBlockSize; + complexity += kLocalHeaderSize; mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity); itemIndex++; } @@ -993,15 +1004,18 @@ STDMETHODIMP CCacheOutStream::Write(const void *data, UInt32 size, UInt32 *proce STDMETHODIMP CCacheOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - switch(seekOrigin) + switch (seekOrigin) { - case STREAM_SEEK_SET: _virtPos = offset; break; - case STREAM_SEEK_CUR: _virtPos += offset; break; - case STREAM_SEEK_END: _virtPos = _virtSize + offset; break; + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: offset += _virtSize; break; default: return STG_E_INVALIDFUNCTION; } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = offset; if (newPosition) - *newPosition = _virtPos; + *newPosition = offset; return S_OK; } @@ -1029,16 +1043,33 @@ HRESULT Update( const CObjectVector &inputItems, const CObjectVector &updateItems, ISequentialOutStream *seqOutStream, - CInArchive *inArchive, + CInArchive *inArchive, bool removeSfx, CCompressionMethodMode *compressionMethodMode, IArchiveUpdateCallback *updateCallback) { + if (inArchive) + { + if (!inArchive->CanUpdate()) + return E_NOTIMPL; + } + + CMyComPtr outStream; { CMyComPtr outStreamReal; seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStreamReal); if (!outStreamReal) return E_NOTIMPL; + + if (inArchive) + { + if (inArchive->ArcInfo.Base > 0 && !removeSfx) + { + RINOK(inArchive->Stream->Seek(0, STREAM_SEEK_SET, NULL)); + RINOK(NCompress::CopyStream_ExactSize(inArchive->Stream, outStreamReal, inArchive->ArcInfo.Base, NULL)); + } + } + CCacheOutStream *cacheStream = new CCacheOutStream(); outStream = cacheStream; if (!cacheStream->Allocate()) @@ -1046,32 +1077,23 @@ HRESULT Update( 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) + RINOK(outArchive.Create(outStream)); + + if (inArchive) { - CMyComPtr inStream; - inStream.Attach(inArchive->CreateLimitedStream(0, inArchive->ArcInfo.StartPosition)); - RINOK(CopyBlockToArchive(inStream, outArchive, NULL)); - outArchive.MoveBasePosition(inArchive->ArcInfo.StartPosition); + if ((Int64)inArchive->ArcInfo.MarkerPos2 > inArchive->ArcInfo.Base) + { + RINOK(inArchive->Stream->Seek(inArchive->ArcInfo.Base, STREAM_SEEK_SET, NULL)); + UInt64 embStubSize = inArchive->ArcInfo.MarkerPos2 - inArchive->ArcInfo.Base; + RINOK(NCompress::CopyStream_ExactSize(inArchive->Stream, outStream, embStubSize, NULL)); + outArchive.MoveCurPos(embStubSize); + } } - */ - CMyComPtr inStream; - if (inArchive) - inStream.Attach(inArchive->CreateStream()); return Update2( EXTERNAL_CODECS_LOC_VARS - outArchive, inArchive, inStream, + outArchive, inArchive, inputItems, updateItems, compressionMethodMode, inArchive ? &inArchive->ArcInfo.Comment : NULL, diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.h b/CPP/7zip/Archive/Zip/ZipUpdate.h old mode 100755 new mode 100644 index eee16738..747c07bc --- a/CPP/7zip/Archive/Zip/ZipUpdate.h +++ b/CPP/7zip/Archive/Zip/ZipUpdate.h @@ -1,4 +1,4 @@ -// Zip/Update.h +// ZipUpdate.h #ifndef __ZIP_UPDATE_H #define __ZIP_UPDATE_H @@ -18,28 +18,29 @@ struct CUpdateRange { UInt64 Position; UInt64 Size; - CUpdateRange() {}; + + // CUpdateRange() {}; CUpdateRange(UInt64 position, UInt64 size): Position(position), Size(size) {}; }; struct CUpdateItem { bool NewData; - bool NewProperties; + bool NewProps; bool IsDir; bool NtfsTimeIsDefined; bool IsUtf8; - int IndexInArchive; + int IndexInArc; int IndexInClient; - UInt32 Attributes; + UInt32 Attrib; UInt32 Time; UInt64 Size; AString Name; // bool Commented; // CUpdateRange CommentRange; - FILETIME NtfsMTime; - FILETIME NtfsATime; - FILETIME NtfsCTime; + FILETIME Ntfs_MTime; + FILETIME Ntfs_ATime; + FILETIME Ntfs_CTime; CUpdateItem(): NtfsTimeIsDefined(false), IsUtf8(false), Size(0) {} }; @@ -49,7 +50,7 @@ HRESULT Update( const CObjectVector &inputItems, const CObjectVector &updateItems, ISequentialOutStream *seqOutStream, - CInArchive *inArchive, + CInArchive *inArchive, bool removeSfx, CCompressionMethodMode *compressionMethodMode, IArchiveUpdateCallback *updateCallback); diff --git a/CPP/7zip/Archive/makefile b/CPP/7zip/Archive/makefile old mode 100755 new mode 100644 diff --git a/CPP/7zip/Asm.mak b/CPP/7zip/Asm.mak old mode 100755 new mode 100644 index 4ab94f15..4f77dddf --- a/CPP/7zip/Asm.mak +++ b/CPP/7zip/Asm.mak @@ -1,3 +1,4 @@ +!IFDEF ASM_OBJS !IF "$(CPU)" == "ARM" $(ASM_OBJS): ../../../../Asm/Arm/$(*B).asm $(COMPL_ASM) @@ -5,3 +6,4 @@ $(ASM_OBJS): ../../../../Asm/Arm/$(*B).asm $(ASM_OBJS): ../../../../Asm/x86/$(*B).asm $(COMPL_ASM) !ENDIF +!ENDIF diff --git a/CPP/7zip/Bundles/Alone/Alone.dsp b/CPP/7zip/Bundles/Alone/Alone.dsp old mode 100755 new mode 100644 index 5e0e3e51..017a3f1b --- a/CPP/7zip/Bundles/Alone/Alone.dsp +++ b/CPP/7zip/Bundles/Alone/Alone.dsp @@ -44,7 +44,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /Gz /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gz /MT /W4 /WX /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 @@ -52,7 +52,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /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 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Alone - Win32 Debug" @@ -69,7 +69,8 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /Gz /MDd /W4 /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 +# SUBTRACT CPP /WX # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe @@ -77,7 +78,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za.exe" /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" @@ -94,7 +95,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /Yu"StdAfx.h" /FD /c -# ADD CPP /nologo /Gz /MD /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 CPP /nologo /Gz /MD /W4 /WX /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 @@ -103,7 +104,7 @@ BSC32=bscmake.exe 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 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zan.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" @@ -121,7 +122,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c -# ADD CPP /nologo /Gz /MDd /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 CPP /nologo /Gz /MDd /W4 /WX /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 @@ -129,7 +130,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /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 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zan.exe" /pdbtype:sept !ENDIF @@ -176,6 +177,14 @@ SOURCE=..\..\UI\Console\ExtractCallbackConsole.h # End Source File # Begin Source File +SOURCE=..\..\UI\Console\HashCon.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\HashCon.h +# End Source File +# Begin Source File + SOURCE=..\..\UI\Console\List.cpp # End Source File # Begin Source File @@ -269,6 +278,10 @@ SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File +SOURCE=..\..\..\Common\CrcReg.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File @@ -337,6 +350,10 @@ SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\Sha256Reg.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\StdInStream.cpp # End Source File # Begin Source File @@ -387,6 +404,10 @@ SOURCE=..\..\..\Common\Wildcard.cpp SOURCE=..\..\..\Common\Wildcard.h # End Source File +# Begin Source File + +SOURCE=..\..\..\Common\XzCrc64Reg.cpp +# End Source File # End Group # Begin Group "Windows" @@ -409,11 +430,11 @@ SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Error.cpp +SOURCE=..\..\..\Windows\ErrorMsg.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Error.h +SOURCE=..\..\..\Windows\ErrorMsg.h # End Source File # Begin Source File @@ -449,6 +470,14 @@ 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 @@ -469,11 +498,11 @@ SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\PropVariantConversions.cpp +SOURCE=..\..\..\Windows\PropVariantConv.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\PropVariantConversions.h +SOURCE=..\..\..\Windows\PropVariantConv.h # End Source File # Begin Source File @@ -497,11 +526,11 @@ SOURCE=..\..\..\Windows\Thread.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Time.cpp +SOURCE=..\..\..\Windows\TimeUtils.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Time.h +SOURCE=..\..\..\Windows\TimeUtils.h # End Source File # End Group # Begin Group "7zip Common" @@ -649,6 +678,18 @@ SOURCE=..\..\Common\ProgressUtils.h # End Source File # Begin Source File +SOURCE=..\..\Common\PropId.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\RegisterArc.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\RegisterCodec.h +# End Source File +# Begin Source File + SOURCE=..\..\Common\StreamBinder.cpp # End Source File # Begin Source File @@ -673,6 +714,14 @@ SOURCE=..\..\Common\StreamUtils.h # End Source File # Begin Source File +SOURCE=..\..\Common\UniqBlocks.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\UniqBlocks.h +# End Source File +# Begin Source File + SOURCE=..\..\Common\VirtThread.cpp # End Source File # Begin Source File @@ -1404,10 +1453,6 @@ 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 @@ -1685,6 +1730,14 @@ SOURCE=..\..\UI\Common\ExtractingFilePath.h # End Source File # Begin Source File +SOURCE=..\..\UI\Common\HashCalc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\HashCalc.h +# End Source File +# Begin Source File + SOURCE=..\..\UI\Common\LoadCodecs.cpp # End Source File # Begin Source File @@ -1853,6 +1906,10 @@ SOURCE=..\..\Crypto\MyAes.h # End Source File # Begin Source File +SOURCE=..\..\Crypto\MyAesReg.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Crypto\Pbkdf2HmacSha1.cpp !IF "$(CFG)" == "Alone - Win32 Release" @@ -1905,6 +1962,10 @@ SOURCE=..\..\Crypto\Sha1.h # End Source File # Begin Source File +SOURCE=..\..\Crypto\Sha1Reg.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Crypto\WzAes.cpp # End Source File # Begin Source File @@ -2035,6 +2096,30 @@ SOURCE=..\..\..\..\C\XzCrc64.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\XzCrc64Opt.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\XzDec.c !IF "$(CFG)" == "Alone - Win32 Release" diff --git a/CPP/7zip/Bundles/Alone/Alone.dsw b/CPP/7zip/Bundles/Alone/Alone.dsw old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/Alone/StdAfx.cpp b/CPP/7zip/Bundles/Alone/StdAfx.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/Alone/StdAfx.h b/CPP/7zip/Bundles/Alone/StdAfx.h old mode 100755 new mode 100644 index 2e4be10b..2854ff3e --- a/CPP/7zip/Bundles/Alone/StdAfx.h +++ b/CPP/7zip/Bundles/Alone/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" -#include "../../../Common/NewHandler.h" +#include "../../../Common/Common.h" #endif diff --git a/CPP/7zip/Bundles/Alone/afxres.h b/CPP/7zip/Bundles/Alone/afxres.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/Alone/makefile b/CPP/7zip/Bundles/Alone/makefile old mode 100755 new mode 100644 index a99c61ec..15139714 --- a/CPP/7zip/Bundles/Alone/makefile +++ b/CPP/7zip/Bundles/Alone/makefile @@ -1,26 +1,16 @@ PROG = 7za.exe MY_CONSOLE = 1 -CFLAGS = $(CFLAGS) -I ../../../ +CFLAGS = $(CFLAGS) !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\CrcReg.obj \ $O\IntToString.obj \ $O\ListFileUtils.obj \ $O\NewHandler.obj \ @@ -32,20 +22,24 @@ COMMON_OBJS = \ $O\UTFConvert.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ + $O\XzCrc64Reg.obj \ + $O\Sha256Reg.obj \ WIN_OBJS = \ $O\DLL.obj \ - $O\Error.obj \ + $O\ErrorMsg.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ + $O\FileLink.obj \ $O\FileName.obj \ + $O\FileSystem.obj \ $O\MemoryLock.obj \ $O\PropVariant.obj \ - $O\PropVariantConversions.obj \ + $O\PropVariantConv.obj \ $O\Synchronization.obj \ $O\System.obj \ - $O\Time.obj \ + $O\TimeUtils.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ @@ -65,32 +59,13 @@ WIN_OBJS = \ $O\OutMemStream.obj \ $O\ProgressMt.obj \ $O\ProgressUtils.obj \ + $O\PropId.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ + $O\UniqBlocks.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 \ - AR_OBJS = \ $O\Bz2Handler.obj \ $O\DeflateProps.obj \ @@ -151,7 +126,6 @@ ZIP_OBJS = \ $O\ZipAddCommon.obj \ $O\ZipHandler.obj \ $O\ZipHandlerOut.obj \ - $O\ZipHeader.obj \ $O\ZipIn.obj \ $O\ZipItem.obj \ $O\ZipOut.obj \ @@ -204,9 +178,11 @@ CRYPTO_OBJS = \ $O\7zAesRegister.obj \ $O\HmacSha1.obj \ $O\MyAes.obj \ + $O\MyAesReg.obj \ $O\Pbkdf2HmacSha1.obj \ $O\RandGen.obj \ $O\Sha1.obj \ + $O\Sha1Reg.obj \ $O\WzAes.obj \ $O\ZipCrypto.obj \ $O\ZipStrong.obj \ @@ -238,70 +214,14 @@ C_OBJS = \ $O\Sort.obj \ $O\Threads.obj \ $O\Xz.obj \ - $O\XzCrc64.obj \ $O\XzDec.obj \ $O\XzEnc.obj \ $O\XzIn.obj \ +!include "../../UI/Console/Console.mak" + !include "../../Aes.mak" !include "../../Crc.mak" +!include "../../Crc64.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" +!include "../../7zip.mak" diff --git a/CPP/7zip/Bundles/Alone/resource.rc b/CPP/7zip/Bundles/Alone/resource.rc old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/Alone7z/StdAfx.cpp b/CPP/7zip/Bundles/Alone7z/StdAfx.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/Alone7z/StdAfx.h b/CPP/7zip/Bundles/Alone7z/StdAfx.h old mode 100755 new mode 100644 index 2e4be10b..2854ff3e --- a/CPP/7zip/Bundles/Alone7z/StdAfx.h +++ b/CPP/7zip/Bundles/Alone7z/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" -#include "../../../Common/NewHandler.h" +#include "../../../Common/Common.h" #endif diff --git a/CPP/7zip/Bundles/Alone7z/makefile b/CPP/7zip/Bundles/Alone7z/makefile old mode 100755 new mode 100644 index 8de884f7..9f7ef516 --- a/CPP/7zip/Bundles/Alone7z/makefile +++ b/CPP/7zip/Bundles/Alone7z/makefile @@ -1,52 +1,43 @@ PROG = 7zr.exe MY_CONSOLE = 1 -CFLAGS = $(CFLAGS) -I ../../../ \ - -D_NO_CRYPTO \ +CFLAGS = $(CFLAGS) \ !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\CrcReg.obj \ $O\IntToString.obj \ $O\ListFileUtils.obj \ $O\NewHandler.obj \ $O\StdInStream.obj \ $O\StdOutStream.obj \ $O\MyString.obj \ + $O\Sha256Reg.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\UTFConvert.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ + $O\XzCrc64Reg.obj \ WIN_OBJS = \ $O\DLL.obj \ - $O\Error.obj \ + $O\ErrorMsg.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ + $O\FileLink.obj \ $O\FileName.obj \ $O\MemoryLock.obj \ $O\PropVariant.obj \ - $O\PropVariantConversions.obj \ + $O\PropVariantConv.obj \ $O\Synchronization.obj \ $O\System.obj \ - $O\Time.obj \ + $O\TimeUtils.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ @@ -63,32 +54,13 @@ WIN_OBJS = \ $O\OffsetStream.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ + $O\PropId.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ + $O\UniqBlocks.obj \ $O\VirtThread.obj \ -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 \ - AR_OBJS = \ $O\LzmaHandler.obj \ $O\SplitHandler.obj \ @@ -143,6 +115,13 @@ COMPRESS_OBJS = \ $O\LzmaEncoder.obj \ $O\LzmaRegister.obj \ +CRYPTO_OBJS = \ + $O\7zAes.obj \ + $O\7zAesRegister.obj \ + $O\MyAes.obj \ + $O\MyAesReg.obj \ + $O\RandGen.obj \ + C_OBJS = \ $O\7zStream.obj \ $O\Alloc.obj \ @@ -159,54 +138,17 @@ C_OBJS = \ $O\LzmaEnc.obj \ $O\MtCoder.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 "../../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 "../../UI/Console/Console.mak" +!include "../../Aes.mak" +!include "../../Crc.mak" +!include "../../Crc64.mak" -!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" +!include "../../7zip.mak" diff --git a/CPP/7zip/Bundles/Alone7z/resource.rc b/CPP/7zip/Bundles/Alone7z/resource.rc old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/Fm/FM.dsp b/CPP/7zip/Bundles/Fm/FM.dsp old mode 100755 new mode 100644 index dded8b1d..1f214b33 --- a/CPP/7zip/Bundles/Fm/FM.dsp +++ b/CPP/7zip/Bundles/Fm/FM.dsp @@ -45,7 +45,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /Gz /MD /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 CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" @@ -72,7 +72,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /Gz /MDd /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 CPP /nologo /Gz /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" @@ -99,7 +99,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"StdAfx.h" /FD /c -# ADD CPP /nologo /Gz /MD /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 CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" @@ -127,7 +127,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c -# ADD CPP /nologo /Gz /MDd /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 CPP /nologo /Gz /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" @@ -493,6 +493,14 @@ SOURCE=..\..\UI\FileManager\DialogSize.h # End Source File # Begin Source File +SOURCE=..\..\UI\FileManager\LinkDialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\LinkDialog.h +# End Source File +# Begin Source File + SOURCE=..\..\UI\FileManager\ListViewDialog.cpp # End Source File # Begin Source File @@ -629,6 +637,10 @@ SOURCE=..\..\Common\ProgressUtils.h # End Source File # Begin Source File +SOURCE=..\..\Common\PropId.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Common\StreamObjects.cpp # End Source File # Begin Source File @@ -643,6 +655,14 @@ SOURCE=..\..\Common\StreamUtils.cpp SOURCE=..\..\Common\StreamUtils.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\UniqBlocks.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\UniqBlocks.h +# End Source File # End Group # Begin Group "C" @@ -683,6 +703,10 @@ SOURCE=..\..\..\..\C\7zCrcOpt.c # End Source File # Begin Source File +SOURCE=..\..\..\..\C\7zTypes.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File @@ -887,11 +911,11 @@ SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Error.cpp +SOURCE=..\..\..\Windows\ErrorMsg.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Error.h +SOURCE=..\..\..\Windows\ErrorMsg.h # End Source File # Begin Source File @@ -919,6 +943,10 @@ SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File +SOURCE=..\..\..\Windows\FileLink.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Windows\FileMapping.h # End Source File # Begin Source File @@ -943,11 +971,11 @@ SOURCE=..\..\..\Windows\Handle.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Memory.cpp +SOURCE=..\..\..\Windows\MemoryGlobal.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Memory.h +SOURCE=..\..\..\Windows\MemoryGlobal.h # End Source File # Begin Source File @@ -975,11 +1003,11 @@ SOURCE=..\..\..\Windows\Net.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Process.cpp +SOURCE=..\..\..\Windows\ProcessUtils.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Process.h +SOURCE=..\..\..\Windows\ProcessUtils.h # End Source File # Begin Source File @@ -991,11 +1019,11 @@ SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\PropVariantConversions.cpp +SOURCE=..\..\..\Windows\PropVariantConv.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\PropVariantConversions.h +SOURCE=..\..\..\Windows\PropVariantConv.h # End Source File # Begin Source File @@ -1015,11 +1043,11 @@ SOURCE=..\..\..\Windows\ResourceString.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Security.cpp +SOURCE=..\..\..\Windows\SecurityUtils.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Security.h +SOURCE=..\..\..\Windows\SecurityUtils.h # End Source File # Begin Source File @@ -1051,15 +1079,11 @@ SOURCE=..\..\..\Windows\Thread.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Time.cpp +SOURCE=..\..\..\Windows\TimeUtils.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Time.h -# End Source File -# Begin Source File - -SOURCE=..\..\..\Windows\Timer.h +SOURCE=..\..\..\Windows\TimeUtils.h # End Source File # Begin Source File @@ -1075,15 +1099,15 @@ SOURCE=..\..\..\Windows\Window.h # PROP Default_Filter "" # Begin Source File -SOURCE=..\..\..\Common\Buffer.h +SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Common\CommandLineParser.cpp +SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File -SOURCE=..\..\..\Common\CommandLineParser.h +SOURCE=..\..\..\Common\Common.h # End Source File # Begin Source File @@ -1095,6 +1119,10 @@ SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File +SOURCE=..\..\..\Common\CrcReg.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File @@ -1123,6 +1151,14 @@ SOURCE=..\..\..\Common\Lang.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\ListFileUtils.cpp # End Source File # Begin Source File @@ -1131,6 +1167,10 @@ SOURCE=..\..\..\Common\ListFileUtils.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\MyBuffer.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File @@ -1167,6 +1207,10 @@ SOURCE=..\..\..\Common\Random.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\Sha256Reg.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File @@ -1183,14 +1227,6 @@ 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 @@ -1326,6 +1362,14 @@ SOURCE=..\..\Common\FilterCoder.h # End Source File # Begin Source File +SOURCE=..\..\UI\Common\HashCalc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\HashCalc.h +# End Source File +# Begin Source File + SOURCE=..\..\UI\Common\IFileExtractCallback.h # End Source File # Begin Source File @@ -1558,6 +1602,14 @@ SOURCE=..\..\UI\GUI\ExtractGUI.h # End Source File # Begin Source File +SOURCE=..\..\UI\GUI\HashGUI.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\GUI\HashGUI.h +# End Source File +# Begin Source File + SOURCE=..\..\UI\GUI\UpdateCallbackGUI.cpp # End Source File # Begin Source File @@ -1606,6 +1658,18 @@ SOURCE=..\..\IPassword.h SOURCE=..\..\IProgress.h # End Source File # End Group +# Begin Group "Crypto" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Crypto\Sha1.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Sha1.h +# End Source File +# End Group # Begin Source File SOURCE=..\..\UI\FileManager\7zFM.exe.manifest diff --git a/CPP/7zip/Bundles/Fm/FM.dsw b/CPP/7zip/Bundles/Fm/FM.dsw old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/Fm/StdAfx.cpp b/CPP/7zip/Bundles/Fm/StdAfx.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/Fm/StdAfx.h b/CPP/7zip/Bundles/Fm/StdAfx.h old mode 100755 new mode 100644 index b09de592..d2301e48 --- a/CPP/7zip/Bundles/Fm/StdAfx.h +++ b/CPP/7zip/Bundles/Fm/StdAfx.h @@ -3,21 +3,14 @@ #ifndef __STDAFX_H #define __STDAFX_H -#define _WIN32_WINNT 0x0400 +// #define _WIN32_WINNT 0x0400 +#define _WIN32_WINNT 0x0500 +#define WINVER _WIN32_WINNT -// it's for Windows NT supporting (MENUITEMINFOW) -#define WINVER 0x0400 +#include "../../../Common/Common.h" -#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 old mode 100755 new mode 100644 index b8f9133f..fd211a1d --- a/CPP/7zip/Bundles/Fm/makefile +++ b/CPP/7zip/Bundles/Fm/makefile @@ -1,5 +1,5 @@ PROG = 7zFM.exe -CFLAGS = $(CFLAGS) -I ../../../ \ +CFLAGS = $(CFLAGS) \ -DLANG \ -DNEW_FOLDER_INTERFACE \ -DEXTERNAL_CODECS \ @@ -11,121 +11,32 @@ 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 \ +!include "../Format7zF/Arc.mak" -COMMON_OBJS = \ +!include "../../UI/FileManager/FM.mak" + +COMMON_OBJS = $(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 = \ +WIN_OBJS = $(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\ErrorMsg.obj \ + $O\FileLink.obj \ + $O\MemoryGlobal.obj \ $O\MemoryLock.obj \ $O\Menu.obj \ - $O\Process.obj \ - $O\PropVariant.obj \ - $O\PropVariantConversions.obj \ - $O\PropVariantUtils.obj \ + $O\ProcessUtils.obj \ + $O\PropVariantConv.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 \ @@ -133,73 +44,9 @@ WIN_CTRL_OBJS = \ $O\PropertyPage.obj \ $O\Window2.obj \ -7ZIP_COMMON_OBJS = \ - $O\CreateCoder.obj \ - $O\CWrappers.obj \ +7ZIP_COMMON_OBJS = $(7ZIP_COMMON_OBJS) \ $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\UefiHandler.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 \ @@ -212,6 +59,7 @@ UI_COMMON_OBJS = \ $O\EnumDirItems.obj \ $O\Extract.obj \ $O\ExtractingFilePath.obj \ + $O\HashCalc.obj \ $O\LoadCodecs.obj \ $O\OpenArchive.obj \ $O\PropIDUtils.obj \ @@ -226,15 +74,6 @@ UI_COMMON_OBJS = \ $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 \ @@ -245,292 +84,9 @@ GUI_OBJS = \ $O\CompressDialog.obj \ $O\ExtractDialog.obj \ $O\ExtractGUI.obj \ + $O\HashGUI.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" +!include "../../7zip.mak" diff --git a/CPP/7zip/Bundles/Fm/resource.rc b/CPP/7zip/Bundles/Fm/resource.rc old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/Format7z/StdAfx.cpp b/CPP/7zip/Bundles/Format7z/StdAfx.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/Format7z/StdAfx.h b/CPP/7zip/Bundles/Format7z/StdAfx.h old mode 100755 new mode 100644 index 2e4be10b..2854ff3e --- a/CPP/7zip/Bundles/Format7z/StdAfx.h +++ b/CPP/7zip/Bundles/Format7z/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" -#include "../../../Common/NewHandler.h" +#include "../../../Common/Common.h" #endif diff --git a/CPP/7zip/Bundles/Format7z/makefile b/CPP/7zip/Bundles/Format7z/makefile old mode 100755 new mode 100644 index 3b04c5e7..01e63e67 --- a/CPP/7zip/Bundles/Format7z/makefile +++ b/CPP/7zip/Bundles/Format7z/makefile @@ -1,14 +1,16 @@ PROG = 7za.dll DEF_FILE = ../../Archive/Archive2.def -CFLAGS = $(CFLAGS) -I ../../../ \ +CFLAGS = $(CFLAGS) \ -DDEFLATE_EXTRACT_ONLY \ -DBZIP2_EXTRACT_ONLY \ COMMON_OBJS = \ $O\CRC.obj \ + $O\CrcReg.obj \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ + $O\Sha256Reg.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ @@ -18,6 +20,7 @@ WIN_OBJS = \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ + $O\FileName.obj \ $O\PropVariant.obj \ $O\Synchronization.obj \ $O\System.obj \ @@ -34,9 +37,11 @@ WIN_OBJS = \ $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ + $O\PropId.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ + $O\UniqBlocks.obj \ $O\VirtThread.obj \ AR_OBJS = \ @@ -85,12 +90,10 @@ COMPRESS_OBJS = \ $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 \ @@ -108,6 +111,7 @@ CRYPTO_OBJS = \ $O\7zAes.obj \ $O\7zAesRegister.obj \ $O\MyAes.obj \ + $O\MyAesReg.obj \ $O\RandGen.obj \ C_OBJS = \ @@ -136,45 +140,4 @@ C_OBJS = \ !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" +!include "../../7zip.mak" diff --git a/CPP/7zip/Bundles/Format7z/resource.rc b/CPP/7zip/Bundles/Format7z/resource.rc old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/Format7zExtract/StdAfx.cpp b/CPP/7zip/Bundles/Format7zExtract/StdAfx.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/Format7zExtract/StdAfx.h b/CPP/7zip/Bundles/Format7zExtract/StdAfx.h old mode 100755 new mode 100644 index 2e4be10b..2854ff3e --- a/CPP/7zip/Bundles/Format7zExtract/StdAfx.h +++ b/CPP/7zip/Bundles/Format7zExtract/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" -#include "../../../Common/NewHandler.h" +#include "../../../Common/Common.h" #endif diff --git a/CPP/7zip/Bundles/Format7zExtract/makefile b/CPP/7zip/Bundles/Format7zExtract/makefile old mode 100755 new mode 100644 index 5598adc2..86a76e3d --- a/CPP/7zip/Bundles/Format7zExtract/makefile +++ b/CPP/7zip/Bundles/Format7zExtract/makefile @@ -1,13 +1,15 @@ PROG = 7zxa.dll DEF_FILE = ../../Archive/Archive2.def -CFLAGS = $(CFLAGS) -I ../../../ \ +CFLAGS = $(CFLAGS) \ -DEXTRACT_ONLY \ COMMON_OBJS = \ $O\CRC.obj \ + $O\CrcReg.obj \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ + $O\Sha256Reg.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ @@ -29,6 +31,7 @@ WIN_OBJS = \ $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ + $O\PropId.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ @@ -89,6 +92,7 @@ CRYPTO_OBJS = \ $O\7zAes.obj \ $O\7zAesRegister.obj \ $O\MyAes.obj \ + $O\MyAesReg.obj \ C_OBJS = \ $O\Alloc.obj \ @@ -107,45 +111,4 @@ C_OBJS = \ !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" +!include "../../7zip.mak" \ No newline at end of file diff --git a/CPP/7zip/Bundles/Format7zExtract/resource.rc b/CPP/7zip/Bundles/Format7zExtract/resource.rc old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp b/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h b/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h old mode 100755 new mode 100644 index 2e4be10b..2854ff3e --- a/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h +++ b/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" -#include "../../../Common/NewHandler.h" +#include "../../../Common/Common.h" #endif diff --git a/CPP/7zip/Bundles/Format7zExtractR/makefile b/CPP/7zip/Bundles/Format7zExtractR/makefile old mode 100755 new mode 100644 index e953af90..7241b37c --- a/CPP/7zip/Bundles/Format7zExtractR/makefile +++ b/CPP/7zip/Bundles/Format7zExtractR/makefile @@ -1,11 +1,12 @@ PROG = 7zxr.dll DEF_FILE = ../../Archive/Archive2.def -CFLAGS = $(CFLAGS) -I ../../../ \ +CFLAGS = $(CFLAGS) \ -DEXTRACT_ONLY \ -D_NO_CRYPTO COMMON_OBJS = \ $O\CRC.obj \ + $O\CrcReg.obj \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ @@ -30,6 +31,7 @@ WIN_OBJS = \ $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ + $O\PropId.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ @@ -92,41 +94,4 @@ C_OBJS = \ !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" +!include "../../7zip.mak" diff --git a/CPP/7zip/Bundles/Format7zExtractR/resource.rc b/CPP/7zip/Bundles/Format7zExtractR/resource.rc old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/Format7zF/Arc.mak b/CPP/7zip/Bundles/Format7zF/Arc.mak new file mode 100644 index 00000000..c26a6d67 --- /dev/null +++ b/CPP/7zip/Bundles/Format7zF/Arc.mak @@ -0,0 +1,275 @@ +COMMON_OBJS = \ + $O\CRC.obj \ + $O\CrcReg.obj \ + $O\DynLimBuf.obj \ + $O\IntToString.obj \ + $O\MyMap.obj \ + $O\MyString.obj \ + $O\MyVector.obj \ + $O\MyXml.obj \ + $O\NewHandler.obj \ + $O\Sha256Reg.obj \ + $O\StringConvert.obj \ + $O\StringToInt.obj \ + $O\UTFConvert.obj \ + $O\Wildcard.obj \ + $O\XzCrc64Reg.obj \ + +WIN_OBJS = \ + $O\FileDir.obj \ + $O\FileFind.obj \ + $O\FileIO.obj \ + $O\FileName.obj \ + $O\PropVariant.obj \ + $O\PropVariantUtils.obj \ + $O\Synchronization.obj \ + $O\System.obj \ + $O\TimeUtils.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\PropId.obj \ + $O\StreamBinder.obj \ + $O\StreamObjects.obj \ + $O\StreamUtils.obj \ + $O\UniqBlocks.obj \ + $O\VirtThread.obj \ + +AR_OBJS = \ + $O\ApmHandler.obj \ + $O\ArHandler.obj \ + $O\ArjHandler.obj \ + $O\Bz2Handler.obj \ + $O\ComHandler.obj \ + $O\CpioHandler.obj \ + $O\CramfsHandler.obj \ + $O\DeflateProps.obj \ + $O\DmgHandler.obj \ + $O\ElfHandler.obj \ + $O\FatHandler.obj \ + $O\FlvHandler.obj \ + $O\GzHandler.obj \ + $O\HfsHandler.obj \ + $O\IhexHandler.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\UefiHandler.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\ChmIn.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 \ + +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 \ + +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\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\MyAesReg.obj \ + $O\Pbkdf2HmacSha1.obj \ + $O\RandGen.obj \ + $O\Rar20Crypto.obj \ + $O\RarAes.obj \ + $O\Sha1.obj \ + $O\Sha1Reg.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\XzDec.obj \ + $O\XzEnc.obj \ + $O\XzIn.obj \ + +!include "../../Aes.mak" +!include "../../Crc.mak" +!include "../../Crc64.mak" diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsp b/CPP/7zip/Bundles/Format7zF/Format7z.dsp old mode 100755 new mode 100644 index 5bf1277d..40f45455 --- a/CPP/7zip/Bundles/Format7zF/Format7z.dsp +++ b/CPP/7zip/Bundles/Format7zF/Format7z.dsp @@ -43,7 +43,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 1 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /YX /FD /c -# ADD CPP /nologo /Gr /MT /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 CPP /nologo /Gr /MT /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /D "NO_REGISTRY" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /FAs /Yu"StdAfx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" @@ -70,7 +70,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 1 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /Gr /MTd /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 CPP /nologo /Gr /MTd /W4 /WX /Gm /GX /ZI /Od /I "..\..\..\..\SDK" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /D "NO_REGISTRY" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" @@ -230,7 +230,7 @@ SOURCE=.\StdAfx.h # PROP Default_Filter "" # Begin Source File -SOURCE=..\..\..\Common\Buffer.h +SOURCE=..\..\..\Common\Common.h # End Source File # Begin Source File @@ -238,10 +238,22 @@ SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File +SOURCE=..\..\..\Common\CrcReg.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\DynamicBuffer.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\DynLimBuf.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\DynLimBuf.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File @@ -250,6 +262,10 @@ SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\MyBuffer.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File @@ -278,6 +294,10 @@ SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\MyTypes.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\MyUnknown.h # End Source File # Begin Source File @@ -290,6 +310,10 @@ 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 @@ -310,6 +334,10 @@ SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\Sha256Reg.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File @@ -326,10 +354,6 @@ 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 @@ -344,6 +368,10 @@ SOURCE=..\..\..\Common\Wildcard.cpp SOURCE=..\..\..\Common\Wildcard.h # End Source File +# Begin Source File + +SOURCE=..\..\..\Common\XzCrc64Reg.cpp +# End Source File # End Group # Begin Group "Compress" @@ -830,6 +858,10 @@ SOURCE=..\..\Crypto\MyAes.h # End Source File # Begin Source File +SOURCE=..\..\Crypto\MyAesReg.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Crypto\Pbkdf2HmacSha1.cpp !IF "$(CFG)" == "7z - Win32 Release" @@ -910,6 +942,10 @@ SOURCE=..\..\Crypto\Sha1.h # End Source File # Begin Source File +SOURCE=..\..\Crypto\Sha1Reg.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Crypto\WzAes.cpp # End Source File # Begin Source File @@ -1078,6 +1114,10 @@ SOURCE=..\..\Common\ProgressUtils.h # End Source File # Begin Source File +SOURCE=..\..\Common\PropId.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Common\RegisterArc.h # End Source File # Begin Source File @@ -1110,6 +1150,14 @@ SOURCE=..\..\Common\StreamUtils.h # End Source File # Begin Source File +SOURCE=..\..\Common\UniqBlocks.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\UniqBlocks.h +# End Source File +# Begin Source File + SOURCE=..\..\Common\VirtThread.cpp # End Source File # Begin Source File @@ -1167,6 +1215,22 @@ SOURCE=..\..\..\..\C\XzCrc64.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\XzCrc64Opt.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\XzDec.c !IF "$(CFG)" == "7z - Win32 Release" @@ -1241,6 +1305,10 @@ SOURCE=..\..\..\..\C\7zStream.c # End Source File # Begin Source File +SOURCE=..\..\..\..\C\7zTypes.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Aes.c !IF "$(CFG)" == "7z - Win32 Release" @@ -1342,6 +1410,10 @@ SOURCE=..\..\..\..\C\BwtSort.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Compiler.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\CpuArch.c # SUBTRACT CPP /YX /Yc /Yu # End Source File @@ -1621,6 +1693,10 @@ SOURCE=..\..\..\..\C\Ppmd8Enc.c # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Precomp.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\RotateDefs.h # End Source File # Begin Source File @@ -1665,16 +1741,16 @@ SOURCE=..\..\..\..\C\Sort.h # End Source File # Begin Source File -SOURCE=..\..\..\..\C\Threads.c -# SUBTRACT CPP /YX /Yc /Yu +SOURCE=..\..\..\..\C\StdAfx.h # End Source File # Begin Source File -SOURCE=..\..\..\..\C\Threads.h +SOURCE=..\..\..\..\C\Threads.c +# SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File -SOURCE=..\..\..\..\C\Types.h +SOURCE=..\..\..\..\C\Threads.h # End Source File # End Group # Begin Group "Archive" @@ -1813,40 +1889,12 @@ 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" @@ -1905,24 +1953,12 @@ 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" @@ -2169,10 +2205,6 @@ 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 @@ -2193,10 +2225,6 @@ 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 @@ -2244,54 +2272,6 @@ SOURCE=..\..\Archive\Wim\WimIn.h 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 "" @@ -2311,14 +2291,14 @@ SOURCE=..\..\Archive\Udf\UdfIn.cpp SOURCE=..\..\Archive\Udf\UdfIn.h # End Source File +# End Group # Begin Source File -SOURCE=..\..\Archive\Udf\UdfRegister.cpp +SOURCE=..\..\Archive\ApmHandler.cpp # End Source File -# End Group # Begin Source File -SOURCE=..\..\Archive\ApmHandler.cpp +SOURCE=..\..\Archive\ArHandler.cpp # End Source File # Begin Source File @@ -2330,15 +2310,15 @@ SOURCE=..\..\Archive\Bz2Handler.cpp # End Source File # Begin Source File -SOURCE=..\..\Archive\CpioHandler.cpp +SOURCE=..\..\Archive\ComHandler.cpp # End Source File # Begin Source File -SOURCE=..\..\Archive\CramfsHandler.cpp +SOURCE=..\..\Archive\CpioHandler.cpp # End Source File # Begin Source File -SOURCE=..\..\Archive\DebHandler.cpp +SOURCE=..\..\Archive\CramfsHandler.cpp # End Source File # Begin Source File @@ -2370,10 +2350,18 @@ SOURCE=..\..\Archive\GzHandler.cpp # End Source File # Begin Source File +SOURCE=..\..\Archive\HfsHandler.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Archive\IArchive.h # End Source File # Begin Source File +SOURCE=..\..\Archive\IhexHandler.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Archive\LzhHandler.cpp # End Source File # Begin Source File @@ -2488,6 +2476,10 @@ SOURCE=..\..\PropID.h # PROP Default_Filter "" # Begin Source File +SOURCE=..\..\..\Windows\Defs.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Windows\FileDir.cpp # End Source File # Begin Source File @@ -2512,6 +2504,14 @@ 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 @@ -2548,11 +2548,11 @@ SOURCE=..\..\..\Windows\Thread.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Time.cpp +SOURCE=..\..\..\Windows\TimeUtils.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Time.h +SOURCE=..\..\..\Windows\TimeUtils.h # End Source File # End Group # Begin Group "Asm" diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsw b/CPP/7zip/Bundles/Format7zF/Format7z.dsw old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/Format7zF/StdAfx.cpp b/CPP/7zip/Bundles/Format7zF/StdAfx.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/Format7zF/StdAfx.h b/CPP/7zip/Bundles/Format7zF/StdAfx.h old mode 100755 new mode 100644 index 2e4be10b..2854ff3e --- a/CPP/7zip/Bundles/Format7zF/StdAfx.h +++ b/CPP/7zip/Bundles/Format7zF/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" -#include "../../../Common/NewHandler.h" +#include "../../../Common/Common.h" #endif diff --git a/CPP/7zip/Bundles/Format7zF/makefile b/CPP/7zip/Bundles/Format7zF/makefile old mode 100755 new mode 100644 index 2601f1d6..97318dc6 --- a/CPP/7zip/Bundles/Format7zF/makefile +++ b/CPP/7zip/Bundles/Format7zF/makefile @@ -1,370 +1,20 @@ PROG = 7z.dll DEF_FILE = ../../Archive/Archive2.def -CFLAGS = $(CFLAGS) -I ../../../ \ +CFLAGS = $(CFLAGS) \ -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 \ +!include "Arc.mak" -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 \ +COMPRESS_OBJS = $(COMPRESS_OBJS) \ + $O\CodecExports.obj \ -AR_OBJS = \ +AR_OBJS = $(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\UefiHandler.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" +!include "../../7zip.mak" diff --git a/CPP/7zip/Bundles/Format7zF/resource.rc b/CPP/7zip/Bundles/Format7zF/resource.rc old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/Format7zR/StdAfx.cpp b/CPP/7zip/Bundles/Format7zR/StdAfx.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/Format7zR/StdAfx.h b/CPP/7zip/Bundles/Format7zR/StdAfx.h old mode 100755 new mode 100644 index 2e4be10b..2854ff3e --- a/CPP/7zip/Bundles/Format7zR/StdAfx.h +++ b/CPP/7zip/Bundles/Format7zR/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" -#include "../../../Common/NewHandler.h" +#include "../../../Common/Common.h" #endif diff --git a/CPP/7zip/Bundles/Format7zR/makefile b/CPP/7zip/Bundles/Format7zR/makefile old mode 100755 new mode 100644 index d7ffcea1..555654bc --- a/CPP/7zip/Bundles/Format7zR/makefile +++ b/CPP/7zip/Bundles/Format7zR/makefile @@ -1,10 +1,11 @@ PROG = 7zra.dll DEF_FILE = ../../Archive/Archive2.def -CFLAGS = $(CFLAGS) -I ../../../ \ +CFLAGS = $(CFLAGS) \ -D_NO_CRYPTO COMMON_OBJS = \ $O\CRC.obj \ + $O\CrcReg.obj \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ @@ -17,6 +18,7 @@ WIN_OBJS = \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ + $O\FileName.obj \ $O\PropVariant.obj \ $O\Synchronization.obj \ $O\System.obj \ @@ -33,9 +35,11 @@ WIN_OBJS = \ $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ + $O\PropId.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ + $O\UniqBlocks.obj \ $O\VirtThread.obj \ AR_OBJS = \ @@ -109,41 +113,4 @@ C_OBJS = \ !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" +!include "../../7zip.mak" diff --git a/CPP/7zip/Bundles/Format7zR/resource.rc b/CPP/7zip/Bundles/Format7zR/resource.rc old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp old mode 100755 new mode 100644 index e0f4dcba..d321e454 --- a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp +++ b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp @@ -69,27 +69,25 @@ enum Enum static const CSwitchForm kSwitchForms[] = { - { L"?", NSwitchType::kSimple, false }, - { L"H", NSwitchType::kSimple, false }, - { L"MM", NSwitchType::kUnLimitedPostString, false, 1 }, - { L"X", NSwitchType::kUnLimitedPostString, false, 1 }, - { 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"+" } + { "?", NSwitchType::kSimple, false }, + { "H", NSwitchType::kSimple, false }, + { "MM", NSwitchType::kString, false, 1 }, + { "X", NSwitchType::kString, false, 1 }, + { "A", NSwitchType::kString, false, 1 }, + { "D", NSwitchType::kString, false, 1 }, + { "FB", NSwitchType::kString, false, 1 }, + { "MC", NSwitchType::kString, false, 1 }, + { "LC", NSwitchType::kString, false, 1 }, + { "LP", NSwitchType::kString, false, 1 }, + { "PB", NSwitchType::kString, false, 1 }, + { "MF", NSwitchType::kString, false, 1 }, + { "MT", NSwitchType::kString, false, 0 }, + { "EOS", NSwitchType::kSimple, false }, + { "SI", NSwitchType::kSimple, false }, + { "SO", NSwitchType::kSimple, false }, + { "F86", NSwitchType::kChar, false, 0, "+" } }; -static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]); - static void PrintMessage(const char *s) { fputs(s, stderr); @@ -138,19 +136,14 @@ static void WriteArgumentsToStringList(int numArgs, const char *args[], UStringV static bool GetNumber(const wchar_t *s, UInt32 &value) { value = 0; - if (MyStringLen(s) == 0) + if (*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; + value = ConvertStringToUInt32(s, &end); + return *end == 0; } -static void ParseUInt32(const CParser &parser, int index, UInt32 &res) +static void ParseUInt32(const CParser &parser, unsigned index, UInt32 &res) { if (parser[index].ThereIs) if (!GetNumber(parser[index].PostStrings[0], res)) @@ -180,7 +173,8 @@ int main2(int numArgs, const char *args[]) UStringVector commandStrings; WriteArgumentsToStringList(numArgs, args, commandStrings); - CParser parser(kNumSwitches); + + CParser parser(ARRAY_SIZE(kSwitchForms)); try { parser.ParseStrings(kSwitchForms, commandStrings); @@ -197,7 +191,7 @@ int main2(int numArgs, const char *args[]) } const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; - int paramIndex = 0; + unsigned paramIndex = 0; if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &command = nonSwitchStrings[paramIndex++]; @@ -259,11 +253,11 @@ int main2(int numArgs, const char *args[]) IncorrectCommand(); CProperty prop; prop.Name = L"m"; - prop.Value = s.Mid(1); + prop.Value = s.Ptr(1); props.Add(prop); } - if (command.CompareNoCase(L"b") == 0) + if (MyStringCompareNoCase(command, L"b") == 0) { const UInt32 kNumDefaultItereations = 1; UInt32 numIterations = kNumDefaultItereations; @@ -288,9 +282,9 @@ int main2(int numArgs, const char *args[]) numThreads = 1; bool encodeMode = false; - if (command.CompareNoCase(L"e") == 0) + if (MyStringCompareNoCase(command, L"e") == 0) encodeMode = true; - else if (command.CompareNoCase(L"d") == 0) + else if (MyStringCompareNoCase(command, L"d") == 0) encodeMode = false; else IncorrectCommand(); @@ -456,7 +450,7 @@ int main2(int numArgs, const char *args[]) NCoderPropID::kNumThreads, NCoderPropID::kMatchFinderCycles, }; - const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]); + const unsigned kNumPropsMax = ARRAY_SIZE(propIDs); PROPVARIANT props[kNumPropsMax]; for (int p = 0; p < 6; p++) @@ -482,7 +476,7 @@ int main2(int numArgs, const char *args[]) props[9].vt = VT_UI4; props[9].ulVal = (UInt32)mc; - int numProps = kNumPropsMax; + unsigned numProps = kNumPropsMax; if (!mcDefined) numProps--; @@ -512,7 +506,7 @@ int main2(int numArgs, const char *args[]) } else if (result != S_OK) { - fprintf(stderr, "\nEncoder error = %X\n", (unsigned int)result); + fprintf(stderr, "\nEncoder error = %X\n", (unsigned)result); return 1; } } @@ -537,11 +531,18 @@ int main2(int numArgs, const char *args[]) 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) + bool isSizeDefined = (fileSize != (UInt64)(Int64)-1); + HRESULT res = decoder->Code(inStream, outStream, 0, isSizeDefined ? &fileSize : NULL, 0) != S_OK; + if (res != S_OK) { PrintMessage("Decoder error"); return 1; } + if (isSizeDefined && decoderSpec->GetOutputProcessedSize() != fileSize) + { + PrintMessage("Error: incorrect uncompressed size in header"); + return 1; + } } if (outStreamSpec != NULL) { diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp old mode 100755 new mode 100644 index 6111aa7e..47f36c84 --- a/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp +++ b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp @@ -42,7 +42,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /Gr /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gr /MD /W4 /WX /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe @@ -66,7 +66,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /MDd /W4 /WX /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe @@ -180,6 +180,10 @@ SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File +SOURCE=..\..\..\Common\CrcReg.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp b/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/LzmaCon/StdAfx.h b/CPP/7zip/Bundles/LzmaCon/StdAfx.h old mode 100755 new mode 100644 index e7fb6986..2854ff3e --- a/CPP/7zip/Bundles/LzmaCon/StdAfx.h +++ b/CPP/7zip/Bundles/LzmaCon/StdAfx.h @@ -3,6 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" +#include "../../../Common/Common.h" #endif diff --git a/CPP/7zip/Bundles/LzmaCon/makefile b/CPP/7zip/Bundles/LzmaCon/makefile old mode 100755 new mode 100644 index 35d031af..54919f73 --- a/CPP/7zip/Bundles/LzmaCon/makefile +++ b/CPP/7zip/Bundles/LzmaCon/makefile @@ -2,7 +2,7 @@ PROG = lzma.exe MY_CONSOLE = 1 CFLAGS = $(CFLAGS) -LZMA_OBJS = \ +CURRENT_OBJS = \ $O\LzmaAlone.obj \ COMPRESS_OBJS = \ @@ -13,8 +13,10 @@ COMPRESS_OBJS = \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ + $O\CrcReg.obj \ $O\IntToString.obj \ $O\MyString.obj \ + $O\NewHandler.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj @@ -54,36 +56,4 @@ C_OBJS = \ !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" +!include "../../7zip.mak" diff --git a/CPP/7zip/Bundles/LzmaCon/makefile.gcc b/CPP/7zip/Bundles/LzmaCon/makefile.gcc old mode 100755 new mode 100644 index 0f9f498c..42e52246 --- a/CPP/7zip/Bundles/LzmaCon/makefile.gcc +++ b/CPP/7zip/Bundles/LzmaCon/makefile.gcc @@ -35,6 +35,7 @@ OBJS = \ $(FILE_IO).o \ CommandLineParser.o \ CRC.o \ + CrcReg.o \ IntToString.o \ MyString.o \ MyVector.o \ @@ -108,6 +109,9 @@ CommandLineParser.o: ../../../Common/CommandLineParser.cpp CRC.o: ../../../Common/CRC.cpp $(CXX) $(CFLAGS) ../../../Common/CRC.cpp +CrcReg.o: ../../../Common/CrcReg.cpp + $(CXX) $(CFLAGS) ../../../Common/CrcReg.cpp + IntToString.o: ../../../Common/IntToString.cpp $(CXX) $(CFLAGS) ../../../Common/IntToString.cpp diff --git a/CPP/7zip/Bundles/LzmaCon/resource.rc b/CPP/7zip/Bundles/LzmaCon/resource.rc new file mode 100644 index 00000000..43b50738 --- /dev/null +++ b/CPP/7zip/Bundles/LzmaCon/resource.rc @@ -0,0 +1,3 @@ +#include "../../MyVersionInfo.rc" + +MY_VERSION_INFO_APP("LZMA", "lzma") diff --git a/CPP/7zip/Bundles/SFXCon/7z.ico b/CPP/7zip/Bundles/SFXCon/7z.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/SFXCon/Main.cpp b/CPP/7zip/Bundles/SFXCon/Main.cpp deleted file mode 100755 index 3e9a8162..00000000 --- a/CPP/7zip/Bundles/SFXCon/Main.cpp +++ /dev/null @@ -1,447 +0,0 @@ -// 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 "Windows/FileName.h" - -#include "../../UI/Common/ExitCode.h" -#include "../../UI/Common/Extract.h" - -#include "../../UI/Console/ExtractCallbackConsole.h" -#include "../../UI/Console/List.h" -#include "../../UI/Console/OpenCallbackConsole.h" - -#include "../../MyVersion.h" - -using namespace NWindows; -using namespace NFile; -using namespace NCommandLineParser; - -#ifdef _WIN32 -HINSTANCE g_hInstance = 0; -#endif -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 - - FString arcPath; - { - FString path; - NDLL::MyGetModuleFileName(path); - if (!NDirectory::MyGetFullPathName(path, arcPath)) - { - 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; - - FString outputDir; - if (parser[NKey::kOutputDir].ThereIs) - { - outputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]); - NName::NormalizeDirPathPrefix(outputDir); - } - - { - UStringVector v1, v2; - v1.Add(fs2us(arcPath)); - v2.Add(fs2us(arcPath)); - const NWildcard::CCensorNode &wildcardCensorHead = - wildcardCensor.Pairs.Front().Head; - - CCodecs *codecs = new CCodecs; - CMyComPtr< - #ifdef EXTERNAL_CODECS - ICompressCodecsInfo - #else - IUnknown - #endif - > compressCodecsInfo = codecs; - HRESULT result = codecs->Load(); - if (result != S_OK) - throw CSystemException(result); - - if (command.CommandType != NCommandType::kList) - { - CExtractCallbackConsole *ecs = new CExtractCallbackConsole; - CMyComPtr extractCallback = ecs; - ecs->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 old mode 100755 new mode 100644 index e355d6e1..092fedcd --- a/CPP/7zip/Bundles/SFXCon/SFXCon.dsp +++ b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp @@ -42,7 +42,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /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 CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "EXTRACT_ONLY" /D "_SFX" /D "NO_READ_FROM_CODER" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe @@ -50,7 +50,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /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 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"C:\Util\7zCon.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "SFXCon - Win32 Debug" @@ -67,7 +67,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /Gz /MTd /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 CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "EXTRACT_ONLY" /D "_SFX" /D "NO_READ_FROM_CODER" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe @@ -75,7 +75,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 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 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"C:\Util\7zCon.exe" /pdbtype:sept !ENDIF @@ -141,6 +141,14 @@ 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 @@ -229,10 +237,6 @@ 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 @@ -251,6 +255,10 @@ SOURCE=..\..\Archive\7z\7zItem.h SOURCE=..\..\Archive\7z\7zRegister.cpp # End Source File +# Begin Source File + +SOURCE=..\..\Archive\SplitHandler.cpp +# End Source File # End Group # Begin Group "Compress" @@ -345,11 +353,11 @@ SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Error.cpp +SOURCE=..\..\..\Windows\ErrorMsg.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Error.h +SOURCE=..\..\..\Windows\ErrorMsg.h # End Source File # Begin Source File @@ -393,11 +401,11 @@ SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\PropVariantConversions.cpp +SOURCE=..\..\..\Windows\PropVariantConv.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\PropVariantConversions.h +SOURCE=..\..\..\Windows\PropVariantConv.h # End Source File # Begin Source File @@ -593,6 +601,10 @@ SOURCE=..\..\Common\ProgressUtils.h # End Source File # Begin Source File +SOURCE=..\..\Common\PropId.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Common\StreamBinder.cpp # End Source File # Begin Source File @@ -815,7 +827,11 @@ SOURCE=.\7z.ico # End Source File # Begin Source File -SOURCE=.\Main.cpp +SOURCE=..\..\Archive\IArchive.h +# End Source File +# Begin Source File + +SOURCE=.\SfxCon.cpp # End Source File # End Target # End Project diff --git a/CPP/7zip/Bundles/SFXCon/SFXCon.dsw b/CPP/7zip/Bundles/SFXCon/SFXCon.dsw old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp new file mode 100644 index 00000000..c8837f9d --- /dev/null +++ b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp @@ -0,0 +1,453 @@ +// 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 "../../../Windows/FileName.h" + +#include "../../UI/Common/ExitCode.h" +#include "../../UI/Common/Extract.h" + +#include "../../UI/Console/ExtractCallbackConsole.h" +#include "../../UI/Console/List.h" +#include "../../UI/Console/OpenCallbackConsole.h" + +#include "../../MyVersion.h" + +using namespace NWindows; +using namespace NFile; +using namespace NDir; +using namespace NCommandLineParser; + +#ifdef _WIN32 +HINSTANCE g_hInstance = 0; +#endif +int g_CodePage = -1; +extern CStdOutStream *g_StdStream; + +static const char *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] = +{ + { "?", NSwitchType::kSimple }, + { "H", NSwitchType::kSimple }, + { "BD", NSwitchType::kSimple }, + { "Y", NSwitchType::kSimple }, + { "P", NSwitchType::kString, false, 1 }, + { "O", NSwitchType::kString, false, 1 }, +}; + +static const int kNumCommandForms = 3; + +static const NRecursedType::EEnum kCommandRecursedDefault[kNumCommandForms] = +{ + NRecursedType::kRecursed +}; + +// static const bool kTestExtractRecursedDefault = true; +// static const bool kAddRecursedDefault = false; + +static const 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"; + +namespace NCommandType +{ + enum EEnum + { + kTest = 0, + kFullExtract, + kList + }; +} + +static const char *g_Commands = "txl"; + +struct CArchiveCommand +{ + NCommandType::EEnum CommandType; + + NRecursedType::EEnum DefaultRecursedType() const; +}; + +bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command) +{ + UString s = commandString; + s.MakeLower_Ascii(); + if (s.Len() != 1) + return false; + if (s[0] >= 0x80) + return false; + int index = FindCharPosInString(g_Commands, (char)s[0]); + if (index < 0) + return false; + command.CommandType = (NCommandType::EEnum)index; + return true; +} + +NRecursedType::EEnum CArchiveCommand::DefaultRecursedType() const +{ + return kCommandRecursedDefault[CommandType]; +} + +void PrintHelp(void) +{ + g_StdOut << kHelpString; +} + +static void ShowMessageAndThrowException(const char *message, NExitCode::EEnum code) +{ + g_StdOut << message << endl; + throw code; +} + +static void PrintHelpAndExit() // yyy +{ + PrintHelp(); + ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError); +} + +// ------------------------------------------------------------------ +// filenames functions + +static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor, + const UString &name, bool include, NRecursedType::EEnum type) +{ + /* + if (!IsWildcardFilePathLegal(name)) + return false; + */ + bool isWildcard = DoesNameContainWildcard(name); + bool recursed = false; + + switch (type) + { + case NRecursedType::kWildcardOnlyRecursed: + recursed = isWildcard; + break; + case NRecursedType::kRecursed: + recursed = true; + break; + case NRecursedType::kNonRecursed: + recursed = false; + break; + } + wildcardCensor.AddPreItem(include, name, recursed, true); + return true; +} + +void AddCommandLineWildcardToCensor(NWildcard::CCensor &wildcardCensor, + const UString &name, bool include, NRecursedType::EEnum type) +{ + if (!AddNameToCensor(wildcardCensor, name, include, type)) + ShowMessageAndThrowException(kIncorrectWildcardInCommandLine, NExitCode::kUserError); +} + +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 + + FString arcPath; + { + FString path; + NDLL::MyGetModuleFileName(path); + if (!MyGetFullPathName(path, arcPath)) + { + 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; + + FString outputDir; + if (parser[NKey::kOutputDir].ThereIs) + { + outputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]); + NName::NormalizeDirPathPrefix(outputDir); + } + + + wildcardCensor.AddPathsToCensor(NWildcard::k_RelatPath); + + { + UStringVector v1, v2; + v1.Add(fs2us(arcPath)); + v2.Add(fs2us(arcPath)); + const NWildcard::CCensorNode &wildcardCensorHead = + wildcardCensor.Pairs.Front().Head; + + CCodecs *codecs = new CCodecs; + CMyComPtr< + #ifdef EXTERNAL_CODECS + ICompressCodecsInfo + #else + IUnknown + #endif + > compressCodecsInfo = codecs; + HRESULT result = codecs->Load(); + if (result != S_OK) + throw CSystemException(result); + + if (command.CommandType != NCommandType::kList) + { + CExtractCallbackConsole *ecs = new CExtractCallbackConsole; + CMyComPtr extractCallback = ecs; + ecs->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.YesToAll = yesToAll; + eo.TestMode = command.CommandType == NCommandType::kTest; + eo.PathMode = NExtract::NPathMode::kFullPaths; + eo.OverwriteMode = yesToAll ? + NExtract::NOverwriteMode::kOverwrite : + NExtract::NOverwriteMode::kAsk; + eo.OutputDir = outputDir; + + UString errorMessage; + CDecompressStat stat; + HRESULT result = Extract( + codecs, CObjectVector(), CIntVector(), + v1, v2, + wildcardCensorHead, + eo, &openCallback, ecs, + // NULL, // hash + errorMessage, stat); + if (!errorMessage.IsEmpty()) + { + (*g_StdStream) << endl << "Error: " << errorMessage;; + if (result == S_OK) + result = E_FAIL; + } + + if (ecs->NumArcsWithError != 0 || ecs->NumFileErrors != 0) + { + if (ecs->NumArcsWithError != 0) + (*g_StdStream) << endl << "Archive Errors" << endl; + if (ecs->NumFileErrors != 0) + (*g_StdStream) << endl << "Sub items Errors: " << ecs->NumFileErrors << endl; + return NExitCode::kFatalError; + } + if (result != S_OK) + throw CSystemException(result); + } + else + { + UInt64 numErrors = 0; + UInt64 numWarnings = 0; + HRESULT result = ListArchives( + codecs, CObjectVector(), CIntVector(), + false, // stdInMode + v1, v2, + true, // processAltStreams + false, // showAltStreams + wildcardCensorHead, + true, // enableHeaders + false, // techMode + #ifndef _NO_CRYPTO + passwordEnabled, password, + #endif + numErrors, numWarnings); + if (numErrors > 0) + { + g_StdOut << endl << "Errors: " << numErrors; + return NExitCode::kFatalError; + } + if (result != S_OK) + throw CSystemException(result); + } + } + return 0; +} diff --git a/CPP/7zip/Bundles/SFXCon/StdAfx.cpp b/CPP/7zip/Bundles/SFXCon/StdAfx.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/SFXCon/StdAfx.h b/CPP/7zip/Bundles/SFXCon/StdAfx.h old mode 100755 new mode 100644 index 2e4be10b..2854ff3e --- a/CPP/7zip/Bundles/SFXCon/StdAfx.h +++ b/CPP/7zip/Bundles/SFXCon/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" -#include "../../../Common/NewHandler.h" +#include "../../../Common/Common.h" #endif diff --git a/CPP/7zip/Bundles/SFXCon/makefile b/CPP/7zip/Bundles/SFXCon/makefile old mode 100755 new mode 100644 index c92236bf..dd795b0b --- a/CPP/7zip/Bundles/SFXCon/makefile +++ b/CPP/7zip/Bundles/SFXCon/makefile @@ -1,12 +1,12 @@ PROG = 7zCon.sfx MY_CONSOLE = 1 -CFLAGS = $(CFLAGS) -I ../../../ \ +CFLAGS = $(CFLAGS) \ -DEXTRACT_ONLY \ -DNO_READ_FROM_CODER \ -D_SFX \ -SFX_CONSOLE_OBJS = \ - $O\Main.obj \ +CURRENT_OBJS = \ + $O\SfxCon.obj \ CONSOLE_OBJS = \ $O\ConsoleClose.obj \ @@ -20,24 +20,24 @@ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\IntToString.obj \ + $O\MyString.obj \ + $O\MyVector.obj \ $O\NewHandler.obj \ $O\StdInStream.obj \ $O\StdOutStream.obj \ - $O\MyString.obj \ $O\StringConvert.obj \ - $O\MyVector.obj \ $O\Wildcard.obj \ $O\UTFConvert.obj \ WIN_OBJS = \ $O\DLL.obj \ - $O\Error.obj \ + $O\ErrorMsg.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\PropVariant.obj \ - $O\PropVariantConversions.obj \ + $O\PropVariantConv.obj \ $O\Synchronization.obj \ 7ZIP_COMMON_OBJS = \ @@ -51,6 +51,7 @@ WIN_OBJS = \ $O\LockedStream.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ + $O\PropId.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ @@ -66,11 +67,15 @@ UI_COMMON_OBJS = \ $O\OpenArchive.obj \ $O\PropIDUtils.obj \ +AR_OBJS = \ + $O\SplitHandler.obj \ + AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\ItemNameUtils.obj \ + $O\MultiStream.obj \ $O\OutStreamWithCRC.obj \ @@ -79,7 +84,6 @@ AR_COMMON_OBJS = \ $O\7zExtract.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ - $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zRegister.obj \ @@ -117,48 +121,4 @@ C_OBJS = \ !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" +!include "../../7zip.mak" diff --git a/CPP/7zip/Bundles/SFXCon/resource.rc b/CPP/7zip/Bundles/SFXCon/resource.rc old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractCallback.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractCallback.cpp deleted file mode 100755 index 9b733da0..00000000 --- a/CPP/7zip/Bundles/SFXSetup/ExtractCallback.cpp +++ /dev/null @@ -1,237 +0,0 @@ -// ExtractCallback.h - -#include "StdAfx.h" - -#include "Common/Wildcard.h" - -#include "Windows/FileDir.h" -#include "Windows/FileFind.h" -#include "Windows/FileName.h" -#include "Windows/PropVariant.h" - -#include "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 FString &directoryPath, - const UString &itemDefaultName, - const FILETIME &defaultMTime, - UInt32 defaultAttributes) -{ - _message.Empty(); - _isCorrupt = false; - _itemDefaultName = itemDefaultName; - _defaultMTime = defaultMTime; - _defaultAttributes = defaultAttributes; - _archiveHandler = archiveHandler; - _directoryPath = directoryPath; - NName::NormalizeDirPathPrefix(_directoryPath); -} - -HRESULT CExtractCallbackImp::Open_CheckBreak() -{ - #ifndef _NO_PROGRESS - return ProgressDialog.Sync.ProcessStopAndPause(); - #else - return S_OK; - #endif -} - -HRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */) -{ - return S_OK; -} - -HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */) -{ - #ifndef _NO_PROGRESS - return ProgressDialog.Sync.ProcessStopAndPause(); - #else - return S_OK; - #endif -} - -STDMETHODIMP CExtractCallbackImp::SetTotal(UInt64 size) -{ - #ifndef _NO_PROGRESS - ProgressDialog.Sync.SetProgress(size, 0); - #endif - return S_OK; -} - -STDMETHODIMP CExtractCallbackImp::SetCompleted(const UInt64 *completeValue) -{ - #ifndef _NO_PROGRESS - RINOK(ProgressDialog.Sync.ProcessStopAndPause()); - if (completeValue != NULL) - ProgressDialog.Sync.SetPos(*completeValue); - #endif - return S_OK; -} - -void CExtractCallbackImp::CreateComplexDirectory(const UStringVector &dirPathParts) -{ - FString fullPath = _directoryPath; - for (int i = 0; i < dirPathParts.Size(); i++) - { - fullPath += us2fs(dirPathParts[i]); - NDirectory::MyCreateDirectory(fullPath); - fullPath += FCHAR_PATH_SEPARATOR; - } -} - -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); - } - - FString fullProcessedPath = _directoryPath + us2fs(processedPath); - - if (_processedFileInfo.IsDir) - { - _diskFilePath = fullProcessedPath; - - if (isAnti) - NDirectory::MyRemoveDirectory(_diskFilePath); - else - NDirectory::SetDirTime(_diskFilePath, NULL, NULL, &_processedFileInfo.MTime); - return S_OK; - } - - NFind::CFileInfo 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 deleted file mode 100755 index 128988f9..00000000 --- a/CPP/7zip/Bundles/SFXSetup/ExtractCallback.h +++ /dev/null @@ -1,88 +0,0 @@ -// 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; - FString _directoryPath; - UString _filePath; - FString _diskFilePath; - - bool _extractMode; - struct CProcessedFileInfo - { - FILETIME MTime; - bool IsDir; - UInt32 Attributes; - } _processedFileInfo; - - COutFileStream *_outFileStreamSpec; - CMyComPtr _outFileStream; - - UString _itemDefaultName; - FILETIME _defaultMTime; - UInt32 _defaultAttributes; - - void CreateComplexDirectory(const UStringVector &dirPathParts); -public: - #ifndef _NO_PROGRESS - CProgressDialog ProgressDialog; - #endif - - bool _isCorrupt; - UString _message; - - void Init(IInArchive *archiveHandler, - const FString &directoryPath, - const UString &itemDefaultName, - const FILETIME &defaultMTime, - UInt32 defaultAttributes); - - #ifndef _NO_PROGRESS - HRESULT StartProgressDialog(const UString &title, NWindows::CThread &thread) - { - ProgressDialog.Create(title, thread, 0); - { - #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/ExtractCallbackSfx.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp new file mode 100644 index 00000000..9fe98fc0 --- /dev/null +++ b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp @@ -0,0 +1,238 @@ +// ExtractCallbackSfx.h + +#include "StdAfx.h" + +#include "../../../Common/Wildcard.h" + +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/PropVariant.h" + +#include "ExtractCallbackSfx.h" + +using namespace NWindows; +using namespace NFile; +using namespace NDir; + +static 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 FString &directoryPath, + const UString &itemDefaultName, + const FILETIME &defaultMTime, + UInt32 defaultAttributes) +{ + _message.Empty(); + _isCorrupt = false; + _itemDefaultName = itemDefaultName; + _defaultMTime = defaultMTime; + _defaultAttributes = defaultAttributes; + _archiveHandler = archiveHandler; + _directoryPath = directoryPath; + NName::NormalizeDirPathPrefix(_directoryPath); +} + +HRESULT CExtractCallbackImp::Open_CheckBreak() +{ + #ifndef _NO_PROGRESS + return ProgressDialog.Sync.ProcessStopAndPause(); + #else + return S_OK; + #endif +} + +HRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */) +{ + return S_OK; +} + +HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */) +{ + #ifndef _NO_PROGRESS + return ProgressDialog.Sync.ProcessStopAndPause(); + #else + return S_OK; + #endif +} + +STDMETHODIMP CExtractCallbackImp::SetTotal(UInt64 size) +{ + #ifndef _NO_PROGRESS + ProgressDialog.Sync.SetProgress(size, 0); + #endif + return S_OK; +} + +STDMETHODIMP CExtractCallbackImp::SetCompleted(const UInt64 *completeValue) +{ + #ifndef _NO_PROGRESS + RINOK(ProgressDialog.Sync.ProcessStopAndPause()); + if (completeValue != NULL) + ProgressDialog.Sync.SetPos(*completeValue); + #endif + return S_OK; +} + +void CExtractCallbackImp::CreateComplexDirectory(const UStringVector &dirPathParts) +{ + FString fullPath = _directoryPath; + FOR_VECTOR (i, dirPathParts) + { + fullPath += us2fs(dirPathParts[i]); + CreateDir(fullPath); + fullPath += FCHAR_PATH_SEPARATOR; + } +} + +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); + } + + FString fullProcessedPath = _directoryPath + us2fs(processedPath); + + if (_processedFileInfo.IsDir) + { + _diskFilePath = fullProcessedPath; + + if (isAnti) + RemoveDir(_diskFilePath); + else + SetDirTime(_diskFilePath, NULL, NULL, &_processedFileInfo.MTime); + return S_OK; + } + + NFind::CFileInfo fileInfo; + if (fileInfo.Find(fullProcessedPath)) + { + if (!DeleteFileAlways(fullProcessedPath)) + { + _message = kCantDeleteFile; + return E_FAIL; + } + } + + if (!isAnti) + { + _outFileStreamSpec = new COutFileStream; + CMyComPtr outStreamLoc(_outFileStreamSpec); + if (!_outFileStreamSpec->Create(fullProcessedPath, true)) + { + _message = kCantOpenFile; + return E_FAIL; + } + _outFileStream = outStreamLoc; + *outStream = outStreamLoc.Detach(); + } + _diskFilePath = fullProcessedPath; + } + else + { + *outStream = NULL; + } + return S_OK; +} + +STDMETHODIMP CExtractCallbackImp::PrepareOperation(Int32 askExtractMode) +{ + _extractMode = (askExtractMode == NArchive::NExtract::NAskMode::kExtract); + return S_OK; +} + +STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 resultEOperationResult) +{ + switch(resultEOperationResult) + { + case NArchive::NExtract::NOperationResult::kOK: + break; + + default: + { + _outFileStream.Release(); + switch(resultEOperationResult) + { + case NArchive::NExtract::NOperationResult::kUnsupportedMethod: + _message = kUnsupportedMethod; + break; + default: + _isCorrupt = true; + } + return E_FAIL; + } + } + if (_outFileStream != NULL) + { + _outFileStreamSpec->SetMTime(&_processedFileInfo.MTime); + RINOK(_outFileStreamSpec->Close()); + } + _outFileStream.Release(); + if (_extractMode) + SetFileAttrib(_diskFilePath, _processedFileInfo.Attributes); + return S_OK; +} diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.h b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.h new file mode 100644 index 00000000..cfbc5c07 --- /dev/null +++ b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.h @@ -0,0 +1,86 @@ +// ExtractCallbackSfx.h + +#ifndef __EXTRACT_CALLBACK_SFX_H +#define __EXTRACT_CALLBACK_SFX_H + +#include "resource.h" + +#include "../../../Windows/ResourceString.h" + +#include "../../Archive/IArchive.h" + +#include "../../Common/FileStreams.h" +#include "../../ICoder.h" + +#include "../../UI/FileManager/LangUtils.h" + +#ifndef _NO_PROGRESS +#include "../../UI/FileManager/ProgressDialog.h" +#endif +#include "../../UI/Common/ArchiveOpenCallback.h" + +class CExtractCallbackImp: + public IArchiveExtractCallback, + public IOpenCallbackUI, + public CMyUnknownImp +{ +public: + + MY_UNKNOWN_IMP + + INTERFACE_IArchiveExtractCallback(;) + INTERFACE_IOpenCallbackUI(;) + +private: + CMyComPtr _archiveHandler; + FString _directoryPath; + UString _filePath; + FString _diskFilePath; + + bool _extractMode; + struct CProcessedFileInfo + { + FILETIME MTime; + bool IsDir; + UInt32 Attributes; + } _processedFileInfo; + + COutFileStream *_outFileStreamSpec; + CMyComPtr _outFileStream; + + UString _itemDefaultName; + FILETIME _defaultMTime; + UInt32 _defaultAttributes; + + void CreateComplexDirectory(const UStringVector &dirPathParts); +public: + #ifndef _NO_PROGRESS + CProgressDialog ProgressDialog; + #endif + + bool _isCorrupt; + UString _message; + + void Init(IInArchive *archiveHandler, + const FString &directoryPath, + const UString &itemDefaultName, + const FILETIME &defaultMTime, + UInt32 defaultAttributes); + + #ifndef _NO_PROGRESS + HRESULT StartProgressDialog(const UString &title, NWindows::CThread &thread) + { + ProgressDialog.Create(title, thread, 0); + { + ProgressDialog.SetText(LangString(IDS_PROGRESS_EXTRACTING)); + } + + ProgressDialog.Show(SW_SHOWNORMAL); + return S_OK; + } + virtual ~CExtractCallbackImp() { ProgressDialog.Destroy(); } + #endif + +}; + +#endif diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp old mode 100755 new mode 100644 index 8f830de5..ba41fd1a --- a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp +++ b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp @@ -2,18 +2,21 @@ #include "StdAfx.h" -#include "Windows/FileDir.h" -#include "Windows/FileName.h" -#include "Windows/Thread.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/Thread.h" #include "../../UI/Common/OpenArchive.h" #include "../../UI/FileManager/FormatUtils.h" +#include "../../UI/FileManager/LangUtils.h" -#include "ExtractCallback.h" +#include "ExtractCallbackSfx.h" #include "ExtractEngine.h" using namespace NWindows; +using namespace NFile; +using namespace NDir; static LPCWSTR kCantFindArchive = L"Can not find archive file"; static LPCWSTR kCantOpenArchive = L"Can not open the file as archive"; @@ -33,15 +36,23 @@ struct CThreadExtracting void Process2() { - NFile::NFind::CFileInfo fi; + NFind::CFileInfo fi; if (!fi.Find(FileName)) { ErrorMessage = kCantFindArchive; Result = E_FAIL; return; } + + CObjectVector incl; + CIntVector excl; + COpenOptions options; + options.codecs = Codecs; + options.types = &incl; + options.excludedFormats = ! + options.filePath = fs2us(FileName); - Result = ArchiveLink.Open2(Codecs, CIntVector(), false, NULL, fs2us(FileName), ExtractCallbackSpec); + Result = ArchiveLink.Open2(options, ExtractCallbackSpec); if (Result != S_OK) { if (Result != S_OK) @@ -50,9 +61,9 @@ struct CThreadExtracting } FString dirPath = DestFolder; - NFile::NName::NormalizeDirPathPrefix(dirPath); + NName::NormalizeDirPathPrefix(dirPath); - if (!NFile::NDirectory::CreateComplexDirectory(dirPath)) + if (!CreateComplexDir(dirPath)) { ErrorMessage = MyFormatNew(IDS_CANNOT_CREATE_FOLDER, #ifdef LANG @@ -65,7 +76,7 @@ struct CThreadExtracting ExtractCallbackSpec->Init(ArchiveLink.GetArchive(), dirPath, L"Default", fi.MTime, 0); - Result = ArchiveLink.GetArchive()->Extract(0, (UInt32)-1 , BoolToInt(false), ExtractCallback); + Result = ArchiveLink.GetArchive()->Extract(0, (UInt32)(Int32)-1 , BoolToInt(false), ExtractCallback); } void Process() @@ -109,11 +120,7 @@ HRESULT ExtractArchive(CCodecs *codecs, const FString &fileName, const FString & RINOK(thread.Create(CThreadExtracting::MyThreadFunction, &t)); UString title; - #ifdef LANG - title = LangLoadString(IDS_PROGRESS_EXTRACTING, 0x02000890); - #else - title = NWindows::MyLoadStringW(IDS_PROGRESS_EXTRACTING); - #endif + LangString(IDS_PROGRESS_EXTRACTING, title); t.ExtractCallbackSpec->StartProgressDialog(title, thread); } else diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/SFXSetup/Main.cpp b/CPP/7zip/Bundles/SFXSetup/Main.cpp deleted file mode 100755 index 008c0e42..00000000 --- a/CPP/7zip/Bundles/SFXSetup/Main.cpp +++ /dev/null @@ -1,337 +0,0 @@ -// 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/FileName.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 CFSTR kTempDirPrefix = FTEXT("7zS"); - -#define _SHELL_EXECUTE - -static bool ReadDataString(CFSTR 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 -{ - FString m_CurrentDirectory; -public: - CCurrentDirRestorer() { NFile::NDirectory::MyGetCurrentDirectory(m_CurrentDirectory); } - ~CCurrentDirRestorer() { RestoreDirectory();} - bool RestoreDirectory() const { return NFile::NDirectory::MySetCurrentDirectory(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); - - FString fullPath; - NDLL::MyGetModuleFileName(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::CTempDir 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; - } - - FString tempDirPath = 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 (!NFile::NDirectory::MySetCurrentDirectory(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(us2fs(appLaunched))) - { - if (!assumeYes) - ShowErrorMessage(L"Can not find setup.exe"); - return 1; - } - } - - { - FString s2 = tempDirPath; - NFile::NName::NormalizeDirPathPrefix(s2); - appLaunched.Replace(L"%%T" WSTRING_PATH_SEPARATOR, fs2us(s2)); - } - - appLaunched.Replace(L"%%T", fs2us(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 old mode 100755 new mode 100644 index 68fe84d6..3a8ae36b --- a/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp +++ b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp @@ -44,7 +44,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_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 CPP /nologo /Gz /MT /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "_SFX" /D "_NO_CRYPTO" /Yu"StdAfx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" @@ -71,7 +71,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /Gz /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 CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "_SFX" /D "_NO_CRYPTO" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" @@ -98,7 +98,7 @@ LINK32=link.exe # 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 CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "_SFX" /D "_NO_CRYPTO" /Yu"StdAfx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" @@ -173,10 +173,6 @@ 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 @@ -401,11 +397,11 @@ SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Error.cpp +SOURCE=..\..\..\Windows\ErrorMsg.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Error.h +SOURCE=..\..\..\Windows\ErrorMsg.h # End Source File # Begin Source File @@ -541,6 +537,10 @@ SOURCE=..\..\Common\ProgressUtils.h # End Source File # Begin Source File +SOURCE=..\..\Common\PropId.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Common\StreamBinder.cpp # End Source File # Begin Source File @@ -641,6 +641,10 @@ SOURCE=..\..\UI\FileManager\FormatUtils.h # End Source File # Begin Source File +SOURCE=..\..\UI\FileManager\LangUtils.h +# End Source File +# Begin Source File + SOURCE=..\..\UI\FileManager\ProgressDialog.cpp # End Source File # Begin Source File @@ -722,11 +726,11 @@ SOURCE=..\..\..\..\C\Threads.h # End Group # Begin Source File -SOURCE=.\ExtractCallback.cpp +SOURCE=.\ExtractCallbackSfx.cpp # End Source File # Begin Source File -SOURCE=.\ExtractCallback.h +SOURCE=.\ExtractCallbackSfx.h # End Source File # Begin Source File @@ -738,11 +742,11 @@ SOURCE=.\ExtractEngine.h # End Source File # Begin Source File -SOURCE=.\Main.cpp +SOURCE=.\setup.ico # End Source File # Begin Source File -SOURCE=.\setup.ico +SOURCE=.\SfxSetup.cpp # End Source File # End Target # End Project diff --git a/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp new file mode 100644 index 00000000..20bde9e9 --- /dev/null +++ b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp @@ -0,0 +1,356 @@ +// 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/ErrorMsg.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/FileIO.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/NtCheck.h" +#include "../../../Windows/ResourceString.h" + +#include "../../UI/Explorer/MyMessages.h" + +#include "ExtractEngine.h" + +#include "resource.h" + +using namespace NWindows; +using namespace NFile; +using namespace NDir; + +HINSTANCE g_hInstance; + +static CFSTR kTempDirPrefix = FTEXT("7zS"); + +#define _SHELL_EXECUTE + +static bool ReadDataString(CFSTR fileName, LPCSTR startID, + LPCSTR endID, AString &stringResult) +{ + stringResult.Empty(); + NIO::CInFile inFile; + if (!inFile.Open(fileName)) + return false; + const int kBufferSize = (1 << 12); + + Byte buffer[kBufferSize]; + int signatureStartSize = MyStringLen(startID); + int signatureEndSize = MyStringLen(endID); + + UInt32 numBytesPrev = 0; + bool writeMode = false; + UInt64 posTotal = 0; + for (;;) + { + if (posTotal > (1 << 20)) + return (stringResult.IsEmpty()); + UInt32 numReadBytes = kBufferSize - numBytesPrev; + UInt32 processedSize; + if (!inFile.Read(buffer + numBytesPrev, numReadBytes, processedSize)) + return false; + if (processedSize == 0) + return true; + UInt32 numBytesInBuffer = numBytesPrev + processedSize; + UInt32 pos = 0; + for (;;) + { + if (writeMode) + { + if (pos > numBytesInBuffer - signatureEndSize) + break; + if (memcmp(buffer + pos, endID, signatureEndSize) == 0) + return true; + char b = buffer[pos]; + if (b == 0) + return false; + stringResult += b; + pos++; + } + else + { + if (pos > numBytesInBuffer - signatureStartSize) + break; + if (memcmp(buffer + pos, startID, signatureStartSize) == 0) + { + writeMode = true; + pos += signatureStartSize; + } + else + pos++; + } + } + numBytesPrev = numBytesInBuffer - pos; + posTotal += pos; + memmove(buffer, buffer + pos, numBytesPrev); + } +} + +static char kStartID[] = ",!@Install@!UTF-8!"; +static char kEndID[] = ",!@InstallEnd@!"; + +class CInstallIDInit +{ +public: + CInstallIDInit() + { + kStartID[0] = ';'; + kEndID[0] = ';'; + }; +} g_CInstallIDInit; + + +#define NT_CHECK_FAIL_ACTION ShowErrorMessage(L"Unsupported Windows version"); return 1; + +static void ShowErrorMessageSpec(const UString &name) +{ + UString message = NError::MyFormatMessage(::GetLastError()); + int pos = message.Find(L"%1"); + if (pos >= 0) + { + message.Delete(pos, 2); + message.Insert(pos, name); + } + ShowErrorMessage(NULL, message); +} + +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); + + FString fullPath; + NDLL::MyGetModuleFileName(fullPath); + + switches.Trim(); + bool assumeYes = false; + if (MyStringCompareNoCase_N(switches, L"-y", 2) == 0) + { + assumeYes = true; + switches = switches.Ptr(2); + switches.Trim(); + } + + AString config; + if (!ReadDataString(fullPath, kStartID, kEndID, config)) + { + if (!assumeYes) + ShowErrorMessage(L"Can't load config info"); + return 1; + } + + UString dirPrefix = 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.IsEqualToNoCase(L"no")) + 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"); + #endif + } + + CTempDir 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; + } + + const FString tempDirPath = tempDir.GetPath(); + // tempDirPath = L"M:\\1\\"; // to test low disk space + { + bool isCorrupt = false; + UString errorMessage; + HRESULT result = ExtractArchive(codecs, fullPath, tempDirPath, showProgress, + isCorrupt, errorMessage); + + if (result != S_OK) + { + if (!assumeYes) + { + if (result == S_FALSE || isCorrupt) + { + NWindows::MyLoadString(IDS_EXTRACTION_ERROR_MESSAGE, errorMessage); + result = E_FAIL; + } + if (result != E_ABORT) + { + if (errorMessage.IsEmpty()) + errorMessage = NError::MyFormatMessage(result); + ::MessageBoxW(0, errorMessage, NWindows::MyLoadString(IDS_EXTRACTION_ERROR_TITLE), MB_ICONERROR); + } + } + return 1; + } + } + + #ifndef UNDER_CE + CCurrentDirRestorer currentDirRestorer; + if (!SetCurrentDir(tempDirPath)) + return 1; + #endif + + HANDLE hProcess = 0; +#ifdef _SHELL_EXECUTE + if (!executeFile.IsEmpty()) + { + CSysString filePath = GetSystemString(executeFile); + SHELLEXECUTEINFO execInfo; + execInfo.cbSize = sizeof(execInfo); + execInfo.fMask = SEE_MASK_NOCLOSEPROCESS + #ifndef UNDER_CE + | SEE_MASK_FLAG_DDEWAIT + #endif + ; + execInfo.hwnd = NULL; + execInfo.lpVerb = NULL; + execInfo.lpFile = filePath; + + if (!switches.IsEmpty()) + { + if (!executeParameters.IsEmpty()) + executeParameters += L' '; + executeParameters += switches; + } + + CSysString parametersSys = GetSystemString(executeParameters); + if (parametersSys.IsEmpty()) + execInfo.lpParameters = NULL; + else + execInfo.lpParameters = parametersSys; + + execInfo.lpDirectory = NULL; + execInfo.nShow = SW_SHOWNORMAL; + execInfo.hProcess = 0; + /* BOOL success = */ ::ShellExecuteEx(&execInfo); + UINT32 result = (UINT32)(UINT_PTR)execInfo.hInstApp; + if(result <= 32) + { + if (!assumeYes) + ShowErrorMessage(L"Can not open file"); + return 1; + } + hProcess = execInfo.hProcess; + } + else +#endif + { + if (appLaunched.IsEmpty()) + { + appLaunched = L"setup.exe"; + if (!NFind::DoesFileExist(us2fs(appLaunched))) + { + if (!assumeYes) + ShowErrorMessage(L"Can not find setup.exe"); + return 1; + } + } + + { + FString s2 = tempDirPath; + NName::NormalizeDirPathPrefix(s2); + appLaunched.Replace(L"%%T" WSTRING_PATH_SEPARATOR, fs2us(s2)); + } + + UString appNameForError = appLaunched; // actually we need to rtemove parameters also + + appLaunched.Replace(L"%%T", fs2us(tempDirPath)); + + if (!switches.IsEmpty()) + { + appLaunched += 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) + { + // we print name of exe file, if error message is + // ERROR_BAD_EXE_FORMAT: "%1 is not a valid Win32 application". + ShowErrorMessageSpec(appNameForError); + } + return 1; + } + ::CloseHandle(processInformation.hThread); + hProcess = processInformation.hProcess; + } + if (hProcess != 0) + { + WaitForSingleObject(hProcess, INFINITE); + ::CloseHandle(hProcess); + } + return 0; +} diff --git a/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp b/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/SFXSetup/StdAfx.h b/CPP/7zip/Bundles/SFXSetup/StdAfx.h old mode 100755 new mode 100644 index 19ece34b..37bbd0c3 --- a/CPP/7zip/Bundles/SFXSetup/StdAfx.h +++ b/CPP/7zip/Bundles/SFXSetup/StdAfx.h @@ -3,8 +3,11 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" -#include "../../../Common/NewHandler.h" +#include "../../../Common/Common.h" + #include +// #define printf(x) NO_PRINTF_(x) +// #define sprintf(x) NO_SPRINTF_(x) + #endif diff --git a/CPP/7zip/Bundles/SFXSetup/makefile b/CPP/7zip/Bundles/SFXSetup/makefile old mode 100755 new mode 100644 index 9136e432..ac5c6aa4 --- a/CPP/7zip/Bundles/SFXSetup/makefile +++ b/CPP/7zip/Bundles/SFXSetup/makefile @@ -1,14 +1,14 @@ PROG = 7zS.sfx -CFLAGS = $(CFLAGS) -I ../../../ \ +CFLAGS = $(CFLAGS) \ -DNO_REGISTRY \ -DEXTRACT_ONLY \ -DNO_READ_FROM_CODER \ -D_SFX \ -D_NO_CRYPTO \ -SFX_WIN_OBJS = \ - $O\Main.obj \ - $O\ExtractCallback.obj \ +CURRENT_OBJS = \ + $O\SfxSetup.obj \ + $O\ExtractCallbackSfx.obj \ $O\ExtractEngine.obj \ COMMON_OBJS = \ @@ -25,7 +25,7 @@ COMMON_OBJS = \ WIN_OBJS = \ $O\DLL.obj \ - $O\Error.obj \ + $O\ErrorMsg.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ @@ -47,6 +47,7 @@ WIN_CTRL_OBJS = \ $O\LockedStream.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ + $O\PropId.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ @@ -58,6 +59,9 @@ UI_COMMON_OBJS = \ $O\LoadCodecs.obj \ $O\OpenArchive.obj \ +EXPLORER_OBJS = \ + $O\MyMessages.obj \ + FM_OBJS = \ $O\FormatUtils.obj \ $O\ProgressDialog.obj \ @@ -74,7 +78,6 @@ AR_COMMON_OBJS = \ $O\7zExtract.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ - $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zRegister.obj \ @@ -101,53 +104,4 @@ C_OBJS = \ !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" +!include "../../7zip.mak" diff --git a/CPP/7zip/Bundles/SFXSetup/resource.h b/CPP/7zip/Bundles/SFXSetup/resource.h old mode 100755 new mode 100644 index 58cd13cb..d5f440bb --- a/CPP/7zip/Bundles/SFXSetup/resource.h +++ b/CPP/7zip/Bundles/SFXSetup/resource.h @@ -1,6 +1,6 @@ -#define IDI_ICON 1 +#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 +#define IDS_EXTRACTION_ERROR_TITLE 7 +#define IDS_EXTRACTION_ERROR_MESSAGE 8 +#define IDS_CANNOT_CREATE_FOLDER 3003 +#define IDS_PROGRESS_EXTRACTING 3300 diff --git a/CPP/7zip/Bundles/SFXSetup/resource.rc b/CPP/7zip/Bundles/SFXSetup/resource.rc old mode 100755 new mode 100644 index 8ccdcf2c..47e1b762 --- a/CPP/7zip/Bundles/SFXSetup/resource.rc +++ b/CPP/7zip/Bundles/SFXSetup/resource.rc @@ -7,10 +7,10 @@ IDI_ICON ICON "setup.ico" STRINGTABLE BEGIN - IDS_EXTRACTION_ERROR_TITLE "Extraction Failed" - IDS_EXTRACTION_ERROR_MESSAGE "File is corrupt" - IDS_CANNOT_CREATE_FOLDER "Cannot create folder '{0}'" - IDS_PROGRESS_EXTRACTING "Extracting" + IDS_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 old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/SFXWin/7z.ico b/CPP/7zip/Bundles/SFXWin/7z.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/SFXWin/Main.cpp b/CPP/7zip/Bundles/SFXWin/Main.cpp deleted file mode 100755 index bd72fc08..00000000 --- a/CPP/7zip/Bundles/SFXWin/Main.cpp +++ /dev/null @@ -1,184 +0,0 @@ -// 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/FileManager/MyWindowsNew.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() -{ - // OleInitialize is required for ProgressBar in TaskBar. - #ifndef UNDER_CE - OleInitialize(NULL); - #endif - - UString password; - bool assumeYes = false; - bool outputFolderDefined = false; - FString outputFolder; - UStringVector commandStrings; - NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); - - #ifndef UNDER_CE - if (commandStrings.Size() > 0) - commandStrings.Delete(0); - #endif - - for (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 = us2fs(s.Mid(2)); - NWindows::NFile::NName::NormalizeDirPathPrefix(outputFolder); - outputFolderDefined = !outputFolder.IsEmpty(); - } - else if (s.Left(2).CompareNoCase(L"-p") == 0) - { - password = s.Mid(2); - } - } - - FString path; - NWindows::NDLL::MyGetModuleFileName(path); - - FString fullPath; - if (!NWindows::NFile::NDirectory::MyGetFullPathName(path, fullPath)) - { - ShowErrorMessage(L"Error 1329484"); - return 1; - } - - CCodecs *codecs = new CCodecs; - CMyComPtr compressCodecsInfo = codecs; - HRESULT result = codecs->Load(); - if (result != S_OK) - { - ErrorMessageForHRESULT(result); - return 1; - } - - // COpenCallbackGUI openCallback; - - // openCallback.PasswordIsDefined = !password.IsEmpty(); - // openCallback.Password = password; - - CExtractCallbackImp *ecs = new CExtractCallbackImp; - CMyComPtr extractCallback = ecs; - ecs->Init(); - - #ifndef _NO_CRYPTO - ecs->PasswordIsDefined = !password.IsEmpty(); - ecs->Password = password; - #endif - - CExtractOptions eo; - - FString dirPrefix; - if (!NWindows::NFile::NDirectory::GetOnlyDirPrefix(path, dirPrefix)) - { - ShowErrorMessage(L"Error 1329485"); - return 1; - } - - eo.OutputDir = outputFolderDefined ? outputFolder : dirPrefix; - 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(fs2us(fullPath)); - v2.Add(fs2us(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 old mode 100755 new mode 100644 index 9cd7e8d2..55dbe377 --- a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp +++ b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp @@ -44,7 +44,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_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 CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_SFXWIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "NO_READ_FROM_CODER" /D "_SFX" /Yu"StdAfx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" @@ -71,7 +71,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /Gz /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 CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_SFXWIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "NO_READ_FROM_CODER" /D "_SFX" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" @@ -81,7 +81,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /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 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Util\7zsfx.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "SFXWin - Win32 ReleaseD" @@ -98,7 +98,7 @@ LINK32=link.exe # 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 CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_SFXWIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "NO_READ_FROM_CODER" /D "_SFX" /Yu"StdAfx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" @@ -165,10 +165,6 @@ 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 @@ -183,6 +179,10 @@ SOURCE=..\..\Archive\7z\7zIn.h SOURCE=..\..\Archive\7z\7zRegister.cpp # End Source File +# Begin Source File + +SOURCE=..\..\Archive\SplitHandler.cpp +# End Source File # End Group # Begin Group "Archive Common" @@ -221,6 +221,14 @@ 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 @@ -313,6 +321,22 @@ SOURCE=..\..\Crypto\MyAes.h # PROP Default_Filter "" # Begin Source File +SOURCE=..\..\UI\FileManager\BrowseDialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\BrowseDialog.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\ComboDialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\ComboDialog.h +# End Source File +# Begin Source File + SOURCE=..\..\UI\FileManager\MessagesDialog.cpp # End Source File # Begin Source File @@ -429,6 +453,10 @@ SOURCE=..\..\Common\ProgressUtils.h # End Source File # Begin Source File +SOURCE=..\..\Common\PropId.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Common\StreamBinder.cpp # End Source File # Begin Source File @@ -479,6 +507,14 @@ SOURCE=..\..\UI\FileManager\FormatUtils.cpp SOURCE=..\..\UI\FileManager\FormatUtils.h # End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\SysIconUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\SysIconUtils.h +# End Source File # End Group # Begin Group "Windows" @@ -488,6 +524,14 @@ SOURCE=..\..\UI\FileManager\FormatUtils.h # 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 @@ -505,6 +549,14 @@ SOURCE=..\..\..\Windows\Control\ListView.h # End Group # Begin Source File +SOURCE=..\..\..\Windows\CommonDialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\CommonDialog.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Windows\DLL.cpp # End Source File # Begin Source File @@ -513,11 +565,11 @@ SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Error.cpp +SOURCE=..\..\..\Windows\ErrorMsg.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Error.h +SOURCE=..\..\..\Windows\ErrorMsg.h # End Source File # Begin Source File @@ -561,11 +613,11 @@ SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\PropVariantConversions.cpp +SOURCE=..\..\..\Windows\PropVariantConv.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\PropVariantConversions.h +SOURCE=..\..\..\Windows\PropVariantConv.h # End Source File # Begin Source File @@ -875,11 +927,11 @@ SOURCE=.\7z1.ico # End Source File # Begin Source File -SOURCE=.\Main.cpp +SOURCE=.\resource.rc # End Source File # Begin Source File -SOURCE=.\resource.rc +SOURCE=.\SfxWin.cpp # End Source File # End Target # End Project diff --git a/CPP/7zip/Bundles/SFXWin/SFXWin.dsw b/CPP/7zip/Bundles/SFXWin/SFXWin.dsw old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/SFXWin/SfxWin.cpp b/CPP/7zip/Bundles/SFXWin/SfxWin.cpp new file mode 100644 index 00000000..ee57d445 --- /dev/null +++ b/CPP/7zip/Bundles/SFXWin/SfxWin.cpp @@ -0,0 +1,233 @@ +// Main.cpp + +#include "StdAfx.h" + +#include + +#include "../../../Common/MyInitGuid.h" + +#include "../../../Common/CommandLineParser.h" +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/DLL.h" +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/NtCheck.h" +#include "../../../Windows/ResourceString.h" + +#include "../../ICoder.h" +#include "../../IPassword.h" +#include "../../Archive/IArchive.h" +#include "../../UI/Common/Extract.h" +#include "../../UI/Common/ExitCode.h" +#include "../../UI/Explorer/MyMessages.h" +#include "../../UI/FileManager/MyWindowsNew.h" +#include "../../UI/GUI/ExtractGUI.h" +#include "../../UI/GUI/ExtractRes.h" + +using namespace NWindows; +using namespace NFile; +using namespace NDir; + +HINSTANCE g_hInstance; + +#ifndef UNDER_CE + +DWORD g_ComCtl32Version; + +static DWORD GetDllVersion(LPCTSTR dllName) +{ + DWORD dwVersion = 0; + HINSTANCE hinstDll = LoadLibrary(dllName); + if (hinstDll) + { + DLLGETVERSIONPROC pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hinstDll, "DllGetVersion"); + if (pDllGetVersion) + { + DLLVERSIONINFO dvi; + ZeroMemory(&dvi, sizeof(dvi)); + dvi.cbSize = sizeof(dvi); + HRESULT hr = (*pDllGetVersion)(&dvi); + if (SUCCEEDED(hr)) + dwVersion = MAKELONG(dvi.dwMinorVersion, dvi.dwMajorVersion); + } + FreeLibrary(hinstDll); + } + return dwVersion; +} + +#endif + +bool g_LVN_ITEMACTIVATE_Support = true; + +static const wchar_t *kUnknownExceptionMessage = L"ERROR: Unknown Error!"; + +void ErrorMessageForHRESULT(HRESULT res) +{ + ShowErrorMessage(HResultToMessage(res)); +} + +int APIENTRY WinMain2() +{ + // OleInitialize is required for ProgressBar in TaskBar. + #ifndef UNDER_CE + OleInitialize(NULL); + #endif + + #ifndef UNDER_CE + g_ComCtl32Version = ::GetDllVersion(TEXT("comctl32.dll")); + g_LVN_ITEMACTIVATE_Support = (g_ComCtl32Version >= MAKELONG(71, 4)); + #endif + + UString password; + bool assumeYes = false; + bool outputFolderDefined = false; + FString outputFolder; + UStringVector commandStrings; + NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); + + #ifndef UNDER_CE + if (commandStrings.Size() > 0) + commandStrings.Delete(0); + #endif + + FOR_VECTOR (i, commandStrings) + { + const UString &s = commandStrings[i]; + if (s.Len() > 1 && s[0] == '-') + { + wchar_t c = MyCharLower_Ascii(s[1]); + if (c == 'y') + { + assumeYes = true; + if (s.Len() != 2) + { + ShowErrorMessage(L"Bad command"); + return 1; + } + } + else if (c == 'o') + { + outputFolder = us2fs(s.Ptr(2)); + NName::NormalizeDirPathPrefix(outputFolder); + outputFolderDefined = !outputFolder.IsEmpty(); + } + else if (c == 'p') + { + password = s.Ptr(2); + } + } + } + + FString path; + NDLL::MyGetModuleFileName(path); + + FString fullPath; + if (!MyGetFullPathName(path, fullPath)) + { + ShowErrorMessage(L"Error 1329484"); + return 1; + } + + CCodecs *codecs = new CCodecs; + CMyComPtr compressCodecsInfo = codecs; + HRESULT result = codecs->Load(); + if (result != S_OK) + { + ErrorMessageForHRESULT(result); + return 1; + } + + // COpenCallbackGUI openCallback; + + // openCallback.PasswordIsDefined = !password.IsEmpty(); + // openCallback.Password = password; + + CExtractCallbackImp *ecs = new CExtractCallbackImp; + CMyComPtr extractCallback = ecs; + ecs->Init(); + + #ifndef _NO_CRYPTO + ecs->PasswordIsDefined = !password.IsEmpty(); + ecs->Password = password; + #endif + + CExtractOptions eo; + + FString dirPrefix; + if (!GetOnlyDirPrefix(path, dirPrefix)) + { + ShowErrorMessage(L"Error 1329485"); + return 1; + } + + eo.OutputDir = outputFolderDefined ? outputFolder : dirPrefix; + eo.YesToAll = assumeYes; + eo.OverwriteMode = assumeYes ? + NExtract::NOverwriteMode::kOverwrite : + NExtract::NOverwriteMode::kAsk; + eo.PathMode = NExtract::NPathMode::kFullPaths; + eo.TestMode = false; + + UStringVector v1, v2; + v1.Add(fs2us(fullPath)); + v2.Add(fs2us(fullPath)); + NWildcard::CCensorNode wildcardCensor; + wildcardCensor.AddItem(true, L"*", true, true, true, true); + + bool messageWasDisplayed = false; + result = ExtractGUI(codecs, + CObjectVector(), CIntVector(), + v1, v2, + wildcardCensor, eo, (assumeYes ? false: true), messageWasDisplayed, ecs); + + if (result == S_OK) + { + if (!ecs->IsOK()) + return NExitCode::kFatalError; + return 0; + } + if (result == E_ABORT) + return NExitCode::kUserBreak; + if (!messageWasDisplayed) + { + if (result == S_FALSE) + ShowErrorMessage(L"Error in archive"); + else + ErrorMessageForHRESULT(result); + } + if (result == E_OUTOFMEMORY) + return NExitCode::kMemoryError; + return NExitCode::kFatalError; +} + +#define NT_CHECK_FAIL_ACTION ShowErrorMessage(L"Unsupported Windows version"); return NExitCode::kFatalError; + +int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, + #ifdef UNDER_CE + LPWSTR + #else + LPSTR + #endif + /* lpCmdLine */, int /* nCmdShow */) +{ + g_hInstance = (HINSTANCE)hInstance; + + NT_CHECK + + try + { + return WinMain2(); + } + catch(const CNewException &) + { + ErrorMessageForHRESULT(E_OUTOFMEMORY); + return NExitCode::kMemoryError; + } + catch(...) + { + ShowErrorMessage(kUnknownExceptionMessage); + return NExitCode::kFatalError; + } +} diff --git a/CPP/7zip/Bundles/SFXWin/StdAfx.cpp b/CPP/7zip/Bundles/SFXWin/StdAfx.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Bundles/SFXWin/StdAfx.h b/CPP/7zip/Bundles/SFXWin/StdAfx.h old mode 100755 new mode 100644 index c5f7231f..975a17e8 --- a/CPP/7zip/Bundles/SFXWin/StdAfx.h +++ b/CPP/7zip/Bundles/SFXWin/StdAfx.h @@ -3,10 +3,12 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" -#include "../../../Common/NewHandler.h" +#include "../../../Common/Common.h" #include #include +// #define printf(x) NO_PRINTF_(x) +// #define sprintf(x) NO_SPRINTF_(x) + #endif diff --git a/CPP/7zip/Bundles/SFXWin/makefile b/CPP/7zip/Bundles/SFXWin/makefile old mode 100755 new mode 100644 index 458ac665..d6e1de78 --- a/CPP/7zip/Bundles/SFXWin/makefile +++ b/CPP/7zip/Bundles/SFXWin/makefile @@ -1,5 +1,5 @@ PROG = 7z.sfx -CFLAGS = $(CFLAGS) -I ../../../ \ +CFLAGS = $(CFLAGS) \ -DNO_REGISTRY \ -DEXTRACT_ONLY \ -DNO_READ_FROM_CODER \ @@ -11,8 +11,8 @@ LIBS = $(LIBS) ceshell.lib Commctrl.lib LIBS = $(LIBS) comctl32.lib comdlg32.lib !ENDIF -SFX_WIN_OBJS = \ - $O\Main.obj \ +CURRENT_OBJS = \ + $O\SfxWin.obj \ GUI_OBJS = \ $O\ExtractDialog.obj \ @@ -29,20 +29,22 @@ COMMON_OBJS = \ $O\Wildcard.obj \ WIN_OBJS = \ + $O\CommonDialog.obj \ $O\DLL.obj \ - $O\Error.obj \ + $O\ErrorMsg.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\PropVariant.obj \ - $O\PropVariantConversions.obj \ + $O\PropVariantConv.obj \ $O\ResourceString.obj \ $O\Shell.obj \ $O\Synchronization.obj \ $O\Window.obj \ WIN_CTRL_OBJS = \ + $O\ComboBox.obj \ $O\Dialog.obj \ $O\ListView.obj \ @@ -57,6 +59,7 @@ WIN_CTRL_OBJS = \ $O\LockedStream.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ + $O\PropId.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ @@ -71,24 +74,28 @@ UI_COMMON_OBJS = \ $O\LoadCodecs.obj \ $O\OpenArchive.obj \ +EXPLORER_OBJS = \ + $O\MyMessages.obj \ + FM_OBJS = \ + $O\BrowseDialog.obj \ + $O\ComboDialog.obj \ $O\ExtractCallback.obj \ $O\FormatUtils.obj \ $O\OverwriteDialog.obj \ $O\PasswordDialog.obj \ $O\ProgressDialog2.obj \ - -!IFDEF UNDER_CE -FM_OBJS = $(FM_OBJS) \ - $O\BrowseDialog.obj \ $O\SysIconUtils.obj \ -!ENDIF + +AR_OBJS = \ + $O\SplitHandler.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\ItemNameUtils.obj \ + $O\MultiStream.obj \ $O\OutStreamWithCRC.obj \ 7Z_OBJS = \ @@ -96,7 +103,6 @@ AR_COMMON_OBJS = \ $O\7zExtract.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ - $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zRegister.obj \ @@ -134,58 +140,4 @@ C_OBJS = \ !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" +!include "../../7zip.mak" diff --git a/CPP/7zip/Bundles/SFXWin/resource.h b/CPP/7zip/Bundles/SFXWin/resource.h old mode 100755 new mode 100644 index 99878ee6..30fe2030 --- a/CPP/7zip/Bundles/SFXWin/resource.h +++ b/CPP/7zip/Bundles/SFXWin/resource.h @@ -1 +1 @@ -#define IDI_ICON 1 +#define IDI_ICON 1 diff --git a/CPP/7zip/Bundles/SFXWin/resource.rc b/CPP/7zip/Bundles/SFXWin/resource.rc old mode 100755 new mode 100644 index 35234cae..91292b2f --- a/CPP/7zip/Bundles/SFXWin/resource.rc +++ b/CPP/7zip/Bundles/SFXWin/resource.rc @@ -1,6 +1,8 @@ #include "../../MyVersionInfo.rc" #include "../../GuiCommon.rc" #include "../../UI/GUI/ExtractDialogRes.h" +#include "../../UI/FileManager/PropertyNameRes.h" + #include "resource.h" MY_VERSION_INFO_APP("7z SFX", "7z.sfx") @@ -10,14 +12,14 @@ MY_VERSION_INFO_APP("7z SFX", "7z.sfx") IDI_ICON ICON "7z.ico" -IDD_DIALOG_EXTRACT MY_DIALOG +IDD_EXTRACT DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT 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 + LTEXT "E&xtract to:", IDT_EXTRACT_EXTRACT_TO, m, m, xc, 8 + EDITTEXT IDC_EXTRACT_PATH, m, 21, xc - bxsDots - 12, 14, ES_AUTOHSCROLL + PUSHBUTTON "...", IDB_EXTRACT_SET_PATH, xs - m - bxsDots, 20, bxsDots, bys, WS_GROUP + DEFPUSHBUTTON "Extract", IDOK, bx2, by, bxs, bys, WS_GROUP + PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys END #ifdef UNDER_CE @@ -25,14 +27,14 @@ END #undef xc #define xc 144 -IDD_DIALOG_EXTRACT_2 MY_DIALOG +IDD_EXTRACT_2 DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT CAPTION "7-Zip self-extracting archive" BEGIN - LTEXT "E&xtract to:", 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 + LTEXT "E&xtract to:", IDT_EXTRACT_EXTRACT_TO, m, m, xc - bxsDots - 12, 8 + EDITTEXT IDC_EXTRACT_PATH, m, m + bys + 4, xc, 14, ES_AUTOHSCROLL + PUSHBUTTON "...", IDB_EXTRACT_SET_PATH, xs - m - bxsDots, m, bxsDots, bys, WS_GROUP + DEFPUSHBUTTON "Extract", IDOK, bx2, by, bxs, bys, WS_GROUP + PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys END #endif @@ -41,3 +43,8 @@ END #include "../../UI/FileManager/PasswordDialog.rc" #include "../../UI/FileManager/ProgressDialog2.rc" #include "../../UI/GUI/Extract.rc" + +STRINGTABLE DISCARDABLE +BEGIN + IDS_PROP_MTIME "Modified" +END diff --git a/CPP/7zip/Bundles/makefile b/CPP/7zip/Bundles/makefile old mode 100755 new mode 100644 diff --git a/CPP/7zip/Common/CWrappers.cpp b/CPP/7zip/Common/CWrappers.cpp old mode 100755 new mode 100644 index ef21228e..e67f5bc4 --- a/CPP/7zip/Common/CWrappers.cpp +++ b/CPP/7zip/Common/CWrappers.cpp @@ -12,7 +12,7 @@ #define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x) -static SRes CompressProgress(void *pp, UInt64 inSize, UInt64 outSize) +static SRes CompressProgress(void *pp, UInt64 inSize, UInt64 outSize) throw() { CCompressProgressWrap *p = (CCompressProgressWrap *)pp; p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outSize)); @@ -30,7 +30,7 @@ static const UInt32 kStreamStepSize = (UInt32)1 << 31; SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) { - switch(res) + switch (res) { case S_OK: return SZ_OK; case E_OUTOFMEMORY: return SZ_ERROR_MEM; @@ -42,18 +42,19 @@ SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) return defaultRes; } -static SRes MyRead(void *object, void *data, size_t *size) +static SRes MyRead(void *object, void *data, size_t *size) throw() { CSeqInStreamWrap *p = (CSeqInStreamWrap *)object; UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize); p->Res = (p->Stream->Read(data, curSize, &curSize)); *size = curSize; + p->Processed += curSize; if (p->Res == S_OK) return SZ_OK; return HRESULT_To_SRes(p->Res, SZ_ERROR_READ); } -static size_t MyWrite(void *object, const void *data, size_t size) +static size_t MyWrite(void *object, const void *data, size_t size) throw() { CSeqOutStreamWrap *p = (CSeqOutStreamWrap *)object; if (p->Stream) @@ -72,6 +73,7 @@ CSeqInStreamWrap::CSeqInStreamWrap(ISequentialInStream *stream) { p.Read = MyRead; Stream = stream; + Processed = 0; } CSeqOutStreamWrap::CSeqOutStreamWrap(ISequentialOutStream *stream) @@ -96,7 +98,7 @@ HRESULT SResToHRESULT(SRes res) return E_FAIL; } -static SRes InStreamWrap_Read(void *pp, void *data, size_t *size) +static SRes InStreamWrap_Read(void *pp, void *data, size_t *size) throw() { CSeekInStreamWrap *p = (CSeekInStreamWrap *)pp; UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize); @@ -105,7 +107,7 @@ static SRes InStreamWrap_Read(void *pp, void *data, size_t *size) return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ; } -static SRes InStreamWrap_Seek(void *pp, Int64 *offset, ESzSeek origin) +static SRes InStreamWrap_Seek(void *pp, Int64 *offset, ESzSeek origin) throw() { CSeekInStreamWrap *p = (CSeekInStreamWrap *)pp; UInt32 moveMethod; @@ -166,7 +168,7 @@ Byte CByteInBufWrap::ReadByteFromNewBlock() return 0; } -static Byte Wrap_ReadByte(void *pp) +static Byte Wrap_ReadByte(void *pp) throw() { CByteInBufWrap *p = (CByteInBufWrap *)pp; if (p->Cur != p->Lim) @@ -212,7 +214,7 @@ HRESULT CByteOutBufWrap::Flush() return Res; } -static void Wrap_WriteByte(void *pp, Byte b) +static void Wrap_WriteByte(void *pp, Byte b) throw() { CByteOutBufWrap *p = (CByteOutBufWrap *)pp; Byte *dest = p->Cur; diff --git a/CPP/7zip/Common/CWrappers.h b/CPP/7zip/Common/CWrappers.h old mode 100755 new mode 100644 index 80a8a1b6..acadc170 --- a/CPP/7zip/Common/CWrappers.h +++ b/CPP/7zip/Common/CWrappers.h @@ -11,7 +11,8 @@ struct CCompressProgressWrap ICompressProgress p; ICompressProgressInfo *Progress; HRESULT Res; - CCompressProgressWrap(ICompressProgressInfo *progress); + + CCompressProgressWrap(ICompressProgressInfo *progress) throw(); }; struct CSeqInStreamWrap @@ -19,7 +20,9 @@ struct CSeqInStreamWrap ISeqInStream p; ISequentialInStream *Stream; HRESULT Res; - CSeqInStreamWrap(ISequentialInStream *stream); + UInt64 Processed; + + CSeqInStreamWrap(ISequentialInStream *stream) throw(); }; struct CSeekInStreamWrap @@ -27,7 +30,8 @@ struct CSeekInStreamWrap ISeekInStream p; IInStream *Stream; HRESULT Res; - CSeekInStreamWrap(IInStream *stream); + + CSeekInStreamWrap(IInStream *stream) throw(); }; struct CSeqOutStreamWrap @@ -36,10 +40,11 @@ struct CSeqOutStreamWrap ISequentialOutStream *Stream; HRESULT Res; UInt64 Processed; - CSeqOutStreamWrap(ISequentialOutStream *stream); + + CSeqOutStreamWrap(ISequentialOutStream *stream) throw(); }; -HRESULT SResToHRESULT(SRes res); +HRESULT SResToHRESULT(SRes res) throw(); struct CByteInBufWrap { @@ -54,9 +59,9 @@ struct CByteInBufWrap HRESULT Res; CByteInBufWrap(); - ~CByteInBufWrap() { Free(); } - void Free(); - bool Alloc(UInt32 size); + ~CByteInBufWrap() { Free(); } + void Free() throw(); + bool Alloc(UInt32 size) throw(); void Init() { Lim = Cur = Buf; @@ -65,7 +70,7 @@ struct CByteInBufWrap Res = S_OK; } UInt64 GetProcessed() const { return Processed + (Cur - Buf); } - Byte ReadByteFromNewBlock(); + Byte ReadByteFromNewBlock() throw(); Byte ReadByte() { if (Cur != Lim) @@ -85,10 +90,10 @@ struct CByteOutBufWrap UInt64 Processed; HRESULT Res; - CByteOutBufWrap(); - ~CByteOutBufWrap() { Free(); } - void Free(); - bool Alloc(size_t size); + CByteOutBufWrap() throw(); + ~CByteOutBufWrap() { Free(); } + void Free() throw(); + bool Alloc(size_t size) throw(); void Init() { Cur = Buf; @@ -97,7 +102,7 @@ struct CByteOutBufWrap Res = S_OK; } UInt64 GetProcessed() const { return Processed + (Cur - Buf); } - HRESULT Flush(); + HRESULT Flush() throw(); void WriteByte(Byte b) { *Cur++ = b; diff --git a/CPP/7zip/Common/CreateCoder.cpp b/CPP/7zip/Common/CreateCoder.cpp old mode 100755 new mode 100644 index cc82a0db..c586561d --- a/CPP/7zip/Common/CreateCoder.cpp +++ b/CPP/7zip/Common/CreateCoder.cpp @@ -13,12 +13,21 @@ static const unsigned int kNumCodecsMax = 64; unsigned int g_NumCodecs = 0; const CCodecInfo *g_Codecs[kNumCodecsMax]; -void RegisterCodec(const CCodecInfo *codecInfo) +void RegisterCodec(const CCodecInfo *codecInfo) throw() { if (g_NumCodecs < kNumCodecsMax) g_Codecs[g_NumCodecs++] = codecInfo; } +static const unsigned int kNumHashersMax = 16; +unsigned int g_NumHashers = 0; +const CHasherInfo *g_Hashers[kNumHashersMax]; +void RegisterHasher(const CHasherInfo *hashInfo) throw() +{ + if (g_NumHashers < kNumHashersMax) + g_Hashers[g_NumHashers++] = hashInfo; +} + #ifdef EXTERNAL_CODECS static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res) { @@ -46,56 +55,74 @@ static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, return S_OK; } -HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector &externalCodecs) +HRESULT CExternalCodecs::LoadCodecs() { - UInt32 num; - RINOK(codecsInfo->GetNumberOfMethods(&num)); - for (UInt32 i = 0; i < num; i++) + if (GetCodecs) + { + UInt32 num; + RINOK(GetCodecs->GetNumberOfMethods(&num)); + for (UInt32 i = 0; i < num; i++) + { + CCodecInfoEx info; + NWindows::NCOM::CPropVariant prop; + RINOK(GetCodecs->GetProperty(i, NMethodPropID::kID, &prop)); + // if (prop.vt != VT_BSTR) + // info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal); + // memcpy(info.Id.ID, prop.bstrVal, info.Id.IDSize); + if (prop.vt != VT_UI8) + continue; // old Interface + info.Id = prop.uhVal.QuadPart; + prop.Clear(); + + RINOK(GetCodecs->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(GetCodecs, i, NMethodPropID::kInStreams, info.NumInStreams)); + RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kOutStreams, info.NumOutStreams)); + RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned)); + RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned)); + + Codecs.Add(info); + } + } + if (GetHashers) { - 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) + UInt32 num = num = GetHashers->GetNumHashers(); + for (UInt32 i = 0; i < num; i++) { - continue; // old Interface - // return E_INVALIDARG; + CHasherInfoEx info; + NWindows::NCOM::CPropVariant prop; + RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kID, &prop)); + if (prop.vt != VT_UI8) + continue; + info.Id = prop.uhVal.QuadPart; + prop.Clear(); + + RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kName, &prop)); + if (prop.vt == VT_BSTR) + info.Name = prop.bstrVal; + else if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + + Hashers.Add(info); } - 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) +bool FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS + 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) + if (name.IsEqualToNoCase(codec.Name)) { methodId = codec.Id; numInStreams = codec.NumInStreams; @@ -104,11 +131,11 @@ bool FindMethod( } } #ifdef EXTERNAL_CODECS - if (externalCodecs) - for (i = 0; i < (UInt32)externalCodecs->Size(); i++) + if (__externalCodecs) + for (i = 0; i < (UInt32)__externalCodecs->Codecs.Size(); i++) { - const CCodecInfoEx &codec = (*externalCodecs)[i]; - if (codec.Name.CompareNoCase(name) == 0) + const CCodecInfoEx &codec = __externalCodecs->Codecs[i]; + if (codec.Name.IsEqualToNoCase(name)) { methodId = codec.Id; numInStreams = codec.NumInStreams; @@ -120,11 +147,8 @@ bool FindMethod( return false; } -bool FindMethod( - #ifdef EXTERNAL_CODECS - ICompressCodecsInfo * /* codecsInfo */, const CObjectVector *externalCodecs, - #endif - CMethodId methodId, UString &name) +bool FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, UString &name) { UInt32 i; for (i = 0; i < g_NumCodecs; i++) @@ -137,10 +161,10 @@ bool FindMethod( } } #ifdef EXTERNAL_CODECS - if (externalCodecs) - for (i = 0; i < (UInt32)externalCodecs->Size(); i++) + if (__externalCodecs) + for (i = 0; i < (UInt32)__externalCodecs->Codecs.Size(); i++) { - const CCodecInfoEx &codec = (*externalCodecs)[i]; + const CCodecInfoEx &codec = __externalCodecs->Codecs[i]; if (methodId == codec.Id) { name = codec.Name; @@ -151,6 +175,49 @@ bool FindMethod( return false; } +bool FindHashMethod(DECL_EXTERNAL_CODECS_LOC_VARS + const UString &name, + CMethodId &methodId) +{ + UInt32 i; + for (i = 0; i < g_NumHashers; i++) + { + const CHasherInfo &codec = *g_Hashers[i]; + if (name.IsEqualToNoCase(codec.Name)) + { + methodId = codec.Id; + return true; + } + } + #ifdef EXTERNAL_CODECS + if (__externalCodecs) + for (i = 0; i < (UInt32)__externalCodecs->Hashers.Size(); i++) + { + const CHasherInfoEx &codec = __externalCodecs->Hashers[i]; + if (codec.Name.IsEqualToNoCase(name)) + { + methodId = codec.Id; + return true; + } + } + #endif + return false; +} + +void GetHashMethods(DECL_EXTERNAL_CODECS_LOC_VARS + CRecordVector &methods) +{ + methods.ClearAndSetSize(g_NumHashers); + UInt32 i; + for (i = 0; i < g_NumHashers; i++) + methods[i] = (*g_Hashers[i]).Id; + #ifdef EXTERNAL_CODECS + if (__externalCodecs) + for (i = 0; i < (UInt32)__externalCodecs->Hashers.Size(); i++) + methods.Add(__externalCodecs->Hashers[i].Id); + #endif +} + HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, @@ -192,10 +259,10 @@ HRESULT CreateCoder( } #ifdef EXTERNAL_CODECS - if (!created && externalCodecs) - for (i = 0; i < (UInt32)externalCodecs->Size(); i++) + if (!created && __externalCodecs) + for (i = 0; i < (UInt32)__externalCodecs->Codecs.Size(); i++) { - const CCodecInfoEx &codec = (*externalCodecs)[i]; + const CCodecInfoEx &codec = __externalCodecs->Codecs[i]; if (codec.Id == methodId) { if (encode) @@ -204,17 +271,17 @@ HRESULT CreateCoder( { if (codec.IsSimpleCodec()) { - HRESULT result = codecsInfo->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder); + HRESULT result = __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder); if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) return result; if (!coder) { - RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter)); + RINOK(__externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter)); } } else { - RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2)); + RINOK(__externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2)); } break; } @@ -224,17 +291,17 @@ HRESULT CreateCoder( { if (codec.IsSimpleCodec()) { - HRESULT result = codecsInfo->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder); + HRESULT result = __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder); if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) return result; if (!coder) { - RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter)); + RINOK(__externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter)); } } else { - RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2)); + RINOK(__externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2)); } break; } @@ -291,3 +358,37 @@ HRESULT CreateFilter( methodId, filter, coder, coder2, encode, false); } + +HRESULT CreateHasher( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + UString &name, + CMyComPtr &hasher) +{ + UInt32 i; + for (i = 0; i < g_NumHashers; i++) + { + const CHasherInfo &codec = *g_Hashers[i]; + if (codec.Id == methodId) + { + hasher = (IHasher *)codec.CreateHasher(); + name = codec.Name; + break; + } + } + + #ifdef EXTERNAL_CODECS + if (!hasher && __externalCodecs) + for (i = 0; i < (UInt32)__externalCodecs->Hashers.Size(); i++) + { + const CHasherInfoEx &codec = __externalCodecs->Hashers[i]; + if (codec.Id == methodId) + { + name = codec.Name; + return __externalCodecs->GetHashers->CreateHasher(i, &hasher); + } + } + #endif + + return S_OK; +} diff --git a/CPP/7zip/Common/CreateCoder.h b/CPP/7zip/Common/CreateCoder.h old mode 100755 new mode 100644 index bf0e96a3..50a68ce1 --- a/CPP/7zip/Common/CreateCoder.h +++ b/CPP/7zip/Common/CreateCoder.h @@ -19,27 +19,43 @@ struct CCodecInfoEx 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); +struct CHasherInfoEx +{ + UString Name; + CMethodId Id; +}; #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 } + COM_TRY_BEGIN __externalCodecs.GetCodecs = compressCodecsInfo; return __externalCodecs.LoadCodecs(); COM_TRY_END } #define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler) -#define EXTERNAL_CODECS_VARS2 _codecsInfo, &_externalCodecs +struct CExternalCodecs +{ + CMyComPtr GetCodecs; + CMyComPtr GetHashers; + + CObjectVector Codecs; + CObjectVector Hashers; + + HRESULT LoadCodecs(); +}; -#define DECL_EXTERNAL_CODECS_VARS CMyComPtr _codecsInfo; CObjectVector _externalCodecs; +#define EXTERNAL_CODECS_VARS2 &__externalCodecs + +#define DECL_EXTERNAL_CODECS_VARS CExternalCodecs __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_VARS2 const CExternalCodecs *__externalCodecs +#define EXTERNAL_CODECS_LOC_VARS2 __externalCodecs #define DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS2, #define EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS2, @@ -68,6 +84,13 @@ bool FindMethod( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, UString &name); +bool FindHashMethod( + DECL_EXTERNAL_CODECS_LOC_VARS + const UString &name, CMethodId &methodId); + +void GetHashMethods( + DECL_EXTERNAL_CODECS_LOC_VARS + CRecordVector &methods); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS @@ -95,4 +118,10 @@ HRESULT CreateFilter( CMyComPtr &filter, bool encode); +HRESULT CreateHasher( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + UString &name, + CMyComPtr &hacher); + #endif diff --git a/CPP/7zip/Common/FilePathAutoRename.cpp b/CPP/7zip/Common/FilePathAutoRename.cpp old mode 100755 new mode 100644 index 495f886b..958360fa --- a/CPP/7zip/Common/FilePathAutoRename.cpp +++ b/CPP/7zip/Common/FilePathAutoRename.cpp @@ -2,10 +2,10 @@ #include "StdAfx.h" -#include "Common/Defs.h" -#include "Common/IntToString.h" +#include "../../Common/Defs.h" +#include "../../Common/IntToString.h" -#include "Windows/FileFind.h" +#include "../../Windows/FileFind.h" #include "FilePathAutoRename.h" @@ -36,8 +36,8 @@ bool AutoRenamePath(FString &fullProcessedPath) FString name, extension; if (dotPos > slashPos && dotPos > 0) { - name = fullProcessedPath.Left(dotPos); - extension = fullProcessedPath.Mid(dotPos); + name.SetFrom(fullProcessedPath, dotPos); + extension = fullProcessedPath.Ptr(dotPos); } else name = fullProcessedPath; diff --git a/CPP/7zip/Common/FilePathAutoRename.h b/CPP/7zip/Common/FilePathAutoRename.h old mode 100755 new mode 100644 index eee0aba7..7b576591 --- a/CPP/7zip/Common/FilePathAutoRename.h +++ b/CPP/7zip/Common/FilePathAutoRename.h @@ -3,7 +3,7 @@ #ifndef __FILE_PATH_AUTO_RENAME_H #define __FILE_PATH_AUTO_RENAME_H -#include "Common/MyString.h" +#include "../../Common/MyString.h" bool AutoRenamePath(FString &fullProcessedPath); diff --git a/CPP/7zip/Common/FileStreams.cpp b/CPP/7zip/Common/FileStreams.cpp old mode 100755 new mode 100644 index a8be8aa4..374336d8 --- a/CPP/7zip/Common/FileStreams.cpp +++ b/CPP/7zip/Common/FileStreams.cpp @@ -1,4 +1,4 @@ -// FileStreams.cpp +/ FileStreams.cpp #include "StdAfx.h" @@ -35,8 +35,9 @@ static const UInt32 kClusterSize = 1 << 18; CInFileStream::CInFileStream(): VirtPos(0), PhyPos(0), - Buffer(0), - BufferSize(0) + Buf(0), + BufSize(0), + SupportHardLinks(false) { } @@ -45,7 +46,7 @@ CInFileStream::CInFileStream(): CInFileStream::~CInFileStream() { #ifdef SUPPORT_DEVICE_FILE - MidFree(Buffer); + MidFree(Buf); #endif } @@ -54,41 +55,41 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) #ifdef USE_WIN_FILE #ifdef SUPPORT_DEVICE_FILE - if (processedSize != NULL) + if (processedSize) *processedSize = 0; if (size == 0) return S_OK; if (File.IsDeviceFile) { - if (File.LengthDefined) + if (File.SizeDefined) { - if (VirtPos >= File.Length) - return VirtPos == File.Length ? S_OK : E_FAIL; - UInt64 rem = File.Length - VirtPos; + if (VirtPos >= File.Size) + return VirtPos == File.Size ? S_OK : E_FAIL; + UInt64 rem = File.Size - VirtPos; if (size > rem) size = (UInt32)rem; } for (;;) { const UInt32 mask = kClusterSize - 1; - UInt64 mask2 = ~(UInt64)mask; + const UInt64 mask2 = ~(UInt64)mask; UInt64 alignedPos = VirtPos & mask2; - if (BufferSize > 0 && BufferStartPos == alignedPos) + if (BufSize > 0 && BufStartPos == alignedPos) { UInt32 pos = (UInt32)VirtPos & mask; - if (pos >= BufferSize) + if (pos >= BufSize) return S_OK; - UInt32 rem = MyMin(BufferSize - pos, size); - memcpy(data, Buffer + pos, rem); + UInt32 rem = MyMin(BufSize - pos, size); + memcpy(data, Buf + pos, rem); VirtPos += rem; - if (processedSize != NULL) + if (processedSize) *processedSize += rem; return S_OK; } - bool useBuffer = false; + bool useBuf = false; if ((VirtPos & mask) != 0 || ((ptrdiff_t)data & mask) != 0 ) - useBuffer = true; + useBuf = true; else { UInt64 end = VirtPos + size; @@ -96,12 +97,12 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { end &= mask2; if (end <= VirtPos) - useBuffer = true; + useBuf = true; else size = (UInt32)(end - VirtPos); } } - if (!useBuffer) + if (!useBuf) break; if (alignedPos != PhyPos) { @@ -112,24 +113,24 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) PhyPos = realNewPosition; } - BufferStartPos = alignedPos; + BufStartPos = alignedPos; UInt32 readSize = kClusterSize; - if (File.LengthDefined) - readSize = (UInt32)MyMin(File.Length - PhyPos, (UInt64)kClusterSize); + if (File.SizeDefined) + readSize = (UInt32)MyMin(File.Size - PhyPos, (UInt64)kClusterSize); - if (Buffer == 0) + if (!Buf) { - Buffer = (Byte *)MidAlloc(kClusterSize); - if (Buffer == 0) + Buf = (Byte *)MidAlloc(kClusterSize); + if (!Buf) return E_OUTOFMEMORY; } - bool result = File.Read1(Buffer, readSize, BufferSize); + bool result = File.Read1(Buf, readSize, BufSize); if (!result) return ConvertBoolToHRESULT(result); - if (BufferSize == 0) + if (BufSize == 0) return S_OK; - PhyPos += BufferSize; + PhyPos += BufSize; } if (VirtPos != PhyPos) @@ -145,7 +146,7 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) UInt32 realProcessedSize; bool result = File.ReadPart(data, size, realProcessedSize); - if (processedSize != NULL) + if (processedSize) *processedSize = realProcessedSize; #ifdef SUPPORT_DEVICE_FILE VirtPos += realProcessedSize; @@ -155,12 +156,12 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) #else - if (processedSize != NULL) + if (processedSize) *processedSize = 0; ssize_t res = File.Read(data, (size_t)size); if (res == -1) return E_FAIL; - if (processedSize != NULL) + if (processedSize) *processedSize = (UInt32)res; return S_OK; @@ -170,10 +171,13 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) #ifdef UNDER_CE STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { - size_t s2 = fread(data, 1, size, stdout); - if (processedSize != 0) + size_t s2 = fread(data, 1, size, stdin); + int error = ferror(stdin); + if (processedSize) *processedSize = s2; - return (s2 = size) ? S_OK : E_FAIL; + if (s2 <= size && error == 0) + return S_OK; + return E_FAIL; } #else STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) @@ -185,7 +189,7 @@ STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSi if (sizeTemp > size) sizeTemp = size; BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, sizeTemp, &realProcessedSize, NULL); - if (processedSize != NULL) + if (processedSize) *processedSize = realProcessedSize; if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE) return S_OK; @@ -193,7 +197,7 @@ STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSi #else - if (processedSize != NULL) + if (processedSize) *processedSize = 0; ssize_t res; do @@ -203,7 +207,7 @@ STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSi while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; - if (processedSize != NULL) + if (processedSize) *processedSize = (UInt32)res; return S_OK; @@ -212,8 +216,7 @@ STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSi #endif -STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, - UInt64 *newPosition) +STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if (seekOrigin >= 3) return STG_E_INVALIDFUNCTION; @@ -221,19 +224,20 @@ STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, #ifdef USE_WIN_FILE #ifdef SUPPORT_DEVICE_FILE - if (File.IsDeviceFile) + if (File.IsDeviceFile && (File.SizeDefined || seekOrigin != STREAM_SEEK_END)) { - UInt64 newVirtPos = offset; - switch(seekOrigin) + switch (seekOrigin) { case STREAM_SEEK_SET: break; - case STREAM_SEEK_CUR: newVirtPos += VirtPos; break; - case STREAM_SEEK_END: newVirtPos += File.Length; break; + case STREAM_SEEK_CUR: offset += VirtPos; break; + case STREAM_SEEK_END: offset += File.Size; break; default: return STG_E_INVALIDFUNCTION; } - VirtPos = newVirtPos; + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + VirtPos = offset; if (newPosition) - *newPosition = newVirtPos; + *newPosition = offset; return S_OK; } #endif @@ -245,7 +249,7 @@ STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, PhyPos = VirtPos = realNewPosition; #endif - if (newPosition != NULL) + if (newPosition) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); @@ -254,7 +258,7 @@ STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, off_t res = File.Seek((off_t)offset, seekOrigin); if (res == -1) return E_FAIL; - if (newPosition != NULL) + if (newPosition) *newPosition = (UInt64)res; return S_OK; @@ -266,6 +270,43 @@ STDMETHODIMP CInFileStream::GetSize(UInt64 *size) return ConvertBoolToHRESULT(File.GetLength(*size)); } +#ifdef USE_WIN_FILE + +STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib) +{ + BY_HANDLE_FILE_INFORMATION info; + if (File.GetFileInformation(&info)) + { + if (size) *size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; + if (cTime) *cTime = info.ftCreationTime; + if (aTime) *aTime = info.ftLastAccessTime; + if (mTime) *mTime = info.ftLastWriteTime; + if (attrib) *attrib = info.dwFileAttributes; + return S_OK; + } + return GetLastError(); +} + +STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) +{ + BY_HANDLE_FILE_INFORMATION info; + if (File.GetFileInformation(&info)) + { + props->Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; + props->VolID = info.dwVolumeSerialNumber; + props->FileID_Low = (((UInt64)info.nFileIndexHigh) << 32) + info.nFileIndexLow; + props->FileID_High = 0; + props->NumLinks = SupportHardLinks ? info.nNumberOfLinks : 1; + props->Attrib = info.dwFileAttributes; + props->CTime = info.ftCreationTime; + props->ATime = info.ftLastAccessTime; + props->MTime = info.ftLastWriteTime; + return S_OK; + } + return GetLastError(); +} + +#endif ////////////////////////// // COutFileStream @@ -282,18 +323,18 @@ STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *proces UInt32 realProcessedSize; bool result = File.WritePart(data, size, realProcessedSize); ProcessedSize += realProcessedSize; - if (processedSize != NULL) + if (processedSize) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else - if (processedSize != NULL) + if (processedSize) *processedSize = 0; ssize_t res = File.Write(data, (size_t)size); if (res == -1) return E_FAIL; - if (processedSize != NULL) + if (processedSize) *processedSize = (UInt32)res; ProcessedSize += res; return S_OK; @@ -309,7 +350,7 @@ STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); - if (newPosition != NULL) + if (newPosition) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); @@ -318,7 +359,7 @@ STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo off_t res = File.Seek((off_t)offset, seekOrigin); if (res == -1) return E_FAIL; - if (newPosition != NULL) + if (newPosition) *newPosition = (UInt64)res; return S_OK; @@ -344,14 +385,14 @@ STDMETHODIMP COutFileStream::SetSize(UInt64 newSize) STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { size_t s2 = fwrite(data, 1, size, stdout); - if (processedSize != 0) + if (processedSize) *processedSize = s2; - return (s2 = size) ? S_OK : E_FAIL; + return (s2 == size) ? S_OK : E_FAIL; } #else STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { - if (processedSize != NULL) + if (processedSize) *processedSize = 0; #ifdef _WIN32 @@ -368,7 +409,7 @@ STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro data, sizeTemp, (DWORD *)&realProcessedSize, NULL); size -= realProcessedSize; data = (const void *)((const Byte *)data + realProcessedSize); - if (processedSize != NULL) + if (processedSize) *processedSize += realProcessedSize; } return ConvertBoolToHRESULT(res != FALSE); @@ -383,7 +424,7 @@ STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; - if (processedSize != NULL) + if (processedSize) *processedSize = (UInt32)res; return S_OK; diff --git a/CPP/7zip/Common/FileStreams.h b/CPP/7zip/Common/FileStreams.h old mode 100755 new mode 100644 index bb2b1d41..971366e9 --- a/CPP/7zip/Common/FileStreams.h +++ b/CPP/7zip/Common/FileStreams.h @@ -22,21 +22,30 @@ class CInFileStream: public IInStream, public IStreamGetSize, + #ifdef USE_WIN_FILE + public IStreamGetProps, + public IStreamGetProps2, + #endif public CMyUnknownImp { public: #ifdef USE_WIN_FILE NWindows::NFile::NIO::CInFile File; + #ifdef SUPPORT_DEVICE_FILE UInt64 VirtPos; UInt64 PhyPos; - UInt64 BufferStartPos; - Byte *Buffer; - UInt32 BufferSize; + UInt64 BufStartPos; + Byte *Buf; + UInt32 BufSize; #endif + #else NC::NFile::NIO::CInFile File; #endif + + bool SupportHardLinks; + virtual ~CInFileStream(); #ifdef SUPPORT_DEVICE_FILE @@ -53,12 +62,23 @@ public: return File.OpenShared(fileName, shareForWrite); } - MY_UNKNOWN_IMP2(IInStream, IStreamGetSize) + MY_QUERYINTERFACE_BEGIN2(IInStream) + MY_QUERYINTERFACE_ENTRY(IStreamGetSize) + #ifdef USE_WIN_FILE + MY_QUERYINTERFACE_ENTRY(IStreamGetProps) + MY_QUERYINTERFACE_ENTRY(IStreamGetProps2) + #endif + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(GetSize)(UInt64 *size); + #ifdef USE_WIN_FILE + STDMETHOD(GetProps)(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib); + STDMETHOD(GetProps2)(CStreamFileProps *props); + #endif }; class CStdInFileStream: diff --git a/CPP/7zip/Common/FilterCoder.cpp b/CPP/7zip/Common/FilterCoder.cpp old mode 100755 new mode 100644 index 69673527..578a3193 --- a/CPP/7zip/Common/FilterCoder.cpp +++ b/CPP/7zip/Common/FilterCoder.cpp @@ -153,10 +153,16 @@ STDMETHODIMP CFilterCoder::Flush() } -STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream) +void CFilterCoder::SetInStream_NoSubFilterInit(ISequentialInStream *inStream) { _convertedPosBegin = _convertedPosEnd = _bufferPos = 0; _inStream = inStream; + Init2(); +} + +STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream) +{ + SetInStream_NoSubFilterInit(inStream); return Init(); } @@ -210,10 +216,22 @@ STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize) } #ifndef _NO_CRYPTO + STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size) { return _setPassword->CryptoSetPassword(data, size); } + +STDMETHODIMP CFilterCoder::SetKey(const Byte *data, UInt32 size) +{ + return _cryptoProperties->SetKey(data, size); +} + +STDMETHODIMP CFilterCoder::SetInitVector(const Byte *data, UInt32 size) +{ + return _cryptoProperties->SetInitVector(data, size); +} + #endif #ifndef EXTRACT_ONLY diff --git a/CPP/7zip/Common/FilterCoder.h b/CPP/7zip/Common/FilterCoder.h old mode 100755 new mode 100644 index 8132a6dd..2b8f142f --- a/CPP/7zip/Common/FilterCoder.h +++ b/CPP/7zip/Common/FilterCoder.h @@ -7,9 +7,9 @@ #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; } +#define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) else if (iid == IID_ ## i) \ + { if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \ + *outObject = (void *)(i *)this; } class CFilterCoder: public ICompressCoder, @@ -21,6 +21,7 @@ class CFilterCoder: #ifndef _NO_CRYPTO public ICryptoSetPassword, + public ICryptoProperties, #endif #ifndef EXTRACT_ONLY public ICompressSetCoderProperties, @@ -42,14 +43,20 @@ protected: UInt64 _outSize; UInt64 _nowPos64; - HRESULT Init() + void Init2() { _nowPos64 = 0; _outSizeIsDefined = false; + } + + HRESULT Init() + { + Init2(); return Filter->Init(); } CMyComPtr _setPassword; + CMyComPtr _cryptoProperties; #ifndef EXTRACT_ONLY CMyComPtr _SetCoderProperties; CMyComPtr _writeCoderProperties; @@ -74,6 +81,7 @@ public: #ifndef _NO_CRYPTO MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword) + MY_QUERYINTERFACE_ENTRY_AG(ICryptoProperties, Filter, _cryptoProperties) #endif #ifndef EXTRACT_ONLY @@ -98,6 +106,9 @@ public: #ifndef _NO_CRYPTO STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); + + STDMETHOD(SetKey)(const Byte *data, UInt32 size); + STDMETHOD(SetInitVector)(const Byte *data, UInt32 size); #endif #ifndef EXTRACT_ONLY STDMETHOD(SetCoderProperties)(const PROPID *propIDs, @@ -107,6 +118,9 @@ public: STDMETHOD(ResetInitVector)(); #endif STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); + + void SetInStream_NoSubFilterInit(ISequentialInStream *inStream); + }; class CInStreamReleaser diff --git a/CPP/7zip/Common/InBuffer.cpp b/CPP/7zip/Common/InBuffer.cpp old mode 100755 new mode 100644 index ad4f8825..8edefa31 --- a/CPP/7zip/Common/InBuffer.cpp +++ b/CPP/7zip/Common/InBuffer.cpp @@ -6,50 +6,49 @@ #include "InBuffer.h" -CInBuffer::CInBuffer(): - _buffer(0), - _bufferLimit(0), - _bufferBase(0), +CInBufferBase::CInBufferBase(): + _buf(0), + _bufLim(0), + _bufBase(0), _stream(0), - _bufferSize(0) + _processedSize(0), + _bufSize(0), + _wasFinished(false), + NumExtraBytes(0) {} -bool CInBuffer::Create(UInt32 bufferSize) +bool CInBuffer::Create(size_t bufSize) { - const UInt32 kMinBlockSize = 1; - if (bufferSize < kMinBlockSize) - bufferSize = kMinBlockSize; - if (_bufferBase != 0 && _bufferSize == bufferSize) + const unsigned kMinBlockSize = 1; + if (bufSize < kMinBlockSize) + bufSize = kMinBlockSize; + if (_bufBase != 0 && _bufSize == bufSize) return true; Free(); - _bufferSize = bufferSize; - _bufferBase = (Byte *)::MidAlloc(bufferSize); - return (_bufferBase != 0); + _bufSize = bufSize; + _bufBase = (Byte *)::MidAlloc(bufSize); + return (_bufBase != 0); } void CInBuffer::Free() { - ::MidFree(_bufferBase); - _bufferBase = 0; + ::MidFree(_bufBase); + _bufBase = 0; } -void CInBuffer::SetStream(ISequentialInStream *stream) -{ - _stream = stream; -} - -void CInBuffer::Init() +void CInBufferBase::Init() { _processedSize = 0; - _buffer = _bufferBase; - _bufferLimit = _buffer; + _buf = _bufBase; + _bufLim = _buf; _wasFinished = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif + NumExtraBytes = 0; } -bool CInBuffer::ReadBlock() +bool CInBufferBase::ReadBlock() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) @@ -57,27 +56,80 @@ bool CInBuffer::ReadBlock() #endif if (_wasFinished) return false; - _processedSize += (_buffer - _bufferBase); - UInt32 numProcessedBytes; - HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes); + _processedSize += (_buf - _bufBase); + _buf = _bufBase; + _bufLim = _bufBase; + UInt32 processed; + // FIX_ME: we can improve it to support (_bufSize >= (1 << 32)) + HRESULT result = _stream->Read(_bufBase, (UInt32)_bufSize, &processed); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw CInBufferException(result); #endif - _buffer = _bufferBase; - _bufferLimit = _buffer + numProcessedBytes; - _wasFinished = (numProcessedBytes == 0); - return (!_wasFinished); + _bufLim = _buf + processed; + _wasFinished = (processed == 0); + return !_wasFinished; } -Byte CInBuffer::ReadBlock2() +bool CInBufferBase::ReadByte_FromNewBlock(Byte &b) { if (!ReadBlock()) { - _processedSize++; + NumExtraBytes++; + b = 0xFF; + return false; + } + b = *_buf++; + return true; +} + +Byte CInBufferBase::ReadByte_FromNewBlock() +{ + if (!ReadBlock()) + { + NumExtraBytes++; return 0xFF; } - return *_buffer++; + return *_buf++; +} + +size_t CInBufferBase::ReadBytes(Byte *buf, size_t size) +{ + if ((size_t)(_bufLim - _buf) >= size) + { + const Byte *src = _buf; + for (size_t i = 0; i < size; i++) + buf[i] = src[i]; + _buf += size; + return size; + } + for (size_t i = 0; i < size; i++) + { + if (_buf >= _bufLim) + if (!ReadBlock()) + return i; + buf[i] = *_buf++; + } + return size; +} + +size_t CInBufferBase::Skip(size_t size) +{ + size_t processed = 0; + for (;;) + { + size_t rem = (_bufLim - _buf); + if (rem >= size) + { + _buf += size; + return processed + size; + } + _buf += rem; + processed += rem; + size -= rem; + if (!ReadBlock()) + return processed; + } } diff --git a/CPP/7zip/Common/InBuffer.h b/CPP/7zip/Common/InBuffer.h old mode 100755 new mode 100644 index 75625bfd..4b8662bb --- a/CPP/7zip/Common/InBuffer.h +++ b/CPP/7zip/Common/InBuffer.h @@ -1,11 +1,10 @@ // InBuffer.h -#ifndef __INBUFFER_H -#define __INBUFFER_H +#ifndef __IN_BUFFER_H +#define __IN_BUFFER_H -#include "../IStream.h" -#include "../../Common/MyCom.h" #include "../../Common/MyException.h" +#include "../IStream.h" #ifndef _NO_EXCEPTIONS struct CInBufferException: public CSystemException @@ -14,68 +13,78 @@ struct CInBufferException: public CSystemException }; #endif -class CInBuffer +class CInBufferBase { - Byte *_buffer; - Byte *_bufferLimit; - Byte *_bufferBase; - CMyComPtr _stream; +protected: + Byte *_buf; + Byte *_bufLim; + Byte *_bufBase; + + ISequentialInStream *_stream; UInt64 _processedSize; - UInt32 _bufferSize; + size_t _bufSize; // actually it's number of Bytes for next read. The buf can be larger + // only up to 32-bits values now are supported! bool _wasFinished; bool ReadBlock(); - Byte ReadBlock2(); + bool ReadByte_FromNewBlock(Byte &b); + Byte ReadByte_FromNewBlock(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif + UInt32 NumExtraBytes; - CInBuffer(); - ~CInBuffer() { Free(); } + CInBufferBase() throw(); + + UInt64 GetStreamSize() const { return _processedSize + (_buf - _bufBase); } + UInt64 GetProcessedSize() const { return _processedSize + NumExtraBytes + (_buf - _bufBase); } + bool WasFinished() const { return _wasFinished; } - bool Create(UInt32 bufferSize); - void Free(); + void SetStream(ISequentialInStream *stream) { _stream = stream; } - void SetStream(ISequentialInStream *stream); - void Init(); - void ReleaseStream() { _stream.Release(); } + void SetBuf(Byte *buf, size_t bufSize, size_t end, size_t pos) + { + _bufBase = buf; + _bufSize = bufSize; + _processedSize = 0; + _buf = buf + pos; + _bufLim = buf + end; + _wasFinished = false; + #ifdef _NO_EXCEPTIONS + ErrorCode = S_OK; + #endif + NumExtraBytes = 0; + } + + void Init() throw(); bool ReadByte(Byte &b) { - if (_buffer >= _bufferLimit) - if (!ReadBlock()) - return false; - b = *_buffer++; + if (_buf >= _bufLim) + return ReadByte_FromNewBlock(b); + b = *_buf++; return true; } + Byte ReadByte() { - if (_buffer >= _bufferLimit) - return ReadBlock2(); - return *_buffer++; + if (_buf >= _bufLim) + return ReadByte_FromNewBlock(); + return *_buf++; } - 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; } + + size_t ReadBytes(Byte *buf, size_t size); + size_t Skip(size_t size); +}; + +class CInBuffer: public CInBufferBase +{ +public: + ~CInBuffer() { Free(); } + bool Create(size_t bufSize) throw(); // only up to 32-bits values now are supported! + void Free() throw(); }; #endif diff --git a/CPP/7zip/Common/InMemStream.cpp b/CPP/7zip/Common/InMemStream.cpp old mode 100755 new mode 100644 index 38c5c92c..d88c2d8a --- a/CPP/7zip/Common/InMemStream.cpp +++ b/CPP/7zip/Common/InMemStream.cpp @@ -178,7 +178,7 @@ HRESULT CInMemStreamMt::ReadSubStream(int subStreamIndex, void *data, UInt32 siz if (curSize > size) curSize = size; void *p = blocks.Blocks[blocks.CurBlockIndex]; - memmove(data, (const Byte *)p + curPos, curSize); + memcpy(data, (const Byte *)p + curPos, curSize); data = (void *)((Byte *)data + curSize); size -= curSize; if (processedSize != NULL) diff --git a/CPP/7zip/Common/InMemStream.h b/CPP/7zip/Common/InMemStream.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Common/InOutTempBuffer.cpp b/CPP/7zip/Common/InOutTempBuffer.cpp old mode 100755 new mode 100644 index 442374da..be65ba32 --- a/CPP/7zip/Common/InOutTempBuffer.cpp +++ b/CPP/7zip/Common/InOutTempBuffer.cpp @@ -4,12 +4,14 @@ #include "../../../C/7zCrc.h" +#include "../../Common/Defs.h" + #include "InOutTempBuffer.h" #include "StreamUtils.h" using namespace NWindows; using namespace NFile; -using namespace NDirectory; +using namespace NDir; static const UInt32 kTempBufSize = (1 << 20); diff --git a/CPP/7zip/Common/InOutTempBuffer.h b/CPP/7zip/Common/InOutTempBuffer.h old mode 100755 new mode 100644 index bdf937de..256d7242 --- a/CPP/7zip/Common/InOutTempBuffer.h +++ b/CPP/7zip/Common/InOutTempBuffer.h @@ -10,7 +10,7 @@ class CInOutTempBuffer { - NWindows::NFile::NDirectory::CTempFile _tempFile; + NWindows::NFile::NDir::CTempFile _tempFile; NWindows::NFile::NIO::COutFile _outFile; Byte *_buf; UInt32 _bufPos; diff --git a/CPP/7zip/Common/LimitedStreams.cpp b/CPP/7zip/Common/LimitedStreams.cpp old mode 100755 new mode 100644 index 1837e320..de236040 --- a/CPP/7zip/Common/LimitedStreams.cpp +++ b/CPP/7zip/Common/LimitedStreams.cpp @@ -17,17 +17,21 @@ STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *p if (realProcessedSize == 0) _wasFinished = true; } - if (processedSize != NULL) + if (processedSize) *processedSize = realProcessedSize; return result; } STDMETHODIMP CLimitedInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { - if (processedSize != NULL) + if (processedSize) *processedSize = 0; if (_virtPos >= _size) - return (_virtPos == _size) ? S_OK: E_FAIL; + { + // 9.31: Fixed. Windows doesn't return error in ReadFile and IStream->Read in that case. + return S_OK; + // return (_virtPos == _size) ? S_OK: E_FAIL; // ERROR_HANDLE_EOF + } UInt64 rem = _size - _virtPos; if (rem < size) size = (UInt32)rem; @@ -38,7 +42,7 @@ STDMETHODIMP CLimitedInStream::Read(void *data, UInt32 size, UInt32 *processedSi RINOK(SeekToPhys()); } HRESULT res = _stream->Read(data, size, &size); - if (processedSize != NULL) + if (processedSize) *processedSize = size; _physPos += size; _virtPos += size; @@ -47,24 +51,39 @@ STDMETHODIMP CLimitedInStream::Read(void *data, UInt32 size, UInt32 *processedSi STDMETHODIMP CLimitedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - switch(seekOrigin) + switch (seekOrigin) { - case STREAM_SEEK_SET: _virtPos = offset; break; - case STREAM_SEEK_CUR: _virtPos += offset; break; - case STREAM_SEEK_END: _virtPos = _size + offset; break; + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: offset += _size; break; default: return STG_E_INVALIDFUNCTION; } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = offset; if (newPosition) *newPosition = _virtPos; return S_OK; } +HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream) +{ + *resStream = 0; + CLimitedInStream *streamSpec = new CLimitedInStream; + CMyComPtr streamTemp = streamSpec; + streamSpec->SetStream(inStream); + RINOK(streamSpec->InitAndSeek(pos, size)); + streamSpec->SeekToStart(); + *resStream = streamTemp.Detach(); + return S_OK; +} + STDMETHODIMP CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { - if (processedSize != NULL) + if (processedSize) *processedSize = 0; if (_virtPos >= Size) - return (_virtPos == Size) ? S_OK: E_FAIL; + return S_OK; if (_curRem == 0) { @@ -88,7 +107,7 @@ STDMETHODIMP CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSi if (size > _curRem) size = _curRem; HRESULT res = Stream->Read(data, size, &size); - if (processedSize != NULL) + if (processedSize) *processedSize = size; _physPos += size; _virtPos += size; @@ -98,39 +117,88 @@ STDMETHODIMP CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSi STDMETHODIMP CClusterInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - UInt64 newVirtPos = offset; - switch(seekOrigin) + switch (seekOrigin) { case STREAM_SEEK_SET: break; - case STREAM_SEEK_CUR: newVirtPos += _virtPos; break; - case STREAM_SEEK_END: newVirtPos += Size; break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: offset += Size; break; default: return STG_E_INVALIDFUNCTION; } - if (_virtPos != newVirtPos) + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + if (_virtPos != (UInt64)offset) _curRem = 0; - _virtPos = newVirtPos; + _virtPos = offset; if (newPosition) - *newPosition = newVirtPos; + *newPosition = offset; return S_OK; } -HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream) +STDMETHODIMP CExtentsStream::Read(void *data, UInt32 size, UInt32 *processedSize) { - *resStream = 0; - CLimitedInStream *streamSpec = new CLimitedInStream; - CMyComPtr streamTemp = streamSpec; - streamSpec->SetStream(inStream); - RINOK(streamSpec->InitAndSeek(pos, size)); - streamSpec->SeekToStart(); - *resStream = streamTemp.Detach(); + if (processedSize) + *processedSize = 0; + if (_virtPos >= Extents.Back().Virt) + return S_OK; + if (size == 0) + return S_OK; + + unsigned left = 0, right = Extents.Size() - 1; + for (;;) + { + unsigned mid = (left + right) / 2; + if (mid == left) + break; + if (_virtPos < Extents[mid].Virt) + right = mid; + else + left = mid; + } + + const CSeekExtent &extent = Extents[left]; + UInt64 phyPos = extent.Phy + (_virtPos - extent.Virt); + if (_needStartSeek || _phyPos != phyPos) + { + _needStartSeek = false; + _phyPos = phyPos; + RINOK(SeekToPhys()); + } + + UInt64 rem = Extents[left + 1].Virt - _virtPos; + if (size > rem) + size = (UInt32)rem; + + HRESULT res = Stream->Read(data, size, &size); + _phyPos += size; + _virtPos += size; + if (processedSize) + *processedSize = size; + return res; +} + +STDMETHODIMP CExtentsStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: offset += Extents.Back().Virt; break; + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = offset; + if (newPosition) + *newPosition = _virtPos; return S_OK; } + STDMETHODIMP CLimitedSequentialOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { HRESULT result = S_OK; - if (processedSize != NULL) + if (processedSize) *processedSize = 0; if (size > _size) { @@ -139,7 +207,7 @@ STDMETHODIMP CLimitedSequentialOutStream::Write(const void *data, UInt32 size, U _overflow = true; if (!_overflowIsAllowed) return E_FAIL; - if (processedSize != NULL) + if (processedSize) *processedSize = size; return S_OK; } @@ -148,7 +216,134 @@ STDMETHODIMP CLimitedSequentialOutStream::Write(const void *data, UInt32 size, U if (_stream) result = _stream->Write(data, size, &size); _size -= size; - if (processedSize != NULL) + if (processedSize) *processedSize = size; return result; } + + +STDMETHODIMP CTailInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 cur; + HRESULT res = Stream->Read(data, size, &cur); + if (processedSize) + *processedSize = cur; + _virtPos += cur; + return res; +} + +STDMETHODIMP CTailInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: + { + UInt64 pos = 0; + RINOK(Stream->Seek(offset, STREAM_SEEK_END, &pos)); + if (pos < Offset) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = pos - Offset; + if (newPosition) + *newPosition = _virtPos; + return S_OK; + } + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = offset; + if (newPosition) + *newPosition = _virtPos; + return Stream->Seek(Offset + _virtPos, STREAM_SEEK_SET, NULL); +} + +STDMETHODIMP CLimitedCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (_virtPos >= _size) + { + // 9.31: Fixed. Windows doesn't return error in ReadFile and IStream->Read in that case. + return S_OK; + // return (_virtPos == _size) ? S_OK: E_FAIL; // ERROR_HANDLE_EOF + } + UInt64 rem = _size - _virtPos; + if (rem < size) + size = (UInt32)rem; + + UInt64 newPos = _startOffset + _virtPos; + UInt64 offsetInCache = newPos - _cachePhyPos; + HRESULT res = S_OK; + if (newPos >= _cachePhyPos && + offsetInCache <= _cacheSize && + size <= _cacheSize - (size_t)offsetInCache) + memcpy(data, _cache + (size_t)offsetInCache, size); + else + { + if (newPos != _physPos) + { + _physPos = newPos; + RINOK(SeekToPhys()); + } + res = _stream->Read(data, size, &size); + _physPos += size; + } + if (processedSize) + *processedSize = size; + _virtPos += size; + return res; +} + +STDMETHODIMP CLimitedCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: offset += _size; break; + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = offset; + if (newPosition) + *newPosition = _virtPos; + return S_OK; +} + +STDMETHODIMP CTailOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 cur; + HRESULT res = Stream->Write(data, size, &cur); + if (processedSize) + *processedSize = cur; + _virtPos += cur; + if (_virtSize < _virtPos) + _virtSize = _virtPos; + return res; +} + +STDMETHODIMP CTailOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: offset += _virtSize; break; + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = offset; + if (newPosition) + *newPosition = _virtPos; + return Stream->Seek(Offset + _virtPos, STREAM_SEEK_SET, NULL); +} + +STDMETHODIMP CTailOutStream::SetSize(UInt64 newSize) +{ + _virtSize = newSize; + return Stream->SetSize(Offset + newSize); +} diff --git a/CPP/7zip/Common/LimitedStreams.h b/CPP/7zip/Common/LimitedStreams.h old mode 100755 new mode 100644 index 2cbe18e4..a9378491 --- a/CPP/7zip/Common/LimitedStreams.h +++ b/CPP/7zip/Common/LimitedStreams.h @@ -3,6 +3,7 @@ #ifndef __LIMITED_STREAMS_H #define __LIMITED_STREAMS_H +#include "../../Common/MyBuffer.h" #include "../../Common/MyCom.h" #include "../../Common/MyVector.h" #include "../IStream.h" @@ -25,7 +26,7 @@ public: _wasFinished = false; } - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP1(ISequentialInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); UInt64 GetSize() const { return _pos; } @@ -54,7 +55,7 @@ public: return SeekToPhys(); } - MY_UNKNOWN_IMP1(IInStream) + MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); @@ -62,6 +63,8 @@ public: HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); } }; +HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream); + class CClusterInStream: public IInStream, public CMyUnknownImp @@ -73,7 +76,7 @@ public: CMyComPtr Stream; UInt64 StartOffset; UInt64 Size; - int BlockSizeLog; + unsigned BlockSizeLog; CRecordVector Vector; HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); } @@ -91,13 +94,44 @@ public: return S_OK; } - MY_UNKNOWN_IMP1(IInStream) + MY_UNKNOWN_IMP2(ISequentialInStream, 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); +struct CSeekExtent +{ + UInt64 Phy; + UInt64 Virt; +}; + +class CExtentsStream: + public IInStream, + public CMyUnknownImp +{ + UInt64 _phyPos; + UInt64 _virtPos; + bool _needStartSeek; + + HRESULT SeekToPhys() { return Stream->Seek(_phyPos, STREAM_SEEK_SET, NULL); } + +public: + CMyComPtr Stream; + CRecordVector Extents; + + MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + void ReleaseStream() { Stream.Release(); } + + void Init() + { + _virtPos = 0; + _phyPos = 0; + _needStartSeek = true; + } +}; class CLimitedSequentialOutStream: public ISequentialOutStream, @@ -108,7 +142,7 @@ class CLimitedSequentialOutStream: bool _overflow; bool _overflowIsAllowed; public: - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP1(ISequentialOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); void SetStream(ISequentialOutStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } @@ -122,4 +156,96 @@ public: UInt64 GetRem() const { return _size; } }; + +class CTailInStream: + public IInStream, + public CMyUnknownImp +{ + UInt64 _virtPos; +public: + CMyComPtr Stream; + UInt64 Offset; + + void Init() + { + _virtPos = 0; + } + + MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + + HRESULT SeekToStart() { return Stream->Seek(Offset, STREAM_SEEK_SET, NULL); } +}; + +class CLimitedCachedInStream: + public IInStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + UInt64 _virtPos; + UInt64 _physPos; + UInt64 _size; + UInt64 _startOffset; + + const Byte *_cache; + size_t _cacheSize; + size_t _cachePhyPos; + + + HRESULT SeekToPhys() { return _stream->Seek(_physPos, STREAM_SEEK_SET, NULL); } +public: + CByteBuffer Buffer; + + void SetStream(IInStream *stream) { _stream = stream; } + void SetCache(size_t cacheSize, size_t cachePos) + { + _cache = Buffer; + _cacheSize = cacheSize; + _cachePhyPos = cachePos; + } + + HRESULT InitAndSeek(UInt64 startOffset, UInt64 size) + { + _startOffset = startOffset; + _physPos = startOffset; + _virtPos = 0; + _size = size; + return SeekToPhys(); + } + + MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + + HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); } +}; + +class CTailOutStream: + public IOutStream, + public CMyUnknownImp +{ + UInt64 _virtPos; + UInt64 _virtSize; +public: + CMyComPtr Stream; + UInt64 Offset; + + virtual ~CTailOutStream() {} + + MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStream) + + void Init() + { + _virtPos = 0; + _virtSize = 0; + } + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + STDMETHOD(SetSize)(UInt64 newSize); +}; + #endif diff --git a/CPP/7zip/Common/LockedStream.cpp b/CPP/7zip/Common/LockedStream.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Common/LockedStream.h b/CPP/7zip/Common/LockedStream.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Common/MemBlocks.cpp b/CPP/7zip/Common/MemBlocks.cpp old mode 100755 new mode 100644 index a5b93b5e..eb0cc39a --- a/CPP/7zip/Common/MemBlocks.cpp +++ b/CPP/7zip/Common/MemBlocks.cpp @@ -120,7 +120,7 @@ void CMemBlocks::FreeOpt(CMemBlockManagerMt *manager) HRESULT CMemBlocks::WriteToStream(size_t blockSize, ISequentialOutStream *outStream) const { UInt64 totalSize = TotalSize; - for (int blockIndex = 0; totalSize > 0; blockIndex++) + for (unsigned blockIndex = 0; totalSize > 0; blockIndex++) { UInt32 curSize = (UInt32)blockSize; if (totalSize < curSize) @@ -169,7 +169,7 @@ void CMemLockBlocks::Detach(CMemLockBlocks &blocks, CMemBlockManagerMt *memManag blocks.LockMode = LockMode; UInt64 totalSize = 0; size_t blockSize = memManager->GetBlockSize(); - for (int i = 0; i < Blocks.Size(); i++) + FOR_VECTOR (i, Blocks) { if (totalSize < TotalSize) blocks.Blocks.Add(Blocks[i]); diff --git a/CPP/7zip/Common/MemBlocks.h b/CPP/7zip/Common/MemBlocks.h old mode 100755 new mode 100644 index e1058ae3..ec56c14d --- a/CPP/7zip/Common/MemBlocks.h +++ b/CPP/7zip/Common/MemBlocks.h @@ -3,9 +3,9 @@ #ifndef __MEM_BLOCKS_H #define __MEM_BLOCKS_H -#include "Common/MyVector.h" +#include "../../Common/MyVector.h" -#include "Windows/Synchronization.h" +#include "../../Windows/Synchronization.h" #include "../IStream.h" diff --git a/CPP/7zip/Common/MethodId.cpp b/CPP/7zip/Common/MethodId.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Common/MethodId.h b/CPP/7zip/Common/MethodId.h old mode 100755 new mode 100644 index 54ebc9f7..28b615fc --- a/CPP/7zip/Common/MethodId.h +++ b/CPP/7zip/Common/MethodId.h @@ -3,7 +3,7 @@ #ifndef __7Z_METHOD_ID_H #define __7Z_METHOD_ID_H -#include "../../Common/Types.h" +#include "../../Common/MyTypes.h" typedef UInt64 CMethodId; diff --git a/CPP/7zip/Common/MethodProps.cpp b/CPP/7zip/Common/MethodProps.cpp old mode 100755 new mode 100644 index e15a3cc8..f1c34ada --- a/CPP/7zip/Common/MethodProps.cpp +++ b/CPP/7zip/Common/MethodProps.cpp @@ -10,12 +10,12 @@ using namespace NWindows; bool StringToBool(const UString &s, bool &res) { - if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0 || s.Compare(L"+") == 0) + if (s.IsEmpty() || s == L"+" || StringsAreEqualNoCase_Ascii(s, "ON")) { res = true; return true; } - if (s.CompareNoCase(L"OFF") == 0 || s.Compare(L"-") == 0) + if (s == L"-" || StringsAreEqualNoCase_Ascii(s, "OFF")) { res = false; return true; @@ -34,18 +34,12 @@ HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest) return E_INVALIDARG; } -int ParseStringToUInt32(const UString &srcString, UInt32 &number) +unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number) { const wchar_t *start = srcString; const wchar_t *end; - UInt64 number64 = ConvertStringToUInt64(start, &end); - if (number64 > (UInt32)0xFFFFFFFF) - { - number = 0; - return 0; - } - number = (UInt32)number64; - return (int)(end - start); + number = ConvertStringToUInt32(start, &end); + return (unsigned)(end - start); } HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) @@ -66,7 +60,7 @@ HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 & if (name.IsEmpty()) return S_OK; UInt32 v; - if (ParseStringToUInt32(name, v) != name.Length()) + if (ParseStringToUInt32(name, v) != name.Len()) return E_INVALIDARG; resValue = v; return S_OK; @@ -96,36 +90,33 @@ HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 default return ParsePropToUInt32(name, prop, numThreads); } -static HRESULT StringToDictSize(const UString &srcStringSpec, UInt32 &dicSize) +static HRESULT StringToDictSize(const UString &s, 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) + UInt32 number = ConvertStringToUInt32(s, &end); + unsigned numDigits = (unsigned)(end - s); + if (numDigits == 0 || s.Len() > numDigits + 1) return E_INVALIDARG; const unsigned kLogDictSizeLimit = 32; - if (srcString.Length() == numDigits) + if (s.Len() == numDigits) { if (number >= kLogDictSizeLimit) return E_INVALIDARG; - dicSize = (UInt32)1 << (int)number; + dicSize = (UInt32)1 << (unsigned)number; return S_OK; } unsigned numBits; - switch (srcString[numDigits]) + switch (MyCharLower_Ascii(s[numDigits])) { - case 'B': numBits = 0; break; - case 'K': numBits = 10; break; - case 'M': numBits = 20; break; - case 'G': numBits = 30; break; + case 'b': dicSize = number; return S_OK; + case 'k': numBits = 10; break; + case 'm': numBits = 20; break; + case 'g': numBits = 30; break; default: return E_INVALIDARG; } - if (number >= ((UInt64)1 << (kLogDictSizeLimit - numBits))) + if (number >= ((UInt32)1 << (kLogDictSizeLimit - numBits))) return E_INVALIDARG; - dicSize = (UInt32)number << numBits; + dicSize = number << numBits; return S_OK; } @@ -191,7 +182,7 @@ void CCoderProps::AddProp(const CProp &prop) HRESULT CProps::SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const { CCoderProps coderProps(Props.Size() + (dataSizeReduce ? 1 : 0)); - for (int i = 0; i < Props.Size(); i++) + FOR_VECTOR (i, Props) coderProps.AddProp(Props[i]); if (dataSizeReduce) { @@ -226,34 +217,34 @@ int CMethodProps::GetLevel() const struct CNameToPropID { VARTYPE VarType; - const wchar_t *Name; + const char *Name; }; static const CNameToPropID g_NameToPropID[] = { - { VT_UI4, L"" }, - { VT_UI4, L"d" }, - { VT_UI4, L"mem" }, - { VT_UI4, L"o" }, - { VT_UI4, L"c" }, - { VT_UI4, L"pb" }, - { VT_UI4, L"lc" }, - { VT_UI4, L"lp" }, - { VT_UI4, L"fb" }, - { VT_BSTR, L"mf" }, - { VT_UI4, L"mc" }, - { VT_UI4, L"pass" }, - { VT_UI4, L"a" }, - { VT_UI4, L"mt" }, - { VT_BOOL, L"eos" }, - { VT_UI4, L"x" }, - { VT_UI4, L"reduceSize" } + { VT_UI4, "" }, + { VT_UI4, "d" }, + { VT_UI4, "mem" }, + { VT_UI4, "o" }, + { VT_UI4, "c" }, + { VT_UI4, "pb" }, + { VT_UI4, "lc" }, + { VT_UI4, "lp" }, + { VT_UI4, "fb" }, + { VT_BSTR, "mf" }, + { VT_UI4, "mc" }, + { VT_UI4, "pass" }, + { VT_UI4, "a" }, + { VT_UI4, "mt" }, + { VT_BOOL, "eos" }, + { VT_UI4, "x" }, + { VT_UI4, "reduceSize" } }; static int FindPropIdExact(const UString &name) { - for (unsigned i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++) - if (name.CompareNoCase(g_NameToPropID[i].Name) == 0) + for (unsigned i = 0; i < ARRAY_SIZE(g_NameToPropID); i++) + if (StringsAreEqualNoCase_Ascii(name, g_NameToPropID[i].Name)) return i; return -1; } @@ -285,7 +276,7 @@ static void SplitParams(const UString &srcString, UStringVector &subStrings) { subStrings.Clear(); UString s; - int len = srcString.Length(); + int len = srcString.Len(); if (len == 0) return; for (int i = 0; i < len; i++) @@ -307,19 +298,19 @@ 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); + name.SetFrom(param, eqPos); + value = param.Ptr(eqPos + 1); return; } - int i; - for (i = 0; i < param.Length(); i++) + unsigned i; + for (i = 0; i < param.Len(); i++) { wchar_t c = param[i]; if (c >= L'0' && c <= L'9') break; } - name = param.Left(i); - value = param.Mid(i); + name.SetFrom(param, i); + value = param.Ptr(i); } static bool IsLogSizeProp(PROPID propid) @@ -365,7 +356,7 @@ HRESULT CMethodProps::SetParam(const UString &name, const UString &value) else if (!value.IsEmpty()) { UInt32 number; - if (ParseStringToUInt32(value, number) == value.Length()) + if (ParseStringToUInt32(value, number) == value.Len()) propValue = number; else propValue = value; @@ -381,7 +372,7 @@ HRESULT CMethodProps::ParseParamsFromString(const UString &srcString) { UStringVector params; SplitParams(srcString, params); - for (int i = 0; i < params.Size(); i++) + FOR_VECTOR (i, params) { const UString ¶m = params[i]; UString name, value; @@ -393,7 +384,7 @@ HRESULT CMethodProps::ParseParamsFromString(const UString &srcString) HRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value) { - if (realName.Length() == 0) + if (realName.Len() == 0) { // [empty]=method return E_INVALIDARG; @@ -429,20 +420,22 @@ HRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const return S_OK; } +HRESULT COneMethodInfo::ParseMethodFromString(const UString &s) +{ + int splitPos = s.Find(':'); + MethodName = s; + if (splitPos < 0) + return S_OK; + MethodName.DeleteFrom(splitPos); + return ParseParamsFromString(s.Ptr(splitPos + 1)); +} + HRESULT COneMethodInfo::ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value) { - if (!realName.IsEmpty() && realName.CompareNoCase(L"m") != 0) + if (!realName.IsEmpty() && !StringsAreEqualNoCase_Ascii(realName, "m")) return ParseParamsFromPROPVARIANT(realName, value); // -m{N}=method if (value.vt != VT_BSTR) return E_INVALIDARG; - const UString s = value.bstrVal; - int splitPos = s.Find(':'); - if (splitPos < 0) - { - MethodName = s; - return S_OK; - } - MethodName = s.Left(splitPos); - return ParseParamsFromString(s.Mid(splitPos + 1)); + return ParseMethodFromString(value.bstrVal); } diff --git a/CPP/7zip/Common/MethodProps.h b/CPP/7zip/Common/MethodProps.h old mode 100755 new mode 100644 index 0bdddc6b..18672bde --- a/CPP/7zip/Common/MethodProps.h +++ b/CPP/7zip/Common/MethodProps.h @@ -11,7 +11,7 @@ bool StringToBool(const UString &s, bool &res); HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest); -int ParseStringToUInt32(const UString &srcString, UInt32 &number); +unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number); HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads); @@ -32,7 +32,7 @@ struct CProps bool AreThereNonOptionalProps() const { - for (int i = 0; i < Props.Size(); i++) + FOR_VECTOR (i, Props) if (!Props[i].IsOptional) return true; return false; @@ -179,6 +179,7 @@ public: } bool IsEmpty() const { return MethodName.IsEmpty() && Props.IsEmpty(); } HRESULT ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value); + HRESULT ParseMethodFromString(const UString &s); }; #endif diff --git a/CPP/7zip/Common/OffsetStream.cpp b/CPP/7zip/Common/OffsetStream.cpp old mode 100755 new mode 100644 index c5e4e6da..368d39b6 --- a/CPP/7zip/Common/OffsetStream.cpp +++ b/CPP/7zip/Common/OffsetStream.cpp @@ -2,7 +2,8 @@ #include "StdAfx.h" -#include "Common/Defs.h" +#include "../../Common/Defs.h" + #include "OffsetStream.h" HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset) @@ -17,14 +18,17 @@ STDMETHODIMP COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *proc return _stream->Write(data, size, processedSize); } -STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin, - UInt64 *newPosition) +STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { UInt64 absoluteNewPosition; if (seekOrigin == STREAM_SEEK_SET) + { + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; offset += _offset; + } HRESULT result = _stream->Seek(offset, seekOrigin, &absoluteNewPosition); - if (newPosition != NULL) + if (newPosition) *newPosition = absoluteNewPosition - _offset; return result; } diff --git a/CPP/7zip/Common/OffsetStream.h b/CPP/7zip/Common/OffsetStream.h old mode 100755 new mode 100644 index de9d06dd..9074a24e --- a/CPP/7zip/Common/OffsetStream.h +++ b/CPP/7zip/Common/OffsetStream.h @@ -1,9 +1,10 @@ // OffsetStream.h -#ifndef __OFFSETSTREAM_H -#define __OFFSETSTREAM_H +#ifndef __OFFSET_STREAM_H +#define __OFFSET_STREAM_H + +#include "../../Common/MyCom.h" -#include "Common/MyCom.h" #include "../IStream.h" class COffsetOutStream: diff --git a/CPP/7zip/Common/OutBuffer.cpp b/CPP/7zip/Common/OutBuffer.cpp old mode 100755 new mode 100644 index 2e5debd8..df254f27 --- a/CPP/7zip/Common/OutBuffer.cpp +++ b/CPP/7zip/Common/OutBuffer.cpp @@ -6,34 +6,29 @@ #include "OutBuffer.h" -bool COutBuffer::Create(UInt32 bufferSize) +bool COutBuffer::Create(UInt32 bufSize) { const UInt32 kMinBlockSize = 1; - if (bufferSize < kMinBlockSize) - bufferSize = kMinBlockSize; - if (_buffer != 0 && _bufferSize == bufferSize) + if (bufSize < kMinBlockSize) + bufSize = kMinBlockSize; + if (_buf != 0 && _bufSize == bufSize) return true; Free(); - _bufferSize = bufferSize; - _buffer = (Byte *)::MidAlloc(bufferSize); - return (_buffer != 0); + _bufSize = bufSize; + _buf = (Byte *)::MidAlloc(bufSize); + return (_buf != 0); } void COutBuffer::Free() { - ::MidFree(_buffer); - _buffer = 0; -} - -void COutBuffer::SetStream(ISequentialOutStream *stream) -{ - _stream = stream; + ::MidFree(_buf); + _buf = 0; } void COutBuffer::Init() { _streamPos = 0; - _limitPos = _bufferSize; + _limitPos = _bufSize; _pos = 0; _processedSize = 0; _overDict = false; @@ -46,23 +41,23 @@ UInt64 COutBuffer::GetProcessedSize() const { UInt64 res = _processedSize + _pos - _streamPos; if (_streamPos > _pos) - res += _bufferSize; + res += _bufSize; return res; } HRESULT COutBuffer::FlushPart() { - // _streamPos < _bufferSize - UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos); + // _streamPos < _bufSize + UInt32 size = (_streamPos >= _pos) ? (_bufSize - _streamPos) : (_pos - _streamPos); HRESULT result = S_OK; #ifdef _NO_EXCEPTIONS result = ErrorCode; #endif - if (_buffer2 != 0) + if (_buf2 != 0) { - memmove(_buffer2, _buffer + _streamPos, size); - _buffer2 += size; + memcpy(_buf2, _buf + _streamPos, size); + _buf2 += size; } if (_stream != 0 @@ -72,18 +67,18 @@ HRESULT COutBuffer::FlushPart() ) { UInt32 processedSize = 0; - result = _stream->Write(_buffer + _streamPos, size, &processedSize); + result = _stream->Write(_buf + _streamPos, size, &processedSize); size = processedSize; } _streamPos += size; - if (_streamPos == _bufferSize) + if (_streamPos == _bufSize) _streamPos = 0; - if (_pos == _bufferSize) + if (_pos == _bufSize) { _overDict = true; _pos = 0; } - _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize; + _limitPos = (_streamPos > _pos) ? _streamPos : _bufSize; _processedSize += size; return result; } @@ -95,7 +90,7 @@ HRESULT COutBuffer::Flush() return ErrorCode; #endif - while(_streamPos != _pos) + while (_streamPos != _pos) { HRESULT result = FlushPart(); if (result != S_OK) diff --git a/CPP/7zip/Common/OutBuffer.h b/CPP/7zip/Common/OutBuffer.h old mode 100755 new mode 100644 index 62e77caa..3bdfb87c --- a/CPP/7zip/Common/OutBuffer.h +++ b/CPP/7zip/Common/OutBuffer.h @@ -1,7 +1,7 @@ // OutBuffer.h -#ifndef __OUTBUFFER_H -#define __OUTBUFFER_H +#ifndef __OUT_BUFFER_H +#define __OUT_BUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" @@ -17,39 +17,38 @@ struct COutBufferException: public CSystemException class COutBuffer { protected: - Byte *_buffer; + Byte *_buf; UInt32 _pos; UInt32 _limitPos; UInt32 _streamPos; - UInt32 _bufferSize; - CMyComPtr _stream; + UInt32 _bufSize; + ISequentialOutStream *_stream; UInt64 _processedSize; - Byte *_buffer2; + Byte *_buf2; bool _overDict; - HRESULT FlushPart(); + HRESULT FlushPart() throw(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif - COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {} + COutBuffer(): _buf(0), _pos(0), _stream(0), _buf2(0) {} ~COutBuffer() { Free(); } - bool Create(UInt32 bufferSize); - void Free(); + bool Create(UInt32 bufSize) throw(); + void Free() throw(); - void SetMemStream(Byte *buffer) { _buffer2 = buffer; } - void SetStream(ISequentialOutStream *stream); - void Init(); - HRESULT Flush(); + void SetMemStream(Byte *buf) { _buf2 = buf; } + void SetStream(ISequentialOutStream *stream) { _stream = stream; } + void Init() throw(); + HRESULT Flush() throw(); void FlushWithCheck(); - void ReleaseStream() { _stream.Release(); } void WriteByte(Byte b) { - _buffer[_pos++] = b; - if(_pos == _limitPos) + _buf[_pos++] = b; + if (_pos == _limitPos) FlushWithCheck(); } void WriteBytes(const void *data, size_t size) @@ -58,7 +57,7 @@ public: WriteByte(((const Byte *)data)[i]); } - UInt64 GetProcessedSize() const; + UInt64 GetProcessedSize() const throw(); }; #endif diff --git a/CPP/7zip/Common/OutMemStream.cpp b/CPP/7zip/Common/OutMemStream.cpp old mode 100755 new mode 100644 index 2e92886b..768c2d45 --- a/CPP/7zip/Common/OutMemStream.cpp +++ b/CPP/7zip/Common/OutMemStream.cpp @@ -40,15 +40,15 @@ STDMETHODIMP COutMemStream::Write(const void *data, UInt32 size, UInt32 *process return OutSeqStream->Write(data, size, processedSize); if (processedSize != 0) *processedSize = 0; - while(size != 0) + while (size != 0) { - if ((int)_curBlockIndex < Blocks.Blocks.Size()) + if (_curBlockIndex < Blocks.Blocks.Size()) { - Byte *p = (Byte *)Blocks.Blocks[(int)_curBlockIndex] + _curBlockPos; + Byte *p = (Byte *)Blocks.Blocks[_curBlockIndex] + _curBlockPos; size_t curSize = _memManager->GetBlockSize() - _curBlockPos; if (size < curSize) curSize = size; - memmove(p, data, curSize); + memcpy(p, data, curSize); if (processedSize != 0) *processedSize += (UInt32)curSize; data = (const void *)((const Byte *)data + curSize); @@ -124,7 +124,7 @@ STDMETHODIMP COutMemStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPos } else return E_NOTIMPL; - if (newPosition != 0) + if (newPosition) *newPosition = GetPos(); return S_OK; } diff --git a/CPP/7zip/Common/OutMemStream.h b/CPP/7zip/Common/OutMemStream.h old mode 100755 new mode 100644 index b47f339e..0a892c52 --- a/CPP/7zip/Common/OutMemStream.h +++ b/CPP/7zip/Common/OutMemStream.h @@ -1,9 +1,10 @@ // OutMemStream.h -#ifndef __OUTMEMSTREAM_H -#define __OUTMEMSTREAM_H +#ifndef __OUT_MEM_STREAM_H +#define __OUT_MEM_STREAM_H + +#include "../../Common/MyCom.h" -#include "Common/MyCom.h" #include "MemBlocks.h" class COutMemStream: @@ -11,7 +12,7 @@ class COutMemStream: public CMyUnknownImp { CMemBlockManagerMt *_memManager; - size_t _curBlockIndex; + unsigned _curBlockIndex; size_t _curBlockPos; bool _realStreamMode; diff --git a/CPP/7zip/Common/ProgressMt.cpp b/CPP/7zip/Common/ProgressMt.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Common/ProgressMt.h b/CPP/7zip/Common/ProgressMt.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Common/ProgressUtils.cpp b/CPP/7zip/Common/ProgressUtils.cpp old mode 100755 new mode 100644 index f24ff6b6..bac45c1c --- a/CPP/7zip/Common/ProgressUtils.cpp +++ b/CPP/7zip/Common/ProgressUtils.cpp @@ -1,4 +1,4 @@ -// ProgressUtils.h +// ProgressUtils.cpp #include "StdAfx.h" diff --git a/CPP/7zip/Common/ProgressUtils.h b/CPP/7zip/Common/ProgressUtils.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Common/PropId.cpp b/CPP/7zip/Common/PropId.cpp new file mode 100644 index 00000000..10daef71 --- /dev/null +++ b/CPP/7zip/Common/PropId.cpp @@ -0,0 +1,99 @@ +// PropId.cpp + +#include "StdAfx.h" + +#include "../PropID.h" + +// VARTYPE +Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] = +{ + VT_EMPTY, + VT_UI4, + VT_UI4, + VT_BSTR, + VT_BSTR, + VT_BSTR, + VT_BOOL, + VT_UI8, + VT_UI8, + VT_UI4, + VT_FILETIME, + VT_FILETIME, + VT_FILETIME, + VT_BOOL, + VT_BOOL, + VT_BOOL, + VT_BOOL, + VT_BOOL, + VT_UI4, + VT_UI4, + VT_BSTR, + VT_BOOL, + VT_BSTR, + VT_BSTR, + VT_BSTR, + VT_BSTR, + VT_BSTR, + VT_UI8, + VT_BSTR, + VT_UI8, + VT_BSTR, + VT_UI8, + VT_UI8, + VT_BSTR, // or VT_UI8 kpidUnpackVer + VT_UI4, // or VT_UI8 kpidVolume + VT_BOOL, + VT_UI8, + VT_UI8, + VT_UI8, + VT_UI8, + VT_UI4, + VT_BOOL, + VT_BOOL, + VT_BSTR, + VT_UI8, + VT_UI8, + VT_UI4, // kpidChecksum + VT_BSTR, + VT_UI8, + VT_BSTR, // or VT_UI8 kpidId + VT_BSTR, + VT_BSTR, + VT_UI4, + VT_UI4, + VT_BSTR, + VT_BSTR, + VT_UI8, + VT_UI8, + VT_UI4, + VT_BSTR, + VT_BSTR, + VT_BSTR, + VT_BSTR, // kpidNtSecure + VT_BOOL, + VT_BOOL, + VT_BOOL, + VT_BOOL, + VT_BSTR, // SHA-1 + VT_BSTR, // SHA-256 + VT_BSTR, + VT_UI8, + VT_UI4, + VT_UI4, + VT_BSTR, + VT_UI8, + VT_UI8, + VT_UI8, + VT_UI8, + VT_UI8, + VT_UI8, + VT_UI8, + VT_BSTR, + VT_BSTR, + VT_BSTR, + VT_BOOL, + VT_BOOL, + VT_BOOL, + VT_UI8, + VT_UI8 +}; diff --git a/CPP/7zip/Common/RegisterArc.h b/CPP/7zip/Common/RegisterArc.h old mode 100755 new mode 100644 index bc2a034f..edc3abdd --- a/CPP/7zip/Common/RegisterArc.h +++ b/CPP/7zip/Common/RegisterArc.h @@ -5,23 +5,28 @@ #include "../Archive/IArchive.h" -typedef IInArchive * (*CreateInArchiveP)(); -typedef IOutArchive * (*CreateOutArchiveP)(); - struct CArcInfo { - const wchar_t *Name; - const wchar_t *Ext; - const wchar_t *AddExt; + const char *Name; + const char *Ext; + const char *AddExt; + Byte ClassId; - Byte Signature[16]; - int SignatureSize; - bool KeepName; - CreateInArchiveP CreateInArchive; - CreateOutArchiveP CreateOutArchive; + + Byte SignatureSize; + Byte Signature[20]; + UInt16 SignatureOffset; + + UInt16 Flags; + + Func_CreateInArchive CreateInArchive; + Func_CreateOutArchive CreateOutArchive; + Func_IsArc IsArc; + + bool IsMultiSignature() const { return (Flags & NArcInfoFlags::kMultiSignature) != 0; } }; -void RegisterArc(const CArcInfo *arcInfo); +void RegisterArc(const CArcInfo *arcInfo) throw(); #define REGISTER_ARC_NAME(x) CRegister ## x @@ -29,4 +34,22 @@ void RegisterArc(const CArcInfo *arcInfo); REGISTER_ARC_NAME(x)() { RegisterArc(&g_ArcInfo); }}; \ static REGISTER_ARC_NAME(x) g_RegisterArc; +#define REGISTER_ARC_DEC_SIG(x) struct REGISTER_ARC_NAME(x) { \ + REGISTER_ARC_NAME(x)() { g_ArcInfo.Signature[0]--; RegisterArc(&g_ArcInfo); }}; \ + static REGISTER_ARC_NAME(x) g_RegisterArc; + + +#define IMP_CreateArcIn_2(c) \ + static IInArchive *CreateArc() { return new c; } + +#define IMP_CreateArcIn IMP_CreateArcIn_2(CHandler) + +#ifdef EXTRACT_ONLY + #define IMP_CreateArcOut + #define REF_CreateArc_Pair CreateArc, NULL +#else + #define IMP_CreateArcOut static IOutArchive *CreateArcOut() { return new CHandler; } + #define REF_CreateArc_Pair CreateArc, CreateArcOut +#endif + #endif diff --git a/CPP/7zip/Common/RegisterCodec.h b/CPP/7zip/Common/RegisterCodec.h old mode 100755 new mode 100644 index 786b4a4c..4222a305 --- a/CPP/7zip/Common/RegisterCodec.h +++ b/CPP/7zip/Common/RegisterCodec.h @@ -1,9 +1,10 @@ // RegisterCodec.h -#ifndef __REGISTERCODEC_H -#define __REGISTERCODEC_H +#ifndef __REGISTER_CODEC_H +#define __REGISTER_CODEC_H #include "../Common/MethodId.h" +#include "../ICoder.h" typedef void * (*CreateCodecP)(); struct CCodecInfo @@ -16,7 +17,7 @@ struct CCodecInfo bool IsFilter; }; -void RegisterCodec(const CCodecInfo *codecInfo); +void RegisterCodec(const CCodecInfo *codecInfo) throw(); #define REGISTER_CODEC_NAME(x) CRegisterCodec ## x @@ -26,8 +27,25 @@ void RegisterCodec(const CCodecInfo *codecInfo); #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++) \ + REGISTER_CODECS_NAME(x)() { for (unsigned i = 0; i < ARRAY_SIZE(g_CodecsInfo); i++) \ RegisterCodec(&g_CodecsInfo[i]); }}; \ static REGISTER_CODECS_NAME(x) g_RegisterCodecs; + +struct CHasherInfo +{ + IHasher * (*CreateHasher)(); + CMethodId Id; + const wchar_t *Name; + UInt32 DigestSize; +}; + +void RegisterHasher(const CHasherInfo *hasher) throw(); + +#define REGISTER_HASHER_NAME(x) CRegisterHasher ## x + +#define REGISTER_HASHER(x) struct REGISTER_HASHER_NAME(x) { \ + REGISTER_HASHER_NAME(x)() { RegisterHasher(&g_HasherInfo); }}; \ + static REGISTER_HASHER_NAME(x) g_RegisterHasher; + #endif diff --git a/CPP/7zip/Common/StdAfx.h b/CPP/7zip/Common/StdAfx.h old mode 100755 new mode 100644 index ef555ec1..1cbd7fea --- a/CPP/7zip/Common/StdAfx.h +++ b/CPP/7zip/Common/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../Common/MyWindows.h" -#include "../../Common/NewHandler.h" +#include "../../Common/Common.h" #endif diff --git a/CPP/7zip/Common/StreamBinder.cpp b/CPP/7zip/Common/StreamBinder.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Common/StreamBinder.h b/CPP/7zip/Common/StreamBinder.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Common/StreamObjects.cpp b/CPP/7zip/Common/StreamObjects.cpp old mode 100755 new mode 100644 index 1b6b0af0..480cb2db --- a/CPP/7zip/Common/StreamObjects.cpp +++ b/CPP/7zip/Common/StreamObjects.cpp @@ -14,8 +14,8 @@ STDMETHODIMP CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize) *processedSize = 0; if (size == 0) return S_OK; - if (_pos > _size) - return E_FAIL; + if (_pos >= _size) + return S_OK; size_t rem = _size - (size_t)_pos; if (rem > size) rem = (size_t)size; @@ -28,18 +28,43 @@ STDMETHODIMP CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize) STDMETHODIMP CBufInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - switch(seekOrigin) + switch (seekOrigin) { - case STREAM_SEEK_SET: _pos = offset; break; - case STREAM_SEEK_CUR: _pos += offset; break; - case STREAM_SEEK_END: _pos = _size + offset; break; + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _pos; break; + case STREAM_SEEK_END: offset += _size; break; default: return STG_E_INVALIDFUNCTION; } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _pos = offset; if (newPosition) - *newPosition = _pos; + *newPosition = offset; return S_OK; } +/* +void Create_BufInStream_WithReference(const void *data, size_t size, ISequentialInStream **stream) +{ + CBufInStream *inStreamSpec = new CBufInStream; + CMyComPtr streamTemp = inStreamSpec; + inStreamSpec->Init((const Byte *)data, size); + *stream = streamTemp.Detach(); +} +*/ + +void Create_BufInStream_WithNewBuf(const void *data, size_t size, ISequentialInStream **stream) +{ + CReferenceBuf *referenceBuf = new CReferenceBuf; + CMyComPtr ref = referenceBuf; + referenceBuf->Buf.CopyFrom((const Byte *)data, size); + + CBufInStream *inStreamSpec = new CBufInStream; + CMyComPtr streamTemp = inStreamSpec; + inStreamSpec->Init(referenceBuf); + *stream = streamTemp.Detach(); +} + void CByteDynBuffer::Free() { free(_buf); @@ -79,8 +104,7 @@ Byte *CDynBufSeqOutStream::GetBufPtrForWriting(size_t addSize) void CDynBufSeqOutStream::CopyToBuffer(CByteBuffer &dest) const { - dest.SetCapacity(_size); - memcpy(dest, (const Byte *)_buffer, _size); + dest.CopyFrom((const Byte *)_buffer, _size); } STDMETHODIMP CDynBufSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) @@ -172,8 +196,8 @@ STDMETHODIMP CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSiz *processedSize = 0; if (size == 0) return S_OK; - if (_pos > _size) - return E_FAIL; + if (_pos >= _size) + return S_OK; { UInt64 rem = _size - _pos; @@ -210,14 +234,17 @@ STDMETHODIMP CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSiz STDMETHODIMP CCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - switch(seekOrigin) + 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; + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _pos; break; + case STREAM_SEEK_END: offset += _size; break; default: return STG_E_INVALIDFUNCTION; } - if (newPosition != 0) - *newPosition = _pos; + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _pos = offset; + if (newPosition) + *newPosition = offset; return S_OK; } diff --git a/CPP/7zip/Common/StreamObjects.h b/CPP/7zip/Common/StreamObjects.h old mode 100755 new mode 100644 index 8cd95c70..d0c86b56 --- a/CPP/7zip/Common/StreamObjects.h +++ b/CPP/7zip/Common/StreamObjects.h @@ -3,8 +3,10 @@ #ifndef __STREAM_OBJECTS_H #define __STREAM_OBJECTS_H -#include "../../Common/Buffer.h" +#include "../../Common/MyBuffer.h" #include "../../Common/MyCom.h" +#include "../../Common/MyVector.h" + #include "../IStream.h" struct CReferenceBuf: @@ -31,13 +33,16 @@ public: _pos = 0; _ref = ref; } - void Init(CReferenceBuf *ref) { Init(ref->Buf, ref->Buf.GetCapacity(), ref); } + void Init(CReferenceBuf *ref) { Init(ref->Buf, ref->Buf.Size(), ref); } - MY_UNKNOWN_IMP1(IInStream) + MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; +// void Create_BufInStream_WithReference(const void *data, size_t size, ISequentialInStream **stream); +void Create_BufInStream_WithNewBuf(const void *data, size_t size, ISequentialInStream **stream); + class CByteDynBuffer { size_t _capacity; @@ -46,11 +51,11 @@ 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; } + void Free() throw(); + size_t GetCapacity() const { return _capacity; } operator Byte*() const { return _buf; }; operator const Byte*() const { return _buf; }; - bool EnsureCapacity(size_t capacity); + bool EnsureCapacity(size_t capacity) throw(); }; class CDynBufSeqOutStream: @@ -68,7 +73,7 @@ public: Byte *GetBufPtrForWriting(size_t addSize); void UpdateSize(size_t addSize) { _size += addSize; } - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP1(ISequentialOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; @@ -88,7 +93,7 @@ public: } size_t GetPos() const { return _pos; } - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP1(ISequentialOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; @@ -103,7 +108,7 @@ public: void Init() { _size = 0; } UInt64 GetSize() const { return _size; } - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP1(ISequentialOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; @@ -123,9 +128,9 @@ protected: 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); + void Free() throw(); + bool Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw(); + void Init(UInt64 size) throw(); MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); diff --git a/CPP/7zip/Common/StreamUtils.cpp b/CPP/7zip/Common/StreamUtils.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Common/StreamUtils.h b/CPP/7zip/Common/StreamUtils.h old mode 100755 new mode 100644 index f1cfd184..ae914c00 --- a/CPP/7zip/Common/StreamUtils.h +++ b/CPP/7zip/Common/StreamUtils.h @@ -1,13 +1,13 @@ // StreamUtils.h -#ifndef __STREAMUTILS_H -#define __STREAMUTILS_H +#ifndef __STREAM_UTILS_H +#define __STREAM_UTILS_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); +HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *size) throw(); +HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) throw(); +HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) throw(); +HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size) throw(); #endif diff --git a/CPP/7zip/Common/UniqBlocks.cpp b/CPP/7zip/Common/UniqBlocks.cpp new file mode 100644 index 00000000..7fcc88f5 --- /dev/null +++ b/CPP/7zip/Common/UniqBlocks.cpp @@ -0,0 +1,56 @@ +// UniqBlocks.cpp + +#include "StdAfx.h" + +#include "UniqBlocks.h" + +int CUniqBlocks::AddUniq(const Byte *data, size_t size) +{ + unsigned left = 0, right = Sorted.Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + int index = Sorted[mid]; + const CByteBuffer &buf = Bufs[index]; + size_t sizeMid = buf.Size(); + if (size < sizeMid) + right = mid; + else if (size > sizeMid) + left = mid + 1; + else + { + int cmp = memcmp(data, buf, size); + if (cmp == 0) + return index; + if (cmp < 0) + right = mid; + else + left = mid + 1; + } + } + int index = Bufs.Size(); + Sorted.Insert(left, index); + CByteBuffer &buf = Bufs.AddNew(); + buf.CopyFrom(data, size); + return index; +} + +UInt64 CUniqBlocks::GetTotalSizeInBytes() const +{ + UInt64 size = 0; + FOR_VECTOR (i, Bufs) + size += Bufs[i].Size(); + return size; +} + +void CUniqBlocks::GetReverseMap() +{ + unsigned num = Sorted.Size(); + BufIndexToSortedIndex.ClearAndSetSize(num); + int *p = &BufIndexToSortedIndex[0]; + unsigned i; + for (i = 0; i < num; i++) + p[i] = 0; + for (i = 0; i < num; i++) + p[Sorted[i]] = i; +} diff --git a/CPP/7zip/Common/UniqBlocks.h b/CPP/7zip/Common/UniqBlocks.h new file mode 100644 index 00000000..9c08b09f --- /dev/null +++ b/CPP/7zip/Common/UniqBlocks.h @@ -0,0 +1,30 @@ +// UniqBlocks.h + +#ifndef __UNIQ_BLOCKS_H +#define __UNIQ_BLOCKS_H + +#include "../../Common/MyTypes.h" +#include "../../Common/MyBuffer.h" +#include "../../Common/MyVector.h" + +struct CUniqBlocks +{ + CObjectVector Bufs; + CIntVector Sorted; + CIntVector BufIndexToSortedIndex; + + int AddUniq(const Byte *data, size_t size); + UInt64 GetTotalSizeInBytes() const; + void GetReverseMap(); + + bool IsOnlyEmpty() const + { + if (Bufs.Size() == 0) + return true; + if (Bufs.Size() > 1) + return false; + return Bufs[0].Size() == 0; + } +}; + +#endif diff --git a/CPP/7zip/Common/VirtThread.cpp b/CPP/7zip/Common/VirtThread.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Common/VirtThread.h b/CPP/7zip/Common/VirtThread.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/ArjDecoder1.cpp b/CPP/7zip/Compress/ArjDecoder1.cpp old mode 100755 new mode 100644 index 2c354e1e..2eaa591c --- a/CPP/7zip/Compress/ArjDecoder1.cpp +++ b/CPP/7zip/Compress/ArjDecoder1.cpp @@ -260,7 +260,7 @@ HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *ou UInt32 blockSize = 0; - while(pos < *outSize) + while (pos < *outSize) { if (blockSize == 0) { diff --git a/CPP/7zip/Compress/ArjDecoder1.h b/CPP/7zip/Compress/ArjDecoder1.h old mode 100755 new mode 100644 index 17939daf..dd12e445 --- a/CPP/7zip/Compress/ArjDecoder1.h +++ b/CPP/7zip/Compress/ArjDecoder1.h @@ -55,12 +55,6 @@ class CCoder : UInt32 c_table[CTABLESIZE]; UInt32 pt_table[PTABLESIZE]; - void ReleaseStreams() - { - m_OutWindowStream.ReleaseStream(); - m_InBitStream.ReleaseStream(); - } - class CCoderReleaser { CCoder *m_Coder; @@ -71,7 +65,6 @@ class CCoder : { if (NeedFlush) m_Coder->m_OutWindowStream.Flush(); - m_Coder->ReleaseStreams(); } }; friend class CCoderReleaser; diff --git a/CPP/7zip/Compress/ArjDecoder2.cpp b/CPP/7zip/Compress/ArjDecoder2.cpp old mode 100755 new mode 100644 index 365993bc..4903605c --- a/CPP/7zip/Compress/ArjDecoder2.cpp +++ b/CPP/7zip/Compress/ArjDecoder2.cpp @@ -27,9 +27,10 @@ HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *ou m_OutWindowStream.Init(false); m_InBitStream.SetStream(inStream); m_InBitStream.Init(); + CCoderReleaser coderReleaser(this); - while(pos < *outSize) + while (pos < *outSize) { const UInt32 kStartWidth = 0; const UInt32 kStopWidth = 7; diff --git a/CPP/7zip/Compress/ArjDecoder2.h b/CPP/7zip/Compress/ArjDecoder2.h old mode 100755 new mode 100644 index cf00975d..cf544d9e --- a/CPP/7zip/Compress/ArjDecoder2.h +++ b/CPP/7zip/Compress/ArjDecoder2.h @@ -23,12 +23,6 @@ class CCoder : CLzOutWindow m_OutWindowStream; NBitm::CDecoder m_InBitStream; - void ReleaseStreams() - { - m_OutWindowStream.ReleaseStream(); - m_InBitStream.ReleaseStream(); - } - class CCoderReleaser { CCoder *m_Coder; @@ -39,7 +33,6 @@ class CCoder : { if (NeedFlush) m_Coder->m_OutWindowStream.Flush(); - m_Coder->ReleaseStreams(); } }; friend class CCoderReleaser; diff --git a/CPP/7zip/Compress/BZip2Const.h b/CPP/7zip/Compress/BZip2Const.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/BZip2Crc.cpp b/CPP/7zip/Compress/BZip2Crc.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/BZip2Crc.h b/CPP/7zip/Compress/BZip2Crc.h old mode 100755 new mode 100644 index 876945b5..1b5755b5 --- a/CPP/7zip/Compress/BZip2Crc.h +++ b/CPP/7zip/Compress/BZip2Crc.h @@ -3,7 +3,7 @@ #ifndef __BZIP2_CRC_H #define __BZIP2_CRC_H -#include "Common/Types.h" +#include "../../Common/MyTypes.h" class CBZip2Crc { diff --git a/CPP/7zip/Compress/BZip2Decoder.cpp b/CPP/7zip/Compress/BZip2Decoder.cpp old mode 100755 new mode 100644 index cb1f981a..3798421e --- a/CPP/7zip/Compress/BZip2Decoder.cpp +++ b/CPP/7zip/Compress/BZip2Decoder.cpp @@ -85,41 +85,21 @@ void CState::Free() 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; } +Byte CDecoder::ReadByte() { return (Byte)Base.ReadBits(8); } -UInt32 CDecoder::ReadCrc() -{ - UInt32 crc = 0; - for (int i = 0; i < 4; i++) - { - crc <<= 8; - crc |= ReadByte(); - } - return crc; -} +UInt32 CBase::ReadBits(unsigned numBits) { return BitDecoder.ReadBits(numBits); } +unsigned CBase::ReadBit() { return (unsigned)BitDecoder.ReadBits(1); } -static UInt32 NO_INLINE ReadBits(NBitm::CDecoder *m_InStream, unsigned num) +HRESULT CBase::ReadBlock(UInt32 *charCounters, UInt32 blockSizeMax, CBlockProps *props) { - return m_InStream->ReadBits(num); -} - -static UInt32 NO_INLINE ReadBit(NBitm::CDecoder *m_InStream) -{ - return m_InStream->ReadBits(1); -} + NumBlocks++; -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); + if (props->randMode) + props->randMode = ReadBit() ? true : false; + props->origPtr = ReadBits(kNumOrigBits); // in original code it compares OrigPtr to (UInt32)(10 + blockSizeMax)) : why ? - if (*origPtrRes >= blockSizeMax) + if (props->origPtr >= blockSizeMax) return S_FALSE; CMtf8Decoder mtf; @@ -130,11 +110,11 @@ static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder *m_InStream, Byte inUse16[16]; int i; for (i = 0; i < 16; i++) - inUse16[i] = (Byte)ReadBit(m_InStream); + inUse16[i] = (Byte)ReadBit(); for (i = 0; i < 256; i++) if (inUse16[i >> 4]) { - if (ReadBit(m_InStream)) + if (ReadBit()) mtf.Add(numInUse++, (Byte)i); } if (numInUse == 0) @@ -143,11 +123,11 @@ static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder *m_InStream, } int alphaSize = numInUse + 2; - int numTables = ReadBits(m_InStream, kNumTablesBits); + int numTables = ReadBits(kNumTablesBits); if (numTables < kNumTablesMin || numTables > kNumTablesMax) return S_FALSE; - UInt32 numSelectors = ReadBits(m_InStream, kNumSelectorsBits); + UInt32 numSelectors = ReadBits(kNumSelectorsBits); if (numSelectors < 1 || numSelectors > kNumSelectorsMax) return S_FALSE; @@ -156,12 +136,12 @@ static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder *m_InStream, int t = 0; do mtfPos[t] = (Byte)t; - while(++t < numTables); + while (++t < numTables); UInt32 i = 0; do { int j = 0; - while (ReadBit(m_InStream)) + while (ReadBit()) if (++j >= numTables) return S_FALSE; Byte tmp = mtfPos[j]; @@ -169,14 +149,14 @@ static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder *m_InStream, mtfPos[j] = mtfPos[j - 1]; m_Selectors[i] = mtfPos[0] = tmp; } - while(++i < numSelectors); + while (++i < numSelectors); } int t = 0; do { Byte lens[kMaxAlphaSize]; - int len = (int)ReadBits(m_InStream, kNumLevelsBits); + int len = (int)ReadBits(kNumLevelsBits); int i; for (i = 0; i < alphaSize; i++) { @@ -184,22 +164,22 @@ static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder *m_InStream, { if (len < 1 || len > kMaxHuffmanLen) return S_FALSE; - if (!ReadBit(m_InStream)) + if (!ReadBit()) break; - len += 1 - (int)(ReadBit(m_InStream) << 1); + len += 1 - (int)(ReadBit() << 1); } lens[i] = (Byte)len; } for (; i < kMaxAlphaSize; i++) lens[i] = 0; - if(!m_HuffmanDecoders[t].SetCodeLengths(lens)) + if (!m_HuffmanDecoders[t].SetCodeLengths(lens)) return S_FALSE; } - while(++t < numTables); + while (++t < numTables); { for (int i = 0; i < 256; i++) - CharCounters[i] = 0; + charCounters[i] = 0; } UInt32 blockSize = 0; @@ -221,7 +201,10 @@ static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder *m_InStream, } groupSize--; - UInt32 nextSym = huffmanDecoder->DecodeSymbol(m_InStream); + if (BitDecoder.ExtraBitsWereRead_Fast()) + break; + + UInt32 nextSym = huffmanDecoder->DecodeSymbol(&BitDecoder); if (nextSym < 2) { @@ -233,10 +216,10 @@ static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder *m_InStream, if (runCounter != 0) { UInt32 b = (UInt32)mtf.GetHead(); - CharCounters[b] += runCounter; + charCounters[b] += runCounter; do - CharCounters[256 + blockSize++] = b; - while(--runCounter != 0); + charCounters[256 + blockSize++] = b; + while (--runCounter != 0); runPower = 0; } if (nextSym <= (UInt32)numInUse) @@ -244,17 +227,20 @@ static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder *m_InStream, UInt32 b = (UInt32)mtf.GetAndMove((int)nextSym - 1); if (blockSize >= blockSizeMax) return S_FALSE; - CharCounters[b]++; - CharCounters[256 + blockSize++] = b; + charCounters[b]++; + charCounters[256 + blockSize++] = b; } else if (nextSym == (UInt32)numInUse + 1) break; else return S_FALSE; } + + if (BitDecoder.ExtraBitsWereRead()) + return S_FALSE; } - *blockSizeRes = blockSize; - return (*origPtrRes < blockSize) ? S_OK : S_FALSE; + props->blockSize = blockSize; + return (props->origPtr < props->blockSize) ? S_OK : S_FALSE; } static void NO_INLINE DecodeBlock1(UInt32 *charCounters, UInt32 blockSize) @@ -273,7 +259,7 @@ static void NO_INLINE DecodeBlock1(UInt32 *charCounters, UInt32 blockSize) UInt32 i = 0; do tt[charCounters[tt[i] & 0xFF]++] |= (i << 8); - while(++i < blockSize); + while (++i < blockSize); } static UInt32 NO_INLINE DecodeBlock2(const UInt32 *tt, UInt32 blockSize, UInt32 OrigPtr, COutBuffer &m_OutStream) @@ -363,7 +349,7 @@ static UInt32 NO_INLINE DecodeBlock2(const UInt32 *tt, UInt32 blockSize, UInt32 } */ } - while(--blockSize != 0); + while (--blockSize != 0); return crc.GetDigest(); } @@ -412,10 +398,17 @@ static UInt32 NO_INLINE DecodeBlock2Rand(const UInt32 *tt, UInt32 blockSize, UIn crc.UpdateByte(b); m_OutStream.WriteByte((Byte)b); } - while(--blockSize != 0); + while (--blockSize != 0); return crc.GetDigest(); } +static UInt32 NO_INLINE DecodeBlock(const CBlockProps &props, UInt32 *tt, COutBuffer &m_OutStream) +{ + if (props.randMode) + return DecodeBlock2Rand(tt, props.blockSize, props.origPtr, m_OutStream); + else + return DecodeBlock2 (tt, props.blockSize, props.origPtr, m_OutStream); +} CDecoder::CDecoder() { @@ -434,7 +427,7 @@ CDecoder::~CDecoder() Free(); } -#define RINOK_THREAD(x) { WRes __result_ = (x); if(__result_ != 0) return __result_; } +#define RINOK_THREAD(x) { WRes __result_ = (x); if (__result_ != 0) return __result_; } HRESULT CDecoder::Create() { @@ -489,37 +482,71 @@ void CDecoder::Free() #endif -HRESULT CDecoder::ReadSignatures(bool &wasFinished, UInt32 &crc) +bool IsEndSig(const Byte *p) throw() { - wasFinished = false; - Byte s[6]; - for (int i = 0; i < 6; i++) + return + p[0] == kFinSig0 && + p[1] == kFinSig1 && + p[2] == kFinSig2 && + p[3] == kFinSig3 && + p[4] == kFinSig4 && + p[5] == kFinSig5; +} + +bool IsBlockSig(const Byte *p) throw() +{ + return + p[0] == kBlockSig0 && + p[1] == kBlockSig1 && + p[2] == kBlockSig2 && + p[3] == kBlockSig3 && + p[4] == kBlockSig4 && + p[5] == kBlockSig5; +} + +HRESULT CDecoder::ReadSignature(UInt32 &crc) +{ + BzWasFinished = false; + crc = 0; + + Byte s[10]; + int i; + for (i = 0; i < 10; i++) s[i] = ReadByte(); - crc = ReadCrc(); - if (s[0] == kFinSig0) + + if (Base.BitDecoder.ExtraBitsWereRead()) + return S_FALSE; + + UInt32 v = 0; + for (i = 0; i < 4; i++) { - 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; + v <<= 8; + v |= s[6 + i]; } - if (s[0] != kBlockSig0 || - s[1] != kBlockSig1 || - s[2] != kBlockSig2 || - s[3] != kBlockSig3 || - s[4] != kBlockSig4 || - s[5] != kBlockSig5) + + crc = v; + + if (IsBlockSig(s)) + { + IsBz = true; + CombinedCrc.Update(crc); + return S_OK; + } + + if (!IsEndSig(s)) return S_FALSE; - CombinedCrc.Update(crc); + + IsBz = true; + BzWasFinished = true; + if (crc != CombinedCrc.GetDigest()) + { + CrcError = true; + return S_FALSE; + } return S_OK; } -HRESULT CDecoder::DecodeFile(bool &isBZ, ICompressProgressInfo *progress) +HRESULT CDecoder::DecodeFile(ICompressProgressInfo *progress) { Progress = progress; #ifndef _7ZIP_ST @@ -541,18 +568,27 @@ HRESULT CDecoder::DecodeFile(bool &isBZ, ICompressProgressInfo *progress) return E_OUTOFMEMORY; #endif - isBZ = false; - Byte s[6]; + IsBz = false; + + /* + if (Base.BitDecoder.ExtraBitsWereRead()) + return E_FAIL; + */ + + Byte s[4]; int i; for (i = 0; i < 4; i++) s[i] = ReadByte(); + if (Base.BitDecoder.ExtraBitsWereRead()) + return S_FALSE; + if (s[0] != kArSig0 || s[1] != kArSig1 || s[2] != kArSig2 || s[3] <= kArSig3 || s[3] > kArSig3 + kBlockSizeMultMax) - return S_OK; - isBZ = true; + return S_FALSE; + UInt32 dicSize = (UInt32)(s[3] - kArSig3) * kBlockSizeStep; CombinedCrc.Init(); @@ -584,58 +620,59 @@ HRESULT CDecoder::DecodeFile(bool &isBZ, ICompressProgressInfo *progress) CState &state = m_States[0]; for (;;) { - RINOK(SetRatioProgress(m_InStream.GetProcessedSize())); - bool wasFinished; + RINOK(SetRatioProgress(Base.BitDecoder.GetProcessedSize())); UInt32 crc; - RINOK(ReadSignatures(wasFinished, crc)); - if (wasFinished) + RINOK(ReadSignature(crc)); + if (BzWasFinished) 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) + CBlockProps props; + props.randMode = true; + RINOK(Base.ReadBlock(state.Counters, dicSize, &props)); + DecodeBlock1(state.Counters, props.blockSize); + if (DecodeBlock(props, state.Counters + 256, m_OutStream) != crc) + { + CrcError = true; return S_FALSE; + } } } - return SetRatioProgress(m_InStream.GetProcessedSize()); + return SetRatioProgress(Base.BitDecoder.GetProcessedSize()); } HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, - bool &isBZ, ICompressProgressInfo *progress) + ICompressProgressInfo *progress) { - isBZ = false; + IsBz = false; + BzWasFinished = false; + CrcError = false; + try { - if (!m_InStream.Create(kBufferSize)) + if (!Base.BitDecoder.Create(kBufferSize)) return E_OUTOFMEMORY; if (!m_OutStream.Create(kBufferSize)) return E_OUTOFMEMORY; if (inStream) - m_InStream.SetStream(inStream); + Base.BitDecoder.SetStream(inStream); - CDecoderFlusher flusher(this, inStream != NULL); + CDecoderFlusher flusher(this); if (_needInStreamInit) { - m_InStream.Init(); + Base.BitDecoder.Init(); _needInStreamInit = false; } - _inStart = m_InStream.GetProcessedSize(); + _inStart = Base.BitDecoder.GetProcessedSize(); - m_InStream.AlignToByte(); + Base.BitDecoder.AlignToByte(); m_OutStream.SetStream(outStream); m_OutStream.Init(); - RINOK(DecodeFile(isBZ, progress)); + RINOK(DecodeFile(progress)); flusher.NeedFlush = false; return Flush(); @@ -649,18 +686,26 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) { _needInStreamInit = true; - bool isBZ; - RINOK(CodeReal(inStream, outStream, isBZ, progress)); - return isBZ ? S_OK : S_FALSE; + return CodeReal(inStream, outStream, progress); } -HRESULT CDecoder::CodeResume(ISequentialOutStream *outStream, bool &isBZ, ICompressProgressInfo *progress) +HRESULT CDecoder::CodeResume(ISequentialOutStream *outStream, ICompressProgressInfo *progress) { - return CodeReal(NULL, outStream, isBZ, progress); + return CodeReal(NULL, outStream, progress); } -STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { m_InStream.SetStream(inStream); return S_OK; } -STDMETHODIMP CDecoder::ReleaseInStream() { m_InStream.ReleaseStream(); return S_OK; } +STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) +{ + Base.InStreamRef = inStream; + Base.BitDecoder.SetStream(inStream); + return S_OK; +} + +STDMETHODIMP CDecoder::ReleaseInStream() +{ + Base.InStreamRef.Release(); + return S_OK; +} #ifndef _7ZIP_ST @@ -709,36 +754,33 @@ void CState::ThreadFunc() Decoder->NextBlockIndex = nextBlockIndex; UInt32 crc; UInt64 packSize = 0; - UInt32 blockSize = 0, origPtr = 0; - bool randMode = false; + CBlockProps props; try { - bool wasFinished; - res = Decoder->ReadSignatures(wasFinished, crc); + res = Decoder->ReadSignature(crc); if (res != S_OK) { Decoder->Result1 = res; FinishStream(); continue; } - if (wasFinished) + if (Decoder->BzWasFinished) { Decoder->Result1 = res; FinishStream(); continue; } - res = ReadBlock(&Decoder->m_InStream, Counters, Decoder->BlockSizeMax, - Decoder->m_Selectors, Decoder->m_HuffmanDecoders, - &blockSize, &origPtr, &randMode); + props.randMode = true; + res = Decoder->Base.ReadBlock(Counters, Decoder->BlockSizeMax, &props); if (res != S_OK) { Decoder->Result1 = res; FinishStream(); continue; } - packSize = Decoder->m_InStream.GetProcessedSize(); + packSize = Decoder->Base.BitDecoder.GetProcessedSize(); } catch(const CInBufferException &e) { res = e.ErrorCode; if (res != S_OK) res = E_FAIL; } catch(...) { res = E_FAIL; } @@ -751,7 +793,7 @@ void CState::ThreadFunc() Decoder->CS.Leave(); - DecodeBlock1(Counters, blockSize); + DecodeBlock1(Counters, props.blockSize); bool needFinish = true; try @@ -760,9 +802,7 @@ void CState::ThreadFunc() needFinish = Decoder->StreamWasFinished2; if (!needFinish) { - if ((randMode ? - DecodeBlock2Rand(Counters + 256, blockSize, origPtr, Decoder->m_OutStream) : - DecodeBlock2(Counters + 256, blockSize, origPtr, Decoder->m_OutStream)) == crc) + if (DecodeBlock(props, Counters + 256, Decoder->m_OutStream) == crc) res = Decoder->SetRatioProgress(packSize); else res = S_FALSE; @@ -818,8 +858,17 @@ enum 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::SetInStream(ISequentialInStream *inStream) +{ + Base.InStreamRef = inStream; + Base.BitDecoder.SetStream(inStream); + return S_OK; +} +STDMETHODIMP CNsisDecoder::ReleaseInStream() +{ + Base.InStreamRef.Release(); + return S_OK; +} STDMETHODIMP CNsisDecoder::SetOutStreamSize(const UInt64 * /* outSize */) { @@ -843,17 +892,17 @@ STDMETHODIMP CNsisDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) if (_nsisState == NSIS_STATE_INIT) { - if (!m_InStream.Create(kBufferSize)) + if (!Base.BitDecoder.Create(kBufferSize)) return E_OUTOFMEMORY; if (!state.Alloc()) return E_OUTOFMEMORY; - m_InStream.Init(); + Base.BitDecoder.Init(); _nsisState = NSIS_STATE_NEW_BLOCK; } if (_nsisState == NSIS_STATE_NEW_BLOCK) { - Byte b = (Byte)m_InStream.ReadBits(8); + Byte b = (Byte)Base.ReadBits(8); if (b == kFinSig0) { _nsisState = NSIS_STATE_FINISHED; @@ -864,12 +913,13 @@ STDMETHODIMP CNsisDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) _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); + CBlockProps props; + props.randMode = false; + RINOK(Base.ReadBlock(state.Counters, 9 * kBlockSizeStep, &props)); + _blockSize = props.blockSize; + DecodeBlock1(state.Counters, props.blockSize); const UInt32 *tt = state.Counters + 256; - _tPos = tt[tt[origPtr] >> 8]; + _tPos = tt[tt[props.origPtr] >> 8]; _prevByte = (unsigned)(_tPos & 0xFF); _numReps = 0; _repRem = 0; diff --git a/CPP/7zip/Compress/BZip2Decoder.h b/CPP/7zip/Compress/BZip2Decoder.h old mode 100755 new mode 100644 index e6dec1ea..2c28c5a1 --- a/CPP/7zip/Compress/BZip2Decoder.h +++ b/CPP/7zip/Compress/BZip2Decoder.h @@ -23,6 +23,9 @@ namespace NCompress { namespace NBZip2 { +bool IsEndSig(const Byte *p) throw(); +bool IsBlockSig(const Byte *p) throw(); + typedef NCompress::NHuffman::CDecoder CHuffmanDecoder; class CDecoder; @@ -57,6 +60,40 @@ struct CState void Free(); }; +struct CBlockProps +{ + UInt32 blockSize; + UInt32 origPtr; + bool randMode; + + CBlockProps(): blockSize(0), origPtr(0), randMode(false) {} +}; + +struct CBase +{ + CMyComPtr InStreamRef; + NBitm::CDecoder BitDecoder; + +private: + Byte m_Selectors[kNumSelectorsMax]; + CHuffmanDecoder m_HuffmanDecoders[kNumTablesMax]; + +public: + UInt64 NumBlocks; + + CBase(): NumBlocks(0) {} + UInt32 ReadBits(unsigned numBits); + unsigned ReadBit(); + void InitNumBlocks() { NumBlocks = 0; } + + /* + ReadBlock() props->randMode: + in: need read randMode bit, + out: randMode status + */ + HRESULT ReadBlock(UInt32 *charCounters, UInt32 blockSizeMax, CBlockProps *props); +}; + class CDecoder : public ICompressCoder, #ifndef _7ZIP_ST @@ -67,37 +104,30 @@ class CDecoder : 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]; + + CBase Base; + 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); + + HRESULT DecodeFile(ICompressProgressInfo *progress); + HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress); + class CDecoderFlusher { CDecoder *_decoder; public: bool NeedFlush; - bool ReleaseInStream; - CDecoderFlusher(CDecoder *decoder, bool releaseInStream): - _decoder(decoder), - ReleaseInStream(releaseInStream), - NeedFlush(true) {} + CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {} ~CDecoderFlusher() { if (NeedFlush) _decoder->Flush(); - _decoder->ReleaseStreams(ReleaseInStream); } }; @@ -123,6 +153,11 @@ public: HRESULT Result2; UInt32 BlockSizeMax; + + bool IsBz; + bool BzWasFinished; // bzip stream was finished with end signature + bool CrcError; // it can CRC error of block or CRC error of whole stream. + ~CDecoder(); HRESULT Create(); void Free(); @@ -134,15 +169,9 @@ public: CDecoder(); HRESULT SetRatioProgress(UInt64 packSize); - HRESULT ReadSignatures(bool &wasFinished, UInt32 &crc); + HRESULT ReadSignature(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 @@ -159,8 +188,13 @@ public: STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(ReleaseInStream)(); - HRESULT CodeResume(ISequentialOutStream *outStream, bool &isBZ, ICompressProgressInfo *progress); - UInt64 GetInputProcessedSize() const { return m_InStream.GetProcessedSize(); } + HRESULT CodeResume(ISequentialOutStream *outStream, ICompressProgressInfo *progress); + + UInt64 GetStreamSize() const { return Base.BitDecoder.GetStreamSize(); } + UInt64 GetInputProcessedSize() const { return Base.BitDecoder.GetProcessedSize(); } + + void InitNumBlocks() { Base.InitNumBlocks(); } + UInt64 GetNumBlocks() const { return Base.NumBlocks; } #ifndef _7ZIP_ST STDMETHOD(SetNumberOfThreads)(UInt32 numThreads); @@ -174,9 +208,8 @@ class CNsisDecoder : public ICompressSetOutStreamSize, public CMyUnknownImp { - NBitm::CDecoder m_InStream; - Byte m_Selectors[kNumSelectorsMax]; - CHuffmanDecoder m_HuffmanDecoders[kNumTablesMax]; + CBase Base; + CState m_State; int _nsisState; diff --git a/CPP/7zip/Compress/BZip2Encoder.cpp b/CPP/7zip/Compress/BZip2Encoder.cpp old mode 100755 new mode 100644 index 6dafc45f..2bdbe989 --- a/CPP/7zip/Compress/BZip2Encoder.cpp +++ b/CPP/7zip/Compress/BZip2Encoder.cpp @@ -53,7 +53,7 @@ static THREAD_FUNC_DECL MFThread(void *threadCoderInfo) return ((CThreadInfo *)threadCoderInfo)->ThreadFunc(); } -#define RINOK_THREAD(x) { WRes __result_ = (x); if(__result_ != 0) return __result_; } +#define RINOK_THREAD(x) { WRes __result_ = (x); if (__result_ != 0) return __result_; } HRESULT CThreadInfo::Create() { @@ -244,9 +244,8 @@ UInt32 CEncoder::ReadRleBlock(Byte *buffer) return i; } -void CThreadInfo::WriteBits2(UInt32 value, UInt32 numBits) - { m_OutStreamCurrent->WriteBits(value, numBits); } -void CThreadInfo::WriteByte2(Byte b) { WriteBits2(b , 8); } +void CThreadInfo::WriteBits2(UInt32 value, unsigned numBits) { m_OutStreamCurrent->WriteBits(value, numBits); } +void CThreadInfo::WriteByte2(Byte b) { WriteBits2(b, 8); } void CThreadInfo::WriteBit2(bool v) { WriteBits2((v ? 1 : 0), 1); } void CThreadInfo::WriteCrc2(UInt32 v) { @@ -254,9 +253,8 @@ void CThreadInfo::WriteCrc2(UInt32 v) 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::WriteBits(UInt32 value, unsigned numBits) { m_OutStream.WriteBits(value, numBits); } +void CEncoder::WriteByte(Byte b) { WriteBits(b, 8); } void CEncoder::WriteBit(bool v) { WriteBits((v ? 1 : 0), 1); } void CEncoder::WriteCrc(UInt32 v) { @@ -318,7 +316,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) block--; do { - int pos = mtf.FindAndMove(block[bsIndex[i]]); + unsigned pos = mtf.FindAndMove(block[bsIndex[i]]); if (pos == 0) rleSize++; else @@ -374,7 +372,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) { int numTables; - if(m_OptimizeNumTables) + if (m_OptimizeNumTables) { m_OutStreamCurrent->SetPos(startPos); m_OutStreamCurrent->SetCurState((startPos & 7), startCurByte); @@ -415,12 +413,12 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) Byte *lens = Lens[t - 1]; int i = 0; do - lens[i] = (i >= gs && i < ge) ? 0 : 1; + lens[i] = (Byte)((i >= gs && i < ge) ? 0 : 1); while (++i < alphaSize); gs = ge; remFreq -= aFreq; } - while(--t != 0); + while (--t != 0); } @@ -430,7 +428,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) int t = 0; do memset(Freqs[t], 0, sizeof(Freqs[t])); - while(++t < numTables); + while (++t < numTables); } { @@ -465,7 +463,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) bestPrice = price; } } - while(++t < numTables); + while (++t < numTables); UInt32 *freqs = Freqs[m_Selectors[g++]]; int j = 0; do @@ -483,10 +481,10 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) do if (freqs[i] == 0) freqs[i] = 1; - while(++i < alphaSize); + while (++i < alphaSize); Huffman_Generate(freqs, Codes[t], Lens[t], kMaxAlphaSize, kMaxHuffmanLenForEncoding); } - while(++t < numTables); + while (++t < numTables); } { @@ -495,7 +493,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) int t = 0; do mtfSel[t] = (Byte)t; - while(++t < numTables); + while (++t < numTables); } UInt32 i = 0; @@ -510,7 +508,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) mtfSel[pos] = mtfSel[pos - 1]; mtfSel[0] = sel; } - while(++i < numSelectors); + while (++i < numSelectors); } { @@ -542,7 +540,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) } while (++i < alphaSize); } - while(++t < numTables); + while (++t < numTables); } { @@ -722,7 +720,7 @@ HRESULT CThreadInfo::EncodeBlock3(UInt32 blockSize) void CEncoder::WriteBytes(const Byte *data, UInt32 sizeInBits, Byte lastByte) { - UInt32 bytesSize = (sizeInBits / 8); + UInt32 bytesSize = (sizeInBits >> 3); for (UInt32 i = 0; i < bytesSize; i++) m_OutStream.WriteBits(data[i], 8); WriteBits(lastByte, (sizeInBits & 7)); @@ -770,8 +768,6 @@ HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * m_OutStream.SetStream(outStream); m_OutStream.Init(); - CFlusher flusher(this); - CombinedCrc.Init(); #ifndef _7ZIP_ST NextBlockIndex = 0; diff --git a/CPP/7zip/Compress/BZip2Encoder.h b/CPP/7zip/Compress/BZip2Encoder.h old mode 100755 new mode 100644 index 5aa8a786..6b04eca1 --- a/CPP/7zip/Compress/BZip2Encoder.h +++ b/CPP/7zip/Compress/BZip2Encoder.h @@ -25,61 +25,61 @@ namespace NBZip2 { class CMsbfEncoderTemp { - UInt32 m_Pos; - int m_BitPos; - Byte m_CurByte; - Byte *Buffer; + UInt32 _pos; + unsigned _bitPos; + Byte _curByte; + Byte *_buf; public: - void SetStream(Byte *buffer) { Buffer = buffer; } - Byte *GetStream() const { return Buffer; } + void SetStream(Byte *buf) { _buf = buf; } + Byte *GetStream() const { return _buf; } void Init() { - m_Pos = 0; - m_BitPos = 8; - m_CurByte = 0; + _pos = 0; + _bitPos = 8; + _curByte = 0; } void Flush() { - if (m_BitPos < 8) - WriteBits(0, m_BitPos); + if (_bitPos < 8) + WriteBits(0, _bitPos); } - void WriteBits(UInt32 value, int numBits) + void WriteBits(UInt32 value, unsigned numBits) { while (numBits > 0) { - int numNewBits = MyMin(numBits, m_BitPos); + unsigned numNewBits = MyMin(numBits, _bitPos); numBits -= numNewBits; - m_CurByte <<= numNewBits; + _curByte <<= numNewBits; UInt32 newBits = value >> numBits; - m_CurByte |= Byte(newBits); + _curByte |= Byte(newBits); value -= (newBits << numBits); - m_BitPos -= numNewBits; + _bitPos -= numNewBits; - if (m_BitPos == 0) + if (_bitPos == 0) { - Buffer[m_Pos++] = m_CurByte; - m_BitPos = 8; + _buf[_pos++] = _curByte; + _bitPos = 8; } } } - UInt32 GetBytePos() const { return m_Pos ; } - UInt32 GetPos() const { return m_Pos * 8 + (8 - m_BitPos); } - Byte GetCurByte() const { return m_CurByte; } + UInt32 GetBytePos() const { return _pos ; } + UInt32 GetPos() const { return _pos * 8 + (8 - _bitPos); } + Byte GetCurByte() const { return _curByte; } void SetPos(UInt32 bitPos) { - m_Pos = bitPos / 8; - m_BitPos = 8 - ((int)bitPos & 7); + _pos = bitPos >> 3; + _bitPos = 8 - ((unsigned)bitPos & 7); } - void SetCurState(int bitPos, Byte curByte) + void SetCurState(unsigned bitPos, Byte curByte) { - m_BitPos = 8 - bitPos; - m_CurByte = curByte; + _bitPos = 8 - bitPos; + _curByte = curByte; } }; @@ -109,7 +109,7 @@ private: UInt32 m_BlockIndex; - void WriteBits2(UInt32 value, UInt32 numBits); + void WriteBits2(UInt32 value, unsigned numBits); void WriteByte2(Byte b); void WriteBit2(bool v); void WriteCrc2(UInt32 v); @@ -193,10 +193,10 @@ public: CThreadInfo ThreadsInfo; #endif - UInt32 ReadRleBlock(Byte *buffer); + UInt32 ReadRleBlock(Byte *buf); void WriteBytes(const Byte *data, UInt32 sizeInBits, Byte lastByte); - void WriteBits(UInt32 value, UInt32 numBits); + void WriteBits(UInt32 value, unsigned numBits); void WriteByte(Byte b); void WriteBit(bool v); void WriteCrc(UInt32 v); @@ -214,23 +214,6 @@ public: 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 diff --git a/CPP/7zip/Compress/BZip2Register.cpp b/CPP/7zip/Compress/BZip2Register.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/Bcj2Coder.cpp b/CPP/7zip/Compress/Bcj2Coder.cpp old mode 100755 new mode 100644 index 684da5ab..2d737e8a --- a/CPP/7zip/Compress/Bcj2Coder.cpp +++ b/CPP/7zip/Compress/Bcj2Coder.cpp @@ -15,35 +15,22 @@ inline unsigned GetIndex(Byte b0, Byte b1) { return ((b1 == 0xE8) ? b0 : ((b1 == #ifndef EXTRACT_ONLY -static const int kBufferSize = 1 << 17; +static const unsigned kBufSize = 1 << 17; + +#define NUM_BITS 2 +#define SIGN_BIT (1 << NUM_BITS) +#define MASK_HIGH (0x100 - (1 << (NUM_BITS + 1))) + +static const UInt32 kDefaultLimit = (1 << (24 + NUM_BITS)); 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; + return (((b) + SIGN_BIT) & MASK_HIGH) == 0; } CEncoder::~CEncoder() { - ::MidFree(_buffer); + ::MidFree(_buf); } HRESULT CEncoder::Flush() @@ -51,12 +38,10 @@ HRESULT CEncoder::Flush() RINOK(_mainStream.Flush()); RINOK(_callStream.Flush()); RINOK(_jumpStream.Flush()); - _rangeEncoder.FlushData(); - return _rangeEncoder.FlushStream(); + _rc.FlushData(); + return _rc.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) @@ -64,32 +49,34 @@ HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSiz if (numInStreams != 1 || numOutStreams != 4) return E_INVALIDARG; - if (!Create()) - return E_OUTOFMEMORY; + if (!_mainStream.Create(1 << 18)) return E_OUTOFMEMORY; + if (!_callStream.Create(1 << 18)) return E_OUTOFMEMORY; + if (!_jumpStream.Create(1 << 18)) return E_OUTOFMEMORY; + if (!_rc.Create(1 << 20)) return E_OUTOFMEMORY; + if (_buf == 0) + { + _buf = (Byte *)MidAlloc(kBufSize); + if (_buf == 0) + return E_OUTOFMEMORY; + } bool sizeIsDefined = false; UInt64 inSize = 0; - if (inSizes != NULL) - if (inSizes[0] != NULL) + if (inSizes) + if (inSizes[0]) { 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++) + _mainStream.SetStream(outStreams[0]); _mainStream.Init(); + _callStream.SetStream(outStreams[1]); _callStream.Init(); + _jumpStream.SetStream(outStreams[2]); _jumpStream.Init(); + _rc.SetStream(outStreams[3]); _rc.Init(); + for (unsigned i = 0; i < 256 + 2; i++) _statusEncoder[i].Init(); CMyComPtr getSubStreamSize; @@ -99,12 +86,12 @@ HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSiz UInt32 nowPos = 0; UInt64 nowPos64 = 0; - UInt32 bufferPos = 0; + UInt32 bufPos = 0; Byte prevByte = 0; UInt64 subStreamIndex = 0; - UInt64 subStreamStartPos = 0; + UInt64 subStreamStartPos = 0; UInt64 subStreamEndPos = 0; for (;;) @@ -112,23 +99,23 @@ HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSiz UInt32 processedSize = 0; for (;;) { - UInt32 size = kBufferSize - (bufferPos + processedSize); + UInt32 size = kBufSize - (bufPos + processedSize); UInt32 processedSizeLoc; if (size == 0) break; - RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc)); + RINOK(inStream->Read(_buf + bufPos + processedSize, size, &processedSizeLoc)); if (processedSizeLoc == 0) break; processedSize += processedSizeLoc; } - UInt32 endPos = bufferPos + processedSize; + UInt32 endPos = bufPos + processedSize; if (endPos < 5) { // change it - for (bufferPos = 0; bufferPos < endPos; bufferPos++) + for (bufPos = 0; bufPos < endPos; bufPos++) { - Byte b = _buffer[bufferPos]; + Byte b = _buf[bufPos]; _mainStream.WriteByte(b); UInt32 index; if (b == 0xE8) @@ -142,37 +129,37 @@ HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSiz prevByte = b; continue; } - _statusEncoder[index].Encode(&_rangeEncoder, 0); + _statusEncoder[index].Encode(&_rc, 0); prevByte = b; } return Flush(); } - bufferPos = 0; + bufPos = 0; UInt32 limit = endPos - 5; - while(bufferPos <= limit) + while (bufPos <= limit) { - Byte b = _buffer[bufferPos]; + Byte b = _buf[bufPos]; _mainStream.WriteByte(b); if (!IsJ(prevByte, b)) { - bufferPos++; + bufPos++; prevByte = b; continue; } - Byte nextByte = _buffer[bufferPos + 4]; + Byte nextByte = _buf[bufPos + 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; + (UInt32(_buf[bufPos + 3]) << 16) | + (UInt32(_buf[bufPos + 2]) << 8) | + (_buf[bufPos + 1]); + UInt32 dest = (nowPos + bufPos + 5) + src; // if (Test86MSByte(nextByte)) bool convert; - if (getSubStreamSize != NULL) + if (getSubStreamSize) { - UInt64 currentPos = (nowPos64 + bufferPos); + UInt64 currentPos = (nowPos64 + bufPos); while (subStreamEndPos < currentPos) { UInt64 subStreamSize; @@ -214,8 +201,8 @@ HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSiz unsigned index = GetIndex(prevByte, b); if (convert) { - _statusEncoder[index].Encode(&_rangeEncoder, 1); - bufferPos += 5; + _statusEncoder[index].Encode(&_rc, 1); + bufPos += 5; COutBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; for (int i = 24; i >= 0; i -= 8) s.WriteByte((Byte)(dest >> i)); @@ -223,30 +210,30 @@ HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSiz } else { - _statusEncoder[index].Encode(&_rangeEncoder, 0); - bufferPos++; + _statusEncoder[index].Encode(&_rc, 0); + bufPos++; prevByte = b; } } - nowPos += bufferPos; - nowPos64 += bufferPos; + nowPos += bufPos; + nowPos64 += bufPos; - if (progress != NULL) + if (progress) { /* const UInt64 compressedSize = _mainStream.GetProcessedSize() + _callStream.GetProcessedSize() + _jumpStream.GetProcessedSize() + - _rangeEncoder.GetProcessedSize(); + _rc.GetProcessedSize(); */ RINOK(progress->SetRatioInfo(&nowPos64, NULL)); } UInt32 i = 0; - while(bufferPos < endPos) - _buffer[i++] = _buffer[bufferPos++]; - bufferPos = i; + while (bufPos < endPos) + _buf[i++] = _buf[bufPos++]; + bufPos = i; } } @@ -284,46 +271,39 @@ HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams, const UInt64 ** /* i 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); + if (!_mainStream.Create(_inBufSizes[0])) return E_OUTOFMEMORY; + if (!_callStream.Create(_inBufSizes[1])) return E_OUTOFMEMORY; + if (!_jumpStream.Create(_inBufSizes[2])) return E_OUTOFMEMORY; + if (!_rc.Create(_inBufSizes[3])) return E_OUTOFMEMORY; + if (!_outStream.Create(_outBufSize)) return E_OUTOFMEMORY; - _mainInStream.SetStream(inStreams[0]); + _mainStream.SetStream(inStreams[0]); _callStream.SetStream(inStreams[1]); _jumpStream.SetStream(inStreams[2]); - _rangeDecoder.SetStream(inStreams[3]); + _rc.SetStream(inStreams[3]); _outStream.SetStream(outStreams[0]); - _mainInStream.Init(); + _mainStream.Init(); _callStream.Init(); _jumpStream.Init(); - _rangeDecoder.Init(); + _rc.Init(); _outStream.Init(); - for (int i = 0; i < 256 + 2; i++) + for (unsigned i = 0; i < 256 + 2; i++) _statusDecoder[i].Init(); Byte prevByte = 0; UInt32 processedBytes = 0; for (;;) { - if (processedBytes >= (1 << 20) && progress != NULL) + if (processedBytes >= (1 << 20) && progress) { /* const UInt64 compressedSize = - _mainInStream.GetProcessedSize() + + _mainStream.GetProcessedSize() + _callStream.GetProcessedSize() + _jumpStream.GetProcessedSize() + - _rangeDecoder.GetProcessedSize(); + _rc.GetProcessedSize(); */ const UInt64 nowPos64 = _outStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(NULL, &nowPos64)); @@ -334,8 +314,8 @@ HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams, const UInt64 ** /* i const UInt32 kBurstSize = (1 << 18); for (i = 0; i < kBurstSize; i++) { - if (!_mainInStream.ReadByte(b)) - return Flush(); + if (!_mainStream.ReadByte(b)) + return _outStream.Flush(); _outStream.WriteByte(b); if (IsJ(prevByte, b)) break; @@ -345,14 +325,14 @@ HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams, const UInt64 ** /* i if (i == kBurstSize) continue; unsigned index = GetIndex(prevByte, b); - if (_statusDecoder[index].Decode(&_rangeDecoder) == 1) + if (_statusDecoder[index].Decode(&_rc) == 1) { UInt32 src = 0; CInBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; - for (int i = 0; i < 4; i++) + for (unsigned i = 0; i < 4; i++) { Byte b0; - if(!s.ReadByte(b0)) + if (!s.ReadByte(b0)) return S_FALSE; src <<= 8; src |= ((UInt32)b0); diff --git a/CPP/7zip/Compress/Bcj2Coder.h b/CPP/7zip/Compress/Bcj2Coder.h old mode 100755 new mode 100644 index 79a713f1..d2b3bda3 --- a/CPP/7zip/Compress/Bcj2Coder.h +++ b/CPP/7zip/Compress/Bcj2Coder.h @@ -12,7 +12,7 @@ namespace NCompress { namespace NBcj2 { -const int kNumMoveBits = 5; +const unsigned kNumMoveBits = 5; #ifndef EXTRACT_ONLY @@ -20,32 +20,15 @@ class CEncoder: public ICompressCoder2, public CMyUnknownImp { - Byte *_buffer; - bool Create(); + Byte *_buf; COutBuffer _mainStream; COutBuffer _callStream; COutBuffer _jumpStream; - NCompress::NRangeCoder::CEncoder _rangeEncoder; - NCompress::NRangeCoder::CBitEncoder _statusEncoder[256 + 2]; + NRangeCoder::CEncoder _rc; + 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 @@ -56,7 +39,8 @@ public: STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); - CEncoder(): _buffer(0) {}; + + CEncoder(): _buf(0) {}; ~CEncoder(); }; @@ -67,37 +51,19 @@ class CDecoder: public ICompressSetBufSize, public CMyUnknownImp { - CInBuffer _mainInStream; + CInBuffer _mainStream; CInBuffer _callStream; CInBuffer _jumpStream; - NCompress::NRangeCoder::CDecoder _rangeDecoder; - NCompress::NRangeCoder::CBitDecoder _statusDecoder[256 + 2]; + NRangeCoder::CDecoder _rc; + 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); @@ -107,6 +73,7 @@ public: STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size); STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size); + CDecoder(); }; diff --git a/CPP/7zip/Compress/Bcj2Register.cpp b/CPP/7zip/Compress/Bcj2Register.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/BcjCoder.cpp b/CPP/7zip/Compress/BcjCoder.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/BcjCoder.h b/CPP/7zip/Compress/BcjCoder.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/BcjRegister.cpp b/CPP/7zip/Compress/BcjRegister.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/BitlDecoder.cpp b/CPP/7zip/Compress/BitlDecoder.cpp old mode 100755 new mode 100644 index 78665be8..516b0932 --- a/CPP/7zip/Compress/BitlDecoder.cpp +++ b/CPP/7zip/Compress/BitlDecoder.cpp @@ -12,9 +12,9 @@ struct CInverterTableInitializer { CInverterTableInitializer() { - for (int i = 0; i < 256; i++) + for (unsigned i = 0; i < 256; i++) { - int x = ((i & 0x55) << 1) | ((i & 0xAA) >> 1); + unsigned x = ((i & 0x55) << 1) | ((i & 0xAA) >> 1); x = ((x & 0x33) << 2) | ((x & 0xCC) >> 2); kInvertTable[i] = (Byte)(((x & 0x0F) << 4) | ((x & 0xF0) >> 4)); } diff --git a/CPP/7zip/Compress/BitlDecoder.h b/CPP/7zip/Compress/BitlDecoder.h old mode 100755 new mode 100644 index ff373bac..27be1716 --- a/CPP/7zip/Compress/BitlDecoder.h +++ b/CPP/7zip/Compress/BitlDecoder.h @@ -9,130 +9,127 @@ namespace NBitl { const unsigned kNumBigValueBits = 8 * 4; const unsigned kNumValueBytes = 3; -const unsigned kNumValueBits = 8 * kNumValueBytes; +const unsigned kNumValueBits = 8 * kNumValueBytes; const UInt32 kMask = (1 << kNumValueBits) - 1; extern Byte kInvertTable[256]; +/* TInByte must support "Extra Bytes" (bytes that can be read after the end of stream + TInByte::ReadByte() returns 0xFF after the end of stream + TInByte::NumExtraBytes contains the number "Extra Bytes" + + Bitl decoder can read up to 4 bytes ahead to internal buffer. */ + template class CBaseDecoder { protected: - unsigned m_BitPos; - UInt32 m_Value; - TInByte m_Stream; + unsigned _bitPos; + UInt32 _value; + TInByte _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(); } + bool Create(UInt32 bufSize) { return _stream.Create(bufSize); } + void SetStream(ISequentialInStream *inStream) { _stream.SetStream(inStream); } void Init() { - m_Stream.Init(); - m_BitPos = kNumBigValueBits; - m_Value = 0; - NumExtraBytes = 0; + _stream.Init(); + _bitPos = kNumBigValueBits; + _value = 0; } - UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() + NumExtraBytes - (kNumBigValueBits - m_BitPos) / 8; } + + UInt64 GetStreamSize() const { return _stream.GetStreamSize(); } + UInt64 GetProcessedSize() const { return _stream.GetProcessedSize() - ((kNumBigValueBits - _bitPos) >> 3); } + + bool ThereAreDataInBitsBuffer() const { return this->_bitPos != kNumBigValueBits; } 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; - } + for (; _bitPos >= 8; _bitPos -= 8) + _value = ((UInt32)_stream.ReadByte() << (kNumBigValueBits - _bitPos)) | _value; } UInt32 ReadBits(unsigned numBits) { Normalize(); - UInt32 res = m_Value & ((1 << numBits) - 1); - m_BitPos += numBits; - m_Value >>= numBits; + UInt32 res = _value & ((1 << numBits) - 1); + _bitPos += numBits; + _value >>= numBits; return res; } bool ExtraBitsWereRead() const { - if (NumExtraBytes == 0) - return false; - return ((UInt32)(kNumBigValueBits - m_BitPos) < (NumExtraBytes << 3)); + return (_stream.NumExtraBytes > 4 || kNumBigValueBits - _bitPos < (_stream.NumExtraBytes << 3)); + } + + bool ExtraBitsWereRead_Fast() const + { + // full version is not inlined in vc6. + // return _stream.NumExtraBytes != 0 && (_stream.NumExtraBytes > 4 || kNumBigValueBits - _bitPos < (_stream.NumExtraBytes << 3)); + + // (_stream.NumExtraBytes > 4) is fast overread detection. It's possible that + // it doesn't return true, if small number of extra bits were read. + return (_stream.NumExtraBytes > 4); } + + // it must be fixed !!! with extra bits + // UInt32 GetNumExtraBytes() const { return _stream.NumExtraBytes; } }; template class CDecoder: public CBaseDecoder { - UInt32 m_NormalValue; + UInt32 _normalValue; public: void Init() { CBaseDecoder::Init(); - m_NormalValue = 0; + _normalValue = 0; } void Normalize() { - for (; this->m_BitPos >= 8; this->m_BitPos -= 8) + for (; this->_bitPos >= 8; this->_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]; + Byte b = this->_stream.ReadByte(); + _normalValue = ((UInt32)b << (kNumBigValueBits - this->_bitPos)) | _normalValue; + this->_value = (this->_value << 8) | kInvertTable[b]; } } UInt32 GetValue(unsigned numBits) { Normalize(); - return ((this->m_Value >> (8 - this->m_BitPos)) & kMask) >> (kNumValueBits - numBits); + return ((this->_value >> (8 - this->_bitPos)) & kMask) >> (kNumValueBits - numBits); } void MovePos(unsigned numBits) { - this->m_BitPos += numBits; - m_NormalValue >>= numBits; + this->_bitPos += numBits; + _normalValue >>= numBits; } UInt32 ReadBits(unsigned numBits) { Normalize(); - UInt32 res = m_NormalValue & ((1 << numBits) - 1); + UInt32 res = _normalValue & ((1 << numBits) - 1); MovePos(numBits); return res; } - void AlignToByte() { MovePos((32 - this->m_BitPos) & 7); } + void AlignToByte() { MovePos((32 - this->_bitPos) & 7); } - Byte ReadByte() + Byte ReadDirectByte() { return _stream.ReadByte(); } + + Byte ReadAlignedByte() { - 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; - } + if (this->_bitPos == kNumBigValueBits) + return _stream.ReadByte(); + Byte b = (Byte)(_normalValue & 0xFF); + MovePos(8); + return b; } }; diff --git a/CPP/7zip/Compress/BitlEncoder.h b/CPP/7zip/Compress/BitlEncoder.h old mode 100755 new mode 100644 index 7de57545..22b83545 --- a/CPP/7zip/Compress/BitlEncoder.h +++ b/CPP/7zip/Compress/BitlEncoder.h @@ -7,51 +7,50 @@ class CBitlEncoder { - COutBuffer m_Stream; - unsigned m_BitPos; - Byte m_CurByte; + COutBuffer _stream; + unsigned _bitPos; + Byte _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; } + bool Create(UInt32 bufSize) { return _stream.Create(bufSize); } + void SetStream(ISequentialOutStream *outStream) { _stream.SetStream(outStream); } + // unsigned GetBitPosition() const { return (8 - _bitPos); } + UInt64 GetProcessedSize() const { return _stream.GetProcessedSize() + ((8 - _bitPos + 7) >> 3); } void Init() { - m_Stream.Init(); - m_BitPos = 8; - m_CurByte = 0; + _stream.Init(); + _bitPos = 8; + _curByte = 0; } HRESULT Flush() { FlushByte(); - return m_Stream.Flush(); + return _stream.Flush(); } void FlushByte() { - if (m_BitPos < 8) - m_Stream.WriteByte(m_CurByte); - m_BitPos = 8; - m_CurByte = 0; + if (_bitPos < 8) + _stream.WriteByte(_curByte); + _bitPos = 8; + _curByte = 0; } void WriteBits(UInt32 value, unsigned numBits) { while (numBits > 0) { - if (numBits < m_BitPos) + if (numBits < _bitPos) { - m_CurByte |= (value & ((1 << numBits) - 1)) << (8 - m_BitPos); - m_BitPos -= numBits; + _curByte |= (value & ((1 << numBits) - 1)) << (8 - _bitPos); + _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; + numBits -= _bitPos; + _stream.WriteByte((Byte)(_curByte | (value << (8 - _bitPos)))); + value >>= _bitPos; + _bitPos = 8; + _curByte = 0; } } - void WriteByte(Byte b) { m_Stream.WriteByte(b);} + void WriteByte(Byte b) { _stream.WriteByte(b);} }; #endif diff --git a/CPP/7zip/Compress/BitmDecoder.h b/CPP/7zip/Compress/BitmDecoder.h old mode 100755 new mode 100644 index 4369b452..fef20e06 --- a/CPP/7zip/Compress/BitmDecoder.h +++ b/CPP/7zip/Compress/BitmDecoder.h @@ -9,45 +9,59 @@ namespace NBitm { const unsigned kNumBigValueBits = 8 * 4; const unsigned kNumValueBytes = 3; -const unsigned kNumValueBits = 8 * kNumValueBytes; +const unsigned kNumValueBits = 8 * kNumValueBytes; const UInt32 kMask = (1 << kNumValueBits) - 1; +// _bitPos - the number of free bits (high bits in _value) +// (kNumBigValueBits - _bitPos) = (32 - _bitPos) == the number of ready to read bits (low bits of _value) + template class CDecoder { - unsigned m_BitPos; - UInt32 m_Value; + unsigned _bitPos; + UInt32 _value; + TInByte _stream; 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();} + bool Create(UInt32 bufSize) { return _stream.Create(bufSize); } + void SetStream(ISequentialInStream *inStream) { _stream.SetStream(inStream);} void Init() { - m_Stream.Init(); - m_BitPos = kNumBigValueBits; + _stream.Init(); + _bitPos = kNumBigValueBits; + _value = 0; Normalize(); } - UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() - (kNumBigValueBits - m_BitPos) / 8; } - + UInt64 GetStreamSize() const { return _stream.GetStreamSize(); } + UInt64 GetProcessedSize() const { return _stream.GetProcessedSize() - ((kNumBigValueBits - _bitPos) >> 3); } + + bool ExtraBitsWereRead() const + { + return (_stream.NumExtraBytes > 4 || kNumBigValueBits - _bitPos < (_stream.NumExtraBytes << 3)); + } + + bool ExtraBitsWereRead_Fast() const + { + return (_stream.NumExtraBytes > 4); + } + void Normalize() { - for (;m_BitPos >= 8; m_BitPos -= 8) - m_Value = (m_Value << 8) | m_Stream.ReadByte(); + for (; _bitPos >= 8; _bitPos -= 8) + _value = (_value << 8) | _stream.ReadByte(); } UInt32 GetValue(unsigned numBits) const { - // return (m_Value << m_BitPos) >> (kNumBigValueBits - numBits); - return ((m_Value >> (8 - m_BitPos)) & kMask) >> (kNumValueBits - numBits); + // return (_value << _bitPos) >> (kNumBigValueBits - numBits); + return ((_value >> (8 - _bitPos)) & kMask) >> (kNumValueBits - numBits); } void MovePos(unsigned numBits) { - m_BitPos += numBits; + _bitPos += numBits; Normalize(); } @@ -58,7 +72,7 @@ public: return res; } - void AlignToByte() { MovePos((32 - m_BitPos) & 7); } + void AlignToByte() { MovePos((kNumBigValueBits - _bitPos) & 7); } }; } diff --git a/CPP/7zip/Compress/BitmEncoder.h b/CPP/7zip/Compress/BitmEncoder.h old mode 100755 new mode 100644 index a85dbff8..05079ace --- a/CPP/7zip/Compress/BitmEncoder.h +++ b/CPP/7zip/Compress/BitmEncoder.h @@ -8,41 +8,40 @@ template class CBitmEncoder { - TOutByte m_Stream; - unsigned m_BitPos; - Byte m_CurByte; + unsigned _bitPos; + Byte _curByte; + TOutByte _stream; 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; } + bool Create(UInt32 bufferSize) { return _stream.Create(bufferSize); } + void SetStream(ISequentialOutStream *outStream) { _stream.SetStream(outStream);} + UInt64 GetProcessedSize() const { return _stream.GetProcessedSize() + ((8 - _bitPos + 7) >> 3); } void Init() { - m_Stream.Init(); - m_BitPos = 8; - m_CurByte = 0; + _stream.Init(); + _bitPos = 8; + _curByte = 0; } HRESULT Flush() { - if (m_BitPos < 8) - WriteBits(0, m_BitPos); - return m_Stream.Flush(); + if (_bitPos < 8) + WriteBits(0, _bitPos); + return _stream.Flush(); } void WriteBits(UInt32 value, unsigned numBits) { while (numBits > 0) { - if (numBits < m_BitPos) + if (numBits < _bitPos) { - m_CurByte |= ((Byte)value << (m_BitPos -= numBits)); + _curByte |= ((Byte)value << (_bitPos -= numBits)); return; } - numBits -= m_BitPos; + numBits -= _bitPos; UInt32 newBits = (value >> numBits); value -= (newBits << numBits); - m_Stream.WriteByte((Byte)(m_CurByte | newBits)); - m_BitPos = 8; - m_CurByte = 0; + _stream.WriteByte((Byte)(_curByte | newBits)); + _bitPos = 8; + _curByte = 0; } } }; diff --git a/CPP/7zip/Compress/BranchCoder.cpp b/CPP/7zip/Compress/BranchCoder.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/BranchCoder.h b/CPP/7zip/Compress/BranchCoder.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/BranchMisc.cpp b/CPP/7zip/Compress/BranchMisc.cpp old mode 100755 new mode 100644 index 423b723a..239f2513 --- a/CPP/7zip/Compress/BranchMisc.cpp +++ b/CPP/7zip/Compress/BranchMisc.cpp @@ -6,32 +6,16 @@ #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); } +#define SUB_FILTER_IMP2(name, coderStr, coderNum) \ + UInt32 CBC_ ## name ## coderStr::SubFilter(Byte *data, UInt32 size) \ + { return (UInt32)::name ## Convert(data, size, _bufferPos, coderNum); } + +#define SUB_FILTER_IMP(name) \ + SUB_FILTER_IMP2(name, Encoder, 1) \ + SUB_FILTER_IMP2(name, Decoder, 0) \ + +SUB_FILTER_IMP(ARM_) +SUB_FILTER_IMP(ARMT_) +SUB_FILTER_IMP(PPC_) +SUB_FILTER_IMP(SPARC_) +SUB_FILTER_IMP(IA64_) diff --git a/CPP/7zip/Compress/BranchMisc.h b/CPP/7zip/Compress/BranchMisc.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/BranchRegister.cpp b/CPP/7zip/Compress/BranchRegister.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/ByteSwap.cpp b/CPP/7zip/Compress/ByteSwap.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/Codec.def b/CPP/7zip/Compress/Codec.def old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/CodecExports.cpp b/CPP/7zip/Compress/CodecExports.cpp old mode 100755 new mode 100644 index 4ff1c0fc..726d35fc --- a/CPP/7zip/Compress/CodecExports.cpp +++ b/CPP/7zip/Compress/CodecExports.cpp @@ -2,7 +2,10 @@ #include "StdAfx.h" +#include "../../../C/CpuArch.h" + #include "../../Common/ComTry.h" +#include "../../Common/MyCom.h" #include "../../Windows/PropVariant.h" @@ -13,10 +16,15 @@ extern unsigned int g_NumCodecs; extern const CCodecInfo *g_Codecs[]; +extern unsigned int g_NumHashers; +extern const CHasherInfo *g_Hashers[]; + static const UInt16 kDecodeId = 0x2790; +static const UInt16 kEncodeId = 0x2791; +static const UInt16 kHasherId = 0x2792; DEFINE_GUID(CLSID_CCodec, -0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); +0x23170F69, 0x40C1, kDecodeId, 0, 0, 0, 0, 0, 0, 0, 0); static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value) { @@ -30,13 +38,13 @@ 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) +static HRESULT SetClassID(CMethodId id, UInt16 typeId, 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++; + GUID clsId; + clsId.Data1 = CLSID_CCodec.Data1; + clsId.Data2 = CLSID_CCodec.Data2; + clsId.Data3 = typeId; + SetUi64(clsId.Data4, id); return SetPropGUID(clsId, value); } @@ -44,13 +52,14 @@ static HRESULT FindCodecClassId(const GUID *clsID, UInt32 isCoder2, bool isFilte { index = -1; if (clsID->Data1 != CLSID_CCodec.Data1 || - clsID->Data2 != CLSID_CCodec.Data2 || - (clsID->Data3 & ~1) != kDecodeId) + clsID->Data2 != CLSID_CCodec.Data2) + return S_OK; + encode = true; + if (clsID->Data3 == kDecodeId) + encode = false; + else if (clsID->Data3 != kEncodeId) return S_OK; - encode = (clsID->Data3 != kDecodeId); - UInt64 id = 0; - for (int j = 0; j < 8; j++) - id |= ((UInt64)clsID->Data4[j]) << (8 * j); + UInt64 id = GetUi64(clsID->Data4); for (unsigned i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; @@ -65,7 +74,7 @@ static HRESULT FindCodecClassId(const GUID *clsID, UInt32 isCoder2, bool isFilte return S_OK; } -STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject) +STDAPI CreateCoder2(bool encode, int index, const GUID *iid, void **outObject) { COM_TRY_BEGIN *outObject = 0; @@ -88,18 +97,22 @@ STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject return CLASS_E_CLASSNOTAVAILABLE; *outObject = codec.CreateDecoder(); } - if (isCoder) - ((ICompressCoder *)*outObject)->AddRef(); - else if (isCoder2) - ((ICompressCoder2 *)*outObject)->AddRef(); - else - ((ICompressFilter *)*outObject)->AddRef(); + if (*outObject) + { + 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) { + COM_TRY_BEGIN *outObject = 0; bool isCoder = (*iid == IID_ICompressCoder) != 0; bool isCoder2 = (*iid == IID_ICompressCoder2) != 0; @@ -113,42 +126,54 @@ STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject) return res; if (codecIndex < 0) return CLASS_E_CLASSNOTAVAILABLE; - return CreateCoder2(encode, codecIndex, iid, outObject); + + const CCodecInfo &codec = *g_Codecs[codecIndex]; + if (encode) + *outObject = codec.CreateEncoder(); + else + *outObject = codec.CreateDecoder(); + if (*outObject) + { + if (isCoder) + ((ICompressCoder *)*outObject)->AddRef(); + else if (isCoder2) + ((ICompressCoder2 *)*outObject)->AddRef(); + else + ((ICompressFilter *)*outObject)->AddRef(); + } + return S_OK; + COM_TRY_END } STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value) { ::VariantClear((VARIANTARG *)value); const CCodecInfo &codec = *g_Codecs[codecIndex]; - switch(propID) + 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); + return SetClassID(codec.Id, kDecodeId, value); break; case NMethodPropID::kEncoder: if (codec.CreateEncoder) - return SetClassID(codec.Id, true, value); + return SetClassID(codec.Id, kEncodeId, value); break; case NMethodPropID::kInStreams: - { if (codec.NumInStreams != 1) { value->vt = VT_UI4; value->ulVal = (ULONG)codec.NumInStreams; } break; - } } return S_OK; } @@ -158,3 +183,101 @@ STDAPI GetNumberOfMethods(UINT32 *numCodecs) *numCodecs = g_NumCodecs; return S_OK; } + + +static int FindHasherClassId(const GUID *clsID) +{ + if (clsID->Data1 != CLSID_CCodec.Data1 || + clsID->Data2 != CLSID_CCodec.Data2 || + clsID->Data3 != kHasherId) + return -1; + UInt64 id = GetUi64(clsID->Data4); + for (unsigned i = 0; i < g_NumCodecs; i++) + if (id == g_Hashers[i]->Id) + return i; + return -1; +} + +static HRESULT CreateHasher2(UInt32 index, IHasher **hasher) +{ + COM_TRY_BEGIN + *hasher = g_Hashers[index]->CreateHasher(); + if (*hasher) + (*hasher)->AddRef(); + return S_OK; + COM_TRY_END +} + +STDAPI CreateHasher(const GUID *clsid, IHasher **outObject) +{ + COM_TRY_BEGIN + *outObject = 0; + int index = FindHasherClassId(clsid); + if (index < 0) + return CLASS_E_CLASSNOTAVAILABLE; + return CreateHasher2(index, outObject); + COM_TRY_END +} + +STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value) +{ + ::VariantClear((VARIANTARG *)value); + const CHasherInfo &codec = *g_Hashers[codecIndex]; + switch (propID) + { + case NMethodPropID::kID: + value->uhVal.QuadPart = (UInt64)codec.Id; + value->vt = VT_UI8; + break; + case NMethodPropID::kName: + if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0) + value->vt = VT_BSTR; + break; + case NMethodPropID::kEncoder: + if (codec.CreateHasher) + return SetClassID(codec.Id, kHasherId, value); + break; + case NMethodPropID::kDigestSize: + value->ulVal = (ULONG)codec.DigestSize; + value->vt = VT_UI4; + break; + } + return S_OK; +} + +class CHashers: + public IHashers, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP1(IHashers) + + STDMETHOD_(UInt32, GetNumHashers)(); + STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value); + STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher); +}; + +STDAPI GetHashers(IHashers **hashers) +{ + COM_TRY_BEGIN + *hashers = new CHashers; + if (*hashers) + (*hashers)->AddRef(); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP_(UInt32) CHashers::GetNumHashers() +{ + return g_NumHashers; +} + +STDMETHODIMP CHashers::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + return ::GetHasherProp(index, propID, value); +} + +STDMETHODIMP CHashers::CreateHasher(UInt32 index, IHasher **hasher) +{ + return ::CreateHasher2(index, hasher); +} diff --git a/CPP/7zip/Compress/CopyCoder.cpp b/CPP/7zip/Compress/CopyCoder.cpp old mode 100755 new mode 100644 index f71692a7..f0863202 --- a/CPP/7zip/Compress/CopyCoder.cpp +++ b/CPP/7zip/Compress/CopyCoder.cpp @@ -22,10 +22,10 @@ STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { - if (_buffer == 0) + if (!_buffer) { _buffer = (Byte *)::MidAlloc(kBufferSize); - if (_buffer == 0) + if (!_buffer) return E_OUTOFMEMORY; } @@ -33,9 +33,8 @@ STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream, for (;;) { UInt32 size = kBufferSize; - if (outSize != 0) - if (size > *outSize - TotalSize) - size = (UInt32)(*outSize - TotalSize); + if (outSize && size > *outSize - TotalSize) + size = (UInt32)(*outSize - TotalSize); RINOK(inStream->Read(_buffer, size, &size)); if (size == 0) break; @@ -44,7 +43,7 @@ STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream, RINOK(WriteStream(outStream, _buffer, size)); } TotalSize += size; - if (progress != NULL) + if (progress) { RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize)); } @@ -60,8 +59,16 @@ STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value) HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress) { - CMyComPtr copyCoder = new NCompress::CCopyCoder; + CMyComPtr copyCoder = new CCopyCoder; return copyCoder->Code(inStream, outStream, NULL, NULL, progress); } +HRESULT CopyStream_ExactSize(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 size, ICompressProgressInfo *progress) +{ + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; + CMyComPtr copyCoder = copyCoderSpec; + RINOK(copyCoder->Code(inStream, outStream, NULL, &size, progress)); + return copyCoderSpec->TotalSize == size ? S_OK : E_FAIL; +} + } diff --git a/CPP/7zip/Compress/CopyCoder.h b/CPP/7zip/Compress/CopyCoder.h old mode 100755 new mode 100644 index c5445ccf..5e0bb643 --- a/CPP/7zip/Compress/CopyCoder.h +++ b/CPP/7zip/Compress/CopyCoder.h @@ -28,6 +28,7 @@ public: }; HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress); +HRESULT CopyStream_ExactSize(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 size, ICompressProgressInfo *progress); } diff --git a/CPP/7zip/Compress/CopyRegister.cpp b/CPP/7zip/Compress/CopyRegister.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/Deflate64Register.cpp b/CPP/7zip/Compress/Deflate64Register.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/DeflateConst.h b/CPP/7zip/Compress/DeflateConst.h old mode 100755 new mode 100644 index 00e5ab8b..c3ae5719 --- a/CPP/7zip/Compress/DeflateConst.h +++ b/CPP/7zip/Compress/DeflateConst.h @@ -48,7 +48,7 @@ const Byte kLenDirectBits32[kFixedLenTableSize] = 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] = +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] = @@ -106,24 +106,21 @@ struct CLevels void SubClear() { UInt32 i; - for(i = kNumLitLenCodesMin; i < kFixedMainTableSize; i++) + for (i = kNumLitLenCodesMin; i < kFixedMainTableSize; i++) litLenLevels[i] = 0; - for(i = 0; i < kFixedDistTableSize; i++) + for (i = 0; i < kFixedDistTableSize; i++) distLevels[i] = 0; } void SetFixedLevels() { - int i; + int i = 0; + + for (; 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 < 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; } diff --git a/CPP/7zip/Compress/DeflateDecoder.cpp b/CPP/7zip/Compress/DeflateDecoder.cpp old mode 100755 new mode 100644 index 2848cd81..5285e143 --- a/CPP/7zip/Compress/DeflateDecoder.cpp +++ b/CPP/7zip/Compress/DeflateDecoder.cpp @@ -8,24 +8,27 @@ 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), + _needFinishInput(false), _needInitInStream(true), ZlibMode(false) {} -UInt32 CCoder::ReadBits(int numBits) +UInt32 CCoder::ReadBits(unsigned numBits) { return m_InBitStream.ReadBits(numBits); } -bool CCoder::DeCodeLevelTable(Byte *values, int numSymbols) +Byte CCoder::ReadAlignedByte() +{ + return m_InBitStream.ReadAlignedByte(); +} + +bool CCoder::DeCodeLevelTable(Byte *values, unsigned numSymbols) { - int i = 0; + unsigned i = 0; do { UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream); @@ -37,25 +40,25 @@ bool CCoder::DeCodeLevelTable(Byte *values, int numSymbols) { if (i == 0) return false; - int num = ReadBits(2) + 3; + unsigned num = ReadBits(2) + 3; for (; num > 0 && i < numSymbols; num--, i++) values[i] = values[i - 1]; } else { - int num; + unsigned num; if (number == kTableLevel0Number) num = ReadBits(3) + 3; else num = ReadBits(7) + 11; - for (;num > 0 && i < numSymbols; num--) + for (; num > 0 && i < numSymbols; num--) values[i++] = 0; } } else return false; } - while(i < numSymbols); + while (i < numSymbols); return true; } @@ -64,18 +67,22 @@ bool CCoder::DeCodeLevelTable(Byte *values, int numSymbols) bool CCoder::ReadTables(void) { m_FinalBlock = (ReadBits(kFinalBlockFieldSize) == NFinalBlockField::kFinalBlock); + if (m_InBitStream.ExtraBitsWereRead()) + return false; UInt32 blockType = ReadBits(kBlockTypeFieldSize); if (blockType > NBlockType::kDynamicHuffman) return false; + if (m_InBitStream.ExtraBitsWereRead()) + return false; if (blockType == NBlockType::kStored) { m_StoredMode = true; m_InBitStream.AlignToByte(); - m_StoredBlockSize = ReadBits(kStoredBlockLengthFieldSize); + m_StoredBlockSize = ReadAligned_UInt16(); // ReadBits(kStoredBlockLengthFieldSize) if (_deflateNSIS) return true; - return (m_StoredBlockSize == (UInt16)~ReadBits(kStoredBlockLengthFieldSize)); + return (m_StoredBlockSize == (UInt16)~ReadAligned_UInt16()); } m_StoredMode = false; @@ -88,29 +95,35 @@ bool CCoder::ReadTables(void) } else { - int numLitLenLevels = ReadBits(kNumLenCodesFieldSize) + kNumLitLenCodesMin; + unsigned numLitLenLevels = ReadBits(kNumLenCodesFieldSize) + kNumLitLenCodesMin; _numDistLevels = ReadBits(kNumDistCodesFieldSize) + kNumDistCodesMin; - int numLevelCodes = ReadBits(kNumLevelCodesFieldSize) + kNumLevelCodesMin; + unsigned numLevelCodes = ReadBits(kNumLevelCodesFieldSize) + kNumLevelCodesMin; if (!_deflate64Mode) if (_numDistLevels > kDistTableSize32) return false; Byte levelLevels[kLevelTableSize]; - for (int i = 0; i < kLevelTableSize; i++) + for (unsigned i = 0; i < kLevelTableSize; i++) { int position = kCodeLengthAlphabetOrder[i]; - if(i < numLevelCodes) + if (i < numLevelCodes) levelLevels[position] = (Byte)ReadBits(kLevelFieldSize); else levelLevels[position] = 0; } + if (m_InBitStream.ExtraBitsWereRead()) + return false; + RIF(m_LevelDecoder.SetCodeLengths(levelLevels)); Byte tmpLevels[kFixedMainTableSize + kFixedDistTableSize]; if (!DeCodeLevelTable(tmpLevels, numLitLenLevels + _numDistLevels)) return false; + + if (m_InBitStream.ExtraBitsWereRead()) + return false; levels.SubClear(); memcpy(levels.litLenLevels, tmpLevels, numLitLenLevels); @@ -120,7 +133,7 @@ bool CCoder::ReadTables(void) return m_DistDecoder.SetCodeLengths(levels.distLevels); } -HRESULT CCoder::CodeSpec(UInt32 curSize) +HRESULT CCoder::CodeSpec(UInt32 curSize, bool finishInputStream) { if (_remainLen == kLenIdFinished) return S_OK; @@ -136,10 +149,7 @@ HRESULT CCoder::CodeSpec(UInt32 curSize) _needReadTable = true; } - if (curSize == 0) - return S_OK; - - while(_remainLen > 0 && curSize > 0) + while (_remainLen > 0 && curSize > 0) { _remainLen--; Byte b = m_OutWindowStream.GetByte(_rep0); @@ -147,8 +157,10 @@ HRESULT CCoder::CodeSpec(UInt32 curSize) curSize--; } - while(curSize > 0) + while (curSize > 0 || finishInputStream) { + if (m_InBitStream.ExtraBitsWereRead()) + return S_FALSE; if (_needReadTable) { if (m_FinalBlock) @@ -158,19 +170,28 @@ HRESULT CCoder::CodeSpec(UInt32 curSize) } if (!ReadTables()) return S_FALSE; + if (m_InBitStream.ExtraBitsWereRead()) + return S_FALSE; _needReadTable = false; } - if(m_StoredMode) + if (m_StoredMode) { + if (finishInputStream && curSize == 0 && m_StoredBlockSize != 0) + return S_FALSE; + /* NSIS version contains some bits in bitl bits buffer. + So we must read some first bytes via ReadAlignedByte */ + for (; m_StoredBlockSize > 0 && curSize > 0 && m_InBitStream.ThereAreDataInBitsBuffer(); m_StoredBlockSize--, curSize--) + m_OutWindowStream.PutByte(ReadAlignedByte()); for (; m_StoredBlockSize > 0 && curSize > 0; m_StoredBlockSize--, curSize--) - m_OutWindowStream.PutByte(m_InBitStream.ReadByte()); + m_OutWindowStream.PutByte(m_InBitStream.ReadDirectByte()); _needReadTable = (m_StoredBlockSize == 0); continue; } - while(curSize > 0) + + while (curSize > 0) { - if (m_InBitStream.NumExtraBytes > 4) + if (m_InBitStream.ExtraBitsWereRead_Fast()) return S_FALSE; UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream); @@ -190,7 +211,7 @@ HRESULT CCoder::CodeSpec(UInt32 curSize) number -= kSymbolMatch; UInt32 len; { - int numBits; + unsigned numBits; if (_deflate64Mode) { len = kLenStart64[number]; @@ -224,28 +245,40 @@ HRESULT CCoder::CodeSpec(UInt32 curSize) else return S_FALSE; } + + if (finishInputStream && curSize == 0) + { + if (m_MainDecoder.DecodeSymbol(&m_InBitStream) != kSymbolEndOfBlock) + return S_FALSE; + _needReadTable = true; + } } + + if (m_InBitStream.ExtraBitsWereRead()) + return S_FALSE; + return S_OK; } #ifdef _NO_EXCEPTIONS #define DEFLATE_TRY_BEGIN -#define DEFLATE_TRY_END +#define DEFLATE_TRY_END(res) #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; } +#define DEFLATE_TRY_END(res) } \ + catch(const CInBufferException &e) { res = e.ErrorCode; } \ + catch(const CLzOutWindowException &e) { res = e.ErrorCode; } \ + catch(...) { res = S_FALSE; } #endif HRESULT CCoder::CodeReal(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress) { + HRESULT res; DEFLATE_TRY_BEGIN m_OutWindowStream.SetStream(outStream); CCoderReleaser flusher(this); @@ -255,18 +288,23 @@ HRESULT CCoder::CodeReal(ISequentialOutStream *outStream, for (;;) { UInt32 curSize = 1 << 18; - if (outSize != 0) + bool finishInputStream = false; + if (outSize) { const UInt64 rem = *outSize - (m_OutWindowStream.GetProcessedSize() - start); - if (curSize > rem) + if (curSize >= rem) + { curSize = (UInt32)rem; + if (ZlibMode || _needFinishInput) + finishInputStream = true; + } } if (curSize == 0) break; - RINOK(CodeSpec(curSize)); + RINOK(CodeSpec(curSize, finishInputStream)); if (_remainLen == kLenIdFinished) break; - if (progress != NULL) + if (progress) { const UInt64 inSize = m_InBitStream.GetProcessedSize() - inStart; const UInt64 nowPos64 = m_OutWindowStream.GetProcessedSize() - start; @@ -277,14 +315,14 @@ HRESULT CCoder::CodeReal(ISequentialOutStream *outStream, { m_InBitStream.AlignToByte(); for (int i = 0; i < 4; i++) - ZlibFooter[i] = m_InBitStream.ReadByte(); + ZlibFooter[i] = ReadAlignedByte(); } flusher.NeedFlush = false; - HRESULT res = Flush(); + res = Flush(); if (res == S_OK && InputEofError()) return S_FALSE; + DEFLATE_TRY_END(res) return res; - DEFLATE_TRY_END } HRESULT CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, @@ -307,13 +345,14 @@ STDMETHODIMP CCoder::GetInStreamProcessedSize(UInt64 *value) STDMETHODIMP CCoder::SetInStream(ISequentialInStream *inStream) { + m_InStreamRef = inStream; m_InBitStream.SetStream(inStream); return S_OK; } STDMETHODIMP CCoder::ReleaseInStream() { - m_InBitStream.ReleaseStream(); + m_InStreamRef.Release(); return S_OK; } @@ -329,16 +368,22 @@ STDMETHODIMP CCoder::SetOutStreamSize(const UInt64 * /* outSize */) STDMETHODIMP CCoder::Read(void *data, UInt32 size, UInt32 *processedSize) { + HRESULT res; 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 + res = CodeSpec(size, false); + if (res == S_OK) + { + res = Flush(); + if (processedSize) + *processedSize = (UInt32)(m_OutWindowStream.GetProcessedSize() - startPos); + } + DEFLATE_TRY_END(res) + m_OutWindowStream.SetMemStream(NULL); + return res; } #endif diff --git a/CPP/7zip/Compress/DeflateDecoder.h b/CPP/7zip/Compress/DeflateDecoder.h old mode 100755 new mode 100644 index 56ab2bea..856a5771 --- a/CPP/7zip/Compress/DeflateDecoder.h +++ b/CPP/7zip/Compress/DeflateDecoder.h @@ -18,6 +18,9 @@ namespace NCompress { namespace NDeflate { namespace NDecoder { +const int kLenIdFinished = -1; +const int kLenIdNeedInit = -2; + class CCoder: public ICompressCoder, public ICompressGetInStreamProcessedSize, @@ -29,6 +32,7 @@ class CCoder: public CMyUnknownImp { CLzOutWindow m_OutWindowStream; + CMyComPtr m_InStreamRef; NBitl::CDecoder m_InBitStream; NCompress::NHuffman::CDecoder m_MainDecoder; NCompress::NHuffman::CDecoder m_DistDecoder; @@ -36,22 +40,23 @@ class CCoder: UInt32 m_StoredBlockSize; + UInt32 _numDistLevels; bool m_FinalBlock; bool m_StoredMode; - UInt32 _numDistLevels; - bool _deflateNSIS; bool _deflate64Mode; bool _keepHistory; + bool _needFinishInput; + bool _needInitInStream; + bool _needReadTable; Int32 _remainLen; UInt32 _rep0; - bool _needReadTable; - UInt32 ReadBits(int numBits); + UInt32 ReadBits(unsigned numBits); - bool DeCodeLevelTable(Byte *values, int numSymbols); + bool DeCodeLevelTable(Byte *values, unsigned numSymbols); bool ReadTables(); HRESULT Flush() { return m_OutWindowStream.Flush(); } @@ -65,12 +70,11 @@ class CCoder: { if (NeedFlush) _coder->Flush(); - _coder->ReleaseOutStream(); } }; friend class CCoderReleaser; - HRESULT CodeSpec(UInt32 curSize); + HRESULT CodeSpec(UInt32 curSize, bool finishInputStream); public: bool ZlibMode; Byte ZlibFooter[4]; @@ -78,12 +82,11 @@ public: CCoder(bool deflate64Mode, bool deflateNSIS = false); virtual ~CCoder() {}; - void SetKeepHistory(bool keepHistory) { _keepHistory = keepHistory; } + void Set_KeepHistory(bool keepHistory) { _keepHistory = keepHistory; } + void Set_NeedFinishInput(bool needFinishInput) { _needFinishInput = needFinishInput; } - void ReleaseOutStream() - { - m_OutWindowStream.ReleaseStream(); - } + bool IsFinished() const { return _remainLen == kLenIdFinished;; } + bool IsFinalBlock() const { return m_FinalBlock; } HRESULT CodeReal(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress); @@ -126,31 +129,24 @@ public: } void AlignToByte() { m_InBitStream.AlignToByte(); } - Byte ReadByte() { return (Byte)m_InBitStream.ReadBits(8); } + Byte ReadAlignedByte(); + UInt32 ReadAligned_UInt16() // aligned for Byte range + { + UInt32 v = m_InBitStream.ReadAlignedByte(); + return v | ((UInt32)m_InBitStream.ReadAlignedByte() << 8); + } bool InputEofError() const { return m_InBitStream.ExtraBitsWereRead(); } + + UInt64 GetStreamSize() const { return m_InBitStream.GetStreamSize(); } 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) {} -}; +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) {} }; }}} diff --git a/CPP/7zip/Compress/DeflateEncoder.cpp b/CPP/7zip/Compress/DeflateEncoder.cpp old mode 100755 new mode 100644 index 813b6de4..392ee93d --- a/CPP/7zip/Compress/DeflateEncoder.cpp +++ b/CPP/7zip/Compress/DeflateEncoder.cpp @@ -5,7 +5,7 @@ #include "../../../C/Alloc.h" #include "../../../C/HuffEnc.h" -#include "Common/ComTry.h" +#include "../../Common/ComTry.h" #include "DeflateEncoder.h" @@ -50,11 +50,11 @@ public: CFastPosInit() { int i; - for(i = 0; i < kNumLenSlots; i++) + for (i = 0; i < kNumLenSlots; i++) { int c = kLenStart32[i]; int j = 1 << kLenDirectBits32[i]; - for(int k = 0; k < j; k++, c++) + for (int k = 0; k < j; k++, c++) g_LenSlots[c] = (Byte)i; } @@ -147,7 +147,7 @@ CCoder::CCoder(bool deflate64Mode): HRESULT CCoder::Create() { - COM_TRY_BEGIN + // COM_TRY_BEGIN if (m_Values == 0) { m_Values = (CCodeValue *)MyAlloc((kMaxUncompressedBlockSize) * sizeof(CCodeValue)); @@ -197,7 +197,7 @@ HRESULT CCoder::Create() _lzInWindow.cutValue = m_MatchFinderCycles; m_Created = true; return S_OK; - COM_TRY_END + // COM_TRY_END } HRESULT CCoder::BaseSetEncoderProperties2(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps) @@ -264,7 +264,7 @@ NO_INLINE void CCoder::GetMatches() if (numPairs > 0) { UInt32 i; - for(i = 0; i < numPairs; i += 2) + for (i = 0; i < numPairs; i += 2) { m_MatchDistances[i + 1] = (UInt16)distanceTmp[i]; m_MatchDistances[i + 2] = (UInt16)distanceTmp[i + 1]; @@ -316,7 +316,7 @@ NO_INLINE UInt32 CCoder::Backward(UInt32 &backRes, UInt32 cur) m_Optimum[posPrev].PosPrev = (UInt16)cur; cur = posPrev; } - while(cur > 0); + while (cur > 0); backRes = m_Optimum[0].BackPrev; m_OptimumCurrentIndex = m_Optimum[0].PosPrev; return m_OptimumCurrentIndex; @@ -324,7 +324,7 @@ NO_INLINE UInt32 CCoder::Backward(UInt32 &backRes, UInt32 cur) NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes) { - if(m_OptimumEndIndex != m_OptimumCurrentIndex) + if (m_OptimumEndIndex != m_OptimumCurrentIndex) { UInt32 len = m_Optimum[m_OptimumCurrentIndex].PosPrev - m_OptimumCurrentIndex; backRes = m_Optimum[m_OptimumCurrentIndex].BackPrev; @@ -336,13 +336,13 @@ NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes) GetMatches(); UInt32 numDistancePairs = m_MatchDistances[0]; - if(numDistancePairs == 0) + if (numDistancePairs == 0) return 1; const UInt16 *matchDistances = m_MatchDistances + 1; UInt32 lenMain = matchDistances[numDistancePairs - 2]; - if(lenMain > m_NumFastBytes) + if (lenMain > m_NumFastBytes) { backRes = matchDistances[numDistancePairs - 1]; MovePos(lenMain - 1); @@ -356,7 +356,7 @@ NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes) UInt32 offs = 0; - for(UInt32 i = kMatchMinLen; i <= lenMain; i++) + for (UInt32 i = kMatchMinLen; i <= lenMain; i++) { UInt32 distance = matchDistances[offs + 1]; m_Optimum[i].PosPrev = 0; @@ -371,17 +371,17 @@ NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes) for (;;) { ++cur; - if(cur == lenEnd || cur == kNumOptsBase || m_Pos >= kMatchArrayLimit) + 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) + if (numDistancePairs != 0) { newLen = matchDistances[numDistancePairs - 2]; - if(newLen > m_NumFastBytes) + if (newLen > m_NumFastBytes) { UInt32 len = Backward(backRes, cur); m_Optimum[cur].BackPrev = matchDistances[numDistancePairs - 1]; @@ -399,14 +399,14 @@ NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes) optimum.Price = curAnd1Price; optimum.PosPrev = (UInt16)cur; } - if(numDistancePairs == 0) + if (numDistancePairs == 0) continue; - while(lenEnd < cur + newLen) + 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++) + for (UInt32 lenTest = kMatchMinLen; ; lenTest++) { UInt32 curAndLenPrice = curPrice + m_LenPrices[lenTest - kMatchMinLen]; COptimal &optimum = m_Optimum[cur + lenTest]; @@ -444,12 +444,12 @@ UInt32 CCoder::GetOptimalFast(UInt32 &backRes) void CTables::InitStructures() { UInt32 i; - for(i = 0; i < 256; i++) + for (i = 0; i < 256; i++) litLenLevels[i] = 8; litLenLevels[i++] = 13; - for(;i < kFixedMainTableSize; i++) + for (;i < kFixedMainTableSize; i++) litLenLevels[i] = 5; - for(i = 0; i < kFixedDistTableSize; i++) + for (i = 0; i < kFixedDistTableSize; i++) distLevels[i] = 5; } @@ -539,7 +539,7 @@ NO_INLINE void CCoder::LevelTableCode(const Byte *levels, int numLevels, const B continue; if (count < minCount) - for(int i = 0; i < count; i++) + for (int i = 0; i < count; i++) WRITE_HF(curLen); else if (curLen != 0) { @@ -662,20 +662,20 @@ NO_INLINE void CCoder::SetPrices(const CLevels &levels) if (_fastMode) return; UInt32 i; - for(i = 0; i < 256; 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++) + 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++) + for (i = 0; i < kDistTableSize64; i++) { Byte price = levels.distLevels[i]; m_PosPrices[i] = (Byte)(((price != 0) ? price: kNoPosStatPrice) + kDistDirectBits[i]); @@ -731,7 +731,7 @@ static UInt32 GetStorePrice(UInt32 blockSize, int bitPosition) bitPosition = 0; blockSize -= curBlockSize; } - while(blockSize != 0); + while (blockSize != 0); return price; } @@ -747,11 +747,11 @@ void CCoder::WriteStoreBlock(UInt32 blockSize, UInt32 additionalOffset, bool fin WriteBits((UInt16)curBlockSize, kStoredBlockLengthFieldSize); WriteBits((UInt16)~curBlockSize, kStoredBlockLengthFieldSize); const Byte *data = Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow)- additionalOffset; - for(UInt32 i = 0; i < curBlockSize; i++) + for (UInt32 i = 0; i < curBlockSize; i++) m_OutStream.WriteByte(data[i]); additionalOffset -= curBlockSize; } - while(blockSize != 0); + while (blockSize != 0); } NO_INLINE UInt32 CCoder::TryDynBlock(int tableIndex, UInt32 numPasses) @@ -776,11 +776,11 @@ NO_INLINE UInt32 CCoder::TryDynBlock(int tableIndex, UInt32 numPasses) (CLevels &)t = m_NewLevels; m_NumLitLenLevels = kMainTableSize; - while(m_NumLitLenLevels > kNumLitLenCodesMin && m_NewLevels.litLenLevels[m_NumLitLenLevels - 1] == 0) + 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) + while (m_NumDistLevels > kNumDistCodesMin && m_NewLevels.distLevels[m_NumDistLevels - 1] == 0) m_NumDistLevels--; UInt32 levelFreqs[kLevelTableSize]; @@ -947,8 +947,6 @@ HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *ou m_OutStream.SetStream(outStream); m_OutStream.Init(); - CCoderReleaser coderReleaser(this); - m_OptimumEndIndex = m_OptimumCurrentIndex = 0; CTables &t = m_Tables[1]; diff --git a/CPP/7zip/Compress/DeflateEncoder.h b/CPP/7zip/Compress/DeflateEncoder.h old mode 100755 new mode 100644 index f25d802e..d8e88f89 --- a/CPP/7zip/Compress/DeflateEncoder.h +++ b/CPP/7zip/Compress/DeflateEncoder.h @@ -5,7 +5,7 @@ #include "../../../C/LzFind.h" -#include "Common/MyCom.h" +#include "../../Common/MyCom.h" #include "../ICoder.h" @@ -49,7 +49,7 @@ struct CTables: public CLevels typedef struct _CSeqInStream { ISeqInStream SeqInStream; - CMyComPtr RealStream; + ISequentialInStream *RealStream; } CSeqInStream; struct CEncProps @@ -165,20 +165,6 @@ public: 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); diff --git a/CPP/7zip/Compress/DeflateRegister.cpp b/CPP/7zip/Compress/DeflateRegister.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/DeltaFilter.cpp b/CPP/7zip/Compress/DeltaFilter.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/DllExports.cpp b/CPP/7zip/Compress/DllExports.cpp deleted file mode 100755 index 6af7e5ec..00000000 --- a/CPP/7zip/Compress/DllExports.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// 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 deleted file mode 100755 index 286ef08b..00000000 --- a/CPP/7zip/Compress/DllExports2.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// DllExports.cpp - -#include "StdAfx.h" - -#include "../../Common/MyInitGuid.h" - -#include "../ICoder.h" - -#include "../Common/RegisterCodec.h" - -extern "C" -BOOL WINAPI DllMain( - #ifdef UNDER_CE - HANDLE - #else - HINSTANCE - #endif - /* 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/DllExports2Compress.cpp b/CPP/7zip/Compress/DllExports2Compress.cpp new file mode 100644 index 00000000..286ef08b --- /dev/null +++ b/CPP/7zip/Compress/DllExports2Compress.cpp @@ -0,0 +1,33 @@ +// DllExports.cpp + +#include "StdAfx.h" + +#include "../../Common/MyInitGuid.h" + +#include "../ICoder.h" + +#include "../Common/RegisterCodec.h" + +extern "C" +BOOL WINAPI DllMain( + #ifdef UNDER_CE + HANDLE + #else + HINSTANCE + #endif + /* 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/DllExportsCompress.cpp b/CPP/7zip/Compress/DllExportsCompress.cpp new file mode 100644 index 00000000..8b37c899 --- /dev/null +++ b/CPP/7zip/Compress/DllExportsCompress.cpp @@ -0,0 +1,53 @@ +// DllExportsCompress.cpp + +#include "StdAfx.h" + +#include "../../Common/MyInitGuid.h" + +#include "../ICoder.h" + +#include "../Common/RegisterCodec.h" + +static const unsigned kNumCodecsMax = 48; +unsigned g_NumCodecs = 0; +const CCodecInfo *g_Codecs[kNumCodecsMax]; +void RegisterCodec(const CCodecInfo *codecInfo) +{ + if (g_NumCodecs < kNumCodecsMax) + g_Codecs[g_NumCodecs++] = codecInfo; +} + +static const unsigned kNumHashersMax = 16; +unsigned g_NumHashers = 0; +const CHasherInfo *g_Hashers[kNumHashersMax]; +void RegisterHasher(const CHasherInfo *hashInfo) throw() +{ + if (g_NumHashers < kNumHashersMax) + g_Hashers[g_NumHashers++] = hashInfo; +} + +#ifdef _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/HuffmanDecoder.h b/CPP/7zip/Compress/HuffmanDecoder.h old mode 100755 new mode 100644 index 82a1e6f2..21f96f0d --- a/CPP/7zip/Compress/HuffmanDecoder.h +++ b/CPP/7zip/Compress/HuffmanDecoder.h @@ -3,7 +3,7 @@ #ifndef __COMPRESS_HUFFMAN_DECODER_H #define __COMPRESS_HUFFMAN_DECODER_H -#include "../../Common/Types.h" +#include "../../Common/MyTypes.h" namespace NCompress { namespace NHuffman { @@ -25,7 +25,7 @@ public: int lenCounts[kNumBitsMax + 1]; UInt32 tmpPositions[kNumBitsMax + 1]; int i; - for(i = 1; i <= kNumBitsMax; i++) + for (i = 1; i <= kNumBitsMax; i++) lenCounts[i] = 0; UInt32 symbol; for (symbol = 0; symbol < m_NumSymbols; symbol++) @@ -49,7 +49,7 @@ public: 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) + if (i <= kNumTableBits) { UInt32 limit = (m_Limits[i] >> (kNumBitsMax - kNumTableBits)); for (; index < limit; index++) diff --git a/CPP/7zip/Compress/ImplodeDecoder.cpp b/CPP/7zip/Compress/ImplodeDecoder.cpp old mode 100755 new mode 100644 index f84a013c..e1d68a43 --- a/CPP/7zip/Compress/ImplodeDecoder.cpp +++ b/CPP/7zip/Compress/ImplodeDecoder.cpp @@ -1,9 +1,10 @@ -// Implode/Decoder.cpp +// ImplodeDecoder.cpp #include "StdAfx.h" +#include "../../Common/Defs.h" + #include "ImplodeDecoder.h" -#include "Common/Defs.h" namespace NCompress { namespace NImplode { @@ -67,11 +68,13 @@ CCoder::CCoder(): { } +/* void CCoder::ReleaseStreams() { m_OutWindowStream.ReleaseStream(); m_InBitStream.ReleaseStream(); } +*/ bool CCoder::ReadLevelItems(NImplode::NHuffman::CDecoder &decoder, Byte *levels, int numLevelItems) @@ -79,7 +82,7 @@ bool CCoder::ReadLevelItems(NImplode::NHuffman::CDecoder &decoder, int numCodedStructures = m_InBitStream.ReadBits(kNumBitsInByte) + kLevelStructuresNumberAdditionalValue; int currentIndex = 0; - for(int i = 0; i < numCodedStructures; i++) + for (int i = 0; i < numCodedStructures; i++) { int level = m_InBitStream.ReadBits(kNumLevelStructureLevelBits) + kLevelStructureLevelAdditionalValue; @@ -87,7 +90,7 @@ bool CCoder::ReadLevelItems(NImplode::NHuffman::CDecoder &decoder, kLevelStructureRepNumberAdditionalValue; if (currentIndex + rep > numLevelItems) throw CException(CException::kData); - for(int j = 0; j < rep; j++) + for (int j = 0; j < rep; j++) levels[currentIndex++] = (Byte)level; } if (currentIndex != numLevelItems) @@ -113,6 +116,7 @@ bool CCoder::ReadTables(void) return ReadLevelItems(m_DistanceDecoder, distanceLevels, kDistanceTableSize); } +/* class CCoderReleaser { CCoder *m_Coder; @@ -120,6 +124,7 @@ 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) @@ -136,19 +141,19 @@ HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *ou m_OutWindowStream.Init(false); m_InBitStream.SetStream(inStream); m_InBitStream.Init(); - CCoderReleaser coderReleaser(this); + // CCoderReleaser coderReleaser(this); if (!ReadTables()) return S_FALSE; - while(pos < unPackSize) + 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 + if (m_InBitStream.ReadBits(1) == kMatchId) // match { UInt32 lowDistBits = m_InBitStream.ReadBits(m_NumDistanceLowDirectBits); UInt32 distance = m_DistanceDecoder.DecodeSymbol(&m_InBitStream); @@ -159,9 +164,9 @@ HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *ou if (lengthSymbol >= kLengthTableSize) return S_FALSE; UInt32 length = lengthSymbol + m_MinMatchLength; - if (lengthSymbol == kLengthTableSize - 1) // special symbol = 63 + if (lengthSymbol == kLengthTableSize - 1) // special symbol = 63 length += m_InBitStream.ReadBits(kNumAdditionalLengthBits); - while(distance >= pos && length > 0) + while (distance >= pos && length > 0) { m_OutWindowStream.PutByte(0); pos++; diff --git a/CPP/7zip/Compress/ImplodeDecoder.h b/CPP/7zip/Compress/ImplodeDecoder.h old mode 100755 new mode 100644 index 7ea1553e..5876ecac --- a/CPP/7zip/Compress/ImplodeDecoder.h +++ b/CPP/7zip/Compress/ImplodeDecoder.h @@ -40,9 +40,8 @@ public: MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2) - void ReleaseStreams(); - HRESULT Flush() { return m_OutWindowStream.Flush(); } - + // void ReleaseStreams(); + HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); diff --git a/CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp b/CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp old mode 100755 new mode 100644 index 64345e08..2170326e --- a/CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp +++ b/CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp @@ -24,7 +24,7 @@ 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++) + for (i = 0; i <= kNumBitsInLongestCode; i++) lenCounts[i] = 0; UInt32 symbolIndex; for (symbolIndex = 0; symbolIndex < m_NumSymbols; symbolIndex++) @@ -34,7 +34,7 @@ bool CDecoder::SetCodeLengths(const Byte *codeLengths) // tmpPositions[0] = m_Positions[0] = m_Limitits[0] = 0; m_Limitits[kNumBitsInLongestCode + 1] = 0; m_Positions[kNumBitsInLongestCode + 1] = 0; - lenCounts[kNumBitsInLongestCode + 1] = 0; + lenCounts[kNumBitsInLongestCode + 1] = 0; UInt32 startPos = 0; @@ -68,7 +68,7 @@ UInt32 CDecoder::DecodeSymbol(CInBit *inStream) UInt32 numBits = 0; UInt32 value = inStream->GetValue(kNumBitsInLongestCode); int i; - for(i = kNumBitsInLongestCode; i > 0; i--) + for (i = kNumBitsInLongestCode; i > 0; i--) { if (value < m_Limitits[i]) { diff --git a/CPP/7zip/Compress/ImplodeHuffmanDecoder.h b/CPP/7zip/Compress/ImplodeHuffmanDecoder.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/LzOutWindow.cpp b/CPP/7zip/Compress/LzOutWindow.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/LzOutWindow.h b/CPP/7zip/Compress/LzOutWindow.h old mode 100755 new mode 100644 index d8d13c22..507aa7f4 --- a/CPP/7zip/Compress/LzOutWindow.h +++ b/CPP/7zip/Compress/LzOutWindow.h @@ -3,8 +3,6 @@ #ifndef __LZ_OUT_WINDOW_H #define __LZ_OUT_WINDOW_H -#include "../IStream.h" - #include "../Common/OutBuffer.h" #ifndef _NO_EXCEPTIONS @@ -14,7 +12,7 @@ typedef COutBufferException CLzOutWindowException; class CLzOutWindow: public COutBuffer { public: - void Init(bool solid = false); + void Init(bool solid = false) throw(); // distance >= 0, len > 0, bool CopyBlock(UInt32 distance, UInt32 len) @@ -22,34 +20,34 @@ public: UInt32 pos = _pos - distance - 1; if (distance >= _pos) { - if (!_overDict || distance >= _bufferSize) + if (!_overDict || distance >= _bufSize) return false; - pos += _bufferSize; + pos += _bufSize; } - if (_limitPos - _pos > len && _bufferSize - pos > len) + if (_limitPos - _pos > len && _bufSize - pos > len) { - const Byte *src = _buffer + pos; - Byte *dest = _buffer + _pos; + const Byte *src = _buf + pos; + Byte *dest = _buf + _pos; _pos += len; do *dest++ = *src++; - while(--len != 0); + while (--len != 0); } else do { - if (pos == _bufferSize) + if (pos == _bufSize) pos = 0; - _buffer[_pos++] = _buffer[pos++]; + _buf[_pos++] = _buf[pos++]; if (_pos == _limitPos) FlushWithCheck(); } - while(--len != 0); + while (--len != 0); return true; } void PutByte(Byte b) { - _buffer[_pos++] = b; + _buf[_pos++] = b; if (_pos == _limitPos) FlushWithCheck(); } @@ -57,9 +55,9 @@ public: Byte GetByte(UInt32 distance) const { UInt32 pos = _pos - distance - 1; - if (pos >= _bufferSize) - pos += _bufferSize; - return _buffer[pos]; + if (pos >= _bufSize) + pos += _bufSize; + return _buf[pos]; } }; diff --git a/CPP/7zip/Compress/LzhDecoder.cpp b/CPP/7zip/Compress/LzhDecoder.cpp old mode 100755 new mode 100644 index 6f9b5065..ad6e873a --- a/CPP/7zip/Compress/LzhDecoder.cpp +++ b/CPP/7zip/Compress/LzhDecoder.cpp @@ -4,8 +4,6 @@ #include "LzhDecoder.h" -#include "Windows/Defs.h" - namespace NCompress{ namespace NLzh { namespace NDecoder { @@ -16,7 +14,7 @@ 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); } +UInt32 CCoder::ReadBits(int numBits) { return m_InBitStream.ReadBits(numBits); } HRESULT CCoder::ReadLevelTable() { @@ -163,7 +161,7 @@ STDMETHODIMP CCoder::CodeReal(ISequentialInStream *inStream, UInt32 blockSize = 0; - while(pos < *outSize) + while (pos < *outSize) { // for (i = 0; i < dictSize; i++) dtext[i] = 0x20; @@ -191,7 +189,7 @@ STDMETHODIMP CCoder::CodeReal(ISequentialInStream *inStream, else { // offset = (interface->method == LARC_METHOD_NUM) ? 0x100 - 2 : 0x100 - 3; - UInt32 len = c - 256 + kMinMatch; + UInt32 len = c - 256 + kMinMatch; UInt32 distance = m_PHuffmanDecoder.Decode(&m_InBitStream); if (distance != 0) distance = (1 << (distance - 1)) + ReadBits(distance - 1); diff --git a/CPP/7zip/Compress/LzhDecoder.h b/CPP/7zip/Compress/LzhDecoder.h old mode 100755 new mode 100644 index ed631e20..a805f9f9 --- a/CPP/7zip/Compress/LzhDecoder.h +++ b/CPP/7zip/Compress/LzhDecoder.h @@ -56,11 +56,12 @@ class CCoder : CHuffmanDecoder m_PHuffmanDecoder; CHuffmanDecoder m_CHuffmanDecoder; + /* void ReleaseStreams() { m_OutWindowStream.ReleaseStream(); - m_InBitStream.ReleaseStream(); } + */ class CCoderReleaser { @@ -72,7 +73,7 @@ class CCoder : { if (NeedFlush) m_Coder->m_OutWindowStream.Flush(); - m_Coder->ReleaseStreams(); + // m_Coder->ReleaseStreams(); } }; friend class CCoderReleaser; diff --git a/CPP/7zip/Compress/Lzma2Decoder.cpp b/CPP/7zip/Compress/Lzma2Decoder.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/Lzma2Decoder.h b/CPP/7zip/Compress/Lzma2Decoder.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/Lzma2Encoder.cpp b/CPP/7zip/Compress/Lzma2Encoder.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/Lzma2Encoder.h b/CPP/7zip/Compress/Lzma2Encoder.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/Lzma2Register.cpp b/CPP/7zip/Compress/Lzma2Register.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/LzmaDecoder.cpp b/CPP/7zip/Compress/LzmaDecoder.cpp old mode 100755 new mode 100644 index b7c260bd..a7ee31ba --- a/CPP/7zip/Compress/LzmaDecoder.cpp +++ b/CPP/7zip/Compress/LzmaDecoder.cpp @@ -27,7 +27,8 @@ namespace NLzma { CDecoder::CDecoder(): _inBuf(0), _propsWereSet(false), _outSizeDefined(false), _inBufSize(1 << 20), _outBufSize(1 << 22), - FinishStream(false) + FinishStream(false), + NeedMoreInput(false) { _inSizeProcessed = 0; _inPos = _inSize = 0; @@ -81,6 +82,7 @@ STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { _inSizeProcessed = 0; _inPos = _inSize = 0; + NeedMoreInput = false; SetOutStreamSizeResume(outSize); return S_OK; } @@ -144,9 +146,21 @@ HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream * return S_FALSE; RINOK(res2); if (stopDecoding) + { + if (status == LZMA_STATUS_NEEDS_MORE_INPUT) + NeedMoreInput = true; + if (FinishStream && + status != LZMA_STATUS_FINISHED_WITH_MARK && + status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) + return S_FALSE; return S_OK; + } if (finished) + { + if (status == LZMA_STATUS_NEEDS_MORE_INPUT) + NeedMoreInput = true; return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE); + } } if (progress) { diff --git a/CPP/7zip/Compress/LzmaDecoder.h b/CPP/7zip/Compress/LzmaDecoder.h old mode 100755 new mode 100644 index d28a4634..754eaa3f --- a/CPP/7zip/Compress/LzmaDecoder.h +++ b/CPP/7zip/Compress/LzmaDecoder.h @@ -73,10 +73,14 @@ public: #endif - bool FinishStream; + bool FinishStream; // set it before decoding, if you need to decode full LZMA stream + + bool NeedMoreInput; // it's set by decoder, if it needs more input data to decode stream CDecoder(); virtual ~CDecoder(); + + UInt64 GetOutputProcessedSize() const { return _outSizeProcessed; } }; }} diff --git a/CPP/7zip/Compress/LzmaEncoder.cpp b/CPP/7zip/Compress/LzmaEncoder.cpp old mode 100755 new mode 100644 index 80e12f18..484d0452 --- a/CPP/7zip/Compress/LzmaEncoder.cpp +++ b/CPP/7zip/Compress/LzmaEncoder.cpp @@ -87,8 +87,8 @@ HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep) return S_OK; if (propID == NCoderPropID::kReduceSize) { - if (prop.vt == VT_UI8 && prop.uhVal.QuadPart < (UInt32)(Int32)-1) - ep.reduceSize = (UInt32)prop.uhVal.QuadPart; + if (prop.vt == VT_UI8) + ep.reduceSize = prop.uhVal.QuadPart; return S_OK; } if (prop.vt != VT_UI4) @@ -124,7 +124,7 @@ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, switch (propID) { case NCoderPropID::kEndMarker: - if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.boolVal == VARIANT_TRUE); break; + if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.boolVal != VARIANT_FALSE); break; default: RINOK(SetLzmaProp(propID, prop, props)); } @@ -148,6 +148,7 @@ STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream CCompressProgressWrap progressWrap(progress); SRes res = LzmaEnc_Encode(_encoder, &outWrap.p, &inWrap.p, progress ? &progressWrap.p : NULL, &g_Alloc, &g_BigAlloc); + _inputProcessed = inWrap.Processed; if (res == SZ_ERROR_READ && inWrap.Res != S_OK) return inWrap.Res; if (res == SZ_ERROR_WRITE && outWrap.Res != S_OK) @@ -156,5 +157,5 @@ STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream return progressWrap.Res; return SResToHRESULT(res); } - + }} diff --git a/CPP/7zip/Compress/LzmaEncoder.h b/CPP/7zip/Compress/LzmaEncoder.h old mode 100755 new mode 100644 index 904c0002..3ed067f1 --- a/CPP/7zip/Compress/LzmaEncoder.h +++ b/CPP/7zip/Compress/LzmaEncoder.h @@ -19,6 +19,7 @@ class CEncoder: public CMyUnknownImp { CLzmaEncHandle _encoder; + UInt64 _inputProcessed; public: MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties) @@ -29,6 +30,7 @@ public: CEncoder(); virtual ~CEncoder(); + UInt64 GetInputProcessedSize() const { return _inputProcessed; } }; }} diff --git a/CPP/7zip/Compress/LzmaRegister.cpp b/CPP/7zip/Compress/LzmaRegister.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/Lzx.h b/CPP/7zip/Compress/Lzx.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/Lzx86Converter.cpp b/CPP/7zip/Compress/Lzx86Converter.cpp old mode 100755 new mode 100644 index 9e53f18a..3a63057a --- a/CPP/7zip/Compress/Lzx86Converter.cpp +++ b/CPP/7zip/Compress/Lzx86Converter.cpp @@ -9,31 +9,31 @@ namespace NCompress { namespace NLzx { -static const int kResidue = 6 + 4; +static const UInt32 kResidue = 6 + 4; void Cx86ConvertOutStream::MakeTranslation() { - if (m_Pos <= kResidue) + if (_pos <= kResidue) return; - UInt32 numBytes = m_Pos - kResidue; - Byte *buffer = m_Buffer; + UInt32 numBytes = _pos - kResidue; + Byte *buf = _buf; for (UInt32 i = 0; i < numBytes;) { - if (buffer[i++] == 0xE8) + if (buf[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) + unsigned j; + for (j = 0; j < 4; j++) + absValue += (UInt32)buf[i + j] << (j * 8); + Int32 pos = (Int32)(_processedSize + i - 1); + if (absValue >= -pos && absValue < (Int32)_translationSize) { UInt32 offset = (absValue >= 0) ? absValue - pos : - absValue + m_TranslationSize; - for(j = 0; j < 4; j++) + absValue + _translationSize; + for (j = 0; j < 4; j++) { - buffer[i + j] = (Byte)(offset & 0xFF); + buf[i + j] = (Byte)(offset & 0xFF); offset >>= 8; } } @@ -44,46 +44,46 @@ void Cx86ConvertOutStream::MakeTranslation() STDMETHODIMP Cx86ConvertOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { - if (processedSize != NULL) + if (processedSize) *processedSize = 0; - if (!m_TranslationMode) - return m_Stream->Write(data, size, processedSize); + if (!_translationMode) + return _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; + UInt32 writeSize = MyMin(size - realProcessedSize, kUncompressedBlockSize - _pos); + memcpy(_buf + _pos, (const Byte *)data + realProcessedSize, writeSize); + _pos += writeSize; realProcessedSize += writeSize; - if (m_Pos == kUncompressedBlockSize) + if (_pos == kUncompressedBlockSize) { RINOK(Flush()); } } - if (processedSize != NULL) + if (processedSize) *processedSize = realProcessedSize; return S_OK; } HRESULT Cx86ConvertOutStream::Flush() { - if (m_Pos == 0) + if (_pos == 0) return S_OK; - if (m_TranslationMode) + if (_translationMode) MakeTranslation(); UInt32 pos = 0; do { UInt32 processed; - RINOK(m_Stream->Write(m_Buffer + pos, m_Pos - pos, &processed)); + RINOK(_stream->Write(_buf + pos, _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))); + while (pos < _pos); + _processedSize += _pos; + _pos = 0; + _translationMode = (_translationMode && (_processedSize < ((UInt32)1 << 30))); return S_OK; } diff --git a/CPP/7zip/Compress/Lzx86Converter.h b/CPP/7zip/Compress/Lzx86Converter.h old mode 100755 new mode 100644 index 9f110c29..1e531d1a --- a/CPP/7zip/Compress/Lzx86Converter.h +++ b/CPP/7zip/Compress/Lzx86Converter.h @@ -10,29 +10,28 @@ namespace NCompress { namespace NLzx { -const int kUncompressedBlockSize = 1 << 15; +const unsigned kUncompressedBlockSize = (unsigned)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]; + ISequentialOutStream *_stream; + UInt32 _processedSize; + UInt32 _pos; + UInt32 _translationSize; + bool _translationMode; + Byte _buf[kUncompressedBlockSize]; void MakeTranslation(); public: - void SetStream(ISequentialOutStream *outStream) { m_Stream = outStream; } - void ReleaseStream() { m_Stream.Release(); } + void SetStream(ISequentialOutStream *outStream) { _stream = outStream; } void Init(bool translationMode, UInt32 translationSize) { - m_TranslationMode = translationMode; - m_TranslationSize = translationSize; - m_ProcessedSize = 0; - m_Pos = 0; + _translationMode = translationMode; + _translationSize = translationSize; + _processedSize = 0; + _pos = 0; } HRESULT Flush(); diff --git a/CPP/7zip/Compress/LzxDecoder.cpp b/CPP/7zip/Compress/LzxDecoder.cpp old mode 100755 new mode 100644 index 924229e9..acf3b037 --- a/CPP/7zip/Compress/LzxDecoder.cpp +++ b/CPP/7zip/Compress/LzxDecoder.cpp @@ -20,12 +20,14 @@ CDecoder::CDecoder(bool wimMode): m_x86ConvertOutStream = m_x86ConvertOutStreamSpec; } +/* void CDecoder::ReleaseStreams() { m_OutWindowStream.ReleaseStream(); m_InBitStream.ReleaseStream(); m_x86ConvertOutStreamSpec->ReleaseStream(); } +*/ STDMETHODIMP CDecoder::Flush() { @@ -152,7 +154,7 @@ public: { if (NeedFlush) m_Decoder->Flush(); - m_Decoder->ReleaseStreams(); + // m_Decoder->ReleaseStreams(); } }; @@ -308,7 +310,8 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * return E_INVALIDARG; UInt64 size = *outSize; - RINOK(SetInStream(inStream)); + // RINOK(SetInStream(inStream)); + m_InBitStream.SetStream(inStream); m_x86ConvertOutStreamSpec->SetStream(outStream); m_OutWindowStream.SetStream(m_x86ConvertOutStream); RINOK(SetOutStreamSize(outSize)); @@ -344,17 +347,20 @@ HRESULT CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outS catch(...) { return S_FALSE; } } +/* STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { + m_InStreamRef = inStream; m_InBitStream.SetStream(inStream); return S_OK; } STDMETHODIMP CDecoder::ReleaseInStream() { - m_InBitStream.ReleaseStream(); + m_InStreamRef.Release(); return S_OK; } +*/ STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { diff --git a/CPP/7zip/Compress/LzxDecoder.h b/CPP/7zip/Compress/LzxDecoder.h old mode 100755 new mode 100644 index 73a05061..62d5b488 --- a/CPP/7zip/Compress/LzxDecoder.h +++ b/CPP/7zip/Compress/LzxDecoder.h @@ -23,45 +23,44 @@ const UInt32 kBitDecoderValueMask = (1 << kNumValueBits) - 1; class CDecoder { - CInBuffer m_Stream; - UInt32 m_Value; - unsigned m_BitPos; + CInBuffer _stream; + UInt32 _value; + unsigned _bitPos; public: CDecoder() {} - bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); } + bool Create(UInt32 bufSize) { return _stream.Create(bufSize); } - void SetStream(ISequentialInStream *s) { m_Stream.SetStream(s); } - void ReleaseStream() { m_Stream.ReleaseStream(); } + void SetStream(ISequentialInStream *s) { _stream.SetStream(s); } void Init() { - m_Stream.Init(); - m_BitPos = kNumBigValueBits; + _stream.Init(); + _bitPos = kNumBigValueBits; } - UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() - (kNumBigValueBits - m_BitPos) / 8; } + UInt64 GetProcessedSize() const { return _stream.GetProcessedSize() - ((kNumBigValueBits - _bitPos) >> 3); } - unsigned GetBitPosition() const { return m_BitPos & 0xF; } + unsigned GetBitPosition() const { return _bitPos & 0xF; } void Normalize() { - for (; m_BitPos >= 16; m_BitPos -= 16) + for (; _bitPos >= 16; _bitPos -= 16) { - Byte b0 = m_Stream.ReadByte(); - Byte b1 = m_Stream.ReadByte(); - m_Value = (m_Value << 8) | b1; - m_Value = (m_Value << 8) | b0; + Byte b0 = _stream.ReadByte(); + Byte b1 = _stream.ReadByte(); + _value = (_value << 8) | b1; + _value = (_value << 8) | b0; } } UInt32 GetValue(unsigned numBits) const { - return ((m_Value >> ((32 - kNumValueBits) - m_BitPos)) & kBitDecoderValueMask) >> (kNumValueBits - numBits); + return ((_value >> ((32 - kNumValueBits) - _bitPos)) & kBitDecoderValueMask) >> (kNumValueBits - numBits); } void MovePos(unsigned numBits) { - m_BitPos += numBits; + _bitPos += numBits; Normalize(); } @@ -82,14 +81,14 @@ public: bool ReadUInt32(UInt32 &v) { - if (m_BitPos != 0) + if (_bitPos != 0) return false; - v = ((m_Value >> 16) & 0xFFFF) | ((m_Value << 16) & 0xFFFF0000); - m_BitPos = kNumBigValueBits; + v = ((_value >> 16) & 0xFFFF) | ((_value << 16) & 0xFFFF0000); + _bitPos = kNumBigValueBits; return true; } - Byte DirectReadByte() { return m_Stream.ReadByte(); } + Byte DirectReadByte() { return _stream.ReadByte(); } }; } @@ -98,6 +97,7 @@ class CDecoder : public ICompressCoder, public CMyUnknownImp { + // CMyComPtr m_InStreamRef; NBitStream::CDecoder m_InBitStream; CLzOutWindow m_OutWindowStream; @@ -140,14 +140,14 @@ public: MY_UNKNOWN_IMP - void ReleaseStreams(); + // 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(SetInStream)(ISequentialInStream *inStream); + // STDMETHOD(ReleaseInStream)(); STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); HRESULT SetParams(unsigned numDictBits); diff --git a/CPP/7zip/Compress/Mtf8.h b/CPP/7zip/Compress/Mtf8.h old mode 100755 new mode 100644 index d15dd4a5..5d49fe44 --- a/CPP/7zip/Compress/Mtf8.h +++ b/CPP/7zip/Compress/Mtf8.h @@ -5,19 +5,17 @@ #include "../../../C/CpuArch.h" -#include "../../Common/Types.h" - namespace NCompress { struct CMtf8Encoder { Byte Buf[256]; - int FindAndMove(Byte v) + unsigned FindAndMove(Byte v) { - int pos; + unsigned pos; for (pos = 0; Buf[pos] != v; pos++); - int resPos = pos; + unsigned resPos = pos; for (; pos >= 8; pos -= 8) { Buf[pos] = Buf[pos - 1]; @@ -29,7 +27,7 @@ struct CMtf8Encoder Buf[pos - 6] = Buf[pos - 7]; Buf[pos - 7] = Buf[pos - 8]; } - for (; pos > 0; pos--) + for (; pos != 0; pos--) Buf[pos] = Buf[pos - 1]; Buf[0] = v; return resPos; @@ -81,9 +79,9 @@ 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)); } + void Add(unsigned 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) + Byte GetAndMove(unsigned pos) { UInt32 lim = ((UInt32)pos >> MTF_MOVS); pos = (pos & MTF_MASK) << 3; @@ -164,7 +162,7 @@ public: for (int t = Counts[g] - 1; t >= 0; t--, i--) Buf[i] = Buf[offset + t]; } - while(g != 0); + while (g != 0); for (i = kSmallSize - 1; i >= 0; i--) Buf[i] = SmallBuffer[i]; diff --git a/CPP/7zip/Compress/PpmdDecoder.cpp b/CPP/7zip/Compress/PpmdDecoder.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/PpmdDecoder.h b/CPP/7zip/Compress/PpmdDecoder.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/PpmdEncoder.cpp b/CPP/7zip/Compress/PpmdEncoder.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/PpmdEncoder.h b/CPP/7zip/Compress/PpmdEncoder.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/PpmdRegister.cpp b/CPP/7zip/Compress/PpmdRegister.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/PpmdZip.cpp b/CPP/7zip/Compress/PpmdZip.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/PpmdZip.h b/CPP/7zip/Compress/PpmdZip.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/QuantumDecoder.cpp b/CPP/7zip/Compress/QuantumDecoder.cpp old mode 100755 new mode 100644 index 63da32cc..b184dfb6 --- a/CPP/7zip/Compress/QuantumDecoder.cpp +++ b/CPP/7zip/Compress/QuantumDecoder.cpp @@ -70,7 +70,7 @@ HRESULT CDecoder::CodeSpec(UInt32 curSize) { lenSlot -= 2; int numDirectBits = (int)(lenSlot >> 2); - len += ((4 | (lenSlot & 3)) << numDirectBits) - 2; + len += ((4 | (lenSlot & 3)) << numDirectBits) - 2; if (numDirectBits < 6) len += _rangeDecoder.Stream.ReadBits(numDirectBits); } @@ -108,7 +108,9 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * return E_INVALIDARG; UInt64 size = *outSize; - SetInStream(inStream); + // SetInStream(inStream); + _rangeDecoder.SetStream(inStream); + _outWindowStream.SetStream(outStream); SetOutStreamSize(outSize); CDecoderFlusher flusher(this); @@ -143,17 +145,20 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream catch(...) { return S_FALSE; } } +/* STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { + m_InStreamRef = inStream; _rangeDecoder.SetStream(inStream); return S_OK; } STDMETHODIMP CDecoder::ReleaseInStream() { - _rangeDecoder.ReleaseStream(); + m_InStreamRef.Release(); return S_OK; } +*/ STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { diff --git a/CPP/7zip/Compress/QuantumDecoder.h b/CPP/7zip/Compress/QuantumDecoder.h old mode 100755 new mode 100644 index a5f78358..c18ea2aa --- a/CPP/7zip/Compress/QuantumDecoder.h +++ b/CPP/7zip/Compress/QuantumDecoder.h @@ -21,7 +21,7 @@ class CStreamBitDecoder public: bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } - void ReleaseStream() { Stream.ReleaseStream(); } + // void ReleaseStream() { Stream.ReleaseStream(); } void Finish() { Value = 0x10000; } @@ -71,7 +71,7 @@ public: CStreamBitDecoder Stream; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } - void ReleaseStream() { Stream.ReleaseStream(); } + // void ReleaseStream() { Stream.ReleaseStream(); } void Init() { @@ -196,11 +196,12 @@ public: class CDecoder: public ICompressCoder, - public ICompressSetInStream, - public ICompressSetOutStreamSize, + // public ICompressSetInStream, + // public ICompressSetOutStreamSize, public CMyUnknownImp { CLzOutWindow _outWindowStream; + // CMyComPtr m_InStreamRef; NRangeCoder::CDecoder _rangeDecoder; UInt64 _outSize; @@ -217,15 +218,19 @@ class CDecoder: void Init(); HRESULT CodeSpec(UInt32 size); public: + + MY_UNKNOWN_IMP + + /* MY_UNKNOWN_IMP2( ICompressSetInStream, ICompressSetOutStreamSize) - void ReleaseStreams() { _outWindowStream.ReleaseStream(); ReleaseInStream(); } + */ class CDecoderFlusher { @@ -237,11 +242,11 @@ public: { if (NeedFlush) _decoder->Flush(); - _decoder->ReleaseStreams(); + // _decoder->ReleaseStreams(); } }; - HRESULT Flush() { return _outWindowStream.Flush(); } + HRESULT Flush() { return _outWindowStream.Flush(); } HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); @@ -249,8 +254,8 @@ public: STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); - STDMETHOD(SetInStream)(ISequentialInStream *inStream); - STDMETHOD(ReleaseInStream)(); + // STDMETHOD(SetInStream)(ISequentialInStream *inStream); + // STDMETHOD(ReleaseInStream)(); STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); HRESULT SetParams(int numDictBits); diff --git a/CPP/7zip/Compress/RangeCoder.h b/CPP/7zip/Compress/RangeCoder.h old mode 100755 new mode 100644 index 1eb2a6d4..0b0d44ae --- a/CPP/7zip/Compress/RangeCoder.h +++ b/CPP/7zip/Compress/RangeCoder.h @@ -1,5 +1,5 @@ // Compress/RangeCoder.h -// 2009-05-30 : Igor Pavlov : Public domain +// 2013-01-10 : Igor Pavlov : Public domain #ifndef __COMPRESS_RANGE_CODER_H #define __COMPRESS_RANGE_CODER_H @@ -10,7 +10,7 @@ namespace NCompress { namespace NRangeCoder { -const int kNumTopBits = 24; +const unsigned kNumTopBits = 24; const UInt32 kTopValue = (1 << kNumTopBits); class CEncoder @@ -21,7 +21,7 @@ public: UInt64 Low; UInt32 Range; COutBuffer Stream; - bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } + bool Create(UInt32 bufSize) { return Stream.Create(bufSize); } void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); } void Init() @@ -36,14 +36,12 @@ public: void FlushData() { // Low += 1; - for(int i = 0; i < 5; i++) + 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); @@ -57,7 +55,7 @@ public: void ShiftLow() { - if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0) + if ((UInt32)Low < (UInt32)0xFF000000 || (unsigned)(Low >> 32) != 0) { Byte temp = _cache; do @@ -65,7 +63,7 @@ public: Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32))); temp = 0xFF; } - while(--_cacheSize != 0); + while (--_cacheSize != 0); _cache = (Byte)((UInt32)Low >> 24); } _cacheSize++; @@ -103,7 +101,7 @@ public: } } - UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; } + UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; } }; class CDecoder @@ -112,7 +110,7 @@ public: CInBuffer Stream; UInt32 Range; UInt32 Code; - bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } + bool Create(UInt32 bufSize) { return Stream.Create(bufSize); } void Normalize() { @@ -129,15 +127,13 @@ public: Stream.Init(); Code = 0; Range = 0xFFFFFFFF; - for(int i = 0; i < 5; i++) + for (int i = 0; i < 5; i++) Code = (Code << 8) | Stream.ReadByte(); } - void ReleaseStream() { Stream.ReleaseStream(); } - UInt32 GetThreshold(UInt32 total) { - return (Code) / ( Range /= total); + return (Code) / (Range /= total); } void Decode(UInt32 start, UInt32 size) @@ -197,7 +193,7 @@ public: return symbol; } - UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); } + UInt64 GetProcessedSize() { return Stream.GetProcessedSize(); } }; }} diff --git a/CPP/7zip/Compress/RangeCoderBit.h b/CPP/7zip/Compress/RangeCoderBit.h old mode 100755 new mode 100644 index b5a1830d..0eddd558 --- a/CPP/7zip/Compress/RangeCoderBit.h +++ b/CPP/7zip/Compress/RangeCoderBit.h @@ -1,5 +1,5 @@ // Compress/RangeCoderBit.h -// 2009-05-30 : Igor Pavlov : Public domain +// 2013-01-10 : Igor Pavlov : Public domain #ifndef __COMPRESS_RANGE_CODER_BIT_H #define __COMPRESS_RANGE_CODER_BIT_H @@ -9,17 +9,17 @@ namespace NCompress { namespace NRangeCoder { -const int kNumBitModelTotalBits = 11; +const unsigned kNumBitModelTotalBits = 11; const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits); -const int kNumMoveReducingBits = 4; +const unsigned kNumMoveReducingBits = 4; -const int kNumBitPriceShiftBits = 4; +const unsigned kNumBitPriceShiftBits = 4; const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits; extern UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; -template +template class CBitModel { public: @@ -39,7 +39,7 @@ public: void Init() { Prob = kBitModelTotal / 2; } }; -template +template class CBitEncoder: public CBitModel { public: @@ -69,14 +69,14 @@ public: } UInt32 GetPrice(UInt32 symbol) const { - return ProbPrices[(this->Prob ^ ((-(int)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; + return ProbPrices[(this->Prob ^ ((-(int)(Int32)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } UInt32 GetPrice0() const { return ProbPrices[this->Prob >> kNumMoveReducingBits]; } UInt32 GetPrice1() const { return ProbPrices[(this->Prob ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } }; -template +template class CBitDecoder: public CBitModel { public: diff --git a/CPP/7zip/Compress/Rar1Decoder.cpp b/CPP/7zip/Compress/Rar1Decoder.cpp old mode 100755 new mode 100644 index eadca7b3..8eb904df --- a/CPP/7zip/Compress/Rar1Decoder.cpp +++ b/CPP/7zip/Compress/Rar1Decoder.cpp @@ -19,6 +19,7 @@ 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; @@ -26,12 +27,13 @@ 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++) + for (int i = 0; i < kNumRepDists; i++) m_RepDists[i] = 0; m_RepDistPtr = 0; LastLength = 0; @@ -65,9 +67,9 @@ UInt32 CDecoder::DecodeNum(const UInt32 *posTab) return((num >> (12 - startPos)) + posTab[startPos]); } -static Byte kShortLen1[] = {1,3,4,4,5,6,7,8,8,4,4,5,6,6 }; +static Byte 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 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}; @@ -389,7 +391,7 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * m_InBitStream.SetStream(inStream); m_InBitStream.Init(); - CCoderReleaser coderReleaser(this); + // CCoderReleaser coderReleaser(this); InitData(); if (!m_IsSolid) { diff --git a/CPP/7zip/Compress/Rar1Decoder.h b/CPP/7zip/Compress/Rar1Decoder.h old mode 100755 new mode 100644 index f7c08b38..630f0893 --- a/CPP/7zip/Compress/Rar1Decoder.h +++ b/CPP/7zip/Compress/Rar1Decoder.h @@ -70,11 +70,13 @@ public: 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); diff --git a/CPP/7zip/Compress/Rar2Decoder.cpp b/CPP/7zip/Compress/Rar2Decoder.cpp old mode 100755 new mode 100644 index 4e669bd6..1773939c --- a/CPP/7zip/Compress/Rar2Decoder.cpp +++ b/CPP/7zip/Compress/Rar2Decoder.cpp @@ -85,7 +85,7 @@ CDecoder::CDecoder(): void CDecoder::InitStructures() { m_MmFilter.Init(); - for(int i = 0; i < kNumRepDists; i++) + for (int i = 0; i < kNumRepDists; i++) m_RepDists[i] = 0; m_RepDistPtr = 0; m_LastLength = 0; @@ -191,6 +191,7 @@ bool CDecoder::ReadLastTables() return true; } +/* class CCoderReleaser { CDecoder *m_Coder; @@ -201,6 +202,7 @@ public: m_Coder->ReleaseStreams(); } }; +*/ bool CDecoder::DecodeMm(UInt32 pos) { @@ -319,7 +321,7 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * m_InBitStream.SetStream(inStream); m_InBitStream.Init(); - CCoderReleaser coderReleaser(this); + // CCoderReleaser coderReleaser(this); if (!m_IsSolid) { InitStructures(); @@ -335,7 +337,7 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * } UInt64 startPos = m_OutWindowStream.GetProcessedSize(); - while(pos < unPackSize) + while (pos < unPackSize) { UInt32 blockSize = 1 << 20; if (blockSize > unPackSize - pos) diff --git a/CPP/7zip/Compress/Rar2Decoder.h b/CPP/7zip/Compress/Rar2Decoder.h old mode 100755 new mode 100644 index 61a8b4da..44b262c1 --- a/CPP/7zip/Compress/Rar2Decoder.h +++ b/CPP/7zip/Compress/Rar2Decoder.h @@ -53,10 +53,10 @@ 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 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 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}; @@ -156,11 +156,13 @@ public: 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); diff --git a/CPP/7zip/Compress/Rar3Decoder.cpp b/CPP/7zip/Compress/Rar3Decoder.cpp old mode 100755 new mode 100644 index dde7c6de..3c70e1c0 --- a/CPP/7zip/Compress/Rar3Decoder.cpp +++ b/CPP/7zip/Compress/Rar3Decoder.cpp @@ -25,7 +25,7 @@ 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 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] = @@ -153,7 +153,7 @@ HRESULT CDecoder::WriteBuf() { UInt32 writtenBorder = _wrPtr; UInt32 writeSize = (_winPos - writtenBorder) & kWindowMask; - for (int i = 0; i < _tempFilters.Size(); i++) + FOR_VECTOR (i, _tempFilters) { CTempFilter *filter = _tempFilters[i]; if (filter == NULL) @@ -202,7 +202,7 @@ HRESULT CDecoder::WriteBuf() } else { - for (int j = i; j < _tempFilters.Size(); j++) + for (unsigned j = i; j < _tempFilters.Size(); j++) { CTempFilter *filter = _tempFilters[j]; if (filter != NULL && filter->NextWindow) @@ -221,7 +221,7 @@ HRESULT CDecoder::WriteBuf() void CDecoder::InitFilters() { _lastFilter = 0; - int i; + unsigned i; for (i = 0; i < _tempFilters.Size(); i++) delete _tempFilters[i]; _tempFilters.Clear(); @@ -238,7 +238,7 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize) UInt32 filterIndex; if (firstByte & 0x80) { - filterIndex = NVm::ReadEncodedUInt32(inp); + filterIndex = inp.ReadEncodedUInt32(); if (filterIndex == 0) InitFilters(); else @@ -267,7 +267,7 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize) } int numEmptyItems = 0; - int i; + unsigned i; for (i = 0; i < _tempFilters.Size(); i++) { _tempFilters[i - numEmptyItems] = _tempFilters[i]; @@ -284,62 +284,56 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize) CTempFilter *tempFilter = new CTempFilter; _tempFilters[_tempFilters.Size() - numEmptyItems] = tempFilter; tempFilter->FilterIndex = filterIndex; - tempFilter->ExecCount = filter->ExecCount; - UInt32 blockStart = NVm::ReadEncodedUInt32(inp); + UInt32 blockStart = inp.ReadEncodedUInt32(); if (firstByte & 0x40) blockStart += 258; tempFilter->BlockStart = (blockStart + _winPos) & kWindowMask; if (firstByte & 0x20) - filter->BlockSize = NVm::ReadEncodedUInt32(inp); + filter->BlockSize = inp.ReadEncodedUInt32(); 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; + tempFilter->InitR[5] = filter->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); + tempFilter->InitR[i] = inp.ReadEncodedUInt32(); } if (newFilter) { - UInt32 vmCodeSize = NVm::ReadEncodedUInt32(inp); + UInt32 vmCodeSize = inp.ReadEncodedUInt32(); 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); + filter->PrepareProgram(_vmCode, vmCodeSize); } - 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); + NVm::SetValue32(&globalData[NVm::NGlobalOffset::kExecCount], filter->ExecCount); if (firstByte & 8) { - UInt32 dataSize = NVm::ReadEncodedUInt32(inp); + UInt32 dataSize = inp.ReadEncodedUInt32(); 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); - } + unsigned requiredSize = (unsigned)(dataSize + NVm::kFixedGlobalSize); + if (globalData.Size() < requiredSize) + globalData.ChangeSize_KeepData(requiredSize); + Byte *dest = &globalData[NVm::kFixedGlobalSize]; for (UInt32 i = 0; i < dataSize; i++) - globalData[NVm::kFixedGlobalSize + i] = (Byte)inp.ReadBits(8); + dest[i] = (Byte)inp.ReadBits(8); } return true; } @@ -384,6 +378,8 @@ bool CDecoder::ReadVmCodePPM() } if (length > kVmDataSizeMax) return false; + if (InputEofError_Fast()) + return false; for (UInt32 i = 0; i < length; i++) { int b = DecodePpmSymbol(); @@ -396,14 +392,13 @@ bool CDecoder::ReadVmCodePPM() #define RIF(x) { if (!(x)) return S_FALSE; } -UInt32 CDecoder::ReadBits(int numBits) { return m_InBitStream.bitDecoder.ReadBits(numBits); } +UInt32 CDecoder::ReadBits(int numBits) { return m_InBitStream.BitDecoder.ReadBits(numBits); } -///////////////////////////////////////////////// -// PPM +// ---------- PPM ---------- HRESULT CDecoder::InitPPM() { - Byte maxOrder = (Byte)ReadBits(7); + unsigned maxOrder = (unsigned)ReadBits(7); bool reset = ((maxOrder & 0x20) != 0); int maxMB = 0; @@ -458,6 +453,8 @@ HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing) return S_OK; } } + if (InputEofError_Fast()) + return false; int c = DecodePpmSymbol(); if (c < 0) { @@ -526,13 +523,12 @@ HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing) return S_OK; } -///////////////////////////////////////////////// -// LZ +// ---------- LZ ---------- HRESULT CDecoder::ReadTables(bool &keepDecompressing) { keepDecompressing = true; - ReadBits((8 - m_InBitStream.bitDecoder.GetBitPosition()) & 7); + m_InBitStream.BitDecoder.AlignToByte(); if (ReadBits(1) != 0) { _lzMode = false; @@ -571,7 +567,7 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing) i = 0; while (i < kTablesSizesSum) { - UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream.bitDecoder); + UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream.BitDecoder); if (number < 16) { newLevels[i] = Byte((number + m_LastLevels[i]) & 15); @@ -620,6 +616,7 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing) return S_OK; } +/* class CCoderReleaser { CDecoder *m_Coder; @@ -630,6 +627,7 @@ public: m_Coder->ReleaseStreams(); } }; +*/ HRESULT CDecoder::ReadEndOfBlock(bool &keepDecompressing) { @@ -680,7 +678,11 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing) return S_OK; } } - UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream.bitDecoder); + + if (InputEofError_Fast()) + return S_FALSE; + + UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream.BitDecoder); if (number < 256) { PutByte((Byte)number); @@ -724,10 +726,10 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing) rep0 = distance; } - UInt32 number = m_LenDecoder.DecodeSymbol(&m_InBitStream.bitDecoder); + UInt32 number = m_LenDecoder.DecodeSymbol(&m_InBitStream.BitDecoder); if (number >= kLenTableSize) return S_FALSE; - length = 2 + kLenStart[number] + m_InBitStream.bitDecoder.ReadBits(kLenDirectBits[number]); + length = 2 + kLenStart[number] + m_InBitStream.BitDecoder.ReadBits(kLenDirectBits[number]); } else { @@ -737,14 +739,14 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing) if (number < 271) { number -= 263; - rep0 = kLen2DistStarts[number] + m_InBitStream.bitDecoder.ReadBits(kLen2DistDirectBits[number]); + 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); + 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]; @@ -752,7 +754,7 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing) if (number >= (kNumAlignBits * 2) + 2) { if (numBits > kNumAlignBits) - rep0 += (m_InBitStream.bitDecoder.ReadBits(numBits - kNumAlignBits) << kNumAlignBits); + rep0 += (m_InBitStream.BitDecoder.ReadBits(numBits - kNumAlignBits) << kNumAlignBits); if (PrevAlignCount > 0) { PrevAlignCount--; @@ -760,13 +762,13 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing) } else { - UInt32 number = m_AlignDecoder.DecodeSymbol(&m_InBitStream.bitDecoder); + UInt32 number = m_AlignDecoder.DecodeSymbol(&m_InBitStream.BitDecoder); if (number < (1 << kNumAlignBits)) { rep0 += number; PrevAlignBits = number; } - else if (number == (1 << kNumAlignBits)) + else if (number == (1 << kNumAlignBits)) { PrevAlignCount = kNumAlignReps; rep0 += PrevAlignBits; @@ -776,7 +778,7 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing) } } else - rep0 += m_InBitStream.bitDecoder.ReadBits(numBits); + rep0 += m_InBitStream.BitDecoder.ReadBits(numBits); length += ((kDistLimit4 - rep0) >> 31) + ((kDistLimit3 - rep0) >> 31); } else @@ -831,13 +833,17 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress) { RINOK(DecodePPM(1 << 18, keepDecompressing)) } - UInt64 packSize = m_InBitStream.bitDecoder.GetProcessedSize(); + + if (InputEofError()) + return S_FALSE; + + UInt64 packSize = m_InBitStream.BitDecoder.GetProcessedSize(); RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize)); if (!keepDecompressing) break; } RINOK(WriteBuf()); - UInt64 packSize = m_InBitStream.bitDecoder.GetProcessedSize(); + UInt64 packSize = m_InBitStream.BitDecoder.GetProcessedSize(); RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize)); if (_writtenFileSize < _unpackSize) return S_FALSE; @@ -866,17 +872,17 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream if (_window == 0) return E_OUTOFMEMORY; } - if (!m_InBitStream.bitDecoder.Create(1 << 20)) + 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(); + m_InBitStream.BitDecoder.SetStream(inStream); + m_InBitStream.BitDecoder.Init(); _outStream = outStream; - CCoderReleaser coderReleaser(this); + // CCoderReleaser coderReleaser(this); _unpackSize = *outSize; return CodeReal(progress); } diff --git a/CPP/7zip/Compress/Rar3Decoder.h b/CPP/7zip/Compress/Rar3Decoder.h old mode 100755 new mode 100644 index 99b647dc..77379858 --- a/CPP/7zip/Compress/Rar3Decoder.h +++ b/CPP/7zip/Compress/Rar3Decoder.h @@ -40,43 +40,53 @@ const UInt32 kTablesSizesSum = kMainTableSize + kDistTableSize + kAlignTableSize class CBitDecoder { - UInt32 m_Value; - unsigned m_BitPos; + UInt32 _value; + unsigned _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();} + CInBuffer Stream; + + bool Create(UInt32 bufSize) { return Stream.Create(bufSize); } + void SetStream(ISequentialInStream *inStream) { Stream.SetStream(inStream);} void Init() { - m_Stream.Init(); - m_BitPos = 0; - m_Value = 0; + Stream.Init(); + _bitPos = 0; + _value = 0; } - UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() - (m_BitPos) / 8; } - UInt32 GetBitPosition() const { return ((8 - m_BitPos) & 7); } + bool ExtraBitsWereRead() const + { + return (Stream.NumExtraBytes > 4 || _bitPos < (Stream.NumExtraBytes << 3)); + } + + UInt64 GetProcessedSize() const { return Stream.GetProcessedSize() - (_bitPos >> 3); } + + void AlignToByte() + { + _bitPos &= ~(unsigned)7; + _value = _value & ((1 << _bitPos) - 1); + } UInt32 GetValue(unsigned numBits) { - if (m_BitPos < numBits) + if (_bitPos < numBits) { - m_BitPos += 8; - m_Value = (m_Value << 8) | m_Stream.ReadByte(); - if (m_BitPos < numBits) + _bitPos += 8; + _value = (_value << 8) | Stream.ReadByte(); + if (_bitPos < numBits) { - m_BitPos += 8; - m_Value = (m_Value << 8) | m_Stream.ReadByte(); + _bitPos += 8; + _value = (_value << 8) | Stream.ReadByte(); } } - return m_Value >> (m_BitPos - numBits); + return _value >> (_bitPos - numBits); } void MovePos(unsigned numBits) { - m_BitPos -= numBits; - m_Value = m_Value & ((1 << m_BitPos) - 1); + _bitPos -= numBits; + _value = _value & ((1 << _bitPos) - 1); } UInt32 ReadBits(unsigned numBits) @@ -96,7 +106,7 @@ struct CRangeDecoder UInt32 Range; UInt32 Code; UInt32 Low; - CBitDecoder bitDecoder; + CBitDecoder BitDecoder; SRes Res; public: @@ -106,7 +116,7 @@ public: Low = 0; Range = 0xFFFFFFFF; for (int i = 0; i < 4; i++) - Code = (Code << 8) | bitDecoder.ReadBits(8); + Code = (Code << 8) | BitDecoder.ReadBits(8); } void Normalize() @@ -114,7 +124,7 @@ public: while ((Low ^ (Low + Range)) < kTopValue || Range < kBot && ((Range = (0 - Low) & (kBot - 1)), 1)) { - Code = (Code << 8) | bitDecoder.m_Stream.ReadByte(); + Code = (Code << 8) | BitDecoder.Stream.ReadByte(); Range <<= 8; Low <<= 8; } @@ -129,6 +139,7 @@ struct CFilter: public NVm::CProgram UInt32 BlockStart; UInt32 BlockSize; UInt32 ExecCount; + CFilter(): BlockStart(0), BlockSize(0), ExecCount(0) {} }; @@ -136,10 +147,15 @@ struct CTempFilter: public NVm::CProgramInitState { UInt32 BlockStart; UInt32 BlockSize; - UInt32 ExecCount; bool NextWindow; UInt32 FilterIndex; + + CTempFilter() + { + // all filters must contain at least FixedGlobal block + AllocateEmptyFixedGlobal(); + } }; const int kNumHuffmanBits = 15; @@ -156,7 +172,7 @@ class CDecoder: UInt64 _lzSize; UInt64 _unpackSize; UInt64 _writtenFileSize; // if it's > _unpackSize, then _unpackSize only written - CMyComPtr _outStream; + ISequentialOutStream *_outStream; NHuffman::CDecoder m_MainDecoder; NHuffman::CDecoder m_DistDecoder; NHuffman::CDecoder m_AlignDecoder; @@ -209,18 +225,16 @@ class CDecoder: HRESULT ReadEndOfBlock(bool &keepDecompressing); HRESULT DecodeLZ(bool &keepDecompressing); HRESULT CodeReal(ICompressProgressInfo *progress); + + bool InputEofError() const { return m_InBitStream.BitDecoder.ExtraBitsWereRead(); } + bool InputEofError_Fast() const { return (m_InBitStream.BitDecoder.Stream.NumExtraBytes > 2); } + 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); diff --git a/CPP/7zip/Compress/Rar3Vm.cpp b/CPP/7zip/Compress/Rar3Vm.cpp old mode 100755 new mode 100644 index 74051dd7..5b113bfa --- a/CPP/7zip/Compress/Rar3Vm.cpp +++ b/CPP/7zip/Compress/Rar3Vm.cpp @@ -15,18 +15,20 @@ Note: #include "../../../C/7zCrc.h" #include "../../../C/Alloc.h" +#include "../../Common/Defs.h" + #include "Rar3Vm.h" namespace NCompress { namespace NRar3 { -UInt32 CMemBitDecoder::ReadBits(int numBits) +UInt32 CMemBitDecoder::ReadBits(unsigned numBits) { UInt32 res = 0; for (;;) { - Byte b = _bitPos < _bitSize ? _data[_bitPos >> 3] : 0; - int avail = (int)(8 - (_bitPos & 7)); + unsigned b = _bitPos < _bitSize ? (unsigned)_data[_bitPos >> 3] : 0; + unsigned avail = (unsigned)(8 - (_bitPos & 7)); if (numBits <= avail) { _bitPos += numBits; @@ -40,6 +42,15 @@ UInt32 CMemBitDecoder::ReadBits(int numBits) UInt32 CMemBitDecoder::ReadBit() { return ReadBits(1); } +UInt32 CMemBitDecoder::ReadEncodedUInt32() +{ + unsigned v = (unsigned)ReadBits(2); + UInt32 res = ReadBits(4 << v); + if (v == 1 && res < 16) + res = 0xFFFFFF00 | (res << 4) | ReadBits(4); + return res; +} + namespace NVm { static const UInt32 kStackRegIndex = kNumRegs - 1; @@ -58,7 +69,7 @@ static const Byte CF_PROC = 16; static const Byte CF_USEFLAGS = 32; static const Byte CF_CHFLAGS = 64; -static Byte kCmdFlags[]= +static const Byte kCmdFlags[]= { /* CMD_MOV */ CF_OP2 | CF_BYTEMODE, /* CMD_CMP */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS, @@ -142,7 +153,11 @@ bool CVm::Execute(CProgram *prg, const CProgramInitState *initState, { res = ExecuteCode(prg); if (!res) - prg->Commands[0].OpCode = CMD_RET; + { + prg->Commands.Clear(); + prg->Commands.Add(CCommand()); + prg->Commands.Back().OpCode = CMD_RET; + } } UInt32 newBlockPos = GetFixedGlobalValue32(NGlobalOffset::kBlockPos) & kSpaceMask; UInt32 newBlockSize = GetFixedGlobalValue32(NGlobalOffset::kBlockSize) & kSpaceMask; @@ -157,9 +172,8 @@ bool CVm::Execute(CProgram *prg, const CProgramInitState *initState, if (dataSize != 0) { dataSize += kFixedGlobalSize; - outGlobalData.Reserve(dataSize); - for (UInt32 i = 0; i < dataSize; i++) - outGlobalData.Add(Mem[kGlobalOffset + i]); + outGlobalData.ClearAndSetSize(dataSize); + memcpy(&outGlobalData[0], Mem + kGlobalOffset, dataSize); } return res; } @@ -234,6 +248,9 @@ bool CVm::ExecuteCode(const CProgram *prg) const CCommand *commands = &prg->Commands[0]; const CCommand *cmd = commands; UInt32 numCommands = prg->Commands.Size(); + if (numCommands == 0) + return false; + for (;;) { switch(cmd->OpCode) @@ -256,8 +273,7 @@ bool CVm::ExecuteCode(const CProgram *prg) case CMD_CMPB: { Byte v1 = GetOperand8(&cmd->Op1); - Byte res = v1 - GetOperand8(&cmd->Op2); - res &= 0xFF; + Byte res = (Byte)((v1 - GetOperand8(&cmd->Op2)) & 0xFF); Flags = res == 0 ? FLAG_Z : (res > v1) | GET_FLAG_S_B(res); } break; @@ -272,8 +288,7 @@ bool CVm::ExecuteCode(const CProgram *prg) case CMD_ADDB: { Byte v1 = GetOperand8(&cmd->Op1); - Byte res = v1 + GetOperand8(&cmd->Op2); - res &= 0xFF; + Byte res = (Byte)((v1 + GetOperand8(&cmd->Op2)) & 0xFF); SetOperand8(&cmd->Op1, (Byte)res); Flags = (res < v1) | (res == 0 ? FLAG_Z : GET_FLAG_S_B(res)); } @@ -326,7 +341,7 @@ bool CVm::ExecuteCode(const CProgram *prg) break; case CMD_INCB: { - Byte res = GetOperand8(&cmd->Op1) + 1; + Byte res = (Byte)(GetOperand8(&cmd->Op1) + 1); SetOperand8(&cmd->Op1, res);; FLAGS_UPDATE_SZ_B; } @@ -340,7 +355,7 @@ bool CVm::ExecuteCode(const CProgram *prg) break; case CMD_DECB: { - Byte res = GetOperand8(&cmd->Op1) - 1; + Byte res = (Byte)(GetOperand8(&cmd->Op1) - 1); SetOperand8(&cmd->Op1, res);; FLAGS_UPDATE_SZ_B; } @@ -354,7 +369,7 @@ bool CVm::ExecuteCode(const CProgram *prg) break; case CMD_XORB: { - Byte res = GetOperand8(&cmd->Op1) ^ GetOperand8(&cmd->Op2); + Byte res = (Byte)(GetOperand8(&cmd->Op1) ^ GetOperand8(&cmd->Op2)); SetOperand8(&cmd->Op1, res); FLAGS_UPDATE_SZ_B; } @@ -368,7 +383,7 @@ bool CVm::ExecuteCode(const CProgram *prg) break; case CMD_ANDB: { - Byte res = GetOperand8(&cmd->Op1) & GetOperand8(&cmd->Op2); + Byte res = (Byte)(GetOperand8(&cmd->Op1) & GetOperand8(&cmd->Op2)); SetOperand8(&cmd->Op1, res); FLAGS_UPDATE_SZ_B; } @@ -382,7 +397,7 @@ bool CVm::ExecuteCode(const CProgram *prg) break; case CMD_ORB: { - Byte res = GetOperand8(&cmd->Op1) | GetOperand8(&cmd->Op2); + Byte res = (Byte)(GetOperand8(&cmd->Op1) | GetOperand8(&cmd->Op2)); SetOperand8(&cmd->Op1, res); FLAGS_UPDATE_SZ_B; } @@ -395,7 +410,7 @@ bool CVm::ExecuteCode(const CProgram *prg) break; case CMD_TESTB: { - Byte res = GetOperand8(&cmd->Op1) & GetOperand8(&cmd->Op2); + Byte res = (Byte)(GetOperand8(&cmd->Op1) & GetOperand8(&cmd->Op2)); FLAGS_UPDATE_SZ_B; } break; @@ -589,7 +604,7 @@ bool CVm::ExecuteCode(const CProgram *prg) break; case CMD_MULB: { - Byte res = GetOperand8(&cmd->Op1) * GetOperand8(&cmd->Op2); + Byte res = (Byte)(GetOperand8(&cmd->Op1) * GetOperand8(&cmd->Op2)); SetOperand8(&cmd->Op1, res); } break; @@ -627,28 +642,7 @@ bool CVm::ExecuteCode(const CProgram *prg) ////////////////////////////////////////////////////// // 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) +static void DecodeArg(CMemBitDecoder &inp, COperand &op, bool byteMode) { if (inp.ReadBit()) { @@ -661,7 +655,7 @@ void CVm::DecodeArg(CMemBitDecoder &inp, COperand &op, bool byteMode) if (byteMode) op.Data = inp.ReadBits(8); else - op.Data = ReadEncodedUInt32(inp); + op.Data = inp.ReadEncodedUInt32(); } else { @@ -677,27 +671,27 @@ void CVm::DecodeArg(CMemBitDecoder &inp, COperand &op, bool byteMode) op.Data = inp.ReadBits(kNumRegBits); else op.Data = kNumRegs; - op.Base = ReadEncodedUInt32(inp); + op.Base = inp.ReadEncodedUInt32(); } } } -void CVm::ReadVmProgram(const Byte *code, UInt32 codeSize, CProgram *prg) +void CProgram::ReadProgram(const Byte *code, UInt32 codeSize) { CMemBitDecoder inp; inp.Init(code, codeSize); - prg->StaticData.Clear(); + StaticData.Clear(); if (inp.ReadBit()) { - UInt32 dataSize = ReadEncodedUInt32(inp) + 1; + UInt32 dataSize = inp.ReadEncodedUInt32() + 1; for (UInt32 i = 0; inp.Avail() && i < dataSize; i++) - prg->StaticData.Add((Byte)inp.ReadBits(8)); + StaticData.Add((Byte)inp.ReadBits(8)); } while (inp.Avail()) { - prg->Commands.Add(CCommand()); - CCommand *cmd = &prg->Commands.Back(); + Commands.Add(CCommand()); + CCommand *cmd = &Commands.Back(); if (inp.ReadBit() == 0) cmd->OpCode = (ECommand)inp.ReadBits(3); else @@ -716,20 +710,20 @@ void CVm::ReadVmProgram(const Byte *code, UInt32 codeSize, CProgram *prg) { if (cmd->Op1.Type == OP_TYPE_INT && (kCmdFlags[cmd->OpCode] & (CF_JUMP | CF_PROC))) { - int Distance = cmd->Op1.Data; - if (Distance >= 256) - Distance -= 256; + int dist = cmd->Op1.Data; + if (dist >= 256) + dist -= 256; else { - if (Distance >= 136) - Distance -= 264; - else if (Distance >= 16) - Distance -= 8; - else if (Distance >= 8) - Distance -= 16; - Distance += prg->Commands.Size() - 1; + if (dist >= 136) + dist -= 264; + else if (dist >= 16) + dist -= 8; + else if (dist >= 8) + dist -= 16; + dist += Commands.Size() - 1; } - cmd->Op1.Data = Distance; + cmd->Op1.Data = dist; } } } @@ -770,7 +764,7 @@ enum EStandardFilter SF_UPCASE }; -struct StandardFilterSignature +static const struct CStandardFilterSignature { UInt32 Length; UInt32 CRC; @@ -792,7 +786,7 @@ 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]; + const CStandardFilterSignature &sfs = kStdFilters[i]; if (sfs.CRC == crc && sfs.Length == codeSize) return i; } @@ -801,30 +795,28 @@ static int FindStandardFilter(const Byte *code, UInt32 codeSize) #endif -void CVm::PrepareProgram(const Byte *code, UInt32 codeSize, CProgram *prg) +void CProgram::PrepareProgram(const Byte *code, UInt32 codeSize) { Byte xorSum = 0; for (UInt32 i = 1; i < codeSize; i++) xorSum ^= code[i]; - prg->Commands.Clear(); + Commands.Clear(); #ifdef RARVM_STANDARD_FILTERS - prg->StandardFilterIndex = -1; + StandardFilterIndex = -1; #endif if (xorSum == code[0] && codeSize > 0) { #ifdef RARVM_STANDARD_FILTERS - prg->StandardFilterIndex = FindStandardFilter(code, codeSize); - if (prg->StandardFilterIndex >= 0) + StandardFilterIndex = FindStandardFilter(code, codeSize); + if (StandardFilterIndex >= 0) return; #endif - // 1 byte for checksum - ReadVmProgram(code + 1, codeSize - 1, prg); + ReadProgram(code + 1, codeSize - 1); } - prg->Commands.Add(CCommand()); - CCommand *cmd = &prg->Commands.Back(); - cmd->OpCode = CMD_RET; + Commands.Add(CCommand()); + Commands.Back().OpCode = CMD_RET; } void CVm::SetMemory(UInt32 pos, const Byte *data, UInt32 dataSize) @@ -841,7 +833,7 @@ static void E8E9Decode(Byte *data, UInt32 dataSize, UInt32 fileOffset, bool e9) return; dataSize -= 4; const UInt32 kFileSize = 0x1000000; - Byte cmpByte2 = (e9 ? 0xE9 : 0xE8); + Byte cmpByte2 = (Byte)(e9 ? 0xE9 : 0xE8); for (UInt32 curPos = 0; curPos < dataSize;) { Byte curByte = *(data++); @@ -886,7 +878,7 @@ static void ItaniumDecode(Byte *data, UInt32 dataSize, UInt32 fileOffset) { const UInt32 kMask = 0xFFFFF; Byte *p = data + ((unsigned int)startPos >> 3); - UInt32 bitField = ((UInt32)p[0]) | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16); + 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); @@ -915,7 +907,7 @@ static void DeltaDecode(Byte *data, UInt32 dataSize, UInt32 numChannels) { Byte prevByte = 0; for (UInt32 destPos = dataSize + curChannel; destPos < border; destPos += numChannels) - data[destPos] = (prevByte = prevByte - data[srcPos++]); + data[destPos] = (prevByte = (Byte)(prevByte - data[srcPos++])); } } @@ -956,8 +948,8 @@ static void RgbDecode(Byte *srcData, UInt32 dataSize, UInt32 width, UInt32 posR) 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; + destData[i ] = (Byte)(destData[i ] + g); + destData[i + 2] = (Byte)(destData[i + 2] + g); } } diff --git a/CPP/7zip/Compress/Rar3Vm.h b/CPP/7zip/Compress/Rar3Vm.h old mode 100755 new mode 100644 index c02534c6..55842b90 --- a/CPP/7zip/Compress/Rar3Vm.h +++ b/CPP/7zip/Compress/Rar3Vm.h @@ -7,8 +7,8 @@ #include "../../../C/CpuArch.h" -#include "Common/MyVector.h" -#include "Common/Types.h" +#include "../../Common/MyTypes.h" +#include "../../Common/MyVector.h" #define RARVM_STANDARD_FILTERS @@ -27,9 +27,11 @@ public: _bitSize = (byteSize << 3); _bitPos = 0; } - UInt32 ReadBits(int numBits); + UInt32 ReadBits(unsigned numBits); UInt32 ReadBit(); bool Avail() const { return (_bitPos < _bitSize); } + + UInt32 ReadEncodedUInt32(); }; namespace NVm { @@ -37,8 +39,6 @@ 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; @@ -95,13 +95,19 @@ struct CBlockRef UInt32 Size; }; -struct CProgram +class CProgram { +public: CRecordVector Commands; #ifdef RARVM_STANDARD_FILTERS int StandardFilterIndex; #endif CRecordVector StaticData; + +private: + void ReadProgram(const Byte *code, UInt32 codeSize); +public: + void PrepareProgram(const Byte *code, UInt32 codeSize); }; struct CProgramInitState @@ -111,10 +117,8 @@ struct CProgramInitState void AllocateEmptyFixedGlobal() { - GlobalData.Clear(); - GlobalData.Reserve(NVm::kFixedGlobalSize); - for (UInt32 i = 0; i < NVm::kFixedGlobalSize; i++) - GlobalData.Add(0); + GlobalData.ClearAndSetSize(NVm::kFixedGlobalSize); + memset(&GlobalData[0], 0, NVm::kFixedGlobalSize); } }; @@ -150,8 +154,6 @@ private: 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 @@ -161,12 +163,10 @@ private: 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); diff --git a/CPP/7zip/Compress/RarCodecsRegister.cpp b/CPP/7zip/Compress/RarCodecsRegister.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/ShrinkDecoder.cpp b/CPP/7zip/Compress/ShrinkDecoder.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/ShrinkDecoder.h b/CPP/7zip/Compress/ShrinkDecoder.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/StdAfx.h b/CPP/7zip/Compress/StdAfx.h old mode 100755 new mode 100644 index 99a8aa46..1cbd7fea --- a/CPP/7zip/Compress/StdAfx.h +++ b/CPP/7zip/Compress/StdAfx.h @@ -3,6 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../Common/MyWindows.h" +#include "../../Common/Common.h" #endif diff --git a/CPP/7zip/Compress/ZDecoder.cpp b/CPP/7zip/Compress/ZDecoder.cpp old mode 100755 new mode 100644 index e28c6451..7308bc0b --- a/CPP/7zip/Compress/ZDecoder.cpp +++ b/CPP/7zip/Compress/ZDecoder.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +// #include + #include "../../../C/Alloc.h" #include "../Common/InBuffer.h" @@ -15,8 +17,8 @@ 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; +static const unsigned kNumMinBits = 9; +static const unsigned kNumMaxBits = 16; void CDecoder::Free() { @@ -33,6 +35,8 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * CInBuffer inBuffer; COutBuffer outBuffer; + PackSize = 0; + if (!inBuffer.Create(kBufferSize)) return E_OUTOFMEMORY; inBuffer.SetStream(inStream); @@ -43,11 +47,22 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * outBuffer.SetStream(outStream); outBuffer.Init(); - int maxbits = _properties & kNumBitsMask; + Byte buf[kNumMaxBits + 4]; + { + if (inBuffer.ReadBytes(buf, 3) < 3) + return S_FALSE; + if (buf[0] != 0x1F || buf[1] != 0x9D) + return S_FALSE;; + } + Byte prop = buf[2]; + + if ((prop & 0x60) != 0) + return S_FALSE; + unsigned maxbits = prop & kNumBitsMask; if (maxbits < kNumMinBits || maxbits > kNumMaxBits) return S_FALSE; UInt32 numItems = 1 << maxbits; - bool blockMode = ((_properties & kBlockModeMask) != 0); + // Speed optimization: blockSymbol can contain unused velue. if (maxbits != _numMaxBits || _parents == 0 || _suffixes == 0 || _stack == 0) { @@ -59,18 +74,16 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * } UInt64 prevPos = 0; - int numBits = kNumMinBits; - UInt32 head = blockMode ? 257 : 256; - + UInt32 blockSymbol = ((prop & kBlockModeMask) != 0) ? 256 : ((UInt32)1 << kNumMaxBits); + unsigned numBits = kNumMinBits; + UInt32 head = (blockSymbol == 256) ? 257 : 256; bool needPrev = false; - unsigned bitPos = 0; unsigned numBufBits = 0; - Byte buf[kNumMaxBits + 4]; - _parents[256] = 0; // virus protection _suffixes[256] = 0; + HRESULT res = S_OK; for (;;) { @@ -79,7 +92,7 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * numBufBits = (unsigned)inBuffer.ReadBytes(buf, numBits) * 8; bitPos = 0; UInt64 nowPos = outBuffer.GetProcessedSize(); - if (progress != NULL && nowPos - prevPos >= (1 << 18)) + if (progress && nowPos - prevPos >= (1 << 13)) { prevPos = nowPos; UInt64 packSize = inBuffer.GetProcessedSize(); @@ -94,8 +107,11 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * if (bitPos > numBufBits) break; if (symbol >= head) - return S_FALSE; - if (blockMode && symbol == 256) + { + res = S_FALSE; + break; + } + if (symbol == blockSymbol) { numBufBits = bitPos = 0; numBits = kNumMinBits; @@ -104,7 +120,7 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * continue; } UInt32 cur = symbol; - int i = 0; + unsigned i = 0; while (cur >= 256) { _stack[i++] = _suffixes[cur]; @@ -136,7 +152,9 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * else needPrev = false; } - return outBuffer.Flush(); + PackSize = inBuffer.GetProcessedSize(); + HRESULT res2 = outBuffer.Flush(); + return (res == S_OK) ? res2 : res; } STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, @@ -148,12 +166,72 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream catch(...) { return S_FALSE; } } -STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) +bool CheckStream(const Byte *data, size_t size) { - if (size < 1) - return E_INVALIDARG; - _properties = data[0]; - return S_OK; + if (size < 3) + return false; + if (data[0] != 0x1F || data[1] != 0x9D) + return false; + Byte prop = data[2]; + if ((prop & 0x60) != 0) + return false; + unsigned maxbits = prop & kNumBitsMask; + if (maxbits < kNumMinBits || maxbits > kNumMaxBits) + return false; + UInt32 numItems = 1 << maxbits; + UInt32 blockSymbol = ((prop & kBlockModeMask) != 0) ? 256 : ((UInt32)1 << kNumMaxBits); + unsigned numBits = kNumMinBits; + UInt32 head = (blockSymbol == 256) ? 257 : 256; + unsigned bitPos = 0; + unsigned numBufBits = 0; + Byte buf[kNumMaxBits + 4]; + data += 3; + size -= 3; + // printf("\n\n"); + for (;;) + { + if (numBufBits == bitPos) + { + unsigned num = (numBits < size) ? numBits : (unsigned)size; + memcpy(buf, data, num); + data += num; + size -= num; + numBufBits = num * 8; + bitPos = 0; + } + 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) + { + // printf(" OK", symbol); + return true; + } + // printf("%3X ", symbol); + if (symbol >= head) + return false; + if (symbol == blockSymbol) + { + numBufBits = bitPos = 0; + numBits = kNumMinBits; + head = 257; + continue; + } + if (head < numItems) + { + head++; + if (head > ((UInt32)1 << numBits)) + { + if (numBits < maxbits) + { + numBufBits = bitPos = 0; + numBits++; + } + } + } + } } }} diff --git a/CPP/7zip/Compress/ZDecoder.h b/CPP/7zip/Compress/ZDecoder.h old mode 100755 new mode 100644 index 2bd83a17..19acd498 --- a/CPP/7zip/Compress/ZDecoder.h +++ b/CPP/7zip/Compress/ZDecoder.h @@ -10,33 +10,45 @@ namespace NCompress { namespace NZ { +// Z decoder decodes Z data stream, including 3 bytes of header. + class CDecoder: public ICompressCoder, - public ICompressSetDecoderProperties2, public CMyUnknownImp { UInt16 *_parents; Byte *_suffixes; Byte *_stack; - Byte _properties; - int _numMaxBits; + unsigned _numMaxBits; public: - CDecoder(): _parents(0), _suffixes(0), _stack(0), _properties(0), _numMaxBits(0) {}; + CDecoder(): _parents(0), _suffixes(0), _stack(0), /* _prop(0), */ _numMaxBits(0) {}; ~CDecoder(); void Free(); + UInt64 PackSize; - MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2) + MY_UNKNOWN_IMP1(ICompressCoder) 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); }; +/* + There is no end_of_payload_marker in Z stream. + Z decoder stops decoding, if it reaches end of input stream. + + CheckStream function: + (size) must be at least 3 bytes (size of Z header). + if (size) is larger than size of real Z stream in (data), CheckStream can return false. +*/ + +const unsigned kRecommendedCheckSize = 64; + +bool CheckStream(const Byte *data, size_t size); + }} #endif diff --git a/CPP/7zip/Compress/ZlibDecoder.cpp b/CPP/7zip/Compress/ZlibDecoder.cpp old mode 100755 new mode 100644 index 90d6715d..8f3a63cb --- a/CPP/7zip/Compress/ZlibDecoder.cpp +++ b/CPP/7zip/Compress/ZlibDecoder.cpp @@ -38,9 +38,12 @@ UInt32 Adler32_Update(UInt32 adler, const Byte *buf, size_t size) STDMETHODIMP COutStreamWithAdler::Write(const void *data, UInt32 size, UInt32 *processedSize) { - HRESULT result = _stream->Write(data, size, &size); + HRESULT result = S_OK; + if (_stream) + result = _stream->Write(data, size, &size); _adler = Adler32_Update(_adler, (const Byte *)data, size); - if (processedSize != NULL) + _size += size; + if (processedSize) *processedSize = size; return result; } @@ -58,21 +61,21 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream DeflateDecoder = DeflateDecoderSpec; } + if (inSize && *inSize < 2) + return S_FALSE; 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) + if (!IsZlib(buf)) 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); + + UInt64 inSize2 = 0; + if (inSize) + inSize2 = *inSize - 2; + + HRESULT res = DeflateDecoder->Code(inStream, AdlerStream, inSize ? &inSize2 : NULL, outSize, progress); AdlerSpec->ReleaseStream(); if (res == S_OK) diff --git a/CPP/7zip/Compress/ZlibDecoder.h b/CPP/7zip/Compress/ZlibDecoder.h old mode 100755 new mode 100644 index 95c11002..8c5e73b0 --- a/CPP/7zip/Compress/ZlibDecoder.h +++ b/CPP/7zip/Compress/ZlibDecoder.h @@ -16,13 +16,15 @@ class COutStreamWithAdler: { CMyComPtr _stream; UInt32 _adler; + UInt64 _size; 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; } + void Init() { _adler = ADLER_INIT_VAL; _size = 0; } UInt32 GetAdler() const { return _adler; } + UInt64 GetSize() const { return _size; } }; class CDecoder: @@ -39,10 +41,39 @@ public: const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); UInt64 GetInputProcessedSize() const { return DeflateDecoderSpec->GetInputProcessedSize() + 2; } + UInt64 GetOutputProcessedSize() const { return AdlerSpec->GetSize(); } MY_UNKNOWN_IMP }; +static bool inline IsZlib(const Byte *p) +{ + if ((p[0] & 0xF) != 8) // method + return false; + if (((unsigned)p[0] >> 4) > 7) // logar_window_size minus 8. + return false; + if ((p[1] & 0x20) != 0) // dictPresent + return false; + if ((((UInt32)p[0] << 8) + p[1]) % 31 != 0) + return false; + return true; +} + +// IsZlib_3bytes checks 2 bytes of zlib header and starting byte of Deflate stream + +static bool inline IsZlib_3bytes(const Byte *p) +{ + if (!IsZlib(p)) + return false; + unsigned val = p[2]; + unsigned blockType = (val >> 1) & 0x3; + if (blockType == 3) // unsupported block type for deflate + return false; + if (blockType == NCompress::NDeflate::NBlockType::kStored && (val >> 3) != 0) + return false; + return true; +} + }} #endif diff --git a/CPP/7zip/Compress/ZlibEncoder.cpp b/CPP/7zip/Compress/ZlibEncoder.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/ZlibEncoder.h b/CPP/7zip/Compress/ZlibEncoder.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Compress/makefile b/CPP/7zip/Compress/makefile old mode 100755 new mode 100644 diff --git a/CPP/7zip/Crc.mak b/CPP/7zip/Crc.mak old mode 100755 new mode 100644 diff --git a/CPP/7zip/Crc64.mak b/CPP/7zip/Crc64.mak new file mode 100644 index 00000000..57301c22 --- /dev/null +++ b/CPP/7zip/Crc64.mak @@ -0,0 +1,8 @@ +C_OBJS = $(C_OBJS) \ + $O\XzCrc64.obj +!IF "$(CPU)" == "IA64" || "$(CPU)" == "MIPS" || "$(CPU)" == "ARM" +C_OBJS = $(C_OBJS) \ +!ELSE +ASM_OBJS = $(ASM_OBJS) \ +!ENDIF + $O\XzCrc64Opt.obj diff --git a/CPP/7zip/Crypto/7zAes.cpp b/CPP/7zip/Crypto/7zAes.cpp old mode 100755 new mode 100644 index b686fb61..548c674b --- a/CPP/7zip/Crypto/7zAes.cpp +++ b/CPP/7zip/Crypto/7zAes.cpp @@ -4,7 +4,7 @@ #include "../../../C/Sha256.h" -#include "Windows/Synchronization.h" +#include "../../Windows/Synchronization.h" #include "../Common/StreamObjects.h" #include "../Common/StreamUtils.h" @@ -38,7 +38,7 @@ void CKeyInfo::CalculateDigest() UInt32 pos; for (pos = 0; pos < SaltSize; pos++) Key[pos] = Salt[pos]; - for (UInt32 i = 0; i < Password.GetCapacity() && pos < kKeySize; i++) + for (UInt32 i = 0; i < Password.Size() && pos < kKeySize; i++) Key[pos++] = Password[i]; for (; pos < kKeySize; pos++) Key[pos] = 0; @@ -52,7 +52,7 @@ void CKeyInfo::CalculateDigest() for (UInt64 round = 0; round < numRounds; round++) { Sha256_Update(&sha, Salt, (size_t)SaltSize); - Sha256_Update(&sha, Password, Password.GetCapacity()); + Sha256_Update(&sha, Password, Password.Size()); Sha256_Update(&sha, temp, 8); for (int i = 0; i < 8; i++) if (++(temp[i]) != 0) @@ -64,7 +64,7 @@ void CKeyInfo::CalculateDigest() bool CKeyInfoCache::Find(CKeyInfo &key) { - for (int i = 0; i < Keys.Size(); i++) + FOR_VECTOR (i, Keys) { const CKeyInfo &cached = Keys[i]; if (key.IsEqualTo(cached)) @@ -72,10 +72,7 @@ bool CKeyInfoCache::Find(CKeyInfo &key) for (int j = 0; j < kKeySize; j++) key.Key[j] = cached.Key[j]; if (i != 0) - { - Keys.Insert(0, cached); - Keys.Delete(i+1); - } + Keys.MoveToFront(i); return true; } } @@ -170,7 +167,7 @@ STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) HRESULT CEncoder::CreateFilter() { - _aesFilter = new CAesCbcEncoder; + _aesFilter = new CAesCbcEncoder(kKeySize); return S_OK; } @@ -211,8 +208,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size) { - _key.Password.SetCapacity((size_t)size); - memcpy(_key.Password, data, (size_t)size); + _key.Password.CopyFrom(data, (size_t)size); return S_OK; } @@ -227,7 +223,7 @@ STDMETHODIMP CBaseCoder::Init() RINOK(_aesFilter.QueryInterface(IID_ICryptoProperties, &cp)); RINOK(cp->SetKey(_key.Key, sizeof(_key.Key))); RINOK(cp->SetInitVector(_iv, sizeof(_iv))); - return S_OK; + return _aesFilter->Init(); } STDMETHODIMP_(UInt32) CBaseCoder::Filter(Byte *data, UInt32 size) @@ -237,7 +233,7 @@ STDMETHODIMP_(UInt32) CBaseCoder::Filter(Byte *data, UInt32 size) HRESULT CDecoder::CreateFilter() { - _aesFilter = new CAesCbcDecoder; + _aesFilter = new CAesCbcDecoder(kKeySize); return S_OK; } diff --git a/CPP/7zip/Crypto/7zAes.h b/CPP/7zip/Crypto/7zAes.h old mode 100755 new mode 100644 index 79d723fa..560af5c2 --- a/CPP/7zip/Crypto/7zAes.h +++ b/CPP/7zip/Crypto/7zAes.h @@ -3,9 +3,9 @@ #ifndef __CRYPTO_7Z_AES_H #define __CRYPTO_7Z_AES_H -#include "Common/Buffer.h" -#include "Common/MyCom.h" -#include "Common/MyVector.h" +#include "../../Common/MyBuffer.h" +#include "../../Common/MyCom.h" +#include "../../Common/MyVector.h" #include "../ICoder.h" #include "../IPassword.h" @@ -39,10 +39,10 @@ public: class CKeyInfoCache { - int Size; + unsigned Size; CObjectVector Keys; public: - CKeyInfoCache(int size): Size(size) {} + CKeyInfoCache(unsigned size): Size(size) {} bool Find(CKeyInfo &key); // HRESULT Calculate(CKeyInfo &key); void Add(CKeyInfo &key); diff --git a/CPP/7zip/Crypto/7zAesRegister.cpp b/CPP/7zip/Crypto/7zAesRegister.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Crypto/Codec.def b/CPP/7zip/Crypto/Codec.def old mode 100755 new mode 100644 diff --git a/CPP/7zip/Crypto/HmacSha1.cpp b/CPP/7zip/Crypto/HmacSha1.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Crypto/HmacSha1.h b/CPP/7zip/Crypto/HmacSha1.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Crypto/MyAes.cpp b/CPP/7zip/Crypto/MyAes.cpp old mode 100755 new mode 100644 index 70a7dccf..52eaab7a --- a/CPP/7zip/Crypto/MyAes.cpp +++ b/CPP/7zip/Crypto/MyAes.cpp @@ -2,21 +2,34 @@ #include "StdAfx.h" +#include "../../../C/CpuArch.h" + #include "MyAes.h" namespace NCrypto { -struct CAesTabInit { CAesTabInit() { AesGenTables();} } g_AesTabInit; +static struct CAesTabInit { CAesTabInit() { AesGenTables();} } g_AesTabInit; -CAesCbcCoder::CAesCbcCoder() +CAesCbcCoder::CAesCbcCoder(bool encodeMode, unsigned keySize): + _keySize(keySize), + _keyIsSet(false), + _encodeMode(encodeMode) { _offset = ((0 - (unsigned)(ptrdiff_t)_aes) & 0xF) / sizeof(UInt32); + memset(_iv, 0, AES_BLOCK_SIZE); + SetFunctions(0); } -STDMETHODIMP CAesCbcCoder::Init() { return S_OK; } +STDMETHODIMP CAesCbcCoder::Init() +{ + AesCbc_Init(_aes + _offset, _iv); + return _keyIsSet ? S_OK : E_FAIL; +} STDMETHODIMP_(UInt32) CAesCbcCoder::Filter(Byte *data, UInt32 size) { + if (!_keyIsSet) + return 0; if (size == 0) return 0; if (size < AES_BLOCK_SIZE) @@ -30,7 +43,11 @@ 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); + if (_keySize != 0 && size != _keySize) + return E_INVALIDARG; + AES_SET_KEY_FUNC setKeyFunc = _encodeMode ? Aes_SetKey_Enc : Aes_SetKey_Dec; + setKeyFunc(_aes + _offset + 4, data, size); + _keyIsSet = true; return S_OK; } @@ -38,11 +55,58 @@ STDMETHODIMP CAesCbcCoder::SetInitVector(const Byte *data, UInt32 size) { if (size != AES_BLOCK_SIZE) return E_INVALIDARG; - AesCbc_Init(_aes + _offset, data); + memcpy(_iv, data, size); + CAesCbcCoder::Init(); // don't call virtual function here !!! return S_OK; } -CAesCbcEncoder::CAesCbcEncoder() { _codeFunc = g_AesCbc_Encode; _setKeyFunc = Aes_SetKey_Enc; } -CAesCbcDecoder::CAesCbcDecoder() { _codeFunc = g_AesCbc_Decode; _setKeyFunc = Aes_SetKey_Dec; } +EXTERN_C_BEGIN + +void MY_FAST_CALL AesCbc_Encode(UInt32 *ivAes, Byte *data, size_t numBlocks); +void MY_FAST_CALL AesCbc_Decode(UInt32 *ivAes, Byte *data, size_t numBlocks); +void MY_FAST_CALL AesCtr_Code(UInt32 *ivAes, Byte *data, size_t numBlocks); + +void MY_FAST_CALL AesCbc_Encode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks); +void MY_FAST_CALL AesCbc_Decode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks); +void MY_FAST_CALL AesCtr_Code_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks); + +EXTERN_C_END + +bool CAesCbcCoder::SetFunctions(UInt32 algo) +{ + _codeFunc = _encodeMode ? + g_AesCbc_Encode : + g_AesCbc_Decode; + if (algo == 1) + { + _codeFunc = _encodeMode ? + AesCbc_Encode: + AesCbc_Decode; + } + if (algo == 2) + { + #ifdef MY_CPU_X86_OR_AMD64 + if (g_AesCbc_Encode != AesCbc_Encode_Intel) + #endif + return false; + } + return true; +} + +STDMETHODIMP CAesCbcCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps) +{ + for (UInt32 i = 0; i < numProps; i++) + { + const PROPVARIANT &prop = coderProps[i]; + if (propIDs[i] == NCoderPropID::kDefaultProp) + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + if (!SetFunctions(prop.ulVal)) + return E_NOTIMPL; + } + } + return S_OK; +} } diff --git a/CPP/7zip/Crypto/MyAes.h b/CPP/7zip/Crypto/MyAes.h old mode 100755 new mode 100644 index 60b13845..99a17fef --- a/CPP/7zip/Crypto/MyAes.h +++ b/CPP/7zip/Crypto/MyAes.h @@ -14,24 +14,38 @@ namespace NCrypto { class CAesCbcCoder: public ICompressFilter, public ICryptoProperties, + public ICompressSetCoderProperties, public CMyUnknownImp { -protected: AES_CODE_FUNC _codeFunc; - AES_SET_KEY_FUNC _setKeyFunc; unsigned _offset; + unsigned _keySize; + bool _keyIsSet; + bool _encodeMode; UInt32 _aes[AES_NUM_IVMRK_WORDS + 3]; + Byte _iv[AES_BLOCK_SIZE]; + + bool SetFunctions(UInt32 algo); public: - CAesCbcCoder(); - MY_UNKNOWN_IMP1(ICryptoProperties) + CAesCbcCoder(bool encodeMode, unsigned keySize); + MY_UNKNOWN_IMP2(ICryptoProperties, ICompressSetCoderProperties) STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); STDMETHOD(SetKey)(const Byte *data, UInt32 size); STDMETHOD(SetInitVector)(const Byte *data, UInt32 size); + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); +}; + +struct CAesCbcEncoder: public CAesCbcCoder +{ + CAesCbcEncoder(unsigned keySize = 0): CAesCbcCoder(true, keySize) {} +}; + +struct CAesCbcDecoder: public CAesCbcCoder +{ + CAesCbcDecoder(unsigned keySize = 0): CAesCbcCoder(false, keySize) {} }; -struct CAesCbcEncoder: public CAesCbcCoder { CAesCbcEncoder(); }; -struct CAesCbcDecoder: public CAesCbcCoder { CAesCbcDecoder(); }; } diff --git a/CPP/7zip/Crypto/MyAesReg.cpp b/CPP/7zip/Crypto/MyAesReg.cpp new file mode 100644 index 00000000..faaa104b --- /dev/null +++ b/CPP/7zip/Crypto/MyAesReg.cpp @@ -0,0 +1,19 @@ +// MyAesReg.cpp + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" + +#include "MyAes.h" + +static void *CreateCodecCbc() { return (void *)(ICompressFilter *)(new NCrypto::CAesCbcDecoder(32)); } +#ifndef EXTRACT_ONLY +static void *CreateCodecCbcOut() { return (void *)(ICompressFilter *)(new NCrypto::CAesCbcEncoder(32)); } +#else +#define CreateCodecCbcOut 0 +#endif + +static CCodecInfo g_CodecInfo = + { CreateCodecCbc, CreateCodecCbcOut, 0x06F00181, L"AES256CBC", 1, true }; +REGISTER_CODEC(AES256CBC) + diff --git a/CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp b/CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Crypto/Pbkdf2HmacSha1.h b/CPP/7zip/Crypto/Pbkdf2HmacSha1.h old mode 100755 new mode 100644 index bb90e121..6560b8d1 --- a/CPP/7zip/Crypto/Pbkdf2HmacSha1.h +++ b/CPP/7zip/Crypto/Pbkdf2HmacSha1.h @@ -5,7 +5,8 @@ #define __CRYPTO_PBKDF2_HMAC_SHA1_H #include -#include "../../Common/Types.h" + +#include "../../Common/MyTypes.h" namespace NCrypto { namespace NSha1 { diff --git a/CPP/7zip/Crypto/RandGen.cpp b/CPP/7zip/Crypto/RandGen.cpp old mode 100755 new mode 100644 index 3a8c9fbd..0ed65a30 --- a/CPP/7zip/Crypto/RandGen.cpp +++ b/CPP/7zip/Crypto/RandGen.cpp @@ -2,7 +2,7 @@ #include "StdAfx.h" -#include "Windows/Synchronization.h" +#include "../../Windows/Synchronization.h" #include "RandGen.h" @@ -44,7 +44,13 @@ void CRandomGenerator::Init() HASH_UPD(pid); #endif - for (unsigned i = 0; i < 1000; i++) + for (unsigned i = 0; i < + #ifdef _DEBUG + 2; + #else + 1000; + #endif + i++) { #ifdef _WIN32 LARGE_INTEGER v; diff --git a/CPP/7zip/Crypto/RandGen.h b/CPP/7zip/Crypto/RandGen.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/Crypto/Rar20Crypto.cpp b/CPP/7zip/Crypto/Rar20Crypto.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Crypto/Rar20Crypto.h b/CPP/7zip/Crypto/Rar20Crypto.h old mode 100755 new mode 100644 index b9648f59..1b6d6024 --- a/CPP/7zip/Crypto/Rar20Crypto.h +++ b/CPP/7zip/Crypto/Rar20Crypto.h @@ -3,7 +3,7 @@ #ifndef __CRYPTO_RAR20_CRYPTO_H #define __CRYPTO_RAR20_CRYPTO_H -#include "Common/MyCom.h" +#include "../../Common/MyCom.h" #include "../ICoder.h" #include "../IPassword.h" diff --git a/CPP/7zip/Crypto/RarAes.cpp b/CPP/7zip/Crypto/RarAes.cpp old mode 100755 new mode 100644 index b0f00ea8..e8f716d9 --- a/CPP/7zip/Crypto/RarAes.cpp +++ b/CPP/7zip/Crypto/RarAes.cpp @@ -10,6 +10,7 @@ namespace NCrypto { namespace NRar29 { CDecoder::CDecoder(): + CAesCbcDecoder(kRarAesKeySize), _thereIsSalt(false), _needCalculate(true), _rar350Mode(false) @@ -55,7 +56,7 @@ STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size) if (size > kMaxPasswordLength) size = kMaxPasswordLength; bool same = false; - if (size == buffer.GetCapacity()) + if (size == buffer.Size()) { same = true; for (UInt32 i = 0; i < size; i++) @@ -67,17 +68,16 @@ STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size) } if (!_needCalculate && !same) _needCalculate = true; - buffer.SetCapacity(size); - memcpy(buffer, data, size); + buffer.CopyFrom(data, (size_t)size); return S_OK; } STDMETHODIMP CDecoder::Init() { Calculate(); - SetKey(aesKey, kRarAesKeySize); - AesCbc_Init(_aes + _offset, _aesInit); - return S_OK; + RINOK(SetKey(aesKey, kRarAesKeySize)); + RINOK(SetInitVector(_aesInit, AES_BLOCK_SIZE)); + return CAesCbcCoder::Init(); } void CDecoder::Calculate() @@ -88,9 +88,9 @@ void CDecoder::Calculate() Byte rawPassword[kMaxPasswordLength + kSaltSize]; - memcpy(rawPassword, buffer, buffer.GetCapacity()); + memcpy(rawPassword, buffer, buffer.Size()); - size_t rawLength = buffer.GetCapacity(); + size_t rawLength = buffer.Size(); if (_thereIsSalt) { diff --git a/CPP/7zip/Crypto/RarAes.h b/CPP/7zip/Crypto/RarAes.h old mode 100755 new mode 100644 index 119cc233..9d9ee127 --- a/CPP/7zip/Crypto/RarAes.h +++ b/CPP/7zip/Crypto/RarAes.h @@ -5,7 +5,7 @@ #include "../../../C/Aes.h" -#include "Common/Buffer.h" +#include "../../Common/MyBuffer.h" #include "../IPassword.h" diff --git a/CPP/7zip/Crypto/Sha1.cpp b/CPP/7zip/Crypto/Sha1.cpp old mode 100755 new mode 100644 index 82ca986c..2f284071 --- a/CPP/7zip/Crypto/Sha1.cpp +++ b/CPP/7zip/Crypto/Sha1.cpp @@ -117,7 +117,7 @@ void CContext::Update(const Byte *data, size_t size) unsigned curBufferPos = _count2; while (size--) { - int pos = (int)(curBufferPos & 3); + unsigned pos = (curBufferPos & 3); if (pos == 0) _buffer[curBufferPos >> 2] = 0; _buffer[curBufferPos >> 2] |= ((UInt32)*data++) << (8 * (3 - pos)); @@ -136,7 +136,7 @@ void CContext::UpdateRar(Byte *data, size_t size, bool rar350Mode) unsigned curBufferPos = _count2; while (size--) { - int pos = (int)(curBufferPos & 3); + unsigned pos = (curBufferPos & 3); if (pos == 0) _buffer[curBufferPos >> 2] = 0; _buffer[curBufferPos >> 2] |= ((UInt32)*data++) << (8 * (3 - pos)); @@ -145,13 +145,13 @@ void CContext::UpdateRar(Byte *data, size_t size, bool rar350Mode) curBufferPos = 0; CContextBase::UpdateBlock(_buffer, returnRes); if (returnRes) - for (int i = 0; i < kBlockSizeInWords; i++) + for (unsigned 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); + data[(int)i * 4 + 0 - (int)kBlockSize] = (Byte)(d); + data[(int)i * 4 + 1 - (int)kBlockSize] = (Byte)(d >> 8); + data[(int)i * 4 + 2 - (int)kBlockSize] = (Byte)(d >> 16); + data[(int)i * 4 + 3 - (int)kBlockSize] = (Byte)(d >> 24); } returnRes = rar350Mode; } @@ -163,7 +163,7 @@ void CContext::Final(Byte *digest) { const UInt64 lenInBits = (_count << 9) + ((UInt64)_count2 << 3); unsigned curBufferPos = _count2; - int pos = (int)(curBufferPos & 3); + unsigned pos = (curBufferPos & 3); curBufferPos >>= 2; if (pos == 0) _buffer[curBufferPos] = 0; @@ -180,7 +180,7 @@ void CContext::Final(Byte *digest) _buffer[curBufferPos++] = (UInt32)(lenInBits); UpdateBlock(); - int i; + unsigned i; for (i = 0; i < kDigestSizeInWords; i++) { UInt32 state = _state[i] & 0xFFFFFFFF; diff --git a/CPP/7zip/Crypto/Sha1.h b/CPP/7zip/Crypto/Sha1.h old mode 100755 new mode 100644 index 1bad1f91..df9477d8 --- a/CPP/7zip/Crypto/Sha1.h +++ b/CPP/7zip/Crypto/Sha1.h @@ -6,7 +6,8 @@ #define __CRYPTO_SHA1_H #include -#include "../../Common/Types.h" + +#include "../../Common/MyTypes.h" // Sha1 implementation in RAR before version 3.60 has bug: // it changes data bytes in some cases. diff --git a/CPP/7zip/Crypto/Sha1Reg.cpp b/CPP/7zip/Crypto/Sha1Reg.cpp new file mode 100644 index 00000000..a32972e4 --- /dev/null +++ b/CPP/7zip/Crypto/Sha1Reg.cpp @@ -0,0 +1,55 @@ +// Sha1Reg.cpp + +#include "StdAfx.h" + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" +#include "../Common/RegisterCodec.h" + +#include "Sha1.h" + +using namespace NCrypto; +using namespace NSha1; + +class CSha1Hasher: + public IHasher, + public CMyUnknownImp +{ + CContext _sha; +public: + CSha1Hasher() { Init(); } + + MY_UNKNOWN_IMP + + STDMETHOD_(void, Init)(); + STDMETHOD_(void, Update)(const void *data, UInt32 size); + STDMETHOD_(void, Final)(Byte *digest); + STDMETHOD_(UInt32, GetDigestSize)(); +}; + +STDMETHODIMP_(void) CSha1Hasher::Init() +{ + _sha.Init(); +} + +STDMETHODIMP_(void) CSha1Hasher::Update(const void *data, UInt32 size) +{ + _sha.Update((const Byte *)data, size); +} + +STDMETHODIMP_(void) CSha1Hasher::Final(Byte *digest) +{ + _sha.Final(digest); +} + +STDMETHODIMP_(UInt32) CSha1Hasher::GetDigestSize() +{ + return kDigestSize; +} + +static IHasher *CreateHasher() { return new CSha1Hasher; } + +static CHasherInfo g_HasherInfo = { CreateHasher, 0x201, L"SHA1", kDigestSize }; + +REGISTER_HASHER(Sha1) diff --git a/CPP/7zip/Crypto/StdAfx.h b/CPP/7zip/Crypto/StdAfx.h old mode 100755 new mode 100644 index 99a8aa46..1cbd7fea --- a/CPP/7zip/Crypto/StdAfx.h +++ b/CPP/7zip/Crypto/StdAfx.h @@ -3,6 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../Common/MyWindows.h" +#include "../../Common/Common.h" #endif diff --git a/CPP/7zip/Crypto/WzAes.cpp b/CPP/7zip/Crypto/WzAes.cpp old mode 100755 new mode 100644 index 08a1818c..4194c02f --- a/CPP/7zip/Crypto/WzAes.cpp +++ b/CPP/7zip/Crypto/WzAes.cpp @@ -27,10 +27,9 @@ static const UInt32 kNumKeyGenIterations = 1000; STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size) { - if(size > kPasswordSizeMax) + if (size > kPasswordSizeMax) return E_INVALIDARG; - _key.Password.SetCapacity(size); - memcpy(_key.Password, data, size); + _key.Password.CopyFrom(data, (size_t)size); return S_OK; } @@ -59,7 +58,7 @@ STDMETHODIMP CBaseCoder::Init() #ifdef _NO_WZAES_OPTIMIZATIONS NSha1::Pbkdf2Hmac( - _key.Password, _key.Password.GetCapacity(), + _key.Password, _key.Password.Size(), _key.Salt, _key.GetSaltSize(), kNumKeyGenIterations, buf, keysTotalSize); @@ -72,7 +71,7 @@ STDMETHODIMP CBaseCoder::Init() UInt32 saltSizeInWords = _key.GetSaltSize() / 4; BytesToBeUInt32s(_key.Salt, salt, saltSizeInWords); NSha1::Pbkdf2Hmac32( - _key.Password, _key.Password.GetCapacity(), + _key.Password, _key.Password.Size(), salt, saltSizeInWords, kNumKeyGenIterations, buf32, key32SizeTotal); @@ -85,8 +84,8 @@ STDMETHODIMP CBaseCoder::Init() _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); + AesCtr2_Init(&_aes); return S_OK; } @@ -199,7 +198,7 @@ void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size) pos = 0; do *data++ ^= buf[pos++]; - while (--size != 0 && pos != AES_BLOCK_SIZE); + while (--size != 0); } p->pos = pos; } diff --git a/CPP/7zip/Crypto/WzAes.h b/CPP/7zip/Crypto/WzAes.h old mode 100755 new mode 100644 index f37fe644..980be8b3 --- a/CPP/7zip/Crypto/WzAes.h +++ b/CPP/7zip/Crypto/WzAes.h @@ -14,9 +14,8 @@ specified in password Based File Encryption Utility: #include "../../../C/Aes.h" -#include "Common/Buffer.h" -#include "Common/MyCom.h" -#include "Common/MyVector.h" +#include "../../Common/MyBuffer.h" +#include "../../Common/MyCom.h" #include "../ICoder.h" #include "../IPassword.h" diff --git a/CPP/7zip/Crypto/ZipCrypto.cpp b/CPP/7zip/Crypto/ZipCrypto.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/Crypto/ZipCrypto.h b/CPP/7zip/Crypto/ZipCrypto.h old mode 100755 new mode 100644 index 6f104beb..51b9e301 --- a/CPP/7zip/Crypto/ZipCrypto.h +++ b/CPP/7zip/Crypto/ZipCrypto.h @@ -3,7 +3,7 @@ #ifndef __CRYPTO_ZIP_CRYPTO_H #define __CRYPTO_ZIP_CRYPTO_H -#include "Common/MyCom.h" +#include "../../Common/MyCom.h" #include "../ICoder.h" #include "../IPassword.h" diff --git a/CPP/7zip/Crypto/ZipStrong.cpp b/CPP/7zip/Crypto/ZipStrong.cpp old mode 100755 new mode 100644 index 1554b348..a8765c26 --- a/CPP/7zip/Crypto/ZipStrong.cpp +++ b/CPP/7zip/Crypto/ZipStrong.cpp @@ -65,11 +65,16 @@ HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream, UInt32 /* crc */, UI if (_ivSize == 0) { return E_NOTIMPL; + + /* we don't know how to decode that case: + From Appnote: If IVSize is 0,then IV = CRC32 + Uncompressed File Size (as a 64 bit little-endian, unsigned integer value). + But it doesn't work. If you know solution, please write about it to 7-Zip developers. */ + /* - SetUi32(_iv, crc); - for (int i = 0; i < 8; i++) - _iv[4 + i] = (Byte)(unpackSize >> (8 * i)); - SetUi32(_iv + 12, 0); + memset(_iv, 0, 16); + // unpackSize += crc; + SetUi32(_iv + 0, crc); + SetUi64(_iv + 4, unpackSize); */ } else if (_ivSize == 16) @@ -83,10 +88,9 @@ HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream, UInt32 /* crc */, UI const UInt32 kAlign = 16; if (_remSize < 16 || _remSize > (1 << 18)) return E_NOTIMPL; - if (_remSize + kAlign > _buf.GetCapacity()) + if (_remSize + kAlign > _buf.Size()) { - _buf.Free(); - _buf.SetCapacity(_remSize + kAlign); + _buf.Alloc(_remSize + kAlign); _bufAligned = (Byte *)((ptrdiff_t)((Byte *)_buf + kAlign - 1) & ~(ptrdiff_t)(kAlign - 1)); } return ReadStream_FALSE(inStream, _bufAligned, _remSize); @@ -135,7 +139,7 @@ HRESULT CDecoder::CheckPassword(bool &passwOK) { RINOK(SetKey(_key.MasterKey, _key.KeySize)); RINOK(SetInitVector(_iv, 16)); - Init(); + RINOK(Init()); Filter(p, rdSize); } @@ -157,7 +161,8 @@ HRESULT CDecoder::CheckPassword(bool &passwOK) if (GetUi32(validData + validSize) != CrcCalc(validData, validSize)) return S_OK; passwOK = true; - Init(); + /* 9.31: The BUG in 9.24-9.30 was fixed. + We don't need to call CAesCbcCoder::Init() to reset IV for data. */ return S_OK; } diff --git a/CPP/7zip/Crypto/ZipStrong.h b/CPP/7zip/Crypto/ZipStrong.h old mode 100755 new mode 100644 index 151677ea..e3a43000 --- a/CPP/7zip/Crypto/ZipStrong.h +++ b/CPP/7zip/Crypto/ZipStrong.h @@ -3,7 +3,7 @@ #ifndef __CRYPTO_ZIP_STRONG_H #define __CRYPTO_ZIP_STRONG_H -#include "Common/Buffer.h" +#include "../../Common/MyBuffer.h" #include "../IPassword.h" diff --git a/CPP/7zip/GuiCommon.rc b/CPP/7zip/GuiCommon.rc old mode 100755 new mode 100644 index 736f94da..6b26ddd8 --- a/CPP/7zip/GuiCommon.rc +++ b/CPP/7zip/GuiCommon.rc @@ -1,7 +1,12 @@ -#include -#include +#include + +// #include +// #include + +// for Windows CE: #include + LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #undef m @@ -26,6 +31,10 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #undef marg2 #undef marg3 +#undef MY_DIALOG +#undef MY_RESIZE_DIALOG +#undef MY_PAGE + #define m 8 #define bxs 64 #define bys 16 @@ -54,8 +63,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #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_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 \ @@ -68,3 +77,5 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #define MY_COMBO_WITH_EDIT CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP #define MY_CHECKBOX "Button", BS_AUTOCHECKBOX | WS_TABSTOP + +#define MY_TEXT_NOPREFIX 8, SS_NOPREFIX diff --git a/CPP/7zip/Guid.txt b/CPP/7zip/Guid.txt old mode 100755 new mode 100644 index 0db316a5..8ded1f96 --- a/CPP/7zip/Guid.txt +++ b/CPP/7zip/Guid.txt @@ -6,14 +6,17 @@ 01 IFolderArchive.h - 05 IArchiveFolder + // 05 IArchiveFolder // old // 06 IInFolderArchive // old 07 IFileExtractCallback.h::IFolderArchiveExtractCallback - 0A IOutFolderArchive + // 0A IOutFolderArchive 0B IFolderArchiveUpdateCallback 0C Agent.h::IArchiveFolderInternal - 0D + 0D IArchiveFolder 0E IInFolderArchive + 0F IOutFolderArchive + 20 IFileExtractCallback.h::IGetProp + 30 IFileExtractCallback.h::IFolderExtractToStreamCallback 03 IStream.h @@ -23,6 +26,8 @@ 04 IOutStream 06 IStreamGetSize 07 IOutStreamFlush + 08 IStreamGetProps + 09 IStreamGetProps2 04 ICoder.h @@ -50,6 +55,8 @@ 8C ICryptoResetInitVector 90 ICryptoSetPassword A0 ICryptoSetCRC + C0 IHasher + C1 IHashers 05 IPassword.h @@ -61,6 +68,8 @@ 06 IArchive.h 03 ISetProperties + 04 IArchiveKeepModeForNextOpen + 05 IArchiveAllowTail 10 IArchiveOpenCallback 20 IArchiveExtractCallback @@ -69,6 +78,8 @@ 50 IArchiveOpenSetSubArchiveName 60 IInArchive 61 IArchiveOpenSeq + 70 IArchiveGetRawProps + 71 IArchiveGetRootProps 80 IArchiveUpdateCallback 82 IArchiveUpdateCallback2 @@ -96,7 +107,11 @@ 0F 10 IFolderArcProps 11 IGetFolderArcProps - 12 IFolderOperations + 12 // IFolderOperations + 13 IFolderOperations + 14 IFolderCalcItemFullSize + 15 IFolderCompare + 16 IFolderGetItemName 09 IFolder.h :: FOLDER_MANAGER_INTERFACE @@ -129,6 +144,8 @@ Handler GUIDs: 0C xz 0D ppmd + CD IHex + CE Hxs CF TE D0 UEFIc D1 UEFIs @@ -172,3 +189,4 @@ Handler GUIDs: {23170F69-40C1-2790-id} Codec Decoders {23170F69-40C1-2791-id} Codec Encoders +{23170F69-40C1-2792-id} Hashers diff --git a/CPP/7zip/ICoder.h b/CPP/7zip/ICoder.h old mode 100755 new mode 100644 index b43997d4..74ee0e45 --- a/CPP/7zip/ICoder.h +++ b/CPP/7zip/ICoder.h @@ -181,8 +181,31 @@ namespace NMethodPropID kOutStreams, kDescription, kDecoderIsAssigned, - kEncoderIsAssigned + kEncoderIsAssigned, + kDigestSize }; } +CODER_INTERFACE(IHasher, 0xC0) +{ + STDMETHOD_(void, Init)() PURE; + STDMETHOD_(void, Update)(const void *data, UInt32 size) PURE; + STDMETHOD_(void, Final)(Byte *digest) PURE; + STDMETHOD_(UInt32, GetDigestSize)() PURE; +}; + +CODER_INTERFACE(IHashers, 0xC1) +{ + STDMETHOD_(UInt32, GetNumHashers)() PURE; + STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE; + STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher) PURE; +}; + +extern "C" +{ + typedef HRESULT (WINAPI *Func_GetNumberOfMethods)(UInt32 *numMethods); + typedef HRESULT (WINAPI *Func_GetMethodProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); + typedef HRESULT (WINAPI *Func_GetHashers)(IHashers **hashers); +} + #endif diff --git a/CPP/7zip/IDecl.h b/CPP/7zip/IDecl.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/IPassword.h b/CPP/7zip/IPassword.h old mode 100755 new mode 100644 index 3ca7b090..7ea45537 --- a/CPP/7zip/IPassword.h +++ b/CPP/7zip/IPassword.h @@ -3,8 +3,8 @@ #ifndef __IPASSWORD_H #define __IPASSWORD_H +#include "../Common/MyTypes.h" #include "../Common/MyUnknown.h" -#include "../Common/Types.h" #include "IDecl.h" @@ -21,4 +21,3 @@ PASSWORD_INTERFACE(ICryptoGetTextPassword2, 0x11) }; #endif - diff --git a/CPP/7zip/IProgress.h b/CPP/7zip/IProgress.h old mode 100755 new mode 100644 index d6093f17..a270e693 --- a/CPP/7zip/IProgress.h +++ b/CPP/7zip/IProgress.h @@ -3,8 +3,8 @@ #ifndef __IPROGRESS_H #define __IPROGRESS_H +#include "../Common/MyTypes.h" #include "../Common/MyUnknown.h" -#include "../Common/Types.h" #include "IDecl.h" diff --git a/CPP/7zip/IStream.h b/CPP/7zip/IStream.h old mode 100755 new mode 100644 index 165e8baa..bf8dc4ca --- a/CPP/7zip/IStream.h +++ b/CPP/7zip/IStream.h @@ -3,8 +3,8 @@ #ifndef __ISTREAM_H #define __ISTREAM_H +#include "../Common/MyTypes.h" #include "../Common/MyUnknown.h" -#include "../Common/Types.h" #include "IDecl.h" @@ -21,6 +21,9 @@ STREAM_INTERFACE(ISequentialInStream, 0x01) 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 + + If seek pointer before Read() function call was changed to position past the + end of stream, the Read() function returns S_OK and *processedSize is set to 0. */ }; @@ -34,6 +37,20 @@ STREAM_INTERFACE(ISequentialOutStream, 0x02) */ }; + +#define HRESULT_WIN32_ERROR_NEGATIVE_SEEK __HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK) + +/* Seek() Function + If you seek before the beginning of the stream, Seek() function returns error code: + Recommended error code is __HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK). + or STG_E_INVALIDFUNCTION + + It is allowed to seek past the end of the stream. + + + if Seek() returns error, then the value of *newPosition is undefined. +*/ + STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; @@ -55,4 +72,28 @@ STREAM_INTERFACE(IOutStreamFlush, 0x07) STDMETHOD(Flush)() PURE; }; + +STREAM_INTERFACE(IStreamGetProps, 0x08) +{ + STDMETHOD(GetProps)(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib) PURE; +}; + +struct CStreamFileProps +{ + UInt64 Size; + UInt64 VolID; + UInt64 FileID_Low; + UInt64 FileID_High; + UInt32 NumLinks; + UInt32 Attrib; + FILETIME CTime; + FILETIME ATime; + FILETIME MTime; +}; + +STREAM_INTERFACE(IStreamGetProps2, 0x09) +{ + STDMETHOD(GetProps2)(CStreamFileProps *props) PURE; +}; + #endif diff --git a/CPP/7zip/MyVersion.h b/CPP/7zip/MyVersion.h old mode 100755 new mode 100644 index 2e657393..952333a8 --- a/CPP/7zip/MyVersion.h +++ b/CPP/7zip/MyVersion.h @@ -2,5 +2,5 @@ #undef MY_COPYRIGHT #undef MY_VERSION_COPYRIGHT_DATE -#define MY_COPYRIGHT "Copyright (c) 1999-2011 Igor Pavlov" +#define MY_COPYRIGHT "Copyright (c) 1999-2014 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 old mode 100755 new mode 100644 diff --git a/CPP/7zip/PropID.h b/CPP/7zip/PropID.h old mode 100755 new mode 100644 index 8f888526..cd56663e --- a/CPP/7zip/PropID.h +++ b/CPP/7zip/PropID.h @@ -1,13 +1,15 @@ // PropID.h -#ifndef __7ZIP_PROPID_H -#define __7ZIP_PROPID_H +#ifndef __7ZIP_PROP_ID_H +#define __7ZIP_PROP_ID_H + +#include "../Common/MyTypes.h" enum { kpidNoProperty = 0, - kpidMainSubfile = 1, - kpidHandlerItemIndex = 2, + kpidMainSubfile, + kpidHandlerItemIndex, kpidPath, kpidName, kpidExtension, @@ -59,18 +61,64 @@ enum kpidCreatorApp, kpidSectorSize, kpidPosixAttrib, - kpidLink, + kpidSymLink, kpidError, - - kpidTotalSize = 0x1100, + kpidTotalSize, kpidFreeSpace, kpidClusterSize, kpidVolumeName, - - kpidLocalName = 0x1200, + kpidLocalName, kpidProvider, + kpidNtSecure, + kpidIsAltStream, + kpidIsAux, + kpidIsDeleted, + kpidIsTree, + kpidSha1, + kpidSha256, + kpidErrorType, + kpidNumErrors, + kpidErrorFlags, + kpidWarningFlags, + kpidWarning, + kpidNumStreams, + kpidNumAltStreams, + kpidAltStreamsSize, + kpidVirtualSize, + kpidUnpackSize, + kpidTotalPhySize, + kpidVolumeIndex, + kpidSubType, + kpidShortComment, + kpidCodePage, + kpidIsNotArcType, + kpidPhySizeCantBeDetected, + kpidZerosTailIsAllowed, + kpidTailSize, + kpidEmbeddedStubSize, + kpidNtReparse, + kpidHardLink, + kpidINode, + kpidStreamId, + + kpid_NUM_DEFINED, kpidUserDefined = 0x10000 }; +Byte k7z_PROPID_To_VARTYPE[]; // VARTYPE + +const UInt32 kpv_ErrorFlags_IsNotArc = 1 << 0; +const UInt32 kpv_ErrorFlags_HeadersError = 1 << 1; +const UInt32 kpv_ErrorFlags_EncryptedHeadersError = 1 << 2; +const UInt32 kpv_ErrorFlags_UnavailableStart = 1 << 3; +const UInt32 kpv_ErrorFlags_UnconfirmedStart = 1 << 4; +const UInt32 kpv_ErrorFlags_UnexpectedEnd = 1 << 5; +const UInt32 kpv_ErrorFlags_DataAfterEnd = 1 << 6; +const UInt32 kpv_ErrorFlags_UnsupportedMethod = 1 << 7; +const UInt32 kpv_ErrorFlags_UnsupportedFeature = 1 << 8; +const UInt32 kpv_ErrorFlags_DataError = 1 << 9; +const UInt32 kpv_ErrorFlags_CrcError = 1 << 10; +// const UInt32 kpv_ErrorFlags_Unsupported = 1 << 11; + #endif diff --git a/CPP/7zip/SubBuild.mak b/CPP/7zip/SubBuild.mak old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/Agent/Agent.cpp b/CPP/7zip/UI/Agent/Agent.cpp old mode 100755 new mode 100644 index c11bd490..e4f46f0a --- a/CPP/7zip/UI/Agent/Agent.cpp +++ b/CPP/7zip/UI/Agent/Agent.cpp @@ -4,9 +4,12 @@ #include "../../../../C/Sort.h" -#include "Common/ComTry.h" +#include "../../../Common/ComTry.h" + +#include "../../../Windows/PropVariantConv.h" #include "../Common/ArchiveExtractCallback.h" +#include "../FileManager/RegistryUtils.h" #include "Agent.h" @@ -18,19 +21,37 @@ STDMETHODIMP CAgentFolder::GetAgentFolder(CAgentFolder **agentFolder) return S_OK; } -void CAgentFolder::LoadFolder(const CProxyFolder *folder) +void CAgentFolder::LoadFolder(unsigned proxyFolderIndex) { - int i; + unsigned i; CProxyItem item; - item.Folder = folder; - for (i = 0; i < folder->Folders.Size(); i++) + item.ProxyFolderIndex = proxyFolderIndex; + if (_proxyArchive2) + { + const CProxyFolder2 &folder = _proxyArchive2->Folders[proxyFolderIndex]; + for (i = 0; i < folder.SubFiles.Size(); i++) + { + item.Index = i; + _items.Add(item); + const CProxyFile2 &file = _proxyArchive2->Files[folder.SubFiles[i]]; + int subFolderIndex = file.FolderIndex; + if (subFolderIndex >= 0) + LoadFolder(subFolderIndex); + subFolderIndex = file.AltStreamsFolderIndex; + if (subFolderIndex >= 0) + LoadFolder(subFolderIndex); + } + return; + } + const CProxyFolder &folder = _proxyArchive->Folders[proxyFolderIndex]; + for (i = 0; i < folder.Folders.Size(); i++) { item.Index = i; _items.Add(item); - LoadFolder(&folder->Folders[i]); + LoadFolder(folder.Folders[i]); } - int start = folder->Folders.Size(); - for (i = 0; i < folder->Files.Size(); i++) + unsigned start = folder.Folders.Size(); + for (i = 0; i < folder.Files.Size(); i++) { item.Index = start + i; _items.Add(item); @@ -51,58 +72,210 @@ STDMETHODIMP CAgentFolder::GetNumberOfItems(UInt32 *numItems) { if (_flatMode) *numItems = _items.Size(); + else if (_proxyArchive2) + *numItems = _proxyArchive2->Folders[_proxyFolderItem].SubFiles.Size(); else - *numItems = _proxyFolderItem->Folders.Size() +_proxyFolderItem->Files.Size(); + { + const CProxyFolder *folder = &_proxyArchive->Folders[_proxyFolderItem]; + *numItems = folder->Folders.Size() + folder ->Files.Size(); + } return S_OK; } #define SET_realIndex_AND_folder \ UInt32 realIndex; const CProxyFolder *folder; \ - if (_flatMode) { const CProxyItem &item = _items[index]; folder = item.Folder; realIndex = item.Index; } \ - else { folder = _proxyFolderItem; realIndex = index; } + if (_flatMode) { const CProxyItem &item = _items[index]; folder = &_proxyArchive->Folders[item.ProxyFolderIndex]; realIndex = item.Index; } \ + else { folder = &_proxyArchive->Folders[_proxyFolderItem]; realIndex = index; } +#define SET_realIndex_AND_folder_2 \ + UInt32 realIndex; const CProxyFolder2 *folder; \ + if (_flatMode) { const CProxyItem &item = _items[index]; folder = &_proxyArchive2->Folders[item.ProxyFolderIndex]; realIndex = item.Index; } \ + else { folder = &_proxyArchive2->Folders[_proxyFolderItem]; realIndex = index; } UString CAgentFolder::GetName(UInt32 index) const { + if (_proxyArchive2) + { + SET_realIndex_AND_folder_2 + return _proxyArchive2->Files[folder->SubFiles[realIndex]].Name; + } SET_realIndex_AND_folder if (realIndex < (UInt32)folder->Folders.Size()) - return folder->Folders[realIndex].Name; + return _proxyArchive->Folders[folder->Folders[realIndex]].Name; return folder->Files[realIndex - folder->Folders.Size()].Name; } -UString CAgentFolder::GetPrefix(UInt32 index) const +void CAgentFolder::GetPrefix(UInt32 index, UString &prefix) const { if (!_flatMode) - return UString(); + { + prefix.Empty(); + return; + } const CProxyItem &item = _items[index]; - const CProxyFolder *folder = item.Folder; - UString path; - while (folder != _proxyFolderItem) + unsigned proxyIndex = item.ProxyFolderIndex; + unsigned totalLen; + if (_proxyArchive2) { - path = folder->Name + UString(WCHAR_PATH_SEPARATOR) + path; - folder = folder->Parent; + unsigned len = 0; + while (proxyIndex != _proxyFolderItem) + { + const CProxyFile2 &file = _proxyArchive2->Files[_proxyArchive2->Folders[proxyIndex].ArcIndex]; + len += file.NameSize + 1; + proxyIndex = (file.Parent < 0) ? 0 : _proxyArchive2->Files[file.Parent].GetFolderIndex(file.IsAltStream); + } + totalLen = len; + + wchar_t *p = prefix.GetBuffer(len); + proxyIndex = item.ProxyFolderIndex; + while (proxyIndex != _proxyFolderItem) + { + const CProxyFile2 &file = _proxyArchive2->Files[_proxyArchive2->Folders[proxyIndex].ArcIndex]; + MyStringCopy(p + len - file.NameSize - 1, file.Name); + p[--len] = WCHAR_PATH_SEPARATOR; + len -= file.NameSize; + proxyIndex = (file.Parent < 0) ? 0 : _proxyArchive2->Files[file.Parent].GetFolderIndex(file.IsAltStream); + } + } + else + { + unsigned len = 0; + while (proxyIndex != _proxyFolderItem) + { + const CProxyFolder *folder = &_proxyArchive->Folders[proxyIndex]; + len += folder->Name.Len() + 1; + proxyIndex = folder->Parent; + } + totalLen = len; + + wchar_t *p = prefix.GetBuffer(len); + proxyIndex = item.ProxyFolderIndex; + while (proxyIndex != _proxyFolderItem) + { + const CProxyFolder *folder = &_proxyArchive->Folders[proxyIndex]; + MyStringCopy(p + len - folder->Name.Len() - 1, (const wchar_t *)folder->Name); + p[--len] = WCHAR_PATH_SEPARATOR; + len -= folder->Name.Len(); + proxyIndex = folder->Parent; + } } - return path; + prefix.ReleaseBuffer(totalLen); } UString CAgentFolder::GetFullPathPrefixPlusPrefix(UInt32 index) const { - return _proxyFolderItem->GetFullPathPrefix() + GetPrefix(index); + UString prefix; + GetPrefix(index, prefix); + if (_proxyArchive2) + return _proxyArchive2->GetFullPathPrefix(_proxyFolderItem) + prefix; + else + return _proxyArchive->GetFullPathPrefix(_proxyFolderItem) + prefix; +} + +STDMETHODIMP_(UInt64) CAgentFolder::GetItemSize(UInt32 index) +{ + unsigned arcIndex; + if (_proxyArchive2) + { + SET_realIndex_AND_folder_2 + arcIndex = folder->SubFiles[realIndex]; + const CProxyFile2 &item = _proxyArchive2->Files[arcIndex]; + if (item.IsDir()) + { + const CProxyFolder2 &itemFolder = _proxyArchive2->Folders[item.FolderIndex]; + if (!_flatMode) + return itemFolder.Size; + } + } + else + { + SET_realIndex_AND_folder + if (realIndex < (UInt32)folder->Folders.Size()) + { + const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]]; + if (!_flatMode) + return item.Size; + arcIndex = item.Index; + } + else + { + const CProxyFile &item = folder->Files[realIndex - folder->Folders.Size()]; + arcIndex = item.Index; + } + } + NCOM::CPropVariant prop; + _agentSpec->GetArchive()->GetProperty(arcIndex, kpidSize, &prop); + if (prop.vt == VT_UI8) + return prop.uhVal.QuadPart; + else + return 0; } STDMETHODIMP CAgentFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; - SET_realIndex_AND_folder + if (propID == kpidPrefix) { if (_flatMode) - prop = GetPrefix(index); + { + UString prefix; + GetPrefix(index, prefix); + prop = prefix; + } + } + else if (_proxyArchive2) + { + SET_realIndex_AND_folder_2 + unsigned arcIndex = folder->SubFiles[realIndex]; + const CProxyFile2 &item = _proxyArchive2->Files[arcIndex]; + if (!item.IsDir()) + { + switch (propID) + { + case kpidIsDir: prop = false; break; + case kpidName: prop = item.Name; break; + default: return _agentSpec->GetArchive()->GetProperty(arcIndex, propID, value); + } + } + else + { + const CProxyFolder2 &itemFolder = _proxyArchive2->Folders[item.FolderIndex]; + if (!_flatMode && propID == kpidSize) + prop = itemFolder.Size; + else if (!_flatMode && propID == kpidPackSize) + prop = itemFolder.PackSize; + else switch (propID) + { + case kpidIsDir: prop = true; break; + case kpidNumSubDirs: prop = itemFolder.NumSubFolders; break; + case kpidNumSubFiles: prop = itemFolder.NumSubFiles; break; + case kpidName: prop = item.Name; break; + case kpidCRC: + { + // if (itemFolder.IsLeaf) + if (!item.Ignore) + { + RINOK(_agentSpec->GetArchive()->GetProperty(arcIndex, propID, value)); + } + if (itemFolder.CrcIsDefined && value->vt == VT_EMPTY) + prop = itemFolder.Crc; + break; + } + default: + // if (itemFolder.IsLeaf) + if (!item.Ignore) + return _agentSpec->GetArchive()->GetProperty(arcIndex, propID, value); + } + } } - else if (realIndex < (UInt32)folder->Folders.Size()) + else { - const CProxyFolder &item = folder->Folders[realIndex]; + SET_realIndex_AND_folder + if (realIndex < (UInt32)folder->Folders.Size()) + { + const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]]; if (!_flatMode && propID == kpidSize) prop = item.Size; else if (!_flatMode && propID == kpidPackSize) @@ -140,23 +313,457 @@ STDMETHODIMP CAgentFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT return _agentSpec->GetArchive()->GetProperty(item.Index, propID, value); } } + } prop.Detach(value); return S_OK; COM_TRY_END } -HRESULT CAgentFolder::BindToFolder(const CProxyFolder *folder, IFolderFolder **resultFolder) +static UInt64 GetUInt64Prop(IInArchive *archive, UInt32 index, PROPID propID) +{ + NCOM::CPropVariant prop; + if (archive->GetProperty(index, propID, &prop) != S_OK) + throw 111233443; + UInt64 v = 0; + if (ConvertPropVariantToUInt64(prop, v)) + return v; + return 0; +} + +STDMETHODIMP CAgentFolder::GetItemName(UInt32 index, const wchar_t **name, unsigned *len) +{ + if (_proxyArchive2) + { + SET_realIndex_AND_folder_2 + unsigned arcIndex = folder->SubFiles[realIndex]; + const CProxyFile2 &item = _proxyArchive2->Files[arcIndex]; + *name = item.Name; + *len = item.NameSize; + return S_OK; + } + else + { + SET_realIndex_AND_folder + if (realIndex < (UInt32)folder->Folders.Size()) + { + const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]]; + *name = item.Name; + *len = item.Name.Len(); + return S_OK; + } + else + { + const CProxyFile &item = folder->Files[realIndex - folder->Folders.Size()]; + *name = item.Name; + *len = item.Name.Len(); + return S_OK; + } + } +} + +STDMETHODIMP CAgentFolder::GetItemPrefix(UInt32 index, const wchar_t **name, unsigned *len) +{ + *name = 0; + *len = 0; + if (!_flatMode) + return S_OK; + if (_proxyArchive2) + { + SET_realIndex_AND_folder_2 + + unsigned arcIndex = folder->SubFiles[realIndex]; + const CProxyFile2 &item = _proxyArchive2->Files[arcIndex]; + if (item.Parent >= 0) + { + const CProxyFile2 &item2 = _proxyArchive2->Files[item.Parent]; + int foldInd = item2.GetFolderIndex(item.IsAltStream); + if (foldInd >= 0) + { + const UString &s = _proxyArchive2->Folders[foldInd].PathPrefix; + unsigned baseLen = _proxyArchive2->Folders[_proxyFolderItem].PathPrefix.Len(); + if (baseLen <= s.Len()) + { + *name = (const wchar_t *)s + baseLen; + *len = s.Len() - baseLen; + } + } + } + } + return S_OK; +} + +static int CompareRawProps(IArchiveGetRawProps *rawProps, int arcIndex1, int arcIndex2, PROPID propID) +{ + // if (propID == kpidSha1) + if (rawProps) + { + const void *p1, *p2; + UInt32 size1, size2; + UInt32 propType1, propType2; + HRESULT res1 = rawProps->GetRawProp(arcIndex1, propID, &p1, &size1, &propType1); + HRESULT res2 = rawProps->GetRawProp(arcIndex2, propID, &p2, &size2, &propType2); + if (res1 == S_OK && res2 == S_OK) + { + for (UInt32 i = 0; i < size1 && i < size2; i++) + { + Byte b1 = ((const Byte *)p1)[i]; + Byte b2 = ((const Byte *)p2)[i]; + if (b1 < b2) return -1; + if (b1 > b2) return 1; + } + if (size1 < size2) return -1; + if (size1 > size2) return 1; + return 0; + } + } + return 0; +} + +// returns pointer to extension including '.' + +static const wchar_t *GetExtension(const wchar_t *name) +{ + for (const wchar_t *dotPtr = NULL;; name++) + { + wchar_t c = *name; + if (c == 0) + return dotPtr ? dotPtr : name; + if (c == '.') + dotPtr = name; + } +} + +int CAgentFolder::CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw) +{ + UInt32 realIndex1, realIndex2; + const CProxyFolder2 *folder1, *folder2; + + if (_flatMode) + { + const CProxyItem &item1 = _items[index1]; + const CProxyItem &item2 = _items[index2]; + folder1 = &_proxyArchive2->Folders[item1.ProxyFolderIndex]; + folder2 = &_proxyArchive2->Folders[item2.ProxyFolderIndex]; + realIndex1 = item1.Index; + realIndex2 = item2.Index; + } + else + { + folder2 = folder1 = &_proxyArchive2->Folders[_proxyFolderItem]; + realIndex1 = index1; + realIndex2 = index2; + } + + UInt32 arcIndex1; + UInt32 arcIndex2; + bool isDir1, isDir2; + arcIndex1 = folder1->SubFiles[realIndex1]; + arcIndex2 = folder2->SubFiles[realIndex2]; + const CProxyFile2 &prox1 = _proxyArchive2->Files[arcIndex1]; + const CProxyFile2 &prox2 = _proxyArchive2->Files[arcIndex2]; + + if (propID == kpidName) + { + return CompareFileNames_ForFolderList(prox1.Name, prox2.Name); + } + + if (propID == kpidPrefix) + { + if (!_flatMode) + return 0; + if (prox1.Parent < 0) return prox2.Parent < 0 ? 0 : -1; + if (prox2.Parent < 0) return 1; + + const CProxyFile2 &proxPar1 = _proxyArchive2->Files[prox1.Parent]; + const CProxyFile2 &proxPar2 = _proxyArchive2->Files[prox2.Parent]; + return CompareFileNames_ForFolderList( + _proxyArchive2->Folders[proxPar1.GetFolderIndex(prox1.IsAltStream)].PathPrefix, + _proxyArchive2->Folders[proxPar2.GetFolderIndex(prox2.IsAltStream)].PathPrefix); + } + + if (propID == kpidExtension) + { + return CompareFileNames_ForFolderList( + GetExtension(prox1.Name), + GetExtension(prox2.Name)); + } + + isDir1 = prox1.IsDir(); + isDir2 = prox2.IsDir(); + + if (propID == kpidIsDir) + { + if (isDir1 == isDir2) + return 0; + return isDir1 ? -1 : 1; + } + + const CProxyFolder2 *proxFolder1 = NULL; + const CProxyFolder2 *proxFolder2 = NULL; + if (isDir1) proxFolder1 = &_proxyArchive2->Folders[prox1.FolderIndex]; + if (isDir2) proxFolder2 = &_proxyArchive2->Folders[prox2.FolderIndex]; + + if (propID == kpidNumSubDirs) + { + UInt32 n1 = 0; + UInt32 n2 = 0; + if (isDir1) n1 = proxFolder1->NumSubFolders; + if (isDir2) n2 = proxFolder2->NumSubFolders; + return MyCompare(n1, n2); + } + + if (propID == kpidNumSubFiles) + { + UInt32 n1 = 0; + UInt32 n2 = 0; + if (isDir1) n1 = proxFolder1->NumSubFiles; + if (isDir2) n2 = proxFolder2->NumSubFiles; + return MyCompare(n1, n2); + } + + if (propID == kpidSize) + { + UInt64 n1, n2; + if (isDir1) + n1 = _flatMode ? 0 : proxFolder1->Size; + else + n1 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex1, kpidSize); + if (isDir2) + n2 = _flatMode ? 0 : proxFolder2->Size; + else + n2 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex2, kpidSize); + return MyCompare(n1, n2); + } + + if (propID == kpidPackSize) + { + UInt64 n1, n2; + if (isDir1) + n1 = _flatMode ? 0 : proxFolder1->PackSize; + else + n1 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex1, kpidPackSize); + if (isDir2) + n2 = _flatMode ? 0 : proxFolder2->PackSize; + else + n2 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex2, kpidPackSize); + return MyCompare(n1, n2); + } + + if (propID == kpidCRC) + { + UInt64 n1, n2; + if (!isDir1 || !prox1.Ignore) + n1 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex1, kpidCRC); + else + n1 = proxFolder1->Crc; + if (!isDir2 || !prox2.Ignore) + n2 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex2, kpidCRC); + else + n2 = proxFolder2->Crc; + return MyCompare(n1, n2); + } + + if (propIsRaw) + return CompareRawProps(_agentSpec->_archiveLink.GetArchiveGetRawProps(), arcIndex1, arcIndex2, propID); + + NCOM::CPropVariant prop1, prop2; + // Name must be first property + GetProperty(index1, propID, &prop1); + GetProperty(index2, 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); +} + +STDMETHODIMP_(Int32) CAgentFolder::CompareItems(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw) +{ + COM_TRY_BEGIN + if (_proxyArchive2) + return CompareItems2(index1, index2, propID, propIsRaw); + UInt32 realIndex1, realIndex2; + const CProxyFolder *folder1, *folder2; + + if (_flatMode) + { + const CProxyItem &item1 = _items[index1]; + const CProxyItem &item2 = _items[index2]; + folder1 = &_proxyArchive->Folders[item1.ProxyFolderIndex]; + folder2 = &_proxyArchive->Folders[item2.ProxyFolderIndex]; + realIndex1 = item1.Index; + realIndex2 = item2.Index; + } + else + { + folder2 = folder1 = &_proxyArchive->Folders[_proxyFolderItem]; + realIndex1 = index1; + realIndex2 = index2; + } + if (propID == kpidPrefix) + { + if (!_flatMode) + return 0; + UString prefix1, prefix2; + GetPrefix(index1, prefix1); + GetPrefix(index2, prefix2); + return CompareFileNames_ForFolderList(prefix1, prefix2); + } + const CProxyFile *prox1; + const CProxyFile *prox2; + const CProxyFolder *proxFolder1 = NULL; + const CProxyFolder *proxFolder2 = NULL; + bool isDir1, isDir2; + if (realIndex1 < (UInt32)folder1->Folders.Size()) + { + isDir1 = true; + prox1 = proxFolder1 = &_proxyArchive->Folders[folder1->Folders[realIndex1]]; + } + else + { + isDir1 = false; + prox1 = &folder1->Files[realIndex1 - folder1->Folders.Size()]; + } + + if (realIndex2 < (UInt32)folder2->Folders.Size()) + { + isDir2 = true; + prox2 = proxFolder2 = &_proxyArchive->Folders[folder2->Folders[realIndex2]]; + } + else + { + isDir2 = false; + prox2 = &folder2->Files[realIndex2 - folder2->Folders.Size()]; + } + + if (propID == kpidName) + { + return CompareFileNames_ForFolderList(prox1->Name, prox2->Name); + } + if (propID == kpidExtension) + { + return CompareFileNames_ForFolderList( + GetExtension(prox1->Name), + GetExtension(prox2->Name)); + } + + if (propID == kpidIsDir) + { + if (isDir1 == isDir2) + return 0; + return isDir1 ? -1 : 1; + } + if (propID == kpidNumSubDirs) + { + UInt32 n1 = 0; + UInt32 n2 = 0; + if (isDir1) n1 = proxFolder1->NumSubFolders; + if (isDir2) n2 = proxFolder2->NumSubFolders; + return MyCompare(n1, n2); + } + if (propID == kpidNumSubFiles) + { + UInt32 n1 = 0; + UInt32 n2 = 0; + if (isDir1) n1 = proxFolder1->NumSubFiles; + if (isDir2) n2 = proxFolder2->NumSubFiles; + return MyCompare(n1, n2); + } + if (propID == kpidSize) + { + UInt64 n1, n2; + if (isDir1) + n1 = _flatMode ? 0 : proxFolder1->Size; + else + n1 = GetUInt64Prop(_agentSpec->GetArchive(), prox1->Index, kpidSize); + if (isDir2) + n2 = _flatMode ? 0 : proxFolder2->Size; + else + n2 = GetUInt64Prop(_agentSpec->GetArchive(), prox2->Index, kpidSize); + return MyCompare(n1, n2); + } + if (propID == kpidPackSize) + { + UInt64 n1, n2; + if (isDir1) + n1 = _flatMode ? 0 : proxFolder1->PackSize; + else + n1 = GetUInt64Prop(_agentSpec->GetArchive(), prox1->Index, kpidPackSize); + if (isDir2) + n2 = _flatMode ? 0 : proxFolder2->PackSize; + else + n2 = GetUInt64Prop(_agentSpec->GetArchive(), prox2->Index, kpidPackSize); + return MyCompare(n1, n2); + } + + if (propID == kpidCRC) + { + UInt64 n1, n2; + if (!isDir1 || proxFolder1->IsLeaf) + n1 = GetUInt64Prop(_agentSpec->GetArchive(), prox1->Index, kpidCRC); + else + n1 = proxFolder1->Crc; + if (!isDir2 || proxFolder2->IsLeaf) + n2 = GetUInt64Prop(_agentSpec->GetArchive(), prox2->Index, kpidCRC); + else + n2 = proxFolder2->Crc; + return MyCompare(n1, n2); + } + + if (propIsRaw) + return CompareRawProps(_agentSpec->_archiveLink.GetArchiveGetRawProps(), prox1->Index, prox2->Index, propID); + + NCOM::CPropVariant prop1, prop2; + // Name must be first property + GetProperty(index1, propID, &prop1); + GetProperty(index2, 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); + + COM_TRY_END +} + +HRESULT CAgentFolder::BindToFolder_Internal(unsigned proxyFolderIndex, IFolderFolder **resultFolder) { CMyComPtr parentFolder; - if (folder->Parent != _proxyFolderItem) + + if (_proxyArchive2) { - RINOK(BindToFolder(folder->Parent, &parentFolder)); + parentFolder = NULL; // Change it; + const CProxyFolder2 &folder = _proxyArchive2->Folders[proxyFolderIndex]; + int par = _proxyArchive2->GetParentFolderOfFile(folder.ArcIndex); + if (par != (int)_proxyFolderItem) + { + // return E_FAIL; + RINOK(BindToFolder_Internal(par, &parentFolder)); + } + else + parentFolder = this; } else - parentFolder = this; + { + const CProxyFolder &folder = _proxyArchive->Folders[proxyFolderIndex]; + if (folder.Parent != (int)_proxyFolderItem) + { + RINOK(BindToFolder_Internal(folder.Parent, &parentFolder)); + } + else + parentFolder = this; + } CAgentFolder *folderSpec = new CAgentFolder; CMyComPtr agentFolder = folderSpec; - folderSpec->Init(_proxyArchive, folder, parentFolder, _agentSpec); + folderSpec->Init(_proxyArchive, _proxyArchive2, proxyFolderIndex, parentFolder, _agentSpec); *resultFolder = agentFolder.Detach(); return S_OK; } @@ -164,30 +771,51 @@ HRESULT CAgentFolder::BindToFolder(const CProxyFolder *folder, IFolderFolder **r STDMETHODIMP CAgentFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder) { COM_TRY_BEGIN + if (_proxyArchive2) + { + SET_realIndex_AND_folder_2 + unsigned arcIndex = folder->SubFiles[realIndex]; + const CProxyFile2 &item = _proxyArchive2->Files[arcIndex]; + if (!item.IsDir()) + return E_INVALIDARG; + return BindToFolder_Internal(item.FolderIndex, resultFolder); + } SET_realIndex_AND_folder if (realIndex >= (UInt32)folder->Folders.Size()) return E_INVALIDARG; - return BindToFolder(&folder->Folders[realIndex], resultFolder); + return BindToFolder_Internal(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 (_proxyArchive2) + { + const CProxyFolder2 &folder = _proxyArchive2->Folders[_proxyFolderItem]; + FOR_VECTOR (i, folder.SubFiles) + { + const CProxyFile2 &file = _proxyArchive2->Files[folder.SubFiles[i]]; + if (file.FolderIndex >= 0) + if (StringsAreEqualNoCase(file.Name, name)) + return BindToFolder_Internal(file.FolderIndex, resultFolder); + } + return E_INVALIDARG; + } + int index = _proxyArchive->FindDirSubItemIndex(_proxyFolderItem, name); if (index < 0) return E_INVALIDARG; - return BindToFolder(index, resultFolder); + return BindToFolder_Internal(index, resultFolder); COM_TRY_END } STDMETHODIMP CAgentFolder::BindToParentFolder(IFolderFolder **resultFolder) { - COM_TRY_BEGIN + // COM_TRY_BEGIN CMyComPtr parentFolder = _parentFolder; *resultFolder = parentFolder.Detach(); return S_OK; - COM_TRY_END + // COM_TRY_END } STDMETHODIMP CAgentFolder::GetStream(UInt32 index, ISequentialInStream **stream) @@ -197,30 +825,36 @@ STDMETHODIMP CAgentFolder::GetStream(UInt32 index, ISequentialInStream **stream) if (!getStream) return S_OK; + UInt32 indexInArchive; + if (_proxyArchive2) + { + SET_realIndex_AND_folder_2 + indexInArchive = folder->SubFiles[realIndex]; + } + else + { SET_realIndex_AND_folder - UInt32 indexInArchive; if (realIndex < (UInt32)folder->Folders.Size()) { - const CProxyFolder &item = folder->Folders[realIndex]; + const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]]; if (!item.IsLeaf) return S_OK; indexInArchive = item.Index; } else indexInArchive = folder->Files[realIndex - folder->Folders.Size()].Index; + } return getStream->GetStream(indexInArchive, stream); } -static const STATPROPSTG kProperties[] = +static const PROPID kProps[] = { - { NULL, kpidNumSubDirs, VT_UI4}, - { NULL, kpidNumSubFiles, VT_UI4}, - { NULL, kpidPrefix, VT_BSTR} + kpidNumSubDirs, + kpidNumSubFiles, + kpidPrefix }; -static const UInt32 kNumProperties = sizeof(kProperties) / sizeof(kProperties[0]); - struct CArchiveItemPropertyTemp { UString Name; @@ -232,10 +866,18 @@ STDMETHODIMP CAgentFolder::GetNumberOfProperties(UInt32 *numProps) { COM_TRY_BEGIN RINOK(_agentSpec->GetArchive()->GetNumberOfProperties(numProps)); - *numProps += kNumProperties; + *numProps += ARRAY_SIZE(kProps); if (!_flatMode) (*numProps)--; - if (!_agentSpec->_proxyArchive->ThereIsPathProp) + /* + bool thereIsPathProp = _proxyArchive2 ? + _agentSpec->_proxyArchive2->ThereIsPathProp : + _agentSpec->_proxyArchive->ThereIsPathProp; + */ + + // if there is kpidPath, we change kpidPath to kpidName + // if there is no kpidPath, we add kpidName. + if (!_agentSpec->ThereIsPathProp) (*numProps)++; return S_OK; COM_TRY_END @@ -246,7 +888,14 @@ STDMETHODIMP CAgentFolder::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *pro COM_TRY_BEGIN UInt32 numProps; _agentSpec->GetArchive()->GetNumberOfProperties(&numProps); - if (!_agentSpec->_proxyArchive->ThereIsPathProp) + + /* + bool thereIsPathProp = _proxyArchive2 ? + _agentSpec->_proxyArchive2->ThereIsPathProp : + _agentSpec->_proxyArchive->ThereIsPathProp; + */ + + if (!_agentSpec->ThereIsPathProp) { if (index == 0) { @@ -266,40 +915,68 @@ STDMETHODIMP CAgentFolder::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *pro } else { - const STATPROPSTG &srcItem = kProperties[index - numProps]; - *propID = srcItem.propid; - *varType = srcItem.vt; + *propID = kProps[index - numProps]; + *varType = k7z_PROPID_To_VARTYPE[(unsigned)*propID]; *name = 0; } return S_OK; COM_TRY_END } -static const STATPROPSTG kFolderProps[] = +static const PROPID kFolderProps[] = { - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, - { NULL, kpidNumSubDirs, VT_UI4}, - { NULL, kpidNumSubFiles, VT_UI4}, - { NULL, kpidCRC, VT_UI4} + kpidSize, + kpidPackSize, + kpidNumSubDirs, + kpidNumSubFiles, + kpidCRC }; -static const UInt32 kNumFolderProps = sizeof(kFolderProps) / sizeof(kFolderProps[0]); - STDMETHODIMP CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + + if (_proxyArchive2) + { + const CProxyFolder2 &folder = _proxyArchive2->Folders[_proxyFolderItem]; + if (propID == kpidName) + { + if (folder.ArcIndex >= 0) + prop = _proxyArchive2->Files[folder.ArcIndex].Name; + } + else if (propID == kpidPath) + { + prop = _proxyArchive2->GetFullPathPrefix(_proxyFolderItem); + } + else switch (propID) + { + case kpidSize: prop = folder.Size; break; + case kpidPackSize: prop = folder.PackSize; break; + case kpidNumSubDirs: prop = folder.NumSubFolders; break; + case kpidNumSubFiles: prop = folder.NumSubFiles; break; + // case kpidName: prop = folder.Name; break; + // case kpidPath: prop = _proxyArchive2->GetFullPathPrefix(_proxyFolderItem); break; + case kpidType: prop = UString(L"7-Zip.") + _agentSpec->ArchiveType; break; + case kpidCRC: if (folder.CrcIsDefined) prop = folder.Crc; break; + } + + } + else + { + const CProxyFolder &folder = _proxyArchive->Folders[_proxyFolderItem]; 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 kpidSize: prop = folder.Size; break; + case kpidPackSize: prop = folder.PackSize; break; + case kpidNumSubDirs: prop = folder.NumSubFolders; break; + case kpidNumSubFiles: prop = folder.NumSubFiles; break; + case kpidName: prop = folder.Name; break; + case kpidPath: prop = _proxyArchive->GetFullPathPrefix(_proxyFolderItem); break; case kpidType: prop = UString(L"7-Zip.") + _agentSpec->ArchiveType; break; - case kpidCRC: if (_proxyFolderItem->CrcIsDefined) prop = _proxyFolderItem->Crc; break; + case kpidCRC: if (folder.CrcIsDefined) prop = folder.Crc; break; + } } prop.Detach(value); return S_OK; @@ -308,20 +985,73 @@ STDMETHODIMP CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) STDMETHODIMP CAgentFolder::GetNumberOfFolderProperties(UInt32 *numProps) { - *numProps = kNumFolderProps; + *numProps = ARRAY_SIZE(kFolderProps); return S_OK; } -STDMETHODIMP CAgentFolder::GetFolderPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) +STDMETHODIMP CAgentFolder::GetFolderPropertyInfo IMP_IFolderFolder_GetProp(kFolderProps) + +STDMETHODIMP CAgentFolder::GetParent(UInt32 /* index */, UInt32 * /* parent */, UInt32 * /* parentType */) { - // if (index < kNumFolderProps) + return E_FAIL; +} + + +STDMETHODIMP CAgentFolder::GetNumRawProps(UInt32 *numProps) +{ + IArchiveGetRawProps *rawProps = _agentSpec->_archiveLink.GetArchiveGetRawProps(); + if (rawProps) + return rawProps->GetNumRawProps(numProps); + *numProps = 0; + return S_OK; +} + +STDMETHODIMP CAgentFolder::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID) +{ + IArchiveGetRawProps *rawProps = _agentSpec->_archiveLink.GetArchiveGetRawProps(); + if (rawProps) + return rawProps->GetRawPropInfo(index, name, propID); + return E_FAIL; +} + +STDMETHODIMP CAgentFolder::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) +{ + IArchiveGetRawProps *rawProps = _agentSpec->_archiveLink.GetArchiveGetRawProps(); + if (rawProps) { - const STATPROPSTG &srcItem = kFolderProps[index]; - *propID = srcItem.propid; - *varType = srcItem.vt; - *name = 0; - return S_OK; + unsigned arcIndex; + if (_proxyArchive2) + { + SET_realIndex_AND_folder_2 + arcIndex = folder->SubFiles[realIndex]; + } + else + { + SET_realIndex_AND_folder + if (realIndex < (UInt32)folder->Folders.Size()) + { + const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]]; + if (!item.IsLeaf) + { + *data = NULL; + *dataSize = 0; + *propType = 0; + return S_OK; + } + arcIndex = item.Index; + } + else + { + const CProxyFile &item = folder->Files[realIndex - folder->Folders.Size()]; + arcIndex = item.Index; + } + } + return rawProps->GetRawProp(arcIndex, propID, data, dataSize, propType); } + *data = NULL; + *dataSize = 0; + *propType = 0; + return S_OK; } STDMETHODIMP CAgentFolder::GetFolderArcProps(IFolderArcProps **object) @@ -341,28 +1071,86 @@ STDMETHODIMP CAgentFolder::SetFlatMode(Int32 flatMode) #endif -void CAgentFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const +int CAgentFolder::GetRealIndex(unsigned index) const { if (!_flatMode) { - _proxyFolderItem->GetRealIndices(indices, numItems, realIndices); + if (_proxyArchive2) + return _proxyArchive2->GetRealIndex(_proxyFolderItem, index); + else + return _proxyArchive->GetRealIndex(_proxyFolderItem, index); + } + { + const CProxyItem &item = _items[index]; + if (_proxyArchive2) + { + const CProxyFolder2 *folder = &_proxyArchive2->Folders[item.ProxyFolderIndex]; + return folder->SubFiles[item.Index]; + } + else + { + const CProxyFolder *folder = &_proxyArchive->Folders[item.ProxyFolderIndex]; + unsigned realIndex = item.Index; + if (realIndex < folder->Folders.Size()) + { + const CProxyFolder &f = _proxyArchive->Folders[folder->Folders[realIndex]]; + if (!f.IsLeaf) + return -1; + return f.Index; + } + return folder->Files[realIndex - folder->Folders.Size()].Index; + } + } +} + +void CAgentFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, bool includeAltStreams, bool includeFolderSubItemsInFlatMode, CUIntVector &realIndices) const +{ + if (!_flatMode) + { + if (_proxyArchive2) + _proxyArchive2->GetRealIndices(_proxyFolderItem, indices, numItems, includeAltStreams, realIndices); + else + _proxyArchive->GetRealIndices(_proxyFolderItem, 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()) + if (_proxyArchive2) + { + const CProxyFolder2 *folder = &_proxyArchive2->Folders[item.ProxyFolderIndex]; + _proxyArchive2->AddRealIndices_of_ArcItem(folder->SubFiles[item.Index], includeAltStreams, realIndices); continue; - realIndices.Add(folder->Files[realIndex - folder->Folders.Size()].Index); + } + UInt32 arcIndex; + { + const CProxyFolder *folder = &_proxyArchive->Folders[item.ProxyFolderIndex]; + unsigned realIndex = item.Index; + if (realIndex < folder->Folders.Size()) + { + if (includeFolderSubItemsInFlatMode) + { + _proxyArchive->AddRealIndices(folder->Folders[realIndex], realIndices); + continue; + } + const CProxyFolder &f = _proxyArchive->Folders[folder->Folders[realIndex]]; + if (!f.IsLeaf) + continue; + arcIndex = f.Index; + } + else + arcIndex = folder->Files[realIndex - folder->Folders.Size()].Index; + } + realIndices.Add(arcIndex); } HeapSort(&realIndices.Front(), realIndices.Size()); } STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices, UInt32 numItems, + Int32 includeAltStreams, + Int32 replaceAltStreamColon, NExtract::NPathMode::EEnum pathMode, NExtract::NOverwriteMode::EEnum overwriteMode, const wchar_t *path, @@ -373,7 +1161,10 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices, CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr extractCallback = extractCallbackSpec; UStringVector pathParts; - _proxyFolderItem->GetPathParts(pathParts); + if (_proxyArchive2) + _proxyArchive2->GetPathParts(_proxyFolderItem, pathParts); + else + _proxyArchive->GetPathParts(_proxyFolderItem, pathParts); /* if (_flatMode) @@ -385,16 +1176,45 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices, FString pathU; if (path) pathU = us2fs(path); - extractCallbackSpec->Init(NULL, &_agentSpec->GetArc(), + + CExtractNtOptions extractNtOptions; + extractNtOptions.AltStreams.Val = IntToBool(includeAltStreams); // change it!!! + extractNtOptions.AltStreams.Def = true; + + extractNtOptions.ReplaceColonForAltStream = IntToBool(replaceAltStreamColon); + + extractCallbackSpec->Init( + extractNtOptions, + NULL, &_agentSpec->GetArc(), extractCallback2, - false, testMode ? true : false, false, + false, // stdOutMode + IntToBool(testMode), path ? pathU : FTEXT(""), pathParts, (UInt64)(Int64)-1); + + if (_proxyArchive2) + extractCallbackSpec->SetBaseParentFolderIndex(_proxyArchive2->Folders[_proxyFolderItem].ArcIndex); + CUIntVector realIndices; - GetRealIndices(indices, numItems, realIndices); - return _agentSpec->GetArchive()->Extract(&realIndices.Front(), + GetRealIndices(indices, numItems, IntToBool(includeAltStreams), + false, // includeFolderSubItemsInFlatMode + realIndices); // + + #ifdef SUPPORT_LINKS + + if (!testMode) + { + RINOK(extractCallbackSpec->PrepareHardLinks(&realIndices)); + } + + #endif + + HRESULT result = _agentSpec->GetArchive()->Extract(&realIndices.Front(), realIndices.Size(), testMode, extractCallback); + if (result == S_OK) + result = extractCallbackSpec->SetDirsTimes(); + return result; COM_TRY_END } @@ -403,14 +1223,32 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices, CAgent::CAgent(): _proxyArchive(NULL), + _proxyArchive2(NULL), + _isDeviceFile(false), _codecs(0) { } CAgent::~CAgent() { - if (_proxyArchive != NULL) + if (_proxyArchive) delete _proxyArchive; + if (_proxyArchive2) + delete _proxyArchive2; +} + +bool CAgent::CanUpdate() const +{ + // FAR plugin uses empty agent to create new archive !!! + if (_archiveLink.Arcs.Size() == 0) + return true; + if (_isDeviceFile) + return false; + if (_archiveLink.Arcs.Size() != 1) + return false; + if (_archiveLink.Arcs[0].ErrorInfo.ThereIsTail) + return false; + return true; } STDMETHODIMP CAgent::Open( @@ -423,12 +1261,14 @@ STDMETHODIMP CAgent::Open( COM_TRY_BEGIN _archiveFilePath = filePath; NFile::NFind::CFileInfo fi; + _isDeviceFile = false; if (!inStream) { if (!fi.Find(us2fs(_archiveFilePath))) return ::GetLastError(); if (fi.IsDir()) return E_FAIL; + _isDeviceFile = fi.IsDevice; } CArcInfoEx archiverInfo0, archiverInfo1; @@ -437,11 +1277,33 @@ STDMETHODIMP CAgent::Open( _compressCodecsInfo = _codecs; RINOK(_codecs->Load()); - CIntVector formatIndices; - if (!_codecs->FindFormatForArchiveType(arcFormat, formatIndices)) + CObjectVector types; + if (!ParseOpenTypes(*_codecs, arcFormat, types)) return S_FALSE; - RINOK(_archiveLink.Open(_codecs, formatIndices, false, inStream, _archiveFilePath, openArchiveCallback)); + /* + CObjectVector optProps; + if (Read_ShowDeleted()) + { + COptionalOpenProperties &optPair = optProps.AddNew(); + optPair.FormatName = L"ntfs"; + // optPair.Props.AddNew().Name = L"LS"; + optPair.Props.AddNew().Name = L"LD"; + } + */ + + COpenOptions options; + options.props = NULL; + options.codecs = _codecs; + options.types = &types; + CIntVector exl; + options.excludedFormats = &exl; + options.stdInMode = false; + options.stream = inStream; + options.filePath = _archiveFilePath; + options.callback = openArchiveCallback; + + RINOK(_archiveLink.Open(options)); CArc &arc = _archiveLink.Arcs.Back(); if (!inStream) @@ -450,22 +1312,42 @@ STDMETHODIMP CAgent::Open( arc.MTime = fi.MTime; } - ArchiveType = _codecs->Formats[arc.FormatIndex].Name; - if (archiveType == 0) - return S_OK; - return StringToBstr(ArchiveType, archiveType); + ArchiveType = GetTypeOfArc(arc); + if (archiveType) + { + RINOK(StringToBstr(ArchiveType, archiveType)); + } + return S_OK; COM_TRY_END } STDMETHODIMP CAgent::ReOpen(IArchiveOpenCallback *openArchiveCallback) { COM_TRY_BEGIN - if (_proxyArchive != NULL) + if (_proxyArchive2) + { + delete _proxyArchive2; + _proxyArchive2 = NULL; + } + if (_proxyArchive) { delete _proxyArchive; _proxyArchive = NULL; } - RINOK(_archiveLink.ReOpen(_codecs, _archiveFilePath, openArchiveCallback)); + + CObjectVector incl; + CIntVector exl; + + COpenOptions options; + options.props = NULL; + options.codecs = _codecs; + options.types = &incl; + options.excludedFormats = &exl; + options.stdInMode = false; + options.filePath = _archiveFilePath; + options.callback = openArchiveCallback; + + RINOK(_archiveLink.ReOpen(options)); return ReadItems(); COM_TRY_END } @@ -486,9 +1368,38 @@ STDMETHODIMP CAgent::EnumProperties(IEnumSTATPROPSTG **EnumProperties) HRESULT CAgent::ReadItems() { - if (_proxyArchive != NULL) + if (_proxyArchive || _proxyArchive2) return S_OK; - _proxyArchive = new CProxyArchive(); + + const CArc &arc = GetArc(); + bool useProxy2 = (arc.GetRawProps && arc.IsTree); + // useProxy2 = false; + + if (useProxy2) + _proxyArchive2 = new CProxyArchive2(); + else + _proxyArchive = new CProxyArchive(); + + { + ThereIsPathProp = false; + UInt32 numProps; + arc.Archive->GetNumberOfProperties(&numProps); + for (UInt32 i = 0; i < numProps; i++) + { + CMyComBSTR name; + PROPID propID; + VARTYPE varType; + RINOK(arc.Archive->GetPropertyInfo(i, &name, &propID, &varType)); + if (propID == kpidPath) + { + ThereIsPathProp = true; + break; + } + } + } + + if (_proxyArchive2) + return _proxyArchive2->Load(GetArc(), NULL); return _proxyArchive->Load(GetArc(), NULL); } @@ -498,13 +1409,12 @@ STDMETHODIMP CAgent::BindToRootFolder(IFolderFolder **resultFolder) RINOK(ReadItems()); CAgentFolder *folderSpec = new CAgentFolder; CMyComPtr rootFolder = folderSpec; - folderSpec->Init(_proxyArchive, &_proxyArchive->RootFolder, NULL, this); + folderSpec->Init(_proxyArchive, _proxyArchive2, 0, NULL, this); *resultFolder = rootFolder.Detach(); return S_OK; COM_TRY_END } - STDMETHODIMP CAgent::Extract( NExtract::NPathMode::EEnum pathMode, NExtract::NOverwriteMode::EEnum overwriteMode, @@ -516,12 +1426,31 @@ STDMETHODIMP CAgent::Extract( CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr extractCallback = extractCallbackSpec; extractCallbackSpec->InitForMulti(false, pathMode, overwriteMode); - extractCallbackSpec->Init(NULL, &GetArc(), + + CExtractNtOptions extractNtOptions; + extractNtOptions.AltStreams.Val = true; // change it!!! + extractNtOptions.AltStreams.Def = true; // change it!!! + extractNtOptions.ReplaceColonForAltStream = false; // change it!!! + + extractCallbackSpec->Init( + extractNtOptions, + NULL, &GetArc(), extractCallback2, - false, testMode ? true : false, false, + false, // stdOutMode + IntToBool(testMode), us2fs(path), UStringVector(), (UInt64)(Int64)-1); + + #ifdef SUPPORT_LINKS + + if (!testMode) + { + RINOK(extractCallbackSpec->PrepareHardLinks(NULL)); // NULL means all items + } + + #endif + return GetArchive()->Extract(0, (UInt32)(Int32)-1, testMode, extractCallback); COM_TRY_END } @@ -554,12 +1483,59 @@ STDMETHODIMP CAgent::GetArcProp(UInt32 level, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NWindows::NCOM::CPropVariant prop; - CArc &arc = _archiveLink.Arcs[level]; - switch (propID) + if (level > (UInt32)_archiveLink.Arcs.Size()) + return E_INVALIDARG; + if (level == (UInt32)_archiveLink.Arcs.Size()) + { + switch (propID) + { + case kpidPath: + if (!_archiveLink.NonOpen_ArcPath.IsEmpty()) + prop = _archiveLink.NonOpen_ArcPath; + break; + case kpidErrorType: + if (_archiveLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) + prop = _codecs->Formats[_archiveLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name; + break; + } + } + else { - case kpidType: prop = GetTypeOfArc(arc); break; - case kpidPath: prop = arc.Path; break; - default: return arc.Archive->GetArchiveProperty(propID, value); + const CArc &arc = _archiveLink.Arcs[level]; + switch (propID) + { + case kpidType: prop = GetTypeOfArc(arc); break; + case kpidPath: prop = arc.Path; break; + case kpidErrorType: if (arc.ErrorInfo.ErrorFormatIndex >= 0) prop = _codecs->Formats[arc.ErrorInfo.ErrorFormatIndex].Name; break; + case kpidErrorFlags: + { + UInt32 flags = arc.ErrorInfo.GetErrorFlags(); + if (flags != 0) + prop = flags; + break; + } + case kpidWarningFlags: + { + UInt32 flags = arc.ErrorInfo.GetWarningFlags(); + if (flags != 0) + prop = flags; + break; + } + case kpidOffset: + { + Int64 v = arc.GetGlobalOffset(); + if (v != 0) + prop = v; + break; + } + case kpidTailSize: + { + if (arc.ErrorInfo.TailSize != 0) + prop = arc.ErrorInfo.TailSize; + break; + } + default: return arc.Archive->GetArchiveProperty(propID, value); + } } prop.Detach(value); return S_OK; diff --git a/CPP/7zip/UI/Agent/Agent.h b/CPP/7zip/UI/Agent/Agent.h old mode 100755 new mode 100644 index cc92b0dd..e06f8576 --- a/CPP/7zip/UI/Agent/Agent.h +++ b/CPP/7zip/UI/Agent/Agent.h @@ -3,9 +3,9 @@ #ifndef __AGENT_AGENT_H #define __AGENT_AGENT_H -#include "Common/MyCom.h" +#include "../../../Common/MyCom.h" -#include "Windows/PropVariant.h" +#include "../../../Windows/PropVariant.h" #include "../Common/OpenArchive.h" #include "../Common/UpdateAction.h" @@ -27,8 +27,8 @@ DECL_INTERFACE(IArchiveFolderInternal, 0x01, 0xC) struct CProxyItem { - const CProxyFolder *Folder; - UInt32 Index; + unsigned ProxyFolderIndex; + unsigned Index; }; class CAgent; @@ -45,25 +45,33 @@ enum AGENT_OP class CAgentFolder: public IFolderFolder, public IFolderProperties, + public IArchiveGetRawProps, public IGetFolderArcProps, + public IFolderCompare, + public IFolderGetItemName, public IArchiveFolder, public IArchiveFolderInternal, public IInArchiveGetStream, + // public IFolderSetReplaceAltStreamCharsMode, #ifdef NEW_FOLDER_INTERFACE public IFolderOperations, public IFolderSetFlatMode, #endif public CMyUnknownImp { - void LoadFolder(const CProxyFolder *folder); + void LoadFolder(unsigned proxyFolderIndex); public: MY_QUERYINTERFACE_BEGIN2(IFolderFolder) MY_QUERYINTERFACE_ENTRY(IFolderProperties) + MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps) MY_QUERYINTERFACE_ENTRY(IGetFolderArcProps) + MY_QUERYINTERFACE_ENTRY(IFolderCompare) + MY_QUERYINTERFACE_ENTRY(IFolderGetItemName) MY_QUERYINTERFACE_ENTRY(IArchiveFolder) MY_QUERYINTERFACE_ENTRY(IArchiveFolderInternal) MY_QUERYINTERFACE_ENTRY(IInArchiveGetStream) + // MY_QUERYINTERFACE_ENTRY(IFolderSetReplaceAltStreamCharsMode) #ifdef NEW_FOLDER_INTERFACE MY_QUERYINTERFACE_ENTRY(IFolderOperations) MY_QUERYINTERFACE_ENTRY(IFolderSetFlatMode) @@ -71,21 +79,24 @@ public: MY_QUERYINTERFACE_END MY_ADDREF_RELEASE - HRESULT BindToFolder(const CProxyFolder *folder, IFolderFolder **resultFolder); - void GetRealIndices(const UINT32 *indices, UINT32 numItems, CUIntVector &realIndices) const; + HRESULT BindToFolder_Internal(unsigned proxyFolderIndex, IFolderFolder **resultFolder); + int GetRealIndex(unsigned index) const; + void GetRealIndices(const UInt32 *indices, UInt32 numItems, + bool includeAltStreams, bool includeFolderSubItemsInFlatMode, CUIntVector &realIndices) const; + + // INTERFACE_FolderSetReplaceAltStreamCharsMode(;) INTERFACE_FolderFolder(;) INTERFACE_FolderProperties(;) + INTERFACE_IArchiveGetRawProps(;) + INTERFACE_IFolderGetItemName(;) STDMETHOD(GetFolderArcProps)(IFolderArcProps **object); + STDMETHOD_(Int32, CompareItems)(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw); + int CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw); // IArchiveFolder - STDMETHOD(Extract)(const UINT32 *indices, UINT32 numItems, - NExtract::NPathMode::EEnum pathMode, - NExtract::NOverwriteMode::EEnum overwriteMode, - const wchar_t *path, - Int32 testMode, - IFolderArchiveExtractCallback *extractCallback); + INTERFACE_IArchiveFolder(;) STDMETHOD(GetAgentFolder)(CAgentFolder **agentFolder); @@ -97,14 +108,15 @@ public: STDMETHOD(SetFlatMode)(Int32 flatMode); #endif - CAgentFolder(): _proxyFolderItem(NULL), _flatMode(0) {} + CAgentFolder(): _proxyFolderItem(0), _flatMode(0) /* , _replaceAltStreamCharsMode(0) */ {} - void Init(const CProxyArchive *proxyHandler, - const CProxyFolder *proxyFolderItem, + void Init(const CProxyArchive *proxyArc, const CProxyArchive2 *proxyArc2, + unsigned proxyFolderItem, IFolderFolder *parentFolder, CAgent *agent) { - _proxyArchive = proxyHandler; + _proxyArchive = proxyArc; + _proxyArchive2 = proxyArc2; _proxyFolderItem = proxyFolderItem; _parentFolder = parentFolder; _agent = (IInFolderArchive *)agent; @@ -114,25 +126,29 @@ public: void GetPathParts(UStringVector &pathParts); HRESULT CommonUpdateOperation( AGENT_OP operation, + bool moveMode, const wchar_t *newItemName, const NUpdateArchive::CActionSet *actionSet, - const UINT32 *indices, UINT32 numItems, + const UInt32 *indices, UInt32 numItems, IFolderArchiveUpdateCallback *updateCallback100); - UString GetPrefix(UInt32 index) const; + void GetPrefix(UInt32 index, UString &prefix) const; UString GetName(UInt32 index) const; UString GetFullPathPrefixPlusPrefix(UInt32 index) const; public: const CProxyArchive *_proxyArchive; - const CProxyFolder *_proxyFolderItem; + const CProxyArchive2 *_proxyArchive2; + // const CProxyFolder *_proxyFolderItem; + unsigned _proxyFolderItem; CMyComPtr _parentFolder; CMyComPtr _agent; CAgent *_agentSpec; CRecordVector _items; bool _flatMode; + // Int32 _replaceAltStreamCharsMode; private: }; @@ -163,7 +179,7 @@ public: INTERFACE_IOutFolderArchive(;) HRESULT CommonUpdate(ISequentialOutStream *outArchiveStream, - int numUpdateItems, IArchiveUpdateCallback *updateCallback); + unsigned numUpdateItems, IArchiveUpdateCallback *updateCallback); HRESULT CreateFolder(ISequentialOutStream *outArchiveStream, const wchar_t *folderName, IFolderArchiveUpdateCallback *updateCallback100); @@ -177,7 +193,7 @@ public: IFolderArchiveUpdateCallback *updateCallback100); // ISetProperties - STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties); + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); #endif CCodecs *_codecs; @@ -189,8 +205,10 @@ private: HRESULT ReadItems(); public: CProxyArchive *_proxyArchive; + CProxyArchive2 *_proxyArchive2; CArchiveLink _archiveLink; + bool ThereIsPathProp; UString ArchiveType; @@ -201,6 +219,7 @@ public: CAgentFolder *_agentFolder; UString _archiveFilePath; + bool _isDeviceFile; #ifndef EXTRACT_ONLY CObjectVector m_PropNames; @@ -209,28 +228,50 @@ public: const CArc &GetArc() const { return _archiveLink.Arcs.Back(); } IInArchive *GetArchive() const { if ( _archiveLink.Arcs.IsEmpty()) return 0; return GetArc().Archive; } - bool CanUpdate() const { return _archiveLink.Arcs.Size() <= 1; } + bool CanUpdate() const; + + UString GetTypeOfArc(const CArc &arc) const + { + if (arc.FormatIndex < 0) + return L"Parser"; + return _codecs->GetFormatNamePtr(arc.FormatIndex); + } - 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"; + + UString s2; + if (arc.ErrorInfo.ErrorFormatIndex >= 0) + s2 = L"Can not open the file as [" + _codecs->Formats[arc.ErrorInfo.ErrorFormatIndex].Name + L"] archive"; + + if (!arc.ErrorInfo.ErrorMessage.IsEmpty()) + { + if (!s2.IsEmpty()) + s2 += L"\n"; + s2 += L"\n["; + s2 += GetTypeOfArc(arc); + s2 += L"]: "; + s2 += arc.ErrorInfo.ErrorMessage; + } + if (!s2.IsEmpty()) + { + if (!s.IsEmpty()) + s += L"--------------------\n"; + s += arc.Path; + s += L"\n"; + s += s2; + s += L"\n"; + } } return s; } + + void KeepModeForNextOpen() { _archiveLink.KeepModeForNextOpen(); } + }; #ifdef NEW_FOLDER_INTERFACE diff --git a/CPP/7zip/UI/Agent/AgentOut.cpp b/CPP/7zip/UI/Agent/AgentOut.cpp old mode 100755 new mode 100644 index 17f5443a..3fd25670 --- a/CPP/7zip/UI/Agent/AgentOut.cpp +++ b/CPP/7zip/UI/Agent/AgentOut.cpp @@ -2,9 +2,9 @@ #include "StdAfx.h" -#include "Windows/FileDir.h" -#include "Windows/FileName.h" -#include "Windows/Time.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/TimeUtils.h" #include "../../Compress/CopyCoder.h" @@ -32,7 +32,10 @@ STDMETHODIMP CAgent::SetFolder(IFolderFolder *folder) RINOK(archiveFolderInternal->GetAgentFolder(&_agentFolder)); } - _archiveNamePrefix = _agentFolder->_proxyFolderItem->GetFullPathPrefix(); + if (_proxyArchive2) + _archiveNamePrefix = _proxyArchive2->GetFullPathPrefix(_agentFolder->_proxyFolderItem); + else + _archiveNamePrefix = _proxyArchive->GetFullPathPrefix(_agentFolder->_proxyFolderItem); return S_OK; } @@ -40,10 +43,9 @@ STDMETHODIMP CAgent::SetFiles(const wchar_t *folderPrefix, const wchar_t **names, UInt32 numNames) { _folderPrefix = us2fs(folderPrefix); - _names.Clear(); - _names.Reserve(numNames); + _names.ClearAndReserve(numNames); for (UInt32 i = 0; i < numNames; i++) - _names.Add(us2fs(names[i])); + _names.AddInReserved(us2fs(names[i])); return S_OK; } @@ -52,7 +54,7 @@ static HRESULT EnumerateArchiveItems(CAgent *agent, const UString &prefix, CObjectVector &arcItems) { - int i; + unsigned i; for (i = 0; i < item.Files.Size(); i++) { const CProxyFile &fileItem = item.Files[i]; @@ -67,7 +69,7 @@ static HRESULT EnumerateArchiveItems(CAgent *agent, } for (i = 0; i < item.Folders.Size(); i++) { - const CProxyFolder &dirItem = item.Folders[i]; + const CProxyFolder &dirItem = agent->_proxyArchive->Folders[item.Folders[i]]; UString fullName = prefix + dirItem.Name; if (dirItem.IsLeaf) { @@ -85,6 +87,38 @@ static HRESULT EnumerateArchiveItems(CAgent *agent, return S_OK; } +static HRESULT EnumerateArchiveItems2(const CAgent *agent, + const CProxyArchive2 *proxyArchive2, + unsigned folderIndex, + const UString &prefix, + CObjectVector &arcItems) +{ + const CProxyFolder2 &folder = proxyArchive2->Folders[folderIndex]; + FOR_VECTOR (i, folder.SubFiles) + { + unsigned arcIndex = folder.SubFiles[i]; + const CProxyFile2 &file = proxyArchive2->Files[arcIndex]; + CArcItem ai; + ai.IndexInServer = arcIndex; + ai.Name = prefix + file.Name; + ai.Censored = true; // test it + RINOK(agent->GetArc().GetItemMTime(arcIndex, ai.MTime, ai.MTimeDefined)); + ai.IsDir = file.IsDir(); + ai.SizeDefined = false; + if (!ai.IsDir) + { + RINOK(agent->GetArc().GetItemSize(arcIndex, ai.Size, ai.SizeDefined)); + ai.IsDir = false; + } + arcItems.Add(ai); + if (ai.IsDir) + { + RINOK(EnumerateArchiveItems2(agent, proxyArchive2, file.FolderIndex, ai.Name + UString(WCHAR_PATH_SEPARATOR), arcItems)); + } + } + return S_OK; +} + struct CAgUpCallbackImp: public IUpdateProduceCallback { const CObjectVector *_arcItems; @@ -100,7 +134,20 @@ HRESULT CAgUpCallbackImp::ShowDeleteFile(int arcIndex) return _callback->DeleteOperation((*_arcItems)[arcIndex].Name); } + +static void SetInArchiveInterfaces(CAgent *agent, CArchiveUpdateCallback *upd) +{ + if (agent->_archiveLink.Arcs.IsEmpty()) + return; + const CArc &arc = agent->GetArc(); + upd->Archive = arc.Archive; + upd->GetRawProps = arc.GetRawProps; + upd->GetRootProps = arc.GetRootProps; +} + STDMETHODIMP CAgent::DoOperation( + FStringVector *requestedPaths, + FStringVector *processedPaths, CCodecs *codecs, int formatIndex, ISequentialOutStream *outArchiveStream, @@ -111,7 +158,7 @@ STDMETHODIMP CAgent::DoOperation( if (!CanUpdate()) return E_NOTIMPL; NUpdateArchive::CActionSet actionSet; - int i; + unsigned i; for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++) actionSet.StateActions[i] = (NUpdateArchive::NPairAction::EEnum)stateActions[i]; @@ -120,11 +167,9 @@ STDMETHODIMP CAgent::DoOperation( { FString folderPrefix = _folderPrefix; NFile::NName::NormalizeDirPathPrefix(folderPrefix); - FStringVector errorPaths; - CRecordVector errorCodes; - dirItems.EnumerateDirItems2(folderPrefix, _archiveNamePrefix, _names, errorPaths, errorCodes); - if (errorCodes.Size() > 0) - return errorCodes.Front(); + dirItems.EnumerateItems2(folderPrefix, _archiveNamePrefix, _names, requestedPaths); + if (dirItems.ErrorCodes.Size() > 0) + return dirItems.ErrorCodes.Front(); } CMyComPtr outArchive; @@ -170,7 +215,14 @@ STDMETHODIMP CAgent::DoOperation( if (GetArchive()) { RINOK(ReadItems()); - EnumerateArchiveItems(this, _proxyArchive->RootFolder, L"", arcItems); + if (_proxyArchive2) + { + RINOK(EnumerateArchiveItems2(this, _proxyArchive2, 0, L"", arcItems)); + } + else + { + RINOK(EnumerateArchiveItems(this, _proxyArchive->Folders[0], L"", arcItems)); + } } CRecordVector updatePairs2; @@ -200,9 +252,21 @@ STDMETHODIMP CAgent::DoOperation( updateCallbackSpec->DirItems = &dirItems; updateCallbackSpec->ArcItems = &arcItems; updateCallbackSpec->UpdatePairs = &updatePairs2; - updateCallbackSpec->Archive = GetArchive(); + + SetInArchiveInterfaces(this, updateCallbackSpec); + updateCallbackSpec->Callback = &updateCallbackAgent; + CByteBuffer processedItems; + if (processedPaths) + { + unsigned num = dirItems.Items.Size(); + processedItems.Alloc(num); + for (i = 0; i < num; i++) + processedItems[i] = 0; + updateCallbackSpec->ProcessedItemsStatuses = processedItems; + } + CMyComPtr setProperties; if (outArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties) == S_OK) { @@ -219,7 +283,7 @@ STDMETHODIMP CAgent::DoOperation( CPropVariant *propValues = new CPropVariant[m_PropValues.Size()]; try { - for (int i = 0; i < m_PropValues.Size(); i++) + FOR_VECTOR (i, m_PropValues) propValues[i] = m_PropValues[i]; RINOK(setProperties->SetProperties(&names.Front(), propValues, names.Size())); } @@ -244,17 +308,27 @@ STDMETHODIMP CAgent::DoOperation( RINOK(NCompress::CopyStream(sfxStream, outArchiveStream, NULL)); } - return outArchive->UpdateItems(outArchiveStream, updatePairs2.Size(),updateCallback); + HRESULT res = outArchive->UpdateItems(outArchiveStream, updatePairs2.Size(), updateCallback); + if (res == S_OK && processedPaths) + { + for (i = 0; i < dirItems.Items.Size(); i++) + if (processedItems[i] != 0) + processedPaths->Add(us2fs(dirItems.GetPhyPath(i))); + } + return res; } -STDMETHODIMP CAgent::DoOperation2(ISequentialOutStream *outArchiveStream, +STDMETHODIMP CAgent::DoOperation2( + FStringVector *requestedPaths, + FStringVector *processedPaths, + ISequentialOutStream *outArchiveStream, const Byte *stateActions, const wchar_t *sfxModule, IFolderArchiveUpdateCallback *updateCallback100) { - return DoOperation(_codecs, -1, outArchiveStream, stateActions, sfxModule, updateCallback100); + return DoOperation(requestedPaths, processedPaths, _codecs, -1, outArchiveStream, stateActions, sfxModule, updateCallback100); } HRESULT CAgent::CommonUpdate(ISequentialOutStream *outArchiveStream, - int numUpdateItems, IArchiveUpdateCallback *updateCallback) + unsigned numUpdateItems, IArchiveUpdateCallback *updateCallback) { if (!CanUpdate()) return E_NOTIMPL; @@ -276,8 +350,11 @@ STDMETHODIMP CAgent::DeleteItems(ISequentialOutStream *outArchiveStream, CMyComPtr updateCallback(updateCallbackSpec); CUIntVector realIndices; - _agentFolder->GetRealIndices(indices, numItems, realIndices); - int curIndex = 0; + _agentFolder->GetRealIndices(indices, numItems, + true, // includeAltStreams + false, // includeFolderSubItemsInFlatMode, we don't want to delete subItems in Flat Mode + realIndices); + unsigned curIndex = 0; UInt32 numItemsInArchive; RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive)); for (UInt32 i = 0; i < numItemsInArchive; i++) @@ -289,13 +366,13 @@ STDMETHODIMP CAgent::DeleteItems(ISequentialOutStream *outArchiveStream, continue; } CUpdatePair2 up2; - up2.NewData = up2.NewProps = false; - up2.IsAnti = false; // check it. Maybe it can be undefined - up2.ArcIndex = i; + up2.SetAs_NoChangeArcItem(i); updatePairs.Add(up2); } updateCallbackSpec->UpdatePairs = &updatePairs; - updateCallbackSpec->Archive = GetArchive(); + + SetInArchiveInterfaces(this, updateCallbackSpec); + updateCallbackSpec->Callback = &updateCallbackAgent; return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback); } @@ -317,14 +394,12 @@ HRESULT CAgent::CreateFolder(ISequentialOutStream *outArchiveStream, for (UInt32 i = 0; i < numItemsInArchive; i++) { CUpdatePair2 up2; - up2.NewData = up2.NewProps = false; - up2.IsAnti = false; // check it. - up2.ArcIndex = i; + up2.SetAs_NoChangeArcItem(i); updatePairs.Add(up2); } CUpdatePair2 up2; up2.NewData = up2.NewProps = true; - up2.IsAnti = false; + up2.UseArcProps = false; up2.DirIndex = 0; updatePairs.Add(up2); @@ -335,7 +410,10 @@ HRESULT CAgent::CreateFolder(ISequentialOutStream *outArchiveStream, di.Attrib = FILE_ATTRIBUTE_DIRECTORY; di.Size = 0; - di.Name = _agentFolder->_proxyFolderItem->GetFullPathPrefix() + folderName; + if (_proxyArchive2) + di.Name = _proxyArchive2->GetFullPathPrefix(_agentFolder->_proxyFolderItem) + folderName; + else + di.Name = _proxyArchive->GetFullPathPrefix(_agentFolder->_proxyFolderItem) + folderName; FILETIME ft; NTime::GetCurUtcFileTime(ft); @@ -346,7 +424,9 @@ HRESULT CAgent::CreateFolder(ISequentialOutStream *outArchiveStream, updateCallbackSpec->Callback = &updateCallbackAgent; updateCallbackSpec->DirItems = &dirItems; updateCallbackSpec->UpdatePairs = &updatePairs; - updateCallbackSpec->Archive = GetArchive(); + + SetInArchiveInterfaces(this, updateCallbackSpec); + return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback); } @@ -359,6 +439,8 @@ HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream, return E_NOTIMPL; if (numItems != 1) return E_INVALIDARG; + if (!_archiveLink.IsOpen) + return E_FAIL; CRecordVector updatePairs; CUpdateCallbackAgent updateCallbackAgent; updateCallbackAgent.SetCallback(updateCallback100); @@ -366,7 +448,12 @@ HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream, CMyComPtr updateCallback(updateCallbackSpec); CUIntVector realIndices; - _agentFolder->GetRealIndices(indices, numItems, realIndices); + _agentFolder->GetRealIndices(indices, numItems, + true, // includeAltStreams + true, // includeFolderSubItemsInFlatMode + realIndices); + + int mainRealIndex = _agentFolder->GetRealIndex(indices[0]); UString fullPrefix = _agentFolder->GetFullPathPrefixPlusPrefix(indices[0]); UString oldItemPath = fullPrefix + _agentFolder->GetName(indices[0]); @@ -374,41 +461,37 @@ HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream, UStringVector newNames; - int curIndex = 0; + unsigned curIndex = 0; UInt32 numItemsInArchive; RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive)); for (UInt32 i = 0; i < numItemsInArchive; i++) { + CUpdatePair2 up2; + up2.SetAs_NoChangeArcItem(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; + RINOK(GetArc().IsItemAnti(i, up2.IsAnti)); // it must work without that line too. UString oldFullPath; - RINOK(GetArc().GetItemPath(i, oldFullPath)); + RINOK(GetArc().GetItemPath2(i, oldFullPath)); - if (oldItemPath.CompareNoCase(oldFullPath.Left(oldItemPath.Length())) != 0) + if (MyStringCompareNoCase_N(oldFullPath, oldItemPath, oldItemPath.Len()) != 0) return E_INVALIDARG; - up2.NewNameIndex = newNames.Add(newItemPath + oldFullPath.Mid(oldItemPath.Length())); - updatePairs.Add(up2); + up2.NewNameIndex = newNames.Add(newItemPath + oldFullPath.Ptr(oldItemPath.Len())); + up2.IsMainRenameItem = (mainRealIndex == (int)i); 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(); + + SetInArchiveInterfaces(this, updateCallbackSpec); + return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback); } @@ -428,7 +511,10 @@ HRESULT CAgent::UpdateOneFile(ISequentialOutStream *outArchiveStream, UInt32 realIndex; { CUIntVector realIndices; - _agentFolder->GetRealIndices(indices, numItems, realIndices); + _agentFolder->GetRealIndices(indices, numItems, + false, // includeAltStreams // we update only main stream of file + false, // includeFolderSubItemsInFlatMode + realIndices); if (realIndices.Size() != 1) return E_FAIL; realIndex = realIndices[0]; @@ -437,9 +523,7 @@ HRESULT CAgent::UpdateOneFile(ISequentialOutStream *outArchiveStream, { FStringVector filePaths; filePaths.Add(us2fs(diskFilePath)); - FStringVector errorPaths; - CRecordVector errorCodes; - dirItems.EnumerateDirItems2(FString(), UString(), filePaths, errorPaths, errorCodes); + dirItems.EnumerateItems2(FString(), UString(), filePaths, NULL); if (dirItems.Items.Size() != 1) return E_FAIL; } @@ -449,32 +533,31 @@ HRESULT CAgent::UpdateOneFile(ISequentialOutStream *outArchiveStream, for (UInt32 i = 0; i < numItemsInArchive; i++) { CUpdatePair2 up2; - up2.ArcIndex = i; - up2.IsAnti = false; - up2.NewData = false; - up2.NewProps = false; + up2.SetAs_NoChangeArcItem(i); if (realIndex == i) { up2.DirIndex = 0; up2.NewData = true; up2.NewProps = true; + up2.UseArcProps = false; } updatePairs.Add(up2); } updateCallbackSpec->DirItems = &dirItems; updateCallbackSpec->Callback = &updateCallbackAgent; updateCallbackSpec->UpdatePairs = &updatePairs; - updateCallbackSpec->Archive = GetArchive(); + + SetInArchiveInterfaces(this, updateCallbackSpec); + updateCallbackSpec->KeepOriginalItemNames = true; return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback); } -STDMETHODIMP CAgent::SetProperties(const wchar_t **names, - const PROPVARIANT *values, Int32 numProperties) +STDMETHODIMP CAgent::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) { m_PropNames.Clear(); m_PropValues.Clear(); - for (int i = 0; i < numProperties; i++) + for (UInt32 i = 0; i < numProps; i++) { m_PropNames.Add(names[i]); m_PropValues.Add(values[i]); diff --git a/CPP/7zip/UI/Agent/AgentProxy.cpp b/CPP/7zip/UI/Agent/AgentProxy.cpp old mode 100755 new mode 100644 index ce9b3bfb..a31a904b --- a/CPP/7zip/UI/Agent/AgentProxy.cpp +++ b/CPP/7zip/UI/Agent/AgentProxy.cpp @@ -3,17 +3,21 @@ #include "StdAfx.h" #include "../../../../C/Sort.h" +#include "../../../../C/CpuArch.h" -#include "Windows/PropVariant.h" -#include "Windows/PropVariantConversions.h" +#include "../../../Common/Wildcard.h" + +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/PropVariantConv.h" #include "AgentProxy.h" using namespace NWindows; -int CProxyFolder::FindDirSubItemIndex(const UString &name, int &insertPos) const +int CProxyArchive::FindDirSubItemIndex(unsigned folderIndex, const UString &name, unsigned &insertPos) const { - int left = 0, right = Folders.Size(); + const CRecordVector &subFolders = Folders[folderIndex].Folders; + unsigned left = 0, right = subFolders.Size(); for (;;) { if (left == right) @@ -21,10 +25,11 @@ int CProxyFolder::FindDirSubItemIndex(const UString &name, int &insertPos) const insertPos = left; return -1; } - int mid = (left + right) / 2; - int compare = name.CompareNoCase(Folders[mid].Name); + unsigned mid = (left + right) / 2; + unsigned folderIndex = subFolders[mid]; + int compare = CompareFileNames(name, Folders[folderIndex].Name); if (compare == 0) - return mid; + return folderIndex; if (compare < 0) right = mid; else @@ -32,40 +37,41 @@ int CProxyFolder::FindDirSubItemIndex(const UString &name, int &insertPos) const } } -int CProxyFolder::FindDirSubItemIndex(const UString &name) const +int CProxyArchive::FindDirSubItemIndex(unsigned folderIndex, const UString &name) const { - int insertPos; - return FindDirSubItemIndex(name, insertPos); + unsigned insertPos; + return FindDirSubItemIndex(folderIndex, name, insertPos); } void CProxyFolder::AddFileSubItem(UInt32 index, const UString &name) { - Files.Add(CProxyFile()); - Files.Back().Name = name; - Files.Back().Index = index; + CProxyFile &f = Files.AddNew(); + f.Index = index; + f.Name = name; } -CProxyFolder* CProxyFolder::AddDirSubItem(UInt32 index, bool leaf, const UString &name) +unsigned CProxyArchive::AddDirSubItem(unsigned folderIndex, UInt32 index, bool leaf, const UString &name) { - int insertPos; - int folderIndex = FindDirSubItemIndex(name, insertPos); - if (folderIndex >= 0) + unsigned insertPos; + int subFolderIndex = FindDirSubItemIndex(folderIndex, name, insertPos); + if (subFolderIndex >= 0) { - CProxyFolder *item = &Folders[folderIndex]; + CProxyFolder &item = Folders[subFolderIndex]; if (leaf) { - item->Index = index; - item->IsLeaf = true; + item.Index = index; + item.IsLeaf = true; } - return item; + return subFolderIndex; } - Folders.Insert(insertPos, CProxyFolder()); - CProxyFolder *item = &Folders[insertPos]; - item->Name = name; - item->Index = index; - item->Parent = this; - item->IsLeaf = leaf; - return item; + subFolderIndex = Folders.Size(); + Folders[folderIndex].Folders.Insert(insertPos, subFolderIndex); + CProxyFolder &item = Folders.AddNew(); + item.Name = name; + item.Index = index; + item.Parent = folderIndex; + item.IsLeaf = leaf; + return subFolderIndex; } void CProxyFolder::Clear() @@ -74,51 +80,71 @@ void CProxyFolder::Clear() Files.Clear(); } -void CProxyFolder::GetPathParts(UStringVector &pathParts) const +void CProxyArchive::GetPathParts(int folderIndex, UStringVector &pathParts) const { pathParts.Clear(); - const CProxyFolder *current = this; - while (current->Parent != NULL) + while (folderIndex >= 0) { - pathParts.Insert(0, current->Name); - current = current->Parent; + const CProxyFolder &folder = Folders[folderIndex]; + folderIndex = folder.Parent; + if (folderIndex < 0) + break; + pathParts.Insert(0, folder.Name); } } -UString CProxyFolder::GetFullPathPrefix() const +UString CProxyArchive::GetFullPathPrefix(int folderIndex) const { UString result; - const CProxyFolder *current = this; - while (current->Parent != NULL) + while (folderIndex >= 0) { - result = current->Name + UString(WCHAR_PATH_SEPARATOR) + result; - current = current->Parent; + const CProxyFolder &folder = Folders[folderIndex]; + folderIndex = folder.Parent; + if (folderIndex < 0) + break; + result = folder.Name + UString(WCHAR_PATH_SEPARATOR) + result; } return result; } -void CProxyFolder::AddRealIndices(CUIntVector &realIndices) const +void CProxyArchive::AddRealIndices(unsigned folderIndex, 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); + const CProxyFolder &folder = Folders[folderIndex]; + if (folder.IsLeaf) + realIndices.Add(folder.Index); + unsigned i; + for (i = 0; i < folder.Folders.Size(); i++) + AddRealIndices(folder.Folders[i], realIndices); + for (i = 0; i < folder.Files.Size(); i++) + realIndices.Add(folder.Files[i].Index); +} + +int CProxyArchive::GetRealIndex(unsigned folderIndex, unsigned index) const +{ + const CProxyFolder &folder = Folders[folderIndex]; + unsigned numDirItems = folder.Folders.Size(); + if (index < numDirItems) + { + const CProxyFolder &f = Folders[folder.Folders[index]]; + if (f.IsLeaf) + return f.Index; + return -1; + } + return folder.Files[index - numDirItems].Index; } -void CProxyFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const +void CProxyArchive::GetRealIndices(unsigned folderIndex, const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const { + const CProxyFolder &folder = Folders[folderIndex]; realIndices.Clear(); for (UInt32 i = 0; i < numItems; i++) { - int index = indices[i]; - int numDirItems = Folders.Size(); + UInt32 index = indices[i]; + unsigned numDirItems = folder.Folders.Size(); if (index < numDirItems) - Folders[index].AddRealIndices(realIndices); + AddRealIndices(folder.Folders[index], realIndices); else - realIndices.Add(Files[index - numDirItems].Index); + realIndices.Add(folder.Files[index - numDirItems].Index); } HeapSort(&realIndices.Front(), realIndices.Size()); } @@ -126,111 +152,426 @@ void CProxyFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, CUIntV /////////////////////////////////////////////// // CProxyArchive -static UInt64 GetSize(IInArchive *archive, UInt32 index, PROPID propID) +static bool GetSize(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &size) { + size = 0; NCOM::CPropVariant prop; - if (archive->GetProperty(index, propID, &prop) == S_OK) - if (prop.vt != VT_EMPTY) - return ConvertPropVariantToUInt64(prop); - return 0; + if (archive->GetProperty(index, propID, &prop) != S_OK) + throw 20120228; + return ConvertPropVariantToUInt64(prop, size); } -void CProxyFolder::CalculateSizes(IInArchive *archive) +void CProxyArchive::CalculateSizes(unsigned folderIndex, IInArchive *archive) { - Size = PackSize = 0; - NumSubFolders = Folders.Size(); - NumSubFiles = Files.Size(); - CrcIsDefined = true; - Crc = 0; - int i; - for (i = 0; i < Files.Size(); i++) + CProxyFolder &folder = Folders[folderIndex]; + folder.Size = folder.PackSize = 0; + folder.NumSubFolders = folder.Folders.Size(); + folder.NumSubFiles = folder.Files.Size(); + folder.CrcIsDefined = true; + folder.Crc = 0; + unsigned i; + for (i = 0; i < folder.Files.Size(); i++) { - UInt32 index = Files[i].Index; - Size += GetSize(archive, index, kpidSize); - PackSize += GetSize(archive, index, kpidPackSize); + UInt32 index = folder.Files[i].Index; + UInt64 size, packSize; + bool sizeDefined = GetSize(archive, index, kpidSize, size); + folder.Size += size; + GetSize(archive, index, kpidPackSize, packSize); + folder.PackSize += packSize; { NCOM::CPropVariant prop; - if (archive->GetProperty(index, kpidCRC, &prop) == S_OK && prop.vt == VT_UI4) - Crc += prop.ulVal; + if (archive->GetProperty(index, kpidCRC, &prop) == S_OK) + { + if (prop.vt == VT_UI4) + folder.Crc += prop.ulVal; + else if (prop.vt != VT_EMPTY || size != 0 || !sizeDefined) + folder.CrcIsDefined = false; + } else - CrcIsDefined = false; + folder.CrcIsDefined = false; } } - for (i = 0; i < Folders.Size(); i++) + for (i = 0; i < folder.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; + unsigned subFolderIndex = folder.Folders[i]; + CProxyFolder &f = Folders[subFolderIndex]; + CalculateSizes(subFolderIndex, archive); + folder.Size += f.Size; + folder.PackSize += f.PackSize; + folder.NumSubFiles += f.NumSubFiles; + folder.NumSubFolders += f.NumSubFolders; + folder.Crc += f.Crc; if (!f.CrcIsDefined) - CrcIsDefined = false; + folder.CrcIsDefined = false; } } HRESULT CProxyArchive::Load(const CArc &arc, IProgress *progress) { - RootFolder.Clear(); + /* + DWORD tickCount = GetTickCount(); + for (int ttt = 0; ttt < 1000; ttt++) { + */ + + Folders.Clear(); + Folders.AddNew(); 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)); - } + if (progress) + RINOK(progress->SetTotal(numItems)); + UString filePath; UString fileName; for (UInt32 i = 0; i < numItems; i++) { - if (progress != NULL && (i & 0xFFFFF) == 0) + if (progress && (i & 0xFFFFF) == 0) { UInt64 currentItemIndex = i; RINOK(progress->SetCompleted(¤tItemIndex)); } - UString filePath; RINOK(arc.GetItemPath(i, filePath)); - CProxyFolder *curItem = &RootFolder; - int len = filePath.Length(); + unsigned curItem = 0; + unsigned len = filePath.Len(); fileName.Empty(); - for (int j = 0; j < len; j++) + + /* + if (arc.Ask_Deleted) + { + bool isDeleted = false; + RINOK(Archive_IsItem_Deleted(archive, i, isDeleted)); + if (isDeleted) + curItem = AddDirSubItem(curItem, (UInt32)(Int32)-1, false, L"[DELETED]"); + } + */ + + for (unsigned 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); + curItem = AddDirSubItem(curItem, (UInt32)(Int32)-1, false, fileName); fileName.Empty(); } else fileName += c; } + /* + that code must be implemeted to hide alt streams in list. + if (arc.Ask_AltStreams) + { + bool isAltStream; + RINOK(Archive_IsItem_AltStream(archive, i, isAltStream)); + if (isAltStream) + { + + } + } + */ + bool isFolder; - RINOK(IsArchiveItemFolder(archive, i, isFolder)); + RINOK(Archive_IsItem_Folder(archive, i, isFolder)); if (isFolder) - curItem->AddDirSubItem(i, true, fileName); + AddDirSubItem(curItem, i, true, fileName); else - curItem->AddFileSubItem(i, fileName); + Folders[curItem].AddFileSubItem(i, fileName); + } + CalculateSizes(0, archive); + + /* + } + char s[128]; + sprintf(s, "load archive %7d ms", GetTickCount() - tickCount); + OutputDebugStringA(s); + */ + + return S_OK; +} + + + +// ---------- for Tree-mode archive ---------- + +void CProxyArchive2::GetPathParts(int folderIndex, UStringVector &pathParts) const +{ + pathParts.Clear(); + while (folderIndex > 0) + { + const CProxyFolder2 &folder = Folders[folderIndex]; + const CProxyFile2 &file = Files[folder.ArcIndex]; + pathParts.Insert(0, file.Name); + int par = file.Parent; + if (par < 0) + break; + folderIndex = Files[par].FolderIndex; + } +} + +UString CProxyArchive2::GetFullPathPrefix(unsigned folderIndex) const +{ + return Folders[folderIndex].PathPrefix; + /* + UString result; + while (folderIndex > 0) + { + const CProxyFile2 &file = Files[Folders[folderIndex].ArcIndex]; + result = (UString)(file.Name) + (UString)WCHAR_PATH_SEPARATOR + result; + if (file.Parent < 0) + break; + folderIndex = Files[file.Parent].FolderIndex; + } + return result; + */ +} + +void CProxyArchive2::AddRealIndices_of_ArcItem(unsigned arcIndex, bool includeAltStreams, CUIntVector &realIndices) const +{ + realIndices.Add(arcIndex); + const CProxyFile2 &file = Files[arcIndex]; + if (file.FolderIndex >= 0) + AddRealIndices_of_Folder(file.FolderIndex, includeAltStreams, realIndices); + if (includeAltStreams && file.AltStreamsFolderIndex >= 0) + AddRealIndices_of_Folder(file.AltStreamsFolderIndex, includeAltStreams, realIndices); +} + +void CProxyArchive2::AddRealIndices_of_Folder(unsigned folderIndex, bool includeAltStreams, CUIntVector &realIndices) const +{ + const CRecordVector &subFiles = Folders[folderIndex].SubFiles; + FOR_VECTOR (i, subFiles) + { + AddRealIndices_of_ArcItem(subFiles[i], includeAltStreams, realIndices); } - RootFolder.CalculateSizes(archive); +} + +unsigned CProxyArchive2::GetRealIndex(unsigned folderIndex, unsigned index) const +{ + return Folders[folderIndex].SubFiles[index]; +} + +void CProxyArchive2::GetRealIndices(unsigned folderIndex, const UInt32 *indices, UInt32 numItems, bool includeAltStreams, CUIntVector &realIndices) const +{ + const CProxyFolder2 &folder = Folders[folderIndex]; + realIndices.Clear(); + for (UInt32 i = 0; i < numItems; i++) + { + AddRealIndices_of_ArcItem(folder.SubFiles[indices[i]], includeAltStreams, realIndices); + } + HeapSort(&realIndices.Front(), realIndices.Size()); +} + +void CProxyArchive2::CalculateSizes(unsigned folderIndex, IInArchive *archive) +{ + CProxyFolder2 &folder = Folders[folderIndex]; + folder.Size = folder.PackSize = 0; + folder.NumSubFolders = 0; // folder.Folders.Size(); + folder.NumSubFiles = 0; // folder.Files.Size(); + folder.CrcIsDefined = true; + folder.Crc = 0; + FOR_VECTOR (i, folder.SubFiles) + { + UInt32 index = folder.SubFiles[i]; + UInt64 size, packSize; + bool sizeDefined = GetSize(archive, index, kpidSize, size); + folder.Size += size; + GetSize(archive, index, kpidPackSize, packSize); + folder.PackSize += packSize; + { + NCOM::CPropVariant prop; + if (archive->GetProperty(index, kpidCRC, &prop) == S_OK) + { + if (prop.vt == VT_UI4) + folder.Crc += prop.ulVal; + else if (prop.vt != VT_EMPTY || size != 0 || !sizeDefined) + folder.CrcIsDefined = false; + } + else + folder.CrcIsDefined = false; + } + + const CProxyFile2 &subFile = Files[index]; + if (subFile.FolderIndex < 0) + { + folder.NumSubFiles++; + } + else + { + folder.NumSubFolders++; + CProxyFolder2 &f = Folders[subFile.FolderIndex]; + f.PathPrefix = folder.PathPrefix + subFile.Name + WCHAR_PATH_SEPARATOR; + CalculateSizes(subFile.FolderIndex, archive); + folder.Size += f.Size; + folder.PackSize += f.PackSize; + folder.NumSubFiles += f.NumSubFiles; + folder.NumSubFolders += f.NumSubFolders; + folder.Crc += f.Crc; + if (!f.CrcIsDefined) + folder.CrcIsDefined = false; + } + + if (subFile.AltStreamsFolderIndex < 0) + { + // folder.NumSubFiles++; + } + else + { + // folder.NumSubFolders++; + CProxyFolder2 &f = Folders[subFile.AltStreamsFolderIndex]; + f.PathPrefix = folder.PathPrefix + subFile.Name + L":"; + CalculateSizes(subFile.AltStreamsFolderIndex, archive); + /* + folder.Size += f.Size; + folder.PackSize += f.PackSize; + folder.NumSubFiles += f.NumSubFiles; + folder.NumSubFolders += f.NumSubFolders; + folder.Crc += f.Crc; + if (!f.CrcIsDefined) + folder.CrcIsDefined = false; + */ + } + + + } +} + + +bool CProxyArchive2::IsThere_SubDir(unsigned folderIndex, const UString &name) const +{ + const CRecordVector &subFiles = Folders[folderIndex].SubFiles; + FOR_VECTOR (i, subFiles) + { + const CProxyFile2 &file = Files[subFiles[i]]; + if (file.IsDir()) + if (CompareFileNames(name, file.Name) == 0) + return true; + } + return false; +} + +HRESULT CProxyArchive2::Load(const CArc &arc, IProgress *progress) +{ + if (!arc.GetRawProps) + return E_FAIL; + + // DWORD tickCount = GetTickCount(); + + Folders.Clear(); + + IInArchive *archive = arc.Archive; + + UInt32 numItems; + RINOK(archive->GetNumberOfItems(&numItems)); + if (progress) + RINOK(progress->SetTotal(numItems)); + UString fileName; + { + CProxyFolder2 &folder = Folders.AddNew(); + folder.ArcIndex = -1; + } + + Files.Alloc(numItems); + + UInt32 i; + for (i = 0; i < numItems; i++) + { + if (progress && (i & 0xFFFFF) == 0) + { + UInt64 currentItemIndex = i; + RINOK(progress->SetCompleted(¤tItemIndex)); + } + + CProxyFile2 &file = Files[i]; + + #ifdef MY_CPU_LE + const void *p; + UInt32 size; + UInt32 propType; + RINOK(arc.GetRawProps->GetRawProp(i, kpidName, &p, &size, &propType)); + + if (p && propType == PROP_DATA_TYPE_wchar_t_PTR_Z_LE) + { + file.Name = (const wchar_t *)p; + file.NameSize = 0; + if (size >= 2) + file.NameSize = size / 2 - 1; + } + else + #endif + { + NCOM::CPropVariant prop; + RINOK(arc.Archive->GetProperty(i, kpidName, &prop)); + const wchar_t *s; + if (prop.vt == VT_BSTR) + s = prop.bstrVal; + else if (prop.vt == VT_EMPTY) + s = L"[Content]"; + else + return E_FAIL; + file.NameSize = MyStringLen(s); + file.Name = new wchar_t[file.NameSize + 1]; + file.NeedDeleteName = true; + MyStringCopy((wchar_t *)file.Name, s); + } + UInt32 parent = (UInt32)(Int32)-1; + UInt32 parentType = 0; + RINOK(arc.GetRawProps->GetParent(i, &parent, &parentType)); + file.Parent = (Int32)parent; + + if (arc.Ask_Deleted) + { + bool isDeleted = false; + RINOK(Archive_IsItem_Deleted(archive, i, isDeleted)); + if (isDeleted) + { + // continue; + // curItem = AddDirSubItem(curItem, (UInt32)(Int32)-1, false, L"[DELETED]"); + } + } + + bool isFolder; + RINOK(Archive_IsItem_Folder(archive, i, isFolder)); + + if (isFolder) + { + file.FolderIndex = Folders.Size(); + CProxyFolder2 &folder = Folders.AddNew(); + folder.ArcIndex = i; + } + if (arc.Ask_AltStream) + RINOK(Archive_IsItem_AltStream(archive, i, file.IsAltStream)); + } + + for (i = 0; i < numItems; i++) + { + CProxyFile2 &file = Files[i]; + if (file.IsAltStream) + { + if (file.Parent >= 0) + { + int &folderIndex = Files[file.Parent].AltStreamsFolderIndex; + if (folderIndex < 0) + { + folderIndex = Folders.Size(); + CProxyFolder2 &folder = Folders.AddNew(); + folder.ArcIndex = file.Parent; // do we need it ??? + } + Folders[folderIndex].SubFiles.Add(i); + } + } + else + { + int folderIndex = GetParentFolderOfFile(i); + if (folderIndex < 0) + return E_FAIL; + Folders[folderIndex].SubFiles.Add(i); + } + } + CalculateSizes(0, archive); + + /* + char s[128]; + sprintf(s, "load archive %7d ms", GetTickCount() - tickCount); + OutputDebugStringA(s); + */ return S_OK; } diff --git a/CPP/7zip/UI/Agent/AgentProxy.h b/CPP/7zip/UI/Agent/AgentProxy.h old mode 100755 new mode 100644 index dcf52f04..1755d444 --- a/CPP/7zip/UI/Agent/AgentProxy.h +++ b/CPP/7zip/UI/Agent/AgentProxy.h @@ -13,39 +13,116 @@ struct CProxyFile class CProxyFolder: public CProxyFile { - int FindDirSubItemIndex(const UString &name, int &insertPos) const; - void AddRealIndices(CUIntVector &realIndices) const; public: - CProxyFolder *Parent; - CObjectVector Folders; + int Parent; + CRecordVector Folders; CObjectVector Files; + UInt64 Size; + UInt64 PackSize; + UInt32 Crc; + UInt32 NumSubFolders; + UInt32 NumSubFiles; bool IsLeaf; - bool CrcIsDefined; + + CProxyFolder(): Parent(-1) {}; + void AddFileSubItem(UInt32 index, const UString &name); + void Clear(); +}; + +class CProxyArchive +{ + int FindDirSubItemIndex(unsigned folderIndex, const UString &name, unsigned &insertPos) const; + + void CalculateSizes(unsigned folderIndex, IInArchive *archive); + unsigned AddDirSubItem(unsigned folderIndex, UInt32 index, bool leaf, const UString &name); +public: + CObjectVector Folders; // Folders[0] - isRoot + + int FindDirSubItemIndex(unsigned folderIndex, const UString &name) const; + void GetPathParts(int folderIndex, UStringVector &pathParts) const; + UString GetFullPathPrefix(int folderIndex) const; + + // AddRealIndices DOES ADD also item represented by folderIndex (if it's Leaf) + void AddRealIndices(unsigned folderIndex, CUIntVector &realIndices) const; + int GetRealIndex(unsigned folderIndex, unsigned index) const; + void GetRealIndices(unsigned folderIndex, const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const; + + HRESULT Load(const CArc &arc, IProgress *progress); +}; + + +// ---------- for Tree-mode archive ---------- + +struct CProxyFile2 +{ + int FolderIndex; // >= 0 for dir. (index in ProxyArchive2->Folders) + int AltStreamsFolderIndex; // >= 0 if there are alt streams. (index in ProxyArchive2->Folders) + int Parent; // >= 0 if there is parent. (index in archive and in ProxyArchive2->Files) + const wchar_t *Name; + unsigned NameSize; + bool Ignore; + bool IsAltStream; + bool NeedDeleteName; + + int GetFolderIndex(bool forAltStreams) const { return forAltStreams ? AltStreamsFolderIndex : FolderIndex; } + + bool IsDir() const { return FolderIndex >= 0; } + CProxyFile2(): FolderIndex(-1), AltStreamsFolderIndex(-1), Name(NULL), Ignore(false), IsAltStream(false), NeedDeleteName(false) {} + ~CProxyFile2() + { + if (NeedDeleteName) + delete [](wchar_t *)Name; + } +}; + +class CProxyFolder2 +{ +public: + Int32 ArcIndex; // = -1 for Root folder + CRecordVector SubFiles; + UString PathPrefix; UInt64 Size; UInt64 PackSize; + bool CrcIsDefined; UInt32 Crc; UInt32 NumSubFolders; UInt32 NumSubFiles; - CProxyFolder(): Parent(NULL) {}; - int FindDirSubItemIndex(const UString &name) const; - CProxyFolder* AddDirSubItem(UInt32 index, bool leaf, const UString &name); + CProxyFolder2(): ArcIndex(-1) {}; void AddFileSubItem(UInt32 index, const UString &name); void Clear(); - void GetPathParts(UStringVector &pathParts) const; - UString GetFullPathPrefix() const; - void GetRealIndices(const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const; - void CalculateSizes(IInArchive *archive); }; -struct CProxyArchive +class CProxyArchive2 { - CProxyFolder RootFolder; - bool ThereIsPathProp; + void CalculateSizes(unsigned folderIndex, IInArchive *archive); + // AddRealIndices_of_Folder DOES NOT ADD item itself represented by folderIndex + void AddRealIndices_of_Folder(unsigned folderIndex, bool includeAltStreams, CUIntVector &realIndices) const; +public: + CObjectVector Folders; // Folders[0] - is root folder + CObjArray Files; // all aitems from archive in same order + + bool IsThere_SubDir(unsigned folderIndex, const UString &name) const; + + void GetPathParts(int folderIndex, UStringVector &pathParts) const; + UString GetFullPathPrefix(unsigned folderIndex) const; + + // AddRealIndices_of_ArcItem DOES ADD item and subItems + void AddRealIndices_of_ArcItem(unsigned arcIndex, bool includeAltStreams, CUIntVector &realIndices) const; + unsigned GetRealIndex(unsigned folderIndex, unsigned index) const; + void GetRealIndices(unsigned folderIndex, const UInt32 *indices, UInt32 numItems, bool includeAltStreams, CUIntVector &realIndices) const; HRESULT Load(const CArc &arc, IProgress *progress); + + int GetParentFolderOfFile(UInt32 indexInArc) const + { + const CProxyFile2 &file = Files[indexInArc]; + if (file.Parent < 0) + return 0; + return Files[file.Parent].FolderIndex; + } }; #endif diff --git a/CPP/7zip/UI/Agent/ArchiveFolder.cpp b/CPP/7zip/UI/Agent/ArchiveFolder.cpp old mode 100755 new mode 100644 index 237afa05..81291f44 --- a/CPP/7zip/UI/Agent/ArchiveFolder.cpp +++ b/CPP/7zip/UI/Agent/ArchiveFolder.cpp @@ -2,15 +2,26 @@ #include "StdAfx.h" -#include "Common/ComTry.h" +#include "../../../Common/ComTry.h" #include "../Common/ArchiveExtractCallback.h" #include "Agent.h" -STDMETHODIMP CAgentFolder::CopyTo(const UInt32 *indices, UInt32 numItems, +/* +STDMETHODIMP CAgentFolder::SetReplaceAltStreamCharsMode(Int32 replaceAltStreamCharsMode) +{ + _replaceAltStreamCharsMode = replaceAltStreamCharsMode; + return S_OK; +} +*/ + +STDMETHODIMP CAgentFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 numItems, + Int32 includeAltStreams, Int32 replaceAltStreamCharsMode, const wchar_t *path, IFolderOperationsExtractCallback *callback) { + if (moveMode) + return E_NOTIMPL; COM_TRY_BEGIN CMyComPtr extractCallback2; { @@ -18,15 +29,11 @@ STDMETHODIMP CAgentFolder::CopyTo(const UInt32 *indices, UInt32 numItems, RINOK(callbackWrap.QueryInterface(IID_IFolderArchiveExtractCallback, &extractCallback2)); } NExtract::NPathMode::EEnum pathMode = _flatMode ? - NExtract::NPathMode::kNoPathnames : - NExtract::NPathMode::kCurrentPathnames; - return Extract(indices,numItems, pathMode, NExtract::NOverwriteMode::kAskBefore, + NExtract::NPathMode::kNoPaths : + NExtract::NPathMode::kCurPaths; + return Extract(indices, numItems, + includeAltStreams, replaceAltStreamCharsMode, + pathMode, NExtract::NOverwriteMode::kAsk, path, BoolToInt(false), extractCallback2); 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 old mode 100755 new mode 100644 index 3a16a667..13d94bdf --- a/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp +++ b/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp @@ -15,8 +15,8 @@ void CArchiveFolderManager::LoadFormats() int CArchiveFolderManager::FindFormat(const UString &type) { - for (int i = 0; i < _codecs->Formats.Size(); i++) - if (type.CompareNoCase(_codecs->Formats[i].Name) == 0) + FOR_VECTOR (i, _codecs->Formats) + if (type.IsEqualToNoCase(_codecs->Formats[i].Name)) return i; return -1; } @@ -60,11 +60,11 @@ STDMETHODIMP CArchiveFolderManager::GetExtensions(const wchar_t *type, BSTR *ext static void AddIconExt(const CCodecIcons &lib, UString &dest) { - for (int j = 0; j < lib.IconPairs.Size(); j++) + FOR_VECTOR (i, lib.IconPairs) { if (!dest.IsEmpty()) dest += L' '; - dest += lib.IconPairs[j].Ext; + dest += lib.IconPairs[i].Ext; } } @@ -73,7 +73,7 @@ STDMETHODIMP CArchiveFolderManager::GetExtensions(BSTR *extensions) LoadFormats(); *extensions = 0; UString res; - for (int i = 0; i < _codecs->Libs.Size(); i++) + FOR_VECTOR (i, _codecs->Libs) AddIconExt(_codecs->Libs[i], res); AddIconExt(_codecs->InternalIcons, res); return StringToBstr(res, extensions); @@ -84,7 +84,7 @@ STDMETHODIMP CArchiveFolderManager::GetIconPath(const wchar_t *ext, BSTR *iconPa LoadFormats(); *iconPath = 0; *iconIndex = 0; - for (int i = 0; i < _codecs->Libs.Size(); i++) + FOR_VECTOR (i, _codecs->Libs) { const CCodecLib &lib = _codecs->Libs[i]; int ii; @@ -112,7 +112,7 @@ STDMETHODIMP CArchiveFolderManager::GetTypes(BSTR *types) { LoadFormats(); UString typesStrings; - for(int i = 0; i < _codecs.Formats.Size(); i++) + FOR_VECTOR(i, _codecs.Formats) { const CArcInfoEx &ai = _codecs.Formats[i]; if (ai.AssociateExts.Size() == 0) diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp old mode 100755 new mode 100644 index 656602cb..003f6d98 --- a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp +++ b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp @@ -2,79 +2,157 @@ #include "StdAfx.h" -#include "Common/ComTry.h" +#include "../../../Common/ComTry.h" -#include "Windows/FileDir.h" +#include "../../../Windows/FileDir.h" #include "../../Common/FileStreams.h" +#include "../../Common/LimitedStreams.h" + +#include "../../Compress/CopyCoder.h" + #include "../Common/WorkDir.h" #include "Agent.h" using namespace NWindows; using namespace NFile; -using namespace NDirectory; +using namespace NDir; void CAgentFolder::GetPathParts(UStringVector &pathParts) { - _proxyFolderItem->GetPathParts(pathParts); + if (_proxyArchive2) + _proxyArchive2->GetPathParts(_proxyFolderItem, pathParts); + else + _proxyArchive->GetPathParts(_proxyFolderItem, pathParts); +} + +static bool DeleteEmptyFolderAndEmptySubFolders(const FString &path) +{ + NFind::CFileInfo fileInfo; + FString pathPrefix = path + FCHAR_PATH_SEPARATOR; + { + NFind::CEnumerator enumerator(pathPrefix + FCHAR_ANY_MASK); + while (enumerator.Next(fileInfo)) + { + if (fileInfo.IsDir()) + if (!DeleteEmptyFolderAndEmptySubFolders(pathPrefix + fileInfo.Name)) + return false; + } + } + /* + // we don't need clear readonly for folders + if (!SetFileAttrib(path, 0)) + return false; + */ + return RemoveDir(path); } + HRESULT CAgentFolder::CommonUpdateOperation( AGENT_OP operation, + bool moveMode, const wchar_t *newItemName, const NUpdateArchive::CActionSet *actionSet, - const UINT32 *indices, UINT32 numItems, + const UInt32 *indices, UInt32 numItems, IFolderArchiveUpdateCallback *updateCallback100) { - CWorkDirTempFile tempFile; - RINOK(tempFile.CreateTempFile(us2fs(_agentSpec->_archiveFilePath))); + if (!_agentSpec->CanUpdate()) + return E_NOTIMPL; - /* - if (SetOutProperties(anOutArchive, aCompressionInfo.Method) != S_OK) - return NFileOperationReturnCode::kError; - */ - //////////////////////////// // Save FolderItem; UStringVector pathParts; GetPathParts(pathParts); - HRESULT result; - switch (operation) + FStringVector requestedPaths; + FStringVector processedPaths; + + CWorkDirTempFile tempFile; + RINOK(tempFile.CreateTempFile(us2fs(_agentSpec->_archiveFilePath))); { - case AGENT_OP_Delete: - result = _agentSpec->DeleteItems(tempFile.OutStream, indices, numItems, updateCallback100); - break; - case AGENT_OP_CreateFolder: - result = _agentSpec->CreateFolder(tempFile.OutStream, newItemName, updateCallback100); - break; - case AGENT_OP_Rename: - result = _agentSpec->RenameItem(tempFile.OutStream, indices, numItems, newItemName, updateCallback100); - break; - case AGENT_OP_CopyFromFile: - result = _agentSpec->UpdateOneFile(tempFile.OutStream, indices, numItems, newItemName, updateCallback100); - break; - case AGENT_OP_Uni: + CMyComPtr tailStream; + const CArc &arc = *_agentSpec->_archiveLink.GetArc(); + + if (arc.ArcStreamOffset == 0) + tailStream = tempFile.OutStream; + else { - Byte actionSetByte[NUpdateArchive::NPairState::kNumValues]; - for (int i = 0; i < NUpdateArchive::NPairState::kNumValues; i++) - actionSetByte[i] = (Byte)actionSet->StateActions[i]; - result = _agentSpec->DoOperation2(tempFile.OutStream, actionSetByte, NULL, updateCallback100); - break; + if (arc.Offset < 0) + return E_NOTIMPL; + RINOK(arc.InStream->Seek(0, STREAM_SEEK_SET, NULL)); + RINOK(NCompress::CopyStream_ExactSize(arc.InStream, tempFile.OutStream, arc.ArcStreamOffset, NULL)); + CTailOutStream *tailStreamSpec = new CTailOutStream; + tailStream = tailStreamSpec; + tailStreamSpec->Stream = tempFile.OutStream; + tailStreamSpec->Offset = arc.ArcStreamOffset; + tailStreamSpec->Init(); } - default: - return E_FAIL; + + HRESULT result; + + switch (operation) + { + case AGENT_OP_Delete: + result = _agentSpec->DeleteItems(tailStream, indices, numItems, updateCallback100); + break; + case AGENT_OP_CreateFolder: + result = _agentSpec->CreateFolder(tailStream, newItemName, updateCallback100); + break; + case AGENT_OP_Rename: + result = _agentSpec->RenameItem(tailStream, indices, numItems, newItemName, updateCallback100); + break; + case AGENT_OP_CopyFromFile: + result = _agentSpec->UpdateOneFile(tailStream, indices, numItems, newItemName, updateCallback100); + break; + case AGENT_OP_Uni: + { + Byte actionSetByte[NUpdateArchive::NPairState::kNumValues]; + for (int i = 0; i < NUpdateArchive::NPairState::kNumValues; i++) + actionSetByte[i] = (Byte)actionSet->StateActions[i]; + result = _agentSpec->DoOperation2( + moveMode ? &requestedPaths : NULL, + moveMode ? &processedPaths : NULL, + tailStream, actionSetByte, NULL, updateCallback100); + break; + } + default: + return E_FAIL; + } + + RINOK(result); } - - RINOK(result); + _agentSpec->KeepModeForNextOpen(); _agentSpec->Close(); + // before 9.26: if there was error for MoveToOriginal archive was closed. + // now: we reopen archive after close + // m_FolderItem = NULL; - RINOK(tempFile.MoveToOriginal(true)); + HRESULT res = tempFile.MoveToOriginal(true); + + // RINOK(res); + if (res == S_OK) + { + if (moveMode) + { + unsigned i; + for (i = 0; i < processedPaths.Size(); i++) + { + DeleteFileAlways(processedPaths[i]); + } + for (i = 0; i < requestedPaths.Size(); i++) + { + const FString &fs = requestedPaths[i]; + if (NFind::DoesDirExist(fs)) + DeleteEmptyFolderAndEmptySubFolders(fs); + } + } + } + { CMyComPtr openCallback; @@ -85,12 +163,11 @@ HRESULT CAgentFolder::CommonUpdateOperation( RINOK(_agentSpec->ReOpen(openCallback)); } - //////////////////////////// // Restore FolderItem; CMyComPtr archiveFolder; RINOK(_agentSpec->BindToRootFolder(&archiveFolder)); - for (int i = 0; i < pathParts.Size(); i++) + FOR_VECTOR (i, pathParts) { CMyComPtr newFolder; archiveFolder->BindToFolder(pathParts[i], &newFolder); @@ -105,15 +182,16 @@ HRESULT CAgentFolder::CommonUpdateOperation( RINOK(archiveFolderInternal->GetAgentFolder(&agentFolder)); _proxyFolderItem = agentFolder->_proxyFolderItem; _proxyArchive = agentFolder->_proxyArchive; + _proxyArchive2 = agentFolder->_proxyArchive2; _parentFolder = agentFolder->_parentFolder; - return S_OK; + return res; } -STDMETHODIMP CAgentFolder::CopyFrom( +STDMETHODIMP CAgentFolder::CopyFrom(Int32 moveMode, const wchar_t *fromFolderPath, // test it const wchar_t **itemsPaths, - UINT32 numItems, + UInt32 numItems, IProgress *progress) { COM_TRY_BEGIN @@ -126,8 +204,9 @@ STDMETHODIMP CAgentFolder::CopyFrom( { RINOK(_agentSpec->SetFiles(fromFolderPath, itemsPaths, numItems)); RINOK(_agentSpec->SetFolder(this)); - return CommonUpdateOperation(AGENT_OP_Uni, NULL, - &NUpdateArchive::kAddActionSet, 0, 0, updateCallback100); + return CommonUpdateOperation(AGENT_OP_Uni, (moveMode != 0), NULL, + &NUpdateArchive::k_ActionSet_Add, + 0, 0, updateCallback100); } catch(const UString &s) { @@ -150,8 +229,8 @@ STDMETHODIMP CAgentFolder::CopyFromFile(UInt32 destIndex, const wchar_t *itemPat try { RINOK(_agentSpec->SetFolder(this)); - return CommonUpdateOperation(AGENT_OP_CopyFromFile, itemPath, - &NUpdateArchive::kAddActionSet, + return CommonUpdateOperation(AGENT_OP_CopyFromFile, false, itemPath, + &NUpdateArchive::k_ActionSet_Add, &indices.Front(), indices.Size(), updateCallback100); } catch(const UString &s) @@ -162,7 +241,7 @@ STDMETHODIMP CAgentFolder::CopyFromFile(UInt32 destIndex, const wchar_t *itemPat COM_TRY_END } -STDMETHODIMP CAgentFolder::Delete(const UINT32 *indices, UINT32 numItems, IProgress *progress) +STDMETHODIMP CAgentFolder::Delete(const UInt32 *indices, UInt32 numItems, IProgress *progress) { COM_TRY_BEGIN RINOK(_agentSpec->SetFolder(this)); @@ -173,16 +252,24 @@ STDMETHODIMP CAgentFolder::Delete(const UINT32 *indices, UINT32 numItems, IProgr RINOK(progressWrapper.QueryInterface( IID_IFolderArchiveUpdateCallback, &updateCallback100)); } - return CommonUpdateOperation(AGENT_OP_Delete, NULL, - &NUpdateArchive::kDeleteActionSet, indices, numItems, updateCallback100); + return CommonUpdateOperation(AGENT_OP_Delete, false, NULL, + &NUpdateArchive::k_ActionSet_Delete, 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; + if (_proxyArchive2) + { + if (_proxyArchive2->IsThere_SubDir(_proxyFolderItem, name)) + return ERROR_ALREADY_EXISTS; + } + else + { + if (_proxyArchive->FindDirSubItemIndex(_proxyFolderItem, name) >= 0) + return ERROR_ALREADY_EXISTS; + } RINOK(_agentSpec->SetFolder(this)); CMyComPtr updateCallback100; if (progress) @@ -190,11 +277,11 @@ STDMETHODIMP CAgentFolder::CreateFolder(const wchar_t *name, IProgress *progress CMyComPtr progressWrapper = progress; RINOK(progressWrapper.QueryInterface(IID_IFolderArchiveUpdateCallback, &updateCallback100)); } - return CommonUpdateOperation(AGENT_OP_CreateFolder, name, NULL, NULL, 0, updateCallback100); + return CommonUpdateOperation(AGENT_OP_CreateFolder, false, name, NULL, NULL, 0, updateCallback100); COM_TRY_END } -STDMETHODIMP CAgentFolder::Rename(UINT32 index, const wchar_t *newName, IProgress *progress) +STDMETHODIMP CAgentFolder::Rename(UInt32 index, const wchar_t *newName, IProgress *progress) { COM_TRY_BEGIN CUIntVector indices; @@ -206,7 +293,7 @@ STDMETHODIMP CAgentFolder::Rename(UINT32 index, const wchar_t *newName, IProgres CMyComPtr progressWrapper = progress; RINOK(progressWrapper.QueryInterface(IID_IFolderArchiveUpdateCallback, &updateCallback100)); } - return CommonUpdateOperation(AGENT_OP_Rename, newName, NULL, &indices.Front(), + return CommonUpdateOperation(AGENT_OP_Rename, false, newName, NULL, &indices.Front(), indices.Size(), updateCallback100); COM_TRY_END } @@ -216,7 +303,7 @@ STDMETHODIMP CAgentFolder::CreateFile(const wchar_t * /* name */, IProgress * /* return E_NOTIMPL; } -STDMETHODIMP CAgentFolder::SetProperty(UINT32 /* index */, PROPID /* propID */, +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 old mode 100755 new mode 100644 index 2357af31..0f87cb55 --- a/CPP/7zip/UI/Agent/IFolderArchive.h +++ b/CPP/7zip/UI/Agent/IFolderArchive.h @@ -3,6 +3,8 @@ #ifndef __IFOLDER_ARCHIVE_H #define __IFOLDER_ARCHIVE_H +#include "../../../Common/MyString.h" + #include "../../Archive/IArchive.h" #include "../../UI/Common/LoadCodecs.h" #include "../../UI/FileManager/IFolder.h" @@ -15,12 +17,14 @@ #define INTERFACE_IArchiveFolder(x) \ STDMETHOD(Extract)(const UInt32 *indices, UInt32 numItems, \ + Int32 includeAltStreams, \ + Int32 replaceAltStreamCharsMode, \ NExtract::NPathMode::EEnum pathMode, \ NExtract::NOverwriteMode::EEnum overwriteMode, \ const wchar_t *path, Int32 testMode, \ IFolderArchiveExtractCallback *extractCallback2) x; \ -FOLDER_ARCHIVE_INTERFACE(IArchiveFolder, 0x05) +FOLDER_ARCHIVE_INTERFACE(IArchiveFolder, 0x0D) { INTERFACE_IArchiveFolder(PURE) }; @@ -58,14 +62,19 @@ FOLDER_ARCHIVE_INTERFACE_SUB(IFolderArchiveUpdateCallback, IProgress, 0x0B) STDMETHOD(SetFiles)(const wchar_t *folderPrefix, const wchar_t **names, UInt32 numNames) x; \ STDMETHOD(DeleteItems)(ISequentialOutStream *outArchiveStream, \ const UInt32 *indices, UInt32 numItems, IFolderArchiveUpdateCallback *updateCallback) x; \ - STDMETHOD(DoOperation)(CCodecs *codecs, int index, \ + STDMETHOD(DoOperation)( \ + FStringVector *requestedPaths, \ + FStringVector *processedPaths, \ + CCodecs *codecs, int index, \ ISequentialOutStream *outArchiveStream, const Byte *stateActions, const wchar_t *sfxModule, \ IFolderArchiveUpdateCallback *updateCallback) x; \ STDMETHOD(DoOperation2)( \ + FStringVector *requestedPaths, \ + FStringVector *processedPaths, \ ISequentialOutStream *outArchiveStream, const Byte *stateActions, const wchar_t *sfxModule, \ IFolderArchiveUpdateCallback *updateCallback) x; \ -FOLDER_ARCHIVE_INTERFACE(IOutFolderArchive, 0x0A) +FOLDER_ARCHIVE_INTERFACE(IOutFolderArchive, 0x0F) { INTERFACE_IOutFolderArchive(PURE) }; diff --git a/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp b/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp old mode 100755 new mode 100644 index 3687c3d0..cfdacb2f --- a/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp +++ b/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp @@ -2,8 +2,9 @@ #include "StdAfx.h" -#include "Windows/Error.h" -#include "Common/IntToString.h" +#include "../../../Common/IntToString.h" + +#include "../../../Windows/ErrorMsg.h" #include "UpdateCallbackAgent.h" @@ -62,11 +63,11 @@ HRESULT CUpdateCallbackAgent::OpenFileError(const wchar_t *name, DWORD systemErr { if (Callback) { - RINOK(Callback->UpdateErrorMessage( - UString(L"WARNING: ") + - NError::MyFormatMessageW(systemError) + - UString(L": ") + - name)); + UString s = L"WARNING: "; + s += NError::MyFormatMessage(systemError); + s += L": "; + s += name; + RINOK(Callback->UpdateErrorMessage(s)); return S_FALSE; } } diff --git a/CPP/7zip/UI/Agent/UpdateCallbackAgent.h b/CPP/7zip/UI/Agent/UpdateCallbackAgent.h old mode 100755 new mode 100644 index 1d5ed17a..3707a93c --- a/CPP/7zip/UI/Agent/UpdateCallbackAgent.h +++ b/CPP/7zip/UI/Agent/UpdateCallbackAgent.h @@ -1,9 +1,10 @@ // UpdateCallbackAgent.h -#ifndef __UPDATECALLBACKAGENT_H -#define __UPDATECALLBACKAGENT_H +#ifndef __UPDATE_CALLBACK_AGENT_H +#define __UPDATE_CALLBACK_AGENT_H #include "../Common/UpdateCallback.h" + #include "IFolderArchive.h" class CUpdateCallbackAgent: public IUpdateCallbackUI diff --git a/CPP/7zip/UI/Client7z/Client7z.cpp b/CPP/7zip/UI/Client7z/Client7z.cpp old mode 100755 new mode 100644 index d181843d..0c7ae1c9 --- a/CPP/7zip/UI/Client7z/Client7z.cpp +++ b/CPP/7zip/UI/Client7z/Client7z.cpp @@ -2,39 +2,46 @@ #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 + +#include "../../../Common/Defs.h" +#include "../../../Common/MyInitGuid.h" + +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/DLL.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/NtCheck.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/PropVariantConv.h" #include "../../Common/FileStreams.h" #include "../../Archive/IArchive.h" #include "../../IPassword.h" -#include "../../MyVersion.h" +#include "../../../../C/7zVersion.h" #ifdef _WIN32 HINSTANCE g_hInstance = 0; #endif +// Tou can find the list of all GUIDs in Guid.txt file. // use another CLSIDs, if you want to support other formats (zip, rar, ...). // {23170F69-40C1-278A-1000-000110070000} DEFINE_GUID(CLSID_CFormat7z, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00); using namespace NWindows; +using namespace NFile; +using namespace NDir; #define kDllName "7z.dll" -static const char *kCopyrightString = "\n" MY_7ZIP_VERSION +static const char *kCopyrightString = "\n7-Zip " MY_VERSION " (" kDllName " client) " MY_COPYRIGHT " " MY_DATE "\n"; @@ -46,12 +53,6 @@ static const char *kHelpString = " Client7z.exe x archive.7z : eXtract files from archive.7z\n"; -typedef UINT32 (WINAPI * CreateObjectFunc)( - const GUID *clsID, - const GUID *interfaceID, - void **outObject); - - static AString FStringToConsoleString(const FString &s) { return GetOemString(fs2us(s)); @@ -177,7 +178,11 @@ 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"; +static const char *kUnavailableData = "Unavailable data"; +static const char *kUnexpectedEnd = "Unexpected end of data"; +static const char *kDataAfterEnd = "There are some data after the end of the payload data"; +static const char *kIsNotArc = "Is not archive"; +static const char *kHeadersError = "Headers Error"; class CArchiveExtractCallback: public IArchiveExtractCallback, @@ -232,7 +237,7 @@ void CArchiveExtractCallback::Init(IInArchive *archiveHandler, const FString &di NumErrors = 0; _archiveHandler = archiveHandler; _directoryPath = directoryPath; - NFile::NName::NormalizeDirPathPrefix(_directoryPath); + NName::NormalizeDirPathPrefix(_directoryPath); } STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 /* size */) @@ -314,10 +319,8 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, // Get Size NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop)); - bool newFileSizeDefined = (prop.vt != VT_EMPTY); UInt64 newFileSize; - if (newFileSizeDefined) - newFileSize = ConvertPropVariantToUInt64(prop); + /* bool newFileSizeDefined = */ ConvertPropVariantToUInt64(prop, newFileSize); } @@ -325,7 +328,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, // Create folders for file int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR); if (slashPos >= 0) - NFile::NDirectory::CreateComplexDirectory(_directoryPath + us2fs(_filePath.Left(slashPos))); + CreateComplexDir(_directoryPath + us2fs(_filePath.Left(slashPos))); } FString fullProcessedPath = _directoryPath + us2fs(_filePath); @@ -333,14 +336,14 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, if (_processedFileInfo.isDir) { - NFile::NDirectory::CreateComplexDirectory(fullProcessedPath); + CreateComplexDir(fullProcessedPath); } else { - NFile::NFind::CFileInfo fi; + NFind::CFileInfo fi; if (fi.Find(fullProcessedPath)) { - if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) + if (!DeleteFileAlways(fullProcessedPath)) { PrintError("Can not delete output file", fullProcessedPath); return E_ABORT; @@ -379,27 +382,53 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) { - switch(operationResult) + switch (operationResult) { case NArchive::NExtract::NOperationResult::kOK: break; default: { NumErrors++; - PrintString(" "); - switch(operationResult) + PrintString(" : "); + const char *s = NULL; + switch (operationResult) { - case NArchive::NExtract::NOperationResult::kUnSupportedMethod: - PrintString(kUnsupportedMethod); + case NArchive::NExtract::NOperationResult::kUnsupportedMethod: + s = kUnsupportedMethod; break; case NArchive::NExtract::NOperationResult::kCRCError: - PrintString(kCRCFailed); + s = kCRCFailed; break; case NArchive::NExtract::NOperationResult::kDataError: - PrintString(kDataError); + s = kDataError; + break; + case NArchive::NExtract::NOperationResult::kUnavailable: + s = kUnavailableData; + break; + case NArchive::NExtract::NOperationResult::kUnexpectedEnd: + s = kUnexpectedEnd; + break; + case NArchive::NExtract::NOperationResult::kDataAfterEnd: + s = kDataAfterEnd; + break; + case NArchive::NExtract::NOperationResult::kIsNotArc: + s = kIsNotArc; + break; + case NArchive::NExtract::NOperationResult::kHeadersError: + s = kHeadersError; break; - default: - PrintString(kUnknownError); + } + if (s) + { + PrintString("Error : "); + PrintString(s); + } + else + { + char temp[16]; + ConvertUInt32ToString(operationResult, temp); + PrintString("Error #"); + PrintString(temp); } } } @@ -412,7 +441,7 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) } _outFileStream.Release(); if (_extractMode && _processedFileInfo.AttribDefined) - NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attrib); + SetFileAttrib(_diskFilePath, _processedFileInfo.Attrib); PrintNewLine(); return S_OK; } @@ -528,7 +557,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 /* index */, if (newProperties != NULL) *newProperties = BoolToInt(true); if (indexInArchive != NULL) - *indexInArchive = (UInt32)-1; + *indexInArchive = (UInt32)(Int32)-1; return S_OK; } @@ -632,7 +661,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOu wchar_t temp[16]; ConvertUInt32ToString(index + 1, temp); UString res = temp; - while (res.Length() < 2) + while (res.Len() < 2) res = UString(L'0') + res; UString fileName = VolName; fileName += L'.'; @@ -685,8 +714,8 @@ int MY_CDECL main(int numArgs, const char *args[]) PrintError("Can not load 7-zip library"); return 1; } - CreateObjectFunc createObjectFunc = (CreateObjectFunc)lib.GetProc("CreateObject"); - if (createObjectFunc == 0) + Func_CreateObject createObjectFunc = (Func_CreateObject)lib.GetProc("CreateObject"); + if (!createObjectFunc) { PrintError("Can not get CreateObject"); return 1; @@ -695,15 +724,15 @@ int MY_CDECL main(int numArgs, const char *args[]) char c; { AString command = args[1]; - if (command.Length() != 1) + if (command.Len() != 1) { PrintError("incorrect command"); return 1; } - c = (char)MyCharUpper(command[0]); + c = (char)MyCharLower_Ascii(command[0]); } FString archiveName = CmdStringToFString(args[2]); - if (c == 'A') + if (c == 'a') { // create archive command if (numArgs < 4) @@ -712,27 +741,29 @@ int MY_CDECL main(int numArgs, const char *args[]) return 1; } CObjectVector dirItems; - int i; - for (i = 3; i < numArgs; i++) { - CDirItem di; - FString name = CmdStringToFString(args[i]); - - NFile::NFind::CFileInfo fi; - if (!fi.Find(name)) + int i; + for (i = 3; i < numArgs; i++) { - PrintError("Can't find file", name); - return 1; + CDirItem di; + FString name = CmdStringToFString(args[i]); + + NFind::CFileInfo fi; + if (!fi.Find(name)) + { + PrintError("Can't find file", name); + return 1; + } + + di.Attrib = fi.Attrib; + di.Size = fi.Size; + di.CTime = fi.CTime; + di.ATime = fi.ATime; + di.MTime = fi.MTime; + di.Name = fs2us(name); + di.FullPath = name; + dirItems.Add(di); } - - di.Attrib = fi.Attrib; - di.Size = fi.Size; - di.CTime = fi.CTime; - di.ATime = fi.ATime; - di.MTime = fi.MTime; - di.Name = fs2us(name); - di.FullPath = name; - dirItems.Add(di); } COutFileStream *outFileStreamSpec = new COutFileStream; CMyComPtr outFileStream = outFileStreamSpec; @@ -762,7 +793,7 @@ int MY_CDECL main(int numArgs, const char *args[]) L"s", L"x" }; - const int kNumProps = sizeof(names) / sizeof(names[0]); + const unsigned kNumProps = ARRAY_SIZE(names); NCOM::CPropVariant values[kNumProps] = { false, // solid mode OFF @@ -786,7 +817,7 @@ int MY_CDECL main(int numArgs, const char *args[]) PrintError("Update Error"); return 1; } - for (i = 0; i < updateCallbackSpec->FailedFiles.Size(); i++) + FOR_VECTOR (i, updateCallbackSpec->FailedFiles) { PrintNewLine(); PrintError("Error for file", updateCallbackSpec->FailedFiles[i]); @@ -803,9 +834,9 @@ int MY_CDECL main(int numArgs, const char *args[]) } bool listCommand; - if (c == 'L') + if (c == 'l') listCommand = true; - else if (c == 'X') + else if (c == 'x') listCommand = false; else { @@ -854,7 +885,8 @@ int MY_CDECL main(int numArgs, const char *args[]) // Get uncompressed size of file NCOM::CPropVariant prop; archive->GetProperty(i, kpidSize, &prop); - UString s = ConvertPropVariantToString(prop); + char s[32]; + ConvertPropVariantToShortString(prop, s); PrintString(s); PrintString(" "); } @@ -862,8 +894,10 @@ int MY_CDECL main(int numArgs, const char *args[]) // Get name of file NCOM::CPropVariant prop; archive->GetProperty(i, kpidPath, &prop); - UString s = ConvertPropVariantToString(prop); - PrintString(s); + if (prop.vt == VT_BSTR) + PrintString(prop.bstrVal); + else if (prop.vt != VT_EMPTY) + PrintString("ERROR!"); } PrintNewLine(); } diff --git a/CPP/7zip/UI/Client7z/Client7z.dsp b/CPP/7zip/UI/Client7z/Client7z.dsp old mode 100755 new mode 100644 index 542e2852..8ad7fb13 --- a/CPP/7zip/UI/Client7z/Client7z.dsp +++ b/CPP/7zip/UI/Client7z/Client7z.dsp @@ -39,9 +39,10 @@ RSC=rc.exe # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe @@ -49,7 +50,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /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 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zcl.exe" !ELSEIF "$(CFG)" == "Client7z - Win32 Debug" @@ -65,7 +66,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /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 CPP /nologo /W4 /WX /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe @@ -73,7 +74,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zcl.exe" /pdbtype:sept !ENDIF @@ -86,6 +87,10 @@ LINK32=link.exe # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File +SOURCE=.\resource.rc +# End Source File +# Begin Source File + SOURCE=.\StdAfx.cpp # ADD CPP /Yc"stdafx.h" # End Source File @@ -147,11 +152,11 @@ SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\PropVariantConversions.cpp +SOURCE=..\..\..\Windows\PropVariantConv.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\PropVariantConversions.h +SOURCE=..\..\..\Windows\PropVariantConv.h # End Source File # End Group # Begin Group "Common" @@ -222,5 +227,9 @@ SOURCE=..\..\Common\FileStreams.h SOURCE=.\Client7z.cpp # End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Sort.h +# End Source File # End Target # End Project diff --git a/CPP/7zip/UI/Client7z/Client7z.dsw b/CPP/7zip/UI/Client7z/Client7z.dsw old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/Client7z/StdAfx.cpp b/CPP/7zip/UI/Client7z/StdAfx.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/Client7z/StdAfx.h b/CPP/7zip/UI/Client7z/StdAfx.h old mode 100755 new mode 100644 index b23436e9..2854ff3e --- a/CPP/7zip/UI/Client7z/StdAfx.h +++ b/CPP/7zip/UI/Client7z/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include -#include +#include "../../../Common/Common.h" #endif diff --git a/CPP/7zip/UI/Client7z/makefile b/CPP/7zip/UI/Client7z/makefile old mode 100755 new mode 100644 index 0ff8e72f..99a6d494 --- a/CPP/7zip/UI/Client7z/makefile +++ b/CPP/7zip/UI/Client7z/makefile @@ -1,8 +1,7 @@ -PROG = 7z.exe +PROG = 7zcl.exe MY_CONSOLE = 1 -CFLAGS = $(CFLAGS) -I ../../../ -CONSOLE_OBJS = \ +CURRENT_OBJS = \ $O\Client7z.obj \ COMMON_OBJS = \ @@ -21,25 +20,9 @@ WIN_OBJS = \ $O\FileIO.obj \ $O\FileName.obj \ $O\PropVariant.obj \ - $O\PropVariantConversions.obj \ + $O\PropVariantConv.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) +!include "../../7zip.mak" diff --git a/CPP/7zip/UI/Client7z/resource.rc b/CPP/7zip/UI/Client7z/resource.rc new file mode 100644 index 00000000..a09bb044 --- /dev/null +++ b/CPP/7zip/UI/Client7z/resource.rc @@ -0,0 +1,3 @@ +#include "../../MyVersionInfo.rc" + +MY_VERSION_INFO_APP("7-Zip client", "7zcl") diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp old mode 100755 new mode 100644 index 85ec17b4..4d5c7023 --- a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp +++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp @@ -1,6 +1,8 @@ // ArchiveCommandLine.cpp #include "StdAfx.h" +#undef printf +#undef sprintf #ifdef _WIN32 #ifndef UNDER_CE @@ -9,15 +11,15 @@ #endif #include -#include "Common/ListFileUtils.h" -#include "Common/StringConvert.h" -#include "Common/StringToInt.h" +#include "../../../Common/ListFileUtils.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/StringToInt.h" -#include "Windows/FileDir.h" -#include "Windows/FileName.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileName.h" #ifdef _WIN32 -#include "Windows/FileMapping.h" -#include "Windows/Synchronization.h" +#include "../../../Windows/FileMapping.h" +#include "../../../Windows/Synchronization.h" #endif #include "ArchiveCommandLine.h" @@ -48,6 +50,30 @@ using namespace NCommandLineParser; using namespace NWindows; using namespace NFile; +static bool StringToUInt32(const wchar_t *s, UInt32 &v) +{ + if (*s == 0) + return false; + const wchar_t *end; + v = ConvertStringToUInt32(s, &end); + return *end == 0; +} + +static void AddNewLine(UString &s) +{ + s += L'\n'; +} + +CArcCmdLineException::CArcCmdLineException(const char *a, const wchar_t *u) +{ + (*this) += MultiByteToUnicodeString(a); + if (u) + { + AddNewLine(*this); + (*this) += u; + } +} + int g_CodePage = -1; namespace NKey { @@ -86,19 +112,47 @@ enum Enum kTechMode, kShareForWrite, kCaseSensitive, - kCalcCrc + kHash, + kArcNameMode, + + kDisableWildcardParsing, + kElimDup, + kFullPathMode, + + kHardLinks, + kSymLinks, + kNtSecurity, + kAltStreams, + kReplaceColonForAltStream, + kWriteToAltStreamIfColon, + + kDeleteAfterCompressing, + kSetArcMTime, + kExcludedArcType }; } -static const wchar_t kRecursedIDChar = 'R'; -static const wchar_t *kRecursedPostCharSet = L"0-"; +static const wchar_t kRecursedIDChar = 'r'; +static const char *kRecursedPostCharSet = "0-"; + +static const char *k_ArcNameMode_PostCharSet = "sea"; + +static inline const EArcNameMode ParseArcNameMode(int postCharIndex) +{ + switch (postCharIndex) + { + case 1: return k_ArcNameMode_Exact; + case 2: return k_ArcNameMode_Add; + default: return k_ArcNameMode_Smart; + } +} namespace NRecursedPostCharIndex { enum EEnum { - kWildCardRecursionOnly = 0, + kWildcardRecursionOnly = 0, kNoRecursion = 1 }; } @@ -110,135 +164,127 @@ 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"; +static const char *kOverwritePostCharSet = "asut"; NExtract::NOverwriteMode::EEnum k_OverwriteModes[] = { - NExtract::NOverwriteMode::kWithoutPrompt, - NExtract::NOverwriteMode::kSkipExisting, - NExtract::NOverwriteMode::kAutoRename, - NExtract::NOverwriteMode::kAutoRenameExisting + NExtract::NOverwriteMode::kOverwrite, + NExtract::NOverwriteMode::kSkip, + NExtract::NOverwriteMode::kRename, + NExtract::NOverwriteMode::kRenameExisting }; 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 } +{ + { "?" }, + { "h" }, + { "-help" }, + { "ba" }, + { "bd" }, + { "t", NSwitchType::kString, false, 1 }, + { "y" }, + #ifndef _NO_CRYPTO + { "p", NSwitchType::kString }, + #endif + { "m", NSwitchType::kString, true, 1 }, + { "o", NSwitchType::kString, false, 1 }, + { "w", NSwitchType::kString }, + { "i", NSwitchType::kString, true, kSomeCludePostStringMinSize}, + { "x", NSwitchType::kString, true, kSomeCludePostStringMinSize}, + { "ai", NSwitchType::kString, true, kSomeCludePostStringMinSize}, + { "ax", NSwitchType::kString, true, kSomeCludePostStringMinSize}, + { "an" }, + { "u", NSwitchType::kString, true, 1}, + { "v", NSwitchType::kString, true, 1}, + { "r", NSwitchType::kChar, false, 0, kRecursedPostCharSet }, + { "sfx", NSwitchType::kString }, + { "si", NSwitchType::kString }, + { "so" }, + { "ao", NSwitchType::kChar, false, 1, kOverwritePostCharSet}, + { "seml", NSwitchType::kString, false, 0}, + { "ad" }, + { "slp", NSwitchType::kMinus }, + { "scs", NSwitchType::kString }, + { "scc", NSwitchType::kString }, + { "slt" }, + { "ssw" }, + { "ssc", NSwitchType::kMinus }, + { "scrc", NSwitchType::kString, true, 0 }, + { "sa", NSwitchType::kChar, false, 1, k_ArcNameMode_PostCharSet }, + + { "spd" }, + { "spe", NSwitchType::kMinus }, + { "spf", NSwitchType::kString, false, 0 }, + + { "snh", NSwitchType::kMinus }, + { "snl", NSwitchType::kMinus }, + { "sni" }, + { "sns", NSwitchType::kMinus }, + + { "snr" }, + { "snc" }, + + { "sdel" }, + { "stl" }, + { "stx", NSwitchType::kString, true, 1 } }; -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 *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 *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 const char *kCannotFindArchive = "Cannot find archive"; -static void ThrowException(const char *errorMessage) -{ - throw CArchiveCommandLineException(errorMessage); -} - -static void ThrowUserErrorException() +bool CArcCommand::IsFromExtractGroup() const { - ThrowException(kUserErrorMessage); -} - -// --------------------------- - -bool CArchiveCommand::IsFromExtractGroup() const -{ - switch(CommandType) + switch (CommandType) { case NCommandType::kTest: case NCommandType::kExtract: - case NCommandType::kFullExtract: + case NCommandType::kExtractFull: return true; - default: - return false; } + return false; } -NExtract::NPathMode::EEnum CArchiveCommand::GetPathMode() const +NExtract::NPathMode::EEnum CArcCommand::GetPathMode() const { - switch(CommandType) + switch (CommandType) { case NCommandType::kTest: - case NCommandType::kFullExtract: - return NExtract::NPathMode::kFullPathnames; - default: - return NExtract::NPathMode::kNoPathnames; + case NCommandType::kExtractFull: + return NExtract::NPathMode::kFullPaths; } + return NExtract::NPathMode::kNoPaths; } -bool CArchiveCommand::IsFromUpdateGroup() const +bool CArcCommand::IsFromUpdateGroup() const { - return (CommandType == NCommandType::kAdd || - CommandType == NCommandType::kUpdate || - CommandType == NCommandType::kDelete); + switch (CommandType) + { + case NCommandType::kAdd: + case NCommandType::kUpdate: + case NCommandType::kDelete: + case NCommandType::kRename: + return true; + } + return false; } static NRecursedType::EEnum GetRecursedTypeFromIndex(int index) { switch (index) { - case NRecursedPostCharIndex::kWildCardRecursionOnly: - return NRecursedType::kWildCardOnlyRecursed; + case NRecursedPostCharIndex::kWildcardRecursionOnly: + return NRecursedType::kWildcardOnlyRecursed; case NRecursedPostCharIndex::kNoRecursion: return NRecursedType::kNonRecursed; default: @@ -246,170 +292,281 @@ static NRecursedType::EEnum GetRecursedTypeFromIndex(int index) } } -static bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command) +static const char *g_Commands = "audtexlbih"; + +static bool ParseArchiveCommand(const UString &commandString, CArcCommand &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; + UString s = commandString; + s.MakeLower_Ascii(); + if (s.Len() == 1) + { + if (s[0] > 0x7F) + return false; + int index = FindCharPosInString(g_Commands, (char)s[0]); + if (index < 0) + return false; + command.CommandType = (NCommandType::EEnum)index; + return true; + } + if (s.Len() == 2 && s[0] == 'r' && s[1] == 'n') + { + command.CommandType = (NCommandType::kRename); + return true; + } + return false; } // ------------------------------------------------------------------ // filenames functions -static void AddNameToCensor(NWildcard::CCensor &wildcardCensor, - const UString &name, bool include, NRecursedType::EEnum type) +static void AddNameToCensor(NWildcard::CCensor &censor, + const UString &name, bool include, NRecursedType::EEnum type, bool wildcardMatching) { bool recursed = false; switch (type) { - case NRecursedType::kWildCardOnlyRecursed: - recursed = DoesNameContainWildCard(name); + case NRecursedType::kWildcardOnlyRecursed: + recursed = DoesNameContainWildcard(name); break; case NRecursedType::kRecursed: recursed = true; break; } - wildcardCensor.AddItem(include, name, recursed); + censor.AddPreItem(include, name, recursed, wildcardMatching); +} + +static void AddRenamePair(CObjectVector *renamePairs, + const UString &oldName, const UString &newName, NRecursedType::EEnum type, + bool wildcardMatching) +{ + CRenamePair &pair = renamePairs->AddNew(); + pair.OldName = oldName; + pair.NewName = newName; + pair.RecursedType = type; + pair.WildcardParsing = wildcardMatching; + + if (!pair.Prepare()) + { + UString val; + val += pair.OldName; + AddNewLine(val); + val += pair.NewName; + AddNewLine(val); + if (type == NRecursedType::kRecursed) + val += L"-r"; + else if (type == NRecursedType::kRecursed) + val += L"-r0"; + throw CArcCmdLineException("Unsupported rename command:", val); + } } -static void AddToCensorFromListFile(NWildcard::CCensor &wildcardCensor, - LPCWSTR fileName, bool include, NRecursedType::EEnum type, UINT codePage) +static void AddToCensorFromListFile( + CObjectVector *renamePairs, + NWildcard::CCensor &censor, + LPCWSTR fileName, bool include, NRecursedType::EEnum type, bool wildcardMatching, Int32 codePage) { UStringVector names; if (!NFind::DoesFileExist(us2fs(fileName))) - throw kCannotFindListFile; + throw CArcCmdLineException(kCannotFindListFile, fileName); if (!ReadNamesFromListFile(us2fs(fileName), names, codePage)) - throw kIncorrectListFile; - for (int i = 0; i < names.Size(); i++) - AddNameToCensor(wildcardCensor, names[i], include, type); + throw CArcCmdLineException(kIncorrectListFile, fileName); + if (renamePairs) + { + if ((names.Size() & 1) != 0) + throw CArcCmdLineException(kIncorrectListFile, fileName); + for (unsigned i = 0; i < names.Size(); i += 2) + { + // change type !!!! + AddRenamePair(renamePairs, names[i], names[i + 1], type, wildcardMatching); + } + } + else + FOR_VECTOR (i, names) + AddNameToCensor(censor, names[i], include, type, wildcardMatching); } static void AddToCensorFromNonSwitchesStrings( - int startIndex, - NWildcard::CCensor &wildcardCensor, + CObjectVector *renamePairs, + unsigned startIndex, + NWildcard::CCensor &censor, const UStringVector &nonSwitchStrings, NRecursedType::EEnum type, - bool thereAreSwitchIncludes, UINT codePage) + bool wildcardMatching, + bool thereAreSwitchIncludes, Int32 codePage) { - if (nonSwitchStrings.Size() == startIndex && (!thereAreSwitchIncludes)) - AddNameToCensor(wildcardCensor, kUniversalWildcard, true, type); - for (int i = startIndex; i < nonSwitchStrings.Size(); i++) + if ((renamePairs || nonSwitchStrings.Size() == startIndex) && !thereAreSwitchIncludes) + AddNameToCensor(censor, kUniversalWildcard, true, type, + true // wildcardMatching + ); + + int oldIndex = -1; + + for (unsigned i = startIndex; i < nonSwitchStrings.Size(); i++) { const UString &s = nonSwitchStrings[i]; if (s.IsEmpty()) - throw kEmptyFilePath; + throw CArcCmdLineException(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 + AddToCensorFromListFile(renamePairs, censor, s.Ptr(1), true, type, wildcardMatching, codePage); + else if (renamePairs) { - 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++) + if (oldIndex == -1) + oldIndex = startIndex; + else { - wchar_t c = curData[i]; - if (c == L'\0') - { - AddNameToCensor(wildcardCensor, name, include, commonRecursedType); - name.Empty(); - } - else - name += c; + // NRecursedType::EEnum type is used for global wildcard (-i! switches) + AddRenamePair(renamePairs, nonSwitchStrings[oldIndex], s, NRecursedType::kNonRecursed, wildcardMatching); + // AddRenamePair(renamePairs, nonSwitchStrings[oldIndex], s, type); + oldIndex = -1; } - if (!name.IsEmpty()) - ThrowException("data error"); } - catch(...) - { - UnmapViewOfFile(data); - throw; - } - UnmapViewOfFile(data); + else + AddNameToCensor(censor, s, true, type, wildcardMatching); } + if (oldIndex != -1) + { + throw CArcCmdLineException("There is no second file name for rename pair:", nonSwitchStrings[oldIndex]); + } +} + +#ifdef _WIN32 + +struct CEventSetEnd +{ + UString Name; + + CEventSetEnd(const wchar_t *name): Name(name) {} + ~CEventSetEnd() { NSynchronization::CManualResetEvent event; - if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(eventName)) == S_OK) + if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(Name)) == 0) event.Set(); } +}; + +const char *k_IncorrectMapCommand = "Incorrect Map command"; + +static const char *ParseMapWithPaths( + NWildcard::CCensor &censor, + const UString &s2, bool include, + NRecursedType::EEnum commonRecursedType, + bool wildcardMatching) +{ + UString s = s2; + int pos = s.Find(L':'); + if (pos < 0) + return k_IncorrectMapCommand; + int pos2 = s.Find(L':', pos + 1); + if (pos2 < 0) + return k_IncorrectMapCommand; + + CEventSetEnd eventSetEnd((const wchar_t *)s + (pos2 + 1)); + s.DeleteFrom(pos2); + UInt32 size; + if (!StringToUInt32(s.Ptr(pos + 1), size) + || size < sizeof(wchar_t) + || size > ((UInt32)1 << 31) + || size % sizeof(wchar_t) != 0) + return "Unsupported Map data size"; + + s.DeleteFrom(pos); + CFileMapping map; + if (map.Open(FILE_MAP_READ, GetSystemString(s)) != 0) + return "Can not open mapping"; + LPVOID data = map.Map(FILE_MAP_READ, 0, size); + if (!data) + return "MapViewOfFile error"; + CFileUnmapper unmapper(data); + + UString name; + const wchar_t *p = (const wchar_t *)data; + if (*p != 0) // data format marker + return "Unsupported Map data"; + UInt32 numChars = size / sizeof(wchar_t); + for (UInt32 i = 1; i < numChars; i++) + { + wchar_t c = p[i]; + if (c == 0) + { + // MessageBoxW(0, name, L"7-Zip", 0); + AddNameToCensor(censor, name, include, commonRecursedType, wildcardMatching); + name.Empty(); + } + else + name += c; + } + if (!name.IsEmpty()) + return "Map data error"; + + return NULL; } + #endif -static void AddSwitchWildCardsToCensor(NWildcard::CCensor &wildcardCensor, +static void AddSwitchWildcardsToCensor( + NWildcard::CCensor &censor, const UStringVector &strings, bool include, - NRecursedType::EEnum commonRecursedType, UINT codePage) + NRecursedType::EEnum commonRecursedType, + bool wildcardMatching, + Int32 codePage) { - for (int i = 0; i < strings.Size(); i++) + const char *errorMessage = NULL; + unsigned i; + for (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) + unsigned pos = 0; + + if (name.Len() < kSomeCludePostStringMinSize) + { + errorMessage = "Too short switch"; + break; + } + + if (::MyCharLower_Ascii(name[pos]) == kRecursedIDChar) { pos++; - int index = UString(kRecursedPostCharSet).Find(name[pos]); + wchar_t c = name[pos]; + int index = -1; + if (c <= 0x7F) + index = FindCharPosInString(kRecursedPostCharSet, (char)c); recursedType = GetRecursedTypeFromIndex(index); if (index >= 0) pos++; } else recursedType = commonRecursedType; - if (name.Length() < pos + kSomeCludeAfterRecursedPostStringMinSize) - ThrowUserErrorException(); - UString tail = name.Mid(pos + 1); + + if (name.Len() < pos + kSomeCludeAfterRecursedPostStringMinSize) + { + errorMessage = "Too short switch"; + break; + } + + UString tail = name.Ptr(pos + 1); + if (name[pos] == kImmediateNameID) - AddNameToCensor(wildcardCensor, tail, include, recursedType); + AddNameToCensor(censor, tail, include, recursedType, wildcardMatching); else if (name[pos] == kFileListID) - AddToCensorFromListFile(wildcardCensor, tail, include, recursedType, codePage); + AddToCensorFromListFile(NULL, censor, tail, include, recursedType, wildcardMatching, codePage); #ifdef _WIN32 else if (name[pos] == kMapNameID) - ParseMapWithPaths(wildcardCensor, tail, include, recursedType); + { + errorMessage = ParseMapWithPaths(censor, tail, include, recursedType, wildcardMatching); + if (errorMessage) + break; + } #endif else - ThrowUserErrorException(); + { + errorMessage = "Incorrect wildcarc type marker"; + break; + } } + if (i != strings.Size()) + throw CArcCmdLineException(errorMessage, strings[i]); } #ifdef _WIN32 @@ -418,20 +575,25 @@ static void AddSwitchWildCardsToCensor(NWildcard::CCensor &wildcardCensor, static void ConvertToLongName(const UString &prefix, UString &name) { - if (name.IsEmpty() || DoesNameContainWildCard(name)) + if (name.IsEmpty() || DoesNameContainWildcard(name)) return; NFind::CFileInfo fi; - if (fi.Find(us2fs(prefix + name))) + const FString path = us2fs(prefix + name); + if (NFile::NName::IsDevicePath(path)) + return; + if (fi.Find(path)) name = fs2us(fi.Name); } static void ConvertToLongNames(const UString &prefix, CObjectVector &items) { - for (int i = 0; i < items.Size(); i++) + FOR_VECTOR (i, items) { NWildcard::CItem &item = items[i]; if (item.Recursive || item.PathParts.Size() != 1) continue; + if (prefix.IsEmpty() && item.IsDriveItem()) + continue; ConvertToLongName(prefix, item.PathParts.Front()); } } @@ -440,17 +602,22 @@ static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &no { ConvertToLongNames(prefix, node.IncludeItems); ConvertToLongNames(prefix, node.ExcludeItems); - int i; + unsigned i; for (i = 0; i < node.SubNodes.Size(); i++) - ConvertToLongName(prefix, node.SubNodes[i].Name); + { + UString &name = node.SubNodes[i].Name; + if (prefix.IsEmpty() && NWildcard::IsDriveColonName(name)) + continue; + ConvertToLongName(prefix, name); + } // mix folders with same name for (i = 0; i < node.SubNodes.Size(); i++) { NWildcard::CCensorNode &nextNode1 = node.SubNodes[i]; - for (int j = i + 1; j < node.SubNodes.Size();) + for (unsigned j = i + 1; j < node.SubNodes.Size();) { const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j]; - if (nextNode1.Name.CompareNoCase(nextNode2.Name) == 0) + if (nextNode1.Name.IsEqualToNoCase(nextNode2.Name)) { nextNode1.IncludeItems += nextNode2.IncludeItems; nextNode1.ExcludeItems += nextNode2.ExcludeItems; @@ -467,9 +634,9 @@ static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &no } } -static void ConvertToLongNames(NWildcard::CCensor &censor) +void ConvertToLongNames(NWildcard::CCensor &censor) { - for (int i = 0; i < censor.Pairs.Size(); i++) + FOR_VECTOR (i, censor.Pairs) { NWildcard::CPair &pair = censor.Pairs[i]; ConvertToLongNames(pair.Prefix, pair.Head); @@ -478,9 +645,10 @@ static void ConvertToLongNames(NWildcard::CCensor &censor) #endif +/* static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i) { - switch(i) + switch (i) { case NUpdateArchive::NPairAction::kIgnore: return NUpdateArchive::NPairAction::kIgnore; case NUpdateArchive::NPairAction::kCopy: return NUpdateArchive::NPairAction::kCopy; @@ -489,35 +657,36 @@ static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i) } throw 98111603; } +*/ -const UString kUpdatePairStateIDSet = L"PQRXYZW"; -const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1}; +static const wchar_t *kUpdatePairStateIDSet = L"pqrxyzw"; +static 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 const unsigned kNumUpdatePairActions = 4; +static const char *kUpdateIgnoreItselfPostStringID = "-"; +static const wchar_t kUpdateNewArchivePostCharID = '!'; static bool ParseUpdateCommandString2(const UString &command, NUpdateArchive::CActionSet &actionSet, UString &postString) { - for (int i = 0; i < command.Length();) + for (unsigned i = 0; i < command.Len();) { - wchar_t c = MyCharUpper(command[i]); - int statePos = kUpdatePairStateIDSet.Find(c); + wchar_t c = MyCharLower_Ascii(command[i]); + int statePos = FindCharPosInString(kUpdatePairStateIDSet, c); if (statePos < 0) { - postString = command.Mid(i); + postString = command.Ptr(i); return true; } i++; - if (i >= command.Length()) + if (i >= command.Len()) return false; - int actionPos = kUpdatePairActionIDSet.Find(::MyCharUpper(command[i])); - if (actionPos < 0) + c = command[i]; + if (c < '0' || c >= '0' + kNumUpdatePairActions) return false; - actionSet.StateActions[statePos] = GetUpdatePairActionType(actionPos); + int actionPos = c - '0'; + actionSet.StateActions[statePos] = (NUpdateArchive::NPairAction::EEnum)(actionPos); if (kUpdatePairStateNotSupportedActions[statePos] == actionPos) return false; i++; @@ -530,10 +699,12 @@ static void ParseUpdateCommandString(CUpdateOptions &options, const UStringVector &updatePostStrings, const NUpdateArchive::CActionSet &defaultActionSet) { - for (int i = 0; i < updatePostStrings.Size(); i++) + const char *errorMessage = "incorrect update switch command"; + unsigned i; + for (i = 0; i < updatePostStrings.Size(); i++) { const UString &updateString = updatePostStrings[i]; - if (updateString.CompareNoCase(kUpdateIgnoreItselfPostStringID) == 0) + if (updateString.IsEqualTo(kUpdateIgnoreItselfPostStringID)) { if (options.UpdateArchiveItself) { @@ -547,7 +718,7 @@ static void ParseUpdateCommandString(CUpdateOptions &options, UString postString; if (!ParseUpdateCommandString2(updateString, actionSet, postString)) - ThrowUserErrorException(); + break; if (postString.IsEmpty()) { if (options.UpdateArchiveItself) @@ -555,64 +726,23 @@ static void ParseUpdateCommandString(CUpdateOptions &options, } else { - if (MyCharUpper(postString[0]) != kUpdateNewArchivePostCharID) - ThrowUserErrorException(); + if (postString[0] != kUpdateNewArchivePostCharID) + break; CUpdateArchiveCommand uc; - UString archivePath = postString.Mid(1); + UString archivePath = postString.Ptr(1); if (archivePath.IsEmpty()) - ThrowUserErrorException(); + break; uc.UserArchivePath = archivePath; uc.ActionSet = actionSet; options.Commands.Add(uc); } } } + if (i != updatePostStrings.Size()) + throw CArcCmdLineException(errorMessage, updatePostStrings[i]); } -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; -} +bool ParseComplexSize(const wchar_t *s, UInt64 &result); static void SetAddCommandOptions( NCommandType::EEnum commandType, @@ -620,16 +750,16 @@ static void SetAddCommandOptions( CUpdateOptions &options) { NUpdateArchive::CActionSet defaultActionSet; - switch(commandType) + switch (commandType) { case NCommandType::kAdd: - defaultActionSet = NUpdateArchive::kAddActionSet; + defaultActionSet = NUpdateArchive::k_ActionSet_Add; break; case NCommandType::kDelete: - defaultActionSet = NUpdateArchive::kDeleteActionSet; + defaultActionSet = NUpdateArchive::k_ActionSet_Delete; break; default: - defaultActionSet = NUpdateArchive::kUpdateActionSet; + defaultActionSet = NUpdateArchive::k_ActionSet_Update; } options.UpdateArchiveItself = true; @@ -645,7 +775,7 @@ static void SetAddCommandOptions( { const UString &postString = parser[NKey::kWorkingDir].PostStrings[0]; if (postString.IsEmpty()) - NDirectory::MyGetTempPath(options.WorkingDir); + NDir::MyGetTempPath(options.WorkingDir); else options.WorkingDir = us2fs(postString); } @@ -656,11 +786,11 @@ static void SetAddCommandOptions( if (parser[NKey::kVolume].ThereIs) { const UStringVector &sv = parser[NKey::kVolume].PostStrings; - for (int i = 0; i < sv.Size(); i++) + FOR_VECTOR (i, sv) { UInt64 size; - if (!ParseComplexSize(sv[i], size)) - ThrowException("Incorrect volume size"); + if (!ParseComplexSize(sv[i], size) || size == 0) + throw CArcCmdLineException("Incorrect volume size:", sv[i]); options.VolumesSizes.Add(size); } } @@ -670,37 +800,28 @@ static void SetMethodOptions(const CParser &parser, CObjectVector &pr { if (parser[NKey::kProperty].ThereIs) { - for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++) + FOR_VECTOR (i, parser[NKey::kProperty].PostStrings) { - CProperty property; - const UString &postString = parser[NKey::kProperty].PostStrings[i]; - int index = postString.Find(L'='); - if (index < 0) - property.Name = postString; - else + CProperty prop; + prop.Name = parser[NKey::kProperty].PostStrings[i]; + int index = prop.Name.Find(L'='); + if (index >= 0) { - property.Name = postString.Left(index); - property.Value = postString.Mid(index + 1); + prop.Value = prop.Name.Ptr(index + 1); + prop.Name.DeleteFrom(index); } - properties.Add(property); + properties.Add(prop); } } } -CArchiveCommandLineParser::CArchiveCommandLineParser(): - parser(sizeof(kSwitchForms) / sizeof(kSwitchForms[0])) {} +CArcCmdLineParser::CArcCmdLineParser(): parser(ARRAY_SIZE(kSwitchForms)) {} -void CArchiveCommandLineParser::Parse1(const UStringVector &commandStrings, - CArchiveCommandLineOptions &options) +void CArcCmdLineParser::Parse1(const UStringVector &commandStrings, + CArcCmdLineOptions &options) { - try - { - parser.ParseStrings(kSwitchForms, commandStrings); - } - catch(...) - { - ThrowUserErrorException(); - } + if (!parser.ParseStrings(kSwitchForms, commandStrings)) + throw CArcCmdLineException(parser.ErrorMessage, parser.ErrorLine); options.IsInTerminal = MY_IS_TERMINAL(stdin); options.IsStdOutTerminal = MY_IS_TERMINAL(stdout); @@ -710,62 +831,67 @@ void CArchiveCommandLineParser::Parse1(const UStringVector &commandStrings, options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs; options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs || parser[NKey::kHelp3].ThereIs; + if (parser[NKey::kCaseSensitive].ThereIs) + { + g_CaseSensitive = !parser[NKey::kCaseSensitive].WithMinus; + options.CaseSensitiveChange = true; + options.CaseSensitive = g_CaseSensitive; + } + #ifdef _WIN32 options.LargePages = false; if (parser[NKey::kLargePages].ThereIs) { - const UString &postString = parser[NKey::kLargePages].PostStrings.Front(); - if (postString.IsEmpty()) - options.LargePages = true; + options.LargePages = !parser[NKey::kLargePages].WithMinus; } #endif } struct CCodePagePair { - const wchar_t *Name; - UINT CodePage; + const char *Name; + Int32 CodePage; }; +static const unsigned kNumByteOnlyCodePages = 3; + static CCodePagePair g_CodePagePairs[] = { - { L"UTF-8", CP_UTF8 }, - { L"WIN", CP_ACP }, - { L"DOS", CP_OEMCP } + { "utf-8", CP_UTF8 }, + { "win", CP_ACP }, + { "dos", CP_OEMCP }, + { "utf-16le", MY__CP_UTF16 }, + { "utf-16be", MY__CP_UTF16BE } }; -static int FindCharset(const NCommandLineParser::CParser &parser, int keyIndex, int defaultVal) +static Int32 FindCharset(const NCommandLineParser::CParser &parser, int keyIndex, + bool byteOnlyCodePages, Int32 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++) + UInt32 v; + if (StringToUInt32(name, v)) + if (v < ((UInt32)1 << 16)) + return (Int32)v; + name.MakeLower_Ascii(); + unsigned num = byteOnlyCodePages ? kNumByteOnlyCodePages : ARRAY_SIZE(g_CodePagePairs); + for (unsigned i = 0;; i++) { + if (i == num) // to disable warnings from different compilers + throw CArcCmdLineException("Unsupported charset:", name); const CCodePagePair &pair = g_CodePagePairs[i]; - if (name.Compare(pair.Name) == 0) + if (name.IsEqualTo(pair.Name)) 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, +void EnumerateDirItemsAndSort( + bool storeAltStreams, + NWildcard::CCensor &censor, + NWildcard::ECensorPathMode censorPathMode, + const UString &addPathPrefix, UStringVector &sortedPaths, UStringVector &sortedFullPaths) { @@ -773,13 +899,18 @@ void EnumerateDirItemsAndSort(NWildcard::CCensor &wildcardCensor, { CDirItems dirItems; { - FStringVector errorPaths; - CRecordVector errorCodes; - HRESULT res = EnumerateItems(wildcardCensor, dirItems, NULL, errorPaths, errorCodes); - if (res != S_OK || errorPaths.Size() > 0) - throw "cannot find archive"; + dirItems.ScanAltStreams = storeAltStreams; + HRESULT res = EnumerateItems(censor, censorPathMode, addPathPrefix, dirItems, NULL); + if (res != S_OK || dirItems.ErrorPaths.Size() > 0) + { + UString errorPath; + if (dirItems.ErrorPaths.Size() > 0) + errorPath = fs2us(dirItems.ErrorPaths[0]); + throw CArcCmdLineException(kCannotFindArchive, + dirItems.ErrorPaths.Size() > 0 ? (const wchar_t *)errorPath : NULL); + } } - for (int i = 0; i < dirItems.Items.Size(); i++) + FOR_VECTOR (i, dirItems.Items) { const CDirItem &dirItem = dirItems.Items[i]; if (!dirItem.IsDir()) @@ -788,44 +919,72 @@ void EnumerateDirItemsAndSort(NWildcard::CCensor &wildcardCensor, } if (paths.Size() == 0) - throw "there is no such archive"; + throw CArcCmdLineException(kCannotFindArchive); UStringVector fullPaths; - int i; + unsigned i; for (i = 0; i < paths.Size(); i++) { FString fullPath; - NFile::NDirectory::MyGetFullPathName(us2fs(paths[i]), fullPath); + NFile::NDir::MyGetFullPathName(us2fs(paths[i]), fullPath); fullPaths.Add(fs2us(fullPath)); } - CIntVector indices; + CUIntVector indices; SortFileNames(fullPaths, indices); - sortedPaths.Reserve(indices.Size()); - sortedFullPaths.Reserve(indices.Size()); + sortedPaths.ClearAndReserve(indices.Size()); + sortedFullPaths.ClearAndReserve(indices.Size()); for (i = 0; i < indices.Size(); i++) { - int index = indices[i]; - sortedPaths.Add(paths[index]); - sortedFullPaths.Add(fullPaths[index]); + unsigned index = indices[i]; + sortedPaths.AddInReserved(paths[index]); + sortedFullPaths.AddInReserved(fullPaths[index]); + if (i > 0 && CompareFileNames(sortedFullPaths[i], sortedFullPaths[i - 1]) == 0) + throw CArcCmdLineException("Duplicate archive path:", sortedFullPaths[i]); } } -void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) +static void SetBoolPair(NCommandLineParser::CParser &parser, unsigned switchID, CBoolPair &bp) +{ + bp.Def = parser[switchID].ThereIs; + if (bp.Def) + bp.Val = !parser[switchID].WithMinus; +} + +void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) { const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int numNonSwitchStrings = nonSwitchStrings.Size(); if (numNonSwitchStrings < kMinNonSwitchWords) - ThrowUserErrorException(); + throw CArcCmdLineException("The command must be spcified"); if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command)) - ThrowUserErrorException(); + throw CArcCmdLineException("Unsupported command:", nonSwitchStrings[kCommandIndex]); options.TechMode = parser[NKey::kTechMode].ThereIs; - options.CalcCrc = parser[NKey::kCalcCrc].ThereIs; - - if (parser[NKey::kCaseSensitive].ThereIs) - g_CaseSensitive = (parser[NKey::kCaseSensitive].PostCharIndex < 0); + if (parser[NKey::kHash].ThereIs) + options.HashMethods = parser[NKey::kHash].PostStrings; + + if (parser[NKey::kElimDup].ThereIs) + { + options.ExtractOptions.ElimDup.Def = true; + options.ExtractOptions.ElimDup.Val = !parser[NKey::kElimDup].WithMinus; + } + + NWildcard::ECensorPathMode censorPathMode = NWildcard::k_RelatPath; + bool fullPathMode = parser[NKey::kFullPathMode].ThereIs; + if (fullPathMode) + { + censorPathMode = NWildcard::k_AbsPath; + const UString &s = parser[NKey::kFullPathMode].PostStrings[0]; + if (!s.IsEmpty()) + { + if (s == L"2") + censorPathMode = NWildcard::k_FullPath; + else + throw CArcCmdLineException("Unsupported -spf:", s); + } + } NRecursedType::EEnum recursedType; if (parser[NKey::kRecursed].ThereIs) @@ -833,43 +992,55 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) else recursedType = NRecursedType::kNonRecursed; - g_CodePage = FindCharset(parser, NKey::kConsoleCharSet, -1); - UINT codePage = FindCharset(parser, NKey::kListfileCharSet, CP_UTF8); + bool wildcardMatching = true; + if (parser[NKey::kDisableWildcardParsing].ThereIs) + wildcardMatching = false; + + g_CodePage = FindCharset(parser, NKey::kConsoleCharSet, true, -1); + Int32 codePage = FindCharset(parser, NKey::kListfileCharSet, false, CP_UTF8); bool thereAreSwitchIncludes = false; + if (parser[NKey::kInclude].ThereIs) { thereAreSwitchIncludes = true; - AddSwitchWildCardsToCensor(options.WildcardCensor, - parser[NKey::kInclude].PostStrings, true, recursedType, codePage); + AddSwitchWildcardsToCensor(options.Censor, + parser[NKey::kInclude].PostStrings, true, recursedType, wildcardMatching, codePage); } + if (parser[NKey::kExclude].ThereIs) - AddSwitchWildCardsToCensor(options.WildcardCensor, - parser[NKey::kExclude].PostStrings, false, recursedType, codePage); + AddSwitchWildcardsToCensor(options.Censor, + parser[NKey::kExclude].PostStrings, false, recursedType, wildcardMatching, codePage); int curCommandIndex = kCommandIndex + 1; bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs && options.Command.CommandType != NCommandType::kBenchmark && - options.Command.CommandType != NCommandType::kInfo; + options.Command.CommandType != NCommandType::kInfo && + options.Command.CommandType != NCommandType::kHash; bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); bool isExtractOrList = isExtractGroupCommand || options.Command.CommandType == NCommandType::kList; + bool isRename = options.Command.CommandType == NCommandType::kRename; - if (isExtractOrList && options.StdInMode) + if ((isExtractOrList || isRename) && options.StdInMode) thereIsArchiveName = false; + if (parser[NKey::kArcNameMode].ThereIs) + options.UpdateOptions.ArcNameMode = ParseArcNameMode(parser[NKey::kArcNameMode].PostCharIndex); + if (thereIsArchiveName) { if (curCommandIndex >= numNonSwitchStrings) - ThrowUserErrorException(); + throw CArcCmdLineException("Cannot find archive name"); options.ArchiveName = nonSwitchStrings[curCommandIndex++]; if (options.ArchiveName.IsEmpty()) - ThrowUserErrorException(); + throw CArcCmdLineException("Archive name cannot by empty"); } - AddToCensorFromNonSwitchesStrings( - curCommandIndex, options.WildcardCensor, - nonSwitchStrings, recursedType, thereAreSwitchIncludes, codePage); + AddToCensorFromNonSwitchesStrings(isRename ? &options.UpdateOptions.RenamePairs : NULL, + curCommandIndex, options.Censor, + nonSwitchStrings, recursedType, wildcardMatching, + thereAreSwitchIncludes, codePage); options.YesToAll = parser[NKey::kYes].ThereIs; @@ -885,30 +1056,73 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) if (parser[NKey::kArchiveType].ThereIs) options.ArcType = parser[NKey::kArchiveType].PostStrings[0]; + options.ExcludedArcTypes = parser[NKey::kExcludedArcType].PostStrings; + SetMethodOptions(parser, options.Properties); + options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs; + + if (options.EnablePercents) + { + if ((options.StdOutMode && !options.IsStdErrTerminal) || + (!options.StdOutMode && !options.IsStdOutTerminal)) + options.EnablePercents = false; + } + + if (parser[NKey::kNtSecurity].ThereIs) options.NtSecurity.SetTrueTrue(); + + SetBoolPair(parser, NKey::kAltStreams, options.AltStreams); + SetBoolPair(parser, NKey::kHardLinks, options.HardLinks); + SetBoolPair(parser, NKey::kSymLinks, options.SymLinks); + if (isExtractOrList) { - if (!options.WildcardCensor.AllAreRelative()) - ThrowException("Cannot use absolute pathnames for this command"); + CExtractOptionsBase &eo = options.ExtractOptions; + + { + CExtractNtOptions &nt = eo.NtOptions; + nt.NtSecurity = options.NtSecurity; - NWildcard::CCensor archiveWildcardCensor; + nt.AltStreams = options.AltStreams; + if (!options.AltStreams.Def) + nt.AltStreams.Val = true; + + nt.HardLinks = options.HardLinks; + if (!options.HardLinks.Def) + nt.HardLinks.Val = true; + + nt.SymLinks = options.SymLinks; + if (!options.SymLinks.Def) + nt.SymLinks.Val = true; + + nt.ReplaceColonForAltStream = parser[NKey::kReplaceColonForAltStream].ThereIs; + nt.WriteToAltStreamIfColon = parser[NKey::kWriteToAltStreamIfColon].ThereIs; + } + + options.Censor.AddPathsToCensor(NWildcard::k_AbsPath); + options.Censor.ExtendExclude(); + + // are there paths that look as non-relative (!Prefix.IsEmpty()) + if (!options.Censor.AllAreRelative()) + throw CArcCmdLineException("Cannot use absolute pathnames for this command"); + + NWildcard::CCensor arcCensor; if (parser[NKey::kArInclude].ThereIs) - AddSwitchWildCardsToCensor(archiveWildcardCensor, - parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, codePage); + AddSwitchWildcardsToCensor(arcCensor, parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, wildcardMatching, codePage); if (parser[NKey::kArExclude].ThereIs) - AddSwitchWildCardsToCensor(archiveWildcardCensor, - parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, codePage); + AddSwitchWildcardsToCensor(arcCensor, parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, wildcardMatching, codePage); if (thereIsArchiveName) - AddNameToCensor(archiveWildcardCensor, options.ArchiveName, true, NRecursedType::kNonRecursed); + AddNameToCensor(arcCensor, options.ArchiveName, true, NRecursedType::kNonRecursed, wildcardMatching); + + arcCensor.AddPathsToCensor(NWildcard::k_RelatPath); #ifdef _WIN32 - ConvertToLongNames(archiveWildcardCensor); + ConvertToLongNames(arcCensor); #endif - archiveWildcardCensor.ExtendExclude(); + arcCensor.ExtendExclude(); if (options.StdInMode) { @@ -918,30 +1132,55 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) } else { - EnumerateDirItemsAndSort(archiveWildcardCensor, - options.ArchivePathsSorted, - options.ArchivePathsFullSorted); + EnumerateDirItemsAndSort( + false, // scanAltStreams + arcCensor, + NWildcard::k_RelatPath, + UString(), // addPathPrefix + options.ArchivePathsSorted, + options.ArchivePathsFullSorted); } if (isExtractGroupCommand) { if (options.StdOutMode && options.IsStdOutTerminal && options.IsStdErrTerminal) - throw kSameTerminalError; + throw CArcCmdLineException(kSameTerminalError); if (parser[NKey::kOutputDir].ThereIs) { - options.OutputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]); - NFile::NName::NormalizeDirPathPrefix(options.OutputDir); + eo.OutputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]); + NFile::NName::NormalizeDirPathPrefix(eo.OutputDir); } - options.OverwriteMode = NExtract::NOverwriteMode::kAskBefore; + eo.OverwriteMode = NExtract::NOverwriteMode::kAsk; if (parser[NKey::kOverwrite].ThereIs) - options.OverwriteMode = k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex]; + { + eo.OverwriteMode = k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex]; + eo.OverwriteMode_Force = true; + } else if (options.YesToAll) - options.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; + { + eo.OverwriteMode = NExtract::NOverwriteMode::kOverwrite; + eo.OverwriteMode_Force = true; + } + } + + eo.PathMode = options.Command.GetPathMode(); + if (censorPathMode == NWildcard::k_AbsPath) + { + eo.PathMode = NExtract::NPathMode::kAbsPaths; + eo.PathMode_Force = true; + } + else if (censorPathMode == NWildcard::k_FullPath) + { + eo.PathMode = NExtract::NPathMode::kFullPaths; + eo.PathMode_Force = true; } } else if (options.Command.IsFromUpdateGroup()) { + if (parser[NKey::kArInclude].ThereIs) + throw CArcCmdLineException("-ai switch is not supported for this command"); + CUpdateOptions &updateOptions = options.UpdateOptions; SetAddCommandOptions(options.Command.CommandType, parser, updateOptions); @@ -951,20 +1190,18 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) if (parser[NKey::kShareForWrite].ThereIs) updateOptions.OpenShareForWrite = true; - options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs; + updateOptions.PathMode = censorPathMode; - if (options.EnablePercents) - { - if ((options.StdOutMode && !options.IsStdErrTerminal) || - (!options.StdOutMode && !options.IsStdOutTerminal)) - options.EnablePercents = false; - } + updateOptions.AltStreams = options.AltStreams; + updateOptions.NtSecurity = options.NtSecurity; + updateOptions.HardLinks = options.HardLinks; + updateOptions.SymLinks = options.SymLinks; updateOptions.EMailMode = parser[NKey::kEmail].ThereIs; if (updateOptions.EMailMode) { updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front(); - if (updateOptions.EMailAddress.Length() > 0) + if (updateOptions.EMailAddress.Len() > 0) if (updateOptions.EMailAddress[0] == L'.') { updateOptions.EMailRemoveAfter = true; @@ -975,30 +1212,46 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) updateOptions.StdOutMode = options.StdOutMode; updateOptions.StdInMode = options.StdInMode; + updateOptions.DeleteAfterCompressing = parser[NKey::kDeleteAfterCompressing].ThereIs; + updateOptions.SetArcMTime = parser[NKey::kSetArcMTime].ThereIs; + if (updateOptions.StdOutMode && updateOptions.EMailMode) - throw "stdout mode and email mode cannot be combined"; + throw CArcCmdLineException("stdout mode and email mode cannot be combined"); if (updateOptions.StdOutMode && options.IsStdOutTerminal) - throw kTerminalOutError; + throw CArcCmdLineException(kTerminalOutError); if (updateOptions.StdInMode) updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front(); - #ifdef _WIN32 - ConvertToLongNames(options.WildcardCensor); - #endif + if (options.Command.CommandType == NCommandType::kRename) + if (updateOptions.Commands.Size() != 1) + throw CArcCmdLineException("Only one archive can be created with rename command"); } else if (options.Command.CommandType == NCommandType::kBenchmark) { options.NumIterations = 1; if (curCommandIndex < numNonSwitchStrings) { - if (!ConvertStringToUInt32(nonSwitchStrings[curCommandIndex++], options.NumIterations)) - ThrowUserErrorException(); + if (!StringToUInt32(nonSwitchStrings[curCommandIndex], options.NumIterations)) + throw CArcCmdLineException("Incorrect Number of benmchmark iterations", nonSwitchStrings[curCommandIndex]); + curCommandIndex++; } } + else if (options.Command.CommandType == NCommandType::kHash) + { + options.Censor.AddPathsToCensor(censorPathMode); + options.Censor.ExtendExclude(); + + CHashOptions &hashOptions = options.HashOptions; + hashOptions.PathMode = censorPathMode; + hashOptions.Methods = options.HashMethods; + if (parser[NKey::kShareForWrite].ThereIs) + hashOptions.OpenShareForWrite = true; + hashOptions.StdInMode = options.StdInMode; + hashOptions.AltStreamsMode = options.AltStreams.Val; + } else if (options.Command.CommandType == NCommandType::kInfo) { } else - ThrowUserErrorException(); - options.WildcardCensor.ExtendExclude(); + throw 9815676711; } diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.h b/CPP/7zip/UI/Common/ArchiveCommandLine.h old mode 100755 new mode 100644 index 96646d60..22e3d4bf --- a/CPP/7zip/UI/Common/ArchiveCommandLine.h +++ b/CPP/7zip/UI/Common/ArchiveCommandLine.h @@ -3,15 +3,16 @@ #ifndef __ARCHIVE_COMMAND_LINE_H #define __ARCHIVE_COMMAND_LINE_H -#include "Common/CommandLineParser.h" -#include "Common/Wildcard.h" +#include "../../../Common/CommandLineParser.h" +#include "../../../Common/Wildcard.h" #include "Extract.h" +#include "HashCalc.h" #include "Update.h" -struct CArchiveCommandLineException: public AString +struct CArcCmdLineException: public UString { - CArchiveCommandLineException(const char *errorMessage): AString(errorMessage) {} + CArcCmdLineException(const char *a, const wchar_t *u = NULL); }; namespace NCommandType { enum EEnum @@ -21,35 +22,33 @@ namespace NCommandType { enum EEnum kDelete, kTest, kExtract, - kFullExtract, + kExtractFull, kList, kBenchmark, - kInfo + kInfo, + kHash, + kRename };} -namespace NRecursedType { enum EEnum -{ - kRecursed, - kWildCardOnlyRecursed, - kNonRecursed -};} - -struct CArchiveCommand +struct CArcCommand { NCommandType::EEnum CommandType; + bool IsFromExtractGroup() const; bool IsFromUpdateGroup() const; - bool IsTestMode() const { return CommandType == NCommandType::kTest; } + bool IsTestCommand() const { return CommandType == NCommandType::kTest; } NExtract::NPathMode::EEnum GetPathMode() const; }; -struct CArchiveCommandLineOptions +struct CArcCmdLineOptions { bool HelpMode; #ifdef _WIN32 bool LargePages; #endif + bool CaseSensitiveChange; + bool CaseSensitive; bool IsInTerminal; bool IsStdOutTerminal; @@ -60,10 +59,9 @@ struct CArchiveCommandLineOptions bool YesToAll; bool ShowDialog; - // NWildcard::CCensor ArchiveWildcardCensor; - NWildcard::CCensor WildcardCensor; + NWildcard::CCensor Censor; - CArchiveCommand Command; + CArcCommand Command; UString ArchiveName; #ifndef _NO_CRYPTO @@ -72,35 +70,52 @@ struct CArchiveCommandLineOptions #endif bool TechMode; - // Extract - bool CalcCrc; + + UStringVector HashMethods; + bool AppendName; - FString OutputDir; - NExtract::NOverwriteMode::EEnum OverwriteMode; UStringVector ArchivePathsSorted; UStringVector ArchivePathsFullSorted; CObjectVector Properties; + CExtractOptionsBase ExtractOptions; + + CBoolPair NtSecurity; + CBoolPair AltStreams; + CBoolPair HardLinks; + CBoolPair SymLinks; + CUpdateOptions UpdateOptions; + CHashOptions HashOptions; UString ArcType; + UStringVector ExcludedArcTypes; bool EnablePercents; // Benchmark UInt32 NumIterations; - CArchiveCommandLineOptions(): StdInMode(false), StdOutMode(false) {}; + CArcCmdLineOptions(): + StdInMode(false), + StdOutMode(false), + CaseSensitiveChange(false), + CaseSensitive(false) + {}; }; -class CArchiveCommandLineParser +class CArcCmdLineParser { NCommandLineParser::CParser parser; public: - CArchiveCommandLineParser(); - void Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options); - void Parse2(CArchiveCommandLineOptions &options); + CArcCmdLineParser(); + void Parse1(const UStringVector &commandStrings, CArcCmdLineOptions &options); + void Parse2(CArcCmdLineOptions &options); }; -void EnumerateDirItemsAndSort(NWildcard::CCensor &wildcardCensor, +void EnumerateDirItemsAndSort( + bool storeAltStreams, + NWildcard::CCensor &censor, + NWildcard::ECensorPathMode pathMode, + const UString &addPathPrefix, UStringVector &sortedPaths, UStringVector &sortedFullPaths); diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp old mode 100755 new mode 100644 index 9c9c0422..c365d66f --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp @@ -2,42 +2,200 @@ #include "StdAfx.h" -#include "Common/ComTry.h" -#include "Common/StringConvert.h" -#include "Common/Wildcard.h" +#undef sprintf +#undef printf -#include "Windows/FileDir.h" -#include "Windows/FileFind.h" -#include "Windows/FileName.h" -#include "Windows/PropVariant.h" -#include "Windows/PropVariantConversions.h" +#include "../../../Common/ComTry.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/Wildcard.h" + +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/PropVariantConv.h" + +#if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX) +#define _USE_SECURITY_CODE +#include "../../../Windows/SecurityUtils.h" +#endif #include "../../Common/FilePathAutoRename.h" #include "../Common/ExtractingFilePath.h" +#include "../Common/PropIDUtils.h" #include "ArchiveExtractCallback.h" using namespace NWindows; +using namespace NFile; +using namespace NDir; + +static const char *kCantAutoRename = "Can not create file with auto name"; +static const char *kCantRenameFile = "Can not rename existing file"; +static const char *kCantDeleteOutputFile = "Can not delete output file"; +static const char *kCantDeleteOutputDir = "Can not delete output folder"; + + +#ifndef _SFX + +STDMETHODIMP COutStreamWithHash::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + HRESULT result = S_OK; + if (_stream) + result = _stream->Write(data, size, &size); + if (_calculate) + _hash->Update(data, size); + _size += size; + if (processedSize) + *processedSize = size; + return result; +} + +#endif + +#ifdef _USE_SECURITY_CODE +bool InitLocalPrivileges() +{ + NSecurity::CAccessToken token; + if (!token.OpenProcessToken(GetCurrentProcess(), + TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES)) + return false; + + TOKEN_PRIVILEGES tp; + + tp.PrivilegeCount = 1; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + if (!::LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &tp.Privileges[0].Luid)) + return false; + if (!token.AdjustPrivileges(&tp)) + return false; + return (GetLastError() == ERROR_SUCCESS); +} +#endif + +#ifdef SUPPORT_LINKS + +int CHardLinkNode::Compare(const CHardLinkNode &a) const +{ + if (StreamId < a.StreamId) return -1; + if (StreamId > a.StreamId) return 1; + return MyCompare(INode, a.INode); +} + +HRESULT Archive_Get_HardLinkNode(IInArchive *archive, UInt32 index, CHardLinkNode &h, bool &defined) +{ + h.INode = 0; + h.StreamId = (UInt64)(Int64)-1; + defined = false; + { + NCOM::CPropVariant prop; + RINOK(archive->GetProperty(index, kpidINode, &prop)); + if (!ConvertPropVariantToUInt64(prop, h.INode)) + return S_OK; + } + { + NCOM::CPropVariant prop; + RINOK(archive->GetProperty(index, kpidStreamId, &prop)); + ConvertPropVariantToUInt64(prop, h.StreamId); + } + defined = true; + return S_OK; +} + + +HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector *realIndices) +{ + _hardLinks.Clear(); + + if (!_arc->Ask_INode) + return S_OK; + + IInArchive *archive = _arc->Archive; + CRecordVector &hardIDs = _hardLinks.IDs; + + { + UInt32 numItems; + if (realIndices) + numItems = realIndices->Size(); + else + { + RINOK(archive->GetNumberOfItems(&numItems)); + } -static const char *kCantAutoRename = "ERROR: Can not create file with auto name"; -static const char *kCantRenameFile = "ERROR: Can not rename existing file "; -static const char *kCantDeleteOutputFile = "ERROR: Can not delete output file "; + for (UInt32 i = 0; i < numItems; i++) + { + CHardLinkNode h; + bool defined; + RINOK(Archive_Get_HardLinkNode(archive, realIndices ? (*realIndices)[i] : i, h, defined)); + if (defined) + hardIDs.Add(h); + } + } + + hardIDs.Sort2(); + + { + // wee keep only items that have 2 or more items + unsigned k = 0; + unsigned numSame = 1; + for (unsigned i = 1; i < hardIDs.Size(); i++) + { + if (hardIDs[i].Compare(hardIDs[i - 1]) != 0) + numSame = 1; + else if (++numSame == 2) + { + if (i - 1 != k) + hardIDs[k] = hardIDs[i - 1]; + k++; + } + } + hardIDs.DeleteFrom(k); + } + + _hardLinks.PrepareLinks(); + return S_OK; +} + +#endif + +CArchiveExtractCallback::CArchiveExtractCallback(): + WriteCTime(true), + WriteATime(true), + WriteMTime(true), + _multiArchives(false) +{ + LocalProgressSpec = new CLocalProgress(); + _localProgress = LocalProgressSpec; + + #ifdef _USE_SECURITY_CODE + _saclEnabled = InitLocalPrivileges(); + #endif +} void CArchiveExtractCallback::Init( + const CExtractNtOptions &ntOptions, const NWildcard::CCensorNode *wildcardCensor, const CArc *arc, IFolderArchiveExtractCallback *extractCallback2, - bool stdOutMode, bool testMode, bool crcMode, + bool stdOutMode, bool testMode, const FString &directoryPath, const UStringVector &removePathParts, UInt64 packSize) { + _extractedFolderPaths.Clear(); + _extractedFolderIndices.Clear(); + + #ifdef SUPPORT_LINKS + _hardLinks.Clear(); + #endif + + _ntOptions = ntOptions; _wildcardCensor = wildcardCensor; _stdOutMode = stdOutMode; _testMode = testMode; - _crcMode = crcMode; _unpTotal = 1; _packTotal = packSize; @@ -45,14 +203,31 @@ void CArchiveExtractCallback::Init( _compressProgress.Release(); _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress); + #ifndef _SFX + + _extractCallback2.QueryInterface(IID_IFolderExtractToStreamCallback, &ExtractToStreamCallback); + if (ExtractToStreamCallback) + { + Int32 useStreams = 0; + if (ExtractToStreamCallback->UseExtractToStream(&useStreams) != S_OK) + useStreams = 0; + if (useStreams == 0) + ExtractToStreamCallback.Release(); + } + + #endif + LocalProgressSpec->Init(extractCallback2, true); LocalProgressSpec->SendProgress = false; - _removePathParts = removePathParts; + _baseParentFolder = (UInt32)(Int32)-1; + _use_baseParentFolder_mode = false; + _arc = arc; _directoryPath = directoryPath; - NFile::NName::NormalizeDirPathPrefix(_directoryPath); + NName::NormalizeDirPathPrefix(_directoryPath); + NDir::MyGetFullPathName(directoryPath, _directoryPathFull); } STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size) @@ -109,15 +284,48 @@ STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const U COM_TRY_END } +#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z') + +static inline bool IsDriveName(const UString &s) +{ + return s.Len() == 2 && s[1] == ':' && IS_LETTER_CHAR(s[0]); +} + void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath) { - fullPath = _directoryPath; - for (int i = 0; i < dirPathParts.Size(); i++) + bool isAbsPath = false; + + if (!dirPathParts.IsEmpty()) + { + const UString &s = dirPathParts[0]; + if (s.IsEmpty()) + isAbsPath = true; + #ifdef _WIN32 + else + { + if (dirPathParts.Size() > 1 && IsDriveName(s)) + isAbsPath = true; + } + #endif + } + + if (_pathMode == NExtract::NPathMode::kAbsPaths && isAbsPath) + fullPath.Empty(); + else + fullPath = _directoryPath; + + FOR_VECTOR (i, dirPathParts) { if (i > 0) fullPath += FCHAR_PATH_SEPARATOR; - fullPath += us2fs(dirPathParts[i]); - NFile::NDirectory::MyCreateDirectory(fullPath); + const UString &s = dirPathParts[i]; + fullPath += us2fs(s); + #ifdef _WIN32 + if (_pathMode == NExtract::NPathMode::kAbsPaths) + if (i == 0 && IsDriveName(s)) + continue; + #endif + CreateDir(fullPath); } } @@ -143,18 +351,95 @@ HRESULT CArchiveExtractCallback::GetUnpackSize() HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FString &path) { - return _extractCallback2->MessageError(GetUnicodeString(message) + fs2us(path)); + return _extractCallback2->MessageError( + UString(L"ERROR: ") + + GetUnicodeString(message) + L": " + fs2us(path)); } +HRESULT CArchiveExtractCallback::SendMessageError2(const char *message, const FString &path1, const FString &path2) +{ + return _extractCallback2->MessageError( + UString(L"ERROR: ") + + GetUnicodeString(message) + UString(L": ") + fs2us(path1) + UString(L" : ") + fs2us(path2)); +} + +#ifndef _SFX + +STDMETHODIMP CGetProp::GetProp(PROPID propID, PROPVARIANT *value) +{ + if (propID == kpidName) + { + COM_TRY_BEGIN + NCOM::CPropVariant prop = Name; + prop.Detach(value); + return S_OK; + COM_TRY_END + } + return Arc->Archive->GetProperty(IndexInArc, propID, value); +} + +#endif + + +#ifdef SUPPORT_LINKS + +static UString GetDirPrefixOf(const UString &src) +{ + UString s = src; + if (!s.IsEmpty()) + { + if (s.Back() == WCHAR_PATH_SEPARATOR) + s.DeleteBack(); + int pos = s.ReverseFind(WCHAR_PATH_SEPARATOR); + s.DeleteFrom(pos + 1); + } + return s; +} + +static bool IsSafePath(const UString &path) +{ + UStringVector parts; + SplitPathToParts(path, parts); + int level = 0; + FOR_VECTOR(i, parts) + { + const UString &s = parts[i]; + if (s.IsEmpty()) + continue; + if (s == L".") + continue; + if (s == L"..") + { + if (level <= 0) + return false; + level--; + } + else + level++; + } + return level > 0; +} + +#endif + + STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { COM_TRY_BEGIN - _crcStream.Release(); + *outStream = 0; + + #ifndef _SFX + if (_hashStream) + _hashStreamSpec->ReleaseStream(); + _hashStreamWasUsed = false; + #endif + _outFileStream.Release(); _encrypted = false; _isSplit = false; + _isAltStream = false; _curSize = 0; _curSizeDefined = false; _index = index; @@ -163,7 +448,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre IInArchive *archive = _arc->Archive; RINOK(_arc->GetItemPath(index, fullPath)); - RINOK(IsArchiveItemFolder(archive, index, _fi.IsDir)); + RINOK(Archive_IsItem_Folder(archive, index, _fi.IsDir)); _filePath = fullPath; @@ -178,26 +463,220 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre _isSplit = true; } } + + #ifdef SUPPORT_LINKS + + bool isHardLink = false; + bool isJunction = false; + bool isRelative = false; + + UString linkPath; + // RINOK(Archive_GetItemBoolProp(archive, index, kpidIsHardLink, isHardLink)); + // if (isHardLink) + { + NCOM::CPropVariant prop; + RINOK(archive->GetProperty(index, kpidHardLink, &prop)); + if (prop.vt == VT_BSTR) + { + isHardLink = true; + linkPath = prop.bstrVal; + isRelative = false; // TAR: hard links are from root folder of archive + } + else if (prop.vt == VT_EMPTY) + { + // linkPath.Empty(); + } + else + return E_FAIL; + } + { + NCOM::CPropVariant prop; + RINOK(archive->GetProperty(index, kpidSymLink, &prop)); + if (prop.vt == VT_BSTR) + { + isHardLink = false; + linkPath = prop.bstrVal; + isRelative = true; // TAR: symbolic links are relative + } + else if (prop.vt == VT_EMPTY) + { + // linkPath.Empty(); + } + else + return E_FAIL; + } + + bool isOkReparse = false; + + if (linkPath.IsEmpty() && _arc->GetRawProps) + { + const void *data; + UInt32 dataSize; + UInt32 propType; + _arc->GetRawProps->GetRawProp(_index, kpidNtReparse, &data, &dataSize, &propType); + if (dataSize != 0) + { + if (propType != NPropDataType::kRaw) + return E_FAIL; + UString s; + CReparseAttr reparse; + isOkReparse = reparse.Parse((const Byte *)data, dataSize); + if (isOkReparse) + { + isHardLink = false; + linkPath = reparse.GetPath(); + isJunction = reparse.IsMountPoint(); + isRelative = reparse.IsRelative(); + #ifndef _WIN32 + linkPath.Replace(WCHAR_PATH_SEPARATOR, '/', ); + #endif + } + } + } + + if (!linkPath.IsEmpty()) + { + #ifdef _WIN32 + linkPath.Replace('/', WCHAR_PATH_SEPARATOR); + #endif - RINOK(GetArchiveItemBoolProp(archive, index, kpidEncrypted, _encrypted)); + for (;;) + // while (NName::IsAbsolutePath(linkPath)) + { + unsigned n = NName::GetRootPrefixSize(linkPath); + if (n == 0) + break; + isRelative = false; + linkPath.DeleteFrontal(n); + } + } + + if (!linkPath.IsEmpty() && !isRelative && _removePathParts.Size() != 0) + { + UStringVector pathParts; + SplitPathToParts(linkPath, pathParts); + bool badPrefix = false; + FOR_VECTOR (i, _removePathParts) + { + if (CompareFileNames(_removePathParts[i], pathParts[i]) != 0) + { + badPrefix = true; + break; + } + } + if (!badPrefix) + pathParts.DeleteFrontal(_removePathParts.Size()); + linkPath = MakePathNameFromParts(pathParts); + } + + #endif + + RINOK(Archive_GetItemBoolProp(archive, index, kpidEncrypted, _encrypted)); RINOK(GetUnpackSize()); + RINOK(Archive_IsItem_AltStream(archive, index, _isAltStream)); + + if (!_ntOptions.AltStreams.Val && _isAltStream) + return S_OK; + if (_wildcardCensor) { - if (!_wildcardCensor->CheckPath(fullPath, !_fi.IsDir)) + if (!_wildcardCensor->CheckPath(_isAltStream, fullPath, !_fi.IsDir)) return S_OK; } - if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) + + UStringVector pathParts; + + if (_use_baseParentFolder_mode) { - if (_stdOutMode) + int baseParent = _baseParentFolder; + if (_pathMode == NExtract::NPathMode::kFullPaths || + _pathMode == NExtract::NPathMode::kAbsPaths) + baseParent = -1; + RINOK(_arc->GetItemPathToParent(index, baseParent, pathParts)); + if (_pathMode == NExtract::NPathMode::kNoPaths && !pathParts.IsEmpty()) + pathParts.DeleteFrontal(pathParts.Size() - 1); + } + else + { + SplitPathToParts(fullPath, pathParts); + + if (pathParts.IsEmpty()) + return E_FAIL; + unsigned numRemovePathParts = 0; + + switch (_pathMode) { - CMyComPtr outStreamLoc = new CStdOutFileStream; - *outStream = outStreamLoc.Detach(); - return S_OK; + case NExtract::NPathMode::kCurPaths: + { + bool badPrefix = false; + if (pathParts.Size() <= _removePathParts.Size()) + badPrefix = true; + else + { + FOR_VECTOR (i, _removePathParts) + { + if (!_removePathParts[i].IsEqualToNoCase(pathParts[i])) + { + badPrefix = true; + break; + } + } + } + if (badPrefix) + { + if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) + return E_FAIL; + } + else + numRemovePathParts = _removePathParts.Size(); + break; + } + case NExtract::NPathMode::kNoPaths: + { + numRemovePathParts = pathParts.Size() - 1; + break; + } + /* + case NExtract::NPathMode::kFullPaths: + case NExtract::NPathMode::kAbsPaths: + break; + */ } + + pathParts.DeleteFrontal(numRemovePathParts); + } + + #ifndef _SFX + if (ExtractToStreamCallback) + { + if (!GetProp) + { + GetProp_Spec = new CGetProp; + GetProp = GetProp_Spec; + } + GetProp_Spec->Arc = _arc; + GetProp_Spec->IndexInArc = index; + GetProp_Spec->Name = MakePathNameFromParts(pathParts); + + return ExtractToStreamCallback->GetStream7(GetProp_Spec->Name, _fi.IsDir, outStream, askExtractMode, GetProp); + } + + #endif + + CMyComPtr outStreamLoc; + +if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) +{ + if (_stdOutMode) + { + outStreamLoc = new CStdOutFileStream; + } + else + { { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidAttrib, &prop)); @@ -219,35 +698,15 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre 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); + bool replace = _isAltStream ? + _ntOptions.ReplaceColonForAltStream : + !_ntOptions.WriteToAltStreamIfColon; + + if (_pathMode != NExtract::NPathMode::kAbsPaths) + MakeCorrectPath(_directoryPath.IsEmpty(), pathParts, replace); + Correct_IfEmptyLastPart(pathParts); UString processedPath = MakePathNameFromParts(pathParts); + if (!isAnti) { if (!_fi.IsDir) @@ -261,65 +720,72 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre FString fullPathNew; CreateComplexDirectory(pathParts, fullPathNew); if (_fi.IsDir) - NFile::NDirectory::SetDirTime(fullPathNew, + { + _extractedFolderPaths.Add(fullPathNew); + _extractedFolderIndices.Add(index); + SetDirTime(fullPathNew, (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL, (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL, (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL)); + } } } - FString fullProcessedPath = _directoryPath + us2fs(processedPath); + FString fullProcessedPath = us2fs(processedPath); + if (_pathMode != NExtract::NPathMode::kAbsPaths || + !NName::IsAbsolutePath(processedPath)) + fullProcessedPath = _directoryPath + fullProcessedPath; if (_fi.IsDir) { _diskFilePath = fullProcessedPath; if (isAnti) - NFile::NDirectory::MyRemoveDirectory(_diskFilePath); - return S_OK; + RemoveDir(_diskFilePath); + #ifdef SUPPORT_LINKS + if (linkPath.IsEmpty()) + #endif + return S_OK; } - - if (!_isSplit) + else if (!_isSplit) { - NFile::NFind::CFileInfo fileInfo; + NFind::CFileInfo fileInfo; if (fileInfo.Find(fullProcessedPath)) { - switch(_overwriteMode) + switch (_overwriteMode) { - case NExtract::NOverwriteMode::kSkipExisting: + case NExtract::NOverwriteMode::kSkip: return S_OK; - case NExtract::NOverwriteMode::kAskBefore: + case NExtract::NOverwriteMode::kAsk: { + int slashPos = fullProcessedPath.ReverseFind(FTEXT('/')); + #ifdef _WIN32 + int slash1Pos = fullProcessedPath.ReverseFind(FTEXT('\\')); + slashPos = MyMax(slashPos, slash1Pos); + #endif + FString realFullProcessedPath = fullProcessedPath.Left(slashPos + 1) + fileInfo.Name; + Int32 overwiteResult; RINOK(_extractCallback2->AskOverwrite( - fs2us(fullProcessedPath), &fileInfo.MTime, &fileInfo.Size, fullPath, + fs2us(realFullProcessedPath), &fileInfo.MTime, &fileInfo.Size, fullPath, _fi.MTimeDefined ? &_fi.MTime : NULL, _curSizeDefined ? &_curSize : NULL, &overwiteResult)) - switch(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; + case NOverwriteAnswer::kCancel: return E_ABORT; + case NOverwriteAnswer::kNo: return S_OK; + case NOverwriteAnswer::kNoToAll: _overwriteMode = NExtract::NOverwriteMode::kSkip; return S_OK; + case NOverwriteAnswer::kYes: break; + case NOverwriteAnswer::kYesToAll: _overwriteMode = NExtract::NOverwriteMode::kOverwrite; break; + case NOverwriteAnswer::kAutoRename: _overwriteMode = NExtract::NOverwriteMode::kRename; break; default: return E_FAIL; } } } - if (_overwriteMode == NExtract::NOverwriteMode::kAutoRename) + if (_overwriteMode == NExtract::NOverwriteMode::kRename) { if (!AutoRenamePath(fullProcessedPath)) { @@ -327,7 +793,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre return E_FAIL; } } - else if (_overwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting) + else if (_overwriteMode == NExtract::NOverwriteMode::kRenameExisting) { FString existPath = fullProcessedPath; if (!AutoRenamePath(existPath)) @@ -335,57 +801,186 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre RINOK(SendMessageError(kCantAutoRename, fullProcessedPath)); return E_FAIL; } - if (!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath)) + // MyMoveFile can raname folders. So it's OK to use it folders too + if (!MyMoveFile(fullProcessedPath, existPath)) { RINOK(SendMessageError(kCantRenameFile, fullProcessedPath)); return E_FAIL; } } else - if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) + { + if (fileInfo.IsDir()) + { + // do we need to delete all files in folder? + if (!RemoveDir(fullProcessedPath)) + { + RINOK(SendMessageError(kCantDeleteOutputDir, fullProcessedPath)); + return S_OK; + } + } + else if (!DeleteFileAlways(fullProcessedPath)) { RINOK(SendMessageError(kCantDeleteOutputFile, fullProcessedPath)); return S_OK; // return E_FAIL; } + } } } + _diskFilePath = fullProcessedPath; + + if (!isAnti) { - _outFileStreamSpec = new COutFileStream; - CMyComPtr outStreamLoc(_outFileStreamSpec); - if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS)) + #ifdef SUPPORT_LINKS + + if (!linkPath.IsEmpty()) { - // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit) + #ifndef UNDER_CE + + UString relatPath; + if (isRelative) + relatPath = GetDirPrefixOf(_filePath); + relatPath += linkPath; + + if (!IsSafePath(relatPath)) { - RINOK(SendMessageError("can not open output file ", fullProcessedPath)); - return S_OK; + RINOK(SendMessageError("Dangerous link path was ignored", us2fs(relatPath))); } + else + { + FString existPath; + if (isHardLink || !isRelative) + { + if (!NName::GetFullPath(_directoryPathFull, us2fs(relatPath), existPath)) + { + RINOK(SendMessageError("Incorrect path", us2fs(relatPath))); + } + } + else + { + existPath = us2fs(linkPath); + } + + if (!existPath.IsEmpty()) + { + if (isHardLink) + { + if (!MyCreateHardLink(fullProcessedPath, existPath)) + { + RINOK(SendMessageError2("Can not create hard link", fullProcessedPath, existPath)); + // return S_OK; + } + } + else if (_ntOptions.SymLinks.Val) + { + // bool isSymLink = true; // = false for junction + if (_fi.IsDir && !isRelative) + { + // if it's before Vista we use Junction Point + // isJunction = true; + // convertToAbs = true; + } + + CByteBuffer data; + if (FillLinkData(data, fs2us(existPath), !isJunction)) + { + CReparseAttr attr; + if (!attr.Parse(data, data.Size())) + { + return E_FAIL; // "Internal conversion error"; + } + + if (!NFile::NIO::SetReparseData(fullProcessedPath, _fi.IsDir, data, (DWORD)data.Size())) + { + RINOK(SendMessageError("Can not set reparse data", fullProcessedPath)); + } + } + } + } + } + + #endif } - if (_isSplit) + else + #endif // SUPPORT_LINKS { - RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL)); + bool needWriteFile = true; + + #ifdef SUPPORT_LINKS + if (!_hardLinks.IDs.IsEmpty()) + { + CHardLinkNode h; + bool defined; + RINOK(Archive_Get_HardLinkNode(archive, index, h, defined)); + if (defined) + { + { + int linkIndex = _hardLinks.IDs.FindInSorted2(h); + if (linkIndex >= 0) + { + FString &hl = _hardLinks.Links[linkIndex]; + if (hl.IsEmpty()) + hl = fullProcessedPath; + else + { + if (!MyCreateHardLink(fullProcessedPath, hl)) + { + RINOK(SendMessageError2("Can not create hard link", fullProcessedPath, hl)); + return S_OK; + } + needWriteFile = false; + } + } + } + } + } + #endif + + if (needWriteFile) + { + _outFileStreamSpec = new COutFileStream; + CMyComPtr outStreamLoc(_outFileStreamSpec); + if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS)) + { + // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit) + { + RINOK(SendMessageError("Can not open output file ", fullProcessedPath)); + return S_OK; + } + } + if (_isSplit) + { + RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL)); + } + _outFileStream = outStreamLoc; + } } - _outFileStream = outStreamLoc; - *outStream = outStreamLoc.Detach(); } - _diskFilePath = fullProcessedPath; - } - else - { - *outStream = NULL; + + outStreamLoc = _outFileStream; } - if (_crcMode) +} + + #ifndef _SFX + + if (_hashStream) { - _crcStreamSpec = new COutStreamWithCRC; - _crcStream = _crcStreamSpec; - CMyComPtr crcStream = _crcStreamSpec; - _crcStreamSpec->SetStream(*outStream); - if (*outStream) - (*outStream)->Release(); - *outStream = crcStream.Detach(); - _crcStreamSpec->Init(true); + if (askExtractMode == NArchive::NExtract::NAskMode::kExtract || + askExtractMode == NArchive::NExtract::NAskMode::kTest) + { + _hashStreamSpec->SetStream(outStreamLoc); + outStreamLoc = _hashStream; + _hashStreamSpec->Init(true); + _hashStreamWasUsed = true; + } } + + #endif + + if (outStreamLoc) + *outStream = outStreamLoc.Detach(); return S_OK; COM_TRY_END } @@ -393,6 +988,12 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) { COM_TRY_BEGIN + + #ifndef _SFX + if (ExtractToStreamCallback) + return ExtractToStreamCallback->PrepareOperation7(askExtractMode); + #endif + _extractMode = false; switch (askExtractMode) { @@ -411,24 +1012,25 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) 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) + + #ifndef _SFX + if (ExtractToStreamCallback) + return ExtractToStreamCallback->SetOperationResult7(operationResult, _encrypted); + #endif + + #ifndef _SFX + + if (_hashStreamWasUsed) { - CrcSum += _crcStreamSpec->GetCRC(); - _curSize = _crcStreamSpec->GetSize(); + _hashStreamSpec->_hash->Final(_fi.IsDir, _isAltStream, _filePath); + _curSize = _hashStreamSpec->GetSize(); _curSizeDefined = true; - _crcStream.Release(); + _hashStreamSpec->ReleaseStream(); + _hashStreamWasUsed = false; } + + #endif + if (_outFileStream) { _outFileStreamSpec->SetTime( @@ -440,17 +1042,48 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) RINOK(_outFileStreamSpec->Close()); _outFileStream.Release(); } + + #ifdef _USE_SECURITY_CODE + if (_ntOptions.NtSecurity.Val && _arc->GetRawProps) + { + const void *data; + UInt32 dataSize; + UInt32 propType; + _arc->GetRawProps->GetRawProp(_index, kpidNtSecure, &data, &dataSize, &propType); + if (dataSize != 0) + { + if (propType != NPropDataType::kRaw) + return E_FAIL; + if (CheckNtSecure((const Byte *)data, dataSize)) + { + SECURITY_INFORMATION securInfo = DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION; + if (_saclEnabled) + securInfo |= SACL_SECURITY_INFORMATION; + ::SetFileSecurityW(fs2us(_diskFilePath), securInfo, (void *)data); + } + } + } + #endif + if (!_curSizeDefined) GetUnpackSize(); if (_curSizeDefined) - UnpackSize += _curSize; + { + if (_isAltStream) + AltStreams_UnpackSize += _curSize; + else + UnpackSize += _curSize; + } + if (_fi.IsDir) NumFolders++; + else if (_isAltStream) + NumAltStreams++; else NumFiles++; if (_extractMode && _fi.AttribDefined) - NFile::NDirectory::MySetFileAttributes(_diskFilePath, _fi.Attrib); + SetFileAttrib(_diskFilePath, _fi.Attrib); RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted)); return S_OK; COM_TRY_END @@ -482,3 +1115,77 @@ STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) return _cryptoGetTextPassword->CryptoGetTextPassword(password); COM_TRY_END } + + +struct CExtrRefSortPair +{ + int Len; + int Index; + + int Compare(const CExtrRefSortPair &a) const; +}; + +#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } + +int CExtrRefSortPair::Compare(const CExtrRefSortPair &a) const +{ + RINOZ(-MyCompare(Len, a.Len)); + return MyCompare(Index, a.Index); +} + +static int GetNumSlashes(const FChar *s) +{ + for (int numSlashes = 0;;) + { + FChar c = *s++; + if (c == 0) + return numSlashes; + if ( + #ifdef _WIN32 + c == FTEXT('\\') || + #endif + c == FTEXT('/')) + numSlashes++; + } +} + +HRESULT CArchiveExtractCallback::SetDirsTimes() +{ + CRecordVector pairs; + pairs.ClearAndSetSize(_extractedFolderPaths.Size()); + unsigned i; + + for (i = 0; i < _extractedFolderPaths.Size(); i++) + { + CExtrRefSortPair &pair = pairs[i]; + pair.Index = i; + pair.Len = GetNumSlashes(_extractedFolderPaths[i]); + } + + pairs.Sort2(); + + for (i = 0; i < pairs.Size(); i++) + { + int pairIndex = pairs[i].Index; + int index = _extractedFolderIndices[pairIndex]; + + FILETIME CTime; + FILETIME ATime; + FILETIME MTime; + + bool CTimeDefined; + bool ATimeDefined; + bool MTimeDefined; + + RINOK(GetTime(index, kpidCTime, CTime, CTimeDefined)); + RINOK(GetTime(index, kpidATime, ATime, ATimeDefined)); + RINOK(GetTime(index, kpidMTime, MTime, MTimeDefined)); + + // printf("\n%S", _extractedFolderPaths[pairIndex]); + SetDirTime(_extractedFolderPaths[pairIndex], + (WriteCTime && CTimeDefined) ? &CTime : NULL, + (WriteATime && ATimeDefined) ? &ATime : NULL, + (WriteMTime && MTimeDefined) ? &MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL)); + } + return S_OK; +} diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h old mode 100755 new mode 100644 index cee7c5b6..ed41ba8d --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h @@ -3,8 +3,8 @@ #ifndef __ARCHIVE_EXTRACT_CALLBACK_H #define __ARCHIVE_EXTRACT_CALLBACK_H -#include "Common/MyCom.h" -#include "Common/Wildcard.h" +#include "../../../Common/MyCom.h" +#include "../../../Common/Wildcard.h" #include "../../IPassword.h" @@ -13,12 +13,117 @@ #include "../../Archive/IArchive.h" -#include "../../Archive/Common/OutStreamWithCRC.h" - #include "ExtractMode.h" #include "IFileExtractCallback.h" #include "OpenArchive.h" +#include "HashCalc.h" + +#ifndef _SFX + +class COutStreamWithHash: + public ISequentialOutStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + UInt64 _size; + bool _calculate; +public: + IHashCalc *_hash; + + MY_UNKNOWN_IMP + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + void SetStream(ISequentialOutStream *stream) { _stream = stream; } + void ReleaseStream() { _stream.Release(); } + void Init(bool calculate = true) + { + InitCRC(); + _size = 0; + _calculate = calculate; + } + void EnableCalc(bool calculate) { _calculate = calculate; } + void InitCRC() { _hash->InitForNewFile(); } + UInt64 GetSize() const { return _size; } +}; + +#endif + +struct CExtractNtOptions +{ + CBoolPair NtSecurity; + CBoolPair SymLinks; + CBoolPair HardLinks; + CBoolPair AltStreams; + bool ReplaceColonForAltStream; + bool WriteToAltStreamIfColon; + + CExtractNtOptions(): + ReplaceColonForAltStream(false), + WriteToAltStreamIfColon(false) + { + SymLinks.Val = true; + HardLinks.Val = true; + AltStreams.Val = true; + } +}; + +#ifndef _SFX + +class CGetProp: + public IGetProp, + public CMyUnknownImp +{ +public: + const CArc *Arc; + UInt32 IndexInArc; + UString Name; // relative path + + MY_UNKNOWN_IMP1(IGetProp) + INTERFACE_IGetProp(;) +}; + +#endif + +#ifndef _SFX +#ifndef UNDER_CE + +#define SUPPORT_LINKS + +#endif +#endif + + +#ifdef SUPPORT_LINKS + +struct CHardLinkNode +{ + UInt64 StreamId; + UInt64 INode; + + int Compare(const CHardLinkNode &a) const; +}; + +class CHardLinks +{ +public: + CRecordVector IDs; + CObjectVector Links; + + void Clear() + { + IDs.Clear(); + Links.Clear(); + } + + void PrepareLinks() + { + while (Links.Size() < IDs.Size()) + Links.AddNew(); + } +}; + +#endif + class CArchiveExtractCallback: public IArchiveExtractCallback, // public IArchiveVolumeExtractCallback, @@ -27,18 +132,30 @@ class CArchiveExtractCallback: public CMyUnknownImp { const CArc *_arc; + CExtractNtOptions _ntOptions; + const NWildcard::CCensorNode *_wildcardCensor; CMyComPtr _extractCallback2; CMyComPtr _compressProgress; CMyComPtr _cryptoGetTextPassword; FString _directoryPath; + FString _directoryPathFull; NExtract::NPathMode::EEnum _pathMode; NExtract::NOverwriteMode::EEnum _overwriteMode; + #ifndef _SFX + + CMyComPtr ExtractToStreamCallback; + CGetProp *GetProp_Spec; + CMyComPtr GetProp; + + #endif + FString _diskFilePath; UString _filePath; UInt64 _position; bool _isSplit; + bool _isAltStream; bool _extractMode; @@ -69,25 +186,39 @@ class CArchiveExtractCallback: COutFileStream *_outFileStreamSpec; CMyComPtr _outFileStream; - COutStreamWithCRC *_crcStreamSpec; - CMyComPtr _crcStream; + #ifndef _SFX + + COutStreamWithHash *_hashStreamSpec; + CMyComPtr _hashStream; + bool _hashStreamWasUsed; + + #endif UStringVector _removePathParts; + bool _use_baseParentFolder_mode; + UInt32 _baseParentFolder; bool _stdOutMode; bool _testMode; - bool _crcMode; bool _multiArchives; CMyComPtr _localProgress; UInt64 _packTotal; UInt64 _unpTotal; + FStringVector _extractedFolderPaths; + CRecordVector _extractedFolderIndices; + + #if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX) + bool _saclEnabled; + #endif + void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath); HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined); HRESULT GetUnpackSize(); HRESULT SendMessageError(const char *message, const FString &path); + HRESULT SendMessageError2(const char *message, const FString &path1, const FString &path2); public: @@ -95,8 +226,9 @@ public: UInt64 NumFolders; UInt64 NumFiles; + UInt64 NumAltStreams; UInt64 UnpackSize; - UInt32 CrcSum; + UInt64 AltStreams_UnpackSize; MY_UNKNOWN_IMP2(ICryptoGetTextPassword, ICompressProgressInfo) // COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback) @@ -110,15 +242,7 @@ public: STDMETHOD(CryptoGetTextPassword)(BSTR *password); - CArchiveExtractCallback(): - WriteCTime(true), - WriteATime(true), - WriteMTime(true), - _multiArchives(false) - { - LocalProgressSpec = new CLocalProgress(); - _localProgress = LocalProgressSpec; - } + CArchiveExtractCallback(); void InitForMulti(bool multiArchives, NExtract::NPathMode::EEnum pathMode, @@ -127,19 +251,49 @@ public: _multiArchives = multiArchives; _pathMode = pathMode; _overwriteMode = overwriteMode; - NumFolders = NumFiles = UnpackSize = 0; - CrcSum = 0; + NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0; } + #ifndef _SFX + + void SetHashMethods(IHashCalc *hash) + { + if (!hash) + return; + _hashStreamSpec = new COutStreamWithHash; + _hashStream = _hashStreamSpec; + _hashStreamSpec->_hash = hash; + } + + #endif + void Init( + const CExtractNtOptions &ntOptions, const NWildcard::CCensorNode *wildcardCensor, const CArc *arc, IFolderArchiveExtractCallback *extractCallback2, - bool stdOutMode, bool testMode, bool crcMode, + bool stdOutMode, bool testMode, const FString &directoryPath, const UStringVector &removePathParts, UInt64 packSize); + #ifdef SUPPORT_LINKS +private: + CHardLinks _hardLinks; +public: + // call PrepareHardLinks() after Init() + HRESULT PrepareHardLinks(const CRecordVector *realIndices); // NULL means all items + #endif + + // call it after Init() + + void SetBaseParentFolderIndex(UInt32 indexInArc) + { + _use_baseParentFolder_mode = true; + _baseParentFolder = indexInArc; + } + + HRESULT SetDirsTimes(); }; #endif diff --git a/CPP/7zip/UI/Common/ArchiveName.cpp b/CPP/7zip/UI/Common/ArchiveName.cpp old mode 100755 new mode 100644 index 17947dce..dcf6590e --- a/CPP/7zip/UI/Common/ArchiveName.cpp +++ b/CPP/7zip/UI/Common/ArchiveName.cpp @@ -2,22 +2,38 @@ #include "StdAfx.h" -#include "Windows/FileDir.h" -#include "Windows/FileFind.h" +#include "../../../Windows/FileDir.h" #include "ExtractingFilePath.h" +#include "ArchiveName.h" using namespace NWindows; +UString CreateArchiveName(const NFile::NFind::CFileInfo fileInfo, bool keepName) +{ + FString resultName = fileInfo.Name; + if (!fileInfo.IsDir() && !keepName) + { + int dotPos = resultName.ReverseFind(FTEXT('.')); + if (dotPos > 0) + { + FString archiveName2 = resultName.Left(dotPos); + if (archiveName2.ReverseFind(FTEXT('.')) < 0) + resultName = archiveName2; + } + } + return GetCorrectFsPath(fs2us(resultName)); +} + static FString CreateArchiveName2(const FString &srcName, bool fromPrev, bool keepName) { FString resultName = FTEXT("Archive"); if (fromPrev) { FString dirPrefix; - if (NFile::NDirectory::GetOnlyDirPrefix(srcName, dirPrefix)) + if (NFile::NDir::GetOnlyDirPrefix(srcName, dirPrefix)) { - if (dirPrefix.Length() > 0) + if (dirPrefix.Len() > 0) if (dirPrefix.Back() == FCHAR_PATH_SEPARATOR) { dirPrefix.DeleteBack(); diff --git a/CPP/7zip/UI/Common/ArchiveName.h b/CPP/7zip/UI/Common/ArchiveName.h old mode 100755 new mode 100644 index 9513fb2b..99ba086c --- a/CPP/7zip/UI/Common/ArchiveName.h +++ b/CPP/7zip/UI/Common/ArchiveName.h @@ -1,10 +1,13 @@ // ArchiveName.h -#ifndef __ARCHIVENAME_H -#define __ARCHIVENAME_H +#ifndef __ARCHIVE_NAME_H +#define __ARCHIVE_NAME_H -#include "Common/MyString.h" +#include "../../../Common/MyString.h" + +#include "../../../Windows/FileFind.h" UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName); +UString CreateArchiveName(const NWindows::NFile::NFind::CFileInfo fileInfo, bool keepName); #endif diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp old mode 100755 new mode 100644 index be20940c..e698f56f --- a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp +++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp @@ -2,9 +2,10 @@ #include "StdAfx.h" -#include "Common/ComTry.h" +#include "../../../Common/ComTry.h" -#include "Windows/PropVariant.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/PropVariant.h" #include "../../Common/FileStreams.h" @@ -59,41 +60,32 @@ STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value) 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; + int FileNameIndex; COpenCallbackImp *OpenCallbackImp; CMyComPtr OpenCallbackRef; + ~CInFileStreamVol() { if (OpenCallbackRef) - { - int index = OpenCallbackImp->FindName(Name); - if (index >= 0) - OpenCallbackImp->FileNames.Delete(index); - } + OpenCallbackImp->FileNames_WasUsed[FileNameIndex] = false; } }; STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream) { COM_TRY_BEGIN + *inStream = NULL; if (_subArchiveMode) return S_FALSE; if (Callback) { RINOK(Callback->Open_CheckBreak()); } - *inStream = NULL; - FString fullPath = _folderPrefix + us2fs(name); + FString fullPath; + if (!NFile::NName::GetFullPath(_folderPrefix, us2fs(name), fullPath)) + return S_FALSE; if (!_fileInfo.Find(fullPath)) return S_FALSE; if (_fileInfo.IsDir()) @@ -102,12 +94,14 @@ STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStre CMyComPtr inStreamTemp = inFile; if (!inFile->Open(fullPath)) return ::GetLastError(); - *inStream = inStreamTemp.Detach(); - inFile->Name = name; + + FileSizes.Add(_fileInfo.Size); + FileNames.Add(name); + inFile->FileNameIndex = FileNames_WasUsed.Add(true); inFile->OpenCallbackImp = this; inFile->OpenCallbackRef = this; - FileNames.Add(name); - TotalSize += _fileInfo.Size; + // TotalSize += _fileInfo.Size; + *inStream = inStreamTemp.Detach(); return S_OK; COM_TRY_END } diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.h b/CPP/7zip/UI/Common/ArchiveOpenCallback.h old mode 100755 new mode 100644 index afada4a6..8627de00 --- a/CPP/7zip/UI/Common/ArchiveOpenCallback.h +++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.h @@ -3,10 +3,9 @@ #ifndef __ARCHIVE_OPEN_CALLBACK_H #define __ARCHIVE_OPEN_CALLBACK_H -#include "Common/MyCom.h" -#include "Common/MyString.h" +#include "../../../Common/MyCom.h" -#include "Windows/FileFind.h" +#include "../../../Windows/FileFind.h" #ifndef _NO_CRYPTO #include "../../IPassword.h" @@ -21,7 +20,7 @@ #define INTERFACE_IOpenCallbackUI_Crypto(x) \ virtual HRESULT Open_CryptoGetTextPassword(BSTR *password) x; \ - virtual HRESULT Open_GetPasswordIfAny(UString &password) x; \ + virtual HRESULT Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) x; \ virtual bool Open_WasPasswordAsked() x; \ virtual void Open_ClearPasswordWasAskedFlag() x; \ @@ -72,8 +71,8 @@ public: { _subArchiveMode = true; _subArchiveName = name; - TotalSize = 0; - return S_OK; + // TotalSize = 0; + return S_OK; } private: @@ -81,23 +80,32 @@ private: NWindows::NFile::NFind::CFileInfo _fileInfo; bool _subArchiveMode; UString _subArchiveName; + public: UStringVector FileNames; + CBoolVector FileNames_WasUsed; + CRecordVector FileSizes; + IOpenCallbackUI *Callback; CMyComPtr ReOpenCallback; - UInt64 TotalSize; + // UInt64 TotalSize; COpenCallbackImp(): Callback(NULL) {} void Init(const FString &folderPrefix, const FString &fileName) { _folderPrefix = folderPrefix; if (!_fileInfo.Find(_folderPrefix + fileName)) - throw 1; + throw 20121118; FileNames.Clear(); + FileNames_WasUsed.Clear(); + FileSizes.Clear(); _subArchiveMode = false; - TotalSize = 0; + // TotalSize = 0; + } + bool SetSecondFileInfo(CFSTR newName) + { + return _fileInfo.Find(newName) && !_fileInfo.IsDir(); } - int FindName(const UString &name); }; #endif diff --git a/CPP/7zip/UI/Common/Bench.cpp b/CPP/7zip/UI/Common/Bench.cpp old mode 100755 new mode 100644 index 5adfcc20..1b10ee26 --- a/CPP/7zip/UI/Common/Bench.cpp +++ b/CPP/7zip/UI/Common/Bench.cpp @@ -28,6 +28,7 @@ #include "../../../../C/7zCrc.h" #include "../../../../C/Alloc.h" +#include "../../../../C/CpuArch.h" #if !defined(_7ZIP_ST) || defined(_WIN32) #include "../../../Windows/System.h" @@ -43,24 +44,38 @@ #include "../../../Common/StringToInt.h" #include "../../Common/MethodProps.h" +#include "../../Common/StreamUtils.h" #include "Bench.h" using namespace NWindows; -static const UInt64 kUncompressMinBlockSize = -#ifdef UNDER_CE -(UInt64)1 << 30; -#else -(UInt64)1 << 33; -#endif +static const UInt64 kComplexInCommands = (UInt64)1 << + #ifdef UNDER_CE + 31; + #else + 34; + #endif -static const UInt32 kCrcBlockSize = -#ifdef UNDER_CE -1 << 25; -#else -1 << 30; -#endif +static const UInt64 kComplexInSeconds = 4; + +static void SetComplexCommands(UInt32 complexInSeconds, UInt64 cpuFreq, UInt64 &complexInCommands) +{ + complexInCommands = kComplexInCommands; + const UInt64 kMinFreq = (UInt64)1000000 * 30; + const UInt64 kMaxFreq = (UInt64)1000000 * 20000; + if (cpuFreq < kMinFreq) cpuFreq = kMinFreq; + if (cpuFreq < kMaxFreq) + { + if (complexInSeconds != 0) + complexInCommands = complexInSeconds * cpuFreq; + else + complexInCommands = cpuFreq >> 2; + } +} + +static const unsigned kNumHashDictBits = 17; +static const UInt32 kFilterUnpackSize = (48 << 10); static const unsigned kOldLzmaDictBits = 30; @@ -88,6 +103,7 @@ class CBenchBuffer public: size_t BufferSize; Byte *Buffer; + CBenchBuffer(): Buffer(0) {} virtual ~CBenchBuffer() { Free(); } void Free() @@ -102,7 +118,7 @@ public: Free(); Buffer = (Byte *)::MidAlloc(bufferSize); BufferSize = bufferSize; - return (Buffer != 0); + return (Buffer != 0 || bufferSize == 0); } }; @@ -122,6 +138,13 @@ public: UInt32 len = GetVal(res, 2); return GetVal(res, 1 + len); } + + void GenerateSimpleRandom() + { + for (UInt32 i = 0; i < BufferSize; i++) + Buffer[i] = (Byte)RG->GetRnd(); + } + void Generate(unsigned dictBits) { UInt32 pos = 0; @@ -202,9 +225,16 @@ class CBenchmarkOutStream: // bool _overflow; public: UInt32 Pos; + bool RealCopy; + bool CalcCrc; + UInt32 Crc; + // CBenchmarkOutStream(): _overflow(false) {} - void Init() + void Init(bool realCopy, bool calcCrc) { + Crc = CRC_INIT_VAL; + RealCopy = realCopy; + CalcCrc = calcCrc; // _overflow = false; Pos = 0; } @@ -217,7 +247,10 @@ STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *p size_t curSize = BufferSize - Pos; if (curSize > size) curSize = size; - memcpy(Buffer + Pos, data, curSize); + if (RealCopy) + memcpy(Buffer + Pos, data, curSize); + if (CalcCrc) + Crc = CrcUpdate(Crc, data, curSize); Pos += (UInt32)curSize; if(processedSize != NULL) *processedSize = (UInt32)curSize; @@ -234,15 +267,19 @@ class CCrcOutStream: public CMyUnknownImp { public: + bool CalcCrc; UInt32 Crc; MY_UNKNOWN_IMP + + CCrcOutStream(): CalcCrc(true) {}; void Init() { Crc = CRC_INIT_VAL; } STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { - Crc = CrcUpdate(Crc, data, size); + if (CalcCrc) + Crc = CrcUpdate(Crc, data, size); if (processedSize != NULL) *processedSize = size; return S_OK; @@ -369,25 +406,16 @@ public: } }; -class CBenchProgressInfo: - public ICompressProgressInfo, - public CMyUnknownImp +struct CBenchInfoCalc { -public: - CBenchProgressStatus *Status; CBenchInfo BenchInfo; CUserTime UserTime; - HRESULT Res; - IBenchCallback *Callback; - CBenchProgressInfo(): Callback(0) {} void SetStartTime(); void SetFinishTime(CBenchInfo &dest); - MY_UNKNOWN_IMP - STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; -void CBenchProgressInfo::SetStartTime() +void CBenchInfoCalc::SetStartTime() { BenchInfo.GlobalFreq = GetFreq(); BenchInfo.UserFreq = GetUserFreq(); @@ -396,13 +424,28 @@ void CBenchProgressInfo::SetStartTime() UserTime.Init(); } -void CBenchProgressInfo::SetFinishTime(CBenchInfo &dest) +void CBenchInfoCalc::SetFinishTime(CBenchInfo &dest) { dest = BenchInfo; dest.GlobalTime = ::GetTimeCount() - BenchInfo.GlobalTime; dest.UserTime = UserTime.GetUserTime(); } +class CBenchProgressInfo: + public ICompressProgressInfo, + public CMyUnknownImp, + public CBenchInfoCalc +{ +public: + CBenchProgressStatus *Status; + HRESULT Res; + IBenchCallback *Callback; + + CBenchProgressInfo(): Callback(0) {} + MY_UNKNOWN_IMP + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); +}; + STDMETHODIMP CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { HRESULT res = Status->GetResult(); @@ -414,8 +457,8 @@ STDMETHODIMP CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 SetFinishTime(info); if (Status->EncodeMode) { - info.UnpackSize = *inSize; - info.PackSize = *outSize; + info.UnpackSize = BenchInfo.UnpackSize + *inSize; + info.PackSize = BenchInfo.PackSize + *outSize; res = Callback->SetEncodeResult(info, false); } else @@ -488,6 +531,11 @@ static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq) return value * freq / elTime; } +UInt64 CBenchInfo::GetSpeed(UInt64 numCommands) const +{ + return MyMultDiv64(numCommands, GlobalTime, GlobalFreq); +} + struct CBenchProps { bool LzmaRatingMode; @@ -499,19 +547,25 @@ struct CBenchProps CBenchProps(): LzmaRatingMode(false) {} void SetLzmaCompexity(); + UInt64 GeComprCommands(UInt64 unpackSize) + { + return unpackSize * EncComplex; + } + UInt64 GeDecomprCommands(UInt64 packSize, UInt64 unpackSize) { return (packSize * DecComplexCompr + unpackSize * DecComplexUnc); } UInt64 GetCompressRating(UInt32 dictSize, UInt64 elapsedTime, UInt64 freq, UInt64 size); - UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations); + UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt64 numIterations); }; void CBenchProps::SetLzmaCompexity() { + EncComplex = 1200; DecComplexUnc = 4; - DecComplexCompr = 200; + DecComplexCompr = 190; LzmaRatingMode = true; } @@ -529,7 +583,7 @@ UInt64 CBenchProps::GetCompressRating(UInt32 dictSize, UInt64 elapsedTime, UInt6 return MyMultDiv64(numCommands, elapsedTime, freq); } -UInt64 CBenchProps::GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations) +UInt64 CBenchProps::GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt64 numIterations) { UInt64 numCommands = (inSize * DecComplexCompr + outSize * DecComplexUnc) * numIterations; return MyMultDiv64(numCommands, elapsedTime, freq); @@ -542,7 +596,7 @@ UInt64 GetCompressRating(UInt32 dictSize, UInt64 elapsedTime, UInt64 freq, UInt6 return props.GetCompressRating(dictSize, elapsedTime, freq, size); } -UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations) +UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt64 numIterations) { CBenchProps props; props.SetLzmaCompexity(); @@ -557,14 +611,21 @@ struct CEncoderInfo NWindows::CThread thread[2]; UInt32 NumDecoderSubThreads; #endif - CMyComPtr encoder; + CMyComPtr _encoder; + CMyComPtr _encoderFilter; CBenchProgressInfo *progressInfoSpec[2]; CMyComPtr progressInfo[2]; - UInt32 NumIterations; + UInt64 NumIterations; #ifdef USE_ALLOCA size_t AllocaSize; #endif + Byte _key[32]; + Byte _iv[16]; + Byte _psw[16]; + bool CheckCrc_Enc; + bool CheckCrc_Dec; + struct CDecoderInfo { CEncoderInfo *Encoder; @@ -576,7 +637,9 @@ struct CEncoderInfo }; CDecoderInfo decodersInfo[2]; - CMyComPtr decoders[2]; + CMyComPtr _decoders[2]; + CMyComPtr _decoderFilter; + HRESULT Results[2]; CBenchmarkOutStream *outStreamSpec; CMyComPtr outStream; @@ -586,8 +649,14 @@ struct CEncoderInfo UInt32 kBufferSize; UInt32 compressedSize; CBenchRandomGenerator rg; + CBenchBuffer rgCopy; // it must be 16-byte aligned !!! CBenchmarkOutStream *propStreamSpec; CMyComPtr propStream; + + // for decode + COneMethodInfo _method; + UInt32 _uncompressedDataSize; + HRESULT Init( const COneMethodInfo &method, UInt32 uncompressedDataSize, @@ -596,20 +665,30 @@ struct CEncoderInfo HRESULT Encode(); HRESULT Decode(UInt32 decoderIndex); - CEncoderInfo(): outStreamSpec(0), callback(0), printCallback(0), propStreamSpec(0) {} + CEncoderInfo(): + CheckCrc_Enc(true), + CheckCrc_Dec(true), + outStreamSpec(0), callback(0), printCallback(0), propStreamSpec(0) {} #ifndef _7ZIP_ST static THREAD_FUNC_DECL EncodeThreadFunction(void *param) { + HRESULT res; CEncoderInfo *encoder = (CEncoderInfo *)param; - #ifdef USE_ALLOCA - alloca(encoder->AllocaSize); - #endif - HRESULT res = encoder->Encode(); - encoder->Results[0] = res; + try + { + #ifdef USE_ALLOCA + alloca(encoder->AllocaSize); + #endif + res = encoder->Encode(); + encoder->Results[0] = res; + } + catch(...) + { + res = E_FAIL; + } if (res != S_OK) encoder->progressInfoSpec[0]->Status->SetResult(res); - return 0; } static THREAD_FUNC_DECL DecodeThreadFunction(void *param) @@ -656,12 +735,24 @@ HRESULT CEncoderInfo::Init( { rg.Set(rgLoc); kBufferSize = uncompressedDataSize; - UInt32 kCompressedBufferSize = (kBufferSize - kBufferSize / 4) + kCompressedAdditionalSize; + UInt32 kCompressedBufferSize = + kBufferSize + kCompressedAdditionalSize; + // (kBufferSize - kBufferSize / 4) + kCompressedAdditionalSize; if (!rg.Alloc(kBufferSize)) return E_OUTOFMEMORY; - rg.Generate(generateDictBits); + if (generateDictBits == 0) + rg.GenerateSimpleRandom(); + else + rg.Generate(generateDictBits); crc = CrcCalc(rg.Buffer, rg.BufferSize); + if (_encoderFilter) + { + if (!rgCopy.Alloc(rg.BufferSize)) + return E_OUTOFMEMORY; + } + + outStreamSpec = new CBenchmarkOutStream; if (!outStreamSpec->Alloc(kCompressedBufferSize)) return E_OUTOFMEMORY; @@ -676,12 +767,17 @@ HRESULT CEncoderInfo::Init( } if (!propStreamSpec->Alloc(kMaxLzmaPropSize)) return E_OUTOFMEMORY; - propStreamSpec->Init(); + propStreamSpec->Init(true, false); + CMyComPtr coder; + if (_encoderFilter) + coder = _encoderFilter; + else + coder = _encoder; { CMyComPtr scp; - encoder.QueryInterface(IID_ICompressSetCoderProperties, &scp); + coder.QueryInterface(IID_ICompressSetCoderProperties, &scp); if (scp) { UInt64 reduceSize = uncompressedDataSize; @@ -690,29 +786,111 @@ HRESULT CEncoderInfo::Init( else { if (method.AreThereNonOptionalProps()) - return E_FAIL; + return E_INVALIDARG; } CMyComPtr writeCoderProps; - encoder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProps); + coder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProps); if (writeCoderProps) { RINOK(writeCoderProps->WriteCoderProperties(propStream)); } + + { + CMyComPtr sp; + coder.QueryInterface(IID_ICryptoSetPassword, &sp); + if (sp) + { + RINOK(sp->CryptoSetPassword(_psw, sizeof(_psw))); + + // we must call encoding one time to calculate password key for key cache. + // it must be after WriteCoderProperties! + CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; + CMyComPtr inStream = inStreamSpec; + Byte temp[16]; + memset(temp, 0, sizeof(temp)); + inStreamSpec->Init(temp, sizeof(temp)); + + CCrcOutStream *outStreamSpec = new CCrcOutStream; + CMyComPtr outStream = outStreamSpec; + outStreamSpec->Init(); + + if (_encoderFilter) + { + _encoderFilter->Init(); + _encoderFilter->Filter(temp, sizeof(temp)); + } + else + { + RINOK(_encoder->Code(inStream, outStream, 0, 0, NULL)); + } + } + } + } return S_OK; } HRESULT CEncoderInfo::Encode() { + CBenchInfo &bi = progressInfoSpec[0]->BenchInfo; + bi.UnpackSize = 0; + bi.PackSize = 0; + CMyComPtr cp; + CMyComPtr coder; + if (_encoderFilter) + coder = _encoderFilter; + else + coder = _encoder; + coder.QueryInterface(IID_ICryptoProperties, &cp); CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; CMyComPtr inStream = inStreamSpec; - inStreamSpec->Init(rg.Buffer, rg.BufferSize); - outStreamSpec->Init(); + UInt64 prev = 0; + + UInt32 crcPrev = 0; + + if (cp) + { + RINOK(cp->SetKey(_key, sizeof(_key))); + RINOK(cp->SetInitVector(_iv, sizeof(_iv))); + } + + for (UInt64 i = 0; i < NumIterations; i++) + { + if (printCallback && bi.UnpackSize - prev > (1 << 20)) + { + RINOK(printCallback->CheckBreak()); + prev = bi.UnpackSize; + } + + bool isLast = (i == NumIterations - 1); + bool calcCrc = ((isLast || (i & 0x7F) == 0 || CheckCrc_Enc) && NumIterations != 1); + outStreamSpec->Init(isLast, calcCrc); + + if (_encoderFilter) + { + memcpy(rgCopy.Buffer, rg.Buffer, rg.BufferSize); + _encoderFilter->Init(); + _encoderFilter->Filter(rgCopy.Buffer, (UInt32)rg.BufferSize); + RINOK(WriteStream(outStream, rgCopy.Buffer, rg.BufferSize)); + } + else + { + inStreamSpec->Init(rg.Buffer, rg.BufferSize); + RINOK(_encoder->Code(inStream, outStream, 0, 0, progressInfo[0])); + } - RINOK(encoder->Code(inStream, outStream, 0, 0, progressInfo[0])); - compressedSize = outStreamSpec->Pos; - encoder.Release(); + UInt32 crcNew = CRC_GET_DIGEST(outStreamSpec->Crc); + if (i == 0) + crcPrev = crcNew; + else if (calcCrc && crcPrev != crcNew) + return E_FAIL; + compressedSize = outStreamSpec->Pos; + bi.UnpackSize += rg.BufferSize; + bi.PackSize += compressedSize; + } + _encoder.Release(); + _encoderFilter.Release(); return S_OK; } @@ -720,10 +898,19 @@ HRESULT CEncoderInfo::Decode(UInt32 decoderIndex) { CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; CMyComPtr inStream = inStreamSpec; - CMyComPtr &decoder = decoders[decoderIndex]; + CMyComPtr &decoder = _decoders[decoderIndex]; + CMyComPtr coder; + if (_decoderFilter) + { + if (decoderIndex != 0) + return E_FAIL; + coder = _decoderFilter; + } + else + coder = decoder; CMyComPtr setDecProps; - decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecProps); + coder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecProps); if (!setDecProps && propStreamSpec->Pos != 0) return E_FAIL; @@ -737,7 +924,7 @@ HRESULT CEncoderInfo::Decode(UInt32 decoderIndex) #ifndef _7ZIP_ST { CMyComPtr setCoderMt; - decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); + coder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(NumDecoderSubThreads)); @@ -745,27 +932,72 @@ HRESULT CEncoderInfo::Decode(UInt32 decoderIndex) } #endif - for (UInt32 j = 0; j < NumIterations; j++) + CMyComPtr scp; + coder.QueryInterface(IID_ICompressSetCoderProperties, &scp); + if (scp) + { + UInt64 reduceSize = _uncompressedDataSize; + RINOK(_method.SetCoderProps(scp, &reduceSize)); + } + + CMyComPtr cp; + coder.QueryInterface(IID_ICryptoProperties, &cp); + + if (setDecProps) + { + RINOK(setDecProps->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos)); + } + { - if (printCallback) + CMyComPtr sp; + coder.QueryInterface(IID_ICryptoSetPassword, &sp); + if (sp) + { + RINOK(sp->CryptoSetPassword(_psw, sizeof(_psw))); + } + } + + UInt64 prev = 0; + + if (cp) + { + RINOK(cp->SetKey(_key, sizeof(_key))); + RINOK(cp->SetInitVector(_iv, sizeof(_iv))); + } + + for (UInt64 i = 0; i < NumIterations; i++) + { + if (printCallback && pi->BenchInfo.UnpackSize - prev > (1 << 20)) { RINOK(printCallback->CheckBreak()); + prev = pi->BenchInfo.UnpackSize; } + inStreamSpec->Init(outStreamSpec->Buffer, compressedSize); crcOutStreamSpec->Init(); - if (setDecProps) + UInt64 outSize = kBufferSize; + crcOutStreamSpec->CalcCrc = ((i & 0x7F) == 0 || CheckCrc_Dec); + if (_decoderFilter) + { + if (compressedSize > rgCopy.BufferSize) + return E_FAIL; + memcpy(rgCopy.Buffer, outStreamSpec->Buffer, compressedSize); + _decoderFilter->Init(); + _decoderFilter->Filter(rgCopy.Buffer, compressedSize); + RINOK(WriteStream(crcOutStream, rgCopy.Buffer, rg.BufferSize)); + } + else { - RINOK(setDecProps->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos)); + RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex])); } - UInt64 outSize = kBufferSize; - RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex])); - if (CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc) + if (crcOutStreamSpec->CalcCrc && CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc) return S_FALSE; pi->BenchInfo.UnpackSize += kBufferSize; pi->BenchInfo.PackSize += compressedSize; } decoder.Release(); + _decoderFilter.Release(); return S_OK; } @@ -778,8 +1010,17 @@ struct CBenchEncoders ~CBenchEncoders() { delete []encoders; } }; +static UInt64 GetNumIterations(UInt64 numCommands, UInt64 complexInCommands) +{ + if (numCommands < (1 << 4)) + numCommands = (1 << 4); + UInt64 res = complexInCommands / numCommands; + return (res == 0 ? 1 : res); +} + static HRESULT MethodBench( DECL_EXTERNAL_CODECS_LOC_VARS + UInt64 complexInCommands, bool oldLzmaBenchMode, UInt32 numThreads, const COneMethodInfo &method2, @@ -819,9 +1060,6 @@ static HRESULT MethodBench( } #endif - if (numThreads < 1 || numEncoderThreads > kNumThreadsMax) - return E_INVALIDARG; - CBenchEncoders encodersSpec(numEncoderThreads); CEncoderInfo *encoders = encodersSpec.encoders; @@ -832,13 +1070,27 @@ static HRESULT MethodBench( encoder.callback = (i == 0) ? callback : 0; encoder.printCallback = printCallback; - RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodId, encoder.encoder, true)); - if (!encoder.encoder) + CMyComPtr coder2; + RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodId, + encoder._encoderFilter, encoder._encoder, coder2, true, false)); + if (!encoder._encoder && !encoder._encoderFilter) return E_NOTIMPL; + // encoder._encoderFilter.Release(); // we can disable filter to check the speed of FilterCoder. + + encoder.CheckCrc_Enc = (benchProps->EncComplex) > 30 ; + encoder.CheckCrc_Dec = (benchProps->DecComplexCompr + benchProps->DecComplexUnc) > 30 ; + + memset(encoder._iv, 0, sizeof(encoder._iv)); + memset(encoder._key, 0, sizeof(encoder._key)); + memset(encoder._psw, 0, sizeof(encoder._psw)); + for (UInt32 j = 0; j < numSubDecoderThreads; j++) { - RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodId, encoder.decoders[j], false)); - if (!encoder.decoders[j]) + CMyComPtr coder2de; + CMyComPtr &decoder = encoder._decoders[j]; + RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodId, + encoder._decoderFilter, decoder, coder2de, false, false)); + if (!encoder._decoderFilter && !decoder) return E_NOTIMPL; } } @@ -847,6 +1099,9 @@ static HRESULT MethodBench( rg.Init(); for (i = 0; i < numEncoderThreads; i++) { + CEncoderInfo &encoder = encoders[i]; + encoder._method = method; + encoder._uncompressedDataSize = uncompressedDataSize; RINOK(encoders[i].Init(method, uncompressedDataSize, generateDictBits, &rg)); } @@ -857,10 +1112,14 @@ static HRESULT MethodBench( for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; + encoder.NumIterations = GetNumIterations(benchProps->GeComprCommands(uncompressedDataSize), complexInCommands); + for (int j = 0; j < 2; j++) { - encoder.progressInfo[j] = encoder.progressInfoSpec[j] = new CBenchProgressInfo; - encoder.progressInfoSpec[j]->Status = &status; + CBenchProgressInfo *spec = new CBenchProgressInfo; + encoder.progressInfoSpec[j] = spec; + encoder.progressInfo[j] = spec; + spec->Status = &status; } if (i == 0) { @@ -897,7 +1156,7 @@ static HRESULT MethodBench( encoders[0].progressInfoSpec[0]->SetFinishTime(info); info.UnpackSize = 0; info.PackSize = 0; - info.NumIterations = 1; // progressInfoSpec->NumIterations; + info.NumIterations = encoders[0].NumIterations; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; @@ -917,8 +1176,7 @@ static HRESULT MethodBench( if (i == 0) { - encoder.NumIterations = (UInt32)(1 + kUncompressMinBlockSize / - benchProps->GeDecomprCommands(encoder.compressedSize, encoder.kBufferSize)); + encoder.NumIterations = GetNumIterations(benchProps->GeDecomprCommands(encoder.compressedSize, encoder.kBufferSize), complexInCommands); CBenchProgressInfo *bpi = encoder.progressInfoSpec[0]; bpi->Callback = callback; bpi->BenchInfo.NumIterations = numDecoderThreads; @@ -1018,23 +1276,123 @@ UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary) GetLZMAUsage((numThreads > 1), dictionary) + (2 << 20)) * numBigThreads; } -static bool CrcBig(const void *data, UInt32 size, UInt32 numCycles, UInt32 crcBase) +static HRESULT CrcBig(const void *data, UInt32 size, UInt64 numIterations, + const UInt32 *checkSum, IHasher *hf, + IBenchPrintCallback *callback) { - for (UInt32 i = 0; i < numCycles; i++) - if (CrcCalc(data, size) != crcBase) - return false; - return true; + Byte hash[64]; + UInt64 i; + for (i = 0; i < sizeof(hash); i++) + hash[i] = 0; + for (i = 0; i < numIterations; i++) + { + if (callback && (i & 0xFF) == 0) + { + RINOK(callback->CheckBreak()); + } + hf->Init(); + hf->Update(data, size); + hf->Final(hash); + UInt32 hashSize = hf->GetDigestSize(); + if (hashSize > sizeof(hash)) + return S_FALSE; + UInt32 sum = 0; + for (UInt32 j = 0; j < hashSize; j += 4) + sum ^= GetUi32(hash + j); + if (checkSum && sum != *checkSum) + { + // printf(" %08X ", sum); + return S_FALSE; + } + } + return S_OK; +} + +UInt32 g_BenchCpuFreqTemp = 1; + +#define YY1 sum += val; sum ^= val; +#define YY3 YY1 YY1 YY1 YY1 +#define YY5 YY3 YY3 YY3 YY3 +#define YY7 YY5 YY5 YY5 YY5 +static const UInt32 kNumFreqCommands = 128; + +static UInt32 CountCpuFreq(UInt32 num, UInt32 val) +{ + UInt32 sum = 0; + for (UInt32 i = 0; i < num; i++) + { + YY7 + } + return sum; } #ifndef _7ZIP_ST + +struct CFreqInfo +{ + NWindows::CThread Thread; + IBenchPrintCallback *Callback; + HRESULT CallbackRes; + UInt32 ValRes; + UInt32 Size; + UInt64 NumIterations; + + void Wait() + { + Thread.Wait(); + Thread.Close(); + } +}; + +static THREAD_FUNC_DECL FreqThreadFunction(void *param) +{ + CFreqInfo *p = (CFreqInfo *)param; + + UInt32 sum = g_BenchCpuFreqTemp; + for (UInt64 k = p->NumIterations; k > 0; k--) + { + p->CallbackRes = p->Callback->CheckBreak(); + if (p->CallbackRes != S_OK) + return 0; + sum = CountCpuFreq(p->Size, sum); + } + p->ValRes = sum; + return 0; +} + +struct CFreqThreads +{ + CFreqInfo *Items; + UInt32 NumThreads; + + CFreqThreads(): Items(0), NumThreads(0) {} + void WaitAll() + { + for (UInt32 i = 0; i < NumThreads; i++) + Items[i].Wait(); + NumThreads = 0; + } + ~CFreqThreads() + { + WaitAll(); + delete []Items; + } +}; + struct CCrcInfo { NWindows::CThread Thread; + IBenchPrintCallback *Callback; + HRESULT CallbackRes; + const Byte *Data; UInt32 Size; - UInt32 NumCycles; - UInt32 Crc; - bool Res; + UInt64 NumIterations; + bool CheckSumDefined; + UInt32 CheckSum; + CMyComPtr Hasher; + HRESULT Res; + void Wait() { Thread.Wait(); @@ -1045,14 +1403,17 @@ struct CCrcInfo static THREAD_FUNC_DECL CrcThreadFunction(void *param) { CCrcInfo *p = (CCrcInfo *)param; - p->Res = CrcBig(p->Data, p->Size, p->NumCycles, p->Crc); + p->Res = CrcBig(p->Data, p->Size, p->NumIterations, + p->CheckSumDefined ? &p->CheckSum : NULL, p->Hasher, + p->Callback); return 0; } struct CCrcThreads { - UInt32 NumThreads; CCrcInfo *Items; + UInt32 NumThreads; + CCrcThreads(): Items(0), NumThreads(0) {} void WaitAll() { @@ -1066,6 +1427,7 @@ struct CCrcThreads delete []Items; } }; + #endif static UInt32 CrcCalc1(const Byte *buf, UInt32 size) @@ -1112,70 +1474,9 @@ bool CrcInternalTest() return true; } -static 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; -} - struct CBenchMethod { - unsigned dictBits; + unsigned DictBits; UInt32 EncComplex; UInt32 DecComplexCompr; UInt32 DecComplexUnc; @@ -1184,21 +1485,39 @@ struct CBenchMethod static const CBenchMethod g_Bench[] = { - { 17, 340, 155, 20, "LZMA:x1" }, - { 24, 1182, 155, 20, "LZMA:x5:mt1" }, - { 24, 1182, 155, 20, "LZMA:x5:mt2" }, - { 16, 124, 47, 14, "Deflate:x1" }, - { 16, 376, 47, 14, "Deflate:x5" }, - { 16, 1084, 47, 14, "Deflate:x7" }, - { 17, 420, 47, 14, "Deflate64:x5" }, - { 15, 590, 69, 70, "BZip2:x1" }, - { 19, 792, 119, 119, "BZip2:x5" }, - #ifndef UNDER_CE - { 19, 792, 119, 119, "BZip2:x5:mt2" }, - #endif - { 19, 2500, 118, 118, "BZip2:x7" }, - { 18, 1010, 0, 1155, "PPMD:x1" }, - { 22, 1650, 0, 1830, "PPMD:x5" } + { 17, 357, 145, 20, "LZMA:x1" }, + { 24, 1220, 145, 20, "LZMA:x5:mt1" }, + { 24, 1220, 145, 20, "LZMA:x5:mt2" }, + { 16, 124, 40, 14, "Deflate:x1" }, + { 16, 376, 40, 14, "Deflate:x5" }, + { 16, 1082, 40, 14, "Deflate:x7" }, + { 17, 422, 40, 14, "Deflate64:x5" }, + { 15, 590, 69, 69, "BZip2:x1" }, + { 19, 815, 122, 122, "BZip2:x5" }, + { 19, 815, 122, 122, "BZip2:x5:mt2" }, + { 19, 2530, 122, 122, "BZip2:x7" }, + { 18, 1010, 0, 1150, "PPMD:x1" }, + { 22, 1655, 0, 1830, "PPMD:x5" }, + { 0, 6, 0, 6, "Delta:4" }, + { 0, 4, 0, 4, "BCJ" }, + { 0, 24, 0, 24, "AES256CBC:1" }, + { 0, 8, 0, 2, "AES256CBC:2" } +}; + +struct CBenchHash +{ + UInt32 Complex; + UInt32 CheckSum; + const char *Name; +}; + +static const CBenchHash g_Hash[] = +{ + { 558, 0x8F8FEDAB, "CRC32:4" }, + { 339, 0x8F8FEDAB, "CRC32:8" }, + { 512, 0xDF1C17CC, "CRC64" }, + { 11900, 0x2D79FF2E, "SHA256" }, + { 5230, 0x4C25132B, "SHA1" } }; struct CTotalBenchRes @@ -1208,31 +1527,22 @@ struct CTotalBenchRes 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) + void SetSum(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; + Rating = (r1.Rating + r2.Rating); + Usage = (r1.Usage + r2.Usage); + RPU = (r1.RPU + r2.RPU); + NumIterations = (r1.NumIterations + r2.NumIterations); } }; -static void PrintNumber(IBenchPrintCallback &f, UInt64 value, int size, bool withSpace = true) +static void PrintNumber(IBenchPrintCallback &f, UInt64 value, int size) { char s[128]; int startPos = (int)sizeof(s) - 32; memset(s, ' ', startPos); ConvertUInt64ToString(value, s + startPos); - if (withSpace) + // if (withSpace) { startPos--; size++; @@ -1247,45 +1557,106 @@ static void PrintNumber(IBenchPrintCallback &f, UInt64 value, int size, bool wit f.Print(s + startPos); } -static void PrintRating(IBenchPrintCallback &f, UInt64 rating) -{ - PrintNumber(f, rating / 1000000, 6); +static const int kFieldSize_Name = 12; +static const int kFieldSize_SmallName = 4; +static const int kFieldSize_Speed = 9; +static const int kFieldSize_Usage = 5; +static const int kFieldSize_RU = 6; +static const int kFieldSize_Rating = 6; +static const int kFieldSize_EU = 5; +static const int kFieldSize_Effec = 5; + +static const int kFieldSize_TotalSize = 4 + kFieldSize_Speed + kFieldSize_Usage + kFieldSize_RU + kFieldSize_Rating; +static const int kFieldSize_EUAndEffec = 2 + kFieldSize_EU + kFieldSize_Effec; + + +static void PrintRating(IBenchPrintCallback &f, UInt64 rating, int size) +{ + PrintNumber(f, (rating + 500000) / 1000000, size); +} + + +static void PrintPercents(IBenchPrintCallback &f, UInt64 val, UInt64 divider, int size) +{ + PrintNumber(f, (val * 100 + divider / 2) / divider, size); } -static void PrintResults(IBenchPrintCallback &f, UInt64 usage, UInt64 rpu, UInt64 rating) +static void PrintChars(IBenchPrintCallback &f, char c, int size) { - PrintNumber(f, (usage + 5000) / 10000, 5); - PrintRating(f, rpu); - PrintRating(f, rating); + char s[256]; + memset(s, (Byte)c, size); + s[size] = 0; + f.Print(s); +} + +static void PrintSpaces(IBenchPrintCallback &f, int size) +{ + PrintChars(f, ' ', size); +} + +static void PrintResults(IBenchPrintCallback &f, UInt64 usage, UInt64 rpu, UInt64 rating, bool showFreq, UInt64 cpuFreq) +{ + PrintNumber(f, (usage + 5000) / 10000, kFieldSize_Usage); + PrintRating(f, rpu, kFieldSize_RU); + PrintRating(f, rating, kFieldSize_Rating); + if (showFreq) + { + if (cpuFreq == 0) + PrintSpaces(f, kFieldSize_EUAndEffec); + else + { + UInt64 ddd = cpuFreq * usage / 100; + if (ddd == 0) + ddd = 1; + PrintPercents(f, (rating * 10000), ddd, kFieldSize_EU); + PrintPercents(f, rating, cpuFreq, kFieldSize_Effec); + } + } } -static void PrintResults(IBenchPrintCallback &f, const CBenchInfo &info, UInt64 rating, CTotalBenchRes &res) +static void PrintResults(IBenchPrintCallback *f, const CBenchInfo &info, UInt64 rating, bool showFreq, UInt64 cpuFreq, CTotalBenchRes *res) { - UInt64 speed = MyMultDiv64(info.UnpackSize, info.GlobalTime, info.GlobalFreq); - PrintNumber(f, speed / 1024, 7); + UInt64 speed = info.GetSpeed(info.UnpackSize * info.NumIterations); + if (f) + { + if (speed != 0) + PrintNumber(*f, speed / 1024, kFieldSize_Speed); + else + PrintSpaces(*f, 1 + kFieldSize_Speed); + } UInt64 usage = info.GetUsage(); UInt64 rpu = info.GetRatingPerUsage(rating); - PrintResults(f, usage, rpu, rating); - res.NumIterations++; - res.RPU += rpu; - res.Rating += rating; - res.Usage += usage; + if (f) + { + PrintResults(*f, usage, rpu, rating, showFreq, cpuFreq); + } + + if (res) + { + res->NumIterations++; + res->RPU += rpu; + res->Rating += rating; + res->Usage += usage; + } } -static void PrintTotals(IBenchPrintCallback &f, const CTotalBenchRes &res) +static void PrintTotals(IBenchPrintCallback &f, bool showFreq, UInt64 cpuFreq, const CTotalBenchRes &res) { - f.Print(" "); - PrintResults(f, res.Usage, res.RPU, res.Rating); + PrintSpaces(f, 1 + kFieldSize_Speed); + UInt64 numIterations = res.NumIterations; + if (numIterations == 0) + numIterations = 1; + PrintResults(f, res.Usage / numIterations, res.RPU / numIterations, res.Rating / numIterations, showFreq, cpuFreq); } static void PrintRequirements(IBenchPrintCallback &f, const char *sizeString, UInt64 size, const char *threadsString, UInt32 numThreads) { f.Print("RAM "); f.Print(sizeString); - PrintNumber(f, (size >> 20), 5, true); + PrintNumber(f, (size >> 20), 5); f.Print(" MB, # "); f.Print(threadsString); - PrintNumber(f, numThreads, 3, true); + PrintNumber(f, numThreads, 3); f.NewLine(); } @@ -1297,41 +1668,61 @@ struct CBenchCallbackToPrint: public IBenchCallback IBenchPrintCallback *_file; UInt32 DictSize; + bool Use2Columns; + int NameFieldSize; + + bool ShowFreq; + UInt64 CpuFreq; + + CBenchCallbackToPrint(): Use2Columns(false), NameFieldSize(0), ShowFreq(false), CpuFreq(0) {} + void Init() { EncodeRes.Init(); DecodeRes.Init(); } - void Normalize() { EncodeRes.Normalize(); DecodeRes.Normalize(); } + void Print(const char *s); + void NewLine(); + + HRESULT SetFreq(bool showFreq, UInt64 cpuFreq); HRESULT SetEncodeResult(const CBenchInfo &info, bool final); HRESULT SetDecodeResult(const CBenchInfo &info, bool final); - void Print(const char *string); - void NewLine(); - void PrintLeftAligned(const char *string, unsigned size); }; +HRESULT CBenchCallbackToPrint::SetFreq(bool showFreq, UInt64 cpuFreq) +{ + ShowFreq = showFreq; + CpuFreq = cpuFreq; + return S_OK; +} + HRESULT CBenchCallbackToPrint::SetEncodeResult(const CBenchInfo &info, bool final) { RINOK(_file->CheckBreak()); if (final) { - UInt64 rating = BenchProps.GetCompressRating(DictSize, info.GlobalTime, info.GlobalFreq, info.UnpackSize); - PrintResults(*_file, info, rating, EncodeRes); + UInt64 rating = BenchProps.GetCompressRating(DictSize, info.GlobalTime, info.GlobalFreq, info.UnpackSize * info.NumIterations); + PrintResults(_file, info, rating, ShowFreq, CpuFreq, &EncodeRes); } return S_OK; } static const char *kSep = " | "; - HRESULT CBenchCallbackToPrint::SetDecodeResult(const CBenchInfo &info, bool final) { RINOK(_file->CheckBreak()); if (final) { UInt64 rating = BenchProps.GetDecompressRating(info.GlobalTime, info.GlobalFreq, info.UnpackSize, info.PackSize, info.NumIterations); - _file->Print(kSep); + if (Use2Columns) + _file->Print(kSep); + else + { + _file->NewLine(); + PrintSpaces(*_file, NameFieldSize); + } CBenchInfo info2 = info; info2.UnpackSize *= info2.NumIterations; info2.PackSize *= info2.NumIterations; info2.NumIterations = 1; - PrintResults(*_file, info2, rating, DecodeRes); + PrintResults(_file, info2, rating, ShowFreq, CpuFreq, &DecodeRes); } return S_OK; } @@ -1346,22 +1737,31 @@ void CBenchCallbackToPrint::NewLine() _file->NewLine(); } -void CBenchCallbackToPrint::PrintLeftAligned(const char *s, unsigned size) +void PrintLeft(IBenchPrintCallback &f, const char *s, unsigned size) +{ + f.Print(s); + int numSpaces = size - MyStringLen(s); + if (numSpaces > 0) + PrintSpaces(f, numSpaces); +} + +void PrintRight(IBenchPrintCallback &f, const char *s, unsigned size) { - AString s2 = s; - for (unsigned len = (unsigned)strlen(s); len < size; len++) - s2 += ' '; - Print(s2); + int numSpaces = size - MyStringLen(s); + if (numSpaces > 0) + PrintSpaces(f, numSpaces); + f.Print(s); } static HRESULT TotalBench( - DECL_EXTERNAL_CODECS_LOC_VARS - UInt32 numThreads, UInt32 unpackSize, IBenchPrintCallback *printCallback, CBenchCallbackToPrint *callback) + DECL_EXTERNAL_CODECS_LOC_VARS + UInt64 complexInCommands, + UInt32 numThreads, bool forceUnpackSize, UInt32 unpackSize, IBenchPrintCallback *printCallback, CBenchCallbackToPrint *callback) { - for (unsigned i = 0; i < sizeof(g_Bench) / sizeof(g_Bench[0]); i++) + for (unsigned i = 0; i < ARRAY_SIZE(g_Bench); i++) { CBenchMethod bench = g_Bench[i]; - callback->PrintLeftAligned(bench.Name, 12); + PrintLeft(*callback->_file, bench.Name, kFieldSize_Name); callback->BenchProps.DecComplexUnc = bench.DecComplexUnc; callback->BenchProps.DecComplexCompr = bench.DecComplexCompr; callback->BenchProps.EncComplex = bench.EncComplex; @@ -1370,19 +1770,294 @@ static HRESULT TotalBench( propVariant = bench.Name; RINOK(method.ParseMethodFromPROPVARIANT(L"", propVariant)); + UInt32 unpackSize2 = unpackSize; + if (!forceUnpackSize && bench.DictBits == 0) + unpackSize2 = kFilterUnpackSize; + HRESULT res = MethodBench( EXTERNAL_CODECS_LOC_VARS - false, numThreads, method, unpackSize, bench.dictBits, + complexInCommands, + false, numThreads, method, unpackSize2, bench.DictBits, printCallback, callback, &callback->BenchProps); if (res == E_NOTIMPL) - callback->Print(" ---"); + { + // callback->Print(" ---"); + // we need additional empty line as line for decompression results + if (!callback->Use2Columns) + callback->NewLine(); + } + else + { + RINOK(res); + } + callback->NewLine(); + } + return S_OK; +} + + +static HRESULT FreqBench( + UInt64 complexInCommands, + UInt32 numThreads, + IBenchPrintCallback *_file, + bool showFreq, + UInt64 &cpuFreq, + UInt32 &res) +{ + res = 0; + cpuFreq = 0; + + UInt32 bufferSize = 1 << 20; + UInt32 complexity = kNumFreqCommands; + if (numThreads == 0) + numThreads = 1; + + #ifdef _7ZIP_ST + numThreads = 1; + #endif + + UInt32 bsize = (bufferSize == 0 ? 1 : bufferSize); + UInt64 numIterations = complexInCommands / complexity / bsize; + if (numIterations == 0) + numIterations = 1; + + CBenchInfoCalc progressInfoSpec; + + #ifndef _7ZIP_ST + CFreqThreads threads; + if (numThreads > 1) + { + threads.Items = new CFreqInfo[numThreads]; + UInt32 i; + for (i = 0; i < numThreads; i++) + { + CFreqInfo &info = threads.Items[i]; + info.Callback = _file; + info.CallbackRes = S_OK; + info.NumIterations = numIterations; + info.Size = bufferSize; + } + progressInfoSpec.SetStartTime(); + for (i = 0; i < numThreads; i++) + { + CFreqInfo &info = threads.Items[i]; + RINOK(info.Thread.Create(FreqThreadFunction, &info)); + threads.NumThreads++; + } + threads.WaitAll(); + for (i = 0; i < numThreads; i++) + { + RINOK(threads.Items[i].CallbackRes); + } + } + else + #endif + { + progressInfoSpec.SetStartTime(); + UInt32 sum = g_BenchCpuFreqTemp; + for (UInt64 k = numIterations; k > 0; k--) + { + RINOK(_file->CheckBreak()); + sum = CountCpuFreq(bufferSize, sum); + } + res += sum; + } + CBenchInfo info; + progressInfoSpec.SetFinishTime(info); + + info.UnpackSize = 0; + info.PackSize = 0; + info.NumIterations = 1; + + if (_file) + { + { + UInt64 numCommands = (UInt64)numIterations * bufferSize * numThreads * complexity; + UInt64 rating = info.GetSpeed(numCommands); + cpuFreq = rating / numThreads; + PrintResults(_file, info, rating, showFreq, showFreq ? cpuFreq : 0, NULL); + } + RINOK(_file->CheckBreak()); + } + + return S_OK; +} + + + +static HRESULT CrcBench( + DECL_EXTERNAL_CODECS_LOC_VARS + UInt64 complexInCommands, + UInt32 numThreads, UInt32 bufferSize, + UInt64 &speed, + UInt32 complexity, + const UInt32 *checkSum, + const COneMethodInfo &method, + IBenchPrintCallback *_file, + CTotalBenchRes *encodeRes, + bool showFreq, UInt64 cpuFreq) +{ + if (numThreads == 0) + numThreads = 1; + + #ifdef _7ZIP_ST + numThreads = 1; + #endif + + UString methodName = method.MethodName; + // methodName.RemoveChar(L'-'); + CMethodId hashID; + if (!FindHashMethod( + EXTERNAL_CODECS_LOC_VARS + methodName, hashID)) + return E_NOTIMPL; + + CBenchBuffer buffer; + size_t totalSize = (size_t)bufferSize * numThreads; + if (totalSize / numThreads != bufferSize) + return E_OUTOFMEMORY; + if (!buffer.Alloc(totalSize)) + return E_OUTOFMEMORY; + + Byte *buf = buffer.Buffer; + CBaseRandomGenerator RG; + UInt32 bsize = (bufferSize == 0 ? 1 : bufferSize); + UInt64 numIterations = complexInCommands * 256 / complexity / bsize; + if (numIterations == 0) + numIterations = 1; + + CBenchInfoCalc progressInfoSpec; + + #ifndef _7ZIP_ST + CCrcThreads threads; + if (numThreads > 1) + { + threads.Items = new CCrcInfo[numThreads]; + UInt32 i; + for (i = 0; i < numThreads; i++) + { + CCrcInfo &info = threads.Items[i]; + UString name; + RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS hashID, name, info.Hasher)); + if (!info.Hasher) + return E_NOTIMPL; + CMyComPtr scp; + info.Hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp); + if (scp) + { + UInt64 reduceSize = 1; + RINOK(method.SetCoderProps(scp, &reduceSize)); + } + + Byte *data = buf + (size_t)bufferSize * i; + info.Callback = _file; + info.Data = data; + info.NumIterations = numIterations; + info.Size = bufferSize; + /* info.Crc = */ RandGenCrc(data, bufferSize, RG); + info.CheckSumDefined = false; + if (checkSum) + { + info.CheckSum = *checkSum; + info.CheckSumDefined = (checkSum && (i == 0)); + } + } + progressInfoSpec.SetStartTime(); + for (i = 0; i < numThreads; i++) + { + CCrcInfo &info = threads.Items[i]; + RINOK(info.Thread.Create(CrcThreadFunction, &info)); + threads.NumThreads++; + } + threads.WaitAll(); + for (i = 0; i < numThreads; i++) + { + RINOK(threads.Items[i].Res); + } + } + else + #endif + { + /* UInt32 crc = */ RandGenCrc(buf, bufferSize, RG); + progressInfoSpec.SetStartTime(); + CMyComPtr hasher; + UString name; + RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS hashID, name, hasher)); + if (!hasher) + return E_NOTIMPL; + CMyComPtr scp; + hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp); + if (scp) + { + UInt64 reduceSize = 1; + RINOK(method.SetCoderProps(scp, &reduceSize)); + } + RINOK(CrcBig(buf, bufferSize, numIterations, checkSum, hasher, _file)); + } + CBenchInfo info; + progressInfoSpec.SetFinishTime(info); + + UInt64 unpSize = numIterations * bufferSize; + UInt64 unpSizeThreads = unpSize * numThreads; + info.UnpackSize = unpSizeThreads; + info.PackSize = unpSizeThreads; + info.NumIterations = 1; + + if (_file) + { + { + UInt64 numCommands = unpSizeThreads * complexity / 256; + UInt64 rating = info.GetSpeed(numCommands); + PrintResults(_file, info, rating, showFreq, cpuFreq, encodeRes); + } + RINOK(_file->CheckBreak()); + } + + speed = info.GetSpeed(unpSizeThreads); + + return S_OK; +} + +static HRESULT TotalBench_Hash( + DECL_EXTERNAL_CODECS_LOC_VARS + UInt64 complexInCommands, + UInt32 numThreads, UInt32 bufSize, + IBenchPrintCallback *printCallback, CBenchCallbackToPrint *callback, + CTotalBenchRes *encodeRes, + bool showFreq, UInt64 cpuFreq) +{ + for (unsigned i = 0; i < ARRAY_SIZE(g_Hash); i++) + { + const CBenchHash &bench = g_Hash[i]; + PrintLeft(*callback->_file, bench.Name, kFieldSize_Name); + // callback->BenchProps.DecComplexUnc = bench.DecComplexUnc; + // callback->BenchProps.DecComplexCompr = bench.DecComplexCompr; + // callback->BenchProps.EncComplex = bench.EncComplex; + + COneMethodInfo method; + NCOM::CPropVariant propVariant; + propVariant = bench.Name; + RINOK(method.ParseMethodFromPROPVARIANT(L"", propVariant)); + + UInt64 speed; + HRESULT res = CrcBench( + EXTERNAL_CODECS_LOC_VARS + complexInCommands, + numThreads, bufSize, + speed, + bench.Complex, &bench.CheckSum, method, + printCallback, encodeRes, showFreq, cpuFreq); + if (res == E_NOTIMPL) + { + // callback->Print(" ---"); + } else { RINOK(res); } callback->NewLine(); } - return S_OK; + return S_OK; } struct CTempValues @@ -1392,23 +2067,45 @@ struct CTempValues ~CTempValues() { delete []Values; } }; -static void String_to_PropVariant(const UString &s, NCOM::CPropVariant &prop) +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()) + const wchar_t *end; + UInt64 result = ConvertStringToUInt64(s, &end); + if (*end != 0 || s.IsEmpty()) prop = s; - else if (result <= 0xFFFFFFFF) + else if (result <= (UInt32)0xFFFFFFFF) prop = (UInt32)result; else prop = result; } +static UInt32 GetNumThreadsNext(unsigned i, UInt32 numThreads) +{ + if (i < 2) + return i + 1; + i -= 1; + UInt32 num = (UInt32)(2 + (i & 1)) << (i >> 1); + return (num <= numThreads) ? num : numThreads; +} + +static bool AreSameMethodNames(const char *fullName, const wchar_t *shortName) +{ + for (;;) + { + wchar_t c2 = *shortName++; + if (c2 == 0) + return true; + char c1 = *fullName++; + if ((unsigned char)MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2)) + return false; + } +} + HRESULT Bench( DECL_EXTERNAL_CODECS_LOC_VARS IBenchPrintCallback *printCallback, IBenchCallback *benchCallback, - const CObjectVector props, + const CObjectVector &props, UInt32 numIterations, bool multiDict) { @@ -1425,29 +2122,76 @@ HRESULT Bench( #endif UInt32 numThreads = numCPUs; - if (printCallback) - PrintRequirements(*printCallback, "size: ", ramSize, "CPU hardware threads:", numCPUs); + UInt32 testTime = kComplexInSeconds; COneMethodInfo method; - int i; + unsigned i; for (i = 0; i < props.Size(); i++) { const CProperty &property = props[i]; NCOM::CPropVariant propVariant; UString name = property.Name; - name.MakeUpper(); + name.MakeLower_Ascii(); if (!property.Value.IsEmpty()) - String_to_PropVariant(property.Value, propVariant); - if (name.Left(2).CompareNoCase(L"MT") == 0) + ParseNumberString(property.Value, propVariant); + if (name.IsEqualTo("testtime")) + { + RINOK(ParsePropToUInt32(L"", propVariant, testTime)); + continue; + } + if (name.IsPrefixedBy(L"mt")) { #ifndef _7ZIP_ST - RINOK(ParseMtProp(name.Mid(2), propVariant, numCPUs, numThreads)); + RINOK(ParseMtProp(name.Ptr(2), propVariant, numCPUs, numThreads)); #endif continue; } RINOK(method.ParseMethodFromPROPVARIANT(name, propVariant)); } + if (printCallback) + { + printCallback->Print("CPU Freq:"); + } + + UInt64 complexInCommands = kComplexInCommands; + + if (printCallback) + { + UInt64 numMilCommands = (1 << 6); + + for (int jj = 0;; jj++) + { + UInt64 start = ::GetTimeCount(); + UInt32 sum = (UInt32)start; + sum += CountCpuFreq((UInt32)(numMilCommands * 1000000 / kNumFreqCommands), g_BenchCpuFreqTemp); + start = ::GetTimeCount() - start; + if (start == 0) + start = 1; + UInt64 freq = GetFreq(); + UInt64 mips = numMilCommands * freq / start; + if (printCallback) + PrintNumber(*printCallback, mips, 5 + ((sum >> 31) & 1)); + if (jj >= 3) + { + SetComplexCommands(testTime, mips * 1000000, complexInCommands); + if (jj >= 8 || start >= freq) + break; + // break; // change it + numMilCommands <<= 1; + } + } + } + if (printCallback) + { + printCallback->NewLine(); + printCallback->NewLine(); + PrintRequirements(*printCallback, "size: ", ramSize, "CPU hardware threads:", numCPUs); + } + + if (numThreads < 1 || numThreads > kNumThreadsMax) + return E_INVALIDARG; + UInt32 dict; bool dictIsDefined = method.Get_DicSize(dict); @@ -1462,12 +2206,18 @@ HRESULT Bench( UInt32 uncompressedDataSize = kAdditionalSize + dictSize; return MethodBench( EXTERNAL_CODECS_LOC_VARS + complexInCommands, true, numThreads, method, uncompressedDataSize, kOldLzmaDictBits, printCallback, benchCallback, &benchProps); } - if (method.MethodName.CompareNoCase(L"CRC") == 0) + UString methodName = method.MethodName; + if (methodName.IsEqualToNoCase(L"CRC")) + methodName = L"crc32"; + method.MethodName = methodName; + CMethodId hashID; + if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS methodName, hashID)) { if (!printCallback) return S_FALSE; @@ -1475,33 +2225,69 @@ HRESULT Bench( if (!dictIsDefined) dict = (1 << 24); - CTempValues speedTotals(numThreads); + + // methhodName.RemoveChar(L'-'); + UInt32 complexity = 10000; + const UInt32 *checkSum = NULL; + { + for (unsigned i = 0; i < ARRAY_SIZE(g_Hash); i++) + { + const CBenchHash &h = g_Hash[i]; + if (AreSameMethodNames(h.Name, methodName)) + { + complexity = h.Complex; + checkSum = &h.CheckSum; + if (strcmp(h.Name, "CRC32:4") != 0) + break; + } + } + } + f.NewLine(); f.Print("Size"); - for (UInt32 ti = 0; ti < numThreads; ti++) + const int kFieldSize_CrcSpeed = 6; + unsigned numThreadsTests = 0; + for (;;) { - PrintNumber(f, ti + 1, 5); - speedTotals.Values[ti] = 0; + UInt32 t = GetNumThreadsNext(numThreadsTests, numThreads); + PrintNumber(f, t, kFieldSize_CrcSpeed); + numThreadsTests++; + if (t >= numThreads) + break; } f.NewLine(); f.NewLine(); + CTempValues speedTotals(numThreadsTests); + { + for (unsigned ti = 0; ti < numThreadsTests; ti++) + speedTotals.Values[ti] = 0; + } UInt64 numSteps = 0; for (UInt32 i = 0; i < numIterations; i++) { - for (int pow = 10; pow < 32; pow++) + for (unsigned pow = 10; pow < 32; pow++) { UInt32 bufSize = (UInt32)1 << pow; if (bufSize > dict) break; - PrintNumber(f, pow, 2, false); - f.Print(": "); - for (UInt32 ti = 0; ti < numThreads; ti++) + char s[16]; + ConvertUInt32ToString(pow, s); + int pos = MyStringLen(s); + s[pos++] = ':'; + s[pos++] = ' '; + s[pos] = 0; + f.Print(s); + + for (unsigned ti = 0; ti < numThreadsTests; ti++) { RINOK(f.CheckBreak()); - UInt64 speed; - RINOK(CrcBench(ti + 1, bufSize, speed)); - PrintNumber(f, (speed >> 20), 5); + UInt32 t = GetNumThreadsNext(ti, numThreads); + UInt64 speed = 0; + RINOK(CrcBench(EXTERNAL_CODECS_LOC_VARS complexInCommands, + t, bufSize, speed, complexity, + (pow == kNumHashDictBits) ? checkSum : NULL, method, NULL, NULL, false, 0)); + PrintNumber(f, (speed >> 20), kFieldSize_CrcSpeed); speedTotals.Values[ti] += speed; } f.NewLine(); @@ -1512,13 +2298,17 @@ HRESULT Bench( { f.NewLine(); f.Print("Avg:"); - for (UInt32 ti = 0; ti < numThreads; ti++) - PrintNumber(f, ((speedTotals.Values[ti] / numSteps) >> 20), 5); + for (unsigned ti = 0; ti < numThreadsTests; ti++) + { + PrintNumber(f, ((speedTotals.Values[ti] / numSteps) >> 20), kFieldSize_CrcSpeed); + } f.NewLine(); } return S_OK; } + bool use2Columns = false; + CBenchCallbackToPrint callback; callback.Init(); callback._file = printCallback; @@ -1537,27 +2327,80 @@ HRESULT Bench( bool totalBenchMode = (method.MethodName == L"*"); f.NewLine(); - f.Print(totalBenchMode ? "Method " : "Dict"); - f.Print(" Compressing | Decompressing"); + + if (totalBenchMode) + { + callback.NameFieldSize = kFieldSize_Name; + use2Columns = false; + } + else + { + callback.NameFieldSize = kFieldSize_SmallName; + use2Columns = true; + } + callback.Use2Columns = use2Columns; + + bool showFreq = false; + UInt64 cpuFreq = 0; + + if (totalBenchMode) + { + showFreq = true; + } + + int fileldSize = kFieldSize_TotalSize; + if (showFreq) + fileldSize += kFieldSize_EUAndEffec; + + if (use2Columns) + { + PrintSpaces(f, callback.NameFieldSize); + PrintRight(f, "Compressing", fileldSize); + f.Print(kSep); + PrintRight(f, "Decompressing", fileldSize); + } f.NewLine(); - const char *kSpaces = totalBenchMode ? " " : " "; - f.Print(kSpaces); + PrintLeft(f, totalBenchMode ? "Method" : "Dict", callback.NameFieldSize); + int j; - + for (j = 0; j < 2; j++) { - f.Print(" Speed Usage R/U Rating"); + PrintRight(f, "Speed", kFieldSize_Speed + 1); + PrintRight(f, "Usage", kFieldSize_Usage + 1); + PrintRight(f, "R/U", kFieldSize_RU + 1); + PrintRight(f, "Rating", kFieldSize_Rating + 1); + if (showFreq) + { + PrintRight(f, "E/U", kFieldSize_EU + 1); + PrintRight(f, "Effec", kFieldSize_Effec + 1); + } + if (!use2Columns) + break; if (j == 0) f.Print(kSep); } + f.NewLine(); - f.Print(kSpaces); + PrintSpaces(f, callback.NameFieldSize); + for (j = 0; j < 2; j++) { - f.Print(" KB/s % MIPS MIPS"); + PrintRight(f, "KB/s", kFieldSize_Speed + 1); + PrintRight(f, "%", kFieldSize_Usage + 1); + PrintRight(f, "MIPS", kFieldSize_RU + 1); + PrintRight(f, "MIPS", kFieldSize_Rating + 1); + if (showFreq) + { + PrintRight(f, "%", kFieldSize_EU + 1); + PrintRight(f, "%", kFieldSize_Effec + 1); + } + if (!use2Columns) + break; if (j == 0) f.Print(kSep); } + f.NewLine(); f.NewLine(); @@ -1574,38 +2417,101 @@ HRESULT Bench( { if (i != 0) printCallback->NewLine(); - HRESULT res = TotalBench( - EXTERNAL_CODECS_LOC_VARS - numThreads, dict, printCallback, &callback); + HRESULT res; + + int freqTest; + const int kNumCpuTests = 3; + for (freqTest = 0; freqTest < kNumCpuTests; freqTest++) + { + PrintLeft(f, "CPU", kFieldSize_Name); + UInt32 resVal; + RINOK(FreqBench(complexInCommands, numThreads, printCallback, freqTest == kNumCpuTests - 1, cpuFreq, resVal)); + callback.NewLine(); + + if (freqTest == kNumCpuTests - 1) + SetComplexCommands(testTime, cpuFreq, complexInCommands); + } + callback.NewLine(); + + callback.SetFreq(true, cpuFreq); + res = TotalBench(EXTERNAL_CODECS_LOC_VARS complexInCommands, numThreads, dictIsDefined, dict, printCallback, &callback); RINOK(res); + + res = TotalBench_Hash(EXTERNAL_CODECS_LOC_VARS complexInCommands, numThreads, + 1 << kNumHashDictBits, printCallback, &callback, &callback.EncodeRes, true, cpuFreq); + RINOK(res); + + callback.NewLine(); + { + PrintLeft(f, "CPU", kFieldSize_Name); + UInt32 resVal; + UInt64 cpuFreqLastTemp = cpuFreq; + RINOK(FreqBench(complexInCommands, numThreads, printCallback, false, cpuFreqLastTemp, resVal)); + callback.NewLine(); + } } } else { + bool needSetComplexity = true; + if (!methodName.IsEqualToNoCase(L"LZMA")) + { + for (unsigned i = 0; i < ARRAY_SIZE(g_Bench); i++) + { + const CBenchMethod &h = g_Bench[i]; + AString s = h.Name; + if (AreSameMethodNames(h.Name, methodName)) + { + callback.BenchProps.EncComplex = h.EncComplex; + callback.BenchProps.DecComplexCompr = h.DecComplexCompr; + callback.BenchProps.DecComplexUnc = h.DecComplexUnc;; + needSetComplexity = false; + break; + } + } + } + if (needSetComplexity) + callback.BenchProps.SetLzmaCompexity(); - callback.BenchProps.SetLzmaCompexity(); - - for (i = 0; i < (int)numIterations; i++) + for (i = 0; i < numIterations; i++) { - const int kStartDicLog = 22; - int pow = (dict < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog; + const unsigned kStartDicLog = 22; + unsigned pow = (dict < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog; if (!multiDict) pow = 31; - while (((UInt32)1 << pow) > dict) + while (((UInt32)1 << pow) > dict && pow > 0) pow--; for (; ((UInt32)1 << pow) <= dict; pow++) { - PrintNumber(f, pow, 2, false); - f.Print(":"); + char s[16]; + ConvertUInt32ToString(pow, s); + unsigned pos = MyStringLen(s); + s[pos++] = ':'; + s[pos] = 0; + PrintLeft(f, s, kFieldSize_SmallName); callback.DictSize = (UInt32)1 << pow; - UInt32 uncompressedDataSize = kAdditionalSize + callback.DictSize; + COneMethodInfo method2 = method; + + if (StringsAreEqualNoCase_Ascii(method2.MethodName, L"LZMA")) + { + // We add dictionary size property. + // method2 can have two different dictionary size properties. + // And last property is main. + NCOM::CPropVariant propVariant = (UInt32)pow; + RINOK(method2.ParseMethodFromPROPVARIANT(L"d", propVariant)); + } + + UInt32 uncompressedDataSize = callback.DictSize; + if (uncompressedDataSize >= (1 << 18)) + uncompressedDataSize += kAdditionalSize; HRESULT res = MethodBench( - EXTERNAL_CODECS_LOC_VARS - true, numThreads, - method, uncompressedDataSize, - kOldLzmaDictBits, printCallback, &callback, &callback.BenchProps); + EXTERNAL_CODECS_LOC_VARS + complexInCommands, + true, numThreads, + method2, uncompressedDataSize, + kOldLzmaDictBits, printCallback, &callback, &callback.BenchProps); f.NewLine(); RINOK(res); if (!multiDict) @@ -1613,21 +2519,27 @@ HRESULT Bench( } } } - callback.Normalize(); - f.Print("----------------------------------------------------------------"); - f.NewLine(); - f.Print("Avr:"); - const char *kSpaces2 = totalBenchMode ? " " : ""; - f.Print(kSpaces2); - PrintTotals(f, callback.EncodeRes); - f.Print(" "); - PrintTotals(f, callback.DecodeRes); + + PrintChars(f, '-', callback.NameFieldSize + fileldSize); + + if (use2Columns) + { + f.Print(kSep); + PrintChars(f, '-', fileldSize); + } f.NewLine(); - f.Print("Tot:"); - f.Print(kSpaces2); + if (use2Columns) + { + PrintLeft(f, "Avr:", callback.NameFieldSize); + PrintTotals(f, showFreq, cpuFreq, callback.EncodeRes); + f.Print(kSep); + PrintTotals(f, showFreq, cpuFreq, callback.DecodeRes); + f.NewLine(); + } + PrintLeft(f, "Tot:", callback.NameFieldSize); CTotalBenchRes midRes; - midRes.SetMid(callback.EncodeRes, callback.DecodeRes); - PrintTotals(f, midRes); + midRes.SetSum(callback.EncodeRes, callback.DecodeRes); + PrintTotals(f, showFreq, cpuFreq, midRes); f.NewLine(); return S_OK; } diff --git a/CPP/7zip/UI/Common/Bench.h b/CPP/7zip/UI/Common/Bench.h old mode 100755 new mode 100644 index 46146e24..b123675b --- a/CPP/7zip/UI/Common/Bench.h +++ b/CPP/7zip/UI/Common/Bench.h @@ -14,21 +14,23 @@ struct CBenchInfo UInt64 UserFreq; UInt64 UnpackSize; UInt64 PackSize; - UInt32 NumIterations; + UInt64 NumIterations; CBenchInfo(): NumIterations(0) {} UInt64 GetUsage() const; UInt64 GetRatingPerUsage(UInt64 rating) const; + UInt64 GetSpeed(UInt64 numCommands) const; }; struct IBenchCallback { + virtual HRESULT SetFreq(bool showFreq, UInt64 cpuFreq) = 0; virtual HRESULT SetEncodeResult(const CBenchInfo &info, bool final) = 0; virtual HRESULT SetDecodeResult(const CBenchInfo &info, bool final) = 0; }; UInt64 GetCompressRating(UInt32 dictSize, UInt64 elapsedTime, UInt64 freq, UInt64 size); -UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations); +UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt64 numIterations); const int kBenchMinDicLogSize = 18; @@ -45,7 +47,7 @@ HRESULT Bench( DECL_EXTERNAL_CODECS_LOC_VARS IBenchPrintCallback *printCallback, IBenchCallback *benchCallback, - const CObjectVector props, + const CObjectVector &props, UInt32 numIterations, bool multiDict ); diff --git a/CPP/7zip/UI/Common/CompressCall.cpp b/CPP/7zip/UI/Common/CompressCall.cpp old mode 100755 new mode 100644 index eb20d5cc..f5407b03 --- a/CPP/7zip/UI/Common/CompressCall.cpp +++ b/CPP/7zip/UI/Common/CompressCall.cpp @@ -2,17 +2,17 @@ #include "StdAfx.h" -#include "Common/IntToString.h" -#include "Common/MyCom.h" -#include "Common/Random.h" -#include "Common/StringConvert.h" - -#include "Windows/DLL.h" -#include "Windows/Error.h" -#include "Windows/FileDir.h" -#include "Windows/FileMapping.h" -#include "Windows/Process.h" -#include "Windows/Synchronization.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/MyCom.h" +#include "../../../Common/Random.h" +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/DLL.h" +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileMapping.h" +#include "../../../Windows/ProcessUtils.h" +#include "../../../Windows/Synchronization.h" #include "../FileManager/RegistryUtils.h" @@ -23,12 +23,15 @@ using namespace NWindows; #define MY_TRY_BEGIN try { #define MY_TRY_FINISH } \ catch(...) { ErrorMessageHRESULT(E_FAIL); return E_FAIL; } +#define MY_TRY_FINISH_VOID } \ + catch(...) { ErrorMessageHRESULT(E_FAIL); } static LPCWSTR kShowDialogSwitch = L" -ad"; static LPCWSTR kEmailSwitch = L" -seml."; static LPCWSTR kIncludeSwitch = L" -i"; static LPCWSTR kArchiveTypeSwitch = L" -t"; static LPCWSTR kArcIncludeSwitches = L" -an -ai"; +static LPCWSTR kHashIncludeSwitches = L" -i"; static LPCWSTR kStopSwitchParsing = L" --"; static LPCWSTR kLargePagesDisable = L" -slp-"; @@ -46,7 +49,7 @@ static void ErrorMessage(LPCWSTR message) static void ErrorMessageHRESULT(HRESULT res, LPCWSTR s = NULL) { - UString s2 = NError::MyFormatMessageW(res); + UString s2 = NError::MyFormatMessage(res); if (s) { s2 += L'\n'; @@ -56,11 +59,12 @@ static void ErrorMessageHRESULT(HRESULT res, LPCWSTR s = NULL) } static HRESULT MyCreateProcess(LPCWSTR imageName, const UString ¶ms, - LPCWSTR curDir, bool waitFinish, + // LPCWSTR curDir, + bool waitFinish, NSynchronization::CBaseEvent *event) { CProcess process; - WRes res = process.Create(imageName, params, curDir); + WRes res = process.Create(imageName, params, NULL); // curDir); if (res != 0) { ErrorMessageHRESULT(res, imageName); @@ -71,7 +75,7 @@ static HRESULT MyCreateProcess(LPCWSTR imageName, const UString ¶ms, else if (event != NULL) { HANDLE handles[] = { process, *event }; - ::WaitForMultipleObjects(sizeof(handles) / sizeof(handles[0]), handles, FALSE, INFINITE); + ::WaitForMultipleObjects(ARRAY_SIZE(handles), handles, FALSE, INFINITE); } return S_OK; } @@ -105,8 +109,8 @@ static HRESULT CreateMap(const UStringVector &names, UString ¶ms) { UInt32 totalSize = 1; - for (int i = 0; i < names.Size(); i++) - totalSize += (names[i].Length() + 1); + FOR_VECTOR (i, names) + totalSize += (names[i].Len() + 1); totalSize *= sizeof(wchar_t); CRandNameGenerator random; @@ -153,10 +157,10 @@ static HRESULT CreateMap(const UStringVector &names, { wchar_t *cur = (wchar_t *)data; *cur++ = 0; - for (int i = 0; i < names.Size(); i++) + FOR_VECTOR (i, names) { const UString &s = names[i]; - int len = s.Length() + 1; + int len = s.Len() + 1; memcpy(cur, (const wchar_t *)s, len * sizeof(wchar_t)); cur += len; } @@ -168,6 +172,7 @@ HRESULT CompressFiles( const UString &arcPathPrefix, const UString &arcName, const UString &arcType, + bool addExtension, const UStringVector &names, bool email, bool showDialog, bool waitFinish) { @@ -193,31 +198,46 @@ HRESULT CompressFiles( AddLagePagesSwitch(params); + if (arcName.IsEmpty()) + params += L" -an"; + + if (addExtension) + params += L" -saa"; + else + params += L" -sae"; + params += kStopSwitchParsing; params += L' '; - params += GetQuotedString( - #ifdef UNDER_CE - arcPathPrefix + - #endif + if (!arcName.IsEmpty()) + { + params += GetQuotedString( + // #ifdef UNDER_CE + arcPathPrefix + + // #endif arcName); + } return MyCreateProcess(Get7zGuiPath(), params, - (arcPathPrefix.IsEmpty()? 0: (LPCWSTR)arcPathPrefix), waitFinish, &event); + // (arcPathPrefix.IsEmpty()? 0: (LPCWSTR)arcPathPrefix), + waitFinish, &event); MY_TRY_FINISH } -static HRESULT ExtractGroupCommand(const UStringVector &arcPaths, UString ¶ms) +static void ExtractGroupCommand(const UStringVector &arcPaths, UString ¶ms, bool isHash) { AddLagePagesSwitch(params); - params += kArcIncludeSwitches; + params += isHash ? kHashIncludeSwitches : kArcIncludeSwitches; CFileMapping fileMapping; NSynchronization::CManualResetEvent event; - RINOK(CreateMap(arcPaths, fileMapping, event, params)); - return MyCreateProcess(Get7zGuiPath(), params, 0, false, &event); + HRESULT result = CreateMap(arcPaths, fileMapping, event, params); + if (result == S_OK) + result = MyCreateProcess(Get7zGuiPath(), params, false, &event); + if (result != S_OK) + ErrorMessageHRESULT(result); } -HRESULT ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog) +void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup) { MY_TRY_BEGIN UString params = L'x'; @@ -226,23 +246,40 @@ HRESULT ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, params += L" -o"; params += GetQuotedString(outFolder); } + if (elimDup) + params += L" -spe"; if (showDialog) params += kShowDialogSwitch; - return ExtractGroupCommand(arcPaths, params); - MY_TRY_FINISH + ExtractGroupCommand(arcPaths, params, false); + MY_TRY_FINISH_VOID } -HRESULT TestArchives(const UStringVector &arcPaths) +void TestArchives(const UStringVector &arcPaths) { MY_TRY_BEGIN UString params = L't'; - return ExtractGroupCommand(arcPaths, params); - MY_TRY_FINISH + ExtractGroupCommand(arcPaths, params, false); + MY_TRY_FINISH_VOID } -HRESULT Benchmark(bool totalMode) +void CalcChecksum(const UStringVector &paths, const UString &methodName) { MY_TRY_BEGIN - return MyCreateProcess(Get7zGuiPath(), totalMode ? L"b -mm=*" : L"b", 0, false, NULL); - MY_TRY_FINISH + UString params = L'h'; + if (!methodName.IsEmpty()) + { + params += L" -scrc"; + params += methodName; + } + ExtractGroupCommand(paths, params, true); + MY_TRY_FINISH_VOID +} + +void Benchmark(bool totalMode) +{ + MY_TRY_BEGIN + HRESULT result = MyCreateProcess(Get7zGuiPath(), totalMode ? L"b -mm=*" : L"b", false, NULL); + if (result != S_OK) + ErrorMessageHRESULT(result); + MY_TRY_FINISH_VOID } diff --git a/CPP/7zip/UI/Common/CompressCall.h b/CPP/7zip/UI/Common/CompressCall.h old mode 100755 new mode 100644 index f777b9f2..c71c21f7 --- a/CPP/7zip/UI/Common/CompressCall.h +++ b/CPP/7zip/UI/Common/CompressCall.h @@ -3,7 +3,7 @@ #ifndef __COMPRESS_CALL_H #define __COMPRESS_CALL_H -#include "Common/MyString.h" +#include "../../../Common/MyString.h" UString GetQuotedString(const UString &s); @@ -11,11 +11,13 @@ HRESULT CompressFiles( const UString &arcPathPrefix, const UString &arcName, const UString &arcType, + bool addExtension, 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(bool totalMode); +void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup); +void TestArchives(const UStringVector &arcPaths); +void CalcChecksum(const UStringVector &paths, const UString &methodName); +void Benchmark(bool totalMode); #endif diff --git a/CPP/7zip/UI/Common/CompressCall2.cpp b/CPP/7zip/UI/Common/CompressCall2.cpp old mode 100755 new mode 100644 index ab483d2f..bd27f37b --- a/CPP/7zip/UI/Common/CompressCall2.cpp +++ b/CPP/7zip/UI/Common/CompressCall2.cpp @@ -2,13 +2,14 @@ #include "StdAfx.h" -#include "Common/MyException.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/HashGUI.h" #include "../../UI/GUI/ExtractRes.h" @@ -16,20 +17,38 @@ extern HWND g_HWND; -#define MY_TRY_BEGIN try { +#define MY_TRY_BEGIN HRESULT result; try { #define MY_TRY_FINISH } \ catch(CSystemException &e) { result = e.ErrorCode; } \ catch(...) { result = E_FAIL; } \ if (result != S_OK && result != E_ABORT) \ ErrorMessageHRESULT(result); +static void ThrowException_if_Error(HRESULT res) +{ + if (res != S_OK) + throw CSystemException(res); +} + #define CREATE_CODECS \ CCodecs *codecs = new CCodecs; \ - CMyComPtr compressCodecsInfo = codecs; \ - result = codecs->Load(); \ - if (result != S_OK) \ - throw CSystemException(result); + CMyComPtr compressCodecsInfo = codecs; \ + ThrowException_if_Error(codecs->Load()); + +#ifdef EXTERNAL_CODECS +#define LOAD_EXTERNAL_CODECS \ + CExternalCodecs __externalCodecs; \ + __externalCodecs.GetCodecs = codecs; \ + __externalCodecs.GetHashers = codecs; \ + ThrowException_if_Error(__externalCodecs.LoadCodecs()); + +#else + +LOAD_EXTERNAL_CODECS + +#endif + UString GetQuotedString(const UString &s) { return UString(L'\"') + s + UString(L'\"'); @@ -45,19 +64,19 @@ static void ErrorMessageHRESULT(HRESULT res) ErrorMessage(HResultToMessage(res)); } -static void ErrorLangMessage(UINT resourceID, UInt32 langID) +static void ErrorLangMessage(UINT resourceID) { - ErrorMessage(LangString(resourceID, langID)); + ErrorMessage(LangString(resourceID)); } HRESULT CompressFiles( const UString &arcPathPrefix, const UString &arcName, const UString &arcType, + bool addExtension, const UStringVector &names, bool email, bool showDialog, bool /* waitFinish */) { - HRESULT result; MY_TRY_BEGIN CREATE_CODECS @@ -67,26 +86,35 @@ HRESULT CompressFiles( CUpdateOptions uo; uo.EMailMode = email; - uo.SetAddActionCommand(); + uo.SetActionCommand_Add(); - CIntVector formatIndices; - if (!codecs->FindFormatForArchiveType(arcType, formatIndices)) + uo.ArcNameMode = (addExtension ? k_ArcNameMode_Add : k_ArcNameMode_Exact); + + CObjectVector formatIndices; + if (!ParseOpenTypes(*codecs, arcType, formatIndices)) { - ErrorLangMessage(IDS_UNSUPPORTED_ARCHIVE_TYPE, 0x0200060D); + ErrorLangMessage(IDS_UNSUPPORTED_ARCHIVE_TYPE); return E_FAIL; } - if (!uo.Init(codecs, formatIndices, arcPathPrefix + arcName)) + const UString arcPath = arcPathPrefix + arcName; + if (!uo.InitFormatIndex(codecs, formatIndices, arcPath) || + !uo.SetArcPath(codecs, arcPath)) { - ErrorLangMessage(IDS_UPDATE_NOT_SUPPORTED, 0x02000601); + ErrorLangMessage(IDS_UPDATE_NOT_SUPPORTED); return E_FAIL; } NWildcard::CCensor censor; - for (int i = 0; i < names.Size(); i++) - censor.AddItem(true, names[i], false); + FOR_VECTOR (i, names) + { + censor.AddPreItem(names[i]); + } bool messageWasDisplayed = false; - result = UpdateGUI(codecs, censor, uo, showDialog, messageWasDisplayed, &callback, g_HWND); + + result = UpdateGUI(codecs, + formatIndices, arcPath, + censor, uo, showDialog, messageWasDisplayed, &callback, g_HWND); if (result != S_OK) { @@ -105,15 +133,16 @@ HRESULT CompressFiles( } static HRESULT ExtractGroupCommand(const UStringVector &arcPaths, - bool showDialog, const UString &outFolder, bool testMode) + bool showDialog, const UString &outFolder, bool testMode, bool elimDup = false) { - HRESULT result; MY_TRY_BEGIN CREATE_CODECS CExtractOptions eo; eo.OutputDir = us2fs(outFolder); eo.TestMode = testMode; + eo.ElimDup.Val = elimDup; + eo.ElimDup.Def = elimDup; CExtractCallbackImp *ecs = new CExtractCallbackImp; CMyComPtr extractCallback = ecs; @@ -125,20 +154,29 @@ static HRESULT ExtractGroupCommand(const UStringVector &arcPaths, 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); + NWildcard::CCensor arcCensor; + FOR_VECTOR (i, arcPaths) + { + arcCensor.AddPreItem(arcPaths[i]); + } + arcCensor.AddPathsToCensor(NWildcard::k_RelatPath); + EnumerateDirItemsAndSort(false, arcCensor, NWildcard::k_RelatPath, UString(), arcPathsSorted, arcFullPathsSorted); } - CIntVector formatIndices; - + CObjectVector formatIndices; + NWildcard::CCensor censor; - censor.AddItem(true, L"*", false); + { + censor.AddPreItem_Wildcard(); + } + censor.AddPathsToCensor(NWildcard::k_RelatPath); + bool messageWasDisplayed = false; - result = ExtractGUI(codecs, formatIndices, arcPathsSorted, arcFullPathsSorted, - censor.Pairs.Front().Head, eo, showDialog, messageWasDisplayed, ecs, g_HWND); + result = ExtractGUI(codecs, + formatIndices, CIntVector(), + arcPathsSorted, arcFullPathsSorted, + censor.Pairs.Front().Head, eo, NULL, showDialog, messageWasDisplayed, ecs, g_HWND); if (result != S_OK) { if (result != E_ABORT && messageWasDisplayed) @@ -150,26 +188,51 @@ static HRESULT ExtractGroupCommand(const UStringVector &arcPaths, return result; } -HRESULT ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog) +void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup) { - return ExtractGroupCommand(arcPaths, showDialog, outFolder, false); + ExtractGroupCommand(arcPaths, showDialog, outFolder, false, elimDup); } -HRESULT TestArchives(const UStringVector &arcPaths) +void TestArchives(const UStringVector &arcPaths) { - return ExtractGroupCommand(arcPaths, true, UString(), true); + ExtractGroupCommand(arcPaths, true, UString(), true); } -HRESULT Benchmark(bool totalMode) +void CalcChecksum(const UStringVector &paths, const UString &methodName) { - HRESULT result; MY_TRY_BEGIN CREATE_CODECS + LOAD_EXTERNAL_CODECS - #ifdef EXTERNAL_CODECS - CObjectVector externalCodecs; - RINOK(LoadExternalCodecs(codecs, externalCodecs)); - #endif + NWildcard::CCensor censor; + FOR_VECTOR (i, paths) + { + censor.AddPreItem(paths[i]); + } + + censor.AddPathsToCensor(NWildcard::k_RelatPath); + bool messageWasDisplayed = false; + + CHashOptions options; + options.Methods.Add(methodName); + + result = HashCalcGUI(EXTERNAL_CODECS_VARS censor, options, messageWasDisplayed); + if (result != S_OK) + { + if (result != E_ABORT && messageWasDisplayed) + return; // E_FAIL; + throw CSystemException(result); + } + MY_TRY_FINISH + return; // result; +} + +void Benchmark(bool totalMode) +{ + MY_TRY_BEGIN + CREATE_CODECS + LOAD_EXTERNAL_CODECS + CObjectVector props; if (totalMode) { @@ -178,11 +241,6 @@ HRESULT Benchmark(bool totalMode) prop.Value = L"*"; props.Add(prop); } - result = Benchmark( - #ifdef EXTERNAL_CODECS - codecs, &externalCodecs, - #endif - props, g_HWND); + result = Benchmark(EXTERNAL_CODECS_VARS props, g_HWND); MY_TRY_FINISH - return result; } diff --git a/CPP/7zip/UI/Common/DefaultName.cpp b/CPP/7zip/UI/Common/DefaultName.cpp old mode 100755 new mode 100644 index 4335e273..ce0b327b --- a/CPP/7zip/UI/Common/DefaultName.cpp +++ b/CPP/7zip/UI/Common/DefaultName.cpp @@ -7,13 +7,13 @@ static UString GetDefaultName3(const UString &fileName, const UString &extension, const UString &addSubExtension) { - int extLength = extension.Length(); - int fileNameLength = fileName.Length(); + int extLength = extension.Len(); + int fileNameLength = fileName.Len(); if (fileNameLength > extLength + 1) { int dotPos = fileNameLength - (extLength + 1); if (fileName[dotPos] == '.') - if (extension.CompareNoCase(fileName.Mid(dotPos + 1)) == 0) + if (extension.IsEqualToNoCase(fileName.Ptr(dotPos + 1))) return fileName.Left(dotPos) + addSubExtension; } int dotPos = fileName.ReverseFind(L'.'); diff --git a/CPP/7zip/UI/Common/DefaultName.h b/CPP/7zip/UI/Common/DefaultName.h old mode 100755 new mode 100644 index 9764ff87..df164560 --- a/CPP/7zip/UI/Common/DefaultName.h +++ b/CPP/7zip/UI/Common/DefaultName.h @@ -1,9 +1,9 @@ // DefaultName.h -#ifndef __DEFAULTNAME_H -#define __DEFAULTNAME_H +#ifndef __DEFAULT_NAME_H +#define __DEFAULT_NAME_H -#include "Common/MyString.h" +#include "../../../Common/MyString.h" UString GetDefaultName2(const UString &fileName, const UString &extension, const UString &addSubExtension); diff --git a/CPP/7zip/UI/Common/DirItem.h b/CPP/7zip/UI/Common/DirItem.h old mode 100755 new mode 100644 index 6d6dc673..4bb62b0e --- a/CPP/7zip/UI/Common/DirItem.h +++ b/CPP/7zip/UI/Common/DirItem.h @@ -3,8 +3,12 @@ #ifndef __DIR_ITEM_H #define __DIR_ITEM_H -#include "Common/MyString.h" -#include "Common/Types.h" +#include "../../../Common/MyString.h" + +#include "../../../Windows/FileFind.h" + +#include "../../Common/UniqBlocks.h" + #include "../../Archive/IArchive.h" struct CDirItem @@ -14,11 +18,23 @@ struct CDirItem FILETIME ATime; FILETIME MTime; UString Name; + + #if defined(_WIN32) && !defined(UNDER_CE) + // UString ShortName; + CByteBuffer ReparseData; + CByteBuffer ReparseData2; // fixed (reduced) absolute links + + bool AreReparseData() const { return ReparseData.Size() != 0 || !ReparseData2.Size() != 0; } + #endif + UInt32 Attrib; int PhyParent; int LogParent; + int SecureIndex; + + bool IsAltStream; - CDirItem(): PhyParent(-1), LogParent(-1) {} + CDirItem(): PhyParent(-1), LogParent(-1), SecureIndex(-1), IsAltStream(false) {} bool IsDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; } }; @@ -29,24 +45,64 @@ class CDirItems CIntVector LogParents; UString GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const; + + void EnumerateDir(int phyParent, int logParent, const FString &phyPrefix); + public: CObjectVector Items; - int GetNumFolders() const { return Prefixes.Size(); } - UString GetPhyPath(int index) const; - UString GetLogPath(int index) const; + bool SymLinks; + + bool ScanAltStreams; + FStringVector ErrorPaths; + CRecordVector ErrorCodes; + UInt64 TotalSize; - int AddPrefix(int phyParent, int logParent, const UString &prefix); - void DeleteLastPrefix(); - void EnumerateDirectory(int phyParent, int logParent, const FString &phyPrefix, - FStringVector &errorPaths, CRecordVector &errorCodes); + #ifndef UNDER_CE + void SetLinkInfo(CDirItem &dirItem, const NWindows::NFile::NFind::CFileInfo &fi, + const FString &phyPrefix); + #endif - void EnumerateDirItems2( + void AddError(const FString &path, DWORD errorCode) + { + ErrorCodes.Add(errorCode); + ErrorPaths.Add(path); + } + + void AddError(const FString &path) + { + AddError(path, ::GetLastError()); + } + + #if defined(_WIN32) && !defined(UNDER_CE) + + CUniqBlocks SecureBlocks; + CByteBuffer TempSecureBuf; + bool _saclEnabled; + bool ReadSecure; + + void AddSecurityItem(const FString &path, int &secureIndex); + + #endif + + CDirItems(); + + int GetNumFolders() const { return Prefixes.Size(); } + UString GetPhyPath(unsigned index) const; + UString GetLogPath(unsigned index) const; + + unsigned AddPrefix(int phyParent, int logParent, const UString &prefix); + void DeleteLastPrefix(); + void EnumerateItems2( const FString &phyPrefix, const UString &logPrefix, const FStringVector &filePaths, - FStringVector &errorPaths, CRecordVector &errorCodes); + FStringVector *requestedPaths); + + #if defined(_WIN32) && !defined(UNDER_CE) + void FillFixedReparse(); + #endif void ReserveDown(); }; @@ -57,13 +113,14 @@ struct CArcItem FILETIME MTime; UString Name; bool IsDir; + bool IsAltStream; bool SizeDefined; bool MTimeDefined; bool Censored; UInt32 IndexInServer; int TimeType; - CArcItem(): IsDir(false), SizeDefined(false), MTimeDefined(false), Censored(false), TimeType(-1) {} + CArcItem(): IsDir(false), IsAltStream(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 old mode 100755 new mode 100644 index 8c83a9fb..955f459c --- a/CPP/7zip/UI/Common/EnumDirItems.cpp +++ b/CPP/7zip/UI/Common/EnumDirItems.cpp @@ -2,7 +2,16 @@ #include "StdAfx.h" -#include "Windows/FileName.h" +#include "../../../Common/Wildcard.h" + +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileIO.h" +#include "../../../Windows/FileName.h" + +#if defined(_WIN32) && !defined(UNDER_CE) +#define _USE_SECURITY_CODE +#include "../../../Windows/SecurityUtils.h" +#endif #include "EnumDirItems.h" @@ -10,7 +19,7 @@ using namespace NWindows; using namespace NFile; using namespace NName; -void AddDirFileInfo(int phyParent, int logParent, +void AddDirFileInfo(int phyParent, int logParent, int secureIndex, const NFind::CFileInfo &fi, CObjectVector &dirItems) { CDirItem di; @@ -19,41 +28,46 @@ void AddDirFileInfo(int phyParent, int logParent, di.ATime = fi.ATime; di.MTime = fi.MTime; di.Attrib = fi.Attrib; + di.IsAltStream = fi.IsAltStream; di.PhyParent = phyParent; di.LogParent = logParent; + di.SecureIndex = secureIndex; di.Name = fs2us(fi.Name); + #if defined(_WIN32) && !defined(UNDER_CE) + // di.ShortName = fs2us(fi.ShortName); + #endif dirItems.Add(di); } UString CDirItems::GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const { UString path; - int len = name.Length(); + unsigned len = name.Len(); int i; for (i = index; i >= 0; i = parents[i]) - len += Prefixes[i].Length(); - int totalLen = len; + len += Prefixes[i].Len(); + unsigned 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)); + len -= name.Len(); + memcpy(p + len, (const wchar_t *)name, name.Len() * 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)); + len -= s.Len(); + memcpy(p + len, (const wchar_t *)s, s.Len() * sizeof(wchar_t)); } path.ReleaseBuffer(totalLen); return path; } -UString CDirItems::GetPhyPath(int index) const +UString CDirItems::GetPhyPath(unsigned index) const { const CDirItem &di = Items[index]; return GetPrefixesPath(PhyParents, di.PhyParent, di.Name); } -UString CDirItems::GetLogPath(int index) const +UString CDirItems::GetLogPath(unsigned index) const { const CDirItem &di = Items[index]; return GetPrefixesPath(LogParents, di.LogParent, di.Name); @@ -67,7 +81,7 @@ void CDirItems::ReserveDown() Items.ReserveDown(); } -int CDirItems::AddPrefix(int phyParent, int logParent, const UString &prefix) +unsigned CDirItems::AddPrefix(int phyParent, int logParent, const UString &prefix) { PhyParents.Add(phyParent); LogParents.Add(logParent); @@ -81,8 +95,77 @@ void CDirItems::DeleteLastPrefix() Prefixes.DeleteBack(); } -void CDirItems::EnumerateDirectory(int phyParent, int logParent, const FString &phyPrefix, - FStringVector &errorPaths, CRecordVector &errorCodes) +bool InitLocalPrivileges(); + +CDirItems::CDirItems(): + SymLinks(false), + TotalSize(0) + #ifdef _USE_SECURITY_CODE + , ReadSecure(false) + #endif +{ + #ifdef _USE_SECURITY_CODE + _saclEnabled = InitLocalPrivileges(); + #endif +} + +#ifdef _USE_SECURITY_CODE + +void CDirItems::AddSecurityItem(const FString &path, int &secureIndex) +{ + secureIndex = -1; + + SECURITY_INFORMATION securInfo = + DACL_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | + OWNER_SECURITY_INFORMATION; + if (_saclEnabled) + securInfo |= SACL_SECURITY_INFORMATION; + + DWORD errorCode = 0; + DWORD secureSize; + BOOL res = ::GetFileSecurityW(fs2us(path), securInfo, TempSecureBuf, (DWORD)TempSecureBuf.Size(), &secureSize); + if (res) + { + if (secureSize == 0) + return; + if (secureSize > TempSecureBuf.Size()) + errorCode = ERROR_INVALID_FUNCTION; + } + else + { + errorCode = GetLastError(); + if (errorCode == ERROR_INSUFFICIENT_BUFFER) + { + if (secureSize <= TempSecureBuf.Size()) + errorCode = ERROR_INVALID_FUNCTION; + else + { + TempSecureBuf.Alloc(secureSize); + res = ::GetFileSecurityW(fs2us(path), securInfo, TempSecureBuf, (DWORD)TempSecureBuf.Size(), &secureSize); + if (res) + { + if (secureSize != TempSecureBuf.Size()) + errorCode = ERROR_INVALID_FUNCTION;; + } + else + errorCode = GetLastError(); + } + } + } + if (res) + { + secureIndex = SecureBlocks.AddUniq(TempSecureBuf, secureSize); + return; + } + if (errorCode == 0) + errorCode = ERROR_INVALID_FUNCTION; + AddError(path, errorCode); +} + +#endif + +void CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phyPrefix) { NFind::CEnumerator enumerator(phyPrefix + FCHAR_ANY_MASK); for (;;) @@ -91,140 +174,320 @@ void CDirItems::EnumerateDirectory(int phyParent, int logParent, const FString & bool found; if (!enumerator.Next(fi, found)) { - errorCodes.Add(::GetLastError()); - errorPaths.Add(phyPrefix); + AddError(phyPrefix); return; } if (!found) break; - AddDirFileInfo(phyParent, logParent, fi, Items); + + int secureIndex = -1; + #ifdef _USE_SECURITY_CODE + if (ReadSecure) + AddSecurityItem(phyPrefix + fi.Name, secureIndex); + #endif + + AddDirFileInfo(phyParent, logParent, secureIndex, fi, Items); + if (fi.IsDir()) { const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR; - int parent = AddPrefix(phyParent, logParent, fs2us(name2)); - EnumerateDirectory(parent, parent, phyPrefix + name2, errorPaths, errorCodes); + unsigned parent = AddPrefix(phyParent, logParent, fs2us(name2)); + EnumerateDir(parent, parent, phyPrefix + name2); } } } -void CDirItems::EnumerateDirItems2(const FString &phyPrefix, const UString &logPrefix, - const FStringVector &filePaths, FStringVector &errorPaths, CRecordVector &errorCodes) +void CDirItems::EnumerateItems2( + const FString &phyPrefix, + const UString &logPrefix, + const FStringVector &filePaths, + FStringVector *requestedPaths) { int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, fs2us(phyPrefix)); int logParent = logPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, logPrefix); - for (int i = 0; i < filePaths.Size(); i++) + FOR_VECTOR (i, filePaths) { const FString &filePath = filePaths[i]; NFind::CFileInfo fi; const FString phyPath = phyPrefix + filePath; if (!fi.Find(phyPath)) { - errorCodes.Add(::GetLastError()); - errorPaths.Add(phyPath); + AddError(phyPath); continue; } + if (requestedPaths) + requestedPaths->Add(phyPath); + int delimiter = filePath.ReverseFind(FCHAR_PATH_SEPARATOR); FString phyPrefixCur; int phyParentCur = phyParent; if (delimiter >= 0) { - phyPrefixCur = filePath.Left(delimiter + 1); + phyPrefixCur.SetFrom(filePath, delimiter + 1); phyParentCur = AddPrefix(phyParent, logParent, fs2us(phyPrefixCur)); } - AddDirFileInfo(phyParentCur, logParent, fi, Items); + + int secureIndex = -1; + #ifdef _USE_SECURITY_CODE + if (ReadSecure) + AddSecurityItem(phyPath, secureIndex); + #endif + + AddDirFileInfo(phyParentCur, logParent, secureIndex, fi, Items); + if (fi.IsDir()) { const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR; - int parent = AddPrefix(phyParentCur, logParent, fs2us(name2)); - EnumerateDirectory(parent, parent, phyPrefix + phyPrefixCur + name2, errorPaths, errorCodes); + unsigned parent = AddPrefix(phyParentCur, logParent, fs2us(name2)); + EnumerateDir(parent, parent, phyPrefix + phyPrefixCur + name2); } } ReserveDown(); } -static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, + + + + + +static HRESULT EnumerateDirItems( + const NWildcard::CCensorNode &curNode, int phyParent, int logParent, const FString &phyPrefix, const UStringVector &addArchivePrefix, CDirItems &dirItems, bool enterToSubFolders, - IEnumDirItemCallback *callback, - FStringVector &errorPaths, - CRecordVector &errorCodes); + IEnumDirItemCallback *callback); -static HRESULT EnumerateDirItems_Spec(const NWildcard::CCensorNode &curNode, +static HRESULT EnumerateDirItems_Spec( + const NWildcard::CCensorNode &curNode, int phyParent, int logParent, const FString &curFolderName, const FString &phyPrefix, const UStringVector &addArchivePrefix, CDirItems &dirItems, bool enterToSubFolders, - IEnumDirItemCallback *callback, - FStringVector &errorPaths, - CRecordVector &errorCodes) - + IEnumDirItemCallback *callback) { const FString name2 = curFolderName + FCHAR_PATH_SEPARATOR; - int parent = dirItems.AddPrefix(phyParent, logParent, fs2us(name2)); - int numItems = dirItems.Items.Size(); - HRESULT res = EnumerateDirItems(curNode, parent, parent, phyPrefix + name2, - addArchivePrefix, dirItems, enterToSubFolders, callback, errorPaths, errorCodes); + unsigned parent = dirItems.AddPrefix(phyParent, logParent, fs2us(name2)); + unsigned numItems = dirItems.Items.Size(); + HRESULT res = EnumerateDirItems( + curNode, parent, parent, phyPrefix + name2, + addArchivePrefix, dirItems, enterToSubFolders, callback); if (numItems == dirItems.Items.Size()) dirItems.DeleteLastPrefix(); return res; } +#ifndef UNDER_CE + +static void EnumerateAltStreams( + const NFind::CFileInfo &fi, + const NWildcard::CCensorNode &curNode, + int phyParent, int logParent, const FString &phyPrefix, + const UStringVector &addArchivePrefix, // prefix from curNode + CDirItems &dirItems) +{ + const FString fullPath = phyPrefix + fi.Name; + NFind::CStreamEnumerator enumerator(fullPath); + for (;;) + { + NFind::CStreamInfo si; + bool found; + if (!enumerator.Next(si, found)) + { + dirItems.AddError(fullPath + FTEXT(":*"), (DWORD)E_FAIL); + break; + } + if (!found) + break; + if (si.IsMainStream()) + continue; + UStringVector addArchivePrefixNew = addArchivePrefix; + UString reducedName = si.GetReducedName(); + addArchivePrefixNew.Back() += reducedName; + if (curNode.CheckPathToRoot(false, addArchivePrefixNew, true)) + continue; + NFind::CFileInfo fi2 = fi; + fi2.Name += us2fs(reducedName); + fi2.Size = si.Size; + fi2.Attrib &= ~FILE_ATTRIBUTE_DIRECTORY; + fi2.IsAltStream = true; + AddDirFileInfo(phyParent, logParent, -1, fi2, dirItems.Items); + dirItems.TotalSize += fi2.Size; + } +} + +void CDirItems::SetLinkInfo(CDirItem &dirItem, const NFind::CFileInfo &fi, + const FString &phyPrefix) +{ + if (!SymLinks || !fi.HasReparsePoint()) + return; + const FString path = phyPrefix + fi.Name; + CByteBuffer &buf = dirItem.ReparseData; + if (NIO::GetReparseData(path, buf)) + { + CReparseAttr attr; + if (attr.Parse(buf, buf.Size())) + return; + } + AddError(path); + buf.Free(); +} + +#endif + +static HRESULT EnumerateForItem( + NFind::CFileInfo &fi, + const NWildcard::CCensorNode &curNode, + int phyParent, int logParent, const FString &phyPrefix, + const UStringVector &addArchivePrefix, // prefix from curNode + CDirItems &dirItems, + bool enterToSubFolders, + IEnumDirItemCallback *callback) +{ + const UString name = fs2us(fi.Name); + bool enterToSubFolders2 = enterToSubFolders; + UStringVector addArchivePrefixNew = addArchivePrefix; + addArchivePrefixNew.Add(name); + { + UStringVector addArchivePrefixNewTemp(addArchivePrefixNew); + if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fi.IsDir())) + return S_OK; + } + int dirItemIndex = -1; + + if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir())) + { + int secureIndex = -1; + #ifdef _USE_SECURITY_CODE + if (dirItems.ReadSecure) + dirItems.AddSecurityItem(phyPrefix + fi.Name, secureIndex); + #endif + + dirItemIndex = dirItems.Items.Size(); + AddDirFileInfo(phyParent, logParent, secureIndex, fi, dirItems.Items); + dirItems.TotalSize += fi.Size; + if (fi.IsDir()) + enterToSubFolders2 = true; + } + + #ifndef UNDER_CE + if (dirItems.ScanAltStreams) + { + EnumerateAltStreams(fi, curNode, phyParent, logParent, phyPrefix, + addArchivePrefixNew, dirItems); + } + + if (dirItemIndex >= 0) + { + CDirItem &dirItem = dirItems.Items[dirItemIndex]; + dirItems.SetLinkInfo(dirItem, fi, phyPrefix); + if (dirItem.ReparseData.Size() != 0) + return S_OK; + } + #endif + + if (!fi.IsDir()) + return S_OK; + + const NWildcard::CCensorNode *nextNode = 0; + if (addArchivePrefix.IsEmpty()) + { + int index = curNode.FindSubNode(name); + if (index >= 0) + nextNode = &curNode.SubNodes[index]; + } + if (!enterToSubFolders2 && nextNode == 0) + return S_OK; + + addArchivePrefixNew = addArchivePrefix; + if (nextNode == 0) + { + nextNode = &curNode; + addArchivePrefixNew.Add(name); + } + + return EnumerateDirItems_Spec( + *nextNode, phyParent, logParent, fi.Name, phyPrefix, + addArchivePrefixNew, + dirItems, + enterToSubFolders2, callback); +} + + +static bool CanUseFsDirect(const NWildcard::CCensorNode &curNode) +{ + FOR_VECTOR (i, curNode.IncludeItems) + { + const NWildcard::CItem &item = curNode.IncludeItems[i]; + if (item.Recursive || item.PathParts.Size() != 1) + return false; + const UString &name = item.PathParts.Front(); + if (name.IsEmpty()) + return false; + + /* Windows doesn't support file name with wildcard. + but if another system supports file name with wildcard, + and wildcard mode is disabled, we can ignore wildcard in name */ + /* + if (!item.WildcardParsing) + continue; + */ + if (DoesNameContainWildcard(name)) + return false; + } + return true; +} + -static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, +static HRESULT EnumerateDirItems( + const NWildcard::CCensorNode &curNode, int phyParent, int logParent, const FString &phyPrefix, const UStringVector &addArchivePrefix, // prefix from curNode CDirItems &dirItems, bool enterToSubFolders, - IEnumDirItemCallback *callback, - FStringVector &errorPaths, - CRecordVector &errorCodes) + IEnumDirItemCallback *callback) { if (!enterToSubFolders) if (curNode.NeedCheckSubDirs()) enterToSubFolders = true; if (callback) - RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), fs2us(phyPrefix))); + RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), dirItems.TotalSize, fs2us(phyPrefix), true)); // 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()) + if (CanUseFsDirect(curNode)) { // all names are direct (no wildcards) // so we don't need file_system's dir enumerator CRecordVector needEnterVector; + unsigned i; + for (i = 0; i < curNode.IncludeItems.Size(); i++) { const NWildcard::CItem &item = curNode.IncludeItems[i]; const UString &name = item.PathParts.Front(); const FString fullPath = phyPrefix + us2fs(name); NFind::CFileInfo fi; + #ifdef _WIN32 + if (phyPrefix.IsEmpty() && item.IsDriveItem()) + { + fi.SetAsDir(); + fi.Name = fullPath; + } + else + #endif if (!fi.Find(fullPath)) { - errorCodes.Add(::GetLastError()); - errorPaths.Add(fullPath); + dirItems.AddError(fullPath); continue; } bool isDir = fi.IsDir(); if (isDir && !item.ForDir || !isDir && !item.ForFile) { - errorCodes.Add((DWORD)E_FAIL); - errorPaths.Add(fullPath); + dirItems.AddError(fullPath, (DWORD)E_FAIL); continue; } { @@ -233,7 +496,36 @@ static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, if (curNode.CheckPathToRoot(false, pathParts, !isDir)) continue; } - AddDirFileInfo(phyParent, logParent, fi, dirItems.Items); + + int secureIndex = -1; + #ifdef _USE_SECURITY_CODE + if (dirItems.ReadSecure) + dirItems.AddSecurityItem(fullPath, secureIndex); + #endif + + AddDirFileInfo(phyParent, logParent, secureIndex, fi, dirItems.Items); + + #ifndef UNDER_CE + { + CDirItem &dirItem = dirItems.Items.Back(); + dirItems.SetLinkInfo(dirItem, fi, phyPrefix); + if (dirItem.ReparseData.Size() != 0) + continue; + } + #endif + + dirItems.TotalSize += fi.Size; + + #ifndef UNDER_CE + if (dirItems.ScanAltStreams) + { + UStringVector pathParts; + pathParts.Add(fs2us(fi.Name)); + EnumerateAltStreams(fi, curNode, phyParent, logParent, phyPrefix, + pathParts, dirItems); + } + #endif + if (!isDir) continue; @@ -254,8 +546,9 @@ static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, } RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix, - addArchivePrefixNew, dirItems, true, callback, errorPaths, errorCodes)); + addArchivePrefixNew, dirItems, true, callback)); } + for (i = 0; i < curNode.SubNodes.Size(); i++) { if (i < needEnterVector.Size()) @@ -264,100 +557,201 @@ static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i]; const FString fullPath = phyPrefix + us2fs(nextNode.Name); NFind::CFileInfo fi; + #ifdef _WIN32 + if (phyPrefix.IsEmpty() && NWildcard::IsDriveColonName(nextNode.Name)) + { + fi.SetAsDir(); + fi.Name = fullPath; + } + else + #endif if (!fi.Find(fullPath)) { if (!nextNode.AreThereIncludeItems()) continue; - errorCodes.Add(::GetLastError()); - errorPaths.Add(fullPath); + dirItems.AddError(fullPath); continue; } if (!fi.IsDir()) { - errorCodes.Add((DWORD)E_FAIL); - errorPaths.Add(fullPath); + dirItems.AddError(fullPath, (DWORD)E_FAIL); continue; } RINOK(EnumerateDirItems_Spec(nextNode, phyParent, logParent, fi.Name, phyPrefix, - UStringVector(), dirItems, false, callback, errorPaths, errorCodes)); + UStringVector(), dirItems, false, callback)); } + return S_OK; } } + #ifdef _WIN32 + #ifndef UNDER_CE + + // scan drives, if wildcard is "*:\" + + if (phyPrefix.IsEmpty() && curNode.IncludeItems.Size() > 0) + { + unsigned i; + for (i = 0; i < curNode.IncludeItems.Size(); i++) + { + const NWildcard::CItem &item = curNode.IncludeItems[i]; + if (item.PathParts.Size() < 1) + break; + const UString &name = item.PathParts.Front(); + if (name.Len() != 2 || name[1] != ':') + break; + if (item.PathParts.Size() == 1) + if (item.ForFile || !item.ForDir) + break; + if (NWildcard::IsDriveColonName(name)) + continue; + if (name[0] != '*' && name[0] != '?') + break; + } + if (i == curNode.IncludeItems.Size()) + { + FStringVector driveStrings; + NFind::MyGetLogicalDriveStrings(driveStrings); + for (i = 0; i < driveStrings.Size(); i++) + { + FString driveName = driveStrings[i]; + if (driveName.Len() < 3 || driveName.Back() != '\\') + return E_FAIL; + driveName.DeleteBack(); + NFind::CFileInfo fi; + fi.SetAsDir(); + fi.Name = driveName; + + RINOK(EnumerateForItem(fi, curNode, phyParent, logParent, phyPrefix, + addArchivePrefix, dirItems, enterToSubFolders, callback)); + } + return S_OK; + } + } + + #endif + #endif NFind::CEnumerator enumerator(phyPrefix + FCHAR_ANY_MASK); - for (int ttt = 0; ; ttt++) + for (unsigned ttt = 0; ; ttt++) { NFind::CFileInfo fi; bool found; if (!enumerator.Next(fi, found)) { - errorCodes.Add(::GetLastError()); - errorPaths.Add(phyPrefix); + dirItems.AddError(phyPrefix); break; } if (!found) break; if (callback && (ttt & 0xFF) == 0xFF) - RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), fs2us(phyPrefix))); - const UString &name = fs2us(fi.Name); - bool enterToSubFolders2 = enterToSubFolders; - UStringVector addArchivePrefixNew = addArchivePrefix; - addArchivePrefixNew.Add(name); - { - UStringVector addArchivePrefixNewTemp(addArchivePrefixNew); - if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fi.IsDir())) - continue; - } - if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir())) - { - AddDirFileInfo(phyParent, logParent, fi, dirItems.Items); - if (fi.IsDir()) - enterToSubFolders2 = true; - } - if (!fi.IsDir()) - continue; + RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), dirItems.TotalSize, fs2us(phyPrefix), true)); - 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, fi.Name, phyPrefix, - addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes)); + RINOK(EnumerateForItem(fi, curNode, phyParent, logParent, phyPrefix, + addArchivePrefix, dirItems, enterToSubFolders, callback)); } return S_OK; } HRESULT EnumerateItems( const NWildcard::CCensor &censor, + const NWildcard::ECensorPathMode pathMode, + const UString &addPathPrefix, CDirItems &dirItems, - IEnumDirItemCallback *callback, - FStringVector &errorPaths, - CRecordVector &errorCodes) + IEnumDirItemCallback *callback) { - for (int i = 0; i < censor.Pairs.Size(); i++) + FOR_VECTOR (i, censor.Pairs) { 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, us2fs(pair.Prefix), UStringVector(), dirItems, false, - callback, errorPaths, errorCodes)); + int logParent = -1; + + if (pathMode == NWildcard::k_AbsPath) + logParent = phyParent; + else + { + if (!addPathPrefix.IsEmpty()) + logParent = dirItems.AddPrefix(-1, -1, addPathPrefix); + } + + RINOK(EnumerateDirItems(pair.Head, phyParent, logParent, us2fs(pair.Prefix), UStringVector(), + dirItems, + false, // enterToSubFolders + callback)); } dirItems.ReserveDown(); + + #if defined(_WIN32) && !defined(UNDER_CE) + dirItems.FillFixedReparse(); + #endif + return S_OK; } + +#if defined(_WIN32) && !defined(UNDER_CE) + +void CDirItems::FillFixedReparse() +{ + /* imagex/WIM reduces absolute pathes in links (raparse data), + if we archive non root folder. We do same thing here */ + + if (!SymLinks) + return; + + FOR_VECTOR(i, Items) + { + CDirItem &item = Items[i]; + if (item.ReparseData.Size() == 0) + continue; + + CReparseAttr attr; + if (!attr.Parse(item.ReparseData, item.ReparseData.Size())) + continue; + if (attr.IsRelative()) + continue; + + const UString &link = attr.GetPath(); + if (!IsDrivePath(link)) + continue; + // maybe we need to support networks paths also ? + + FString fullPathF; + if (!NDir::MyGetFullPathName(us2fs(GetPhyPath(i)), fullPathF)) + continue; + UString fullPath = fs2us(fullPathF); + const UString logPath = GetLogPath(i); + if (logPath.Len() >= fullPath.Len()) + continue; + if (CompareFileNames(logPath, fullPath.RightPtr(logPath.Len())) != 0) + continue; + + const UString prefix = fullPath.Left(fullPath.Len() - logPath.Len()); + if (prefix.Back() != WCHAR_PATH_SEPARATOR) + continue; + + unsigned rootPrefixSize = GetRootPrefixSize(prefix); + if (rootPrefixSize == 0) + continue; + if (rootPrefixSize == prefix.Len()) + continue; // simple case: paths are from root + + if (link.Len() <= prefix.Len()) + continue; + + if (CompareFileNames(link.Left(prefix.Len()), prefix) != 0) + continue; + + UString newLink = prefix.Left(rootPrefixSize); + newLink += link.Ptr(prefix.Len()); + + CByteBuffer data; + if (!FillLinkData(data, newLink, attr.IsSymLink())) + continue; + item.ReparseData2 = data; + } +} + +#endif diff --git a/CPP/7zip/UI/Common/EnumDirItems.h b/CPP/7zip/UI/Common/EnumDirItems.h old mode 100755 new mode 100644 index c96c7b9e..803a64e7 --- a/CPP/7zip/UI/Common/EnumDirItems.h +++ b/CPP/7zip/UI/Common/EnumDirItems.h @@ -3,23 +3,25 @@ #ifndef __ENUM_DIR_ITEMS_H #define __ENUM_DIR_ITEMS_H -#include "Common/Wildcard.h" -#include "Windows/FileFind.h" +#include "../../../Common/Wildcard.h" + +#include "../../../Windows/FileFind.h" + #include "DirItem.h" -void AddDirFileInfo(int phyParent, int logParent, +void AddDirFileInfo(int phyParent, int logParent, int secureIndex, const NWindows::NFile::NFind::CFileInfo &fi, CObjectVector &dirItems); struct IEnumDirItemCallback { - virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) = 0; + virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) = 0; }; HRESULT EnumerateItems( const NWildcard::CCensor &censor, + NWildcard::ECensorPathMode pathMode, + const UString &addPathPrefix, CDirItems &dirItems, - IEnumDirItemCallback *callback, - FStringVector &errorPaths, - CRecordVector &errorCodes); + IEnumDirItemCallback *callback); #endif diff --git a/CPP/7zip/UI/Common/ExitCode.h b/CPP/7zip/UI/Common/ExitCode.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp old mode 100755 new mode 100644 index 81186772..891cc7d8 --- a/CPP/7zip/UI/Common/Extract.cpp +++ b/CPP/7zip/UI/Common/Extract.cpp @@ -2,11 +2,13 @@ #include "StdAfx.h" -#include +#include "../../../../C/Sort.h" -#include "Windows/FileDir.h" -#include "Windows/PropVariant.h" -#include "Windows/PropVariantConversions.h" +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/FileDir.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/PropVariantConv.h" #include "../Common/ExtractingFilePath.h" @@ -14,54 +16,117 @@ #include "SetProperties.h" using namespace NWindows; +using namespace NFile; +using namespace NDir; static HRESULT DecompressArchive( - const CArc &arc, + CCodecs *codecs, + const CArchiveLink &arcLink, UInt64 packSize, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, + bool calcCrc, IExtractCallbackUI *callback, - CArchiveExtractCallback *extractCallbackSpec, + CArchiveExtractCallback *ecs, UString &errorMessage, UInt64 &stdInProcessed) { + const CArc &arc = arcLink.Arcs.Back(); stdInProcessed = 0; IInArchive *archive = arc.Archive; CRecordVector realIndices; + + UStringVector removePathParts; + + FString outDir = options.OutputDir; + UString replaceName = arc.DefaultName; + + if (arcLink.Arcs.Size() > 1) + { + // Most "pe" archives have same name of archive subfile "[0]" or ".rsrc_1". + // So it extracts different archives to one folder. + // We will use top level archive name + const CArc &arc0 = arcLink.Arcs[0]; + if (StringsAreEqualNoCase_Ascii(codecs->Formats[arc0.FormatIndex].Name, "pe")) + replaceName = arc0.DefaultName; + } + + outDir.Replace(FSTRING_ANY_MASK, us2fs(GetCorrectFsPath(replaceName))); + + bool elimIsPossible = false; + UString elimPrefix; // only pure name without dir delimiter + FString outDirReduced = outDir; + + if (options.ElimDup.Val) + { + UString dirPrefix; + SplitPathToParts_Smart(fs2us(outDir), dirPrefix, elimPrefix); + if (!elimPrefix.IsEmpty()) + { + if (IsCharDirLimiter(elimPrefix.Back())) + elimPrefix.DeleteBack(); + if (!elimPrefix.IsEmpty()) + { + outDirReduced = us2fs(dirPrefix); + elimIsPossible = true; + } + } + } + if (!options.StdInMode) { UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); + UString filePath; + for (UInt32 i = 0; i < numItems; i++) { - UString filePath; RINOK(arc.GetItemPath(i, filePath)); + + if (elimIsPossible && options.ElimDup.Val) + { + if (!IsPath1PrefixedByPath2(filePath, elimPrefix)) + elimIsPossible = false; + else + { + wchar_t c = filePath[elimPrefix.Len()]; + if (c != 0 && !IsCharDirLimiter(c)) + elimIsPossible = false; + } + } + bool isFolder; - RINOK(IsArchiveItemFolder(archive, i, isFolder)); - if (!wildcardCensor.CheckPath(filePath, !isFolder)) + RINOK(Archive_IsItem_Folder(archive, i, isFolder)); + bool isAltStream; + RINOK(Archive_IsItem_AltStream(archive, i, isAltStream)); + if (!options.NtOptions.AltStreams.Val && isAltStream) + continue; + if (!wildcardCensor.CheckPath(isAltStream, filePath, !isFolder)) continue; realIndices.Add(i); } + if (realIndices.Size() == 0) { callback->ThereAreNoFiles(); - return S_OK; + return callback->ExtractResult(S_OK); } } - UStringVector removePathParts; + if (elimIsPossible) + outDir = outDirReduced; - FString outDir = options.OutputDir; - outDir.Replace(FSTRING_ANY_MASK, us2fs(GetCorrectFsPath(arc.DefaultName))); #ifdef _WIN32 // GetCorrectFullFsPath doesn't like "..". // outDir.TrimRight(); // outDir = GetCorrectFullFsPath(outDir); #endif - if (!outDir.IsEmpty()) - if (!NFile::NDirectory::CreateComplexDirectory(outDir)) + if (outDir.IsEmpty()) + outDir = FString(FTEXT(".")) + FString(FSTRING_PATH_SEPARATOR); + else + if (!CreateComplexDir(outDir)) { HRESULT res = ::GetLastError(); if (res == S_OK) @@ -70,55 +135,92 @@ static HRESULT DecompressArchive( return res; } - extractCallbackSpec->Init( + ecs->Init( + options.NtOptions, options.StdInMode ? &wildcardCensor : NULL, &arc, callback, - options.StdOutMode, options.TestMode, options.CalcCrc, + options.StdOutMode, options.TestMode, outDir, removePathParts, packSize); - #if !defined(_7ZIP_ST) && !defined(_SFX) - RINOK(SetProperties(archive, options.Properties)); + + #ifdef SUPPORT_LINKS + + if (!options.StdInMode && + !options.TestMode && + options.NtOptions.HardLinks.Val) + { + RINOK(ecs->PrepareHardLinks(&realIndices)); + } + #endif + HRESULT result; - Int32 testMode = (options.TestMode && !options.CalcCrc) ? 1: 0; + Int32 testMode = (options.TestMode && !calcCrc) ? 1: 0; if (options.StdInMode) { - result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, extractCallbackSpec); + result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, ecs); NCOM::CPropVariant prop; if (archive->GetArchiveProperty(kpidPhySize, &prop) == S_OK) - if (prop.vt == VT_UI8 || prop.vt == VT_UI4) - stdInProcessed = ConvertPropVariantToUInt64(prop); + ConvertPropVariantToUInt64(prop, stdInProcessed); } else - result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, extractCallbackSpec); - + result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, ecs); + if (result == S_OK) + result = ecs->SetDirsTimes(); return callback->ExtractResult(result); } -HRESULT DecompressArchives( - CCodecs *codecs, const CIntVector &formatIndices, +/* v9.31: BUG was fixed: + Sorted list for file paths was sorted with case insensitive compare function. + But FindInSorted function did binary search via case sensitive compare function */ + +int Find_FileName_InSortedVector(const UStringVector &fileName, const UString &name) +{ + unsigned left = 0, right = fileName.Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + const UString &midValue = fileName[mid]; + int compare = CompareFileNames(name, midValue); + if (compare == 0) + return mid; + if (compare < 0) + right = mid; + else + left = mid + 1; + } + return -1; +} + +HRESULT Extract( + CCodecs *codecs, + const CObjectVector &types, + const CIntVector &excludedFormats, UStringVector &arcPaths, UStringVector &arcPathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, + #ifndef _SFX + IHashCalc *hash, + #endif UString &errorMessage, CDecompressStat &stat) { stat.Clear(); - int i; UInt64 totalPackSize = 0; - CRecordVector archiveSizes; + CRecordVector arcSizes; - int numArcs = options.StdInMode ? 1 : arcPaths.Size(); + unsigned numArcs = options.StdInMode ? 1 : arcPaths.Size(); + unsigned i; for (i = 0; i < numArcs; i++) { - NFile::NFind::CFileInfo fi; + NFind::CFileInfo fi; fi.Size = 0; if (!options.StdInMode) { @@ -128,21 +230,37 @@ HRESULT DecompressArchives( if (fi.IsDir()) throw "can't decompress folder"; } - archiveSizes.Add(fi.Size); + arcSizes.Add(fi.Size); totalPackSize += fi.Size; } - CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; - CMyComPtr ec(extractCallbackSpec); + + CBoolArr skipArcs(numArcs); + for (i = 0; i < numArcs; i++) + skipArcs[i] = false; + + CArchiveExtractCallback *ecs = new CArchiveExtractCallback; + CMyComPtr ec(ecs); bool multi = (numArcs > 1); - extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode); + ecs->InitForMulti(multi, options.PathMode, options.OverwriteMode); + #ifndef _SFX + ecs->SetHashMethods(hash); + #endif + if (multi) { RINOK(extractCallback->SetTotal(totalPackSize)); } + + UInt64 totalPackProcessed = 0; + bool thereAreNotOpenArcs = false; + for (i = 0; i < numArcs; i++) { + if (skipArcs[i]) + continue; + const UString &arcPath = arcPaths[i]; - NFile::NFind::CFileInfo fi; + NFind::CFileInfo fi; if (options.StdInMode) { fi.Size = 0; @@ -159,16 +277,17 @@ HRESULT DecompressArchives( #endif RINOK(extractCallback->BeforeOpen(arcPath)); - CArchiveLink archiveLink; + CArchiveLink arcLink; - CIntVector formatIndices2 = formatIndices; + CObjectVector types2 = types; + /* #ifndef _SFX - if (formatIndices.IsEmpty()) + if (types.IsEmpty()) { int pos = arcPath.ReverseFind(L'.'); if (pos >= 0) { - UString s = arcPath.Mid(pos + 1); + UString s = arcPath.Ptr(pos + 1); int index = codecs->FindFormatForExtension(s); if (index >= 0 && s == L"001") { @@ -176,18 +295,31 @@ HRESULT DecompressArchives( pos = s.ReverseFind(L'.'); if (pos >= 0) { - int index2 = codecs->FindFormatForExtension(s.Mid(pos + 1)); - if (index2 >= 0 && s.CompareNoCase(L"rar") != 0) + int index2 = codecs->FindFormatForExtension(s.Ptr(pos + 1)); + if (index2 >= 0) // && s.CompareNoCase(L"rar") != 0 { - formatIndices2.Add(index2); - formatIndices2.Add(index); + types2.Add(index2); + types2.Add(index); } } } } } #endif - HRESULT result = archiveLink.Open2(codecs, formatIndices2, options.StdInMode, NULL, arcPath, openCallback); + */ + + COpenOptions op; + #ifndef _SFX + op.props = &options.Properties; + #endif + op.codecs = codecs; + op.types = &types2; + op.excludedFormats = &excludedFormats; + op.stdInMode = options.StdInMode; + op.stream = NULL; + op.filePath = arcPath; + HRESULT result = arcLink.Open2(op, openCallback); + if (result == E_ABORT) return result; @@ -196,68 +328,148 @@ HRESULT DecompressArchives( crypted = openCallback->Open_WasPasswordAsked(); #endif + if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) + result = S_FALSE; + + // arcLink.Set_ErrorsText(); RINOK(extractCallback->OpenResult(arcPath, result, crypted)); + + + { + FOR_VECTOR (r, arcLink.Arcs) + { + const CArc &arc = arcLink.Arcs[r]; + const CArcErrorInfo &er = arc.ErrorInfo; + if (er.IsThereErrorOrWarning()) + { + RINOK(extractCallback->SetError(r, arc.Path, + er.GetErrorFlags(), er.ErrorMessage, + er.GetWarningFlags(), er.WarningMessage)); + } + } + } + if (result != S_OK) + { + thereAreNotOpenArcs = true; + if (!options.StdInMode) + { + NFind::CFileInfo fi; + if (fi.Find(us2fs(arcPath))) + if (!fi.IsDir()) + totalPackProcessed += fi.Size; + } 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) + // numVolumes += arcLink.VolumePaths.Size(); + // arcLink.VolumesSize; + + // totalPackSize -= DeleteUsedFileNamesFromList(arcLink, i + 1, arcPaths, arcPathsFull, &arcSizes); + // numArcs = arcPaths.Size(); + if (arcLink.VolumePaths.Size() != 0) { - arcPaths.Delete(index); - arcPathsFull.Delete(index); - totalPackSize -= archiveSizes[index]; - archiveSizes.Delete(index); - numArcs = arcPaths.Size(); + Int64 correctionSize = arcLink.VolumesSize; + FOR_VECTOR (v, arcLink.VolumePaths) + { + int index = Find_FileName_InSortedVector(arcPathsFull, arcLink.VolumePaths[v]); + if (index >= 0) + { + if ((unsigned)index > i) + { + skipArcs[index] = true; + correctionSize -= arcSizes[index]; + } + } + } + if (correctionSize != 0) + { + Int64 newPackSize = (Int64)totalPackSize + correctionSize; + if (newPackSize < 0) + newPackSize = 0; + totalPackSize = newPackSize; + RINOK(extractCallback->SetTotal(totalPackSize)); + } } } - if (archiveLink.VolumePaths.Size() != 0) - { - totalPackSize += archiveLink.VolumesSize; - RINOK(extractCallback->SetTotal(totalPackSize)); - } #ifndef _NO_CRYPTO + bool passwordIsDefined; UString password; - RINOK(openCallback->Open_GetPasswordIfAny(password)); - if (!password.IsEmpty()) + RINOK(openCallback->Open_GetPasswordIfAny(passwordIsDefined, password)); + if (passwordIsDefined) { RINOK(extractCallback->SetPassword(password)); } #endif - for (int v = 0; v < archiveLink.Arcs.Size(); v++) + FOR_VECTOR (k, arcLink.Arcs) { - const UString &s = archiveLink.Arcs[v].ErrorMessage; - if (!s.IsEmpty()) + const CArc &arc = arcLink.Arcs[k]; + const CArcErrorInfo &er = arc.ErrorInfo; + + if (er.ErrorFormatIndex >= 0) { + RINOK(extractCallback->OpenTypeWarning(arc.Path, + codecs->GetFormatNamePtr(arc.FormatIndex), + codecs->GetFormatNamePtr(er.ErrorFormatIndex))) + /* + UString s = L"Can not open the file as [" + codecs->Formats[arc.ErrorFormatIndex].Name + L"] archive\n"; + s += L"The file is open as [" + codecs->Formats[arc.FormatIndex].Name + L"] archive"; RINOK(extractCallback->MessageError(s)); + */ + } + { + const UString &s = er.ErrorMessage; + if (!s.IsEmpty()) + { + RINOK(extractCallback->MessageError(s)); + } } } - CArc &arc = archiveLink.Arcs.Back(); + CArc &arc = arcLink.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)); + bool calcCrc = + #ifndef _SFX + (hash != NULL); + #else + false; + #endif + + RINOK(DecompressArchive( + codecs, + arcLink, + fi.Size + arcLink.VolumesSize, + wildcardCensor, + options, + calcCrc, + extractCallback, ecs, errorMessage, packProcessed)); if (!options.StdInMode) - packProcessed = fi.Size + archiveLink.VolumesSize; - extractCallbackSpec->LocalProgressSpec->InSize += packProcessed; - extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize; + packProcessed = fi.Size + arcLink.VolumesSize; + totalPackProcessed += packProcessed; + ecs->LocalProgressSpec->InSize += packProcessed; + ecs->LocalProgressSpec->OutSize = ecs->UnpackSize; if (!errorMessage.IsEmpty()) return E_FAIL; } - stat.NumFolders = extractCallbackSpec->NumFolders; - stat.NumFiles = extractCallbackSpec->NumFiles; - stat.UnpackSize = extractCallbackSpec->UnpackSize; - stat.CrcSum = extractCallbackSpec->CrcSum; + if (multi || thereAreNotOpenArcs) + { + RINOK(extractCallback->SetTotal(totalPackSize)); + RINOK(extractCallback->SetCompleted(&totalPackProcessed)); + } + stat.NumFolders = ecs->NumFolders; + stat.NumFiles = ecs->NumFiles; + stat.NumAltStreams = ecs->NumAltStreams; + stat.UnpackSize = ecs->UnpackSize; + stat.AltStreams_UnpackSize = ecs->AltStreams_UnpackSize; stat.NumArchives = arcPaths.Size(); - stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize; + stat.PackSize = ecs->LocalProgressSpec->InSize; return S_OK; } diff --git a/CPP/7zip/UI/Common/Extract.h b/CPP/7zip/UI/Common/Extract.h old mode 100755 new mode 100644 index 2904a0ab..e6bd5cb7 --- a/CPP/7zip/UI/Common/Extract.h +++ b/CPP/7zip/UI/Common/Extract.h @@ -3,7 +3,7 @@ #ifndef __EXTRACT_H #define __EXTRACT_H -#include "Windows/FileFind.h" +#include "../../../Windows/FileFind.h" #include "../../Archive/IArchive.h" @@ -14,21 +14,37 @@ #include "../Common/LoadCodecs.h" -struct CExtractOptions +struct CExtractOptionsBase +{ + CBoolPair ElimDup; + + bool PathMode_Force; + bool OverwriteMode_Force; + NExtract::NPathMode::EEnum PathMode; + NExtract::NOverwriteMode::EEnum OverwriteMode; + + FString OutputDir; + CExtractNtOptions NtOptions; + + CExtractOptionsBase(): + PathMode_Force(false), + OverwriteMode_Force(false), + PathMode(NExtract::NPathMode::kFullPaths), + OverwriteMode(NExtract::NOverwriteMode::kAsk) + {} +}; + +struct CExtractOptions: public CExtractOptionsBase { bool StdInMode; bool StdOutMode; bool YesToAll; bool TestMode; - bool CalcCrc; - NExtract::NPathMode::EEnum PathMode; - NExtract::NOverwriteMode::EEnum OverwriteMode; - FString OutputDir; // bool ShowDialog; // bool PasswordEnabled; // UString Password; - #if !defined(_7ZIP_ST) && !defined(_SFX) + #ifndef _SFX CObjectVector Properties; #endif @@ -37,13 +53,10 @@ struct CExtractOptions #endif CExtractOptions(): + TestMode(false), StdInMode(false), StdOutMode(false), - YesToAll(false), - TestMode(false), - CalcCrc(false), - PathMode(NExtract::NPathMode::kFullPathnames), - OverwriteMode(NExtract::NOverwriteMode::kAskBefore) + YesToAll(false) {} }; @@ -51,25 +64,30 @@ struct CDecompressStat { UInt64 NumArchives; UInt64 UnpackSize; + UInt64 AltStreams_UnpackSize; UInt64 PackSize; UInt64 NumFolders; UInt64 NumFiles; - UInt32 CrcSum; + UInt64 NumAltStreams; void Clear() { - NumArchives = UnpackSize = PackSize = NumFolders = NumFiles = 0; - CrcSum = 0; + NumArchives = UnpackSize = AltStreams_UnpackSize = PackSize = NumFolders = NumFiles = NumAltStreams = 0; } }; -HRESULT DecompressArchives( - CCodecs *codecs, const CIntVector &formatIndices, +HRESULT Extract( + CCodecs *codecs, + const CObjectVector &types, + const CIntVector &excludedFormats, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, + #ifndef _SFX + IHashCalc *hash, + #endif UString &errorMessage, CDecompressStat &stat); diff --git a/CPP/7zip/UI/Common/ExtractMode.h b/CPP/7zip/UI/Common/ExtractMode.h old mode 100755 new mode 100644 index b448fb30..c2e43f6a --- a/CPP/7zip/UI/Common/ExtractMode.h +++ b/CPP/7zip/UI/Common/ExtractMode.h @@ -5,27 +5,29 @@ namespace NExtract { - namespace NPathMode +namespace NPathMode +{ + enum EEnum { - enum EEnum - { - kFullPathnames, - kCurrentPathnames, - kNoPathnames - }; - } - - namespace NOverwriteMode + kFullPaths, + kCurPaths, + kNoPaths, + kAbsPaths + }; +} + +namespace NOverwriteMode +{ + enum EEnum { - enum EEnum - { - kAskBefore, - kWithoutPrompt, - kSkipExisting, - kAutoRename, - kAutoRenameExisting - }; - } + kAsk, + kOverwrite, + kSkip, + kRename, + kRenameExisting + }; +} + } #endif diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/CPP/7zip/UI/Common/ExtractingFilePath.cpp old mode 100755 new mode 100644 index 25494d0e..37e15013 --- a/CPP/7zip/UI/Common/ExtractingFilePath.cpp +++ b/CPP/7zip/UI/Common/ExtractingFilePath.cpp @@ -2,26 +2,44 @@ #include "StdAfx.h" -#include "../../../../C/Types.h" +#include "../../../Common/Wildcard.h" -#include "Common/Wildcard.h" +#include "../../../Windows/FileName.h" #include "ExtractingFilePath.h" -static UString ReplaceIncorrectChars(const UString &s) +static UString ReplaceIncorrectChars(const UString &s, bool repaceColon) { #ifdef _WIN32 UString res; - for (int i = 0; i < s.Length(); i++) + bool beforeColon = true; { - wchar_t c = s[i]; - if (c < 0x20 || c == '*' || c == '?' || c == '<' || c == '>' || c == '|' || c == ':' || c == '"') - c = '_'; - res += c; + for (unsigned i = 0; i < s.Len(); i++) + { + wchar_t c = s[i]; + if (beforeColon) + if (c == '*' || c == '?' || c < 0x20 || c == '<' || c == '>' || c == '|' || c == '"') + c = '_'; + if (c == ':') + { + if (repaceColon) + c = '_'; + else + beforeColon = false; + } + res += c; + } + } + if (beforeColon) + { + for (int i = res.Len() - 1; i >= 0; i--) + { + wchar_t c = res[i]; + if (c != '.' && c != ' ') + break; + res.ReplaceOneCharAtPos(i, '_'); + } } - res.TrimRight(); - while (!res.IsEmpty() && res.Back() == '.') - res.DeleteBack(); return res; #else return s; @@ -29,27 +47,28 @@ static UString ReplaceIncorrectChars(const UString &s) } #ifdef _WIN32 + static const wchar_t *g_ReservedNames[] = { L"CON", L"PRN", L"AUX", L"NUL" }; -static bool CheckTail(const UString &name, int len) +static bool CheckTail(const UString &name, unsigned len) { int dotPos = name.Find(L'.'); if (dotPos < 0) - dotPos = name.Length(); + dotPos = name.Len(); UString s = name.Left(dotPos); s.TrimRight(); - return (s.Length() != len); + return s.Len() != len; } static bool CheckNameNum(const UString &name, const wchar_t *reservedName) { - int len = MyStringLen(reservedName); - if (name.Length() <= len) + unsigned len = MyStringLen(reservedName); + if (name.Len() <= len) return true; - if (name.Left(len).CompareNoCase(reservedName) != 0) + if (MyStringCompareNoCase_N(name, reservedName, len) != 0) return true; wchar_t c = name[len]; if (c < L'0' || c > L'9') @@ -59,13 +78,13 @@ static bool CheckNameNum(const UString &name, const wchar_t *reservedName) static bool IsSupportedName(const UString &name) { - for (int i = 0; i < sizeof(g_ReservedNames) / sizeof(g_ReservedNames[0]); i++) + for (unsigned i = 0; i < ARRAY_SIZE(g_ReservedNames); i++) { const wchar_t *reservedName = g_ReservedNames[i]; - int len = MyStringLen(reservedName); - if (name.Length() < len) + unsigned len = MyStringLen(reservedName); + if (name.Len() < len) continue; - if (name.Left(len).CompareNoCase(reservedName) != 0) + if (MyStringCompareNoCase_N(name, reservedName, len) != 0) continue; if (!CheckTail(name, len)) return false; @@ -74,21 +93,34 @@ static bool IsSupportedName(const UString &name) return false; return CheckNameNum(name, L"LPT"); } + #endif -static UString GetCorrectFileName(const UString &path) +static UString GetCorrectFileName(const UString &path, bool repaceColon) { if (path == L".." || path == L".") return UString(); - return ReplaceIncorrectChars(path); + return ReplaceIncorrectChars(path, repaceColon); } -void MakeCorrectPath(UStringVector &pathParts) +void MakeCorrectPath(bool isPathFromRoot, UStringVector &pathParts, bool replaceAltStreamColon) { - for (int i = 0; i < pathParts.Size();) + for (unsigned i = 0; i < pathParts.Size();) { UString &s = pathParts[i]; - s = GetCorrectFileName(s); + #ifdef _WIN32 + bool needReplaceColon = (replaceAltStreamColon || i != pathParts.Size() - 1); + if (i == 0 && isPathFromRoot && NWindows::NFile::NName::IsDrivePath(s)) + { + UString s2 = s[0]; + s2 += L'_'; + s2 += GetCorrectFileName(s.Ptr(2), needReplaceColon); + s = s2; + } + else + s = GetCorrectFileName(s, needReplaceColon); + #endif + if (s.IsEmpty()) pathParts.Delete(i); else @@ -105,7 +137,7 @@ void MakeCorrectPath(UStringVector &pathParts) UString MakePathNameFromParts(const UStringVector &parts) { UString result; - for (int i = 0; i < parts.Size(); i++) + FOR_VECTOR (i, parts) { if (i != 0) result += WCHAR_PATH_SEPARATOR; @@ -114,13 +146,29 @@ UString MakePathNameFromParts(const UStringVector &parts) return result; } +static const wchar_t *k_EmptyReplaceName = L"[]"; + +void Correct_IfEmptyLastPart(UStringVector &parts) +{ + if (parts.IsEmpty()) + parts.Add(k_EmptyReplaceName); + else + { + UString &s = parts.Back(); + if (s.IsEmpty()) + s = k_EmptyReplaceName; + } +} + UString GetCorrectFsPath(const UString &path) { - UString res = GetCorrectFileName(path); + UString res = GetCorrectFileName(path, true); #ifdef _WIN32 if (!IsSupportedName(res)) res = (UString)L"_" + res; #endif + if (res.IsEmpty()) + res = k_EmptyReplaceName; return res; } @@ -128,14 +176,14 @@ UString GetCorrectFullFsPath(const UString &path) { UStringVector parts; SplitPathToParts(path, parts); - for (int i = 0; i < parts.Size(); i++) + FOR_VECTOR (i, parts) { UString &s = parts[i]; #ifdef _WIN32 - while (!s.IsEmpty() && s.Back() == '.') + while (!s.IsEmpty() && (s.Back() == '.' || s.Back() == ' ')) s.DeleteBack(); if (!IsSupportedName(s)) - s = (UString)L"_" + s; + s.InsertAtFront(L'_'); #endif } return MakePathNameFromParts(parts); diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.h b/CPP/7zip/UI/Common/ExtractingFilePath.h old mode 100755 new mode 100644 index da28bfc2..751248a9 --- a/CPP/7zip/UI/Common/ExtractingFilePath.h +++ b/CPP/7zip/UI/Common/ExtractingFilePath.h @@ -3,11 +3,19 @@ #ifndef __EXTRACTING_FILE_PATH_H #define __EXTRACTING_FILE_PATH_H -#include "Common/MyString.h" +#include "../../../Common/MyString.h" UString MakePathNameFromParts(const UStringVector &parts); -void MakeCorrectPath(UStringVector &pathParts); + +/* for WIN32: + if (isRoot == true), and pathParts[0] contains path like "c:name", + it thinks that "c:" is drive prefix (it's not ":name alt stream) and + the function changes part to c_name */ +void MakeCorrectPath(bool isPathFromRoot, UStringVector &pathParts, bool replaceAltStreamColon); + UString GetCorrectFsPath(const UString &path); UString GetCorrectFullFsPath(const UString &path); +void Correct_IfEmptyLastPart(UStringVector &parts); + #endif diff --git a/CPP/7zip/UI/Common/HashCalc.cpp b/CPP/7zip/UI/Common/HashCalc.cpp new file mode 100644 index 00000000..6abe59ac --- /dev/null +++ b/CPP/7zip/UI/Common/HashCalc.cpp @@ -0,0 +1,361 @@ +// HashCalc.cpp + +#include "StdAfx.h" + +#include "../../../../C/Alloc.h" + +#include "../../../Common/StringToInt.h" + +#include "../../Common/FileStreams.h" +#include "../../Common/StreamUtils.h" + +#include "EnumDirItems.h" +#include "HashCalc.h" + +using namespace NWindows; + +class CHashMidBuf +{ + void *_data; +public: + CHashMidBuf(): _data(0) {} + operator void *() { return _data; } + bool Alloc(size_t size) + { + if (_data != 0) + return false; + _data = ::MidAlloc(size); + return _data != 0; + } + ~CHashMidBuf() { ::MidFree(_data); } +}; + +struct CEnumDirItemCallback_Hash: public IEnumDirItemCallback +{ + IHashCallbackUI *Callback; + + HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) + { + return Callback->ScanProgress(numFolders, numFiles, totalSize, path, isDir); + } +}; + +static const wchar_t *k_DefaultHashMethod = L"CRC32"; + +HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &hashMethods) +{ + UStringVector names = hashMethods; + if (names.IsEmpty()) + names.Add(k_DefaultHashMethod); + + CRecordVector ids; + CObjectVector methods; + + unsigned i; + for (i = 0; i < names.Size(); i++) + { + COneMethodInfo m; + RINOK(m.ParseMethodFromString(names[i])); + + if (m.MethodName.IsEmpty()) + m.MethodName = k_DefaultHashMethod; + + if (m.MethodName == L"*") + { + CRecordVector tempMethods; + GetHashMethods(EXTERNAL_CODECS_LOC_VARS tempMethods); + methods.Clear(); + ids.Clear(); + FOR_VECTOR (t, tempMethods) + { + int index = ids.AddToUniqueSorted(tempMethods[t]); + if (ids.Size() != methods.Size()) + methods.Insert(index, m); + } + break; + } + else + { + // m.MethodName.RemoveChar(L'-'); + CMethodId id; + if (!FindHashMethod(EXTERNAL_CODECS_LOC_VARS m.MethodName, id)) + return E_NOTIMPL; + int index = ids.AddToUniqueSorted(id); + if (ids.Size() != methods.Size()) + methods.Insert(index, m); + } + } + + for (i = 0; i < ids.Size(); i++) + { + CMyComPtr hasher; + UString name; + RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS ids[i], name, hasher)); + if (!hasher) + throw "Can't create hasher"; + const COneMethodInfo &m = methods[i]; + { + CMyComPtr scp; + hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp); + if (scp) + { + RINOK(m.SetCoderProps(scp, NULL)); + } + } + UInt32 digestSize = hasher->GetDigestSize(); + if (digestSize > k_HashCalc_DigestSize_Max) + return E_NOTIMPL; + CHasherState &h = Hashers.AddNew(); + h.Hasher = hasher; + h.Name = name; + h.DigestSize = digestSize; + for (int i = 0; i < k_HashCalc_NumGroups; i++) + memset(h.Digests[i], 0, digestSize); + } + return S_OK; +} + +void CHashBundle::InitForNewFile() +{ + CurSize = 0; + FOR_VECTOR (i, Hashers) + { + CHasherState &h = Hashers[i]; + h.Hasher->Init(); + memset(h.Digests[k_HashCalc_Index_Current], 0, h.DigestSize); + } +} + +void CHashBundle::Update(const void *data, UInt32 size) +{ + CurSize += size; + FOR_VECTOR (i, Hashers) + Hashers[i].Hasher->Update(data, size); +} + +void CHashBundle::SetSize(UInt64 size) +{ + CurSize = size; +} + +static void AddDigests(Byte *dest, const Byte *src, UInt32 size) +{ + unsigned next = 0; + for (UInt32 i = 0; i < size; i++) + { + next += (unsigned)dest[i] + (unsigned)src[i]; + dest[i] = (Byte)next; + next >>= 8; + } +} + +void CHashBundle::Final(bool isDir, bool isAltStream, const UString &path) +{ + if (isDir) + NumDirs++; + else if (isAltStream) + { + NumAltStreams++; + AltStreamsSize += CurSize; + } + else + { + NumFiles++; + FilesSize += CurSize; + } + + Byte pre[16]; + memset(pre, 0, sizeof(pre)); + if (isDir) + pre[0] = 1; + + FOR_VECTOR (i, Hashers) + { + CHasherState &h = Hashers[i]; + if (!isDir) + { + h.Hasher->Final(h.Digests[0]); + if (!isAltStream) + AddDigests(h.Digests[k_HashCalc_Index_DataSum], h.Digests[0], h.DigestSize); + } + + h.Hasher->Init(); + h.Hasher->Update(pre, sizeof(pre)); + h.Hasher->Update(h.Digests[0], h.DigestSize); + + for (unsigned k = 0; k < path.Len(); k++) + { + wchar_t c = path[k]; + Byte temp[2] = { (Byte)(c & 0xFF), (Byte)((c >> 8) & 0xFF) }; + h.Hasher->Update(temp, 2); + } + + Byte tempDigest[k_HashCalc_DigestSize_Max]; + h.Hasher->Final(tempDigest); + if (!isAltStream) + AddDigests(h.Digests[k_HashCalc_Index_NamesSum], tempDigest, h.DigestSize); + AddDigests(h.Digests[k_HashCalc_Index_StreamsSum], tempDigest, h.DigestSize); + } +} + + +HRESULT HashCalc( + DECL_EXTERNAL_CODECS_LOC_VARS + const NWildcard::CCensor &censor, + const CHashOptions &options, + UString &errorInfo, + IHashCallbackUI *callback) +{ + CDirItems dirItems; + + UInt64 numErrors = 0; + UInt64 totalBytes = 0; + if (options.StdInMode) + { + CDirItem di; + di.Size = (UInt64)(Int64)-1; + di.Attrib = 0; + di.MTime.dwLowDateTime = 0; + di.MTime.dwHighDateTime = 0; + di.CTime = di.ATime = di.MTime; + dirItems.Items.Add(di); + } + else + { + CEnumDirItemCallback_Hash enumCallback; + enumCallback.Callback = callback; + RINOK(callback->StartScanning()); + dirItems.ScanAltStreams = options.AltStreamsMode; + HRESULT res = EnumerateItems(censor, + options.PathMode, + UString(), + dirItems, &enumCallback); + totalBytes = dirItems.TotalSize; + FOR_VECTOR (i, dirItems.ErrorPaths) + { + RINOK(callback->CanNotFindError(fs2us(dirItems.ErrorPaths[i]), dirItems.ErrorCodes[i])); + } + numErrors = dirItems.ErrorPaths.Size(); + if (res != S_OK) + { + if (res != E_ABORT) + errorInfo = L"Scanning error"; + return res; + } + RINOK(callback->FinishScanning()); + } + + unsigned i; + CHashBundle hb; + RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS options.Methods)); + hb.Init(); + hb.NumErrors = numErrors; + + if (options.StdInMode) + { + RINOK(callback->SetNumFiles(1)); + } + else + { + RINOK(callback->SetTotal(totalBytes)); + } + + const UInt32 kBufSize = 1 << 15; + CHashMidBuf buf; + if (!buf.Alloc(kBufSize)) + return E_OUTOFMEMORY; + + UInt64 completeValue = 0; + + RINOK(callback->BeforeFirstFile(hb)); + + for (i = 0; i < dirItems.Items.Size(); i++) + { + CMyComPtr inStream; + UString path; + bool isDir = false; + bool isAltStream = false; + if (options.StdInMode) + { + inStream = new CStdInFileStream; + } + else + { + CInFileStream *inStreamSpec = new CInFileStream; + inStream = inStreamSpec; + const CDirItem &dirItem = dirItems.Items[i]; + isDir = dirItem.IsDir(); + isAltStream = dirItem.IsAltStream; + path = dirItems.GetLogPath(i); + if (!isDir) + { + UString phyPath = dirItems.GetPhyPath(i); + if (!inStreamSpec->OpenShared(us2fs(phyPath), options.OpenShareForWrite)) + { + HRESULT res = callback->OpenFileError(phyPath, ::GetLastError()); + hb.NumErrors++; + if (res != S_FALSE) + return res; + continue; + } + } + } + RINOK(callback->GetStream(path, isDir)); + UInt64 fileSize = 0; + + hb.InitForNewFile(); + if (!isDir) + { + for (UInt32 step = 0;; step++) + { + if ((step & 0xFF) == 0) + RINOK(callback->SetCompleted(&completeValue)); + UInt32 size; + RINOK(inStream->Read(buf, kBufSize, &size)); + if (size == 0) + break; + hb.Update(buf, size); + fileSize += size; + completeValue += size; + } + } + hb.Final(isDir, isAltStream, path); + RINOK(callback->SetOperationResult(fileSize, hb, !isDir)); + RINOK(callback->SetCompleted(&completeValue)); + } + return callback->AfterLastFile(hb); +} + + +static inline char GetHex(Byte value) +{ + return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); +} + +void AddHashHexToString(char *dest, const Byte *data, UInt32 size) +{ + dest[size * 2] = 0; + if (!data) + { + for (UInt32 i = 0; i < size; i++) + { + dest[0] = ' '; + dest[1] = ' '; + dest += 2; + } + return; + } + int step = 2; + if (size <= 8) + { + step = -2; + dest += size * 2 - 2; + } + for (UInt32 i = 0; i < size; i++) + { + Byte b = data[i]; + dest[0] = GetHex((Byte)((b >> 4) & 0xF)); + dest[1] = GetHex((Byte)(b & 0xF)); + dest += step; + } +} diff --git a/CPP/7zip/UI/Common/HashCalc.h b/CPP/7zip/UI/Common/HashCalc.h new file mode 100644 index 00000000..3d7b9bc8 --- /dev/null +++ b/CPP/7zip/UI/Common/HashCalc.h @@ -0,0 +1,107 @@ +// HashCalc.h + +#ifndef __HASH_CALC_H +#define __HASH_CALC_H + +#include "../../../Common/Wildcard.h" + +#include "../../Common/CreateCoder.h" +#include "../../Common/MethodProps.h" + +#include "Property.h" + +const unsigned k_HashCalc_DigestSize_Max = 64; + +const unsigned k_HashCalc_NumGroups = 4; + +enum +{ + k_HashCalc_Index_Current, + k_HashCalc_Index_DataSum, + k_HashCalc_Index_NamesSum, + k_HashCalc_Index_StreamsSum +}; + +struct CHasherState +{ + CMyComPtr Hasher; + UString Name; + UInt32 DigestSize; + Byte Digests[k_HashCalc_NumGroups][k_HashCalc_DigestSize_Max]; +}; + +struct IHashCalc +{ + virtual void InitForNewFile() = 0; + virtual void Update(const void *data, UInt32 size) = 0; + virtual void SetSize(UInt64 size) = 0; + virtual void Final(bool isDir, bool isAltStream, const UString &path) = 0; +}; + +struct CHashBundle: public IHashCalc +{ + CObjectVector Hashers; + + UInt64 NumFiles; + UInt64 NumDirs; + UInt64 NumAltStreams; + UInt64 FilesSize; + UInt64 AltStreamsSize; + UInt64 NumErrors; + + UInt64 CurSize; + + HRESULT SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &methods); + + void Init() + { + NumFiles = NumDirs = NumAltStreams = FilesSize = AltStreamsSize = NumErrors = 0; + } + + void InitForNewFile(); + void Update(const void *data, UInt32 size); + void SetSize(UInt64 size); + void Final(bool isDir, bool isAltStream, const UString &path); +}; + +#define INTERFACE_IHashCallbackUI(x) \ + virtual HRESULT StartScanning() x; \ + virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) x; \ + virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) x; \ + virtual HRESULT FinishScanning() x; \ + virtual HRESULT SetNumFiles(UInt64 numFiles) x; \ + virtual HRESULT SetTotal(UInt64 size) x; \ + virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \ + virtual HRESULT CheckBreak() x; \ + virtual HRESULT BeforeFirstFile(const CHashBundle &hb) x; \ + virtual HRESULT GetStream(const wchar_t *name, bool isFolder) x; \ + virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) x; \ + virtual HRESULT SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash) x; \ + virtual HRESULT AfterLastFile(const CHashBundle &hb) x; \ + +struct IHashCallbackUI +{ + INTERFACE_IHashCallbackUI(=0) +}; + +struct CHashOptions +{ + UStringVector Methods; + bool OpenShareForWrite; + bool StdInMode; + bool AltStreamsMode; + NWildcard::ECensorPathMode PathMode; + + CHashOptions(): StdInMode(false), OpenShareForWrite(false), AltStreamsMode(false), PathMode(NWildcard::k_RelatPath) {}; +}; + +HRESULT HashCalc( + DECL_EXTERNAL_CODECS_LOC_VARS + const NWildcard::CCensor &censor, + const CHashOptions &options, + UString &errorInfo, + IHashCallbackUI *callback); + +void AddHashHexToString(char *dest, const Byte *data, UInt32 size); + +#endif diff --git a/CPP/7zip/UI/Common/IFileExtractCallback.h b/CPP/7zip/UI/Common/IFileExtractCallback.h old mode 100755 new mode 100644 index e8dcdce5..7bb85279 --- a/CPP/7zip/UI/Common/IFileExtractCallback.h +++ b/CPP/7zip/UI/Common/IFileExtractCallback.h @@ -1,9 +1,10 @@ // IFileExtractCallback.h -#ifndef __IFILEEXTRACTCALLBACK_H -#define __IFILEEXTRACTCALLBACK_H +#ifndef __I_FILE_EXTRACT_CALLBACK_H +#define __I_FILE_EXTRACT_CALLBACK_H + +#include "../../../Common/MyString.h" -#include "Common/MyString.h" #include "../../IDecl.h" namespace NOverwriteAnswer @@ -35,12 +36,37 @@ struct IExtractCallbackUI: IFolderArchiveExtractCallback { virtual HRESULT BeforeOpen(const wchar_t *name) = 0; virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted) = 0; + virtual HRESULT SetError(int level, const wchar_t *name, + UInt32 errorFlags, const wchar_t *errors, + UInt32 warningFlags, const wchar_t *warnings) = 0; virtual HRESULT ThereAreNoFiles() = 0; virtual HRESULT ExtractResult(HRESULT result) = 0; + virtual HRESULT OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType) = 0; #ifndef _NO_CRYPTO virtual HRESULT SetPassword(const UString &password) = 0; #endif }; + +#define INTERFACE_IGetProp(x) \ + STDMETHOD(GetProp)(PROPID propID, PROPVARIANT *value) x; \ + +DECL_INTERFACE_SUB(IGetProp, IUnknown, 0x01, 0x20) +{ + INTERFACE_IGetProp(PURE) +}; + +#define INTERFACE_IFolderExtractToStreamCallback(x) \ + STDMETHOD(UseExtractToStream)(Int32 *res) x; \ + STDMETHOD(GetStream7)(const wchar_t *name, Int32 isDir, ISequentialOutStream **outStream, Int32 askExtractMode, IGetProp *getProp) x; \ + STDMETHOD(PrepareOperation7)(Int32 askExtractMode) x; \ + STDMETHOD(SetOperationResult7)(Int32 resultEOperationResult, bool encrypted) x; \ + +DECL_INTERFACE_SUB(IFolderExtractToStreamCallback, IUnknown, 0x01, 0x30) +{ + INTERFACE_IFolderExtractToStreamCallback(PURE) +}; + + #endif diff --git a/CPP/7zip/UI/Common/LoadCodecs.cpp b/CPP/7zip/UI/Common/LoadCodecs.cpp old mode 100755 new mode 100644 index cb4f83ee..285b6588 --- a/CPP/7zip/UI/Common/LoadCodecs.cpp +++ b/CPP/7zip/UI/Common/LoadCodecs.cpp @@ -2,18 +2,27 @@ #include "StdAfx.h" -#include "LoadCodecs.h" +#include "../../../../C/7zVersion.h" #include "../../../Common/MyCom.h" +#include "../../../Common/StringToInt.h" +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/PropVariant.h" + +#include "LoadCodecs.h" + +using namespace NWindows; + #ifdef NEW_FOLDER_INTERFACE #include "../../../Common/StringToInt.h" #endif -#include "../../../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 @@ -22,11 +31,10 @@ static const UINT kIconTypesResId = 100; #endif #ifdef _WIN32 -#include "Windows/FileName.h" -#include "Windows/Registry.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/Registry.h" #endif -using namespace NWindows; using namespace NFile; #ifdef _WIN32 @@ -64,7 +72,97 @@ static bool ReadPathFromRegistry(HKEY baseKey, LPCWSTR value, FString &path) return false; } -#endif +#endif // _WIN32 + +#endif // EXTERNAL_CODECS + + +static const unsigned kNumArcsMax = 48; +static unsigned g_NumArcs = 0; +static const CArcInfo *g_Arcs[kNumArcsMax]; + +void RegisterArc(const CArcInfo *arcInfo) +{ + if (g_NumArcs < kNumArcsMax) + { + g_Arcs[g_NumArcs] = arcInfo; + g_NumArcs++; + } +} + +static void SplitString(const UString &srcString, UStringVector &destStrings) +{ + destStrings.Clear(); + UString s; + unsigned len = srcString.Len(); + if (len == 0) + return; + for (unsigned i = 0; i < len; i++) + { + wchar_t c = srcString[i]; + if (c == L' ') + { + if (!s.IsEmpty()) + { + destStrings.Add(s); + s.Empty(); + } + } + else + s += c; + } + if (!s.IsEmpty()) + destStrings.Add(s); +} + +int CArcInfoEx::FindExtension(const UString &ext) const +{ + FOR_VECTOR (i, Exts) + if (ext.IsEqualToNoCase(Exts[i].Ext)) + return i; + return -1; +} + +void CArcInfoEx::AddExts(const UString &ext, const UString &addExt) +{ + UStringVector exts, addExts; + SplitString(ext, exts); + SplitString(addExt, addExts); + FOR_VECTOR (i, exts) + { + CArcExtInfo extInfo; + extInfo.Ext = exts[i]; + if (i < addExts.Size()) + { + extInfo.AddExt = addExts[i]; + if (extInfo.AddExt == L"*") + extInfo.AddExt.Empty(); + } + Exts.Add(extInfo); + } +} + +#ifndef _SFX + +static bool ParseSignatures(const Byte *data, unsigned size, CObjectVector &signatures) +{ + signatures.Clear(); + while (size > 0) + { + unsigned len = *data++; + size--; + if (len > size) + return false; + signatures.AddNew().CopyFrom(data, len); + data += len; + size -= len; + } + return true; +} + +#endif // _SFX + +#ifdef EXTERNAL_CODECS static FString GetBaseFolderPrefixFromRegistry() { @@ -84,22 +182,16 @@ static FString GetBaseFolderPrefixFromRegistry() 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, +static HRESULT GetCoderClass(Func_GetMethodProperty getMethodProperty, UInt32 index, PROPID propId, CLSID &clsId, bool &isAssigned) { - NWindows::NCOM::CPropVariant prop; + NCOM::CPropVariant prop; isAssigned = false; RINOK(getMethodProperty(index, propId, &prop)); if (prop.vt == VT_BSTR) { + if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID)) + return E_FAIL; isAssigned = true; clsId = *(const GUID *)prop.bstrVal; } @@ -111,34 +203,48 @@ static HRESULT GetCoderClass(GetMethodPropertyFunc getMethodProperty, UInt32 ind 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) + lib.GetMethodProperty = (Func_GetMethodProperty)lib.Lib.GetProc("GetMethodProperty"); + if (lib.GetMethodProperty) { - RINOK(getNumberOfMethodsFunc(&numMethods)); + UInt32 numMethods = 1; + Func_GetNumberOfMethods getNumberOfMethodsFunc = (Func_GetNumberOfMethods)lib.Lib.GetProc("GetNumberOfMethods"); + if (getNumberOfMethodsFunc) + { + 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); + } } - for(UInt32 i = 0; i < numMethods; i++) + Func_GetHashers getHashers = (Func_GetHashers)lib.Lib.GetProc("GetHashers"); + if (getHashers) { - 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); + RINOK(getHashers(&lib.Hashers)); + if (lib.Hashers) + { + UInt32 numMethods = lib.Hashers->GetNumHashers(); + for (UInt32 i = 0; i < numMethods; i++) + { + CDllHasherInfo info; + info.LibIndex = Libs.Size() - 1; + info.HasherIndex = i; + Hashers.Add(info); + } + } } return S_OK; } -static HRESULT ReadProp( - GetHandlerPropertyFunc getProp, - GetHandlerPropertyFunc2 getProp2, +static HRESULT GetProp( + Func_GetHandlerProperty getProp, + Func_GetHandlerProperty2 getProp2, UInt32 index, PROPID propID, NCOM::CPropVariant &prop) { if (getProp2) @@ -146,13 +252,14 @@ static HRESULT ReadProp( return getProp(propID, &prop); } -static HRESULT ReadBoolProp( - GetHandlerPropertyFunc getProp, - GetHandlerPropertyFunc2 getProp2, +static HRESULT GetProp_Bool( + Func_GetHandlerProperty getProp, + Func_GetHandlerProperty2 getProp2, UInt32 index, PROPID propID, bool &res) { + res = false; NCOM::CPropVariant prop; - RINOK(ReadProp(getProp, getProp2, index, propID, prop)); + RINOK(GetProp(getProp, getProp2, index, propID, prop)); if (prop.vt == VT_BOOL) res = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt != VT_EMPTY) @@ -160,140 +267,150 @@ static HRESULT ReadBoolProp( return S_OK; } -static HRESULT ReadStringProp( - GetHandlerPropertyFunc getProp, - GetHandlerPropertyFunc2 getProp2, - UInt32 index, PROPID propID, UString &res) +static HRESULT GetProp_UInt32( + Func_GetHandlerProperty getProp, + Func_GetHandlerProperty2 getProp2, + UInt32 index, PROPID propID, UInt32 &res, bool &defined) { + res = 0; + defined = false; NCOM::CPropVariant prop; - RINOK(ReadProp(getProp, getProp2, index, propID, prop)); - if (prop.vt == VT_BSTR) - res = prop.bstrVal; + RINOK(GetProp(getProp, getProp2, index, propID, prop)); + if (prop.vt == VT_UI4) + { + res = prop.ulVal; + defined = true; + } else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } -#endif - -static const unsigned int kNumArcsMax = 48; -static unsigned int g_NumArcs = 0; -static const CArcInfo *g_Arcs[kNumArcsMax]; -void RegisterArc(const CArcInfo *arcInfo) +static HRESULT GetProp_String( + Func_GetHandlerProperty getProp, + Func_GetHandlerProperty2 getProp2, + UInt32 index, PROPID propID, UString &res) { - if (g_NumArcs < kNumArcsMax) - g_Arcs[g_NumArcs++] = arcInfo; + res.Empty(); + NCOM::CPropVariant prop; + RINOK(GetProp(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; } -static void SplitString(const UString &srcString, UStringVector &destStrings) +static HRESULT GetProp_RawData( + Func_GetHandlerProperty getProp, + Func_GetHandlerProperty2 getProp2, + UInt32 index, PROPID propID, CByteBuffer &bb) { - destStrings.Clear(); - UString s; - int len = srcString.Length(); - if (len == 0) - return; - for (int i = 0; i < len; i++) + bb.Free(); + NCOM::CPropVariant prop; + RINOK(GetProp(getProp, getProp2, index, propID, prop)); + if (prop.vt == VT_BSTR) { - wchar_t c = srcString[i]; - if (c == L' ') - { - if (!s.IsEmpty()) - { - destStrings.Add(s); - s.Empty(); - } - } - else - s += c; + UINT len = ::SysStringByteLen(prop.bstrVal); + bb.CopyFrom((const Byte *)prop.bstrVal, len); } - if (!s.IsEmpty()) - destStrings.Add(s); + else if (prop.vt != VT_EMPTY) + return E_FAIL; + return S_OK; } -int CArcInfoEx::FindExtension(const UString &ext) const +static const UInt32 kArcFlagsPars[] = { - for (int i = 0; i < Exts.Size(); i++) - if (ext.CompareNoCase(Exts[i].Ext) == 0) - return i; - return -1; -} + NArchive::NHandlerPropID::kKeepName, NArcInfoFlags::kKeepName, + NArchive::NHandlerPropID::kAltStreams, NArcInfoFlags::kAltStreams, + NArchive::NHandlerPropID::kNtSecure, NArcInfoFlags::kNtSecure +}; -void CArcInfoEx::AddExts(const wchar_t *ext, const wchar_t *addExt) +HRESULT CCodecs::LoadFormats() { - UStringVector exts, addExts; - if (ext != 0) - SplitString(ext, exts); - if (addExt != 0) - SplitString(addExt, addExts); - for (int i = 0; i < exts.Size(); i++) + const NDLL::CLibrary &lib = Libs.Back().Lib; + + Func_GetHandlerProperty getProp = NULL; + Func_GetHandlerProperty2 getProp2 = (Func_GetHandlerProperty2)lib.GetProc("GetHandlerProperty2"); + Func_GetIsArc getIsArc = (Func_GetIsArc)lib.GetProc("GetIsArc"); + + UInt32 numFormats = 1; + + if (getProp2) { - CArcExtInfo extInfo; - extInfo.Ext = exts[i]; - if (i < addExts.Size()) + Func_GetNumberOfFormats getNumberOfFormats = (Func_GetNumberOfFormats)lib.GetProc("GetNumberOfFormats"); + if (getNumberOfFormats) { - extInfo.AddExt = addExts[i]; - if (extInfo.AddExt == L"*") - extInfo.AddExt.Empty(); + RINOK(getNumberOfFormats(&numFormats)); } - 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) + else { - getProp = (GetHandlerPropertyFunc)lib.GetProc("GetHandlerProperty"); - if (getProp == NULL) + getProp = (Func_GetHandlerProperty)lib.GetProc("GetHandlerProperty"); + if (!getProp) 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++) + + 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)); + RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::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(); + { + NCOM::CPropVariant prop; + if (GetProp(getProp, getProp2, i, NArchive::NHandlerPropID::kClassID, prop) != S_OK) + continue; + if (prop.vt != VT_BSTR) + continue; + if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID)) + return E_FAIL; + item.ClassID = *(const GUID *)prop.bstrVal; + prop.Clear(); + } UString ext, addExt; - RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kExtension, ext)); - RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kAddExtension, addExt)); + RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kExtension, ext)); + RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kAddExtension, addExt)); item.AddExts(ext, addExt); - 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) + GetProp_Bool(getProp, getProp2, i, NArchive::NHandlerPropID::kUpdate, item.UpdateEnabled); + bool flags_Defined = false; + RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kFlags, item.Flags, flags_Defined)); + item.NewInterface = flags_Defined; + if (!flags_Defined) // && item.UpdateEnabled + { + // support for DLL version before 9.31: + for (unsigned j = 0; j < ARRAY_SIZE(kArcFlagsPars); j += 2) { - UINT len = ::SysStringByteLen(prop.bstrVal); - item.StartSignature.SetCapacity(len); - memmove(item.StartSignature, prop.bstrVal, len); + bool val = false; + GetProp_Bool(getProp, getProp2, i, kArcFlagsPars[j], val); + if (val) + item.Flags |= kArcFlagsPars[j + 1]; } + } + + CByteBuffer sig; + RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kSignature, sig)); + if (sig.Size() != 0) + item.Signatures.Add(sig); + else + { + RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kMultiSignature, sig)); + ParseSignatures(sig, (unsigned)sig.Size(), item.Signatures); + } + + bool signatureOffset_Defined; + RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kSignatureOffset, item.SignatureOffset, signatureOffset_Defined)); + + // bool version_Defined; + // RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kVersion, item.Version, version_Defined)); + + if (getIsArc) + getIsArc(i, &item.IsArcFunc); + Formats.Add(item); } return S_OK; @@ -302,25 +419,26 @@ HRESULT CCodecs::LoadFormats() #ifdef NEW_FOLDER_INTERFACE void CCodecIcons::LoadIcons(HMODULE m) { - UString iconTypes = MyLoadStringW(m, kIconTypesResId); + UString iconTypes; + MyLoadString(m, kIconTypesResId, iconTypes); UStringVector pairs; SplitString(iconTypes, pairs); - for (int i = 0; i < pairs.Size(); i++) + FOR_VECTOR (i, pairs) { const UString &s = pairs[i]; int pos = s.Find(L':'); CIconPair iconPair; iconPair.IconIndex = -1; if (pos < 0) - pos = s.Length(); + pos = s.Len(); else { - UString num = s.Mid(pos + 1); + UString num = s.Ptr(pos + 1); if (!num.IsEmpty()) { const wchar_t *end; - iconPair.IconIndex = (UInt32)ConvertStringToUInt64(num, &end); - if (*end != L'\0') + iconPair.IconIndex = ConvertStringToUInt32(num, &end); + if (*end != 0) continue; } } @@ -332,10 +450,10 @@ void CCodecIcons::LoadIcons(HMODULE m) bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const { iconIndex = -1; - for (int i = 0; i < IconPairs.Size(); i++) + FOR_VECTOR (i, IconPairs) { const CIconPair &pair = IconPairs[i]; - if (ext.CompareNoCase(pair.Ext) == 0) + if (ext.IsEqualToNoCase(pair.Ext)) { iconIndex = pair.IconIndex; return true; @@ -343,7 +461,8 @@ bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const } return false; } -#endif + +#endif // EXTERNAL_CODECS #ifdef _7ZIP_LARGE_PAGES extern "C" @@ -362,9 +481,7 @@ HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll) } 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)) @@ -376,23 +493,31 @@ HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll) #ifdef _7ZIP_LARGE_PAGES if (g_LargePageSize != 0) { - SetLargePageModeFunc setLargePageMode = (SetLargePageModeFunc)lib.Lib.GetProc("SetLargePageMode"); - if (setLargePageMode != 0) + Func_SetLargePageMode setLargePageMode = (Func_SetLargePageMode)lib.Lib.GetProc("SetLargePageMode"); + if (setLargePageMode) setLargePageMode(); } #endif - lib.CreateObject = (CreateObjectFunc)lib.Lib.GetProc("CreateObject"); - if (lib.CreateObject != 0) + if (CaseSensitiveChange) { - int startSize = Codecs.Size(); + Func_SetCaseSensitive setCaseSensitive = (Func_SetCaseSensitive)lib.Lib.GetProc("SetCaseSensitive"); + if (setCaseSensitive) + setCaseSensitive(CaseSensitive ? 1 : 0); + } + + lib.CreateObject = (Func_CreateObject)lib.Lib.GetProc("CreateObject"); + if (lib.CreateObject) + { + unsigned startSize = Codecs.Size() + Hashers.Size(); res = LoadCodecs(); - used = (Codecs.Size() != startSize); + used = (startSize != Codecs.Size() + Hashers.Size()); if (res == S_OK) { startSize = Formats.Size(); res = LoadFormats(); - used = used || (Formats.Size() != startSize); + if (startSize != Formats.Size()) + used = true; } } } @@ -416,46 +541,63 @@ HRESULT CCodecs::LoadDllsFromFolder(const FString &folderPrefix) #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); + InternalIcons.LoadIcons(g_hInstance); #endif Formats.Clear(); + #ifdef EXTERNAL_CODECS - Codecs.Clear(); + Codecs.Clear(); + Hashers.Clear(); #endif + for (UInt32 i = 0; i < g_NumArcs; i++) { const CArcInfo &arc = *g_Arcs[i]; CArcInfoEx item; - item.Name = arc.Name; + + item.Name.SetFromAscii(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; + item.IsArcFunc = arc.IsArc; + item.Flags = arc.Flags; + + { + UString e, ae; + if (arc.Ext) + e.SetFromAscii(arc.Ext); + if (arc.AddExt) + ae.SetFromAscii(arc.AddExt); + item.AddExts(e, ae); + } #ifndef _SFX - SetBuffer(item.StartSignature, arc.Signature, arc.SignatureSize); + + item.CreateOutArchive = arc.CreateOutArchive; + item.UpdateEnabled = (arc.CreateOutArchive != NULL); + item.SignatureOffset = arc.SignatureOffset; + // item.Version = MY_VER_MIX; + item.NewInterface = true; + + if (arc.IsMultiSignature()) + ParseSignatures(arc.Signature, arc.SignatureSize, item.Signatures); + else + item.Signatures.AddNew().CopyFrom(arc.Signature, arc.SignatureSize); + #endif + Formats.Add(item); } + #ifdef EXTERNAL_CODECS - const FString baseFolder = GetBaseFolderPrefixFromRegistry(); - RINOK(LoadDll(baseFolder + kMainDll, false)); - RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName FSTRING_PATH_SEPARATOR)); - RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName FSTRING_PATH_SEPARATOR)); + const FString baseFolder = GetBaseFolderPrefixFromRegistry(); + RINOK(LoadDll(baseFolder + kMainDll, false)); + RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName FSTRING_PATH_SEPARATOR)); + RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName FSTRING_PATH_SEPARATOR)); #endif + return S_OK; } @@ -467,12 +609,18 @@ int CCodecs::FindFormatForArchiveName(const UString &arcPath) const int dotPos = arcPath.ReverseFind(L'.'); if (dotPos < 0 || dotPos < slashPos) return -1; - const UString ext = arcPath.Mid(dotPos + 1); - for (int i = 0; i < Formats.Size(); i++) + const UString ext = arcPath.Ptr(dotPos + 1); + if (ext.IsEmpty()) + return -1; + if (ext.IsEqualToNoCase(L"exe")) + return -1; + FOR_VECTOR (i, Formats) { const CArcInfoEx &arc = Formats[i]; + /* if (!arc.UpdateEnabled) continue; + */ if (arc.FindExtension(ext) >= 0) return i; } @@ -483,7 +631,7 @@ int CCodecs::FindFormatForExtension(const UString &ext) const { if (ext.IsEmpty()) return -1; - for (int i = 0; i < Formats.Size(); i++) + FOR_VECTOR (i, Formats) if (Formats[i].FindExtension(ext) >= 0) return i; return -1; @@ -491,8 +639,8 @@ int CCodecs::FindFormatForExtension(const UString &ext) const int CCodecs::FindFormatForArchiveType(const UString &arcType) const { - for (int i = 0; i < Formats.Size(); i++) - if (Formats[i].Name.CompareNoCase(arcType) == 0) + FOR_VECTOR (i, Formats) + if (Formats[i].Name.IsEqualToNoCase(arcType)) return i; return -1; } @@ -500,12 +648,14 @@ int CCodecs::FindFormatForArchiveType(const UString &arcType) const bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const { formatIndices.Clear(); - for (int pos = 0; pos < arcType.Length();) + for (unsigned pos = 0; pos < arcType.Len();) { int pos2 = arcType.Find('.', pos); if (pos2 < 0) - pos2 = arcType.Length(); + pos2 = arcType.Len(); const UString name = arcType.Mid(pos, pos2 - pos); + if (name.IsEmpty()) + return false; int index = FindFormatForArchiveType(name); if (index < 0 && name != L"*") { @@ -518,24 +668,39 @@ bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &forma return true; } -#endif +#endif // _SFX + #ifdef EXTERNAL_CODECS +// #define EXPORT_CODECS + #ifdef EXPORT_CODECS -extern unsigned int g_NumCodecs; + +extern unsigned 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 +#define NUM_EXPORT_CODECS g_NumCodecs + +extern unsigned g_NumHashers; +STDAPI CreateHasher(UInt32 index, IHasher **hasher); +STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); +#define NUM_EXPORT_HASHERS g_NumHashers + +#else // EXPORT_CODECS + +#define NUM_EXPORT_CODECS 0 +#define NUM_EXPORT_HASHERS 0 + +#endif // EXPORT_CODECS STDMETHODIMP CCodecs::GetNumberOfMethods(UInt32 *numMethods) { - *numMethods = - #ifdef EXPORT_CODECS - g_NumCodecs + - #endif - Codecs.Size(); + *numMethods = NUM_EXPORT_CODECS + #ifdef EXTERNAL_CODECS + + Codecs.Size() + #endif + ; return S_OK; } @@ -546,27 +711,23 @@ STDMETHODIMP CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *valu return GetMethodProperty(index, propID, value); #endif - const CDllCodecInfo &ci = Codecs[index - #ifdef EXPORT_CODECS - - g_NumCodecs - #endif - ]; + #ifdef EXTERNAL_CODECS + const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; - if (propID == NMethodPropID::kDecoderIsAssigned) - { - NWindows::NCOM::CPropVariant propVariant; - propVariant = ci.DecoderIsAssigned; - propVariant.Detach(value); - return S_OK; - } - if (propID == NMethodPropID::kEncoderIsAssigned) + if (propID == NMethodPropID::kDecoderIsAssigned || + propID == NMethodPropID::kEncoderIsAssigned) { - NWindows::NCOM::CPropVariant propVariant; - propVariant = ci.EncoderIsAssigned; - propVariant.Detach(value); + NCOM::CPropVariant prop; + prop = (propID == NMethodPropID::kDecoderIsAssigned) ? + ci.DecoderIsAssigned : + ci.EncoderIsAssigned; + prop.Detach(value); return S_OK; } return Libs[ci.LibIndex].GetMethodProperty(ci.CodecIndex, propID, value); + #else + return E_FAIL; + #endif } STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder) @@ -575,14 +736,14 @@ STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder) if (index < g_NumCodecs) return CreateCoder2(false, index, iid, coder); #endif - const CDllCodecInfo &ci = Codecs[index - #ifdef EXPORT_CODECS - - g_NumCodecs - #endif - ]; + #ifdef EXTERNAL_CODECS + const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; if (ci.DecoderIsAssigned) return Libs[ci.LibIndex].CreateObject(&ci.Decoder, iid, (void **)coder); return S_OK; + #else + return E_FAIL; + #endif } STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder) @@ -591,35 +752,53 @@ STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder) if (index < g_NumCodecs) return CreateCoder2(true, index, iid, coder); #endif - const CDllCodecInfo &ci = Codecs[index - #ifdef EXPORT_CODECS - - g_NumCodecs - #endif - ]; + #ifdef EXTERNAL_CODECS + const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; if (ci.EncoderIsAssigned) return Libs[ci.LibIndex].CreateObject(&ci.Encoder, iid, (void **)coder); return S_OK; + #else + return E_FAIL; + #endif } -HRESULT CCodecs::CreateCoder(const UString &name, bool encode, CMyComPtr &coder) const + +STDMETHODIMP_(UInt32) CCodecs::GetNumHashers() { - 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; + return NUM_EXPORT_HASHERS + #ifdef EXTERNAL_CODECS + + Hashers.Size() + #endif + ; +} + +STDMETHODIMP CCodecs::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + #ifdef EXPORT_CODECS + if (index < g_NumHashers) + return ::GetHasherProp(index, propID, value); + #endif + + #ifdef EXTERNAL_CODECS + const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; + return Libs[ci.LibIndex].Hashers->GetHasherProp(ci.HasherIndex, propID, value); + #else + return E_FAIL; + #endif +} + +STDMETHODIMP CCodecs::CreateHasher(UInt32 index, IHasher **hasher) +{ + #ifdef EXPORT_CODECS + if (index < g_NumHashers) + return CreateHasher(index, hasher); + #endif + #ifdef EXTERNAL_CODECS + const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; + return Libs[ci.LibIndex].Hashers->CreateHasher(ci.HasherIndex, hasher); + #else + return E_FAIL; + #endif } int CCodecs::GetCodecLibIndex(UInt32 index) @@ -629,11 +808,21 @@ int CCodecs::GetCodecLibIndex(UInt32 index) return -1; #endif #ifdef EXTERNAL_CODECS - const CDllCodecInfo &ci = Codecs[index - #ifdef EXPORT_CODECS - - g_NumCodecs - #endif - ]; + const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; + return ci.LibIndex; + #else + return -1; + #endif +} + +int CCodecs::GetHasherLibIndex(UInt32 index) +{ + #ifdef EXPORT_CODECS + if (index < g_NumHashers) + return -1; + #endif + #ifdef EXTERNAL_CODECS + const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; return ci.LibIndex; #else return -1; @@ -645,7 +834,7 @@ bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index) #ifdef EXPORT_CODECS if (index < g_NumCodecs) { - NWindows::NCOM::CPropVariant prop; + NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kEncoder, &prop) == S_OK) if (prop.vt != VT_EMPTY) return true; @@ -653,11 +842,7 @@ bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index) } #endif #ifdef EXTERNAL_CODECS - const CDllCodecInfo &ci = Codecs[index - #ifdef EXPORT_CODECS - - g_NumCodecs - #endif - ]; + const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; return ci.EncoderIsAssigned; #else return false; @@ -666,8 +851,7 @@ bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index) HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id) { - UString s; - NWindows::NCOM::CPropVariant prop; + NCOM::CPropVariant prop; RINOK(GetProperty(index, NMethodPropID::kID, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; @@ -678,11 +862,39 @@ HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id) UString CCodecs::GetCodecName(UInt32 index) { UString s; - NWindows::NCOM::CPropVariant prop; + NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK) if (prop.vt == VT_BSTR) s = prop.bstrVal; return s; } -#endif +UInt64 CCodecs::GetHasherId(UInt32 index) +{ + NCOM::CPropVariant prop; + RINOK(GetHasherProp(index, NMethodPropID::kID, &prop)); + if (prop.vt != VT_UI8) + return 0; + return prop.uhVal.QuadPart; +} + +UString CCodecs::GetHasherName(UInt32 index) +{ + UString s; + NCOM::CPropVariant prop; + if (GetHasherProp(index, NMethodPropID::kName, &prop) == S_OK) + if (prop.vt == VT_BSTR) + s = prop.bstrVal; + return s; +} + +UInt32 CCodecs::GetHasherDigestSize(UInt32 index) +{ + NCOM::CPropVariant prop; + RINOK(GetHasherProp(index, NMethodPropID::kDigestSize, &prop)); + if (prop.vt != VT_UI4) + return 0; + return prop.ulVal; +} + +#endif // EXTERNAL_CODECS diff --git a/CPP/7zip/UI/Common/LoadCodecs.h b/CPP/7zip/UI/Common/LoadCodecs.h old mode 100755 new mode 100644 index f5963ed6..5a54d365 --- a/CPP/7zip/UI/Common/LoadCodecs.h +++ b/CPP/7zip/UI/Common/LoadCodecs.h @@ -3,9 +3,11 @@ #ifndef __LOAD_CODECS_H #define __LOAD_CODECS_H +#include "../../../Common/MyBuffer.h" #include "../../../Common/MyCom.h" #include "../../../Common/MyString.h" -#include "../../../Common/Buffer.h" +#include "../../../Common/ComTry.h" + #include "../../ICoder.h" #ifdef EXTERNAL_CODECS @@ -22,15 +24,19 @@ struct CDllCodecInfo UInt32 CodecIndex; }; -#include "../../Archive/IArchive.h" +struct CDllHasherInfo +{ + int LibIndex; + UInt32 HasherIndex; +}; -typedef IInArchive * (*CreateInArchiveP)(); -typedef IOutArchive * (*CreateOutArchiveP)(); +#include "../../Archive/IArchive.h" struct CArcExtInfo { UString Ext; UString AddExt; + CArcExtInfo() {} CArcExtInfo(const UString &ext): Ext(ext) {} CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {} @@ -39,24 +45,45 @@ struct CArcExtInfo struct CArcInfoEx { - #ifdef EXTERNAL_CODECS - int LibIndex; - UInt32 FormatIndex; - CLSID ClassID; - #endif - bool UpdateEnabled; - CreateInArchiveP CreateInArchive; - CreateOutArchiveP CreateOutArchive; + UInt32 Flags; + + Func_CreateInArchive CreateInArchive; + Func_IsArc IsArcFunc; + UString Name; CObjectVector Exts; + #ifndef _SFX - CByteBuffer StartSignature; - // CByteBuffer FinishSignature; - #ifdef NEW_FOLDER_INTERFACE - UStringVector AssociateExts; + Func_CreateOutArchive CreateOutArchive; + bool UpdateEnabled; + bool NewInterface; + // UInt32 Version; + UInt32 SignatureOffset; + CObjectVector Signatures; + #ifdef NEW_FOLDER_INTERFACE + UStringVector AssociateExts; + #endif #endif + + #ifdef EXTERNAL_CODECS + int LibIndex; + UInt32 FormatIndex; + CLSID ClassID; #endif - bool KeepName; + + bool Flags_KeepName() const { return (Flags & NArcInfoFlags::kKeepName) != 0; } + bool Flags_FindSignature() const { return (Flags & NArcInfoFlags::kFindSignature) != 0; } + + bool Flags_AltStreams() const { return (Flags & NArcInfoFlags::kAltStreams) != 0; } + bool Flags_NtSecure() const { return (Flags & NArcInfoFlags::kNtSecure) != 0; } + bool Flags_SymLinks() const { return (Flags & NArcInfoFlags::kSymLinks) != 0; } + bool Flags_HardLinks() const { return (Flags & NArcInfoFlags::kHardLinks) != 0; } + + bool Flags_UseGlobalOffset() const { return (Flags & NArcInfoFlags::kUseGlobalOffset) != 0; } + bool Flags_StartOpen() const { return (Flags & NArcInfoFlags::kStartOpen) != 0; } + bool Flags_BackwardOpen() const { return (Flags & NArcInfoFlags::kBackwardOpen) != 0; } + bool Flags_PreArc() const { return (Flags & NArcInfoFlags::kPreArc) != 0; } + bool Flags_PureStartOpen() const { return (Flags & NArcInfoFlags::kPureStartOpen) != 0; } UString GetMainExt() const { @@ -80,24 +107,29 @@ struct CArcInfoEx } */ - void AddExts(const wchar_t* ext, const wchar_t* addExt); + void AddExts(const UString &ext, const UString &addExt); + + bool IsSplit() const { return StringsAreEqualNoCase_Ascii(Name, "Split"); } + // bool IsRar() const { return StringsAreEqualNoCase_Ascii(Name, "Rar"); } CArcInfoEx(): - #ifdef EXTERNAL_CODECS - LibIndex(-1), - #endif - UpdateEnabled(false), - CreateInArchive(0), CreateOutArchive(0), - KeepName(false) - #ifndef _SFX - #endif + Flags(0), + CreateInArchive(NULL), + IsArcFunc(NULL) + #ifndef _SFX + , CreateOutArchive(NULL) + , UpdateEnabled(false) + , NewInterface(false) + // , Version(0) + , SignatureOffset(0) + #endif + #ifdef EXTERNAL_CODECS + , LibIndex(-1) + #endif {} }; #ifdef 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 @@ -114,24 +146,28 @@ struct CCodecIcons #endif struct CCodecLib -#ifdef NEW_FOLDER_INTERFACE -: public CCodecIcons -#endif + #ifdef NEW_FOLDER_INTERFACE + : public CCodecIcons + #endif { NWindows::NDLL::CLibrary Lib; - GetMethodPropertyFunc GetMethodProperty; - CreateObjectFunc CreateObject; - #ifdef NEW_FOLDER_INTERFACE FString Path; + Func_GetMethodProperty GetMethodProperty; + Func_CreateObject CreateObject; + CMyComPtr Hashers; + + #ifdef NEW_FOLDER_INTERFACE void LoadIcons() { CCodecIcons::LoadIcons((HMODULE)Lib); } #endif - CCodecLib(): GetMethodProperty(0) {} + + CCodecLib(): GetMethodProperty(NULL) {} }; #endif class CCodecs: #ifdef EXTERNAL_CODECS public ICompressCodecsInfo, + public IHashers, #else public IUnknown, #endif @@ -140,7 +176,8 @@ class CCodecs: public: #ifdef EXTERNAL_CODECS CObjectVector Libs; - CObjectVector Codecs; + CRecordVector Codecs; + CRecordVector Hashers; #ifdef NEW_FOLDER_INTERFACE CCodecIcons InternalIcons; @@ -159,6 +196,16 @@ public: public: CObjectVector Formats; + bool CaseSensitiveChange; + bool CaseSensitive; + + CCodecs(): CaseSensitiveChange(false), CaseSensitive(false) {} + + const wchar_t *GetFormatNamePtr(int formatIndex) + { + return formatIndex < 0 ? L"#" : (const wchar_t *)Formats[formatIndex].Name; + } + HRESULT Load(); #ifndef _SFX @@ -168,65 +215,89 @@ public: bool FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const; #endif - MY_UNKNOWN_IMP - #ifdef EXTERNAL_CODECS + + MY_UNKNOWN_IMP2(ICompressCodecsInfo, IHashers) + 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 + + STDMETHOD_(UInt32, GetNumHashers)(); + STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value); + STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher); + + #else + + MY_UNKNOWN_IMP + + #endif // EXTERNAL_CODECS + + #ifdef EXTERNAL_CODECS int GetCodecLibIndex(UInt32 index); bool GetCodecEncoderIsAssigned(UInt32 index); HRESULT GetCodecId(UInt32 index, UInt64 &id); UString GetCodecName(UInt32 index); - HRESULT CreateInArchive(int formatIndex, CMyComPtr &archive) const + int GetHasherLibIndex(UInt32 index); + UInt64 GetHasherId(UInt32 index); + UString GetHasherName(UInt32 index); + UInt32 GetHasherDigestSize(UInt32 index); + + #endif + + HRESULT CreateInArchive(unsigned formatIndex, CMyComPtr &archive) const { const CArcInfoEx &ai = Formats[formatIndex]; #ifdef EXTERNAL_CODECS if (ai.LibIndex < 0) #endif { + COM_TRY_BEGIN archive = ai.CreateInArchive(); return S_OK; + COM_TRY_END } #ifdef EXTERNAL_CODECS return CreateArchiveHandler(ai, (void **)&archive, false); #endif } - HRESULT CreateOutArchive(int formatIndex, CMyComPtr &archive) const + + #ifndef _SFX + + HRESULT CreateOutArchive(unsigned formatIndex, CMyComPtr &archive) const { const CArcInfoEx &ai = Formats[formatIndex]; #ifdef EXTERNAL_CODECS if (ai.LibIndex < 0) #endif { + COM_TRY_BEGIN archive = ai.CreateOutArchive(); return S_OK; + COM_TRY_END } #ifdef EXTERNAL_CODECS return CreateArchiveHandler(ai, (void **)&archive, true); #endif } + int FindOutFormatFromName(const UString &name) const { - for (int i = 0; i < Formats.Size(); i++) + FOR_VECTOR (i, Formats) { const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; - if (arc.Name.CompareNoCase(name) == 0) + if (arc.Name.IsEqualToNoCase(name)) return i; } return -1; } - #ifdef EXTERNAL_CODECS - HRESULT CreateCoder(const UString &name, bool encode, CMyComPtr &coder) const; - #endif - + #endif // _SFX }; #endif diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp old mode 100755 new mode 100644 index 60d2f6f5..ac077660 --- a/CPP/7zip/UI/Common/OpenArchive.cpp +++ b/CPP/7zip/UI/Common/OpenArchive.cpp @@ -2,27 +2,487 @@ #include "StdAfx.h" -#include "Common/Wildcard.h" +// #define SHOW_DEBUG_INFO -#include "Windows/FileDir.h" -#include "Windows/PropVariant.h" +#ifdef SHOW_DEBUG_INFO +#include +#endif + +#include "../../../../C/CpuArch.h" + +#include "../../../Common/ComTry.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/StringToInt.h" +#include "../../../Common/Wildcard.h" + +#include "../../../Windows/FileDir.h" #include "../../Common/FileStreams.h" +#include "../../Common/LimitedStreams.h" +#include "../../Common/ProgressUtils.h" #include "../../Common/StreamUtils.h" +#include "../../Compress/CopyCoder.h" + #include "DefaultName.h" #include "OpenArchive.h" +#ifndef _SFX +#include "SetProperties.h" +#endif + +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif + +// increase it, if you need to support larger SFX stubs +static const UInt64 kMaxCheckStartPosition = 1 << 22; + +/* +Open: + - formatIndex >= 0 (exact Format) + 1) Open with main type. Archive handler is allowed to use archive start finder. + Warning, if there is tail. + + - formatIndex = -1 (Parser:0) (default) + - same as #1 but doesn't return Parser + + - formatIndex = -2 (#1) + - file has supported extension (like a.7z) + Open with that main type (only starting from start of file). + - open OK: + - if there is no tail - return OK + - if there is tail: + - archive is not "Self Exe" - return OK with Warning, that there is tail + - archive is "Self Exe" + ignore "Self Exe" stub, and tries to open tail + - tail can be open as archive - shows that archive and stub size property. + - tail can't be open as archive - shows Parser ??? + - open FAIL: + Try to open with all other types from offset 0 only. + If some open type is OK and physical archive size is uequal or larger + than file size, then return that archive with warning that can not be open as [extension type]. + If extension was EXE, it will try to open as unknown_extension case + - file has unknown extension (like a.hhh) + It tries to open via parser code. + - if there is full archive or tail archive and unknown block or "Self Exe" + at front, it shows tail archive and stub size property. + - in another cases, if there is some archive inside file, it returns parser/ + - in another cases, it retuens S_FALSE + + + - formatIndex = -3 (#2) + - same as #1, but + - stub (EXE) + archive is open in Parser + + - formatIndex = -4 (#3) + - returns only Parser. skip full file archive. And show other sub-archives + + - formatIndex = -5 (#4) + - returns only Parser. skip full file archive. And show other sub-archives for each byte pos + +*/ + + + + using namespace NWindows; -// Static-SFX (for Linux) can be big. -const UInt64 kMaxCheckStartPosition = 1 << 22; +/* +#ifdef _SFX +#define OPEN_PROPS_PARAM +#else +#define OPEN_PROPS_PARAM , props +#endif +*/ + +/* +CArc::~CArc() +{ + GetRawProps.Release(); + Archive.Release(); + printf("\nCArc::~CArc()\n"); +} +*/ + +#ifndef _SFX + +namespace NArchive { +namespace NParser { + +struct CParseItem +{ + UInt64 Offset; + UInt64 Size; + // UInt64 OkSize; + UString Name; + UString Extension; + FILETIME FileTime; + UString Comment; + UString ArcType; + + bool FileTime_Defined; + bool UnpackSize_Defined; + bool NumSubDirs_Defined; + bool NumSubFiles_Defined; + + bool IsSelfExe; + bool IsNotArcType; + + UInt64 UnpackSize; + UInt64 NumSubDirs; + UInt64 NumSubFiles; + + int FormatIndex; + + bool LenIsUnknown; + + CParseItem(): + LenIsUnknown(false), + FileTime_Defined(false), + UnpackSize_Defined(false), + NumSubFiles_Defined(false), + NumSubDirs_Defined(false), + IsSelfExe(false), + IsNotArcType(false) + // OkSize(0) + {} + + /* + bool IsEqualTo(const CParseItem &item) const + { + return Offset == item.Offset && Size == item.Size; + } + */ + + void NormalizeOffset() + { + if ((Int64)Offset < 0) + { + Size += Offset; + // OkSize += Offset; + Offset = 0; + } + } +}; + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ +public: + CObjectVector _items; + UInt64 _maxEndOffset; + CMyComPtr _stream; + + MY_UNKNOWN_IMP2( + IInArchive, + IInArchiveGetStream) + + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); + + UInt64 GetLastEnd() const + { + if (_items.IsEmpty()) + return 0; + const CParseItem &back = _items.Back(); + return back.Offset + back.Size; + } + + void AddUnknownItem(UInt64 next); + int FindInsertPos(const CParseItem &item); + void AddItem(const CParseItem &item); + // void Init(); + + CHandler() + { + _maxEndOffset = 0; + } +}; + +int CHandler::FindInsertPos(const CParseItem &item) +{ + unsigned left = 0, right = _items.Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + const CParseItem & midItem = _items[mid]; + if (item.Offset < midItem.Offset) + right = mid; + else if (item.Offset > midItem.Offset) + left = mid + 1; + else if (item.Size < midItem.Size) + right = mid; + else if (item.Size > midItem.Size) + left = mid + 1; + else + { + left = mid + 1; + // return -1; + } + } + return left; +} + +void CHandler::AddUnknownItem(UInt64 next) +{ + /* + UInt64 prevEnd = 0; + if (!_items.IsEmpty()) + { + const CParseItem &back = _items.Back(); + prevEnd = back.Offset + back.Size; + } + */ + if (_maxEndOffset < next) + { + CParseItem item2; + item2.Offset = _maxEndOffset; + item2.Size = next - _maxEndOffset; + _maxEndOffset = next; + _items.Add(item2); + } + else if (_maxEndOffset > next && !_items.IsEmpty()) + { + CParseItem &back = _items.Back(); + if (back.LenIsUnknown) + { + back.Size = next - back.Offset; + _maxEndOffset = next; + } + } +} + +void CHandler::AddItem(const CParseItem &item) +{ + AddUnknownItem(item.Offset); + int pos = FindInsertPos(item); + if (pos >= 0) + { + _items.Insert(pos, item); + UInt64 next = item.Offset + item.Size; + if (_maxEndOffset < next) + _maxEndOffset = next; + } +} + +/* +static const STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidType, VT_BSTR}, + { NULL, kpidComment, VT_BSTR}, + { NULL, kpidOffset, VT_UI8}, + { NULL, kpidUnpackSize, VT_UI8}, +// { NULL, kpidNumSubDirs, VT_UI8}, +}; +*/ + +static const Byte kProps[] = +{ + kpidPath, + kpidSize, + kpidMTime, + kpidType, + kpidComment, + kpidOffset, + kpidUnpackSize +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* openArchiveCallback */) +{ + COM_TRY_BEGIN + { + Close(); + _stream = stream; + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _items.Clear(); + _stream.Release(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _items.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NCOM::CPropVariant prop; + + const CParseItem &item = _items[index]; + + switch (propID) + { + case kpidPath: + { + wchar_t sz[32]; + ConvertUInt32ToString(index + 1, sz); + UString s = sz; + if (!item.Name.IsEmpty()) + { + s += L'.'; + s += item.Name; + } + if (!item.Extension.IsEmpty()) + { + s += L'.'; + s += item.Extension; + } + prop = s; break; + } + case kpidSize: + case kpidPackSize: prop = item.Size; break; + case kpidOffset: prop = item.Offset; break; + case kpidUnpackSize: if (item.UnpackSize_Defined) prop = item.UnpackSize; break; + case kpidNumSubFiles: if (item.NumSubFiles_Defined) prop = item.NumSubFiles; break; + case kpidNumSubDirs: if (item.NumSubDirs_Defined) prop = item.NumSubDirs; break; + case kpidMTime: if (item.FileTime_Defined) prop = item.FileTime; break; + case kpidComment: if (!item.Comment.IsEmpty()) prop = item.Comment; break; + case kpidType: if (!item.ArcType.IsEmpty()) prop = item.ArcType; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)(Int32)-1); + if (allFilesMode) + numItems = _items.Size(); + if (_stream && numItems == 0) + return S_OK; + UInt64 totalSize = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + totalSize += _items[allFilesMode ? i : indices[i]].Size; + extractCallback->SetTotal(totalSize); + + totalSize = 0; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStream(streamSpec); + streamSpec->SetStream(_stream); + + CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream; + CMyComPtr outStream(outStreamSpec); + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; -HRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) + for (i = 0; i < numItems; i++) + { + lps->InSize = totalSize; + lps->OutSize = totalSize; + RINOK(lps->SetCur()); + CMyComPtr realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + const CParseItem &item = _items[index]; + + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + UInt64 unpackSize = item.Size; + totalSize += unpackSize; + bool skipMode = false; + if (!testMode && !realOutStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + + outStreamSpec->SetStream(realOutStream); + realOutStream.Release(); + outStreamSpec->Init(skipMode ? 0 : unpackSize, true); + + Int32 opRes = NExtract::NOperationResult::kOK; + RINOK(_stream->Seek(item.Offset, STREAM_SEEK_SET, NULL)); + streamSpec->Init(unpackSize); + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + + if (outStreamSpec->GetRem() != 0) + opRes = NExtract::NOperationResult::kDataError; + outStreamSpec->ReleaseStream(); + RINOK(extractCallback->SetOperationResult(opRes)); + } + return S_OK; + COM_TRY_END +} + + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + const CParseItem &item = _items[index]; + return CreateLimitedInStream(_stream, item.Offset, item.Size, stream); + COM_TRY_END +} + +}} + +#endif + +HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) +{ + NCOM::CPropVariant prop; + result = false; + RINOK(arc->GetProperty(index, propID, &prop)); + if (prop.vt == VT_BOOL) + result = VARIANT_BOOLToBool(prop.boolVal); + else if (prop.vt != VT_EMPTY) + return E_FAIL; + return S_OK; +} + +HRESULT Archive_IsItem_Folder(IInArchive *arc, UInt32 index, bool &result) +{ + return Archive_GetItemBoolProp(arc, index, kpidIsDir, result); +} + +HRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) +{ + return Archive_GetItemBoolProp(arc, index, kpidIsAux, result); +} + +HRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) +{ + return Archive_GetItemBoolProp(arc, index, kpidIsAltStream, result); +} + +HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &result) +{ + return Archive_GetItemBoolProp(arc, index, kpidIsDeleted, result); +} + +static HRESULT Archive_GetArcBoolProp(IInArchive *arc, PROPID propid, bool &result) { NCOM::CPropVariant prop; result = false; - RINOK(archive->GetProperty(index, propID, &prop)); + RINOK(arc->GetArchiveProperty(propid, &prop)); if (prop.vt == VT_BOOL) result = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt != VT_EMPTY) @@ -30,13 +490,176 @@ HRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID, return S_OK; } -HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) +static HRESULT Archive_GetArcProp_UInt(IInArchive *arc, PROPID propid, UInt64 &result, bool &defined) +{ + defined = false; + NCOM::CPropVariant prop; + RINOK(arc->GetArchiveProperty(propid, &prop)); + switch (prop.vt) + { + case VT_UI4: result = prop.ulVal; defined = true; break; + case VT_I4: result = prop.lVal; defined = true; break; + case VT_UI8: result = (UInt64)prop.uhVal.QuadPart; defined = true; break; + case VT_I8: result = (UInt64)prop.hVal.QuadPart; defined = true; break; + case VT_EMPTY: break; + default: return E_FAIL; + } + return S_OK; +} + +static HRESULT Archive_GetArcProp_Int(IInArchive *arc, PROPID propid, Int64 &result, bool &defined) +{ + defined = false; + NCOM::CPropVariant prop; + RINOK(arc->GetArchiveProperty(propid, &prop)); + switch (prop.vt) + { + case VT_UI4: result = prop.ulVal; defined = true; break; + case VT_I4: result = prop.lVal; defined = true; break; + case VT_UI8: result = (Int64)prop.uhVal.QuadPart; defined = true; break; + case VT_I8: result = (Int64)prop.hVal.QuadPart; defined = true; break; + case VT_EMPTY: break; + default: return E_FAIL; + } + return S_OK; +} + +HRESULT CArc::GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const { - return GetArchiveItemBoolProp(archive, index, kpidIsDir, result); + if (!GetRawProps) + return E_FAIL; + UInt32 curIndex = index; + bool prevWasAltStream = false; + for (;;) + { + UString s; + + #ifdef MY_CPU_LE + const void *p; + UInt32 size; + UInt32 propType; + RINOK(GetRawProps->GetRawProp(curIndex, kpidName, &p, &size, &propType)); + if (p && propType == PROP_DATA_TYPE_wchar_t_PTR_Z_LE) + s = (const wchar_t *)p; + else + #endif + { + NCOM::CPropVariant prop; + RINOK(Archive->GetProperty(curIndex, kpidName, &prop)); + if (prop.vt == VT_BSTR) + s = prop.bstrVal; + else if (prop.vt == VT_EMPTY) + s = L"[Content]"; + else + return E_FAIL; + } + + if (prevWasAltStream) + parts[0] = s + L":" + parts[0]; + else + parts.Insert(0, s); + + UInt32 curParent = (UInt32)(Int32)-1; + UInt32 parentType = 0; + RINOK(GetRawProps->GetParent(curIndex, &curParent, &parentType)); + if (parent == curParent) + return S_OK; + if (curParent == (UInt32)(Int32)-1) + return E_FAIL; + prevWasAltStream = (parentType == NParentType::kAltStream); + curIndex = curParent; + } } HRESULT CArc::GetItemPath(UInt32 index, UString &result) const { + #ifdef MY_CPU_LE + if (GetRawProps) + { + const void *p; + UInt32 size; + UInt32 propType; + if (!IsTree) + { + if (GetRawProps->GetRawProp(index, kpidPath, &p, &size, &propType) == S_OK && + propType == NPropDataType::kUtf16z) + { + unsigned len = size / 2 - 1; + wchar_t *s = result.GetBuffer(len); + for (unsigned i = 0; i < len; i++) + { + wchar_t c = GetUi16(p); + p = (const void *)((const Byte *)p + 2); + if (c == '/') + c = WCHAR_PATH_SEPARATOR; + *s++ = c; + } + result.ReleaseBuffer(len); + return S_OK; + } + } + /* + else if (GetRawProps->GetRawProp(index, kpidName, &p, &size, &propType) == S_OK && + p && propType == NPropDataType::kUtf16z) + { + UInt32 totalSize = size; + bool isOK = false; + { + UInt32 index2 = index; + for (;;) + { + UInt32 parent = (UInt32)(Int32)-1; + UInt32 parentType = 0; + if (GetRawProps->GetParent(index2, &parent, &parentType) != S_OK) + break; + if (parent == (UInt32)(Int32)-1) + { + isOK = true; + break; + } + index2 = parent; + UInt32 size2; + const void *p2; + if (GetRawProps->GetRawProp(index2, kpidName, &p2, &size2, &propType) != S_OK) + break; + totalSize += size2; + } + } + + if (isOK) + { + wchar_t *sz = result.GetBuffer(totalSize / 2); + UInt32 pos = totalSize - size; + memcpy((Byte *)sz + pos, p, size - 2); + UInt32 index2 = index; + for (;;) + { + UInt32 parent = (UInt32)(Int32)-1; + UInt32 parentType = 0; + if (GetRawProps->GetParent(index2, &parent, &parentType) != S_OK) + break; + if (parent == (UInt32)(Int32)-1) + break; + index2 = parent; + UInt32 size2; + const void *p2; + if (GetRawProps->GetRawProp(index2, kpidName, &p2, &size2, &propType) != S_OK) + break; + pos -= size2; + memcpy((Byte *)sz + pos, p2, size2); + sz[(pos + size2 - 2) / 2] = (parentType == 0) ? WCHAR_PATH_SEPARATOR : L':'; + } + result.ReleaseBuffer((totalSize - 2) / 2); + #ifdef _WIN32 + // result.Replace(L'/', WCHAR_PATH_SEPARATOR); + #endif + return S_OK; + } + } + */ + } + #endif + { NCOM::CPropVariant prop; RINOK(Archive->GetProperty(index, kpidPath, &prop)); @@ -47,6 +670,7 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const else return E_FAIL; } + if (result.IsEmpty()) { result = DefaultName; @@ -63,6 +687,42 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const return S_OK; } +HRESULT CArc::GetItemPath2(UInt32 index, UString &result) const +{ + RINOK(GetItemPath(index, result)); + if (Ask_Deleted) + { + bool isDeleted = false; + RINOK(Archive_IsItem_Deleted(Archive, index, isDeleted)); + if (isDeleted) + result.Insert(0, L"[DELETED]" WSTRING_PATH_SEPARATOR); + } + return S_OK; +} + +#ifndef _SFX + +static HRESULT Archive_GetItem_Size(IInArchive *archive, UInt32 index, UInt64 &size, bool &defined) +{ + NCOM::CPropVariant prop; + defined = false; + size = 0; + RINOK(archive->GetProperty(index, kpidSize, &prop)); + switch (prop.vt) + { + case VT_UI1: size = prop.bVal; break; + case VT_UI2: size = prop.uiVal; break; + case VT_UI4: size = prop.ulVal; break; + case VT_UI8: size = (UInt64)prop.uhVal.QuadPart; break; + case VT_EMPTY: return S_OK; + default: return E_FAIL; + } + defined = true; + return S_OK; +} + +#endif + HRESULT CArc::GetItemSize(UInt32 index, UInt64 &size, bool &defined) const { NCOM::CPropVariant prop; @@ -103,304 +763,2031 @@ HRESULT CArc::GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const 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 +#ifndef _SFX + +static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size) +{ + for (size_t i = 0; i < size; i++) + if (p1[i] != p2[i]) + return false; + return true; +} + +static void MakeCheckOrder(CCodecs *codecs, + CIntVector &orderIndices, unsigned numTypes, CIntVector &orderIndices2, + const Byte *data, size_t dataSize) +{ + for (unsigned i = 0; i < numTypes; i++) + { + int index = orderIndices[i]; + if (index < 0) + continue; + const CArcInfoEx &ai = codecs->Formats[index]; + if (ai.SignatureOffset != 0) + { + orderIndices2.Add(index); + orderIndices[i] = -1; + continue; + } + + const CObjectVector &sigs = ai.Signatures; + FOR_VECTOR (k, sigs) + { + const CByteBuffer &sig = sigs[k]; + if (sig.Size() == 0 && dataSize == 0 || + sig.Size() != 0 && sig.Size() <= dataSize && + TestSignature(data, sig, sig.Size())) + { + orderIndices2.Add(index); + orderIndices[i] = -1; + break; + } + } + } +} + +#endif + +#ifdef UNDER_CE + static const unsigned kNumHashBytes = 1; + #define HASH_VAL(buf, pos) ((buf)[pos]) +#else + static const unsigned kNumHashBytes = 2; + #define HASH_VAL(buf, pos) ((buf)[pos] | ((UInt32)(buf)[pos + 1] << 8)) +#endif + + +#ifndef _SFX + +static bool IsExeExt(const UString &ext) +{ + return ext.IsEqualToNoCase(L"exe"); +} + +static const char *k_PreArcFormats[] = +{ + "pe" + , "elf" + , "macho" + , "mub" + , "te" +}; + +static bool IsNameFromList(const UString &s, const char *names[], size_t num) +{ + for (unsigned i = 0; i < num; i++) + if (StringsAreEqualNoCase_Ascii(s, names[i])) + return true; + return false; +} + + +static bool IsPreArcFormat(const CArcInfoEx &ai) +{ + if (ai.Flags_PreArc()) + return true; + return IsNameFromList(ai.Name, k_PreArcFormats, ARRAY_SIZE(k_PreArcFormats)); +} + +static const char *k_Formats_with_simple_signuature[] = +{ + "7z" + , "xz" + , "rar" + , "bzip2" + , "gzip" + , "cab" + , "wim" + , "rpm" + , "vhd" + , "xar" +}; + +static bool IsNewStyleSignature(const CArcInfoEx &ai) +{ + // if (ai.Version >= 0x91F) + if (ai.NewInterface) + return true; + return IsNameFromList(ai.Name, k_Formats_with_simple_signuature, ARRAY_SIZE(k_Formats_with_simple_signuature)); +} + +class CArchiveOpenCallback_Offset: + public IArchiveOpenCallback, + #ifndef _NO_CRYPTO + public ICryptoGetTextPassword, + #endif + public CMyUnknownImp +{ +public: + CMyComPtr Callback; + UInt64 Files; + UInt64 Offset; + + #ifndef _NO_CRYPTO + CMyComPtr GetTextPassword; + MY_UNKNOWN_IMP2( + IArchiveOpenCallback, + ICryptoGetTextPassword) + #else + MY_UNKNOWN_IMP1(IArchiveOpenCallback) + #endif + STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes); + STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes); + #ifndef _NO_CRYPTO + STDMETHOD(CryptoGetTextPassword)(BSTR *password); + #endif +}; + +#ifndef _NO_CRYPTO +STDMETHODIMP CArchiveOpenCallback_Offset::CryptoGetTextPassword(BSTR *password) +{ + COM_TRY_BEGIN + if (GetTextPassword) + return GetTextPassword->CryptoGetTextPassword(password); + return E_NOTIMPL; + COM_TRY_END +} +#endif + +STDMETHODIMP CArchiveOpenCallback_Offset::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */) +{ + return S_OK; +} + +STDMETHODIMP CArchiveOpenCallback_Offset::SetCompleted(const UInt64 * /* files */, const UInt64 *bytes) +{ + if (!Callback) + return S_OK; + UInt64 value = Offset; + if (bytes) + value += *bytes; + return Callback->SetCompleted(&Files, &value); +} + +#endif + +UInt32 GetOpenArcErrorFlags(const NCOM::CPropVariant &prop, bool *isDefinedProp) +{ + if (isDefinedProp != NULL) + *isDefinedProp = false; + + switch (prop.vt) + { + case VT_UI8: if (isDefinedProp) *isDefinedProp = true; return (UInt32)prop.uhVal.QuadPart; + case VT_UI4: if (isDefinedProp) *isDefinedProp = true; return prop.ulVal; + case VT_EMPTY: return 0; + default: throw 151199; + } +} + +void CArcErrorInfo::ClearErrors() +{ + // ErrorFormatIndex = -1; // we don't need to clear ErrorFormatIndex here !!! + + ThereIsTail = false; + UnexpecedEnd = false; + IgnoreTail = false; + // NonZerosTail = false; + ErrorFlags_Defined = false; + ErrorFlags = 0; + WarningFlags = 0; + TailSize = 0; + + ErrorMessage.Empty(); + WarningMessage.Empty(); +} + +HRESULT CArc::ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes) +{ + // OkPhySize_Defined = false; + PhySizeDefined = false; + PhySize = 0; + Offset = 0; + AvailPhySize = FileSize - startPos; + + ErrorInfo.ClearErrors(); + { + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(kpidErrorFlags, &prop)); + ErrorInfo.ErrorFlags = GetOpenArcErrorFlags(prop, &ErrorInfo.ErrorFlags_Defined); + } + { + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(kpidWarningFlags, &prop)); + ErrorInfo.WarningFlags = GetOpenArcErrorFlags(prop); + } + + { + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(kpidError, &prop)); + if (prop.vt != VT_EMPTY) + ErrorInfo.ErrorMessage = (prop.vt == VT_BSTR) ? prop.bstrVal : L"Unknown error"; + } + + { + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(kpidWarning, &prop)); + if (prop.vt != VT_EMPTY) + ErrorInfo.WarningMessage = (prop.vt == VT_BSTR) ? prop.bstrVal : L"Unknown warning"; + } + + if (openRes == S_OK || ErrorInfo.IsArc_After_NonOpen()) + { + RINOK(Archive_GetArcProp_UInt(archive, kpidPhySize, PhySize, PhySizeDefined)); + /* + RINOK(Archive_GetArcProp_UInt(archive, kpidOkPhySize, OkPhySize, OkPhySize_Defined)); + if (!OkPhySize_Defined) + { + OkPhySize_Defined = PhySizeDefined; + OkPhySize = PhySize; + } + */ + + bool offsetDefined; + RINOK(Archive_GetArcProp_Int(archive, kpidOffset, Offset, offsetDefined)); + + Int64 globalOffset = startPos + Offset; + AvailPhySize = FileSize - globalOffset; + if (PhySizeDefined) + { + UInt64 endPos = globalOffset + PhySize; + if (endPos < FileSize) + { + AvailPhySize = PhySize; + ErrorInfo.ThereIsTail = true; + ErrorInfo.TailSize = FileSize - endPos; + } + else if (endPos > FileSize) + ErrorInfo.UnexpecedEnd = true; + } + } + + return S_OK; +} + +/* +static PrintNumber(const char *s, int n) +{ + char temp[100]; + sprintf(temp, "%s %d", s, n); + OutputDebugStringA(temp); +} +*/ + +HRESULT CArc::PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr &archive) +{ + // OutputDebugStringW(L"a1"); + // PrintNumber("formatIndex", formatIndex); + + RINOK(op.codecs->CreateInArchive(formatIndex, archive)); + // OutputDebugStringW(L"a2"); + if (!archive) + return S_OK; + + #ifdef EXTERNAL_CODECS + { + CMyComPtr setCompressCodecsInfo; + archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); + if (setCompressCodecsInfo) + { + RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(op.codecs)); + } + } + #endif + + // OutputDebugStringW(ai.Name); + // OutputDebugStringW(L"a3"); + + #ifndef _SFX + const CArcInfoEx &ai = op.codecs->Formats[formatIndex]; + if (ai.Flags_PreArc()) + { + /* we notify parsers that extract executables, that they don't need + to open archive, if there is tail after executable (for SFX cases) */ + CMyComPtr allowTail; + archive.QueryInterface(IID_IArchiveAllowTail, (void **)&allowTail); + if (allowTail) + allowTail->AllowTail(BoolToInt(true)); + } + if (op.props) + { + /* + FOR_VECTOR (y, op.props) + { + const COptionalOpenProperties &optProps = (*op.props)[y]; + if (optProps.FormatName.IsEmpty() || optProps.FormatName.CompareNoCase(ai.Name) == 0) + { + RINOK(SetProperties(archive, optProps.Props)); + break; + } + } + */ + RINOK(SetProperties(archive, *op.props)); + } + #endif + return S_OK; +} + +#ifndef _SFX + +static HRESULT ReadParseItemProps(IInArchive *archive, const CArcInfoEx &ai, NArchive::NParser::CParseItem &pi) +{ + pi.Extension = ai.GetMainExt(); + pi.FileTime_Defined = false; + pi.ArcType = ai.Name; + + RINOK(Archive_GetArcBoolProp(archive, kpidIsNotArcType, pi.IsNotArcType)); + + // RINOK(Archive_GetArcBoolProp(archive, kpidIsSelfExe, pi.IsSelfExe)); + pi.IsSelfExe = ai.Flags_PreArc(); + + { + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(kpidMTime, &prop)); + if (prop.vt == VT_FILETIME) + { + pi.FileTime_Defined = true; + pi.FileTime = prop.filetime; + } + } + + if (!pi.FileTime_Defined) + { + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(kpidCTime, &prop)); + if (prop.vt == VT_FILETIME) + { + pi.FileTime_Defined = true; + pi.FileTime = prop.filetime; + } + } + + { + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(kpidName, &prop)); + if (prop.vt == VT_BSTR) + { + pi.Name = prop.bstrVal; + pi.Extension.Empty(); + } + else + { + RINOK(archive->GetArchiveProperty(kpidExtension, &prop)); + if (prop.vt == VT_BSTR) + pi.Extension = prop.bstrVal; + } + } + + { + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(kpidShortComment, &prop)); + if (prop.vt == VT_BSTR) + pi.Comment = prop.bstrVal; + } + + + UInt32 numItems; + RINOK(archive->GetNumberOfItems(&numItems)); + + // pi.NumSubFiles = numItems; + // RINOK(Archive_GetArcProp_UInt(archive, kpidUnpackSize, pi.UnpackSize, pi.UnpackSize_Defined)); + // if (!pi.UnpackSize_Defined) + { + pi.NumSubFiles = 0; + pi.NumSubDirs = 0; + pi.UnpackSize = 0; + for (UInt32 i = 0; i < numItems; i++) + { + UInt64 size = 0; + bool defined = false; + Archive_GetItem_Size(archive, i, size, defined); + if (defined) + { + pi.UnpackSize_Defined = true; + pi.UnpackSize += size; + } + + bool isDir = false; + Archive_IsItem_Folder(archive, i, isDir); + if (isDir) + pi.NumSubDirs++; + else + pi.NumSubFiles++; + } + if (pi.NumSubDirs != 0) + pi.NumSubDirs_Defined = true; + pi.NumSubFiles_Defined = true; + } + + return S_OK; +} + +#endif + +HRESULT CArc::CheckZerosTail(const COpenOptions &op, UInt64 offset) +{ + if (!op.stream) + return S_OK; + RINOK(op.stream->Seek(offset, STREAM_SEEK_SET, NULL)); + const UInt32 kBufSize = 1 << 11; + Byte buf[kBufSize]; + + for (;;) + { + UInt32 processed = 0; + RINOK(op.stream->Read(buf, kBufSize, &processed)); + if (processed == 0) + { + // ErrorInfo.NonZerosTail = false; + ErrorInfo.IgnoreTail = true; + return S_OK; + } + for (size_t i = 0; i < processed; i++) + { + if (buf[i] != 0) + { + // ErrorInfo.IgnoreTail = false; + // ErrorInfo.NonZerosTail = true; + return S_OK; + } + } + } +} + +#ifndef _SFX + +class CExtractCallback_To_OpenCallback: + public IArchiveExtractCallback, + public ICompressProgressInfo, + public CMyUnknownImp +{ +public: + CMyComPtr Callback; + UInt64 Files; + UInt64 Offset; + + MY_UNKNOWN_IMP2(IArchiveExtractCallback, ICompressProgressInfo) + INTERFACE_IArchiveExtractCallback(;) + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); + void Init(IArchiveOpenCallback *callback) + { + Callback = callback; + Files = 0; + Offset = 0; + } +}; + +STDMETHODIMP CExtractCallback_To_OpenCallback::SetTotal(UInt64 /* size */) +{ + return S_OK; +} + +STDMETHODIMP CExtractCallback_To_OpenCallback::SetCompleted(const UInt64 * /* completeValue */) +{ + return S_OK; +} + +STDMETHODIMP CExtractCallback_To_OpenCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */) +{ + if (Callback) + { + UInt64 value = Offset; + if (inSize) + value += *inSize; + return Callback->SetCompleted(&Files, &value); + } + return S_OK; +} + +STDMETHODIMP CExtractCallback_To_OpenCallback::GetStream(UInt32 /* index */, ISequentialOutStream **outStream, Int32 /* askExtractMode */) +{ + *outStream = 0; + return S_OK; +} + +STDMETHODIMP CExtractCallback_To_OpenCallback::PrepareOperation(Int32 /* askExtractMode */) +{ + return S_OK; +} + +STDMETHODIMP CExtractCallback_To_OpenCallback::SetOperationResult(Int32 /* operationResult */) +{ + return S_OK; +} + +static HRESULT OpenArchiveSpec(IInArchive *archive, bool needPhySize, + IInStream *stream, const UInt64 *maxCheckStartPosition, + IArchiveOpenCallback *openCallback, + IArchiveExtractCallback *extractCallback) +{ + /* + if (needPhySize) + { + CMyComPtr open2; + archive->QueryInterface(IID_IArchiveOpen2, (void **)&open2); + if (open2) + return open2->ArcOpen2(stream, kOpenFlags_RealPhySize, openCallback); + } + */ + RINOK(archive->Open(stream, maxCheckStartPosition, openCallback)); + if (needPhySize) + { + bool phySize_Defined = false; + UInt64 phySize = 0; + RINOK(Archive_GetArcProp_UInt(archive, kpidPhySize, phySize, phySize_Defined)); + if (phySize_Defined) + return S_OK; + + bool phySizeCantBeDetected = false;; + RINOK(Archive_GetArcBoolProp(archive, kpidPhySizeCantBeDetected, phySizeCantBeDetected)); + + if (!phySizeCantBeDetected) + { + RINOK(archive->Extract(0, (UInt32)(Int32)-1, BoolToInt(true), extractCallback)); + } + } + return S_OK; +} + +static int FindFormatForArchiveType(CCodecs *codecs, CIntVector orderIndices, const char *name) +{ + FOR_VECTOR (i, orderIndices) + if (StringsAreEqualNoCase_Ascii(codecs->Formats[orderIndices[i]].Name, name)) + return i; + return -1; +} + +#endif + +HRESULT CArc::OpenStream2(const COpenOptions &op) +{ + // fprintf(stdout, "\nOpen: %S", Path); fflush(stdout); + + Archive.Release(); + GetRawProps.Release(); + GetRootProps.Release(); + + ErrorInfo.ClearErrors(); + ErrorInfo.ErrorFormatIndex = -1; + + IsParseArc = false; + ArcStreamOffset = 0; + + // OutputDebugStringW(L"1"); + // OutputDebugStringW(Path); + + const UString fileName = ExtractFileNameFromPath(Path); + UString extension; + { + int dotPos = fileName.ReverseFind(L'.'); + if (dotPos >= 0) + extension = fileName.Ptr(dotPos + 1); + } + + CIntVector orderIndices; + + bool searchMarkerInHandler = false; + #ifdef _SFX + searchMarkerInHandler = true; + #endif + + CBoolArr isMainFormatArr(op.codecs->Formats.Size()); + { + FOR_VECTOR(i, op.codecs->Formats) + isMainFormatArr[i] = false; + } + + UInt64 maxStartOffset = + op.openType.MaxStartOffset_Defined ? + op.openType.MaxStartOffset : + kMaxCheckStartPosition; + + #ifndef _SFX + bool isUnknownExt = false; + #endif + + bool isForced = false; + unsigned numMainTypes = 0; + int formatIndex = op.openType.FormatIndex; + + if (formatIndex >= 0) + { + isForced = true; + orderIndices.Add(formatIndex); + numMainTypes = 1; + isMainFormatArr[formatIndex] = true; + + searchMarkerInHandler = true; + } + else + { + unsigned numFinded = 0; + #ifndef _SFX + bool isPrearcExt = false; + #endif + + { + FOR_VECTOR (i, op.codecs->Formats) + { + const CArcInfoEx &ai = op.codecs->Formats[i]; + + if (IgnoreSplit || !op.openType.CanReturnArc) + if (ai.IsSplit()) + continue; + if (op.excludedFormats->FindInSorted(i) >= 0) + continue; + + #ifndef _SFX + if (IsPreArcFormat(ai)) + isPrearcExt = true; + #endif + + if (ai.FindExtension(extension) >= 0) + { + // PrintNumber("orderIndices.Insert", i); + orderIndices.Insert(numFinded++, i); + isMainFormatArr[i] = true; + } + else + orderIndices.Add(i); + } + } + + if (!op.stream) + { + if (numFinded != 1) + return E_NOTIMPL; + orderIndices.DeleteFrom(1); + } + // PrintNumber("numFinded", numFinded ); + + /* + if (op.openOnlySpecifiedByExtension) + { + if (numFinded != 0 && !IsExeExt(extension)) + orderIndices.DeleteFrom(numFinded); + } + */ + + #ifndef _SFX + + if (op.stream && orderIndices.Size() >= 2) + { + RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL)); + CByteBuffer byteBuffer; + CIntVector orderIndices2; + if (numFinded == 0 || IsExeExt(extension)) + { + // signature search was here + } + else if (extension == L"000" || extension == L"001") + { + int i = FindFormatForArchiveType(op.codecs, orderIndices, "rar"); + if (i >= 0) + { + const size_t kBufSize = (1 << 10); + byteBuffer.Alloc(kBufSize); + size_t processedSize = kBufSize; + RINOK(ReadStream(op.stream, byteBuffer, &processedSize)); + if (processedSize >= 16) + { + const Byte *buf = byteBuffer; + const Byte kRarHeader[] = { 0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00 }; + if (TestSignature(buf, kRarHeader, 7) && buf[9] == 0x73 && (buf[10] & 1) != 0) + { + orderIndices2.Add(orderIndices[i]); + orderIndices[i] = -1; + if (i >= (int)numFinded) + numFinded++; + } + } + } + } + else + { + const size_t kBufSize = (1 << 10); + byteBuffer.Alloc(kBufSize); + size_t processedSize = kBufSize; + RINOK(ReadStream(op.stream, byteBuffer, &processedSize)); + if (processedSize == 0) + return S_FALSE; + + /* + check type order: + 1) matched extension, no signuature + 2) matched extension, matched signuature + // 3) no signuature + // 4) matched signuature + */ + + MakeCheckOrder(op.codecs, orderIndices, numFinded, orderIndices2, NULL, 0); + MakeCheckOrder(op.codecs, orderIndices, numFinded, orderIndices2, byteBuffer, processedSize); + // MakeCheckOrder(op.codecs, orderIndices, orderIndices.Size(), orderIndices2, NULL, 0); + // MakeCheckOrder(op.codecs, orderIndices, orderIndices.Size(), orderIndices2, byteBuffer, processedSize); + } + + FOR_VECTOR (i, orderIndices) + { + int val = orderIndices[i]; + if (val != -1) + orderIndices2.Add(val); + } + orderIndices = orderIndices2; + } + + if (orderIndices.Size() >= 2) + { + int iIso = FindFormatForArchiveType(op.codecs, orderIndices, "iso"); + int iUdf = FindFormatForArchiveType(op.codecs, orderIndices, "udf"); + if (iUdf > iIso && iIso >= 0) + { + int isoIndex = orderIndices[iIso]; + int udfIndex = orderIndices[iUdf]; + orderIndices[iUdf] = isoIndex; + orderIndices[iIso] = udfIndex; + } + } + + numMainTypes = numFinded; + isUnknownExt = (numMainTypes == 0) || isPrearcExt; + + #else // _SFX + + numMainTypes = orderIndices.Size(); + + #endif + } + + UInt64 fileSize = 0; + if (op.stream) + { + RINOK(op.stream->Seek(0, STREAM_SEEK_END, &fileSize)); + RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL)); + } + FileSize = fileSize; + + + #ifndef _SFX + + CBoolArr skipFrontalFormat(op.codecs->Formats.Size()); + { + FOR_VECTOR(i, op.codecs->Formats) + skipFrontalFormat[i] = false; + } + + #endif + + const COpenType &mode = op.openType; + + + + + + if (mode.CanReturnArc) + { + // ---------- OPEN main type by extenssion ---------- + + unsigned numCheckTypes = orderIndices.Size(); + if (formatIndex >= 0) + numCheckTypes = numMainTypes; + + for (unsigned i = 0; i < numCheckTypes; i++) + { + FormatIndex = orderIndices[i]; + const CArcInfoEx &ai = op.codecs->Formats[FormatIndex]; + // OutputDebugStringW(ai.Name); + + bool exactOnly = false; + if (i >= numMainTypes) + { + if (!ai.Flags_BackwardOpen() + // && !ai.Flags_PureStartOpen() + ) + continue; + exactOnly = true; + } + + // Some handlers do not set total bytes. So we set it here + RINOK(op.callback->SetTotal(NULL, &fileSize)); + if (op.stream) + { + RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL)); + } + + CMyComPtr archive; + + RINOK(PrepareToOpen(op, FormatIndex, archive)); + if (!archive) + continue; + + HRESULT result; + if (op.stream) + { + UInt64 searchLimit = (!exactOnly && searchMarkerInHandler) ? maxStartOffset: 0; + result = archive->Open(op.stream, &searchLimit, op.callback); + } + else + { + CMyComPtr openSeq; + archive.QueryInterface(IID_IArchiveOpenSeq, (void **)&openSeq); + if (!openSeq) + return E_NOTIMPL; + result = openSeq->OpenSeq(op.seqStream); + } + + RINOK(ReadBasicProps(archive, 0, result)); + + if (result == S_FALSE) + { + bool isArc = ErrorInfo.IsArc_After_NonOpen(); + + #ifndef _SFX + // if it's archive, we allow another open attempt for parser + if (!mode.CanReturnParser || !isArc) + skipFrontalFormat[FormatIndex] = true; + #endif + + if (exactOnly) + continue; + + if (i == 0 && numMainTypes == 1) + { + // we set NonOpenErrorInfo, only if there is only one main format (defined by extension). + ErrorInfo.ErrorFormatIndex = FormatIndex; + NonOpen_ErrorInfo = ErrorInfo; + + if (!mode.CanReturnParser && isArc) + { + // if (formatIndex < 0 && !searchMarkerInHandler) + { + // if bad archive was detected, we don't need additional open attempts + #ifndef _SFX + if (!IsPreArcFormat(ai) /* || !mode.SkipSfxStub */) + #endif + return S_FALSE; + } + } + } + + /* + #ifndef _SFX + if (IsExeExt(extension) || ai.Flags_PreArc()) + { + // openOnlyFullArc = false; + // canReturnTailArc = true; + // limitSignatureSearch = true; + } + #endif + */ + + continue; + } + + RINOK(result); + + #ifndef _SFX + + bool isMainFormat = isMainFormatArr[FormatIndex]; + const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt); + + bool thereIsTail = ErrorInfo.ThereIsTail; + if (thereIsTail && mode.ZerosTailIsAllowed) + { + RINOK(CheckZerosTail(op, Offset + PhySize)); + if (ErrorInfo.IgnoreTail) + thereIsTail = false; + } + + if (Offset > 0) + { + if (exactOnly + || !searchMarkerInHandler + || !specFlags.CanReturn_NonStart() + || (mode.MaxStartOffset_Defined && (UInt64)Offset > mode.MaxStartOffset)) + continue; + } + if (thereIsTail) + { + if (Offset > 0) + { + if (!specFlags.CanReturnMid) + continue; + } + else if (!specFlags.CanReturnFrontal) + continue; + } + + if (Offset > 0 || thereIsTail) + { + if (formatIndex < 0) + { + if (IsPreArcFormat(ai)) + { + // openOnlyFullArc = false; + // canReturnTailArc = true; + /* + if (mode.SkipSfxStub) + limitSignatureSearch = true; + */ + // if (mode.SkipSfxStub) + { + // skipFrontalFormat[FormatIndex] = true; + continue; + } + } + } + } + + #endif + + Archive = archive; + return S_OK; + } + } + + + + #ifndef _SFX + + if (!op.stream) + return S_FALSE; + + if (formatIndex >= 0 && !mode.CanReturnParser) + { + if (mode.MaxStartOffset_Defined) + { + if (mode.MaxStartOffset == 0) + return S_FALSE; + } + else + { + const CArcInfoEx &ai = op.codecs->Formats[formatIndex]; + if (ai.FindExtension(extension) >= 0) + { + const CArcInfoEx &ai = op.codecs->Formats[formatIndex]; + if (ai.Flags_FindSignature() && searchMarkerInHandler) + return S_FALSE; + } + } + } + + NArchive::NParser::CHandler *handlerSpec = new NArchive::NParser::CHandler; + CMyComPtr handler = handlerSpec; + + CExtractCallback_To_OpenCallback *extractCallback_To_OpenCallback_Spec = new CExtractCallback_To_OpenCallback; + CMyComPtr extractCallback_To_OpenCallback = extractCallback_To_OpenCallback_Spec; + extractCallback_To_OpenCallback_Spec->Init(op.callback); + + { + // ---------- Check all possible START archives ---------- + // this code is better for full file archives than Parser's code. + + CByteBuffer byteBuffer; + bool endOfFile = false; + size_t processedSize; + { + size_t bufSize = 1 << 20; // it must be larger than max signature offset or IsArcFunc offset ((1 << 19) + x for UDF) + if (bufSize > fileSize) + { + bufSize = (size_t)fileSize; + endOfFile = true; + } + byteBuffer.Alloc(bufSize); + RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL)); + processedSize = bufSize; + RINOK(ReadStream(op.stream, byteBuffer, &processedSize)); + if (processedSize == 0) + return S_FALSE; + if (processedSize < bufSize) + endOfFile = true; + } + CUIntVector sortedFormats; + + unsigned i; + + int splitIndex = -1; + + for (i = 0; i < orderIndices.Size(); i++) + { + unsigned form = orderIndices[i]; + if (skipFrontalFormat[form]) + continue; + const CArcInfoEx &ai = op.codecs->Formats[form]; + if (ai.IsSplit()) + { + splitIndex = form; + continue; + } + + if (ai.IsArcFunc) + { + UInt32 isArcRes = ai.IsArcFunc(byteBuffer, processedSize); + if (isArcRes == k_IsArc_Res_NO) + continue; + if (isArcRes == k_IsArc_Res_NEED_MORE && endOfFile) + continue; + // if (isArcRes == k_IsArc_Res_YES_LOW_PROB) continue; + sortedFormats.Insert(0, form); + continue; + } + + bool isNewStyleSignature = IsNewStyleSignature(ai); + bool needCheck = !isNewStyleSignature + || ai.Signatures.IsEmpty() + || ai.Flags_PureStartOpen() + || ai.Flags_StartOpen() + || ai.Flags_BackwardOpen(); + + if (isNewStyleSignature && !ai.Signatures.IsEmpty()) + { + unsigned k; + for (k = 0; k < ai.Signatures.Size(); k++) + { + const CByteBuffer &sig = ai.Signatures[k]; + UInt32 signatureEnd = ai.SignatureOffset + (UInt32)sig.Size(); + if (processedSize < signatureEnd) + { + if (!endOfFile) + needCheck = true; + } + else if (memcmp(sig, byteBuffer + ai.SignatureOffset, sig.Size()) == 0) + break; + } + if (k != ai.Signatures.Size()) + { + sortedFormats.Insert(0, form); + continue; + } + } + if (needCheck) + sortedFormats.Add(form); + } + + if (splitIndex >= 0) + sortedFormats.Insert(0, splitIndex); + + for (i = 0; i < sortedFormats.Size(); i++) + { + FormatIndex = sortedFormats[i]; + const CArcInfoEx &ai = op.codecs->Formats[FormatIndex]; + + RINOK(op.callback->SetTotal(NULL, &fileSize)); + RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL)); + + CMyComPtr archive; + RINOK(PrepareToOpen(op, FormatIndex, archive)); + if (!archive) + continue; + + PRF(printf("\nSorted Open %S", (const wchar_t *)ai.Name)); + HRESULT result; + { + UInt64 searchLimit = 0; + /* + if (mode.CanReturnArc) + result = archive->Open(op.stream, &searchLimit, op.callback); + else + */ + result = OpenArchiveSpec(archive, !mode.CanReturnArc, op.stream, &searchLimit, op.callback, extractCallback_To_OpenCallback); + } + + if (result == S_FALSE) + { + skipFrontalFormat[FormatIndex] = true; + // FIXME: maybe we must use LenIsUnknown. + // printf(" OpenForSize Error"); + continue; + } + RINOK(result); + + RINOK(ReadBasicProps(archive, 0, result)); + + if (Offset > 0) + { + continue; // good handler doesn't return such Offset > 0 + // but there are some cases like false prefixed PK00 archive, when + // we can support it? + } + + NArchive::NParser::CParseItem pi; + pi.Offset = Offset; + pi.Size = AvailPhySize; + + // bool needScan = false; + + if (!PhySizeDefined) + { + // it's for Z format + pi.LenIsUnknown = true; + // needScan = true; + // phySize = arcRem; + // nextNeedCheckStartOpen = false; + } + + /* + if (OkPhySize_Defined) + pi.OkSize = pi.OkPhySize; + else + pi.OkSize = pi.Size; + */ + + pi.NormalizeOffset(); + // printf(" phySize = %8d", (unsigned)phySize); + + + if (mode.CanReturnArc) + { + bool isMainFormat = isMainFormatArr[FormatIndex]; + const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt); + bool openCur = false; + + if (!ErrorInfo.ThereIsTail) + openCur = true; + else + { + if (mode.ZerosTailIsAllowed) + { + RINOK(CheckZerosTail(op, Offset + PhySize)); + if (ErrorInfo.IgnoreTail) + openCur = true; + } + if (!openCur) + { + openCur = specFlags.CanReturnFrontal; + if (formatIndex < 0) // format is not forced + { + if (IsPreArcFormat(ai)) + { + // if (mode.SkipSfxStub) + { + openCur = false; + } + } + } + } + } + + if (openCur) + { + InStream = op.stream; + Archive = archive; + return S_OK; + } + } + + skipFrontalFormat[FormatIndex] = true; + + + // if (!mode.CanReturnArc) + /* + if (!ErrorInfo.ThereIsTail) + continue; + */ + if (pi.Offset == 0 && !pi.LenIsUnknown && pi.Size >= FileSize) + continue; + + // printf("\nAdd offset = %d", (int)pi.Offset); + RINOK(ReadParseItemProps(archive, ai, pi)); + handlerSpec->AddItem(pi); + } + } + + + + + + // ---------- PARSER ---------- + + CUIntVector arc2sig; // formatIndex to signatureIndex + CUIntVector sig2arc; // signatureIndex to formatIndex; + { + unsigned sum = 0; + FOR_VECTOR (i, op.codecs->Formats) + { + arc2sig.Add(sum); + const CObjectVector &sigs = op.codecs->Formats[i].Signatures; + sum += sigs.Size(); + FOR_VECTOR (k, sigs) + sig2arc.Add(i); + } + } + + { + CArchiveOpenCallback_Offset *openCallback_Offset_Spec = new CArchiveOpenCallback_Offset; + CMyComPtr openCallback_Offset = openCallback_Offset_Spec; + + const size_t kBeforeSize = 1 << 16; + const size_t kAfterSize = 1 << 20; + const size_t kBufSize = 1 << 22; // it must be more than kBeforeSize + kAfterSize + + const UInt32 kNumVals = (UInt32)1 << (kNumHashBytes * 8); + CByteArr hashBuffer(kNumVals); + Byte *hash = hashBuffer; + memset(hash, 0xFF, kNumVals); + Byte prevs[256]; + memset(prevs, 0xFF, sizeof(prevs)); + if (sig2arc.Size() >= 0xFF) + return S_FALSE; + + CUIntVector difficultFormats; + CBoolArr difficultBools(256); + { + for (unsigned i = 0; i < 256; i++) + difficultBools[i] = false; + } + + bool thereAreHandlersForSearch = false; + + // UInt32 maxSignatureEnd = 0; + + FOR_VECTOR (i, orderIndices) + { + int index = orderIndices[i]; + if (index < 0) + continue; + const CArcInfoEx &ai = op.codecs->Formats[index]; + bool isDifficult = false; + // if (ai.Version < 0x91F) // we don't use parser with old DLL (before 9.31) + if (!ai.NewInterface) + isDifficult = true; + else + { + if (ai.Flags_StartOpen()) + isDifficult = true; + FOR_VECTOR (k, ai.Signatures) + { + const CByteBuffer &sig = ai.Signatures[k]; + /* + UInt32 signatureEnd = ai.SignatureOffset + (UInt32)sig.Size(); + if (maxSignatureEnd < signatureEnd) + maxSignatureEnd = signatureEnd; + */ + if (sig.Size() < kNumHashBytes) + { + isDifficult = true; + continue; + } + thereAreHandlersForSearch = true; + UInt32 v = HASH_VAL(sig, 0); + unsigned sigIndex = arc2sig[index] + k; + prevs[sigIndex] = hash[v]; + hash[v] = (Byte)sigIndex; + } + } + if (isDifficult) + { + difficultFormats.Add(index); + difficultBools[index] = true; + } + } + + if (!thereAreHandlersForSearch) + { + // openOnlyFullArc = true; + // canReturnTailArc = true; + } + + RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL)); + + CLimitedCachedInStream *limitedStreamSpec = new CLimitedCachedInStream; + CMyComPtr limitedStream = limitedStreamSpec; + limitedStreamSpec->SetStream(op.stream); + + openCallback_Offset_Spec->Callback = op.callback; + + #ifndef _NO_CRYPTO + if (op.callback) + { + openCallback_Offset_Spec->Callback.QueryInterface(IID_ICryptoGetTextPassword, &openCallback_Offset_Spec->GetTextPassword); + } + #endif + + RINOK(op.callback->SetTotal(NULL, &fileSize)); + CByteBuffer &byteBuffer = limitedStreamSpec->Buffer; + byteBuffer.Alloc(kBufSize); + + UInt64 callbackPrev = 0; + bool needCheckStartOpen = true; // = true, if we need to test all archives types for current pos. + + bool endOfFile = false; + UInt64 bufPhyPos = 0; + size_t bytesInBuf = 0; + // UInt64 prevPos = 0; + + // ---------- Main Scan Loop ---------- + + UInt64 pos = 0; + + if (!mode.EachPos && handlerSpec->_items.Size() == 1) + { + NArchive::NParser::CParseItem &pi = handlerSpec->_items[0]; + if (!pi.LenIsUnknown && pi.Offset == 0) + pos = pi.Size; + } + + for (;;) + { + // printf("\nPos = %d", (int)pos); + UInt64 posInBuf = pos - bufPhyPos; + + // if (pos > ((UInt64)1 << 35)) break; + + if (!endOfFile) + { + if (bytesInBuf < kBufSize) + { + size_t processedSize = kBufSize - bytesInBuf; + // printf("\nRead ask = %d", (unsigned)processedSize); + UInt64 seekPos = bufPhyPos + bytesInBuf; + RINOK(op.stream->Seek(bufPhyPos + bytesInBuf, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream(op.stream, byteBuffer + bytesInBuf, &processedSize)); + // printf(" processed = %d", (unsigned)processedSize); + if (processedSize == 0) + { + fileSize = seekPos; + endOfFile = true; + } + else + { + bytesInBuf += processedSize; + limitedStreamSpec->SetCache(processedSize, (size_t)bufPhyPos); + } + continue; + } + + if (bytesInBuf < posInBuf) + { + UInt64 skipSize = posInBuf - bytesInBuf; + if (skipSize <= kBeforeSize) + { + size_t keepSize = (size_t)(kBeforeSize - skipSize); + // printf("\nmemmove skip = %d", (int)keepSize); + memmove(byteBuffer, byteBuffer + bytesInBuf - keepSize, keepSize); + bytesInBuf = keepSize; + bufPhyPos = pos - keepSize; + continue; + } + // printf("\nSkip %d", (int)(skipSize - kBeforeSize)); + // RINOK(op.stream->Seek(skipSize - kBeforeSize, STREAM_SEEK_CUR, NULL)); + bytesInBuf = 0; + bufPhyPos = pos - kBeforeSize; + continue; + } + + if (bytesInBuf - posInBuf < kAfterSize) + { + size_t beg = (size_t)posInBuf - kBeforeSize; + // printf("\nmemmove for after beg = %d", (int)beg); + memmove(byteBuffer, byteBuffer + beg, bytesInBuf - beg); + bufPhyPos += beg; + bytesInBuf -= beg; + continue; + } + } + + if (pos >= callbackPrev + (1 << 23)) + { + openCallback_Offset_Spec->Files = handlerSpec->_items.Size(); + openCallback_Offset_Spec->Offset = pos; + RINOK(openCallback_Offset->SetCompleted(NULL, NULL)); + callbackPrev = pos; + } + + { + UInt64 endPos = bufPhyPos + bytesInBuf; + if (fileSize < endPos) + { + FileSize = fileSize; // why ???? + fileSize = endPos; + } + } + + size_t availSize = bytesInBuf - (size_t)posInBuf; + if (availSize < kNumHashBytes) + break; + size_t scanSize = availSize - + ((availSize >= kAfterSize) ? kAfterSize : kNumHashBytes); + + { + /* + UInt64 scanLimit = openOnlyFullArc ? + maxSignatureEnd : + op.openType.ScanSize + maxSignatureEnd; + */ + if (!mode.CanReturnParser) + { + if (pos > maxStartOffset) + break; + UInt64 remScan = maxStartOffset - pos; + if (scanSize > remScan) + scanSize = (size_t)remScan; + } + } + + scanSize++; + + const Byte *buf = byteBuffer + (size_t)posInBuf; + size_t ppp = 0; + + if (!needCheckStartOpen) + { + for (; ppp < scanSize && hash[HASH_VAL(buf, ppp)] == 0xFF; ppp++); + pos += ppp; + if (ppp == scanSize) + continue; + } + + UInt32 v = HASH_VAL(buf, ppp); + bool nextNeedCheckStartOpen = true; + unsigned i = hash[v]; + unsigned indexOfDifficult = 0; + + // ---------- Open Loop for Current Pos ---------- + bool wasOpen = false; + + for (;;) + { + unsigned index; + bool isDifficult; + if (needCheckStartOpen && indexOfDifficult < difficultFormats.Size()) + { + index = difficultFormats[indexOfDifficult++]; + isDifficult = true; + } + else + { + if (i == 0xFF) + break; + index = sig2arc[i]; + unsigned sigIndex = i - arc2sig[index]; + i = prevs[i]; + if (needCheckStartOpen && difficultBools[index]) + continue; + const CArcInfoEx &ai = op.codecs->Formats[index]; + + if (pos < ai.SignatureOffset) + continue; + + /* + if (openOnlyFullArc) + if (pos != ai.SignatureOffset) + continue; + */ + + const CByteBuffer &sig = ai.Signatures[sigIndex]; + + if (ppp + sig.Size() > availSize + || !TestSignature(buf + ppp, sig, sig.Size())) + continue; + // printf("\nSignature OK: %10S %8x %5d", (const wchar_t *)ai.Name, (int)pos, (int)(pos - prevPos)); + // prevPos = pos; + isDifficult = false; + } + + const CArcInfoEx &ai = op.codecs->Formats[index]; + + + if ((isDifficult && pos == 0) || ai.SignatureOffset == pos) + { + // we don't check same archive second time */ + if (skipFrontalFormat[index]) + continue; + } + + UInt64 startArcPos = pos; + if (!isDifficult) + { + if (pos < ai.SignatureOffset) + continue; + startArcPos = pos - ai.SignatureOffset; + /* + // we don't need the check for Z files + if (startArcPos < handlerSpec->GetLastEnd()) + continue; + */ + } + + if (ai.IsArcFunc && startArcPos >= bufPhyPos) + { + size_t offsetInBuf = (size_t)(startArcPos - bufPhyPos); + if (offsetInBuf < bytesInBuf) + { + UInt32 isArcRes = ai.IsArcFunc(byteBuffer + offsetInBuf, bytesInBuf - offsetInBuf); + if (isArcRes == k_IsArc_Res_NO) + continue; + if (isArcRes == k_IsArc_Res_NEED_MORE && endOfFile) + continue; + /* + if (isArcRes == k_IsArc_Res_YES_LOW_PROB) + { + // if (pos != ai.SignatureOffset) + continue; + } + */ + } + // printf("\nIsArc OK: %S", (const wchar_t *)ai.Name); + } + + /* + if (pos == 67109888) + pos = pos; + */ + PRF(printf("\npos = %9I64d : %S", pos, (const wchar_t *)ai.Name)); + + bool isMainFormat = isMainFormatArr[index]; + const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt); + + CMyComPtr archive; + RINOK(PrepareToOpen(op, index, archive)); + if (!archive) + return E_FAIL; + + // OutputDebugStringW(ai.Name); + + UInt64 rem = fileSize - startArcPos; + + UInt64 arcStreamOffset = 0; + + if (ai.Flags_UseGlobalOffset()) + { + limitedStreamSpec->InitAndSeek(0, fileSize); + limitedStream->Seek(startArcPos, STREAM_SEEK_SET, NULL); + } + else + { + limitedStreamSpec->InitAndSeek(startArcPos, rem); + arcStreamOffset = startArcPos; + } + + UInt64 maxCheckStartPosition = 0; + openCallback_Offset_Spec->Files = handlerSpec->_items.Size(); + openCallback_Offset_Spec->Offset = startArcPos; + // HRESULT result = archive->Open(limitedStream, &maxCheckStartPosition, openCallback_Offset); + extractCallback_To_OpenCallback_Spec->Files = 0; + extractCallback_To_OpenCallback_Spec->Offset = startArcPos; + + HRESULT result = OpenArchiveSpec(archive, true, limitedStream, &maxCheckStartPosition, openCallback_Offset, extractCallback_To_OpenCallback); + + RINOK(ReadBasicProps(archive, ai.Flags_UseGlobalOffset() ? 0 : startArcPos, result)); + + bool isOpen = false; + if (result == S_FALSE) + { + if (!mode.CanReturnParser) + { + if (formatIndex < 0 && ErrorInfo.IsArc_After_NonOpen()) + { + ErrorInfo.ErrorFormatIndex = index; + NonOpen_ErrorInfo = ErrorInfo; + // if archive was detected, we don't need additional open attempts + return S_FALSE; + } + continue; + } + if (!ErrorInfo.IsArc_After_NonOpen() || !PhySizeDefined || PhySize == 0) + continue; + } + else + { + isOpen = true; + RINOK(result); + PRF(printf(" OK ")); + } + + // fprintf(stderr, "\n %8X %S", startArcPos, Path); + // printf("\nOpen OK: %S", ai.Name); + + + NArchive::NParser::CParseItem pi; + pi.Offset = startArcPos; + + if (ai.Flags_UseGlobalOffset()) + pi.Offset = Offset; + else if (Offset != 0) + return E_FAIL; + UInt64 arcRem = FileSize - pi.Offset; + UInt64 phySize = arcRem; + bool phySizeDefined = PhySizeDefined; + if (phySizeDefined) + { + if (pi.Offset + PhySize > FileSize) + { + // ErrorInfo.ThereIsTail = true; + PhySize = FileSize - pi.Offset; + } + phySize = PhySize; + } + if (phySize == 0 || (UInt64)phySize > ((UInt64)1 << 63)) + return E_FAIL; + + /* + if (!ai.UseGlobalOffset) + { + if (phySize > arcRem) + { + ThereIsTail = true; + phySize = arcRem; + } + } + */ + + bool needScan = false; + + + if (isOpen && !phySizeDefined) + { + // it's for Z format + pi.LenIsUnknown = true; + needScan = true; + phySize = arcRem; + nextNeedCheckStartOpen = false; + } + + pi.Size = phySize; + /* + if (OkPhySize_Defined) + pi.OkSize = OkPhySize; + */ + pi.NormalizeOffset(); + // printf(" phySize = %8d", (unsigned)phySize); + + /* + if (needSkipFullArc) + if (pi.Offset == 0 && phySizeDefined && pi.Size >= fileSize) + continue; + */ + if (pi.Offset == 0 && !pi.LenIsUnknown && pi.Size >= FileSize) + { + // it's possible for dmg archives + if (!mode.CanReturnArc) + continue; + } + + if (mode.EachPos) + pos++; + else if (needScan) + { + pos++; + /* + if (!OkPhySize_Defined) + pos++; + else + pos = pi.Offset + pi.OkSize; + */ + } + else + pos = pi.Offset + pi.Size; + + + RINOK(ReadParseItemProps(archive, ai, pi)); + + if (pi.Offset < startArcPos && !mode.EachPos /* && phySizeDefined */) + { + /* It's for DMG format. + This code deletes all previous items that are included to current item */ + + while (!handlerSpec->_items.IsEmpty()) + { + { + const NArchive::NParser::CParseItem &back = handlerSpec->_items.Back(); + if (back.Offset < pi.Offset) + break; + if (back.Offset + back.Size > pi.Offset + pi.Size) + break; + } + handlerSpec->_items.DeleteBack(); + } + } + -#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 + if (isOpen && mode.CanReturnArc && phySizeDefined) + { + // if (pi.Offset + pi.Size >= fileSize) + bool openCur = false; + bool thereIsTail = ErrorInfo.ThereIsTail; + if (thereIsTail && mode.ZerosTailIsAllowed) + { + RINOK(CheckZerosTail(op, arcStreamOffset + Offset + PhySize)); + if (ErrorInfo.IgnoreTail) + thereIsTail = false; + } -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 - { + if (pi.Offset != 0) + { + if (!pi.IsNotArcType) + if (thereIsTail) + openCur = specFlags.CanReturnMid; + else + openCur = specFlags.CanReturnTail; + } + else + { + if (!thereIsTail) + openCur = true; + else + openCur = specFlags.CanReturnFrontal; + - 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); - } + if (formatIndex >= -2) + openCur = true; + } + if (formatIndex < 0 && pi.IsSelfExe /* && mode.SkipSfxStub */) + openCur = false; - #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; + // We open file as SFX, if there is front archive or first archive is "Self Executable" + if (!openCur && !pi.IsSelfExe && !thereIsTail && + (!pi.IsNotArcType || pi.Offset == 0)) + { + if (handlerSpec->_items.IsEmpty()) + { + if (specFlags.CanReturnTail) + openCur = true; + } + else if (handlerSpec->_items.Size() == 1) + { + if (handlerSpec->_items[0].IsSelfExe) + { + if (mode.SpecUnknownExt.CanReturnTail) + openCur = true; + } + } + } - 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; - } + if (openCur) + { + InStream = op.stream; + Archive = archive; + FormatIndex = index; + ArcStreamOffset = arcStreamOffset; + return S_OK; + } + } - 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())) + /* + if (openOnlyFullArc) { - orderIndices2.Add(index); - orderIndices[i] = 0xFF; - *ptr = prevs[i]; + ErrorInfo.ClearErrors(); + return S_FALSE; } - else - ptr = &prevs[i]; - i = *ptr; + */ + + pi.FormatIndex = index; + + // printf("\nAdd offset = %d", (int)pi.Offset); + handlerSpec->AddItem(pi); + wasOpen = true; + break; } - while (i != 0xFF); + // ---------- End of Open Loop for Current Pos ---------- + + if (!wasOpen) + pos++; + needCheckStartOpen = (nextNeedCheckStartOpen && wasOpen); } - - for (i = 0; i < orderIndices.Size(); i++) + // ---------- End of Main Scan Loop ---------- + + /* + if (handlerSpec->_items.Size() == 1) { - 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; - } + const NArchive::NParser::CParseItem &pi = handlerSpec->_items[0]; + if (pi.Size == fileSize && pi.Offset == 0) + { + Archive = archive; + FormatIndex2 = pi.FormatIndex; + return S_OK; } } - } - 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) + */ + + if (mode.CanReturnParser) { - orderIndices[iUdf] = isoIndex; - orderIndices[iIso] = udfIndex; + bool returnParser = (handlerSpec->_items.Size() == 1); // it's possible if fileSize was not correct at start of parsing + handlerSpec->AddUnknownItem(fileSize); + if (handlerSpec->_items.Size() == 0) + return S_FALSE; + if (returnParser || handlerSpec->_items.Size() != 1) + { + // return S_FALSE; + handlerSpec->_stream = op.stream; + Archive = handler; + ErrorInfo.ClearErrors(); + IsParseArc = true; + FormatIndex = -1; // It's parser + Offset = 0; + return S_OK; + } } } #endif - } - 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 + if (!Archive) + return S_FALSE; + return S_OK; +} - // OutputDebugStringW(codecs->Formats[FormatIndex].Name); +HRESULT CArc::OpenStream(const COpenOptions &op) +{ + RINOK(OpenStream2(op)); + // PrintNumber("op.formatIndex 3", op.formatIndex); - 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 (Archive) + { + GetRawProps.Release(); + GetRootProps.Release(); + Archive->QueryInterface(IID_IArchiveGetRawProps, (void **)&GetRawProps); + Archive->QueryInterface(IID_IArchiveGetRootProps, (void **)&GetRootProps); - if (result == S_FALSE) - continue; - RINOK(result); + RINOK(Archive_GetArcBoolProp(Archive, kpidIsTree, IsTree)); + RINOK(Archive_GetArcBoolProp(Archive, kpidIsDeleted, Ask_Deleted)); + RINOK(Archive_GetArcBoolProp(Archive, kpidIsAltStream, Ask_AltStream)); + RINOK(Archive_GetArcBoolProp(Archive, kpidIsAux, Ask_Aux)); + RINOK(Archive_GetArcBoolProp(Archive, kpidINode, Ask_INode)); + const UString fileName = ExtractFileNameFromPath(Path); + UString extension; { - NCOM::CPropVariant prop; - archive->GetArchiveProperty(kpidError, &prop); - if (prop.vt != VT_EMPTY) - ErrorMessage = (prop.vt == VT_BSTR) ? prop.bstrVal : L"Unknown error"; + int dotPos = fileName.ReverseFind(L'.'); + if (dotPos >= 0) + extension = fileName.Ptr(dotPos + 1); } - Archive = archive; - const CArcInfoEx &format = codecs->Formats[FormatIndex]; - if (format.Exts.Size() == 0) - DefaultName = GetDefaultName2(fileName, L"", L""); - else + DefaultName.Empty(); + if (FormatIndex >= 0) { - int subExtIndex = format.FindExtension(extension); - if (subExtIndex < 0) - subExtIndex = 0; - const CArcExtInfo &extInfo = format.Exts[subExtIndex]; - DefaultName = GetDefaultName2(fileName, extInfo.Ext, extInfo.AddExt); + const CArcInfoEx &ai = op.codecs->Formats[FormatIndex]; + if (ai.Exts.Size() == 0) + DefaultName = GetDefaultName2(fileName, L"", L""); + else + { + int subExtIndex = ai.FindExtension(extension); + if (subExtIndex < 0) + subExtIndex = 0; + const CArcExtInfo &extInfo = ai.Exts[subExtIndex]; + DefaultName = GetDefaultName2(fileName, extInfo.Ext, extInfo.AddExt); + } } - return S_OK; } - return S_FALSE; + + return S_OK; } -HRESULT CArc::OpenStreamOrFile( - CCodecs *codecs, - int formatIndex, - bool stdInMode, - IInStream *stream, - IArchiveOpenCallback *callback) +#ifdef _WIN32 + static const wchar_t *k_ExeExt = L".exe"; + static const unsigned k_ExeExt_Len = 4; +#else + static const wchar_t *k_ExeExt = L""; + static const unsigned k_ExeExt_Len = 0; +#endif + +HRESULT CArc::OpenStreamOrFile(COpenOptions &op) { CMyComPtr fileStream; CMyComPtr seqStream; - if (stdInMode) + CInFileStream *fileStreamSpec = NULL; + if (op.stdInMode) + { seqStream = new CStdInFileStream; - else if (!stream) + op.seqStream = seqStream; + } + else if (!op.stream) { - CInFileStream *fileStreamSpec = new CInFileStream; + fileStreamSpec = new CInFileStream; fileStream = fileStreamSpec; + Path = filePath; if (!fileStreamSpec->Open(us2fs(Path))) + { return GetLastError(); - stream = fileStream; + } + op.stream = fileStream; + #ifdef _SFX + IgnoreSplit = true; + #endif } /* if (callback) { UInt64 fileSize; - RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize)); - RINOK(callback->SetTotal(NULL, &fileSize)) + RINOK(op.stream->Seek(0, STREAM_SEEK_END, &fileSize)); + RINOK(op.callback->SetTotal(NULL, &fileSize)) } */ - return OpenStream(codecs, formatIndex, stream, seqStream, callback); + HRESULT res = OpenStream(op); + IgnoreSplit = false; + + #ifdef _SFX + + if (res != S_FALSE + || !fileStreamSpec + || !op.callbackSpec + || NonOpen_ErrorInfo.IsArc_After_NonOpen()) + return res; + { + if (filePath.Len() > k_ExeExt_Len + && MyStringCompareNoCase(filePath.RightPtr(k_ExeExt_Len), k_ExeExt) == 0) + { + const UString path2 = filePath.Left(filePath.Len() - k_ExeExt_Len); + FOR_VECTOR (i, op.codecs->Formats) + { + const CArcInfoEx &ai = op.codecs->Formats[i]; + if (ai.IsSplit()) + continue; + UString path3 = path2; + path3 += L"."; + path3 += ai.GetMainExt(); // "7z" for SFX. + Path = path3 + L".001"; + bool isOk = op.callbackSpec->SetSecondFileInfo(us2fs(Path)); + if (!isOk) + { + Path = path3; + isOk = op.callbackSpec->SetSecondFileInfo(us2fs(Path)); + } + if (isOk) + { + if (fileStreamSpec->Open(us2fs(Path))) + { + op.stream = fileStream; + NonOpen_ErrorInfo.ClearErrors_Full(); + if (OpenStream(op) == S_OK) + return S_OK; + } + } + } + } + } + + #endif + + return res; +} + +void CArchiveLink::KeepModeForNextOpen() +{ + for (int i = Arcs.Size() - 1; i >= 0; i--) + { + CMyComPtr keep; + Arcs[i].Archive->QueryInterface(IID_IArchiveKeepModeForNextOpen, (void **)&keep); + if (keep) + keep->KeepModeForNextOpen(); + } } HRESULT CArchiveLink::Close() { - for (int i = Arcs.Size() - 1; i >= 0; i--) + for (int i = Arcs.Size() - 1; i >= 0; i--) { - RINOK(Arcs[i].Archive->Close()); + RINOK(Arcs[i].Close()); } IsOpen = false; + // ErrorsText.Empty(); return S_OK; } void CArchiveLink::Release() { + // NonOpenErrorFormatIndex = -1; + NonOpen_ErrorInfo.ClearErrors(); + NonOpen_ArcPath.Empty(); while (!Arcs.IsEmpty()) Arcs.DeleteBack(); } -HRESULT CArchiveLink::Open( - CCodecs *codecs, - const CIntVector &formatIndices, - bool stdInMode, - IInStream *stream, - const UString &filePath, - IArchiveOpenCallback *callback) +/* +void CArchiveLink::Set_ErrorsText() +{ + FOR_VECTOR(i, Arcs) + { + const CArc &arc = Arcs[i]; + if (!arc.ErrorFlagsText.IsEmpty()) + { + if (!ErrorsText.IsEmpty()) + ErrorsText += L'\n'; + ErrorsText += GetUnicodeString(arc.ErrorFlagsText); + } + if (!arc.ErrorMessage.IsEmpty()) + { + if (!ErrorsText.IsEmpty()) + ErrorsText += L'\n'; + ErrorsText += arc.ErrorMessage; + } + + if (!arc.WarningMessage.IsEmpty()) + { + if (!ErrorsText.IsEmpty()) + ErrorsText += L'\n'; + ErrorsText += arc.WarningMessage; + } + } +} +*/ + +HRESULT CArchiveLink::Open(COpenOptions &op) { Release(); - if (formatIndices.Size() >= 32) + if (op.types->Size() >= 32) return E_NOTIMPL; HRESULT resSpec; @@ -408,29 +2795,79 @@ HRESULT CArchiveLink::Open( for (;;) { resSpec = S_OK; - int formatIndex = -1; - if (formatIndices.Size() >= 1) + + op.openType = COpenType(); + if (op.types->Size() >= 1) { - if (Arcs.Size() >= formatIndices.Size()) - break; - formatIndex = formatIndices[formatIndices.Size() - Arcs.Size() - 1]; + COpenType latest; + if (Arcs.Size() < op.types->Size()) + latest = (*op.types)[op.types->Size() - Arcs.Size() - 1]; + else + { + latest = (*op.types)[0]; + if (!latest.Recursive) + break; + } + op.openType = latest; + } + else if (Arcs.Size() >= 32) + break; + + /* + op.formatIndex = -1; + if (op.types->Size() >= 1) + { + int latest; + if (Arcs.Size() < op.types->Size()) + latest = (*op.types)[op.types->Size() - Arcs.Size() - 1]; + else + { + latest = (*op.types)[0]; + if (latest != -2 && latest != -3) + break; + } + if (latest >= 0) + op.formatIndex = latest; + else if (latest == -1 || latest == -2) + { + // default + } + else if (latest == -3) + op.formatIndex = -2; + else + op.formatIndex = latest + 2; } else if (Arcs.Size() >= 32) break; + */ if (Arcs.IsEmpty()) { CArc arc; - arc.Path = filePath; + arc.filePath = op.filePath; + arc.Path = op.filePath; arc.SubfileIndex = (UInt32)(Int32)-1; - RINOK(arc.OpenStreamOrFile(codecs, formatIndex, stdInMode, stream, callback)); + HRESULT result = arc.OpenStreamOrFile(op); + if (result != S_OK) + { + if (result == S_FALSE) + { + NonOpen_ErrorInfo = arc.NonOpen_ErrorInfo; + // NonOpenErrorFormatIndex = arc.ErrorFormatIndex; + NonOpen_ArcPath = arc.Path; + } + return result; + } Arcs.Add(arc); continue; } + // PrintNumber("op.formatIndex 11", op.formatIndex); + const CArc &arc = Arcs.Back(); - resSpec = (formatIndices.Size() == 0 ? S_OK : E_NOTIMPL); + if (op.types->Size() > Arcs.Size()) + resSpec = E_NOTIMPL; UInt32 mainSubfile; { @@ -461,23 +2898,50 @@ HRESULT CArchiveLink::Open( CArc arc2; RINOK(arc.GetItemPath(mainSubfile, arc2.Path)); - + + bool zerosTailIsAllowed; + RINOK(Archive_GetItemBoolProp(arc.Archive, mainSubfile, kpidZerosTailIsAllowed, zerosTailIsAllowed)); + CMyComPtr setSubArchiveName; - callback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName); + op.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); + + // CIntVector incl; + CIntVector excl; + + COpenOptions op2; + #ifndef _SFX + op2.props = op.props; + #endif + op2.codecs = op.codecs; + // op2.types = &incl; + op2.openType = op.openType; + op2.openType.ZerosTailIsAllowed = zerosTailIsAllowed; + op2.excludedFormats = ! + op2.stdInMode = false; + op2.stream = subStream; + op2.filePath = arc2.Path; + op2.callback = op.callback; + op2.callbackSpec = op.callbackSpec; + + + HRESULT result = arc2.OpenStream(op2); + resSpec = (op.types->Size() == 0 ? S_OK : S_FALSE); if (result == S_FALSE) + { + NonOpen_ErrorInfo = arc2.ErrorInfo; + NonOpen_ArcPath = arc2.Path; break; + } RINOK(result); RINOK(arc.GetItemMTime(mainSubfile, arc2.MTime, arc2.MTimeDefined)); Arcs.Add(arc2); } IsOpen = !Arcs.IsEmpty(); - return S_OK; + return resSpec; } static void SetCallback(const FString &filePath, @@ -491,15 +2955,11 @@ static void SetCallback(const FString &filePath, openCallbackSpec->ReOpenCallback = reOpenCallback; FString dirPrefix, fileName; - NFile::NDirectory::GetFullPathAndSplit(filePath, dirPrefix, fileName); + NFile::NDir::GetFullPathAndSplit(filePath, dirPrefix, fileName); openCallbackSpec->Init(dirPrefix, fileName); } -HRESULT CArchiveLink::Open2(CCodecs *codecs, - const CIntVector &formatIndices, - bool stdInMode, - IInStream *stream, - const UString &filePath, +HRESULT CArchiveLink::Open2(COpenOptions &op, IOpenCallbackUI *callbackUI) { VolumesSize = 0; @@ -508,41 +2968,237 @@ HRESULT CArchiveLink::Open2(CCodecs *codecs, openCallbackSpec->Callback = callbackUI; FString prefix, name; - if (!stream && !stdInMode) + if (!op.stream && !op.stdInMode) { - NFile::NDirectory::GetFullPathAndSplit(us2fs(filePath), prefix, name); + NFile::NDir::GetFullPathAndSplit(us2fs(op.filePath), prefix, name); openCallbackSpec->Init(prefix, name); } else { - openCallbackSpec->SetSubArchiveName(filePath); + openCallbackSpec->SetSubArchiveName(op.filePath); } - RINOK(Open(codecs, formatIndices, stdInMode, stream, filePath, callback)); - VolumePaths.Add(fs2us(prefix + name)); - for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++) - VolumePaths.Add(fs2us(prefix) + openCallbackSpec->FileNames[i]); - VolumesSize = openCallbackSpec->TotalSize; + op.callback = callback; + op.callbackSpec = openCallbackSpec; + RINOK(Open(op)); + // VolumePaths.Add(fs2us(prefix + name)); + + FOR_VECTOR (i, openCallbackSpec->FileNames_WasUsed) + { + if (openCallbackSpec->FileNames_WasUsed[i]) + { + VolumePaths.Add(fs2us(prefix) + openCallbackSpec->FileNames[i]); + VolumesSize += openCallbackSpec->FileSizes[i]; + } + } + // VolumesSize = openCallbackSpec->TotalSize; return S_OK; } -HRESULT CArchiveLink::ReOpen(CCodecs *codecs, const UString &filePath, - IArchiveOpenCallback *callback) +HRESULT CArc::ReOpen(const COpenOptions &op) +{ + ErrorInfo.ClearErrors(); + ErrorInfo.ErrorFormatIndex = -1; + + UInt64 fileSize = 0; + if (op.stream) + { + RINOK(op.stream->Seek(0, STREAM_SEEK_END, &fileSize)); + RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL)); + } + FileSize = fileSize; + + CMyComPtr stream2; + Int64 globalOffset = GetGlobalOffset(); + if (globalOffset <= 0) + stream2 = op.stream; + else + { + CTailInStream *tailStreamSpec = new CTailInStream; + stream2 = tailStreamSpec; + tailStreamSpec->Stream = op.stream; + tailStreamSpec->Offset = globalOffset; + tailStreamSpec->Init(); + RINOK(tailStreamSpec->SeekToStart()); + } + + // There are archives with embedded STUBs (like ZIP), so we must support signature scanning + // But for another archives we can use 0 here. So the code can be fixed !!! + UInt64 maxStartPosition = kMaxCheckStartPosition; + HRESULT res = Archive->Open(stream2, &maxStartPosition, op.callback); + + if (res == S_OK) + { + RINOK(ReadBasicProps(Archive, globalOffset, res)); + ArcStreamOffset = globalOffset; + if (ArcStreamOffset != 0) + InStream = op.stream; + } + return res; +} + + +HRESULT CArchiveLink::ReOpen(COpenOptions &op) { if (Arcs.Size() > 1) return E_NOTIMPL; - if (Arcs.Size() == 0) - return Open2(codecs, CIntVector(), false, NULL, filePath, 0); + CObjectVector inc; + CIntVector excl; + + op.types = &inc; + op.excludedFormats = ! + op.stdInMode = false; + op.stream = NULL; + if (Arcs.Size() == 0) // ??? + return Open2(op, NULL); CMyComPtr openCallbackNew; - SetCallback(us2fs(filePath), NULL, callback, openCallbackNew); + SetCallback(us2fs(op.filePath), NULL, op.callback, openCallbackNew); CInFileStream *fileStreamSpec = new CInFileStream; CMyComPtr stream(fileStreamSpec); - if (!fileStreamSpec->Open(us2fs(filePath))) + if (!fileStreamSpec->Open(us2fs(op.filePath))) return GetLastError(); - HRESULT res = GetArchive()->Open(stream, &kMaxCheckStartPosition, callback); + op.stream = stream; + + CArc &arc = Arcs[0]; + HRESULT res = arc.ReOpen(op); IsOpen = (res == S_OK); return res; } + +#ifndef _SFX + +bool ParseComplexSize(const wchar_t *s, UInt64 &result) +{ + result = 0; + const wchar_t *end; + UInt64 number = ConvertStringToUInt64(s, &end); + if (end == s) + return false; + if (*end == 0) + { + result = number; + return true; + } + if (end[1] != 0) + return false; + unsigned numBits; + switch (MyCharLower_Ascii(*end)) + { + case 'b': result = number; return true; + case 'k': numBits = 10; break; + case 'm': numBits = 20; break; + case 'g': numBits = 30; break; + case 't': numBits = 40; break; + default: return false; + } + if (number >= ((UInt64)1 << (64 - numBits))) + return false; + result = number << numBits; + return true; +} + +static bool ParseTypeParams(const UString &s, COpenType &type) +{ + if (s[0] == 0) + return true; + if (s[1] == 0) + { + switch ((unsigned)(Byte)s[0]) + { + case 'e': type.EachPos = true; return true; + case 'a': type.CanReturnArc = true; return true; + case 'r': type.Recursive = true; return true; + } + return false; + } + if (s[0] == 's') + { + UInt64 result; + if (!ParseComplexSize(s.Ptr(1), result)) + return false; + type.MaxStartOffset = result; + type.MaxStartOffset_Defined = true; + return true; + } + + return false; +} + +bool ParseType(CCodecs &codecs, const UString &s, COpenType &type) +{ + int pos2 = s.Find(':'); + UString name; + if (pos2 < 0) + { + name = s; + pos2 = s.Len(); + } + else + { + name = s.Left(pos2); + pos2++; + } + + int index = codecs.FindFormatForArchiveType(name); + type.Recursive = false; + + if (index < 0) + { + if (name[0] == '*') + { + if (name[1] != 0) + return false; + } + else if (name[0] == '#') + { + if (name[1] != 0) + return false; + type.CanReturnArc = false; + type.CanReturnParser = true; + } + else + return false; + } + + type.FormatIndex = index; + + for (unsigned i = pos2; i < s.Len();) + { + int next = s.Find(':', i); + if (next < 0) + next = s.Len(); + UString name = s.Mid(i, next - i); + if (name.IsEmpty()) + return false; + if (!ParseTypeParams(name, type)) + return false; + i = next + 1; + } + + return true; +} + +bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector &types) +{ + types.Clear(); + for (unsigned pos = 0; pos < s.Len();) + { + int pos2 = s.Find('.', pos); + if (pos2 < 0) + pos2 = s.Len(); + UString name = s.Mid(pos, pos2 - pos); + if (name.IsEmpty()) + return false; + COpenType type; + if (!ParseType(codecs, name, type)) + return false; + types.Add(type); + pos = pos2 + 1; + } + return true; +} + +#endif diff --git a/CPP/7zip/UI/Common/OpenArchive.h b/CPP/7zip/UI/Common/OpenArchive.h old mode 100755 new mode 100644 index 25f739e3..aab6669d --- a/CPP/7zip/UI/Common/OpenArchive.h +++ b/CPP/7zip/UI/Common/OpenArchive.h @@ -3,50 +3,309 @@ #ifndef __OPEN_ARCHIVE_H #define __OPEN_ARCHIVE_H -#include "Common/MyString.h" - -#include "Windows/FileFind.h" - -#include "../../Archive/IArchive.h" +#include "../../../Windows/PropVariant.h" #include "ArchiveOpenCallback.h" #include "LoadCodecs.h" +#include "Property.h" + +HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw(); +HRESULT Archive_IsItem_Folder(IInArchive *arc, UInt32 index, bool &result) throw(); +HRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw(); +HRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw(); +HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &deleted) throw(); + +/* +struct COptionalOpenProperties +{ + UString FormatName; + CObjectVector Props; +}; +*/ + +#ifdef _SFX +#define OPEN_PROPS_DECL +#else +#define OPEN_PROPS_DECL const CObjectVector *props; +// #define OPEN_PROPS_DECL , const CObjectVector *props +#endif + +struct COpenSpecFlags +{ + // bool CanReturnFull; + bool CanReturnFrontal; + bool CanReturnTail; + bool CanReturnMid; + + bool CanReturn_NonStart() const { return CanReturnTail || CanReturnMid; } + + COpenSpecFlags(): + // CanReturnFull(true), + CanReturnFrontal(false), + CanReturnTail(false), + CanReturnMid(false) + {} +}; + +struct COpenType +{ + int FormatIndex; + + COpenSpecFlags SpecForcedType; + COpenSpecFlags SpecMainType; + COpenSpecFlags SpecWrongExt; + COpenSpecFlags SpecUnknownExt; + + bool Recursive; + + bool CanReturnArc; + bool CanReturnParser; + bool EachPos; + + // bool SkipSfxStub; + // bool ExeAsUnknown; + + bool ZerosTailIsAllowed; + + bool MaxStartOffset_Defined; + UInt64 MaxStartOffset; + + const COpenSpecFlags &GetSpec(bool isForced, bool isMain, bool isUnknown) const + { + return isForced ? SpecForcedType : (isMain ? SpecMainType : (isUnknown ? SpecUnknownExt : SpecWrongExt)); + } + + COpenType(): + FormatIndex(-1), + Recursive(true), + EachPos(false), + CanReturnArc(true), + CanReturnParser(false), + // SkipSfxStub(true), + // ExeAsUnknown(true), + ZerosTailIsAllowed(false), + MaxStartOffset_Defined(false), + MaxStartOffset(0) + { + SpecForcedType.CanReturnFrontal = true; + SpecForcedType.CanReturnTail = true; + SpecForcedType.CanReturnMid = true; + + SpecMainType.CanReturnFrontal = true; + + SpecUnknownExt.CanReturnTail = true; // for sfx + SpecUnknownExt.CanReturnMid = true; + SpecUnknownExt.CanReturnFrontal = true; // for alt streams of sfx with pad + + // ZerosTailIsAllowed = true; + } +}; + +struct COpenOptions +{ + CCodecs *codecs; + COpenType openType; + const CObjectVector *types; + const CIntVector *excludedFormats; + + IInStream *stream; + ISequentialInStream *seqStream; + IArchiveOpenCallback *callback; + COpenCallbackImp *callbackSpec; + OPEN_PROPS_DECL + // bool openOnlySpecifiedByExtension, + + bool stdInMode; + UString filePath; + + COpenOptions(): + codecs(NULL), + types(NULL), + excludedFormats(NULL), + stream(NULL), + seqStream(NULL), + callback(NULL), + callbackSpec(NULL), + stdInMode(false) + {} + +}; + +UInt32 GetOpenArcErrorFlags(const NWindows::NCOM::CPropVariant &prop, bool *isDefinedProp = NULL); + +struct CArcErrorInfo +{ + bool ThereIsTail; + bool UnexpecedEnd; + bool IgnoreTail; // all are zeros + // bool NonZerosTail; + bool ErrorFlags_Defined; + UInt32 ErrorFlags; + UInt32 WarningFlags; + int ErrorFormatIndex; // - 1 means no Error. + // if FormatIndex == ErrorFormatIndex, the archive is open with offset + UInt64 TailSize; + + /* if CArc is Open OK with some format: + - ErrorFormatIndex shows error format index, if extension is incorrect + - other variables show message and warnings of archive that is open */ + + UString ErrorMessage; + UString WarningMessage; + + // call IsArc_After_NonOpen only if Open returns S_FALSE + bool IsArc_After_NonOpen() const + { + return (ErrorFlags_Defined && (ErrorFlags & kpv_ErrorFlags_IsNotArc) == 0); + } + + + CArcErrorInfo(): + ThereIsTail(false), + UnexpecedEnd(false), + IgnoreTail(false), + // NonZerosTail(false), + ErrorFlags_Defined(false), + ErrorFlags(0), + WarningFlags(0), + ErrorFormatIndex(-1), + TailSize(0) + {} + + void ClearErrors(); + + void ClearErrors_Full() + { + ErrorFormatIndex = -1; + ClearErrors(); + } + + bool IsThereErrorOrWarning() const + { + return ErrorFlags != 0 + || WarningFlags != 0 + || NeedTailWarning() + || UnexpecedEnd + || !ErrorMessage.IsEmpty() + || !WarningMessage.IsEmpty(); + } + + bool AreThereErrors() const { return ErrorFlags != 0 || UnexpecedEnd; } + bool AreThereWarnings() const { return WarningFlags != 0 || NeedTailWarning(); } -HRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result); -HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result); + bool NeedTailWarning() const { return !IgnoreTail && ThereIsTail; } -struct CArc + UInt32 GetWarningFlags() const + { + UInt32 a = WarningFlags; + if (NeedTailWarning() && (ErrorFlags & kpv_ErrorFlags_DataAfterEnd) == 0) + a |= kpv_ErrorFlags_DataAfterEnd; + return a; + } + + UInt32 GetErrorFlags() const + { + UInt32 a = ErrorFlags; + if (UnexpecedEnd) + a |= kpv_ErrorFlags_UnexpectedEnd; + return a; + } +}; + +class CArc { + HRESULT PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr &archive); + HRESULT CheckZerosTail(const COpenOptions &op, UInt64 offset); + HRESULT OpenStream2(const COpenOptions &options); + +public: CMyComPtr Archive; + CMyComPtr InStream; + // we use InStream in 2 cases (ArcStreamOffset != 0): + // 1) if we use additional cache stream + // 2) we reopen sfx archive with CTailInStream + + CMyComPtr GetRawProps; + CMyComPtr GetRootProps; + + CArcErrorInfo ErrorInfo; // for OK archives + CArcErrorInfo NonOpen_ErrorInfo; // ErrorInfo for mainArchive (false OPEN) + UString Path; + UString filePath; UString DefaultName; - int FormatIndex; + int FormatIndex; // - 1 means Parser. int SubfileIndex; FILETIME MTime; bool MTimeDefined; - UString ErrorMessage; + + Int64 Offset; // it's offset of start of archive inside stream that is open by Archive Handler + UInt64 PhySize; + // UInt64 OkPhySize; + bool PhySizeDefined; + // bool OkPhySize_Defined; + UInt64 FileSize; + UInt64 AvailPhySize; // PhySize, but it's reduced if exceed end of file + // bool offsetDefined; + + UInt64 ArcStreamOffset; // offset of stream that is open by Archive Handler + Int64 GetGlobalOffset() const { return ArcStreamOffset + Offset; } // it's global offset of archive - CArc(): MTimeDefined(false) {} + // AString ErrorFlagsText; + + bool IsParseArc; + + bool IsTree; + + bool Ask_Deleted; + bool Ask_AltStream; + bool Ask_Aux; + bool Ask_INode; + + bool IgnoreSplit; // don't try split handler + + // void Set_ErrorFlagsText(); + + CArc(): + MTimeDefined(false), + IsTree(false), + Ask_Deleted(false), + Ask_AltStream(false), + Ask_Aux(false), + Ask_INode(false), + IgnoreSplit(false) + {} + + HRESULT ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes); + + // ~CArc(); + + HRESULT Close() + { + InStream.Release(); + return Archive->Close(); + } + + // AltStream's name is concatenated with base file name in one string in parts.Back() + HRESULT GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const; HRESULT GetItemPath(UInt32 index, UString &result) const; + + // GetItemPath2 adds [DELETED] dir prefix for deleted items. + HRESULT GetItemPath2(UInt32 index, UString &result) const; + HRESULT GetItemSize(UInt32 index, UInt64 &size, bool &defined) const; HRESULT GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const; HRESULT IsItemAnti(UInt32 index, bool &result) const - { return 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); + { return Archive_GetItemBoolProp(Archive, index, kpidIsAnti, result); } + + + HRESULT OpenStream(const COpenOptions &options); + HRESULT OpenStreamOrFile(COpenOptions &options); + + HRESULT ReOpen(const COpenOptions &options); + + HRESULT CreateNewTailStream(CMyComPtr &stream); }; struct CArchiveLink @@ -56,33 +315,32 @@ struct CArchiveLink UInt64 VolumesSize; bool IsOpen; + // int NonOpenErrorFormatIndex; // - 1 means no Error. + UString NonOpen_ArcPath; + + CArcErrorInfo NonOpen_ErrorInfo; + + // UString ErrorsText; + // void Set_ErrorsText(); + CArchiveLink(): VolumesSize(0), IsOpen(false) {} + void KeepModeForNextOpen(); HRESULT Close(); void Release(); ~CArchiveLink() { Release(); } + const CArc *GetArc() const { return &Arcs.Back(); } IInArchive *GetArchive() const { return Arcs.Back().Archive; } + IArchiveGetRawProps *GetArchiveGetRawProps() const { return Arcs.Back().GetRawProps; } + IArchiveGetRootProps *GetArchiveGetRootProps() const { return Arcs.Back().GetRootProps; } + + HRESULT Open(COpenOptions &options); - HRESULT 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); + HRESULT Open2(COpenOptions &options, IOpenCallbackUI *callbackUI); + + HRESULT ReOpen(COpenOptions &options); }; +bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector &types); + #endif diff --git a/CPP/7zip/UI/Common/PropIDUtils.cpp b/CPP/7zip/UI/Common/PropIDUtils.cpp old mode 100755 new mode 100644 index dacaca5f..6e91efd8 --- a/CPP/7zip/UI/Common/PropIDUtils.cpp +++ b/CPP/7zip/UI/Common/PropIDUtils.cpp @@ -2,33 +2,29 @@ #include "StdAfx.h" -#include "Common/IntToString.h" +#include "../../../../C/CpuArch.h" -#include "Windows/FileFind.h" -#include "Windows/PropVariantConversions.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/FileFind.h" +#include "../../../Windows/FileIO.h" +#include "../../../Windows/PropVariantConv.h" #include "../../PropID.h" #include "PropIDUtils.h" -using namespace NWindows; +#define Get16(x) GetUi16(x) +#define Get32(x) GetUi32(x) -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'; -} +using namespace NWindows; -static const char g_WinAttrib[17] = "RHS8DAdNTsrCOnE_"; +static const char g_WinAttribChars[16 + 1] = "RHS8DAdNTsLCOnE_"; /* 0 READONLY 1 HIDDEN -3 SYSTEM +2 SYSTEM 4 DIRECTORY 5 ARCHIVE @@ -45,46 +41,45 @@ static const char g_WinAttrib[17] = "RHS8DAdNTsrCOnE_"; 16 VIRTUAL */ +void ConvertWinAttribToString(char *s, UInt32 wa) +{ + for (int i = 0; i < 16; i++) + if ((wa & (1 << i)) && i != 7) + *s++ = g_WinAttribChars[i]; + *s = 0; +} + static const char kPosixTypes[16] = { '0', 'p', 'c', '3', 'd', '5', 'b', '7', '-', '9', 'l', 'B', 's', 'D', 'E', 'F' }; -#define MY_ATTR_CHAR(a, n, c) ((a )& (1 << (n))) ? c : L'-'; +#define MY_ATTR_CHAR(a, n, c) ((a) & (1 << (n))) ? c : '-'; -UString ConvertPropertyToString(const PROPVARIANT &prop, PROPID propID, bool full) +void ConvertPropertyToShortString(char *dest, const PROPVARIANT &prop, PROPID propID, bool full) { - switch(propID) + *dest = 0; + if (prop.vt == VT_FILETIME) + { + FILETIME localFileTime; + if ((prop.filetime.dwHighDateTime == 0 && + prop.filetime.dwLowDateTime == 0) || + !::FileTimeToLocalFileTime(&prop.filetime, &localFileTime)) + return; + ConvertFileTimeToString(localFileTime, dest, true, full); + return; + } + 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; + ConvertUInt32ToHex8Digits(prop.ulVal, dest); + return; } 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; + ConvertWinAttribToString(dest, prop.ulVal); + return; } case kpidPosixAttrib: { @@ -92,29 +87,467 @@ UString ConvertPropertyToString(const PROPVARIANT &prop, PROPID propID, bool ful break; UString res; UInt32 a = prop.ulVal; - wchar_t temp[16]; - temp[0] = kPosixTypes[(a >> 12) & 0xF]; + dest[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'); + dest[7 - i] = MY_ATTR_CHAR(a, i + 2, 'r'); + dest[8 - i] = MY_ATTR_CHAR(a, i + 1, 'w'); + dest[9 - i] = MY_ATTR_CHAR(a, i + 0, 'x'); } - if ((a & 0x800) != 0) 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; + if ((a & 0x800) != 0) dest[3] = ((a & (1 << 6)) ? 's' : 'S'); + if ((a & 0x400) != 0) dest[6] = ((a & (1 << 3)) ? 's' : 'S'); + if ((a & 0x200) != 0) dest[9] = ((a & (1 << 0)) ? 't' : 'T'); + dest[10] = 0; a &= ~(UInt32)0xFFFF; if (a != 0) { - ConvertUInt32ToHex(a, temp); - res = UString(temp) + L' ' + res; + dest[10] = ' '; + ConvertUInt32ToHex8Digits(a, dest + 11); } - return res; + return; } + case kpidINode: + { + if (prop.vt != VT_UI8) + break; + ConvertUInt32ToString((UInt32)(prop.uhVal.QuadPart >> 48), dest); + dest += strlen(dest); + *dest++ = '-'; + UInt64 low = prop.uhVal.QuadPart & (((UInt64)1 << 48) - 1); + ConvertUInt64ToString(low, dest); + return; + } + case kpidVa: + { + UInt64 v = 0; + if (ConvertPropVariantToUInt64(prop, v)) + { + dest[0] = '0'; + dest[1] = 'x'; + ConvertUInt64ToHex(prop.ulVal, dest + 2); + return; + } + break; + } + } + ConvertPropVariantToShortString(prop, dest); +} + +void ConvertPropertyToString(UString &dest, const PROPVARIANT &prop, PROPID propID, bool full) +{ + if (prop.vt == VT_BSTR) + { + dest = prop.bstrVal; + return; } - return ConvertPropVariantToString(prop); + char temp[64]; + ConvertPropertyToShortString(temp, prop, propID, full); + int len = MyStringLen(temp); + wchar_t *str = dest.GetBuffer(len); + for (int i = 0; i < len; i++) + str[i] = temp[i]; + dest.ReleaseBuffer(len); +} + +static inline char GetHex(Byte value) +{ + return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); +} + +#ifndef _SFX + +static inline void AddHexToString(AString &res, Byte value) +{ + res += GetHex((Byte)(value >> 4)); + res += GetHex((Byte)(value & 0xF)); + res += ' '; +} + +/* +static AString Data_To_Hex(const Byte *data, size_t size) +{ + AString s; + for (size_t i = 0; i < size; i++) + AddHexToString(s, data[i]); + return s; } +*/ + +static const char *sidNames[] = +{ + "0", + "Dialup", + "Network", + "Batch", + "Interactive", + "Logon", // S-1-5-5-X-Y + "Service", + "Anonymous", + "Proxy", + "EnterpriseDC", + "Self", + "AuthenticatedUsers", + "RestrictedCode", + "TerminalServer", + "RemoteInteractiveLogon", + "ThisOrganization", + "16", + "IUserIIS", + "LocalSystem", + "LocalService", + "NetworkService", + "Domains" +}; + +struct CSecID2Name +{ + UInt32 n; + char *sz; +}; + +const CSecID2Name sid_32_Names[] = +{ + { 544, "Administrators" }, + { 545, "Users" }, + { 546, "Guests" }, + { 547, "PowerUsers" }, + { 548, "AccountOperators" }, + { 549, "ServerOperators" }, + { 550, "PrintOperators" }, + { 551, "BackupOperators" }, + { 552, "Replicators" }, + { 553, "Backup Operators" }, + { 554, "PreWindows2000CompatibleAccess" }, + { 555, "RemoteDesktopUsers" }, + { 556, "NetworkConfigurationOperators" }, + { 557, "IncomingForestTrustBuilders" }, + { 558, "PerformanceMonitorUsers" }, + { 559, "PerformanceLogUsers" }, + { 560, "WindowsAuthorizationAccessGroup" }, + { 561, "TerminalServerLicenseServers" }, + { 562, "DistributedCOMUsers" }, + { 569, "CryptographicOperators" }, + { 573, "EventLogReaders" }, + { 574, "CertificateServiceDCOMAccess" } +}; + +static const CSecID2Name sid_21_Names[] = +{ + { 500, "Administrator" }, + { 501, "Guest" }, + { 502, "KRBTGT" }, + { 512, "DomainAdmins" }, + { 513, "DomainUsers" }, + { 515, "DomainComputers" }, + { 516, "DomainControllers" }, + { 517, "CertPublishers" }, + { 518, "SchemaAdmins" }, + { 519, "EnterpriseAdmins" }, + { 520, "GroupPolicyCreatorOwners" }, + { 553, "RASandIASServers" }, + { 553, "RASandIASServers" }, + { 571, "AllowedRODCPasswordReplicationGroup" }, + { 572, "DeniedRODCPasswordReplicationGroup" } +}; + +struct CServicesToName +{ + UInt32 n[5]; + char *sz; +}; + +static const CServicesToName services_to_name[] = +{ + { { 956008885, 3418522649, 1831038044, 1853292631, 2271478464 } , "TrustedInstaller" } +}; + +static void ParseSid(AString &s, const Byte *p, UInt32 lim, UInt32 &sidSize) +{ + sidSize = 0; + if (lim < 8) + { + s += "ERROR"; + return; + } + UInt32 rev = p[0]; + if (rev != 1) + { + s += "UNSUPPORTED"; + return; + } + UInt32 num = p[1]; + if (8 + num * 4 > lim) + { + s += "ERROR"; + return; + } + sidSize = 8 + num * 4; + UInt32 authority = GetBe32(p + 4); + + if (p[2] == 0 && p[3] == 0 && authority == 5 && num >= 1) + { + UInt32 v0 = Get32(p + 8); + if (v0 < ARRAY_SIZE(sidNames)) + { + s += sidNames[v0]; + return; + } + if (v0 == 32 && num == 2) + { + UInt32 v1 = Get32(p + 12); + for (int i = 0; i < ARRAY_SIZE(sid_32_Names); i++) + if (sid_32_Names[i].n == v1) + { + s += sid_32_Names[i].sz; + return; + } + } + if (v0 == 21 && num == 5) + { + UInt32 v4 = Get32(p + 8 + 4 * 4); + for (int i = 0; i < ARRAY_SIZE(sid_21_Names); i++) + if (sid_21_Names[i].n == v4) + { + s += sid_21_Names[i].sz; + return; + } + } + if (v0 == 80 && num == 6) + { + for (int i = 0; i < ARRAY_SIZE(services_to_name); i++) + { + const CServicesToName &sn = services_to_name[i]; + int j; + for (j = 0; j < 5 && sn.n[j] == Get32(p + 8 + 4 + j * 4); j++); + if (j == 5) + { + s += sn.sz; + return; + } + } + } + } + + char sz[16]; + s += "S-1-"; + if (p[2] == 0 && p[3] == 0) + { + ConvertUInt32ToString(authority, sz); + s += sz; + } + else + { + s += "0x"; + for (int i = 2; i < 8; i++) + AddHexToString(s, p[i]); + } + for (UInt32 i = 0; i < num; i++) + { + s += '-'; + ConvertUInt32ToString(Get32(p + 8 + i * 4), sz); + s += sz; + } +} + +static void ParseOwner(AString &s, const Byte *p, UInt32 size, UInt32 pos) +{ + if (pos > size) + { + s += "ERROR"; + return; + } + UInt32 sidSize = 0; + ParseSid(s, p + pos, size - pos, sidSize); +} + +static void AddUInt32ToString(AString &s, UInt32 val) +{ + char sz[16]; + ConvertUInt32ToString(val, sz); + s += sz; +} + +static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName, UInt32 flags, UInt32 offset) +{ + UInt32 control = Get16(p + 2); + if ((flags & control) == 0) + return; + UInt32 pos = Get32(p + offset); + s += ' '; + s += strName; + if (pos >= size) + return; + p += pos; + size -= pos; + if (size < 8) + return; + if (Get16(p) != 2) // revision + return; + // UInt32 aclSize = Get16(p + 2); + UInt32 num = Get32(p + 4); + AddUInt32ToString(s, num); + /* + if (num >= (1 << 16)) + return; + if (aclSize > size) + return; + size = aclSize; + size -= 8; + p += 8; + for (UInt32 i = 0 ; i < num; i++) + { + if (size <= 8) + return; + // Byte type = p[0]; + // Byte flags = p[1]; + // UInt32 aceSize = Get16(p + 2); + // UInt32 mask = Get32(p + 4); + p += 8; + size -= 8; + + UInt32 sidSize = 0; + s += ' '; + s += ParseSid(p, size, sidSize); + if (sidSize == 0) + return; + p += sidSize; + size -= sidSize; + } + if (size != 0) + s += " ERROR"; + */ +} + +#define MY_SE_OWNER_DEFAULTED (0x0001) +#define MY_SE_GROUP_DEFAULTED (0x0002) +#define MY_SE_DACL_PRESENT (0x0004) +#define MY_SE_DACL_DEFAULTED (0x0008) +#define MY_SE_SACL_PRESENT (0x0010) +#define MY_SE_SACL_DEFAULTED (0x0020) +#define MY_SE_DACL_AUTO_INHERIT_REQ (0x0100) +#define MY_SE_SACL_AUTO_INHERIT_REQ (0x0200) +#define MY_SE_DACL_AUTO_INHERITED (0x0400) +#define MY_SE_SACL_AUTO_INHERITED (0x0800) +#define MY_SE_DACL_PROTECTED (0x1000) +#define MY_SE_SACL_PROTECTED (0x2000) +#define MY_SE_RM_CONTROL_VALID (0x4000) +#define MY_SE_SELF_RELATIVE (0x8000) + +void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s) +{ + s.Empty(); + if (size < 20 || size > (1 << 18)) + { + s += "ERROR"; + return; + } + if (Get16(data) != 1) // revision + { + s += "UNSUPPORTED"; + return; + } + ParseOwner(s, data, size, Get32(data + 4)); + s += ' '; + ParseOwner(s, data, size, Get32(data + 8)); + ParseAcl(s, data, size, "s:", MY_SE_SACL_PRESENT, 12); + ParseAcl(s, data, size, "d:", MY_SE_DACL_PRESENT, 16); + s += ' '; + AddUInt32ToString(s, size); + // s += '\n'; + // s += Data_To_Hex(data, size); +} + +#ifdef _WIN32 + +static bool CheckSid(const Byte *data, UInt32 size, UInt32 pos) +{ + if (pos >= size) + return false; + size -= pos; + if (size < 8) + return false; + UInt32 rev = data[pos]; + if (rev != 1) + return false; + UInt32 num = data[pos + 1]; + return (8 + num * 4 <= size); +} + +static bool CheckAcl(const Byte *p, UInt32 size, UInt32 flags, UInt32 offset) +{ + UInt32 control = Get16(p + 2); + if ((flags & control) == 0) + return true; + UInt32 pos = Get32(p + offset); + if (pos >= size) + return false; + p += pos; + size -= pos; + if (size < 8) + return false; + UInt32 aclSize = Get16(p + 2); + return (aclSize <= size); +} + +bool CheckNtSecure(const Byte *data, UInt32 size) +{ + if (size < 20) + return false; + if (Get16(data) != 1) // revision + return true; // windows function can handle such error, so we allow it + if (size > (1 << 18)) + return false; + if (!CheckSid(data, size, Get32(data + 4))) return false; + if (!CheckSid(data, size, Get32(data + 8))) return false; + if (!CheckAcl(data, size, MY_SE_SACL_PRESENT, 12)) return false; + if (!CheckAcl(data, size, MY_SE_DACL_PRESENT, 16)) return false; + return true; +} + +#endif + +bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s) +{ + s.Empty(); + NFile::CReparseAttr attr; + if (attr.Parse(data, size)) + { + if (!attr.IsSymLink()) + s += L"Junction: "; + s += attr.GetPath(); + if (!attr.IsOkNamePair()) + { + s += L" : "; + s += attr.PrintName; + } + return true; + } + + if (size < 8) + return false; + UInt32 tag = Get32(data); + UInt32 len = Get16(data + 4); + if (len + 8 > size) + return false; + if (Get16(data + 6) != 0) // padding + return false; + + char hex[16]; + ConvertUInt32ToHex8Digits(tag, hex); + s.AddAsciiStr(hex); + s += L' '; + + data += 8; + + for (UInt32 i = 0; i < len; i++) + { + Byte b = ((const Byte *)data)[i]; + s += (wchar_t)GetHex((Byte)((b >> 4) & 0xF)); + s += (wchar_t)GetHex((Byte)(b & 0xF)); + } + return true; +} + +#endif diff --git a/CPP/7zip/UI/Common/PropIDUtils.h b/CPP/7zip/UI/Common/PropIDUtils.h old mode 100755 new mode 100644 index ca14d091..3ee2981d --- a/CPP/7zip/UI/Common/PropIDUtils.h +++ b/CPP/7zip/UI/Common/PropIDUtils.h @@ -3,10 +3,15 @@ #ifndef __PROPID_UTILS_H #define __PROPID_UTILS_H -#include "Common/MyString.h" -#include "Common/Types.h" +#include "../../../Common/MyString.h" -void ConvertUInt32ToHex(UInt32 value, wchar_t *s); -UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full = true); +// provide at least 64 bytes for buffer including zero-end +void ConvertPropertyToShortString(char *dest, const PROPVARIANT &propVariant, PROPID propID, bool full = true) throw(); +void ConvertPropertyToString(UString &dest, const PROPVARIANT &propVariant, PROPID propID, bool full = true); + +bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s); +void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s); +bool CheckNtSecure(const Byte *data, UInt32 size); +void ConvertWinAttribToString(char *s, UInt32 wa); #endif diff --git a/CPP/7zip/UI/Common/Property.h b/CPP/7zip/UI/Common/Property.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/Common/SetProperties.cpp b/CPP/7zip/UI/Common/SetProperties.cpp old mode 100755 new mode 100644 index ac9b59a3..c3de5d5a --- a/CPP/7zip/UI/Common/SetProperties.cpp +++ b/CPP/7zip/UI/Common/SetProperties.cpp @@ -2,25 +2,26 @@ #include "StdAfx.h" -#include "SetProperties.h" +#include "../../../Common/MyCom.h" +#include "../../../Common/MyString.h" +#include "../../../Common/StringToInt.h" -#include "Windows/PropVariant.h" -#include "Common/MyString.h" -#include "Common/StringToInt.h" -#include "Common/MyCom.h" +#include "../../../Windows/PropVariant.h" #include "../../Archive/IArchive.h" +#include "SetProperties.h" + using namespace NWindows; using namespace NCOM; static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop) { - const wchar_t *endPtr; - UInt64 result = ConvertStringToUInt64(s, &endPtr); - if (endPtr - (const wchar_t *)s != s.Length()) + const wchar_t *end; + UInt64 result = ConvertStringToUInt64(s, &end); + if (*end != 0 || s.IsEmpty()) prop = s; - else if (result <= 0xFFFFFFFF) + else if (result <= (UInt32)0xFFFFFFFF) prop = (UInt32)result; else prop = result; @@ -39,8 +40,8 @@ HRESULT SetProperties(IUnknown *unknown, const CObjectVector &propert CPropVariant *values = new CPropVariant[properties.Size()]; try { - int i; - for(i = 0; i < properties.Size(); i++) + unsigned i; + for (i = 0; i < properties.Size(); i++) { const CProperty &property = properties[i]; NCOM::CPropVariant propVariant; @@ -64,7 +65,7 @@ HRESULT SetProperties(IUnknown *unknown, const CObjectVector &propert values[i] = propVariant; } CRecordVector names; - for(i = 0; i < realNames.Size(); i++) + for (i = 0; i < realNames.Size(); i++) names.Add((const wchar_t *)realNames[i]); RINOK(setProperties->SetProperties(&names.Front(), values, names.Size())); diff --git a/CPP/7zip/UI/Common/SetProperties.h b/CPP/7zip/UI/Common/SetProperties.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/Common/SortUtils.cpp b/CPP/7zip/UI/Common/SortUtils.cpp old mode 100755 new mode 100644 index 061e7773..b7e422a2 --- a/CPP/7zip/UI/Common/SortUtils.cpp +++ b/CPP/7zip/UI/Common/SortUtils.cpp @@ -2,21 +2,22 @@ #include "StdAfx.h" +#include "../../../Common/Wildcard.h" + #include "SortUtils.h" -#include "Common/Wildcard.h" -static int CompareStrings(const int *p1, const int *p2, void *param) +static int CompareStrings(const unsigned *p1, const unsigned *p2, void *param) { const UStringVector &strings = *(const UStringVector *)param; return CompareFileNames(strings[*p1], strings[*p2]); } -void SortFileNames(const UStringVector &strings, CIntVector &indices) +void SortFileNames(const UStringVector &strings, CUIntVector &indices) { - indices.Clear(); - int numItems = strings.Size(); - indices.Reserve(numItems); - for(int i = 0; i < numItems; i++) - indices.Add(i); + unsigned numItems = strings.Size(); + indices.ClearAndSetSize(numItems); + unsigned *vals = &indices[0]; + for (unsigned i = 0; i < numItems; i++) + vals[i] = i; indices.Sort(CompareStrings, (void *)&strings); } diff --git a/CPP/7zip/UI/Common/SortUtils.h b/CPP/7zip/UI/Common/SortUtils.h old mode 100755 new mode 100644 index e1522461..8e42e068 --- a/CPP/7zip/UI/Common/SortUtils.h +++ b/CPP/7zip/UI/Common/SortUtils.h @@ -1,10 +1,10 @@ // SortUtils.h -#ifndef __SORTUTLS_H -#define __SORTUTLS_H +#ifndef __SORT_UTLS_H +#define __SORT_UTLS_H -#include "Common/MyString.h" +#include "../../../Common/MyString.h" -void SortFileNames(const UStringVector &strings, CIntVector &indices); +void SortFileNames(const UStringVector &strings, CUIntVector &indices); #endif diff --git a/CPP/7zip/UI/Common/StdAfx.h b/CPP/7zip/UI/Common/StdAfx.h old mode 100755 new mode 100644 index 9a8e7d21..2854ff3e --- a/CPP/7zip/UI/Common/StdAfx.h +++ b/CPP/7zip/UI/Common/StdAfx.h @@ -1,9 +1,8 @@ -// stdafx.h +// StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" -#include "../../../Common/NewHandler.h" +#include "../../../Common/Common.h" #endif diff --git a/CPP/7zip/UI/Common/TempFiles.cpp b/CPP/7zip/UI/Common/TempFiles.cpp old mode 100755 new mode 100644 index c799c7bf..0c13ae15 --- a/CPP/7zip/UI/Common/TempFiles.cpp +++ b/CPP/7zip/UI/Common/TempFiles.cpp @@ -2,9 +2,9 @@ #include "StdAfx.h" -#include "TempFiles.h" +#include "../../../Windows/FileDir.h" -#include "Windows/FileDir.h" +#include "TempFiles.h" using namespace NWindows; using namespace NFile; @@ -13,7 +13,7 @@ void CTempFiles::Clear() { while (!Paths.IsEmpty()) { - NDirectory::DeleteFileAlways(Paths.Back()); + NDir::DeleteFileAlways(Paths.Back()); Paths.DeleteBack(); } } diff --git a/CPP/7zip/UI/Common/TempFiles.h b/CPP/7zip/UI/Common/TempFiles.h old mode 100755 new mode 100644 index 5dcda5b6..4099e655 --- a/CPP/7zip/UI/Common/TempFiles.h +++ b/CPP/7zip/UI/Common/TempFiles.h @@ -3,7 +3,7 @@ #ifndef __TEMP_FILES_H #define __TEMP_FILES_H -#include "Common/MyString.h" +#include "../../../Common/MyString.h" class CTempFiles { diff --git a/CPP/7zip/UI/Common/Update.cpp b/CPP/7zip/UI/Common/Update.cpp old mode 100755 new mode 100644 index e740e8a7..2e095b06 --- a/CPP/7zip/UI/Common/Update.cpp +++ b/CPP/7zip/UI/Common/Update.cpp @@ -4,18 +4,19 @@ #include "Update.h" -#include "Common/IntToString.h" -#include "Common/StringConvert.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" -#include "Windows/DLL.h" -#include "Windows/FileDir.h" -#include "Windows/FileFind.h" -#include "Windows/FileName.h" -#include "Windows/PropVariant.h" -#include "Windows/PropVariantConversions.h" -#include "Windows/Time.h" +#include "../../../Windows/DLL.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/PropVariantConv.h" +#include "../../../Windows/TimeUtils.h" #include "../../Common/FileStreams.h" +#include "../../Common/LimitedStreams.h" #include "../../Compress/CopyCoder.h" @@ -35,22 +36,46 @@ static const char *kUpdateIsNotSupoorted = using namespace NWindows; using namespace NCOM; using namespace NFile; +using namespace NDir; using namespace NName; static CFSTR kTempFolderPrefix = FTEXT("7zE"); + +static bool DeleteEmptyFolderAndEmptySubFolders(const FString &path) +{ + NFind::CFileInfo fileInfo; + FString pathPrefix = path + FCHAR_PATH_SEPARATOR; + { + NFind::CEnumerator enumerator(pathPrefix + FCHAR_ANY_MASK); + while (enumerator.Next(fileInfo)) + { + if (fileInfo.IsDir()) + if (!DeleteEmptyFolderAndEmptySubFolders(pathPrefix + fileInfo.Name)) + return false; + } + } + /* + // we don't need clear read-only for folders + if (!MySetFileAttributes(path, 0)) + return false; + */ + return RemoveDir(path); +} + + using namespace NUpdateArchive; class COutMultiVolStream: public IOutStream, public CMyUnknownImp { - int _streamIndex; // required stream + unsigned _streamIndex; // required stream UInt64 _offsetPos; // offset from start of _streamIndex index UInt64 _absPos; UInt64 _length; - struct CSubStreamInfo + struct CAltStreamInfo { COutFileStream *StreamSpec; CMyComPtr Stream; @@ -58,7 +83,7 @@ class COutMultiVolStream: UInt64 Pos; UInt64 RealSize; }; - CObjectVector Streams; + CObjectVector Streams; public: // CMyComPtr VolumeCallback; CRecordVector Sizes; @@ -73,6 +98,7 @@ public: _length = 0; } + bool SetMTime(const FILETIME *mTime); HRESULT Close(); MY_UNKNOWN_IMP1(IOutStream) @@ -87,12 +113,12 @@ public: HRESULT COutMultiVolStream::Close() { HRESULT res = S_OK; - for (int i = 0; i < Streams.Size(); i++) + FOR_VECTOR (i, Streams) { - CSubStreamInfo &s = Streams[i]; - if (s.StreamSpec) + COutFileStream *s = Streams[i].StreamSpec; + if (s) { - HRESULT res2 = s.StreamSpec->Close(); + HRESULT res2 = s->Close(); if (res2 != S_OK) res = res2; } @@ -100,6 +126,19 @@ HRESULT COutMultiVolStream::Close() return res; } +bool COutMultiVolStream::SetMTime(const FILETIME *mTime) +{ + bool res = true; + FOR_VECTOR (i, Streams) + { + COutFileStream *s = Streams[i].StreamSpec; + if (s) + if (!s->SetMTime(mTime)) + res = false; + } + return res; +} + STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (processedSize != NULL) @@ -108,32 +147,32 @@ STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *pr { if (_streamIndex >= Streams.Size()) { - CSubStreamInfo subStream; + CAltStreamInfo altStream; FChar temp[16]; ConvertUInt32ToString(_streamIndex + 1, temp); FString res = temp; - while (res.Length() < 3) + while (res.Len() < 3) res = FString(FTEXT('0')) + res; FString name = Prefix + res; - subStream.StreamSpec = new COutFileStream; - subStream.Stream = subStream.StreamSpec; - if (!subStream.StreamSpec->Create(name, false)) + altStream.StreamSpec = new COutFileStream; + altStream.Stream = altStream.StreamSpec; + if (!altStream.StreamSpec->Create(name, false)) return ::GetLastError(); { // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS); TempFiles->Paths.Add(name); } - subStream.Pos = 0; - subStream.RealSize = 0; - subStream.Name = name; - Streams.Add(subStream); + altStream.Pos = 0; + altStream.RealSize = 0; + altStream.Name = name; + Streams.Add(altStream); continue; } - CSubStreamInfo &subStream = Streams[_streamIndex]; + CAltStreamInfo &altStream = Streams[_streamIndex]; - int index = _streamIndex; + unsigned index = _streamIndex; if (index >= Sizes.Size()) index = Sizes.Size() - 1; UInt64 volSize = Sizes[index]; @@ -144,29 +183,29 @@ STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *pr _streamIndex++; continue; } - if (_offsetPos != subStream.Pos) + if (_offsetPos != altStream.Pos) { // CMyComPtr outStream; - // RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream)); - RINOK(subStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); - subStream.Pos = _offsetPos; + // RINOK(altStream.Stream.QueryInterface(IID_IOutStream, &outStream)); + RINOK(altStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); + altStream.Pos = _offsetPos; } - UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - subStream.Pos); + UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - altStream.Pos); UInt32 realProcessed; - RINOK(subStream.Stream->Write(data, curSize, &realProcessed)); + RINOK(altStream.Stream->Write(data, curSize, &realProcessed)); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; - subStream.Pos += realProcessed; + altStream.Pos += realProcessed; _offsetPos += realProcessed; _absPos += realProcessed; if (_absPos > _length) _length = _absPos; - if (_offsetPos > subStream.RealSize) - subStream.RealSize = _offsetPos; + if (_offsetPos > altStream.RealSize) + altStream.RealSize = _offsetPos; if (processedSize != NULL) *processedSize += realProcessed; - if (subStream.Pos == volSize) + if (altStream.Pos == volSize) { _streamIndex++; _offsetPos = 0; @@ -182,17 +221,11 @@ STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *n { if (seekOrigin >= 3) return STG_E_INVALIDFUNCTION; - switch(seekOrigin) + switch (seekOrigin) { - case STREAM_SEEK_SET: - _absPos = offset; - break; - case STREAM_SEEK_CUR: - _absPos += offset; - break; - case STREAM_SEEK_END: - _absPos = _length + offset; - break; + 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) @@ -205,24 +238,24 @@ STDMETHODIMP COutMultiVolStream::SetSize(UInt64 newSize) { if (newSize < 0) return E_INVALIDARG; - int i = 0; + unsigned i = 0; while (i < Streams.Size()) { - CSubStreamInfo &subStream = Streams[i++]; - if ((UInt64)newSize < subStream.RealSize) + CAltStreamInfo &altStream = Streams[i++]; + if ((UInt64)newSize < altStream.RealSize) { - RINOK(subStream.Stream->SetSize(newSize)); - subStream.RealSize = newSize; + RINOK(altStream.Stream->SetSize(newSize)); + altStream.RealSize = newSize; break; } - newSize -= subStream.RealSize; + newSize -= altStream.RealSize; } while (i < Streams.Size()) { { - CSubStreamInfo &subStream = Streams.Back(); - subStream.Stream.Release(); - NDirectory::DeleteFileAlways(subStream.Name); + CAltStreamInfo &altStream = Streams.Back(); + altStream.Stream.Release(); + DeleteFileAlways(altStream.Name); } Streams.DeleteBack(); } @@ -232,7 +265,67 @@ STDMETHODIMP COutMultiVolStream::SetSize(UInt64 newSize) return S_OK; } -static const wchar_t *kDefaultArchiveType = L"7z"; +void CArchivePath::ParseFromPath(const UString &path, EArcNameMode mode) +{ + OriginalPath = path; + + SplitPathToParts_2(path, Prefix, Name); + + if (mode == k_ArcNameMode_Add) + return; + if (mode == k_ArcNameMode_Exact) + { + BaseExtension.Empty(); + return; + } + + int dotPos = Name.ReverseFind(L'.'); + if (dotPos < 0) + return; + if ((unsigned)dotPos == Name.Len() - 1) + { + Name.DeleteBack(); + BaseExtension.Empty(); + return; + } + const UString ext = Name.Ptr(dotPos + 1); + if (BaseExtension.IsEqualToNoCase(ext)) + { + BaseExtension = ext; + Name.DeleteFrom(dotPos); + } + else + BaseExtension.Empty(); +} + +UString CArchivePath::GetFinalPath() const +{ + UString path = GetPathWithoutExt(); + if (!BaseExtension.IsEmpty()) + path += UString(L'.') + BaseExtension; + return path; +} + +UString CArchivePath::GetFinalVolPath() const +{ + UString path = GetPathWithoutExt(); + if (!BaseExtension.IsEmpty()) + path += UString(L'.') + VolExtension; + return path; +} + +FString CArchivePath::GetTempPath() const +{ + FString path = TempPrefix + us2fs(Name); + if (!BaseExtension.IsEmpty()) + path += FString(FTEXT('.')) + us2fs(BaseExtension); + path += FTEXT(".tmp"); + path += TempPostfix; + return path; +} + +static const wchar_t *kDefaultArcType = L"7z"; +static const wchar_t *kDefaultArcExt = L"7z"; static const wchar_t *kSFXExtension = #ifdef _WIN32 L"exe"; @@ -240,40 +333,58 @@ static const wchar_t *kSFXExtension = L""; #endif -bool CUpdateOptions::Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath) +bool CUpdateOptions::InitFormatIndex(const CCodecs *codecs, + const CObjectVector &types, const UString &arcPath) { - if (formatIndices.Size() > 1) + if (types.Size() > 1) return false; - int arcTypeIndex = -1; - if (formatIndices.Size() != 0) - arcTypeIndex = formatIndices[0]; - if (arcTypeIndex >= 0) - MethodMode.FormatIndex = arcTypeIndex; + // int arcTypeIndex = -1; + if (types.Size() != 0) + { + MethodMode.Type = types[0]; + MethodMode.Type_Defined = true; + } + if (MethodMode.Type.FormatIndex < 0) + { + // MethodMode.Type = -1; + MethodMode.Type = COpenType(); + if (ArcNameMode != k_ArcNameMode_Add) + { + MethodMode.Type.FormatIndex = codecs->FindFormatForArchiveName(arcPath); + if (MethodMode.Type.FormatIndex >= 0) + MethodMode.Type_Defined = true; + } + } + return true; +} + +bool CUpdateOptions::SetArcPath(const CCodecs *codecs, const UString &arcPath) +{ + UString typeExt; + int formatIndex = MethodMode.Type.FormatIndex; + if (formatIndex < 0) + { + typeExt = kDefaultArcExt; + } else { - 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); + const CArcInfoEx &arcInfo = codecs->Formats[formatIndex]; + if (!arcInfo.UpdateEnabled) + return false; + typeExt = arcInfo.GetMainExt(); } - 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++) + ArchivePath.ParseFromPath(arcPath, ArcNameMode); + FOR_VECTOR (i, Commands) { CUpdateArchiveCommand &uc = Commands[i]; uc.ArchivePath.BaseExtension = ext; uc.ArchivePath.VolExtension = typeExt; - uc.ArchivePath.ParseFromPath(uc.UserArchivePath); + uc.ArchivePath.ParseFromPath(uc.UserArchivePath, ArcNameMode); } return true; } @@ -295,36 +406,98 @@ HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(int arcIndex) } */ +bool CRenamePair::Prepare() +{ + if (RecursedType != NRecursedType::kNonRecursed) + return false; + if (!WildcardParsing) + return true; + return !DoesNameContainWildcard(OldName); +} + +extern bool g_CaseSensitive; + +static int CompareTwoNames(const wchar_t *s1, const wchar_t *s2) +{ + for (int i = 0;; i++) + { + wchar_t c1 = s1[i]; + wchar_t c2 = s2[i]; + if (c1 == 0 || c2 == 0) + return i; + if (c1 == c2) + continue; + if (!g_CaseSensitive && (MyCharUpper(c1) == MyCharUpper(c2))) + continue; + if (IsCharDirLimiter(c1) && IsCharDirLimiter(c2)) + continue; + return i; + } +} + +bool CRenamePair::GetNewPath(bool isFolder, const UString &src, UString &dest) const +{ + int num = CompareTwoNames(OldName, src); + if (OldName[num] == 0) + { + if (src[num] != 0 && !IsCharDirLimiter(src[num]) && num != 0 && !IsCharDirLimiter(src[num - 1])) + return false; + } + else + { + // OldName[num] != 0 + // OldName = "1\1a.txt" + // src = "1" + + if (!isFolder || + src[num] != 0 || + !IsCharDirLimiter(OldName[num]) || + OldName[num + 1] != 0) + return false; + } + dest = NewName + src.Ptr(num); + return true; +} + +static int GetReverseSlashPos(const UString &name) +{ + int slashPos = name.ReverseFind(L'/'); + #ifdef _WIN32 + int slash1Pos = name.ReverseFind(L'\\'); + slashPos = MyMax(slashPos, slash1Pos); + #endif + return slashPos; +} + static HRESULT Compress( + const CUpdateOptions &options, CCodecs *codecs, const CActionSet &actionSet, - IInArchive *archive, - const CCompressionMethodMode &compressionMethod, + const CArc *arc, CArchivePath &archivePath, const CObjectVector &arcItems, - bool shareForWrite, - bool stdInMode, - /* const UString & stdInFileName, */ - bool stdOutMode, + Byte *processedItemsStatuses, const CDirItems &dirItems, - bool sfxMode, - const FString &sfxModule, - const CRecordVector &volumesSizes, + const CDirItem *parentDirItem, CTempFiles &tempFiles, CUpdateErrorInfo &errorInfo, IUpdateCallbackUI *callback) { CMyComPtr outArchive; - if (archive != NULL) + int formatIndex = options.MethodMode.Type.FormatIndex; + if (arc) { - CMyComPtr archive2 = archive; + formatIndex = arc->FormatIndex; + if (formatIndex < 0) + return E_NOTIMPL; + CMyComPtr archive2 = arc->Archive; HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive); if (result != S_OK) throw kUpdateIsNotSupoorted; } else { - RINOK(codecs->CreateOutArchive(compressionMethod.FormatIndex, outArchive)); + RINOK(codecs->CreateOutArchive(formatIndex, outArchive)); #ifdef EXTERNAL_CODECS { @@ -344,7 +517,7 @@ static HRESULT Compress( UInt32 value; RINOK(outArchive->GetFileTimeType(&value)); - switch(value) + switch (value) { case NFileTimeType::kWindows: case NFileTimeType::kUnix: @@ -355,8 +528,69 @@ static HRESULT Compress( return E_FAIL; } + { + const CArcInfoEx &arcInfo = codecs->Formats[formatIndex]; + if (options.AltStreams.Val && !arcInfo.Flags_AltStreams()) + return E_NOTIMPL; + if (options.NtSecurity.Val && !arcInfo.Flags_NtSecure()) + return E_NOTIMPL; + } + CRecordVector updatePairs2; + UStringVector newNames; + + if (options.RenamePairs.Size() != 0) + { + FOR_VECTOR (i, arcItems) + { + const CArcItem &ai = arcItems[i]; + bool needRename = false; + UString dest; + if (ai.Censored) + { + FOR_VECTOR (j, options.RenamePairs) + { + const CRenamePair &rp = options.RenamePairs[j]; + if (rp.GetNewPath(ai.IsDir, ai.Name, dest)) + { + needRename = true; + break; + } + if (ai.IsAltStream) + { + int colonPos = ai.Name.ReverseFind(':'); + int slashPosPos = GetReverseSlashPos(ai.Name); + if (colonPos > slashPosPos) + { + UString mainName = ai.Name.Left(colonPos); + /* + actually we must improve that code to support cases + with folder renaming like: rn arc dir1\ dir2\ + */ + if (rp.GetNewPath(false, mainName, dest)) + { + needRename = true; + dest += ':'; + dest += ai.Name.Ptr(colonPos + 1); + break; + } + } + } + } + } + CUpdatePair2 up2; + up2.SetAs_NoChangeArcItem(ai.IndexInServer); + if (needRename) + { + up2.NewProps = true; + RINOK(arc->IsItemAnti(i, up2.IsAnti)); + up2.NewNameIndex = newNames.Add(dest); + } + updatePairs2.Add(up2); + } + } + else { CRecordVector updatePairs; GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // must be done only once!!! @@ -365,44 +599,65 @@ static HRESULT Compress( } UInt32 numFiles = 0; - for (int i = 0; i < updatePairs2.Size(); i++) + FOR_VECTOR (i, updatePairs2) if (updatePairs2[i].NewData) numFiles++; RINOK(callback->SetNumFiles(numFiles)); - CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr updateCallback(updateCallbackSpec); - updateCallbackSpec->ShareForWrite = shareForWrite; - updateCallbackSpec->StdInMode = stdInMode; + updateCallbackSpec->ShareForWrite = options.OpenShareForWrite; + updateCallbackSpec->StdInMode = options.StdInMode; updateCallbackSpec->Callback = callback; + + if (arc) + { + // we set Archive to allow to transfer GetProperty requests back to DLL. + updateCallbackSpec->Archive = arc->Archive; + updateCallbackSpec->GetRawProps = arc->GetRawProps; + updateCallbackSpec->GetRootProps = arc->GetRootProps; + } + updateCallbackSpec->DirItems = &dirItems; + updateCallbackSpec->ParentDirItem = parentDirItem; + + updateCallbackSpec->StoreNtSecurity = options.NtSecurity.Val; + updateCallbackSpec->StoreHardLinks = options.HardLinks.Val; + updateCallbackSpec->StoreSymLinks = options.SymLinks.Val; + updateCallbackSpec->ArcItems = &arcItems; updateCallbackSpec->UpdatePairs = &updatePairs2; + updateCallbackSpec->ProcessedItemsStatuses = processedItemsStatuses; + + if (options.RenamePairs.Size() != 0) + updateCallbackSpec->NewNames = &newNames; + + CMyComPtr outSeekStream; CMyComPtr outStream; - if (!stdOutMode) + if (!options.StdOutMode) { FString dirPrefix; - if (!NFile::NDirectory::GetOnlyDirPrefix(us2fs(archivePath.GetFinalPath()), dirPrefix)) + if (!GetOnlyDirPrefix(us2fs(archivePath.GetFinalPath()), dirPrefix)) throw 1417161; - NFile::NDirectory::CreateComplexDirectory(dirPrefix); + CreateComplexDir(dirPrefix); } COutFileStream *outStreamSpec = NULL; COutMultiVolStream *volStreamSpec = NULL; - if (volumesSizes.Size() == 0) + if (options.VolumesSizes.Size() == 0) { - if (stdOutMode) + if (options.StdOutMode) outStream = new CStdOutFileStream; else { outStreamSpec = new COutFileStream; - outStream = outStreamSpec; + outSeekStream = outStreamSpec; + outStream = outSeekStream; bool isOK = false; FString realPath; for (int i = 0; i < (1 << 16); i++) @@ -441,12 +696,16 @@ static HRESULT Compress( } else { - if (stdOutMode) + if (options.StdOutMode) return E_FAIL; + if (arc && arc->GetGlobalOffset() > 0) + return E_NOTIMPL; + volStreamSpec = new COutMultiVolStream; - outStream = volStreamSpec; - volStreamSpec->Sizes = volumesSizes; - volStreamSpec->Prefix = us2fs(archivePath.GetFinalPath() + L"."); + outSeekStream = volStreamSpec; + outStream = outSeekStream; + volStreamSpec->Sizes = options.VolumesSizes; + volStreamSpec->Prefix = us2fs(archivePath.GetFinalVolPath() + L"."); volStreamSpec->TempFiles = &tempFiles; volStreamSpec->Init(); @@ -458,23 +717,23 @@ static HRESULT Compress( */ } - RINOK(SetProperties(outArchive, compressionMethod.Properties)); + RINOK(SetProperties(outArchive, options.MethodMode.Properties)); - if (sfxMode) + if (options.SfxMode) { CInFileStream *sfxStreamSpec = new CInFileStream; CMyComPtr sfxStream(sfxStreamSpec); - if (!sfxStreamSpec->Open(sfxModule)) + if (!sfxStreamSpec->Open(options.SfxModule)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"7-Zip cannot open SFX module"; - errorInfo.FileName = sfxModule; + errorInfo.FileName = options.SfxModule; return E_FAIL; } CMyComPtr sfxOutStream; COutFileStream *outStreamSpec = NULL; - if (volumesSizes.Size() == 0) + if (options.VolumesSizes.Size() == 0) sfxOutStream = outStream; else { @@ -496,9 +755,61 @@ static HRESULT Compress( } } - HRESULT result = outArchive->UpdateItems(outStream, updatePairs2.Size(), updateCallback); + CMyComPtr tailStream; + + if (options.SfxMode || !arc || arc->ArcStreamOffset == 0) + tailStream = outStream; + else + { + // Int64 globalOffset = arc->GetGlobalOffset(); + RINOK(arc->InStream->Seek(0, STREAM_SEEK_SET, NULL)); + RINOK(NCompress::CopyStream_ExactSize(arc->InStream, outStream, arc->ArcStreamOffset, NULL)); + if (options.StdOutMode) + tailStream = outStream; + else + { + CTailOutStream *tailStreamSpec = new CTailOutStream; + tailStream = tailStreamSpec; + tailStreamSpec->Stream = outSeekStream; + tailStreamSpec->Offset = arc->ArcStreamOffset; + tailStreamSpec->Init(); + } + } + + + HRESULT result = outArchive->UpdateItems(tailStream, updatePairs2.Size(), updateCallback); callback->Finilize(); RINOK(result); + + + if (options.SetArcMTime) + { + FILETIME ft; + ft.dwLowDateTime = 0; + ft.dwHighDateTime = 0; + FOR_VECTOR (i, updatePairs2) + { + CUpdatePair2 &pair2 = updatePairs2[i]; + const FILETIME *ft2 = NULL; + if (pair2.NewProps && pair2.DirIndex >= 0) + ft2 = &dirItems.Items[pair2.DirIndex].MTime; + else if (pair2.UseArcProps && pair2.ArcIndex >= 0) + ft2 = &arcItems[pair2.ArcIndex].MTime; + if (ft2) + { + if (::CompareFileTime(&ft, ft2) < 0) + ft = *ft2; + } + } + if (ft.dwLowDateTime != 0 || ft.dwHighDateTime != 0) + { + if (outStreamSpec) + outStreamSpec->SetMTime(&ft); + else if (volStreamSpec) + volStreamSpec->SetMTime(&ft);; + } + } + if (outStreamSpec) result = outStreamSpec->Close(); else if (volStreamSpec) @@ -506,7 +817,9 @@ static HRESULT Compress( return result; } -HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor, +static HRESULT EnumerateInArchiveItems( + // bool storeStreamsMode, + const NWildcard::CCensor &censor, const CArc &arc, CObjectVector &arcItems) { @@ -514,14 +827,19 @@ HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor, UInt32 numItems; IInArchive *archive = arc.Archive; RINOK(archive->GetNumberOfItems(&numItems)); - arcItems.Reserve(numItems); + arcItems.ClearAndReserve(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(Archive_IsItem_Folder(archive, i, ai.IsDir)); + RINOK(Archive_IsItem_AltStream(archive, i, ai.IsAltStream)); + /* + if (!storeStreamsMode && ai.IsAltStream) + continue; + */ + ai.Censored = censor.CheckPath(ai.IsAltStream, ai.Name, !ai.IsDir); RINOK(arc.GetItemMTime(i, ai.MTime, ai.MTimeDefined)); RINOK(arc.GetItemSize(i, ai.Size, ai.SizeDefined)); @@ -531,7 +849,7 @@ HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor, if (prop.vt == VT_UI4) { ai.TimeType = (int)(NFileTimeType::EEnum)prop.ulVal; - switch(ai.TimeType) + switch (ai.TimeType) { case NFileTimeType::kWindows: case NFileTimeType::kUnix: @@ -544,99 +862,102 @@ HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor, } ai.IndexInServer = i; - arcItems.Add(ai); + arcItems.AddInReserved(ai); } return S_OK; } - -static HRESULT UpdateWithItemLists( - CCodecs *codecs, - CUpdateOptions &options, - IInArchive *archive, - const CObjectVector &arcItems, - CDirItems &dirItems, - CTempFiles &tempFiles, - CUpdateErrorInfo &errorInfo, - IUpdateCallbackUI2 *callback) +struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback { - for(int i = 0; i < options.Commands.Size(); i++) + IUpdateCallbackUI2 *Callback; + HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) { - 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 Callback->ScanProgress(numFolders, numFiles, totalSize, path, isDir); } - return S_OK; -} +}; #if defined(_WIN32) && !defined(UNDER_CE) -class CCurrentDirRestorer + +#include + +#endif + +struct CRefSortPair { - FString _path; -public: - CCurrentDirRestorer() { NFile::NDirectory::MyGetCurrentDirectory(_path); } - ~CCurrentDirRestorer() { RestoreDirectory();} - bool RestoreDirectory() const { return BOOLToBool(NFile::NDirectory::MySetCurrentDirectory(_path)); } + int Len; + int Index; }; -#endif -struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback +#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } + +static int CompareRefSortPair(const CRefSortPair *a1, const CRefSortPair *a2, void *) { - IUpdateCallbackUI2 *Callback; - HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) + RINOZ(-MyCompare(a1->Len, a2->Len)); + return MyCompare(a1->Index, a2->Index); +} + +static int GetNumSlashes(const FChar *s) +{ + for (int numSlashes = 0;;) { - return Callback->ScanProgress(numFolders, numFiles, path); + FChar c = *s++; + if (c == 0) + return numSlashes; + if ( + #ifdef _WIN32 + c == FTEXT('\\') || + #endif + c == FTEXT('/')) + numSlashes++; } -}; +} #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; +void ConvertToLongNames(NWildcard::CCensor &censor); #endif HRESULT UpdateArchive( CCodecs *codecs, - const NWildcard::CCensor &censor, + const CObjectVector &types, + const UString &cmdArcPath2, + NWildcard::CCensor &censor, CUpdateOptions &options, CUpdateErrorInfo &errorInfo, IOpenCallbackUI *openCallback, - IUpdateCallbackUI2 *callback) + IUpdateCallbackUI2 *callback, + bool needSetPath) { if (options.StdOutMode && options.EMailMode) return E_FAIL; - if (options.VolumesSizes.Size() > 0 && (options.EMailMode || options.SfxMode)) + if (types.Size() > 1) + return E_NOTIMPL; + + bool renameMode = !options.RenamePairs.IsEmpty(); + if (renameMode) + { + if (options.Commands.Size() != 1) + return E_FAIL; + } + + if (options.DeleteAfterCompressing) + { + if (options.Commands.Size() != 1) + return E_NOTIMPL; + const CActionSet &as = options.Commands[0].ActionSet; + for (int i = 2; i < NPairState::kNumValues; i++) + if (as.StateActions[i] != NPairAction::kCompress) + return E_NOTIMPL; + } + + censor.AddPathsToCensor(options.PathMode); + #ifdef _WIN32 + ConvertToLongNames(censor); + #endif + censor.ExtendExclude(); + + + if (options.VolumesSizes.Size() > 0 && (options.EMailMode /* || options.SfxMode */)) return E_NOTIMPL; if (options.SfxMode) @@ -672,26 +993,74 @@ HRESULT UpdateArchive( } } - CArchiveLink arcLink; - const UString arcPath = options.ArchivePath.GetFinalPath(); - if (!options.ArchivePath.OriginalPath.IsEmpty()) + + if (needSetPath) + { + if (!options.InitFormatIndex(codecs, types, cmdArcPath2) || + !options.SetArcPath(codecs, cmdArcPath2)) + return E_NOTIMPL; + } + UString arcPath = options.ArchivePath.GetFinalPath(); + + if (cmdArcPath2.IsEmpty()) + { + if (options.MethodMode.Type.FormatIndex < 0) + throw "type of archive is not specified"; + } + else { NFind::CFileInfo fi; - if (fi.Find(us2fs(arcPath))) + if (!fi.Find(us2fs(arcPath))) + { + if (renameMode) + throw "can't find archive";; + if (options.MethodMode.Type.FormatIndex < 0) + { + if (!options.SetArcPath(codecs, cmdArcPath2)) + return E_NOTIMPL; + } + } + else { if (fi.IsDir()) throw "there is no such archive"; + if (fi.IsDevice) + return E_NOTIMPL; if (options.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); + CObjectVector types; + // change it. + if (options.MethodMode.Type_Defined) + types.Add(options.MethodMode.Type); + // We need to set Properties to open archive only in some cases (WIM archives). + + CIntVector excl; + COpenOptions op; + #ifndef _SFX + op.props = &options.MethodMode.Properties; + #endif + op.codecs = codecs; + op.types = &types; + op.excludedFormats = ! + op.stdInMode = false; + op.stream = NULL; + op.filePath = arcPath; + + HRESULT result = arcLink.Open2(op, openCallback); + if (result == E_ABORT) return result; - RINOK(callback->OpenResult(arcPath, result)); + + const wchar_t *errorArcType = NULL; + if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex > 0) + errorArcType = codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name; + RINOK(callback->OpenResult(arcPath, result, errorArcType)); + /* + if (result == S_FALSE) + return E_FAIL; + */ RINOK(result); if (arcLink.VolumePaths.Size() > 1) { @@ -703,17 +1072,42 @@ HRESULT UpdateArchive( CArc &arc = arcLink.Arcs.Back(); arc.MTimeDefined = !fi.IsDevice; arc.MTime = fi.MTime; + + if (arc.ErrorInfo.ThereIsTail) + { + errorInfo.SystemError = (DWORD)E_NOTIMPL; + errorInfo.Message = L"There is some data block after the end of the archive"; + return E_NOTIMPL; + } + if (options.MethodMode.Type.FormatIndex < 0) + { + options.MethodMode.Type.FormatIndex = arcLink.GetArc()->FormatIndex; + if (!options.SetArcPath(codecs, cmdArcPath2)) + return E_NOTIMPL; + } } } - else + + if (options.MethodMode.Type.FormatIndex < 0) { - /* - if (archiveType.IsEmpty()) - throw "type of archive is not specified"; - */ + options.MethodMode.Type.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArcType); + if (options.MethodMode.Type.FormatIndex < 0) + return E_NOTIMPL; } + bool thereIsInArchive = arcLink.IsOpen; + if (!thereIsInArchive && renameMode) + return E_FAIL; + CDirItems dirItems; + CDirItem parentDirItem; + CDirItem *parentDirItem_Ptr = NULL; + + FStringVector requestedPaths; + FStringVector *requestedPaths_Ptr = NULL; + if (options.DeleteAfterCompressing) + requestedPaths_Ptr = &requestedPaths; + if (options.StdInMode) { CDirItem di; @@ -727,7 +1121,8 @@ HRESULT UpdateArchive( else { bool needScanning = false; - for(int i = 0; i < options.Commands.Size(); i++) + if (!renameMode) + FOR_VECTOR (i, options.Commands) if (options.Commands[i].ActionSet.NeedScanning()) needScanning = true; if (needScanning) @@ -735,12 +1130,21 @@ HRESULT UpdateArchive( CEnumDirItemUpdateCallback enumCallback; enumCallback.Callback = callback; RINOK(callback->StartScanning()); - FStringVector errorPaths; - CRecordVector errorCodes; - HRESULT res = EnumerateItems(censor, dirItems, &enumCallback, errorPaths, errorCodes); - for (int i = 0; i < errorPaths.Size(); i++) + + dirItems.SymLinks = options.SymLinks.Val; + + #if defined(_WIN32) && !defined(UNDER_CE) + dirItems.ReadSecure = options.NtSecurity.Val; + #endif + + dirItems.ScanAltStreams = options.AltStreams.Val; + HRESULT res = EnumerateItems(censor, + options.PathMode, + options.AddPathPrefix, + dirItems, &enumCallback); + FOR_VECTOR (i, dirItems.ErrorPaths) { - RINOK(callback->CanNotFindError(fs2us(errorPaths[i]), errorCodes[i])); + RINOK(callback->CanNotFindError(fs2us(dirItems.ErrorPaths[i]), dirItems.ErrorCodes[i])); } if (res != S_OK) { @@ -749,6 +1153,38 @@ HRESULT UpdateArchive( return res; } RINOK(callback->FinishScanning()); + + if (censor.Pairs.Size() == 1) + { + NFind::CFileInfo fi; + FString prefix = us2fs(censor.Pairs[0].Prefix) + FTEXT("."); + // UString prefix = censor.Pairs[0].Prefix; + /* + if (prefix.Back() == WCHAR_PATH_SEPARATOR) + { + prefix.DeleteBack(); + } + */ + if (fi.Find(prefix)) + if (fi.IsDir()) + { + parentDirItem.Size = fi.Size; + parentDirItem.CTime = fi.CTime; + parentDirItem.ATime = fi.ATime; + parentDirItem.MTime = fi.MTime; + parentDirItem.Attrib = fi.Attrib; + parentDirItem_Ptr = &parentDirItem; + + int secureIndex = -1; + #if defined(_WIN32) && !defined(UNDER_CE) + if (options.NtSecurity.Val) + dirItems.AddSecurityItem(prefix, secureIndex); + #endif + parentDirItem.SecureIndex = secureIndex; + + parentDirItem_Ptr = &parentDirItem; + } + } } } @@ -756,7 +1192,7 @@ HRESULT UpdateArchive( bool usesTempDir = false; #ifdef _WIN32 - NDirectory::CTempDir tempDirectory; + CTempDir tempDirectory; if (options.EMailMode && options.EMailRemoveAfter) { tempDirectory.Create(kTempFolderPrefix); @@ -770,8 +1206,6 @@ HRESULT UpdateArchive( bool createTempFile = false; - bool thereIsInArchive = arcLink.IsOpen; - if (!options.StdOutMode && options.UpdateArchiveItself) { CArchivePath &ap = options.Commands[0].ArchivePath; @@ -789,7 +1223,8 @@ HRESULT UpdateArchive( } } - for (int i = 0; i < options.Commands.Size(); i++) + unsigned i; + for (i = 0; i < options.Commands.Size(); i++) { CArchivePath &ap = options.Commands[i].ArchivePath; if (usesTempDir) @@ -816,13 +1251,64 @@ HRESULT UpdateArchive( CObjectVector arcItems; if (thereIsInArchive) { - RINOK(EnumerateInArchiveItems(censor, arcLink.Arcs.Back(), arcItems)); + RINOK(EnumerateInArchiveItems( + // options.StoreAltStreams, + censor, arcLink.Arcs.Back(), arcItems)); + } + + /* + FStringVector processedFilePaths; + FStringVector *processedFilePaths_Ptr = NULL; + if (options.DeleteAfterCompressing) + processedFilePaths_Ptr = &processedFilePaths; + */ + + CByteBuffer processedItems; + if (options.DeleteAfterCompressing) + { + unsigned num = dirItems.Items.Size(); + processedItems.Alloc(num); + for (i = 0; i < num; i++) + processedItems[i] = 0; + } + + for (i = 0; i < options.Commands.Size(); i++) + { + const CArc *arc = thereIsInArchive ? arcLink.GetArc() : 0; + // IInArchiveExtra *archiveExtra = thereIsInArchive ? arcLink.GetArchiveExtra() : 0; + // IArchiveGetRootProps *archiveGetRootProps = thereIsInArchive ? arcLink.GetArchiveGetRootProps() : 0; + CUpdateArchiveCommand &command = options.Commands[i]; + UString name; + bool isUpdating; + if (options.StdOutMode) + { + name = L"stdout"; + isUpdating = arc != 0; + } + else + { + name = command.ArchivePath.GetFinalPath(); + isUpdating = (i == 0 && options.UpdateArchiveItself && arc != 0); + } + RINOK(callback->StartArchive(name, isUpdating)) + + RINOK(Compress(options, + codecs, + command.ActionSet, + arc, + command.ArchivePath, + arcItems, + options.DeleteAfterCompressing ? (Byte *)processedItems : NULL, + + dirItems, + parentDirItem_Ptr, + + tempFiles, + errorInfo, callback)); + + RINOK(callback->FinishArchive()); } - RINOK(UpdateWithItemLists(codecs, options, - thereIsInArchive ? arcLink.GetArchive() : 0, - arcItems, dirItems, - tempFiles, errorInfo, callback)); if (thereIsInArchive) { @@ -838,14 +1324,14 @@ HRESULT UpdateArchive( CArchivePath &ap = options.Commands[0].ArchivePath; const FString &tempPath = ap.GetTempPath(); if (thereIsInArchive) - if (!NDirectory::DeleteFileAlways(us2fs(arcPath))) + if (!DeleteFileAlways(us2fs(arcPath))) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"7-Zip cannot delete the file"; errorInfo.FileName = us2fs(arcPath); return E_FAIL; } - if (!NDirectory::MyMoveFile(tempPath, us2fs(arcPath))) + if (!MyMoveFile(tempPath, us2fs(arcPath))) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"7-Zip cannot move the file"; @@ -860,6 +1346,7 @@ HRESULT UpdateArchive( } } + #if defined(_WIN32) && !defined(UNDER_CE) if (options.EMailMode) { @@ -870,20 +1357,31 @@ HRESULT UpdateArchive( errorInfo.Message = L"7-Zip cannot load Mapi32.dll"; return E_FAIL; } - MY_LPMAPISENDDOCUMENTS fnSend = (MY_LPMAPISENDDOCUMENTS)mapiLib.GetProc("MAPISendDocuments"); + + /* + LPMAPISENDDOCUMENTS fnSend = (LPMAPISENDDOCUMENTS)mapiLib.GetProc("MAPISendDocuments"); if (fnSend == 0) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"7-Zip cannot find MAPISendDocuments function"; return E_FAIL; } + */ + LPMAPISENDMAIL sendMail = (LPMAPISENDMAIL)mapiLib.GetProc("MAPISendMail"); + if (sendMail == 0) + { + errorInfo.SystemError = ::GetLastError(); + errorInfo.Message = L"7-Zip cannot find MAPISendMail function"; + return E_FAIL; + } + FStringVector fullPaths; - int i; + unsigned i; for (i = 0; i < options.Commands.Size(); i++) { CArchivePath &ap = options.Commands[i].ArchivePath; FString arcPath; - if (!NFile::NDirectory::MyGetFullPathName(us2fs(ap.GetFinalPath()), arcPath)) + if (!MyGetFullPathName(us2fs(ap.GetFinalPath()), arcPath)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"GetFullPathName error"; @@ -899,9 +1397,79 @@ HRESULT UpdateArchive( AString path = GetAnsiString(arcPath); AString name = GetAnsiString(fileName); // Warning!!! MAPISendDocuments function changes Current directory - fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0); + // fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0); + + MapiFileDesc f; + memset(&f, 0, sizeof(f)); + f.nPosition = 0xFFFFFFFF; + f.lpszPathName = (char *)(const char *)path; + f.lpszFileName = (char *)(const char *)name; + + MapiMessage m; + memset(&m, 0, sizeof(m)); + m.nFileCount = 1; + m.lpFiles = &f; + + const AString addr = GetAnsiString(options.EMailAddress); + MapiRecipDesc rec; + if (!addr.IsEmpty()) + { + memset(&rec, 0, sizeof(rec)); + rec.ulRecipClass = MAPI_TO; + rec.lpszAddress = (char *)(const char *)addr; + m.nRecipCount = 1; + m.lpRecips = &rec; + } + + sendMail(NULL, 0, &m, MAPI_DIALOG, 0); } } #endif + + if (options.DeleteAfterCompressing) + { + CRecordVector pairs; + FStringVector foldersNames; + for (i = 0; i < dirItems.Items.Size(); i++) + { + const CDirItem &dirItem = dirItems.Items[i]; + FString phyPath = us2fs(dirItems.GetPhyPath(i)); + if (dirItem.IsDir()) + { + CRefSortPair pair; + pair.Index = i; + pair.Len = GetNumSlashes(phyPath); + pairs.Add(pair); + } + else + { + if (processedItems[i] != 0 || dirItem.Size == 0) + { + DeleteFileAlways(phyPath); + } + else + { + // file was skipped + /* + errorInfo.SystemError = 0; + errorInfo.Message = L"file was not processed"; + errorInfo.FileName = phyPath; + return E_FAIL; + */ + } + } + } + + pairs.Sort(CompareRefSortPair, NULL); + for (i = 0; i < pairs.Size(); i++) + { + FString phyPath = us2fs(dirItems.GetPhyPath(pairs[i].Index)); + if (NFind::DoesDirExist(phyPath)) + { + // printf("delete %S\n", phyPath); + RemoveDir(phyPath); + } + } + } return S_OK; } diff --git a/CPP/7zip/UI/Common/Update.h b/CPP/7zip/UI/Common/Update.h old mode 100755 new mode 100644 index 43a3c0fd..68e51d85 --- a/CPP/7zip/UI/Common/Update.h +++ b/CPP/7zip/UI/Common/Update.h @@ -3,14 +3,22 @@ #ifndef __COMMON_UPDATE_H #define __COMMON_UPDATE_H -#include "Common/Wildcard.h" +#include "../../../Common/Wildcard.h" #include "ArchiveOpenCallback.h" #include "LoadCodecs.h" +#include "OpenArchive.h" #include "Property.h" #include "UpdateAction.h" #include "UpdateCallback.h" +enum EArcNameMode +{ + k_ArcNameMode_Smart, + k_ArcNameMode_Exact, + k_ArcNameMode_Add, +}; + struct CArchivePath { UString OriginalPath; @@ -26,52 +34,11 @@ struct CArchivePath 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; - } - - - FString GetTempPath() const - { - FString path = TempPrefix + us2fs(Name); - if (!BaseExtension.IsEmpty()) - path += FString(FTEXT('.')) + us2fs(BaseExtension); - path += FTEXT(".tmp"); - path += TempPostfix; - return path; - } + void ParseFromPath(const UString &path, EArcNameMode mode); + UString GetPathWithoutExt() const { return Prefix + Name; } + UString GetFinalPath() const; + UString GetFinalVolPath() const; + FString GetTempPath() const; }; struct CUpdateArchiveCommand @@ -83,9 +50,31 @@ struct CUpdateArchiveCommand struct CCompressionMethodMode { - int FormatIndex; + bool Type_Defined; + COpenType Type; CObjectVector Properties; - CCompressionMethodMode(): FormatIndex(-1) {} + + CCompressionMethodMode(): Type_Defined(false) {} +}; + +namespace NRecursedType { enum EEnum +{ + kRecursed, + kWildcardOnlyRecursed, + kNonRecursed +};} + +struct CRenamePair +{ + UString OldName; + UString NewName; + bool WildcardParsing; + NRecursedType::EEnum RecursedType; + + CRenamePair(): WildcardParsing(true), RecursedType(NRecursedType::kNonRecursed) {} + + bool Prepare(); + bool GetNewPath(bool isFolder, const UString &src, UString &dest) const; }; struct CUpdateOptions @@ -95,7 +84,8 @@ struct CUpdateOptions CObjectVector Commands; bool UpdateArchiveItself; CArchivePath ArchivePath; - + EArcNameMode ArcNameMode; + bool SfxMode; FString SfxModule; @@ -110,8 +100,22 @@ struct CUpdateOptions UString EMailAddress; FString WorkingDir; + NWildcard::ECensorPathMode PathMode; + UString AddPathPrefix; + + CBoolPair NtSecurity; + CBoolPair AltStreams; + CBoolPair HardLinks; + CBoolPair SymLinks; + + bool DeleteAfterCompressing; - bool Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath); + bool SetArcMTime; + + CObjectVector RenamePairs; + + bool InitFormatIndex(const CCodecs *codecs, const CObjectVector &types, const UString &arcPath); + bool SetArcPath(const CCodecs *codecs, const UString &arcPath); CUpdateOptions(): UpdateArchiveItself(true), @@ -120,14 +124,20 @@ struct CUpdateOptions StdOutMode(false), EMailMode(false), EMailRemoveAfter(false), - OpenShareForWrite(false) + OpenShareForWrite(false), + ArcNameMode(k_ArcNameMode_Smart), + PathMode(NWildcard::k_RelatPath), + + DeleteAfterCompressing(false), + SetArcMTime(false) + {}; - void SetAddActionCommand() + void SetActionCommand_Add() { Commands.Clear(); CUpdateArchiveCommand c; - c.ActionSet = NUpdateArchive::kAddActionSet; + c.ActionSet = NUpdateArchive::k_ActionSet_Add; Commands.Add(c); } @@ -151,9 +161,9 @@ struct CUpdateErrorInfo: public CErrorInfo #define INTERFACE_IUpdateCallbackUI2(x) \ INTERFACE_IUpdateCallbackUI(x) \ - virtual HRESULT OpenResult(const wchar_t *name, HRESULT result) x; \ + virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, const wchar_t *errorArcType) x; \ virtual HRESULT StartScanning() x; \ - virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) x; \ + virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) x; \ virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) x; \ virtual HRESULT FinishScanning() x; \ virtual HRESULT StartArchive(const wchar_t *name, bool updating) x; \ @@ -166,10 +176,13 @@ struct IUpdateCallbackUI2: public IUpdateCallbackUI HRESULT UpdateArchive( CCodecs *codecs, - const NWildcard::CCensor &censor, + const CObjectVector &types, + const UString &cmdArcPath2, + NWildcard::CCensor &censor, CUpdateOptions &options, CUpdateErrorInfo &errorInfo, IOpenCallbackUI *openCallback, - IUpdateCallbackUI2 *callback); + IUpdateCallbackUI2 *callback, + bool needSetPath); #endif diff --git a/CPP/7zip/UI/Common/UpdateAction.cpp b/CPP/7zip/UI/Common/UpdateAction.cpp old mode 100755 new mode 100644 index 879a49c5..a80db721 --- a/CPP/7zip/UI/Common/UpdateAction.cpp +++ b/CPP/7zip/UI/Common/UpdateAction.cpp @@ -6,7 +6,7 @@ namespace NUpdateArchive { -const CActionSet kAddActionSet = +const CActionSet k_ActionSet_Add = {{ NPairAction::kCopy, NPairAction::kCopy, @@ -17,7 +17,7 @@ const CActionSet kAddActionSet = NPairAction::kCompress }}; -const CActionSet kUpdateActionSet = +const CActionSet k_ActionSet_Update = {{ NPairAction::kCopy, NPairAction::kCopy, @@ -28,7 +28,7 @@ const CActionSet kUpdateActionSet = NPairAction::kCompress }}; -const CActionSet kFreshActionSet = +const CActionSet k_ActionSet_Fresh = {{ NPairAction::kCopy, NPairAction::kCopy, @@ -39,7 +39,7 @@ const CActionSet kFreshActionSet = NPairAction::kCompress }}; -const CActionSet kSynchronizeActionSet = +const CActionSet k_ActionSet_Sync = {{ NPairAction::kCopy, NPairAction::kIgnore, @@ -50,7 +50,7 @@ const CActionSet kSynchronizeActionSet = NPairAction::kCompress, }}; -const CActionSet kDeleteActionSet = +const CActionSet k_ActionSet_Delete = {{ NPairAction::kCopy, NPairAction::kIgnore, diff --git a/CPP/7zip/UI/Common/UpdateAction.h b/CPP/7zip/UI/Common/UpdateAction.h old mode 100755 new mode 100644 index 0ac1c108..28dd28c3 --- a/CPP/7zip/UI/Common/UpdateAction.h +++ b/CPP/7zip/UI/Common/UpdateAction.h @@ -7,7 +7,7 @@ namespace NUpdateArchive { namespace NPairState { - const int kNumValues = 7; + const unsigned kNumValues = 7; enum EEnum { kNotMasked = 0, @@ -34,9 +34,18 @@ namespace NUpdateArchive { struct CActionSet { NPairAction::EEnum StateActions[NPairState::kNumValues]; + + const bool IsEqualTo(const CActionSet &a) const + { + for (unsigned i = 0; i < NPairState::kNumValues; i++) + if (StateActions[i] != a.StateActions[i]) + return false; + return true; + } + bool NeedScanning() const { - int i; + unsigned i; for (i = 0; i < NPairState::kNumValues; i++) if (StateActions[i] == NPairAction::kCompress) return true; @@ -47,11 +56,11 @@ namespace NUpdateArchive { } }; - extern const CActionSet kAddActionSet; - extern const CActionSet kUpdateActionSet; - extern const CActionSet kFreshActionSet; - extern const CActionSet kSynchronizeActionSet; - extern const CActionSet kDeleteActionSet; + extern const CActionSet k_ActionSet_Add; + extern const CActionSet k_ActionSet_Update; + extern const CActionSet k_ActionSet_Fresh; + extern const CActionSet k_ActionSet_Sync; + extern const CActionSet k_ActionSet_Delete; } #endif diff --git a/CPP/7zip/UI/Common/UpdateCallback.cpp b/CPP/7zip/UI/Common/UpdateCallback.cpp old mode 100755 new mode 100644 index 21146bb0..6be832b8 --- a/CPP/7zip/UI/Common/UpdateCallback.cpp +++ b/CPP/7zip/UI/Common/UpdateCallback.cpp @@ -2,18 +2,32 @@ #include "StdAfx.h" -#include "Common/ComTry.h" -#include "Common/Defs.h" -#include "Common/IntToString.h" -#include "Common/StringConvert.h" +#include "../../../Common/ComTry.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/Wildcard.h" -#include "Windows/PropVariant.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/Synchronization.h" #include "../../Common/FileStreams.h" +#include "../../Common/StreamObjects.h" #include "UpdateCallback.h" +#if defined(_WIN32) && !defined(UNDER_CE) +#define _USE_SECURITY_CODE +#include "../../../Windows/SecurityUtils.h" +#endif + using namespace NWindows; +using namespace NFile; + +#ifdef _USE_SECURITY_CODE +bool InitLocalPrivileges(); +#endif CArchiveUpdateCallback::CArchiveUpdateCallback(): Callback(0), @@ -23,8 +37,18 @@ CArchiveUpdateCallback::CArchiveUpdateCallback(): ArcItems(0), UpdatePairs(0), NewNames(0), - KeepOriginalItemNames(0) - {} + KeepOriginalItemNames(false), + ProcessedItemsStatuses(NULL), + ParentDirItem(NULL), + StoreNtSecurity(false), + StoreHardLinks(false), + StoreSymLinks(false), + _hardIndex_From((UInt32)(Int32)-1) +{ + #ifdef _USE_SECURITY_CODE + _saclEnabled = InitLocalPrivileges(); + #endif +} STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size) @@ -50,7 +74,7 @@ STDMETHODIMP CArchiveUpdateCallback::SetRatioInfo(const UInt64 *inSize, const UI /* -STATPROPSTG kProperties[] = +static const STATPROPSTG kProps[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidIsDir, VT_BOOL}, @@ -64,7 +88,7 @@ STATPROPSTG kProperties[] = STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **) { - return CStatPropEnumerator::CreateEnumerator(kProperties, sizeof(kProperties) / sizeof(kProperties[0]), enumerator); + return CStatPropEnumerator::CreateEnumerator(kProps, ARRAY_SIZE(kProps), enumerator); } */ @@ -74,11 +98,11 @@ STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index, 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) + if (newData) *newData = BoolToInt(up.NewData); + if (newProps) *newProps = BoolToInt(up.NewProps); + if (indexInArchive) { - *indexInArchive = (UInt32)-1; + *indexInArchive = (UInt32)(Int32)-1; if (up.ExistInArchive()) *indexInArchive = (ArcItems == 0) ? up.ArcIndex : (*ArcItems)[up.ArcIndex].IndexInServer; } @@ -86,84 +110,302 @@ STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index, COM_TRY_END } -STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +STDMETHODIMP CArchiveUpdateCallback::GetRootProp(PROPID propID, PROPVARIANT *value) { - COM_TRY_BEGIN - const CUpdatePair2 &up = (*UpdatePairs)[index]; - NWindows::NCOM::CPropVariant prop; - - if (propID == kpidIsAnti) + NCOM::CPropVariant prop; + switch (propID) { - prop = up.IsAnti; - prop.Detach(value); - return S_OK; + case kpidIsDir: prop = true; break; + case kpidAttrib: if (ParentDirItem) prop = ParentDirItem->Attrib; break; + case kpidCTime: if (ParentDirItem) prop = ParentDirItem->CTime; break; + case kpidATime: if (ParentDirItem) prop = ParentDirItem->ATime; break; + case kpidMTime: if (ParentDirItem) prop = ParentDirItem->MTime; break; } + prop.Detach(value); + return S_OK; +} - if (up.IsAnti) +STDMETHODIMP CArchiveUpdateCallback::GetParent(UInt32 /* index */, UInt32 *parent, UInt32 *parentType) +{ + *parentType = NParentType::kDir; + *parent = (UInt32)(Int32)-1; + return S_OK; +} + +STDMETHODIMP CArchiveUpdateCallback::GetNumRawProps(UInt32 *numProps) +{ + *numProps = 0; + if (StoreNtSecurity) + *numProps = 1; + return S_OK; +} + +STDMETHODIMP CArchiveUpdateCallback::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID) +{ + *name = NULL; + *propID = kpidNtSecure; + return S_OK; +} + +STDMETHODIMP CArchiveUpdateCallback::GetRootRawProp(PROPID + #ifdef _USE_SECURITY_CODE + propID + #endif + , const void **data, UInt32 *dataSize, UInt32 *propType) +{ + *data = 0; + *dataSize = 0; + *propType = 0; + if (!StoreNtSecurity) + return S_OK; + #ifdef _USE_SECURITY_CODE + if (propID == kpidNtSecure) { - switch(propID) + if (StdInMode) + return S_OK; + + if (ParentDirItem) { - case kpidIsDir: - case kpidPath: - break; - case kpidSize: - prop = (UInt64)0; - prop.Detach(value); + if (ParentDirItem->SecureIndex < 0) return S_OK; - default: - prop.Detach(value); + const CByteBuffer &buf = DirItems->SecureBlocks.Bufs[ParentDirItem->SecureIndex]; + *data = buf; + *dataSize = (UInt32)buf.Size(); + *propType = NPropDataType::kRaw; + return S_OK; + } + + if (GetRootProps) + return GetRootProps->GetRootRawProp(propID, data, dataSize, propType); + } + #endif + return S_OK; +} + +// #ifdef _USE_SECURITY_CODE +// #endif + +STDMETHODIMP CArchiveUpdateCallback::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) +{ + *data = 0; + *dataSize = 0; + *propType = 0; + + if (propID == kpidNtSecure || + propID == kpidNtReparse) + { + if (StdInMode) + return S_OK; + + const CUpdatePair2 &up = (*UpdatePairs)[index]; + if (up.UseArcProps && up.ExistInArchive() && GetRawProps) + return GetRawProps->GetRawProp( + ArcItems ? (*ArcItems)[up.ArcIndex].IndexInServer : up.ArcIndex, + propID, data, dataSize, propType); + + { + const CUpdatePair2 &up = (*UpdatePairs)[index]; + /* + if (!up.NewData) + return E_FAIL; + */ + if (up.IsAnti) return S_OK; + + #ifndef UNDER_CE + const CDirItem &di = DirItems->Items[up.DirIndex]; + #endif + + #ifdef _USE_SECURITY_CODE + if (propID == kpidNtSecure) + { + if (!StoreNtSecurity) + return S_OK; + if (di.SecureIndex < 0) + return S_OK; + const CByteBuffer &buf = DirItems->SecureBlocks.Bufs[di.SecureIndex]; + *data = buf; + *dataSize = (UInt32)buf.Size(); + *propType = NPropDataType::kRaw; + } + else + #endif + { + // propID == kpidNtReparse + if (!StoreSymLinks) + return S_OK; + #ifndef UNDER_CE + const CByteBuffer *buf = &di.ReparseData2; + if (buf->Size() == 0) + buf = &di.ReparseData; + if (buf->Size() != 0) + { + *data = *buf; + *dataSize = (UInt32)buf->Size(); + *propType = NPropDataType::kRaw; + } + #endif + } + + return S_OK; } } + + return S_OK; +} + +#ifndef UNDER_CE + +static UString GetRelativePath(const UString &to, const UString &from) +{ + UStringVector partsTo, partsFrom; + SplitPathToParts(to, partsTo); + SplitPathToParts(from, partsFrom); + + unsigned i; + for (i = 0;; i++) + { + if (i + 1 >= partsFrom.Size() || + i + 1 >= partsTo.Size()) + break; + if (CompareFileNames(partsFrom[i], partsTo[i]) != 0) + break; + } + + if (i == 0) + { + #ifdef _WIN32 + if (NName::IsDrivePath(to) || + NName::IsDrivePath(from)) + return to; + #endif + } + + UString s; + unsigned k; + + for (k = i + 1; k < partsFrom.Size(); k++) + s += L".." WSTRING_PATH_SEPARATOR; - if (up.ExistOnDisk()) + for (k = i; k < partsTo.Size(); k++) { - const CDirItem &di = DirItems->Items[up.DirIndex]; - switch(propID) + if (k != i) + s += WCHAR_PATH_SEPARATOR; + s += partsTo[k]; + } + + return s; +} + +#endif + +STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + const CUpdatePair2 &up = (*UpdatePairs)[index]; + NCOM::CPropVariant prop; + + if (up.NewData) + { + /* + if (propID == kpidIsHardLink) + { + prop = _isHardLink; + prop.Detach(value); + return S_OK; + } + */ + if (propID == kpidSymLink) { - case kpidPath: + if (index == _hardIndex_From) + { + prop.Detach(value); + return S_OK; + } + if (up.DirIndex >= 0) + { + #ifndef UNDER_CE + const CDirItem &di = DirItems->Items[up.DirIndex]; + // if (di.IsDir()) { - if (KeepOriginalItemNames) + di.ReparseData; + CReparseAttr attr; + if (attr.Parse(di.ReparseData, di.ReparseData.Size())) { - if (up.ExistInArchive() && Archive) + UString simpleName = attr.GetPath(); + if (attr.IsRelative()) + prop = simpleName; + else { - UInt32 indexInArchive; - if (ArcItems == 0) - indexInArchive = up.ArcIndex; - else - indexInArchive = (*ArcItems)[up.ArcIndex].IndexInServer; - return Archive->GetProperty(indexInArchive, propID, value); + const UString phyPath = DirItems->GetPhyPath(up.DirIndex); + FString fullPath; + if (NDir::MyGetFullPathName(us2fs(phyPath), fullPath)) + { + prop = GetRelativePath(simpleName, fs2us(fullPath)); + } } + prop.Detach(value); + return S_OK; } - 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; + #endif + } } - } - else - { - if (propID == kpidPath) + else if (propID == kpidHardLink) { - if (up.NewNameIndex >= 0) + if (index == _hardIndex_From) + { + const CKeyKeyValPair &pair = _map[_hardIndex_To]; + const CUpdatePair2 &up2 = (*UpdatePairs)[pair.Value]; + prop = DirItems->GetLogPath(up2.DirIndex); + prop.Detach(value); + return S_OK; + } + if (up.DirIndex >= 0) { - prop = (*NewNames)[up.NewNameIndex]; prop.Detach(value); return S_OK; } } - if (up.ExistInArchive() && Archive) + } + + if (up.IsAnti + && propID != kpidIsDir + && propID != kpidPath + && propID != kpidIsAltStream) + { + switch (propID) { - UInt32 indexInArchive; - if (ArcItems == 0) - indexInArchive = up.ArcIndex; - else - indexInArchive = (*ArcItems)[up.ArcIndex].IndexInServer; - return Archive->GetProperty(indexInArchive, propID, value); + case kpidSize: prop = (UInt64)0; break; + case kpidIsAnti: prop = true; break; + } + } + else if (propID == kpidPath && up.NewNameIndex >= 0) + prop = (*NewNames)[up.NewNameIndex]; + else if (propID == kpidShortName && up.NewNameIndex >= 0 && up.IsMainRenameItem) + { + // we can generate new ShortName here; + } + else if ((up.UseArcProps + || (KeepOriginalItemNames && (propID == kpidPath || propID == kpidIsAltStream))) + && up.ExistInArchive() && Archive) + return Archive->GetProperty(ArcItems ? (*ArcItems)[up.ArcIndex].IndexInServer : up.ArcIndex, propID, value); + else if (up.ExistOnDisk()) + { + const CDirItem &di = DirItems->Items[up.DirIndex]; + switch (propID) + { + case kpidPath: prop = DirItems->GetLogPath(up.DirIndex); break; + case kpidIsDir: prop = di.IsDir(); break; + case kpidSize: prop = di.Size; break; + case kpidAttrib: prop = di.Attrib; break; + case kpidCTime: prop = di.CTime; break; + case kpidATime: prop = di.ATime; break; + case kpidMTime: prop = di.MTime; break; + case kpidIsAltStream: prop = di.IsAltStream; break; + #if defined(_WIN32) && !defined(UNDER_CE) + // case kpidShortName: prop = di.ShortName; break; + #endif } } prop.Detach(value); @@ -171,9 +413,12 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR COM_TRY_END } +static NSynchronization::CCriticalSection CS; + STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) { COM_TRY_BEGIN + *inStream = NULL; const CUpdatePair2 &up = (*UpdatePairs)[index]; if (!up.NewData) return E_FAIL; @@ -181,14 +426,33 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream RINOK(Callback->CheckBreak()); RINOK(Callback->Finilize()); + bool isDir = IsDir(up); + if (up.IsAnti) { - return Callback->GetStream((*ArcItems)[up.ArcIndex].Name, true); + UString name; + if (up.ArcIndex >= 0) + name = (*ArcItems)[up.ArcIndex].Name; + else if (up.DirIndex >= 0) + name = DirItems->GetLogPath(up.DirIndex); + RINOK(Callback->GetStream(name, true)); + + /* 9.33: fixed. Handlers expect real stream object for files, even for anti-file. + so we return empty stream */ + + if (!isDir) + { + CBufInStream *inStreamSpec = new CBufInStream(); + CMyComPtr inStreamLoc = inStreamSpec; + inStreamSpec->Init(NULL, 0); + *inStream = inStreamLoc.Detach(); + } + return S_OK; } - const CDirItem &di = DirItems->Items[up.DirIndex]; + RINOK(Callback->GetStream(DirItems->GetLogPath(up.DirIndex), false)); - if (di.IsDir()) + if (isDir) return S_OK; if (StdInMode) @@ -201,13 +465,59 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr inStreamLoc(inStreamSpec); + + inStreamSpec->SupportHardLinks = StoreHardLinks; + const UString path = DirItems->GetPhyPath(up.DirIndex); + + #if defined(_WIN32) && !defined(UNDER_CE) + if (DirItems->Items[up.DirIndex].AreReparseData()) + { + if (!inStreamSpec->File.OpenReparse(us2fs(path))) + { + return Callback->OpenFileError(path, ::GetLastError()); + } + } + else + #endif if (!inStreamSpec->OpenShared(us2fs(path), ShareForWrite)) { return Callback->OpenFileError(path, ::GetLastError()); } + + if (StoreHardLinks) + { + CStreamFileProps props; + if (inStreamSpec->GetProps2(&props) == S_OK) + { + if (props.NumLinks > 1) + { + CKeyKeyValPair pair; + pair.Key1 = props.VolID; + pair.Key2 = props.FileID_Low; + pair.Value = index; + unsigned numItems = _map.Size(); + unsigned pairIndex = _map.AddToUniqueSorted2(pair); + if (numItems == _map.Size()) + { + // const CKeyKeyValPair &pair2 = _map.Pairs[pairIndex]; + _hardIndex_From = index; + _hardIndex_To = pairIndex; + // we could return NULL as stream, but it's better to return real stream + // return S_OK; + } + } + } + } + + if (ProcessedItemsStatuses) + { + NSynchronization::CCriticalSectionLock lock(CS); + ProcessedItemsStatuses[up.DirIndex] = 1; + } *inStream = inStreamLoc.Detach(); } + return S_OK; COM_TRY_END } @@ -235,8 +545,8 @@ STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOu FChar temp[16]; ConvertUInt32ToString(index + 1, temp); FString res = temp; - while (res.Length() < 2) - res = FString(FTEXT('0')) + res; + while (res.Len() < 2) + res.InsertAtFront(FTEXT('0')); FString fileName = VolName; fileName += L'.'; fileName += res; diff --git a/CPP/7zip/UI/Common/UpdateCallback.h b/CPP/7zip/UI/Common/UpdateCallback.h old mode 100755 new mode 100644 index 09f1c0d3..3372e628 --- a/CPP/7zip/UI/Common/UpdateCallback.h +++ b/CPP/7zip/UI/Common/UpdateCallback.h @@ -1,10 +1,9 @@ // UpdateCallback.h -#ifndef __UPDATECALLBACK_H -#define __UPDATECALLBACK_H +#ifndef __UPDATE_CALLBACK_H +#define __UPDATE_CALLBACK_H -#include "Common/MyCom.h" -#include "Common/MyString.h" +#include "../../../Common/MyCom.h" #include "../../IPassword.h" #include "../../ICoder.h" @@ -32,16 +31,43 @@ struct IUpdateCallbackUI INTERFACE_IUpdateCallbackUI(=0) }; +struct CKeyKeyValPair +{ + UInt64 Key1; + UInt64 Key2; + unsigned Value; + + int Compare(const CKeyKeyValPair &a) const + { + if (Key1 < a.Key1) return -1; + if (Key1 > a.Key1) return 1; + return MyCompare(Key2, a.Key2); + } +}; + + class CArchiveUpdateCallback: public IArchiveUpdateCallback2, + public IArchiveGetRawProps, + public IArchiveGetRootProps, public ICryptoGetTextPassword2, public ICryptoGetTextPassword, public ICompressProgressInfo, public CMyUnknownImp { + #if defined(_WIN32) && !defined(UNDER_CE) + bool _saclEnabled; + #endif + CRecordVector _map; + + UInt32 _hardIndex_From; + UInt32 _hardIndex_To; + public: - MY_UNKNOWN_IMP4( + MY_UNKNOWN_IMP6( IArchiveUpdateCallback2, + IArchiveGetRawProps, + IArchiveGetRootProps, ICryptoGetTextPassword2, ICryptoGetTextPassword, ICompressProgressInfo) @@ -49,11 +75,12 @@ public: STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); INTERFACE_IArchiveUpdateCallback2(;) + INTERFACE_IArchiveGetRawProps(;) + INTERFACE_IArchiveGetRootProps(;) STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); STDMETHOD(CryptoGetTextPassword)(BSTR *password); -public: CRecordVector VolumesSizes; FString VolName; FString VolExt; @@ -62,14 +89,34 @@ public: bool ShareForWrite; bool StdInMode; + const CDirItems *DirItems; + const CDirItem *ParentDirItem; + const CObjectVector *ArcItems; const CRecordVector *UpdatePairs; const UStringVector *NewNames; CMyComPtr Archive; + CMyComPtr GetRawProps; + CMyComPtr GetRootProps; + bool KeepOriginalItemNames; + bool StoreNtSecurity; + bool StoreHardLinks; + bool StoreSymLinks; + + Byte *ProcessedItemsStatuses; CArchiveUpdateCallback(); + + bool IsDir(const CUpdatePair2 &up) const + { + if (up.DirIndex >= 0) + return DirItems->Items[up.DirIndex].IsDir(); + else if (up.ArcIndex >= 0) + return (*ArcItems)[up.ArcIndex].IsDir; + return false; + } }; #endif diff --git a/CPP/7zip/UI/Common/UpdatePair.cpp b/CPP/7zip/UI/Common/UpdatePair.cpp old mode 100755 new mode 100644 index a43a9e77..aad4a402 --- a/CPP/7zip/UI/Common/UpdatePair.cpp +++ b/CPP/7zip/UI/Common/UpdatePair.cpp @@ -4,10 +4,9 @@ #include -#include "Common/Defs.h" -#include "Common/Wildcard.h" +#include "../../../Common/Wildcard.h" -#include "Windows/Time.h" +#include "../../../Windows/TimeUtils.h" #include "SortUtils.h" #include "UpdatePair.h" @@ -17,7 +16,7 @@ using namespace NTime; static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time1, const FILETIME &time2) { - switch(fileTimeType) + switch (fileTimeType) { case NFileTimeType::kWindows: return ::CompareFileTime(&time1, &time2); @@ -39,24 +38,38 @@ static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time 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 const char *k_Duplicate_inArc_Message = "Duplicate filename in archive:"; +static const char *k_Duplicate_inDir_Message = "Duplicate filename on disk:"; +static const char *k_NotCensoredCollision_Message = "Internal file name collision (file on disk, file in archive):"; -static void ThrowError(const UString &message, const UString &s1, const UString &s2) +static void ThrowError(const char *message, const UString &s1, const UString &s2) { - UString m = message; - m += L'\n'; - m += s1; - m += L'\n'; - m += s2; + UString m; + m.SetFromAscii(message); + m += L'\n'; m += s1; + m += L'\n'; m += s2; throw m; } -static void TestDuplicateString(const UStringVector &strings, const CIntVector &indices) +static int CompareArcItemsBase(const CArcItem &ai1, const CArcItem &ai2) { - 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]]); + int res = CompareFileNames(ai1.Name, ai2.Name); + if (res != 0) + return res; + if (ai1.IsDir != ai2.IsDir) + return ai1.IsDir ? -1 : 1; + return 0; +} + +static int CompareArcItems(const unsigned *p1, const unsigned *p2, void *param) +{ + unsigned i1 = *p1; + unsigned i2 = *p2; + const CObjectVector &arcItems = *(const CObjectVector *)param; + int res = CompareArcItemsBase(arcItems[i1], arcItems[i2]); + if (res != 0) + return res; + return MyCompare(i1, i2); } void GetUpdatePairInfoList( @@ -65,48 +78,103 @@ void GetUpdatePairInfoList( NFileTimeType::EEnum fileTimeType, CRecordVector &updatePairs) { - CIntVector dirIndices, arcIndices; - - int numDirItems = dirItems.Items.Size(); - int numArcItems = arcItems.Size(); + CUIntVector dirIndices, arcIndices; + unsigned numDirItems = dirItems.Items.Size(); + unsigned numArcItems = arcItems.Size(); + CIntArr duplicatedArcItem(numArcItems); { - UStringVector arcNames; - arcNames.Reserve(numArcItems); - for (int i = 0; i < numArcItems; i++) - arcNames.Add(arcItems[i].Name); - SortFileNames(arcNames, arcIndices); - TestDuplicateString(arcNames, arcIndices); + int *vals = &duplicatedArcItem[0]; + for (unsigned i = 0; i < numArcItems; i++) + vals[i] = 0; + } + + { + arcIndices.ClearAndSetSize(numArcItems); + { + unsigned *vals = &arcIndices[0]; + for (unsigned i = 0; i < numArcItems; i++) + vals[i] = i; + } + arcIndices.Sort(CompareArcItems, (void *)&arcItems); + for (unsigned i = 0; i + 1 < numArcItems; i++) + if (CompareArcItemsBase( + arcItems[arcIndices[i]], + arcItems[arcIndices[i + 1]]) == 0) + { + duplicatedArcItem[i] = 1; + duplicatedArcItem[i + 1] = -1; + } } UStringVector dirNames; { - dirNames.Reserve(numDirItems); - for (int i = 0; i < numDirItems; i++) - dirNames.Add(dirItems.GetLogPath(i)); + dirNames.ClearAndReserve(numDirItems); + unsigned i; + for (i = 0; i < numDirItems; i++) + dirNames.AddInReserved(dirItems.GetLogPath(i)); SortFileNames(dirNames, dirIndices); - TestDuplicateString(dirNames, dirIndices); + for (i = 0; i + 1 < numDirItems; i++) + { + const UString &s1 = dirNames[dirIndices[i]]; + const UString &s2 = dirNames[dirIndices[i + 1]]; + if (CompareFileNames(s1, s2) == 0) + ThrowError(k_Duplicate_inDir_Message, s1, s2); + } } - int dirIndex = 0, arcIndex = 0; - while (dirIndex < numDirItems && arcIndex < numArcItems) + unsigned dirIndex = 0; + unsigned arcIndex = 0; + + int prevHostFile = -1; + const UString *prevHostName = NULL; + + 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); + + int dirIndex2 = -1; + int arcIndex2 = -1; + const CDirItem *di = NULL; + const CArcItem *ai = NULL; + + int compareResult = -1; + const UString *name = NULL; + + if (dirIndex < numDirItems) + { + dirIndex2 = dirIndices[dirIndex]; + di = &dirItems.Items[dirIndex2]; + } + + if (arcIndex < numArcItems) + { + arcIndex2 = arcIndices[arcIndex]; + ai = &arcItems[arcIndex2]; + compareResult = 1; + if (dirIndex < numDirItems) + { + compareResult = CompareFileNames(dirNames[dirIndex2], ai->Name); + if (compareResult == 0) + { + if (di->IsDir() != ai->IsDir) + compareResult = (ai->IsDir ? 1 : -1); + } + } + } + if (compareResult < 0) { + name = &dirNames[dirIndex2]; pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; pair.DirIndex = dirIndex2; dirIndex++; } else if (compareResult > 0) { - pair.State = ai.Censored ? + name = &ai->Name; + pair.State = ai->Censored ? NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked; pair.ArcIndex = arcIndex2; @@ -114,43 +182,50 @@ void GetUpdatePairInfoList( } else { - if (!ai.Censored) - ThrowError(kNotCensoredCollisionMessaged, dirNames[dirIndex2], ai.Name); + int dupl = duplicatedArcItem[arcIndex]; + if (dupl != 0) + ThrowError(k_Duplicate_inArc_Message, ai->Name, arcItems[arcIndices[arcIndex + dupl]].Name); + + name = &dirNames[dirIndex2]; + if (!ai->Censored) + ThrowError(k_NotCensoredCollision_Message, *name, ai->Name); + pair.DirIndex = dirIndex2; pair.ArcIndex = arcIndex2; - switch (ai.MTimeDefined ? MyCompareTime( - ai.TimeType != - 1 ? (NFileTimeType::EEnum)ai.TimeType : fileTimeType, - di.MTime, ai.MTime): 0) + + 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; + case 1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break; default: - pair.State = (ai.SizeDefined && di.Size == ai.Size) ? + 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; + + if ((di && di->IsAltStream) || + (ai && ai->IsAltStream)) + { + if (prevHostName) + { + unsigned hostLen = prevHostName->Len(); + if (name->Len() > hostLen) + if ((*name)[hostLen] == ':' && CompareFileNames(*prevHostName, name->Left(hostLen)) == 0) + pair.HostIndex = prevHostFile; + } + } + else + { + prevHostFile = updatePairs.Size(); + prevHostName = name; + } + updatePairs.Add(pair); } diff --git a/CPP/7zip/UI/Common/UpdatePair.h b/CPP/7zip/UI/Common/UpdatePair.h old mode 100755 new mode 100644 index 3a332649..296d3b09 --- a/CPP/7zip/UI/Common/UpdatePair.h +++ b/CPP/7zip/UI/Common/UpdatePair.h @@ -13,7 +13,9 @@ struct CUpdatePair NUpdateArchive::NPairState::EEnum State; int ArcIndex; int DirIndex; - CUpdatePair(): ArcIndex(-1), DirIndex(-1) {} + int HostIndex; // >= 0 for alt streams only, contains index of host pair + + CUpdatePair(): ArcIndex(-1), DirIndex(-1), HostIndex(-1) {} }; void GetUpdatePairInfoList( diff --git a/CPP/7zip/UI/Common/UpdateProduce.cpp b/CPP/7zip/UI/Common/UpdateProduce.cpp old mode 100755 new mode 100644 index c21db3b2..3089d73c --- a/CPP/7zip/UI/Common/UpdateProduce.cpp +++ b/CPP/7zip/UI/Common/UpdateProduce.cpp @@ -14,17 +14,17 @@ void UpdateProduce( CRecordVector &operationChain, IUpdateProduceCallback *callback) { - for (int i = 0; i < updatePairs.Size(); i++) + FOR_VECTOR (i, updatePairs) { const CUpdatePair &pair = updatePairs[i]; CUpdatePair2 up2; - up2.IsAnti = false; up2.DirIndex = pair.DirIndex; up2.ArcIndex = pair.ArcIndex; up2.NewData = up2.NewProps = true; + up2.UseArcProps = false; - switch(actionSet.StateActions[pair.State]) + switch (actionSet.StateActions[pair.State]) { case NPairAction::kIgnore: /* @@ -39,7 +39,21 @@ void UpdateProduce( case NPairAction::kCopy: if (pair.State == NPairState::kOnlyOnDisk) throw kUpdateActionSetCollision; + if (pair.State == NPairState::kOnlyInArchive) + { + if (pair.HostIndex >= 0) + { + /* + ignore alt stream if + 1) no such alt stream in Disk + 2) there is Host file in disk + */ + if (updatePairs[pair.HostIndex].DirIndex >= 0) + continue; + } + } up2.NewData = up2.NewProps = false; + up2.UseArcProps = true; break; case NPairAction::kCompress: @@ -50,6 +64,7 @@ void UpdateProduce( case NPairAction::kCompressAsAnti: up2.IsAnti = true; + up2.UseArcProps = (pair.ArcIndex >= 0); break; } operationChain.Add(up2); diff --git a/CPP/7zip/UI/Common/UpdateProduce.h b/CPP/7zip/UI/Common/UpdateProduce.h old mode 100755 new mode 100644 index e18648cd..b919965d --- a/CPP/7zip/UI/Common/UpdateProduce.h +++ b/CPP/7zip/UI/Common/UpdateProduce.h @@ -9,16 +9,27 @@ struct CUpdatePair2 { bool NewData; bool NewProps; - bool IsAnti; + bool UseArcProps; // if (UseArcProps && NewProps), we want to change only some properties. + bool IsAnti; // if (!IsAnti) we use other ways to detect Anti status int DirIndex; int ArcIndex; int NewNameIndex; + bool IsMainRenameItem; + + void SetAs_NoChangeArcItem(int arcIndex) + { + NewData = NewProps = false; + UseArcProps = true; + IsAnti = false; + ArcIndex = arcIndex; + } + bool ExistOnDisk() const { return DirIndex != -1; } bool ExistInArchive() const { return ArcIndex != -1; } - CUpdatePair2(): IsAnti(false), DirIndex(-1), ArcIndex(-1), NewNameIndex(-1) {} + CUpdatePair2(): IsAnti(false), UseArcProps(false), DirIndex(-1), ArcIndex(-1), NewNameIndex(-1) {} }; struct IUpdateProduceCallback diff --git a/CPP/7zip/UI/Common/WorkDir.cpp b/CPP/7zip/UI/Common/WorkDir.cpp old mode 100755 new mode 100644 index 1ecb5b54..9ad617f7 --- a/CPP/7zip/UI/Common/WorkDir.cpp +++ b/CPP/7zip/UI/Common/WorkDir.cpp @@ -2,16 +2,16 @@ #include "StdAfx.h" -#include "Common/StringConvert.h" -#include "Common/Wildcard.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/Wildcard.h" -#include "Windows/FileName.h" +#include "../../../Windows/FileName.h" #include "WorkDir.h" using namespace NWindows; using namespace NFile; -using namespace NDirectory; +using namespace NDir; FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FString &fileName) { @@ -37,7 +37,7 @@ FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FStr } #endif int pos = path.ReverseFind(FCHAR_PATH_SEPARATOR) + 1; - fileName = path.Mid(pos); + fileName = path.Ptr(pos); switch (mode) { case NWorkDir::NMode::kCurrent: @@ -66,7 +66,7 @@ HRESULT CWorkDirTempFile::CreateTempFile(const FString &originalPath) workDirInfo.Load(); FString namePart; FString workDir = GetWorkDir(workDirInfo, originalPath, namePart); - CreateComplexDirectory(workDir); + CreateComplexDir(workDir); CTempFile tempFile; _outStreamSpec = new COutFileStream; OutStream = _outStreamSpec; diff --git a/CPP/7zip/UI/Common/WorkDir.h b/CPP/7zip/UI/Common/WorkDir.h old mode 100755 new mode 100644 index 79ea2b9d..75850a92 --- a/CPP/7zip/UI/Common/WorkDir.h +++ b/CPP/7zip/UI/Common/WorkDir.h @@ -3,18 +3,18 @@ #ifndef __WORK_DIR_H #define __WORK_DIR_H -#include "Windows/FileDir.h" - -#include "ZipRegistry.h" +#include "../../../Windows/FileDir.h" #include "../../Common/FileStreams.h" +#include "ZipRegistry.h" + FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FString &fileName); class CWorkDirTempFile { FString _originalPath; - NWindows::NFile::NDirectory::CTempFile _tempFile; + NWindows::NFile::NDir::CTempFile _tempFile; COutFileStream *_outStreamSpec; public: CMyComPtr OutStream; diff --git a/CPP/7zip/UI/Common/ZipRegistry.cpp b/CPP/7zip/UI/Common/ZipRegistry.cpp old mode 100755 new mode 100644 index d2aec4c6..4c48bd70 --- a/CPP/7zip/UI/Common/ZipRegistry.cpp +++ b/CPP/7zip/UI/Common/ZipRegistry.cpp @@ -2,11 +2,11 @@ #include "StdAfx.h" -#include "Common/IntToString.h" +#include "../../../Common/IntToString.h" -#include "Windows/FileDir.h" -#include "Windows/Registry.h" -#include "Windows/Synchronization.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/Registry.h" +#include "../../../Windows/Synchronization.h" #include "ZipRegistry.h" @@ -30,6 +30,18 @@ static LONG CreateMainKey(CKey &key, LPCTSTR keyName) return key.Create(HKEY_CURRENT_USER, GetKeyPath(keyName)); } +static void Key_Set_BoolPair(CKey &key, LPCTSTR name, const CBoolPair &b) +{ + if (b.Def) + key.SetValue(name, b.Val); +} + +static void Key_Get_BoolPair(CKey &key, LPCTSTR name, CBoolPair &b) +{ + b.Val = false; + b.Def = (key.GetValue_IfOk(name, b.Val) == ERROR_SUCCESS); +} + namespace NExtract { @@ -39,15 +51,28 @@ static const TCHAR *kExtractMode = TEXT("ExtractMode"); static const TCHAR *kOverwriteMode = TEXT("OverwriteMode"); static const TCHAR *kShowPassword = TEXT("ShowPassword"); static const TCHAR *kPathHistory = TEXT("PathHistory"); +static const TCHAR *kSplitDest = TEXT("SplitDest"); +static const TCHAR *kElimDup = TEXT("ElimDup"); +// static const TCHAR *kAltStreams = TEXT("AltStreams"); +static const TCHAR *kNtSecur = TEXT("Security"); 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); + + if (PathMode_Force) + key.SetValue(kExtractMode, (UInt32)PathMode); + if (OverwriteMode_Force) + key.SetValue(kOverwriteMode, (UInt32)OverwriteMode); + + Key_Set_BoolPair(key, kSplitDest, SplitDest); + Key_Set_BoolPair(key, kElimDup, ElimDup); + // Key_Set_BoolPair(key, kAltStreams, AltStreams); + Key_Set_BoolPair(key, kNtSecur, NtSecurity); + Key_Set_BoolPair(key, kShowPassword, ShowPassword); + key.RecurseDeleteKey(kPathHistory); key.SetValue_Strings(kPathHistory, Paths); } @@ -62,9 +87,11 @@ void Save_ShowPassword(bool showPassword) void CInfo::Load() { - PathMode = NPathMode::kCurrentPathnames; - OverwriteMode = NOverwriteMode::kAskBefore; - ShowPassword = false; + PathMode = NPathMode::kCurPaths; + PathMode_Force = false; + OverwriteMode = NOverwriteMode::kAsk; + OverwriteMode_Force = false; + Paths.Clear(); CS_LOCK @@ -74,11 +101,24 @@ void CInfo::Load() key.GetValue_Strings(kPathHistory, Paths); UInt32 v; - if (key.QueryValue(kExtractMode, v) == ERROR_SUCCESS && v <= NPathMode::kNoPathnames) + if (key.QueryValue(kExtractMode, v) == ERROR_SUCCESS && v <= NPathMode::kAbsPaths) + { PathMode = (NPathMode::EEnum)v; - if (key.QueryValue(kOverwriteMode, v) == ERROR_SUCCESS && v <= NOverwriteMode::kAutoRenameExisting) + PathMode_Force = true; + } + if (key.QueryValue(kOverwriteMode, v) == ERROR_SUCCESS && v <= NOverwriteMode::kRenameExisting) + { OverwriteMode = (NOverwriteMode::EEnum)v; - key.GetValue_IfOk(kShowPassword, ShowPassword); + OverwriteMode_Force = true; + } + + Key_Get_BoolPair(key, kSplitDest, SplitDest); + if (!SplitDest.Def) + SplitDest.Val = true; + Key_Get_BoolPair(key, kElimDup, ElimDup); + // Key_Get_BoolPair(key, kAltStreams, AltStreams); + Key_Get_BoolPair(key, kNtSecur, NtSecurity); + Key_Get_BoolPair(key, kShowPassword, ShowPassword); } bool Read_ShowPassword() @@ -115,6 +155,11 @@ static const WCHAR *kMethod = L"Method"; static const WCHAR *kOptions = L"Options"; static const WCHAR *kEncryptionMethod = L"EncryptionMethod"; +static const TCHAR *kNtSecur = TEXT("Security"); +static const TCHAR *kAltStreams = TEXT("AltStreams"); +static const TCHAR *kHardLinks = TEXT("HardLinks"); +static const TCHAR *kSymLinks = TEXT("SymLinks"); + static void SetRegString(CKey &key, const WCHAR *name, const UString &value) { if (value.IsEmpty()) @@ -125,7 +170,7 @@ static void SetRegString(CKey &key, const WCHAR *name, const UString &value) static void SetRegUInt32(CKey &key, const TCHAR *name, UInt32 value) { - if (value == (UInt32)-1) + if (value == (UInt32)(Int32)-1) key.DeleteValue(name); else key.SetValue(name, value); @@ -140,7 +185,7 @@ static void GetRegString(CKey &key, const WCHAR *name, UString &value) static void GetRegUInt32(CKey &key, const TCHAR *name, UInt32 &value) { if (key.QueryValue(name, value) != ERROR_SUCCESS) - value = (UInt32)-1; + value = (UInt32)(Int32)-1; } void CInfo::Save() const @@ -149,6 +194,13 @@ void CInfo::Save() const CKey key; CreateMainKey(key, kKeyName); + + Key_Set_BoolPair(key, kNtSecur, NtSecurity); + Key_Set_BoolPair(key, kAltStreams, AltStreams); + Key_Set_BoolPair(key, kHardLinks, HardLinks); + Key_Set_BoolPair(key, kSymLinks, SymLinks); + + key.SetValue(kShowPassword, ShowPassword); key.SetValue(kLevel, (UInt32)Level); key.SetValue(kArchiver, ArcType); key.SetValue(kShowPassword, ShowPassword); @@ -160,7 +212,7 @@ void CInfo::Save() const { CKey optionsKey; optionsKey.Create(key, kOptionsKeyName); - for (int i = 0; i < Formats.Size(); i++) + FOR_VECTOR (i, Formats) { const CFormatOptions &fo = Formats[i]; CKey fk; @@ -195,6 +247,11 @@ void CInfo::Load() if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS) return; + Key_Get_BoolPair(key, kNtSecur, NtSecurity); + Key_Get_BoolPair(key, kAltStreams, AltStreams); + Key_Get_BoolPair(key, kHardLinks, HardLinks); + Key_Get_BoolPair(key, kSymLinks, SymLinks); + key.GetValue_Strings(kArcHistory, ArcPaths); { @@ -203,7 +260,7 @@ void CInfo::Load() { CSysStringVector formatIDs; optionsKey.EnumKeys(formatIDs); - for (int i = 0; i < formatIDs.Size(); i++) + FOR_VECTOR (i, formatIDs) { CKey fk; CFormatOptions fo; @@ -290,6 +347,7 @@ void CInfo::Load() static const TCHAR *kCascadedMenu = TEXT("CascadedMenu"); static const TCHAR *kContextMenu = TEXT("ContextMenu"); +static const TCHAR *kMenuIcons = TEXT("MenuIcons"); void CContextMenuInfo::Save() const { @@ -297,17 +355,20 @@ void CContextMenuInfo::Save() const CKey key; CreateMainKey(key, kOptionsInfoKeyName); key.SetValue(kCascadedMenu, Cascaded); + key.SetValue(kMenuIcons, MenuIcons); key.SetValue(kContextMenu, Flags); } void CContextMenuInfo::Load() { + MenuIcons = false; Cascaded = true; - Flags = (UInt32)-1; + Flags = (UInt32)(Int32)-1; CS_LOCK CKey key; if (OpenMainKey(key, kOptionsInfoKeyName) != ERROR_SUCCESS) return; key.GetValue_IfOk(kCascadedMenu, Cascaded); + key.GetValue_IfOk(kMenuIcons, MenuIcons); key.GetValue_IfOk(kContextMenu, Flags); } diff --git a/CPP/7zip/UI/Common/ZipRegistry.h b/CPP/7zip/UI/Common/ZipRegistry.h old mode 100755 new mode 100644 index 6d8b7c13..cd2ea67d --- a/CPP/7zip/UI/Common/ZipRegistry.h +++ b/CPP/7zip/UI/Common/ZipRegistry.h @@ -3,8 +3,8 @@ #ifndef __ZIP_REGISTRY_H #define __ZIP_REGISTRY_H -#include "Common/MyString.h" -#include "Common/Types.h" +#include "../../../Common/MyTypes.h" +#include "../../../Common/MyString.h" #include "ExtractMode.h" @@ -14,12 +14,21 @@ namespace NExtract { NPathMode::EEnum PathMode; NOverwriteMode::EEnum OverwriteMode; - bool ShowPassword; + bool PathMode_Force; + bool OverwriteMode_Force; + + CBoolPair SplitDest; + CBoolPair ElimDup; + // CBoolPair AltStreams; + CBoolPair NtSecurity; + CBoolPair ShowPassword; + UStringVector Paths; void Save() const; void Load(); }; + void Save_ShowPassword(bool showPassword); bool Read_ShowPassword(); } @@ -59,6 +68,11 @@ namespace NCompression CObjectVector Formats; + CBoolPair NtSecurity; + CBoolPair AltStreams; + CBoolPair HardLinks; + CBoolPair SymLinks; + void Save() const; void Load(); }; @@ -98,6 +112,7 @@ namespace NWorkDir struct CContextMenuInfo { bool Cascaded; + bool MenuIcons; UInt32 Flags; void Save() const; diff --git a/CPP/7zip/UI/Console/BenchCon.cpp b/CPP/7zip/UI/Console/BenchCon.cpp old mode 100755 new mode 100644 index d0e43222..596f447b --- a/CPP/7zip/UI/Console/BenchCon.cpp +++ b/CPP/7zip/UI/Console/BenchCon.cpp @@ -32,7 +32,7 @@ HRESULT CPrintBenchCallback::CheckBreak() } HRESULT BenchCon(DECL_EXTERNAL_CODECS_LOC_VARS - const CObjectVector props, UInt32 numIterations, FILE *f) + const CObjectVector &props, UInt32 numIterations, FILE *f) { CPrintBenchCallback callback; callback._file = f; diff --git a/CPP/7zip/UI/Console/BenchCon.h b/CPP/7zip/UI/Console/BenchCon.h old mode 100755 new mode 100644 index 73972186..c9da1de3 --- a/CPP/7zip/UI/Console/BenchCon.h +++ b/CPP/7zip/UI/Console/BenchCon.h @@ -9,6 +9,6 @@ #include "../../UI/Common/Property.h" HRESULT BenchCon(DECL_EXTERNAL_CODECS_LOC_VARS - const CObjectVector props, UInt32 numIterations, FILE *f); + const CObjectVector &props, UInt32 numIterations, FILE *f); #endif diff --git a/CPP/7zip/UI/Console/Console.dsp b/CPP/7zip/UI/Console/Console.dsp old mode 100755 new mode 100644 index 7c1719da..c75f4b6e --- a/CPP/7zip/UI/Console/Console.dsp +++ b/CPP/7zip/UI/Console/Console.dsp @@ -44,7 +44,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /Gz /MD /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 CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /FAs /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe @@ -52,7 +52,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /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 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"C:\UTIL\7z.exe" /OPT:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Console - Win32 Debug" @@ -69,7 +69,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /Gz /MTd /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 CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe @@ -77,7 +77,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"C:\UTIL\7z.exe" /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"C:\UTIL\7z.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "Console - Win32 ReleaseU" @@ -94,7 +94,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /Gz /MD /W3 /GX /O1 /I "../../../" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /c -# ADD CPP /nologo /Gz /MD /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 CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe @@ -102,7 +102,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /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 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"C:\UTIL\7zn.exe" /OPT:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Console - Win32 DebugU" @@ -120,7 +120,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /Gz /W3 /Gm /GX /ZI /Od /I "../../../" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c -# ADD CPP /nologo /Gz /MTd /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 CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe @@ -128,7 +128,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /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 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"C:\UTIL\7z.exe" /pdbtype:sept !ENDIF @@ -184,6 +184,14 @@ SOURCE=.\ExtractCallbackConsole.h # End Source File # Begin Source File +SOURCE=.\HashCon.cpp +# End Source File +# Begin Source File + +SOURCE=.\HashCon.h +# End Source File +# Begin Source File + SOURCE=.\List.cpp # End Source File # Begin Source File @@ -244,11 +252,11 @@ SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Error.cpp +SOURCE=..\..\..\Windows\ErrorMsg.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Error.h +SOURCE=..\..\..\Windows\ErrorMsg.h # End Source File # Begin Source File @@ -276,6 +284,14 @@ SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File +SOURCE=..\..\..\Windows\FileLink.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileMapping.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Windows\FileName.cpp # End Source File # Begin Source File @@ -284,6 +300,14 @@ 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\MemoryLock.cpp # End Source File # Begin Source File @@ -304,11 +328,11 @@ SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\PropVariantConversions.cpp +SOURCE=..\..\..\Windows\PropVariantConv.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\PropVariantConversions.h +SOURCE=..\..\..\Windows\PropVariantConv.h # End Source File # Begin Source File @@ -320,6 +344,10 @@ SOURCE=..\..\..\Windows\Registry.h # 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 @@ -328,11 +356,15 @@ SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Time.cpp +SOURCE=..\..\..\Windows\Thread.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\TimeUtils.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Time.h +SOURCE=..\..\..\Windows\TimeUtils.h # End Source File # End Group # Begin Group "Common" @@ -340,10 +372,6 @@ SOURCE=..\..\..\Windows\Time.h # 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 @@ -380,6 +408,10 @@ SOURCE=..\..\..\Common\ListFileUtils.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\MyBuffer.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File @@ -392,6 +424,10 @@ SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\MyTypes.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File @@ -532,6 +568,18 @@ SOURCE=..\Common\ExtractingFilePath.h # End Source File # Begin Source File +SOURCE=..\Common\ExtractMode.h +# End Source File +# Begin Source File + +SOURCE=..\Common\HashCalc.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\HashCalc.h +# End Source File +# Begin Source File + SOURCE=..\Common\IFileExtractCallback.h # End Source File # Begin Source File @@ -668,6 +716,14 @@ SOURCE=..\..\Common\FilterCoder.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\MethodProps.cpp # End Source File # Begin Source File @@ -684,16 +740,36 @@ SOURCE=..\..\Common\ProgressUtils.h # End Source File # Begin Source File +SOURCE=..\..\Common\PropId.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Common\RegisterArc.h # End Source File # Begin Source File +SOURCE=..\..\Common\StreamObjects.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamObjects.h +# End Source File +# Begin Source File + SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\UniqBlocks.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\UniqBlocks.h +# End Source File # End Group # Begin Group "Compress" @@ -740,6 +816,10 @@ SOURCE=..\..\..\..\C\7zCrc.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\7zTypes.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File @@ -758,6 +838,15 @@ SOURCE=..\..\..\..\C\CpuArch.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 @@ -839,6 +928,38 @@ InputName=7zCrcOpt !ENDIF +# End Source File +# End Group +# Begin Group "Interface" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\IArchive.h +# End Source File +# 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 # End Target diff --git a/CPP/7zip/UI/Console/Console.dsw b/CPP/7zip/UI/Console/Console.dsw old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/Console/Console.mak b/CPP/7zip/UI/Console/Console.mak new file mode 100644 index 00000000..29b6a854 --- /dev/null +++ b/CPP/7zip/UI/Console/Console.mak @@ -0,0 +1,35 @@ +CONSOLE_OBJS = \ + $O\BenchCon.obj \ + $O\ConsoleClose.obj \ + $O\ExtractCallbackConsole.obj \ + $O\HashCon.obj \ + $O\List.obj \ + $O\Main.obj \ + $O\MainAr.obj \ + $O\OpenCallbackConsole.obj \ + $O\PercentPrinter.obj \ + $O\UpdateCallbackConsole.obj \ + $O\UserInputUtils.obj \ + +UI_COMMON_OBJS = \ + $O\ArchiveCommandLine.obj \ + $O\ArchiveExtractCallback.obj \ + $O\ArchiveOpenCallback.obj \ + $O\Bench.obj \ + $O\DefaultName.obj \ + $O\EnumDirItems.obj \ + $O\Extract.obj \ + $O\ExtractingFilePath.obj \ + $O\HashCalc.obj \ + $O\LoadCodecs.obj \ + $O\OpenArchive.obj \ + $O\PropIDUtils.obj \ + $O\SetProperties.obj \ + $O\SortUtils.obj \ + $O\TempFiles.obj \ + $O\Update.obj \ + $O\UpdateAction.obj \ + $O\UpdateCallback.obj \ + $O\UpdatePair.obj \ + $O\UpdateProduce.obj \ + diff --git a/CPP/7zip/UI/Console/ConsoleClose.cpp b/CPP/7zip/UI/Console/ConsoleClose.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/Console/ConsoleClose.h b/CPP/7zip/UI/Console/ConsoleClose.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp old mode 100755 new mode 100644 index af379861..d3366a39 --- a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp +++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp @@ -1,20 +1,21 @@ -// ExtractCallbackConsole.h +// ExtractCallbackConsole.cpp #include "StdAfx.h" +// #undef sprintf + +#include "ConsoleClose.h" #include "ExtractCallbackConsole.h" #include "UserInputUtils.h" -#include "ConsoleClose.h" -#include "Common/Wildcard.h" +#include "../../../Common/IntToString.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 "../../../Windows/FileDir.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/TimeUtils.h" +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/PropVariantConv.h" #include "../../Common/FilePathAutoRename.h" @@ -22,11 +23,11 @@ using namespace NWindows; using namespace NFile; -using namespace NDirectory; +using namespace NDir; static const char *kTestString = "Testing "; static const char *kExtractString = "Extracting "; -static const char *kSkipString = "Skipping "; +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"; @@ -43,7 +44,27 @@ 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"; +static const char *kUnavailableData = "Unavailable data"; +static const char *kUnexpectedEnd = "Unexpected end of data"; +static const char *kDataAfterEnd = "There are some data after the end of the payload data"; +static const char *kIsNotArc = "Is not archive"; +static const char *kHeadersError = "Headers Error"; + +static const char *k_ErrorFlagsMessages[] = +{ + "Is not archive" + , "Headers Error" + , "Headers Error in encrypted archive. Wrong password?" + , "Unavailable start of archive" + , "Unconfirmed start of archive" + , "Unexpected end of archive" + , "There are data after the end of archive" + , "Unsupported method" + , "Unsupported feature" + , "Data Error" + , "CRC Error" +}; + STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64) { @@ -64,13 +85,13 @@ STDMETHODIMP CExtractCallbackConsole::AskOverwrite( const wchar_t *newName, const FILETIME *, const UInt64 *, Int32 *answer) { - (*OutStream) << "file " << existName << - "\nalready exists. Overwrite with " << endl; - (*OutStream) << newName; + (*OutStream) << "file " << existName << endl << + "already exists. Overwrite with" << endl << + newName; NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(OutStream); - switch(overwriteAnswer) + switch (overwriteAnswer) { case NUserAnswerMode::kQuit: return E_ABORT; case NUserAnswerMode::kNo: *answer = NOverwriteAnswer::kNo; break; @@ -85,13 +106,15 @@ STDMETHODIMP CExtractCallbackConsole::AskOverwrite( STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 askExtractMode, const UInt64 *position) { + const char *s; 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; + case NArchive::NExtract::NAskMode::kExtract: s = kExtractString; break; + case NArchive::NExtract::NAskMode::kTest: s = kTestString; break; + case NArchive::NExtract::NAskMode::kSkip: s = kSkipString; break; + default: s = ""; // return E_FAIL; }; - (*OutStream) << name; + (*OutStream) << s << name; if (position != 0) (*OutStream) << " <" << *position << ">"; return S_OK; @@ -100,35 +123,57 @@ STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, bool STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message) { (*OutStream) << message << endl; - NumFileErrorsInCurrentArchive++; + NumFileErrorsInCurrent++; NumFileErrors++; return S_OK; } STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 operationResult, bool encrypted) { - switch(operationResult) + switch (operationResult) { case NArchive::NExtract::NOperationResult::kOK: break; default: { - NumFileErrorsInCurrentArchive++; + NumFileErrorsInCurrent++; NumFileErrors++; - (*OutStream) << " "; - switch(operationResult) + (*OutStream) << " : "; + const char *s = NULL; + switch (operationResult) { - case NArchive::NExtract::NOperationResult::kUnSupportedMethod: - (*OutStream) << kUnsupportedMethod; + case NArchive::NExtract::NOperationResult::kUnsupportedMethod: + s = kUnsupportedMethod; break; case NArchive::NExtract::NOperationResult::kCRCError: - (*OutStream) << (encrypted ? kCrcFailedEncrypted: kCrcFailed); + s = (encrypted ? kCrcFailedEncrypted : kCrcFailed); break; case NArchive::NExtract::NOperationResult::kDataError: - (*OutStream) << (encrypted ? kDataErrorEncrypted : kDataError); + s = (encrypted ? kDataErrorEncrypted : kDataError); + break; + case NArchive::NExtract::NOperationResult::kUnavailable: + s = kUnavailableData; + break; + case NArchive::NExtract::NOperationResult::kUnexpectedEnd: + s = kUnexpectedEnd; + break; + case NArchive::NExtract::NOperationResult::kDataAfterEnd: + s = kDataAfterEnd; break; - default: - (*OutStream) << kUnknownError; + case NArchive::NExtract::NOperationResult::kIsNotArc: + s = kIsNotArc; + break; + case NArchive::NExtract::NOperationResult::kHeadersError: + s = kHeadersError; + break; + } + if (s) + (*OutStream) << "Error : " << s; + else + { + char temp[16]; + ConvertUInt32ToString(operationResult, temp); + (*OutStream) << "Error #" << temp; } } } @@ -159,8 +204,10 @@ STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password) HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name) { - NumArchives++; - NumFileErrorsInCurrentArchive = 0; + NumTryArcs++; + ThereIsErrorInCurrent = false; + ThereIsWarningInCurrent = false; + NumFileErrorsInCurrent = 0; (*OutStream) << endl << kProcessing << name << endl; return S_OK; } @@ -182,11 +229,93 @@ HRESULT CExtractCallbackConsole::OpenResult(const wchar_t * /* name */, HRESULT if (result == E_OUTOFMEMORY) (*OutStream) << "Can't allocate required memory"; else - (*OutStream) << NError::MyFormatMessageW(result); + (*OutStream) << NError::MyFormatMessage(result); } (*OutStream) << endl; - NumArchiveErrors++; + NumCantOpenArcs++; + ThereIsErrorInCurrent = true; + } + return S_OK; +} + +AString GetOpenArcErrorMessage(UInt32 errorFlags) +{ + AString s; + for (unsigned i = 0; i < ARRAY_SIZE(k_ErrorFlagsMessages); i++) + { + UInt32 f = (1 << i); + if ((errorFlags & f) == 0) + continue; + const char *m = k_ErrorFlagsMessages[i]; + if (!s.IsEmpty()) + s += '\n'; + s += m; + errorFlags &= ~f; + } + if (errorFlags != 0) + { + char sz[16]; + sz[0] = '0'; + sz[1] = 'x'; + ConvertUInt32ToHex(errorFlags, sz + 2); + if (!s.IsEmpty()) + s += '\n'; + s += sz; + } + return s; +} + + +HRESULT CExtractCallbackConsole::SetError(int level, const wchar_t *name, + UInt32 errorFlags, const wchar_t *errors, + UInt32 warningFlags, const wchar_t *warnings) +{ + if (level != 0) + { + (*OutStream) << name << endl; + } + + if (errorFlags != 0) + { + (*OutStream) << "Errors: "; + (*OutStream) << endl; + (*OutStream) << GetOpenArcErrorMessage(errorFlags); + (*OutStream) << endl; + NumOpenArcErrors++; + ThereIsErrorInCurrent = true; } + + if (errors && wcslen(errors) != 0) + { + (*OutStream) << "Errors: "; + (*OutStream) << endl; + (*OutStream) << errors; + (*OutStream) << endl; + NumOpenArcErrors++; + ThereIsErrorInCurrent = true; + } + + if (warningFlags != 0) + { + (*OutStream) << "Warnings: "; + (*OutStream) << endl; + (*OutStream) << GetOpenArcErrorMessage(warningFlags); + (*OutStream) << endl; + NumOpenArcWarnings++; + ThereIsWarningInCurrent = true; + } + + if (warnings && wcslen(warnings) != 0) + { + (*OutStream) << "Warnings: "; + (*OutStream) << endl; + (*OutStream) << warnings; + (*OutStream) << endl; + NumOpenArcWarnings++; + ThereIsWarningInCurrent = true; + } + + (*OutStream) << endl; return S_OK; } @@ -201,24 +330,54 @@ HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result) if (result == S_OK) { (*OutStream) << endl; - if (NumFileErrorsInCurrentArchive == 0) + + if (NumFileErrorsInCurrent == 0 && !ThereIsErrorInCurrent) + { + if (ThereIsWarningInCurrent) + NumArcsWithWarnings++; + else + NumOkArcs++; (*OutStream) << kEverythingIsOk << endl; + } else { - NumArchiveErrors++; - (*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrentArchive << endl; + NumArcsWithError++; + if (NumFileErrorsInCurrent != 0) + (*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrent << endl; } + return S_OK; } - if (result == S_OK) - return result; - NumArchiveErrors++; + + NumArcsWithError++; if (result == E_ABORT || result == ERROR_DISK_FULL) return result; (*OutStream) << endl << kError; if (result == E_OUTOFMEMORY) (*OutStream) << kMemoryExceptionMessage; else - (*OutStream) << NError::MyFormatMessageW(result); + (*OutStream) << NError::MyFormatMessage(result); (*OutStream) << endl; return S_OK; } + +HRESULT CExtractCallbackConsole::OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType) +{ + UString s = L"Warning:\n"; + if (wcscmp(okType, errorType) == 0) + { + s += L"The archive is open with offset"; + } + else + { + s += name; + s += L"\nCan not open the file as ["; + s += errorType; + s += L"] archive\n"; + s += L"The file is open as ["; + s += okType; + s += L"] archive"; + } + (*OutStream) << s << endl << endl; + ThereIsWarningInCurrent = true; + return S_OK; +} diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.h b/CPP/7zip/UI/Console/ExtractCallbackConsole.h old mode 100755 new mode 100644 index e42ca6f4..9a0afdc9 --- a/CPP/7zip/UI/Console/ExtractCallbackConsole.h +++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.h @@ -3,11 +3,15 @@ #ifndef __EXTRACTCALLBACKCONSOLE_H #define __EXTRACTCALLBACKCONSOLE_H -#include "Common/MyString.h" -#include "Common/StdOutStream.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: @@ -40,8 +44,13 @@ public: HRESULT BeforeOpen(const wchar_t *name); HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted); + HRESULT SetError(int level, const wchar_t *name, + UInt32 errorFlags, const wchar_t *errors, + UInt32 warningFlags, const wchar_t *warnings); + HRESULT ThereAreNoFiles(); HRESULT ExtractResult(HRESULT result); + HRESULT OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType); #ifndef _NO_CRYPTO @@ -53,19 +62,36 @@ public: #endif - UInt64 NumArchives; - UInt64 NumArchiveErrors; + UInt64 NumTryArcs; + bool ThereIsErrorInCurrent; + bool ThereIsWarningInCurrent; + + UInt64 NumCantOpenArcs; + UInt64 NumOkArcs; + UInt64 NumArcsWithError; + UInt64 NumArcsWithWarnings; + + UInt64 NumProblemArcsLevs; + UInt64 NumOpenArcErrors; + UInt64 NumOpenArcWarnings; + UInt64 NumFileErrors; - UInt64 NumFileErrorsInCurrentArchive; + UInt64 NumFileErrorsInCurrent; CStdOutStream *OutStream; void Init() { - NumArchives = 0; - NumArchiveErrors = 0; + NumTryArcs = 0; + NumOkArcs = 0; + NumCantOpenArcs = 0; + NumArcsWithError = 0; + NumArcsWithWarnings = 0; + + NumOpenArcErrors = 0; + NumOpenArcWarnings = 0; NumFileErrors = 0; - NumFileErrorsInCurrentArchive = 0; + NumFileErrorsInCurrent = 0; } }; diff --git a/CPP/7zip/UI/Console/HashCon.cpp b/CPP/7zip/UI/Console/HashCon.cpp new file mode 100644 index 00000000..273f21c8 --- /dev/null +++ b/CPP/7zip/UI/Console/HashCon.cpp @@ -0,0 +1,274 @@ +// HashCon.cpp + +#include "StdAfx.h" + +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/ErrorMsg.h" + +#include "ConsoleClose.h" +#include "HashCon.h" + +static const wchar_t *kEmptyFileAlias = L"[Content]"; + +static const char *kScanningMessage = "Scanning"; + +HRESULT CHashCallbackConsole::CheckBreak() +{ + return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK; +} + +HRESULT CHashCallbackConsole::StartScanning() +{ + (*OutStream) << kScanningMessage; + return CheckBreak(); +} + +HRESULT CHashCallbackConsole::ScanProgress(UInt64 /* numFolders */, UInt64 /* numFiles */, UInt64 /* totalSize */, const wchar_t * /* path */, bool /* isDir */) +{ + return CheckBreak(); +} + +HRESULT CHashCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError) +{ + return CanNotFindError_Base(name, systemError); +} + +HRESULT CHashCallbackConsole::FinishScanning() +{ + (*OutStream) << endl << endl; + return CheckBreak(); +} + +HRESULT CHashCallbackConsole::SetNumFiles(UInt64 /* numFiles */) +{ + return CheckBreak(); +} + +HRESULT CHashCallbackConsole::SetTotal(UInt64 size) +{ + if (EnablePercents) + m_PercentPrinter.SetTotal(size); + return CheckBreak(); +} + +HRESULT CHashCallbackConsole::SetCompleted(const UInt64 *completeValue) +{ + if (completeValue && EnablePercents) + { + m_PercentPrinter.SetRatio(*completeValue); + m_PercentPrinter.PrintRatio(); + } + return CheckBreak(); +} + +static void AddMinuses(AString &s, unsigned num) +{ + for (unsigned i = 0; i < num; i++) + s += '-'; +} + +static void SetSpaces(char *s, int num) +{ + for (int i = 0; i < num; i++) + s[i] = ' '; +} + +static void SetSpacesAndNul(char *s, int num) +{ + SetSpaces(s, num); + s[num] = 0; +} + +static void AddSpaces(UString &s, int num) +{ + for (int i = 0; i < num; i++) + s += ' '; +} + +static const int kSizeField_Len = 13; +static const int kNameField_Len = 12; + +static unsigned GetColumnWidth(unsigned digestSize) +{ + unsigned width = digestSize * 2; + const unsigned kMinColumnWidth = 8; + return width < kMinColumnWidth ? kMinColumnWidth: width; +} + +void CHashCallbackConsole::PrintSeparatorLine(const CObjectVector &hashers) +{ + AString s; + for (unsigned i = 0; i < hashers.Size(); i++) + { + const CHasherState &h = hashers[i]; + AddMinuses(s, GetColumnWidth(h.DigestSize)); + s += ' '; + } + AddMinuses(s, kSizeField_Len); + s += " "; + AddMinuses(s, kNameField_Len); + m_PercentPrinter.PrintString(s); + m_PercentPrinter.PrintNewLine(); +} + +HRESULT CHashCallbackConsole::BeforeFirstFile(const CHashBundle &hb) +{ + UString s; + FOR_VECTOR (i, hb.Hashers) + { + const CHasherState &h = hb.Hashers[i]; + s += h.Name; + AddSpaces(s, (int)GetColumnWidth(h.DigestSize) - h.Name.Len() + 1); + } + UString s2 = L"Size"; + AddSpaces(s, kSizeField_Len - s2.Len()); + s += s2; + s += L" "; + s += L"Name"; + m_PercentPrinter.PrintString(s); + m_PercentPrinter.PrintNewLine(); + PrintSeparatorLine(hb.Hashers); + return CheckBreak(); +} + +HRESULT CHashCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemError) +{ + FailedCodes.Add(systemError); + FailedFiles.Add(name); + // if (systemError == ERROR_SHARING_VIOLATION) + { + m_PercentPrinter.PrintString(name); + m_PercentPrinter.PrintString(": WARNING: "); + m_PercentPrinter.PrintString(NWindows::NError::MyFormatMessage(systemError)); + return S_FALSE; + } + // return systemError; +} + +HRESULT CHashCallbackConsole::GetStream(const wchar_t *name, bool /* isFolder */) +{ + m_FileName = name; + return CheckBreak(); +} + +void CHashCallbackConsole::PrintResultLine(UInt64 fileSize, + const CObjectVector &hashers, unsigned digestIndex, bool showHash) +{ + FOR_VECTOR (i, hashers) + { + const CHasherState &h = hashers[i]; + + char s[k_HashCalc_DigestSize_Max * 2 + 64]; + s[0] = 0; + if (showHash) + AddHashHexToString(s, h.Digests[digestIndex], h.DigestSize); + SetSpacesAndNul(s + strlen(s), (int)GetColumnWidth(h.DigestSize) - (int)strlen(s) + 1); + m_PercentPrinter.PrintString(s); + } + char s[64]; + s[0] = 0; + char *p = s; + if (showHash && fileSize != 0) + { + p = s + 32; + ConvertUInt64ToString(fileSize, p); + int numSpaces = kSizeField_Len - (int)strlen(p); + if (numSpaces > 0) + { + p -= numSpaces; + SetSpaces(p, numSpaces); + } + } + else + SetSpacesAndNul(s, kSizeField_Len - (int)strlen(s)); + unsigned len = (unsigned)strlen(p); + p[len] = ' '; + p[len + 1] = ' '; + p[len + 2] = 0; + m_PercentPrinter.PrintString(p); +} + +HRESULT CHashCallbackConsole::SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash) +{ + PrintResultLine(fileSize, hb.Hashers, k_HashCalc_Index_Current, showHash); + if (m_FileName.IsEmpty()) + m_PercentPrinter.PrintString(kEmptyFileAlias); + else + m_PercentPrinter.PrintString(m_FileName); + m_PercentPrinter.PrintNewLine(); + return S_OK; +} + +static const char *k_DigestTitles[] = +{ + " :" + , " for data: " + , " for data and names: " + , " for streams and names: " +}; + +static void PrintSum(CStdOutStream &p, const CHasherState &h, unsigned digestIndex) +{ + char s[k_HashCalc_DigestSize_Max * 2 + 64]; + UString name = h.Name; + AddSpaces(name, 6 - (int)name.Len()); + p << name; + p << k_DigestTitles[digestIndex]; + s[0] = 0; + AddHashHexToString(s, h.Digests[digestIndex], h.DigestSize); + p << s; + p << "\n"; +} + + +void PrintHashStat(CStdOutStream &p, const CHashBundle &hb) +{ + FOR_VECTOR (i, hb.Hashers) + { + const CHasherState &h = hb.Hashers[i]; + p << "\n"; + PrintSum(p, h, k_HashCalc_Index_DataSum); + if (hb.NumFiles != 1 || hb.NumDirs != 0) + PrintSum(p, h, k_HashCalc_Index_NamesSum); + if (hb.NumAltStreams != 0) + PrintSum(p, h, k_HashCalc_Index_StreamsSum); + } +} + +void CHashCallbackConsole::PrintProperty(const char *name, UInt64 value) +{ + char s[32]; + s[0] = ':'; + s[1] = ' '; + ConvertUInt64ToString(value, s + 2); + m_PercentPrinter.PrintString(name); + m_PercentPrinter.PrintString(s); + m_PercentPrinter.PrintNewLine(); +} + +HRESULT CHashCallbackConsole::AfterLastFile(const CHashBundle &hb) +{ + PrintSeparatorLine(hb.Hashers); + + PrintResultLine(hb.FilesSize, hb.Hashers, k_HashCalc_Index_DataSum, true); + m_PercentPrinter.PrintNewLine(); + m_PercentPrinter.PrintNewLine(); + + if (hb.NumFiles != 1 || hb.NumDirs != 0) + { + if (hb.NumDirs != 0) + PrintProperty("Folders", hb.NumDirs); + PrintProperty("Files", hb.NumFiles); + } + PrintProperty("Size", hb.FilesSize); + if (hb.NumAltStreams != 0) + { + PrintProperty("AltStreams", hb.NumAltStreams); + PrintProperty("AltStreams size", hb.AltStreamsSize); + } + PrintHashStat(*m_PercentPrinter.OutStream, hb); + m_PercentPrinter.PrintNewLine(); + return S_OK; +} diff --git a/CPP/7zip/UI/Console/HashCon.h b/CPP/7zip/UI/Console/HashCon.h new file mode 100644 index 00000000..7d3c72fd --- /dev/null +++ b/CPP/7zip/UI/Console/HashCon.h @@ -0,0 +1,26 @@ +// HashCon.h + +#ifndef __HASH_CON_H +#define __HASH_CON_H + +#include "../Common/HashCalc.h" + +#include "UpdateCallbackConsole.h" + +class CHashCallbackConsole: public IHashCallbackUI, public CCallbackConsoleBase +{ + UString m_FileName; + + void PrintSeparatorLine(const CObjectVector &hashers); + void PrintResultLine(UInt64 fileSize, + const CObjectVector &hashers, unsigned digestIndex, bool showHash); + void PrintProperty(const char *name, UInt64 value); +public: + ~CHashCallbackConsole() { } + + INTERFACE_IHashCallbackUI(;) +}; + +void PrintHashStat(CStdOutStream &stdStream, const CHashBundle &hb); + +#endif diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp old mode 100755 new mode 100644 index 7de2379a..52770c8e --- a/CPP/7zip/UI/Console/List.cpp +++ b/CPP/7zip/UI/Console/List.cpp @@ -2,17 +2,16 @@ #include "StdAfx.h" -#include "Common/IntToString.h" -#include "Common/MyCom.h" -#include "Common/StdOutStream.h" -#include "Common/StringConvert.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/MyCom.h" +#include "../../../Common/StdOutStream.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/UTFConvert.h" -#include "Windows/Error.h" -#include "Windows/FileDir.h" -#include "Windows/PropVariant.h" -#include "Windows/PropVariantConversions.h" - -#include "../../Archive/IArchive.h" +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/PropVariantConv.h" #include "../Common/OpenArchive.h" #include "../Common/PropIDUtils.h" @@ -22,88 +21,131 @@ #include "OpenCallbackConsole.h" using namespace NWindows; +using namespace NCOM; + -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 *kPropIdToName[] = +{ + "0" + , "1" + , "2" + , "Path" + , "Name" + , "Extension" + , "Folder" + , "Size" + , "Packed Size" + , "Attributes" + , "Created" + , "Accessed" + , "Modified" + , "Solid" + , "Commented" + , "Encrypted" + , "Split Before" + , "Split After" + , "Dictionary Size" + , "CRC" + , "Type" + , "Anti" + , "Method" + , "Host OS" + , "File System" + , "User" + , "Group" + , "Block" + , "Comment" + , "Position" + , "Path Prefix" + , "Folders" + , "Files" + , "Version" + , "Volume" + , "Multivolume" + , "Offset" + , "Links" + , "Blocks" + , "Volumes" + , "Time Type" + , "64-bit" + , "Big-endian" + , "CPU" + , "Physical Size" + , "Headers Size" + , "Checksum" + , "Characteristics" + , "Virtual Address" + , "ID" + , "Short Name" + , "Creator Application" + , "Sector Size" + , "Mode" + , "Symbolic Link" + , "Error" + , "Total Size" + , "Free Space" + , "Cluster Size" + , "Label" + , "Local Name" + , "Provider" + , "NT Security" + , "Alternate Stream" + , "Aux" + , "Deleted" + , "Tree" + , "SHA-1" + , "SHA-256" + , "Error Type" + , "Errors" + , "Errors" + , "Warnings" + , "Warning" + , "Streams" + , "Alternate Streams" + , "Alternate Streams Size" + , "Virtual Size" + , "Unpack Size" + , "Total Physical Size" + , "Volume Index" + , "SubType" + , "Short Comment" + , "Code Page" + , "Is not archive type" + , "Physical Size can't be detected" + , "Zeros Tail Is Allowed" + , "Tail Size" + , "Embedded Stub Size" + , "Link" + , "Hard Link" + , "iNode" + , "Stream ID" }; 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) +static const char *kString_Files = "files"; +static const char *kString_Dirs = "folders"; +static const char *kString_AltStreams = "alternate streams"; +static const char *kString_Streams = "streams"; + +static void GetAttribString(UInt32 wa, bool isDir, bool allAttribs, 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'; + if (isDir) + wa |= FILE_ATTRIBUTE_DIRECTORY; + if (allAttribs) + { + ConvertWinAttribToString(s, wa); + return; + } + s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0) ? 'D': kEmptyAttribChar; + s[1] = ((wa & FILE_ATTRIBUTE_READONLY) != 0) ? 'R': kEmptyAttribChar; + s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? 'H': kEmptyAttribChar; + s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? 'S': kEmptyAttribChar; + s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? 'A': kEmptyAttribChar; + s[5] = 0; } enum EAdjustment @@ -116,7 +158,9 @@ enum EAdjustment struct CFieldInfo { PROPID PropID; - UString Name; + bool IsRawProp; + UString NameU; + AString NameA; EAdjustment TitleAdjustment; EAdjustment TextAdjustment; int PrefixSpacesWidth; @@ -126,61 +170,177 @@ struct CFieldInfo struct CFieldInfoInit { PROPID PropID; - const wchar_t *Name; + const char *Name; EAdjustment TitleAdjustment; EAdjustment TextAdjustment; int PrefixSpacesWidth; int Width; }; -static CFieldInfoInit kStandardFieldTable[] = +static const 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 } + { kpidMTime, " Date Time", kLeft, kLeft, 0, 19 }, + { kpidAttrib, "Attr", kRight, kCenter, 1, 5 }, + { kpidSize, "Size", kRight, kRight, 1, 12 }, + { kpidPackSize, "Compressed", kRight, kRight, 1, 12 }, + { kpidPath, "Name", kLeft, kLeft, 2, 24 } }; +const int kNumSpacesMax = 32; // it must be larger than max CFieldInfoInit.Width +static char *g_Spaces = +" " ; + static void PrintSpaces(int numSpaces) { - for (int i = 0; i < numSpaces; i++) - g_StdOut << ' '; + if (numSpaces > 0 && numSpaces <= kNumSpacesMax) + g_StdOut << g_Spaces + (kNumSpacesMax - numSpaces); +} + +static void PrintSpacesToString(char *dest, int numSpaces) +{ + int i; + for (i = 0; i < numSpaces; i++) + dest[i] = ' '; + dest[i] = 0; +} + +static void PrintString(EAdjustment adj, int width, const UString &textString) +{ + const int numSpaces = width - textString.Len(); + int numLeftSpaces = 0; + switch (adj) + { + case kLeft: numLeftSpaces = 0; break; + case kCenter: numLeftSpaces = numSpaces / 2; break; + case kRight: numLeftSpaces = numSpaces; break; + } + PrintSpaces(numLeftSpaces); + g_StdOut << textString; + PrintSpaces(numSpaces - numLeftSpaces); } -static void PrintString(EAdjustment adjustment, int width, const UString &textString) +static void PrintString(EAdjustment adj, int width, const char *textString) { - const int numSpaces = width - textString.Length(); + const int numSpaces = width - (int)strlen(textString); int numLeftSpaces = 0; - switch (adjustment) + switch (adj) { - case kLeft: - numLeftSpaces = 0; - break; - case kCenter: - numLeftSpaces = numSpaces / 2; - break; - case kRight: - numLeftSpaces = numSpaces; - break; + case kLeft: numLeftSpaces = 0; break; + case kCenter: numLeftSpaces = numSpaces / 2; break; + case kRight: numLeftSpaces = numSpaces; break; } PrintSpaces(numLeftSpaces); g_StdOut << textString; PrintSpaces(numSpaces - numLeftSpaces); } +static void PrintStringToString(char *dest, EAdjustment adj, int width, const char *textString) +{ + int len = (int)strlen(textString); + const int numSpaces = width - len; + int numLeftSpaces = 0; + switch (adj) + { + case kLeft: numLeftSpaces = 0; break; + case kCenter: numLeftSpaces = numSpaces / 2; break; + case kRight: numLeftSpaces = numSpaces; break; + } + PrintSpacesToString(dest, numLeftSpaces); + if (numLeftSpaces > 0) + dest += numLeftSpaces; + memcpy(dest, textString, len); + dest += len; + PrintSpacesToString(dest, numSpaces - numLeftSpaces); +} + +struct CListUInt64Def +{ + UInt64 Val; + bool Def; + + CListUInt64Def(): Val(0), Def(false) {} + void Add(UInt64 v) { Val += v; Def = true; } + void Add(const CListUInt64Def &v) { if (v.Def) Add(v.Val); } +}; + +struct CListFileTimeDef +{ + FILETIME Val; + bool Def; + + CListFileTimeDef(): Def(false) { Val.dwLowDateTime = 0; Val.dwHighDateTime = 0; } + void Update(const CListFileTimeDef &t) + { + if (t.Def && (!Def || CompareFileTime(&Val, &t.Val) < 0)) + { + Val = t.Val; + Def = true; + } + } +}; + +struct CListStat +{ + CListUInt64Def Size; + CListUInt64Def PackSize; + CListFileTimeDef MTime; + UInt64 NumFiles; + + CListStat(): NumFiles(0) {} + void Update(const CListStat &stat) + { + Size.Add(stat.Size); + PackSize.Add(stat.PackSize); + MTime.Update(stat.MTime); + NumFiles += stat.NumFiles; + } + void SetSizeDefIfNoFiles() { if (NumFiles == 0) Size.Def = true; } +}; + +struct CListStat2 +{ + CListStat MainFiles; + CListStat AltStreams; + UInt64 NumDirs; + + CListStat2(): NumDirs(0) {} + + void Update(const CListStat2 &stat) + { + MainFiles.Update(stat.MainFiles); + AltStreams.Update(stat.AltStreams); + NumDirs += stat.NumDirs; + } + const UInt64 GetNumStreams() const { return MainFiles.NumFiles + AltStreams.NumFiles; } + CListStat &GetStat(bool altStreamsMode) { return altStreamsMode ? AltStreams : MainFiles; } +}; + class CFieldPrinter { CObjectVector _fields; + + void AddProp(BSTR name, PROPID propID, bool isRawProp); public: - void Clear() { _fields.Clear(); } + const CArc *Arc; + bool TechMode; + UString FilePath; + AString TempAString; + UString TempWString; + bool IsFolder; + + AString LinesString; + + void Clear() { _fields.Clear(); LinesString.Empty(); } void Init(const CFieldInfoInit *standardFieldTable, int numItems); - HRESULT Init(IInArchive *archive); + + HRESULT AddMainProps(IInArchive *archive); + HRESULT AddRawProps(IArchiveGetRawProps *getRawProps); + 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); + HRESULT PrintItemInfo(UInt32 index, const CListStat &stat); + void PrintSum(const CListStat &stat, UInt64 numDirs, const char *str); + void PrintSum(const CListStat2 &stat); }; void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems) @@ -188,36 +348,70 @@ 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); + CFieldInfo &f = _fields.AddNew(); + const CFieldInfoInit &fii = standardFieldTable[i]; + f.PropID = fii.PropID; + f.IsRawProp = false; + f.NameA = fii.Name; + f.TitleAdjustment = fii.TitleAdjustment; + f.TextAdjustment = fii.TextAdjustment; + f.PrefixSpacesWidth = fii.PrefixSpacesWidth; + f.Width = fii.Width; + + int k; + for (k = 0; k < fii.PrefixSpacesWidth; k++) + LinesString += ' '; + for (k = 0; k < fii.Width; k++) + LinesString += '-'; } } -static UString GetPropName(PROPID propID, BSTR name) +static void GetPropName(PROPID propID, const wchar_t *name, AString &nameA, UString &nameU) { - for (int i = 0; i < sizeof(kPropIdToName) / sizeof(kPropIdToName[0]); i++) + if (propID < ARRAY_SIZE(kPropIdToName)) { - const CPropIdToName &propIdToName = kPropIdToName[i]; - if (propIdToName.PropID == propID) - return propIdToName.Name; + nameA = kPropIdToName[propID]; + return; } if (name) - return name; - wchar_t s[16]; - ConvertUInt32ToString(propID, s); - return s; + nameU = name; + else + { + char s[16]; + ConvertUInt32ToString(propID, s); + nameA = s; + } } -HRESULT CFieldPrinter::Init(IInArchive *archive) +void CFieldPrinter::AddProp(BSTR name, PROPID propID, bool isRawProp) +{ + CFieldInfo f; + f.PropID = propID; + f.IsRawProp = isRawProp; + GetPropName(propID, name, f.NameA, f.NameU); + f.NameU += L" = "; + if (!f.NameA.IsEmpty()) + f.NameA += " = "; + else + { + const UString &s = f.NameU; + AString sA; + unsigned i; + for (i = 0; i < s.Len(); i++) + { + wchar_t c = s[i]; + if (c >= 0x80) + break; + sA += (char)c; + } + if (i == s.Len()) + f.NameA = sA; + } + _fields.Add(f); +} + +HRESULT CFieldPrinter::AddMainProps(IInArchive *archive) { - Clear(); UInt32 numProps; RINOK(archive->GetNumberOfProperties(&numProps)); for (UInt32 i = 0; i < numProps; i++) @@ -226,64 +420,80 @@ HRESULT CFieldPrinter::Init(IInArchive *archive) PROPID propID; VARTYPE vt; RINOK(archive->GetPropertyInfo(i, &name, &propID, &vt)); - CFieldInfo fieldInfo; - fieldInfo.PropID = propID; - fieldInfo.Name = GetPropName(propID, name); - _fields.Add(fieldInfo); + AddProp(name, propID, false); } return S_OK; } -void CFieldPrinter::PrintTitle() +HRESULT CFieldPrinter::AddRawProps(IArchiveGetRawProps *getRawProps) { - for (int i = 0; i < _fields.Size(); i++) + UInt32 numProps; + RINOK(getRawProps->GetNumRawProps(&numProps)); + for (UInt32 i = 0; i < numProps; i++) { - const CFieldInfo &fieldInfo = _fields[i]; - PrintSpaces(fieldInfo.PrefixSpacesWidth); - PrintString(fieldInfo.TitleAdjustment, - ((fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width), fieldInfo.Name); + CMyComBSTR name; + PROPID propID; + RINOK(getRawProps->GetRawPropInfo(i, &name, &propID)); + AddProp(name, propID, true); } + return S_OK; } -void CFieldPrinter::PrintTitleLines() +void CFieldPrinter::PrintTitle() { - for (int i = 0; i < _fields.Size(); i++) + FOR_VECTOR (i, _fields) { - const CFieldInfo &fieldInfo = _fields[i]; - PrintSpaces(fieldInfo.PrefixSpacesWidth); - for (int i = 0; i < fieldInfo.Width; i++) - g_StdOut << '-'; + const CFieldInfo &f = _fields[i]; + PrintSpaces(f.PrefixSpacesWidth); + PrintString(f.TitleAdjustment, ((f.PropID == kpidPath) ? 0: f.Width), f.NameA); } } +void CFieldPrinter::PrintTitleLines() +{ + g_StdOut << LinesString; +} -static BOOL IsFileTimeZero(CONST FILETIME *lpFileTime) +static void PrintTime(char *dest, const FILETIME *ft) { - return (lpFileTime->dwLowDateTime == 0) && (lpFileTime->dwHighDateTime == 0); + *dest = 0; + if (ft->dwLowDateTime == 0 && ft->dwHighDateTime == 0) + return; + FILETIME locTime; + if (!FileTimeToLocalFileTime(ft, &locTime)) + throw 20121211; + ConvertFileTimeToString(locTime, dest, true, true); } -static const char *kEmptyTimeString = " "; -static void PrintTime(const NCOM::CPropVariant &prop) +#ifndef _SFX + +static inline char GetHex(Byte value) { - if (prop.vt != VT_FILETIME) - throw "incorrect item"; - if (IsFileTimeZero(&prop.filetime)) - g_StdOut << kEmptyTimeString; - else + return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); +} + +static void HexToString(char *dest, const Byte *data, UInt32 size) +{ + for (UInt32 i = 0; i < size; i++) { - 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; + Byte b = data[i]; + dest[0] = GetHex((Byte)((b >> 4) & 0xF)); + dest[1] = GetHex((Byte)(b & 0xF)); + dest += 2; } + *dest = 0; } -HRESULT CFieldPrinter::PrintItemInfo(const CArc &arc, UInt32 index, bool techMode) +#endif + +#define MY_ENDL '\n' + +HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &stat) { + char temp[128]; + size_t tempPos = 0; + + bool techMode = this->TechMode; /* if (techMode) { @@ -292,148 +502,393 @@ HRESULT CFieldPrinter::PrintItemInfo(const CArc &arc, UInt32 index, bool techMod g_StdOut << endl; } */ - for (int i = 0; i < _fields.Size(); i++) + FOR_VECTOR (i, _fields) { - const CFieldInfo &fieldInfo = _fields[i]; - if (!techMode) - PrintSpaces(fieldInfo.PrefixSpacesWidth); + const CFieldInfo &f = _fields[i]; - NCOM::CPropVariant prop; - if (fieldInfo.PropID == kpidPath) - { - UString s; - RINOK(arc.GetItemPath(index, s)); - prop = s; - } - else + if (!techMode) { - RINOK(arc.Archive->GetProperty(index, fieldInfo.PropID, &prop)); + PrintSpacesToString(temp + tempPos, f.PrefixSpacesWidth); + tempPos += f.PrefixSpacesWidth; } + 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; + if (!f.NameA.IsEmpty()) + g_StdOut << f.NameA; + else + g_StdOut << f.NameU; } - else if (prop.vt == VT_EMPTY) + + if (f.PropID == kpidPath) { if (!techMode) - PrintSpaces(width); - } - else if (fieldInfo.PropID == kpidMTime) - { - PrintTime(prop); + g_StdOut << temp; + g_StdOut.PrintUString(FilePath, TempAString); + if (techMode) + g_StdOut << MY_ENDL; + continue; } - else if (prop.vt == VT_BSTR) + + int width = f.Width; + + if (f.IsRawProp) { - if (techMode) - g_StdOut << prop.bstrVal; - else - PrintString(fieldInfo.TextAdjustment, width, prop.bstrVal); + #ifndef _SFX + + const void *data; + UInt32 dataSize; + UInt32 propType; + RINOK(Arc->GetRawProps->GetRawProp(index, f.PropID, &data, &dataSize, &propType)); + + if (dataSize != 0) + { + bool needPrint = true; + + if (f.PropID == kpidNtSecure) + { + if (propType != NPropDataType::kRaw) + return E_FAIL; + #ifndef _SFX + ConvertNtSecureToString((const Byte *)data, dataSize, TempAString); + g_StdOut << TempAString; + needPrint = false; + #endif + } + else if (f.PropID == kpidNtReparse) + { + UString s; + if (ConvertNtReparseToString((const Byte *)data, dataSize, s)) + { + needPrint = false; + g_StdOut << s; + } + } + + if (needPrint) + { + if (propType != NPropDataType::kRaw) + return E_FAIL; + + const UInt32 kMaxDataSize = 64; + + if (dataSize > kMaxDataSize) + { + g_StdOut << "data:"; + g_StdOut << dataSize; + } + else + { + char hexStr[kMaxDataSize * 2 + 4]; + HexToString(hexStr, (const Byte *)data, dataSize); + g_StdOut << hexStr; + } + } + } + + #endif } else { - UString s = ConvertPropertyToString(prop, fieldInfo.PropID); - s.Replace(wchar_t(0xA), L' '); - s.Replace(wchar_t(0xD), L' '); - - if (techMode) - g_StdOut << s; + CPropVariant prop; + switch (f.PropID) + { + case kpidSize: if (stat.Size.Def) prop = stat.Size.Val; break; + case kpidPackSize: if (stat.PackSize.Def) prop = stat.PackSize.Val; break; + case kpidMTime: if (stat.MTime.Def) prop = stat.MTime.Val; break; + default: + RINOK(Arc->Archive->GetProperty(index, f.PropID, &prop)); + } + if (f.PropID == kpidAttrib && (prop.vt == VT_EMPTY || prop.vt == VT_UI4)) + { + GetAttribString((prop.vt == VT_EMPTY) ? 0 : prop.ulVal, IsFolder, techMode, temp + tempPos); + if (techMode) + g_StdOut << temp + tempPos; + else + tempPos += strlen(temp + tempPos); + } + else if (prop.vt == VT_EMPTY) + { + if (!techMode) + { + PrintSpacesToString(temp + tempPos, width); + tempPos += width; + } + } + else if (prop.vt == VT_FILETIME) + { + PrintTime(temp + tempPos, &prop.filetime); + if (techMode) + g_StdOut << temp + tempPos; + else + { + size_t len = strlen(temp + tempPos); + tempPos += len; + if (len < (unsigned)f.Width) + { + len = (size_t)f.Width - len; + PrintSpacesToString(temp + tempPos, (int)len); + tempPos += len; + } + } + } + else if (prop.vt == VT_BSTR) + { + if (techMode) + { + int len = (int)wcslen(prop.bstrVal); + MyStringCopy(TempWString.GetBuffer(len), prop.bstrVal); + // replace CR/LF here. + TempWString.ReleaseBuffer(len); + g_StdOut.PrintUString(TempWString, TempAString); + } + else + PrintString(f.TextAdjustment, width, prop.bstrVal); + } else - PrintString(fieldInfo.TextAdjustment, width, s); + { + char s[64]; + ConvertPropertyToShortString(s, prop, f.PropID); + if (techMode) + g_StdOut << s; + else + { + PrintStringToString(temp + tempPos, f.TextAdjustment, width, s); + tempPos += strlen(temp + tempPos); + } + } } if (techMode) - g_StdOut << endl; + g_StdOut << MY_ENDL; } + g_StdOut << MY_ENDL; return S_OK; } -static void PrintNumberString(EAdjustment adjustment, int width, const UInt64 *value) +static void PrintNumber(EAdjustment adj, int width, const CListUInt64Def &value) { - wchar_t textString[32] = { 0 }; - if (value != NULL) - ConvertUInt64ToString(*value, textString); - PrintString(adjustment, width, textString); + wchar_t s[32]; + s[0] = 0; + if (value.Def) + ConvertUInt64ToString(value.Val, s); + PrintString(adj, width, s); } +static void PrintNumberAndString(AString &s, UInt64 value, const char *text) +{ + char t[32]; + ConvertUInt64ToString(value, t); + s += t; + s += ' '; + s += text; +} -HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, - const UInt64 *size, const UInt64 *compressedSize) +void CFieldPrinter::PrintSum(const CListStat &stat, UInt64 numDirs, const char *str) { - for (int i = 0; i < _fields.Size(); i++) + FOR_VECTOR (i, _fields) { - 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) + const CFieldInfo &f = _fields[i]; + PrintSpaces(f.PrefixSpacesWidth); + if (f.PropID == kpidSize) + PrintNumber(f.TextAdjustment, f.Width, stat.Size); + else if (f.PropID == kpidPackSize) + PrintNumber(f.TextAdjustment, f.Width, stat.PackSize); + else if (f.PropID == kpidMTime) { - 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); + char s[64]; + s[0] = 0; + if (stat.MTime.Def) + PrintTime(s, &stat.MTime.Val); + PrintString(f.TextAdjustment, f.Width, s); } + else if (f.PropID == kpidPath) + { + AString s; + PrintNumberAndString(s, stat.NumFiles, str); + if (numDirs != 0) + { + s += ", "; + PrintNumberAndString(s, numDirs, kString_Dirs); + } + PrintString(f.TextAdjustment, 0, s); + } + else + PrintString(f.TextAdjustment, f.Width, L""); + } + g_StdOut << endl; +} + +void CFieldPrinter::PrintSum(const CListStat2 &stat2) +{ + PrintSum(stat2.MainFiles, stat2.NumDirs, kString_Files); + if (stat2.AltStreams.NumFiles != 0) + { + PrintSum(stat2.AltStreams, 0, kString_AltStreams);; + CListStat stat = stat2.MainFiles; + stat.Update(stat2.AltStreams); + PrintSum(stat, 0, kString_Streams); + } +} + +static HRESULT GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, CListUInt64Def &value) +{ + value.Val = 0; + value.Def = false; + CPropVariant prop; + RINOK(archive->GetProperty(index, propID, &prop)); + value.Def = ConvertPropVariantToUInt64(prop, value.Val); + return S_OK; +} + +static HRESULT GetItemMTime(IInArchive *archive, UInt32 index, CListFileTimeDef &t) +{ + t.Val.dwLowDateTime = 0; + t.Val.dwHighDateTime = 0; + t.Def = false; + CPropVariant prop; + RINOK(archive->GetProperty(index, kpidMTime, &prop)); + if (prop.vt == VT_FILETIME) + { + t.Val = prop.filetime; + t.Def = true; + } + else if (prop.vt != VT_EMPTY) + return E_FAIL; + return S_OK; +} + +static void PrintPropNameAndNumber(const char *name, UInt64 val) +{ + g_StdOut << name << ": " << val << endl; +} + +static void PrintPropName_and_Eq(PROPID propID) +{ + const char *s; + char temp[16]; + if (propID < ARRAY_SIZE(kPropIdToName)) + s = kPropIdToName[propID]; + else + { + ConvertUInt32ToString(propID, temp); + s = temp; + } + g_StdOut << s << " = "; +} + +static void PrintPropNameAndNumber(PROPID propID, UInt64 val) +{ + PrintPropName_and_Eq(propID); + g_StdOut << val << endl; +} + +static void PrintPropNameAndNumber_Signed(PROPID propID, Int64 val) +{ + PrintPropName_and_Eq(propID); + g_StdOut << val << endl; +} + +static void PrintPropPair(const char *name, const wchar_t *val) +{ + g_StdOut << name << " = " << val << endl; +} + + +static void PrintPropertyPair2(PROPID propID, const wchar_t *name, const CPropVariant &prop) +{ + UString s; + ConvertPropertyToString(s, prop, propID); + if (!s.IsEmpty()) + { + AString nameA; + UString nameU; + GetPropName(propID, name, nameA, nameU); + if (!nameA.IsEmpty()) + PrintPropPair(nameA, s); else - PrintString(fieldInfo.TextAdjustment, fieldInfo.Width, L""); + g_StdOut << nameU << " = " << s << endl; } +} + +static HRESULT PrintArcProp(IInArchive *archive, PROPID propID, const wchar_t *name) +{ + CPropVariant prop; + RINOK(archive->GetArchiveProperty(propID, &prop)); + PrintPropertyPair2(propID, name, prop); return S_OK; } -bool GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &value) +static void PrintArcTypeError(const UString &type, bool isWarning) { - 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; + g_StdOut << "Open " << (isWarning ? "Warning" : "Error") + << ": Can not open the file as [" + << type + << "] archive" + << endl; } -static void PrintPropPair(const wchar_t *name, const wchar_t *value) +int Find_FileName_InSortedVector(const UStringVector &fileName, const UString& name); + +AString GetOpenArcErrorMessage(UInt32 errorFlags); + +static void PrintErrorFlags(const char *s, UInt32 errorFlags) { - g_StdOut << name << " = " << value << endl; + g_StdOut << s << endl << GetOpenArcErrorMessage(errorFlags) << endl; } -HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, +static void ErrorInfo_Print(const CArcErrorInfo &er) +{ + if (er.AreThereErrors()) + PrintErrorFlags("Errors:", er.GetErrorFlags()); + if (!er.ErrorMessage.IsEmpty()) + PrintPropPair("Error", er.ErrorMessage); + if (er.AreThereWarnings()) + PrintErrorFlags("Warnings:", er.GetWarningFlags()); + if (!er.WarningMessage.IsEmpty()) + PrintPropPair("Warning", er.WarningMessage); +} + +HRESULT ListArchives(CCodecs *codecs, + const CObjectVector &types, + const CIntVector &excludedFormats, bool stdInMode, UStringVector &arcPaths, UStringVector &arcPathsFull, + bool processAltStreams, bool showAltStreams, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, #ifndef _NO_CRYPTO bool &passwordEnabled, UString &password, #endif - UInt64 &numErrors) + #ifndef _SFX + const CObjectVector *props, + #endif + UInt64 &numErrors, + UInt64 &numWarnings) { + bool AllFilesAreAllowed = wildcardCensor.AreAllAllowed(); + numErrors = 0; - CFieldPrinter fieldPrinter; + numWarnings = 0; + + CFieldPrinter fp; if (!techMode) - fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0])); + fp.Init(kStandardFieldTable, ARRAY_SIZE(kStandardFieldTable)); - 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++) + CListStat2 stat2; + + CBoolArr skipArcs(arcPaths.Size()); + unsigned arcIndex; + for (arcIndex = 0; arcIndex < arcPaths.Size(); arcIndex++) + skipArcs[arcIndex] = false; + UInt64 numVolumes = 0; + UInt64 numArcs = 0; + UInt64 totalArcSizes = 0; + + for (arcIndex = 0; arcIndex < arcPaths.Size(); arcIndex++) { - const UString &archiveName = arcPaths[i]; + if (skipArcs[arcIndex]) + continue; + const UString &archiveName = arcPaths[arcIndex]; UInt64 arcPackSize = 0; if (!stdInMode) { @@ -445,9 +900,10 @@ HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, continue; } arcPackSize = fi.Size; + totalArcSizes += arcPackSize; } - CArchiveLink archiveLink; + CArchiveLink arcLink; COpenCallbackConsole openCallback; openCallback.OutStream = &g_StdOut; @@ -459,7 +915,24 @@ HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, #endif - HRESULT result = archiveLink.Open2(codecs, formatIndices, stdInMode, NULL, archiveName, &openCallback); + /* + CObjectVector optPropsVector; + COptionalOpenProperties &optProps = optPropsVector.AddNew(); + optProps.Props = *props; + */ + + COpenOptions options; + #ifndef _SFX + options.props = props; + #endif + options.codecs = codecs; + options.types = &types; + options.excludedFormats = &excludedFormats; + options.stdInMode = stdInMode; + options.stream = NULL; + options.filePath = archiveName; + HRESULT result = arcLink.Open2(options, &openCallback); + if (result != S_OK) { if (result == E_ABORT) @@ -472,45 +945,95 @@ HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, g_StdOut << "Can not open encrypted archive. Wrong password?"; else #endif - g_StdOut << "Can not open file as archive"; + { + if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) + { + PrintArcTypeError(codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false); + } + else + g_StdOut << "Can not open the file as archive"; + } + g_StdOut << endl; + ErrorInfo_Print(arcLink.NonOpen_ErrorInfo); } else if (result == E_OUTOFMEMORY) g_StdOut << "Can't allocate required memory"; else - g_StdOut << NError::MyFormatMessageW(result); + g_StdOut << NError::MyFormatMessage(result); g_StdOut << endl; numErrors++; continue; } + { + if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) + numErrors++; + + FOR_VECTOR (r, arcLink.Arcs) + { + const CArcErrorInfo &arc = arcLink.Arcs[r].ErrorInfo; + if (!arc.WarningMessage.IsEmpty()) + numWarnings++; + if (arc.AreThereWarnings()) + numWarnings++; + if (arc.ErrorFormatIndex >= 0) + numWarnings++; + if (arc.AreThereErrors()) + { + numErrors++; + // break; + } + if (!arc.ErrorMessage.IsEmpty()) + numErrors++; + } + } + + numArcs++; + numVolumes++; if (!stdInMode) - for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { - int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]); - if (index >= 0 && index > i) + numVolumes += arcLink.VolumePaths.Size(); + totalArcSizes += arcLink.VolumesSize; + FOR_VECTOR (v, arcLink.VolumePaths) { - arcPaths.Delete(index); - arcPathsFull.Delete(index); - numArcs = arcPaths.Size(); + int index = Find_FileName_InSortedVector(arcPathsFull, arcLink.VolumePaths[v]); + if (index >= 0 && (unsigned)index > arcIndex) + skipArcs[index] = true; } } + if (enableHeaders) { g_StdOut << endl << kListing << archiveName << endl << endl; - for (int i = 0; i < archiveLink.Arcs.Size(); i++) + FOR_VECTOR (r, arcLink.Arcs) { - const CArc &arc = archiveLink.Arcs[i]; + const CArc &arc = arcLink.Arcs[r]; + const CArcErrorInfo &er = arc.ErrorInfo; 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; + PrintPropPair("Path", arc.Path); + if (er.ErrorFormatIndex >= 0) + { + if (er.ErrorFormatIndex == arc.FormatIndex) + g_StdOut << "Warning: The archive is open with offset" << endl; + else + PrintArcTypeError(codecs->GetFormatNamePtr(er.ErrorFormatIndex), true); + } + PrintPropPair("Type", codecs->GetFormatNamePtr(arc.FormatIndex)); + + ErrorInfo_Print(er); + + Int64 offset = arc.GetGlobalOffset(); + if (offset != 0) + PrintPropNameAndNumber_Signed(kpidOffset, offset); IInArchive *archive = arc.Archive; - if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK) + RINOK(PrintArcProp(archive, kpidPhySize, NULL)); + if (er.TailSize != 0) + PrintPropNameAndNumber(kpidTailSize, er.TailSize); + UInt32 numProps; + RINOK(archive->GetNumberOfArchiveProperties(&numProps)); { for (UInt32 j = 0; j < numProps; j++) { @@ -518,35 +1041,28 @@ HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, 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); + RINOK(PrintArcProp(archive, propID, name)); } } - if (i != archiveLink.Arcs.Size() - 1) + if (r != arcLink.Arcs.Size() - 1) { UInt32 numProps; g_StdOut << "----\n"; if (archive->GetNumberOfProperties(&numProps) == S_OK) { - UInt32 mainIndex = archiveLink.Arcs[i + 1].SubfileIndex; + UInt32 mainIndex = arcLink.Arcs[r + 1].SubfileIndex; for (UInt32 j = 0; j < numProps; j++) { CMyComBSTR name; PROPID propID; VARTYPE vt; RINOK(archive->GetPropertyInfo(j, &name, &propID, &vt)); - NCOM::CPropVariant prop; + CPropVariant prop; RINOK(archive->GetProperty(mainIndex, propID, &prop)); - UString s = ConvertPropertyToString(prop, propID); - if (!s.IsEmpty()) - PrintPropPair(GetPropName(propID, name), s); + PrintPropertyPair2(propID, name, prop); } } } - } g_StdOut << endl; if (techMode) @@ -555,20 +1071,28 @@ HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, if (enableHeaders && !techMode) { - fieldPrinter.PrintTitle(); + fp.PrintTitle(); g_StdOut << endl; - fieldPrinter.PrintTitleLines(); + fp.PrintTitleLines(); g_StdOut << endl; } - const CArc &arc = archiveLink.Arcs.Back(); + const CArc &arc = arcLink.Arcs.Back(); + fp.Arc = &arc; + fp.TechMode = techMode; IInArchive *archive = arc.Archive; if (techMode) { - RINOK(fieldPrinter.Init(archive)); + fp.Clear(); + RINOK(fp.AddMainProps(archive)); + if (arc.GetRawProps) + { + RINOK(fp.AddRawProps(arc.GetRawProps)); + } } - UInt64 numFiles = 0, numDirs = 0, totalPackSize = 0, totalUnPackSize = 0; - UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0; + + CListStat2 stat; + UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); for (UInt32 i = 0; i < numItems; i++) @@ -576,79 +1100,93 @@ HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, if (NConsoleClose::TestBreakSignal()) return E_ABORT; - UString filePath; - HRESULT res = arc.GetItemPath(i, filePath); + HRESULT res = arc.GetItemPath2(i, fp.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); + if (arc.Ask_Aux) + { + bool isAux; + RINOK(Archive_IsItem_Aux(archive, i, isAux)); + if (isAux) + continue; + } + + bool isAltStream = false; + if (arc.Ask_AltStream) + { + RINOK(Archive_IsItem_AltStream(archive, i, isAltStream)); + if (isAltStream && !processAltStreams) + continue; + } + + RINOK(Archive_IsItem_Folder(archive, i, fp.IsFolder)); + + if (!AllFilesAreAllowed) + { + if (!wildcardCensor.CheckPath(isAltStream, fp.FilePath, !fp.IsFolder)) + continue; + } - 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; + CListStat st; - g_StdOut << endl; + RINOK(GetUInt64Value(archive, i, kpidSize, st.Size)); + RINOK(GetUInt64Value(archive, i, kpidPackSize, st.PackSize)); + RINOK(GetItemMTime(archive, i, st.MTime)); - if (isFolder) - numDirs++; + if (fp.IsFolder) + stat.NumDirs++; else - numFiles++; - totalPackSize += packSize; - totalUnPackSize += unpackSize; - } + st.NumFiles = 1; + stat.GetStat(isAltStream).Update(st); - if (!stdInMode && totalPackSizePointer == 0) - { - if (archiveLink.VolumePaths.Size() != 0) - arcPackSize += archiveLink.VolumesSize; - totalPackSize = (numFiles == 0) ? 0 : arcPackSize; - totalPackSizePointer = &totalPackSize; + if (isAltStream && !showAltStreams) + continue; + RINOK(fp.PrintItemInfo(i, st)); } - if (totalUnPackSizePointer == 0 && numFiles == 0) + + UInt64 numStreams = stat.GetNumStreams(); + if (!stdInMode + && !stat.MainFiles.PackSize.Def + && !stat.AltStreams.PackSize.Def) { - totalUnPackSize = 0; - totalUnPackSizePointer = &totalUnPackSize; + if (arcLink.VolumePaths.Size() != 0) + arcPackSize += arcLink.VolumesSize; + stat.MainFiles.PackSize.Add((numStreams == 0) ? 0 : arcPackSize); } + stat.MainFiles.SetSizeDefIfNoFiles(); + stat.AltStreams.SetSizeDefIfNoFiles(); if (enableHeaders && !techMode) { - fieldPrinter.PrintTitleLines(); + fp.PrintTitleLines(); g_StdOut << endl; - fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer); - g_StdOut << endl; - } - if (totalPackSizePointer != 0) - { - totalPackSizePointer2 = &totalPackSize2; - totalPackSize2 += totalPackSize; + fp.PrintSum(stat); } - if (totalUnPackSizePointer != 0) + + if (enableHeaders) { - totalUnPackSizePointer2 = &totalUnPackSize2; - totalUnPackSize2 += totalUnPackSize; + if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) + { + g_StdOut << "----------\n"; + PrintPropPair("Path", arcLink.NonOpen_ArcPath); + PrintArcTypeError(codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false); + } } - numFiles2 += numFiles; - numDirs2 += numDirs; + stat2.Update(stat); + fflush(stdout); } - if (enableHeaders && !techMode && numArcs > 1) + if (enableHeaders && !techMode && (arcPaths.Size() > 1 || numVolumes > 1)) { g_StdOut << endl; - fieldPrinter.PrintTitleLines(); + fp.PrintTitleLines(); g_StdOut << endl; - fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2); + fp.PrintSum(stat2); g_StdOut << endl; - g_StdOut << "Archives: " << numArcs << endl; + PrintPropNameAndNumber("Archives", numArcs); + PrintPropNameAndNumber("Volumes", numVolumes); + PrintPropNameAndNumber("Total archives size", totalArcSizes); } return S_OK; } diff --git a/CPP/7zip/UI/Console/List.h b/CPP/7zip/UI/Console/List.h old mode 100755 new mode 100644 index 97d9fb15..462c4710 --- a/CPP/7zip/UI/Console/List.h +++ b/CPP/7zip/UI/Console/List.h @@ -3,18 +3,25 @@ #ifndef __LIST_H #define __LIST_H -#include "Common/Wildcard.h" +#include "../../../Common/Wildcard.h" + #include "../Common/LoadCodecs.h" -HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, +HRESULT ListArchives(CCodecs *codecs, + const CObjectVector &types, + const CIntVector &excludedFormats, bool stdInMode, UStringVector &archivePaths, UStringVector &archivePathsFull, + bool processAltStreams, bool showAltStreams, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, #ifndef _NO_CRYPTO bool &passwordEnabled, UString &password, #endif - UInt64 &errors); + #ifndef _SFX + const CObjectVector *props, + #endif + UInt64 &errors, + UInt64 &numWarnings); #endif - diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp old mode 100755 new mode 100644 index f5a70397..0038dba4 --- a/CPP/7zip/UI/Console/Main.cpp +++ b/CPP/7zip/UI/Console/Main.cpp @@ -2,24 +2,31 @@ #include "StdAfx.h" +#include + #if defined( _WIN32) && defined( _7ZIP_LARGE_PAGES) #include "../../../../C/Alloc.h" #endif -#include "Common/MyInitGuid.h" +#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 "../../../Common/CommandLineParser.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/MyException.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/StringToInt.h" -#include "Windows/Error.h" +#include "../../../Windows/ErrorMsg.h" #ifdef _WIN32 -#include "Windows/MemoryLock.h" +#include "../../../Windows/MemoryLock.h" +#endif + +#ifndef _7ZIP_ST +#include "../../../Windows/Synchronization.h" #endif +#include "../../../Windows/TimeUtils.h" + #include "../Common/ArchiveCommandLine.h" #include "../Common/ExitCode.h" #include "../Common/Extract.h" @@ -28,11 +35,14 @@ #endif #include "BenchCon.h" +#include "ConsoleClose.h" #include "ExtractCallbackConsole.h" #include "List.h" #include "OpenCallbackConsole.h" #include "UpdateCallbackConsole.h" +#include "HashCon.h" + #if !defined(EXTERNAL_CODECS) && defined(_NO_CRYPTO) #define IT_IS_REDUCED_VERSION #endif @@ -80,42 +90,45 @@ static const char *kHelpString = " [<@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 : Add files to archive\n" + " b : Benchmark\n" + " d : Delete files from archive\n" + " e : Extract files from archive (without using directory names)\n" + " h : Calculate hash values for files\n" + " 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" + " rn : Rename files in archive\n" + " t : Test integrity of archive\n" + " u : Update files to archive\n" + " x : eXtract files with full paths\n" "\n" - " -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" + " -- : Stop switches parsing\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" + " -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"; + " -r[-|0] : Recurse subdirectories\n" + " -scs{UTF-8|UTF-16LE|UTF-16BE|WIN|DOS|{id}} : 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 @@ -124,21 +137,16 @@ 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 char *kUnsupportedUpdateArcType = "Can't create archive for that type"; static CFSTR kDefaultSfxModule = FTEXT("7zCon.sfx"); static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExitCode::EEnum code) { - s << message << endl; + s << endl << "Error: " << 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) { @@ -160,26 +168,253 @@ static void ShowCopyrightAndHelp(CStdOutStream &s, bool needHelp) } #ifdef EXTERNAL_CODECS + static void PrintString(CStdOutStream &stdStream, const AString &s, int size) { - int len = s.Length(); - stdStream << s; + int len = s.Len(); for (int i = len; i < size; i++) stdStream << ' '; + stdStream << s; +} + +static void PrintUInt32(CStdOutStream &stdStream, UInt32 val, int size) +{ + char s[16]; + ConvertUInt32ToString(val, s); + PrintString(stdStream, s, size); } + +static void PrintLibIndex(CStdOutStream &stdStream, int libIndex) +{ + if (libIndex >= 0) + PrintUInt32(stdStream, libIndex, 2); + else + stdStream << " "; + stdStream << ' '; +} + #endif static void PrintString(CStdOutStream &stdStream, const UString &s, int size) { - int len = s.Length(); + int len = s.Len(); stdStream << s; for (int i = len; i < size; i++) stdStream << ' '; } -static inline char GetHex(Byte value) +static inline char GetHex(unsigned val) +{ + return (char)((val < 10) ? ('0' + val) : ('A' + (val - 10))); +} + +static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback, + const CErrorInfo &errorInfo, CStdOutStream &stdStream) +{ + int exitCode = NExitCode::kSuccess; + + if (callback.CantFindFiles.Size() > 0) + { + stdStream << endl; + stdStream << "WARNINGS for files:" << endl << endl; + unsigned numErrors = callback.CantFindFiles.Size(); + for (unsigned i = 0; i < numErrors; i++) + { + stdStream << callback.CantFindFiles[i] << " : "; + stdStream << NError::MyFormatMessage(callback.CantFindCodes[i]) << endl; + } + stdStream << "----------------" << endl; + stdStream << "WARNING: Cannot find " << numErrors << " file"; + if (numErrors > 1) + stdStream << "s"; + stdStream << endl; + exitCode = NExitCode::kWarning; + } + + if (result != S_OK) + { + UString message; + if (!errorInfo.Message.IsEmpty()) + { + message += errorInfo.Message; + message += L"\n"; + } + if (!errorInfo.FileName.IsEmpty()) + { + message += fs2us(errorInfo.FileName); + message += L"\n"; + } + if (!errorInfo.FileName2.IsEmpty()) + { + message += fs2us(errorInfo.FileName2); + message += L"\n"; + } + if (errorInfo.SystemError != 0) + { + message += NError::MyFormatMessage(errorInfo.SystemError); + message += L"\n"; + } + if (!message.IsEmpty()) + stdStream << L"\nError:\n" << message; + + // we will work with (result) later + // throw CSystemException(result); + return NExitCode::kFatalError; + } + + unsigned 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 (unsigned i = 0; i < numErrors; i++) + { + stdStream << callback.FailedFiles[i] << " : "; + stdStream << NError::MyFormatMessage(callback.FailedCodes[i]) << endl; + } + stdStream << "----------------" << endl; + stdStream << "WARNING: Cannot open " << numErrors << " file"; + if (numErrors > 1) + stdStream << "s"; + stdStream << endl; + exitCode = NExitCode::kWarning; + } + return exitCode; +} + +static void ThrowException_if_Error(HRESULT res) +{ + if (res != S_OK) + throw CSystemException(res); +} + + +static void PrintNum(UInt64 val, unsigned numDigits, char c = ' ') +{ + char temp[64]; + char *p = temp + 32; + ConvertUInt64ToString(val, p); + unsigned len = MyStringLen(p); + for (; len < numDigits; len++) + *--p = c; + *g_StdStream << p; +} + +static void PrintTime(const char *s, UInt64 val, UInt64 total) +{ + *g_StdStream << endl << s << " Time ="; + const UInt32 kFreq = 10000000; + UInt64 sec = val / kFreq; + PrintNum(sec, 6); + *g_StdStream << '.'; + UInt32 ms = (UInt32)(val - (sec * kFreq)) / (kFreq / 1000); + PrintNum(ms, 3, '0'); + + while (val > ((UInt64)1 << 56)) + { + val >>= 1; + total >>= 1; + } + + UInt64 percent = 0; + if (total != 0) + percent = val * 100 / total; + *g_StdStream << " ="; + PrintNum(percent, 5); + *g_StdStream << '%'; +} + +#ifndef UNDER_CE + +#define SHIFT_SIZE_VALUE(x, num) (((x) + (1 << (num)) - 1) >> (num)) + +static void PrintMemUsage(const char *s, UInt64 val) { - return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); + *g_StdStream << " " << s << " Memory ="; + PrintNum(SHIFT_SIZE_VALUE(val, 20), 7); + *g_StdStream << " MB"; +} + +EXTERN_C_BEGIN +typedef BOOL (WINAPI *Func_GetProcessMemoryInfo)(HANDLE Process, + PPROCESS_MEMORY_COUNTERS ppsmemCounters, DWORD cb); +EXTERN_C_END + +#endif + +static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } + +static void PrintStat() +{ + FILETIME creationTimeFT, exitTimeFT, kernelTimeFT, userTimeFT; + if (! + #ifdef UNDER_CE + ::GetThreadTimes(::GetCurrentThread() + #else + // NT 3.5 + ::GetProcessTimes(::GetCurrentProcess() + #endif + , &creationTimeFT, &exitTimeFT, &kernelTimeFT, &userTimeFT)) + return; + FILETIME curTimeFT; + NTime::GetCurUtcFileTime(curTimeFT); + + #ifndef UNDER_CE + + PROCESS_MEMORY_COUNTERS m; + memset(&m, 0, sizeof(m)); + BOOL memDefined = FALSE; + { + /* NT 4.0: GetProcessMemoryInfo() in Psapi.dll + Win7: new function K32GetProcessMemoryInfo() in kernel32.dll + It's faster to call kernel32.dll code than Psapi.dll code + GetProcessMemoryInfo() requires Psapi.lib + Psapi.lib in SDK7+ can link to K32GetProcessMemoryInfo in kernel32.dll + The program with K32GetProcessMemoryInfo will not work on systems before Win7 + // memDefined = GetProcessMemoryInfo(GetCurrentProcess(), &m, sizeof(m)); + */ + + Func_GetProcessMemoryInfo my_GetProcessMemoryInfo = (Func_GetProcessMemoryInfo) + ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), "K32GetProcessMemoryInfo"); + if (!my_GetProcessMemoryInfo) + { + HMODULE lib = LoadLibraryW(L"Psapi.dll"); + if (lib) + my_GetProcessMemoryInfo = (Func_GetProcessMemoryInfo)::GetProcAddress(lib, "GetProcessMemoryInfo"); + } + if (my_GetProcessMemoryInfo) + memDefined = my_GetProcessMemoryInfo(GetCurrentProcess(), &m, sizeof(m)); + // FreeLibrary(lib); + } + + #endif + + UInt64 curTime = GetTime64(curTimeFT); + UInt64 creationTime = GetTime64(creationTimeFT); + UInt64 kernelTime = GetTime64(kernelTimeFT); + UInt64 userTime = GetTime64(userTimeFT); + + UInt64 totalTime = curTime - creationTime; + + PrintTime("Kernel ", kernelTime, totalTime); + PrintTime("User ", userTime, totalTime); + + PrintTime("Process", kernelTime + userTime, totalTime); + #ifndef UNDER_CE + if (memDefined) PrintMemUsage("Virtual ", m.PeakPagefileUsage); + #endif + + PrintTime("Global ", totalTime, totalTime); + #ifndef UNDER_CE + if (memDefined) PrintMemUsage("Physical", m.PeakWorkingSetSize); + #endif + + *g_StdStream << endl; } int Main2( @@ -191,7 +426,7 @@ int Main2( #if defined(_WIN32) && !defined(UNDER_CE) SetFileApisToOEM(); #endif - + UStringVector commandStrings; #ifdef _WIN32 NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); @@ -204,11 +439,12 @@ int Main2( ShowCopyrightAndHelp(g_StdOut, true); return 0; } + commandStrings.Delete(0); - CArchiveCommandLineOptions options; + CArcCmdLineOptions options; - CArchiveCommandLineParser parser; + CArcCmdLineParser parser; parser.Parse1(commandStrings, options); @@ -218,11 +454,16 @@ int Main2( return 0; } - #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) + #if defined(_WIN32) && !defined(UNDER_CE) + NSecurity::EnablePrivilege_SymLink(); + #endif + #ifdef _7ZIP_LARGE_PAGES if (options.LargePages) { SetLargePageSize(); - NSecurity::EnableLockMemoryPrivilege(); + #if defined(_WIN32) && !defined(UNDER_CE) + NSecurity::EnablePrivilege_LockMemory(); + #endif } #endif @@ -235,55 +476,98 @@ int Main2( 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); + #ifdef EXTERNAL_CODECS + CExternalCodecs __externalCodecs; + __externalCodecs.GetCodecs = codecs; + __externalCodecs.GetHashers = codecs; + #else + CMyComPtr compressCodecsInfo = codecs; + #endif + codecs->CaseSensitiveChange = options.CaseSensitiveChange; + codecs->CaseSensitive = options.CaseSensitive; + ThrowException_if_Error(codecs->Load()); bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); if (codecs->Formats.Size() == 0 && - (isExtractGroupCommand || - options.Command.CommandType == NCommandType::kList || - options.Command.IsFromUpdateGroup())) + (isExtractGroupCommand + || options.Command.CommandType == NCommandType::kList + || options.Command.IsFromUpdateGroup())) throw kNoFormats; - CIntVector formatIndices; - if (!codecs->FindFormatForArchiveType(options.ArcType, formatIndices)) + CObjectVector types; + if (!ParseOpenTypes(*codecs, options.ArcType, types)) throw kUnsupportedArcTypeMessage; + CIntVector excludedFormats; + FOR_VECTOR (k, options.ExcludedArcTypes) + { + CIntVector tempIndices; + if (!codecs->FindFormatForArchiveType(options.ExcludedArcTypes[k], tempIndices) + || tempIndices.Size() != 1) + throw kUnsupportedArcTypeMessage; + excludedFormats.AddToUniqueSorted(tempIndices[0]); + // excludedFormats.Sort(); + } + + + #ifdef EXTERNAL_CODECS + if (isExtractGroupCommand + || options.Command.CommandType == NCommandType::kHash + || options.Command.CommandType == NCommandType::kBenchmark) + ThrowException_if_Error(__externalCodecs.LoadCodecs()); + #endif + + int retCode = NExitCode::kSuccess; + HRESULT hresultMain = S_OK; + + bool showStat = true; + if (!options.EnableHeaders || + options.TechMode) + showStat = false; + + if (options.Command.CommandType == NCommandType::kInfo) { + unsigned i; + + #ifdef EXTERNAL_CODECS + stdStream << endl << "Libs:" << endl; + for (i = 0; i < codecs->Libs.Size(); i++) + { + PrintLibIndex(stdStream, i); + stdStream << ' ' << codecs->Libs[i].Path << endl; + } + #endif + stdStream << endl << "Formats:" << endl; - int i; + + const char *kArcFlags = "KSNFMGOPBELH"; + const unsigned kNumArcFlags = (unsigned)strlen(kArcFlags); + for (i = 0; i < codecs->Formats.Size(); i++) { const CArcInfoEx &arc = codecs->Formats[i]; #ifdef EXTERNAL_CODECS - if (arc.LibIndex >= 0) + PrintLibIndex(stdStream, arc.LibIndex); + #else + stdStream << " "; + #endif + stdStream << (char)(arc.UpdateEnabled ? 'C' : ' '); + for (unsigned b = 0; b < kNumArcFlags; b++) { - char s[16]; - ConvertUInt32ToString(arc.LibIndex, s); - PrintString(stdStream, s, 2); + stdStream << (char) + ((arc.Flags & ((UInt32)1 << b)) != 0 ? kArcFlags[b] : ' '); } - else - #endif - stdStream << " "; + + stdStream << ' '; + PrintString(stdStream, arc.Name, 8); 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++) + FOR_VECTOR (t, arc.Exts) { + if (t != 0) + s += L' '; const CArcExtInfo &ext = arc.Exts[t]; s += ext.Ext; if (!ext.AddExt.IsEmpty()) @@ -292,44 +576,46 @@ int Main2( 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++) + PrintString(stdStream, s, 13); + stdStream << ' '; + if (arc.SignatureOffset != 0) + stdStream << "offset=" << arc.SignatureOffset << ' '; + + FOR_VECTOR(si, arc.Signatures) { - Byte b = sig[j]; - if (b > 0x20 && b < 0x80) - { - stdStream << (char)b; - } - else + if (si != 0) + stdStream << " || "; + + const CByteBuffer &sig = arc.Signatures[si]; + + for (size_t j = 0; j < sig.Size(); j++) { - stdStream << GetHex((Byte)((b >> 4) & 0xF)); - stdStream << GetHex((Byte)(b & 0xF)); + if (j != 0) + stdStream << ' '; + Byte b = sig[j]; + if (b > 0x20 && b < 0x80) + { + stdStream << (char)b; + } + else + { + stdStream << GetHex((b >> 4) & 0xF); + stdStream << GetHex(b & 0xF); + } } - stdStream << ' '; } stdStream << endl; } - stdStream << endl << "Codecs:" << endl; #ifdef EXTERNAL_CODECS + + stdStream << endl << "Codecs:" << endl << "Lib ID Name" << endl; 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 << ' '; + PrintLibIndex(stdStream, codecs->GetCodecLibIndex(j)); stdStream << (char)(codecs->GetCodecEncoderIsAssigned(j) ? 'C' : ' '); UInt64 id; stdStream << " "; @@ -337,43 +623,36 @@ int Main2( if (res != S_OK) id = (UInt64)(Int64)-1; char s[32]; - ConvertUInt64ToString(id, s, 16); + ConvertUInt64ToHex(id, s); PrintString(stdStream, s, 8); - stdStream << " "; - PrintString(stdStream, codecs->GetCodecName(j), 11); - stdStream << endl; - /* - if (res != S_OK) - throw "incorrect Codec ID"; - */ + stdStream << " " << codecs->GetCodecName(j) << endl; } + + stdStream << endl << "Hashers:" << endl << " L Size ID Name" << endl; + numMethods = codecs->GetNumHashers(); + for (UInt32 j = 0; j < numMethods; j++) + { + PrintLibIndex(stdStream, codecs->GetHasherLibIndex(j)); + PrintUInt32(stdStream, codecs->GetHasherDigestSize(j), 4); + stdStream << ' '; + char s[32]; + ConvertUInt64ToHex(codecs->GetHasherId(j), s); + PrintString(stdStream, s, 6); + stdStream << " " << codecs->GetHasherName(j) << endl; + } + #endif - return S_OK; + } else if (options.Command.CommandType == NCommandType::kBenchmark) { + hresultMain = BenchCon(EXTERNAL_CODECS_VARS + options.Properties, options.NumIterations, (FILE *)stdStream); + if (hresultMain == S_FALSE) { - HRESULT res; - #ifdef EXTERNAL_CODECS - CObjectVector externalCodecs; - res = LoadExternalCodecs(compressCodecsInfo, externalCodecs); - if (res != S_OK) - throw CSystemException(res); - #endif - res = BenchCon( - #ifdef EXTERNAL_CODECS - compressCodecsInfo, &externalCodecs, - #endif - options.Properties, options.NumIterations, (FILE *)stdStream); - if (res != S_OK) - { - if (res == S_FALSE) - { - stdStream << "\nDecoding Error\n"; - return NExitCode::kFatalError; - } - throw CSystemException(res); - } + stdStream << "\nDecoding Error\n"; + retCode = NExitCode::kFatalError; + hresultMain = S_OK; } } else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) @@ -401,90 +680,145 @@ int Main2( #endif CExtractOptions eo; + (CExtractOptionsBase &)eo = options.ExtractOptions; 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.TestMode = options.Command.IsTestCommand(); + + #ifndef _SFX eo.Properties = options.Properties; #endif + UString errorMessage; CDecompressStat stat; - HRESULT result = DecompressArchives( + CHashBundle hb; + IHashCalc *hashCalc = NULL; + + if (!options.HashMethods.IsEmpty()) + { + hashCalc = &hb; + ThrowException_if_Error(hb.SetMethods(EXTERNAL_CODECS_VARS options.HashMethods)); + hb.Init(); + } + hresultMain = Extract( codecs, - formatIndices, + types, + excludedFormats, options.ArchivePathsSorted, options.ArchivePathsFullSorted, - options.WildcardCensor.Pairs.Front().Head, - eo, &openCallback, ecs, errorMessage, stat); + options.Censor.Pairs.Front().Head, + eo, &openCallback, ecs, hashCalc, errorMessage, stat); if (!errorMessage.IsEmpty()) { stdStream << endl << "Error: " << errorMessage; - if (result == S_OK) - result = E_FAIL; + if (hresultMain == S_OK) + hresultMain = E_FAIL; } stdStream << endl; - if (ecs->NumArchives > 1) - stdStream << "Archives: " << ecs->NumArchives << endl; - if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0) + + if (ecs->NumTryArcs > 1) { - if (ecs->NumArchives > 1) + stdStream << "Archives: " << ecs->NumTryArcs << endl; + stdStream << "OK archives: " << ecs->NumOkArcs << endl; + } + bool isError = false; + if (ecs->NumCantOpenArcs != 0) + { + isError = true; + stdStream << "Can't open as archive: " << ecs->NumCantOpenArcs << endl; + } + if (ecs->NumArcsWithError != 0) + { + isError = true; + stdStream << "Archives with Errors: " << ecs->NumArcsWithError << endl; + } + if (ecs->NumArcsWithWarnings != 0) + stdStream << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl; + + if (ecs->NumOpenArcWarnings != 0) + { + stdStream << endl; + if (ecs->NumOpenArcWarnings != 0) + stdStream << "Warnings: " << ecs->NumOpenArcWarnings << endl; + } + + if (ecs->NumOpenArcErrors != 0) + { + isError = true; + stdStream << endl; + if (ecs->NumOpenArcErrors != 0) + stdStream << "Open Errors: " << ecs->NumOpenArcErrors << endl; + } + + if (isError) + retCode = NExitCode::kFatalError; + + if (ecs->NumArcsWithError != 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); + else if (hresultMain == S_OK) + { + if (stat.NumFolders != 0) stdStream << "Folders: " << stat.NumFolders << endl; - if (stat.NumFiles != 1 || stat.NumFolders != 0) - stdStream << "Files: " << stat.NumFiles << endl; + if (stat.NumFiles != 1 || stat.NumFolders != 0 || stat.NumAltStreams != 0) + stdStream << "Files: " << stat.NumFiles << endl; + if (stat.NumAltStreams != 0) + { + stdStream << "Alternate Streams: " << stat.NumAltStreams << endl; + stdStream << "Alternate Streams Size: " << stat.AltStreams_UnpackSize << endl; + } + stdStream << "Size: " << stat.UnpackSize << endl << "Compressed: " << stat.PackSize << endl; - if (options.CalcCrc) - { - char s[16]; - ConvertUInt32ToHexWithZeros(stat.CrcSum, s); - stdStream << "CRC: " << s << endl; + if (hashCalc) + PrintHashStat(stdStream, hb); } } else { UInt64 numErrors = 0; - HRESULT result = ListArchives( + UInt64 numWarnings = 0; + + // options.ExtractNtOptions.StoreAltStreams = true, if -sns[-] is not definmed + + hresultMain = ListArchives( codecs, - formatIndices, + types, + excludedFormats, options.StdInMode, options.ArchivePathsSorted, options.ArchivePathsFullSorted, - options.WildcardCensor.Pairs.Front().Head, + options.ExtractOptions.NtOptions.AltStreams.Val, + options.AltStreams.Val, // we don't want to show AltStreams by default + options.Censor.Pairs.Front().Head, options.EnableHeaders, options.TechMode, #ifndef _NO_CRYPTO options.PasswordEnabled, options.Password, #endif - numErrors); + &options.Properties, + numErrors, numWarnings); + + if (options.EnableHeaders) + if (numWarnings > 0) + g_StdOut << endl << "Warnings: " << numWarnings << endl; if (numErrors > 0) { - g_StdOut << endl << "Errors: " << numErrors << endl; - return NExitCode::kFatalError; + if (options.EnableHeaders) + g_StdOut << endl << "Errors: " << numErrors << endl; + retCode = NExitCode::kFatalError; } - if (result != S_OK) - throw CSystemException(result); } } else if (options.Command.IsFromUpdateGroup()) @@ -516,83 +850,42 @@ int Main2( CUpdateErrorInfo errorInfo; - if (!uo.Init(codecs, formatIndices, options.ArchiveName)) - throw kUnsupportedArcTypeMessage; - HRESULT result = UpdateArchive(codecs, - options.WildcardCensor, uo, - errorInfo, &openCallback, &callback); + /* + if (!uo.Init(codecs, types, options.ArchiveName)) + throw kUnsupportedUpdateArcType; + */ + hresultMain = UpdateArchive(codecs, + types, + options.ArchiveName, + options.Censor, + uo, + errorInfo, &openCallback, &callback, true); + retCode = WarningsCheck(hresultMain, callback, errorInfo, stdStream); + } + else if (options.Command.CommandType == NCommandType::kHash) + { + const CHashOptions &uo = options.HashOptions; - 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; - } + CHashCallbackConsole callback; + callback.EnablePercents = options.EnablePercents; - if (result != S_OK) - { - UString message; - if (!errorInfo.Message.IsEmpty()) - { - message += errorInfo.Message; - message += L"\n"; - } - if (!errorInfo.FileName.IsEmpty()) - { - message += fs2us(errorInfo.FileName); - message += L"\n"; - } - if (!errorInfo.FileName2.IsEmpty()) - { - message += fs2us(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; + callback.Init(&stdStream); + + UString errorInfoString; + hresultMain = HashCalc(EXTERNAL_CODECS_VARS + options.Censor, uo, + errorInfoString, &callback); + CErrorInfo errorInfo; + errorInfo.Message = errorInfoString; + retCode = WarningsCheck(hresultMain, callback, errorInfo, stdStream); } else - PrintHelpAndExit(stdStream); - return 0; + ShowMessageAndThrowException(stdStream, kUserErrorMessage, NExitCode::kUserError); + + if (showStat) + PrintStat(); + + ThrowException_if_Error(hresultMain); + + return retCode; } diff --git a/CPP/7zip/UI/Console/MainAr.cpp b/CPP/7zip/UI/Console/MainAr.cpp old mode 100755 new mode 100644 index 25f4bd0d..1cb01689 --- a/CPP/7zip/UI/Console/MainAr.cpp +++ b/CPP/7zip/UI/Console/MainAr.cpp @@ -2,11 +2,11 @@ #include "StdAfx.h" -#include "Common/MyException.h" -#include "Common/StdOutStream.h" +#include "../../../Common/MyException.h" +#include "../../../Common/StdOutStream.h" -#include "Windows/Error.h" -#include "Windows/NtCheck.h" +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/NtCheck.h" #include "../Common/ArchiveCommandLine.h" #include "../Common/ExitCode.h" @@ -23,6 +23,7 @@ extern int Main2( #endif ); +static const char *kException_CmdLine_Error_Message = "\n\nCommand Line Error:\n"; static const char *kExceptionErrorMessage = "\n\nError:\n"; static const char *kUserBreak = "\nBreak signaled\n"; static const char *kMemoryExceptionMessage = "\n\nERROR: Can't allocate required memory!\n"; @@ -62,9 +63,9 @@ int MY_CDECL main (*g_StdStream) << endl << kUserBreak; return (NExitCode::kUserBreak); } - catch(const CArchiveCommandLineException &e) + catch(const CArcCmdLineException &e) { - (*g_StdStream) << kExceptionErrorMessage << e << endl; + (*g_StdStream) << kException_CmdLine_Error_Message << e << endl; return (NExitCode::kUserError); } catch(const CSystemException &systemError) @@ -80,7 +81,7 @@ int MY_CDECL main return (NExitCode::kUserBreak); } (*g_StdStream) << endl << endl << "System error:" << endl << - NError::MyFormatMessageW(systemError.ErrorCode) << endl; + NError::MyFormatMessage(systemError.ErrorCode) << endl; return (NExitCode::kFatalError); } catch(NExitCode::EEnum &exitCode) @@ -120,5 +121,5 @@ int MY_CDECL main (*g_StdStream) << kUnknownExceptionMessage; return (NExitCode::kFatalError); } - return res; + return res; } diff --git a/CPP/7zip/UI/Console/OpenCallbackConsole.cpp b/CPP/7zip/UI/Console/OpenCallbackConsole.cpp old mode 100755 new mode 100644 index 7dba2ad5..f64fd493 --- a/CPP/7zip/UI/Console/OpenCallbackConsole.cpp +++ b/CPP/7zip/UI/Console/OpenCallbackConsole.cpp @@ -38,10 +38,10 @@ HRESULT COpenCallbackConsole::Open_CryptoGetTextPassword(BSTR *password) return StringToBstr(Password, password); } -HRESULT COpenCallbackConsole::Open_GetPasswordIfAny(UString &password) +HRESULT COpenCallbackConsole::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) { - if (PasswordIsDefined) - password = Password; + passwordIsDefined = PasswordIsDefined; + password = Password; return S_OK; } diff --git a/CPP/7zip/UI/Console/OpenCallbackConsole.h b/CPP/7zip/UI/Console/OpenCallbackConsole.h old mode 100755 new mode 100644 index c002e6a7..5828af99 --- a/CPP/7zip/UI/Console/OpenCallbackConsole.h +++ b/CPP/7zip/UI/Console/OpenCallbackConsole.h @@ -1,9 +1,10 @@ // OpenCallbackConsole.h -#ifndef __OPENCALLBACKCONSOLE_H -#define __OPENCALLBACKCONSOLE_H +#ifndef __OPEN_CALLBACK_CONSOLE_H +#define __OPEN_CALLBACK_CONSOLE_H + +#include "../../../Common/StdOutStream.h" -#include "Common/StdOutStream.h" #include "../Common/ArchiveOpenCallback.h" class COpenCallbackConsole: public IOpenCallbackUI diff --git a/CPP/7zip/UI/Console/PercentPrinter.cpp b/CPP/7zip/UI/Console/PercentPrinter.cpp old mode 100755 new mode 100644 index 786db1bc..f2889957 --- a/CPP/7zip/UI/Console/PercentPrinter.cpp +++ b/CPP/7zip/UI/Console/PercentPrinter.cpp @@ -2,8 +2,8 @@ #include "StdAfx.h" -#include "Common/IntToString.h" -#include "Common/MyString.h" +#include "../../../Common/Defs.h" +#include "../../../Common/IntToString.h" #include "PercentPrinter.h" diff --git a/CPP/7zip/UI/Console/PercentPrinter.h b/CPP/7zip/UI/Console/PercentPrinter.h old mode 100755 new mode 100644 index d970cc4b..509bab5f --- a/CPP/7zip/UI/Console/PercentPrinter.h +++ b/CPP/7zip/UI/Console/PercentPrinter.h @@ -3,7 +3,7 @@ #ifndef __PERCENT_PRINTER_H #define __PERCENT_PRINTER_H -#include "Common/StdOutStream.h" +#include "../../../Common/StdOutStream.h" class CPercentPrinter { diff --git a/CPP/7zip/UI/Console/StdAfx.cpp b/CPP/7zip/UI/Console/StdAfx.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/Console/StdAfx.h b/CPP/7zip/UI/Console/StdAfx.h old mode 100755 new mode 100644 index 2e4be10b..2854ff3e --- a/CPP/7zip/UI/Console/StdAfx.h +++ b/CPP/7zip/UI/Console/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Common/MyWindows.h" -#include "../../../Common/NewHandler.h" +#include "../../../Common/Common.h" #endif diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp old mode 100755 new mode 100644 index 7f337319..749021c4 --- a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp +++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp @@ -2,15 +2,14 @@ #include "StdAfx.h" -#include "UpdateCallbackConsole.h" - -#include "Windows/Error.h" +#include "../../../Windows/ErrorMsg.h" #ifndef _7ZIP_ST -#include "Windows/Synchronization.h" +#include "../../../Windows/Synchronization.h" #endif #include "ConsoleClose.h" #include "UserInputUtils.h" +#include "UpdateCallbackConsole.h" using namespace NWindows; @@ -28,11 +27,18 @@ static const char *kUpdatingArchiveMessage = "Updating archive "; static const char *kScanningMessage = "Scanning"; -HRESULT CUpdateCallbackConsole::OpenResult(const wchar_t *name, HRESULT result) +HRESULT CUpdateCallbackConsole::OpenResult(const wchar_t *name, HRESULT result, const wchar_t *errorArcType) { (*OutStream) << endl; if (result != S_OK) - (*OutStream) << "Error: " << name << " is not supported archive" << endl; + { + (*OutStream) << "Error: " << name; + if (errorArcType) + (*OutStream) << " : can not open the file as [" << errorArcType << "] archive"; + else + (*OutStream) << " is not supported archive"; + (*OutStream) << endl; + } return S_OK; } @@ -42,12 +48,12 @@ HRESULT CUpdateCallbackConsole::StartScanning() return S_OK; } -HRESULT CUpdateCallbackConsole::ScanProgress(UInt64 /* numFolders */, UInt64 /* numFiles */, const wchar_t * /* path */) +HRESULT CUpdateCallbackConsole::ScanProgress(UInt64 /* numFolders */, UInt64 /* numFiles */, UInt64 /* totalSize */, const wchar_t * /* path */, bool /* isDir */) { return CheckBreak(); } -HRESULT CUpdateCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError) +HRESULT CCallbackConsoleBase::CanNotFindError_Base(const wchar_t *name, DWORD systemError) { CantFindFiles.Add(name); CantFindCodes.Add(systemError); @@ -60,11 +66,16 @@ HRESULT CUpdateCallbackConsole::CanNotFindError(const wchar_t *name, DWORD syste } m_PercentPrinter.PrintString(name); m_PercentPrinter.PrintString(": WARNING: "); - m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError)); + m_PercentPrinter.PrintString(NError::MyFormatMessage(systemError)); m_PercentPrinter.PrintNewLine(); return S_OK; } +HRESULT CUpdateCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError) +{ + return CanNotFindError_Base(name, systemError); +} + HRESULT CUpdateCallbackConsole::FinishScanning() { (*OutStream) << endl << endl; @@ -176,15 +187,19 @@ HRESULT CUpdateCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemE MT_LOCK FailedCodes.Add(systemError); FailedFiles.Add(name); - // if (systemError == ERROR_SHARING_VIOLATION) + /* + if (systemError == ERROR_SHARING_VIOLATION) { + */ m_PercentPrinter.ClosePrint(); m_PercentPrinter.PrintNewLine(); m_PercentPrinter.PrintString("WARNING: "); - m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError)); + m_PercentPrinter.PrintString(NError::MyFormatMessage(systemError)); return S_FALSE; + /* } - // return systemError; + return systemError; + */ } HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 ) diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.h b/CPP/7zip/UI/Console/UpdateCallbackConsole.h old mode 100755 new mode 100644 index 5ffe3eb7..77e0e178 --- a/CPP/7zip/UI/Console/UpdateCallbackConsole.h +++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.h @@ -3,55 +3,39 @@ #ifndef __UPDATE_CALLBACK_CONSOLE_H #define __UPDATE_CALLBACK_CONSOLE_H -#include "Common/StdOutStream.h" +#include "../../../Common/StdOutStream.h" #include "../Common/Update.h" #include "PercentPrinter.h" -class CUpdateCallbackConsole: public IUpdateCallbackUI2 +class CCallbackConsoleBase { - CPercentPrinter m_PercentPrinter; - bool m_NeedBeClosed; - bool m_NeedNewLine; - bool m_WarningsMode; +protected: + CPercentPrinter m_PercentPrinter; CStdOutStream *OutStream; + HRESULT CanNotFindError_Base(const wchar_t *name, DWORD systemError); public: bool EnablePercents; bool StdOutMode; - #ifndef _NO_CRYPTO - bool PasswordIsDefined; - UString Password; - bool AskPassword; - #endif - - CUpdateCallbackConsole(): + CCallbackConsoleBase(): 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; @@ -59,4 +43,33 @@ public: CRecordVector CantFindCodes; }; +class CUpdateCallbackConsole: public IUpdateCallbackUI2, public CCallbackConsoleBase +{ + bool m_NeedBeClosed; + bool m_NeedNewLine; +public: + #ifndef _NO_CRYPTO + bool PasswordIsDefined; + UString Password; + bool AskPassword; + #endif + + CUpdateCallbackConsole() + #ifndef _NO_CRYPTO + : + PasswordIsDefined(false), + AskPassword(false) + #endif + {} + + void Init(CStdOutStream *outStream) + { + m_NeedBeClosed = false; + m_NeedNewLine = false; + CCallbackConsoleBase::Init(outStream); + } + ~CUpdateCallbackConsole() { Finilize(); } + INTERFACE_IUpdateCallbackUI2(;) +}; + #endif diff --git a/CPP/7zip/UI/Console/UserInputUtils.cpp b/CPP/7zip/UI/Console/UserInputUtils.cpp old mode 100755 new mode 100644 index 75468009..a0d4af38 --- a/CPP/7zip/UI/Console/UserInputUtils.cpp +++ b/CPP/7zip/UI/Console/UserInputUtils.cpp @@ -2,17 +2,17 @@ #include "StdAfx.h" -#include "Common/StdInStream.h" -#include "Common/StringConvert.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 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 = @@ -30,25 +30,14 @@ NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream) AString scannedString = g_StdIn.ScanStringUntilNewLine(); scannedString.Trim(); if (!scannedString.IsEmpty()) - switch( - ::MyCharUpper( - #ifdef UNDER_CE - (wchar_t) - #endif - scannedString[0])) + switch(::MyCharLower_Ascii(scannedString[0])) { - case kYes: - return NUserAnswerMode::kYes; - case kNo: - return NUserAnswerMode::kNo; - case kYesAll: - return NUserAnswerMode::kYesAll; - case kNoAll: - return NUserAnswerMode::kNoAll; - case kAutoRenameAll: - return NUserAnswerMode::kAutoRenameAll; - case kQuit: - return NUserAnswerMode::kQuit; + 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; } } } diff --git a/CPP/7zip/UI/Console/UserInputUtils.h b/CPP/7zip/UI/Console/UserInputUtils.h old mode 100755 new mode 100644 index 8b5232b3..16f04580 --- a/CPP/7zip/UI/Console/UserInputUtils.h +++ b/CPP/7zip/UI/Console/UserInputUtils.h @@ -1,9 +1,9 @@ // UserInputUtils.h -#ifndef __USERINPUTUTILS_H -#define __USERINPUTUTILS_H +#ifndef __USER_INPUT_UTILS_H +#define __USER_INPUT_UTILS_H -#include "Common/StdOutStream.h" +#include "../../../Common/StdOutStream.h" namespace NUserAnswerMode { diff --git a/CPP/7zip/UI/Console/makefile b/CPP/7zip/UI/Console/makefile old mode 100755 new mode 100644 index f100f635..efabf91c --- a/CPP/7zip/UI/Console/makefile +++ b/CPP/7zip/UI/Console/makefile @@ -1,24 +1,13 @@ PROG = 7z.exe MY_CONSOLE = 1 -CFLAGS = $(CFLAGS) -I ../../../ \ +CFLAGS = $(CFLAGS) \ -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 \ +CURRENT_OBJS = \ COMMON_OBJS = \ $O\CommandLineParser.obj \ @@ -37,88 +26,46 @@ COMMON_OBJS = \ WIN_OBJS = \ $O\DLL.obj \ - $O\Error.obj \ + $O\ErrorMsg.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ + $O\FileLink.obj \ $O\FileName.obj \ + $O\FileSystem.obj \ $O\MemoryLock.obj \ $O\PropVariant.obj \ - $O\PropVariantConversions.obj \ + $O\PropVariantConv.obj \ $O\Registry.obj \ $O\System.obj \ - $O\Time.obj \ + $O\TimeUtils.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ $O\FilterCoder.obj \ + $O\LimitedStreams.obj \ $O\MethodProps.obj \ $O\ProgressUtils.obj \ + $O\PropId.obj \ + $O\StreamObjects.obj \ $O\StreamUtils.obj \ - -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\UniqBlocks.obj \ AR_COMMON_OBJS = \ $O\OutStreamWithCRC.obj \ +COMPRESS_OBJS = \ + $O\CopyCoder.obj \ + C_OBJS = \ $O\Alloc.obj \ $O\CpuArch.obj \ + $O\Sort.obj \ $O\Threads.obj \ !include "../../Crc.mak" +!include "Console.mak" -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" +!include "../../7zip.mak" diff --git a/CPP/7zip/UI/Console/resource.rc b/CPP/7zip/UI/Console/resource.rc old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/Explorer/7-zip.dll.manifest b/CPP/7zip/UI/Explorer/7-zip.dll.manifest old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/Explorer/ContextMenu.cpp b/CPP/7zip/UI/Explorer/ContextMenu.cpp old mode 100755 new mode 100644 index 4bdc397a..29ad4945 --- a/CPP/7zip/UI/Explorer/ContextMenu.cpp +++ b/CPP/7zip/UI/Explorer/ContextMenu.cpp @@ -2,19 +2,17 @@ #include "StdAfx.h" -#include "ContextMenu.h" - -#include "Common/StringConvert.h" - -#include "Windows/COM.h" -#include "Windows/DLL.h" -#include "Windows/FileDir.h" -#include "Windows/FileFind.h" -#include "Windows/FileName.h" -#include "Windows/Memory.h" -#include "Windows/Menu.h" -#include "Windows/Process.h" -#include "Windows/Shell.h" +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/COM.h" +#include "../../../Windows/DLL.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/MemoryGlobal.h" +#include "../../../Windows/Menu.h" +#include "../../../Windows/ProcessUtils.h" +#include "../../../Windows/Shell.h" #include "../Common/ArchiveName.h" #include "../Common/CompressCall.h" @@ -27,29 +25,49 @@ #include "../FileManager/LangUtils.h" #endif +#include "ContextMenu.h" #include "ContextMenuFlags.h" #include "MyMessages.h" #include "resource.h" using namespace NWindows; - +using namespace NFile; +using namespace NDir; #ifndef UNDER_CE #define EMAIL_SUPPORT 1 #endif extern LONG g_DllRefCount; + +#ifdef _WIN32 +extern HINSTANCE g_hInstance; +#endif -CZipContextMenu::CZipContextMenu() { InterlockedIncrement(&g_DllRefCount); } -CZipContextMenu::~CZipContextMenu() { InterlockedDecrement(&g_DllRefCount); } +CZipContextMenu::CZipContextMenu(): + _isMenuForFM(false), + _bitmap(NULL) +{ + InterlockedIncrement(&g_DllRefCount); + _bitmap = ::LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_MENU_LOGO)); +} + +CZipContextMenu::~CZipContextMenu() +{ + if (_bitmap != NULL) + DeleteObject(_bitmap); + InterlockedDecrement(&g_DllRefCount); +} HRESULT CZipContextMenu::GetFileNames(LPDATAOBJECT dataObject, UStringVector &fileNames) { - #ifndef UNDER_CE fileNames.Clear(); if (dataObject == NULL) return E_FAIL; + + #ifndef UNDER_CE + FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; NCOM::CStgMedium stgMedium; HRESULT result = dataObject->GetData(&fmte, &stgMedium); @@ -61,7 +79,9 @@ HRESULT CZipContextMenu::GetFileNames(LPDATAOBJECT dataObject, UStringVector &fi NMemory::CGlobalLock globalLock(stgMedium->hGlobal); drop.Attach((HDROP)globalLock.GetPointer()); drop.QueryFileNames(fileNames); + #endif + return S_OK; } @@ -79,7 +99,7 @@ STDMETHODIMP CZipContextMenu::Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT { // OutputDebugString(path); // OutputDebugString(TEXT("\r\n")); - NFile::NName::NormalizeDirPathPrefix(_dropPath); + NName::NormalizeDirPathPrefix(_dropPath); _dropMode = !_dropPath.IsEmpty(); } else @@ -95,8 +115,9 @@ STDMETHODIMP CZipContextMenu::Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT return GetFileNames(dataObject, _fileNames); } -HRESULT CZipContextMenu::InitContextMenu(const wchar_t * /* folder */, const wchar_t **names, UInt32 numFiles) +HRESULT CZipContextMenu::InitContextMenu(const wchar_t * /* folder */, const wchar_t **names, unsigned numFiles) { + _isMenuForFM = true; _fileNames.Clear(); for (UInt32 i = 0; i < numFiles; i++) _fileNames.Add(names[i]); @@ -109,6 +130,8 @@ HRESULT CZipContextMenu::InitContextMenu(const wchar_t * /* folder */, const wch // IContextMenu static LPCWSTR kMainVerb = L"SevenZip"; +static LPCWSTR kOpenCascadedVerb = L"SevenZip.OpenWithType."; +static LPCWSTR kCheckSumCascadedVerb = L"SevenZip.Checksum"; /* static LPCTSTR kOpenVerb = TEXT("SevenOpen"); @@ -128,147 +151,148 @@ struct CContextMenuCommand CZipContextMenu::ECommandInternalID CommandInternalID; LPCWSTR Verb; UINT ResourceID; - UINT ResourceHelpID; - UInt32 LangID; }; -static CContextMenuCommand g_Commands[] = +static const CContextMenuCommand g_Commands[] = { { NContextMenuFlags::kOpen, CZipContextMenu::kOpen, L"Open", - IDS_CONTEXT_OPEN, - IDS_CONTEXT_OPEN_HELP, - 0x02000103 + IDS_CONTEXT_OPEN }, { NContextMenuFlags::kExtract, CZipContextMenu::kExtract, L"Extract", - IDS_CONTEXT_EXTRACT, - IDS_CONTEXT_EXTRACT_HELP, - 0x02000105 + IDS_CONTEXT_EXTRACT }, { NContextMenuFlags::kExtractHere, CZipContextMenu::kExtractHere, L"ExtractHere", - IDS_CONTEXT_EXTRACT_HERE, - IDS_CONTEXT_EXTRACT_HERE_HELP, - 0x0200010B + IDS_CONTEXT_EXTRACT_HERE }, { NContextMenuFlags::kExtractTo, CZipContextMenu::kExtractTo, L"ExtractTo", - IDS_CONTEXT_EXTRACT_TO, - IDS_CONTEXT_EXTRACT_TO_HELP, - 0x0200010D + IDS_CONTEXT_EXTRACT_TO }, { NContextMenuFlags::kTest, CZipContextMenu::kTest, L"Test", - IDS_CONTEXT_TEST, - IDS_CONTEXT_TEST_HELP, - 0x02000109 + IDS_CONTEXT_TEST }, { NContextMenuFlags::kCompress, CZipContextMenu::kCompress, L"Compress", - IDS_CONTEXT_COMPRESS, - IDS_CONTEXT_COMPRESS_HELP, - 0x02000107, + IDS_CONTEXT_COMPRESS }, { NContextMenuFlags::kCompressEmail, CZipContextMenu::kCompressEmail, L"CompressEmail", - IDS_CONTEXT_COMPRESS_EMAIL, - IDS_CONTEXT_COMPRESS_EMAIL_HELP, - 0x02000111 + IDS_CONTEXT_COMPRESS_EMAIL }, { NContextMenuFlags::kCompressTo7z, CZipContextMenu::kCompressTo7z, L"CompressTo7z", - IDS_CONTEXT_COMPRESS_TO, - IDS_CONTEXT_COMPRESS_TO_HELP, - 0x0200010F + IDS_CONTEXT_COMPRESS_TO }, { NContextMenuFlags::kCompressTo7zEmail, CZipContextMenu::kCompressTo7zEmail, L"CompressTo7zEmail", - IDS_CONTEXT_COMPRESS_TO_EMAIL, - IDS_CONTEXT_COMPRESS_TO_EMAIL_HELP, - 0x02000113 + IDS_CONTEXT_COMPRESS_TO_EMAIL }, { NContextMenuFlags::kCompressToZip, CZipContextMenu::kCompressToZip, L"CompressToZip", - IDS_CONTEXT_COMPRESS_TO, - IDS_CONTEXT_COMPRESS_TO_HELP, - 0x0200010F + IDS_CONTEXT_COMPRESS_TO }, { NContextMenuFlags::kCompressToZipEmail, CZipContextMenu::kCompressToZipEmail, L"CompressToZipEmail", - IDS_CONTEXT_COMPRESS_TO_EMAIL, - IDS_CONTEXT_COMPRESS_TO_EMAIL_HELP, - 0x02000113 + IDS_CONTEXT_COMPRESS_TO_EMAIL } }; +struct CHashCommand +{ + CZipContextMenu::ECommandInternalID CommandInternalID; + LPCWSTR UserName; + LPCWSTR MethodName; +}; + +static const CHashCommand g_HashCommands[] = +{ + { CZipContextMenu::kHash_CRC32, L"CRC-32", L"CRC32" }, + { CZipContextMenu::kHash_CRC64, L"CRC-64", L"CRC64" }, + { CZipContextMenu::kHash_SHA1, L"SHA-1", L"SHA1" }, + { CZipContextMenu::kHash_SHA256, L"SHA-256", L"SHA256" }, + { CZipContextMenu::kHash_All, L"*", L"*" } +}; + static int FindCommand(CZipContextMenu::ECommandInternalID &id) { - for (int i = 0; i < sizeof(g_Commands) / sizeof(g_Commands[0]); i++) + for (int i = 0; i < ARRAY_SIZE(g_Commands); i++) if (g_Commands[i].CommandInternalID == id) return i; return -1; } -void CZipContextMenu::FillCommand(ECommandInternalID id, UString &mainString, CCommandMapItem &commandMapItem) +bool CZipContextMenu::FillCommand(ECommandInternalID id, UString &mainString, CCommandMapItem &commandMapItem) { + mainString.Empty(); int i = FindCommand(id); if (i < 0) - return; + return false; 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); + // LangString(command.ResourceHelpID, command.LangID + 1, commandMapItem.HelpString); + LangString(command.ResourceID, mainString); + return true; } -static bool MyInsertMenu(CMenu &menu, int pos, UINT id, const UString &s) +static bool MyInsertMenu(CMenu &menu, int pos, UINT id, const UString &s, HBITMAP bitmap) { - CMenuItem menuItem; - menuItem.fType = MFT_STRING; - menuItem.fMask = MIIM_TYPE | MIIM_ID; - menuItem.wID = id; - menuItem.StringValue = s; - return menu.InsertItem(pos, true, menuItem); + CMenuItem mi; + mi.fType = MFT_STRING; + mi.fMask = MIIM_TYPE | MIIM_ID; + if (bitmap) + mi.fMask |= MIIM_CHECKMARKS; + mi.wID = id; + mi.StringValue = s; + mi.hbmpUnchecked = bitmap; + // mi.hbmpChecked = bitmap; // do we need hbmpChecked ??? + return menu.InsertItem(pos, true, mi); + + // SetMenuItemBitmaps also works + // ::SetMenuItemBitmaps(menu, pos, MF_BYPOSITION, bitmap, NULL); } -static const wchar_t *kArcExts[] = +static const char *kArcExts[] = { - L"7z", - L"bz2", - L"gz", - L"rar", - L"zip" + "7z" + , "bz2" + , "gz" + , "rar" + , "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) + ext.MakeLower_Ascii(); + for (unsigned i = 0; i < ARRAY_SIZE(kArcExts); i++) + if (ext.IsEqualTo(kArcExts[i])) return true; return false; } @@ -277,37 +301,40 @@ 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); + { + return GetCorrectFsPath(archiveName) + L"~"; + } + const UString ext = archiveName.Ptr(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); + const UString ext2 = res.Ptr(dotPos + 1); + if (ext.IsEqualToNoCase(L"rar") && + (ext2.IsEqualToNoCase(L"part001") || + ext2.IsEqualToNoCase(L"part01") || + ext2.IsEqualToNoCase(L"part1")) || + IsItArcExt(ext2) && ext.IsEqualToNoCase(L"001")) + res.DeleteFrom(dotPos); res.TrimRight(); } return GetCorrectFullFsPath(res); } -static UString GetReducedString(const UString &s) +static void ReduceString(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); + const unsigned kMaxSize = 64; + if (s.Len() <= kMaxSize) + return; + s.Delete(kMaxSize / 2, s.Len() - kMaxSize); + s.Insert(kMaxSize / 2, L" ... "); } static UString GetQuotedReducedString(const UString &s) { - UString s2 = GetReducedString(s); + UString s2 = s; + ReduceString(s2); s2.Replace(L"&", L"&&"); return GetQuotedString(s2); } @@ -324,7 +351,7 @@ static const char *kExtractExludeExtensions = " h hpp hta htm html hxx" " ico idl inc ini inl" " java jpeg jpg js" - " la" + " la log" " 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" @@ -336,23 +363,45 @@ static const char *kExtractExludeExtensions = " 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 "; + " 7z arj bz2 cab chm cpio flv gz lha lzh lzma rar swm tar tbz2 tgz wim xar xz z zip "; +*/ + +static const char *kOpenTypes[] = +{ + "" + , "*" + , "#" + , "#:e" + // , "#:a" + , "7z" + , "zip" + , "cab" + , "rar" +}; -static bool FindExt(const char *p, const FString &nameF) +static bool FindExt(const char *p, const FString &name) { - const UString name = fs2us(nameF); - int extPos = name.ReverseFind('.'); - if (extPos < 0) + int dotPos = name.ReverseFind('.'); + if (dotPos < 0 || dotPos == (int)name.Len() - 1) return false; - UString ext = name.Mid(extPos + 1); - ext.MakeLower(); - AString ext2 = UnicodeStringToMultiByte(ext); - for (int i = 0; p[i] != 0;) + + AString s; + for (unsigned pos = dotPos + 1;; pos++) + { + wchar_t c = name[pos]; + if (c == 0) + break; + if (c >= 0x80) + return false; + s += (char)MyCharLower_Ascii((char)c); + } + for (unsigned i = 0; p[i] != 0;) { - int j; + unsigned j; for (j = i; p[j] != ' '; j++); - if (ext2.Length() == j - i && memcmp(p + i, (const char *)ext2, ext2.Length()) == 0) + if (s.Len() == j - i && memcmp(p + i, (const char *)s, s.Len()) == 0) return true; i = j + 1; } @@ -364,9 +413,20 @@ static bool DoNeedExtract(const FString &name) return !FindExt(kExtractExludeExtensions, name); } +// we must use diferent Verbs for Popup subMenu. +void CZipContextMenu::AddMapItem_ForSubMenu(const wchar_t *verb) +{ + CCommandMapItem commandMapItem; + commandMapItem.CommandInternalID = kCommandNULL; + commandMapItem.Verb = verb; + _commandMap.Add(commandMapItem); +} + STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT commandIDFirst, UINT commandIDLast, UINT flags) { + // OutputDebugStringA("QueryContextMenu"); + LoadLangOneTime(); if (_fileNames.Size() == 0) return E_FAIL; @@ -383,20 +443,24 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, CContextMenuInfo ci; ci.Load(); - MENUITEMINFO menuItem; + + HBITMAP bitmap = NULL; + if (ci.MenuIcons) + bitmap = _bitmap; + 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++; + + /* 9.31: we commented the following code. Probably we don't need. + Check more systems. Maybe it was for old Windows? */ + /* + AddMapItem_ForSubMenu(); + currentCommandID++; + */ subIndex = 0; } else @@ -406,14 +470,37 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UInt32 contextMenuFlags = ci.Flags; - UString mainString; - if (_fileNames.Size() == 1 && currentCommandID + 6 <= commandIDLast) + NFind::CFileInfo fi0; + FString folderPrefix; + if (_fileNames.Size() > 0) { const UString &fileName = _fileNames.Front(); - NFile::NFind::CFileInfo fileInfo; - if (!fileInfo.Find(us2fs(fileName))) - return E_FAIL; - if (!fileInfo.IsDir() && DoNeedExtract(fileInfo.Name)) + #ifdef _WIN32 + if (NName::IsDevicePath(us2fs(fileName))) + { + // CFileInfo::Find can be slow for device files. So we don't call it. + // we need only name here. + fi0.Name = us2fs(fileName.Ptr(NName::kDevicePathPrefixSize)); // change it 4 - must be constant + folderPrefix = + #ifdef UNDER_CE + FTEXT("\\"); + #else + FTEXT("C:\\"); + #endif + } + else + #endif + { + if (!fi0.Find(us2fs(fileName))) + return E_FAIL; + GetOnlyDirPrefix(us2fs(fileName), folderPrefix); + } + } + + UString mainString; + if (_fileNames.Size() == 1 && currentCommandID + 14 <= commandIDLast) + { + if (!fi0.IsDir() && DoNeedExtract(fi0.Name)) { // Open bool thereIsMainOpenItem = ((contextMenuFlags & NContextMenuFlags::kOpen) != 0); @@ -421,48 +508,47 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, { CCommandMapItem commandMapItem; FillCommand(kOpen, mainString, commandMapItem); - MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString); + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); _commandMap.Add(commandMapItem); } - if ((contextMenuFlags & NContextMenuFlags::kOpenAs) != 0 && - (!thereIsMainOpenItem || !FindExt(kNoOpenAsExtensions, fileInfo.Name))) + if ((contextMenuFlags & NContextMenuFlags::kOpenAs) != 0 + // && (!thereIsMainOpenItem || !FindExt(kNoOpenAsExtensions, fi0.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); + CMenuItem mi; + mi.fType = MFT_STRING; + mi.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID; + if (bitmap) + mi.fMask |= MIIM_CHECKMARKS; + mi.wID = currentCommandID++; + mi.hSubMenu = subMenu; + mi.hbmpUnchecked = bitmap; + + LangString(IDS_CONTEXT_OPEN, mi.StringValue); + popupMenu.InsertItem(subIndex++, true, mi); + AddMapItem_ForSubMenu(kOpenCascadedVerb); 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++) + for (unsigned i = (thereIsMainOpenItem ? 1 : 0); i < ARRAY_SIZE(kOpenTypes); i++) { CCommandMapItem commandMapItem; if (i == 0) FillCommand(kOpen, mainString, commandMapItem); else { - mainString = exts[i]; + mainString.SetFromAscii(kOpenTypes[i]); commandMapItem.CommandInternalID = kOpen; commandMapItem.Verb = (UString)kMainVerb + L".Open." + mainString; commandMapItem.HelpString = mainString; commandMapItem.ArcType = mainString; } - MyInsertMenu(subMenu, subIndex2++, currentCommandID++, mainString); + MyInsertMenu(subMenu, subIndex2++, currentCommandID++, mainString, bitmap); _commandMap.Add(commandMapItem); } + subMenu.Detach(); } } @@ -471,23 +557,24 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if (_fileNames.Size() > 0 && currentCommandID + 10 <= commandIDLast) { - bool needExtract = false; - for (int i = 0; i < _fileNames.Size(); i++) + bool needExtract = (!fi0.IsDir() && DoNeedExtract(fi0.Name)); + if (!needExtract) { - NFile::NFind::CFileInfo fileInfo; - if (!fileInfo.Find(us2fs(_fileNames[i]))) - return E_FAIL; - if (!fileInfo.IsDir() && DoNeedExtract(fileInfo.Name)) - needExtract = true; + FOR_VECTOR (i, _fileNames) + { + NFind::CFileInfo fi; + if (!fi.Find(us2fs(_fileNames[i]))) + return E_FAIL; + if (!fi.IsDir() && DoNeedExtract(fi.Name)) + { + needExtract = true; + break; + } + } } const UString &fileName = _fileNames.Front(); if (needExtract) { - FString folderPrefix; - NFile::NDirectory::GetOnlyDirPrefix(us2fs(fileName), folderPrefix); - NFile::NFind::CFileInfo fileInfo; - if (!fileInfo.Find(us2fs(fileName))) - return E_FAIL; // Extract if ((contextMenuFlags & NContextMenuFlags::kExtract) != 0) { @@ -497,8 +584,8 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, commandMapItem.Folder = _dropPath; else commandMapItem.Folder = fs2us(folderPrefix); - commandMapItem.Folder += GetSubFolderNameForExtract(fs2us(fileInfo.Name)) + UString(WCHAR_PATH_SEPARATOR); - MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString); + commandMapItem.Folder += GetSubFolderNameForExtract(fs2us(fi0.Name)) + UString(WCHAR_PATH_SEPARATOR); + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); _commandMap.Add(commandMapItem); } @@ -507,7 +594,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, { CCommandMapItem commandMapItem; FillCommand(kExtractHere, mainString, commandMapItem); - MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString); + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); if (_dropMode) commandMapItem.Folder = _dropPath; else @@ -523,7 +610,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, FillCommand(kExtractTo, s, commandMapItem); UString folder; if (_fileNames.Size() == 1) - folder = GetSubFolderNameForExtract(fs2us(fileInfo.Name)); + folder = GetSubFolderNameForExtract(fs2us(fi0.Name)); else folder = L'*'; if (_dropMode) @@ -532,7 +619,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, commandMapItem.Folder = fs2us(folderPrefix); commandMapItem.Folder += folder; s = MyFormatNew(s, GetQuotedReducedString(folder + UString(WCHAR_PATH_SEPARATOR))); - MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s); + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); _commandMap.Add(commandMapItem); } // Test @@ -540,15 +627,18 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, { CCommandMapItem commandMapItem; FillCommand(kTest, mainString, commandMapItem); - MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString); + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); _commandMap.Add(commandMapItem); } } - UString archiveName = CreateArchiveName(fileName, _fileNames.Size() > 1, false); + + UString archiveName; + if (_fileNames.Size() == 1) + archiveName = CreateArchiveName(fi0, false); + else + archiveName = CreateArchiveName(fileName, _fileNames.Size() > 1, false); UString archiveName7z = archiveName + L".7z"; UString archiveNameZip = archiveName + L".zip"; - FString archivePathPrefix; - NFile::NDirectory::GetOnlyDirPrefix(us2fs(fileName), archivePathPrefix); // Compress if ((contextMenuFlags & NContextMenuFlags::kCompress) != 0) @@ -557,10 +647,10 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if (_dropMode) commandMapItem.Folder = _dropPath; else - commandMapItem.Folder = fs2us(archivePathPrefix); + commandMapItem.Folder = fs2us(folderPrefix); commandMapItem.ArcName = archiveName; FillCommand(kCompress, mainString, commandMapItem); - MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString); + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); _commandMap.Add(commandMapItem); } @@ -571,13 +661,14 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, CCommandMapItem commandMapItem; commandMapItem.ArcName = archiveName; FillCommand(kCompressEmail, mainString, commandMapItem); - MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString); + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); _commandMap.Add(commandMapItem); } #endif // CompressTo7z - if (contextMenuFlags & NContextMenuFlags::kCompressTo7z) + if (contextMenuFlags & NContextMenuFlags::kCompressTo7z && + !archiveName7z.IsEqualToNoCase(fs2us(fi0.Name))) { CCommandMapItem commandMapItem; UString s; @@ -585,11 +676,11 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if (_dropMode) commandMapItem.Folder = _dropPath; else - commandMapItem.Folder = fs2us(archivePathPrefix); + commandMapItem.Folder = fs2us(folderPrefix); commandMapItem.ArcName = archiveName7z; commandMapItem.ArcType = L"7z"; s = MyFormatNew(s, GetQuotedReducedString(archiveName7z)); - MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s); + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); _commandMap.Add(commandMapItem); } @@ -603,13 +694,14 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, commandMapItem.ArcName = archiveName7z; commandMapItem.ArcType = L"7z"; s = MyFormatNew(s, GetQuotedReducedString(archiveName7z)); - MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s); + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); _commandMap.Add(commandMapItem); } #endif // CompressToZip - if (contextMenuFlags & NContextMenuFlags::kCompressToZip) + if (contextMenuFlags & NContextMenuFlags::kCompressToZip && + !archiveNameZip.IsEqualToNoCase(fs2us(fi0.Name))) { CCommandMapItem commandMapItem; UString s; @@ -617,11 +709,11 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if (_dropMode) commandMapItem.Folder = _dropPath; else - commandMapItem.Folder = fs2us(archivePathPrefix); + commandMapItem.Folder = fs2us(folderPrefix); commandMapItem.ArcName = archiveNameZip; commandMapItem.ArcType = L"zip"; s = MyFormatNew(s, GetQuotedReducedString(archiveNameZip)); - MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s); + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); _commandMap.Add(commandMapItem); } @@ -635,7 +727,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, commandMapItem.ArcName = archiveNameZip; commandMapItem.ArcType = L"zip"; s = MyFormatNew(s, GetQuotedReducedString(archiveNameZip)); - MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s); + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); _commandMap.Add(commandMapItem); } #endif @@ -645,19 +737,63 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, // 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); + CMenuItem mi; + mi.fType = MFT_STRING; + mi.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID; + if (bitmap) + mi.fMask |= MIIM_CHECKMARKS; + mi.wID = currentCommandID++; + mi.hSubMenu = popupMenu.Detach(); + mi.StringValue = L"7-Zip"; // LangString(IDS_CONTEXT_POPUP_CAPTION); + mi.hbmpUnchecked = bitmap; CMenu menu; menu.Attach(hMenu); - menu.InsertItem(indexMenu++, true, menuItem); + menuDestroyer.Disable(); + menu.InsertItem(indexMenu++, true, mi); + AddMapItem_ForSubMenu(kMainVerb); + } + + if (!_isMenuForFM && + ((contextMenuFlags & NContextMenuFlags::kCRC) != 0 + && currentCommandID + 6 <= commandIDLast)) + { + CMenu subMenu; + // CMenuDestroyer menuDestroyer_CRC; + + UINT subIndex_CRC = 0; + if (subMenu.CreatePopup()) + { + // menuDestroyer_CRC.Attach(subMenu); + CMenuItem mi; + mi.fType = MFT_STRING; + mi.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID; + if (bitmap) + mi.fMask |= MIIM_CHECKMARKS; + mi.wID = currentCommandID++; + mi.hSubMenu = subMenu; + mi.StringValue = L"CRC SHA"; + mi.hbmpUnchecked = bitmap; + CMenu menu; + menu.Attach(hMenu); + // menuDestroyer_CRC.Disable(); + menu.InsertItem(indexMenu++, true, mi); + AddMapItem_ForSubMenu(kCheckSumCascadedVerb); + + for (int i = 0; i < ARRAY_SIZE(g_HashCommands); i++) + { + const CHashCommand &hc = g_HashCommands[i]; + CCommandMapItem commandMapItem; + commandMapItem.CommandInternalID = hc.CommandInternalID; + commandMapItem.Verb = (UString)kCheckSumCascadedVerb + (UString)hc.MethodName; + // commandMapItem.HelpString = hc.Name; + MyInsertMenu(subMenu, subIndex_CRC++, currentCommandID++, hc.UserName, bitmap); + _commandMap.Add(commandMapItem); + } + subMenu.Detach(); + } } return MAKE_HRESULT(SEVERITY_SUCCESS, 0, currentCommandID - commandIDFirst); @@ -666,8 +802,8 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, int CZipContextMenu::FindVerb(const UString &verb) { - for(int i = 0; i < _commandMap.Size(); i++) - if (_commandMap[i].Verb.Compare(verb) == 0) + FOR_VECTOR (i, _commandMap) + if (_commandMap[i].Verb == verb) return i; return -1; } @@ -701,7 +837,7 @@ STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo) else commandOffset = FindVerb(GetUnicodeString(commandInfo->lpVerb)); - if (commandOffset < 0 || commandOffset >= _commandMap.Size()) + if (commandOffset < 0 || (unsigned)commandOffset >= _commandMap.Size()) return E_FAIL; const CCommandMapItem commandMapItem = _commandMap[commandOffset]; @@ -709,13 +845,13 @@ STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo) try { - switch(cmdID) + switch (cmdID) { case kOpen: { UString params; params = GetQuotedString(_fileNames[0]); - if (commandMapItem.ArcType) + if (!commandMapItem.ArcType.IsEmpty()) { params += L" -t"; params += commandMapItem.ArcType; @@ -727,7 +863,10 @@ STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo) case kExtractHere: case kExtractTo: { - ExtractArchives(_fileNames, commandMapItem.Folder, (cmdID == kExtract)); + ExtractArchives(_fileNames, commandMapItem.Folder, + (cmdID == kExtract), // showDialog + (cmdID == kExtractTo) // elimDup + ); break; } case kTest: @@ -749,11 +888,28 @@ STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo) bool showDialog = (cmdID == kCompress) || (cmdID == kCompressEmail); + bool addExtension = (cmdID == kCompress || cmdID == kCompressEmail); CompressFiles(commandMapItem.Folder, commandMapItem.ArcName, commandMapItem.ArcType, + addExtension, _fileNames, email, showDialog, false); break; } + case kHash_CRC32: + case kHash_CRC64: + case kHash_SHA1: + case kHash_SHA256: + case kHash_All: + for (int i = 0; i < ARRAY_SIZE(g_HashCommands); i++) + { + const CHashCommand &hc = g_HashCommands[i]; + if (hc.CommandInternalID == cmdID) + { + CalcChecksum(_fileNames, hc.MethodName); + break; + } + } + break; } } catch(...) @@ -785,12 +941,12 @@ STDMETHODIMP CZipContextMenu::GetCommandString(UINT_PTR commandOffset, UINT uTyp case GCS_VALIDATEA: case GCS_VALIDATEW: #endif - if (cmdOffset < 0 || cmdOffset >= _commandMap.Size()) + if (cmdOffset < 0 || (unsigned)cmdOffset >= _commandMap.Size()) return S_FALSE; else return S_OK; } - if (cmdOffset < 0 || cmdOffset >= _commandMap.Size()) + if (cmdOffset < 0 || (unsigned)cmdOffset >= _commandMap.Size()) return E_FAIL; #ifdef UNDER_CE if (uType == GCS_HELPTEXT) diff --git a/CPP/7zip/UI/Explorer/ContextMenu.h b/CPP/7zip/UI/Explorer/ContextMenu.h old mode 100755 new mode 100644 index 76337b19..b314bb38 --- a/CPP/7zip/UI/Explorer/ContextMenu.h +++ b/CPP/7zip/UI/Explorer/ContextMenu.h @@ -3,7 +3,7 @@ #ifndef __CONTEXT_MENU_H #define __CONTEXT_MENU_H -#include "Common/MyString.h" +#include "../../../Common/MyString.h" #include "../FileManager/MyCom2.h" @@ -27,7 +27,12 @@ public: kCompressTo7z, kCompressTo7zEmail, kCompressToZip, - kCompressToZipEmail + kCompressToZipEmail, + kHash_CRC32, + kHash_CRC64, + kHash_SHA1, + kHash_SHA256, + kHash_All }; MY_UNKNOWN_IMP2_MT(IContextMenu, IShellExtInit) @@ -40,7 +45,7 @@ public: STDMETHOD(InvokeCommand)(LPCMINVOKECOMMANDINFO lpici); STDMETHOD(GetCommandString)(UINT_PTR idCmd, UINT uType, UINT *pwReserved, LPSTR pszName, UINT cchMax); - HRESULT InitContextMenu(const wchar_t *folder, const wchar_t **names, UINT32 numFiles); + HRESULT InitContextMenu(const wchar_t *folder, const wchar_t **names, unsigned numFiles); CZipContextMenu(); ~CZipContextMenu(); @@ -57,14 +62,18 @@ private: UString ArcType; }; + bool _isMenuForFM; UStringVector _fileNames; bool _dropMode; UString _dropPath; CObjectVector _commandMap; + HBITMAP _bitmap; + HRESULT GetFileNames(LPDATAOBJECT dataObject, UStringVector &fileNames); int FindVerb(const UString &verb); - void FillCommand(ECommandInternalID id, UString &mainString, CCommandMapItem &commandMapItem); + bool FillCommand(ECommandInternalID id, UString &mainString, CCommandMapItem &commandMapItem); + void AddMapItem_ForSubMenu(const wchar_t *ver); }; #endif diff --git a/CPP/7zip/UI/Explorer/ContextMenuFlags.h b/CPP/7zip/UI/Explorer/ContextMenuFlags.h old mode 100755 new mode 100644 index 2f9d94d4..f739cdc6 --- a/CPP/7zip/UI/Explorer/ContextMenuFlags.h +++ b/CPP/7zip/UI/Explorer/ContextMenuFlags.h @@ -19,6 +19,8 @@ namespace NContextMenuFlags const UInt32 kCompressTo7zEmail = 1 << 11; const UInt32 kCompressToZip = 1 << 12; const UInt32 kCompressToZipEmail = 1 << 13; + + const UInt32 kCRC = (UInt32)1 << 31; } #endif diff --git a/CPP/7zip/UI/Explorer/DllExports.cpp b/CPP/7zip/UI/Explorer/DllExports.cpp deleted file mode 100755 index 4f649f59..00000000 --- a/CPP/7zip/UI/Explorer/DllExports.cpp +++ /dev/null @@ -1,256 +0,0 @@ -// 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; - -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; - - FString modulePath; - if (!NDLL::MyGetModuleFileName(modulePath)) - return FALSE; - UString modulePathU = fs2us(modulePath); - - CRegItem clsidEntries[] = - { - HKEY_CLASSES_ROOT, kClsidMask, NULL, title, - HKEY_CLASSES_ROOT, kClsidInprocMask, NULL, modulePathU, - 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/DllExportsExplorer.cpp b/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp new file mode 100644 index 00000000..478f6e97 --- /dev/null +++ b/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp @@ -0,0 +1,256 @@ +// 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/ErrorMsg.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; + +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; + + FString modulePath; + if (!NDLL::MyGetModuleFileName(modulePath)) + return FALSE; + UString modulePathU = fs2us(modulePath); + + CRegItem clsidEntries[] = + { + HKEY_CLASSES_ROOT, kClsidMask, NULL, title, + HKEY_CLASSES_ROOT, kClsidInprocMask, NULL, modulePathU, + 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 old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/Explorer/Explorer.dsp b/CPP/7zip/UI/Explorer/Explorer.dsp old mode 100755 new mode 100644 index 158390bb..80aaf464 --- a/CPP/7zip/UI/Explorer/Explorer.dsp +++ b/CPP/7zip/UI/Explorer/Explorer.dsp @@ -45,7 +45,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 1 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "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 CPP /nologo /Gz /MD /W4 /WX /GX /O1 /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" @@ -72,7 +72,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 1 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "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 CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /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" @@ -99,7 +99,7 @@ LINK32=link.exe # 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 CPP /nologo /Gz /MD /W4 /WX /GX /O1 /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" @@ -128,7 +128,7 @@ LINK32=link.exe # 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 CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /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" @@ -153,7 +153,7 @@ LINK32=link.exe # PROP Default_Filter "" # Begin Source File -SOURCE=.\DllExports.cpp +SOURCE=.\DllExportsExplorer.cpp # End Source File # Begin Source File @@ -435,11 +435,11 @@ SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Error.cpp +SOURCE=..\..\..\Windows\ErrorMsg.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Error.h +SOURCE=..\..\..\Windows\ErrorMsg.h # End Source File # Begin Source File @@ -479,11 +479,11 @@ SOURCE=..\..\..\Windows\FileName.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Memory.cpp +SOURCE=..\..\..\Windows\MemoryGlobal.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Memory.h +SOURCE=..\..\..\Windows\MemoryGlobal.h # End Source File # Begin Source File @@ -495,11 +495,11 @@ SOURCE=..\..\..\Windows\Menu.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Process.cpp +SOURCE=..\..\..\Windows\ProcessUtils.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Process.h +SOURCE=..\..\..\Windows\ProcessUtils.h # End Source File # Begin Source File diff --git a/CPP/7zip/UI/Explorer/Explorer.dsw b/CPP/7zip/UI/Explorer/Explorer.dsw old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/Explorer/MenuLogo.bmp b/CPP/7zip/UI/Explorer/MenuLogo.bmp new file mode 100644 index 00000000..906a6c5c Binary files /dev/null and b/CPP/7zip/UI/Explorer/MenuLogo.bmp differ diff --git a/CPP/7zip/UI/Explorer/MyMessages.cpp b/CPP/7zip/UI/Explorer/MyMessages.cpp old mode 100755 new mode 100644 index 62ac42ec..70c2a460 --- a/CPP/7zip/UI/Explorer/MyMessages.cpp +++ b/CPP/7zip/UI/Explorer/MyMessages.cpp @@ -4,12 +4,10 @@ #include "MyMessages.h" -#include "Windows/Error.h" -#include "Windows/ResourceString.h" +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/ResourceString.h" -#ifdef LANG #include "../FileManager/LangUtils.h" -#endif using namespace NWindows; @@ -18,41 +16,22 @@ 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 - ) +void ShowErrorMessageHwndRes(HWND window, UINT resID) { - ShowErrorMessage(window, - #ifdef LANG - LangString(resID, langID) - #else - MyLoadStringW(resID) - #endif - ); + ShowErrorMessage(window, LangString(resID)); } -void ShowErrorMessageRes(UINT resID - #ifdef LANG - , UInt32 langID - #endif - ) +void ShowErrorMessageRes(UINT resID) { - ShowErrorMessageHwndRes(0, resID - #ifdef LANG - , langID - #endif - ); + ShowErrorMessageHwndRes(0, resID); } void ShowErrorMessageDWORD(HWND window, DWORD errorCode) { - ShowErrorMessage(window, NError::MyFormatMessageW(errorCode)); + ShowErrorMessage(window, NError::MyFormatMessage(errorCode)); } void ShowLastErrorMessage(HWND window) { ShowErrorMessageDWORD(window, ::GetLastError()); } - diff --git a/CPP/7zip/UI/Explorer/MyMessages.h b/CPP/7zip/UI/Explorer/MyMessages.h old mode 100755 new mode 100644 index 10da975b..d5822f45 --- a/CPP/7zip/UI/Explorer/MyMessages.h +++ b/CPP/7zip/UI/Explorer/MyMessages.h @@ -1,28 +1,16 @@ // MyMessages.h -#ifndef __MYMESSAGES_H -#define __MYMESSAGES_H +#ifndef __MY_MESSAGES_H +#define __MY_MESSAGES_H -#include "Common/MyString.h" -#include "Common/Types.h" +#include "../../../Common/MyString.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 ShowErrorMessageHwndRes(HWND window, UInt32 langID); +void ShowErrorMessageRes(UInt32 langID); -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 old mode 100755 new mode 100644 index 90a0c0dc..c9531fae --- a/CPP/7zip/UI/Explorer/OptionsDialog.cpp +++ b/CPP/7zip/UI/Explorer/OptionsDialog.cpp @@ -27,7 +27,7 @@ static INT_PTR OptionsDialog(HWND hwndOwner) 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]); + const int kNumPages = ARRAY_SIZE(langIDs); for (int i = 0; i < kNumPages; i++) { NControl::CPageInfo page; diff --git a/CPP/7zip/UI/Explorer/OptionsDialog.h b/CPP/7zip/UI/Explorer/OptionsDialog.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp b/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp old mode 100755 new mode 100644 index 656d0bfa..da6ecf38 --- a/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp +++ b/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp @@ -2,8 +2,8 @@ #include "StdAfx.h" -#include "Windows/Registry.h" -#include "Windows/Synchronization.h" +#include "../../../Windows/Registry.h" +#include "../../../Windows/Synchronization.h" #include "RegistryContextMenu.h" @@ -41,8 +41,7 @@ static bool CheckHandlerCommon(const CSysString &keyName) CSysString value; if (key.QueryValue(NULL, value) != ERROR_SUCCESS) return false; - value.MakeUpper(); - return (value.Compare(kExtensionCLSID) == 0); + return StringsAreEqualNoCase_Ascii(value, kExtensionCLSID); } bool CheckContextMenuHandler() diff --git a/CPP/7zip/UI/Explorer/RegistryContextMenu.h b/CPP/7zip/UI/Explorer/RegistryContextMenu.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/Explorer/StdAfx.cpp b/CPP/7zip/UI/Explorer/StdAfx.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/Explorer/StdAfx.h b/CPP/7zip/UI/Explorer/StdAfx.h old mode 100755 new mode 100644 index e1fe42f2..5e4dc640 --- a/CPP/7zip/UI/Explorer/StdAfx.h +++ b/CPP/7zip/UI/Explorer/StdAfx.h @@ -3,22 +3,12 @@ #ifndef __STDAFX_H #define __STDAFX_H -#define _WIN32_WINNT 0x0400 -// it's hack for Windows NT supporting -#define WINVER 0x0400 +// #define _WIN32_WINNT 0x0400 +#define _WIN32_WINNT 0x0500 +#define WINVER _WIN32_WINNT -// #define _WIN32_IE 0x0500 -#include -#include -#include -#include +#include "../../../Common/Common.h" -#include -#include -#include - -#include - -#include "Common/NewHandler.h" +#include #endif diff --git a/CPP/7zip/UI/Explorer/makefile b/CPP/7zip/UI/Explorer/makefile old mode 100755 new mode 100644 index 89cbc642..5a16ffd5 --- a/CPP/7zip/UI/Explorer/makefile +++ b/CPP/7zip/UI/Explorer/makefile @@ -1,17 +1,17 @@ PROG = 7-zip.dll DEF_FILE = Explorer.def -CFLAGS = $(CFLAGS) -I ../../../ \ +CFLAGS = $(CFLAGS) \ -DLANG \ !IFDEF UNDER_CE LIBS = $(LIBS) Commctrl.lib !ELSE -LIBS = $(LIBS) comctl32.lib htmlhelp.lib comdlg32.lib Mpr.lib Gdi32.lib +LIBS = $(LIBS) htmlhelp.lib comdlg32.lib Mpr.lib Gdi32.lib CFLAGS = $(CFLAGS) -DWIN_LONG_PATH !ENDIF EXPLORER_OBJS = \ - $O\DllExports.obj \ + $O\DllExportsExplorer.obj \ $O\ContextMenu.obj \ $O\MyMessages.obj \ $O\RegistryContextMenu.obj \ @@ -31,13 +31,13 @@ COMMON_OBJS = \ WIN_OBJS = \ $O\DLL.obj \ - $O\Error.obj \ + $O\ErrorMsg.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\Menu.obj \ - $O\Process.obj \ + $O\ProcessUtils.obj \ $O\Registry.obj \ $O\ResourceString.obj \ $O\Shell.obj \ @@ -54,7 +54,6 @@ WIN_OBJS = $(WIN_OBJS) \ WIN_CTRL_OBJS = \ $O\Dialog.obj \ $O\ListView.obj \ - $O\PropertyPage.obj \ UI_COMMON_OBJS = \ $O\ArchiveName.obj \ @@ -62,7 +61,7 @@ UI_COMMON_OBJS = \ $O\ExtractingFilePath.obj \ $O\ZipRegistry.obj \ -FM_COMMON_OBJS = \ +FM_OBJS = \ $O\FormatUtils.obj \ $O\HelpUtils.obj \ $O\LangUtils.obj \ @@ -72,30 +71,4 @@ FM_COMMON_OBJS = \ 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) +!include "../../7zip.mak" diff --git a/CPP/7zip/UI/Explorer/resource.h b/CPP/7zip/UI/Explorer/resource.h old mode 100755 new mode 100644 index 3ddda8f0..8bb82108 --- a/CPP/7zip/UI/Explorer/resource.h +++ b/CPP/7zip/UI/Explorer/resource.h @@ -1,28 +1,13 @@ -#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 +#define IDS_CONTEXT_FOLDER 2320 +#define IDS_CONTEXT_ARCHIVE 2321 +#define IDS_CONTEXT_OPEN 2322 +#define IDS_CONTEXT_EXTRACT 2323 +#define IDS_CONTEXT_COMPRESS 2324 +#define IDS_CONTEXT_TEST 2325 +#define IDS_CONTEXT_EXTRACT_HERE 2326 +#define IDS_CONTEXT_EXTRACT_TO 2327 +#define IDS_CONTEXT_COMPRESS_TO 2328 +#define IDS_CONTEXT_COMPRESS_EMAIL 2329 +#define IDS_CONTEXT_COMPRESS_TO_EMAIL 2330 + +#define IDB_MENU_LOGO 190 diff --git a/CPP/7zip/UI/Explorer/resource.rc b/CPP/7zip/UI/Explorer/resource.rc old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/Explorer/resource2.rc b/CPP/7zip/UI/Explorer/resource2.rc old mode 100755 new mode 100644 index 08bc82bf..c07148fd --- a/CPP/7zip/UI/Explorer/resource2.rc +++ b/CPP/7zip/UI/Explorer/resource2.rc @@ -2,26 +2,17 @@ STRINGTABLE BEGIN + IDS_CONTEXT_FOLDER "" + IDS_CONTEXT_ARCHIVE "" + IDS_CONTEXT_OPEN "Open archive" 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 + +IDB_MENU_LOGO BITMAP "../../UI/Explorer/MenuLogo.bmp" diff --git a/CPP/7zip/UI/Far/ExtractEngine.cpp b/CPP/7zip/UI/Far/ExtractEngine.cpp old mode 100755 new mode 100644 index b18eed59..4384c6ec --- a/CPP/7zip/UI/Far/ExtractEngine.cpp +++ b/CPP/7zip/UI/Far/ExtractEngine.cpp @@ -2,12 +2,13 @@ #include "StdAfx.h" -#include "Common/StringConvert.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" #include "ExtractEngine.h" #include "FarUtils.h" #include "Messages.h" -#include "OverwriteDialog.h" +#include "OverwriteDialogFar.h" using namespace NWindows; using namespace NFar; @@ -119,44 +120,68 @@ STDMETHODIMP CExtractCallBackImp::MessageError(const wchar_t *message) return S_OK; } -static void ReduceString(UString &s, int size) +static void ReduceString(UString &s, unsigned size) { - if (s.Length() > size) - s = s.Left(size / 2) + UString(L" ... ") + s.Right(size / 2); + if (s.Len() > size) + { + s.Delete(size / 2, s.Len() - size); + s.Insert(size / 2, L" ... "); + } } STDMETHODIMP CExtractCallBackImp::SetOperationResult(Int32 operationResult, bool encrypted) { - switch(operationResult) + switch (operationResult) { case NArchive::NExtract::NOperationResult::kOK: break; default: { - UINT idMessage; - switch(operationResult) + UINT messageID = 0; + switch (operationResult) { - case NArchive::NExtract::NOperationResult::kUnSupportedMethod: - idMessage = NMessageID::kExtractUnsupportedMethod; + case NArchive::NExtract::NOperationResult::kUnsupportedMethod: + messageID = NMessageID::kExtractUnsupportedMethod; break; case NArchive::NExtract::NOperationResult::kCRCError: - idMessage = encrypted ? + messageID = encrypted ? NMessageID::kExtractCRCFailedEncrypted : NMessageID::kExtractCRCFailed; break; case NArchive::NExtract::NOperationResult::kDataError: - idMessage = encrypted ? + messageID = 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) + AString s; + if (messageID != 0) + { + s = g_StartupInfo.GetMsgString(messageID); + s.Replace(" '%s'", ""); + } + else if (operationResult == NArchive::NExtract::NOperationResult::kUnavailable) + s = "Unavailable data"; + else if (operationResult == NArchive::NExtract::NOperationResult::kUnexpectedEnd) + s = "Unexpected end of data"; + else if (operationResult == NArchive::NExtract::NOperationResult::kDataAfterEnd) + s = "There are some data after the end of the payload data"; + else if (operationResult == NArchive::NExtract::NOperationResult::kIsNotArc) + s = "Is not archive"; + else if (operationResult == NArchive::NExtract::NOperationResult::kHeadersError) + s = "kHeaders Error"; + else + { + char temp[16]; + ConvertUInt32ToString(operationResult, temp); + s = "Error #"; + s += temp; + } + s += "\n"; + s += UnicodeStringToMultiByte(name, m_CodePage); + if (g_StartupInfo.ShowMessageLines(s) == -1) return E_ABORT; } } diff --git a/CPP/7zip/UI/Far/ExtractEngine.h b/CPP/7zip/UI/Far/ExtractEngine.h old mode 100755 new mode 100644 index 5676103a..f57602a9 --- a/CPP/7zip/UI/Far/ExtractEngine.h +++ b/CPP/7zip/UI/Far/ExtractEngine.h @@ -1,10 +1,10 @@ // ExtractEngine.h -#ifndef __EXTRACTENGINE_H -#define __EXTRACTENGINE_H +#ifndef __EXTRACT_ENGINE_H +#define __EXTRACT_ENGINE_H -#include "Common/MyCom.h" -#include "Common/MyString.h" +#include "../../../Common/MyCom.h" +#include "../../../Common/MyString.h" #include "../../IPassword.h" #include "../Agent/IFolderArchive.h" diff --git a/CPP/7zip/UI/Far/Far.cpp b/CPP/7zip/UI/Far/Far.cpp new file mode 100644 index 00000000..38fed101 --- /dev/null +++ b/CPP/7zip/UI/Far/Far.cpp @@ -0,0 +1,618 @@ +// 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 NFile; +using namespace NDir; +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; + + NFind::CFileInfo _fileInfo; +public: + bool PasswordIsDefined; + UString Password; + + FString _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 FString &folderPrefix, const FString &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]; + message[0] = 0; + if (_numFilesCurDefined) + ConvertUInt64ToStringAligned(_numFilesCur, message, 5); + + if (_numFilesTotalDefined) + { + strcat(message, " / "); + ConvertUInt64ToStringAligned(_numFilesTotal, message + strlen(message), 5); + total = _numFilesTotal; + totalIsDefined = true; + if (_numFilesCurDefined) + { + cur = _numFilesCur; + curIsDefined = true; + } + } + else if (_numBytesTotalDefined) + { + total = _numBytesTotal; + totalIsDefined = true; + if (_numBytesCurDefined) + { + cur = _numBytesCur; + curIsDefined = true; + } + } + _progressBox.Progress( + totalIsDefined ? &total: NULL, + curIsDefined ? &cur: NULL, + message); +} + +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; + FString fullPath = _folderPrefix + us2fs(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) +{ + 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 = ARRAY_SIZE(initItems); + 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) +{ + FString normalizedName = us2fs(name); + normalizedName.Trim(); + FString fullName; + MyGetFullPathName(normalizedName, fullName); + NFind::CFileInfo 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(); + { + FString dirPrefix, fileName; + GetFullPathAndSplit(fullName, dirPrefix, fileName); + openArchiveCallbackSpec->LoadFileInfo(dirPrefix, fileName); + } + + // ::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.Len() >= 2 && + fileName[0] == '\"' && fileName.Back() == '\"') + { + fileName.DeleteBack(); + fileName.DeleteFrontal(1); + } + 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 = ARRAY_SIZE(pluginCfgStrings); + 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 = ARRAY_SIZE(initItems); + 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/Far.def b/CPP/7zip/UI/Far/Far.def old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/Far/Far.dsp b/CPP/7zip/UI/Far/Far.dsp old mode 100755 new mode 100644 index 394977bb..bd50fd93 --- a/CPP/7zip/UI/Far/Far.dsp +++ b/CPP/7zip/UI/Far/Far.dsp @@ -43,7 +43,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 1 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FAR_EXPORTS" /YX /FD /c -# ADD CPP /nologo /Gz /MD /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 CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FAR_EXPORTS" /D "EXTERNAL_CODECS" /Yu"StdAfx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" @@ -70,7 +70,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 1 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FAR_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /Gz /MTd /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 CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FAR_EXPORTS" /D "EXTERNAL_CODECS" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" @@ -158,6 +158,14 @@ 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\Wildcard.cpp # End Source File # Begin Source File @@ -178,7 +186,7 @@ SOURCE=.\ExtractEngine.h # End Source File # Begin Source File -SOURCE=.\Main.cpp +SOURCE=.\Far.cpp # End Source File # Begin Source File @@ -186,11 +194,11 @@ SOURCE=.\Messages.h # End Source File # Begin Source File -SOURCE=.\OverwriteDialog.cpp +SOURCE=.\OverwriteDialogFar.cpp # End Source File # Begin Source File -SOURCE=.\OverwriteDialog.h +SOURCE=.\OverwriteDialogFar.h # End Source File # Begin Source File @@ -218,11 +226,11 @@ SOURCE=.\resource.h # End Source File # Begin Source File -SOURCE=.\UpdateCallback100.cpp +SOURCE=.\UpdateCallbackFar.cpp # End Source File # Begin Source File -SOURCE=.\UpdateCallback100.h +SOURCE=.\UpdateCallbackFar.h # End Source File # End Group # Begin Group "Far" @@ -266,11 +274,11 @@ SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Error.cpp +SOURCE=..\..\..\Windows\ErrorMsg.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Error.h +SOURCE=..\..\..\Windows\ErrorMsg.h # End Source File # Begin Source File @@ -298,6 +306,10 @@ SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File +SOURCE=..\..\..\Windows\FileLink.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Windows\FileName.cpp # End Source File # Begin Source File @@ -314,11 +326,11 @@ SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\PropVariantConversions.cpp +SOURCE=..\..\..\Windows\PropVariantConv.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\PropVariantConversions.h +SOURCE=..\..\..\Windows\PropVariantConv.h # End Source File # Begin Source File @@ -338,7 +350,11 @@ SOURCE=..\..\..\Windows\Synchronization.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Time.cpp +SOURCE=..\..\..\Windows\TimeUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\TimeUtils.h # End Source File # End Group # Begin Group "UI Common" @@ -422,6 +438,14 @@ 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 @@ -546,6 +570,14 @@ SOURCE=..\..\Common\FileStreams.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\ProgressUtils.cpp # End Source File # Begin Source File @@ -554,12 +586,32 @@ SOURCE=..\..\Common\ProgressUtils.h # End Source File # Begin Source File +SOURCE=..\..\Common\PropId.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamObjects.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamObjects.h +# End Source File +# Begin Source File + SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\UniqBlocks.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\UniqBlocks.h +# End Source File # End Group # Begin Group "C" @@ -623,5 +675,41 @@ SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp SOURCE=..\..\Archive\Common\OutStreamWithCRC.h # End Source File # End Group +# Begin Group "Interface" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\IArchive.h +# End Source File +# Begin Source File + +SOURCE=..\..\ICoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\IDecl.h +# End Source File +# Begin Source File + +SOURCE=..\Common\IFileExtractCallback.h +# End Source File +# Begin Source File + +SOURCE=..\FileManager\IFolder.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=..\..\PropID.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 old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/Far/FarPlugin.h b/CPP/7zip/UI/Far/FarPlugin.h old mode 100755 new mode 100644 index d9ea6dca..a6185a1d --- a/CPP/7zip/UI/Far/FarPlugin.h +++ b/CPP/7zip/UI/Far/FarPlugin.h @@ -165,7 +165,7 @@ struct FarDialogItem const char *History; const char *Mask; struct FarList *ListItems; - int ListPos; + int ListPos; CHAR_INFO *VBuf; }; unsigned int Flags; diff --git a/CPP/7zip/UI/Far/FarUtils.cpp b/CPP/7zip/UI/Far/FarUtils.cpp old mode 100755 new mode 100644 index 9f55e8e5..14343522 --- a/CPP/7zip/UI/Far/FarUtils.cpp +++ b/CPP/7zip/UI/Far/FarUtils.cpp @@ -2,13 +2,13 @@ #include "StdAfx.h" -#include "Common/StringConvert.h" +#include "../../../Common/StringConvert.h" #ifndef UNDER_CE -#include "Windows/Console.h" +#include "../../../Windows/Console.h" #endif -#include "Windows/Defs.h" -#include "Windows/Error.h" +#include "../../../Windows/Defs.h" +#include "../../../Windows/ErrorMsg.h" #include "FarUtils.h" @@ -53,17 +53,17 @@ namespace NMessageID 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); + return ShowMessage(FMSG_WARNING, NULL, items, ARRAY_SIZE(items), 1); } static void SplitString(const AString &srcString, AStringVector &destStrings) { destStrings.Clear(); AString string; - int len = srcString.Length(); + unsigned len = srcString.Len(); if (len == 0) return; - for (int i = 0; i < len; i++) + for (unsigned i = 0; i < len; i++) { char c = srcString[i]; if (c == '\n') @@ -85,10 +85,10 @@ int CStartupInfo::ShowMessageLines(const char *message) { AStringVector strings; SplitString(message, strings); - const int kNumStringsMax = 20; + const unsigned kNumStringsMax = 20; const char *items[kNumStringsMax + 1] = { GetMsgString(NMessageID::kError) }; - int pos = 1; - for (int i = 0; i < strings.Size() && pos < kNumStringsMax; i++) + unsigned pos = 1; + for (unsigned i = 0; i < strings.Size() && pos < kNumStringsMax; i++) items[pos++] = strings[i]; items[pos++] = GetMsgString(NMessageID::kOk); @@ -197,7 +197,7 @@ void CStartupInfo::SetRegKeyValue(HKEY parentKey, const CSysString &keyName, } void CStartupInfo::SetRegKeyValue(HKEY parentKey, const CSysString &keyName, - LPCTSTR valueName, UINT32 value) const + LPCTSTR valueName, UInt32 value) const { NRegistry::CKey regKey; CreateRegKey(parentKey, keyName, regKey); @@ -226,14 +226,14 @@ CSysString CStartupInfo::QueryRegKeyValue(HKEY parentKey, const CSysString &keyN return value; } -UINT32 CStartupInfo::QueryRegKeyValue(HKEY parentKey, const CSysString &keyName, - LPCTSTR valueName, UINT32 valueDefault) const +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; + UInt32 value; if(regKey.QueryValue(valueName, value) != ERROR_SUCCESS) return valueDefault; @@ -352,13 +352,13 @@ int CStartupInfo::Menu( int selectedItem) { CRecordVector farMenuItems; - for(int i = 0; i < items.Size(); i++) + FOR_VECTOR (i, items) { 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); + item.Selected = ((int)i == selectedItem); + CSysString reducedString = items[i].Left(ARRAY_SIZE(item.Text) - 1); MyStringCopy(item.Text, (const char *)GetOemString(reducedString)); farMenuItems.Add(item); } @@ -449,9 +449,9 @@ bool WasEscPressed() void ShowErrorMessage(DWORD errorCode) { - UString message = NError::MyFormatMessageW(errorCode); - message.Replace(L"\x0D", L""); - message.Replace(L"\x0A", L" "); + UString message = NError::MyFormatMessage(errorCode); + message.RemoveChar(L'\x0D'); + message.Replace(L'\x0A', L' '); g_StartupInfo.ShowMessage(UnicodeStringToMultiByte(message, CP_OEMCP)); } diff --git a/CPP/7zip/UI/Far/FarUtils.h b/CPP/7zip/UI/Far/FarUtils.h old mode 100755 new mode 100644 index a4887c9a..1a5a49c7 --- a/CPP/7zip/UI/Far/FarUtils.h +++ b/CPP/7zip/UI/Far/FarUtils.h @@ -1,10 +1,11 @@ // FarUtils.h -#ifndef __FARUTILS_H -#define __FARUTILS_H +#ifndef __FAR_UTILS_H +#define __FAR_UTILS_H #include "FarPlugin.h" -#include "Windows/Registry.h" + +#include "../../../Windows/Registry.h" namespace NFar { @@ -79,15 +80,15 @@ public: 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; + 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; + UInt32 QueryRegKeyValue(HKEY parentKey, const CSysString &keyName, + LPCTSTR valueName, UInt32 valueDefault) const; bool QueryRegKeyValue(HKEY parentKey, const CSysString &keyName, LPCTSTR valueName, bool valueDefault) const; diff --git a/CPP/7zip/UI/Far/Main.cpp b/CPP/7zip/UI/Far/Main.cpp deleted file mode 100755 index 7b58d0ca..00000000 --- a/CPP/7zip/UI/Far/Main.cpp +++ /dev/null @@ -1,613 +0,0 @@ -// 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::CFileInfo _fileInfo; -public: - bool PasswordIsDefined; - UString Password; - - FString _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 FString &folderPrefix, const FString &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; - FString fullPath = _folderPrefix + us2fs(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) -{ - FString normalizedName = us2fs(name); - normalizedName.Trim(); - FString fullName; - NFile::NDirectory::MyGetFullPathName(normalizedName, fullName); - NFile::NFind::CFileInfo 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(); - { - FString dirPrefix, fileName; - NFile::NDirectory::GetFullPathAndSplit(fullName, dirPrefix, fileName); - openArchiveCallbackSpec->LoadFileInfo(dirPrefix, fileName); - } - - // ::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.Back() == '\"') - 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 old mode 100755 new mode 100644 index fc3723af..e6972392 --- a/CPP/7zip/UI/Far/Messages.h +++ b/CPP/7zip/UI/Far/Messages.h @@ -1,10 +1,14 @@ -// SevenZip/ Messages.h +// Far/Messages.h -#ifndef __SEVENZIP_MESSAGES_H -#define __SEVENZIP_MESSAGES_H +#ifndef __7ZIP_FAR_MESSAGES_H +#define __7ZIP_FAR_MESSAGES_H + +#include "../../PropID.h" namespace NMessageID { +const UINT k_Last_PropId_supported_by_plugin = kpidStreamId; + enum EEnum { kOk, @@ -20,63 +24,6 @@ enum EEnum 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, @@ -140,18 +87,18 @@ enum EEnum kUpdateAddToArchive, kUpdateMethod, - kUpdateMethodStore, - kUpdateMethodFastest, - kUpdateMethodFast, - kUpdateMethodNormal, - kUpdateMethodMaximum, - kUpdateMethodUltra, + kUpdateMethod_Store, + kUpdateMethod_Fastest, + kUpdateMethod_Fast, + kUpdateMethod_Normal, + kUpdateMethod_Maximum, + kUpdateMethod_Ultra, kUpdateMode, - kUpdateModeAdd, - kUpdateModeUpdate, - kUpdateModeFreshen, - kUpdateModeSynchronize, + kUpdateMode_Add, + kUpdateMode_Update, + kUpdateMode_Fresh, + kUpdateMode_Sync, kUpdateAdd, kUpdateSelectArchiver, @@ -176,7 +123,12 @@ enum EEnum kConfigTitle, - kConfigPluginEnabled + kConfigPluginEnabled, + + // ---------- IDs for Properies (kpid*) ---------- + kNoProperty, + k_Last_MessageID_for_Property = kNoProperty + k_Last_PropId_supported_by_plugin + // ---------- }; } diff --git a/CPP/7zip/UI/Far/OverwriteDialog.cpp b/CPP/7zip/UI/Far/OverwriteDialog.cpp deleted file mode 100755 index 5be6a5f9..00000000 --- a/CPP/7zip/UI/Far/OverwriteDialog.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// 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 deleted file mode 100755 index a0842e78..00000000 --- a/CPP/7zip/UI/Far/OverwriteDialog.h +++ /dev/null @@ -1,37 +0,0 @@ -// 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/OverwriteDialogFar.cpp b/CPP/7zip/UI/Far/OverwriteDialogFar.cpp new file mode 100644 index 00000000..a7fb495e --- /dev/null +++ b/CPP/7zip/UI/Far/OverwriteDialogFar.cpp @@ -0,0 +1,113 @@ +// OverwriteDialogFar.cpp + +#include "StdAfx.h" + +#include + +#include "../../../Common/StringConvert.h" +#include "../../../Common/IntToString.h" + +#include "../../../Windows/FileName.h" +#include "../../../Windows/PropVariantConv.h" + +#include "FarUtils.h" +#include "Messages.h" + +#include "OverwriteDialogFar.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) + { + ConvertUInt64ToString(fileInfo.Size, buffer); + fileInfoStrings.Size = buffer; + fileInfoStrings.Size += ' '; + 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; + char timeString[32]; + ConvertFileTimeToString(localFileTime, timeString); + fileInfoStrings.Time = g_StartupInfo.GetMsgString(NMessageID::kOverwriteModifiedOn); + fileInfoStrings.Time += ' '; + fileInfoStrings.Time += timeString; + } +} + +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 = ARRAY_SIZE(initItems); + 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/OverwriteDialogFar.h b/CPP/7zip/UI/Far/OverwriteDialogFar.h new file mode 100644 index 00000000..34947436 --- /dev/null +++ b/CPP/7zip/UI/Far/OverwriteDialogFar.h @@ -0,0 +1,37 @@ +// OverwriteDialogFar.h + +#ifndef __OVERWRITE_DIALOG_FAR_H +#define __OVERWRITE_DIALOG_FAR_H + +#include "../../../Common/MyString.h" +#include "../../../Common/MyTypes.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 old mode 100755 new mode 100644 index 8bdfb10d..bebd47de --- a/CPP/7zip/UI/Far/Plugin.cpp +++ b/CPP/7zip/UI/Far/Plugin.cpp @@ -2,12 +2,12 @@ #include "StdAfx.h" -#include "Common/IntToString.h" -#include "Common/StringConvert.h" -#include "Common/Wildcard.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/Wildcard.h" -#include "Windows/FileDir.h" -#include "Windows/PropVariantConversions.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/PropVariantConv.h" #include "../Common/PropIDUtils.h" @@ -16,8 +16,17 @@ #include "Plugin.h" using namespace NWindows; +using namespace NFile; +using namespace NDir; using namespace NFar; +// This function is unused +int CompareFileNames_ForFolderList(const wchar_t *s1, const wchar_t *s2) +{ + return MyStringCompareNoCase(s1, s2); +} + + CPlugin::CPlugin(const FString &fileName, IInFolderArchive *archiveHandler, UString archiveTypeName): m_ArchiveHandler(archiveHandler), m_FileName(fileName), @@ -52,16 +61,16 @@ static void MyGetFileTime(IFolderFolder *anArchiveFolder, UInt32 itemIndex, #define kDotsReplaceString "[[..]]" #define kDotsReplaceStringU L"[[..]]" -static void CopyStrLimited(char *dest, const AString &src, int len) +static void CopyStrLimited(char *dest, const AString &src, unsigned len) { len--; - if (src.Length() < len) - len = src.Length(); + if (src.Len() < len) + len = src.Len(); memcpy(dest, src, sizeof(dest[0]) * len); dest[len] = 0; } -#define COPY_STR_LIMITED(dest, src) CopyStrLimited(dest, src, sizeof(dest) / sizeof(dest[0])) +#define COPY_STR_LIMITED(dest, src) CopyStrLimited(dest, src, ARRAY_SIZE(dest)) void CPlugin::ReadPluginPanelItem(PluginPanelItem &panelItem, UInt32 itemIndex) { @@ -100,11 +109,8 @@ void CPlugin::ReadPluginPanelItem(PluginPanelItem &panelItem, UInt32 itemIndex) if (_folder->GetProperty(itemIndex, kpidSize, &prop) != S_OK) throw 271932; - UInt64 length; - if (prop.vt == VT_EMPTY) - length = 0; - else - length = ::ConvertPropVariantToUInt64(prop); + UInt64 length = 0; + ConvertPropVariantToUInt64(prop, length); panelItem.FindData.nFileSizeLow = (UInt32)length; panelItem.FindData.nFileSizeHigh = (UInt32)(length >> 32); @@ -118,10 +124,8 @@ void CPlugin::ReadPluginPanelItem(PluginPanelItem &panelItem, UInt32 itemIndex) if (_folder->GetProperty(itemIndex, kpidPackSize, &prop) != S_OK) throw 271932; - if (prop.vt == VT_EMPTY) - length = 0; - else - length = ::ConvertPropVariantToUInt64(prop); + length = 0; + ConvertPropVariantToUInt64(prop, length); panelItem.PackSize = UInt32(length); panelItem.PackSizeHigh = UInt32(length >> 32); @@ -150,8 +154,7 @@ int CPlugin::GetFindData(PluginPanelItem **panelItems, int *itemsNumber, int opM g_StartupInfo.GetMsgString(NMessageID::kWaitTitle), g_StartupInfo.GetMsgString(NMessageID::kReadingList) }; - g_StartupInfo.ShowMessage(0, NULL, msgItems, - sizeof(msgItems) / sizeof(msgItems[0]), 0); + g_StartupInfo.ShowMessage(0, NULL, msgItems, ARRAY_SIZE(msgItems), 0); */ } @@ -223,14 +226,14 @@ int CPlugin::SetDirectory(const char *aszDir, int /* opMode */) { _folder.Release(); m_ArchiveHandler->BindToRootFolder(&_folder); - path = path.Mid(1); + path.DeleteFrontal(1); } UStringVector pathParts; SplitPathToParts(path, pathParts); - for (int i = 0; i < pathParts.Size(); i++) + FOR_VECTOR (i, pathParts) EnterToDirectory(pathParts[i]); } - GetCurrentDir(); + SetCurrentDirVar(); return TRUE; } @@ -252,12 +255,12 @@ void CPlugin::GetPathParts(UStringVector &pathParts) } } -void CPlugin::GetCurrentDir() +void CPlugin::SetCurrentDirVar() { m_CurrentDir.Empty(); UStringVector pathParts; GetPathParts(pathParts); - for (int i = 0; i < pathParts.Size(); i++) + FOR_VECTOR (i, pathParts) { m_CurrentDir += WCHAR_PATH_SEPARATOR; m_CurrentDir += pathParts[i]; @@ -267,81 +270,11 @@ void CPlugin::GetCurrentDir() 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) +static int FindPropNameID(PROPID propID) { - for (int i = 0; i < kNumPROPIDToName; i++) - if (kPROPIDToName[i].PropID == propID) - return i; - return -1; + if (propID > NMessageID::k_Last_PropId_supported_by_plugin) + return -1; + return NMessageID::kNoProperty + propID; } /* @@ -374,8 +307,7 @@ static CPropertyIDInfo kPropertyIDInfos[] = // { kpidType, L"Type" } }; -static const int kNumPropertyIDInfos = sizeof(kPropertyIDInfos) / - sizeof(kPropertyIDInfos[0]); +static const int kNumPropertyIDInfos = ARRAY_SIZE(kPropertyIDInfos); static int FindPropertyInfo(PROPID propID) { @@ -423,23 +355,21 @@ void CPlugin::AddColumn(PROPID propID) 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); + int farID = FindPropNameID(propID); + if (farID >= 0) + return g_StartupInfo.GetMsgString(farID); + if (name) + return UnicodeStringToMultiByte((const wchar_t *)name, CP_OEMCP); + char s[16]; + ConvertUInt32ToString(propID, s); + return s; } static AString GetNameOfProp2(PROPID propID, const wchar_t *name) { AString s = GetNameOfProp(propID, name); - if (s.Length() > (kInfoPanelLineSize - 1)) - s = s.Left(kInfoPanelLineSize - 1); + if (s.Len() > (kInfoPanelLineSize - 1)) + s.DeleteFrom(kInfoPanelLineSize - 1); return s; } @@ -447,9 +377,9 @@ 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'; + unsigned i = MyStringLen(s); + unsigned pos = ARRAY_SIZE(s); + s[--pos] = 0; while (i > 3) { s[--pos] = s[--i]; @@ -476,7 +406,7 @@ static AString PropToString(const NCOM::CPropVariant &prop, PROPID propID) } else if (prop.vt != VT_EMPTY) { - if (( + if ((prop.vt == VT_UI8 || prop.vt == VT_UI4) && ( propID == kpidSize || propID == kpidPackSize || propID == kpidNumSubDirs || @@ -484,11 +414,20 @@ static AString PropToString(const NCOM::CPropVariant &prop, PROPID propID) propID == kpidNumBlocks || propID == kpidPhySize || propID == kpidHeadersSize || - propID == kpidClusterSize - ) && (prop.vt == VT_UI8 || prop.vt == VT_UI4)) - s = ConvertSizeToString(ConvertPropVariantToUInt64(prop)); + propID == kpidClusterSize || + propID == kpidUnpackSize + )) + { + UInt64 v = 0; + ConvertPropVariantToUInt64(prop, v); + s = ConvertSizeToString(v); + } else - s = UnicodeStringToMultiByte(ConvertPropertyToString(prop, propID), CP_OEMCP); + { + UString temp; + ConvertPropertyToString(temp, prop, propID); + s = UnicodeStringToMultiByte(temp, CP_OEMCP); + } } s.Replace((char)0xA, ' '); s.Replace((char)0xD, ' '); @@ -498,8 +437,8 @@ static AString PropToString(const NCOM::CPropVariant &prop, PROPID propID) static AString PropToString2(const NCOM::CPropVariant &prop, PROPID propID) { AString s = PropToString(prop, propID); - if (s.Length() > (kInfoPanelLineSize - 1)) - s = s.Left(kInfoPanelLineSize - 1); + if (s.Len() > (kInfoPanelLineSize - 1)) + s.DeleteFrom(kInfoPanelLineSize - 1); return s; } @@ -523,8 +462,8 @@ static void InsertSeparator(InfoPanelLine *lines, int &numItems) if (numItems < kNumInfoLinesMax) { InfoPanelLine &item = lines[numItems++]; - MyStringCopy(item.Text, ""); - MyStringCopy(item.Data, ""); + *item.Text = 0; + *item.Data = 0; item.Separator = TRUE; } } @@ -546,7 +485,7 @@ void CPlugin::GetOpenPluginInfo(struct OpenPluginInfo *info) UString name; { FString dirPrefix, fileName; - NFile::NDirectory::GetFullPathAndSplit(m_FileName, dirPrefix, fileName); + GetFullPathAndSplit(m_FileName, dirPrefix, fileName); name = fs2us(fileName); } @@ -566,7 +505,7 @@ void CPlugin::GetOpenPluginInfo(struct OpenPluginInfo *info) info->PanelTitle = m_PannelTitleBuffer; memset(m_InfoLines, 0, sizeof(m_InfoLines)); - MyStringCopy(m_InfoLines[0].Text, ""); + m_InfoLines[0].Text[0] = 0; m_InfoLines[0].Separator = TRUE; MyStringCopy(m_InfoLines[1].Text, g_StartupInfo.GetMsgString(NMessageID::kArchiveType)); @@ -734,15 +673,15 @@ HRESULT CPlugin::ShowAttributesWindow() if (!g_StartupInfo.ControlGetActivePanelCurrentItemInfo(pluginPanelItem)) return S_FALSE; if (strcmp(pluginPanelItem.FindData.cFileName, "..") == 0 && - NFile::NFind::NAttributes::IsDir(pluginPanelItem.FindData.dwFileAttributes)) + 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++) + unsigned i; + for (i = 0; i < numProps; i++) { CMyComBSTR name; PROPID propID; @@ -772,14 +711,9 @@ HRESULT CPlugin::ShowAttributesWindow() 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.DataMessageId = FindPropNameID(property.ID); + if (idi.DataMessageId < 0) idi.DataString = property.Name; - } - else - idi.DataMessageId = kPROPIDToName[index].PluginID; initDialogItems.Add(idi); NCOM::CPropVariant prop; @@ -794,47 +728,43 @@ HRESULT CPlugin::ShowAttributesWindow() } } - int numLines = values.Size(); + unsigned numLines = values.Size(); for (i = 0; i < numLines; i++) { CInitDialogItem &idi = initDialogItems[1 + i * 2 + 1]; idi.DataString = values[i]; } - int numDialogItems = initDialogItems.Size(); + unsigned 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); + CObjArray dialogItems(numDialogItems); + g_StartupInfo.InitDialogItems(&initDialogItems.Front(), dialogItems, numDialogItems); - int maxLen = 0; + unsigned maxLen = 0; for (i = 0; i < numLines; i++) { FarDialogItem &dialogItem = dialogItems[1 + i * 2]; - int len = (int)strlen(dialogItem.Data); + unsigned len = (unsigned)strlen(dialogItem.Data); if (len > maxLen) maxLen = len; } - int maxLen2 = 0; - const int kSpace = 10; + unsigned maxLen2 = 0; + const unsigned kSpace = 10; for (i = 0; i < numLines; i++) { FarDialogItem &dialogItem = dialogItems[1 + i * 2 + 1]; - int len = (int)strlen(dialogItem.Data); + unsigned 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(); + FarDialogItem &firstDialogItem = dialogItems[0]; firstDialogItem.Y2 = size - 2; firstDialogItem.X2 = xSize - 4; - /* int askCode = */ g_StartupInfo.ShowDialog(xSize, size, NULL, &dialogItems.Front(), numDialogItems); + /* int askCode = */ g_StartupInfo.ShowDialog(xSize, size, NULL, dialogItems, numDialogItems); return S_OK; } @@ -852,7 +782,7 @@ int CPlugin::ProcessKey(int key, unsigned int controlState) if ((controlState & PKF_ALT) != 0 && key == VK_F6) { FString folderPath; - if (!NFile::NDirectory::GetOnlyDirPrefix(m_FileName, folderPath)) + if (!GetOnlyDirPrefix(m_FileName, folderPath)) return FALSE; PanelInfo panelInfo; g_StartupInfo.ControlGetActivePanelInfo(panelInfo); diff --git a/CPP/7zip/UI/Far/Plugin.h b/CPP/7zip/UI/Far/Plugin.h old mode 100755 new mode 100644 index c4122c45..f01dc435 --- a/CPP/7zip/UI/Far/Plugin.h +++ b/CPP/7zip/UI/Far/Plugin.h @@ -3,11 +3,11 @@ #ifndef __7ZIP_FAR_PLUGIN_H #define __7ZIP_FAR_PLUGIN_H -#include "Common/MyCom.h" +#include "../../../Common/MyCom.h" -#include "Windows/COM.h" -#include "Windows/FileFind.h" -#include "Windows/PropVariant.h" +#include "../../../Windows/COM.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/PropVariant.h" #include "../Common/WorkDir.h" @@ -37,7 +37,7 @@ class CPlugin void EnterToDirectory(const UString &dirName); void GetPathParts(UStringVector &pathParts); - void GetCurrentDir(); + void SetCurrentDirVar(); HRESULT AfterUpdate(CWorkDirTempFile &tempFile, const UStringVector &pathVector); public: FString m_FileName; diff --git a/CPP/7zip/UI/Far/PluginCommon.cpp b/CPP/7zip/UI/Far/PluginCommon.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/Far/PluginDelete.cpp b/CPP/7zip/UI/Far/PluginDelete.cpp old mode 100755 new mode 100644 index 3a3df300..1adf91a7 --- a/CPP/7zip/UI/Far/PluginDelete.cpp +++ b/CPP/7zip/UI/Far/PluginDelete.cpp @@ -2,9 +2,11 @@ #include "StdAfx.h" +#include + #include "Messages.h" #include "Plugin.h" -#include "UpdateCallback100.h" +#include "UpdateCallbackFar.h" using namespace NFar; @@ -36,12 +38,10 @@ int CPlugin::DeleteFiles(PluginPanelItem *panelItems, int numItems, int opMode) } else if (numItems > 1) { - sprintf(msg, g_StartupInfo.GetMsgString(NMessageID::kDeleteNumberOfFiles), - numItems); + 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) + if (g_StartupInfo.ShowMessage(FMSG_WARNING, NULL, msgItems, ARRAY_SIZE(msgItems), 2) != 0) return (FALSE); } @@ -62,11 +62,10 @@ int CPlugin::DeleteFiles(PluginPanelItem *panelItems, int numItems, int opMode) if (tempFile.CreateTempFile(m_FileName) != S_OK) return FALSE; - CRecordVector indices; - indices.Reserve(numItems); + CObjArray indices(numItems); int i; for (i = 0; i < numItems; i++) - indices.Add((UINT32)panelItems[i].UserData); + indices[i] = (UInt32)panelItems[i].UserData; //////////////////////////// // Save _folder; @@ -88,7 +87,7 @@ int CPlugin::DeleteFiles(PluginPanelItem *panelItems, int numItems, int opMode) updateCallbackSpec->Init(/* m_ArchiveHandler, */ progressBoxPointer); - result = outArchive->DeleteItems(tempFile.OutStream, &indices.Front(), indices.Size(), updateCallback); + result = outArchive->DeleteItems(tempFile.OutStream, indices, numItems, updateCallback); updateCallback.Release(); outArchive.Release(); @@ -101,6 +100,6 @@ int CPlugin::DeleteFiles(PluginPanelItem *panelItems, int numItems, int opMode) ShowErrorMessage(result); return FALSE; } - GetCurrentDir(); + SetCurrentDirVar(); return TRUE; } diff --git a/CPP/7zip/UI/Far/PluginRead.cpp b/CPP/7zip/UI/Far/PluginRead.cpp old mode 100755 new mode 100644 index a4450064..6e77a9d5 --- a/CPP/7zip/UI/Far/PluginRead.cpp +++ b/CPP/7zip/UI/Far/PluginRead.cpp @@ -6,19 +6,20 @@ #include "Messages.h" -#include "Common/StringConvert.h" +#include "../../../Common/StringConvert.h" -#include "Windows/FileName.h" -#include "Windows/FileFind.h" -#include "Windows/FileDir.h" -#include "Windows/Defs.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/FileDir.h" #include "../Common/ZipRegistry.h" #include "ExtractEngine.h" -using namespace NFar; using namespace NWindows; +using namespace NFile; +using namespace NDir; +using namespace NFar; static const char *kHelpTopicExtrFromSevenZip = "Extract"; @@ -28,8 +29,8 @@ static const char *kExractPathHistoryName = "7-ZipExtractPath"; HRESULT CPlugin::ExtractFiles( bool decompressAllItems, - const UINT32 *indices, - UINT32 numIndices, + const UInt32 *indices, + UInt32 numIndices, bool silent, NExtract::NPathMode::EEnum pathMode, NExtract::NOverwriteMode::EEnum overwriteMode, @@ -70,7 +71,10 @@ HRESULT CPlugin::ExtractFiles( CMyComPtr archiveFolder; _folder.QueryInterface(IID_IArchiveFolder, &archiveFolder); - return archiveFolder->Extract(indices, numIndices, pathMode, overwriteMode, + return archiveFolder->Extract(indices, numIndices, + BoolToInt(true), // includeAltStreams + BoolToInt(false), // replaceAltStreamChars + pathMode, overwriteMode, destPath, BoolToInt(false), extractCallback); } } @@ -93,14 +97,14 @@ NFileOperationReturnCode::EEnum CPlugin::GetFilesReal(struct PluginPanelItem *pa AString destPath = destPathLoc; UString destPathU = GetUnicodeString(destPath, CP_OEMCP); - NFile::NName::NormalizeDirPathPrefix(destPathU); + NName::NormalizeDirPathPrefix(destPathU); destPath = UnicodeStringToMultiByte(destPathU, CP_OEMCP); bool extractSelectedFiles = true; NExtract::CInfo extractionInfo; - extractionInfo.PathMode = NExtract::NPathMode::kCurrentPathnames; - extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; + extractionInfo.PathMode = NExtract::NPathMode::kCurPaths; + extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kOverwrite; bool silent = (opMode & OPM_SILENT) != 0; bool decompressAllItems = false; @@ -134,30 +138,30 @@ NFileOperationReturnCode::EEnum CPlugin::GetFilesReal(struct PluginPanelItem *pa { 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, + extractionInfo.PathMode == NExtract::NPathMode::kFullPaths, DIF_GROUP, false, NMessageID::kExtractPathFull, NULL, NULL }, { DI_RADIOBUTTON, 6, 7, 0, 0, false, - extractionInfo.PathMode == NExtract::NPathMode::kCurrentPathnames, + extractionInfo.PathMode == NExtract::NPathMode::kCurPaths, 0, false, NMessageID::kExtractPathCurrent, NULL, NULL }, { DI_RADIOBUTTON, 6, 8, 0, 0, false, - extractionInfo.PathMode == NExtract::NPathMode::kNoPathnames, + extractionInfo.PathMode == NExtract::NPathMode::kNoPaths, 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, + extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kAsk, DIF_GROUP, false, NMessageID::kExtractOwerwriteAsk, NULL, NULL }, { DI_RADIOBUTTON, kXMid + 2, 7, 0, 0, false, - extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kWithoutPrompt, + extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kOverwrite, 0, false, NMessageID::kExtractOwerwritePrompt, NULL, NULL }, { DI_RADIOBUTTON, kXMid + 2, 8, 0, 0, false, - extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kSkipExisting, + extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kSkip, 0, false, NMessageID::kExtractOwerwriteSkip, NULL, NULL }, { DI_RADIOBUTTON, kXMid + 2, 9, 0, 0, false, - extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kAutoRename, + extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kRename, 0, false, NMessageID::kExtractOwerwriteAutoRename, NULL, NULL }, { DI_RADIOBUTTON, kXMid + 2, 10, 0, 0, false, - extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting, + extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kRenameExisting, 0, false, NMessageID::kExtractOwerwriteAutoRenameExisting, NULL, NULL }, { DI_SINGLEBOX, 4, 10, kXMid- 2, 10 + 3, false, false, 0, false, NMessageID::kExtractFilesMode, NULL, NULL }, @@ -174,7 +178,7 @@ NFileOperationReturnCode::EEnum CPlugin::GetFilesReal(struct PluginPanelItem *pa { 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 kNumDialogItems = ARRAY_SIZE(initItems); const int kOkButtonIndex = kNumDialogItems - 2; const int kPasswordIndex = kNumDialogItems - 4; @@ -195,9 +199,9 @@ NFileOperationReturnCode::EEnum CPlugin::GetFilesReal(struct PluginPanelItem *pa destPathU = L"\\"; #else FString destPathF = us2fs(destPathU); - if (!NFile::NDirectory::MyGetCurrentDirectory(destPathF)) + if (!GetCurrentDir(destPathF)) throw 318016; - NFile::NName::NormalizeDirPathPrefix(destPathF); + NName::NormalizeDirPathPrefix(destPathF); destPathU = fs2us(destPathF); #endif break; @@ -211,24 +215,24 @@ NFileOperationReturnCode::EEnum CPlugin::GetFilesReal(struct PluginPanelItem *pa } if (dialogItems[kPathModeRadioIndex].Selected) - extractionInfo.PathMode = NExtract::NPathMode::kFullPathnames; + extractionInfo.PathMode = NExtract::NPathMode::kFullPaths; else if (dialogItems[kPathModeRadioIndex + 1].Selected) - extractionInfo.PathMode = NExtract::NPathMode::kCurrentPathnames; + extractionInfo.PathMode = NExtract::NPathMode::kCurPaths; else if (dialogItems[kPathModeRadioIndex + 2].Selected) - extractionInfo.PathMode = NExtract::NPathMode::kNoPathnames; + extractionInfo.PathMode = NExtract::NPathMode::kNoPaths; else throw 31806; if (dialogItems[kOverwriteModeRadioIndex].Selected) - extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kAskBefore; + extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kAsk; else if (dialogItems[kOverwriteModeRadioIndex + 1].Selected) - extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; + extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kOverwrite; else if (dialogItems[kOverwriteModeRadioIndex + 2].Selected) - extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kSkipExisting; + extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kSkip; else if (dialogItems[kOverwriteModeRadioIndex + 3].Selected) - extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kAutoRename; + extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kRename; else if (dialogItems[kOverwriteModeRadioIndex + 4].Selected) - extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kAutoRenameExisting; + extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kRenameExisting; else throw 31806; @@ -253,19 +257,18 @@ NFileOperationReturnCode::EEnum CPlugin::GetFilesReal(struct PluginPanelItem *pa passwordIsDefined = !password.IsEmpty(); } - NFile::NDirectory::CreateComplexDirectory(us2fs(destPathU)); + CreateComplexDir(us2fs(destPathU)); /* vector realIndices; if (!decompressAllItems) GetRealIndexes(panelItems, itemsNumber, realIndices); */ - CRecordVector indices; - indices.Reserve(itemsNumber); + CObjArray indices(itemsNumber); for (int i = 0; i < itemsNumber; i++) - indices.Add((UINT32)panelItems[i].UserData); + indices[i] = (UInt32)panelItems[i].UserData; - HRESULT result = ExtractFiles(decompressAllItems, &indices.Front(), itemsNumber, + HRESULT result = ExtractFiles(decompressAllItems, indices, itemsNumber, !showBox, extractionInfo.PathMode, extractionInfo.OverwriteMode, destPathU, passwordIsDefined, password); diff --git a/CPP/7zip/UI/Far/PluginWrite.cpp b/CPP/7zip/UI/Far/PluginWrite.cpp old mode 100755 new mode 100644 index e02f4d80..e36f3911 --- a/CPP/7zip/UI/Far/PluginWrite.cpp +++ b/CPP/7zip/UI/Far/PluginWrite.cpp @@ -2,13 +2,15 @@ #include "StdAfx.h" +#include + #include "Plugin.h" -#include "Common/Wildcard.h" -#include "Common/StringConvert.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/Wildcard.h" -#include "Windows/FileName.h" -#include "Windows/FileFind.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/FileFind.h" #include "../Common/ZipRegistry.h" @@ -16,11 +18,11 @@ #include "ProgressBox.h" #include "Messages.h" -#include "UpdateCallback100.h" +#include "UpdateCallbackFar.h" using namespace NWindows; using namespace NFile; -using namespace NDirectory; +using namespace NDir; using namespace NFar; using namespace NUpdateArchive; @@ -29,9 +31,9 @@ static const char *kHelpTopic = "Update"; static const char *kArchiveHistoryKeyName = "7-ZipArcName"; -static const UINT32 g_MethodMap[] = { 0, 1, 3, 5, 7, 9 }; +static const UInt32 g_MethodMap[] = { 0, 1, 3, 5, 7, 9 }; -static HRESULT SetOutProperties(IOutFolderArchive *outArchive, UINT32 method) +static HRESULT SetOutProperties(IOutFolderArchive *outArchive, UInt32 method) { CMyComPtr setProperties; if (outArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties) == S_OK) @@ -40,7 +42,7 @@ static HRESULT SetOutProperties(IOutFolderArchive *outArchive, UINT32 method) realNames.Add(UString(L"x")); NCOM::CPropVariant value = (UInt32)method; CRecordVector names; - for (int i = 0; i < realNames.Size(); i++) + FOR_VECTOR (i, realNames) names.Add(realNames[i]); RINOK(setProperties->SetProperties(&names.Front(), &value, names.Size())); } @@ -57,7 +59,7 @@ HRESULT CPlugin::AfterUpdate(CWorkDirTempFile &tempFile, const UStringVector &pa RINOK(m_ArchiveHandler->ReOpen(NULL)); // check it m_ArchiveHandler->BindToRootFolder(&_folder); - for (int i = 0; i < pathVector.Size(); i++) + FOR_VECTOR (i, pathVector) { CMyComPtr newFolder; _folder->BindToFolder(pathVector[i], &newFolder); @@ -96,7 +98,7 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles( int methodIndex = 0; int i; - for (i = sizeof(g_MethodMap) / sizeof(g_MethodMap[0]) - 1; i >= 0; i--) + for (i = ARRAY_SIZE(g_MethodMap) - 1; i >= 0; i--) if (compressionInfo.Level >= g_MethodMap[i]) { methodIndex = i; @@ -108,29 +110,22 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles( 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_RADIOBUTTON, 6, 3, 0, 0, methodIndex == 0, methodIndex == 0, DIF_GROUP, false, NMessageID::kUpdateMethod_Store, NULL, NULL }, + { DI_RADIOBUTTON, 6, 4, 0, 0, methodIndex == 1, methodIndex == 1, 0, false, NMessageID::kUpdateMethod_Fastest, NULL, NULL }, + { DI_RADIOBUTTON, 6, 5, 0, 0, methodIndex == 2, methodIndex == 2, 0, false, NMessageID::kUpdateMethod_Fast, NULL, NULL }, + { DI_RADIOBUTTON, 6, 6, 0, 0, methodIndex == 3, methodIndex == 3, 0, false, NMessageID::kUpdateMethod_Normal, NULL, NULL }, + { DI_RADIOBUTTON, 6, 7, 0, 0, methodIndex == 4, methodIndex == 4, 0, false, NMessageID::kUpdateMethod_Maximum, NULL, NULL }, + { DI_RADIOBUTTON, 6, 8, 0, 0, methodIndex == 5, methodIndex == 5, 0, false, NMessageID::kUpdateMethod_Ultra, 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_RADIOBUTTON, kXMid + 2, 3, 0, 0, false, true, DIF_GROUP, false, NMessageID::kUpdateMode_Add, NULL, NULL }, + { DI_RADIOBUTTON, kXMid + 2, 4, 0, 0, false, false, 0, false, NMessageID::kUpdateMode_Update, NULL, NULL }, + { DI_RADIOBUTTON, kXMid + 2, 5, 0, 0, false, false, 0, false, NMessageID::kUpdateMode_Fresh, NULL, NULL }, + { DI_RADIOBUTTON, kXMid + 2, 6, 0, 0, false, false, 0, false, NMessageID::kUpdateMode_Sync, NULL, NULL }, { DI_TEXT, 3, kYSize - 4, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL }, @@ -138,7 +133,7 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles( { 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 kNumDialogItems = ARRAY_SIZE(initItems); const int kOkButtonIndex = kNumDialogItems - 2; FarDialogItem dialogItems[kNumDialogItems]; g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumDialogItems); @@ -148,22 +143,17 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles( return NFileOperationReturnCode::kInterruptedByUser; compressionInfo.Level = g_MethodMap[0]; - for (i = 0; i < sizeof(g_MethodMap)/ sizeof(g_MethodMap[0]); i++) + for (i = 0; i < ARRAY_SIZE(g_MethodMap); 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; + if (dialogItems[kModeRadioIndex ].Selected) actionSet = &k_ActionSet_Add; + else if (dialogItems[kModeRadioIndex + 1].Selected) actionSet = &k_ActionSet_Update; + else if (dialogItems[kModeRadioIndex + 2].Selected) actionSet = &k_ActionSet_Fresh; + else if (dialogItems[kModeRadioIndex + 3].Selected) actionSet = &k_ActionSet_Sync; + else throw 51751; compressionInfo.Save(); @@ -201,13 +191,12 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles( GetPathParts(pathVector); UStringVector fileNames; - fileNames.Reserve(numItems); + fileNames.ClearAndReserve(numItems); for (i = 0; i < numItems; i++) - fileNames.Add(MultiByteToUnicodeString(panelItems[i].FindData.cFileName, CP_OEMCP)); - CRecordVector fileNamePointers; - fileNamePointers.Reserve(numItems); + fileNames.AddInReserved(MultiByteToUnicodeString(panelItems[i].FindData.cFileName, CP_OEMCP)); + CObjArray fileNamePointers(numItems); for (i = 0; i < numItems; i++) - fileNamePointers.Add(fileNames[i]); + fileNamePointers[i] = fileNames[i]; CMyComPtr outArchive; HRESULT result = m_ArchiveHandler.QueryInterface(IID_IOutFolderArchive, &outArchive); @@ -218,7 +207,7 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles( } outArchive->SetFolder(_folder); - outArchive->SetFiles(L"", &fileNamePointers.Front(), fileNamePointers.Size()); + outArchive->SetFiles(L"", fileNamePointers, numItems); BYTE actionSetByte[NUpdateArchive::NPairState::kNumValues]; for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++) actionSetByte[i] = (BYTE)actionSet->StateActions[i]; @@ -231,7 +220,12 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles( if (SetOutProperties(outArchive, compressionInfo.Level) != S_OK) return NFileOperationReturnCode::kError; - result = outArchive->DoOperation2(tempFile.OutStream, actionSetByte, NULL, updateCallback); + // FStringVector requestedPaths; + // FStringVector processedPaths; + result = outArchive->DoOperation2( + // &requestedPaths, &processedPaths, + NULL, NULL, + tempFile.OutStream, actionSetByte, NULL, updateCallback); updateCallback.Release(); outArchive.Release(); @@ -289,7 +283,7 @@ namespace NPathType { EEnum GetPathType(const UString &path) { - if (path.Length() <= 2) + if (path.Len() <= 2) return kLocal; if (path[0] == kDirDelimiter && path[1] == kDirDelimiter) return kUNC; @@ -308,7 +302,7 @@ void CParsedPath::ParsePath(const UString &path) if (posDiskDelimiter >= 0) { curPos = posDiskDelimiter + 1; - if (path.Length() > curPos) + if ((int)path.Len() > curPos) if (path[curPos] == kDirDelimiter) curPos++; } @@ -316,21 +310,22 @@ void CParsedPath::ParsePath(const UString &path) } case NPathType::kUNC: { - int curPos = path.Find(kDirDelimiter, 2); + // the bug was fixed: + curPos = path.Find(kDirDelimiter, 2); if (curPos < 0) - curPos = path.Length(); + curPos = path.Len(); else curPos++; } } Prefix = path.Left(curPos); - SplitPathToParts(path.Mid(curPos), PathParts); + SplitPathToParts(path.Ptr(curPos), PathParts); } UString CParsedPath::MergePath() const { UString result = Prefix; - for (int i = 0; i < PathParts.Size(); i++) + FOR_VECTOR (i, PathParts) { if (i != 0) result += kDirDelimiter; @@ -352,21 +347,22 @@ HRESULT CompressFiles(const CObjectVector &pluginPanelItems) return E_FAIL; UStringVector fileNames; - int i; - for (i = 0; i < pluginPanelItems.Size(); i++) { - const PluginPanelItem &panelItem = pluginPanelItems[i]; - 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; - FString fullPath; - FString fileNameUnicode = us2fs(MultiByteToUnicodeString(panelItem.FindData.cFileName, CP_OEMCP)); - if (!MyGetFullPathName(fileNameUnicode, fullPath)) - return E_FAIL; - fileNames.Add(fs2us(fullPath)); + FOR_VECTOR (i, pluginPanelItems) + { + const PluginPanelItem &panelItem = pluginPanelItems[i]; + 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; + FString fullPath; + FString fileNameUnicode = us2fs(MultiByteToUnicodeString(panelItem.FindData.cFileName, CP_OEMCP)); + if (!MyGetFullPathName(fileNameUnicode, fullPath)) + return E_FAIL; + fileNames.Add(fs2us(fullPath)); + } } NCompression::CInfo compressionInfo; @@ -379,14 +375,14 @@ HRESULT CompressFiles(const CObjectVector &pluginPanelItems) if (codecs->Load() != S_OK) throw "Can't load 7-Zip codecs"; { - for (int i = 0; i < codecs->Formats.Size(); i++) + FOR_VECTOR (i, codecs->Formats) { const CArcInfoEx &arcInfo = codecs->Formats[i]; if (arcInfo.UpdateEnabled) { if (archiverIndex == -1) archiverIndex = i; - if (arcInfo.Name.CompareNoCase(compressionInfo.ArcType) == 0) + if (MyStringCompareNoCase(arcInfo.Name, compressionInfo.ArcType) == 0) archiverIndex = i; } } @@ -416,7 +412,7 @@ HRESULT CompressFiles(const CObjectVector &pluginPanelItems) const CArcInfoEx &arcInfo = codecs->Formats[archiverIndex]; int prevFormat = archiverIndex; - if (!arcInfo.KeepName) + if (!arcInfo.Flags_KeepName()) { int dotPos = archiveName.ReverseFind('.'); int slashPos = MyMax(archiveName.ReverseFind('\\'), archiveName.ReverseFind('/')); @@ -426,7 +422,7 @@ HRESULT CompressFiles(const CObjectVector &pluginPanelItems) archiveName += L'.'; archiveName += arcInfo.GetMainExt(); - const CActionSet *actionSet = &kAddActionSet; + const CActionSet *actionSet = &k_ActionSet_Add; for (;;) { @@ -448,7 +444,7 @@ HRESULT CompressFiles(const CObjectVector &pluginPanelItems) int methodIndex = 0; int i; - for (i = sizeof(g_MethodMap) / sizeof(g_MethodMap[0]) - 1; i >= 0; i--) + for (i = ARRAY_SIZE(g_MethodMap) - 1; i >= 0; i--) if (compressionInfo.Level >= g_MethodMap[i]) { methodIndex = i; @@ -465,32 +461,20 @@ HRESULT CompressFiles(const CObjectVector &pluginPanelItems) // { 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_RADIOBUTTON, 6, 5, 0, 0, false, methodIndex == 0, DIF_GROUP, false, NMessageID::kUpdateMethod_Store, NULL, NULL }, + { DI_RADIOBUTTON, 6, 6, 0, 0, false, methodIndex == 1, 0, false, NMessageID::kUpdateMethod_Fastest, NULL, NULL }, + { DI_RADIOBUTTON, 6, 7, 0, 0, false, methodIndex == 2, 0, false, NMessageID::kUpdateMethod_Fast, NULL, NULL }, + { DI_RADIOBUTTON, 6, 8, 0, 0, false, methodIndex == 3, 0, false, NMessageID::kUpdateMethod_Normal, NULL, NULL }, + { DI_RADIOBUTTON, 6, 9, 0, 0, false, methodIndex == 4, 0, false, NMessageID::kUpdateMethod_Maximum, NULL, NULL }, + { DI_RADIOBUTTON, 6,10, 0, 0, false, methodIndex == 5, 0, false, NMessageID::kUpdateMethod_Ultra, 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_RADIOBUTTON, kXMid + 2, 5, 0, 0, false, actionSet == &k_ActionSet_Add, DIF_GROUP, false, NMessageID::kUpdateMode_Add, NULL, NULL }, + { DI_RADIOBUTTON, kXMid + 2, 6, 0, 0, false, actionSet == &k_ActionSet_Update, 0, false, NMessageID::kUpdateMode_Update, NULL, NULL }, + { DI_RADIOBUTTON, kXMid + 2, 7, 0, 0, false, actionSet == &k_ActionSet_Fresh, 0, false, NMessageID::kUpdateMode_Fresh, NULL, NULL }, + { DI_RADIOBUTTON, kXMid + 2, 8, 0, 0, false, actionSet == &k_ActionSet_Sync, 0, false, NMessageID::kUpdateMode_Sync, NULL, NULL }, { DI_TEXT, 3, kYSize - 4, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL }, @@ -499,7 +483,7 @@ HRESULT CompressFiles(const CObjectVector &pluginPanelItems) { 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 kNumDialogItems = ARRAY_SIZE(initItems); const int kOkButtonIndex = kNumDialogItems - 3; const int kSelectarchiverButtonIndex = kNumDialogItems - 2; @@ -514,26 +498,21 @@ HRESULT CompressFiles(const CObjectVector &pluginPanelItems) archiveName = MultiByteToUnicodeString(archiveNameA, CP_OEMCP); compressionInfo.Level = g_MethodMap[0]; - for (i = 0; i < sizeof(g_MethodMap)/ sizeof(g_MethodMap[0]); i++) + for (i = 0; i < ARRAY_SIZE(g_MethodMap); 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 (dialogItems[kModeRadioIndex ].Selected) actionSet = &k_ActionSet_Add; + else if (dialogItems[kModeRadioIndex + 1].Selected) actionSet = &k_ActionSet_Update; + else if (dialogItems[kModeRadioIndex + 2].Selected) actionSet = &k_ActionSet_Fresh; + else if (dialogItems[kModeRadioIndex + 3].Selected) actionSet = &k_ActionSet_Sync; + else throw 51751; if (askCode == kSelectarchiverButtonIndex) { CIntVector indices; CSysStringVector archiverNames; - for (int i = 0; i < codecs->Formats.Size(); i++) + FOR_VECTOR (i, codecs->Formats) { const CArcInfoEx &arc = codecs->Formats[i]; if (arc.UpdateEnabled) @@ -549,13 +528,14 @@ HRESULT CompressFiles(const CObjectVector &pluginPanelItems) if (index >= 0) { const CArcInfoEx &prevArchiverInfo = codecs->Formats[prevFormat]; - if (prevArchiverInfo.KeepName) + if (prevArchiverInfo.Flags_KeepName()) { const UString &prevExtension = prevArchiverInfo.GetMainExt(); - const int prevExtensionLen = prevExtension.Length(); - if (archiveName.Right(prevExtensionLen).CompareNoCase(prevExtension) == 0) + const unsigned prevExtensionLen = prevExtension.Len(); + if (archiveName.Len() >= prevExtensionLen && + MyStringCompareNoCase(archiveName.RightPtr(prevExtensionLen), prevExtension) == 0) { - int pos = archiveName.Length() - prevExtensionLen; + int pos = archiveName.Len() - prevExtensionLen; if (pos > 1) { int dotPos = archiveName.ReverseFind('.'); @@ -569,7 +549,7 @@ HRESULT CompressFiles(const CObjectVector &pluginPanelItems) const CArcInfoEx &arcInfo = codecs->Formats[archiverIndex]; prevFormat = archiverIndex; - if (arcInfo.KeepName) + if (arcInfo.Flags_KeepName()) archiveName = archiveNameSrc; else { @@ -636,7 +616,7 @@ HRESULT CompressFiles(const CObjectVector &pluginPanelItems) &archiveType, NULL)); - if (archiverInfoFinal.Name.CompareNoCase((const wchar_t *)archiveType) != 0) + if (MyStringCompareNoCase(archiverInfoFinal.Name, (const wchar_t *)archiveType) != 0) throw "Type of existing archive differs from specified type"; HRESULT result = archiveHandler.QueryInterface( IID_IOutFolderArchive, &outArchive); @@ -662,13 +642,14 @@ HRESULT CompressFiles(const CObjectVector &pluginPanelItems) */ } - CRecordVector fileNamePointers; - fileNamePointers.Reserve(fileNames.Size()); + CObjArray fileNamePointers(fileNames.Size()); + + unsigned i; for (i = 0; i < fileNames.Size(); i++) - fileNamePointers.Add(fileNames[i]); + fileNamePointers[i] = fileNames[i]; outArchive->SetFolder(NULL); - outArchive->SetFiles(L"", &fileNamePointers.Front(), fileNamePointers.Size()); + outArchive->SetFiles(L"", fileNamePointers, fileNames.Size()); BYTE actionSetByte[NUpdateArchive::NPairState::kNumValues]; for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++) actionSetByte[i] = (BYTE)actionSet->StateActions[i]; @@ -681,7 +662,11 @@ HRESULT CompressFiles(const CObjectVector &pluginPanelItems) RINOK(SetOutProperties(outArchive, compressionInfo.Level)); + // FStringVector requestedPaths; + // FStringVector processedPaths; HRESULT result = outArchive->DoOperation( + // &requestedPaths, &processedPaths, + NULL, NULL, codecs, archiverIndex, tempFile.OutStream, actionSetByte, NULL, updateCallback); @@ -698,10 +683,12 @@ HRESULT CompressFiles(const CObjectVector &pluginPanelItems) { archiveHandler->Close(); } - if (!tempFile.MoveToOriginal(archiveHandler != NULL)) + + result = tempFile.MoveToOriginal(archiveHandler != NULL); + if (result != S_OK) { - ShowLastErrorMessage(); - return E_FAIL; + ShowErrorMessage(result); + return result; } return S_OK; } diff --git a/CPP/7zip/UI/Far/ProgressBox.cpp b/CPP/7zip/UI/Far/ProgressBox.cpp old mode 100755 new mode 100644 index b13b0b51..3ad0560a --- a/CPP/7zip/UI/Far/ProgressBox.cpp +++ b/CPP/7zip/UI/Far/ProgressBox.cpp @@ -4,9 +4,10 @@ #include -#include "ProgressBox.h" -#include "Common/IntToString.h" +#include "../../../Common/IntToString.h" + #include "FarUtils.h" +#include "ProgressBox.h" static void CopySpaces(char *dest, int numSpaces) { @@ -106,7 +107,7 @@ void CProgressBox::Progress(const UInt64 *total, const UInt64 *completed, const _prevMessage = message; _prevPercentMessage = percentMessage; const char *strings[] = { message, percentMessage }; - ShowMessages(strings, sizeof(strings) / sizeof(strings[0])); + ShowMessages(strings, ARRAY_SIZE(strings)); _wasShown = true; } } diff --git a/CPP/7zip/UI/Far/ProgressBox.h b/CPP/7zip/UI/Far/ProgressBox.h old mode 100755 new mode 100644 index 2bada8e9..9c26763d --- a/CPP/7zip/UI/Far/ProgressBox.h +++ b/CPP/7zip/UI/Far/ProgressBox.h @@ -1,10 +1,10 @@ // ProgressBox.h -#ifndef __PROGRESSBOX_H -#define __PROGRESSBOX_H +#ifndef __PROGRESS_BOX_H +#define __PROGRESS_BOX_H -#include "Common/MyString.h" -#include "Common/Types.h" +#include "../../../Common/MyString.h" +#include "../../../Common/MyTypes.h" void ConvertUInt64ToStringAligned(UInt64 value, char *s, int alignSize); diff --git a/CPP/7zip/UI/Far/StdAfx.cpp b/CPP/7zip/UI/Far/StdAfx.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/Far/StdAfx.h b/CPP/7zip/UI/Far/StdAfx.h old mode 100755 new mode 100644 index ae0e328a..3bff655e --- a/CPP/7zip/UI/Far/StdAfx.h +++ b/CPP/7zip/UI/Far/StdAfx.h @@ -3,11 +3,11 @@ #ifndef __STDAFX_H #define __STDAFX_H -#define _CRT_SECURE_NO_DEPRECATE -#include -#include +// #define _CRT_SECURE_NO_DEPRECATE +// #include +// #include -#include "Common/NewHandler.h" +#include "../../../Common/Common.h" #endif diff --git a/CPP/7zip/UI/Far/UpdateCallback100.cpp b/CPP/7zip/UI/Far/UpdateCallback100.cpp deleted file mode 100755 index 0785f55b..00000000 --- a/CPP/7zip/UI/Far/UpdateCallback100.cpp +++ /dev/null @@ -1,66 +0,0 @@ -// 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 deleted file mode 100755 index bfe8419a..00000000 --- a/CPP/7zip/UI/Far/UpdateCallback100.h +++ /dev/null @@ -1,43 +0,0 @@ -// 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/UpdateCallbackFar.cpp b/CPP/7zip/UI/Far/UpdateCallbackFar.cpp new file mode 100644 index 00000000..f2877888 --- /dev/null +++ b/CPP/7zip/UI/Far/UpdateCallbackFar.cpp @@ -0,0 +1,65 @@ +// UpdateCallbackFar.cpp + +#include "StdAfx.h" + +#include "../../../Common/StringConvert.h" + +#include "FarUtils.h" +#include "UpdateCallbackFar.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/UpdateCallbackFar.h b/CPP/7zip/UI/Far/UpdateCallbackFar.h new file mode 100644 index 00000000..b2980f21 --- /dev/null +++ b/CPP/7zip/UI/Far/UpdateCallbackFar.h @@ -0,0 +1,43 @@ +// UpdateCallbackFar.h + +#ifndef __UPDATE_CALLBACK_FAR_H +#define __UPDATE_CALLBACK_FAR_H + +#include "../../../Common/MyCom.h" + +#include "../../IPassword.h" + +#include "../Agent/IFolderArchive.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 old mode 100755 new mode 100644 index 0d6f8d68..2c32d533 --- a/CPP/7zip/UI/Far/makefile +++ b/CPP/7zip/UI/Far/makefile @@ -1,24 +1,24 @@ PROG = 7-ZipFar.dll DEF_FILE = Far.def -CFLAGS = $(CFLAGS) -I ../../../ \ +CFLAGS = $(CFLAGS) \ -DEXTERNAL_CODECS !IFNDEF UNDER_CE CFLAGS = $(CFLAGS) -DWIN_LONG_PATH !ENDIF -FAR_OBJS = \ +CURRENT_OBJS = \ $O\ExtractEngine.obj \ $O\FarUtils.obj \ - $O\Main.obj \ - $O\OverwriteDialog.obj \ + $O\Far.obj \ + $O\OverwriteDialogFar.obj \ $O\Plugin.obj \ $O\PluginCommon.obj \ $O\PluginDelete.obj \ $O\PluginRead.obj \ $O\PluginWrite.obj \ $O\ProgressBox.obj \ - $O\UpdateCallback100.obj \ + $O\UpdateCallbackFar.obj \ COMMON_OBJS = \ $O\IntToString.obj \ @@ -31,22 +31,27 @@ COMMON_OBJS = \ WIN_OBJS = \ $O\DLL.obj \ - $O\Error.obj \ + $O\ErrorMsg.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ + $O\FileLink.obj \ $O\FileName.obj \ $O\PropVariant.obj \ - $O\PropVariantConversions.obj \ + $O\PropVariantConv.obj \ $O\Registry.obj \ $O\Synchronization.obj \ - $O\Time.obj \ + $O\TimeUtils.obj \ 7ZIP_COMMON_OBJS = \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ + $O\LimitedStreams.obj \ $O\ProgressUtils.obj \ + $O\PropId.obj \ + $O\StreamObjects.obj \ $O\StreamUtils.obj \ + $O\UniqBlocks.obj \ UI_COMMON_OBJS = \ $O\ArchiveExtractCallback.obj \ @@ -57,6 +62,7 @@ UI_COMMON_OBJS = \ $O\LoadCodecs.obj \ $O\OpenArchive.obj \ $O\PropIDUtils.obj \ + $O\SetProperties.obj \ $O\SortUtils.obj \ $O\UpdateAction.obj \ $O\UpdateCallback.obj \ @@ -74,6 +80,9 @@ AGENT_OBJS = \ $O\AgentProxy.obj \ $O\UpdateCallbackAgent.obj \ +COMPRESS_OBJS = \ + $O\CopyCoder.obj \ + C_OBJS = \ $O\Alloc.obj \ $O\CpuArch.obj \ @@ -82,38 +91,4 @@ C_OBJS = \ !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" +!include "../../7zip.mak" diff --git a/CPP/7zip/UI/Far/resource.rc b/CPP/7zip/UI/Far/resource.rc old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/7zFM.exe.manifest b/CPP/7zip/UI/FileManager/7zFM.exe.manifest old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/7zipLogo.ico b/CPP/7zip/UI/FileManager/7zipLogo.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/AboutDialog.cpp b/CPP/7zip/UI/FileManager/AboutDialog.cpp old mode 100755 new mode 100644 index edfa98ba..10d76671 --- a/CPP/7zip/UI/FileManager/AboutDialog.cpp +++ b/CPP/7zip/UI/FileManager/AboutDialog.cpp @@ -2,31 +2,41 @@ #include "StdAfx.h" +#include "../../../../C/CpuArch.h" + +#include "../../MyVersion.h" + #include "AboutDialog.h" +#include "PropertyNameRes.h" + #include "HelpUtils.h" #include "LangUtils.h" -static CIDLangPair kIDLangPairs[] = +static const UInt32 kLangIDs[] = { - { IDC_ABOUT_STATIC_REGISTER_INFO, 0x01000103 }, - { IDC_ABOUT_BUTTON_SUPPORT, 0x01000104 }, - { IDC_ABOUT_BUTTON_REGISTER, 0x01000105 }, - { IDOK, 0x02000702 } + IDT_ABOUT_INFO }; -#define MY_HOME_PAGE TEXT("http://www.7-zip.org/") - -static LPCTSTR kHomePageURL = MY_HOME_PAGE; -/* -static LPCTSTR kRegisterPageURL = MY_HOME_PAGE TEXT("register.html"); -static LPCTSTR kSupportPageURL = MY_HOME_PAGE TEXT("support.html"); -*/ +static LPCTSTR kHomePageURL = TEXT("http://www.7-zip.org/"); static LPCWSTR kHelpTopic = L"start.htm"; +#define LLL_(quote) L##quote +#define LLL(quote) LLL_(quote) + bool CAboutDialog::OnInit() { - LangSetWindowText(HWND(*this), 0x01000100); - LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); + UString s = L"7-Zip " LLL(MY_VERSION); + #ifdef MY_CPU_64BIT + s += L" ["; + s += LangString(IDS_PROP_BIT64); + s += L']'; + #endif + + SetItemText(IDT_ABOUT_VERSION, s); + SetItemText(IDT_ABOUT_DATE, LLL(MY_DATE)); + + LangSetWindowText(*this, IDD_ABOUT); NormalizePosition(); return CModalDialog::OnInit(); } @@ -39,13 +49,9 @@ void CAboutDialog::OnHelp() bool CAboutDialog::OnButtonClicked(int buttonID, HWND buttonHWND) { LPCTSTR url; - switch(buttonID) + switch (buttonID) { - case IDC_ABOUT_BUTTON_HOMEPAGE: url = kHomePageURL; break; - /* - case IDC_ABOUT_BUTTON_REGISTER: url = kRegisterPageURL; break; - case IDC_ABOUT_BUTTON_SUPPORT: url = kSupportPageURL; break; - */ + case IDB_ABOUT_HOMEPAGE: url = kHomePageURL; break; default: return CModalDialog::OnButtonClicked(buttonID, buttonHWND); } diff --git a/CPP/7zip/UI/FileManager/AboutDialog.h b/CPP/7zip/UI/FileManager/AboutDialog.h old mode 100755 new mode 100644 index c8a4ea9b..39fd3ba7 --- a/CPP/7zip/UI/FileManager/AboutDialog.h +++ b/CPP/7zip/UI/FileManager/AboutDialog.h @@ -1,10 +1,11 @@ // AboutDialog.h -#ifndef __ABOUTDIALOG_H -#define __ABOUTDIALOG_H +#ifndef __ABOUT_DIALOG_H +#define __ABOUT_DIALOG_H + +#include "../../../Windows/Control/Dialog.h" #include "AboutDialogRes.h" -#include "Windows/Control/Dialog.h" class CAboutDialog: public NWindows::NControl::CModalDialog { diff --git a/CPP/7zip/UI/FileManager/AboutDialog.rc b/CPP/7zip/UI/FileManager/AboutDialog.rc old mode 100755 new mode 100644 index fcf2ae6e..6953c141 --- a/CPP/7zip/UI/FileManager/AboutDialog.rc +++ b/CPP/7zip/UI/FileManager/AboutDialog.rc @@ -5,7 +5,7 @@ #define xc 144 #define yc 144 -#define y 80 +#define y 93 IDI_LOGO ICON "../../UI/FileManager/7zipLogo.ico" @@ -13,14 +13,14 @@ IDI_LOGO ICON "../../UI/FileManager/7zipLogo.ico" #define SS_REALSIZEIMAGE 0x800 #endif -IDD_ABOUT MY_DIALOG +IDD_ABOUT DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT CAPTION "About 7-Zip" { DEFPUSHBUTTON "OK", IDOK, bx1, by, bxs, bys - PUSHBUTTON "www.7-zip.org", IDC_ABOUT_BUTTON_HOMEPAGE, bx2, by, bxs, bys - ICON IDI_LOGO, -1, m, m, 32, 32, SS_REALSIZEIMAGE - LTEXT MY_7ZIP_VERSION, -1, m, 54, xc, 8 - LTEXT MY_COPYRIGHT, -1, m, 67, xc, 8 - LTEXT "7-Zip is free software", - IDC_ABOUT_STATIC_REGISTER_INFO, m, y, xc, (by - y - 1) + PUSHBUTTON "www.7-zip.org", IDB_ABOUT_HOMEPAGE, bx2, by, bxs, bys + ICON IDI_LOGO, -1, m, m, 32, 32, SS_REALSIZEIMAGE, + LTEXT "", IDT_ABOUT_VERSION, m, 54, xc, 8 + LTEXT "", IDT_ABOUT_DATE, m, 67, xc, 8 + LTEXT MY_COPYRIGHT, -1, m, 80, xc, 8 + LTEXT "7-Zip is free software", IDT_ABOUT_INFO, m, y, xc, (by - y - 1) } diff --git a/CPP/7zip/UI/FileManager/AboutDialogRes.h b/CPP/7zip/UI/FileManager/AboutDialogRes.h old mode 100755 new mode 100644 index f7dd0602..b4165580 --- a/CPP/7zip/UI/FileManager/AboutDialogRes.h +++ b/CPP/7zip/UI/FileManager/AboutDialogRes.h @@ -1,6 +1,8 @@ -#define IDD_ABOUT 507 -#define IDI_LOGO 138 -#define IDC_ABOUT_STATIC_REGISTER_INFO 1010 -#define IDC_ABOUT_BUTTON_HOMEPAGE 1020 -#define IDC_ABOUT_BUTTON_SUPPORT 1021 -#define IDC_ABOUT_BUTTON_REGISTER 1022 +#define IDD_ABOUT 2900 + +#define IDT_ABOUT_INFO 2901 + +#define IDI_LOGO 100 +#define IDT_ABOUT_VERSION 101 +#define IDT_ABOUT_DATE 102 +#define IDB_ABOUT_HOMEPAGE 110 diff --git a/CPP/7zip/UI/FileManager/Add.bmp b/CPP/7zip/UI/FileManager/Add.bmp old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/Add2.bmp b/CPP/7zip/UI/FileManager/Add2.bmp old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/App.cpp b/CPP/7zip/UI/FileManager/App.cpp old mode 100755 new mode 100644 index 5f31f607..51c8d2db --- a/CPP/7zip/UI/FileManager/App.cpp +++ b/CPP/7zip/UI/FileManager/App.cpp @@ -5,17 +5,17 @@ #include "resource.h" #include "OverwriteDialogRes.h" -#include "Common/IntToString.h" -#include "Common/StringConvert.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/PropVariantConv.h" +/* #include "Windows/COM.h" #include "Windows/Error.h" #include "Windows/FileDir.h" -#include "Windows/FileName.h" #include "Windows/PropVariant.h" -#include "Windows/PropVariantConversions.h" #include "Windows/Thread.h" +*/ #include "App.h" #include "CopyDialog.h" @@ -26,9 +26,13 @@ #include "RegistryUtils.h" #include "ViewSettings.h" +#include "PropertyNameRes.h" + using namespace NWindows; using namespace NFile; +using namespace NDir; using namespace NFind; +using namespace NName; extern DWORD g_ComCtl32Version; extern HINSTANCE g_hInstance; @@ -61,6 +65,11 @@ void CPanelCallbackImp::DragBegin() { _app->DragBegin(_index); } void CPanelCallbackImp::DragEnd() { _app->DragEnd(); } void CPanelCallbackImp::RefreshTitle(bool always) { _app->RefreshTitle(_index, always); } +void CApp::ReloadLang() +{ + LangString(IDS_N_SELECTED_ITEMS, LangString_N_SELECTED_ITEMS); +} + void CApp::SetListSettings() { bool showDots = ReadShowDots(); @@ -102,7 +111,7 @@ void CApp::SetListSettings() void CApp::SetShowSystemMenu() { - ShowSystemMenu = ReadShowSystemMenu(); + ShowSystemMenu = Read_ShowSystemMenu(); } #ifndef ILC_COLOR32 @@ -166,23 +175,23 @@ struct CButtonInfo UINT BitmapResID; UINT Bitmap2ResID; UINT StringResID; - UInt32 LangID; - UString GetText() const { return LangString(StringResID, LangID); } + + UString GetText() const { return LangString(StringResID); } }; 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} + { IDM_COPY_TO, IDB_COPY, IDB_COPY2, IDS_BUTTON_COPY }, + { IDM_MOVE_TO, IDB_MOVE, IDB_MOVE2, IDS_BUTTON_MOVE }, + { IDM_DELETE, IDB_DELETE, IDB_DELETE2, IDS_BUTTON_DELETE } , + { IDM_PROPERTIES, IDB_INFO, IDB_INFO2, IDS_BUTTON_INFO } }; 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} + { kMenuCmdID_Toolbar_Add, IDB_ADD, IDB_ADD2, IDS_ADD }, + { kMenuCmdID_Toolbar_Extract, IDB_EXTRACT, IDB_EXTRACT2, IDS_EXTRACT }, + { kMenuCmdID_Toolbar_Test, IDB_TEST, IDB_TEST2, IDS_TEST } }; static bool SetButtonText(int commandID, CButtonInfo *buttons, int numButtons, UString &s) @@ -201,11 +210,9 @@ static bool SetButtonText(int commandID, CButtonInfo *buttons, int numButtons, U static void SetButtonText(int commandID, UString &s) { - if (SetButtonText(commandID, g_StandardButtons, - sizeof(g_StandardButtons) / sizeof(g_StandardButtons[0]), s)) + if (SetButtonText(commandID, g_StandardButtons, ARRAY_SIZE(g_StandardButtons), s)) return; - SetButtonText(commandID, g_ArchiveButtons, - sizeof(g_ArchiveButtons) / sizeof(g_ArchiveButtons[0]), s); + SetButtonText(commandID, g_ArchiveButtons, ARRAY_SIZE(g_ArchiveButtons), s); } static void AddButton( @@ -253,10 +260,10 @@ void CApp::ReloadToolbars() CreateToolbar(_window, _buttonsImageList, _toolBar, LargeButtons); int i; if (ShowArchiveToolbar) - for (i = 0; i < sizeof(g_ArchiveButtons) / sizeof(g_ArchiveButtons[0]); i++) + for (i = 0; i < ARRAY_SIZE(g_ArchiveButtons); i++) AddButton(_buttonsImageList, _toolBar, g_ArchiveButtons[i], ShowButtonsLables, LargeButtons); if (ShowStandardToolbar) - for (i = 0; i < sizeof(g_StandardButtons) / sizeof(g_StandardButtons[0]); i++) + for (i = 0; i < ARRAY_SIZE(g_StandardButtons); i++) AddButton(_buttonsImageList, _toolBar, g_StandardButtons[i], ShowButtonsLables, LargeButtons); _toolBar.AutoSize(); @@ -295,9 +302,10 @@ HRESULT CApp::Create(HWND hwnd, const UString &mainPath, const UString &arcForma SetShowSystemMenu(); if (LastFocusedPanel >= kNumPanelsMax) LastFocusedPanel = 0; + // ShowDeletedFiles = Read_ShowDeleted(); CListMode listMode; - ReadListMode(listMode); + listMode.Read(); for (i = 0; i < kNumPanelsMax; i++) { CPanel &panel = Panels[i]; @@ -361,7 +369,8 @@ void CApp::Save() listMode.Panels[i] = panel.GetListViewMode(); SaveFlatView(i, panel._flatModeForArc); } - SaveListMode(listMode); + listMode.Save(); + // Save_ShowDeleted(ShowDeletedFiles); } void CApp::Release() @@ -383,20 +392,20 @@ static void ReducePathToRealFileSystemPath(UString &path) } int pos = path.ReverseFind(WCHAR_PATH_SEPARATOR); if (pos < 0) + { path.Empty(); - else + break; + } + path.DeleteFrom(pos + 1); + if (path.Len() == 3 && path[1] == L':') + break; + if (path.Len() > 2 && path[0] == '\\' && path[1] == '\\') { - path = path.Left(pos + 1); - if (path.Length() == 3 && path[1] == L':') + int nextPos = path.Find(WCHAR_PATH_SEPARATOR, 2); // pos after \\COMPNAME + if (nextPos > 0 && path.Find(WCHAR_PATH_SEPARATOR, nextPos + 1) == pos) 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); } + path.DeleteFrom(pos); } } @@ -408,38 +417,27 @@ static bool CheckFolderPath(const UString &path) 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)); + return MyFormatNew(IDS_FILE_SIZE, ConvertSizeToString(size)); } -static void AddValuePair1(UINT resourceID, UInt32 langID, UInt64 size, UString &s) +static void AddValuePair1(UString &s, UINT resourceID, UInt64 size) { - s += LangString(resourceID, langID); - s += L" "; + s += LangString(resourceID); + s += L": "; s += AddSizeValue(size); - s += L"\n"; + s += L'\n'; } -void AddValuePair2(UINT resourceID, UInt32 langID, UInt64 num, UInt64 size, UString &s) +void AddValuePair2(UString &s, UINT resourceID, UInt64 num, UInt64 size) { if (num == 0) return; - s += LangString(resourceID, langID); - s += L" "; + s += LangString(resourceID); + s += L": "; s += ConvertSizeToString(num); if (size != (UInt64)(Int64)-1) @@ -448,7 +446,7 @@ void AddValuePair2(UINT resourceID, UInt32 langID, UInt64 num, UInt64 size, UStr s += AddSizeValue(size); s += L" )"; } - s += L"\n"; + s += L'\n'; } static void AddPropValueToSum(IFolderFolder *folder, int index, PROPID propID, UInt64 &sum) @@ -457,15 +455,11 @@ static void AddPropValueToSum(IFolderFolder *folder, int index, PROPID propID, U 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; - } + UInt64 val = 0; + if (ConvertPropVariantToUInt64(prop, val)) + sum += val; + else + sum = (UInt64)(Int64)-1; } UString CPanel::GetItemsInfoString(const CRecordVector &indices) @@ -473,11 +467,11 @@ UString CPanel::GetItemsInfoString(const CRecordVector &indices) UString info; UInt64 numDirs, numFiles, filesSize, foldersSize; numDirs = numFiles = filesSize = foldersSize = 0; - int i; + unsigned i; for (i = 0; i < indices.Size(); i++) { int index = indices[i]; - if (IsItemFolder(index)) + if (IsItem_Folder(index)) { AddPropValueToSum(_folder, index, kpidSize, foldersSize); numDirs++; @@ -489,22 +483,22 @@ UString CPanel::GetItemsInfoString(const CRecordVector &indices) } } - AddValuePair2(IDS_FOLDERS_COLON, 0x02000321, numDirs, foldersSize, info); - AddValuePair2(IDS_FILES_COLON, 0x02000320, numFiles, filesSize, info); + AddValuePair2(info, IDS_PROP_FOLDERS, numDirs, foldersSize); + AddValuePair2(info, IDS_PROP_FILES, numFiles, filesSize); 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); + AddValuePair1(info, IDS_PROP_SIZE, filesSize + foldersSize); info += L"\n"; info += _currentFolderPrefix; - for (i = 0; i < indices.Size() && i < kCopyDialog_NumInfoLines - 6; i++) + for (i = 0; i < indices.Size() && (int)i < (int)kCopyDialog_NumInfoLines - 6; i++) { info += L"\n "; int index = indices[i]; info += GetItemRelPath(index); - if (IsItemFolder(index)) + if (IsItem_Folder(index)) info += WCHAR_PATH_SEPARATOR; } if (i != indices.Size()) @@ -512,7 +506,7 @@ UString CPanel::GetItemsInfoString(const CRecordVector &indices) return info; } -bool IsCorrectFsName(const UString name); +bool IsCorrectFsName(const UString &name); void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) { @@ -525,7 +519,7 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) if (!srcPanel.DoesItSupportOperations()) { - srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return; } @@ -554,49 +548,49 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) if (NumPanels == 1) ReducePathToRealFileSystemPath(destPath); } - + } + UStringVector copyFolders; + ReadCopyHistory(copyFolders); + { 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); - + LangString(move ? IDS_MOVE : IDS_COPY, copyDialog.Title); + LangString(move ? IDS_MOVE_TO : IDS_COPY_TO, copyDialog.Static); copyDialog.Info = srcPanel.GetItemsInfoString(indices); - if (copyDialog.Create(srcPanel.GetParent()) == IDCANCEL) + if (copyDialog.Create(srcPanel.GetParent()) != IDOK) return; destPath = copyDialog.Value; + } + { if (destPath.IsEmpty()) { - srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return; } - if (!IsPathAbsolute(destPath)) + UString correctName; + if (!srcPanel.CorrectFsPath(destPath, correctName)) { - if (!srcPanel.IsFSFolder()) - { - srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); - return; - } - destPath = srcPanel._currentFolderPrefix + destPath; + srcPanel.MessageBoxError(E_INVALIDARG); + return; } + if (IsAbsolutePath(destPath)) + destPath.Empty(); + else + destPath = srcPanel._currentFolderPrefix; + destPath += correctName; + #ifndef UNDER_CE - if (destPath.Length() > 0 && destPath[0] == '\\') - if (destPath.Length() == 1 || destPath[1] != '\\') + if (destPath.Len() > 0 && destPath[0] == '\\') + if (destPath.Len() == 1 || destPath[1] != '\\') { - srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return; } #endif @@ -606,13 +600,13 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) NFind::DoesDirExist(us2fs(destPath)) || srcPanel.IsArcFolder()) { - NDirectory::CreateComplexDirectory(us2fs(destPath)); + CreateComplexDir(us2fs(destPath)); NName::NormalizeDirPathPrefix(destPath); if (!CheckFolderPath(destPath)) { if (NumPanels < 2 || destPath != destPanel._currentFolderPrefix || !destPanel.DoesItSupportOperations()) { - srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return; } useDestPanel = true; @@ -629,10 +623,10 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) if (pos >= 0) { UString prefix = destPath.Left(pos + 1); - NDirectory::CreateComplexDirectory(us2fs(prefix)); + CreateComplexDir(us2fs(prefix)); if (!CheckFolderPath(prefix)) { - srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return; } } @@ -654,7 +648,7 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) bool useSrcPanel = (!useDestPanel || !srcPanel.IsFsOrDrivesFolder() || destPanel.IsFSFolder()); bool useTemp = useSrcPanel && useDestPanel; - NFile::NDirectory::CTempDir tempDirectory; + CTempDir tempDirectory; FString tempDirPrefix; if (useTemp) { @@ -668,24 +662,23 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) srcPanel.SaveSelectedState(srcSelState); destPanel.SaveSelectedState(destSelState); - HRESULT result; + CPanel::CDisableNotify disableNotify1(destPanel); + CPanel::CDisableNotify disableNotify2(srcPanel); + + HRESULT result = S_OK; if (useSrcPanel) { - UString folder = useTemp ? fs2us(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; - } + CCopyToOptions options; + options.folder = useTemp ? fs2us(tempDirPrefix) : destPath; + options.moveMode = move; + options.includeAltStreams = true; + options.replaceAltStreamChars = false; + options.showErrorMessages = true; + + result = srcPanel.CopyTo(options, indices, NULL); } - if (useDestPanel) + if (result == S_OK && useDestPanel) { UStringVector filePaths; UString folderPrefix; @@ -693,22 +686,22 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) folderPrefix = fs2us(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; - } + filePaths.ClearAndReserve(indices.Size()); + FOR_VECTOR (i, indices) + filePaths.AddInReserved(srcPanel.GetItemRelPath(indices[i])); + result = destPanel.CopyFrom(move, folderPrefix, filePaths, true, 0); + } + if (result != S_OK) + { + // disableNotify1.Restore(); + // disableNotify2.Restore(); + // For Password: + // srcPanel.SetFocusToList(); + // srcPanel.InvalidateList(NULL, true); + + if (result != E_ABORT) + srcPanel.MessageBoxError(result, L"Error"); + // return; } RefreshTitleAlways(); @@ -721,8 +714,8 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) destPanel.RefreshListCtrl(destSelState); srcPanel.KillSelection(); } - disableTimerProcessing1.Restore(); - disableTimerProcessing2.Restore(); + disableNotify1.Restore(); + disableNotify2.Restore(); srcPanel.SetFocusToList(); } @@ -746,7 +739,7 @@ void CApp::OnSetSubFolder(int srcPanelIndex) if (focusedItem < 0) return; int realIndex = srcPanel.GetRealItemIndex(focusedItem); - if (!srcPanel.IsItemFolder(realIndex)) + if (!srcPanel.IsItem_Folder(realIndex)) return; // destPanel.BindToFolder(srcPanel._currentFolderPrefix + srcPanel.GetItemName(realIndex) + WCHAR_PATH_SEPARATOR); @@ -763,7 +756,7 @@ void CApp::OnSetSubFolder(int srcPanelIndex) return; } destPanel.CloseOpenFolders(); - destPanel._folder = newFolder; + destPanel.SetNewFolder(newFolder); destPanel.RefreshListCtrl(); } @@ -821,7 +814,7 @@ void CApp::RefreshTitle(bool always) { UString path = GetFocusedPanel()._currentFolderPrefix; if (path.IsEmpty()) - path += LangString(IDS_APP_TITLE, 0x03000000); + path = L"7-Zip"; // LangString(IDS_APP_TITLE); if (!always && path == PrevTitle) return; PrevTitle = path; @@ -834,3 +827,28 @@ void CApp::RefreshTitle(int panelIndex, bool always) return; RefreshTitle(always); } + +void AddUniqueStringToHead(UStringVector &list, const UString &s) +{ + for (unsigned i = 0; i < list.Size();) + if (s.IsEqualToNoCase(list[i])) + list.Delete(i); + else + i++; + list.Insert(0, s); +} + + +void CFolderHistory::Normalize() +{ + const unsigned kMaxSize = 100; + if (Strings.Size() > kMaxSize) + Strings.DeleteFrom(kMaxSize); +} + +void CFolderHistory::AddString(const UString &s) +{ + NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); + AddUniqueStringToHead(Strings, s); + Normalize(); +} diff --git a/CPP/7zip/UI/FileManager/App.h b/CPP/7zip/UI/FileManager/App.h old mode 100755 new mode 100644 index 2af63b47..c775cc2e --- a/CPP/7zip/UI/FileManager/App.h +++ b/CPP/7zip/UI/FileManager/App.h @@ -3,8 +3,8 @@ #ifndef __APP_H #define __APP_H -#include "Windows/Control/CommandBar.h" -#include "Windows/Control/ImageList.h" +#include "../../../Windows/Control/CommandBar.h" +#include "../../../Windows/Control/ImageList.h" #include "AppState.h" #include "Panel.h" @@ -18,11 +18,15 @@ const int kNumPanelsMax = 2; extern bool g_IsSmallScreen; +const int kMenuCmdID_Plugin_Start = 1000; // must be large them context menu IDs +const int kMenuCmdID_Toolbar_Start = 1500; + enum { - kAddCommand = kToolbarStartID, - kExtractCommand, - kTestCommand + kMenuCmdID_Toolbar_Add = kMenuCmdID_Toolbar_Start, + kMenuCmdID_Toolbar_Extract, + kMenuCmdID_Toolbar_Test, + kMenuCmdID_Toolbar_End }; class CPanelCallbackImp: public CPanelCallback @@ -106,6 +110,7 @@ class CApp public: NWindows::CWindow _window; bool ShowSystemMenu; + // bool ShowDeletedFiles; int NumPanels; int LastFocusedPanel; @@ -129,7 +134,15 @@ public: CDropTarget *_dropTargetSpec; CMyComPtr _dropTarget; - CApp(): _window(0), NumPanels(2), LastFocusedPanel(0) {} + UString LangString_N_SELECTED_ITEMS; + + void ReloadLang(); + + CApp(): _window(0), NumPanels(2), LastFocusedPanel(0), + AutoRefresh_Mode(true) + { + SetPanels_AutoRefresh_Mode(); + } void CreateDragTarget() { @@ -177,17 +190,21 @@ public: void OpenItem() { GetFocusedPanel().OpenSelectedItems(true); } void OpenItemInside() { GetFocusedPanel().OpenFocusedItemAsInternal(); } void OpenItemOutside() { GetFocusedPanel().OpenSelectedItems(false); } - void EditItem() { GetFocusedPanel().EditItem(); } + void EditItem(bool useEditor) { GetFocusedPanel().EditItem(useEditor); } 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 CalculateCrc(const UString &methodName); void DiffFiles(); void Split(); void Combine(); void Properties() { GetFocusedPanel().Properties(); } void Comment() { GetFocusedPanel().ChangeComment(); } + + #ifndef UNDER_CE + void Link(); + #endif void CreateFolder() { GetFocusedPanel().CreateFolder(); } void CreateFile() { GetFocusedPanel().CreateFile(); } @@ -241,8 +258,30 @@ public: void SetListSettings(); void SetShowSystemMenu(); HRESULT SwitchOnOffOnePanel(); + bool GetFlatMode() { return Panels[LastFocusedPanel].GetFlatMode(); } + // bool Get_ShowNtfsStrems_Mode() { return Panels[LastFocusedPanel].Get_ShowNtfsStrems_Mode(); } + void ChangeFlatMode() { Panels[LastFocusedPanel].ChangeFlatMode(); } + // void Change_ShowNtfsStrems_Mode() { Panels[LastFocusedPanel].Change_ShowNtfsStrems_Mode(); } + // void Change_ShowDeleted() { ShowDeletedFiles = !ShowDeletedFiles; } + + bool AutoRefresh_Mode; + bool Get_AutoRefresh_Mode() + { + // return Panels[LastFocusedPanel].Get_ShowNtfsStrems_Mode(); + return AutoRefresh_Mode; + } + void Change_AutoRefresh_Mode() + { + AutoRefresh_Mode = !AutoRefresh_Mode; + SetPanels_AutoRefresh_Mode(); + } + void SetPanels_AutoRefresh_Mode() + { + for (int i = 0; i < kNumPanelsMax; i++) + Panels[i].Set_AutoRefresh_Mode(AutoRefresh_Mode); + } void OpenBookmark(int index) { GetFocusedPanel().OpenBookmark(index); } void SetBookmark(int index) { GetFocusedPanel().SetBookmark(index); } diff --git a/CPP/7zip/UI/FileManager/AppState.h b/CPP/7zip/UI/FileManager/AppState.h old mode 100755 new mode 100644 index 374cf04f..cc887150 --- a/CPP/7zip/UI/FileManager/AppState.h +++ b/CPP/7zip/UI/FileManager/AppState.h @@ -3,34 +3,23 @@ #ifndef __APP_STATE_H #define __APP_STATE_H -#include "Windows/Synchronization.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) + void SetString(unsigned index, const UString &s) { NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); - while(Strings.Size() <= index) - Strings.Add(UString()); - Strings[index] = string; + while (Strings.Size() <= index) + Strings.AddNew(); + Strings[index] = s; } - UString GetString(int index) + UString GetString(unsigned index) { NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); if (index >= Strings.Size()) @@ -53,12 +42,8 @@ class CFolderHistory { NWindows::NSynchronization::CCriticalSection _criticalSection; UStringVector Strings; - void Normalize() - { - const int kMaxSize = 100; - if (Strings.Size() > kMaxSize) - Strings.Delete(kMaxSize, Strings.Size() - kMaxSize); - } + + void Normalize(); public: @@ -68,13 +53,8 @@ public: foldersHistory = Strings; } - void AddString(const UString &string) - { - NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); - AddUniqueStringToHead(Strings, string); - Normalize(); - } - + void AddString(const UString &s); + void RemoveAll() { NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); @@ -99,6 +79,7 @@ struct CAppState { CFastFolders FastFolders; CFolderHistory FolderHistory; + void Save() { FastFolders.Save(); diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.cpp b/CPP/7zip/UI/FileManager/BrowseDialog.cpp old mode 100755 new mode 100644 index 1c350064..32db8f8f --- a/CPP/7zip/UI/FileManager/BrowseDialog.cpp +++ b/CPP/7zip/UI/FileManager/BrowseDialog.cpp @@ -2,63 +2,191 @@ #include "StdAfx.h" +#ifndef UNDER_CE +#include "../../../Windows/CommonDialog.h" +#include "../../../Windows/Shell.h" +#endif + +#include "../../../Windows/FileName.h" +#include "../../../Windows/FileFind.h" + +#ifdef UNDER_CE +#include +#endif + #include "BrowseDialog.h" +#define USE_MY_BROWSE_DIALOG + #ifdef USE_MY_BROWSE_DIALOG -#include "Common/IntToString.h" +#include "../../../Common/Defs.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/Wildcard.h" -#include "Windows/PropVariantConversions.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/PropVariantConv.h" -#include "LangUtils.h" +#include "../../../Windows/Control/ComboBox.h" +#include "../../../Windows/Control/Dialog.h" +#include "../../../Windows/Control/Edit.h" +#include "../../../Windows/Control/ListView.h" + +#include "BrowseDialogRes.h" #include "PropertyNameRes.h" +#include "SysIconUtils.h" #ifndef _SFX #include "RegistryUtils.h" #endif +#endif + +#include "ComboDialog.h" +#include "LangUtils.h" + +#include "resource.h" + using namespace NWindows; using namespace NFile; +using namespace NName; using namespace NFind; +#ifdef USE_MY_BROWSE_DIALOG + extern bool g_LVN_ITEMACTIVATE_Support; static const int kParentIndex = -1; +static const UINT k_Message_RefreshPathEdit = WM_APP + 1; + +static HRESULT GetNormalizedError() +{ + DWORD errorCode = GetLastError(); + return errorCode == 0 ? E_FAIL : errorCode; +} + +extern UString HResultToMessage(HRESULT errorCode); + +static void MessageBox_Error_Global(HWND wnd, const wchar_t *message) +{ + ::MessageBoxW(wnd, message, L"7-Zip", MB_ICONERROR); +} -#ifdef LANG -static CIDLangPair kIDLangPairs[] = +static void MessageBox_HResError(HWND wnd, HRESULT errorCode, const wchar_t *name) { - { IDOK, 0x02000702 }, - { IDCANCEL, 0x02000710 } + UString s = HResultToMessage(errorCode); + if (name) + { + s += L'\n'; + s += name; + } + MessageBox_Error_Global(wnd, s); +} + +class CBrowseDialog: public NControl::CModalDialog +{ + NControl::CListView _list; + NControl::CEdit _pathEdit; + NControl::CComboBox _filterCombo; + + CObjectVector _files; + + CExtToIconMap _extToIconMap; + int _sortIndex; + bool _ascending; + bool _showDots; + UString _topDirPrefix; // we don't open parent of that folder + UString DirPrefix; + + virtual bool OnInit(); + virtual bool OnSize(WPARAM wParam, int xSize, int ySize); + virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam); + virtual bool OnNotify(UINT controlID, LPNMHDR header); + virtual bool OnKeyDown(LPNMLVKEYDOWN keyDownInfo); + virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); + virtual void OnOK(); + + void Post_RefreshPathEdit() { PostMessage(k_Message_RefreshPathEdit); } + + bool GetParentPath(const UString &path, UString &parentPrefix, UString &name); + // Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter + HRESULT Reload(const UString &pathPrefix, const UString &selectedName); + HRESULT Reload(); + + void OpenParentFolder(); + void SetPathEditText(); + void OnCreateDir(); + void OnItemEnter(); + void FinishOnOK(); + + int GetRealItemIndex(int indexInListView) const + { + LPARAM param; + if (!_list.GetItemParam(indexInListView, param)) + return (int)-1; + return (int)param; + } + +public: + bool FolderMode; + UString Title; + UString FilePath; // input/ result path + bool ShowAllFiles; + UStringVector Filters; + UString FilterDescription; + + CBrowseDialog(): FolderMode(false), _showDots(false), ShowAllFiles(true) {} + void SetFilter(const UString &s); + INT_PTR Create(HWND parent = 0) { return CModalDialog::Create(IDD_BROWSE, parent); } + int CompareItems(LPARAM lParam1, LPARAM lParam2); }; -#endif -static bool GetParentPath(const UString &path2, UString &dest, UString &focused) +void CBrowseDialog::SetFilter(const UString &s) { - 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; + Filters.Clear(); + UString mask; + unsigned i; + for (i = 0; i < s.Len(); i++) + { + wchar_t c = s[i]; + if (c == ';') + { + if (!mask.IsEmpty()) + Filters.Add(mask); + mask.Empty(); + } + else + mask += c; + } + if (!mask.IsEmpty()) + Filters.Add(mask); + ShowAllFiles = Filters.IsEmpty(); + for (i = 0; i < Filters.Size(); i++) + { + const UString &f = Filters[i]; + if (f == L"*.*" || f == L"*") + { + ShowAllFiles = true; + break; + } + } } bool CBrowseDialog::OnInit() { #ifdef LANG - LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + LangSetDlgItems(*this, NULL, 0); #endif if (!Title.IsEmpty()) SetText(Title); - _list.Attach(GetItem(IDC_BROWSE_LIST)); + _list.Attach(GetItem(IDL_BROWSE)); + _filterCombo.Attach(GetItem(IDC_BROWSE_FILTER)); + _pathEdit.Attach(GetItem(IDE_BROWSE_PATH)); + + if (FolderMode) + HideItem(IDC_BROWSE_FILTER); + else + EnableItem(IDC_BROWSE_FILTER, false); #ifndef UNDER_CE _list.SetUnicodeFormat(); @@ -70,54 +198,104 @@ bool CBrowseDialog::OnInit() _showDots = ReadShowDots(); #endif + { + UString s; + if (!FilterDescription.IsEmpty()) + s = FilterDescription; + else if (ShowAllFiles) + s = L"*.*"; + else + { + FOR_VECTOR (i, Filters) + { + if (i != 0) + s += L' '; + s += Filters[i]; + } + } + _filterCombo.AddString(s); + _filterCombo.SetCurSel(0); + } + _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); + _list.InsertColumn(0, LangString(IDS_PROP_NAME), 100); + _list.InsertColumn(1, LangString(IDS_PROP_MTIME), 100); { LV_COLUMNW column; + column.iSubItem = 2; column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; column.fmt = LVCFMT_RIGHT; - column.iSubItem = 2; - UString s = LangStringSpec(IDS_PROP_SIZE, 0x02000207); + column.cx = 100; + const UString s = LangString(IDS_PROP_SIZE); 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.InsertItem(0, L"12345678901234567" + #ifndef UNDER_CE + L"1234567890" + #endif + ); + _list.SetSubItem(0, 1, L"2009-09-09" + #ifndef UNDER_CE + L" 09:09" + #endif + ); _list.SetSubItem(0, 2, L"9999 MB"); for (int i = 0; i < 3; i++) _list.SetColumnWidthAuto(i); _list.DeleteAllItems(); - - UString selectedName; - if (!FolderMode) + + _ascending = true; + _sortIndex = 0; + + NormalizeSize(); + + _topDirPrefix.Empty(); { - int pos = Path.ReverseFind(WCHAR_PATH_SEPARATOR); - if (pos >= 0 && Path.Back() != WCHAR_PATH_SEPARATOR) + int rootSize = GetRootPrefixSize(FilePath); + // We can go up from root folder to drives list + if (NName::IsDrivePath(FilePath)) + rootSize = 0; + else if (IsSuperPath(FilePath)) { - selectedName = Path.Mid(pos + 1); - Path = Path.Left(pos + 1); + if (NName::IsDrivePath(&FilePath[kSuperPathPrefixSize])) + rootSize = kSuperPathPrefixSize; } + _topDirPrefix.SetFrom(FilePath, rootSize); } - _ascending = true; - _sortIndex = 0; - NormalizeSize(); + UString name; + if (!GetParentPath(FilePath, DirPrefix, name)) + DirPrefix = _topDirPrefix; - while (Reload(Path, selectedName) != S_OK) + for(;;) { - UString parent; - if (!GetParentPath(Path, parent, selectedName)) + UString baseFolder = DirPrefix; + if (Reload(baseFolder, name) == S_OK) break; - selectedName.Empty(); - Path = parent; + name.Empty(); + if (DirPrefix.IsEmpty()) + break; + UString parent, name2; + GetParentPath(DirPrefix, parent, name2); + DirPrefix = parent; } + if (name.IsEmpty()) + name = FilePath; + if (FolderMode) + NormalizeDirPathPrefix(name); + _pathEdit.SetText(name); + + #ifndef UNDER_CE + /* If we clear UISF_HIDEFOCUS, the focus rectangle in ListView will be visible, + even if we use mouse for pressing the button to open this dialog. */ + PostMessage(MY__WM_UPDATEUISTATE, MAKEWPARAM(MY__UIS_CLEAR, MY__UISF_HIDEFOCUS)); + #endif + return CModalDialog::OnInit(); } @@ -125,67 +303,173 @@ 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; + RECT r; + GetClientRectOfItem(IDB_BROWSE_PARENT, r); + mx = r.left; + my = r.top; } InvalidateRect(NULL); + int xLim = xSize - mx; { - RECT rect; - GetClientRectOfItem(IDC_BROWSE_PATH, rect); - MoveItem(IDC_BROWSE_PATH, rect.left, rect.top, xSize - mx - rect.left, RECT_SIZE_Y(rect)); + RECT r; + GetClientRectOfItem(IDT_BROWSE_FOLDER, r); + MoveItem(IDT_BROWSE_FOLDER, r.left, r.top, xLim - r.left, RECT_SIZE_Y(r)); } int bx1, bx2, by; GetItemSizes(IDCANCEL, bx1, by); GetItemSizes(IDOK, bx2, by); int y = ySize - my - by; - int x = xSize - mx - bx1; + int x = xLim - bx1; MoveItem(IDCANCEL, x, y, bx1, by); MoveItem(IDOK, x - mx - bx2, y, bx2, by); + // Y_Size of ComboBox is tricky. So we use Y_Size of _pathEdit instead + + int yPathSize; + { + RECT r; + GetClientRectOfItem(IDE_BROWSE_PATH, r); + yPathSize = RECT_SIZE_Y(r); + _pathEdit.Move(r.left, y - my - yPathSize - my - yPathSize, xLim - r.left, yPathSize); + } + { - RECT rect; - GetClientRectOfItem(IDC_BROWSE_LIST, rect); - _list.Move(rect.left, rect.top, xSize - mx - rect.left, y - my - rect.top); + RECT r; + GetClientRectOfItem(IDC_BROWSE_FILTER, r); + _filterCombo.Move(r.left, y - my - yPathSize, xLim - r.left, RECT_SIZE_Y(r)); } + + { + RECT r; + GetClientRectOfItem(IDL_BROWSE, r); + _list.Move(r.left, r.top, xLim - r.left, y - my - yPathSize - my - yPathSize - my - r.top); + } + return false; } -static UString ConvertSizeToStringShort(UInt64 value) +bool CBrowseDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) { - wchar_t s[32]; - wchar_t c = L'\0', c2 = L'\0'; - if (value < (UInt64)10000) + if (message == k_Message_RefreshPathEdit) + { + SetPathEditText(); + return true; + } + return CModalDialog::OnMessage(message, wParam, lParam); +} + +bool CBrowseDialog::OnNotify(UINT /* controlID */, LPNMHDR header) +{ + if (header->hwndFrom != _list) + return false; + switch (header->code) { - c = L'\0'; - c2 = L'\0'; + case LVN_ITEMACTIVATE: + if (g_LVN_ITEMACTIVATE_Support) + OnItemEnter(); + break; + case NM_DBLCLK: + case NM_RETURN: // probabably it's unused + if (!g_LVN_ITEMACTIVATE_Support) + OnItemEnter(); + break; + case LVN_COLUMNCLICK: + { + int index = LPNMLISTVIEW(header)->iSubItem; + if (index == _sortIndex) + _ascending = !_ascending; + else + { + _ascending = (index == 0); + _sortIndex = index; + } + Reload(); + return false; + } + case LVN_KEYDOWN: + { + bool boolResult = OnKeyDown(LPNMLVKEYDOWN(header)); + Post_RefreshPathEdit(); + return boolResult; + } + case NM_RCLICK: + case NM_CLICK: + case LVN_BEGINDRAG: + Post_RefreshPathEdit(); + break; } - else if (value < ((UInt64)10000 << 10)) + return false; +} + +bool CBrowseDialog::OnKeyDown(LPNMLVKEYDOWN keyDownInfo) +{ + bool ctrl = IsKeyDown(VK_CONTROL); + + switch (keyDownInfo->wVKey) { - value >>= 10; - c = L'K'; + case VK_BACK: + OpenParentFolder(); + return true; + case 'R': + if (ctrl) + { + Reload(); + return true; + } + return false; + case VK_F7: + OnCreateDir(); + return true; } - else if (value < ((UInt64)10000 << 20)) + return false; +} + +bool CBrowseDialog::OnButtonClicked(int buttonID, HWND buttonHWND) +{ + switch (buttonID) { - value >>= 20; - c = L'M'; + case IDB_BROWSE_PARENT: OpenParentFolder(); break; + case IDB_BROWSE_CREATE_DIR: OnCreateDir(); break; + default: return CModalDialog::OnButtonClicked(buttonID, buttonHWND); } - else + _list.SetFocus(); + return true; +} + +void CBrowseDialog::OnOK() +{ + /* When we press "Enter" in listview, Windows sends message to first Button. + We check that message was from ListView; */ + if (GetFocus() == _list) { - value >>= 30; - c = L'G'; + OnItemEnter(); + return; } - 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; + FinishOnOK(); +} + + +bool CBrowseDialog::GetParentPath(const UString &path, UString &parentPrefix, UString &name) +{ + parentPrefix.Empty(); + name.Empty(); + if (path.IsEmpty()) + return false; + if (_topDirPrefix == path) + return false; + UString s = path; + if (s.Back() == WCHAR_PATH_SEPARATOR) + s.DeleteBack(); + if (s.IsEmpty()) + return false; + if (s.Back() == WCHAR_PATH_SEPARATOR) + return false; + int pos = s.ReverseFind(WCHAR_PATH_SEPARATOR); + parentPrefix.SetFrom(s, pos + 1); + name = s.Ptr(pos + 1); + return true; } int CBrowseDialog::CompareItems(LPARAM lParam1, LPARAM lParam2) @@ -197,77 +481,122 @@ int CBrowseDialog::CompareItems(LPARAM lParam1, LPARAM lParam2) bool isDir1 = f1.IsDir(); bool isDir2 = f2.IsDir(); - if (isDir1 && !isDir2) return -1; if (isDir2 && !isDir1) return 1; - int result = 0; - switch(_sortIndex) + int res = 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; + case 0: res = CompareFileNames(fs2us(f1.Name), fs2us(f2.Name)); break; + case 1: res = CompareFileTime(&f1.MTime, &f2.MTime); break; + case 2: res = MyCompare(f1.Size, f2.Size); break; } - return _ascending ? result: (-result); + return _ascending ? res: -res; } static int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) { - if (lpData == NULL) - return 0; - return ((CBrowseDialog*)lpData)->CompareItems(lParam1, lParam2); + return ((CBrowseDialog *)lpData)->CompareItems(lParam1, lParam2); } -static HRESULT GetNormalizedError() +static void ConvertSizeToString(UInt64 v, wchar_t *s) { - HRESULT errorCode = GetLastError(); - return (errorCode == 0) ? 1 : errorCode; + Byte c = 0; + if (v >= ((UInt64)10000 << 20)) { v >>= 30; c = 'G'; } + else if (v >= ((UInt64)10000 << 10)) { v >>= 20; c = 'M'; } + else if (v >= ((UInt64)10000 << 0)) { v >>= 10; c = 'K'; } + ConvertUInt64ToString(v, s); + if (c != 0) + { + s += MyStringLen(s); + *s++ = ' '; + *s++ = c; + *s++ = 0; + } } +// Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter + HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selectedName) { - CEnumerator enumerator(us2fs(pathPrefix + L'*')); CObjectVector files; - for (;;) + + #ifndef UNDER_CE + bool isDrive = false; + if (pathPrefix.IsEmpty() || pathPrefix == kSuperPathPrefix) { - bool found; - CFileInfo fi; - if (!enumerator.Next(fi, found)) + isDrive = true; + FStringVector drives; + if (!MyGetLogicalDriveStrings(drives)) return GetNormalizedError(); - if (!found) - break; - files.Add(fi); + FOR_VECTOR (i, drives) + { + FString d = drives[i]; + if (d.Len() < 3 || d.Back() != '\\') + return E_FAIL; + d.DeleteBack(); + CFileInfo &fi = files.AddNew(); + fi.SetAsDir(); + fi.Name = d; + } + } + else + #endif + { + CEnumerator enumerator(us2fs(pathPrefix + L'*')); + for (;;) + { + bool found; + CFileInfo fi; + if (!enumerator.Next(fi, found)) + return GetNormalizedError(); + if (!found) + break; + if (!fi.IsDir()) + { + if (FolderMode) + continue; + if (!ShowAllFiles) + { + unsigned i; + for (i = 0; i < Filters.Size(); i++) + if (DoesWildcardMatchName(Filters[i], fs2us(fi.Name))) + break; + if (i == Filters.Size()) + continue; + } + } + files.Add(fi); + } } - Path = pathPrefix; + DirPrefix = pathPrefix; _files = files; - SetItemText(IDC_BROWSE_PATH, Path); + SetItemText(IDT_BROWSE_FOLDER, DirPrefix); + _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) + if (_showDots && _topDirPrefix != DirPrefix) { - UString itemName = L".."; item.iItem = index; + const UString itemName = L".."; if (selectedName.IsEmpty()) - cursorIndex = item.iItem; + cursorIndex = index; item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; int subItem = 0; item.iSubItem = subItem++; item.lParam = kParentIndex; item.pszText = (wchar_t *)(const wchar_t *)itemName; - item.iImage = _extToIconMap.GetIconIndex(FILE_ATTRIBUTE_DIRECTORY, Path); + item.iImage = _extToIconMap.GetIconIndex(FILE_ATTRIBUTE_DIRECTORY, DirPrefix); if (item.iImage < 0) item.iImage = 0; _list.InsertItem(&item); @@ -277,36 +606,52 @@ HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selected } #endif - for (int i = 0; i < _files.Size(); i++) + for (unsigned i = 0; i < _files.Size(); i++, index++) { - const CFileInfo &fi = _files[i]; item.iItem = index; + const CFileInfo &fi = _files[i]; const UString name = fs2us(fi.Name); - if (name.CompareNoCase(selectedName) == 0) - cursorIndex = item.iItem; + if (!selectedName.IsEmpty() && CompareFileNames(name, selectedName) == 0) + cursorIndex = index; item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; int subItem = 0; item.iSubItem = subItem++; item.lParam = i; item.pszText = (wchar_t *)(const wchar_t *)name; - item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, Path + name); + + const UString fullPath = DirPrefix + name; + #ifndef UNDER_CE + if (isDrive) + { + if (GetRealIconIndex(fi.Name + FCHAR_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY, item.iImage) == 0) + item.iImage = 0; + } + else + #endif + item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, fullPath); if (item.iImage < 0) item.iImage = 0; _list.InsertItem(&item); + wchar_t s[32]; { FILETIME ft; - UString s; + s[0] = 0; if (FileTimeToLocalFileTime(&fi.MTime, &ft)) - s = ConvertFileTimeToString(ft, false, false); + ConvertFileTimeToString(ft, s, + #ifndef UNDER_CE + true + #else + false + #endif + , false); _list.SetSubItem(index, subItem++, s); } { - UString s; + s[0] = 0; if (!fi.IsDir()) - s = ConvertSizeToStringShort(fi.Size); + ConvertSizeToString(fi.Size, s); _list.SetSubItem(index, subItem++, s); } - index++; } if (_list.GetItemCount() > 0 && cursorIndex >= 0) @@ -316,144 +661,93 @@ HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selected _list.SetItemState(0, LVIS_FOCUSED, LVIS_FOCUSED); _list.EnsureVisible(_list.GetFocusedItem(), false); _list.SetRedraw(true); + _list.InvalidateRect(NULL, true); return S_OK; } HRESULT CBrowseDialog::Reload() { - UString selectedCur; + UString selected; int index = _list.GetNextSelectedItem(-1); if (index >= 0) { int fileIndex = GetRealItemIndex(index); if (fileIndex != kParentIndex) - selectedCur = fs2us(_files[fileIndex].Name); + selected = fs2us(_files[fileIndex].Name); } - return Reload(Path, selectedCur); + UString dirPathTemp = DirPrefix; + return Reload(dirPathTemp, selected); } void CBrowseDialog::OpenParentFolder() { UString parent, selected; - if (GetParentPath(Path, parent, selected)) + if (GetParentPath(DirPrefix, parent, selected)) + { Reload(parent, selected); + SetPathEditText(); + } } -extern UString HResultToMessage(HRESULT errorCode); - -bool CBrowseDialog::OnNotify(UINT /* controlID */, LPNMHDR header) +void CBrowseDialog::SetPathEditText() { - if (header->hwndFrom != _list) - return false; - switch(header->code) + int index = _list.GetNextSelectedItem(-1); + if (index < 0) { - 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; - } + if (FolderMode) + _pathEdit.SetText(DirPrefix); + return; } - return false; -} - -bool CBrowseDialog::OnKeyDown(LPNMLVKEYDOWN keyDownInfo, LRESULT &result) -{ - bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0; - result = 0; - - switch(keyDownInfo->wVKey) + int fileIndex = GetRealItemIndex(index); + if (fileIndex == kParentIndex) { - case VK_BACK: - OpenParentFolder(); - return true; - case 'R': - if (ctrl) - { - Reload(); - return true; - } - return false; + if (FolderMode) + _pathEdit.SetText(L".." WSTRING_PATH_SEPARATOR); + return; } - return false; -} - -bool CBrowseDialog::OnButtonClicked(int buttonID, HWND buttonHWND) -{ - switch(buttonID) + const CFileInfo &file = _files[fileIndex]; + if (file.IsDir()) { - case IDC_BROWSE_PARENT: - OpenParentFolder(); - return true; + if (!FolderMode) + return; + _pathEdit.SetText(fs2us(file.Name) + WCHAR_PATH_SEPARATOR); } - 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"); + else + _pathEdit.SetText(fs2us(file.Name)); } -void CBrowseDialog::FinishOnOK() +void CBrowseDialog::OnCreateDir() { - int index = _list.GetNextSelectedItem(-1); - if (index < 0) + UString name; { - if (!FolderMode) + UString enteredName; + Dlg_CreateFolder((HWND)*this, enteredName); + if (enteredName.IsEmpty()) + return; + if (!CorrectFsPath(DirPrefix, enteredName, name)) { - ShowSelectError(); + MessageBox_HResError((HWND)*this, ERROR_INVALID_NAME, name); return; } } - else + if (name.IsEmpty()) + return; + + FString destPath; + if (GetFullPath(us2fs(DirPrefix), us2fs(name), destPath)) { - int fileIndex = GetRealItemIndex(index); - if (fileIndex == kParentIndex) + if (!NDir::CreateComplexDir(destPath)) { - OpenParentFolder(); - return; + MessageBox_HResError((HWND)*this, GetNormalizedError(), fs2us(destPath)); } - const CFileInfo &file = _files[fileIndex]; - if (file.IsDir() != FolderMode) + else { - ShowSelectError(); - return; + UString tempPath = DirPrefix; + Reload(tempPath, name); + SetPathEditText(); } - Path += fs2us(file.Name); + _list.SetFocus(); } - End(IDOK); } void CBrowseDialog::OnItemEnter() @@ -471,48 +765,244 @@ void CBrowseDialog::OnItemEnter() { if (!FolderMode) FinishOnOK(); - else - ShowSelectError(); + /* + MessageBox_Error_Global(*this, FolderMode ? + L"You must select some folder": + L"You must select some file"); + */ return; } - HRESULT res = Reload(Path + fs2us(file.Name) + WCHAR_PATH_SEPARATOR, L""); + UString s = DirPrefix + fs2us(file.Name) + WCHAR_PATH_SEPARATOR; + HRESULT res = Reload(s, L""); if (res != S_OK) - ShowError(HResultToMessage(res)); + MessageBox_HResError(*this, res, s); + SetPathEditText(); } } -void CBrowseDialog::OnOK() +void CBrowseDialog::FinishOnOK() { - // When we press "Enter" in listview, windows sends message to first Button. - // We check that message was from listview; - if (GetFocus() == _list) + UString s; + _pathEdit.GetText(s); + FString destPath; + if (!GetFullPath(us2fs(DirPrefix), us2fs(s), destPath)) { - OnItemEnter(); + MessageBox_HResError((HWND)*this, ERROR_INVALID_NAME, s); return; } - FinishOnOK(); + FilePath = fs2us(destPath); + if (FolderMode) + NormalizeDirPathPrefix(FilePath); + End(IDOK); } -static bool MyBrowse(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath, bool folderMode) +#endif + +bool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR path, UString &resultPath) { + resultPath.Empty(); + + #ifndef UNDER_CE + + #ifdef USE_MY_BROWSE_DIALOG + if (!IsSuperOrDevicePath(path)) + #endif + return NShell::BrowseForFolder(owner, title, path, resultPath); + + #endif + + #ifdef USE_MY_BROWSE_DIALOG + CBrowseDialog dialog; - dialog.Title = title; - dialog.Path = initialFolder; - dialog.FolderMode = folderMode; + dialog.FolderMode = true; + if (title) + dialog.Title = title; + if (path) + dialog.FilePath = path; if (dialog.Create(owner) != IDOK) return false; - resultPath = dialog.Path; + resultPath = dialog.FilePath; + #endif + return true; } -bool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath) +bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR path, + LPCWSTR filterDescription, LPCWSTR filter, UString &resultPath) { - return MyBrowse(owner, title, initialFolder, resultPath, true); + resultPath.Empty(); + + #ifndef UNDER_CE + + #ifdef USE_MY_BROWSE_DIALOG + if (!IsSuperOrDevicePath(path)) + #endif + { + if (MyGetOpenFileName(owner, title, NULL, path, filterDescription, filter, resultPath)) + return true; + #ifdef UNDER_CE + return false; + #else + // maybe we must use GetLastError in WinCE. + DWORD errorCode = CommDlgExtendedError(); + const wchar_t *errorMessage = NULL; + switch (errorCode) + { + case 0: return false; // cancel or close obn dialog + case FNERR_INVALIDFILENAME: errorMessage = L"Invalid File Name"; break; + default: errorMessage = L"Open Dialog Error"; + } + if (!errorMessage) + return false; + { + UString s = errorMessage; + s += L"\n"; + s += path; + MessageBox_Error_Global(owner, s); + } + #endif + } + + #endif + + #ifdef USE_MY_BROWSE_DIALOG + CBrowseDialog dialog; + if (title) + dialog.Title = title; + if (path) + dialog.FilePath = path; + dialog.FolderMode = false; + if (filter) + dialog.SetFilter(filter); + if (filterDescription) + dialog.FilterDescription = filterDescription; + if (dialog.Create(owner) != IDOK) + return false; + resultPath = dialog.FilePath; + #endif + + return true; } -bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR initialFolder, LPCWSTR, UString &resultPath) + +#ifdef _WIN32 + +static void RemoveDotsAndSpaces(UString &path) { - return MyBrowse(owner, title, initialFolder, resultPath, false); + while (!path.IsEmpty()) + { + wchar_t c = path.Back(); + if (c != ' ' && c != '.') + return; + path.DeleteBack(); + } } + +bool CorrectFsPath(const UString &relBase, const UString &path2, UString &result) +{ + result.Empty(); + + UString path = path2; + path.Replace('/', WCHAR_PATH_SEPARATOR); + unsigned start = 0; + UString base; + if (NName::IsAbsolutePath(path)) + { + if (IsSuperOrDevicePath(path)) + { + result = path; + return true; + } + int pos = GetRootPrefixSize(path); + if (pos > 0) + start = pos; + } + else + { + if (IsSuperOrDevicePath(relBase)) + { + result = path; + return true; + } + base = relBase; + } + + /* We can't use backward, since we must change only disk paths */ + /* + for (;;) + { + if (path.Len() <= start) + break; + if (DoesFileOrDirExist(us2fs(path))) + break; + if (path.Back() == WCHAR_PATH_SEPARATOR) + { + path.DeleteBack(); + result.Insert(0, WCHAR_PATH_SEPARATOR);; + } + int pos = path.ReverseFind(WCHAR_PATH_SEPARATOR) + 1; + UString cur = path.Ptr(pos); + RemoveDotsAndSpaces(cur); + result.Insert(0, cur); + path.DeleteFrom(pos); + } + result.Insert(0, path); + return true; + */ + + result += path.Left(start); + bool checkExist = true; + UString cur; + for (;;) + { + if (start == path.Len()) + break; + int slashPos = path.Find(WCHAR_PATH_SEPARATOR, start); + cur.SetFrom(path.Ptr(start), (slashPos < 0 ? path.Len() : slashPos) - start); + if (checkExist) + { + CFileInfo fi; + if (fi.Find(us2fs(base + result + cur))) + { + if (!fi.IsDir()) + { + result = path; + break; + } + } + else + checkExist = false; + } + if (!checkExist) + RemoveDotsAndSpaces(cur); + result += cur; + if (slashPos < 0) + break; + result += WCHAR_PATH_SEPARATOR; + start = slashPos + 1; + } + + return true; +} + +#else +bool CorrectFsPath(const UString & /* relBase */, const UString &path, UString &result) +{ + result = path; + return true; +} #endif + +bool Dlg_CreateFolder(HWND wnd, UString &destName) +{ + destName.Empty(); + CComboDialog dlg; + LangString(IDS_CREATE_FOLDER, dlg.Title); + LangString(IDS_CREATE_FOLDER_NAME, dlg.Static); + LangString(IDS_CREATE_FOLDER_DEFAULT_NAME, dlg.Value); + if (dlg.Create(wnd) != IDOK) + return false; + destName = dlg.Value; + return true; +} diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.h b/CPP/7zip/UI/FileManager/BrowseDialog.h old mode 100755 new mode 100644 index f597d1c3..77c749b5 --- a/CPP/7zip/UI/FileManager/BrowseDialog.h +++ b/CPP/7zip/UI/FileManager/BrowseDialog.h @@ -3,79 +3,19 @@ #ifndef __BROWSE_DIALOG_H #define __BROWSE_DIALOG_H -#ifdef UNDER_CE -#define USE_MY_BROWSE_DIALOG -#endif - -#ifdef USE_MY_BROWSE_DIALOG - -#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(); +#include "../../../Common/MyString.h" - void OnItemEnter(); +bool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR path, UString &resultPath); +bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR path, LPCWSTR filterDescription, LPCWSTR filter, UString &resultPath); - int GetRealItemIndex(int indexInListView) const - { - LPARAM param; - if (!_list.GetItemParam(indexInListView, param)) - return (int)-1; - return (int)param; - } +/* CorrectFsPath removes undesirable characters in names (dots and spaces at the end of file) + But it doesn't change "bad" name in any of the following caes: + - path is Super Path (with \\?\ prefix) + - path is relative and relBase is Super Path + - there is file or dir in filesystem with specified "bad" name */ - void ShowError(LPCWSTR s); - void ShowSelectError(); -public: - UString Title; - UString Path; - bool FolderMode; +bool CorrectFsPath(const UString &relBase, const UString &path, UString &result); - 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 +bool Dlg_CreateFolder(HWND wnd, UString &destName); #endif diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.rc b/CPP/7zip/UI/FileManager/BrowseDialog.rc old mode 100755 new mode 100644 index 4d7ec288..04a6ad61 --- a/CPP/7zip/UI/FileManager/BrowseDialog.rc +++ b/CPP/7zip/UI/FileManager/BrowseDialog.rc @@ -1,17 +1,25 @@ #include "BrowseDialogRes.h" #include "../../GuiCommon.rc" -#define xc 180 -#define yc 160 +#define xc 256 +#define yc 320 -IDD_DIALOG_BROWSE MY_RESIZE_DIALOG +#define k_BROWSE_y_CtrlSize 14 + +#define k_BROWSE_y_List 24 + +IDD_BROWSE DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT 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 + EDITTEXT IDE_BROWSE_PATH, m, by - m - k_BROWSE_y_CtrlSize - k_BROWSE_y_CtrlSize - m, xc, k_BROWSE_y_CtrlSize, ES_AUTOHSCROLL + COMBOBOX IDC_BROWSE_FILTER, m, by - m - k_BROWSE_y_CtrlSize, xc, 30, MY_COMBO + PUSHBUTTON "OK", IDOK, bx2, by, bxs, bys PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys - PUSHBUTTON "..", IDC_BROWSE_PARENT, m, m, 16, 14 + PUSHBUTTON "<--", IDB_BROWSE_PARENT, m, m, 24, bys + PUSHBUTTON "+", IDB_BROWSE_CREATE_DIR, m + 32, m, 24, bys + LTEXT "", IDT_BROWSE_FOLDER, m + 64, m + 3, xc - 20, 8 + CONTROL "List1", IDL_BROWSE, "SysListView32", + LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_SINGLESEL | WS_BORDER | WS_TABSTOP, + m, m + k_BROWSE_y_List, xc, yc - bys - m - k_BROWSE_y_List - k_BROWSE_y_CtrlSize - m - k_BROWSE_y_CtrlSize - m } diff --git a/CPP/7zip/UI/FileManager/BrowseDialogRes.h b/CPP/7zip/UI/FileManager/BrowseDialogRes.h old mode 100755 new mode 100644 index 79f0efdb..aff84ec9 --- a/CPP/7zip/UI/FileManager/BrowseDialogRes.h +++ b/CPP/7zip/UI/FileManager/BrowseDialogRes.h @@ -1,4 +1,9 @@ -#define IDD_DIALOG_BROWSE 509 -#define IDC_BROWSE_LIST 1000 -#define IDC_BROWSE_PATH 1001 -#define IDC_BROWSE_PARENT 1002 +#define IDD_BROWSE 95 + +#define IDL_BROWSE 100 +#define IDT_BROWSE_FOLDER 101 +#define IDE_BROWSE_PATH 102 +#define IDC_BROWSE_FILTER 103 + +#define IDB_BROWSE_PARENT 110 +#define IDB_BROWSE_CREATE_DIR 112 diff --git a/CPP/7zip/UI/FileManager/ClassDefs.cpp b/CPP/7zip/UI/FileManager/ClassDefs.cpp old mode 100755 new mode 100644 index 9fec3d92..b092a9ed --- a/CPP/7zip/UI/FileManager/ClassDefs.cpp +++ b/CPP/7zip/UI/FileManager/ClassDefs.cpp @@ -2,7 +2,8 @@ #include "StdAfx.h" -#include "Common/MyInitGuid.h" +#include "../../../Common/MyInitGuid.h" #include "../Agent/Agent.h" + #include "MyWindowsNew.h" diff --git a/CPP/7zip/UI/FileManager/ComboDialog.cpp b/CPP/7zip/UI/FileManager/ComboDialog.cpp old mode 100755 new mode 100644 index c3cc08e7..729743e8 --- a/CPP/7zip/UI/FileManager/ComboDialog.cpp +++ b/CPP/7zip/UI/FileManager/ComboDialog.cpp @@ -3,7 +3,7 @@ #include "StdAfx.h" #include "ComboDialog.h" -#include "Windows/Control/Static.h" +#include "../../../Windows/Control/Static.h" #ifdef LANG #include "LangUtils.h" @@ -11,20 +11,12 @@ 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])); + LangSetDlgItems(*this, NULL, 0); #endif - _comboBox.Attach(GetItem(IDC_COMBO_COMBO)); + _comboBox.Attach(GetItem(IDC_COMBO)); /* // why it doesn't work ? @@ -38,10 +30,10 @@ bool CComboDialog::OnInit() SetText(Title); NControl::CStatic staticContol; - staticContol.Attach(GetItem(IDC_COMBO_STATIC)); + staticContol.Attach(GetItem(IDT_COMBO)); staticContol.SetText(Static); _comboBox.SetText(Value); - for(int i = 0; i < Strings.Size(); i++) + FOR_VECTOR (i, Strings) _comboBox.AddString(Strings[i]); NormalizeSize(); return CModalDialog::OnInit(); diff --git a/CPP/7zip/UI/FileManager/ComboDialog.h b/CPP/7zip/UI/FileManager/ComboDialog.h old mode 100755 new mode 100644 index ff111b19..29b28b5b --- a/CPP/7zip/UI/FileManager/ComboDialog.h +++ b/CPP/7zip/UI/FileManager/ComboDialog.h @@ -3,8 +3,8 @@ #ifndef __COMBO_DIALOG_H #define __COMBO_DIALOG_H -#include "Windows/Control/ComboBox.h" -#include "Windows/Control/Dialog.h" +#include "../../../Windows/Control/ComboBox.h" +#include "../../../Windows/Control/Dialog.h" #include "ComboDialogRes.h" @@ -20,8 +20,9 @@ public: UString Static; UString Value; UStringVector Strings; + // CComboDialog(): Sorted(false) {}; - INT_PTR Create(HWND parentWindow = 0) { return CModalDialog::Create(IDD_DIALOG_COMBO, parentWindow); } + INT_PTR Create(HWND parentWindow = 0) { return CModalDialog::Create(IDD_COMBO, parentWindow); } }; #endif diff --git a/CPP/7zip/UI/FileManager/ComboDialog.rc b/CPP/7zip/UI/FileManager/ComboDialog.rc old mode 100755 new mode 100644 index 6789347a..fddb7484 --- a/CPP/7zip/UI/FileManager/ComboDialog.rc +++ b/CPP/7zip/UI/FileManager/ComboDialog.rc @@ -4,10 +4,13 @@ #define xc 240 #define yc 64 -IDD_DIALOG_COMBO MY_RESIZE_DIALOG +IDD_COMBO DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT CAPTION "Combo" { - LTEXT "", IDC_COMBO_STATIC, m, m, xc, 8 - COMBOBOX IDC_COMBO_COMBO, m, 20, xc, 65, MY_COMBO_WITH_EDIT + LTEXT "", IDT_COMBO, m, m, xc, 8 + COMBOBOX IDC_COMBO, m, 20, xc, 65, MY_COMBO_WITH_EDIT OK_CANCEL } + +#undef xc +#undef yc diff --git a/CPP/7zip/UI/FileManager/ComboDialogRes.h b/CPP/7zip/UI/FileManager/ComboDialogRes.h old mode 100755 new mode 100644 index 7f37cb93..a044797e --- a/CPP/7zip/UI/FileManager/ComboDialogRes.h +++ b/CPP/7zip/UI/FileManager/ComboDialogRes.h @@ -1,4 +1,4 @@ -#define IDD_DIALOG_COMBO 505 +#define IDD_COMBO 98 -#define IDC_COMBO_STATIC 1000 -#define IDC_COMBO_COMBO 1001 +#define IDT_COMBO 100 +#define IDC_COMBO 101 diff --git a/CPP/7zip/UI/FileManager/Copy.bmp b/CPP/7zip/UI/FileManager/Copy.bmp old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/Copy2.bmp b/CPP/7zip/UI/FileManager/Copy2.bmp old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/CopyDialog.cpp b/CPP/7zip/UI/FileManager/CopyDialog.cpp old mode 100755 new mode 100644 index 8cbaf41f..76441215 --- a/CPP/7zip/UI/FileManager/CopyDialog.cpp +++ b/CPP/7zip/UI/FileManager/CopyDialog.cpp @@ -2,9 +2,9 @@ #include "StdAfx.h" -#include "Windows/FileName.h" +#include "../../../Windows/FileName.h" -#include "Windows/Control/Static.h" +#include "../../../Windows/Control/Static.h" #include "BrowseDialog.h" #include "CopyDialog.h" @@ -15,33 +15,25 @@ using namespace NWindows; -#ifdef LANG -static CIDLangPair kIDLangPairs[] = -{ - { IDOK, 0x02000702 }, - { IDCANCEL, 0x02000710 } -}; -#endif - bool CCopyDialog::OnInit() { #ifdef LANG - LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + LangSetDlgItems(*this, NULL, 0); #endif - _path.Attach(GetItem(IDC_COPY_COMBO)); + _path.Attach(GetItem(IDC_COPY)); SetText(Title); NControl::CStatic staticContol; - staticContol.Attach(GetItem(IDC_COPY_STATIC)); + staticContol.Attach(GetItem(IDT_COPY)); staticContol.SetText(Static); #ifdef UNDER_CE // we do it, since WinCE selects Value\something instead of Value !!!! _path.AddString(Value); #endif - for (int i = 0; i < Strings.Size(); i++) + FOR_VECTOR (i, Strings) _path.AddString(Strings[i]); _path.SetText(Value); - SetItemText(IDC_COPY_INFO, Info); + SetItemText(IDT_COPY_INFO, Info); NormalizeSize(true); return CModalDialog::OnInit(); } @@ -59,19 +51,19 @@ bool CCopyDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) InvalidateRect(NULL); { - RECT rect; - GetClientRectOfItem(IDC_COPY_SET_PATH, rect); - int bx = rect.right - rect.left; - MoveItem(IDC_COPY_SET_PATH, xSize - mx - bx, rect.top, bx, rect.bottom - rect.top); + RECT r; + GetClientRectOfItem(IDB_COPY_SET_PATH, r); + int bx = RECT_SIZE_X(r); + MoveItem(IDB_COPY_SET_PATH, xSize - mx - bx, r.top, bx, RECT_SIZE_Y(r)); ChangeSubWindowSizeX(_path, xSize - mx - mx - bx - mx); } { - RECT rect; - GetClientRectOfItem(IDC_COPY_INFO, rect); + RECT r; + GetClientRectOfItem(IDT_COPY_INFO, r); NControl::CStatic staticContol; - staticContol.Attach(GetItem(IDC_COPY_INFO)); - int yPos = rect.top; + staticContol.Attach(GetItem(IDT_COPY_INFO)); + int yPos = r.top; staticContol.Move(mx, yPos, xSize - mx * 2, y - 2 - yPos); } @@ -85,7 +77,7 @@ bool CCopyDialog::OnButtonClicked(int buttonID, HWND buttonHWND) { switch(buttonID) { - case IDC_COPY_SET_PATH: + case IDB_COPY_SET_PATH: OnButtonSetPath(); return true; } @@ -97,10 +89,10 @@ void CCopyDialog::OnButtonSetPath() UString currentPath; _path.GetText(currentPath); - UString title = LangStringSpec(IDS_SET_FOLDER, 0x03020209); + const UString title = LangString(IDS_SET_FOLDER); UString resultPath; - if (!MyBrowseForFolder(HWND(*this), title, currentPath, resultPath)) + if (!MyBrowseForFolder(*this, title, currentPath, resultPath)) return; NFile::NName::NormalizeDirPathPrefix(resultPath); _path.SetCurSel(-1); diff --git a/CPP/7zip/UI/FileManager/CopyDialog.h b/CPP/7zip/UI/FileManager/CopyDialog.h old mode 100755 new mode 100644 index 2c22d700..30fde71f --- a/CPP/7zip/UI/FileManager/CopyDialog.h +++ b/CPP/7zip/UI/FileManager/CopyDialog.h @@ -3,8 +3,8 @@ #ifndef __COPY_DIALOG_H #define __COPY_DIALOG_H -#include "Windows/Control/ComboBox.h" -#include "Windows/Control/Dialog.h" +#include "../../../Windows/Control/ComboBox.h" +#include "../../../Windows/Control/Dialog.h" #include "CopyDialogRes.h" @@ -25,7 +25,7 @@ public: UString Info; UStringVector Strings; - INT_PTR Create(HWND parentWindow = 0) { return CModalDialog::Create(IDD_DIALOG_COPY, parentWindow); } + INT_PTR Create(HWND parentWindow = 0) { return CModalDialog::Create(IDD_COPY, parentWindow); } }; #endif diff --git a/CPP/7zip/UI/FileManager/CopyDialog.rc b/CPP/7zip/UI/FileManager/CopyDialog.rc old mode 100755 new mode 100644 index 922dddc4..73d3ea80 --- a/CPP/7zip/UI/FileManager/CopyDialog.rc +++ b/CPP/7zip/UI/FileManager/CopyDialog.rc @@ -6,12 +6,15 @@ #define y 40 -IDD_DIALOG_COPY MY_RESIZE_DIALOG +IDD_COPY DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT CAPTION "Copy" { - LTEXT "", IDC_COPY_STATIC, m, m, xc, 8 - COMBOBOX IDC_COPY_COMBO, m, 20, xc - bxsDots - m, 65, MY_COMBO_WITH_EDIT - PUSHBUTTON "...", IDC_COPY_SET_PATH, xs - m - bxsDots, 18, bxsDots, bys, WS_GROUP - LTEXT "", IDC_COPY_INFO, m, y, xc, by - y - 1, SS_NOPREFIX | SS_LEFTNOWORDWRAP + LTEXT "", IDT_COPY, m, m, xc, 8 + COMBOBOX IDC_COPY, m, 20, xc - bxsDots - m, 65, MY_COMBO_WITH_EDIT + PUSHBUTTON "...", IDB_COPY_SET_PATH, xs - m - bxsDots, 18, bxsDots, bys, WS_GROUP + LTEXT "", IDT_COPY_INFO, m, y, xc, by - y - 1, SS_NOPREFIX | SS_LEFTNOWORDWRAP OK_CANCEL } + +#undef xc +#undef yc diff --git a/CPP/7zip/UI/FileManager/CopyDialogRes.h b/CPP/7zip/UI/FileManager/CopyDialogRes.h old mode 100755 new mode 100644 index 4944de84..85f5a39a --- a/CPP/7zip/UI/FileManager/CopyDialogRes.h +++ b/CPP/7zip/UI/FileManager/CopyDialogRes.h @@ -1,8 +1,8 @@ -#define IDD_DIALOG_COPY 506 +#define IDD_COPY 96 -#define IDC_COPY_STATIC 1000 -#define IDC_COPY_COMBO 1001 -#define IDC_COPY_SET_PATH 1002 -#define IDC_COPY_INFO 1003 +#define IDT_COPY 100 +#define IDC_COPY 101 +#define IDB_COPY_SET_PATH 102 +#define IDT_COPY_INFO 103 -#define IDS_SET_FOLDER 210 +#define IDS_SET_FOLDER 6007 diff --git a/CPP/7zip/UI/FileManager/Delete.bmp b/CPP/7zip/UI/FileManager/Delete.bmp old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/Delete2.bmp b/CPP/7zip/UI/FileManager/Delete2.bmp old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/DialogSize.h b/CPP/7zip/UI/FileManager/DialogSize.h old mode 100755 new mode 100644 index f4dd1c32..504541bd --- a/CPP/7zip/UI/FileManager/DialogSize.h +++ b/CPP/7zip/UI/FileManager/DialogSize.h @@ -3,7 +3,7 @@ #ifndef __DIALOG_SIZE_H #define __DIALOG_SIZE_H -#include "Windows/Control/Dialog.h" +#include "../../../Windows/Control/Dialog.h" #ifdef UNDER_CE #define BIG_DIALOG_SIZE(x, y) bool isBig = NWindows::NControl::IsDialogSizeOK(x, y); diff --git a/CPP/7zip/UI/FileManager/EditPage.cpp b/CPP/7zip/UI/FileManager/EditPage.cpp old mode 100755 new mode 100644 index 3b38a3a5..627088b9 --- a/CPP/7zip/UI/FileManager/EditPage.cpp +++ b/CPP/7zip/UI/FileManager/EditPage.cpp @@ -12,24 +12,36 @@ using namespace NWindows; -static CIDLangPair kIDLangPairs[] = +static const UInt32 kLangIDs[] = { - { IDC_EDIT_STATIC_EDITOR, 0x03010201}, - { IDC_EDIT_STATIC_DIFF, 0x03010202} + IDT_EDIT_EDITOR, + IDT_EDIT_DIFF +}; + +static const UInt32 kLangIDs_Colon[] = +{ + IDT_EDIT_VIEWER }; static LPCWSTR kEditTopic = L"FM/options.htm#editor"; bool CEditPage::OnInit() { - LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); + LangSetDlgItems_Colon(*this, kLangIDs_Colon, ARRAY_SIZE(kLangIDs_Colon)); - _editor.Attach(GetItem(IDC_EDIT_EDIT_EDITOR)); - _diff.Attach(GetItem(IDC_EDIT_EDIT_DIFF)); + _viewer.Attach(GetItem(IDE_EDIT_VIEWER)); + _editor.Attach(GetItem(IDE_EDIT_EDITOR)); + _diff.Attach(GetItem(IDE_EDIT_DIFF)); { UString path; - ReadRegEditor(path); + ReadRegEditor(false, path); + _viewer.SetText(path); + } + { + UString path; + ReadRegEditor(true, path); _editor.SetText(path); } { @@ -42,10 +54,15 @@ bool CEditPage::OnInit() LONG CEditPage::OnApply() { + { + UString path; + _viewer.GetText(path); + SaveRegEditor(false, path); + } { UString path; _editor.GetText(path); - SaveRegEditor(path); + SaveRegEditor(true, path); } { UString path; @@ -65,7 +82,7 @@ static void Edit_BrowseForFile(NWindows::NControl::CEdit &edit, HWND hwnd) UString path; edit.GetText(path); UString resPath; - if (MyBrowseForFile(hwnd, 0, path, L"*.exe", resPath)) + if (MyBrowseForFile(hwnd, 0, path, NULL, L"*.exe", resPath)) { edit.SetText(resPath); // Changed(); @@ -76,21 +93,19 @@ bool CEditPage::OnButtonClicked(int buttonID, HWND buttonHWND) { switch (buttonID) { - case IDC_EDIT_BUTTON_EDITOR: - Edit_BrowseForFile(_editor, *this); - return true; - case IDC_EDIT_BUTTON_DIFF: - Edit_BrowseForFile(_diff, *this); - return true; + case IDB_EDIT_VIEWER: Edit_BrowseForFile(_viewer, *this); return true; + case IDB_EDIT_EDITOR: Edit_BrowseForFile(_editor, *this); return true; + case IDB_EDIT_DIFF: Edit_BrowseForFile(_diff, *this); return true; } return CPropertyPage::OnButtonClicked(buttonID, buttonHWND); } bool CEditPage::OnCommand(int code, int itemID, LPARAM param) { - if (code == EN_CHANGE && - (itemID == IDC_EDIT_EDIT_EDITOR || - itemID == IDC_EDIT_EDIT_DIFF)) + if (code == EN_CHANGE && ( + itemID == IDE_EDIT_VIEWER || + itemID == IDE_EDIT_EDITOR || + itemID == IDE_EDIT_DIFF)) { Changed(); return true; diff --git a/CPP/7zip/UI/FileManager/EditPage.h b/CPP/7zip/UI/FileManager/EditPage.h old mode 100755 new mode 100644 index fbe3c23c..c11e613b --- a/CPP/7zip/UI/FileManager/EditPage.h +++ b/CPP/7zip/UI/FileManager/EditPage.h @@ -3,11 +3,12 @@ #ifndef __EDIT_PAGE_H #define __EDIT_PAGE_H -#include "Windows/Control/PropertyPage.h" -#include "Windows/Control/Edit.h" +#include "../../../Windows/Control/PropertyPage.h" +#include "../../../Windows/Control/Edit.h" class CEditPage: public NWindows::NControl::CPropertyPage { + NWindows::NControl::CEdit _viewer; NWindows::NControl::CEdit _editor; NWindows::NControl::CEdit _diff; public: diff --git a/CPP/7zip/UI/FileManager/EditPage.rc b/CPP/7zip/UI/FileManager/EditPage.rc old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/EditPage2.rc b/CPP/7zip/UI/FileManager/EditPage2.rc old mode 100755 new mode 100644 index 6b500d27..2d6554fb --- a/CPP/7zip/UI/FileManager/EditPage2.rc +++ b/CPP/7zip/UI/FileManager/EditPage2.rc @@ -1,9 +1,14 @@ CAPTION "Editor" { - LTEXT "&Editor:", IDC_EDIT_STATIC_EDITOR, m, m, xc, 8 - EDITTEXT IDC_EDIT_EDIT_EDITOR, m, 20, xc - m - bxsDots, 14, ES_AUTOHSCROLL - PUSHBUTTON "...", IDC_EDIT_BUTTON_EDITOR, xs - m - bxsDots, 19, bxsDots, bys - LTEXT "&Diff:", IDC_EDIT_STATIC_DIFF, m, 40, xc, 8 - EDITTEXT IDC_EDIT_EDIT_DIFF, m, 52, xc - m - bxsDots, 14, ES_AUTOHSCROLL - PUSHBUTTON "...", IDC_EDIT_BUTTON_DIFF, xs - m - bxsDots, 51, bxsDots, bys + LTEXT "&View:", IDT_EDIT_VIEWER, m, m, xc, 8 + EDITTEXT IDE_EDIT_VIEWER, m, m + 12, xc - m - bxsDots, 14, ES_AUTOHSCROLL + PUSHBUTTON "...", IDB_EDIT_VIEWER, xs - m - bxsDots, m + 11, bxsDots, bys + + LTEXT "&Editor:", IDT_EDIT_EDITOR, m, m + 32, xc, 8 + EDITTEXT IDE_EDIT_EDITOR, m, m + 44, xc - m - bxsDots, 14, ES_AUTOHSCROLL + PUSHBUTTON "...", IDB_EDIT_EDITOR, xs - m - bxsDots, m + 43, bxsDots, bys + + LTEXT "&Diff:", IDT_EDIT_DIFF, m, m + 64, xc, 8 + EDITTEXT IDE_EDIT_DIFF, m, m + 76, xc - m - bxsDots, 14, ES_AUTOHSCROLL + PUSHBUTTON "...", IDB_EDIT_DIFF, xs - m - bxsDots, m + 75, bxsDots, bys } diff --git a/CPP/7zip/UI/FileManager/EditPageRes.h b/CPP/7zip/UI/FileManager/EditPageRes.h old mode 100755 new mode 100644 index 3b958311..017d7024 --- a/CPP/7zip/UI/FileManager/EditPageRes.h +++ b/CPP/7zip/UI/FileManager/EditPageRes.h @@ -1,10 +1,15 @@ -#define IDD_EDIT 542 -#define IDD_EDIT_2 642 +#define IDD_EDIT 2103 +#define IDD_EDIT_2 12103 -#define IDC_EDIT_STATIC_EDITOR 1000 -#define IDC_EDIT_EDIT_EDITOR 1001 -#define IDC_EDIT_BUTTON_EDITOR 1002 +#define IDT_EDIT_VIEWER 543 +#define IDT_EDIT_EDITOR 2104 +#define IDT_EDIT_DIFF 2105 -#define IDC_EDIT_STATIC_DIFF 1010 -#define IDC_EDIT_EDIT_DIFF 1011 -#define IDC_EDIT_BUTTON_DIFF 1012 +#define IDE_EDIT_VIEWER 100 +#define IDB_EDIT_VIEWER 101 + +#define IDE_EDIT_EDITOR 102 +#define IDB_EDIT_EDITOR 103 + +#define IDE_EDIT_DIFF 104 +#define IDB_EDIT_DIFF 105 diff --git a/CPP/7zip/UI/FileManager/EnumFormatEtc.cpp b/CPP/7zip/UI/FileManager/EnumFormatEtc.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/EnumFormatEtc.h b/CPP/7zip/UI/FileManager/EnumFormatEtc.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/Extract.bmp b/CPP/7zip/UI/FileManager/Extract.bmp old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/Extract2.bmp b/CPP/7zip/UI/FileManager/Extract2.bmp old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.cpp b/CPP/7zip/UI/FileManager/ExtractCallback.cpp old mode 100755 new mode 100644 index 90076ebb..ed4bb884 --- a/CPP/7zip/UI/FileManager/ExtractCallback.cpp +++ b/CPP/7zip/UI/FileManager/ExtractCallback.cpp @@ -2,13 +2,20 @@ #include "StdAfx.h" -#include "Common/StringConvert.h" -#include "Windows/Error.h" -#include "Windows/FileDir.h" -#include "Windows/FileFind.h" +#include "../../../Common/ComTry.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/Lang.h" +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/PropVariantConv.h" #include "../../Common/FilePathAutoRename.h" +#include "../../Common/StreamUtils.h" +#include "../Common/ExtractingFilePath.h" #ifndef _SFX #include "../Common/ZipRegistry.h" @@ -18,6 +25,7 @@ #include "ExtractCallback.h" #include "FormatUtils.h" +#include "LangUtils.h" #include "OverwriteDialog.h" #ifndef _NO_CRYPTO #include "PasswordDialog.h" @@ -39,12 +47,14 @@ void CExtractCallbackImp::Init() #endif } -void CExtractCallbackImp::AddErrorMessage(LPCWSTR message) +void CExtractCallbackImp::AddError_Message(LPCWSTR s) { ThereAreMessageErrors = true; - ProgressDialog->Sync.AddErrorMessage(message); + ProgressDialog->Sync.AddError_Message(s); } +#ifndef _SFX + STDMETHODIMP CExtractCallbackImp::SetNumFiles(UInt64 #ifndef _SFX numFiles @@ -52,28 +62,27 @@ STDMETHODIMP CExtractCallbackImp::SetNumFiles(UInt64 ) { #ifndef _SFX - ProgressDialog->Sync.SetNumFilesTotal(numFiles); + ProgressDialog->Sync.Set_NumFilesTotal(numFiles); #endif return S_OK; } +#endif + STDMETHODIMP CExtractCallbackImp::SetTotal(UInt64 total) { - ProgressDialog->Sync.SetProgress(total, 0); + ProgressDialog->Sync.Set_NumBytesTotal(total); return S_OK; } STDMETHODIMP CExtractCallbackImp::SetCompleted(const UInt64 *value) { - RINOK(ProgressDialog->Sync.ProcessStopAndPause()); - if (value != NULL) - ProgressDialog->Sync.SetPos(*value); - return S_OK; + return ProgressDialog->Sync.Set_NumBytesCur(value); } HRESULT CExtractCallbackImp::Open_CheckBreak() { - return ProgressDialog->Sync.ProcessStopAndPause(); + return ProgressDialog->Sync.CheckStop(); } HRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */) @@ -84,9 +93,8 @@ HRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 * /* numFiles */, const HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */) { - RINOK(ProgressDialog->Sync.ProcessStopAndPause()); // if (numFiles != NULL) ProgressDialog->Sync.SetNumFilesCur(*numFiles); - return S_OK; + return ProgressDialog->Sync.CheckStop(); } #ifndef _NO_CRYPTO @@ -96,10 +104,10 @@ HRESULT CExtractCallbackImp::Open_CryptoGetTextPassword(BSTR *password) return CryptoGetTextPassword(password); } -HRESULT CExtractCallbackImp::Open_GetPasswordIfAny(UString &password) +HRESULT CExtractCallbackImp::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) { - if (PasswordIsDefined) - password = Password; + passwordIsDefined = PasswordIsDefined; + password = Password; return S_OK; } @@ -119,7 +127,7 @@ void CExtractCallbackImp::Open_ClearPasswordWasAskedFlag() #ifndef _SFX STDMETHODIMP CExtractCallbackImp::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { - ProgressDialog->Sync.SetRatioInfo(inSize, outSize); + ProgressDialog->Sync.Set_Ratio(inSize, outSize); return S_OK; } #endif @@ -157,14 +165,14 @@ STDMETHODIMP CExtractCallbackImp::AskOverwrite( ProgressDialog->WaitCreating(); INT_PTR writeAnswer = dialog.Create(*ProgressDialog); - switch(writeAnswer) + 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; + case IDCANCEL: *answer = NOverwriteAnswer::kCancel; return E_ABORT; + case IDYES: *answer = NOverwriteAnswer::kYes; break; + case IDNO: *answer = NOverwriteAnswer::kNo; break; + case IDB_YES_TO_ALL: *answer = NOverwriteAnswer::kYesToAll; break; + case IDB_NO_TO_ALL: *answer = NOverwriteAnswer::kNoToAll; break; + case IDB_AUTO_RENAME: *answer = NOverwriteAnswer::kAutoRename; break; default: return E_FAIL; } return S_OK; @@ -177,75 +185,136 @@ STDMETHODIMP CExtractCallbackImp::PrepareOperation(const wchar_t *name, bool isF return SetCurrentFilePath2(name); } -STDMETHODIMP CExtractCallbackImp::MessageError(const wchar_t *message) +STDMETHODIMP CExtractCallbackImp::MessageError(const wchar_t *s) { - AddErrorMessage(message); + AddError_Message(s); return S_OK; } HRESULT CExtractCallbackImp::MessageError(const char *message, const FString &path) { - return MessageError(GetUnicodeString(message) + fs2us(path)); + ThereAreMessageErrors = true; + ProgressDialog->Sync.AddError_Message_Name(GetUnicodeString(message), fs2us(path)); + return S_OK; } -STDMETHODIMP CExtractCallbackImp::ShowMessage(const wchar_t *message) +#ifndef _SFX + +STDMETHODIMP CExtractCallbackImp::ShowMessage(const wchar_t *s) { - AddErrorMessage(message); + AddError_Message(s); return S_OK; } -STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 operationResult, bool encrypted) +#endif + +STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 opRes, bool encrypted) { - switch(operationResult) + switch (opRes) { case NArchive::NExtract::NOperationResult::kOK: break; default: { - UINT messageID; - UInt32 langID; - switch(operationResult) + UINT messageID = 0; + UINT id = 0; + + switch (opRes) { - case NArchive::NExtract::NOperationResult::kUnSupportedMethod: - messageID = IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_UNSUPPORTED_METHOD; - langID = 0x02000A91; + case NArchive::NExtract::NOperationResult::kUnsupportedMethod: + messageID = IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD; + id = IDS_EXTRACT_MSG_UNSUPPORTED_METHOD; break; case NArchive::NExtract::NOperationResult::kDataError: messageID = encrypted ? - IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED: - IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_DATA_ERROR; - langID = encrypted ? 0x02000A94 : 0x02000A92; + IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED: + IDS_EXTRACT_MESSAGE_DATA_ERROR; + id = IDS_EXTRACT_MSG_DATA_ERROR; break; case NArchive::NExtract::NOperationResult::kCRCError: messageID = encrypted ? - IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CRC_ENCRYPTED: - IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CRC; - langID = encrypted ? 0x02000A95 : 0x02000A93; + IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED: + IDS_EXTRACT_MESSAGE_CRC_ERROR; + id = IDS_EXTRACT_MSG_CRC_ERROR; + break; + case NArchive::NExtract::NOperationResult::kUnavailable: + id = IDS_EXTRACT_MSG_UNAVAILABLE_DATA; + break; + case NArchive::NExtract::NOperationResult::kUnexpectedEnd: + id = IDS_EXTRACT_MSG_UEXPECTED_END; break; + case NArchive::NExtract::NOperationResult::kDataAfterEnd: + id = IDS_EXTRACT_MSG_DATA_AFTER_END; + break; + case NArchive::NExtract::NOperationResult::kIsNotArc: + id = IDS_EXTRACT_MSG_IS_NOT_ARC; + break; + case NArchive::NExtract::NOperationResult::kHeadersError: + id = IDS_EXTRACT_MSG_HEADERS_ERROR; + break; + /* default: - return E_FAIL; + messageID = IDS_EXTRACT_MESSAGE_UNKNOWN_ERROR; + break; + */ } if (_needWriteArchivePath) { if (!_currentArchivePath.IsEmpty()) - AddErrorMessage(_currentArchivePath); + AddError_Message(_currentArchivePath); _needWriteArchivePath = false; } - AddErrorMessage( - MyFormatNew(messageID, - #ifdef LANG - langID, - #endif - _currentFilePath)); + + UString msg; + UString msgOld; + + #ifndef _SFX + if (id != 0) + LangString_OnlyFromLangFile(id, msg); + if (messageID != 0 && msg.IsEmpty()) + LangString_OnlyFromLangFile(messageID, msgOld); + #endif + + UString s; + if (msg.IsEmpty() && !msgOld.IsEmpty()) + s = MyFormatNew(msgOld, _currentFilePath); + else + { + if (msg.IsEmpty()) + LangString(id, msg); + if (!msg.IsEmpty()) + s += msg; + else + { + wchar_t temp[16]; + ConvertUInt32ToString(opRes, temp); + s += L"Error #"; + s += temp; + } + + if (encrypted) + { + // s += L" : "; + // s += LangString(IDS_EXTRACT_MSG_ENCRYPTED); + s += L" : "; + s += LangString(IDS_EXTRACT_MSG_WRONG_PSW); + } + s += L" : "; + s += _currentFilePath; + } + + AddError_Message(s); } } + #ifndef _SFX if (_isFolder) NumFolders++; else NumFiles++; - ProgressDialog->Sync.SetNumFilesCur(NumFiles); + ProgressDialog->Sync.Set_NumFilesCur(NumFiles); #endif + return S_OK; } @@ -255,7 +324,8 @@ STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 operationResult, bool HRESULT CExtractCallbackImp::BeforeOpen(const wchar_t *name) { #ifndef _SFX - ProgressDialog->Sync.SetTitleFileName(name); + RINOK(ProgressDialog->Sync.CheckStop()); + ProgressDialog->Sync.Set_TitleFileName(name); #endif _currentArchivePath = name; return S_OK; @@ -265,58 +335,157 @@ HRESULT CExtractCallbackImp::SetCurrentFilePath2(const wchar_t *path) { _currentFilePath = path; #ifndef _SFX - ProgressDialog->Sync.SetCurrentFileName(path); + ProgressDialog->Sync.Set_FilePath(path); #endif return S_OK; } +#ifndef _SFX + HRESULT CExtractCallbackImp::SetCurrentFilePath(const wchar_t *path) { #ifndef _SFX if (NeedAddFile) NumFiles++; NeedAddFile = true; - ProgressDialog->Sync.SetNumFilesCur(NumFiles); + ProgressDialog->Sync.Set_NumFilesCur(NumFiles); #endif return SetCurrentFilePath2(path); } +#endif + +UString HResultToMessage(HRESULT errorCode); + HRESULT CExtractCallbackImp::OpenResult(const wchar_t *name, HRESULT result, bool encrypted) { if (result != S_OK) { - UString message; + UString s; if (result == S_FALSE) - { - message = MyFormatNew(encrypted ? IDS_CANT_OPEN_ENCRYPTED_ARCHIVE : IDS_CANT_OPEN_ARCHIVE, - #ifdef LANG - (encrypted ? 0x0200060A : 0x02000609), - #endif - name); - } + s = MyFormatNew(encrypted ? IDS_CANT_OPEN_ENCRYPTED_ARCHIVE : IDS_CANT_OPEN_ARCHIVE, 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 - message2 = NError::MyFormatMessageW(result); - message += message2; + s = name; + s += L": "; + s += HResultToMessage(result); } - MessageError(message); + MessageError(s); NumArchiveErrors++; } _currentArchivePath = name; _needWriteArchivePath = true; return S_OK; } + +static const UInt32 k_ErrorFlagsIds[] = +{ + IDS_EXTRACT_MSG_IS_NOT_ARC, + IDS_EXTRACT_MSG_HEADERS_ERROR, + IDS_EXTRACT_MSG_HEADERS_ERROR, + IDS_OPEN_MSG_UNAVAILABLE_START, + IDS_OPEN_MSG_UNCONFIRMED_START, + IDS_EXTRACT_MSG_UEXPECTED_END, + IDS_EXTRACT_MSG_DATA_AFTER_END, + IDS_EXTRACT_MSG_UNSUPPORTED_METHOD, + IDS_OPEN_MSG_UNSUPPORTED_FEATURE, + IDS_EXTRACT_MSG_DATA_ERROR, + IDS_EXTRACT_MSG_CRC_ERROR +}; + +UString GetOpenArcErrorMessage(UInt32 errorFlags) +{ + UString s; + for (unsigned i = 0; i < ARRAY_SIZE(k_ErrorFlagsIds); i++) + { + UInt32 f = ((UInt32)1 << i); + if ((errorFlags & f) == 0) + continue; + UInt32 id = k_ErrorFlagsIds[i]; + UString m = LangString(id); + if (m.IsEmpty()) + continue; + if (f == kpv_ErrorFlags_EncryptedHeadersError) + { + m += L" : "; + m += LangString(IDS_EXTRACT_MSG_WRONG_PSW); + } + if (!s.IsEmpty()) + s += L'\n'; + s += m; + errorFlags &= ~f; + } + if (errorFlags != 0) + { + char sz[16]; + sz[0] = '0'; + sz[1] = 'x'; + ConvertUInt32ToHex(errorFlags, sz + 2); + if (!s.IsEmpty()) + s += L'\n'; + s += GetUnicodeString(AString(sz)); + } + return s; +} + +HRESULT CExtractCallbackImp::SetError(int level, const wchar_t *name, + UInt32 errorFlags, const wchar_t *errors, + UInt32 warningFlags, const wchar_t *warnings) +{ + NumArchiveErrors++; + + if (_needWriteArchivePath) + { + if (!_currentArchivePath.IsEmpty()) + AddError_Message(_currentArchivePath); + _needWriteArchivePath = false; + } + + if (level != 0) + { + UString s; + s += name; + s += L": "; + MessageError(s); + } + + if (errorFlags != 0) + MessageError(GetOpenArcErrorMessage(errorFlags)); + + if (errors && wcslen(errors) != 0) + MessageError(errors); + + if (warningFlags != 0) + MessageError((UString)L"Warnings: " + GetOpenArcErrorMessage(warningFlags)); + + if (warnings && wcslen(warnings) != 0) + MessageError((UString)L"Warnings: " + warnings); + + return S_OK; +} + +HRESULT CExtractCallbackImp::OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType) +{ + UString s = L"Warning:\n"; + s += name; + s += L"\n"; + if (wcscmp(okType, errorType) == 0) + { + s += L"The archive is open with offset"; + } + else + { + s += L"Can not open the file as ["; + s += errorType; + s += L"] archive\n"; + s += L"The file is open as ["; + s += okType; + s += L"] archive"; + } + MessageError(s); + NumArchiveErrors++; + return S_OK; +} HRESULT CExtractCallbackImp::ThereAreNoFiles() { @@ -331,7 +500,7 @@ HRESULT CExtractCallbackImp::ExtractResult(HRESULT result) if (result == E_ABORT || result == ERROR_DISK_FULL) return result; MessageError(_currentFilePath); - MessageError(NError::MyFormatMessageW(result)); + MessageError(NError::MyFormatMessage(result)); return S_OK; } @@ -355,7 +524,7 @@ STDMETHODIMP CExtractCallbackImp::CryptoGetTextPassword(BSTR *password) dialog.ShowPassword = showPassword; #endif ProgressDialog->WaitCreating(); - if (dialog.Create(*ProgressDialog) == IDCANCEL) + if (dialog.Create(*ProgressDialog) != IDOK) return E_ABORT; Password = dialog.Password; PasswordIsDefined = true; @@ -369,7 +538,8 @@ STDMETHODIMP CExtractCallbackImp::CryptoGetTextPassword(BSTR *password) #endif -// IExtractCallBack3 +#ifndef _SFX + STDMETHODIMP CExtractCallbackImp::AskWrite( const wchar_t *srcPath, Int32 srcIsFolder, const FILETIME *srcTime, const UInt64 *srcSize, @@ -384,10 +554,10 @@ STDMETHODIMP CExtractCallbackImp::AskWrite( *destPathResult = 0; *writeAnswer = BoolToInt(false); - UString destPathSpec = destPath; FString destPathSys = us2fs(destPath); bool srcIsFolderSpec = IntToBool(srcIsFolder); CFileInfo destFileInfo; + if (destFileInfo.Find(destPathSys)) { if (srcIsFolderSpec) @@ -400,48 +570,51 @@ STDMETHODIMP CExtractCallbackImp::AskWrite( *writeAnswer = BoolToInt(false); return S_OK; } + if (destFileInfo.IsDir()) { RINOK(MessageError("can not replace folder with file with same name: ", destPathSys)); return E_FAIL; } - switch(OverwriteMode) + switch (OverwriteMode) { - case NExtract::NOverwriteMode::kSkipExisting: + case NExtract::NOverwriteMode::kSkip: return S_OK; - case NExtract::NOverwriteMode::kAskBefore: + case NExtract::NOverwriteMode::kAsk: { Int32 overwiteResult; + UString destPathSpec = destPath; + int slashPos = destPathSpec.ReverseFind(L'/'); + #ifdef _WIN32 + int slash1Pos = destPathSpec.ReverseFind(L'\\'); + slashPos = MyMax(slashPos, slash1Pos); + #endif + destPathSpec.DeleteFrom(slashPos + 1); + destPathSpec += fs2us(destFileInfo.Name); + RINOK(AskOverwrite( destPathSpec, &destFileInfo.MTime, &destFileInfo.Size, srcPath, srcTime, srcSize, &overwiteResult)); - switch(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; + case NOverwriteAnswer::kCancel: return E_ABORT; + case NOverwriteAnswer::kNo: return S_OK; + case NOverwriteAnswer::kNoToAll: OverwriteMode = NExtract::NOverwriteMode::kSkip; return S_OK; + case NOverwriteAnswer::kYes: break; + case NOverwriteAnswer::kYesToAll: OverwriteMode = NExtract::NOverwriteMode::kOverwrite; break; + case NOverwriteAnswer::kAutoRename: OverwriteMode = NExtract::NOverwriteMode::kRename; break; default: return E_FAIL; } } } - if (OverwriteMode == NExtract::NOverwriteMode::kAutoRename) + + if (OverwriteMode == NExtract::NOverwriteMode::kRename) { if (!AutoRenamePath(destPathSys)) { @@ -451,7 +624,7 @@ STDMETHODIMP CExtractCallbackImp::AskWrite( destPathResultTemp = fs2us(destPathSys); } else - if (!NFile::NDirectory::DeleteFileAlways(destPathSys)) + if (!NDir::DeleteFileAlways(destPathSys)) { RINOK(MessageError("can not delete output file: ", destPathSys)); return E_ABORT; @@ -460,3 +633,266 @@ STDMETHODIMP CExtractCallbackImp::AskWrite( *writeAnswer = BoolToInt(true); return StringToBstr(destPathResultTemp, destPathResult); } + + +STDMETHODIMP CExtractCallbackImp::UseExtractToStream(Int32 *res) +{ + *res = BoolToInt(StreamMode); + return S_OK; +} + +static HRESULT GetTime(IGetProp *getProp, PROPID propID, FILETIME &ft, bool &ftDefined) +{ + ftDefined = false; + NCOM::CPropVariant prop; + RINOK(getProp->GetProp(propID, &prop)); + if (prop.vt == VT_FILETIME) + { + ft = prop.filetime; + ftDefined = (ft.dwHighDateTime != 0 || ft.dwLowDateTime != 0); + } + else if (prop.vt != VT_EMPTY) + return E_FAIL; + return S_OK; +} + + +static HRESULT GetItemBoolProp(IGetProp *getProp, PROPID propID, bool &result) +{ + NCOM::CPropVariant prop; + result = false; + RINOK(getProp->GetProp(propID, &prop)); + if (prop.vt == VT_BOOL) + result = VARIANT_BOOLToBool(prop.boolVal); + else if (prop.vt != VT_EMPTY) + return E_FAIL; + return S_OK; +} + + +STDMETHODIMP CExtractCallbackImp::GetStream7(const wchar_t *name, + Int32 isDir, + ISequentialOutStream **outStream, Int32 askExtractMode, + IGetProp *getProp) +{ + COM_TRY_BEGIN + *outStream = 0; + _newVirtFileWasAdded = false; + _hashStreamWasUsed = false; + _needUpdateStat = false; + + if (_hashStream) + _hashStreamSpec->ReleaseStream(); + + GetItemBoolProp(getProp, kpidIsAltStream, _isAltStream); + + if (!ProcessAltStreams && _isAltStream) + return S_OK; + + _filePath = name; + _isFolder = IntToBool(isDir); + _curSize = 0; + _curSizeDefined = false; + + UInt64 size = 0; + bool sizeDefined; + { + NCOM::CPropVariant prop; + RINOK(getProp->GetProp(kpidSize, &prop)); + sizeDefined = ConvertPropVariantToUInt64(prop, size); + } + + if (sizeDefined) + { + _curSize = size; + _curSizeDefined = true; + } + + if (askExtractMode != NArchive::NExtract::NAskMode::kExtract && + askExtractMode != NArchive::NExtract::NAskMode::kTest) + return S_OK; + + _needUpdateStat = true; + + CMyComPtr outStreamLoc; + + if (VirtFileSystem && askExtractMode == NArchive::NExtract::NAskMode::kExtract) + { + CVirtFile &file = VirtFileSystemSpec->AddNewFile(); + _newVirtFileWasAdded = true; + file.Name = name; + file.IsDir = IntToBool(isDir); + file.IsAltStream = _isAltStream; + file.Size = 0; + + RINOK(GetTime(getProp, kpidCTime, file.CTime, file.CTimeDefined)); + RINOK(GetTime(getProp, kpidATime, file.ATime, file.ATimeDefined)); + RINOK(GetTime(getProp, kpidMTime, file.MTime, file.MTimeDefined)); + + NCOM::CPropVariant prop; + RINOK(getProp->GetProp(kpidAttrib, &prop)); + if (prop.vt == VT_UI4) + { + file.Attrib = prop.ulVal; + file.AttribDefined = true; + } + // else if (isDir) file.Attrib = FILE_ATTRIBUTE_DIRECTORY; + + file.ExpectedSize = 0; + if (sizeDefined) + file.ExpectedSize = size; + outStreamLoc = VirtFileSystem; + } + + if (_hashStream) + { + { + _hashStreamSpec->SetStream(outStreamLoc); + outStreamLoc = _hashStream; + _hashStreamSpec->Init(true); + _hashStreamWasUsed = true; + } + } + + if (outStreamLoc) + *outStream = outStreamLoc.Detach(); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CExtractCallbackImp::PrepareOperation7(Int32 askExtractMode) +{ + COM_TRY_BEGIN + _needUpdateStat = ( + askExtractMode == NArchive::NExtract::NAskMode::kExtract || + askExtractMode == NArchive::NExtract::NAskMode::kTest); + + /* + _extractMode = false; + switch (askExtractMode) + { + case NArchive::NExtract::NAskMode::kExtract: + if (_testMode) + askExtractMode = NArchive::NExtract::NAskMode::kTest; + else + _extractMode = true; + break; + }; + */ + return SetCurrentFilePath2(_filePath); + COM_TRY_END +} + +STDMETHODIMP CExtractCallbackImp::SetOperationResult7(Int32 opRes, bool encrypted) +{ + COM_TRY_BEGIN + if (VirtFileSystem && _newVirtFileWasAdded) + { + // FIXME: probably we must request file size from VirtFileSystem + // _curSize = VirtFileSystem->GetLastFileSize() + // _curSizeDefined = true; + RINOK(VirtFileSystemSpec->CloseMemFile()); + } + if (_hashStream && _hashStreamWasUsed) + { + _hashStreamSpec->_hash->Final(_isFolder, _isAltStream, _filePath); + _curSize = _hashStreamSpec->GetSize(); + _curSizeDefined = true; + _hashStreamSpec->ReleaseStream(); + _hashStreamWasUsed = false; + } + else if (_hashCalc && _needUpdateStat) + { + _hashCalc->SetSize(_curSize); + _hashCalc->Final(_isFolder, _isAltStream, _filePath); + } + return SetOperationResult(opRes, encrypted); + COM_TRY_END +} + + +static const size_t k_SizeT_MAX = (size_t)((size_t)0 - 1); + +static const UInt32 kBlockSize = ((UInt32)1 << 31); + +STDMETHODIMP CVirtFileSystem::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (size == 0) + return S_OK; + if (!_fileMode) + { + CVirtFile &file = Files.Back(); + size_t rem = file.Data.Size() - (size_t)file.Size; + bool useMem = true; + if (rem < size) + { + UInt64 b = 0; + if (file.Data.Size() == 0) + b = file.ExpectedSize; + UInt64 a = file.Size + size; + if (b < a) + b = a; + a = (UInt64)file.Data.Size() * 2; + if (b < a) + b = a; + useMem = false; + if (b <= k_SizeT_MAX && b <= MaxTotalAllocSize) + useMem = file.Data.ReAlloc_KeepData((size_t)b, (size_t)file.Size); + } + if (useMem) + { + memcpy(file.Data + file.Size, data, size); + file.Size += size; + if (processedSize) + *processedSize = (UInt32)size; + return S_OK; + } + _fileMode = true; + } + RINOK(FlushToDisk(false)); + return _outFileStream->Write(data, size, processedSize); +} + +HRESULT CVirtFileSystem::FlushToDisk(bool closeLast) +{ + if (!_outFileStream) + { + _outFileStreamSpec = new COutFileStream; + _outFileStream = _outFileStreamSpec; + } + while (_numFlushed < Files.Size()) + { + const CVirtFile &file = Files[_numFlushed]; + const FString path = DirPrefix + us2fs(GetCorrectFsPath(file.Name)); + if (!_fileIsOpen) + { + if (!_outFileStreamSpec->Create(path, false)) + { + _outFileStream.Release(); + return E_FAIL; + // MessageBoxMyError(UString(L"Can't create file ") + fs2us(tempFilePath)); + } + _fileIsOpen = true; + RINOK(WriteStream(_outFileStream, file.Data, (size_t)file.Size)); + } + if (_numFlushed == Files.Size() - 1 && !closeLast) + break; + if (file.CTimeDefined || + file.ATimeDefined || + file.MTimeDefined) + _outFileStreamSpec->SetTime( + file.CTimeDefined ? &file.CTime : NULL, + file.ATimeDefined ? &file.ATime : NULL, + file.MTimeDefined ? &file.MTime : NULL); + _outFileStreamSpec->Close(); + _numFlushed++; + _fileIsOpen = false; + if (file.AttribDefined) + NDir::SetFileAttrib(path, file.Attrib); + } + return S_OK; +} + +#endif diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.h b/CPP/7zip/UI/FileManager/ExtractCallback.h old mode 100755 new mode 100644 index 19c29e77..71e48e5e --- a/CPP/7zip/UI/FileManager/ExtractCallback.h +++ b/CPP/7zip/UI/FileManager/ExtractCallback.h @@ -3,18 +3,25 @@ #ifndef __EXTRACT_CALLBACK_H #define __EXTRACT_CALLBACK_H -#include "Common/MyCom.h" +#include "../../../../C/Alloc.h" -#include "Windows/ResourceString.h" +#include "../../../Common/MyCom.h" +#include "../../../Common/StringConvert.h" +#ifndef _SFX #include "../Agent/IFolderArchive.h" +#endif + +#include "../Common/ArchiveExtractCallback.h" #include "../Common/ArchiveOpenCallback.h" #ifndef _NO_CRYPTO #include "../../IPassword.h" #endif +#ifndef _SFX #include "IFolder.h" +#endif #include "ProgressDialog2.h" @@ -22,12 +29,145 @@ #include "LangUtils.h" #endif +#ifndef _SFX + +class CGrowBuf +{ + Byte *_items; + size_t _size; + + CGrowBuf(const CGrowBuf &buffer); + void operator=(const CGrowBuf &buffer); + +public: + bool ReAlloc_KeepData(size_t newSize, size_t keepSize) + { + void *buf = MyAlloc(newSize); + if (!buf) + return false; + memcpy(buf, _items, keepSize); + MyFree(_items); + _items = (Byte *)buf; + _size = newSize; + return true; + } + + CGrowBuf(): _items(0), _size(0) {} + ~CGrowBuf() { MyFree(_items); } + + operator Byte *() { return _items; }; + operator const Byte *() const { return _items; }; + size_t Size() const { return _size; } +}; + +struct CVirtFile +{ + CGrowBuf Data; + + UInt64 Size; // real size + UInt64 ExpectedSize; // the size from props request. 0 if unknown + + UString Name; + + bool CTimeDefined; + bool ATimeDefined; + bool MTimeDefined; + bool AttribDefined; + + bool IsDir; + bool IsAltStream; + + DWORD Attrib; + + FILETIME CTime; + FILETIME ATime; + FILETIME MTime; + + CVirtFile(): + CTimeDefined(false), + ATimeDefined(false), + MTimeDefined(false), + AttribDefined(false), + IsDir(false), + IsAltStream(false) {} +}; + +class CVirtFileSystem: + public ISequentialOutStream, + public CMyUnknownImp +{ + UInt64 _totalAllocSize; + + size_t _pos; + unsigned _numFlushed; + bool _fileIsOpen; + bool _fileMode; + COutFileStream *_outFileStreamSpec; + CMyComPtr _outFileStream; +public: + CObjectVector Files; + UInt64 MaxTotalAllocSize; + FString DirPrefix; + + CVirtFile &AddNewFile() + { + if (!Files.IsEmpty()) + { + MaxTotalAllocSize -= Files.Back().Data.Size(); + } + return Files.AddNew(); + } + HRESULT CloseMemFile() + { + if (_fileMode) + { + return FlushToDisk(true); + } + CVirtFile &file = Files.Back(); + if (file.Data.Size() != file.Size) + { + file.Data.ReAlloc_KeepData((size_t)file.Size, (size_t)file.Size); + } + return S_OK; + } + + bool IsStreamInMem() const + { + if (_fileMode) + return false; + if (Files.Size() < 1 || Files[0].IsAltStream || Files[0].IsDir) + return false; + return true; + } + size_t GetMemStreamWrittenSize() const { return _pos; } + + CVirtFileSystem(): _outFileStreamSpec(NULL), MaxTotalAllocSize((UInt64)0 - 1) {} + + void Init() + { + _totalAllocSize = 0; + _fileMode = false; + _pos = 0; + _numFlushed = 0; + _fileIsOpen = false; + } + + HRESULT CloseFile(const FString &path); + HRESULT FlushToDisk(bool closeLast); + size_t GetPos() const { return _pos; } + + MY_UNKNOWN_IMP + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + +#endif + class CExtractCallbackImp: - public IExtractCallbackUI, + public IExtractCallbackUI, // it includes IFolderArchiveExtractCallback public IOpenCallbackUI, - public IFolderOperationsExtractCallback, - // public IFolderArchiveExtractCallback, // mkultiple from IProgress #ifndef _SFX + public IFolderOperationsExtractCallback, + public IFolderExtractToStreamCallback, public ICompressProgressInfo, #endif #ifndef _NO_CRYPTO @@ -37,9 +177,10 @@ class CExtractCallbackImp: { HRESULT MessageError(const char *message, const FString &path); public: - MY_QUERYINTERFACE_BEGIN2(IFolderOperationsExtractCallback) - MY_QUERYINTERFACE_ENTRY(IFolderArchiveExtractCallback) + MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback) #ifndef _SFX + MY_QUERYINTERFACE_ENTRY(IFolderOperationsExtractCallback) + MY_QUERYINTERFACE_ENTRY(IFolderExtractToStreamCallback) MY_QUERYINTERFACE_ENTRY(ICompressProgressInfo) #endif #ifndef _NO_CRYPTO @@ -48,10 +189,6 @@ public: MY_QUERYINTERFACE_END MY_ADDREF_RELEASE - #ifndef _SFX - STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); - #endif - INTERFACE_IProgress(;) INTERFACE_IOpenCallbackUI(;) @@ -71,13 +208,18 @@ public: HRESULT BeforeOpen(const wchar_t *name); HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted); + HRESULT SetError(int level, const wchar_t *name, + UInt32 errorFlags, const wchar_t *errors, + UInt32 warningFlags, const wchar_t *warnings); HRESULT ThereAreNoFiles(); HRESULT ExtractResult(HRESULT result); + HRESULT OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType); #ifndef _NO_CRYPTO HRESULT SetPassword(const UString &password); #endif + #ifndef _SFX // IFolderOperationsExtractCallback STDMETHOD(AskWrite)( const wchar_t *srcPath, @@ -90,6 +232,9 @@ public: STDMETHOD(ShowMessage)(const wchar_t *message); STDMETHOD(SetCurrentFilePath)(const wchar_t *filePath); STDMETHOD(SetNumFiles)(UInt64 numFiles); + INTERFACE_IFolderExtractToStreamCallback(;) + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); + #endif // ICryptoGetTextPassword #ifndef _NO_CRYPTO @@ -103,9 +248,37 @@ private: UString _currentFilePath; bool _isFolder; + bool _isAltStream; + UInt64 _curSize; + bool _curSizeDefined; + UString _filePath; + // bool _extractMode; + // bool _testMode; + bool _newVirtFileWasAdded; + bool _needUpdateStat; + + HRESULT SetCurrentFilePath2(const wchar_t *filePath); - void AddErrorMessage(LPCWSTR message); + void AddError_Message(LPCWSTR message); + + #ifndef _SFX + bool _hashStreamWasUsed; + COutStreamWithHash *_hashStreamSpec; + CMyComPtr _hashStream; + IHashCalc *_hashCalc; // it's for stat in Test operation + #endif + public: + + #ifndef _SFX + CVirtFileSystem *VirtFileSystemSpec; + CMyComPtr VirtFileSystem; + #endif + + bool ProcessAltStreams; + + bool StreamMode; + CProgressDialog *ProgressDialog; #ifndef _SFX UInt64 NumFolders; @@ -127,12 +300,30 @@ public: PasswordIsDefined(false), PasswordWasAsked(false), #endif - OverwriteMode(NExtract::NOverwriteMode::kAskBefore) + OverwriteMode(NExtract::NOverwriteMode::kAsk), + StreamMode(false), + ProcessAltStreams(true) + #ifndef _SFX + , _hashCalc(NULL) + #endif {} ~CExtractCallbackImp(); void Init(); + #ifndef _SFX + void SetHashCalc(IHashCalc *hashCalc) { _hashCalc = hashCalc; } + + void SetHashMethods(IHashCalc *hash) + { + if (!hash) + return; + _hashStreamSpec = new COutStreamWithHash; + _hashStream = _hashStreamSpec; + _hashStreamSpec->_hash = hash; + } + #endif + bool IsOK() const { return NumArchiveErrors == 0 && !ThereAreMessageErrors; } }; diff --git a/CPP/7zip/UI/FileManager/FM.cpp b/CPP/7zip/UI/FileManager/FM.cpp old mode 100755 new mode 100644 index 147a1fb7..537103ae --- a/CPP/7zip/UI/FileManager/FM.cpp +++ b/CPP/7zip/UI/FileManager/FM.cpp @@ -4,12 +4,17 @@ #include "../../../../C/Alloc.h" -#include "Windows/Error.h" -#include "Windows/MemoryLock.h" -#include "Windows/NtCheck.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/StringToInt.h" + +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/MemoryLock.h" +#include "../../../Windows/NtCheck.h" +#include "../../../Windows/System.h" #ifndef UNDER_CE -#include "Windows/Security.h" +#include "../../../Windows/SecurityUtils.h" #endif #include "../GUI/ExtractRes.h" @@ -33,6 +38,8 @@ using namespace NFind; #define MENU_HEIGHT 26 +UInt64 g_RAM_Size; + #ifdef _WIN32 HINSTANCE g_hInstance; #endif @@ -43,7 +50,30 @@ static UString g_ArcFormat; static bool g_Maximized = false; #ifndef UNDER_CE + DWORD g_ComCtl32Version; + +static DWORD GetDllVersion(LPCTSTR dllName) +{ + DWORD dwVersion = 0; + HINSTANCE hinstDll = LoadLibrary(dllName); + if (hinstDll) + { + DLLGETVERSIONPROC pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hinstDll, "DllGetVersion"); + if (pDllGetVersion) + { + DLLVERSIONINFO dvi; + ZeroMemory(&dvi, sizeof(dvi)); + dvi.cbSize = sizeof(dvi); + HRESULT hr = (*pDllGetVersion)(&dvi); + if (SUCCEEDED(hr)) + dwVersion = MAKELONG(dvi.dwMinorVersion, dvi.dwMajorVersion); + } + FreeLibrary(hinstDll); + } + return dwVersion; +} + #endif bool g_IsSmallScreen = false; @@ -140,18 +170,13 @@ const wchar_t *kWindowClass = L"FM"; #endif // FUNCTION: InitInstance(HANDLE, int) -BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) +static BOOL InitInstance(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); + UString title = L"7-Zip"; // LangString(IDS_APP_TITLE, 0x03000000); /* //If it is already running, then focus on the window @@ -170,8 +195,8 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) wc.lpfnWndProc = (WNDPROC) WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON)); + wc.hInstance = g_hInstance; + wc.hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ICON)); // wc.hCursor = LoadCursor (NULL, IDC_ARROW); wc.hCursor = ::LoadCursor(0, IDC_SIZEWE); @@ -196,39 +221,40 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) DWORD style = WS_OVERLAPPEDWINDOW; // DWORD style = 0; - RECT rect; - bool maximized = false; - int x , y, xSize, ySize; + CWindowInfo info; + info.maximized = false; + int x, y, xSize, ySize; x = y = xSize = ySize = CW_USEDEFAULT; - bool windowPosIsRead = ReadWindowSize(rect, maximized); + bool windowPosIsRead; + info.Read(windowPosIsRead, g_PanelsInfoDefined); if (windowPosIsRead) { // x = rect.left; // y = rect.top; - xSize = rect.right - rect.left; - ySize = rect.bottom - rect.top; + xSize = RECT_SIZE_X(info.rect); + ySize = RECT_SIZE_Y(info.rect); } - 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; + g_SplitterPos = info.splitterPos; + if (info.numPanels < 1 || info.numPanels > 2) + info.numPanels = kNumDefaultPanels; + if (info.currentPanel >= 2) + info.currentPanel = 0; } else { - numPanels = kNumDefaultPanels; - currentPanel = 0; + info.numPanels = kNumDefaultPanels; + info.currentPanel = 0; } - g_App.NumPanels = numPanels; - g_App.LastFocusedPanel = currentPanel; + g_App.NumPanels = info.numPanels; + g_App.LastFocusedPanel = info.currentPanel; if (!wnd.Create(kWindowClass, title, style, - x, y, xSize, ySize, NULL, NULL, hInstance, NULL)) + x, y, xSize, ySize, NULL, NULL, g_hInstance, NULL)) return FALSE; if (nCmdShow == SW_SHOWNORMAL || @@ -238,7 +264,7 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) #endif ) { - if (maximized) + if (info.maximized) nCmdShow = SW_SHOWMAXIMIZED; else nCmdShow = SW_SHOWNORMAL; @@ -253,7 +279,7 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) if (wnd.GetPlacement(&placement)) { if (windowPosIsRead) - placement.rcNormalPosition = rect; + placement.rcNormalPosition = info.rect; placement.showCmd = nCmdShow; wnd.SetPlacement(&placement); } @@ -286,47 +312,10 @@ static void GetCommands(const UString &aCommandLine, UString &aCommands) else aProgramName += aChar; } - aCommands = aCommandLine.Mid(i); + aCommands = aCommandLine.Ptr(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); @@ -368,6 +357,7 @@ bool IsLargePageSupported() } #ifndef UNDER_CE + static void SetMemoryLock() { if (!IsLargePageSupported()) @@ -376,8 +366,27 @@ static void SetMemoryLock() NSecurity::AddLockMemoryPrivilege(); if (ReadLockMemoryEnable()) - NSecurity::EnableLockMemoryPrivilege(); + NSecurity::EnablePrivilege_LockMemory(); +} + +bool g_SymLink_Supported = false; + +static void Set_SymLink_Supported() +{ + g_SymLink_Supported = false; + OSVERSIONINFO versionInfo; + versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); + if (!::GetVersionEx(&versionInfo)) + return; + if (versionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || versionInfo.dwMajorVersion < 6) + return; + g_SymLink_Supported = true; + // if (g_SymLink_Supported) + { + NSecurity::EnablePrivilege_SymLink(); + } } + #endif /* @@ -399,16 +408,18 @@ static const CSwitchForm kSwitchForms[kNumSwitches] = // 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; +static void ErrorMessage(const wchar_t *s) +{ + MessageBoxW(0, s, L"7-Zip", MB_ICONERROR); +} -int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, - #ifdef UNDER_CE - LPWSTR - #else - LPSTR - #endif - /* lpCmdLine */, int nCmdShow) + +#define NT_CHECK_FAIL_ACTION ErrorMessage(L"Unsupported Windows version"); return 1; + +static int WINAPI WinMain2(int nCmdShow) { + g_RAM_Size = NSystem::GetRamSize(); + #ifdef _WIN32 /* @@ -440,6 +451,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, #endif + LoadLangOneTime(); + InitCommonControls(); #ifndef UNDER_CE @@ -471,8 +484,48 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, SplitStringToTwoStrings(commandsString, paramString, tailString); paramString.Trim(); tailString.Trim(); - if (tailString.Left(2) == L"-t") - g_ArcFormat = tailString.Mid(2); + if (tailString.IsPrefixedBy(L"-t")) + g_ArcFormat = tailString.Ptr(2); + + /* + UStringVector switches; + for (;;) + { + if (tailString.IsEmpty()) + break; + UString s1, s2; + SplitStringToTwoStrings(tailString, s1, s2); + if (s2.IsEmpty()) + { + tailString.Trim(); + switches.Add(tailString); + break; + } + s1.Trim(); + switches.Add(s1); + tailString = s2; + } + + FOR_VECTOR(i, switches) + { + const UString &sw = switches[i]; + if (sw.IsPrefixedBy(L"-t")) + g_ArcFormat = sw.Ptr(2); + // + else if (sw.IsPrefixedBy(L"-stp")) + { + const wchar_t *end; + UInt32 val = ConvertStringToUInt32(sw.Ptr(4), &end); + if (*end != 0) + throw 111; + g_TypeParseLevel = val; + } + else + // + throw 112; + } + */ + if (!paramString.IsEmpty()) { g_MainPath = paramString; @@ -504,18 +557,21 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, */ - #ifndef UNDER_CE + #if defined(_WIN32) && !defined(UNDER_CE) SetMemoryLock(); + Set_SymLink_Supported(); #endif + g_App.ReloadLang(); + MSG msg; - if (!InitInstance (hInstance, nCmdShow)) + if (!InitInstance (nCmdShow)) return FALSE; #ifndef _UNICODE if (g_IsNT) { - HACCEL hAccels = LoadAcceleratorsW(hInstance, MAKEINTRESOURCEW(IDR_ACCELERATOR1)); + HACCEL hAccels = LoadAcceleratorsW(g_hInstance, MAKEINTRESOURCEW(IDR_ACCELERATOR1)); while (GetMessageW(&msg, NULL, 0, 0)) { if (TranslateAcceleratorW(g_HWND, hAccels, &msg) == 0) @@ -528,7 +584,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, else #endif { - HACCEL hAccels = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1)); + HACCEL hAccels = LoadAccelerators(g_hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1)); while (GetMessage(&msg, NULL, 0, 0)) { if (TranslateAccelerator(g_HWND, hAccels, &msg) == 0) @@ -548,21 +604,85 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, return (int)msg.wParam; } +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, + #ifdef UNDER_CE + LPWSTR + #else + LPSTR + #endif + /* lpCmdLine */, int nCmdShow) +{ + g_hInstance = hInstance; + + try + { + return WinMain2(nCmdShow); + } + catch(const CNewException &) + { + ErrorMessage(LangString(IDS_MEM_ERROR)); + return 1; + } + catch(const UString &s) + { + ErrorMessage(s); + return 1; + } + catch(const AString &s) + { + ErrorMessage(GetUnicodeString(s)); + return 1; + } + catch(const wchar_t *s) + { + ErrorMessage(s); + return 1; + } + catch(const char *s) + { + ErrorMessage(GetUnicodeString(s)); + return 1; + } + catch(int v) + { + wchar_t s[32]; + ConvertUInt32ToString(v, s); + ErrorMessage(UString(L"Error: ") + s); + return 1; + } + catch(...) + { + ErrorMessage(L"Unknown error"); + return 1; + } +} + static void SaveWindowInfo(HWND aWnd) { + CWindowInfo info; + #ifdef UNDER_CE - RECT rect; - if (!::GetWindowRect(aWnd, &rect)) + + if (!::GetWindowRect(aWnd, &info.rect)) return; - SaveWindowSize(rect, g_Maximized); + info.maximized = g_Maximized; + #else + WINDOWPLACEMENT placement; placement.length = sizeof(placement); if (!::GetWindowPlacement(aWnd, &placement)) return; - SaveWindowSize(placement.rcNormalPosition, BOOLToBool(::IsZoomed(aWnd))); + info.rect = placement.rcNormalPosition; + info.maximized = BOOLToBool(::IsZoomed(aWnd)); + #endif - SavePanelsInfo(g_App.NumPanels, g_App.LastFocusedPanel, g_Splitter.GetPos()); + + info.numPanels = g_App.NumPanels; + info.currentPanel = g_App.LastFocusedPanel; + info.splitterPos = g_Splitter.GetPos(); + + info.Save(); } static void ExecuteCommand(UINT commandID) @@ -572,9 +692,9 @@ static void ExecuteCommand(UINT commandID) switch (commandID) { - case kAddCommand: g_App.AddToArchive(); break; - case kExtractCommand: g_App.ExtractArchives(); break; - case kTestCommand: g_App.TestArchives(); break; + case kMenuCmdID_Toolbar_Add: g_App.AddToArchive(); break; + case kMenuCmdID_Toolbar_Extract: g_App.ExtractArchives(); break; + case kMenuCmdID_Toolbar_Test: g_App.TestArchives(); break; } } @@ -588,7 +708,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) wmEvent = HIWORD(wParam); if ((HWND) lParam != NULL && wmEvent != 0) break; - if (wmId >= kToolbarStartID) + if (wmId >= kMenuCmdID_Toolbar_Start && wmId < kMenuCmdID_Toolbar_End) { ExecuteCommand(wmId); return 0; @@ -636,7 +756,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 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]), + (LPCTBBUTTON)&tbb, ARRAY_SIZE(tbb), 0, 0, 100, 30, sizeof (TBBUTTON))); */ // HCURSOR cursor = ::LoadCursor(0, IDC_SIZEWE); @@ -679,22 +799,14 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 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 - message = NError::MyFormatMessageW(res); - } + message = MyFormatNew(encrypted ? + IDS_CANT_OPEN_ENCRYPTED_ARCHIVE : + IDS_CANT_OPEN_ARCHIVE, + g_MainPath); } - MessageBoxW(0, message, L"7-zip", MB_ICONERROR); + else if (res != S_OK) + message = HResultToMessage(res); + ErrorMessage(message); return -1; } // g_SplitterPos = 0; @@ -824,7 +936,7 @@ static int Window_GetRealHeight(NWindows::CWindow &w) { RECT rect; w.GetWindowRect(&rect); - int res = rect.bottom - rect.top; + int res = RECT_SIZE_Y(rect); #ifndef UNDER_CE WINDOWPLACEMENT placement; if (w.GetPlacement(&placement)) diff --git a/CPP/7zip/UI/FileManager/FM.dsp b/CPP/7zip/UI/FileManager/FM.dsp old mode 100755 new mode 100644 index 3f3cd77c..4a7f16a6 --- a/CPP/7zip/UI/FileManager/FM.dsp +++ b/CPP/7zip/UI/FileManager/FM.dsp @@ -45,7 +45,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /Gz /MD /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 CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /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" @@ -72,7 +72,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /Gz /MDd /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 CPP /nologo /Gz /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" @@ -99,7 +99,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"StdAfx.h" /FD /c -# ADD CPP /nologo /Gz /MD /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 CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" @@ -127,7 +127,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c -# ADD CPP /nologo /Gz /MDd /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 CPP /nologo /Gz /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" @@ -214,22 +214,6 @@ SOURCE=.\StdAfx.h 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 "" @@ -499,6 +483,14 @@ SOURCE=.\DialogSize.h # End Source File # Begin Source File +SOURCE=.\LinkDialog.cpp +# End Source File +# Begin Source File + +SOURCE=.\LinkDialog.h +# End Source File +# Begin Source File + SOURCE=.\ListViewDialog.cpp # End Source File # Begin Source File @@ -603,6 +595,14 @@ SOURCE=.\UpdateCallback100.h # PROP Default_Filter "" # Begin Source File +SOURCE=..\..\Common\CreateCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CreateCoder.h +# End Source File +# Begin Source File + SOURCE=..\..\Common\FilePathAutoRename.cpp # End Source File # Begin Source File @@ -619,131 +619,84 @@ SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File -SOURCE=..\..\Common\ProgressUtils.cpp +SOURCE=..\..\Common\FilterCoder.cpp # End Source File # Begin Source File -SOURCE=..\..\Common\ProgressUtils.h +SOURCE=..\..\Common\FilterCoder.h # End Source File # Begin Source File -SOURCE=..\..\Common\StreamObjects.cpp +SOURCE=..\..\Common\LimitedStreams.cpp # End Source File # Begin Source File -SOURCE=..\..\Common\StreamObjects.h +SOURCE=..\..\Common\LimitedStreams.h # End Source File # Begin Source File -SOURCE=..\..\Common\StreamUtils.cpp +SOURCE=..\..\Common\MethodProps.cpp # End Source File # Begin Source File -SOURCE=..\..\Common\StreamUtils.h +SOURCE=..\..\Common\MethodProps.h # End Source File -# End Group -# Begin Group "C" - -# PROP Default_Filter "" # Begin Source File -SOURCE=..\..\..\..\C\7zCrc.c -# SUBTRACT CPP /YX /Yc /Yu +SOURCE=..\..\Common\ProgressUtils.cpp # End Source File # Begin Source File -SOURCE=..\..\..\..\C\7zCrc.h +SOURCE=..\..\Common\ProgressUtils.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 - +SOURCE=..\..\Common\PropId.cpp # End Source File # Begin Source File -SOURCE=..\..\..\..\C\Alloc.c -# SUBTRACT CPP /YX /Yc /Yu +SOURCE=..\..\Common\StreamObjects.cpp # End Source File # Begin Source File -SOURCE=..\..\..\..\C\Alloc.h +SOURCE=..\..\Common\StreamObjects.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 - +SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File -SOURCE=..\..\..\..\C\CpuArch.h +SOURCE=..\..\Common\StreamUtils.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 +SOURCE=..\..\Common\UniqBlocks.cpp +# End Source File +# Begin Source File -!ELSEIF "$(CFG)" == "FM - Win32 ReleaseU" +SOURCE=..\..\Common\UniqBlocks.h +# End Source File +# End Group +# Begin Group "C" -# SUBTRACT CPP /YX /Yc /Yu +# PROP Default_Filter "" +# Begin Source File -!ELSEIF "$(CFG)" == "FM - Win32 DebugU" +SOURCE=..\..\..\..\C\7zTypes.h +# End Source File +# Begin Source File +SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File -!ENDIF - +SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File -SOURCE=..\..\..\..\C\Sha256.h +SOURCE=..\..\..\..\C\CpuArch.h # End Source File # Begin Source File @@ -836,10 +789,6 @@ 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 @@ -885,11 +834,11 @@ SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Error.cpp +SOURCE=..\..\..\Windows\ErrorMsg.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Error.h +SOURCE=..\..\..\Windows\ErrorMsg.h # End Source File # Begin Source File @@ -917,6 +866,10 @@ SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File +SOURCE=..\..\..\Windows\FileLink.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Windows\FileMapping.h # End Source File # Begin Source File @@ -941,11 +894,11 @@ SOURCE=..\..\..\Windows\Handle.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Memory.cpp +SOURCE=..\..\..\Windows\MemoryGlobal.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Memory.h +SOURCE=..\..\..\Windows\MemoryGlobal.h # End Source File # Begin Source File @@ -973,11 +926,15 @@ SOURCE=..\..\..\Windows\Net.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Process.cpp +SOURCE=..\..\..\Windows\NtCheck.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Process.h +SOURCE=..\..\..\Windows\ProcessUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\ProcessUtils.h # End Source File # Begin Source File @@ -989,11 +946,11 @@ SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\PropVariantConversions.cpp +SOURCE=..\..\..\Windows\PropVariantConv.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\PropVariantConversions.h +SOURCE=..\..\..\Windows\PropVariantConv.h # End Source File # Begin Source File @@ -1013,11 +970,11 @@ SOURCE=..\..\..\Windows\ResourceString.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Security.cpp +SOURCE=..\..\..\Windows\SecurityUtils.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Security.h +SOURCE=..\..\..\Windows\SecurityUtils.h # End Source File # Begin Source File @@ -1037,19 +994,23 @@ SOURCE=..\..\..\Windows\Synchronization.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Thread.h +SOURCE=..\..\..\Windows\System.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Time.cpp +SOURCE=..\..\..\Windows\Thread.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Time.h +SOURCE=..\..\..\Windows\TimeUtils.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Timer.h +SOURCE=..\..\..\Windows\TimeUtils.h # End Source File # Begin Source File @@ -1065,18 +1026,10 @@ SOURCE=..\..\..\Windows\Window.h # 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 @@ -1105,6 +1058,10 @@ SOURCE=..\..\..\Common\Lang.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\MyBuffer.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File @@ -1117,6 +1074,10 @@ SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\MyTypes.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File @@ -1157,18 +1118,6 @@ 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 @@ -1260,6 +1209,14 @@ SOURCE=..\Common\ExtractMode.h # End Source File # Begin Source File +SOURCE=..\Common\HashCalc.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\HashCalc.h +# End Source File +# Begin Source File + SOURCE=..\Common\IFileExtractCallback.h # End Source File # Begin Source File @@ -1292,6 +1249,14 @@ 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 @@ -1412,6 +1377,10 @@ SOURCE=..\Explorer\ContextMenu.h # End Source File # Begin Source File +SOURCE=..\Explorer\ContextMenuFlags.h +# End Source File +# Begin Source File + SOURCE=..\Explorer\RegistryContextMenu.cpp # End Source File # Begin Source File @@ -1419,6 +1388,18 @@ SOURCE=..\Explorer\RegistryContextMenu.cpp SOURCE=..\Explorer\RegistryContextMenu.h # End Source File # End Group +# Begin Group "GUI" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\GUI\HashGUI.cpp +# End Source File +# Begin Source File + +SOURCE=..\GUI\HashGUI.h +# End Source File +# End Group # End Group # Begin Group "Compress" @@ -1437,6 +1418,10 @@ SOURCE=..\..\Compress\CopyCoder.h # PROP Default_Filter "" # Begin Source File +SOURCE=..\..\Archive\IArchive.h +# End Source File +# Begin Source File + SOURCE=..\..\ICoder.h # End Source File # Begin Source File @@ -1451,6 +1436,14 @@ SOURCE=..\..\IPassword.h 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 Source File diff --git a/CPP/7zip/UI/FileManager/FM.dsw b/CPP/7zip/UI/FileManager/FM.dsw old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/FM.ico b/CPP/7zip/UI/FileManager/FM.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/FM.mak b/CPP/7zip/UI/FileManager/FM.mak new file mode 100644 index 00000000..234a5920 --- /dev/null +++ b/CPP/7zip/UI/FileManager/FM.mak @@ -0,0 +1,81 @@ +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 \ + +!IFNDEF UNDER_CE + +FM_OBJS = $(FM_OBJS) \ + $O\FSDrives.obj \ + $O\LinkDialog.obj \ + $O\NetFolder.obj \ + +WIN_OBJS = $(WIN_OBJS) \ + $O\FileSystem.obj \ + $O\Net.obj \ + $O\SecurityUtils.obj \ + +!ENDIF + +AGENT_OBJS = \ + $O\Agent.obj \ + $O\AgentOut.obj \ + $O\AgentProxy.obj \ + $O\ArchiveFolder.obj \ + $O\ArchiveFolderOpen.obj \ + $O\ArchiveFolderOut.obj \ + $O\UpdateCallbackAgent.obj \ diff --git a/CPP/7zip/UI/FileManager/FSDrives.cpp b/CPP/7zip/UI/FileManager/FSDrives.cpp old mode 100755 new mode 100644 index 823b0826..84639de7 --- a/CPP/7zip/UI/FileManager/FSDrives.cpp +++ b/CPP/7zip/UI/FileManager/FSDrives.cpp @@ -4,14 +4,15 @@ #include "../../../../C/Alloc.h" -#include "Common/ComTry.h" -#include "Common/StringConvert.h" +#include "../../../Common/ComTry.h" +#include "../../../Common/Defs.h" +#include "../../../Common/IntToString.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 "../../../Windows/FileDir.h" +#include "../../../Windows/FileIO.h" +#include "../../../Windows/FileSystem.h" +#include "../../../Windows/PropVariant.h" #include "../../PropID.h" @@ -26,7 +27,8 @@ using namespace NWindows; using namespace NFile; using namespace NFind; -static CFSTR kVolPrefix = FTEXT("\\\\.\\"); +static CFSTR kVolPrefix = FTEXT("\\\\.\\"); +static CFSTR kLongPrefix = FTEXT("\\\\?\\"); FString CDriveInfo::GetDeviceFileIoName() const { @@ -43,7 +45,7 @@ struct CPhysTempBuffer static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt64 fileSize, UInt32 bufferSize, UInt64 progressStart, IProgress *progress) { - NFile::NIO::CInFile inFile; + NIO::CInFile inFile; if (!inFile.Open(fromPath)) return GetLastError(); if (fileSize == (UInt64)(Int64)-1) @@ -51,7 +53,7 @@ static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt if (!inFile.GetLength(fileSize)) ::GetLastError(); } - NFile::NIO::COutFile outFile; + NIO::COutFile outFile; if (writeToDisk) { if (!outFile.Open(toPath, FILE_SHARE_WRITE, OPEN_EXISTING, 0)) @@ -62,7 +64,7 @@ static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt return GetLastError(); CPhysTempBuffer tempBuffer; tempBuffer.buffer = MidAlloc(bufferSize); - if (tempBuffer.buffer == 0) + if (!tempBuffer.buffer) return E_OUTOFMEMORY; for (UInt64 pos = 0; pos < fileSize;) @@ -94,26 +96,26 @@ static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt return S_OK; } -static const STATPROPSTG kProps[] = +static const PROPID 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} + kpidName, + kpidTotalSize, + kpidFreeSpace, + kpidType, + kpidVolumeName, + kpidFileSystem, + kpidClusterSize }; static const char *kDriveTypes[] = { - "Unknown", - "No Root Dir", - "Removable", - "Fixed", - "Remote", - "CD-ROM", - "RAM disk" + "Unknown" + , "No Root Dir" + , "Removable" + , "Fixed" + , "Remote" + , "CD-ROM" + , "RAM disk" }; STDMETHODIMP CFSDrives::LoadItems() @@ -122,7 +124,8 @@ STDMETHODIMP CFSDrives::LoadItems() FStringVector driveStrings; MyGetLogicalDriveStrings(driveStrings); - for (int i = 0; i < driveStrings.Size(); i++) + + FOR_VECTOR (i, driveStrings) { CDriveInfo di; @@ -130,12 +133,13 @@ STDMETHODIMP CFSDrives::LoadItems() di.FullSystemName = driveName; if (!driveName.IsEmpty()) - di.Name = driveName.Left(driveName.Length() - 1); + di.Name.SetFrom(driveName, driveName.Len() - 1); di.ClusterSize = 0; di.DriveSize = 0; di.FreeSpace = 0; - di.DriveType = NFile::NSystem::MyGetDriveType(driveName); + di.DriveType = NSystem::MyGetDriveType(driveName); bool needRead = true; + if (di.DriveType == DRIVE_CDROM || di.DriveType == DRIVE_REMOVABLE) { /* @@ -143,25 +147,59 @@ STDMETHODIMP CFSDrives::LoadItems() if (!::GetVolumeInformation(di.FullSystemName, NULL, 0, &dwSerialNumber, NULL, NULL, NULL, 0)) */ - di.KnownSizes = false; { needRead = false; } } + if (needRead) { DWORD volumeSerialNumber, maximumComponentLength, fileSystemFlags; - NFile::NSystem::MyGetVolumeInformation(driveName, + NSystem::MyGetVolumeInformation(driveName, di.VolumeName, &volumeSerialNumber, &maximumComponentLength, &fileSystemFlags, di.FileSystemName); - NFile::NSystem::MyGetDiskFreeSpace(driveName, + NSystem::MyGetDiskFreeSpace(driveName, di.ClusterSize, di.DriveSize, di.FreeSpace); di.KnownSizes = true; + di.KnownSize = true; } + _drives.Add(di); } + + if (_volumeMode) + { + // we must use IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS + for (unsigned n = 0; n < 16; n++) // why 16 ? + { + FChar temp[16]; + ConvertUInt32ToString(n, temp); + FString name = FTEXT("PhysicalDrive"); + name += temp; + FString fullPath = kVolPrefix; + fullPath += name; + + CFileInfo fi; + if (!fi.Find(fullPath)) + continue; + + CDriveInfo di; + di.Name = name; + di.FullSystemName = fullPath; + di.ClusterSize = 0; + di.DriveSize = fi.Size; + di.FreeSpace = 0; + di.DriveType = 0; + + di.IsPhysicalDrive = true; + di.KnownSize = true; + + _drives.Add(di); + } + } + return S_OK; } @@ -177,15 +215,15 @@ STDMETHODIMP CFSDrives::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT return E_INVALIDARG; NCOM::CPropVariant prop; const CDriveInfo &di = _drives[itemIndex]; - switch(propID) + switch (propID) { case kpidIsDir: prop = !_volumeMode; break; case kpidName: prop = di.Name; break; - case kpidTotalSize: if (di.KnownSizes) prop = di.DriveSize; break; + case kpidTotalSize: if (di.KnownSize) prop = di.DriveSize; break; case kpidFreeSpace: if (di.KnownSizes) prop = di.FreeSpace; break; case kpidClusterSize: if (di.KnownSizes) prop = di.ClusterSize; break; case kpidType: - if (di.DriveType < sizeof(kDriveTypes) / sizeof(kDriveTypes[0])) + if (di.DriveType < ARRAY_SIZE(kDriveTypes)) prop = kDriveTypes[di.DriveType]; break; case kpidVolumeName: prop = di.VolumeName; break; @@ -202,7 +240,14 @@ HRESULT CFSDrives::BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder) return S_OK; NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder; CMyComPtr subFolder = fsFolderSpec; - RINOK(fsFolderSpec->Init(name, 0)); + if (_longMode) + { + RINOK(fsFolderSpec->Init((FString)kLongPrefix + name, 0)); + } + else + { + RINOK(fsFolderSpec->Init(name, 0)); + } *resultFolder = subFolder.Detach(); return S_OK; } @@ -243,15 +288,17 @@ IMP_IFolderFolder_Props(CFSDrives) STDMETHODIMP CFSDrives::GetFolderProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; - switch(propID) + NCOM::CPropVariant prop; + switch (propID) { - case kpidType: prop = L"FSDrives"; break; + case kpidType: prop = "FSDrives"; break; case kpidPath: if (_volumeMode) - prop = fs2us(kVolPrefix); + prop = kVolPrefix; + else if (_longMode) + prop = kLongPrefix; else - prop = LangString(IDS_COMPUTER, 0x03020300) + UString(WCHAR_PATH_SEPARATOR); + prop = (UString)LangString(IDS_COMPUTER) + WCHAR_PATH_SEPARATOR; break; } prop.Detach(value); @@ -264,6 +311,8 @@ STDMETHODIMP CFSDrives::GetSystemIconIndex(UInt32 index, Int32 *iconIndex) { *iconIndex = 0; const CDriveInfo &di = _drives[index]; + if (di.IsPhysicalDrive) + return S_OK; int iconIndexTemp; if (GetRealIconIndex(di.FullSystemName, 0, iconIndexTemp) != 0) { @@ -273,10 +322,10 @@ STDMETHODIMP CFSDrives::GetSystemIconIndex(UInt32 index, Int32 *iconIndex) return GetLastError(); } -UString CFSDrives::GetExt(int index) const +const wchar_t *CFSDrives::GetExt(unsigned index) const { const CDriveInfo &di = _drives[index]; - const wchar_t *ext = NULL; + const wchar_t *ext; if (di.DriveType == DRIVE_CDROM) ext = L"iso"; else if (di.FileSystemName.Find(L"NTFS") >= 0) @@ -285,23 +334,27 @@ UString CFSDrives::GetExt(int index) const ext = L"fat"; else ext = L"img"; - return (UString)L'.' + ext; + return ext; } -HRESULT CFSDrives::GetLength(int index, UInt64 &length) const +HRESULT CFSDrives::GetFileSize(unsigned index, UInt64 &fileSize) const { - NFile::NIO::CInFile inFile; + NIO::CInFile inFile; if (!inFile.Open(_drives[index].GetDeviceFileIoName())) return GetLastError(); - if (!inFile.LengthDefined) + if (!inFile.SizeDefined) return E_FAIL; - length = inFile.Length; + fileSize = inFile.Size; return S_OK; } -STDMETHODIMP CFSDrives::CopyTo(const UInt32 *indices, UInt32 numItems, +STDMETHODIMP CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 numItems, + Int32 /* includeAltStreams */, Int32 /* replaceAltStreamColon */, const wchar_t *path, IFolderOperationsExtractCallback *callback) { + if (moveMode) + return E_NOTIMPL; + if (numItems == 0) return S_OK; @@ -313,7 +366,7 @@ STDMETHODIMP CFSDrives::CopyTo(const UInt32 *indices, UInt32 numItems, for (i = 0; i < numItems; i++) { const CDriveInfo &di = _drives[indices[i]]; - if (di.KnownSizes) + if (di.KnownSize) totalSize += di.DriveSize; } RINOK(callback->SetTotal(totalSize)); @@ -331,9 +384,10 @@ STDMETHODIMP CFSDrives::CopyTo(const UInt32 *indices, UInt32 numItems, UInt64 completedSize = 0; RINOK(callback->SetCompleted(&completedSize)); + for (i = 0; i < numItems; i++) { - int index = indices[i]; + unsigned index = indices[i]; const CDriveInfo &di = _drives[index]; UString destPath2 = destPath; UString name = fs2us(di.Name); @@ -343,6 +397,7 @@ STDMETHODIMP CFSDrives::CopyTo(const UInt32 *indices, UInt32 numItems, if (!destName.IsEmpty() && destName.Back() == L':') { destName.DeleteBack(); + destName += L'.'; destName += GetExt(index); } destPath2 += destName; @@ -350,11 +405,11 @@ STDMETHODIMP CFSDrives::CopyTo(const UInt32 *indices, UInt32 numItems, FString srcPath = di.GetDeviceFileIoName(); UInt64 fileSize = 0; - if (GetLength(index, fileSize) != S_OK) + if (GetFileSize(index, fileSize) != S_OK) { return E_FAIL; } - if (!di.KnownSizes) + if (!di.KnownSize) totalSize += fileSize; RINOK(callback->SetTotal(totalSize)); @@ -375,16 +430,7 @@ STDMETHODIMP CFSDrives::CopyTo(const UInt32 *indices, UInt32 numItems, 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 */, +STDMETHODIMP CFSDrives::CopyFrom(Int32 /* moveMode */, const wchar_t * /* fromFolderPath */, const wchar_t ** /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */) { return E_NOTIMPL; diff --git a/CPP/7zip/UI/FileManager/FSDrives.h b/CPP/7zip/UI/FileManager/FSDrives.h old mode 100755 new mode 100644 index a0cfd9be..a8e25d7d --- a/CPP/7zip/UI/FileManager/FSDrives.h +++ b/CPP/7zip/UI/FileManager/FSDrives.h @@ -3,8 +3,8 @@ #ifndef __FS_DRIVES_H #define __FS_DRIVES_H -#include "Common/MyCom.h" -#include "Common/MyString.h" +#include "../../../Common/MyCom.h" +#include "../../../Common/MyString.h" #include "IFolder.h" @@ -12,7 +12,6 @@ struct CDriveInfo { FString Name; FString FullSystemName; - bool KnownSizes; UInt64 DriveSize; UInt64 FreeSpace; UInt64 ClusterSize; @@ -21,7 +20,12 @@ struct CDriveInfo UString FileSystemName; UINT DriveType; + bool KnownSize; + bool KnownSizes; + bool IsPhysicalDrive; + FString GetDeviceFileIoName() const; + CDriveInfo(): KnownSize(false), KnownSizes(false), IsPhysicalDrive(false) {} }; class CFSDrives: @@ -32,10 +36,11 @@ class CFSDrives: { CObjectVector _drives; bool _volumeMode; + bool _longMode; HRESULT BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder); - UString GetExt(int index) const; - HRESULT GetLength(int index, UInt64 &length) const; + const wchar_t *GetExt(unsigned index) const; + HRESULT GetFileSize(unsigned index, UInt64 &fileSize) const; public: MY_UNKNOWN_IMP2(IFolderGetSystemIconIndex, IFolderOperations) @@ -44,9 +49,10 @@ public: STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex); - void Init(bool volMode = false) + void Init(bool volMode = false, bool longMode = false) { _volumeMode = volMode; + _longMode = longMode; } }; diff --git a/CPP/7zip/UI/FileManager/FSFolder.cpp b/CPP/7zip/UI/FileManager/FSFolder.cpp old mode 100755 new mode 100644 index e4cb9f27..a8541eb2 --- a/CPP/7zip/UI/FileManager/FSFolder.cpp +++ b/CPP/7zip/UI/FileManager/FSFolder.cpp @@ -2,13 +2,15 @@ #include "StdAfx.h" -#include "Common/ComTry.h" -#include "Common/StringConvert.h" -#include "Common/UTFConvert.h" +#include "../../../Common/ComTry.h" +#include "../../../Common/Defs.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/UTFConvert.h" -#include "Windows/FileDir.h" -#include "Windows/FileIO.h" -#include "Windows/PropVariant.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileIO.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/PropVariant.h" #include "../../PropID.h" @@ -21,30 +23,49 @@ #include "SysIconUtils.h" -namespace NWindows { -namespace NFile { - -bool GetLongPath(CFSTR path, UString &longPath); - -}} +#if _WIN32_WINNT < 0x0501 +#ifdef _APISETFILE_ +// Windows SDK 8.1 defines in fileapi.h the function GetCompressedFileSizeW only if _WIN32_WINNT >= 0x0501 +// But real support version for that function is NT 3.1 (probably) +// So we must define GetCompressedFileSizeW +EXTERN_C_BEGIN +WINBASEAPI DWORD WINAPI GetCompressedFileSizeW(LPCWSTR lpFileName, LPDWORD lpFileSizeHigh ); +EXTERN_C_END +#endif +#endif using namespace NWindows; using namespace NFile; using namespace NFind; +using namespace NDir; +using namespace NName; + +#ifndef USE_UNICODE_FSTRING +int CompareFileNames_ForFolderList(const FChar *s1, const FChar *s2) +{ + return CompareFileNames_ForFolderList(fs2us(s1), fs2us(s2)); +} +#endif 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} +static const Byte kProps[] = +{ + kpidName, + kpidSize, + kpidMTime, + kpidCTime, + kpidATime, + kpidAttrib, + kpidPackSize, + #ifdef FS_SHOW_LINKS_INFO + kpidINode, + kpidLinks, + #endif + kpidComment, + kpidNumSubDirs, + kpidNumSubFiles, + kpidPrefix }; HRESULT CFSFolder::Init(const FString &path, IFolderFolder *parentFolder) @@ -72,96 +93,173 @@ HRESULT CFSFolder::Init(const FString &path, IFolderFolder *parentFolder) return S_OK; } -static HRESULT GetFolderSize(const FString &path, UInt64 &numFolders, UInt64 &numFiles, UInt64 &size, IProgress *progress) +HRESULT CFsFolderStat::Enumerate() { - RINOK(progress->SetCompleted(NULL)); - numFiles = numFolders = size = 0; - CEnumerator enumerator(path + FSTRING_PATH_SEPARATOR FSTRING_ANY_MASK); + if (Progress) + { + RINOK(Progress->SetCompleted(NULL)); + } + Path += FCHAR_PATH_SEPARATOR; + unsigned len = Path.Len(); + Path += FCHAR_ANY_MASK; + CEnumerator enumerator(Path); CFileInfo fi; while (enumerator.Next(fi)) { if (fi.IsDir()) { - UInt64 subFolders, subFiles, subSize; - RINOK(GetFolderSize(path + FCHAR_PATH_SEPARATOR + fi.Name, subFolders, subFiles, subSize, progress)); - numFolders += subFolders; - numFolders++; - numFiles += subFiles; - size += subSize; + Path.DeleteFrom(len); + Path += fi.Name; + RINOK(Enumerate()); + NumFolders++; } else { - numFiles++; - size += fi.Size; + NumFiles++; + Size += fi.Size; } } return S_OK; } -HRESULT CFSFolder::LoadSubItems(CDirItem &dirItem, const FString &path) +#ifndef UNDER_CE + +static bool MyGetCompressedFileSizeW(CFSTR path, UInt64 &size) +{ + DWORD highPart; + DWORD lowPart = INVALID_FILE_SIZE; + IF_USE_MAIN_PATH + { + lowPart = ::GetCompressedFileSizeW(fs2us(path), &highPart); + if (lowPart != INVALID_FILE_SIZE || ::GetLastError() == NO_ERROR) + { + size = ((UInt64)highPart << 32) | lowPart; + return true; + } + } + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH) + { + UString longPath; + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) + { + lowPart = ::GetCompressedFileSizeW(longPath, &highPart); + if (lowPart != INVALID_FILE_SIZE || ::GetLastError() == NO_ERROR) + { + size = ((UInt64)highPart << 32) | lowPart; + return true; + } + } + } + #endif + return false; +} + +#endif + +HRESULT CFSFolder::LoadSubItems(int dirItem, const FString &relPrefix) { + unsigned startIndex = Folders.Size(); { - CEnumerator enumerator(path + FCHAR_ANY_MASK); + CEnumerator enumerator(_path + relPrefix + FCHAR_ANY_MASK); CDirItem fi; + fi.FolderStat_Defined = false; + fi.NumFolders = 0; + fi.NumFiles = 0; + fi.Parent = dirItem; + 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; + if (_flatMode) + Folders.Add(relPrefix + fi.Name + FCHAR_PATH_SEPARATOR); + } + else + { + /* + fi.PackSize_Defined = true; + if (!MyGetCompressedFileSizeW(_path + relPrefix + fi.Name, fi.PackSize)) + fi.PackSize = fi.Size; + */ + } + + #ifndef UNDER_CE + + fi.Reparse.Free(); + fi.PackSize_Defined = false; + + #ifdef FS_SHOW_LINKS_INFO + fi.FileInfo_Defined = false; + fi.FileInfo_WasRequested = false; + fi.FileIndex = 0; + fi.NumLinks = 0; + #endif + + fi.PackSize = fi.Size; + if (fi.HasReparsePoint()) + { + fi.FileInfo_WasRequested = true; + BY_HANDLE_FILE_INFORMATION info; + NIO::GetReparseData(_path + relPrefix + fi.Name, fi.Reparse, &info); + fi.NumLinks = info.nNumberOfLinks; + fi.FileIndex = (((UInt64)info.nFileIndexHigh) << 32) + info.nFileIndexLow; + fi.FileInfo_Defined = true; } - dirItem.Files.Add(fi); + + #endif + + /* unsigned fileIndex = */ Files.Add(fi); + + #if defined(_WIN32) && !defined(UNDER_CE) + /* + if (_scanAltStreams) + { + CStreamEnumerator enumerator(_path + relPrefix + fi.Name); + CStreamInfo si; + for (;;) + { + bool found; + if (!enumerator.Next(si, found)) + { + // if (GetLastError() == ERROR_ACCESS_DENIED) + // break; + // return E_FAIL; + break; + } + if (!found) + break; + if (si.IsMainStream()) + continue; + CAltStream ss; + ss.Parent = fileIndex; + ss.Name = si.GetReducedName(); + ss.Size = si.Size; + ss.PackSize_Defined = false; + ss.PackSize = si.Size; + Streams.Add(ss); + } + } + */ + #endif } } 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 + FCHAR_PATH_SEPARATOR); - } + unsigned endIndex = Folders.Size(); + for (unsigned i = startIndex; i < endIndex; i++) + LoadSubItems(i, Folders[i]); 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")); + RINOK(LoadSubItems(-1, FString())); _commentsAreLoaded = false; return S_OK; } @@ -170,25 +268,23 @@ static CFSTR kDescriptionFileName = FTEXT("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)) + UInt64 len; + if (!file.GetLength(len)) return false; - if (length >= (1 << 28)) + if (len >= (1 << 28)) return false; AString s; - char *p = s.GetBuffer((int)((size_t)length + 1)); + char *p = s.GetBuffer((unsigned)((size_t)len + 1)); UInt32 processedSize; - file.Read(p, (UInt32)length, processedSize); - p[length] = 0; + file.Read(p, (UInt32)len, processedSize); + p[len] = 0; s.ReleaseBuffer(); - if (processedSize != length) + if (processedSize != len) return false; file.Close(); UString unicodeString; @@ -197,122 +293,394 @@ bool CFSFolder::LoadComments() return _comments.ReadFromString(unicodeString); } -static bool IsAscii(const UString &testString) +static bool IsAscii(const AString &s) { - for (int i = 0; i < testString.Length(); i++) - if (testString[i] >= 0x80) + for (unsigned i = 0; i < s.Len(); i++) + if ((Byte)s[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)) + AString utf; { - Byte bom [] = { 0xEF, 0xBB, 0xBF, 0x0D, 0x0A }; - file.Write(bom , sizeof(bom), processedSize); + UString unicode; + _comments.SaveToString(unicode); + ConvertUnicodeToUTF8(unicode, utf); + } + if (!IsAscii(utf)) + utf.Insert(0, "\xEF\xBB\xBF" "\r\n"); + + FString path = _path + kDescriptionFileName; + // We must set same attrib. COutFile::CreateAlways can fail, if file has another attrib. + DWORD attrib = FILE_ATTRIBUTE_NORMAL; + { + CFileInfo fi; + if (fi.Find(path)) + attrib = fi.Attrib; } - file.Write(utfString, utfString.Length(), processedSize); + NIO::COutFile file; + if (!file.CreateAlways(path, attrib)) + return false; + UInt32 processed; + file.Write(utf, utf.Len(), processed); _commentsAreLoaded = false; return true; } STDMETHODIMP CFSFolder::GetNumberOfItems(UInt32 *numItems) { - *numItems = _refs.Size(); + *numItems = Files.Size() /* + Streams.Size() */; return S_OK; } -/* -STDMETHODIMP CFSFolder::GetNumberOfSubFolders(UInt32 *numSubFolders) +#ifdef USE_UNICODE_FSTRING + +STDMETHODIMP CFSFolder::GetItemPrefix(UInt32 index, const wchar_t **name, unsigned *len) { - UInt32 numSubFoldersLoc = 0; - for (int i = 0; i < _files.Size(); i++) - if (_files[i].IsDir()) - numSubFoldersLoc++; - *numSubFolders = numSubFoldersLoc; + *name = 0; + *len = 0; + /* + if (index >= Files.Size()) + index = Streams[index - Files.Size()].Parent; + */ + CDirItem &fi = Files[index]; + if (fi.Parent >= 0) + { + const FString &fo = Folders[fi.Parent]; + USE_UNICODE_FSTRING + *name = fo; + *len = fo.Len(); + } return S_OK; } -*/ -#ifndef UNDER_CE -static bool MyGetCompressedFileSizeW(CFSTR fileName, UInt64 &size) +STDMETHODIMP CFSFolder::GetItemName(UInt32 index, const wchar_t **name, unsigned *len) { - DWORD highPart; - DWORD lowPart = ::GetCompressedFileSizeW(fs2us(fileName), &highPart); - if (lowPart == INVALID_FILE_SIZE && ::GetLastError() != NO_ERROR) + *name = 0; + *len = 0; + if (index < Files.Size()) { - #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; + CDirItem &fi = Files[index]; + *name = fi.Name; + *len = fi.Name.Len(); + return S_OK; + } + else + { + // const CAltStream &ss = Streams[index - Files.Size()]; + // *name = ss.Name; + // *len = ss.Name.Len(); + // + // change it; } - size = (UInt64(highPart) << 32) | lowPart; + return S_OK; +} + +STDMETHODIMP_(UInt64) CFSFolder::GetItemSize(UInt32 index) +{ + /* + if (index >= Files.Size()) + return Streams[index - Files.Size()].Size; + */ + CDirItem &fi = Files[index]; + return fi.IsDir() ? 0 : fi.Size; +} + +#endif + +#ifdef FS_SHOW_LINKS_INFO +bool CFSFolder::ReadFileInfo(CDirItem &di) +{ + di.FileInfo_WasRequested = true; + BY_HANDLE_FILE_INFORMATION info; + if (!NIO::CFileBase::GetFileInformation(_path + GetRelPath(di), &info)) + return false; + di.NumLinks = info.nNumberOfLinks; + di.FileIndex = (((UInt64)info.nFileIndexHigh) << 32) + info.nFileIndexLow; + di.FileInfo_Defined = true; return true; } #endif -STDMETHODIMP CFSFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value) +STDMETHODIMP CFSFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { NCOM::CPropVariant prop; - if (itemIndex >= (UInt32)_refs.Size()) - return E_INVALIDARG; - CDirItem &fi = *_refs[itemIndex]; - switch(propID) + /* + if (index >= (UInt32)Files.Size()) + { + CAltStream &ss = Streams[index - Files.Size()]; + CDirItem &fi = Files[ss.Parent]; + switch (propID) + { + case kpidIsDir: prop = false; break; + case kpidIsAltStream: prop = true; break; + case kpidName: prop = fs2us(fi.Name) + ss.Name; break; + case kpidSize: prop = ss.Size; break; + case kpidPackSize: + #ifdef UNDER_CE + prop = ss.Size; + #else + if (!ss.PackSize_Defined) + { + ss.PackSize_Defined = true; + if (!MyGetCompressedFileSizeW(_path + GetRelPath(fi) + us2fs(ss.Name), ss.PackSize)) + ss.PackSize = ss.Size; + } + prop = ss.PackSize; + #endif + break; + case kpidComment: break; + default: index = ss.Parent; + } + if (index >= (UInt32)Files.Size()) + { + prop.Detach(value); + return S_OK; + } + } + */ + CDirItem &fi = Files[index]; + switch (propID) { case kpidIsDir: prop = fi.IsDir(); break; + case kpidIsAltStream: prop = false; break; case kpidName: prop = fs2us(fi.Name); break; - case kpidSize: if (!fi.IsDir()) prop = fi.Size; break; + case kpidSize: if (!fi.IsDir() || fi.FolderStat_Defined) prop = fi.Size; break; case kpidPackSize: #ifdef UNDER_CE prop = fi.Size; #else - if (!fi.CompressedSizeIsDefined) + if (!fi.PackSize_Defined) { - fi.CompressedSizeIsDefined = true; - if (fi.IsDir () || - !MyGetCompressedFileSizeW(_path + GetRelPath(fi), fi.CompressedSize)) - fi.CompressedSize = fi.Size; + fi.PackSize_Defined = true; + if (fi.IsDir () || !MyGetCompressedFileSizeW(_path + GetRelPath(fi), fi.PackSize)) + fi.PackSize = fi.Size; } - prop = fi.CompressedSize; + prop = fi.PackSize; #endif break; + + #ifdef FS_SHOW_LINKS_INFO + + case kpidLinks: + #ifdef UNDER_CE + // prop = fi.NumLinks; + #else + if (!fi.FileInfo_WasRequested) + ReadFileInfo(fi); + if (fi.FileInfo_Defined) + prop = fi.NumLinks; + #endif + break; + + case kpidINode: + #ifdef UNDER_CE + // prop = fi.FileIndex; + #else + if (!fi.FileInfo_WasRequested) + ReadFileInfo(fi); + if (fi.FileInfo_Defined) + prop = fi.FileIndex; + #endif + break; + + #endif + 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(); + if (!_commentsAreLoaded) + LoadComments(); UString comment; if (_comments.GetValue(fs2us(GetRelPath(fi)), comment)) + { + int pos = comment.Find((wchar_t)4); + if (pos >= 0) + comment.DeleteFrom(pos); prop = comment; + } break; } case kpidPrefix: - { - if (_flatMode) - prop = GetPrefix(fi); + if (fi.Parent >= 0) + prop = Folders[fi.Parent]; break; - } + case kpidNumSubDirs: if (fi.IsDir() && fi.FolderStat_Defined) prop = fi.NumFolders; break; + case kpidNumSubFiles: if (fi.IsDir() && fi.FolderStat_Defined) prop = fi.NumFiles; break; } prop.Detach(value); return S_OK; } + +// ---------- IArchiveGetRawProps ---------- + + +STDMETHODIMP CFSFolder::GetNumRawProps(UInt32 *numProps) +{ + *numProps = 1; + return S_OK; +} + +STDMETHODIMP CFSFolder::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID) +{ + index = index; + *name = NULL; + *propID = kpidNtReparse; + return S_OK; +} + +STDMETHODIMP CFSFolder::GetParent(UInt32 /* index */, UInt32 * /* parent */, UInt32 * /* parentType */) +{ + return E_FAIL; +} + +STDMETHODIMP CFSFolder::GetRawProp(UInt32 + #ifndef UNDER_CE + index + #endif + , PROPID + #ifndef UNDER_CE + propID + #endif + , const void **data, UInt32 *dataSize, UInt32 *propType) +{ + *data = NULL; + *dataSize = 0; + *propType = 0; + + #ifndef UNDER_CE + if (propID == kpidNtReparse) + { + const CDirItem &fi = Files[index]; + const CByteBuffer &buf = fi.Reparse; + if (buf.Size() == 0) + return S_OK; + *data = buf; + *dataSize = (UInt32)buf.Size(); + *propType = NPropDataType::kRaw; + return S_OK; + } + #endif + + return S_OK; +} + + +// returns Position of extension including '.' + +static inline CFSTR GetExtensionPtr(const FString &name) +{ + int dotPos = name.ReverseFind(FTEXT('.')); + return name.Ptr((dotPos < 0) ? name.Len() : dotPos); +} + +STDMETHODIMP_(Int32) CFSFolder::CompareItems(UInt32 index1, UInt32 index2, PROPID propID, Int32 /* propIsRaw */) +{ + /* + const CAltStream *ss1 = NULL; + const CAltStream *ss2 = NULL; + if (index1 >= (UInt32)Files.Size()) { ss1 = &Streams[index1 - Files.Size()]; index1 = ss1->Parent; } + if (index2 >= (UInt32)Files.Size()) { ss2 = &Streams[index2 - Files.Size()]; index2 = ss2->Parent; } + */ + CDirItem &fi1 = Files[index1]; + CDirItem &fi2 = Files[index2]; + + switch (propID) + { + case kpidName: + { + int comp = CompareFileNames_ForFolderList(fi1.Name, fi2.Name); + /* + if (comp != 0) + return comp; + if (!ss1) + return ss2 ? -1 : 0; + if (!ss2) + return 1; + return MyStringCompareNoCase(ss1->Name, ss2->Name); + */ + return comp; + } + case kpidSize: + return MyCompare( + /* ss1 ? ss1->Size : */ fi1.Size, + /* ss2 ? ss2->Size : */ fi2.Size); + case kpidAttrib: return MyCompare(fi1.Attrib, fi2.Attrib); + case kpidCTime: return CompareFileTime(&fi1.CTime, &fi2.CTime); + case kpidATime: return CompareFileTime(&fi1.ATime, &fi2.ATime); + case kpidMTime: return CompareFileTime(&fi1.MTime, &fi2.MTime); + case kpidIsDir: + { + bool isDir1 = /* ss1 ? false : */ fi1.IsDir(); + bool isDir2 = /* ss2 ? false : */ fi2.IsDir(); + if (isDir1 == isDir2) + return 0; + return isDir1 ? -1 : 1; + } + case kpidPackSize: + { + #ifdef UNDER_CE + return MyCompare(fi1.Size, fi2.Size); + #else + // PackSize can be undefined here + return MyCompare( + /* ss1 ? ss1->PackSize : */ fi1.PackSize, + /* ss2 ? ss2->PackSize : */ fi2.PackSize); + #endif + } + + #ifdef FS_SHOW_LINKS_INFO + case kpidINode: + { + #ifndef UNDER_CE + if (!fi1.FileInfo_WasRequested) ReadFileInfo(fi1); + if (!fi2.FileInfo_WasRequested) ReadFileInfo(fi2); + return MyCompare( + fi1.FileIndex, + fi2.FileIndex); + #endif + } + case kpidLinks: + { + #ifndef UNDER_CE + if (!fi1.FileInfo_WasRequested) ReadFileInfo(fi1); + if (!fi2.FileInfo_WasRequested) ReadFileInfo(fi2); + return MyCompare( + fi1.NumLinks, + fi2.NumLinks); + #endif + } + #endif + + case kpidComment: + { + // change it ! + UString comment1, comment2; + _comments.GetValue(fs2us(GetRelPath(fi1)), comment1); + _comments.GetValue(fs2us(GetRelPath(fi2)), comment2); + return MyStringCompareNoCase(comment1, comment2); + } + case kpidPrefix: + if (fi1.Parent < 0) return (fi2.Parent < 0) ? 0 : -1; + if (fi2.Parent < 0) return 1; + return CompareFileNames_ForFolderList( + Folders[fi1.Parent], + Folders[fi2.Parent]); + case kpidExtension: + return CompareFileNames_ForFolderList( + GetExtensionPtr(fi1.Name), + GetExtensionPtr(fi2.Name)); + } + + return 0; +} + HRESULT CFSFolder::BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder) { *resultFolder = 0; @@ -323,27 +691,57 @@ HRESULT CFSFolder::BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder) return S_OK; } -FString CFSFolder::GetPrefix(const CDirItem &item) const +/* +void CFSFolder::GetPrefix(const CDirItem &item, FString &prefix) const { - FString path; - CDirItem *cur = item.Parent; - while (cur->Parent != 0) + if (item.Parent >= 0) + prefix = Folders[item.Parent]; + else + prefix.Empty(); +} +*/ +/* +void CFSFolder::GetPrefix(const CDirItem &item, FString &prefix) const +{ + int parent = item.Parent; + + unsigned len = 0; + + while (parent >= 0) + { + const CDirItem &cur = Files[parent]; + len += cur.Name.Len() + 1; + parent = cur.Parent; + } + + unsigned totalLen = len; + wchar_t *p = prefix.GetBuffer(len); + parent = item.Parent; + + while (parent >= 0) { - path = cur->Name + FCHAR_PATH_SEPARATOR + path; - cur = cur->Parent; + const CDirItem &cur = Files[parent]; + // path = cur->Name + FCHAR_PATH_SEPARATOR + path; + MyStringCopy(p + len - cur.Name.Len() - 1, (const wchar_t *)cur.Name); + p[--len] = FCHAR_PATH_SEPARATOR; + len -= cur.Name.Len(); + parent = cur.Parent; } - return path; + prefix.ReleaseBuffer(totalLen); } +*/ FString CFSFolder::GetRelPath(const CDirItem &item) const { - return GetPrefix(item) + item.Name; + if (item.Parent < 0) + return item.Name; + return Folders[item.Parent] + item.Name; } STDMETHODIMP CFSFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder) { *resultFolder = 0; - const CDirItem &fi = *_refs[index]; + const CDirItem &fi = Files[index]; if (!fi.IsDir()) return E_INVALIDARG; return BindToFolderSpec(GetRelPath(fi), resultFolder); @@ -354,6 +752,8 @@ STDMETHODIMP CFSFolder::BindToFolder(const wchar_t *name, IFolderFolder **result return BindToFolderSpec(us2fs(name), resultFolder); } +static CFSTR kLongPrefix = FTEXT("\\\\?\\"); + STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder) { *resultFolder = 0; @@ -366,7 +766,7 @@ STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder) if (_path.IsEmpty()) return E_INVALIDARG; int pos = _path.ReverseFind(FCHAR_PATH_SEPARATOR); - if (pos < 0 || pos != _path.Length() - 1) + if (pos < 0 || pos != (int)_path.Len() - 1) return E_FAIL; FString parentPath = _path.Left(pos); pos = parentPath.ReverseFind(FCHAR_PATH_SEPARATOR); @@ -382,8 +782,24 @@ STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder) #endif return S_OK; } + + parentPath.DeleteFrom(pos + 1); + + if (parentPath == kLongPrefix) + { + #ifdef UNDER_CE + *resultFolder = 0; + #else + CFSDrives *drivesFolderSpec = new CFSDrives; + CMyComPtr drivesFolder = drivesFolderSpec; + drivesFolderSpec->Init(false, true); + *resultFolder = drivesFolder.Detach(); + #endif + return S_OK; + } + FString parentPathReduced = parentPath.Left(pos); - parentPath = parentPath.Left(pos + 1); + #ifndef UNDER_CE pos = parentPathReduced.ReverseFind(FCHAR_PATH_SEPARATOR); if (pos == 1) @@ -397,6 +813,7 @@ STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder) return S_OK; } #endif + CFSFolder *parentFolderSpec = new CFSFolder; CMyComPtr parentFolder = parentFolderSpec; RINOK(parentFolderSpec->Init(parentPath, 0)); @@ -406,7 +823,7 @@ STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder) STDMETHODIMP CFSFolder::GetNumberOfProperties(UInt32 *numProperties) { - *numProperties = sizeof(kProps) / sizeof(kProps[0]); + *numProperties = ARRAY_SIZE(kProps); if (!_flatMode) (*numProperties)--; return S_OK; @@ -418,7 +835,7 @@ STDMETHODIMP CFSFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NWindows::NCOM::CPropVariant prop; - switch(propID) + switch (propID) { case kpidType: prop = L"FSFolder"; break; case kpidPath: prop = fs2us(_path); break; @@ -462,58 +879,49 @@ STDMETHODIMP CFSFolder::Clone(IFolderFolder **resultFolder) return S_OK; } -HRESULT CFSFolder::GetItemsFullSize(const UInt32 *indices, UInt32 numItems, - UInt64 &numFolders, UInt64 &numFiles, UInt64 &size, IProgress *progress) +HRESULT CFSFolder::GetItemsFullSize(const UInt32 *indices, UInt32 numItems, CFsFolderStat &stat) { - numFiles = numFolders = size = 0; - UInt32 i; - for (i = 0; i < numItems; i++) + for (UInt32 i = 0; i < numItems; i++) { - int index = indices[i]; - if (index >= _refs.Size()) - return E_INVALIDARG; - const CDirItem &fi = *_refs[index]; + UInt32 index = indices[i]; + /* + if (index >= Files.Size()) + { + size += Streams[index - Files.Size()].Size; + // numFiles++; + continue; + } + */ + const CDirItem &fi = Files[index]; if (fi.IsDir()) { - UInt64 subFolders, subFiles, subSize; - RINOK(GetFolderSize(_path + GetRelPath(fi), subFolders, subFiles, subSize, progress)); - numFolders += subFolders; - numFolders++; - numFiles += subFiles; - size += subSize; + stat.Path = _path; + stat.Path += GetRelPath(fi); + RINOK(stat.Enumerate()); + stat.NumFolders++; } else { - numFiles++; - size += fi.Size; + stat.NumFiles++; + stat.Size += fi.Size; } } return S_OK; } -HRESULT CFSFolder::GetItemFullSize(int index, UInt64 &size, IProgress *progress) +/* +HRESULT CFSFolder::GetItemFullSize(unsigned index, UInt64 &size, IProgress *progress) { - const CDirItem &fi = *_refs[index]; + if (index >= Files.Size()) + { + size = Streams[index - Files.Size()].Size; + return S_OK; + } + const CDirItem &fi = Files[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; + UInt64 numFolders = 0, numFiles = 0; + size = 0; return GetFolderSize(_path + GetRelPath(fi), numFolders, numFiles, size, progress); } size = fi.Size; @@ -523,61 +931,72 @@ HRESULT CFSFolder::GetItemFullSize(int index, UInt64 &size, IProgress *progress) 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(CFSTR name, FString &resultPath) +STDMETHODIMP CFSFolder::CalcItemFullSize(UInt32 index, IProgress *progress) { - FString newName = name; - resultPath = _path + newName; - if (newName.Length() < 1) - return S_OK; - if (newName[0] == FCHAR_PATH_SEPARATOR) - { - resultPath = newName; + if (index >= (UInt32)Files.Size()) return S_OK; - } - if (newName.Length() < 2) + CDirItem &fi = Files[index]; + if (!fi.IsDir()) return S_OK; - if (newName[1] == L':') - resultPath = newName; + CFsFolderStat stat(_path + GetRelPath(fi), progress); + RINOK(stat.Enumerate()); + fi.Size = stat.Size; + fi.NumFolders = stat.NumFolders; + fi.NumFiles = stat.NumFiles; + fi.FolderStat_Defined = true; return S_OK; } +void CFSFolder::GetAbsPath(const wchar_t *name, FString &absPath) +{ + absPath.Empty(); + if (!IsAbsolutePath(name)) + absPath += _path; + absPath += us2fs(name); +} + STDMETHODIMP CFSFolder::CreateFolder(const wchar_t *name, IProgress * /* progress */) { - FString processedName; - RINOK(GetComplexName(us2fs(name), processedName)); - if (NDirectory::MyCreateDirectory(processedName)) + FString absPath; + GetAbsPath(name, absPath); + if (CreateDir(absPath)) return S_OK; if (::GetLastError() == ERROR_ALREADY_EXISTS) return ::GetLastError(); - if (!NDirectory::CreateComplexDirectory(processedName)) + if (!CreateComplexDir(absPath)) return ::GetLastError(); return S_OK; } STDMETHODIMP CFSFolder::CreateFile(const wchar_t *name, IProgress * /* progress */) { - FString processedName; - RINOK(GetComplexName(us2fs(name), processedName)); + FString absPath; + GetAbsPath(name, absPath); NIO::COutFile outFile; - if (!outFile.Create(processedName, false)) + if (!outFile.Create(absPath, false)) return ::GetLastError(); return S_OK; } STDMETHODIMP CFSFolder::Rename(UInt32 index, const wchar_t *newName, IProgress * /* progress */) { - const CDirItem &fi = *_refs[index]; - const FString fullPrefix = _path + GetPrefix(fi); - if (!NDirectory::MyMoveFile(fullPrefix + fi.Name, fullPrefix + us2fs(newName))) + if (index >= (UInt32)Files.Size()) + return E_NOTIMPL; + const CDirItem &fi = Files[index]; + // FString prefix; + // GetPrefix(fi, prefix); + FString fullPrefix = _path; + if (fi.Parent >= 0) + fullPrefix += Folders[fi.Parent]; + if (!MyMoveFile(fullPrefix + fi.Name, fullPrefix + us2fs(newName))) return GetLastError(); return S_OK; } @@ -585,15 +1004,33 @@ STDMETHODIMP CFSFolder::Rename(UInt32 index, const wchar_t *newName, IProgress * STDMETHODIMP CFSFolder::Delete(const UInt32 *indices, UInt32 numItems,IProgress *progress) { RINOK(progress->SetTotal(numItems)); + int prevDeletedFileIndex = -1; for (UInt32 i = 0; i < numItems; i++) { - const CDirItem &fi = *_refs[indices[i]]; - const FString fullPath = _path + GetRelPath(fi); - bool result; - if (fi.IsDir()) - result = NDirectory::RemoveDirectoryWithSubItems(fullPath); + // Sleep(200); + UInt32 index = indices[i]; + bool result = true; + /* + if (index >= (UInt32)Files.Size()) + { + const CAltStream &ss = Streams[index - (UInt32)Files.Size()]; + if (prevDeletedFileIndex != ss.Parent) + { + const CDirItem &fi = Files[ss.Parent]; + result = DeleteFileAlways(_path + GetRelPath(fi) + us2fs(ss.Name)); + } + } else - result = NDirectory::DeleteFileAlways(fullPath); + */ + { + const CDirItem &fi = Files[index]; + const FString fullPath = _path + GetRelPath(fi); + prevDeletedFileIndex = index; + if (fi.IsDir()) + result = RemoveDirWithSubItems(fullPath); + else + result = DeleteFileAlways(fullPath); + } if (!result) return GetLastError(); UInt64 completed = i; @@ -605,12 +1042,12 @@ STDMETHODIMP CFSFolder::Delete(const UInt32 *indices, UInt32 numItems,IProgress STDMETHODIMP CFSFolder::SetProperty(UInt32 index, PROPID propID, const PROPVARIANT *value, IProgress * /* progress */) { - if (index >= (UInt32)_refs.Size()) + if (index >= (UInt32)Files.Size()) return E_INVALIDARG; - CDirItem &fi = *_refs[index]; - if (fi.Parent->Parent != 0) + CDirItem &fi = Files[index]; + if (fi.Parent >= 0) return E_NOTIMPL; - switch(propID) + switch (propID) { case kpidComment: { @@ -643,9 +1080,9 @@ STDMETHODIMP CFSFolder::SetProperty(UInt32 index, PROPID propID, STDMETHODIMP CFSFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex) { - if (index >= (UInt32)_refs.Size()) + if (index >= (UInt32)Files.Size()) return E_INVALIDARG; - const CDirItem &fi = *_refs[index]; + const CDirItem &fi = Files[index]; *iconIndex = 0; int iconIndexTemp; if (GetRealIconIndex(_path + GetRelPath(fi), fi.Attrib, iconIndexTemp) != 0) @@ -662,4 +1099,12 @@ STDMETHODIMP CFSFolder::SetFlatMode(Int32 flatMode) return S_OK; } +/* +STDMETHODIMP CFSFolder::SetShowNtfsStreamsMode(Int32 showStreamsMode) +{ + _scanAltStreams = IntToBool(showStreamsMode); + return S_OK; +} +*/ + } diff --git a/CPP/7zip/UI/FileManager/FSFolder.h b/CPP/7zip/UI/FileManager/FSFolder.h old mode 100755 new mode 100644 index 13e9e018..cb0d4ec2 --- a/CPP/7zip/UI/FileManager/FSFolder.h +++ b/CPP/7zip/UI/FileManager/FSFolder.h @@ -3,116 +3,188 @@ #ifndef __FS_FOLDER_H #define __FS_FOLDER_H -#include "Common/MyCom.h" +#include "../../../Common/MyCom.h" +#include "../../../Common/MyBuffer.h" -#include "Windows/FileFind.h" +#include "../../../Windows/FileFind.h" #include "IFolder.h" #include "TextPairs.h" +#include "..\..\Archive\IArchive.h" namespace NFsFolder { class CFSFolder; -struct CFileInfoEx: public NWindows::NFile::NFind::CFileInfo +#define FS_SHOW_LINKS_INFO + +struct CDirItem: public NWindows::NFile::NFind::CFileInfo { #ifndef UNDER_CE - bool CompressedSizeIsDefined; - UInt64 CompressedSize; + UInt64 PackSize; + #endif + + #ifdef FS_SHOW_LINKS_INFO + UInt64 FileIndex; + UInt32 NumLinks; + bool FileInfo_Defined; + bool FileInfo_WasRequested; + #endif + + #ifndef UNDER_CE + bool PackSize_Defined; #endif + + bool FolderStat_Defined; + + #ifndef UNDER_CE + CByteBuffer Reparse; + #endif + + UInt64 NumFolders; + UInt64 NumFiles; + + int Parent; }; -struct CDirItem; +/* +struct CAltStream +{ + UInt64 Size; + UInt64 PackSize; + bool PackSize_Defined; + int Parent; + UString Name; +}; +*/ -struct CDirItem: public CFileInfoEx +struct CFsFolderStat { - CDirItem *Parent; - CObjectVector Files; + UInt64 NumFolders; + UInt64 NumFiles; + UInt64 Size; + IProgress *Progress; + FString Path; - CDirItem(): Parent(0) {} - void Clear() - { - Files.Clear(); - Parent = 0; - } + CFsFolderStat(): NumFolders(0), NumFiles(0), Size(0), Progress(NULL) {} + CFsFolderStat(const FString &path, IProgress *progress = NULL): + NumFolders(0), NumFiles(0), Size(0), Progress(progress), Path(path) {} + + HRESULT Enumerate(); }; class CFSFolder: public IFolderFolder, + public IArchiveGetRawProps, + public IFolderCompare, + #ifdef USE_UNICODE_FSTRING + public IFolderGetItemName, + #endif public IFolderWasChanged, public IFolderOperations, // public IFolderOperationsDeleteToRecycleBin, - public IFolderGetItemFullSize, + public IFolderCalcItemFullSize, public IFolderClone, public IFolderGetSystemIconIndex, public IFolderSetFlatMode, + // public IFolderSetShowNtfsStreamsMode, public CMyUnknownImp { - UInt64 GetSizeOfItem(int anIndex) const; public: MY_QUERYINTERFACE_BEGIN2(IFolderFolder) + MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps) + MY_QUERYINTERFACE_ENTRY(IFolderCompare) + #ifdef USE_UNICODE_FSTRING + MY_QUERYINTERFACE_ENTRY(IFolderGetItemName) + #endif MY_QUERYINTERFACE_ENTRY(IFolderWasChanged) // MY_QUERYINTERFACE_ENTRY(IFolderOperationsDeleteToRecycleBin) MY_QUERYINTERFACE_ENTRY(IFolderOperations) - MY_QUERYINTERFACE_ENTRY(IFolderGetItemFullSize) + MY_QUERYINTERFACE_ENTRY(IFolderCalcItemFullSize) MY_QUERYINTERFACE_ENTRY(IFolderClone) MY_QUERYINTERFACE_ENTRY(IFolderGetSystemIconIndex) MY_QUERYINTERFACE_ENTRY(IFolderSetFlatMode) + // MY_QUERYINTERFACE_ENTRY(IFolderSetShowNtfsStreamsMode) MY_QUERYINTERFACE_END MY_ADDREF_RELEASE INTERFACE_FolderFolder(;) + INTERFACE_IArchiveGetRawProps(;) INTERFACE_FolderOperations(;) + STDMETHOD_(Int32, CompareItems)(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw); + + #ifdef USE_UNICODE_FSTRING + INTERFACE_IFolderGetItemName(;) + #endif STDMETHOD(WasChanged)(Int32 *wasChanged); STDMETHOD(Clone)(IFolderFolder **resultFolder); - STDMETHOD(GetItemFullSize)(UInt32 index, PROPVARIANT *value, IProgress *progress); + STDMETHOD(CalcItemFullSize)(UInt32 index, IProgress *progress); STDMETHOD(SetFlatMode)(Int32 flatMode); + // STDMETHOD(SetShowNtfsStreamsMode)(Int32 showStreamsMode); STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex); private: FString _path; - CDirItem _root; - CRecordVector _refs; - + + CObjectVector Files; + FStringVector Folders; + // CObjectVector Streams; CMyComPtr _parentFolder; bool _commentsAreLoaded; CPairsStorage _comments; + // bool _scanAltStreams; 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(CFSTR name, FString &resultPath); + HRESULT GetItemsFullSize(const UInt32 *indices, UInt32 numItems, CFsFolderStat &stat); + + HRESULT GetItemFullSize(unsigned index, UInt64 &size, IProgress *progress); + void GetAbsPath(const wchar_t *name, FString &absPath); HRESULT BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder); bool LoadComments(); bool SaveComments(); - HRESULT LoadSubItems(CDirItem &dirItem, const FString &path); - void AddRefs(CDirItem &dirItem); + HRESULT LoadSubItems(int dirItem, const FString &path); + + #ifdef FS_SHOW_LINKS_INFO + bool ReadFileInfo(CDirItem &di); + #endif + public: HRESULT Init(const FString &path, IFolderFolder *parentFolder); #ifdef UNDER_CE HRESULT InitToRoot() { return Init(FTEXT("\\"), NULL); } #endif - CFSFolder() : _flatMode(false) {} + CFSFolder() : _flatMode(false) + // , _scanAltStreams(false) + {} - FString GetPrefix(const CDirItem &item) const; + void GetFullPath(const CDirItem &item, FString &path) const + { + // FString prefix; + // GetPrefix(item, prefix); + path = _path; + if (item.Parent >= 0) + path += Folders[item.Parent]; + path += item.Name; + } + + // void GetPrefix(const CDirItem &item, FString &prefix) const; FString GetRelPath(const CDirItem &item) const; - FString GetRelPath(UInt32 index) const { return GetRelPath(*_refs[index]); } void Clear() { - _root.Clear(); - _refs.Clear(); + Files.Clear(); + Folders.Clear(); + // Streams.Clear(); } }; diff --git a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp old mode 100755 new mode 100644 index c31498c7..0ef3c724 --- a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp +++ b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp @@ -4,11 +4,14 @@ #include -#include "Common/StringConvert.h" +#include "../../../Common/Defs.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/Wildcard.h" -#include "Windows/DLL.h" -#include "Windows/Error.h" -#include "Windows/FileDir.h" +#include "../../../Windows/DLL.h" +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileName.h" #include "../../Common/FilePathAutoRename.h" @@ -16,6 +19,8 @@ using namespace NWindows; using namespace NFile; +using namespace NDir; +using namespace NName; using namespace NFind; #ifndef _UNICODE @@ -102,7 +107,7 @@ typedef BOOL (WINAPI * CopyFileExPointerW)( IN DWORD dwCopyFlags ); -static bool MyCopyFile(CFSTR existingFile, CFSTR newFile, IProgress *progress, UInt64 &completedSize) +static bool FsCopyFile(CFSTR oldFile, CFSTR newFile, IProgress *progress, UInt64 &completedSize) { CProgressInfo progressInfo; progressInfo.Progress = progress; @@ -121,18 +126,25 @@ static bool MyCopyFile(CFSTR existingFile, CFSTR newFile, IProgress *progress, U ; CopyFileExPointerW copyFunctionW = (CopyFileExPointerW) My_GetProcAddress(::GetModuleHandleW(k_DllName), "CopyFileExW"); - if (copyFunctionW == 0) - return BOOLToBool(::CopyFileW(fs2us(existingFile), fs2us(newFile), TRUE)); - if (copyFunctionW(fs2us(existingFile), fs2us(newFile), CopyProgressRoutine, - &progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS)) - return true; + + IF_USE_MAIN_PATH_2(oldFile, newFile) + { + if (copyFunctionW == 0) + return BOOLToBool(::CopyFileW(fs2us(oldFile), fs2us(newFile), TRUE)); + if (copyFunctionW(fs2us(oldFile), fs2us(newFile), CopyProgressRoutine, + &progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS)) + 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; + if (USE_SUPER_PATH_2) + { + UString longPathExisting, longPathNew; + if (!GetSuperPaths(oldFile, newFile, longPathExisting, longPathNew, USE_MAIN_PATH_2)) + return false; + if (copyFunctionW(longPathExisting, longPathNew, CopyProgressRoutine, + &progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS)) + return true; + } #endif return false; } @@ -144,13 +156,13 @@ static bool MyCopyFile(CFSTR existingFile, CFSTR newFile, IProgress *progress, U "CopyFileExA"); if (copyFunction != 0) { - if (copyFunction(fs2fas(existingFile), fs2fas(newFile), + if (copyFunction(fs2fas(oldFile), fs2fas(newFile), CopyProgressRoutine,&progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS)) return true; if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return false; } - return BOOLToBool(::CopyFile(fs2fas(existingFile), fs2fas(newFile), TRUE)); + return BOOLToBool(::CopyFile(fs2fas(oldFile), fs2fas(newFile), TRUE)); } #endif } @@ -163,7 +175,15 @@ typedef BOOL (WINAPI * MoveFileWithProgressPointer)( IN DWORD dwFlags ); -static bool MyMoveFile(CFSTR existingFile, CFSTR newFile, IProgress *progress, UInt64 &completedSize) +#ifdef UNDER_CE +#define NON_CE_VAR(_v_) +#else +#define NON_CE_VAR(_v_) _v_ +#endif + +static bool FsMoveFile(CFSTR oldFile, CFSTR newFile, + IProgress * NON_CE_VAR(progress), + UInt64 & NON_CE_VAR(completedSize)) { #ifndef UNDER_CE // if (IsItWindows2000orHigher()) @@ -177,28 +197,30 @@ static bool MyMoveFile(CFSTR existingFile, CFSTR newFile, IProgress *progress, U "MoveFileWithProgressW"); if (moveFunction != 0) { - if (moveFunction( - fs2us(existingFile), fs2us(newFile), CopyProgressRoutine, - &progressInfo, MOVEFILE_COPY_ALLOWED)) - return true; - if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + IF_USE_MAIN_PATH_2(oldFile, newFile) + { + if (moveFunction(fs2us(oldFile), fs2us(newFile), CopyProgressRoutine, + &progressInfo, MOVEFILE_COPY_ALLOWED)) + return true; + } + #ifdef WIN_LONG_PATH + if ((!(USE_MAIN_PATH_2) || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) && USE_SUPER_PATH_2) { - #ifdef WIN_LONG_PATH UString longPathExisting, longPathNew; - if (!NDirectory::GetLongPaths(existingFile, newFile, longPathExisting, longPathNew)) + if (!GetSuperPaths(oldFile, newFile, longPathExisting, longPathNew, USE_MAIN_PATH_2)) return false; if (moveFunction(longPathExisting, longPathNew, CopyProgressRoutine, &progressInfo, MOVEFILE_COPY_ALLOWED)) return true; - #endif - if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) - return false; } + #endif + if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return false; } // } // else #endif - return NDirectory::MyMoveFile(existingFile, newFile); + return MyMoveFile(oldFile, newFile); } static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback, @@ -213,7 +235,7 @@ static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback, return SendMessageError(callback, MultiByteToUnicodeString(message), fileName); } -static HRESULT MyCopyFile( +static HRESULT FsCopyFile( const FString &srcPath, const CFileInfo &srcFileInfo, const FString &destPathSpec, @@ -221,7 +243,7 @@ static HRESULT MyCopyFile( UInt64 &completedSize) { FString destPath = destPathSpec; - if (destPath.CompareNoCase(srcPath) == 0) + if (CompareFileNames(destPath, srcPath) == 0) { RINOK(SendMessageError(callback, "can not copy file onto itself: ", destPath)); return E_ABORT; @@ -240,9 +262,9 @@ static HRESULT MyCopyFile( { FString destPathNew = us2fs(destPathResult); RINOK(callback->SetCurrentFilePath(fs2us(srcPath))); - if (!MyCopyFile(srcPath, destPathNew, callback, completedSize)) + if (!FsCopyFile(srcPath, destPathNew, callback, completedSize)) { - RINOK(SendMessageError(callback, NError::MyFormatMessageW(GetLastError()) + L" : ", destPathNew)); + RINOK(SendMessageError(callback, NError::MyFormatMessage(GetLastError()) + L" : ", destPathNew)); return E_ABORT; } } @@ -255,32 +277,37 @@ static FString CombinePath(const FString &folderPath, const FString &fileName) return folderPath + FCHAR_PATH_SEPARATOR + fileName; } +static bool IsDestChild(const FString &src, const FString &dest) +{ + unsigned len = src.Len(); + if (dest.Len() < len) + return false; + if (dest.Len() != len && dest[len] != FCHAR_PATH_SEPARATOR) + return false; + return CompareFileNames(dest.Left(len), src) == 0; +} + static HRESULT CopyFolder( const FString &srcPath, - const FString &destPathSpec, + const FString &destPath, IFolderOperationsExtractCallback *callback, UInt64 &completedSize) { RINOK(callback->SetCompleted(&completedSize)); - const FString destPath = destPathSpec; - int len = srcPath.Length(); - if (destPath.Length() >= len && srcPath.CompareNoCase(destPath.Left(len)) == 0) + if (IsDestChild(srcPath, destPath)) { - if (destPath.Length() == len || destPath[len] == FCHAR_PATH_SEPARATOR) - { - RINOK(SendMessageError(callback, "can not copy folder onto itself: ", destPath)); - return E_ABORT; - } + RINOK(SendMessageError(callback, "can not copy folder onto itself: ", destPath)); + return E_ABORT; } - if (!NDirectory::CreateComplexDirectory(destPath)) + if (!CreateComplexDir(destPath)) { RINOK(SendMessageError(callback, "can not create folder: ", destPath)); return E_ABORT; } CEnumerator enumerator(CombinePath(srcPath, FSTRING_ANY_MASK)); - CFileInfoEx fi; + CDirItem fi; while (enumerator.Next(fi)) { const FString srcPath2 = CombinePath(srcPath, fi.Name); @@ -291,61 +318,7 @@ static HRESULT CopyFolder( } 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.Back() != 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]]; - FString destPath2 = us2fs(destPath); - if (!directName) - destPath2 += fi.Name; - FString srcPath = _path + GetPrefix(fi) + fi.Name; - if (fi.IsDir()) - { - RINOK(CopyFolder(srcPath, destPath2, callback, completedSize)); - } - else - { - RINOK(MyCopyFile(srcPath, fi, destPath2, callback, completedSize)); + RINOK(FsCopyFile(srcPath2, fi, destPath2, callback, completedSize)); } } return S_OK; @@ -354,14 +327,14 @@ STDMETHODIMP CFSFolder::CopyTo(const UInt32 *indices, UInt32 numItems, ///////////////////////////////////////////////// // Move Operations -static HRESULT MyMoveFile( +static HRESULT FsMoveFile( const FString &srcPath, const CFileInfo &srcFileInfo, const FString &destPath, IFolderOperationsExtractCallback *callback, UInt64 &completedSize) { - if (destPath.CompareNoCase(srcPath) == 0) + if (CompareFileNames(destPath, srcPath) == 0) { RINOK(SendMessageError(callback, "can not move file onto itself: ", srcPath)); return E_ABORT; @@ -380,7 +353,7 @@ static HRESULT MyMoveFile( { FString destPathNew = us2fs(destPathResult); RINOK(callback->SetCurrentFilePath(fs2us(srcPath))); - if (!MyMoveFile(srcPath, destPathNew, callback, completedSize)) + if (!FsMoveFile(srcPath, destPathNew, callback, completedSize)) { RINOK(SendMessageError(callback, "can not move to file: ", destPathNew)); } @@ -390,48 +363,44 @@ static HRESULT MyMoveFile( return S_OK; } -static HRESULT MyMoveFolder( +static HRESULT FsMoveFolder( const FString &srcPath, const FString &destPath, IFolderOperationsExtractCallback *callback, UInt64 &completedSize) { - int len = srcPath.Length(); - if (destPath.Length() >= len && srcPath.CompareNoCase(destPath.Left(len)) == 0) + if (IsDestChild(srcPath, destPath)) { - if (destPath.Length() == len || destPath[len] == FCHAR_PATH_SEPARATOR) - { - RINOK(SendMessageError(callback, "can not move folder onto itself: ", destPath)); - return E_ABORT; - } + RINOK(SendMessageError(callback, "can not move folder onto itself: ", destPath)); + return E_ABORT; } - if (MyMoveFile(srcPath, destPath, callback, completedSize)) + if (FsMoveFile(srcPath, destPath, callback, completedSize)) return S_OK; - if (!NDirectory::CreateComplexDirectory(destPath)) + if (!CreateComplexDir(destPath)) { RINOK(SendMessageError(callback, "can not create folder: ", destPath)); return E_ABORT; } { CEnumerator enumerator(CombinePath(srcPath, FSTRING_ANY_MASK)); - CFileInfoEx fi; + CDirItem fi; while (enumerator.Next(fi)) { const FString srcPath2 = CombinePath(srcPath, fi.Name); const FString destPath2 = CombinePath(destPath, fi.Name); if (fi.IsDir()) { - RINOK(MyMoveFolder(srcPath2, destPath2, callback, completedSize)); + RINOK(FsMoveFolder(srcPath2, destPath2, callback, completedSize)); } else { - RINOK(MyMoveFile(srcPath2, fi, destPath2, callback, completedSize)); + RINOK(FsMoveFile(srcPath2, fi, destPath2, callback, completedSize)); } } } - if (!NDirectory::MyRemoveDirectory(srcPath)) + if (!RemoveDir(srcPath)) { RINOK(SendMessageError(callback, "can not remove folder: ", srcPath)); return E_ABORT; @@ -439,19 +408,18 @@ static HRESULT MyMoveFolder( return S_OK; } -STDMETHODIMP CFSFolder::MoveTo( - const UInt32 *indices, - UInt32 numItems, - const wchar_t *path, - IFolderOperationsExtractCallback *callback) +STDMETHODIMP CFSFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 numItems, + Int32 /* includeAltStreams */, Int32 /* replaceAltStreamColon */, + 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)); + CFsFolderStat stat; + stat.Progress = callback; + RINOK(GetItemsFullSize(indices, numItems, stat)); + RINOK(callback->SetTotal(stat.Size)); + RINOK(callback->SetNumFiles(stat.NumFiles)); FString destPath = us2fs(path); if (destPath.IsEmpty()) @@ -463,34 +431,55 @@ STDMETHODIMP CFSFolder::MoveTo( return E_INVALIDARG; } else - if (!NDirectory::CreateComplexDirectory(destPath)) + { + // Does CreateComplexDir work in network ? + if (!CreateComplexDir(destPath)) { RINOK(SendMessageError(callback, "can not create folder: ", destPath)); return E_ABORT; } + } UInt64 completedSize = 0; RINOK(callback->SetCompleted(&completedSize)); for (UInt32 i = 0; i < numItems; i++) { - const CDirItem &fi = *_refs[indices[i]]; + UInt32 index = indices[i]; + if (index >= (UInt32)Files.Size()) + continue; + const CDirItem &fi = Files[index]; FString destPath2 = destPath; if (!directName) destPath2 += fi.Name; - FString srcPath = _path + GetPrefix(fi) + fi.Name; + FString srcPath; + GetFullPath(fi, srcPath); if (fi.IsDir()) { - RINOK(MyMoveFolder(srcPath, destPath2, callback, completedSize)); + if (moveMode) + { + RINOK(FsMoveFolder(srcPath, destPath2, callback, completedSize)); + } + else + { + RINOK(CopyFolder(srcPath, destPath2, callback, completedSize)); + } } else { - RINOK(MyMoveFile(srcPath, fi, destPath2, callback, completedSize)); + if (moveMode) + { + RINOK(FsMoveFile(srcPath, fi, destPath2, callback, completedSize)); + } + else + { + RINOK(FsCopyFile(srcPath, fi, destPath2, callback, completedSize)); + } } } return S_OK; } -STDMETHODIMP CFSFolder::CopyFrom(const wchar_t * /* fromFolderPath */, +STDMETHODIMP CFSFolder::CopyFrom(Int32 /* moveMode */, const wchar_t * /* fromFolderPath */, const wchar_t ** /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */) { /* diff --git a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp old mode 100755 new mode 100644 index d29ac44c..2d3b1d92 --- a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp +++ b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp @@ -4,8 +4,8 @@ #include "resource.h" -#include "Windows/FileName.h" -#include "Windows/Thread.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/Thread.h" #include "../Agent/Agent.h" @@ -69,9 +69,9 @@ static void SplitNameToPureNameAndExtension(const FString &fullName, } else { - pureName = fullName.Left(index); + pureName.SetFrom(fullName, index); extensionDelimiter = kExtensionDelimiter; - extension = fullName.Mid(index + 1); + extension = fullName.Ptr(index + 1); } } @@ -94,8 +94,8 @@ HRESULT OpenFileFolderPlugin( FString fileName; if (slashPos >= 0) { - dirPrefix = path.Left(slashPos + 1); - fileName = path.Mid(slashPos + 1); + dirPrefix.SetFrom(path, slashPos + 1); + fileName = path.Ptr(slashPos + 1); } else fileName = path; @@ -122,7 +122,7 @@ HRESULT OpenFileFolderPlugin( } */ - for (int i = 0; i < plugins.Size(); i++) + FOR_VECTOR (i, plugins) { const CPluginInfo &plugin = plugins[i]; if (!plugin.ClassIDDefined) @@ -151,10 +151,10 @@ HRESULT OpenFileFolderPlugin( t.Path = fs2us(path); t.ArcFormat = arcFormat; - UString progressTitle = LangString(IDS_OPENNING, 0x03020283); + UString progressTitle = LangString(IDS_OPENNING); t.OpenCallbackSpec->ProgressDialog.MainWindow = parentWindow; - t.OpenCallbackSpec->ProgressDialog.MainTitle = LangString(IDS_APP_TITLE, 0x03000000); - t.OpenCallbackSpec->ProgressDialog.MainAddTitle = progressTitle + UString(L" "); + t.OpenCallbackSpec->ProgressDialog.MainTitle = L"7-Zip"; // LangString(IDS_APP_TITLE); + t.OpenCallbackSpec->ProgressDialog.MainAddTitle = progressTitle + L' '; t.OpenCallbackSpec->ProgressDialog.WaitMode = true; { @@ -166,11 +166,11 @@ HRESULT OpenFileFolderPlugin( if (t.Result == E_ABORT) return t.Result; + encrypted = t.OpenCallbackSpec->PasswordIsDefined; if (t.Result == S_OK) { // if (openCallbackSpec->PasswordWasAsked) { - encrypted = t.OpenCallbackSpec->PasswordIsDefined; password = t.OpenCallbackSpec->Password; } *module = library.Detach(); diff --git a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.h b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/FilePlugins.cpp b/CPP/7zip/UI/FileManager/FilePlugins.cpp old mode 100755 new mode 100644 index b81850fd..556c54fd --- a/CPP/7zip/UI/FileManager/FilePlugins.cpp +++ b/CPP/7zip/UI/FileManager/FilePlugins.cpp @@ -10,8 +10,8 @@ int CExtDatabase::FindExt(const UString &ext) { - for (int i = 0; i < Exts.Size(); i++) - if (Exts[i].Ext.CompareNoCase(ext) == 0) + FOR_VECTOR (i, Exts) + if (Exts[i].Ext.IsEqualToNoCase(ext)) return i; return -1; } @@ -19,7 +19,7 @@ int CExtDatabase::FindExt(const UString &ext) void CExtDatabase::Read() { ReadFileFolderPluginInfoList(Plugins); - for (int pluginIndex = 0; pluginIndex < Plugins.Size(); pluginIndex++) + FOR_VECTOR (pluginIndex, Plugins) { const CPluginInfo &plugin = Plugins[pluginIndex]; @@ -35,7 +35,7 @@ void CExtDatabase::Read() return; UStringVector exts; SplitString((const wchar_t *)extBSTR, exts); - for (int i = 0; i < exts.Size(); i++) + FOR_VECTOR (i, exts) { const UString &ext = exts[i]; #ifdef UNDER_CE diff --git a/CPP/7zip/UI/FileManager/FilePlugins.h b/CPP/7zip/UI/FileManager/FilePlugins.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/FoldersPage.cpp b/CPP/7zip/UI/FileManager/FoldersPage.cpp old mode 100755 new mode 100644 index b7366fed..8c0b5a0c --- a/CPP/7zip/UI/FileManager/FoldersPage.cpp +++ b/CPP/7zip/UI/FileManager/FoldersPage.cpp @@ -11,36 +11,36 @@ using namespace NWindows; -static CIDLangPair kIDLangPairs[] = +static const UInt32 kLangIDs[] = { - { 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 } + IDT_FOLDERS_WORKING_FOLDER, + IDR_FOLDERS_WORK_SYSTEM, + IDR_FOLDERS_WORK_CURRENT, + IDR_FOLDERS_WORK_SPECIFIED, + IDX_FOLDERS_WORK_FOR_REMOVABLE }; static const int kWorkModeButtons[] = { - IDC_FOLDERS_WORK_RADIO_SYSTEM, - IDC_FOLDERS_WORK_RADIO_CURRENT, - IDC_FOLDERS_WORK_RADIO_SPECIFIED + IDR_FOLDERS_WORK_SYSTEM, + IDR_FOLDERS_WORK_CURRENT, + IDR_FOLDERS_WORK_SPECIFIED }; -static const int kNumWorkModeButtons = sizeof(kWorkModeButtons) / sizeof(kWorkModeButtons[0]); +static const int kNumWorkModeButtons = ARRAY_SIZE(kWorkModeButtons); bool CFoldersPage::OnInit() { - LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); m_WorkDirInfo.Load(); - CheckButton(IDC_FOLDERS_WORK_CHECK_FOR_REMOVABLE, m_WorkDirInfo.ForRemovableOnly); + CheckButton(IDX_FOLDERS_WORK_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.Init(*this, IDE_FOLDERS_WORK_PATH); + m_ButtonSetWorkPath.Init(*this, IDB_FOLDERS_WORK_PATH); m_WorkPath.SetText(fs2us(m_WorkDirInfo.Path)); @@ -69,7 +69,7 @@ void CFoldersPage::GetWorkDir(NWorkDir::CInfo &workDirInfo) UString s; m_WorkPath.GetText(s); workDirInfo.Path = us2fs(s); - workDirInfo.ForRemovableOnly = IsButtonCheckedBool(IDC_FOLDERS_WORK_CHECK_FOR_REMOVABLE); + workDirInfo.ForRemovableOnly = IsButtonCheckedBool(IDX_FOLDERS_WORK_FOR_REMOVABLE); workDirInfo.Mode = NWorkDir::NMode::EEnum(GetWorkMode()); } @@ -106,10 +106,10 @@ bool CFoldersPage::OnButtonClicked(int buttonID, HWND buttonHWND) } switch(buttonID) { - case IDC_FOLDERS_WORK_BUTTON_PATH: + case IDB_FOLDERS_WORK_PATH: OnFoldersWorkButtonPath(); break; - case IDC_FOLDERS_WORK_CHECK_FOR_REMOVABLE: + case IDX_FOLDERS_WORK_FOR_REMOVABLE: break; default: return CPropertyPage::OnButtonClicked(buttonID, buttonHWND); @@ -120,7 +120,7 @@ bool CFoldersPage::OnButtonClicked(int buttonID, HWND buttonHWND) bool CFoldersPage::OnCommand(int code, int itemID, LPARAM lParam) { - if (code == EN_CHANGE && itemID == IDC_FOLDERS_WORK_EDIT_PATH) + if (code == EN_CHANGE && itemID == IDE_FOLDERS_WORK_PATH) { ModifiedEvent(); return true; @@ -132,9 +132,9 @@ void CFoldersPage::OnFoldersWorkButtonPath() { UString currentPath; m_WorkPath.GetText(currentPath); - UString title = LangString(IDS_FOLDERS_SET_WORK_PATH_TITLE, 0x01000281); + UString title = LangString(IDS_FOLDERS_SET_WORK_PATH_TITLE); UString resultPath; - if (MyBrowseForFolder(HWND(*this), title, currentPath, resultPath)) + if (MyBrowseForFolder(*this, title, currentPath, resultPath)) m_WorkPath.SetText(resultPath); } diff --git a/CPP/7zip/UI/FileManager/FoldersPage.h b/CPP/7zip/UI/FileManager/FoldersPage.h old mode 100755 new mode 100644 index d8456a40..7aaa80f7 --- a/CPP/7zip/UI/FileManager/FoldersPage.h +++ b/CPP/7zip/UI/FileManager/FoldersPage.h @@ -3,7 +3,7 @@ #ifndef __FOLDERS_PAGE_H #define __FOLDERS_PAGE_H -#include "Windows/Control/PropertyPage.h" +#include "../../../Windows/Control/PropertyPage.h" #include "../Common/ZipRegistry.h" diff --git a/CPP/7zip/UI/FileManager/FoldersPage.rc b/CPP/7zip/UI/FileManager/FoldersPage.rc old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/FoldersPage2.rc b/CPP/7zip/UI/FileManager/FoldersPage2.rc old mode 100755 new mode 100644 index 0b73ec9f..9b9276ef --- a/CPP/7zip/UI/FileManager/FoldersPage2.rc +++ b/CPP/7zip/UI/FileManager/FoldersPage2.rc @@ -1,16 +1,16 @@ CAPTION "Folders" BEGIN - // GROUPBOX "&Working folder", IDC_FOLDERS_STATIC_WORKING_FOLDER, m, m, xc, 98 + // GROUPBOX "&Working folder", IDT_FOLDERS_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, + LTEXT "&Working folder", IDT_FOLDERS_WORKING_FOLDER, m, m, xc, 8 + CONTROL "&System temp folder", IDR_FOLDERS_WORK_SYSTEM, "Button", BS_AUTORADIOBUTTON | WS_GROUP, m, 20, xc, 10 - CONTROL "&Current", IDC_FOLDERS_WORK_RADIO_CURRENT, "Button", BS_AUTORADIOBUTTON, + CONTROL "&Current", IDR_FOLDERS_WORK_CURRENT, "Button", BS_AUTORADIOBUTTON, m, 34, xc, 10 - CONTROL "Specified:", IDC_FOLDERS_WORK_RADIO_SPECIFIED, "Button", BS_AUTORADIOBUTTON, + CONTROL "Specified:", IDR_FOLDERS_WORK_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, + EDITTEXT IDE_FOLDERS_WORK_PATH, m + m, 62, xc - m - m - bxsDots, 14, ES_AUTOHSCROLL + PUSHBUTTON "...", IDB_FOLDERS_WORK_PATH, xs - m - bxsDots, 61, bxsDots, bys + CONTROL "Use for removable drives only", IDX_FOLDERS_WORK_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 old mode 100755 new mode 100644 index 896f197a..ba9ab73e --- a/CPP/7zip/UI/FileManager/FoldersPageRes.h +++ b/CPP/7zip/UI/FileManager/FoldersPageRes.h @@ -1,13 +1,12 @@ -#define IDD_FOLDERS 571 -#define IDD_FOLDERS_2 671 +#define IDD_FOLDERS 2400 +#define IDD_FOLDERS_2 12400 -#define IDS_FOLDERS_SET_WORK_PATH_TITLE 877 +#define IDT_FOLDERS_WORKING_FOLDER 2401 +#define IDR_FOLDERS_WORK_SYSTEM 2402 +#define IDR_FOLDERS_WORK_CURRENT 2403 +#define IDR_FOLDERS_WORK_SPECIFIED 2404 +#define IDX_FOLDERS_WORK_FOR_REMOVABLE 2405 +#define IDS_FOLDERS_SET_WORK_PATH_TITLE 2406 -#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 +#define IDE_FOLDERS_WORK_PATH 100 +#define IDB_FOLDERS_WORK_PATH 101 diff --git a/CPP/7zip/UI/FileManager/FormatUtils.cpp b/CPP/7zip/UI/FileManager/FormatUtils.cpp old mode 100755 new mode 100644 index 98bb043e..2143c3f1 --- a/CPP/7zip/UI/FileManager/FormatUtils.cpp +++ b/CPP/7zip/UI/FileManager/FormatUtils.cpp @@ -2,13 +2,11 @@ #include "StdAfx.h" +#include "../../../Common/IntToString.h" + #include "FormatUtils.h" -#include "Common/IntToString.h" -#include "Windows/ResourceString.h" -#ifdef LANG #include "LangUtils.h" -#endif UString NumberToString(UInt64 number) { @@ -24,17 +22,7 @@ UString MyFormatNew(const UString &format, const UString &argument) return result; } -UString MyFormatNew(UINT resourceID, - #ifdef LANG - UInt32 langID, - #endif - const UString &argument) +UString MyFormatNew(UINT resourceID, const UString &argument) { - return MyFormatNew( - #ifdef LANG - LangString(resourceID, langID), - #else - NWindows::MyLoadStringW(resourceID), - #endif - argument); + return MyFormatNew(LangString(resourceID), argument); } diff --git a/CPP/7zip/UI/FileManager/FormatUtils.h b/CPP/7zip/UI/FileManager/FormatUtils.h old mode 100755 new mode 100644 index 70a44434..993e8033 --- a/CPP/7zip/UI/FileManager/FormatUtils.h +++ b/CPP/7zip/UI/FileManager/FormatUtils.h @@ -1,18 +1,14 @@ // FormatUtils.h -#ifndef __FORMATUTILS_H -#define __FORMATUTILS_H +#ifndef __FORMAT_UTILS_H +#define __FORMAT_UTILS_H -#include "Common/Types.h" -#include "Common/MyString.h" +#include "../../../Common/MyTypes.h" +#include "../../../Common/MyString.h" UString NumberToString(UInt64 number); UString MyFormatNew(const UString &format, const UString &argument); -UString MyFormatNew(UINT resourceID, - #ifdef LANG - UInt32 langID, - #endif - const UString &argument); +UString MyFormatNew(UINT resourceID, const UString &argument); #endif diff --git a/CPP/7zip/UI/FileManager/HelpUtils.cpp b/CPP/7zip/UI/FileManager/HelpUtils.cpp old mode 100755 new mode 100644 index 3128cb28..fb6fcdd0 --- a/CPP/7zip/UI/FileManager/HelpUtils.cpp +++ b/CPP/7zip/UI/FileManager/HelpUtils.cpp @@ -4,8 +4,10 @@ #include -#include "Common/StringConvert.h" -#include "Windows/DLL.h" +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/DLL.h" + #include "HelpUtils.h" static LPCWSTR kHelpFileName = L"7-zip.chm::/"; diff --git a/CPP/7zip/UI/FileManager/HelpUtils.h b/CPP/7zip/UI/FileManager/HelpUtils.h old mode 100755 new mode 100644 index 2a7b85af..52b1418a --- a/CPP/7zip/UI/FileManager/HelpUtils.h +++ b/CPP/7zip/UI/FileManager/HelpUtils.h @@ -1,9 +1,9 @@ // HelpUtils.h -#ifndef __HELPUTILS_H -#define __HELPUTILS_H +#ifndef __HELP_UTILS_H +#define __HELP_UTILS_H -#include "Common/MyString.h" +#include "../../../Common/MyString.h" void ShowHelpWindow(HWND hwnd, LPCWSTR topicFile); diff --git a/CPP/7zip/UI/FileManager/IFolder.h b/CPP/7zip/UI/FileManager/IFolder.h old mode 100755 new mode 100644 index d6cce88f..60991a71 --- a/CPP/7zip/UI/FileManager/IFolder.h +++ b/CPP/7zip/UI/FileManager/IFolder.h @@ -63,16 +63,15 @@ FOLDER_INTERFACE_SUB(IFolderOperationsExtractCallback, IProgress, 0x0B) 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, \ + STDMETHOD(CopyTo)(Int32 moveMode, const UInt32 *indices, UInt32 numItems, \ + Int32 includeAltStreams, Int32 replaceAltStreamCharsMode, \ 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, \ + STDMETHOD(CopyFrom)(Int32 moveMode, 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; \ STDMETHOD(CopyFromFile)(UInt32 index, const wchar_t *fullFilePath, IProgress *progress) x; \ -FOLDER_INTERFACE(IFolderOperations, 0x12) +FOLDER_INTERFACE(IFolderOperations, 0x13) { INTERFACE_FolderOperations(PURE) }; @@ -94,6 +93,11 @@ FOLDER_INTERFACE(IFolderGetItemFullSize, 0x08) STDMETHOD(GetItemFullSize)(UInt32 index, PROPVARIANT *value, IProgress *progress) PURE; }; +FOLDER_INTERFACE(IFolderCalcItemFullSize, 0x14) +{ + STDMETHOD(CalcItemFullSize)(UInt32 index, IProgress *progress) PURE; +}; + FOLDER_INTERFACE(IFolderClone, 0x09) { STDMETHOD(Clone)(IFolderFolder **resultFolder) PURE; @@ -104,6 +108,13 @@ FOLDER_INTERFACE(IFolderSetFlatMode, 0x0A) STDMETHOD(SetFlatMode)(Int32 flatMode) PURE; }; +/* +FOLDER_INTERFACE(IFolderSetShowNtfsStreamsMode, 0xFA) +{ + STDMETHOD(SetShowNtfsStreamsMode)(Int32 showStreamsMode) PURE; +}; +*/ + #define INTERFACE_FolderProperties(x) \ STDMETHOD(GetNumberOfFolderProperties)(UInt32 *numProperties) x; \ STDMETHOD(GetFolderPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \ @@ -132,6 +143,21 @@ FOLDER_INTERFACE(IGetFolderArcProps, 0x11) STDMETHOD(GetFolderArcProps)(IFolderArcProps **object) PURE; }; +FOLDER_INTERFACE(IFolderCompare, 0x15) +{ + STDMETHOD_(Int32, CompareItems)(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw) PURE; +}; + +#define INTERFACE_IFolderGetItemName(x) \ + STDMETHOD(GetItemName)(UInt32 index, const wchar_t **name, unsigned *len) x; \ + STDMETHOD(GetItemPrefix)(UInt32 index, const wchar_t **name, unsigned *len) x; \ + STDMETHOD_(UInt64, GetItemSize)(UInt32 index) x; \ + +FOLDER_INTERFACE(IFolderGetItemName, 0x16) +{ + INTERFACE_IFolderGetItemName(PURE) +}; + #define FOLDER_MANAGER_INTERFACE(i, x) DECL_INTERFACE(i, 9, x) #define INTERFACE_IFolderManager(x) \ @@ -147,16 +173,31 @@ 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]; \ + { if (index >= ARRAY_SIZE(k)) return E_INVALIDARG; \ + const CMy_STATPROPSTG_2 &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; } \ + { *numProperties = ARRAY_SIZE(kProps); return S_OK; } \ + STDMETHODIMP c::GetPropertyInfo IMP_IFolderFolder_GetProp(kProps) +*/ + +#define IMP_IFolderFolder_GetProp(k) \ + (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ + { if (index >= ARRAY_SIZE(k)) return E_INVALIDARG; \ + *propID = k[index]; *varType = k7z_PROPID_To_VARTYPE[(unsigned)*propID]; *name = 0; return S_OK; } \ + +#define IMP_IFolderFolder_Props(c) \ + STDMETHODIMP c::GetNumberOfProperties(UInt32 *numProperties) \ + { *numProperties = ARRAY_SIZE(kProps); return S_OK; } \ STDMETHODIMP c::GetPropertyInfo IMP_IFolderFolder_GetProp(kProps) + +int CompareFileNames_ForFolderList(const wchar_t *s1, const wchar_t *s2); +// int CompareFileNames_ForFolderList(const FChar *s1, const FChar *s2); + #endif diff --git a/CPP/7zip/UI/FileManager/Info.bmp b/CPP/7zip/UI/FileManager/Info.bmp old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/Info2.bmp b/CPP/7zip/UI/FileManager/Info2.bmp old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/LangPage.cpp b/CPP/7zip/UI/FileManager/LangPage.cpp old mode 100755 new mode 100644 index 85829368..54253295 --- a/CPP/7zip/UI/FileManager/LangPage.cpp +++ b/CPP/7zip/UI/FileManager/LangPage.cpp @@ -2,9 +2,10 @@ #include "StdAfx.h" -#include "Common/StringConvert.h" +#include "../../../Common/Lang.h" -#include "Windows/ResourceString.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/ResourceString.h" #include "HelpUtils.h" #include "LangPage.h" @@ -12,55 +13,85 @@ #include "LangUtils.h" #include "RegistryUtils.h" -static CIDLangPair kIDLangPairs[] = +using namespace NWindows; + +static const UInt32 kLangIDs[] = { - { IDC_LANG_STATIC_LANG, 0x01000401} + IDT_LANG_LANG }; static LPCWSTR kLangTopic = L"fm/options.htm#language"; -static UString NativeLangString(const UString &s) +static void NativeLangString(UString &dest, const wchar_t *s) { - return L" (" + s + L')'; + dest += L" ("; + dest += s; + dest += L')'; } +bool LangOpen(CLang &lang, CFSTR fileName); + bool CLangPage::OnInit() { - LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); - _langCombo.Attach(GetItem(IDC_LANG_COMBO_LANG)); + _langCombo.Attach(GetItem(IDC_LANG_LANG)); - UString s = NWindows::MyLoadStringW(IDS_LANG_ENGLISH) + - NativeLangString(NWindows::MyLoadStringW(IDS_LANG_NATIVE)); - int index = (int)_langCombo.AddString(s); + UString temp = MyLoadString(IDS_LANG_ENGLISH); + NativeLangString(temp, MyLoadString(IDS_LANG_NATIVE)); + int index = (int)_langCombo.AddString(temp); _langCombo.SetItemData(index, _paths.Size()); _paths.Add(L"-"); _langCombo.SetCurSel(0); - CObjectVector langs; - LoadLangs(langs); - for (int i = 0; i < langs.Size(); i++) + const FString dirPrefix = GetLangDirPrefix(); + NFile::NFind::CEnumerator enumerator(dirPrefix + FTEXT("*.txt")); + NFile::NFind::CFileInfo fi; + CLang lang; + UString error; + + while (enumerator.Next(fi)) { - 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); + if (fi.IsDir()) + continue; + const int kExtSize = 4; + if (fi.Name.Len() < kExtSize) + continue; + unsigned pos = fi.Name.Len() - kExtSize; + if (!StringsAreEqualNoCase_Ascii(fi.Name.Ptr(pos), ".txt")) + continue; + + if (!LangOpen(lang, dirPrefix + fi.Name)) + { + if (!error.IsEmpty()) + error += L' '; + error += fs2us(fi.Name); + continue; + } + + const UString shortName = fs2us(fi.Name.Left(pos)); + UString s = shortName; + const wchar_t *eng = lang.Get(IDS_LANG_ENGLISH); + if (eng) + s = eng; + const wchar_t *native = lang.Get(IDS_LANG_NATIVE); + if (native) + NativeLangString(s, native); + index = (int)_langCombo.AddString(s); _langCombo.SetItemData(index, _paths.Size()); - _paths.Add(lang.ShortName); - if (g_LangID.CompareNoCase(lang.ShortName) == 0) + _paths.Add(shortName); + if (g_LangID.IsEqualToNoCase(shortName)) _langCombo.SetCurSel(index); } + + if (!error.IsEmpty()) + MessageBoxW(0, error, L"Error in Lang file", MB_OK | MB_ICONSTOP); return CPropertyPage::OnInit(); } LONG CLangPage::OnApply() { - int selectedIndex = _langCombo.GetCurSel(); - int pathIndex = (int)_langCombo.GetItemData(selectedIndex); + int pathIndex = (int)_langCombo.GetItemData_of_CurSel(); SaveRegLang(_paths[pathIndex]); ReloadLang(); LangWasChanged = true; @@ -74,7 +105,7 @@ void CLangPage::OnNotifyHelp() bool CLangPage::OnCommand(int code, int itemID, LPARAM param) { - if (code == CBN_SELCHANGE && itemID == IDC_LANG_COMBO_LANG) + if (code == CBN_SELCHANGE && itemID == IDC_LANG_LANG) { Changed(); return true; diff --git a/CPP/7zip/UI/FileManager/LangPage.h b/CPP/7zip/UI/FileManager/LangPage.h old mode 100755 new mode 100644 index e58f5098..589941b2 --- a/CPP/7zip/UI/FileManager/LangPage.h +++ b/CPP/7zip/UI/FileManager/LangPage.h @@ -3,8 +3,8 @@ #ifndef __LANG_PAGE_H #define __LANG_PAGE_H -#include "Windows/Control/PropertyPage.h" -#include "Windows/Control/ComboBox.h" +#include "../../../Windows/Control/PropertyPage.h" +#include "../../../Windows/Control/ComboBox.h" class CLangPage: public NWindows::NControl::CPropertyPage { @@ -12,6 +12,7 @@ class CLangPage: public NWindows::NControl::CPropertyPage UStringVector _paths; public: bool LangWasChanged; + CLangPage() { LangWasChanged = false; } virtual bool OnInit(); virtual void OnNotifyHelp(); diff --git a/CPP/7zip/UI/FileManager/LangPage.rc b/CPP/7zip/UI/FileManager/LangPage.rc old mode 100755 new mode 100644 index 327b33e2..5aeaf406 --- a/CPP/7zip/UI/FileManager/LangPage.rc +++ b/CPP/7zip/UI/FileManager/LangPage.rc @@ -4,11 +4,11 @@ #define xc 148 #define yc 100 -IDD_LANG MY_PAGE +IDD_LANG DIALOG 0, 0, xs, ys MY_PAGE_STYLE MY_FONT 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 + LTEXT "Language:", IDT_LANG_LANG, m, m, xc, 8 + COMBOBOX IDC_LANG_LANG, m, 20, xc, yc - 20, MY_COMBO_SORTED } @@ -23,8 +23,8 @@ CAPTION "Language" 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 + LTEXT "Language:", IDT_LANG_LANG, m, m, xc, 8 + COMBOBOX IDC_LANG_LANG, m, 20, xc, yc - 20, MY_COMBO_SORTED } #endif diff --git a/CPP/7zip/UI/FileManager/LangPageRes.h b/CPP/7zip/UI/FileManager/LangPageRes.h old mode 100755 new mode 100644 index eb704dbf..d7a39d75 --- a/CPP/7zip/UI/FileManager/LangPageRes.h +++ b/CPP/7zip/UI/FileManager/LangPageRes.h @@ -1,8 +1,8 @@ -#define IDD_LANG 544 -#define IDD_LANG_2 644 +#define IDD_LANG 2101 +#define IDD_LANG_2 12101 -#define IDS_LANG_ENGLISH 995 -#define IDS_LANG_NATIVE 996 +#define IDS_LANG_ENGLISH 1 +#define IDS_LANG_NATIVE 2 -#define IDC_LANG_STATIC_LANG 1000 -#define IDC_LANG_COMBO_LANG 1001 +#define IDT_LANG_LANG 2102 +#define IDC_LANG_LANG 100 diff --git a/CPP/7zip/UI/FileManager/LangUtils.cpp b/CPP/7zip/UI/FileManager/LangUtils.cpp old mode 100755 new mode 100644 index 20f4655b..15d68f43 --- a/CPP/7zip/UI/FileManager/LangUtils.cpp +++ b/CPP/7zip/UI/FileManager/LangUtils.cpp @@ -2,51 +2,37 @@ #include "StdAfx.h" -#include "Common/StringConvert.h" -#include "Common/StringToInt.h" +#include "../../../Common/Lang.h" -#include "Windows/DLL.h" -#include "Windows/FileFind.h" -#include "Windows/Synchronization.h" -#include "Windows/Window.h" +#include "../../../Windows/DLL.h" +#include "../../../Windows/Synchronization.h" +#include "../../../Windows/Window.h" #include "LangUtils.h" #include "RegistryUtils.h" using namespace NWindows; -static CLang g_Lang; -UString g_LangID; - #ifndef _UNICODE extern bool g_IsNT; #endif -static FString GetLangDirPrefix() +UString g_LangID; + +static CLang g_Lang; +static bool g_Loaded = false; +static NSynchronization::CCriticalSection g_CriticalSection; + +bool LangOpen(CLang &lang, CFSTR fileName) { - return NDLL::GetModuleDirPrefix() + FString(FTEXT("Lang") FSTRING_PATH_SEPARATOR); + return lang.Open(fileName, L"7-Zip"); } -void ReloadLang() +FString GetLangDirPrefix() { - ReadRegLang(g_LangID); - g_Lang.Clear(); - if (!g_LangID.IsEmpty() && g_LangID != L"-") - { - FString langPath = us2fs(g_LangID); - if (langPath.Find(WCHAR_PATH_SEPARATOR) < 0) - { - if (langPath.Find(FTEXT('.')) < 0) - langPath += FTEXT(".txt"); - langPath = GetLangDirPrefix() + langPath; - } - g_Lang.Open(langPath); - } + return NDLL::GetModuleDirPrefix() + FTEXT("Lang") FSTRING_PATH_SEPARATOR; } -static bool g_Loaded = false; -static NSynchronization::CCriticalSection g_CriticalSection; - void LoadLangOneTime() { NSynchronization::CCriticalSectionLock lock(g_CriticalSection); @@ -56,154 +42,210 @@ void LoadLangOneTime() ReloadLang(); } -void LangSetDlgItemsText(HWND dialogWindow, const CIDLangPair *idLangPairs, int numItems) +void LangSetDlgItemText(HWND dialog, UInt32 controlID, UInt32 langID) +{ + const wchar_t *s = g_Lang.Get(langID); + if (s) + { + CWindow window(GetDlgItem(dialog, controlID)); + window.SetText(s); + } +} + +static const CIDLangPair kLangPairs[] = +{ + { IDOK, 401 }, + { IDCANCEL, 402 }, + { IDYES, 406 }, + { IDNO, 407 }, + { IDHELP, 409 } +}; + + +void LangSetDlgItems(HWND dialog, const UInt32 *ids, unsigned numItems) { - for (int i = 0; i < numItems; i++) + unsigned i; + for (i = 0; i < ARRAY_SIZE(kLangPairs); i++) { - const CIDLangPair &idLangPair = idLangPairs[i]; - UString message; - if (g_Lang.GetMessage(idLangPair.LangID, message)) + const CIDLangPair &pair = kLangPairs[i]; + CWindow window(GetDlgItem(dialog, pair.ControlID)); + if (window) { - NWindows::CWindow window(GetDlgItem(dialogWindow, idLangPair.ControlID)); - window.SetText(message); + const wchar_t *s = g_Lang.Get(pair.LangID); + if (s) + window.SetText(s); } } + + for (i = 0; i < numItems; i++) + { + UInt32 id = ids[i]; + LangSetDlgItemText(dialog, id, id); + } } -void LangSetWindowText(HWND window, UInt32 langID) +void LangSetDlgItems_Colon(HWND dialog, const UInt32 *ids, unsigned numItems) { - UString message; - if (g_Lang.GetMessage(langID, message)) - MySetWindowText(window, message); + for (unsigned i = 0; i < numItems; i++) + { + UInt32 id = ids[i]; + const wchar_t *s = g_Lang.Get(id); + if (s) + { + CWindow window(GetDlgItem(dialog, id)); + UString s2 = s; + s2 += L':'; + window.SetText(s2); + } + } } -UString LangString(UInt32 langID) +void LangSetWindowText(HWND window, UInt32 langID) { - UString message; - if (g_Lang.GetMessage(langID, message)) - return message; - return UString(); + const wchar_t *s = g_Lang.Get(langID); + if (s) + MySetWindowText(window, s); } -UString LangString(UINT resourceID, UInt32 langID) +UString LangString(UInt32 langID) { - UString message; - if (g_Lang.GetMessage(langID, message)) - return message; - return MyLoadStringW(resourceID); + const wchar_t *s = g_Lang.Get(langID); + if (s) + return s; + return MyLoadString(langID); } -void LoadLangs(CObjectVector &langs) +void LangString(UInt32 langID, UString &dest) { - langs.Clear(); - const FString dirPrefix = GetLangDirPrefix(); - NFile::NFind::CEnumerator enumerator(dirPrefix + FTEXT("*.txt")); - NFile::NFind::CFileInfo fi; - while (enumerator.Next(fi)) + const wchar_t *s = g_Lang.Get(langID); + if (s) { - if (fi.IsDir()) - continue; - const int kExtSize = 4; - const FString ext = fi.Name.Right(kExtSize); - if (ext.CompareNoCase(FTEXT(".txt")) != 0) - continue; - CLangEx lang; - lang.ShortName = fs2us(fi.Name.Left(fi.Name.Length() - kExtSize)); - if (lang.Lang.Open(dirPrefix + fi.Name)) - langs.Add(lang); + dest = s; + return; } + MyLoadString(langID, dest); } -bool SplidID(const UString &id, WORD &primID, WORD &subID) +void LangString_OnlyFromLangFile(UInt32 langID, UString &dest) { - 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); + dest.Empty(); + const wchar_t *s = g_Lang.Get(langID); + if (s) + dest = s; } -typedef LANGID (WINAPI *GetUserDefaultUILanguageP)(); +static const char *kLangs = +"ar.bg.ca.zh.-tw.-cn.cs.da.de.el.en.es.fi.fr.he.hu.is.it.ja.ko.nl.no.=nb.=nn." +"pl.pt.-br.rm.ro.ru.sr.=hr.-spl.-spc.sk.sq.sv.th.tr.ur.id.uk.be.sl.et.lv.lt.tg." +"fa.vi.hy.az.eu.hsb.mk...tn..xh.zu.af.ka.fo.hi.mt.se.ga." +".ms.kk.ky.sw.tk.uz.tt.bn.pa.-in.gu.or.ta.te.kn.ml.as.mr.sa.mn.=mn.=mng" +"bo.cy.kh.lo..gl.kok..sd.syr.si..iu.am.tzm.ks.ne.fy.ps.fil." +"dv...ha..yo.quz.nso.ba.lb.kl.ig...ti.....ii." +".arn..moh..br..ug.mi.oc.co.gsw.sah.qut.rw.wo....prs."; -void FindMatchLang(UString &shortName) +static void FindShortNames(UInt32 primeLang, UStringVector &names) { - shortName.Empty(); + UInt32 index = 0; + for (const char *p = kLangs; *p != 0;) + { + const char *p2 = p; + for (; *p2 != '.'; p2++); + bool isSub = (p[0] == '-' || p[0] == '='); + if (!isSub) + index++; + if (index > primeLang) + break; + if (index == primeLang) + { + UString s; + if (isSub) + { + if (p[0] == '-') + s = names[0]; + else + p++; + } + while (p != p2) + s += (wchar_t)*p++; + names.Add(s); + } + p = p2 + 1; + } +} - LANGID SystemDefaultLangID = GetSystemDefaultLangID(); // Lang for non-Unicode in XP64 - LANGID UserDefaultLangID = GetUserDefaultLangID(); // Standarts and formats in XP64 +// typedef LANGID (WINAPI *GetUserDefaultUILanguageP)(); - if (SystemDefaultLangID != UserDefaultLangID) +static void OpenDefaultLang() +{ + LANGID sysLang = GetSystemDefaultLangID(); // "Language for non-Unicode programs" in XP64 + LANGID userLang = GetUserDefaultLangID(); // "Standards and formats" language in XP64 + + if (sysLang != userLang) return; - LANGID langID = UserDefaultLangID; + LANGID langID = userLang; + /* - LANGID SystemDefaultUILanguage; // english in XP64 - LANGID UserDefaultUILanguage; // english in XP64 + LANGID sysUILang; // english in XP64 + LANGID userUILang; // english in XP64 GetUserDefaultUILanguageP fn = (GetUserDefaultUILanguageP)GetProcAddress( GetModuleHandle("kernel32"), "GetUserDefaultUILanguage"); - if (fn != NULL) - UserDefaultUILanguage = fn(); + if (fn) + userUILang = fn(); fn = (GetUserDefaultUILanguageP)GetProcAddress( GetModuleHandle("kernel32"), "GetSystemDefaultUILanguage"); - if (fn != NULL) - SystemDefaultUILanguage = fn(); + if (fn) + sysUILang = 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)) + UStringVector names; + FindShortNames(primLang, names); + const FString dirPrefix = GetLangDirPrefix(); + for (unsigned i = 0; i < 2; i++) { - WORD primID; - WORD subID; - if (SplidID(id, primID, subID)) - if (primID == primLang) + unsigned index = (i == 0 ? subLang : 0); + if (index < names.Size()) + { + const UString &name = names[index]; + if (!name.IsEmpty()) { - if (subID == 0) - shortName = lang.ShortName; - if (subLang == subID) + if (LangOpen(g_Lang, dirPrefix + us2fs(name) + FTEXT(".txt"))) { - shortName = lang.ShortName; + g_LangID = name; return; } } + } } } } -void ReloadLangSmart() +void ReloadLang() { + g_Lang.Clear(); + ReadRegLang(g_LangID); #ifndef _UNICODE if (g_IsNT) #endif { - ReadRegLang(g_LangID); if (g_LangID.IsEmpty()) { - UString shortName; - FindMatchLang(shortName); - if (shortName.IsEmpty()) - shortName = L"-"; - SaveRegLang(shortName); + OpenDefaultLang(); + return; } } - ReloadLang(); + if (g_LangID.Len() > 1 || g_LangID[0] != L'-') + { + FString s = us2fs(g_LangID); + if (s.Find(FCHAR_PATH_SEPARATOR) < 0) + { + if (s.Find(FTEXT('.')) < 0) + s += FTEXT(".txt"); + s.Insert(0, GetLangDirPrefix()); + } + LangOpen(g_Lang, s); + } } diff --git a/CPP/7zip/UI/FileManager/LangUtils.h b/CPP/7zip/UI/FileManager/LangUtils.h old mode 100755 new mode 100644 index d11082f6..509a5ae3 --- a/CPP/7zip/UI/FileManager/LangUtils.h +++ b/CPP/7zip/UI/FileManager/LangUtils.h @@ -3,39 +3,36 @@ #ifndef __LANG_UTILS_H #define __LANG_UTILS_H -#include "Common/Lang.h" -#include "Windows/ResourceString.h" +#include "../../../Windows/ResourceString.h" + +#ifdef LANG extern UString g_LangID; struct CIDLangPair { - int ControlID; + UInt32 ControlID; UInt32 LangID; }; void ReloadLang(); void LoadLangOneTime(); -void ReloadLangSmart(); - -struct CLangEx -{ - CLang Lang; - UString ShortName; -}; +FString GetLangDirPrefix(); -void LoadLangs(CObjectVector &langs); - -void LangSetDlgItemsText(HWND dialogWindow, const CIDLangPair *idLangPairs, int numItems); +void LangSetDlgItemText(HWND dialog, UInt32 controlID, UInt32 langID); +void LangSetDlgItems(HWND dialog, const UInt32 *ids, unsigned numItems); +void LangSetDlgItems_Colon(HWND dialog, const UInt32 *ids, unsigned numItems); void LangSetWindowText(HWND window, UInt32 langID); UString LangString(UInt32 langID); -UString LangString(UINT resourceID, UInt32 langID); +void LangString(UInt32 langID, UString &dest); +void LangString_OnlyFromLangFile(UInt32 langID, UString &dest); -#ifdef LANG -#define LangStringSpec(resourceID, langID) LangString(resourceID, langID) #else -#define LangStringSpec(resourceID, langID) NWindows::MyLoadStringW(resourceID) + +inline UString LangString(UInt32 langID) { return NWindows::MyLoadString(langID); } +inline void LangString(UInt32 langID, UString &dest) { NWindows::MyLoadString(langID, dest); } + #endif #endif diff --git a/CPP/7zip/UI/FileManager/LinkDialog.cpp b/CPP/7zip/UI/FileManager/LinkDialog.cpp new file mode 100644 index 00000000..a24ec601 --- /dev/null +++ b/CPP/7zip/UI/FileManager/LinkDialog.cpp @@ -0,0 +1,342 @@ +// LinkDialog.cpp + +#include "StdAfx.h" + +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/FileIO.h" +#include "../../../Windows/FileName.h" + +#ifdef LANG +#include "LangUtils.h" +#endif + +#include "BrowseDialog.h" +#include "CopyDialogRes.h" +#include "LinkDialog.h" +#include "resourceGui.h" + +#include "App.h" + +#include "resource.h" + +extern bool g_SymLink_Supported; + +using namespace NWindows; +using namespace NFile; + +#ifdef LANG +static const UInt32 kLangIDs[] = +{ + IDB_LINK_LINK, + IDT_LINK_PATH_FROM, + IDT_LINK_PATH_TO, + IDG_LINK_TYPE, + IDR_LINK_TYPE_HARD, + IDR_LINK_TYPE_SYM_FILE, + IDR_LINK_TYPE_SYM_DIR, + IDR_LINK_TYPE_JUNCTION +}; +#endif + +static bool GetSymLink(CFSTR path, CReparseAttr &attr) +{ + NFile::NIO::CInFile file; + if (!file.Open(path, + FILE_SHARE_READ, + OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS)) + return false; + + const unsigned kBufSize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE; + CByteArr buf(kBufSize); + DWORD returnedSize; + if (!file.DeviceIoControlOut(my_FSCTL_GET_REPARSE_POINT, buf, kBufSize, &returnedSize)) + return false; + + if (!attr.Parse(buf, returnedSize)) + return false; + + CByteBuffer data2; + if (!FillLinkData(data2, attr.GetPath(), attr.IsSymLink())) + return false; + + if (data2.Size() != returnedSize || + memcmp(data2, buf, returnedSize) != 0) + return false; + + return true; +} + +static const int k_LinkType_Buttons[] = +{ + IDR_LINK_TYPE_HARD, + IDR_LINK_TYPE_SYM_FILE, + IDR_LINK_TYPE_SYM_DIR, + IDR_LINK_TYPE_JUNCTION +}; + +void CLinkDialog::Set_LinkType_Radio(int idb) +{ + CheckRadioButton(k_LinkType_Buttons[0], k_LinkType_Buttons[ARRAY_SIZE(k_LinkType_Buttons) - 1], idb); +} + +bool CLinkDialog::OnInit() +{ + #ifdef LANG + LangSetWindowText(*this, IDD_LINK); + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); + #endif + _pathFromCombo.Attach(GetItem(IDC_LINK_PATH_FROM)); + _pathToCombo.Attach(GetItem(IDC_LINK_PATH_TO)); + + if (!FilePath.IsEmpty()) + { + NFile::NFind::CFileInfo fi; + int linkType = 0; + if (!fi.Find(us2fs(FilePath))) + linkType = IDR_LINK_TYPE_SYM_FILE; + else + { + if (fi.HasReparsePoint()) + { + CReparseAttr attr; + bool res = GetSymLink(us2fs(FilePath), attr); + + UString s = attr.PrintName; + if (!attr.IsOkNamePair()) + { + s += L" : "; + s += attr.SubsName; + } + if (!res) + s = L"ERROR: " + s; + + SetItemText(IDT_LINK_PATH_TO_CUR, s); + + UString destPath = attr.GetPath(); + _pathFromCombo.SetText(FilePath); + _pathToCombo.SetText(destPath); + + if (res) + { + if (attr.IsMountPoint()) + linkType = IDR_LINK_TYPE_JUNCTION; + if (attr.IsSymLink()) + { + linkType = + fi.IsDir() ? + IDR_LINK_TYPE_SYM_DIR : + IDR_LINK_TYPE_SYM_FILE; + // if (attr.IsRelative()) linkType = IDR_LINK_TYPE_SYM_RELATIVE; + } + + if (linkType != 0) + Set_LinkType_Radio(linkType); + } + } + else + { + _pathFromCombo.SetText(AnotherPath); + _pathToCombo.SetText(FilePath); + if (fi.IsDir()) + linkType = g_SymLink_Supported ? + IDR_LINK_TYPE_SYM_DIR : + IDR_LINK_TYPE_JUNCTION; + else + linkType = IDR_LINK_TYPE_HARD; + } + } + if (linkType != 0) + Set_LinkType_Radio(linkType); + } + + NormalizeSize(); + return CModalDialog::OnInit(); +} + +bool CLinkDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) +{ + int mx, my; + GetMargins(8, mx, my); + int bx1, bx2, by; + GetItemSizes(IDCANCEL, bx1, by); + GetItemSizes(IDB_LINK_LINK, bx2, by); + int yPos = ySize - my - by; + int xPos = xSize - mx - bx1; + + InvalidateRect(NULL); + + { + RECT r, r2; + GetClientRectOfItem(IDB_LINK_PATH_FROM, r); + GetClientRectOfItem(IDB_LINK_PATH_TO, r2); + int bx = RECT_SIZE_X(r); + int newButtonXpos = xSize - mx - bx; + + MoveItem(IDB_LINK_PATH_FROM, newButtonXpos, r.top, bx, RECT_SIZE_Y(r)); + MoveItem(IDB_LINK_PATH_TO, newButtonXpos, r2.top, bx, RECT_SIZE_Y(r2)); + + int newComboXsize = newButtonXpos - mx - mx; + ChangeSubWindowSizeX(_pathFromCombo, newComboXsize); + ChangeSubWindowSizeX(_pathToCombo, newComboXsize); + } + + MoveItem(IDCANCEL, xPos, yPos, bx1, by); + MoveItem(IDB_LINK_LINK, xPos - mx - bx2, yPos, bx2, by); + + return false; +} + +bool CLinkDialog::OnButtonClicked(int buttonID, HWND buttonHWND) +{ + switch (buttonID) + { + case IDB_LINK_PATH_FROM: + OnButton_SetPath(false); + return true; + case IDB_LINK_PATH_TO: + OnButton_SetPath(true); + return true; + case IDB_LINK_LINK: + OnButton_Link(); + return true; + } + return CModalDialog::OnButtonClicked(buttonID, buttonHWND); +} + +void CLinkDialog::OnButton_SetPath(bool to) +{ + UString currentPath; + NWindows::NControl::CComboBox &combo = to ? + _pathToCombo : + _pathFromCombo; + combo.GetText(currentPath); + // UString title = L"Specify a location for output folder"; + UString title = LangString(IDS_SET_FOLDER); + + UString resultPath; + if (!MyBrowseForFolder(*this, title, currentPath, resultPath)) + return; + NFile::NName::NormalizeDirPathPrefix(resultPath); + combo.SetCurSel(-1); + combo.SetText(resultPath); +} + +void CLinkDialog::ShowError(const wchar_t *s) +{ + ::MessageBoxW(*this, s, L"7-Zip", MB_ICONERROR); +} + +void CLinkDialog::ShowLastErrorMessage() +{ + ShowError(NError::MyFormatMessage(GetLastError())); +} + +void CLinkDialog::OnButton_Link() +{ + UString from, to; + _pathFromCombo.GetText(from); + _pathToCombo.GetText(to); + int i; + for (i = 0; i < ARRAY_SIZE(k_LinkType_Buttons); i++) + if (IsButtonCheckedBool(k_LinkType_Buttons[i])) + break; + if (i >= ARRAY_SIZE(k_LinkType_Buttons)) + return; + + int idb = k_LinkType_Buttons[i]; + + NFile::NFind::CFileInfo info1, info2; + bool finded1 = info1.Find(us2fs(from)); + bool finded2 = info2.Find(us2fs(to)); + + bool isDirLink = ( + idb == IDR_LINK_TYPE_SYM_DIR || + idb == IDR_LINK_TYPE_JUNCTION); + + if (finded1 && info1.IsDir() != isDirLink || + finded2 && info2.IsDir() != isDirLink) + { + ShowError(L"Incorrect linkType"); + return; + } + + if (idb == IDR_LINK_TYPE_HARD) + { + bool res = NFile::NDir::MyCreateHardLink(us2fs(from), us2fs(to)); + if (!res) + { + ShowLastErrorMessage(); + return; + } + } + else + { + bool isSymLink = (idb != IDR_LINK_TYPE_JUNCTION); + + CByteBuffer data; + if (!FillLinkData(data, to, isSymLink)) + { + ShowError(L"Incorrect link"); + return; + } + + CReparseAttr attr; + if (!attr.Parse(data, data.Size())) + { + ShowError(L"Internal conversion error"); + return; + } + + + if (!NFile::NIO::SetReparseData(us2fs(from), isDirLink, data, (DWORD)data.Size())) + { + ShowLastErrorMessage(); + } + } + + End(IDOK); +} + +void CApp::Link() +{ + int srcPanelIndex = GetFocusedPanelIndex(); + CPanel &srcPanel = Panels[srcPanelIndex]; + if (!srcPanel.IsFSFolder()) + { + srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); + return; + } + CRecordVector indices; + srcPanel.GetOperatedItemIndices(indices); + if (indices.IsEmpty()) + return; + if (indices.Size() != 1) + { + srcPanel.MessageBoxErrorLang(IDS_SELECT_ONE_FILE); + return; + } + int index = indices[0]; + 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; + } + + CLinkDialog dlg; + dlg.FilePath = srcPath + itemName; + dlg.AnotherPath = path; + + if (dlg.Create(srcPanel.GetParent()) != IDOK) + return; + + RefreshTitleAlways(); +} diff --git a/CPP/7zip/UI/FileManager/LinkDialog.h b/CPP/7zip/UI/FileManager/LinkDialog.h new file mode 100644 index 00000000..8417fac8 --- /dev/null +++ b/CPP/7zip/UI/FileManager/LinkDialog.h @@ -0,0 +1,33 @@ +// LinkDialog.h + +#ifndef __LINK_DIALOG_H +#define __LINK_DIALOG_H + +#include "../../../Windows/Control/Dialog.h" +#include "../../../Windows/Control/ComboBox.h" + +#include "LinkDialogRes.h" + +class CLinkDialog: public NWindows::NControl::CModalDialog +{ + NWindows::NControl::CComboBox _pathFromCombo; + NWindows::NControl::CComboBox _pathToCombo; + + virtual bool OnInit(); + virtual bool OnSize(WPARAM wParam, int xSize, int ySize); + virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); + void OnButton_SetPath(bool to); + void OnButton_Link(); + + void ShowLastErrorMessage(); + void ShowError(const wchar_t *s); + void Set_LinkType_Radio(int idb); +public: + UString FilePath; + UString AnotherPath; + + INT_PTR Create(HWND parentWindow = 0) + { return CModalDialog::Create(IDD_LINK, parentWindow); } +}; + +#endif diff --git a/CPP/7zip/UI/FileManager/LinkDialog.rc b/CPP/7zip/UI/FileManager/LinkDialog.rc new file mode 100644 index 00000000..3d481d4d --- /dev/null +++ b/CPP/7zip/UI/FileManager/LinkDialog.rc @@ -0,0 +1,36 @@ +#include "LinkDialogRes.h" +#include "../../GuiCommon.rc" + +#define xc 288 +#define yc 200 + +#undef xRadioSize +#define xRadioSize xc - m - 2 + +IDD_LINK DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT +CAPTION "Link" +BEGIN + LTEXT "Link from:", IDT_LINK_PATH_FROM, m, m, xc, 8 + COMBOBOX IDC_LINK_PATH_FROM, m, 20, xc - bxsDots - m, 64, MY_COMBO_WITH_EDIT + PUSHBUTTON "...", IDB_LINK_PATH_FROM, xs - m - bxsDots, 18, bxsDots, bys, WS_GROUP + + LTEXT "Link to:", IDT_LINK_PATH_TO, m, 48, xc, 8 + COMBOBOX IDC_LINK_PATH_TO, m, 60, xc - bxsDots - m, 64, MY_COMBO_WITH_EDIT + PUSHBUTTON "...", IDB_LINK_PATH_TO, xs - m - bxsDots, 58, bxsDots, bys, WS_GROUP + + LTEXT "", IDT_LINK_PATH_TO_CUR, m, 78, xc, 8 + + GROUPBOX "Link Type", IDG_LINK_TYPE, m, 104, xc, 76 + + CONTROL "Hard Link", IDR_LINK_TYPE_HARD, "Button", BS_AUTORADIOBUTTON | WS_GROUP, + m + m, 120, xRadioSize, 10 + CONTROL "File Symbolic Link", IDR_LINK_TYPE_SYM_FILE, "Button", BS_AUTORADIOBUTTON, + m + m, 134, xRadioSize, 10 + CONTROL "Directory Symbolic Link", IDR_LINK_TYPE_SYM_DIR, "Button", BS_AUTORADIOBUTTON, + m + m, 148, xRadioSize, 10 + CONTROL "Directory Junction", IDR_LINK_TYPE_JUNCTION, "Button", BS_AUTORADIOBUTTON, + m + m, 162, xRadioSize, 10 + + DEFPUSHBUTTON "Link", IDB_LINK_LINK, bx2, by, bxs, bys + PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys +END diff --git a/CPP/7zip/UI/FileManager/LinkDialogRes.h b/CPP/7zip/UI/FileManager/LinkDialogRes.h new file mode 100644 index 00000000..6b2dc2cf --- /dev/null +++ b/CPP/7zip/UI/FileManager/LinkDialogRes.h @@ -0,0 +1,21 @@ +#define IDD_LINK 7700 + +#define IDB_LINK_LINK 7701 + +#define IDT_LINK_PATH_FROM 7702 +#define IDT_LINK_PATH_TO 7703 + +#define IDG_LINK_TYPE 7710 +#define IDR_LINK_TYPE_HARD 7711 +#define IDR_LINK_TYPE_SYM_FILE 7712 +#define IDR_LINK_TYPE_SYM_DIR 7713 +#define IDR_LINK_TYPE_JUNCTION 7714 + + +#define IDC_LINK_PATH_FROM 100 +#define IDC_LINK_PATH_TO 101 + +#define IDT_LINK_PATH_TO_CUR 102 + +#define IDB_LINK_PATH_FROM 103 +#define IDB_LINK_PATH_TO 104 diff --git a/CPP/7zip/UI/FileManager/ListViewDialog.cpp b/CPP/7zip/UI/FileManager/ListViewDialog.cpp old mode 100755 new mode 100644 index b3e989c4..78c9562a --- a/CPP/7zip/UI/FileManager/ListViewDialog.cpp +++ b/CPP/7zip/UI/FileManager/ListViewDialog.cpp @@ -7,19 +7,16 @@ #ifdef LANG #include "LangUtils.h" -static CIDLangPair kIDLangPairs[] = -{ - { IDOK, 0x02000702 }, - { IDCANCEL, 0x02000710 } -}; #endif +using namespace NWindows; + bool CListViewDialog::OnInit() { #ifdef LANG - LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + LangSetDlgItems(*this, NULL, 0); #endif - _listView.Attach(GetItem(IDC_LISTVIEW_LIST)); + _listView.Attach(GetItem(IDL_LISTVIEW)); if (ReadSingleClick()) _listView.SetExtendedListViewStyle(LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT); @@ -34,7 +31,7 @@ bool CListViewDialog::OnInit() _listView.InsertColumn(0, &columnInfo); - for (int i = 0; i < Strings.Size(); i++) + FOR_VECTOR (i, Strings) _listView.InsertItem(i, Strings[i]); if (Strings.Size() > 0) @@ -125,8 +122,7 @@ bool CListViewDialog::OnNotify(UINT /* controlID */, LPNMHDR header) } case 'A': { - bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0; - if (ctrl) + if (IsKeyDown(VK_CONTROL)) { _listView.SelectAll(); return true; diff --git a/CPP/7zip/UI/FileManager/ListViewDialog.h b/CPP/7zip/UI/FileManager/ListViewDialog.h old mode 100755 new mode 100644 index 6be51c7e..b7ba3830 --- a/CPP/7zip/UI/FileManager/ListViewDialog.h +++ b/CPP/7zip/UI/FileManager/ListViewDialog.h @@ -3,8 +3,8 @@ #ifndef __LISTVIEW_DIALOG_H #define __LISTVIEW_DIALOG_H -#include "Windows/Control/Dialog.h" -#include "Windows/Control/ListView.h" +#include "../../../Windows/Control/Dialog.h" +#include "../../../Windows/Control/ListView.h" #include "ListViewDialogRes.h" @@ -22,7 +22,7 @@ public: UStringVector Strings; int FocusedItemIndex; - INT_PTR Create(HWND wndParent = 0) { return CModalDialog::Create(IDD_DIALOG_LISTVIEW, wndParent); } + INT_PTR Create(HWND wndParent = 0) { return CModalDialog::Create(IDD_LISTVIEW, wndParent); } CListViewDialog(): DeleteIsAllowed(false) {} }; diff --git a/CPP/7zip/UI/FileManager/ListViewDialog.rc b/CPP/7zip/UI/FileManager/ListViewDialog.rc old mode 100755 new mode 100644 index 8f963bf1..14d3b2e6 --- a/CPP/7zip/UI/FileManager/ListViewDialog.rc +++ b/CPP/7zip/UI/FileManager/ListViewDialog.rc @@ -4,10 +4,10 @@ #define xc 320 #define yc 240 -IDD_DIALOG_LISTVIEW MY_RESIZE_DIALOG +IDD_LISTVIEW DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT CAPTION "ListView" { - CONTROL "List1", IDC_LISTVIEW_LIST, "SysListView32", LVS_REPORT | LVS_SHOWSELALWAYS | + CONTROL "List1", IDL_LISTVIEW, "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 old mode 100755 new mode 100644 index aaa6521f..9abdb9d2 --- a/CPP/7zip/UI/FileManager/ListViewDialogRes.h +++ b/CPP/7zip/UI/FileManager/ListViewDialogRes.h @@ -1,2 +1,2 @@ -#define IDD_DIALOG_LISTVIEW 508 -#define IDC_LISTVIEW_LIST 1000 +#define IDD_LISTVIEW 99 +#define IDL_LISTVIEW 100 diff --git a/CPP/7zip/UI/FileManager/MenuPage.cpp b/CPP/7zip/UI/FileManager/MenuPage.cpp old mode 100755 new mode 100644 index c3e013b5..0784f92c --- a/CPP/7zip/UI/FileManager/MenuPage.cpp +++ b/CPP/7zip/UI/FileManager/MenuPage.cpp @@ -14,13 +14,16 @@ #include "MenuPageRes.h" #include "FormatUtils.h" +#include "../FileManager/PropertyNameRes.h" + using namespace NContextMenuFlags; -static CIDLangPair kIDLangPairs[] = +static const UInt32 kLangIDs[] = { - { IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU, 0x01000301}, - { IDC_SYSTEM_CASCADED_MENU, 0x01000302}, - { IDC_SYSTEM_STATIC_CONTEXT_MENU_ITEMS, 0x01000310} + IDX_SYSTEM_INTEGRATE_TO_CONTEXT_MENU, + IDX_SYSTEM_CASCADED_MENU, + IDX_SYSTEM_ICON_IN_MENU, + IDT_SYSTEM_CONTEXT_MENU_ITEMS }; static LPCWSTR kSystemTopic = L"fm/options.htm#sevenZip"; @@ -28,77 +31,80 @@ static LPCWSTR kSystemTopic = L"fm/options.htm#sevenZip"; 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_OPEN, kOpen}, + { IDS_CONTEXT_OPEN, kOpenAs}, + { IDS_CONTEXT_EXTRACT, kExtract}, + { IDS_CONTEXT_EXTRACT_HERE, kExtractHere }, + { IDS_CONTEXT_EXTRACT_TO, kExtractTo }, - { IDS_CONTEXT_TEST, 0x02000109, kTest}, + { IDS_CONTEXT_TEST, kTest}, - { IDS_CONTEXT_COMPRESS, 0x02000107, kCompress }, - { IDS_CONTEXT_COMPRESS_TO, 0x0200010F, kCompressTo7z }, - { IDS_CONTEXT_COMPRESS_TO, 0x0200010F, kCompressToZip } + { IDS_CONTEXT_COMPRESS, kCompress }, + { IDS_CONTEXT_COMPRESS_TO, kCompressTo7z }, + { IDS_CONTEXT_COMPRESS_TO, kCompressToZip } #ifndef UNDER_CE , - { IDS_CONTEXT_COMPRESS_EMAIL, 0x02000111, kCompressEmail }, - { IDS_CONTEXT_COMPRESS_TO_EMAIL, 0x02000113, kCompressTo7zEmail }, - { IDS_CONTEXT_COMPRESS_TO_EMAIL, 0x02000113, kCompressToZipEmail } + { IDS_CONTEXT_COMPRESS_EMAIL, kCompressEmail }, + { IDS_CONTEXT_COMPRESS_TO_EMAIL, kCompressTo7zEmail }, + { IDS_CONTEXT_COMPRESS_TO_EMAIL, kCompressToZipEmail } #endif -}; -const int kNumMenuItems = sizeof(kMenuItems) / sizeof(kMenuItems[0]); + , { IDS_PROP_CHECKSUM, kCRC } +}; bool CMenuPage::OnInit() { _initMode = true; - LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); #ifdef UNDER_CE - EnableItem(IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU, false); + EnableItem(IDX_SYSTEM_INTEGRATE_TO_CONTEXT_MENU, false); #else - CheckButton(IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU, NZipRootRegistry::CheckContextMenuHandler()); + CheckButton(IDX_SYSTEM_INTEGRATE_TO_CONTEXT_MENU, NZipRootRegistry::CheckContextMenuHandler()); #endif CContextMenuInfo ci; ci.Load(); - CheckButton(IDC_SYSTEM_CASCADED_MENU, ci.Cascaded); + CheckButton(IDX_SYSTEM_CASCADED_MENU, ci.Cascaded); + CheckButton(IDX_SYSTEM_ICON_IN_MENU, ci.MenuIcons); - _listView.Attach(GetItem(IDC_SYSTEM_OPTIONS_LIST)); + _listView.Attach(GetItem(IDL_SYSTEM_OPTIONS)); UInt32 newFlags = LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT; _listView.SetExtendedListViewStyle(newFlags, newFlags); _listView.InsertColumn(0, L"", 100); - for (int i = 0; i < kNumMenuItems; i++) + for (int i = 0; i < ARRAY_SIZE(kMenuItems); i++) { CContextMenuItem &menuItem = kMenuItems[i]; - UString s = LangString(menuItem.ControlID, menuItem.LangID); - if (menuItem.Flag == kOpenAs) + UString s = LangString(menuItem.ControlID); + if (menuItem.Flag == kCRC) + s = L"CRC SHA"; + if (menuItem.Flag == kOpenAs || + menuItem.Flag == kCRC) s += L" >"; - switch(menuItem.ControlID) + switch (menuItem.ControlID) { case IDS_CONTEXT_EXTRACT_TO: { - s = MyFormatNew(s, LangString(IDS_CONTEXT_FOLDER, 0x02000140)); + s = MyFormatNew(s, LangString(IDS_CONTEXT_FOLDER)); break; } case IDS_CONTEXT_COMPRESS_TO: case IDS_CONTEXT_COMPRESS_TO_EMAIL: { - UString s2 = LangString(IDS_CONTEXT_ARCHIVE, 0x02000141); - switch(menuItem.Flag) + UString s2 = LangString(IDS_CONTEXT_ARCHIVE); + switch (menuItem.Flag) { case kCompressTo7z: case kCompressTo7zEmail: @@ -133,7 +139,7 @@ LONG CMenuPage::OnApply() { #ifndef UNDER_CE g_MenuPageHWND = *this; - if (IsButtonCheckedBool(IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU)) + if (IsButtonCheckedBool(IDX_SYSTEM_INTEGRATE_TO_CONTEXT_MENU)) { DllRegisterServer(); NZipRootRegistry::AddContextMenuHandler(); @@ -146,9 +152,10 @@ LONG CMenuPage::OnApply() #endif CContextMenuInfo ci; - ci.Cascaded = IsButtonCheckedBool(IDC_SYSTEM_CASCADED_MENU); + ci.Cascaded = IsButtonCheckedBool(IDX_SYSTEM_CASCADED_MENU); + ci.MenuIcons = IsButtonCheckedBool(IDX_SYSTEM_ICON_IN_MENU); ci.Flags = 0; - for (int i = 0; i < kNumMenuItems; i++) + for (int i = 0; i < ARRAY_SIZE(kMenuItems); i++) if (_listView.GetCheckState(i)) ci.Flags |= kMenuItems[i].Flag; ci.Save(); @@ -163,10 +170,11 @@ void CMenuPage::OnNotifyHelp() bool CMenuPage::OnButtonClicked(int buttonID, HWND buttonHWND) { - switch(buttonID) + switch (buttonID) { - case IDC_SYSTEM_CASCADED_MENU: - case IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU: + case IDX_SYSTEM_INTEGRATE_TO_CONTEXT_MENU: + case IDX_SYSTEM_CASCADED_MENU: + case IDX_SYSTEM_ICON_IN_MENU: Changed(); return true; } @@ -178,7 +186,7 @@ bool CMenuPage::OnNotify(UINT controlID, LPNMHDR lParam) { if (lParam->hwndFrom == HWND(_listView)) { - switch(lParam->code) + switch (lParam->code) { case (LVN_ITEMCHANGED): return OnItemChanged((const NMLISTVIEW *)lParam); diff --git a/CPP/7zip/UI/FileManager/MenuPage.h b/CPP/7zip/UI/FileManager/MenuPage.h old mode 100755 new mode 100644 index 5005ea9c..1363687f --- a/CPP/7zip/UI/FileManager/MenuPage.h +++ b/CPP/7zip/UI/FileManager/MenuPage.h @@ -3,8 +3,8 @@ #ifndef __MENU_PAGE_H #define __MENU_PAGE_H -#include "Windows/Control/PropertyPage.h" -#include "Windows/Control/ListView.h" +#include "../../../Windows/Control/PropertyPage.h" +#include "../../../Windows/Control/ListView.h" #include "../Common/LoadCodecs.h" diff --git a/CPP/7zip/UI/FileManager/MenuPage.rc b/CPP/7zip/UI/FileManager/MenuPage.rc old mode 100755 new mode 100644 index 791a1c08..626f415e --- a/CPP/7zip/UI/FileManager/MenuPage.rc +++ b/CPP/7zip/UI/FileManager/MenuPage.rc @@ -2,7 +2,7 @@ #include "../../GuiCommon.rc" #define xc 196 -#define yc 174 +#define yc 196 IDD_MENU MY_PAGE #include "MenuPage2.rc" diff --git a/CPP/7zip/UI/FileManager/MenuPage2.rc b/CPP/7zip/UI/FileManager/MenuPage2.rc old mode 100755 new mode 100644 index 1862aa06..442d1bdd --- a/CPP/7zip/UI/FileManager/MenuPage2.rc +++ b/CPP/7zip/UI/FileManager/MenuPage2.rc @@ -1,14 +1,13 @@ -#define y 40 +#define y 54 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", + CONTROL "Integrate 7-Zip to shell context menu", IDX_SYSTEM_INTEGRATE_TO_CONTEXT_MENU, MY_CHECKBOX, m, m, xc, 10 + CONTROL "Cascaded context menu", IDX_SYSTEM_CASCADED_MENU, MY_CHECKBOX, m, m + 14, xc, 10 + CONTROL "Icons in context menu", IDX_SYSTEM_ICON_IN_MENU, MY_CHECKBOX, m, m + 28, xc, 10 + + LTEXT "Context menu items:", IDT_SYSTEM_CONTEXT_MENU_ITEMS, m, m + 42, xc, 8 + CONTROL "List", IDL_SYSTEM_OPTIONS, "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 old mode 100755 new mode 100644 index f1220bfd..91f75710 --- a/CPP/7zip/UI/FileManager/MenuPageRes.h +++ b/CPP/7zip/UI/FileManager/MenuPageRes.h @@ -1,7 +1,9 @@ -#define IDD_MENU 570 -#define IDD_MENU_2 670 +#define IDD_MENU 2300 +#define IDD_MENU_2 12300 -#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 +#define IDX_SYSTEM_INTEGRATE_TO_CONTEXT_MENU 2301 +#define IDX_SYSTEM_CASCADED_MENU 2302 +#define IDT_SYSTEM_CONTEXT_MENU_ITEMS 2303 +#define IDX_SYSTEM_ICON_IN_MENU 2304 + +#define IDL_SYSTEM_OPTIONS 100 diff --git a/CPP/7zip/UI/FileManager/MessagesDialog.cpp b/CPP/7zip/UI/FileManager/MessagesDialog.cpp old mode 100755 new mode 100644 index 05aa823f..41248277 --- a/CPP/7zip/UI/FileManager/MessagesDialog.cpp +++ b/CPP/7zip/UI/FileManager/MessagesDialog.cpp @@ -2,32 +2,25 @@ #include "StdAfx.h" -#include "Common/IntToString.h" +#include "../../../Common/IntToString.h" -#include "Windows/ResourceString.h" +#include "../../../Windows/ResourceString.h" #include "MessagesDialog.h" -#ifdef LANG #include "LangUtils.h" -#endif -using namespace NWindows; +#include "ProgressDialog2Res.h" -#ifdef LANG -static CIDLangPair kIDLangPairs[] = -{ - { IDOK, 0x02000713 } -}; -#endif +using namespace NWindows; 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); + int i = _messageList.GetItemCount(); + wchar_t sz[16]; + ConvertUInt32ToString((UInt32)i, sz); + _messageList.InsertItem(i, sz); + _messageList.SetSubItem(i, 1, message); } void CMessagesDialog::AddMessage(LPCWSTR message) @@ -39,7 +32,7 @@ void CMessagesDialog::AddMessage(LPCWSTR message) if (pos < 0) break; AddMessageDirect(s.Left(pos)); - s.Delete(0, pos + 1); + s.DeleteFrontal(pos + 1); } AddMessageDirect(s); } @@ -47,24 +40,17 @@ void CMessagesDialog::AddMessage(LPCWSTR message) bool CMessagesDialog::OnInit() { #ifdef LANG - LangSetWindowText(HWND(*this), 0x02000A00); - LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + LangSetWindowText(*this, IDD_MESSAGES); + LangSetDlgItems(*this, NULL, 0); + SetItemText(IDOK, LangString(IDS_CLOSE)); #endif - _messageList.Attach(GetItem(IDC_MESSAGE_LIST)); + _messageList.Attach(GetItem(IDL_MESSAGE)); _messageList.SetUnicodeFormat(); _messageList.InsertColumn(0, L"", 30); + _messageList.InsertColumn(1, LangString(IDS_MESSAGE), 600); - 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++) + FOR_VECTOR (i, *Messages) AddMessage((*Messages)[i]); _messageList.SetColumnWidthAuto(0); diff --git a/CPP/7zip/UI/FileManager/MessagesDialog.h b/CPP/7zip/UI/FileManager/MessagesDialog.h old mode 100755 new mode 100644 index 1304d516..5c017eb4 --- a/CPP/7zip/UI/FileManager/MessagesDialog.h +++ b/CPP/7zip/UI/FileManager/MessagesDialog.h @@ -3,21 +3,23 @@ #ifndef __MESSAGES_DIALOG_H #define __MESSAGES_DIALOG_H -#include "Windows/Control/Dialog.h" -#include "Windows/Control/ListView.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); } + + INT_PTR Create(HWND parent = 0) { return CModalDialog::Create(IDD_MESSAGES, parent); } }; #endif diff --git a/CPP/7zip/UI/FileManager/MessagesDialog.rc b/CPP/7zip/UI/FileManager/MessagesDialog.rc old mode 100755 new mode 100644 index fb2f0f7d..49b73e84 --- a/CPP/7zip/UI/FileManager/MessagesDialog.rc +++ b/CPP/7zip/UI/FileManager/MessagesDialog.rc @@ -4,11 +4,11 @@ #define xc 440 #define yc 160 -IDD_DIALOG_MESSAGES MY_RESIZE_DIALOG +IDD_MESSAGES DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT CAPTION "7-Zip: Diagnostic messages" { DEFPUSHBUTTON "&Close", IDOK, bx, by, bxs, bys - CONTROL "List1", IDC_MESSAGE_LIST, "SysListView32", + CONTROL "List1", IDL_MESSAGE, "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 old mode 100755 new mode 100644 index 39d49f57..c8fffff6 --- a/CPP/7zip/UI/FileManager/MessagesDialogRes.h +++ b/CPP/7zip/UI/FileManager/MessagesDialogRes.h @@ -1,3 +1,3 @@ -#define IDS_MESSAGES_DIALOG_MESSAGE_COLUMN 503 -#define IDD_DIALOG_MESSAGES 503 -#define IDC_MESSAGE_LIST 1000 +#define IDD_MESSAGES 6602 +#define IDS_MESSAGE 6603 +#define IDL_MESSAGE 100 diff --git a/CPP/7zip/UI/FileManager/Move.bmp b/CPP/7zip/UI/FileManager/Move.bmp old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/Move2.bmp b/CPP/7zip/UI/FileManager/Move2.bmp old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/MyCom2.h b/CPP/7zip/UI/FileManager/MyCom2.h old mode 100755 new mode 100644 index 98b1d708..224a838d --- a/CPP/7zip/UI/FileManager/MyCom2.h +++ b/CPP/7zip/UI/FileManager/MyCom2.h @@ -3,7 +3,7 @@ #ifndef __MYCOM2_H #define __MYCOM2_H -#include "Common/MyCom.h" +#include "../../../Common/MyCom.h" #define MY_ADDREF_RELEASE_MT \ STDMETHOD_(ULONG, AddRef)() { InterlockedIncrement((LONG *)&__m_RefCount); return __m_RefCount; } \ diff --git a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp old mode 100755 new mode 100644 index b16e8948..401e48ef --- a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp +++ b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp @@ -2,8 +2,8 @@ #include "StdAfx.h" -#include "Windows/Menu.h" -#include "Windows/Control/Dialog.h" +#include "../../../Windows/Menu.h" +#include "../../../Windows/Control/Dialog.h" #include "../../PropID.h" @@ -19,8 +19,8 @@ using namespace NWindows; -static const UINT kOpenBookmarkMenuID = 730; -static const UINT kSetBookmarkMenuID = 740; +static const UINT kOpenBookmarkMenuID = 830; +static const UINT kSetBookmarkMenuID = 810; extern HINSTANCE g_hInstance; @@ -36,102 +36,36 @@ enum kMenuIndex_Bookmarks }; -static const UInt32 kTopMenuLangIDs[] = -{ - 0x03000102, - 0x03000103, - 0x03000104, - 0x03000107, - 0x03000105, - 0x03000106 -}; +static const UInt32 kTopMenuLangIDs[] = { 500, 501, 502, 503, 504, 505 }; -static const UInt32 kAddToFavoritesLangID = 0x03000710; -static const UInt32 kToolbarsLangID = 0x03000451; +static const UInt32 kAddToFavoritesLangID = 800; +static const UInt32 kToolbarsLangID = 733; static const CIDLangPair kIDLangPairs[] = { - // File - { IDM_FILE_OPEN, 0x03000210 }, - { IDM_FILE_OPEN_INSIDE, 0x03000211 }, - { IDM_FILE_OPEN_OUTSIDE, 0x03000212 }, - { IDM_FILE_VIEW, 0x03000220 }, - { IDM_FILE_EDIT, 0x03000221 }, - { IDM_RENAME, 0x03000230 }, - { IDM_COPY_TO, 0x03000231 }, - { IDM_MOVE_TO, 0x03000232 }, - { IDM_DELETE, 0x03000233 }, - { IDM_FILE_PROPERTIES, 0x03000240 }, - { IDM_FILE_COMMENT, 0x03000241 }, - { IDM_FILE_CRC, 0x03000242 }, - { IDM_FILE_DIFF, 0x03000243 }, - { IDM_FILE_SPLIT, 0x03000270 }, - { IDM_FILE_COMBINE, 0x03000271 }, - { IDM_CREATE_FOLDER, 0x03000250 }, - { IDM_CREATE_FILE, 0x03000251 }, - { IDCLOSE, 0x03000260 }, - - // Edit - { IDM_EDIT_CUT, 0x03000320 }, - { IDM_EDIT_COPY, 0x03000321 }, - { IDM_EDIT_PASTE, 0x03000322 }, - - { IDM_SELECT_ALL, 0x03000330 }, - { IDM_DESELECT_ALL, 0x03000331 }, - { IDM_INVERT_SELECTION, 0x03000332 }, - { IDM_SELECT, 0x03000333 }, - { IDM_DESELECT, 0x03000334 }, - { IDM_SELECT_BY_TYPE, 0x03000335 }, - { IDM_DESELECT_BY_TYPE, 0x03000336 }, - - { IDM_VIEW_LARGE_ICONS, 0x03000410 }, - { IDM_VIEW_SMALL_ICONS, 0x03000411 }, - { IDM_VIEW_LIST, 0x03000412 }, - { IDM_VIEW_DETAILS, 0x03000413 }, - - { IDM_VIEW_ARANGE_BY_NAME, 0x02000204 }, - { IDM_VIEW_ARANGE_BY_TYPE, 0x02000214 }, - { IDM_VIEW_ARANGE_BY_DATE, 0x0200020C }, - { IDM_VIEW_ARANGE_BY_SIZE, 0x02000207 }, - { IDM_VIEW_ARANGE_NO_SORT, 0x03000420 }, - - { IDM_OPEN_ROOT_FOLDER, 0x03000430 }, - { IDM_OPEN_PARENT_FOLDER, 0x03000431 }, - { IDM_FOLDERS_HISTORY, 0x03000432 }, - - { IDM_VIEW_REFRESH, 0x03000440 }, - - { IDM_VIEW_FLAT_VIEW, 0x03000449 }, - { IDM_VIEW_TWO_PANELS, 0x03000450 }, - { IDM_VIEW_ARCHIVE_TOOLBAR, 0x03000460 }, - { IDM_VIEW_STANDARD_TOOLBAR, 0x03000461 }, - { IDM_VIEW_TOOLBARS_LARGE_BUTTONS, 0x03000462 }, - { IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT, 0x03000463 }, - - { IDM_OPTIONS, 0x03000510 }, - { IDM_BENCHMARK, 0x03000511 }, - - { IDM_HELP_CONTENTS, 0x03000610 }, - { IDM_ABOUT, 0x03000620 } + { IDCLOSE, 557 }, + { IDM_VIEW_ARANGE_BY_NAME, 1004 }, + { IDM_VIEW_ARANGE_BY_TYPE, 1020 }, + { IDM_VIEW_ARANGE_BY_DATE, 1012 }, + { IDM_VIEW_ARANGE_BY_SIZE, 1007 } }; - -static int FindLangItem(int ControlID) +static int FindLangItem(unsigned controlID) { - for (int i = 0; i < sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]); i++) - if (kIDLangPairs[i].ControlID == ControlID) + for (unsigned i = 0; i < ARRAY_SIZE(kIDLangPairs); i++) + if (kIDLangPairs[i].ControlID == controlID) return i; return -1; } static int GetSortControlID(PROPID propID) { - switch(propID) + switch (propID) { - case kpidName: return IDM_VIEW_ARANGE_BY_NAME; - case kpidExtension: return IDM_VIEW_ARANGE_BY_TYPE; - case kpidMTime: return IDM_VIEW_ARANGE_BY_DATE; - case kpidSize: return IDM_VIEW_ARANGE_BY_SIZE; + case kpidName: return IDM_VIEW_ARANGE_BY_NAME; + case kpidExtension: return IDM_VIEW_ARANGE_BY_TYPE; + case kpidMTime: return IDM_VIEW_ARANGE_BY_DATE; + case kpidSize: return IDM_VIEW_ARANGE_BY_SIZE; case kpidNoProperty: return IDM_VIEW_ARANGE_NO_SORT; } return -1; @@ -203,27 +137,30 @@ static void MyChangeMenu(HMENU menuLoc, int level, int menuIndex) MyChangeMenu(item.hSubMenu, level + 1, i); if (level == 1 && menuIndex == kMenuIndex_View) langID = kToolbarsLangID; - else if (level == 0 && i < sizeof(kTopMenuLangIDs) / sizeof(kTopMenuLangIDs[0])) + else if (level == 0 && i < ARRAY_SIZE(kTopMenuLangIDs)) langID = kTopMenuLangIDs[i]; else continue; } - newString = LangString(langID); + LangString_OnlyFromLangFile(langID, newString); if (newString.IsEmpty()) continue; } else { - int langPos = FindLangItem(item.wID); - if (langPos < 0) + if (item.IsSeparator()) continue; - newString = LangString(kIDLangPairs[langPos].LangID); + int langPos = FindLangItem(item.wID); + + // we don't need lang change for CRC items!!! + LangString_OnlyFromLangFile(langPos >= 0 ? kIDLangPairs[langPos].LangID : item.wID, newString); if (newString.IsEmpty()) continue; + UString shorcutString = item.StringValue; int tabPos = shorcutString.ReverseFind(wchar_t('\t')); if (tabPos >= 0) - newString += shorcutString.Mid(tabPos); + newString += shorcutString.Ptr(tabPos); } { item.StringValue = newString; @@ -243,6 +180,19 @@ struct CFileMenuDestroyer } g_FileMenuDestroyer; +static void CopyMenu(HMENU srcMenuSpec, HMENU destMenuSpec); + +static void CopyPopMenu_IfRequired(CMenuItem &item) +{ + if (item.hSubMenu) + { + CMenu popup; + popup.CreatePopup(); + CopyMenu(item.hSubMenu, popup); + item.hSubMenu = popup; + } +} + static void CopyMenu(HMENU srcMenuSpec, HMENU destMenuSpec) { CMenu srcMenu; @@ -253,15 +203,15 @@ static void CopyMenu(HMENU srcMenuSpec, HMENU destMenuSpec) for (int i = 0;; i++) { CMenuItem item; - item.fMask = MIIM_STATE | MIIM_ID | Get_fMaskForFTypeAndString(); + item.fMask = MIIM_SUBMENU | MIIM_STATE | MIIM_ID | Get_fMaskForFTypeAndString(); item.fType = MFT_STRING; - if (srcMenu.GetItem(i, true, item)) - { - if (destMenu.InsertItem(startPos, true, item)) - startPos++; - } - else + + if (!srcMenu.GetItem(i, true, item)) break; + + CopyPopMenu_IfRequired(item); + if (destMenu.InsertItem(startPos, true, item)) + startPos++; } } @@ -274,7 +224,7 @@ void MyLoadMenu() HMENU oldMenu = g_App._commandBar.GetMenu(0); if (oldMenu) ::DestroyMenu(oldMenu); - BOOL b = g_App._commandBar.InsertMenubar(g_hInstance, IDM_MENU, 0); + /* 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); @@ -344,6 +294,9 @@ void OnMenuActivating(HWND /* hWnd */, HMENU hMenu, int position) 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); + menu.CheckItemByID(IDM_VIEW_AUTO_REFRESH, g_App.Get_AutoRefresh_Mode()); + // menu.CheckItemByID(IDM_VIEW_SHOW_STREAMS, g_App.Get_ShowNtfsStrems_Mode()); + // menu.CheckItemByID(IDM_VIEW_SHOW_DELETED, g_App.ShowDeletedFiles); } else if (position == kMenuIndex_Bookmarks) { @@ -356,8 +309,8 @@ void OnMenuActivating(HWND /* hWnd */, HMENU hMenu, int position) int i; for (i = 0; i < 10; i++) { - UString s = LangString(IDS_BOOKMARK, 0x03000720); - s += L" "; + UString s = LangString(IDS_BOOKMARK); + s += L' '; wchar_t c = (wchar_t)(L'0' + i); s += c; s += L"\tAlt+Shift+"; @@ -369,17 +322,16 @@ void OnMenuActivating(HWND /* hWnd */, HMENU hMenu, int position) for (i = 0; i < 10; i++) { - UString path = g_App.AppState.FastFolders.GetString(i); + UString s = g_App.AppState.FastFolders.GetString(i); const int kMaxSize = 100; const int kFirstPartSize = kMaxSize / 2; - if (path.Length() > kMaxSize) + if (s.Len() > kMaxSize) { - path = path.Left(kFirstPartSize) + UString(L" ... ") + - path.Right(kMaxSize - kFirstPartSize); + s.Delete(kFirstPartSize, s.Len() - kMaxSize); + s.Insert(kFirstPartSize, L" ... "); } - UString s = path; if (s.IsEmpty()) - s = L"-"; + s = L'-'; s += L"\tAlt+"; s += (wchar_t)(L'0' + i); menu.AppendItem(MF_STRING, kOpenBookmarkMenuID + i, s); @@ -410,7 +362,7 @@ void LoadFileMenu(HMENU hMenu, int startPos, bool programMenu, { CMenuItem item; - item.fMask = MIIM_STATE | MIIM_ID | Get_fMaskForFTypeAndString(); + item.fMask = MIIM_SUBMENU | MIIM_STATE | MIIM_ID | Get_fMaskForFTypeAndString(); item.fType = MFT_STRING; if (!g_FileMenu.GetItem(i, true, item)) break; @@ -418,20 +370,24 @@ void LoadFileMenu(HMENU hMenu, int startPos, bool programMenu, if (!programMenu && item.wID == IDCLOSE) continue; - if (item.wID == IDM_FILE_DIFF && diffPath.IsEmpty()) + if (item.wID == IDM_DIFF && diffPath.IsEmpty()) continue; bool isOneFsFile = (isFsFolder && numItems == 1 && allAreFiles); - bool disable = ((item.wID == IDM_FILE_SPLIT || item.wID == IDM_FILE_COMBINE) && !isOneFsFile); + bool disable = (!isOneFsFile && (item.wID == IDM_SPLIT || item.wID == IDM_COMBINE)); bool isBigScreen = NControl::IsDialogSizeOK(40, 200); if (!isBigScreen && (disable || item.IsSeparator())) continue; + + CopyPopMenu_IfRequired(item); if (destMenu.InsertItem(startPos, true, item)) + { + if (disable) + destMenu.EnableItem(startPos, MF_BYPOSITION | MF_GRAYED); startPos++; - if (disable) - destMenu.EnableItem(startPos - 1, MF_BYPOSITION | MF_GRAYED); + } if (!item.IsSeparator()) numRealItems = startPos; @@ -442,7 +398,7 @@ void LoadFileMenu(HMENU hMenu, int startPos, bool programMenu, bool ExecuteFileCommand(int id) { - if (id >= kPluginMenuStartID) + if (id >= kMenuCmdID_Plugin_Start) { g_App.GetFocusedPanel().InvokePluginCommand(id); g_App.GetFocusedPanel()._sevenZipContextMenu.Release(); @@ -453,62 +409,33 @@ bool ExecuteFileCommand(int id) 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; + case IDM_OPEN: g_App.OpenItem(); break; + case IDM_OPEN_INSIDE: g_App.OpenItemInside(); break; + case IDM_OPEN_OUTSIDE: g_App.OpenItemOutside(); break; + case IDM_FILE_VIEW: g_App.EditItem(false); break; + case IDM_FILE_EDIT: g_App.EditItem(true); 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: g_App.Delete(!IsKeyDown(VK_SHIFT)); break; + + case IDM_HASH_ALL: g_App.CalculateCrc(L"*"); break; + case IDM_CRC32: g_App.CalculateCrc(L"CRC32"); break; + case IDM_CRC64: g_App.CalculateCrc(L"CRC64"); break; + case IDM_SHA1: g_App.CalculateCrc(L"SHA1"); break; + case IDM_SHA256: g_App.CalculateCrc(L"SHA256"); break; + + case IDM_DIFF: g_App.DiffFiles(); break; + case IDM_SPLIT: g_App.Split(); break; + case IDM_COMBINE: g_App.Combine(); break; + case IDM_PROPERTIES: g_App.Properties(); break; + case IDM_COMMENT: g_App.Comment(); break; + case IDM_CREATE_FOLDER: g_App.CreateFolder(); break; + case IDM_CREATE_FILE: g_App.CreateFile(); break; + #ifndef UNDER_CE + case IDM_LINK: g_App.Link(); break; + #endif + default: return false; } return true; } @@ -534,6 +461,7 @@ bool OnMenuCommand(HWND hWnd, int id) break; // Edit + /* case IDM_EDIT_CUT: g_App.EditCut(); break; @@ -543,6 +471,7 @@ bool OnMenuCommand(HWND hWnd, int id) case IDM_EDIT_PASTE: g_App.EditPaste(); break; + */ case IDM_SELECT_ALL: g_App.SelectAll(true); g_App.Refresh_StatusBar(); @@ -591,67 +520,38 @@ bool OnMenuCommand(HWND hWnd, int id) } 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: + 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_FLAT_VIEW: g_App.ChangeFlatMode(); break; + case IDM_VIEW_REFRESH: g_App.RefreshView(); break; + case IDM_VIEW_AUTO_REFRESH: g_App.Change_AutoRefresh_Mode(); break; + + // case IDM_VIEW_SHOW_STREAMS: g_App.Change_ShowNtfsStrems_Mode(); break; + /* + case IDM_VIEW_SHOW_DELETED: { - g_App.SortItemsWithPropID(kpidNoProperty); - break; + g_App.Change_ShowDeleted(); + bool isChecked = g_App.ShowDeletedFiles; + Save_ShowDeleted(isChecked); } + */ + + 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_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; + 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_OPTIONS: OptionsDialog(hWnd, g_hInstance); break; case IDM_BENCHMARK: MyBenchmark(false); break; case IDM_BENCHMARK2: MyBenchmark(true); break; diff --git a/CPP/7zip/UI/FileManager/MyLoadMenu.h b/CPP/7zip/UI/FileManager/MyLoadMenu.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/MyWindowsNew.h b/CPP/7zip/UI/FileManager/MyWindowsNew.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/NetFolder.cpp b/CPP/7zip/UI/FileManager/NetFolder.cpp old mode 100755 new mode 100644 index 07387328..f3d531ab --- a/CPP/7zip/UI/FileManager/NetFolder.cpp +++ b/CPP/7zip/UI/FileManager/NetFolder.cpp @@ -2,7 +2,7 @@ #include "StdAfx.h" -#include "Windows/PropVariant.h" +#include "../../../Windows/PropVariant.h" #include "../../PropID.h" @@ -13,23 +13,23 @@ using namespace NWindows; using namespace NNet; -static const STATPROPSTG kProps[] = +static const PROPID kProps[] = { - { NULL, kpidName, VT_BSTR}, - { NULL, kpidLocalName, VT_BSTR}, - { NULL, kpidComment, VT_BSTR}, - { NULL, kpidProvider, VT_BSTR} + kpidName, + kpidLocalName, + kpidComment, + kpidProvider }; void CNetFolder::Init(const UString &path) { /* - if (path.Length() > 2) + if (path.Len() > 2) { if (path[0] == L'\\' && path[1] == L'\\') { CResource netResource; - netResource.RemoteName = GetSystemString(path.Left(path.Length() - 1)); + netResource.RemoteName = GetSystemString(path.Left(path.Len() - 1)); netResource.Scope = RESOURCE_GLOBALNET; netResource.Type = RESOURCETYPE_DISK; netResource.DisplayType = RESOURCEDISPLAYTYPE_SERVER; @@ -42,7 +42,8 @@ void CNetFolder::Init(const UString &path) */ CResourceW resource; resource.RemoteNameIsDefined = true; - resource.RemoteName = path.Left(path.Length() - 1); + if (!path.IsEmpty()) + resource.RemoteName.SetFrom(path, path.Len() - 1); resource.ProviderIsDefined = false; resource.LocalNameIsDefined = false; resource.CommentIsDefined = false; @@ -114,7 +115,7 @@ STDMETHODIMP CNetFolder::LoadItems() if (pos >= 0) { // _path = resource.Name.Left(pos + 1); - resource.Name = resource.Name.Mid(pos + 1); + resource.Name.DeleteFrontal(pos + 1); } _items.Add(resource); } diff --git a/CPP/7zip/UI/FileManager/NetFolder.h b/CPP/7zip/UI/FileManager/NetFolder.h old mode 100755 new mode 100644 index 9962845c..151dd096 --- a/CPP/7zip/UI/FileManager/NetFolder.h +++ b/CPP/7zip/UI/FileManager/NetFolder.h @@ -3,9 +3,9 @@ #ifndef __NET_FOLDER_H #define __NET_FOLDER_H -#include "Common/MyCom.h" +#include "../../../Common/MyCom.h" -#include "Windows/Net.h" +#include "../../../Windows/Net.h" #include "IFolder.h" diff --git a/CPP/7zip/UI/FileManager/OpenCallback.cpp b/CPP/7zip/UI/FileManager/OpenCallback.cpp old mode 100755 new mode 100644 index 95daf37a..d5afb2da --- a/CPP/7zip/UI/FileManager/OpenCallback.cpp +++ b/CPP/7zip/UI/FileManager/OpenCallback.cpp @@ -2,9 +2,11 @@ #include "StdAfx.h" -#include "Common/StringConvert.h" +#include "../../../Common/ComTry.h" +#include "../../../Common/StringConvert.h" -#include "Windows/PropVariant.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/PropVariant.h" #include "../../Common/FileStreams.h" @@ -17,44 +19,40 @@ using namespace NWindows; STDMETHODIMP COpenArchiveCallback::SetTotal(const UInt64 *numFiles, const UInt64 *numBytes) { - RINOK(ProgressDialog.Sync.ProcessStopAndPause()); + RINOK(ProgressDialog.Sync.CheckStop()); { - NSynchronization::CCriticalSectionLock lock(_criticalSection); - if (numFiles != NULL) + // NSynchronization::CCriticalSectionLock lock(_criticalSection); + if (numFiles) { - ProgressDialog.Sync.SetNumFilesTotal(*numFiles); - ProgressDialog.Sync.SetBytesProgressMode(false); + ProgressDialog.Sync.Set_NumFilesTotal(*numFiles); + ProgressDialog.Sync.Set_BytesProgressMode(false); } - if (numBytes != NULL) - ProgressDialog.Sync.SetNumBytesTotal(*numBytes); + if (numBytes) + ProgressDialog.Sync.Set_NumBytesTotal(*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; + // NSynchronization::CCriticalSectionLock lock(_criticalSection); + if (numFiles) + ProgressDialog.Sync.Set_NumFilesCur(*numFiles); + if (numBytes) + ProgressDialog.Sync.Set_NumBytesCur(*numBytes); + return ProgressDialog.Sync.CheckStop(); } STDMETHODIMP COpenArchiveCallback::SetTotal(const UInt64 total) { - RINOK(ProgressDialog.Sync.ProcessStopAndPause()); - ProgressDialog.Sync.SetNumBytesTotal(total); + RINOK(ProgressDialog.Sync.CheckStop()); + ProgressDialog.Sync.Set_NumBytesTotal(total); return S_OK; } STDMETHODIMP COpenArchiveCallback::SetCompleted(const UInt64 *completed) { - RINOK(ProgressDialog.Sync.ProcessStopAndPause()); - if (completed != NULL) - ProgressDialog.Sync.SetPos(*completed); - return S_OK; + return ProgressDialog.Sync.Set_NumBytesCur(completed); } STDMETHODIMP COpenArchiveCallback::GetProperty(PROPID propID, PROPVARIANT *value) @@ -86,16 +84,16 @@ STDMETHODIMP COpenArchiveCallback::GetProperty(PROPID propID, PROPVARIANT *value STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, IInStream **inStream) { + COM_TRY_BEGIN *inStream = NULL; if (_subArchiveMode) return S_FALSE; - NFile::NFind::CFileInfo fileInfo; - - FString fullPath = _folderPrefix + us2fs(name); - if (!fileInfo.Find(fullPath)) + FString fullPath; + if (!NFile::NName::GetFullPath(_folderPrefix, us2fs(name), fullPath)) + return S_FALSE; + if (!_fileInfo.Find(fullPath)) return S_FALSE; - _fileInfo = fileInfo; if (_fileInfo.IsDir()) return S_FALSE; CInFileStream *inFile = new CInFileStream; @@ -104,10 +102,12 @@ STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, IInStream **in return ::GetLastError(); *inStream = inStreamTemp.Detach(); return S_OK; + COM_TRY_END } STDMETHODIMP COpenArchiveCallback::CryptoGetTextPassword(BSTR *password) { + COM_TRY_BEGIN PasswordWasAsked = true; if (!PasswordIsDefined) { @@ -116,7 +116,7 @@ STDMETHODIMP COpenArchiveCallback::CryptoGetTextPassword(BSTR *password) dialog.ShowPassword = showPassword; ProgressDialog.WaitCreating(); - if (dialog.Create(ProgressDialog) == IDCANCEL) + if (dialog.Create(ProgressDialog) != IDOK) return E_ABORT; Password = dialog.Password; @@ -125,4 +125,5 @@ STDMETHODIMP COpenArchiveCallback::CryptoGetTextPassword(BSTR *password) NExtract::Save_ShowPassword(dialog.ShowPassword); } return StringToBstr(Password, password); + COM_TRY_END } diff --git a/CPP/7zip/UI/FileManager/OpenCallback.h b/CPP/7zip/UI/FileManager/OpenCallback.h old mode 100755 new mode 100644 index a0c0167e..c952d7b0 --- a/CPP/7zip/UI/FileManager/OpenCallback.h +++ b/CPP/7zip/UI/FileManager/OpenCallback.h @@ -1,12 +1,11 @@ // OpenCallback.h -#ifndef __OPENCALLBACK_H -#define __OPENCALLBACK_H +#ifndef __OPEN_CALLBACK_H +#define __OPEN_CALLBACK_H -#include "Common/MyCom.h" -#include "Common/MyString.h" +#include "../../../Common/MyCom.h" -#include "Windows/FileFind.h" +#include "../../../Windows/FileFind.h" #include "../../IPassword.h" @@ -29,7 +28,7 @@ class COpenArchiveCallback: { FString _folderPrefix; NWindows::NFile::NFind::CFileInfo _fileInfo; - NWindows::NSynchronization::CCriticalSection _criticalSection; + // NWindows::NSynchronization::CCriticalSection _criticalSection; bool _subArchiveMode; UString _subArchiveName; @@ -58,7 +57,7 @@ public: { _subArchiveMode = true; _subArchiveName = name; - return S_OK; + return S_OK; } COpenArchiveCallback(): diff --git a/CPP/7zip/UI/FileManager/OptionsDialog.cpp b/CPP/7zip/UI/FileManager/OptionsDialog.cpp old mode 100755 new mode 100644 index a1ef1b1d..fa2ab922 --- a/CPP/7zip/UI/FileManager/OptionsDialog.cpp +++ b/CPP/7zip/UI/FileManager/OptionsDialog.cpp @@ -2,8 +2,8 @@ #include "StdAfx.h" -#include "Windows/Control/Dialog.h" -#include "Windows/Control/PropertyPage.h" +#include "../../../Windows/Control/Dialog.h" +#include "../../../Windows/Control/PropertyPage.h" #include "DialogSize.h" #include "EditPage.h" @@ -92,41 +92,36 @@ void OptionsDialog(HWND hwndOwner, HINSTANCE /* hInstance */) CFoldersPage foldersPage; CObjectVector pages; - const 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]); + const int kNumPages = ARRAY_SIZE(pageIDs); for (int i = 0; i < kNumPages; i++) { NControl::CPageInfo page; - page.Title = LangString(langIDs[i]); page.ID = pageIDs[i]; + LangString_OnlyFromLangFile(page.ID, page.Title); page.Page = pagePinters[i]; pages.Add(page); } - INT_PTR res = NControl::MyPropertySheet(pages, hwndOwner, LangString(IDS_OPTIONS, 0x03010000)); + INT_PTR res = NControl::MyPropertySheet(pages, hwndOwner, LangString(IDS_OPTIONS)); if (res != -1 && res != 0) { if (langPage.LangWasChanged) { - g_App._window.SetText(LangString(IDS_APP_TITLE, 0x03000000)); + // g_App._window.SetText(LangString(IDS_APP_TITLE, 0x03000000)); MyLoadMenu(); g_App.ReloadToolbars(); g_App.MoveSubWindows(); + g_App.ReloadLang(); } /* if (systemPage.WasChanged) diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.cpp b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp old mode 100755 new mode 100644 index 5f072daf..a657bc90 --- a/CPP/7zip/UI/FileManager/OverwriteDialog.cpp +++ b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp @@ -2,48 +2,44 @@ #include "StdAfx.h" -#include "Common/StringConvert.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 "../../../Windows/PropVariantConv.h" +#include "../../../Windows/ResourceString.h" + +#include "../../../Windows/Control/Static.h" #include "FormatUtils.h" +#include "LangUtils.h" #include "OverwriteDialog.h" -// #include "../resource.h" - -#ifdef LANG -#include "LangUtils.h" -#endif +#include "PropertyNameRes.h" using namespace NWindows; #ifdef LANG -static CIDLangPair kIDLangPairs[] = +static const UInt32 kLangIDs[] = { - { 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 } + IDT_OVERWRITE_HEADER, + IDT_OVERWRITE_QUESTION_BEGIN, + IDT_OVERWRITE_QUESTION_END, + IDB_YES_TO_ALL, + IDB_NO_TO_ALL, + IDB_AUTO_RENAME }; #endif -static const int kCurrentFileNameSizeLimit = 82; -static const int kCurrentFileNameSizeLimit2 = 30; +static const unsigned kCurrentFileNameSizeLimit = 82; +static const unsigned 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); + unsigned size = _isBig ? kCurrentFileNameSizeLimit : kCurrentFileNameSizeLimit2; + if (s.Len() > size) + { + s.Delete(size / 2, s.Len() - size); + s.Insert(size / 2, L" ... "); + } } void COverwriteDialog::SetFileInfoControl(int textID, int iconID, @@ -51,52 +47,38 @@ void COverwriteDialog::SetFileInfoControl(int textID, int iconID, { UString sizeString; if (fileInfo.SizeIsDefined) - sizeString = MyFormatNew(IDS_FILE_SIZE, - #ifdef LANG - 0x02000982, - #endif - NumberToString(fileInfo.Size)); + sizeString = MyFormatNew(IDS_FILE_SIZE, 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; + UString s1 = fileName.Left(slashPos + 1); + UString s2 = fileName.Ptr(slashPos + 1); + ReduceString(s1); ReduceString(s2); - UString fullString = s1 + L'\n' + s2; - fullString += L'\n'; - fullString += sizeString; - fullString += L'\n'; + UString s = s1; + s += L'\n'; + s += s2; + s += L'\n'; + s += sizeString; + s += 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; + s += LangString(IDS_PROP_MTIME); + s += L": "; + wchar_t t[32]; + ConvertFileTimeToString(localFileTime, t); + s += t; } - NWindows::NControl::CDialogChildControl control; + NControl::CDialogChildControl control; control.Init(*this, textID); - control.SetText(fullString); + control.SetText(s); SHFILEINFO shellFileInfo; if (::SHGetFileInfo( @@ -112,24 +94,24 @@ void COverwriteDialog::SetFileInfoControl(int textID, int iconID, bool COverwriteDialog::OnInit() { #ifdef LANG - LangSetWindowText(HWND(*this), 0x02000900); - LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + LangSetWindowText(*this, IDD_OVERWRITE); + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); #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); + SetFileInfoControl(IDT_OVERWRITE_OLD_FILE_SIZE_TIME, IDI_OVERWRITE_OLD_FILE, OldFileInfo); + SetFileInfoControl(IDT_OVERWRITE_NEW_FILE_SIZE_TIME, IDI_OVERWRITE_NEW_FILE, NewFileInfo); NormalizePosition(); return CModalDialog::OnInit(); } bool COverwriteDialog::OnButtonClicked(int buttonID, HWND buttonHWND) { - switch(buttonID) + 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: + case IDB_YES_TO_ALL: + case IDB_NO_TO_ALL: + case IDB_AUTO_RENAME: End(buttonID); return true; } diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.h b/CPP/7zip/UI/FileManager/OverwriteDialog.h old mode 100755 new mode 100644 index f760611e..da7fa55f --- a/CPP/7zip/UI/FileManager/OverwriteDialog.h +++ b/CPP/7zip/UI/FileManager/OverwriteDialog.h @@ -3,9 +3,7 @@ #ifndef __OVERWRITE_DIALOG_H #define __OVERWRITE_DIALOG_H -#include "Common/Types.h" - -#include "Windows/Control/Dialog.h" +#include "../../../Windows/Control/Dialog.h" #include "DialogSize.h" #include "OverwriteDialogRes.h" @@ -61,7 +59,7 @@ public: #else _isBig = true; #endif - return CModalDialog::Create(SIZED_DIALOG(IDD_DIALOG_OVERWRITE), parent); + return CModalDialog::Create(SIZED_DIALOG(IDD_OVERWRITE), parent); } NOverwriteDialog::CFileInfo OldFileInfo; diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.rc b/CPP/7zip/UI/FileManager/OverwriteDialog.rc old mode 100755 new mode 100644 index 8961d28b..29f99122 --- a/CPP/7zip/UI/FileManager/OverwriteDialog.rc +++ b/CPP/7zip/UI/FileManager/OverwriteDialog.rc @@ -18,26 +18,26 @@ #undef bx1 #define bx1 (xs - m - bSizeBig) -IDD_DIALOG_OVERWRITE MY_DIALOG +IDD_OVERWRITE DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT CAPTION "Confirm File Replace" BEGIN - LTEXT "Destination folder already contains processed file.", 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 + LTEXT "Destination folder already contains processed file.", IDT_OVERWRITE_HEADER, m, 7, xc, 8 + LTEXT "Would you like to replace the existing file", IDT_OVERWRITE_QUESTION_BEGIN, m, 28, xc, 8 - ICON "", IDC_STATIC_OVERWRITE_OLD_FILE_ICON, m, 44, iconSize, iconSize - LTEXT "", IDC_STATIC_OVERWRITE_OLD_FILE_SIZE_TIME, x, 44, fx, fy, SS_NOPREFIX + ICON "", IDI_OVERWRITE_OLD_FILE, m, 44, iconSize, iconSize + LTEXT "", IDT_OVERWRITE_OLD_FILE_SIZE_TIME, x, 44, fx, fy, SS_NOPREFIX - LTEXT "with this one?",IDC_STATIC_OVERWRITE_QUESTION_END, m, 98, xc, 8 + LTEXT "with this one?", IDT_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 + ICON "", IDI_OVERWRITE_NEW_FILE, m, 114, iconSize, iconSize + LTEXT "", IDT_OVERWRITE_NEW_FILE_SIZE_TIME, x, 114, fx, fy, SS_NOPREFIX - PUSHBUTTON "&Yes", IDYES, bx3, by2, bxs, bys - PUSHBUTTON "Yes to &All", 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 + PUSHBUTTON "&Yes", IDYES, bx3, by2, bxs, bys + PUSHBUTTON "Yes to &All", IDB_YES_TO_ALL, bx2, by2, bxs, bys + PUSHBUTTON "A&uto Rename", IDB_AUTO_RENAME, bx1, by2, bSizeBig, bys + PUSHBUTTON "&No", IDNO, bx3, by1, bxs, bys + PUSHBUTTON "No to A&ll", IDB_NO_TO_ALL, bx2, by1, bxs, bys + PUSHBUTTON "&Cancel", IDCANCEL, xs - m - bxs, by1, bxs, bys END @@ -61,25 +61,25 @@ END #define bx1 (xs - m - bxs) -IDD_DIALOG_OVERWRITE_2 MY_DIALOG +IDD_OVERWRITE_2 DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT CAPTION "Confirm File Replace" BEGIN - LTEXT "Would you like to replace the existing file", IDC_STATIC_OVERWRITE_QUESTION_BEGIN, m, m, xc, 8 + LTEXT "Would you like to replace the existing file", IDT_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 + ICON "", IDI_OVERWRITE_OLD_FILE, m, 20, iconSize, iconSize + LTEXT "", IDT_OVERWRITE_OLD_FILE_SIZE_TIME, x, 20, fx, fy, SS_NOPREFIX - LTEXT "with this one?",IDC_STATIC_OVERWRITE_QUESTION_END, m, 60, xc, 8 + LTEXT "with this one?", IDT_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 + ICON "", IDI_OVERWRITE_NEW_FILE, m, 72, iconSize, iconSize + LTEXT "", IDT_OVERWRITE_NEW_FILE_SIZE_TIME, x, 72, fx, fy, SS_NOPREFIX - PUSHBUTTON "&Yes", IDYES, bx3, by2, bxs, bys - PUSHBUTTON "Yes to &All", 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 + PUSHBUTTON "&Yes", IDYES, bx3, by2, bxs, bys + PUSHBUTTON "Yes to &All", IDB_YES_TO_ALL, bx2, by2, bxs, bys + PUSHBUTTON "A&uto Rename", IDB_AUTO_RENAME, bx1, by2, bxs, bys + PUSHBUTTON "&No", IDNO, bx3, by1, bxs, bys + PUSHBUTTON "No to A&ll", IDB_NO_TO_ALL, bx2, by1, bxs, bys + PUSHBUTTON "&Cancel", IDCANCEL, bx1, by1, bxs, bys END #endif @@ -87,6 +87,5 @@ END STRINGTABLE BEGIN - IDS_FILE_MODIFIED "modified on" - IDS_FILE_SIZE "{0} bytes" + IDS_FILE_SIZE "{0} bytes" END diff --git a/CPP/7zip/UI/FileManager/OverwriteDialogRes.h b/CPP/7zip/UI/FileManager/OverwriteDialogRes.h old mode 100755 new mode 100644 index 3bc6900d..b480ba16 --- a/CPP/7zip/UI/FileManager/OverwriteDialogRes.h +++ b/CPP/7zip/UI/FileManager/OverwriteDialogRes.h @@ -1,20 +1,17 @@ -#define IDD_DIALOG_OVERWRITE 502 -#define IDD_DIALOG_OVERWRITE_2 602 +#define IDD_OVERWRITE 3500 +#define IDD_OVERWRITE_2 13500 -#define IDS_FILE_MODIFIED 600 -#define IDS_FILE_SIZE 601 +#define IDT_OVERWRITE_HEADER 3501 +#define IDT_OVERWRITE_QUESTION_BEGIN 3502 +#define IDT_OVERWRITE_QUESTION_END 3503 +#define IDS_FILE_SIZE 3504 -#define IDC_STATIC_OVERWRITE_HEADER 1000 +#define IDB_AUTO_RENAME 3505 +#define IDB_YES_TO_ALL 440 +#define IDB_NO_TO_ALL 441 -#define IDC_STATIC_OVERWRITE_QUESTION_BEGIN 1001 -#define IDC_STATIC_OVERWRITE_QUESTION_END 1002 +#define IDI_OVERWRITE_OLD_FILE 100 +#define IDI_OVERWRITE_NEW_FILE 101 -#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 +#define IDT_OVERWRITE_OLD_FILE_SIZE_TIME 102 +#define IDT_OVERWRITE_NEW_FILE_SIZE_TIME 103 diff --git a/CPP/7zip/UI/FileManager/Panel.cpp b/CPP/7zip/UI/FileManager/Panel.cpp old mode 100755 new mode 100644 index ebbe12b9..d63bdc17 --- a/CPP/7zip/UI/FileManager/Panel.cpp +++ b/CPP/7zip/UI/FileManager/Panel.cpp @@ -4,13 +4,13 @@ #include -#include "Common/Defs.h" -#include "Common/IntToString.h" -#include "Common/StringConvert.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" -#include "Windows/Error.h" -#include "Windows/PropVariant.h" -#include "Windows/Thread.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/Thread.h" #include "../../PropID.h" @@ -29,6 +29,7 @@ #include "Panel.h" #include "RootFolder.h" +#include "PropertyNameRes.h" using namespace NWindows; using namespace NControl; @@ -43,7 +44,6 @@ 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; @@ -94,9 +94,10 @@ HRESULT CPanel::Create(HWND mainWindow, HWND parentWindow, UINT id, if (currentFolderPrefix[0] == L'.') { FString cfpF; - if (NFile::NDirectory::MyGetFullPathName(us2fs(currentFolderPrefix), cfpF)) + if (NFile::NDir::MyGetFullPathName(us2fs(currentFolderPrefix), cfpF)) cfp = fs2us(cfpF); } + RINOK(BindToPath(cfp, arcFormat, archiveIsOpened, encrypted)); if (!CreateEx(0, kClassName, 0, WS_CHILD | WS_VISIBLE, @@ -180,11 +181,9 @@ LRESULT CMyListView::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) */ 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; + bool alt = IsKeyDown(VK_MENU); + bool ctrl = IsKeyDown(VK_CONTROL); + bool shift = IsKeyDown(VK_SHIFT); switch (wParam) { /* @@ -249,6 +248,9 @@ LRESULT CMyComboBox::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) return CallWindowProc(_origWindowProc, *this, message, wParam, lParam); } */ + +#ifndef UNDER_CE + static LRESULT APIENTRY ComboBoxEditSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { CWindow tempDialog(hwnd); @@ -258,6 +260,8 @@ static LRESULT APIENTRY ComboBoxEditSubclassProc(HWND hwnd, UINT message, WPARAM return w->OnMessage(message, wParam, lParam); } +#endif + LRESULT CMyComboBoxEdit::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) { // See MSDN / Subclassing a Combo Box / Creating a Combo-box Toolbar @@ -272,9 +276,9 @@ LRESULT CMyComboBoxEdit::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) // 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; + bool alt = IsKeyDown(VK_MENU); + bool ctrl = IsKeyDown(VK_CONTROL); + bool shift = IsKeyDown(VK_SHIFT); if (alt && !ctrl && !shift) { _panel->_panelCallback->SetFocusToPath(wParam == VK_F1 ? 0 : 1); @@ -293,9 +297,9 @@ LRESULT CMyComboBoxEdit::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) 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; + bool alt = IsKeyDown(VK_MENU); + bool ctrl = IsKeyDown(VK_CONTROL); + bool shift = IsKeyDown(VK_SHIFT); if (!alt && !ctrl && !shift) { g_App.SwitchOnOffOnePanel();; @@ -336,7 +340,7 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */) style |= WS_CLIPCHILDREN; style |= WS_CLIPSIBLINGS; - const UInt32 kNumListModes = sizeof(kStyles) / sizeof(kStyles[0]); + const UInt32 kNumListModes = ARRAY_SIZE(kStyles); if (_ListViewMode >= kNumListModes) _ListViewMode = kNumListModes - 1; @@ -355,7 +359,7 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */) exStyle = WS_EX_CLIENTEDGE; if (!_listView.CreateEx(exStyle, style, 0, 0, 116, 260, - HWND(*this), (HMENU)(UINT_PTR)(_baseID + 1), g_hInstance, NULL)) + *this, (HMENU)(UINT_PTR)(_baseID + 1), g_hInstance, NULL)) return false; _listView.SetUnicodeFormat(); @@ -398,16 +402,18 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */) icex.dwICC = ICC_COOL_CLASSES | ICC_BAR_CLASSES; InitCommonControlsEx(&icex); + // if there is no CCS_NOPARENTALIGN, there is space of some pixels after rebar (Incorrect GetWindowRect ?) + _headerReBar.Attach(::CreateWindowEx(WS_EX_TOOLWINDOW, REBARCLASSNAME, NULL, WS_VISIBLE | WS_BORDER | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVIDER - // | CCS_NOPARENTALIGN + | CCS_NOPARENTALIGN | CCS_TOP | RBS_VARHEIGHT | RBS_BANDBORDERS - ,0,0,0,0, HWND(*this), NULL, g_hInstance, NULL)); + ,0,0,0,0, *this, NULL, g_hInstance, NULL)); } DWORD toolbarStyle = WS_CHILD | WS_VISIBLE ; @@ -428,7 +434,7 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */) _baseID + 2, 11, (HINSTANCE)HINST_COMMCTRL, IDB_VIEW_SMALL_COLOR, - (LPCTBBUTTON)&tbb, sizeof(tbb) / sizeof(tbb[0]), + (LPCTBBUTTON)&tbb, ARRAY_SIZE(tbb), 0, 0, 0, 0, sizeof (TBBUTTON))); #ifndef UNDER_CE @@ -447,7 +453,7 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */) , NULL, WS_BORDER | WS_VISIBLE |WS_CHILD | CBS_DROPDOWN | CBS_AUTOHSCROLL, 0, 0, 100, 520, - ((_headerReBar == 0) ? HWND(*this) : _headerToolBar), + ((_headerReBar == 0) ? (HWND)*this : _headerToolBar), (HMENU)(UINT_PTR)(_comboBoxID), g_hInstance, NULL); #ifndef UNDER_CE @@ -519,14 +525,14 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */) _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}; + int sizes[] = {160, 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); + OnSize(0, RECT_SIZE_X(rect), RECT_SIZE_Y(rect)); */ SetTimer(kTimerID, kTimerElapse); @@ -556,13 +562,13 @@ void CPanel::ChangeWindowSize(int xSize, int ySize) else _headerToolBar.GetWindowRect(&rect); - kHeaderSize = rect.bottom - rect.top; + kHeaderSize = RECT_SIZE_Y(rect); _statusBar.GetWindowRect(&rect); - kStatusBarSize = rect.bottom - rect.top; + kStatusBarSize = RECT_SIZE_Y(rect); // _statusBar2.GetWindowRect(&rect); - // kStatusBar2Size = rect.bottom - rect.top; + // kStatusBar2Size = RECT_SIZE_Y(rect); int yListViewSize = MyMax(ySize - kHeaderSize - kStatusBarSize, 0); const int kStartXPos = 32; @@ -600,7 +606,7 @@ bool CPanel::OnNotifyReBar(LPNMHDR header, LRESULT & /* result */) { RECT rect; GetWindowRect(&rect); - ChangeWindowSize(rect.right - rect.left, rect.bottom - rect.top); + ChangeWindowSize(RECT_SIZE_X(rect), RECT_SIZE_Y(rect)); return false; } } @@ -615,7 +621,6 @@ bool CPanel::OnNotify(UINT /* controlID */, LPNMHDR header, LRESULT &result) 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 && @@ -649,13 +654,15 @@ bool CPanel::OnCommand(int code, int itemID, LPARAM lParam, LRESULT &result) } void CPanel::MessageBoxInfo(LPCWSTR message, LPCWSTR caption) - { ::MessageBoxW(HWND(*this), message, caption, MB_OK); } + { ::MessageBoxW((HWND)*this, message, caption, MB_OK); } void CPanel::MessageBox(LPCWSTR message, LPCWSTR caption) - { ::MessageBoxW(HWND(*this), message, caption, MB_OK | MB_ICONSTOP); } + { ::MessageBoxW((HWND)*this, message, caption, MB_OK | MB_ICONSTOP); } void CPanel::MessageBox(LPCWSTR message) { MessageBox(message, L"7-Zip"); } +void CPanel::MessageBoxWarning(LPCWSTR message) + { ::MessageBoxW(NULL, message, L"7-Zip", MB_OK | MB_ICONWARNING); } void CPanel::MessageBoxMyError(LPCWSTR message) - { MessageBox(message, L"Error"); } + { MessageBox(message, L"7-Zip"); } void CPanel::MessageBoxError(HRESULT errorCode, LPCWSTR caption) @@ -663,15 +670,26 @@ void CPanel::MessageBoxError(HRESULT errorCode, LPCWSTR caption) MessageBox(HResultToMessage(errorCode), caption); } +void CPanel::MessageBoxError2Lines(LPCWSTR message, HRESULT errorCode) +{ + UString m = message; + if (errorCode != 0) + { + m += L'\n'; + m += HResultToMessage(errorCode); + } + MessageBoxMyError(m); +} + void CPanel::MessageBoxError(HRESULT errorCode) { MessageBoxError(errorCode, L"7-Zip"); } void CPanel::MessageBoxLastError(LPCWSTR caption) { MessageBoxError(::GetLastError(), caption); } void CPanel::MessageBoxLastError() - { MessageBoxLastError(L"Error"); } + { MessageBoxLastError(L"7-Zip"); } -void CPanel::MessageBoxErrorLang(UINT resourceID, UInt32 langID) - { MessageBox(LangString(resourceID, langID)); } +void CPanel::MessageBoxErrorLang(UINT resourceID) + { MessageBox(LangString(resourceID)); } void CPanel::SetFocusToList() @@ -707,8 +725,7 @@ 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"; + return GetFolderTypeID().IsPrefixedBy(L"7-Zip"); } UString CPanel::GetFsPath() const @@ -723,22 +740,8 @@ 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); + drive.DeleteFrom(NFile::NName::GetRootPrefixSize(drive)); + return drive; } bool CPanel::DoesItSupportOperations() const @@ -754,9 +757,20 @@ void CPanel::SetListViewMode(UInt32 index) _ListViewMode = index; DWORD oldStyle = (DWORD)_listView.GetStyle(); DWORD newStyle = kStyles[index]; + + // DWORD tickCount1 = GetTickCount(); if ((oldStyle & LVS_TYPEMASK) != newStyle) _listView.SetStyle((oldStyle & ~LVS_TYPEMASK) | newStyle); // RefreshListCtrlSaveFocused(); + /* + DWORD tickCount2 = GetTickCount(); + char s[256]; + sprintf(s, "SetStyle = %5d", + tickCount2 - tickCount1 + ); + OutputDebugStringA(s); + */ + } void CPanel::ChangeFlatMode() @@ -769,6 +783,17 @@ void CPanel::ChangeFlatMode() RefreshListCtrlSaveFocused(); } +/* +void CPanel::Change_ShowNtfsStrems_Mode() +{ + _showNtfsStrems_Mode = !_showNtfsStrems_Mode; + if (_parentFolders.Size() > 0) + _showNtfsStrems_ModeForArc = _showNtfsStrems_Mode; + else + _showNtfsStrems_ModeForDisk = _showNtfsStrems_Mode; + RefreshListCtrlSaveFocused(); +} +*/ void CPanel::Post_Refresh_StatusBar() { @@ -782,12 +807,12 @@ void CPanel::AddToArchive() GetOperatedItemIndices(indices); if (!IsFsOrDrivesFolder()) { - MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return; } if (indices.Size() == 0) { - MessageBoxErrorLang(IDS_SELECT_FILES, 0x03020A03); + MessageBoxErrorLang(IDS_SELECT_FILES); return; } UStringVector names; @@ -801,35 +826,42 @@ void CPanel::AddToArchive() curPrefix.Empty(); } - for (int i = 0; i < indices.Size(); i++) + FOR_VECTOR (i, indices) 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); + bool fromPrev = (names.Size() > 1); + const UString archiveName = CreateArchiveName(names.Front(), fromPrev, false); + HRESULT res = CompressFiles(destCurDirPrefix, archiveName, L"", + true, // addExtension + names, false, true, false); if (res != S_OK) { - if (destCurDirPrefix.Length() >= MAX_PATH) - MessageBoxErrorLang(IDS_MESSAGE_UNSUPPORTED_OPERATION_FOR_LONG_PATH_FOLDER, 0x03020A01); + if (destCurDirPrefix.Len() >= MAX_PATH) + MessageBoxErrorLang(IDS_MESSAGE_UNSUPPORTED_OPERATION_FOR_LONG_PATH_FOLDER); } // KillSelection(); } static UString GetSubFolderNameForExtract(const UString &archiveName) { - int slashPos = archiveName.ReverseFind(WCHAR_PATH_SEPARATOR); - int dotPos = archiveName.ReverseFind(L'.'); + UString res = archiveName; + int slashPos = res.ReverseFind(WCHAR_PATH_SEPARATOR); + int dotPos = res.ReverseFind(L'.'); if (dotPos < 0 || slashPos > dotPos) - return archiveName + UString(L"~"); - UString res = archiveName.Left(dotPos); - res.TrimRight(); + res += L'~'; + else + { + res.DeleteFrom(dotPos); + res.TrimRight(); + } return res; } -void CPanel::GetFilePaths(const CRecordVector &indices, UStringVector &paths) +void CPanel::GetFilePaths(const CRecordVector &indices, UStringVector &paths, bool allowFolders) { - for (int i = 0; i < indices.Size(); i++) + FOR_VECTOR (i, indices) { int index = indices[i]; - if (IsItemFolder(index)) + if (!allowFolders && IsItem_Folder(index)) { paths.Clear(); break; @@ -838,7 +870,7 @@ void CPanel::GetFilePaths(const CRecordVector &indices, UStringVector &p } if (paths.Size() == 0) { - MessageBoxErrorLang(IDS_SELECT_FILES, 0x03020A03); + MessageBoxErrorLang(IDS_SELECT_FILES); return; } } @@ -861,14 +893,17 @@ void CPanel::ExtractArchives() folderName = GetSubFolderNameForExtract(GetItemRelPath(indices[0])); else folderName = L"*"; - ::ExtractArchives(paths, _currentFolderPrefix + folderName + UString(WCHAR_PATH_SEPARATOR), true); + ::ExtractArchives(paths, _currentFolderPrefix + folderName + UString(WCHAR_PATH_SEPARATOR) + , true // showDialog + , false // elimDup + ); } -static void AddValuePair(UINT resourceID, UInt32 langID, UInt64 value, UString &s) +void AddValuePair(UINT resourceID, UInt64 value, UString &s) { wchar_t sz[32]; - s += LangString(resourceID, langID); - s += L' '; + s += LangString(resourceID); + s += L": "; ConvertUInt64ToString(value, sz); s += sz; s += L'\n'; @@ -884,31 +919,40 @@ public: CMyComPtr ArchiveFolder; }; +// actually now we don't need CThreadTest, since now we call CopyTo for "test command + +/* HRESULT CThreadTest::ProcessVirt() { RINOK(ArchiveFolder->Extract(&Indices[0], Indices.Size(), - NExtract::NPathMode::kFullPathnames, NExtract::NOverwriteMode::kAskBefore, - NULL, BoolToInt(true), ExtractCallback)); + true, // includeAltStreams + false, // replaceAltStreamColon + NExtract::NPathMode::kFullPathnames, + NExtract::NOverwriteMode::kAskBefore, + NULL, // path + BoolToInt(true), // testMode + 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); + AddValuePair(IDS_PROP_FOLDERS, ExtractCallbackSpec->NumFolders, s); + AddValuePair(IDS_PROP_FILES, ExtractCallbackSpec->NumFiles, s); + // AddValuePair(IDS_PROP_SIZE, ExtractCallbackSpec->UnpackSize, s); + // AddSizePair(IDS_COMPRESSED_COLON, Stat.PackSize, s); s += L'\n'; - s += LangString(IDS_MESSAGE_NO_ERRORS, 0x02000608); - OkMessage = s; + s += LangString(IDS_MESSAGE_NO_ERRORS); + FinalMessage.OkMessage.Message = 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" "; + s += L' '; ConvertUInt64ToString(value, sz); s += sz; ConvertUInt64ToString(value >> 20, sz); @@ -927,6 +971,21 @@ void CPanel::TestArchives() _folder.QueryInterface(IID_IArchiveFolder, &archiveFolder); if (archiveFolder) { + CCopyToOptions options; + options.streamMode = true; + options.showErrorMessages = true; + options.testMode = true; + + UStringVector messages; + HRESULT res = CopyTo(options, indices, &messages); + if (res != S_OK) + { + if (res != E_ABORT) + MessageBoxError(res); + } + return; + + /* { CThreadTest extracter; @@ -946,13 +1005,13 @@ void CPanel::TestArchives() extracter.Indices = indices; - UString title = LangString(IDS_PROGRESS_TESTING, 0x02000F90); - UString progressWindowTitle = LangString(IDS_APP_TITLE, 0x03000000); + UString title = LangString(IDS_PROGRESS_TESTING); + UString progressWindowTitle = L"7-Zip"; // LangString(IDS_APP_TITLE); extracter.ProgressDialog.CompressingMode = false; extracter.ProgressDialog.MainWindow = GetParent(); extracter.ProgressDialog.MainTitle = progressWindowTitle; - extracter.ProgressDialog.MainAddTitle = title + L" "; + extracter.ProgressDialog.MainAddTitle = title + L' '; extracter.ExtractCallbackSpec->OverwriteMode = NExtract::NOverwriteMode::kAskBefore; extracter.ExtractCallbackSpec->Init(); @@ -963,15 +1022,16 @@ void CPanel::TestArchives() } RefreshTitleAlways(); return; + */ } if (!IsFSFolder()) { - MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return; } UStringVector paths; - GetFilePaths(indices, paths); + GetFilePaths(indices, paths, true); if (paths.IsEmpty()) return; ::TestArchives(paths); diff --git a/CPP/7zip/UI/FileManager/Panel.h b/CPP/7zip/UI/FileManager/Panel.h old mode 100755 new mode 100644 index e33a37a2..a9cf6023 --- a/CPP/7zip/UI/FileManager/Panel.h +++ b/CPP/7zip/UI/FileManager/Panel.h @@ -5,22 +5,27 @@ #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 "../../../Common/Defs.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 "../../Archive/IArchive.h" + +#include "ExtractCallback.h" #include "AppState.h" #include "IFolder.h" @@ -28,9 +33,13 @@ #include "ProgressDialog2.h" #include "SysIconUtils.h" +#ifdef UNDER_CE +#define NON_CE_VAR(_v_) +#else +#define NON_CE_VAR(_v_) _v_ +#endif + const int kParentFolderID = 100; -const int kPluginMenuStartID = 1000; -const int kToolbarStartID = 2000; const int kParentIndex = -1; @@ -62,21 +71,18 @@ struct CItemProperty VARTYPE Type; int Order; bool IsVisible; + bool IsRawProp; 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); } + int Compare(const CItemProperty &a) const { return MyCompare(Order, a.Order); } +}; class CItemProperties: public CObjectVector { public: int FindItemWithID(PROPID id) { - for (int i = 0; i < Size(); i++) + FOR_VECTOR (i, (*this)) if ((*this)[i].ID == id) return i; return -1; @@ -97,8 +103,8 @@ struct CTempFileInfo { if (NeedDelete) { - NWindows::NFile::NDirectory::DeleteFileAlways(FilePath); - NWindows::NFile::NDirectory::MyRemoveDirectory(FolderPath); + NWindows::NFile::NDir::DeleteFileAlways(FilePath); + NWindows::NFile::NDir::RemoveDir(FolderPath); } } bool WasChanged(const NWindows::NFile::NFind::CFileInfo &newFileInfo) const @@ -128,6 +134,8 @@ struct CFolderLink: public CTempFileInfo enum MyMessages { + // we can use WM_USER, since we have defined new window class. + // so we don't need WM_APP. kShiftSelectMessage = WM_USER + 1, kReLoadMessage, kSetFocusToListView, @@ -181,6 +189,35 @@ struct CSelectedState #define MY_NMLISTVIEW_NMITEMACTIVATE NMITEMACTIVATE #endif +struct CCopyToOptions +{ + bool streamMode; + bool moveMode; + bool testMode; + bool includeAltStreams; + bool replaceAltStreamChars; + bool showErrorMessages; + + UString folder; + + UStringVector hashMethods; + + CVirtFileSystem *VirtFileSystemSpec; + ISequentialOutStream *VirtFileSystem; + + CCopyToOptions(): + streamMode(false), + moveMode(false), + testMode(false), + includeAltStreams(true), + replaceAltStreamChars(false), + showErrorMessages(false), + VirtFileSystemSpec(NULL), + VirtFileSystem(NULL) + {} +}; + + class CPanel: public NWindows::NControl::CWindow2 { CExtToIconMap _extToIconMap; @@ -223,6 +260,7 @@ class CPanel: public NWindows::NControl::CWindow2 void OnColumnClick(LPNMLISTVIEW info); bool OnCustomDraw(LPNMLVCUSTOMDRAW lplvcd, LRESULT &result); + public: HWND _mainWindow; CPanelCallback *_panelCallback; @@ -230,9 +268,10 @@ public: void SysIconsWereChanged() { _extToIconMap.Clear(); } void DeleteItems(bool toRecycleBin); - void DeleteItemsInternal(CRecordVector &indices); void CreateFolder(); void CreateFile(); + bool CorrectFsPath(const UString &path, UString &result); + // bool IsPathForPlugin(const UString &path); private: @@ -293,6 +332,8 @@ public: CBoolVector _selectedStatusVector; CSelectedState _selectedState; + bool _thereAreDeletedItems; + bool _markDeletedItems; HWND GetParent(); @@ -323,6 +364,10 @@ public: bool _flatModeForDisk; bool _flatModeForArc; + // bool _showNtfsStrems_Mode; + // bool _showNtfsStrems_ModeForDisk; + // bool _showNtfsStrems_ModeForArc; + bool _dontShowMode; @@ -330,7 +375,33 @@ public: CObjectVector _parentFolders; NWindows::NDLL::CLibrary _library; + CMyComPtr _folder; + CMyComPtr _folderCompare; + CMyComPtr _folderGetItemName; + CMyComPtr _folderRawProps; + + void ReleaseFolder() + { + _folderCompare.Release(); + _folderGetItemName.Release(); + _folderRawProps.Release(); + _folder.Release(); + _thereAreDeletedItems = false; + } + + void SetNewFolder(IFolderFolder *newFolder) + { + ReleaseFolder(); + _folder = newFolder; + if (_folder) + { + _folder.QueryInterface(IID_IFolderCompare, &_folderCompare); + _folder.QueryInterface(IID_IFolderGetItemName, &_folderGetItemName); + _folder.QueryInterface(IID_IArchiveGetRawProps, &_folderRawProps); + } + } + // CMyComPtr _folderGetSystemIconIndex; UStringVector _fastFolders; @@ -340,11 +411,16 @@ public: HRESULT RefreshListCtrl(const CSelectedState &s); HRESULT RefreshListCtrlSaveFocused(); + bool GetItem_BoolProp(UInt32 itemIndex, PROPID propID) const; + bool IsItem_Deleted(int itemIndex) const; + bool IsItem_Folder(int itemIndex) const; + bool IsItem_AltStream(int itemIndex) const; + UString GetItemName(int itemIndex) const; + void GetItemNameFast(int itemIndex, UString &s) 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; //////////////////////// @@ -391,8 +467,15 @@ public: _flatMode(false), _flatModeForDisk(false), _flatModeForArc(false), + + // _showNtfsStrems_Mode(false), + // _showNtfsStrems_ModeForDisk(false), + // _showNtfsStrems_ModeForArc(false), + _xSize(300), _mySelectMode(false), + _thereAreDeletedItems(false), + _markDeletedItems(true), _enableItemChangeNotify(true), _dontShowMode(false) {} @@ -413,6 +496,9 @@ public: PROPID _sortID; // int _sortIndex; bool _ascending; + Int32 _isRawSortProp; + + void SetSortRawStatus(); void Release(); ~CPanel(); @@ -489,8 +575,6 @@ public: class CDisableTimerProcessing { bool _processTimerMem; - bool _processNotifyMem; - bool _processStatusBarMem; CPanel &_panel; public: @@ -500,38 +584,66 @@ public: void Disable() { _processTimerMem = _panel._processTimer; + _panel._processTimer = false; + } + void Restore() + { + _panel._processTimer = _processTimerMem; + } + CDisableTimerProcessing& operator=(const CDisableTimerProcessing &) {; } + }; + + class CDisableNotify + { + bool _processNotifyMem; + bool _processStatusBarMem; + + CPanel &_panel; + public: + + CDisableNotify(CPanel &panel): _panel(panel) { Disable(); } + ~CDisableNotify() { Restore(); } + void Disable() + { _processNotifyMem = _panel._processNotify; _processStatusBarMem = _panel._processStatusBar; - _panel._processTimer = false; _panel._processNotify = false; _panel._processStatusBar = false; } + void SetMemMode_Enable() + { + _processNotifyMem = true; + _processStatusBarMem = true; + } void Restore() { - _panel._processTimer = _processTimerMem; _panel._processNotify = _processNotifyMem; _panel._processStatusBar = _processStatusBarMem; } - CDisableTimerProcessing& operator=(const CDisableTimerProcessing &) {; } + CDisableNotify& operator=(const CDisableNotify &) {; } }; // bool _passwordIsDefined; // UString _password; + void InvalidateList() { _listView.InvalidateRect(NULL, true); } + HRESULT RefreshListCtrl(); void MessageBoxInfo(LPCWSTR message, LPCWSTR caption); void MessageBox(LPCWSTR message); + void MessageBoxWarning(LPCWSTR message); void MessageBox(LPCWSTR message, LPCWSTR caption); void MessageBoxMyError(LPCWSTR message); void MessageBoxError(HRESULT errorCode, LPCWSTR caption); void MessageBoxError(HRESULT errorCode); + void MessageBoxError2Lines(LPCWSTR message, HRESULT errorCode); void MessageBoxLastError(LPCWSTR caption); void MessageBoxLastError(); - void MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID, UInt32 langID); + void MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID); - void MessageBoxErrorLang(UINT resourceID, UInt32 langID); + void MessageBoxErrorLang(UINT resourceID); void OpenFocusedItemAsInternal(); void OpenSelectedItems(bool internal); @@ -548,13 +660,13 @@ public: HRESULT OpenItemAsArchive(const UString &relPath, const UString &arcFormat, bool &encrypted); HRESULT OpenItemAsArchive(int index); void OpenItemInArchive(int index, bool tryInternal, bool tryExternal, - bool editMode); + bool editMode, bool useEditor); HRESULT OnOpenItemChanged(UInt32 index, const wchar_t *fullFilePath, bool usePassword, const UString &password); LRESULT OnOpenItemChanged(LPARAM lParam); void OpenItem(int index, bool tryInternal, bool tryExternal); - void EditItem(); - void EditItem(int index); + void EditItem(bool useEditor); + void EditItem(int index, bool useEditor); void RenameFile(); void ChangeComment(); @@ -564,23 +676,31 @@ public: PROPID GetSortID() const { return _sortID; } void ChangeFlatMode(); + void Change_ShowNtfsStrems_Mode(); bool GetFlatMode() const { return _flatMode; } + // bool Get_ShowNtfsStrems_Mode() const { return _showNtfsStrems_Mode; } + bool AutoRefresh_Mode; + void Set_AutoRefresh_Mode(bool mode) + { + AutoRefresh_Mode = mode; + } + void Post_Refresh_StatusBar(); void Refresh_StatusBar(); void AddToArchive(); - void GetFilePaths(const CRecordVector &indices, UStringVector &paths); + void GetFilePaths(const CRecordVector &indices, UStringVector &paths, bool allowFolders = false); void ExtractArchives(); void TestArchives(); - HRESULT CopyTo(const CRecordVector &indices, const UString &folder, - bool moveMode, bool showErrorMessages, UStringVector *messages, + HRESULT CopyTo(CCopyToOptions &options, + const CRecordVector &indices, + UStringVector *messages, bool &usePassword, UString &password); - HRESULT CopyTo(const CRecordVector &indices, const UString &folder, - bool moveMode, bool showErrorMessages, UStringVector *messages) + HRESULT CopyTo(CCopyToOptions &options, const CRecordVector &indices, UStringVector *messages) { bool usePassword = false; UString password; @@ -590,10 +710,10 @@ public: usePassword = fl.UsePassword; password = fl.Password; } - return CopyTo(indices, folder, moveMode, showErrorMessages, messages, usePassword, password); + return CopyTo(options, indices, messages, usePassword, password); } - HRESULT CopyFrom(const UString &folderPrefix, const UStringVector &filePaths, + HRESULT CopyFrom(bool moveMode, const UString &folderPrefix, const UStringVector &filePaths, bool showErrorMessages, UStringVector *messages); void CopyFromNoAsk(const UStringVector &filePaths); diff --git a/CPP/7zip/UI/FileManager/PanelCopy.cpp b/CPP/7zip/UI/FileManager/PanelCopy.cpp old mode 100755 new mode 100644 index 8c27ef2f..d11368cf --- a/CPP/7zip/UI/FileManager/PanelCopy.cpp +++ b/CPP/7zip/UI/FileManager/PanelCopy.cpp @@ -1,14 +1,15 @@ -// PanelExtract.cpp +/// PanelExtract.cpp #include "StdAfx.h" +#include "../../../Common/MyException.h" + +#include "../GUI/HashGUI.h" + +#include "ExtractCallback.h" +#include "LangUtils.h" #include "Panel.h" #include "resource.h" -#include "LangUtils.h" -#include "ExtractCallback.h" -#include "Windows/Thread.h" -//////////////////////////////////////////////////////////////// - #include "UpdateCallback100.h" using namespace NWindows; @@ -17,35 +18,82 @@ class CPanelCopyThread: public CProgressThreadVirt { HRESULT ProcessVirt(); public: + const CCopyToOptions *options; CMyComPtr FolderOperations; CRecordVector Indices; - UString DestPath; CExtractCallbackImp *ExtractCallbackSpec; CMyComPtr ExtractCallback; + + CHashBundle Hash; + UString FirstFilePath; + HRESULT Result; - bool MoveMode; + - CPanelCopyThread(): MoveMode(false), Result(E_FAIL) {} + CPanelCopyThread(): Result(E_FAIL) {} }; HRESULT CPanelCopyThread::ProcessVirt() { - if (MoveMode) - Result = FolderOperations->MoveTo(&Indices.Front(), Indices.Size(), DestPath, ExtractCallback); + /* + CMyComPtr iReplace; + FolderOperations.QueryInterface(IID_IFolderSetReplaceAltStreamCharsMode, &iReplace); + if (iReplace) + { + RINOK(iReplace->SetReplaceAltStreamCharsMode(ReplaceAltStreamChars ? 1 : 0)); + } + */ + + if (options->testMode) + { + CMyComPtr archiveFolder; + FolderOperations.QueryInterface(IID_IArchiveFolder, &archiveFolder); + if (!archiveFolder) + return E_NOTIMPL; + CMyComPtr extractCallback2; + RINOK(ExtractCallback.QueryInterface(IID_IFolderArchiveExtractCallback, &extractCallback2)); + NExtract::NPathMode::EEnum pathMode = + NExtract::NPathMode::kCurPaths; + // NExtract::NPathMode::kFullPathnames; + Result = archiveFolder->Extract(&Indices.Front(), Indices.Size(), + BoolToInt(options->includeAltStreams), + BoolToInt(options->replaceAltStreamChars), + pathMode, NExtract::NOverwriteMode::kAsk, + options->folder, BoolToInt(true), extractCallback2); + } else - Result = FolderOperations->CopyTo(&Indices.Front(), Indices.Size(), DestPath, ExtractCallback); + Result = FolderOperations->CopyTo( + BoolToInt(options->moveMode), + &Indices.Front(), Indices.Size(), + BoolToInt(options->includeAltStreams), + BoolToInt(options->replaceAltStreamChars), + options->folder, ExtractCallback); + + if (Result == S_OK && !ExtractCallbackSpec->ThereAreMessageErrors && + (!options->hashMethods.IsEmpty() || options->testMode)) + { + CProgressMessageBoxPair &pair = GetMessagePair(false); // GetMessagePair(ExtractCallbackSpec->Hash.NumErrors != 0); + AddHashBundleRes(pair.Message, Hash, FirstFilePath); + } + return Result; } -HRESULT CPanel::CopyTo(const CRecordVector &indices, const UString &folder, - bool moveMode, bool showErrorMessages, UStringVector *messages, +static void ThrowException_if_Error(HRESULT res) +{ + if (res != S_OK) + throw CSystemException(res); +} + +HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector &indices, + 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) + UString errorMessage = LangString(IDS_OPERATION_IS_NOT_SUPPORTED); + if (options.showErrorMessages) MessageBox(errorMessage); else if (messages != 0) messages->Add(errorMessage); @@ -56,27 +104,88 @@ HRESULT CPanel::CopyTo(const CRecordVector &indices, const UString &fold { CPanelCopyThread extracter; - extracter.ExtractCallbackSpec = new CExtractCallbackImp; extracter.ExtractCallback = extracter.ExtractCallbackSpec; + + extracter.options = &options; extracter.ExtractCallbackSpec->ProgressDialog = &extracter.ProgressDialog; extracter.ProgressDialog.CompressingMode = false; + + extracter.ExtractCallbackSpec->StreamMode = options.streamMode; + + #ifdef EXTERNAL_CODECS + CExternalCodecs __externalCodecs; + #else + CMyComPtr compressCodecsInfo; + #endif + + if (indices.Size() == 1) + extracter.FirstFilePath = GetItemRelPath(indices[0]); + + if (options.VirtFileSystem) + { + extracter.ExtractCallbackSpec->VirtFileSystem = options.VirtFileSystem; + extracter.ExtractCallbackSpec->VirtFileSystemSpec = options.VirtFileSystemSpec; + } + extracter.ExtractCallbackSpec->ProcessAltStreams = options.includeAltStreams; + + if (!options.hashMethods.IsEmpty()) + { + { + CCodecs *codecs = new CCodecs; + ThrowException_if_Error(codecs->Load()); + #ifdef EXTERNAL_CODECS + __externalCodecs.GetCodecs = codecs; + __externalCodecs.GetHashers = codecs; + ThrowException_if_Error(__externalCodecs.LoadCodecs()); + #else + compressCodecsInfo = codecs; + #endif + } + + extracter.Hash.SetMethods(EXTERNAL_CODECS_VARS options.hashMethods); + extracter.ExtractCallbackSpec->SetHashMethods(&extracter.Hash); + } + else if (options.testMode) + { + extracter.ExtractCallbackSpec->SetHashCalc(&extracter.Hash); + } + + extracter.Hash.Init(); + - UString title = moveMode ? - LangString(IDS_MOVING, 0x03020206): - LangString(IDS_COPYING, 0x03020205); - UString progressWindowTitle = LangString(IDS_APP_TITLE, 0x03000000); + UString title; + { + UInt32 titleID = IDS_COPYING; + if (options.moveMode) + titleID = IDS_MOVING; + else if (!options.hashMethods.IsEmpty() && options.streamMode) + { + titleID = IDS_CHECKSUM_CALCULATING; + if (options.hashMethods.Size() == 1) + { + const UString &s = options.hashMethods[0]; + if (s != L"*") + title = s; + } + } + else if (options.testMode) + titleID = IDS_PROGRESS_TESTING; + + if (title.IsEmpty()) + title = LangString(titleID); + } + + UString progressWindowTitle = L"7-Zip"; // LangString(IDS_APP_TITLE); extracter.ProgressDialog.MainWindow = GetParent(); extracter.ProgressDialog.MainTitle = progressWindowTitle; - extracter.ProgressDialog.MainAddTitle = title + L" "; + extracter.ProgressDialog.MainAddTitle = title + L' '; - extracter.ExtractCallbackSpec->OverwriteMode = NExtract::NOverwriteMode::kAskBefore; + extracter.ExtractCallbackSpec->OverwriteMode = NExtract::NOverwriteMode::kAsk; extracter.ExtractCallbackSpec->Init(); extracter.Indices = indices; - extracter.DestPath = folder; extracter.FolderOperations = folderOperations; - extracter.MoveMode = moveMode; extracter.ExtractCallbackSpec->PasswordIsDefined = usePassword; extracter.ExtractCallbackSpec->Password = password; @@ -93,6 +202,7 @@ HRESULT CPanel::CopyTo(const CRecordVector &indices, const UString &fold password = extracter.ExtractCallbackSpec->Password; } } + RefreshTitleAlways(); return res; } @@ -108,6 +218,7 @@ struct CThreadUpdate CMyComPtr UpdateCallback; CUpdateCallback100Imp *UpdateCallbackSpec; HRESULT Result; + bool MoveMode; void Process() { @@ -115,6 +226,7 @@ struct CThreadUpdate { CProgressCloser closer(ProgressDialog); Result = FolderOperations->CopyFrom( + MoveMode, FolderPrefix, &FileNamePointers.Front(), FileNamePointers.Size(), @@ -129,7 +241,7 @@ struct CThreadUpdate } }; -HRESULT CPanel::CopyFrom(const UString &folderPrefix, const UStringVector &filePaths, +HRESULT CPanel::CopyFrom(bool moveMode, const UString &folderPrefix, const UStringVector &filePaths, bool showErrorMessages, UStringVector *messages) { CMyComPtr folderOperations; @@ -140,28 +252,29 @@ HRESULT CPanel::CopyFrom(const UString &folderPrefix, const UStringVector &fileP else { CThreadUpdate updater; + updater.MoveMode = moveMode; 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); + UString title = LangString(IDS_COPYING); + UString progressWindowTitle = L"7-Zip"; // LangString(IDS_APP_TITLE); updater.ProgressDialog.MainWindow = GetParent(); updater.ProgressDialog.MainTitle = progressWindowTitle; - updater.ProgressDialog.MainAddTitle = title + UString(L" "); + 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]); + updater.FileNames.ClearAndReserve(filePaths.Size()); + unsigned i; + for (i = 0; i < filePaths.Size(); i++) + updater.FileNames.AddInReserved(filePaths[i]); + updater.FileNamePointers.ClearAndReserve(updater.FileNames.Size()); + for (i = 0; i < updater.FileNames.Size(); i++) + updater.FileNamePointers.AddInReserved(updater.FileNames[i]); NWindows::CThread thread; RINOK(thread.Create(CThreadUpdate::MyThreadFunction, &updater)); @@ -175,7 +288,7 @@ HRESULT CPanel::CopyFrom(const UString &folderPrefix, const UStringVector &fileP if (res == E_NOINTERFACE) { - UString errorMessage = LangString(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + UString errorMessage = LangString(IDS_OPERATION_IS_NOT_SUPPORTED); if (showErrorMessages) MessageBox(errorMessage); else if (messages != 0) @@ -194,11 +307,13 @@ void CPanel::CopyFromNoAsk(const UStringVector &filePaths) CSelectedState srcSelState; SaveSelectedState(srcSelState); - HRESULT result = CopyFrom(L"", filePaths, true, 0); + HRESULT result = CopyFrom(false, L"", filePaths, true, 0); + + CDisableNotify disableNotify(*this); if (result != S_OK) { - disableTimerProcessing.Restore(); + disableNotify.Restore(); // For Password: SetFocusToList(); if (result != E_ABORT) @@ -208,14 +323,14 @@ void CPanel::CopyFromNoAsk(const UStringVector &filePaths) RefreshListCtrl(srcSelState); - disableTimerProcessing.Restore(); + disableNotify.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); + UString title = LangString(IDS_CONFIRM_FILE_COPY); + UString message = LangString(IDS_WANT_TO_COPY_FILES); message += L"\n\'"; message += _currentFolderPrefix; message += L"\' ?"; diff --git a/CPP/7zip/UI/FileManager/PanelCrc.cpp b/CPP/7zip/UI/FileManager/PanelCrc.cpp old mode 100755 new mode 100644 index 2dd5e7ce..ab93ecba --- a/CPP/7zip/UI/FileManager/PanelCrc.cpp +++ b/CPP/7zip/UI/FileManager/PanelCrc.cpp @@ -1,24 +1,19 @@ -// PanelSplitFile.cpp +// PanelCrc.cpp #include "StdAfx.h" -#include "../../../../C/7zCrc.h" -#include "../../../../C/Sha256.h" +#include "../../../Common/MyException.h" -#include "Common/IntToString.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/FileIO.h" -#include "Windows/FileFind.h" -#include "Windows/FileIO.h" -#include "Windows/FileName.h" +#include "../Common/LoadCodecs.h" -#include "OverwriteDialogRes.h" +#include "../GUI/HashGUI.h" #include "App.h" -#include "FormatUtils.h" #include "LangUtils.h" -#include "../Common/PropIDUtils.h" - #include "resource.h" using namespace NWindows; @@ -28,17 +23,18 @@ static const UInt32 kBufSize = (1 << 15); struct CDirEnumerator { - bool FlatMode; + bool EnterToDirs; FString BasePrefix; - FStringVector FileNames; + FStringVector FilePaths; CObjectVector Enumerators; FStringVector Prefixes; - int Index; - HRESULT GetNextFile(NFind::CFileInfo &fileInfo, bool &filled, FString &fullPath); + unsigned Index; + + CDirEnumerator(): EnterToDirs(false), Index(0) {}; + void Init(); - - CDirEnumerator(): FlatMode(false) {}; + DWORD GetNextFile(NFind::CFileInfo &fi, bool &filled, FString &resPath); }; void CDirEnumerator::Init() @@ -48,295 +44,320 @@ void CDirEnumerator::Init() Index = 0; } -static HRESULT GetNormalizedError() +static DWORD GetNormalizedError() { - HRESULT errorCode = GetLastError(); - return (errorCode == 0) ? E_FAIL : errorCode; + DWORD error = GetLastError(); + return (error == 0) ? E_FAIL : error; } -HRESULT CDirEnumerator::GetNextFile(NFind::CFileInfo &fileInfo, bool &filled, FString &resPath) +DWORD CDirEnumerator::GetNextFile(NFind::CFileInfo &fi, bool &filled, FString &resPath) { filled = false; + resPath.Empty(); for (;;) { if (Enumerators.IsEmpty()) { - if (Index >= FileNames.Size()) + if (Index >= FilePaths.Size()) return S_OK; - const FString &path = FileNames[Index]; + const FString &path = FilePaths[Index++]; int pos = path.ReverseFind(FCHAR_PATH_SEPARATOR); - resPath.Empty(); if (pos >= 0) - resPath = path.Left(pos + 1); + resPath.SetFrom(path, pos + 1); #ifdef _WIN32 - // it's for "c:" paths/ - if (BasePrefix.IsEmpty() && path.Length() == 2 && path[1] == ':') + if (BasePrefix.IsEmpty() && path.Len() == 2 && path[1] == ':') { - fileInfo.Name = path; - fileInfo.Attrib = FILE_ATTRIBUTE_DIRECTORY; - fileInfo.Size = 0; + // we use "c:" item as directory item + fi.Clear(); + fi.Name = path; + fi.SetAsDir(); + fi.Size = 0; } else #endif - if (!fileInfo.Find(BasePrefix + path)) + if (!fi.Find(BasePrefix + path)) { - WRes errorCode = GetNormalizedError(); + DWORD error = GetNormalizedError(); resPath = path; - return errorCode; + return error; } - Index++; break; } bool found; - if (!Enumerators.Back().Next(fileInfo, found)) + if (Enumerators.Back().Next(fi, found)) { - HRESULT errorCode = GetNormalizedError(); - resPath = Prefixes.Back(); - return errorCode; + if (found) + { + resPath = Prefixes.Back(); + break; + } } - if (found) + else { + DWORD error = GetNormalizedError(); resPath = Prefixes.Back(); - break; + Enumerators.DeleteBack(); + Prefixes.DeleteBack(); + return error; } Enumerators.DeleteBack(); Prefixes.DeleteBack(); } - resPath += fileInfo.Name; - if (!FlatMode && fileInfo.IsDir()) + resPath += fi.Name; + if (EnterToDirs && fi.IsDir()) { - FString prefix = resPath + FCHAR_PATH_SEPARATOR; - Enumerators.Add(NFind::CEnumerator(BasePrefix + prefix + FCHAR_ANY_MASK)); - Prefixes.Add(prefix); + FString s = resPath; + s += FCHAR_PATH_SEPARATOR; + Prefixes.Add(s); + s += FCHAR_ANY_MASK; + Enumerators.Add(NFind::CEnumerator(BasePrefix + s)); } 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; - + CHashBundle Hash; + + void SetStatus(const UString &s); + void AddErrorMessage(DWORD systemError, const FChar *name); }; -UString CThreadCrc::GetResultMessage() const +void CThreadCrc::AddErrorMessage(DWORD systemError, const FChar *name) { - 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) + ProgressDialog.Sync.AddError_Code_Name(systemError, fs2us(Enumerator.BasePrefix + name)); + Hash.NumErrors++; +} + +void CThreadCrc::SetStatus(const UString &s2) +{ + UString s = s2; + if (Enumerator.BasePrefix) { - 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; - } + if (!s.IsEmpty()) + s += L' '; + s += fs2us(Enumerator.BasePrefix); } - return s; + ProgressDialog.Sync.Set_Status(s); } HRESULT CThreadCrc::ProcessVirt() { - DataSize = NumFolders = NumFiles = NumFilesScan = DataCrcSum = DataNameCrcSum = 0; - memset(Sha256Sum, 0, SHA256_DIGEST_SIZE); - // ProgressDialog.WaitCreating(); + Hash.Init(); - CMyBuffer bufferObject; - if (!bufferObject.Allocate(kBufSize)) + CMyBuffer buf; + if (!buf.Allocate(kBufSize)) return E_OUTOFMEMORY; - Byte *buffer = (Byte *)(void *)bufferObject; - - UInt64 totalSize = 0; + + CProgressSync &sync = ProgressDialog.Sync; + SetStatus(LangString(IDS_SCANNING)); + Enumerator.Init(); - - UString scanningStr = LangString(IDS_SCANNING, 0x03020800); - scanningStr += L' '; - - CProgressSync &sync = ProgressDialog.Sync; + + FString path; + NFind::CFileInfo fi; + UInt64 numFiles = 0; + UInt64 numItems = 0, numItems_Prev = 0; + UInt64 totalSize = 0; for (;;) { - NFind::CFileInfo fileInfo; bool filled; - FString resPath; - HRESULT errorCode = Enumerator.GetNextFile(fileInfo, filled, resPath); - if (errorCode != 0) + DWORD error = Enumerator.GetNextFile(fi, filled, path); + if (error != 0) { - SetErrorPath1(resPath); - return errorCode; + AddErrorMessage(error, path); + continue; } if (!filled) break; - if (!fileInfo.IsDir()) + if (!fi.IsDir()) + { + totalSize += fi.Size; + numFiles++; + } + numItems++; + bool needPrint = false; + // if (fi.IsDir()) { - totalSize += fileInfo.Size; - NumFilesScan++; + if (numItems - numItems_Prev >= 100) + { + needPrint = true; + numItems_Prev = numItems; + } + } + /* + else if (numFiles - numFiles_Prev >= 200) + { + needPrint = true; + numFiles_Prev = numFiles; + } + */ + if (needPrint) + { + RINOK(sync.ScanProgress(numFiles, totalSize, fs2us(path), fi.IsDir())); } - sync.SetCurrentFileName(scanningStr + fs2us(resPath)); - sync.SetProgress(totalSize, 0); - RINOK(sync.SetPosAndCheckPaused(0)); } - sync.SetNumFilesTotal(NumFilesScan); - sync.SetProgress(totalSize, 0); - + RINOK(sync.ScanProgress(numFiles, totalSize, L"", false)); + // sync.SetNumFilesTotal(numFiles); + // sync.SetProgress(totalSize, 0); + // SetStatus(LangString(IDS_CHECKSUM_CALCULATING)); + // sync.SetCurFilePath(L""); + SetStatus(L""); + Enumerator.Init(); - + + FString tempPath; + FString firstFilePath; + bool isFirstFile = true; + UInt64 errorsFilesSize = 0; + for (;;) { - NFind::CFileInfo fileInfo; bool filled; - FString resPath; - HRESULT errorCode = Enumerator.GetNextFile(fileInfo, filled, resPath); - if (errorCode != 0) + DWORD error = Enumerator.GetNextFile(fi, filled, path); + if (error != 0) { - SetErrorPath1(resPath); - return errorCode; + AddErrorMessage(error, path); + continue; } if (!filled) break; - UInt32 crc = CRC_INIT_VAL; - CSha256 sha256; - Sha256_Init(&sha256); - - if (fileInfo.IsDir()) - NumFolders++; - else + error = 0; + Hash.InitForNewFile(); + if (!fi.IsDir()) { NIO::CInFile inFile; - if (!inFile.Open(Enumerator.BasePrefix + resPath)) + tempPath = Enumerator.BasePrefix; + tempPath += path; + if (!inFile.Open(tempPath)) + { + error = GetNormalizedError(); + AddErrorMessage(error, path); + continue; + } + if (isFirstFile) { - errorCode = GetNormalizedError(); - SetErrorPath1(resPath); - return errorCode; + firstFilePath = path; + isFirstFile = false; } - sync.SetCurrentFileName(fs2us(resPath)); - sync.SetNumFilesCur(NumFiles); - NumFiles++; + sync.Set_FilePath(fs2us(path)); + sync.Set_NumFilesCur(Hash.NumFiles); + UInt64 progress_Prev = 0; for (;;) { - UInt32 processedSize; - if (!inFile.Read(buffer, kBufSize, processedSize)) + UInt32 size; + if (!inFile.Read(buf, kBufSize, size)) { - errorCode = GetNormalizedError(); - SetErrorPath1(resPath); - return errorCode; + error = GetNormalizedError(); + AddErrorMessage(error, path); + UInt64 errorSize = 0; + if (inFile.GetLength(errorSize)) + errorsFilesSize += errorSize; + break; } - if (processedSize == 0) + if (size == 0) break; - crc = CrcUpdate(crc, buffer, processedSize); - if (NumFilesScan == 1) - Sha256_Update(&sha256, buffer, processedSize); - - DataSize += processedSize; - RINOK(sync.SetPosAndCheckPaused(DataSize)); + Hash.Update(buf, size); + if (Hash.CurSize - progress_Prev >= ((UInt32)1 << 21)) + { + RINOK(sync.Set_NumBytesCur(errorsFilesSize + Hash.FilesSize + Hash.CurSize)); + progress_Prev = Hash.CurSize; + } } - 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)); + if (error == 0) + Hash.Final(fi.IsDir(), false, fs2us(path)); + RINOK(sync.Set_NumBytesCur(errorsFilesSize + Hash.FilesSize)); } - sync.SetNumFilesCur(NumFiles); - OkMessage = GetResultMessage(); - OkMessageTitle = LangString(IDS_CHECKSUM_INFORMATION, 0x03020720); + RINOK(sync.Set_NumBytesCur(errorsFilesSize + Hash.FilesSize)); + sync.Set_NumFilesCur(Hash.NumFiles); + if (Hash.NumFiles != 1) + sync.Set_FilePath(L""); + SetStatus(L""); + + CProgressMessageBoxPair &pair = GetMessagePair(Hash.NumErrors != 0); + AddHashBundleRes(pair.Message, Hash, fs2us(firstFilePath)); + LangString(IDS_CHECKSUM_INFORMATION, pair.Title); return S_OK; } -void CApp::CalculateCrc() +static void ThrowException_if_Error(HRESULT res) +{ + if (res != S_OK) + throw CSystemException(res); +} + +void CApp::CalculateCrc(const UString &methodName) { int srcPanelIndex = GetFocusedPanelIndex(); CPanel &srcPanel = Panels[srcPanelIndex]; - if (!srcPanel.IsFsOrDrivesFolder()) - { - srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); - return; - } + CRecordVector indices; - srcPanel.GetOperatedItemIndices(indices); + srcPanel.GetOperatedIndicesSmart(indices); if (indices.IsEmpty()) return; + if (!srcPanel.IsFsOrDrivesFolder()) { - CThreadCrc t; - for (int i = 0; i < indices.Size(); i++) - t.Enumerator.FileNames.Add(us2fs(srcPanel.GetItemRelPath(indices[i]))); - t.Enumerator.BasePrefix = us2fs(srcPanel.GetFsPath()); - t.Enumerator.FlatMode = GetFlatMode(); + CCopyToOptions options; + options.streamMode = true; + options.showErrorMessages = true; + options.hashMethods.Add(methodName); - t.ProgressDialog.ShowCompressionInfo = false; + UStringVector messages; + HRESULT res = srcPanel.CopyTo(options, indices, &messages); + if (res != S_OK) + { + if (res != E_ABORT) + srcPanel.MessageBoxError(res); + } + return; + } - UString title = LangString(IDS_CHECKSUM_CALCULATING, 0x03020710); + CCodecs *codecs = new CCodecs; + #ifdef EXTERNAL_CODECS + CExternalCodecs __externalCodecs; + __externalCodecs.GetCodecs = codecs; + __externalCodecs.GetHashers = codecs; + #else + CMyComPtr compressCodecsInfo = codecs; + #endif + ThrowException_if_Error(codecs->Load()); - t.ProgressDialog.MainWindow = _window; - t.ProgressDialog.MainTitle = LangString(IDS_APP_TITLE, 0x03000000); - t.ProgressDialog.MainAddTitle = title + UString(L' '); + #ifdef EXTERNAL_CODECS + ThrowException_if_Error(__externalCodecs.LoadCodecs()); + #endif - if (t.Create(title, _window) != S_OK) - return; + { + CThreadCrc t; + { + UStringVector methods; + methods.Add(methodName); + t.Hash.SetMethods(EXTERNAL_CODECS_VARS methods); + } + FOR_VECTOR (i, indices) + t.Enumerator.FilePaths.Add(us2fs(srcPanel.GetItemRelPath(indices[i]))); + t.Enumerator.BasePrefix = us2fs(srcPanel.GetFsPath()); + t.Enumerator.EnterToDirs = !GetFlatMode(); + + t.ProgressDialog.ShowCompressionInfo = false; + + UString title = LangString(IDS_CHECKSUM_CALCULATING); + + t.ProgressDialog.MainWindow = _window; + t.ProgressDialog.MainTitle = L"7-Zip"; // LangString(IDS_APP_TITLE); + 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 old mode 100755 new mode 100644 index 02bccc03..9434d156 --- a/CPP/7zip/UI/FileManager/PanelDrag.cpp +++ b/CPP/7zip/UI/FileManager/PanelDrag.cpp @@ -6,12 +6,13 @@ #include #endif -#include "Common/StringConvert.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/Wildcard.h" -#include "Windows/Memory.h" -#include "Windows/FileDir.h" -#include "Windows/FileName.h" -#include "Windows/Shell.h" +#include "../../../Windows/MemoryGlobal.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/Shell.h" #include "../Common/ArchiveName.h" #include "../Common/CompressCall.h" @@ -22,6 +23,8 @@ #include "EnumFormatEtc.h" using namespace NWindows; +using namespace NFile; +using namespace NDir; #ifndef _UNICODE extern bool g_IsNT; @@ -204,10 +207,9 @@ STDMETHODIMP CDropSource::QueryContinueDrag(BOOL escapePressed, DWORD keyState) } if (needExtract) { - Result = Panel->CopyTo(Indices, Folder, - false, // moveMode, - false, // showMessages - &Messages); + CCopyToOptions options; + options.folder = Folder; + Result = Panel->CopyTo(options, Indices, &Messages); if (Result != S_OK || !Messages.IsEmpty()) return DRAGDROP_S_CANCEL; } @@ -224,19 +226,19 @@ STDMETHODIMP CDropSource::GiveFeedback(DWORD effect) static bool CopyNamesToHGlobal(NMemory::CGlobal &hgDrop, const UStringVector &names) { - size_t totalLength = 1; + size_t totalLen = 1; #ifndef _UNICODE if (!g_IsNT) { AStringVector namesA; - int i; + unsigned 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; + totalLen += namesA[i].Len() + 1; - if (!hgDrop.Alloc(GHND | GMEM_SHARE, totalLength * sizeof(CHAR) + sizeof(DROPFILES))) + if (!hgDrop.Alloc(GHND | GMEM_SHARE, totalLen * sizeof(CHAR) + sizeof(DROPFILES))) return false; NMemory::CGlobalLock dropLock(hgDrop); @@ -252,21 +254,21 @@ static bool CopyNamesToHGlobal(NMemory::CGlobal &hgDrop, const UStringVector &na for (i = 0; i < names.Size(); i++) { const AString &s = namesA[i]; - int fullLength = s.Length() + 1; + unsigned fullLen = s.Len() + 1; MyStringCopy(p, (const char *)s); - p += fullLength; - totalLength -= fullLength; + p += fullLen; + totalLen -= fullLen; } *p = 0; } else #endif { - int i; + unsigned i; for (i = 0; i < names.Size(); i++) - totalLength += names[i].Length() + 1; + totalLen += names[i].Len() + 1; - if (!hgDrop.Alloc(GHND | GMEM_SHARE, totalLength * sizeof(WCHAR) + sizeof(DROPFILES))) + if (!hgDrop.Alloc(GHND | GMEM_SHARE, totalLen * sizeof(WCHAR) + sizeof(DROPFILES))) return false; NMemory::CGlobalLock dropLock(hgDrop); @@ -282,10 +284,10 @@ static bool CopyNamesToHGlobal(NMemory::CGlobal &hgDrop, const UStringVector &na for (i = 0; i < names.Size(); i++) { const UString &s = names[i]; - int fullLength = s.Length() + 1; + unsigned fullLen = s.Len() + 1; MyStringCopy(p, (const WCHAR *)s); - p += fullLength; - totalLength -= fullLength; + p += fullLen; + totalLen -= fullLen; } *p = 0; } @@ -294,7 +296,7 @@ static bool CopyNamesToHGlobal(NMemory::CGlobal &hgDrop, const UStringVector &na void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */) { - CPanel::CDisableTimerProcessing disableTimerProcessing2(*this); + CDisableTimerProcessing disableTimerProcessing2(*this); if (!DoesItSupportOperations()) return; CRecordVector indices; @@ -306,7 +308,7 @@ void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */) // SaveSelectedState(selState); FString dirPrefix; - NFile::NDirectory::CTempDir tempDirectory; + CTempDir tempDirectory; bool isFSFolder = IsFSFolder(); if (isFSFolder) @@ -323,7 +325,7 @@ void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */) { UStringVector names; - for (int i = 0; i < indices.Size(); i++) + FOR_VECTOR (i, indices) { UInt32 index = indices[i]; UString s; @@ -356,6 +358,7 @@ void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */) HRESULT res = DoDragDrop(dataObject, dropSource, effectsOK, &effect); _panelCallback->DragEnd(); bool canceled = (res == DRAGDROP_S_CANCEL); + CDisableNotify disableNotify(*this); if (res == DRAGDROP_S_DROP) { res = dropSourceSpec->Result; @@ -363,10 +366,10 @@ void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */) if (!dataObjectSpec->Path.IsEmpty()) { NFile::NName::NormalizeDirPathPrefix(dataObjectSpec->Path); - res = CopyTo(indices, dataObjectSpec->Path, - (effect == DROPEFFECT_MOVE),// dropSourceSpec->MoveMode, - false, // showErrorMessages - &dropSourceSpec->Messages); + CCopyToOptions options; + options.folder = dataObjectSpec->Path; + options.moveMode = (effect == DROPEFFECT_MOVE); + res = CopyTo(options, indices, &dropSourceSpec->Messages); } /* if (effect == DROPEFFECT_MOVE) @@ -386,8 +389,14 @@ void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */) messagesDialog.Messages = &dropSourceSpec->Messages; messagesDialog.Create((*this)); } + if (res != S_OK && res != E_ABORT) + { + // we restore Notify before MessageBoxError. So we will se files selection + disableNotify.Restore(); + // SetFocusToList(); MessageBoxError(res); + } if (res == S_OK && dropSourceSpec->Messages.IsEmpty() && !canceled) KillSelection(); } @@ -483,7 +492,7 @@ void CDropTarget::PositionCursor(POINTL ptl) int realIndex = m_Panel->GetRealItemIndex(index); if (realIndex == kParentIndex) return; - if (!m_Panel->IsItemFolder(realIndex)) + if (!m_Panel->IsItem_Folder(realIndex)) return; m_SubFolderIndex = realIndex; m_SubFolderName = m_Panel->GetItemName(m_SubFolderIndex); @@ -585,10 +594,9 @@ bool CDropTarget::IsItSameDrive() const if (m_SourcePaths.Size() == 0) return false; - for (int i = 0; i < m_SourcePaths.Size(); i++) + FOR_VECTOR (i, m_SourcePaths) { - const UString &path = m_SourcePaths[i]; - if (drive.CompareNoCase(path.Left(drive.Length())) != 0) + if (MyStringCompareNoCase_N(m_SourcePaths[i], drive, drive.Len()) != 0) return false; } return true; @@ -649,7 +657,7 @@ bool CDropTarget::SetPath(bool enablePath) const UString path; if (enablePath) path = GetTargetPath(); - size_t size = path.Length() + 1; + size_t size = path.Len() + 1; medium.hGlobal = GlobalAlloc(GHND | GMEM_SHARE, size * sizeof(wchar_t)); if (medium.hGlobal == 0) return false; @@ -752,23 +760,26 @@ void CPanel::CompressDropFiles(HDROP dr) static bool IsFolderInTemp(const FString &path) { FString tempPath; - if (!NFile::NDirectory::MyGetTempPath(tempPath)) + if (!MyGetTempPath(tempPath)) return false; if (tempPath.IsEmpty()) return false; - return (tempPath.CompareNoCase(path.Left(tempPath.Length())) == 0); + unsigned len = tempPath.Len(); + if (path.Len() < len) + return false; + return CompareFileNames(path.Left(len), tempPath) == 0; } static bool AreThereNamesFromTemp(const UStringVector &fileNames) { FString tempPathF; - if (!NFile::NDirectory::MyGetTempPath(tempPathF)) + if (!MyGetTempPath(tempPathF)) return false; UString tempPath = fs2us(tempPathF); if (tempPath.IsEmpty()) return false; - for (int i = 0; i < fileNames.Size(); i++) - if (tempPath.CompareNoCase(fileNames[i].Left(tempPath.Length())) == 0) + FOR_VECTOR (i, fileNames) + if (MyStringCompareNoCase_N(fileNames[i], tempPath, tempPath.Len()) == 0) return true; return false; } @@ -787,13 +798,15 @@ void CPanel::CompressDropFiles(const UStringVector &fileNames, const UString &fo if (folderPath2.IsEmpty()) { FString folderPath2F; - NFile::NDirectory::GetOnlyDirPrefix(us2fs(fileNames.Front()), folderPath2F); + GetOnlyDirPrefix(us2fs(fileNames.Front()), folderPath2F); folderPath2 = fs2us(folderPath2F); if (IsFolderInTemp(folderPath2F)) folderPath2 = ROOT_FS_FOLDER; } const UString archiveName = CreateArchiveName(fileNames.Front(), (fileNames.Size() > 1), false); - CompressFiles(folderPath2, archiveName, L"", fileNames, + CompressFiles(folderPath2, archiveName, L"", + true, // addExtension + fileNames, false, // email true, // showDialog AreThereNamesFromTemp(fileNames) // waitFinish diff --git a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp old mode 100755 new mode 100644 index 995124be..83993bb1 --- a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp +++ b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp @@ -2,11 +2,12 @@ #include "StdAfx.h" -#include "Common/StringConvert.h" -#include "Common/Wildcard.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/Wildcard.h" -#include "Windows/FileName.h" -#include "Windows/PropVariant.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/PropVariant.h" #include "../../PropID.h" @@ -29,10 +30,10 @@ using namespace NFind; void CPanel::SetToRootFolder() { - _folder.Release(); + ReleaseFolder(); _library.Free(); CRootFolder *rootFolderSpec = new CRootFolder; - _folder = rootFolderSpec; + SetNewFolder(rootFolderSpec); rootFolderSpec->Init(); } @@ -40,12 +41,13 @@ HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bo { archiveIsOpened = false; encrypted = false; - CDisableTimerProcessing disableTimerProcessing1(*this); + CDisableTimerProcessing disableTimerProcessing(*this); + CDisableNotify disableNotify(*this); if (_parentFolders.Size() > 0) { const UString &virtPath = _parentFolders.Back().VirtualPath; - if (fullPath.Left(virtPath.Length()) == virtPath) + if (fullPath.IsPrefixedBy(virtPath)) { for (;;) { @@ -53,11 +55,11 @@ HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bo HRESULT res = _folder->BindToParentFolder(&newFolder); if (!newFolder || res != S_OK) break; - _folder = newFolder; + SetNewFolder(newFolder); } UStringVector parts; - SplitPathToParts(fullPath.Mid(virtPath.Length()), parts); - for (int i = 0; i < parts.Size(); i++) + SplitPathToParts(fullPath.Ptr(virtPath.Len()), parts); + FOR_VECTOR (i, parts) { const UString &s = parts[i]; if ((i == 0 || i == parts.Size() - 1) && s.IsEmpty()) @@ -66,7 +68,7 @@ HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bo HRESULT res = _folder->BindToFolder(s, &newFolder); if (!newFolder || res != S_OK) break; - _folder = newFolder; + SetNewFolder(newFolder); } return S_OK; } @@ -85,9 +87,9 @@ HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bo sysPath.Empty(); else { - if (reducedParts.Size() > 0 || pos < sysPath.Length() - 1) - reducedParts.Add(sysPath.Mid(pos + 1)); - sysPath = sysPath.Left(pos); + if (reducedParts.Size() > 0 || pos < (int)sysPath.Len() - 1) + reducedParts.Add(sysPath.Ptr(pos + 1)); + sysPath.DeleteFrom(pos); } } SetToRootFolder(); @@ -95,21 +97,21 @@ HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bo if (sysPath.IsEmpty()) { if (_folder->BindToFolder(fullPath, &newFolder) == S_OK) - _folder = newFolder; + SetNewFolder(newFolder); } else if (fileInfo.IsDir()) { NName::NormalizeDirPathPrefix(sysPath); if (_folder->BindToFolder(sysPath, &newFolder) == S_OK) - _folder = newFolder; + SetNewFolder(newFolder); } else { FString dirPrefix, fileName; - NDirectory::GetFullPathAndSplit(us2fs(sysPath), dirPrefix, fileName); + NDir::GetFullPathAndSplit(us2fs(sysPath), dirPrefix, fileName); if (_folder->BindToFolder(fs2us(dirPrefix), &newFolder) == S_OK) { - _folder = newFolder; + SetNewFolder(newFolder); LoadFullPath(); { HRESULT res = OpenItemAsArchive(fs2us(fileName), arcFormat, encrypted); @@ -130,7 +132,7 @@ HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bo _folder->BindToFolder(reducedParts[i], &newFolder); if (!newFolder) break; - _folder = newFolder; + SetNewFolder(newFolder); } } } @@ -141,7 +143,8 @@ HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bo HRESULT CPanel::BindToPathAndRefresh(const UString &path) { - CDisableTimerProcessing disableTimerProcessing1(*this); + CDisableTimerProcessing disableTimerProcessing(*this); + CDisableNotify disableNotify(*this); bool archiveIsOpened, encrypted; RINOK(BindToPath(path, UString(), archiveIsOpened, encrypted)); RefreshListCtrl(UString(), -1, true, UStringVector()); @@ -170,7 +173,7 @@ UString GetFolderPath(IFolderFolder *folder) void CPanel::LoadFullPath() { _currentFolderPrefix.Empty(); - for (int i = 0; i < _parentFolders.Size(); i++) + FOR_VECTOR (i, _parentFolders) { const CFolderLink &folderLink = _parentFolders[i]; _currentFolderPrefix += GetFolderPath(folderLink.ParentFolder); @@ -197,11 +200,12 @@ void CPanel::LoadFullPathAndShow() _headerComboBox.SetText(_currentFolderPrefix); #ifndef UNDER_CE + COMBOBOXEXITEM item; item.mask = 0; UString path = _currentFolderPrefix; - if (path.Length() > + if (path.Len() > #ifdef _WIN32 3 #else @@ -213,16 +217,15 @@ void CPanel::LoadFullPathAndShow() DWORD attrib = FILE_ATTRIBUTE_DIRECTORY; // GetRealIconIndex is slow for direct DVD/UDF path. So we use dummy path - UString excludePrefix = L"\\\\.\\"; - UString path2 = L"_TestFolder_"; - if (excludePrefix != path.Left(excludePrefix.Length())) + if (path.IsPrefixedBy(L"\\\\.\\")) + path = L"_TestFolder_"; + else { - path2 = path; - CFileInfo info; - if (info.Find(us2fs(path))) - attrib = info.Attrib; + CFileInfo fi; + if (fi.Find(us2fs(path))) + attrib = fi.Attrib; } - item.iImage = GetRealIconIndex(us2fs(path2), attrib); + item.iImage = GetRealIconIndex(us2fs(path), attrib); if (item.iImage >= 0) { @@ -231,6 +234,7 @@ void CPanel::LoadFullPathAndShow() } item.iItem = -1; _headerComboBox.SetItem(&item); + #endif RefreshTitle(); @@ -349,7 +353,7 @@ bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result) ComboBoxPaths.Clear(); _headerComboBox.ResetContent(); - int i; + unsigned i; UStringVector pathParts; SplitPathToParts(_currentFolderPrefix, pathParts); @@ -386,7 +390,7 @@ bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result) FString s = driveStrings[i]; ComboBoxPaths.Add(fs2us(s)); int iconIndex = GetRealIconIndex(s, 0); - if (s.Length() > 0 && s.Back() == FCHAR_PATH_SEPARATOR) + if (s.Len() > 0 && s.Back() == FCHAR_PATH_SEPARATOR) s.DeleteBack(); AddComboBoxItem(fs2us(s), iconIndex, 1, false); } @@ -436,10 +440,10 @@ bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result) return false; } -bool CPanel::OnNotifyComboBox(LPNMHDR header, LRESULT &result) +bool CPanel::OnNotifyComboBox(LPNMHDR NON_CE_VAR(header), LRESULT & NON_CE_VAR(result)) { #ifndef UNDER_CE - switch(header->code) + switch (header->code) { case CBEN_BEGINEDIT: { @@ -467,9 +471,9 @@ void CPanel::FoldersHistory() { CListViewDialog listViewDialog; listViewDialog.DeleteIsAllowed = true; - listViewDialog.Title = LangString(IDS_FOLDERS_HISTORY, 0x03020260); + LangString(IDS_FOLDERS_HISTORY, listViewDialog.Title); _appState->FolderHistory.GetList(listViewDialog.Strings); - if (listViewDialog.Create(GetParent()) == IDCANCEL) + if (listViewDialog.Create(GetParent()) != IDOK) return; UString selectString; if (listViewDialog.StringsWereChanged) @@ -502,15 +506,16 @@ void CPanel::OpenParentFolder() { int pos = focucedName.ReverseFind(WCHAR_PATH_SEPARATOR); if (pos >= 0) - focucedName = focucedName.Mid(pos + 1); + focucedName.DeleteFrontal(pos + 1); } } - CDisableTimerProcessing disableTimerProcessing1(*this); + CDisableTimerProcessing disableTimerProcessing(*this); + CDisableNotify disableNotify(*this); CMyComPtr newFolder; _folder->BindToParentFolder(&newFolder); if (newFolder) - _folder = newFolder; + SetNewFolder(newFolder); else { if (_parentFolders.IsEmpty()) @@ -521,10 +526,10 @@ void CPanel::OpenParentFolder() } else { - _folder.Release(); + ReleaseFolder(); _library.Free(); CFolderLink &link = _parentFolders.Back(); - _folder = link.ParentFolder; + SetNewFolder(link.ParentFolder); _library.Attach(link.Library.Detach()); focucedName = link.RelPath; if (_parentFolders.Size() > 1) @@ -543,29 +548,30 @@ void CPanel::OpenParentFolder() LoadFullPath(); // ::SetCurrentDirectory(::_currentFolderPrefix); RefreshListCtrl(focucedName, -1, true, selectedItems); - _listView.EnsureVisible(_listView.GetFocusedItem(), false); + // _listView.EnsureVisible(_listView.GetFocusedItem(), false); } void CPanel::CloseOpenFolders() { while (_parentFolders.Size() > 0) { - _folder.Release(); + ReleaseFolder(); _library.Free(); - _folder = _parentFolders.Back().ParentFolder; + SetNewFolder(_parentFolders.Back().ParentFolder); _library.Attach(_parentFolders.Back().Library.Detach()); if (_parentFolders.Size() > 1) OpenParentArchiveFolder(); _parentFolders.DeleteBack(); } _flatMode = _flatModeForDisk; - _folder.Release(); + ReleaseFolder(); _library.Free(); } void CPanel::OpenRootFolder() { - CDisableTimerProcessing disableTimerProcessing1(*this); + CDisableTimerProcessing disableTimerProcessing(*this); + CDisableNotify disableNotify(*this); _parentFolders.Clear(); SetToRootFolder(); RefreshListCtrl(UString(), -1, true, UStringVector()); @@ -585,11 +591,11 @@ void CPanel::OpenDrivesFolder() CloseOpenFolders(); #ifdef UNDER_CE NFsFolder::CFSFolder *folderSpec = new NFsFolder::CFSFolder; - _folder = folderSpec; + SetNewFolder(folderSpec); folderSpec->InitToRoot(); #else CFSDrives *folderSpec = new CFSDrives; - _folder = folderSpec; + SetNewFolder(folderSpec); folderSpec->Init(); #endif RefreshListCtrl(); @@ -606,9 +612,8 @@ void CPanel::OpenFolder(int index) _folder->BindToFolder(index, &newFolder); if (!newFolder) return; - _folder = newFolder; + SetNewFolder(newFolder); LoadFullPath(); - // ::SetCurrentDirectory(::_currentFolderPrefix); RefreshListCtrl(); _listView.SetItemState_Selected(_listView.GetFocusedItem()); _listView.EnsureVisible(_listView.GetFocusedItem(), false); diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp old mode 100755 new mode 100644 index 6c4309c6..39585cb2 --- a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp +++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp @@ -4,16 +4,16 @@ #include -#include "Common/AutoPtr.h" -#include "Common/StringConvert.h" +#include "../../../Common/AutoPtr.h" +#include "../../../Common/StringConvert.h" -#include "Windows/Error.h" -#include "Windows/FileDir.h" -#include "Windows/FileFind.h" -#include "Windows/FileName.h" -#include "Windows/Process.h" -#include "Windows/PropVariant.h" -#include "Windows/Thread.h" +#include "../../../Windows/ProcessUtils.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/PropVariantConv.h" + +#include "../../Common/FileStreams.h" +#include "../../Common/StreamObjects.h" #include "../Common/ExtractingFilePath.h" @@ -30,7 +30,9 @@ using namespace NWindows; using namespace NSynchronization; using namespace NFile; -using namespace NDirectory; +using namespace NDir; + +extern UInt64 g_RAM_Size; #ifndef _UNICODE extern bool g_IsNT; @@ -85,7 +87,7 @@ public: void CloseAll() { - for (int i = 0; i < Handles.Size(); i++) + FOR_VECTOR (i, Handles) { HANDLE h = Handles[i]; if (h != NULL) @@ -129,7 +131,7 @@ public: for (;;) { - int i; + unsigned i; for (i = 0; i < ids.Size(); i++) { DWORD id = ids[i]; @@ -225,31 +227,33 @@ HRESULT CPanel::OpenItemAsArchive(IInStream *inStream, _parentFolders.Add(folderLink); _parentFolders.Back().Library.Attach(_library.Detach()); - _folder.Release(); + ReleaseFolder(); _library.Free(); - _folder = newFolder; + SetNewFolder(newFolder); _library.Attach(library.Detach()); _flatMode = _flatModeForArc; CMyComPtr getFolderArcProps; _folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps); + _thereAreDeletedItems = false; 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++) + 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++) + UInt32 level = numLevels - level2; + PROPID propIDs[] = { kpidError, kpidPath, kpidType, kpidErrorType } ; + UString values[4]; + for (Int32 i = 0; i < 4; i++) { CMyComBSTR name; NCOM::CPropVariant prop; @@ -258,17 +262,39 @@ HRESULT CPanel::OpenItemAsArchive(IInStream *inStream, if (prop.vt != VT_EMPTY) values[i] = (prop.vt == VT_BSTR) ? prop.bstrVal : L"?"; } + UString s2; + if (!values[3].IsEmpty()) + { + s2 = L"Can not open the file as [" + values[3] + L"] archive"; + if (level2 != 0) + s2 += L"\nThe file is open as [" + values[2] + L"] archive"; + } if (!values[0].IsEmpty()) + { + if (!s2.IsEmpty()) + s2 += L"\n"; + s2 += L"["; + s2 += values[2]; + s2 += L"] Error: "; + s2 += values[0]; + } + if (!s2.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"; + s += values[1]; + s += L"\n"; + s += s2; } } + */ + /* if (!s.IsEmpty()) - MessageBox(s); + MessageBoxWarning(s); + else + */ + // after MessageBoxWarning it throws exception in nested archives in Debug Mode. why ?. + // MessageBoxWarning(L"test error"); } } @@ -288,15 +314,22 @@ HRESULT CPanel::OpenItemAsArchive(const UString &relPath, const UString &arcForm HRESULT CPanel::OpenItemAsArchive(int index) { CDisableTimerProcessing disableTimerProcessing1(*this); + CDisableNotify disableNotify(*this); bool encrypted; - RINOK(OpenItemAsArchive(GetItemRelPath(index), UString(), encrypted)); + HRESULT res = OpenItemAsArchive(GetItemRelPath(index), UString(), encrypted); + if (res != S_OK) + { + RefreshTitle(true); // in case of error we must refresh changed title of 7zFM + return res; + } RefreshListCtrl(); return S_OK; } HRESULT CPanel::OpenParentArchiveFolder() { - CDisableTimerProcessing disableTimerProcessing1(*this); + CDisableTimerProcessing disableTimerProcessing(*this); + CDisableNotify disableNotify(*this); if (_parentFolders.Size() < 2) return S_OK; const CFolderLink &folderLinkPrev = _parentFolders[_parentFolders.Size() - 2]; @@ -306,14 +339,14 @@ HRESULT CPanel::OpenParentArchiveFolder() { if (folderLink.WasChanged(newFileInfo)) { - UString message = MyFormatNew(IDS_WANT_UPDATE_MODIFIED_FILE, 0x03020280, folderLink.RelPath); - if (::MessageBoxW(HWND(*this), message, L"7-Zip", MB_OKCANCEL | MB_ICONQUESTION) == IDOK) + UString message = MyFormatNew(IDS_WANT_UPDATE_MODIFIED_FILE, folderLink.RelPath); + if (::MessageBoxW((HWND)*this, message, L"7-Zip", MB_OKCANCEL | MB_ICONQUESTION) == IDOK) { - if (OnOpenItemChanged(folderLink.FileIndex, folderLink.FilePath, + if (OnOpenItemChanged(folderLink.FileIndex, fs2us(folderLink.FilePath), folderLinkPrev.UsePassword, folderLinkPrev.Password) != S_OK) { - ::MessageBoxW(HWND(*this), MyFormatNew(IDS_CANNOT_UPDATE_FILE, - 0x03020281, fs2us(folderLink.FilePath)), L"7-Zip", MB_OK | MB_ICONSTOP); + ::MessageBoxW((HWND)*this, MyFormatNew(IDS_CANNOT_UPDATE_FILE, + fs2us(folderLink.FilePath)), L"7-Zip", MB_OK | MB_ICONSTOP); return S_OK; } } @@ -346,17 +379,25 @@ static const char *kStartExtensions = static bool FindExt(const char *p, const UString &name) { - int extPos = name.ReverseFind('.'); - if (extPos < 0) + int dotPos = name.ReverseFind('.'); + if (dotPos < 0 || dotPos == (int)name.Len() - 1) return false; - UString ext = name.Mid(extPos + 1); - ext.MakeLower(); - AString ext2 = UnicodeStringToMultiByte(ext); - for (int i = 0; p[i] != 0;) + + AString s; + for (unsigned pos = dotPos + 1;; pos++) + { + wchar_t c = name[pos]; + if (c == 0) + break; + if (c >= 0x80) + return false; + s += (char)MyCharLower_Ascii((char)c); + } + for (unsigned i = 0; p[i] != 0;) { - int j; + unsigned j; for (j = i; p[j] != ' '; j++); - if (ext2.Length() == j - i && memcmp(p + i, (const char *)ext2, ext2.Length()) == 0) + if (s.Len() == j - i && memcmp(p + i, (const char *)s, s.Len()) == 0) return true; i = j + 1; } @@ -373,19 +414,19 @@ static UString GetQuotedString(const UString &s) return UString(L'\"') + s + UString(L'\"'); } -static HRESULT StartEditApplication(const UString &path, HWND window, CProcess &process) +static HRESULT StartEditApplication(const UString &path, bool useEditor, HWND window, CProcess &process) { UString command; - ReadRegEditor(command); + ReadRegEditor(useEditor, command); if (command.IsEmpty()) { #ifdef UNDER_CE command = L"\\Windows\\"; #else FString winDir; - if (!MyGetWindowsDirectory(winDir)) + if (!GetWindowsDir(winDir)) return 0; - NFile::NName::NormalizeDirPathPrefix(winDir); + NName::NormalizeDirPathPrefix(winDir); command = fs2us(winDir); #endif command += L"notepad.exe"; @@ -393,7 +434,7 @@ static HRESULT StartEditApplication(const UString &path, HWND window, CProcess & 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); + ::MessageBoxW(window, LangString(IDS_CANNOT_START_EDITOR), L"7-Zip", MB_OK | MB_ICONSTOP); return res; } @@ -435,7 +476,7 @@ void CApp::DiffFiles() 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); + ::MessageBoxW(_window, LangString(IDS_CANNOT_START_EDITOR), L"7-Zip", MB_OK | MB_ICONSTOP); } #ifndef _UNICODE @@ -501,7 +542,7 @@ static HRESULT StartApplication(const UString &dir, const UString &path, HWND wi { case SE_ERR_NOASSOC: ::MessageBoxW(window, - NError::MyFormatMessageW(::GetLastError()), + NError::MyFormatMessage(::GetLastError()), // L"There is no application associated with the given file name extension", L"7-Zip", MB_OK | MB_ICONSTOP); } @@ -515,15 +556,15 @@ static void StartApplicationDontWait(const UString &dir, const UString &path, HW StartApplication(dir, path, window, process); } -void CPanel::EditItem(int index) +void CPanel::EditItem(int index, bool useEditor) { if (!_parentFolders.IsEmpty()) { - OpenItemInArchive(index, false, true, true); + OpenItemInArchive(index, false, true, true, useEditor); return; } CProcess process; - StartEditApplication(GetItemFullPath(index), (HWND)*this, process); + StartEditApplication(GetItemFullPath(index), useEditor, (HWND)*this, process); } void CPanel::OpenFolderExternal(int index) @@ -533,12 +574,12 @@ void CPanel::OpenFolderExternal(int index) if (index == kParentIndex) { int pos = fsPrefix.ReverseFind(WCHAR_PATH_SEPARATOR); - if (pos >= 0 && pos == fsPrefix.Length() - 1) + if (pos >= 0 && pos == (int)fsPrefix.Len() - 1) { UString s = fsPrefix.Left(pos); pos = s.ReverseFind(WCHAR_PATH_SEPARATOR); if (pos >= 0) - fsPrefix = s.Left(pos + 1); + fsPrefix.SetFrom(s, pos + 1); } name = fsPrefix; } @@ -549,24 +590,30 @@ void CPanel::OpenFolderExternal(int index) void CPanel::OpenItem(int index, bool tryInternal, bool tryExternal) { - CDisableTimerProcessing disableTimerProcessing1(*this); - if (!_parentFolders.IsEmpty()) + CDisableTimerProcessing disableTimerProcessing(*this); + UString name = GetItemRelPath(index); + if (IsNameVirus(name)) { - OpenItemInArchive(index, tryInternal, tryExternal, false); + MessageBoxErrorLang(IDS_VIRUS); return; } - UString name = GetItemRelPath(index); - if (IsNameVirus(name)) + + if (!_parentFolders.IsEmpty()) { - MessageBoxErrorLang(IDS_VIRUS, 0x03020284); + OpenItemInArchive(index, tryInternal, tryExternal, false, false); return; } + + CDisableNotify disableNotify(*this); UString prefix = GetFsPath(); UString fullPath = prefix + name; + if (tryInternal) if (!tryExternal || !DoItemAlwaysStart(name)) { HRESULT res = OpenItemAsArchive(index); + disableNotify.Restore(); // we must restore to allow text notification update + InvalidateList(); if (res == S_OK || res == E_ABORT) return; if (res != S_FALSE) @@ -606,7 +653,7 @@ HRESULT CPanel::OnOpenItemChanged(UInt32 index, const wchar_t *fullFilePath, CMyComPtr folderOperations; if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) { - MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return E_FAIL; } @@ -649,10 +696,12 @@ LRESULT CPanel::OnOpenItemChanged(LPARAM lParam) CSelectedState state; SaveSelectedState(state); - HRESULT result = OnOpenItemChanged(fileIndex, tpi.FilePath, tpi.UsePassword, tpi.Password); + CDisableNotify disableNotify(*this); // do we need it?? + + HRESULT result = OnOpenItemChanged(fileIndex, fs2us(tpi.FilePath), tpi.UsePassword, tpi.Password); + RefreshListCtrl(state); if (result != S_OK) return 0; - RefreshListCtrl(state); return 1; } @@ -678,7 +727,8 @@ static THREAD_FUNC_DECL MyThreadFunction(void *param) { CRecordVector handles; CRecordVector indices; - for (int i = 0; i < processes.Handles.Size(); i++) + + FOR_VECTOR (i, processes.Handles) { if (processes.NeedWait[i]) { @@ -686,6 +736,7 @@ static THREAD_FUNC_DECL MyThreadFunction(void *param) indices.Add(i); } } + if (handles.IsEmpty()) break; @@ -707,14 +758,13 @@ static THREAD_FUNC_DECL MyThreadFunction(void *param) { if (tpi->WasChanged(newFileInfo)) { - UString message = MyFormatNew(IDS_WANT_UPDATE_MODIFIED_FILE, - 0x03020280, tpi->RelPath); + UString message = MyFormatNew(IDS_WANT_UPDATE_MODIFIED_FILE, tpi->RelPath); if (::MessageBoxW(g_HWND, message, L"7-Zip", MB_OKCANCEL | MB_ICONQUESTION) == IDOK) { if (SendMessage(tpi->Window, kOpenItemChanged, 0, (LONG_PTR)tpi) != 1) { ::MessageBoxW(g_HWND, MyFormatNew(IDS_CANNOT_UPDATE_FILE, - 0x03020281, fs2us(tpi->FilePath)), L"7-Zip", MB_OK | MB_ICONSTOP); + fs2us(tpi->FilePath)), L"7-Zip", MB_OK | MB_ICONSTOP); return 0; } } @@ -724,21 +774,167 @@ static THREAD_FUNC_DECL MyThreadFunction(void *param) return 0; } -void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bool editMode) +#if defined(_WIN32) && !defined(UNDER_CE) +static const FChar *k_ZoneId_StreamName = FTEXT(":Zone.Identifier"); +#endif + + +#ifndef UNDER_CE + +static void ReadZoneFile(CFSTR fileName, CByteBuffer &buf) +{ + buf.Free(); + NIO::CInFile file; + if (!file.Open(fileName)) + return; + UInt64 fileSize; + if (!file.GetLength(fileSize)) + return; + if (fileSize == 0 || fileSize >= ((UInt32)1 << 20)) + return; + buf.Alloc((size_t)fileSize); + UInt32 processed; + if (file.Read(buf, (UInt32)fileSize, processed) && processed == fileSize) + return; + buf.Free(); +} + +static bool WriteZoneFile(CFSTR fileName, const CByteBuffer &buf) +{ + NIO::COutFile file; + if (!file.Create(fileName, true)) + return false; + UInt32 processed; + if (!file.Write(buf, (UInt32)buf.Size(), processed)) + return false; + return processed == buf.Size(); +} + +#endif + +/* +class CBufSeqOutStream_WithFile: + public ISequentialOutStream, + public CMyUnknownImp +{ + Byte *_buffer; + size_t _size; + size_t _pos; + + + size_t _fileWritePos; + bool fileMode; +public: + + bool IsStreamInMem() const { return !fileMode; } + size_t GetMemStreamWrittenSize() const { return _pos; } + + // ISequentialOutStream *FileStream; + FString FilePath; + COutFileStream *outFileStreamSpec; + CMyComPtr outFileStream; + + CBufSeqOutStream_WithFile(): outFileStreamSpec(NULL) {} + + void Init(Byte *buffer, size_t size) + { + fileMode = false; + _buffer = buffer; + _pos = 0; + _size = size; + _fileWritePos = 0; + } + + HRESULT FlushToFile(); + size_t GetPos() const { return _pos; } + + MY_UNKNOWN_IMP + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + +static const UInt32 kBlockSize = ((UInt32)1 << 31); + +STDMETHODIMP CBufSeqOutStream_WithFile::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (!fileMode) + { + if (_size - _pos >= size) + { + memcpy(_buffer + _pos, data, size); + _pos += size; + if (processedSize) + *processedSize = (UInt32)size; + return S_OK; + } + + fileMode = true; + } + RINOK(FlushToFile()); + return outFileStream->Write(data, size, processedSize); +} + +HRESULT CBufSeqOutStream_WithFile::FlushToFile() +{ + if (!outFileStream) + { + outFileStreamSpec = new COutFileStream; + outFileStream = outFileStreamSpec; + if (!outFileStreamSpec->Create(FilePath, false)) + { + outFileStream.Release(); + return E_FAIL; + // MessageBoxMyError(UString(L"Can't create file ") + fs2us(tempFilePath)); + } + } + while (_fileWritePos != _pos) + { + size_t cur = _pos - _fileWritePos; + UInt32 curSize = (cur < kBlockSize) ? (UInt32)cur : kBlockSize; + UInt32 processedSizeLoc = 0; + HRESULT res = outFileStream->Write(_buffer + _fileWritePos, curSize, &processedSizeLoc); + _fileWritePos += processedSizeLoc; + RINOK(res); + if (processedSizeLoc == 0) + return E_FAIL; + } + return S_OK; +} +*/ + +/* +static HRESULT GetTime(IFolderFolder *folder, UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined) +{ + filetimeIsDefined = false; + NCOM::CPropVariant prop; + RINOK(folder->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; +} +*/ + +void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bool editMode, bool useEditor) { const UString name = GetItemName(index); const UString relPath = GetItemRelPath(index); if (IsNameVirus(name)) { - MessageBoxErrorLang(IDS_VIRUS, 0x03020284); + MessageBoxErrorLang(IDS_VIRUS); return; } CMyComPtr folderOperations; if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) { - MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return; } @@ -746,7 +942,7 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo UString fullVirtPath = _currentFolderPrefix + relPath; - NFile::NDirectory::CTempDir tempDirectory; + CTempDir tempDirectory; if (!tempDirectory.Create(kTempDirPrefix)) { MessageBoxLastError(); @@ -754,8 +950,8 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo } FString tempDir = tempDirectory.GetPath(); FString tempDirNorm = tempDir; - NFile::NName::NormalizeDirPathPrefix(tempDirNorm); - FString tempFilePath = tempDirNorm + us2fs(GetCorrectFsPath(name)); + NName::NormalizeDirPathPrefix(tempDirNorm); + const FString tempFilePath = tempDirNorm + us2fs(GetCorrectFsPath(name)); CTempFileInfo tempFileInfo; tempFileInfo.FileIndex = index; @@ -779,12 +975,20 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo if (subStream) { bool encrypted; - if (OpenItemAsArchive(subStream, tempFileInfo, fullVirtPath, UString(), encrypted) == S_OK) + HRESULT res = OpenItemAsArchive(subStream, tempFileInfo, fullVirtPath, UString(), encrypted); + if (res == S_OK) { tempDirectory.DisableDeleting(); RefreshListCtrl(); return; } + if (res == E_ABORT) + return; + if (res != S_FALSE) + { + // probably we must show some message here + // return; + } } } } @@ -805,7 +1009,55 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo password = fl.Password; } - HRESULT result = CopyTo(indices, fs2us(tempDirNorm), false, true, &messages, usePassword, password); + #if defined(_WIN32) && !defined(UNDER_CE) + CByteBuffer zoneBuf; + #ifndef _UNICODE + if (g_IsNT) + #endif + if (_parentFolders.Size() > 0) + { + const CFolderLink &fl = _parentFolders.Front(); + if (!fl.IsVirtual && !fl.FilePath.IsEmpty()) + ReadZoneFile(fl.FilePath + k_ZoneId_StreamName, zoneBuf); + } + #endif + + + CVirtFileSystem *virtFileSystemSpec = NULL; + CMyComPtr virtFileSystem; + + bool isAltStream = IsItem_AltStream(index); + + CCopyToOptions options; + options.includeAltStreams = false; + options.replaceAltStreamChars = isAltStream; + + if (tryAsArchive) + { + NCOM::CPropVariant prop; + _folder->GetProperty(index, kpidSize, &prop); + UInt64 fileLimit = g_RAM_Size / 4; + UInt64 fileSize = 0; + if (!ConvertPropVariantToUInt64(prop, fileSize)) + fileSize = fileLimit; + if (fileSize <= fileLimit && fileSize > 0) + { + options.streamMode = true; + virtFileSystemSpec = new CVirtFileSystem; + virtFileSystem = virtFileSystemSpec; + // we allow additional total size for small alt streams; + virtFileSystemSpec->MaxTotalAllocSize = fileSize + (1 << 10); + + virtFileSystemSpec->DirPrefix = tempDirNorm; + virtFileSystemSpec->Init(); + options.VirtFileSystem = virtFileSystem; + options.VirtFileSystemSpec = virtFileSystemSpec; + } + } + + options.folder = fs2us(tempDirNorm); + options.showErrorMessages = true; + HRESULT result = CopyTo(options, indices, &messages, usePassword, password); if (_parentFolders.Size() > 0) { @@ -823,6 +1075,39 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo return; } + if (options.VirtFileSystem) + { + if (virtFileSystemSpec->IsStreamInMem()) + { + const CVirtFile &file = virtFileSystemSpec->Files[0]; + + size_t streamSize = (size_t)file.Size; + CBufInStream *bufInStreamSpec = new CBufInStream; + CMyComPtr bufInStream = bufInStreamSpec; + bufInStreamSpec->Init(file.Data, streamSize, virtFileSystem); + bool encrypted; + if (OpenItemAsArchive(bufInStream, tempFileInfo, fullVirtPath, UString(), encrypted) == S_OK) + { + tempDirectory.DisableDeleting(); + RefreshListCtrl(); + return; + } + if (virtFileSystemSpec->FlushToDisk(true) != S_OK) + return; + } + } + + + #if defined(_WIN32) && !defined(UNDER_CE) + if (zoneBuf.Size() != 0) + { + if (NFind::DoesFileExist(tempFilePath)) + { + WriteZoneFile(tempFilePath + k_ZoneId_StreamName, zoneBuf); + } + } + #endif + if (tryAsArchive) { @@ -854,7 +1139,7 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo CProcess process; HRESULT res; if (editMode) - res = StartEditApplication(fs2us(tempFilePath), (HWND)*this, process); + res = StartEditApplication(fs2us(tempFilePath), useEditor, (HWND)*this, process); else res = StartApplication(fs2us(tempDirNorm), fs2us(tempFilePath), (HWND)*this, process); @@ -887,7 +1172,7 @@ static bool CheckDeleteItem(UINT64 currentFileTime, UINT64 folderFileTime) void DeleteOldTempFiles() { UString tempPath; - if(!NFile::NDirectory::MyGetTempPath(tempPath)) + if(!MyGetTempPath(tempPath)) throw 1; UINT64 currentFileTime; diff --git a/CPP/7zip/UI/FileManager/PanelItems.cpp b/CPP/7zip/UI/FileManager/PanelItems.cpp old mode 100755 new mode 100644 index daa150c6..b8cc6269 --- a/CPP/7zip/UI/FileManager/PanelItems.cpp +++ b/CPP/7zip/UI/FileManager/PanelItems.cpp @@ -4,11 +4,9 @@ #include "../../../../C/Sort.h" -#include "Common/StringConvert.h" - -#include "Windows/Menu.h" -#include "Windows/PropVariant.h" -#include "Windows/PropVariantConversions.h" +#include "../../../Windows/Menu.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/PropVariantConv.h" #include "../../PropID.h" @@ -21,16 +19,44 @@ using namespace NWindows; +static bool GetColumnVisible(PROPID propID, bool isFsFolder) +{ + if (isFsFolder) + { + switch (propID) + { + case kpidATime: + case kpidAttrib: + case kpidPackSize: + case kpidINode: + case kpidLinks: + case kpidNtReparse: + return false; + } + } + return true; +} + +static int GetColumnWidth(PROPID propID, VARTYPE /* varType */) +{ + switch (propID) + { + case kpidName: return 160; + } + return 100; +} + static int GetColumnAlign(PROPID propID, VARTYPE varType) { - switch(propID) + switch (propID) { case kpidCTime: case kpidATime: case kpidMTime: return LVCFMT_LEFT; } - switch(varType) + + switch (varType) { case VT_UI1: case VT_I2: @@ -65,50 +91,82 @@ HRESULT CPanel::InitColumns() ReadListViewInfo(); - PROPID sortID; /* if (_listViewInfo.SortIndex >= 0) sortID = _listViewInfo.Columns[_listViewInfo.SortIndex].PropID; */ - sortID = _listViewInfo.SortID; + sortID = _listViewInfo.SortID; _ascending = _listViewInfo.Ascending; _properties.Clear(); _needSaveInfo = true; + bool isFsFolder = IsFSFolder(); - 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; + UInt32 numProps; + _folder->GetNumberOfProperties(&numProps); + + for (UInt32 i = 0; i < numProps; i++) + { + CMyComBSTR name; + PROPID propID; + VARTYPE varType; + HRESULT res = _folder->GetPropertyInfo(i, &name, &propID, &varType); + + if (res != S_OK) + { + /* We can return ERROR, but in that case, other code will not be called, + and user can see empty window without error message. So we just ignore that field */ + continue; + } + if (propID == kpidIsDir) + continue; + CItemProperty prop; + prop.Type = varType; + prop.ID = propID; + prop.Name = GetNameOfProperty(propID, name); + prop.Order = -1; + prop.IsVisible = GetColumnVisible(propID, isFsFolder); + prop.Width = GetColumnWidth(propID, varType); + prop.IsRawProp = false; + _properties.Add(prop); + } + } - 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); + if (_folderRawProps) + { + UInt32 numProps; + _folderRawProps->GetNumRawProps(&numProps); + for (UInt32 i = 0; i < numProps; i++) + { + CMyComBSTR name; + PROPID propID; + RINOK(_folderRawProps->GetRawPropInfo(i, &name, &propID)); + + CItemProperty prop; + prop.Type = VT_EMPTY; + prop.ID = propID; + prop.Name = GetNameOfProperty(propID, name); + prop.Order = -1; + prop.IsVisible = GetColumnVisible(propID, isFsFolder); + prop.Width = GetColumnWidth(propID, VT_BSTR);; + prop.IsRawProp = true; + _properties.Add(prop); + } } + // InitColumns2(sortID); for (;;) if (!_listView.DeleteColumn(0)) break; - int order = 0; + unsigned order = 0; + unsigned i; + for (i = 0; i < _listViewInfo.Columns.Size(); i++) { const CColumnInfo &columnInfo = _listViewInfo.Columns[i]; @@ -123,6 +181,7 @@ HRESULT CPanel::InitColumns() continue; } } + for (i = 0; i < _properties.Size(); i++) { CItemProperty &item = _properties[i]; @@ -180,13 +239,11 @@ 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])); + selectedNames.ClearAndReserve(indices.Size()); + FOR_VECTOR (i, indices) + selectedNames.AddInReserved(GetItemRelPath(indices[i])); /* for (int i = 0; i < _listView.GetItemCount(); i++) @@ -196,7 +253,7 @@ void CPanel::GetSelectedNames(UStringVector &selectedNames) LVITEMW item; item.iItem = i; item.pszText = name; - item.cchTextMax = kSize; + item.cchTextMax = kSize; item.iSubItem = 0; item.mask = LVIF_TEXT | LVIF_PARAM; if (!_listView.GetItem(&item)) @@ -228,7 +285,7 @@ void CPanel::SaveSelectedState(CSelectedState &s) LVITEMW item; item.iItem = focusedItem; item.pszText = name; - item.cchTextMax = kSize; + item.cchTextMax = kSize; item.iSubItem = 0; item.mask = LVIF_TEXT; if (_listView.GetItem(&item)) @@ -276,6 +333,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool // OutputDebugStringA("=======\n"); // OutputDebugStringA("s1 \n"); CDisableTimerProcessing timerProcessing(*this); + CDisableNotify disableNotify(*this); if (focusedPos < 0) focusedPos = 0; @@ -286,7 +344,14 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool LVITEMW item; ZeroMemory(&item, sizeof(item)); + // DWORD tickCount0 = GetTickCount(); + _enableItemChangeNotify = false; _listView.DeleteAllItems(); + _enableItemChangeNotify = true; + + + int listViewItemCount = 0; + _selectedStatusVector.Clear(); // _realIndices.Clear(); _startGroupSelect = 0; @@ -294,7 +359,6 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool _selectionIsDefined = false; // m_Files.Clear(); - // _folder.Release(); if (!_folder) { @@ -304,12 +368,25 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool _headerToolBar.EnableButton(kParentFolderID, !IsRootFolder()); - CMyComPtr folderSetFlatMode; - _folder.QueryInterface(IID_IFolderSetFlatMode, &folderSetFlatMode); - if (folderSetFlatMode) - folderSetFlatMode->SetFlatMode(BoolToInt(_flatMode)); + { + CMyComPtr folderSetFlatMode; + _folder.QueryInterface(IID_IFolderSetFlatMode, &folderSetFlatMode); + if (folderSetFlatMode) + folderSetFlatMode->SetFlatMode(BoolToInt(_flatMode)); + } + /* + { + CMyComPtr setShow; + _folder.QueryInterface(IID_IFolderSetShowNtfsStreamsMode, &setShow); + if (setShow) + setShow->SetShowNtfsStreamsMode(BoolToInt(_showNtfsStrems_Mode)); + } + */ + + // DWORD tickCount1 = GetTickCount(); RINOK(_folder->LoadItems()); + // DWORD tickCount2 = GetTickCount(); RINOK(InitColumns()); // OutputDebugString(TEXT("Start Dir\n")); @@ -320,18 +397,40 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool _listView.SetItemCount(numItems + (showDots ? 1 : 0)); - _selectedStatusVector.Reserve(numItems); + _selectedStatusVector.ClearAndReserve(numItems); int cursorIndex = -1; CMyComPtr folderGetSystemIconIndex; if (!IsFSFolder() || _showRealFileIcons) _folder.QueryInterface(IID_IFolderGetSystemIconIndex, &folderGetSystemIconIndex); + if (!IsFSFolder()) + { + CMyComPtr getFolderArcProps; + _folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps); + _thereAreDeletedItems = false; + if (getFolderArcProps) + { + CMyComPtr arcProps; + getFolderArcProps->GetFolderArcProps(&arcProps); + if (arcProps) + { + UInt32 numLevels; + if (arcProps->GetArcNumLevels(&numLevels) != S_OK) + numLevels = 0; + NCOM::CPropVariant prop; + if (arcProps->GetArcProp(numLevels - 1, kpidIsDeleted, &prop) == S_OK) + if (prop.vt == VT_BOOL && VARIANT_BOOLToBool(prop.boolVal)) + _thereAreDeletedItems = true; + } + } + } + if (showDots) { UString itemName = L".."; - item.iItem = _listView.GetItemCount(); - if (itemName.CompareNoCase(focusedName) == 0) + item.iItem = listViewItemCount; + if (itemName == focusedName) cursorIndex = item.iItem; item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; int subItem = 0; @@ -344,20 +443,59 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool item.iImage = 0; if (_listView.InsertItem(&item) == -1) return E_FAIL; + listViewItemCount++; } // OutputDebugStringA("S1\n"); + UString correctedName; + UString itemName; + UString relPath; for (UInt32 i = 0; i < numItems; i++) { - UString itemName = GetItemName(i); - const UString relPath = GetItemRelPath(i); - if (relPath.CompareNoCase(focusedName) == 0) - cursorIndex = _listView.GetItemCount(); + const wchar_t *name = NULL; + unsigned nameLen = 0; + if (_folderGetItemName) + _folderGetItemName->GetItemName(i, &name, &nameLen); + if (name == NULL) + { + GetItemNameFast(i, itemName); + name = itemName; + nameLen = itemName.Len(); + } bool selected = false; - if (selectedNames.FindInSorted(relPath) >= 0) - selected = true; - _selectedStatusVector.Add(selected); + if (!focusedName.IsEmpty() || !selectedNames.IsEmpty()) + { + relPath.Empty(); + + // relPath += GetItemPrefix(i); + // change it (_flatMode) + if (i != kParentIndex && _flatMode) + { + const wchar_t *prefix = NULL; + if (_folderGetItemName) + { + unsigned prefixLen = 0; + _folderGetItemName->GetItemPrefix(i, &prefix, &prefixLen); + if (prefix) + relPath += prefix; + } + if (!prefix) + { + NCOM::CPropVariant prop; + if (_folder->GetProperty(i, kpidPrefix, &prop) != S_OK) + throw 2723400; + if (prop.vt == VT_BSTR) + relPath += prop.bstrVal; + } + } + relPath += name; + if (relPath == focusedName) + cursorIndex = listViewItemCount; + if (selectedNames.FindInSorted(relPath) >= 0) + selected = true; + } + _selectedStatusVector.AddInReserved(selected); item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; @@ -369,21 +507,34 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool } int subItem = 0; - item.iItem = _listView.GetItemCount(); + item.iItem = listViewItemCount; item.iSubItem = subItem++; item.lParam = i; - UString correctedName; - if (itemName.Find(L" ") >= 0) + /* + int finish = nameLen - 4; + int j; + for (j = 0; j < finish; j++) { + if (name[j ] == ' ' && + name[j + 1] == ' ' && + name[j + 2] == ' ' && + name[j + 3] == ' ' && + name[j + 4] == ' ') + break; + } + if (j < finish) + { + correctedName.Empty(); + correctedName = L"virus"; int pos = 0; for (;;) { int posNew = itemName.Find(L" ", pos); if (posNew < 0) { - correctedName += itemName.Mid(pos); + correctedName += itemName.Ptr(pos); break; } correctedName += itemName.Mid(pos, posNew - pos); @@ -394,18 +545,28 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool item.pszText = const_cast((const wchar_t *)correctedName); } else - item.pszText = const_cast((const wchar_t *)itemName); + */ + { + // item.pszText = const_cast((const wchar_t *)name); + item.pszText = LPSTR_TEXTCALLBACKW; + /* LPSTR_TEXTCALLBACKW works, but in some cases there are problems, + since we block notify handler. */ + } + UInt32 attrib = 0; + // for (int yyy = 0; yyy < 6000000; yyy++) { NCOM::CPropVariant prop; RINOK(_folder->GetProperty(i, kpidAttrib, &prop)); - UInt32 attrib = 0; if (prop.vt == VT_UI4) + { + // char s[256]; sprintf(s, "attrib = %7x", attrib); OutputDebugStringA(s); attrib = prop.ulVal; - else if (IsItemFolder(i)) + } + else if (IsItem_Folder(i)) attrib |= FILE_ATTRIBUTE_DIRECTORY; + // } - bool defined = false; - + bool defined = false; if (folderGetSystemIconIndex) { folderGetSystemIconIndex->GetSystemIconIndex(i, &item.iImage); @@ -416,25 +577,29 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool if (_currentFolderPrefix.IsEmpty()) { int iconIndexTemp; - GetRealIconIndex(us2fs(itemName) + FCHAR_PATH_SEPARATOR, attrib, iconIndexTemp); + GetRealIconIndex(us2fs((UString)name) + FCHAR_PATH_SEPARATOR, attrib, iconIndexTemp); item.iImage = iconIndexTemp; } else { - item.iImage = _extToIconMap.GetIconIndex(attrib, itemName); + item.iImage = _extToIconMap.GetIconIndex(attrib, name); } } if (item.iImage < 0) item.iImage = 0; if (_listView.InsertItem(&item) == -1) - return E_FAIL; // error + return E_FAIL; + listViewItemCount++; } // OutputDebugStringA("End2\n"); if (_listView.GetItemCount() > 0 && cursorIndex >= 0) SetFocusedSelectedItem(cursorIndex, selectFocused); + // DWORD tickCount3 = GetTickCount(); + SetSortRawStatus(); _listView.SortItems(CompareItems, (LPARAM)this); + // DWORD tickCount4 = GetTickCount(); if (cursorIndex < 0 && _listView.GetItemCount() > 0) { if (focusedPos >= _listView.GetItemCount()) @@ -443,14 +608,45 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool SetFocusedSelectedItem(focusedPos, showDots); } // m_RedrawEnabled = true; + // DWORD tickCount5 = GetTickCount(); _listView.EnsureVisible(_listView.GetFocusedItem(), false); + // DWORD tickCount6 = GetTickCount(); + + disableNotify.SetMemMode_Enable(); + disableNotify.Restore(); _listView.SetRedraw(true); + // DWORD tickCount7 = GetTickCount(); _listView.InvalidateRect(NULL, true); + // DWORD tickCount8 = GetTickCount(); // OutputDebugStringA("End1\n"); /* _listView.UpdateWindow(); */ Refresh_StatusBar(); + // DWORD tickCount9 = GetTickCount(); + /* + char s[256]; + sprintf(s, + // "attribMap = %5d, extMap = %5d, " + "delete = %5d, load = %5d, list = %5d, sort = %5d, end = %5d", + // _extToIconMap._attribMap.Size(), + // _extToIconMap._extMap.Size(), + tickCount1 - tickCount0, + tickCount2 - tickCount1, + tickCount3 - tickCount2, + tickCount4 - tickCount3, + tickCount5 - tickCount4 + ); + sprintf(s, + "5 = %5d, 6 = %5d, 7 = %5d, 8 = %5d, 9 = %5d", + tickCount5 - tickCount4, + tickCount6 - tickCount5, + tickCount7 - tickCount6, + tickCount8 - tickCount7, + tickCount9 - tickCount8 + ); + OutputDebugStringA(s); + */ return S_OK; } @@ -466,10 +662,10 @@ void CPanel::GetSelectedItemsIndices(CRecordVector &indices) const indices.Add(param); } */ - for (int i = 0; i < _selectedStatusVector.Size(); i++) + FOR_VECTOR (i, _selectedStatusVector) if (_selectedStatusVector[i]) indices.Add(i); - HeapSort(&indices.Front(), indices.Size()); + // HeapSort(&indices.Front(), indices.Size()); } void CPanel::GetOperatedItemIndices(CRecordVector &indices) const @@ -528,16 +724,45 @@ void CPanel::GetOperatedListViewIndices(CRecordVector &indices) const } */ -void CPanel::EditItem() +void CPanel::EditItem(bool useEditor) { + if (!useEditor) + { + CMyComPtr calcItemFullSize; + _folder.QueryInterface(IID_IFolderCalcItemFullSize, &calcItemFullSize); + if (calcItemFullSize) + { + bool needRefresh = false; + CRecordVector indices; + GetOperatedItemIndices(indices); + FOR_VECTOR (i, indices) + { + UInt32 index = indices[i]; + if (IsItem_Folder(index)) + { + calcItemFullSize->CalcItemFullSize(index, NULL); + needRefresh = true; + } + } + if (needRefresh) + { + // _listView.RedrawItem(0); + // _listView.RedrawAllItems(); + InvalidateList(); + return; + } + } + } + + int focusedItem = _listView.GetFocusedItem(); if (focusedItem < 0) return; int realIndex = GetRealItemIndex(focusedItem); if (realIndex == kParentIndex) return; - if (!IsItemFolder(realIndex)) - EditItem(realIndex); + if (!IsItem_Folder(realIndex)) + EditItem(realIndex, useEditor); } void CPanel::OpenFocusedItemAsInternal() @@ -546,7 +771,7 @@ void CPanel::OpenFocusedItemAsInternal() if (focusedItem < 0) return; int realIndex = GetRealItemIndex(focusedItem); - if (IsItemFolder(realIndex)) + if (IsItem_Folder(realIndex)) OpenFolder(realIndex); else OpenItem(realIndex, true, false); @@ -558,7 +783,7 @@ void CPanel::OpenSelectedItems(bool tryInternal) GetOperatedItemIndices(indices); if (indices.Size() > 20) { - MessageBoxErrorLang(IDS_TOO_MANY_ITEMS, 0x02000606); + MessageBoxErrorLang(IDS_TOO_MANY_ITEMS); return; } @@ -571,11 +796,11 @@ void CPanel::OpenSelectedItems(bool tryInternal) } bool dirIsStarted = false; - for (int i = 0; i < indices.Size(); i++) + FOR_VECTOR (i, indices) { UInt32 index = indices[i]; // CFileInfo &aFile = m_Files[index]; - if (IsItemFolder(index)) + if (IsItem_Folder(index)) { if (!dirIsStarted) { @@ -606,6 +831,22 @@ UString CPanel::GetItemName(int itemIndex) const return prop.bstrVal; } +void CPanel::GetItemNameFast(int itemIndex, UString &s) const +{ + if (itemIndex == kParentIndex) + { + s = L".."; + return; + } + NCOM::CPropVariant prop; + if (_folder->GetProperty(itemIndex, kpidName, &prop) != S_OK) + throw 2723400; + if (prop.vt != VT_BSTR) + throw 2723401; + s.Empty(); + s += prop.bstrVal; +} + UString CPanel::GetItemPrefix(int itemIndex) const { if (itemIndex == kParentIndex) @@ -629,42 +870,64 @@ UString CPanel::GetItemFullPath(int itemIndex) const return _currentFolderPrefix + GetItemRelPath(itemIndex); } -bool CPanel::IsItemFolder(int itemIndex) const +bool CPanel::GetItem_BoolProp(UInt32 itemIndex, PROPID propID) const { - if (itemIndex == kParentIndex) - return true; NCOM::CPropVariant prop; - if (_folder->GetProperty(itemIndex, kpidIsDir, &prop) != S_OK) + if (_folder->GetProperty(itemIndex, propID, &prop) != S_OK) throw 2723400; if (prop.vt == VT_BOOL) return VARIANT_BOOLToBool(prop.boolVal); if (prop.vt == VT_EMPTY) return false; - return false; + throw 2723401; +} + +bool CPanel::IsItem_Deleted(int itemIndex) const +{ + if (itemIndex == kParentIndex) + return false; + return GetItem_BoolProp(itemIndex, kpidIsDeleted); +} + +bool CPanel::IsItem_Folder(int itemIndex) const +{ + if (itemIndex == kParentIndex) + return true; + return GetItem_BoolProp(itemIndex, kpidIsDir); +} + +bool CPanel::IsItem_AltStream(int itemIndex) const +{ + if (itemIndex == kParentIndex) + return false; + return GetItem_BoolProp(itemIndex, kpidIsAltStream); } -UINT64 CPanel::GetItemSize(int itemIndex) const +UInt64 CPanel::GetItemSize(int itemIndex) const { if (itemIndex == kParentIndex) return 0; + if (_folderGetItemName) + return _folderGetItemName->GetItemSize(itemIndex); NCOM::CPropVariant prop; if (_folder->GetProperty(itemIndex, kpidSize, &prop) != S_OK) throw 2723400; - if (prop.vt == VT_EMPTY) - return 0; - return ConvertPropVariantToUInt64(prop); + UInt64 val = 0; + if (ConvertPropVariantToUInt64(prop, val)) + return val; + return 0; } void CPanel::ReadListViewInfo() { _typeIDString = GetFolderTypeID(); if (!_typeIDString.IsEmpty()) - ::ReadListViewInfo(_typeIDString, _listViewInfo); + _listViewInfo.Read(_typeIDString); } void CPanel::SaveListViewInfo() { - int i; + unsigned i; for (i = 0; i < _visibleProperties.Size(); i++) { CItemProperty &prop = _visibleProperties[i]; @@ -704,13 +967,11 @@ void CPanel::SaveListViewInfo() } } - // viewInfo.SortIndex = viewInfo.FindColumnWithID(sortPropID); viewInfo.SortID = sortPropID; - viewInfo.Ascending = _ascending; if (!_listViewInfo.IsEqual(viewInfo)) { - ::SaveListViewInfo(_typeIDString, viewInfo); + viewInfo.Save(_typeIDString); _listViewInfo = viewInfo; } } @@ -729,14 +990,13 @@ bool CPanel::OnRightClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActiveate, LRESULT & 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++) + FOR_VECTOR (i, _properties) { const CItemProperty &prop = _properties[i]; UINT flags = MF_STRING; @@ -746,8 +1006,10 @@ void CPanel::ShowColumnsContextMenu(int x, int y) 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()) + + if (menuResult >= kCommandStart && menuResult <= kCommandStart + (int)_properties.Size()) { int index = menuResult - kCommandStart; CItemProperty &prop = _properties[index]; @@ -793,6 +1055,8 @@ void CPanel::OnTimer() { if (!_processTimer) return; + if (!AutoRefresh_Mode) + return; CMyComPtr folderWasChanged; if (_folder.QueryInterface(IID_IFolderWasChanged, &folderWasChanged) != S_OK) return; diff --git a/CPP/7zip/UI/FileManager/PanelKey.cpp b/CPP/7zip/UI/FileManager/PanelKey.cpp old mode 100755 new mode 100644 index 8e3eaaa1..db8e3311 --- a/CPP/7zip/UI/FileManager/PanelKey.cpp +++ b/CPP/7zip/UI/FileManager/PanelKey.cpp @@ -8,6 +8,8 @@ #include "../../PropID.h" #include "App.h" +using namespace NWindows; + // static LPCWSTR kHelpTopic = L"FM/index.htm"; struct CVKeyPropIDPair @@ -27,7 +29,7 @@ static CVKeyPropIDPair g_VKeyPropIDPairs[] = static int FindVKeyPropIDPair(WORD vKey) { - for (int i = 0; i < sizeof(g_VKeyPropIDPairs) / sizeof(g_VKeyPropIDPairs[0]); i++) + for (int i = 0; i < ARRAY_SIZE(g_VKeyPropIDPairs); i++) if (g_VKeyPropIDPairs[i].VKey == vKey) return i; return -1; @@ -41,11 +43,11 @@ bool CPanel::OnKeyDown(LPNMLVKEYDOWN keyDownInfo, LRESULT &result) _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; + bool alt = IsKeyDown(VK_MENU); + bool ctrl = IsKeyDown(VK_CONTROL); + // bool leftCtrl = IsKeyDown(VK_LCONTROL); + bool rightCtrl = IsKeyDown(VK_RCONTROL); + bool shift = IsKeyDown(VK_SHIFT); result = 0; if (keyDownInfo->wVKey >= '0' && keyDownInfo->wVKey <= '9' && @@ -107,11 +109,20 @@ bool CPanel::OnKeyDown(LPNMLVKEYDOWN keyDownInfo, LRESULT &result) } break; } + case VK_F3: + { + if (!alt && !ctrl && !shift) + { + EditItem(false); + return true; + } + break; + } case VK_F4: { if (!alt && !ctrl && !shift) { - EditItem(); + EditItem(true); return true; } if (!alt && !ctrl && shift) @@ -139,17 +150,18 @@ bool CPanel::OnKeyDown(LPNMLVKEYDOWN keyDownInfo, LRESULT &result) } break; } - /* case VK_F7: { if (!alt && !ctrl && !shift) { + /* we can process F7 via menu ACCELERATOR. + But menu loading can be slow in case of UNC paths and system menu. + So we use don't use ACCELERATOR */ CreateFolder(); return true; } break; } - */ case VK_DELETE: { DeleteItems(!shift); diff --git a/CPP/7zip/UI/FileManager/PanelListNotify.cpp b/CPP/7zip/UI/FileManager/PanelListNotify.cpp old mode 100755 new mode 100644 index f28311a4..7be6aa62 --- a/CPP/7zip/UI/FileManager/PanelListNotify.cpp +++ b/CPP/7zip/UI/FileManager/PanelListNotify.cpp @@ -4,79 +4,76 @@ #include "resource.h" -#include "Common/IntToString.h" -#include "Common/StringConvert.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" -#include "Windows/PropVariant.h" -#include "Windows/PropVariantConversions.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/PropVariantConv.h" #include "../Common/PropIDUtils.h" #include "../../PropID.h" +#include "App.h" #include "Panel.h" #include "FormatUtils.h" using namespace NWindows; -/* -static UString ConvertSizeToStringShort(UInt64 value) +static void ConvertSizeToString(UInt64 value, wchar_t *dest) { - 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)) + char s[32]; + ConvertUInt64ToString(value, s); + unsigned i = MyStringLen(s); + unsigned pos = ARRAY_SIZE(s); + s[--pos] = 0; + while (i > 3) { - value >>= 20; - c = L'M'; + s[--pos] = s[--i]; + s[--pos] = s[--i]; + s[--pos] = s[--i]; + s[--pos] = L' '; } - else + while (i > 0) + s[--pos] = s[--i]; + + for (;;) { - value >>= 30; - c = L'G'; + char c = s[pos++]; + *dest++ = (unsigned char)c; + if (c == 0) + break; } - 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) + ConvertSizeToString(value, s); + return s; +} + +static inline char GetHex(Byte value) +{ + return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); +} + +void HexToString(char *dest, const Byte *data, UInt32 size) +{ + for (UInt32 i = 0; i < size; i++) { - s[--pos] = s[--i]; - s[--pos] = s[--i]; - s[--pos] = s[--i]; - s[--pos] = L' '; + Byte b = data[i]; + dest[0] = GetHex((Byte)((b >> 4) & 0xF)); + dest[1] = GetHex((Byte)(b & 0xF)); + dest += 2; } - while (i > 0) - s[--pos] = s[--i]; - return s + pos; + *dest = 0; } LRESULT CPanel::SetItemText(LVITEMW &item) { + if (_dontShowMode) return 0; - UInt32 realIndex = GetRealIndex(item); /* if ((item.mask & LVIF_IMAGE) != 0) @@ -112,23 +109,106 @@ LRESULT CPanel::SetItemText(LVITEMW &item) if (realIndex == kParentIndex) return 0; - UString s; - UInt32 subItemIndex = item.iSubItem; - PROPID propID = _visibleProperties[subItemIndex].ID; + const CItemProperty &property = _visibleProperties[item.iSubItem]; + PROPID propID = property.ID; + + if (property.IsRawProp) + { + const void *data; + UInt32 dataSize; + UInt32 propType; + RINOK(_folderRawProps->GetRawProp(realIndex, propID, &data, &dataSize, &propType)); + int limit = item.cchTextMax - 1; + if (dataSize == 0) + { + item.pszText[0] = 0; + return 0; + } + + if (propID == kpidNtReparse) + { + UString s; + ConvertNtReparseToString((const Byte *)data, dataSize, s); + if (!s.IsEmpty()) + { + int i; + for (i = 0; i < limit; i++) + { + wchar_t c = s[i]; + if (c == 0) + break; + item.pszText[i] = c; + } + item.pszText[i] = 0; + return 0; + } + } + else if (propID == kpidNtSecure) + { + AString s; + ConvertNtSecureToString((const Byte *)data, dataSize, s); + if (!s.IsEmpty()) + { + int i; + for (i = 0; i < limit; i++) + { + wchar_t c = s[i]; + if (c == 0) + break; + item.pszText[i] = c; + } + item.pszText[i] = 0; + return 0; + } + } + { + const UInt32 kMaxDataSize = 64; + if (dataSize > kMaxDataSize) + { + char temp[64]; + MyStringCopy(temp, "data:"); + ConvertUInt32ToString(dataSize, temp + 5); + int i; + for (i = 0; i < limit; i++) + { + wchar_t c = temp[i]; + if (c == 0) + break; + item.pszText[i] = c; + } + item.pszText[i] = 0; + } + else + { + if ((int)dataSize > limit) + dataSize = limit; + WCHAR *dest = item.pszText; + for (UInt32 i = 0; i < dataSize; i++) + { + Byte b = ((const Byte *)data)[i]; + dest[0] = GetHex((Byte)((b >> 4) & 0xF)); + dest[1] = GetHex((Byte)(b & 0xF)); + dest += 2; + } + *dest = 0; + } + } + return 0; + } /* { - NCOM::CPropVariant property; + NCOM::CPropVariant prop; if (propID == kpidType) string = GetFileType(index); else { - HRESULT result = m_ArchiveFolder->GetProperty(index, propID, &property); + HRESULT result = m_ArchiveFolder->GetProperty(index, propID, &prop); if (result != S_OK) { // PrintMessage("GetPropertyValue error"); return 0; } - string = ConvertPropertyToString(property, propID, false); + string = ConvertPropertyToString(prop, propID, false); } } */ @@ -149,11 +229,81 @@ LRESULT CPanel::SetItemText(LVITEMW &item) if (needRead) */ + if (item.cchTextMax < 32) + { + if (item.cchTextMax > 0) + item.pszText[0] = 0; + return 0; + } + + if (propID == kpidName) + { + if (_folderGetItemName) + { + const wchar_t *name = NULL; + unsigned nameLen = 0; + _folderGetItemName->GetItemName(realIndex, &name, &nameLen); + if (name) + { + int dest = 0; + int limit = item.cchTextMax - 1; + for (int i = 0; dest < limit;) + { + wchar_t c = name[i++]; + if (c == 0) + break; + item.pszText[dest++] = c; + if (c != ' ') + continue; + if (name[i + 1] != ' ') + continue; + + int t = 2; + for (; name[i + t] == ' '; t++); + if (t >= 4 && dest + 4 <= limit) + { + item.pszText[dest++] = '.'; + item.pszText[dest++] = '.'; + item.pszText[dest++] = '.'; + item.pszText[dest++] = ' '; + i += t; + } + } + item.pszText[dest] = 0; + return 0; + } + } + } + if (propID == kpidPrefix) + { + if (_folderGetItemName) + { + const wchar_t *name = NULL; + unsigned nameLen = 0; + _folderGetItemName->GetItemPrefix(realIndex, &name, &nameLen); + if (name) + { + int dest = 0; + int limit = item.cchTextMax - 1; + for (int i = 0; dest < limit;) + { + wchar_t c = name[i++]; + if (c == 0) + break; + item.pszText[dest++] = c; + } + item.pszText[dest] = 0; + return 0; + } + } + } 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) && ( + { + MyStringCopy(item.pszText, L"Error: "); + // s = UString(L"Error: ") + HResultToMessage(res); + } + else if ((prop.vt == VT_UI8 || prop.vt == VT_UI4 || prop.vt == VT_UI2) && ( propID == kpidSize || propID == kpidPackSize || propID == kpidNumSubDirs || @@ -162,21 +312,43 @@ LRESULT CPanel::SetItemText(LVITEMW &item) propID == kpidNumBlocks || propID == kpidClusterSize || propID == kpidTotalSize || - propID == kpidFreeSpace + propID == kpidFreeSpace || + propID == kpidUnpackSize )) - s = ConvertSizeToString(ConvertPropVariantToUInt64(prop)); - else { - s = ConvertPropertyToString(prop, propID, false); - s.Replace(wchar_t(0xA), L' '); - s.Replace(wchar_t(0xD), L' '); + UInt64 v = 0; + ConvertPropVariantToUInt64(prop, v); + ConvertSizeToString(v, item.pszText); } - int size = item.cchTextMax; - if (size > 0) + else if (prop.vt == VT_BSTR) { - if (s.Length() + 1 > size) - s = s.Left(size - 1); - MyStringCopy(item.pszText, (const wchar_t *)s); + int limit = item.cchTextMax - 1; + const wchar_t *src = prop.bstrVal; + int i; + for (i = 0; i < limit; i++) + { + wchar_t c = src[i]; + if (c == 0) break; + if (c == 0xA) c = ' '; + if (c == 0xD) c = ' '; + item.pszText[i] = c; + } + item.pszText[i] = 0; + } + else + { + char temp[64]; + ConvertPropertyToShortString(temp, prop, propID, false); + int i; + int limit = item.cchTextMax - 1; + for (i = 0; i < limit; i++) + { + wchar_t c = temp[i]; + if (c == 0) + break; + item.pszText[i] = c; + } + item.pszText[i] = 0; } return 0; } @@ -201,11 +373,9 @@ 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; + bool alt = IsKeyDown(VK_MENU); + bool ctrl = IsKeyDown(VK_CONTROL); + bool shift = IsKeyDown(VK_SHIFT); if (!shift && alt && !ctrl) Properties(); else @@ -222,7 +392,14 @@ bool CPanel::OnNotifyList(LPNMHDR header, LRESULT &result) { if (!_mySelectMode) OnItemChanged((LPNMLISTVIEW)header); - Post_Refresh_StatusBar(); + + // Post_Refresh_StatusBar(); + /* 9.26: we don't call Post_Refresh_StatusBar. + it was very slow if we select big number of files + and then clead slection by selecting just new file. + probably it called slow Refresh_StatusBar for each item deselection. + I hope Refresh_StatusBar still will be called for each key / mouse action. + */ } return false; } @@ -247,8 +424,17 @@ bool CPanel::OnNotifyList(LPNMHDR header, LRESULT &result) } case LVN_KEYDOWN: { - bool boolResult = OnKeyDown(LPNMLVKEYDOWN(header), result); - Post_Refresh_StatusBar(); + LPNMLVKEYDOWN keyDownInfo = LPNMLVKEYDOWN(header); + bool boolResult = OnKeyDown(keyDownInfo, result); + switch(keyDownInfo->wVKey) + { + case VK_CONTROL: + case VK_SHIFT: + case VK_MENU: + break; + default: + Post_Refresh_StatusBar(); + } return boolResult; } @@ -318,7 +504,7 @@ bool CPanel::OnNotifyList(LPNMHDR header, LRESULT &result) case NM_CUSTOMDRAW: { - if (_mySelectMode) + if (_mySelectMode || (_markDeletedItems && _thereAreDeletedItems)) return OnCustomDraw((LPNMLVCUSTOMDRAW)header, result); break; } @@ -352,14 +538,18 @@ bool CPanel::OnCustomDraw(LPNMLVCUSTOMDRAW lplvcd, LRESULT &result) 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->clrTextBk = _listView.GetBkColor(); + if (_mySelectMode) + { + if (realIndex != kParentIndex && _selectedStatusVector[realIndex]) + lplvcd->clrTextBk = RGB(255, 192, 192); + } + + if (_markDeletedItems && _thereAreDeletedItems) + { + if (IsItem_Deleted(realIndex)) + lplvcd->clrText = RGB(255, 0, 0); + } // lplvcd->clrText = RGB(0, 0, 0); // result = CDRF_NEWFONT; result = CDRF_NOTIFYITEMDRAW; @@ -392,38 +582,75 @@ bool CPanel::OnCustomDraw(LPNMLVCUSTOMDRAW lplvcd, LRESULT &result) void CPanel::Refresh_StatusBar() { + /* + g_name_cnt++; + char s[256]; + sprintf(s, "g_name_cnt = %8d", g_name_cnt); + OutputDebugStringA(s); + */ + // DWORD dw = GetTickCount(); + CRecordVector indices; GetOperatedItemIndices(indices); - _statusBar.SetText(0, MyFormatNew(IDS_N_SELECTED_ITEMS, 0x02000301, NumberToString(indices.Size()))); + wchar_t temp[32]; + ConvertUInt32ToString(indices.Size(), temp); - UString selectSizeString; + // UString s1 = MyFormatNew(g_App.LangString_N_SELECTED_ITEMS, NumberToString(indices.Size())); + // UString s1 = MyFormatNew(IDS_N_SELECTED_ITEMS, NumberToString(indices.Size())); + _statusBar.SetText(0, MyFormatNew(g_App.LangString_N_SELECTED_ITEMS, temp)); + // _statusBar.SetText(0, MyFormatNew(IDS_N_SELECTED_ITEMS, NumberToString(indices.Size()))); + + wchar_t selectSizeString[32]; + selectSizeString[0] = 0; if (indices.Size() > 0) { + // for (int ttt = 0; ttt < 1000; ttt++) { UInt64 totalSize = 0; - for (int i = 0; i < indices.Size(); i++) + FOR_VECTOR (i, indices) totalSize += GetItemSize(indices[i]); - selectSizeString = ConvertSizeToString(totalSize); + ConvertSizeToString(totalSize, selectSizeString); + // } } _statusBar.SetText(1, selectSizeString); int focusedItem = _listView.GetFocusedItem(); - UString sizeString; - UString dateString; + wchar_t sizeString[32]; + sizeString[0] = 0; + wchar_t dateString[32]; + dateString[0] = 0; if (focusedItem >= 0 && _listView.GetSelectedCount() > 0) { int realIndex = GetRealItemIndex(focusedItem); if (realIndex != kParentIndex) { - sizeString = ConvertSizeToString(GetItemSize(realIndex)); + ConvertSizeToString(GetItemSize(realIndex), sizeString); NCOM::CPropVariant prop; if (_folder->GetProperty(realIndex, kpidMTime, &prop) == S_OK) - dateString = ConvertPropertyToString(prop, kpidMTime, false); + { + char dateString2[32]; + dateString2[0] = 0; + ConvertPropertyToShortString(dateString2, prop, kpidMTime, false); + for (int i = 0;; i++) + { + char c = dateString2[i]; + dateString[i] = c; + if (c == 0) + break; + } + } } } _statusBar.SetText(2, sizeString); _statusBar.SetText(3, dateString); + // _statusBar.SetText(4, nameString); // _statusBar2.SetText(1, MyFormatNew(L"{0} bytes", NumberToStringW(totalSize))); + // } + /* + dw = GetTickCount() - dw; + sprintf(s, "status = %8d ms", dw); + OutputDebugStringA(s); + */ } diff --git a/CPP/7zip/UI/FileManager/PanelMenu.cpp b/CPP/7zip/UI/FileManager/PanelMenu.cpp old mode 100755 new mode 100644 index badf531b..d6dcf6c1 --- a/CPP/7zip/UI/FileManager/PanelMenu.cpp +++ b/CPP/7zip/UI/FileManager/PanelMenu.cpp @@ -1,12 +1,13 @@ #include "StdAfx.h" -#include "Common/StringConvert.h" +#include "../../../Common/IntToString.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 "../../../Windows/COM.h" +#include "../../../Windows/Clipboard.h" +#include "../../../Windows/Menu.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/PropVariantConv.h" #include "../../PropID.h" #include "../Common/PropIDUtils.h" @@ -24,8 +25,8 @@ using namespace NWindows; LONG g_DllRefCount = 0; -static const UINT kSevenZipStartMenuID = kPluginMenuStartID ; -static const UINT kSystemStartMenuID = kPluginMenuStartID + 100; +static const UINT kSevenZipStartMenuID = kMenuCmdID_Plugin_Start; +static const UINT kSystemStartMenuID = kMenuCmdID_Plugin_Start + 100; void CPanel::InvokeSystemCommand(const char *command) { @@ -54,6 +55,8 @@ static const wchar_t *kPropValueSeparator = L": "; extern UString ConvertSizeToString(UInt64 value); +UString GetOpenArcErrorMessage(UInt32 errorFlags); + static void AddPropertyString(PROPID propID, const wchar_t *nameBSTR, const NCOM::CPropVariant &prop, UString &s) { @@ -61,7 +64,17 @@ static void AddPropertyString(PROPID propID, const wchar_t *nameBSTR, { UString val; - if ((prop.vt == VT_UI8 || prop.vt == VT_UI4) && ( + if (propID == kpidErrorFlags || + propID == kpidWarningFlags) + { + UInt32 flags = GetOpenArcErrorFlags(prop); + if (flags == 0) + return; + if (flags != 0) + val = GetOpenArcErrorMessage(flags); + } + if (val.IsEmpty()) + if ((prop.vt == VT_UI8 || prop.vt == VT_UI4 || prop.vt == VT_UI2) && ( propID == kpidSize || propID == kpidPackSize || propID == kpidNumSubDirs || @@ -72,11 +85,16 @@ static void AddPropertyString(PROPID propID, const wchar_t *nameBSTR, propID == kpidFreeSpace || propID == kpidPhySize || propID == kpidHeadersSize || - propID == kpidFreeSpace + propID == kpidFreeSpace || + propID == kpidUnpackSize )) - val = ConvertSizeToString(ConvertPropVariantToUInt64(prop)); + { + UInt64 v = 0; + ConvertPropVariantToUInt64(prop, v); + val = ConvertSizeToString(v); + } else - val = ConvertPropertyToString(prop, propID); + ConvertPropertyToString(val, prop, propID); if (!val.IsEmpty()) { @@ -92,6 +110,25 @@ static void AddPropertyString(PROPID propID, const wchar_t *nameBSTR, } } +static inline char GetHex(Byte value) +{ + return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); +} + +static const Byte kSpecProps[] = +{ + kpidPath, + kpidType, + kpidErrorType, + kpidError, + kpidErrorFlags, + kpidWarning, + kpidWarningFlags, + kpidOffset, + kpidPhySize, + kpidTailSize +}; + void CPanel::Properties() { CMyComPtr getFolderArcProps; @@ -129,6 +166,57 @@ void CPanel::Properties() AddPropertyString(propID, name, prop, message); } } + + + if (_folderRawProps) + { + _folderRawProps->GetNumRawProps(&numProps); + for (UInt32 i = 0; i < numProps; i++) + { + CMyComBSTR name; + PROPID propID; + if (_folderRawProps->GetRawPropInfo(i, &name, &propID) != S_OK) + continue; + + const void *data; + UInt32 dataSize; + UInt32 propType; + if (_folderRawProps->GetRawProp(index, propID, &data, &dataSize, &propType) != S_OK) + continue; + + if (dataSize != 0) + { + AString s; + if (propID == kpidNtSecure) + ConvertNtSecureToString((const Byte *)data, dataSize, s); + else + { + const UInt32 kMaxDataSize = 64; + if (dataSize > kMaxDataSize) + { + char temp[64]; + s += "data:"; + ConvertUInt32ToString(dataSize, temp); + s += temp; + } + else + { + for (UInt32 i = 0; i < dataSize; i++) + { + Byte b = ((const Byte *)data)[i]; + s += GetHex((Byte)((b >> 4) & 0xF)); + s += GetHex((Byte)(b & 0xF)); + } + } + } + message += GetNameOfProperty(propID, name); + message += kPropValueSeparator; + message += GetUnicodeString(s); + message += L'\n'; + } + } + } + message += kSeparator; } @@ -187,21 +275,19 @@ void CPanel::Properties() UInt32 numProps; if (getProps->GetArcNumProps(level, &numProps) == S_OK) { + const int kNumSpecProps = ARRAY_SIZE(kSpecProps); + message += kSeparator; - for (Int32 i = -3; i < (Int32)numProps; i++) + + for (Int32 i = -(int)kNumSpecProps; 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; - } + if (i < 0) + propID = kSpecProps[i + kNumSpecProps]; + else if (getProps->GetArcPropInfo(level, i, &name, &propID, &vt) != S_OK) + continue; NCOM::CPropVariant prop; if (getProps->GetArcProp(level, propID, &prop) != S_OK) continue; @@ -209,6 +295,7 @@ void CPanel::Properties() } } } + if (level2 != numLevels - 1) { UInt32 level = numLevels - 1 - level2; @@ -233,7 +320,7 @@ void CPanel::Properties() } } } - ::MessageBoxW(*(this), message, LangString(IDS_PROPERTIES, 0x03020900), MB_OK); + ::MessageBoxW(*(this), message, LangString(IDS_PROPERTIES), MB_OK); } } @@ -256,7 +343,7 @@ void CPanel::EditCopy() UString s; CRecordVector indices; GetSelectedItemsIndices(indices); - for (int i = 0; i < indices.Size(); i++) + FOR_VECTOR (i, indices) { if (i > 0) s += L"\xD\n"; @@ -274,7 +361,7 @@ void CPanel::EditPaste() UString s; for (int i = 0; i < names.Size(); i++) { - s += L" "; + s += L' '; s += names[i]; } @@ -323,8 +410,8 @@ HRESULT CPanel::CreateShellContextMenu( // Get a pidl for the file itself. CRecordVector pidls; - pidls.Reserve(operatedIndices.Size()); - for (int i = 0; i < operatedIndices.Size(); i++) + pidls.ClearAndReserve(operatedIndices.Size()); + FOR_VECTOR (i, operatedIndices) { LPITEMIDLIST pidl; UString fileName = GetItemRelPath(operatedIndices[i]); @@ -332,7 +419,7 @@ HRESULT CPanel::CreateShellContextMenu( fileName += WCHAR_PATH_SEPARATOR; RINOK(parentFolder->ParseDisplayName(GetParent(), 0, (wchar_t *)(const wchar_t *)fileName, &eaten, &pidl, 0)); - pidls.Add(pidl); + pidls.AddInReserved(pidl); } ITEMIDLIST temp; @@ -431,7 +518,7 @@ void CPanel::CreateSystemMenu(HMENU menuSpec, menuItem.fType = MFT_STRING; menuItem.hSubMenu = popupMenu.Detach(); // menuDestroyer.Disable(); - menuItem.StringValue = LangString(IDS_SYSTEM, 0x030202A0); + LangString(IDS_SYSTEM, menuItem.StringValue); menu.InsertItem(0, true, menuItem); } /* @@ -489,11 +576,11 @@ void CPanel::CreateSevenZipMenu(HMENU menuSpec, */ UString currentFolderUnicode = _currentFolderPrefix; UStringVector names; - int i; - for(i = 0; i < operatedIndices.Size(); i++) + unsigned i; + for (i = 0; i < operatedIndices.Size(); i++) names.Add(currentFolderUnicode + GetItemRelPath(operatedIndices[i])); CRecordVector namePointers; - for(i = 0; i < operatedIndices.Size(); i++) + for (i = 0; i < operatedIndices.Size(); i++) namePointers.Add(names[i]); // NFile::NDirectory::MySetCurrentDirectory(currentFolderUnicode); @@ -524,19 +611,24 @@ void CPanel::CreateFileMenu(HMENU menuSpec, CMenu menu; menu.Attach(menuSpec); - - CreateSevenZipMenu(menu, operatedIndices, sevenZipContextMenu); - if (g_App.ShowSystemMenu) - CreateSystemMenu(menu, operatedIndices, systemContextMenu); + + if (!IsArcFolder()) + { + CreateSevenZipMenu(menu, operatedIndices, sevenZipContextMenu); + // CreateSystemMenu is very slow if you call it inside ZIP archive with big number of files + // Windows probably can parse items inside ZIP archive. + if (g_App.ShowSystemMenu) + CreateSystemMenu(menu, operatedIndices, systemContextMenu); + } /* if (menu.GetItemCount() > 0) menu.AppendItem(MF_SEPARATOR, 0, (LPCTSTR)0); */ - int i; + unsigned i; for (i = 0; i < operatedIndices.Size(); i++) - if (IsItemFolder(operatedIndices[i])) + if (IsItem_Folder(operatedIndices[i])) break; bool allAreFiles = (i == operatedIndices.Size()); LoadFileMenu(menu, menu.GetItemCount(), programMenu, @@ -627,7 +719,9 @@ bool CPanel::OnContextMenu(HANDLE windowHandle, int xPos, int yPos) CRecordVector operatedIndices; GetOperatedItemIndices(operatedIndices); - if (xPos < 0 || yPos < 0) + // negative x,y are possible for multi-screen modes. + // x=-1 && y=-1 for keyboard call (SHIFT+F10 and others). + if (xPos == -1 && yPos == -1) { if (operatedIndices.Size() == 0) { @@ -669,7 +763,7 @@ bool CPanel::OnContextMenu(HANDLE windowHandle, int xPos, int yPos) if (result == 0) return true; - if (result >= kPluginMenuStartID) + if (result >= kMenuCmdID_Plugin_Start) { InvokePluginCommand(result, sevenZipContextMenu, systemContextMenu); return true; diff --git a/CPP/7zip/UI/FileManager/PanelOperations.cpp b/CPP/7zip/UI/FileManager/PanelOperations.cpp old mode 100755 new mode 100644 index 9c109d0d..4633aead --- a/CPP/7zip/UI/FileManager/PanelOperations.cpp +++ b/CPP/7zip/UI/FileManager/PanelOperations.cpp @@ -2,14 +2,13 @@ #include "StdAfx.h" -#include "Common/DynamicBuffer.h" -#include "Common/StringConvert.h" +#include "../../../Common/DynamicBuffer.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/Wildcard.h" -#include "Windows/COM.h" -#include "Windows/FileDir.h" -#include "Windows/PropVariant.h" -#include "Windows/ResourceString.h" -#include "Windows/Thread.h" +#include "../../../Windows/COM.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/PropVariant.h" #include "ComboDialog.h" @@ -23,6 +22,7 @@ using namespace NWindows; using namespace NFile; +using namespace NName; #ifndef _UNICODE extern bool g_IsNT; @@ -82,7 +82,7 @@ HRESULT CThreadFolderOperations::DoOperation(CPanel &panel, const UString &progr UpdateCallbackSpec->ProgressDialog = &ProgressDialog; ProgressDialog.WaitMode = true; - ProgressDialog.Sync.SetErrorMessageTitle(titleError); + ProgressDialog.Sync.FinalMessage.ErrorMessage.Title = titleError; Result = S_OK; bool usePassword = false; @@ -97,8 +97,8 @@ HRESULT CThreadFolderOperations::DoOperation(CPanel &panel, const UString &progr UpdateCallbackSpec->Init(usePassword, password); ProgressDialog.MainWindow = panel._mainWindow; // panel.GetParent() - ProgressDialog.MainTitle = LangString(IDS_APP_TITLE, 0x03000000); - ProgressDialog.MainAddTitle = progressTitle + UString(L" "); + ProgressDialog.MainTitle = L"7-Zip"; // LangString(IDS_APP_TITLE); + ProgressDialog.MainAddTitle = progressTitle + L' '; RINOK(Create(progressTitle, ProgressDialog.MainWindow)); return Result; @@ -108,9 +108,17 @@ HRESULT CThreadFolderOperations::DoOperation(CPanel &panel, const UString &progr typedef int (WINAPI * SHFileOperationWP)(LPSHFILEOPSTRUCTW lpFileOp); #endif -void CPanel::DeleteItems(bool toRecycleBin) +void CPanel::MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID) { - CPanel::CDisableTimerProcessing disableTimerProcessing2(*this); + if (errorCode == E_NOINTERFACE) + MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); + else + MessageBoxError(errorCode, LangString(resourceID)); +} + +void CPanel::DeleteItems(bool NON_CE_VAR(toRecycleBin)) +{ + CDisableTimerProcessing disableTimerProcessing(*this); CRecordVector indices; GetOperatedItemIndices(indices); if (indices.IsEmpty()) @@ -120,23 +128,19 @@ void CPanel::DeleteItems(bool toRecycleBin) #ifndef UNDER_CE // WM6 / SHFileOperationW doesn't ask user! So we use internal delete - bool useInternalDelete = false; if (IsFSFolder() && toRecycleBin) { + bool useInternalDelete = false; #ifndef _UNICODE if (!g_IsNT) { CDynamicBuffer buffer; - size_t size = 0; - for (int i = 0; i < indices.Size(); i++) + FOR_VECTOR (i, indices) { 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; + memcpy(buffer.GetCurPtrAndGrow(path.Len() + 1), (const CHAR *)path, (path.Len() + 1) * sizeof(CHAR)); } - buffer.EnsureCapacity(size + 1); - ((CHAR *)buffer)[size] = 0; + *buffer.GetCurPtrAndGrow(1) = 0; SHFILEOPSTRUCTA fo; fo.hwnd = GetParent(); fo.wFunc = FO_DELETE; @@ -158,25 +162,21 @@ void CPanel::DeleteItems(bool toRecycleBin) #endif { CDynamicBuffer buffer; - size_t size = 0; - int maxLen = 0; - for (int i = 0; i < indices.Size(); i++) + unsigned maxLen = 0; + FOR_VECTOR (i, indices) { // 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; + if (path.Len() > maxLen) + maxLen = path.Len(); + memcpy(buffer.GetCurPtrAndGrow(path.Len() + 1), (const WCHAR *)path, (path.Len() + 1) * sizeof(WCHAR)); } - buffer.EnsureCapacity(size + 1); - ((WCHAR *)buffer)[size] = 0; + *buffer.GetCurPtrAndGrow(1) = 0; if (maxLen >= MAX_PATH) { if (toRecycleBin) { - MessageBoxErrorLang(IDS_ERROR_LONG_PATH_TO_RECYCLE, 0x03020218); + MessageBoxErrorLang(IDS_ERROR_LONG_PATH_TO_RECYCLE); return; } useInternalDelete = true; @@ -210,67 +210,60 @@ void CPanel::DeleteItems(bool toRecycleBin) if (fo.fAnyOperationsAborted) MessageBoxError(result, LangString(IDS_ERROR_DELETING, 0x03020217)); */ + if (!useInternalDelete) + { + RefreshListCtrl(state); + return; + } } - else - useInternalDelete = true; - if (useInternalDelete) #endif - DeleteItemsInternal(indices); - RefreshListCtrl(state); -} + + // DeleteItemsInternal -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); + MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_ERROR_DELETING); return; } - UString title; - UString message; + UInt32 titleID, messageID; + UString messageParam; if (indices.Size() == 1) { int index = indices[0]; - const UString itemName = GetItemRelPath(index); - if (IsItemFolder(index)) + messageParam = GetItemRelPath(index); + if (IsItem_Folder(index)) { - title = LangString(IDS_CONFIRM_FOLDER_DELETE, 0x03020211); - message = MyFormatNew(IDS_WANT_TO_DELETE_FOLDER, 0x03020214, itemName); + titleID = IDS_CONFIRM_FOLDER_DELETE; + messageID = IDS_WANT_TO_DELETE_FOLDER; } else { - title = LangString(IDS_CONFIRM_FILE_DELETE, 0x03020210); - message = MyFormatNew(IDS_WANT_TO_DELETE_FILE, 0x03020213, itemName); + titleID = IDS_CONFIRM_FILE_DELETE; + messageID = IDS_WANT_TO_DELETE_FILE; } } else { - title = LangString(IDS_CONFIRM_ITEMS_DELETE, 0x03020212); - message = MyFormatNew(IDS_WANT_TO_DELETE_ITEMS, 0x03020215, - NumberToString(indices.Size())); + titleID = IDS_CONFIRM_ITEMS_DELETE; + messageID = IDS_WANT_TO_DELETE_ITEMS; + messageParam = NumberToString(indices.Size()); } - if (::MessageBoxW(GetParent(), message, title, MB_OKCANCEL | MB_ICONQUESTION) != IDOK) + if (::MessageBoxW(GetParent(), MyFormatNew(messageID, messageParam), LangString(titleID), MB_OKCANCEL | MB_ICONQUESTION) != IDOK) return; + CDisableNotify disableNotify(*this); { CThreadFolderOperations op(FOLDER_TYPE_DELETE); op.FolderOperations = folderOperations; op.Indices = indices; op.DoOperation(*this, - LangString(IDS_DELETING, 0x03020216), - LangString(IDS_ERROR_DELETING, 0x03020217)); + LangString(IDS_DELETING), + LangString(IDS_ERROR_DELETING)); } RefreshTitleAlways(); + RefreshListCtrl(state); } BOOL CPanel::OnBeginLabelEdit(LV_DISPINFOW * lpnmh) @@ -291,10 +284,10 @@ static UString GetLastPart(const UString name) int slash1Pos = name.ReverseFind(L'\\'); slashPos = MyMax(slashPos, slash1Pos); #endif - return name.Mid(slashPos + 1); + return name.Ptr(slashPos + 1); } -bool IsCorrectFsName(const UString name) +bool IsCorrectFsName(const UString &name) { const UString lastPart = GetLastPart(name); return @@ -302,23 +295,41 @@ bool IsCorrectFsName(const UString name) lastPart != L".."; } +bool CorrectFsPath(const UString &relBase, const UString &path, UString &result); + +bool CPanel::CorrectFsPath(const UString &path2, UString &result) +{ + return ::CorrectFsPath(_currentFolderPrefix, path2, result); +} + BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh) { if (lpnmh->item.pszText == NULL) return FALSE; + CDisableTimerProcessing disableTimerProcessing2(*this); CMyComPtr folderOperations; if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) { - MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_ERROR_RENAMING, 0x03020221); + MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_ERROR_RENAMING); return FALSE; } - const UString newName = lpnmh->item.pszText; + UString newName = lpnmh->item.pszText; if (!IsCorrectFsName(newName)) { MessageBoxError(E_INVALIDARG); return FALSE; } - CPanel::CDisableTimerProcessing disableTimerProcessing2(*this); + + if (IsFSFolder()) + { + UString correctName; + if (!CorrectFsPath(newName, correctName)) + { + MessageBoxError(E_INVALIDARG); + return FALSE; + } + newName = correctName; + } SaveSelectedState(_selectedState); @@ -328,16 +339,21 @@ BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh) const UString prefix = GetItemPrefix(realIndex); + CDisableNotify disableNotify(*this); { 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)); + /* HRESULTres = */ op.DoOperation(*this, + LangString(IDS_RENAMING), + LangString(IDS_ERROR_RENAMING)); + // fixed in 9.26: we refresh list even after errors + // (it's more safe, since error can be at different stages, so list can be incorrect). + /* if (res != S_OK) return FALSE; + */ } // Can't use RefreshListCtrl here. @@ -357,48 +373,66 @@ BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh) return TRUE; } +bool Dlg_CreateFolder(HWND wnd, UString &destName); + void CPanel::CreateFolder() { CMyComPtr folderOperations; if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) { - MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_CREATE_FOLDER_ERROR, 0x03020233); + MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_CREATE_FOLDER_ERROR); return; } - CPanel::CDisableTimerProcessing disableTimerProcessing2(*this); + 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) + + UString newName; + if (!Dlg_CreateFolder(GetParent(), newName)) return; - UString newName = comboDialog.Value; if (!IsCorrectFsName(newName)) { MessageBoxError(E_INVALIDARG); return; } + + if (IsFSFolder()) + { + UString correctName; + if (!CorrectFsPath(newName, correctName)) + { + MessageBoxError(E_INVALIDARG); + return; + } + newName = correctName; + } + HRESULT res; + CDisableNotify disableNotify(*this); { 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)); + res = op.DoOperation(*this, + LangString(IDS_CREATE_FOLDER), + LangString(IDS_CREATE_FOLDER_ERROR)); + /* + // fixed for 9.26: we must refresh always if (res != S_OK) return; + */ + } + if (res == S_OK) + { + int pos = newName.Find(WCHAR_PATH_SEPARATOR); + if (pos >= 0) + newName.DeleteFrom(pos); + if (!_mySelectMode) + state.SelectedNames.Clear(); + state.FocusedName = newName; + state.SelectFocused = true; } - 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); } @@ -408,28 +442,44 @@ void CPanel::CreateFile() CMyComPtr folderOperations; if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) { - MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_CREATE_FILE_ERROR, 0x03020243); + MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_CREATE_FILE_ERROR); return; } - CPanel::CDisableTimerProcessing disableTimerProcessing2(*this); + 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) + CComboDialog dlg; + LangString(IDS_CREATE_FILE, dlg.Title); + LangString(IDS_CREATE_FILE_NAME, dlg.Static); + LangString(IDS_CREATE_FILE_DEFAULT_NAME, dlg.Value); + + if (dlg.Create(GetParent()) != IDOK) return; - UString newName = comboDialog.Value; + + CDisableNotify disableNotify(*this); + + UString newName = dlg.Value; + + if (IsFSFolder()) + { + UString correctName; + if (!CorrectFsPath(newName, correctName)) + { + MessageBoxError(E_INVALIDARG); + return; + } + newName = correctName; + } + HRESULT result = folderOperations->CreateFile(newName, 0); if (result != S_OK) { - MessageBoxErrorForUpdate(result, IDS_CREATE_FILE_ERROR, 0x03020243); + MessageBoxErrorForUpdate(result, IDS_CREATE_FILE_ERROR); return; } int pos = newName.Find(WCHAR_PATH_SEPARATOR); if (pos >= 0) - newName = newName.Left(pos); + newName.DeleteFrom(pos); if (!_mySelectMode) state.SelectedNames.Clear(); state.FocusedName = newName; @@ -446,7 +496,7 @@ void CPanel::RenameFile() void CPanel::ChangeComment() { - CPanel::CDisableTimerProcessing disableTimerProcessing2(*this); + CDisableTimerProcessing disableTimerProcessing2(*this); int index = _listView.GetFocusedItem(); if (index < 0) return; @@ -458,7 +508,7 @@ void CPanel::ChangeComment() CMyComPtr folderOperations; if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) { - MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return; } @@ -473,19 +523,20 @@ void CPanel::ChangeComment() 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) + CComboDialog dlg; + dlg.Title = name + L' ' + LangString(IDS_COMMENT); + dlg.Value = comment; + LangString(IDS_COMMENT2, dlg.Static); + if (dlg.Create(GetParent()) != IDOK) return; - NCOM::CPropVariant propVariant = comboDialog.Value; + NCOM::CPropVariant propVariant = dlg.Value; + CDisableNotify disableNotify(*this); HRESULT result = folderOperations->SetProperty(realIndex, kpidComment, &propVariant, NULL); if (result != S_OK) { if (result == E_NOINTERFACE) - MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); else MessageBoxError(result, L"Set Comment Error"); } diff --git a/CPP/7zip/UI/FileManager/PanelSelect.cpp b/CPP/7zip/UI/FileManager/PanelSelect.cpp old mode 100755 new mode 100644 index b31c2e9d..a40997c2 --- a/CPP/7zip/UI/FileManager/PanelSelect.cpp +++ b/CPP/7zip/UI/FileManager/PanelSelect.cpp @@ -4,14 +4,12 @@ #include "resource.h" -#include "Common/StringConvert.h" -#include "Common/Wildcard.h" - -#include "Panel.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/Wildcard.h" #include "ComboDialog.h" - #include "LangUtils.h" +#include "Panel.h" void CPanel::OnShiftSelectMessage() { @@ -145,17 +143,15 @@ void CPanel::UpdateSelection() 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) + CComboDialog dlg; + LangString(selectMode ? IDS_SELECT : IDS_DESELECT, dlg.Title ); + LangString(IDS_SELECT_MASK, dlg.Static); + dlg.Value = L'*'; + if (dlg.Create(GetParent()) != IDOK) return; - const UString &mask = comboDialog.Value; - for (int i = 0; i < _selectedStatusVector.Size(); i++) - if (CompareWildCardWithName(mask, GetItemName(i))) + const UString &mask = dlg.Value; + FOR_VECTOR (i, _selectedStatusVector) + if (DoesWildcardMatchName(mask, GetItemName(i))) _selectedStatusVector[i] = selectMode; UpdateSelection(); } @@ -167,7 +163,7 @@ void CPanel::SelectByType(bool selectMode) return; int realIndex = GetRealItemIndex(focusedItem); UString name = GetItemName(realIndex); - bool isItemFolder = IsItemFolder(realIndex); + bool isItemFolder = IsItem_Folder(realIndex); /* UInt32 numItems; @@ -178,8 +174,8 @@ void CPanel::SelectByType(bool selectMode) if (isItemFolder) { - for (int i = 0; i < _selectedStatusVector.Size(); i++) - if (IsItemFolder(i) == isItemFolder) + FOR_VECTOR (i, _selectedStatusVector) + if (IsItem_Folder(i) == isItemFolder) _selectedStatusVector[i] = selectMode; } else @@ -187,15 +183,16 @@ void CPanel::SelectByType(bool selectMode) 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) + FOR_VECTOR (i, _selectedStatusVector) + if (IsItem_Folder(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))) + UString mask = L'*'; + mask += name.Ptr(pos); + FOR_VECTOR (i, _selectedStatusVector) + if (IsItem_Folder(i) == isItemFolder && DoesWildcardMatchName(mask, GetItemName(i))) _selectedStatusVector[i] = selectMode; } } @@ -204,7 +201,7 @@ void CPanel::SelectByType(bool selectMode) void CPanel::SelectAll(bool selectMode) { - for (int i = 0; i < _selectedStatusVector.Size(); i++) + FOR_VECTOR (i, _selectedStatusVector) _selectedStatusVector[i] = selectMode; UpdateSelection(); } @@ -213,8 +210,8 @@ void CPanel::InvertSelection() { if (!_mySelectMode) { - int numSelected = 0; - for (int i = 0; i < _selectedStatusVector.Size(); i++) + unsigned numSelected = 0; + FOR_VECTOR (i, _selectedStatusVector) if (_selectedStatusVector[i]) numSelected++; if (numSelected == 1) @@ -229,7 +226,7 @@ void CPanel::InvertSelection() } } } - for (int i = 0; i < _selectedStatusVector.Size(); i++) + FOR_VECTOR (i, _selectedStatusVector) _selectedStatusVector[i] = !_selectedStatusVector[i]; UpdateSelection(); } @@ -267,9 +264,9 @@ void CPanel::OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate) 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++) + unsigned startItem = MyMin((unsigned)focusedIndex, (unsigned)indexInList); + unsigned finishItem = MyMax((unsigned)focusedIndex, (unsigned)indexInList); + FOR_VECTOR (i, _selectedStatusVector) { int realIndex = GetRealItemIndex(i); if (realIndex == kParentIndex) diff --git a/CPP/7zip/UI/FileManager/PanelSort.cpp b/CPP/7zip/UI/FileManager/PanelSort.cpp old mode 100755 new mode 100644 index 5ac04800..2ca29a15 --- a/CPP/7zip/UI/FileManager/PanelSort.cpp +++ b/CPP/7zip/UI/FileManager/PanelSort.cpp @@ -2,7 +2,8 @@ #include "StdAfx.h" -#include "Windows/PropVariant.h" +#include "../../../../C/CpuArch.h" +#include "../../../Windows/PropVariant.h" #include "../../PropID.h" @@ -10,46 +11,156 @@ using namespace NWindows; -static UString GetExtension(const UString &name) +int CompareFileNames_ForFolderList(const wchar_t *s1, const wchar_t *s2) +{ + for (;;) + { + wchar_t c1 = *s1; + wchar_t c2 = *s2; + if ((c1 >= '0' && c1 <= '9') && + (c2 >= '0' && c2 <= '9')) + { + for (; *s1 == '0'; s1++); + for (; *s2 == '0'; s2++); + size_t len1 = 0; + size_t len2 = 0; + for (; (s1[len1] >= '0' && s1[len1] <= '9'); len1++); + for (; (s2[len2] >= '0' && s2[len2] <= '9'); len2++); + if (len1 < len2) return -1; + if (len1 > len2) return 1; + for (; len1 > 0; s1++, s2++, len1--) + { + if (*s1 == *s2) continue; + return (*s1 < *s2) ? -1 : 1; + } + c1 = *s1; + c2 = *s2; + } + s1++; + s2++; + if (c1 != c2) + { + // Probably we need to change the order for special characters like in Explorer. + 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; + } +} + +static int CompareFileNames_Le16(const Byte *s1, unsigned size1, const Byte *s2, unsigned size2) +{ + size1 &= ~1; + size2 &= ~1; + for (unsigned i = 0;; i += 2) + { + if (i >= size1) + return (i >= size2) ? 0 : -1; + if (i >= size2) + return 1; + UInt16 c1 = GetUi16(s1 + i); + UInt16 c2 = GetUi16(s2 + i); + if (c1 == c2) + { + if (c1 == 0) + return 0; + continue; + } + if (c1 < c2) + return -1; + return 1; + } +} + +static inline const wchar_t *GetExtensionPtr(const UString &name) { int dotPos = name.ReverseFind(L'.'); - if (dotPos < 0) - return UString(); - return name.Mid(dotPos); + return name.Ptr((dotPos < 0) ? name.Len() : dotPos); } +void CPanel::SetSortRawStatus() +{ + _isRawSortProp = false; + FOR_VECTOR (i, _properties) + { + const CItemProperty &prop = _properties[i]; + if (prop.ID == _sortID) + { + _isRawSortProp = prop.IsRawProp ? 1 : 0; + return; + } + } +} + + int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) { if (lpData == NULL) return 0; CPanel *panel = (CPanel*)lpData; - switch(panel->_sortID) + + PROPID propID = panel->_sortID; + + if (propID == kpidNoProperty) + return MyCompare(lParam1, lParam2); + + if (panel->_isRawSortProp) + { + // Sha1, NtSecurity, NtReparse + const void *data1; + const void *data2; + UInt32 dataSize1; + UInt32 dataSize2; + UInt32 propType1; + UInt32 propType2; + if (panel->_folderRawProps->GetRawProp((UInt32)lParam1, propID, &data1, &dataSize1, &propType1) != 0) return 0; + if (panel->_folderRawProps->GetRawProp((UInt32)lParam2, propID, &data2, &dataSize2, &propType2) != 0) return 0; + if (dataSize1 == 0) + return (dataSize2 == 0) ? 0 : -1; + if (dataSize2 == 0) + return 1; + if (propType1 != NPropDataType::kRaw) return 0; + if (propType2 != NPropDataType::kRaw) return 0; + if (propID == kpidNtReparse) + { + NFile::CReparseShortInfo r1; r1.Parse((const Byte *)data1, dataSize1); + NFile::CReparseShortInfo r2; r2.Parse((const Byte *)data2, dataSize2); + return CompareFileNames_Le16( + (const Byte *)data1 + r1.Offset, r1.Size, + (const Byte *)data2 + r2.Offset, r2.Size); + } + } + + if (panel->_folderCompare) + return panel->_folderCompare->CompareItems((UInt32)lParam1, (UInt32)lParam2, propID, panel->_isRawSortProp); + + switch (propID) { // 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); + int res = CompareFileNames_ForFolderList(name1, 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 = CompareFileNames_ForFolderList(prefix1, 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); + const UString name1 = panel->GetItemName((int)lParam1); + const UString name2 = panel->GetItemName((int)lParam2); + return CompareFileNames_ForFolderList( + GetExtensionPtr(name1), + GetExtensionPtr(name2)); } } /* @@ -59,7 +170,6 @@ int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) */ // PROPID propID = panel->_properties[panel->_sortIndex].ID; - PROPID propID = panel->_sortID; NCOM::CPropVariant prop1, prop2; // Name must be first property @@ -85,8 +195,8 @@ int CALLBACK CompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) CPanel *panel = (CPanel*)lpData; - bool isDir1 = panel->IsItemFolder((int)lParam1); - bool isDir2 = panel->IsItemFolder((int)lParam2); + bool isDir1 = panel->IsItem_Folder((int)lParam1); + bool isDir2 = panel->IsItem_Folder((int)lParam2); if (isDir1 && !isDir2) return -1; if (isDir2 && !isDir1) return 1; @@ -145,6 +255,7 @@ void CPanel::SortItemsWithPropID(PROPID propID) break; } } + SetSortRawStatus(); _listView.SortItems(CompareItems, (LPARAM)this); _listView.EnsureVisible(_listView.GetFocusedItem(), false); } diff --git a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp old mode 100755 new mode 100644 index ba0bedf8..ce15fcc5 --- a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp +++ b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp @@ -2,12 +2,10 @@ #include "StdAfx.h" -#include "Common/IntToString.h" +#include "../../../Common/IntToString.h" -#include "Windows/Error.h" -#include "Windows/FileIO.h" -#include "Windows/FileFind.h" -#include "Windows/FileName.h" +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/FileName.h" #include "../GUI/ExtractRes.h" @@ -20,7 +18,11 @@ #include "SplitDialog.h" #include "SplitUtils.h" +#include "PropertyNameRes.h" + using namespace NWindows; +using namespace NFile; +using namespace NDir; static const wchar_t *g_Message_FileWriteError = L"File write error"; @@ -42,47 +44,38 @@ struct CVolSeqName bool ParseName(const UString &name) { - if (name.Right(2) != L"01") + if (name.Len() < 2) 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); + if (name.Back() != L'1' || name[name.Len() - 2] != L'0') + return false; + + unsigned pos = name.Len() - 2; + for (; pos > 0 && name[pos - 1] == '0'; pos--); + UnchangedPart.SetFrom(name, pos); + ChangedPart = name.Ptr(pos); return true; } - UString GetNextName() + UString GetNextName(); +}; + + +UString CVolSeqName::GetNextName() +{ + for (int i = (int)ChangedPart.Len() - 1; i >= 0; i--) { - UString newName; - int i; - int numLetters = ChangedPart.Length(); - for (i = numLetters - 1; i >= 0; i--) + wchar_t c = ChangedPart[i]; + if (c != L'9') { - 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; + ChangedPart.ReplaceOneCharAtPos(i, (wchar_t)(c + 1)); break; } - ChangedPart = newName; - return UnchangedPart + ChangedPart; + ChangedPart.ReplaceOneCharAtPos(i, L'0'); + if (i == 0) + ChangedPart.InsertAtFront(L'1'); } -}; + return UnchangedPart + ChangedPart; +} static const UInt32 kBufSize = (1 << 20); @@ -98,10 +91,10 @@ public: HRESULT CThreadSplit::ProcessVirt() { - NFile::NIO::CInFile inFile; + NIO::CInFile inFile; if (!inFile.Open(FilePath)) return GetLastError(); - NFile::NIO::COutFile outFile; + NIO::COutFile outFile; CMyBuffer bufferObject; if (!bufferObject.Allocate(kBufSize)) return E_OUTOFMEMORY; @@ -114,11 +107,11 @@ HRESULT CThreadSplit::ProcessVirt() return GetLastError(); CProgressSync &sync = ProgressDialog.Sync; - sync.SetProgress(length, 0); + sync.Set_NumBytesTotal(length); UInt64 pos = 0; UInt64 numFiles = 0; - int volIndex = 0; + unsigned volIndex = 0; for (;;) { @@ -140,8 +133,8 @@ HRESULT CThreadSplit::ProcessVirt() FString name = VolBasePath; name += FTEXT('.'); name += us2fs(seqName.GetNextName()); - sync.SetCurrentFileName(fs2us(name)); - sync.SetNumFilesCur(numFiles++); + sync.Set_FilePath(fs2us(name)); + sync.Set_NumFilesCur(numFiles++); if (!outFile.Create(name, false)) { HRESULT res = GetLastError(); @@ -162,9 +155,9 @@ HRESULT CThreadSplit::ProcessVirt() curVolSize = 0; } pos += processedSize; - RINOK(sync.SetPosAndCheckPaused(pos)); + RINOK(sync.Set_NumBytesCur(pos)); } - sync.SetNumFilesCur(numFiles); + sync.Set_NumFilesCur(numFiles); return S_OK; } @@ -174,7 +167,7 @@ void CApp::Split() CPanel &srcPanel = Panels[srcPanelIndex]; if (!srcPanel.IsFSFolder()) { - srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return; } CRecordVector indices; @@ -183,13 +176,13 @@ void CApp::Split() return; if (indices.Size() != 1) { - srcPanel.MessageBoxErrorLang(IDS_SELECT_ONE_FILE, 0x03020A02); + srcPanel.MessageBoxErrorLang(IDS_SELECT_ONE_FILE); return; } int index = indices[0]; - if (srcPanel.IsItemFolder(index)) + if (srcPanel.IsItem_Folder(index)) { - srcPanel.MessageBoxErrorLang(IDS_SELECT_ONE_FILE, 0x03020A02); + srcPanel.MessageBoxErrorLang(IDS_SELECT_ONE_FILE); return; } const UString itemName = srcPanel.GetItemName(index); @@ -204,10 +197,10 @@ void CApp::Split() CSplitDialog splitDialog; splitDialog.FilePath = srcPanel.GetItemRelPath(index); splitDialog.Path = path; - if (splitDialog.Create(srcPanel.GetParent()) == IDCANCEL) + if (splitDialog.Create(srcPanel.GetParent()) != IDOK) return; - NFile::NFind::CFileInfo fileInfo; + NFind::CFileInfo fileInfo; if (!fileInfo.Find(us2fs(srcPath + itemName))) { srcPanel.MessageBoxMyError(L"Can not find file"); @@ -215,7 +208,7 @@ void CApp::Split() } if (fileInfo.Size <= splitDialog.VolumeSizes.Front()) { - srcPanel.MessageBoxErrorLang(IDS_SPLIT_VOL_MUST_BE_SMALLER, 0x03020522); + srcPanel.MessageBoxErrorLang(IDS_SPLIT_VOL_MUST_BE_SMALLER); return; } const UInt64 numVolumes = GetNumberOfVolumes(fileInfo.Size, splitDialog.VolumeSizes); @@ -223,17 +216,17 @@ void CApp::Split() { wchar_t s[32]; ConvertUInt64ToString(numVolumes, s); - if (::MessageBoxW(srcPanel, MyFormatNew(IDS_SPLIT_CONFIRM_MESSAGE, 0x03020521, s), - LangString(IDS_SPLIT_CONFIRM_TITLE, 0x03020520), + if (::MessageBoxW(srcPanel, MyFormatNew(IDS_SPLIT_CONFIRM_MESSAGE, s), + LangString(IDS_SPLIT_CONFIRM_TITLE), MB_YESNOCANCEL | MB_ICONQUESTION) != IDYES) return; } path = splitDialog.Path; - NFile::NName::NormalizeDirPathPrefix(path); - if (!NFile::NDirectory::CreateComplexDirectory(us2fs(path))) + NName::NormalizeDirPathPrefix(path); + if (!CreateComplexDir(us2fs(path))) { - srcPanel.MessageBoxMyError(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, 0x02000603, path)); + srcPanel.MessageBoxError2Lines(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, path), ::GetLastError()); return; } @@ -243,15 +236,15 @@ void CApp::Split() CProgressDialog &progressDialog = spliter.ProgressDialog; - UString progressWindowTitle = LangString(IDS_APP_TITLE, 0x03000000); - UString title = LangString(IDS_SPLITTING, 0x03020510); + UString progressWindowTitle = L"7-Zip"; // LangString(IDS_APP_TITLE, 0x03000000); + UString title = LangString(IDS_SPLITTING); progressDialog.ShowCompressionInfo = false; progressDialog.MainWindow = _window; progressDialog.MainTitle = progressWindowTitle; - progressDialog.MainAddTitle = title + UString(L" "); - progressDialog.Sync.SetTitleFileName(itemName); + progressDialog.MainAddTitle = title + L' '; + progressDialog.Sync.Set_TitleFileName(itemName); spliter.FilePath = us2fs(srcPath + itemName); @@ -269,8 +262,8 @@ void CApp::Split() RefreshTitleAlways(); - // disableTimerProcessing1.Restore(); - // disableTimerProcessing2.Restore(); + // disableNotify.Restore(); + // disableNotify.Restore(); // srcPanel.SetFocusToList(); // srcPanel.RefreshListCtrlSaveFocused(); } @@ -288,7 +281,7 @@ public: HRESULT CThreadCombine::ProcessVirt() { - NFile::NIO::COutFile outFile; + NIO::COutFile outFile; if (!outFile.Create(OutputPath, false)) { HRESULT res = GetLastError(); @@ -297,16 +290,16 @@ HRESULT CThreadCombine::ProcessVirt() } CProgressSync &sync = ProgressDialog.Sync; - sync.SetProgress(TotalSize, 0); + sync.Set_NumBytesTotal(TotalSize); 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++) + FOR_VECTOR (i, Names) { - NFile::NIO::CInFile inFile; + NIO::CInFile inFile; const FString nextName = InputDirPrefix + Names[i]; if (!inFile.Open(nextName)) { @@ -314,7 +307,7 @@ HRESULT CThreadCombine::ProcessVirt() SetErrorPath1(nextName); return res; } - sync.SetCurrentFileName(fs2us(nextName)); + sync.Set_FilePath(fs2us(nextName)); for (;;) { UInt32 processedSize; @@ -336,15 +329,15 @@ HRESULT CThreadCombine::ProcessVirt() if (needSize != processedSize) throw g_Message_FileWriteError; pos += processedSize; - RINOK(sync.SetPosAndCheckPaused(pos)); + RINOK(sync.Set_NumBytesCur(pos)); } } return S_OK; } -extern void AddValuePair2(UINT resourceID, UInt32 langID, UInt64 num, UInt64 size, UString &s); +extern void AddValuePair2(UString &s, UINT resourceID, UInt64 num, UInt64 size); -static void AddInfoFileName(const UString &name, UString &dest) +static void AddInfoFileName(UString &dest, const UString &name) { dest += L"\n "; dest += name; @@ -356,7 +349,7 @@ void CApp::Combine() CPanel &srcPanel = Panels[srcPanelIndex]; if (!srcPanel.IsFSFolder()) { - srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return; } CRecordVector indices; @@ -364,9 +357,9 @@ void CApp::Combine() if (indices.IsEmpty()) return; int index = indices[0]; - if (indices.Size() != 1 || srcPanel.IsItemFolder(index)) + if (indices.Size() != 1 || srcPanel.IsItem_Folder(index)) { - srcPanel.MessageBoxErrorLang(IDS_COMBINE_SELECT_ONE_FILE, 0x03020620); + srcPanel.MessageBoxErrorLang(IDS_COMBINE_SELECT_ONE_FILE); return; } const UString itemName = srcPanel.GetItemName(index); @@ -382,7 +375,7 @@ void CApp::Combine() CVolSeqName volSeqName; if (!volSeqName.ParseName(itemName)) { - srcPanel.MessageBoxErrorLang(IDS_COMBINE_CANT_DETECT_SPLIT_FILE, 0x03020621); + srcPanel.MessageBoxErrorLang(IDS_COMBINE_CANT_DETECT_SPLIT_FILE); return; } @@ -393,7 +386,7 @@ void CApp::Combine() combiner.TotalSize = 0; for (;;) { - NFile::NFind::CFileInfo fileInfo; + NFind::CFileInfo fileInfo; if (!fileInfo.Find(us2fs(srcPath + nextName)) || fileInfo.IsDir()) break; combiner.Names.Add(us2fs(nextName)); @@ -402,7 +395,7 @@ void CApp::Combine() } if (combiner.Names.Size() == 1) { - srcPanel.MessageBoxErrorLang(IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART, 0x03020622); + srcPanel.MessageBoxErrorLang(IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART); return; } @@ -413,38 +406,38 @@ void CApp::Combine() } UString info; - AddValuePair2(IDS_FILES_COLON, 0x02000320, combiner.Names.Size(), combiner.TotalSize, info); + AddValuePair2(info, IDS_PROP_FILES, combiner.Names.Size(), combiner.TotalSize); info += L"\n"; info += srcPath; - int i; + unsigned i; for (i = 0; i < combiner.Names.Size() && i < 2; i++) - AddInfoFileName(fs2us(combiner.Names[i]), info); + AddInfoFileName(info, fs2us(combiner.Names[i])); if (i != combiner.Names.Size()) { if (i + 1 != combiner.Names.Size()) - AddInfoFileName(L"...", info); - AddInfoFileName(fs2us(combiner.Names.Back()), info); + AddInfoFileName(info, L"..."); + AddInfoFileName(info, fs2us(combiner.Names.Back())); } { CCopyDialog copyDialog; copyDialog.Value = path; - copyDialog.Title = LangString(IDS_COMBINE, 0x03020600); + LangString(IDS_COMBINE, copyDialog.Title); copyDialog.Title += ' '; copyDialog.Title += srcPanel.GetItemRelPath(index); - copyDialog.Static = LangString(IDS_COMBINE_TO, 0x03020601); + LangString(IDS_COMBINE_TO, copyDialog.Static); copyDialog.Info = info; - if (copyDialog.Create(srcPanel.GetParent()) == IDCANCEL) + if (copyDialog.Create(srcPanel.GetParent()) != IDOK) return; path = copyDialog.Value; } - NFile::NName::NormalizeDirPathPrefix(path); - if (!NFile::NDirectory::CreateComplexDirectory(us2fs(path))) + NName::NormalizeDirPathPrefix(path); + if (!CreateComplexDir(us2fs(path))) { - srcPanel.MessageBoxMyError(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, 0x02000603, path)); + srcPanel.MessageBoxError2Lines(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, path), ::GetLastError()); return; } @@ -458,24 +451,24 @@ void CApp::Combine() if (outName.IsEmpty()) outName = L"file"; - NFile::NFind::CFileInfo fileInfo; + NFind::CFileInfo fileInfo; UString destFilePath = path + outName; combiner.OutputPath = us2fs(destFilePath); if (fileInfo.Find(combiner.OutputPath)) { - srcPanel.MessageBoxMyError(MyFormatNew(IDS_FILE_EXIST, 0x03020A04, destFilePath)); + srcPanel.MessageBoxMyError(MyFormatNew(IDS_FILE_EXIST, destFilePath)); return; } CProgressDialog &progressDialog = combiner.ProgressDialog; progressDialog.ShowCompressionInfo = false; - UString progressWindowTitle = LangString(IDS_APP_TITLE, 0x03000000); - UString title = LangString(IDS_COMBINING, 0x03020610); + UString progressWindowTitle = L"7-Zip"; // LangString(IDS_APP_TITLE, 0x03000000); + UString title = LangString(IDS_COMBINING); progressDialog.MainWindow = _window; progressDialog.MainTitle = progressWindowTitle; - progressDialog.MainAddTitle = title + UString(L" "); + progressDialog.MainAddTitle = title + L' '; combiner.InputDirPrefix = us2fs(srcPath); @@ -487,8 +480,8 @@ void CApp::Combine() } RefreshTitleAlways(); - // disableTimerProcessing1.Restore(); - // disableTimerProcessing2.Restore(); + // disableNotify.Restore(); + // disableNotify.Restore(); // srcPanel.SetFocusToList(); // srcPanel.RefreshListCtrlSaveFocused(); } diff --git a/CPP/7zip/UI/FileManager/PasswordDialog.cpp b/CPP/7zip/UI/FileManager/PasswordDialog.cpp old mode 100755 new mode 100644 index 92826a1f..6ead39c3 --- a/CPP/7zip/UI/FileManager/PasswordDialog.cpp +++ b/CPP/7zip/UI/FileManager/PasswordDialog.cpp @@ -9,42 +9,40 @@ #endif #ifdef LANG -static CIDLangPair kIDLangPairs[] = +static const UInt32 kLangIDs[] = { - { IDC_STATIC_PASSWORD_HEADER, 0x02000B01 }, - { IDC_CHECK_PASSWORD_SHOW, 0x02000B02 }, - { IDOK, 0x02000702 }, - { IDCANCEL, 0x02000710 } + IDT_PASSWORD_ENTER, + IDX_PASSWORD_SHOW }; #endif void CPasswordDialog::ReadControls() { - _passwordControl.GetText(Password); - ShowPassword = IsButtonCheckedBool(IDC_CHECK_PASSWORD_SHOW); + _passwordEdit.GetText(Password); + ShowPassword = IsButtonCheckedBool(IDX_PASSWORD_SHOW); } void CPasswordDialog::SetTextSpec() { - _passwordControl.SetPasswordChar(ShowPassword ? 0: TEXT('*')); - _passwordControl.SetText(Password); + _passwordEdit.SetPasswordChar(ShowPassword ? 0: TEXT('*')); + _passwordEdit.SetText(Password); } bool CPasswordDialog::OnInit() { #ifdef LANG - LangSetWindowText(HWND(*this), 0x02000B00); - LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + LangSetWindowText(*this, IDD_PASSWORD); + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); #endif - _passwordControl.Attach(GetItem(IDC_EDIT_PASSWORD)); - CheckButton(IDC_CHECK_PASSWORD_SHOW, ShowPassword); + _passwordEdit.Attach(GetItem(IDE_PASSWORD_PASSWORD)); + CheckButton(IDX_PASSWORD_SHOW, ShowPassword); SetTextSpec(); return CModalDialog::OnInit(); } bool CPasswordDialog::OnButtonClicked(int buttonID, HWND buttonHWND) { - if (buttonID == IDC_CHECK_PASSWORD_SHOW) + if (buttonID == IDX_PASSWORD_SHOW) { ReadControls(); SetTextSpec(); diff --git a/CPP/7zip/UI/FileManager/PasswordDialog.h b/CPP/7zip/UI/FileManager/PasswordDialog.h old mode 100755 new mode 100644 index 1d903249..339ebdaf --- a/CPP/7zip/UI/FileManager/PasswordDialog.h +++ b/CPP/7zip/UI/FileManager/PasswordDialog.h @@ -3,13 +3,15 @@ #ifndef __PASSWORD_DIALOG_H #define __PASSWORD_DIALOG_H -#include "Windows/Control/Dialog.h" -#include "Windows/Control/Edit.h" +#include "../../../Windows/Control/Dialog.h" +#include "../../../Windows/Control/Edit.h" + #include "PasswordDialogRes.h" class CPasswordDialog: public NWindows::NControl::CModalDialog { - NWindows::NControl::CEdit _passwordControl; + NWindows::NControl::CEdit _passwordEdit; + virtual void OnOK(); virtual bool OnInit(); virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); @@ -18,8 +20,9 @@ class CPasswordDialog: public NWindows::NControl::CModalDialog public: UString Password; bool ShowPassword; + CPasswordDialog(): ShowPassword(false) {} - INT_PTR Create(HWND parentWindow = 0) { return CModalDialog::Create(IDD_DIALOG_PASSWORD, parentWindow); } + INT_PTR Create(HWND parentWindow = 0) { return CModalDialog::Create(IDD_PASSWORD, parentWindow); } }; #endif diff --git a/CPP/7zip/UI/FileManager/PasswordDialog.rc b/CPP/7zip/UI/FileManager/PasswordDialog.rc old mode 100755 new mode 100644 index 2328ac56..90c57efa --- a/CPP/7zip/UI/FileManager/PasswordDialog.rc +++ b/CPP/7zip/UI/FileManager/PasswordDialog.rc @@ -4,11 +4,11 @@ #define xc 140 #define yc 72 -IDD_DIALOG_PASSWORD MY_DIALOG +IDD_PASSWORD DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT 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 + LTEXT "&Enter password:", IDT_PASSWORD_ENTER, m, m, xc, 8 + EDITTEXT IDE_PASSWORD_PASSWORD, m, 20, xc, 14, ES_PASSWORD | ES_AUTOHSCROLL + CONTROL "&Show password", IDX_PASSWORD_SHOW, MY_CHECKBOX, m, 42, xc, 10 OK_CANCEL END diff --git a/CPP/7zip/UI/FileManager/PasswordDialogRes.h b/CPP/7zip/UI/FileManager/PasswordDialogRes.h old mode 100755 new mode 100644 index e0b42661..1fe32e10 --- a/CPP/7zip/UI/FileManager/PasswordDialogRes.h +++ b/CPP/7zip/UI/FileManager/PasswordDialogRes.h @@ -1,4 +1,5 @@ -#define IDD_DIALOG_PASSWORD 501 -#define IDC_STATIC_PASSWORD_HEADER 1000 -#define IDC_EDIT_PASSWORD 1001 -#define IDC_CHECK_PASSWORD_SHOW 1002 +#define IDD_PASSWORD 3800 +#define IDT_PASSWORD_ENTER 3801 +#define IDX_PASSWORD_SHOW 3803 + +#define IDE_PASSWORD_PASSWORD 120 diff --git a/CPP/7zip/UI/FileManager/PluginInterface.h b/CPP/7zip/UI/FileManager/PluginInterface.h old mode 100755 new mode 100644 index 72711fde..3ce5fa8e --- a/CPP/7zip/UI/FileManager/PluginInterface.h +++ b/CPP/7zip/UI/FileManager/PluginInterface.h @@ -11,7 +11,7 @@ PLUGIN_INTERFACE(IInitContextMenu, 0x00) { - STDMETHOD(InitContextMenu)(const wchar_t *folder, const wchar_t **names, UINT32 numFiles) PURE; + STDMETHOD(InitContextMenu)(const wchar_t *folder, const wchar_t **names, UInt32 numFiles) PURE; }; PLUGIN_INTERFACE(IPluginOptionsCallback, 0x01) diff --git a/CPP/7zip/UI/FileManager/PluginLoader.h b/CPP/7zip/UI/FileManager/PluginLoader.h old mode 100755 new mode 100644 index cb7d4d7c..fed38d65 --- a/CPP/7zip/UI/FileManager/PluginLoader.h +++ b/CPP/7zip/UI/FileManager/PluginLoader.h @@ -3,19 +3,17 @@ #ifndef __PLUGIN_LOADER_H #define __PLUGIN_LOADER_H -#include "Windows/DLL.h" +#include "../../../Windows/DLL.h" #include "IFolder.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) + Func_CreateObject createObject = (Func_CreateObject)GetProc("CreateObject"); + if (!createObject) return GetLastError(); return createObject(&clsID, &IID_IFolderManager, (void **)manager); } diff --git a/CPP/7zip/UI/FileManager/PluginsPage.cpp b/CPP/7zip/UI/FileManager/PluginsPage.cpp old mode 100755 new mode 100644 index 0eeec9d6..39671b75 --- a/CPP/7zip/UI/FileManager/PluginsPage.cpp +++ b/CPP/7zip/UI/FileManager/PluginsPage.cpp @@ -13,19 +13,19 @@ #include "ProgramLocation.h" #include "PluginInterface.h" -static CIDLangPair kIDLangPairs[] = +static const UInt32 kLangIDs[] = { - { IDC_PLUGINS_STATIC_PLUGINS, 0x03010101}, - { IDC_PLUGINS_BUTTON_OPTIONS, 0x03010110} + IDT_PLUGINS_PLUGINS, + IDB_PLUGINS_OPTIONS }; static LPCWSTR kPluginsTopic = L"FM/options.htm#plugins"; bool CPluginsPage::OnInit() { - LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); - _listView.Attach(GetItem(IDC_PLUGINS_LIST)); + _listView.Attach(GetItem(IDL_PLUGINS)); UINT32 newFlags = /* LVS_EX_CHECKBOXES | */ LVS_EX_FULLROWSELECT; _listView.SetExtendedListViewStyle(newFlags, newFlags); @@ -83,7 +83,7 @@ bool CPluginsPage::OnButtonClicked(int buttonID, HWND buttonHWND) { switch(buttonID) { - case IDC_PLUGINS_BUTTON_OPTIONS: + case IDB_PLUGINS_OPTIONS: OnButtonOptions(); break; default: @@ -148,32 +148,32 @@ void CPluginsPage::OnButtonOptions() CPluginInfo pluginInfo = _plugins[index]; if (!pluginInfo.OptionsClassIDDefined) { - MessageBoxW(HWND(*this), L"There are no options", L"7-Zip", 0); + MessageBoxW(*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); + MessageBoxW(*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); + MessageBoxW(*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); + MessageBoxW(*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); + pluginOptions->PluginOptions(*this, callback); } bool CPluginsPage::OnNotify(UINT controlID, LPNMHDR lParam) diff --git a/CPP/7zip/UI/FileManager/PluginsPage.h b/CPP/7zip/UI/FileManager/PluginsPage.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/PluginsPage.rc b/CPP/7zip/UI/FileManager/PluginsPage.rc old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/PluginsPageRes.h b/CPP/7zip/UI/FileManager/PluginsPageRes.h old mode 100755 new mode 100644 index ca07ca5c..81196d3c --- a/CPP/7zip/UI/FileManager/PluginsPageRes.h +++ b/CPP/7zip/UI/FileManager/PluginsPageRes.h @@ -1,4 +1,4 @@ -#define IDD_PLUGINS 541 -#define IDC_PLUGINS_STATIC_PLUGINS 1000 -#define IDC_PLUGINS_LIST 1001 -#define IDC_PLUGINS_BUTTON_OPTIONS 1002 +#define IDD_PLUGINS 999 +#define IDT_PLUGINS_PLUGINS 999 +#define IDL_PLUGINS 999 +#define IDB_PLUGINS_OPTIONS 999 diff --git a/CPP/7zip/UI/FileManager/ProgramLocation.cpp b/CPP/7zip/UI/FileManager/ProgramLocation.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/ProgramLocation.h b/CPP/7zip/UI/FileManager/ProgramLocation.h old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.cpp b/CPP/7zip/UI/FileManager/ProgressDialog.cpp old mode 100755 new mode 100644 index cdb8399e..6c185769 --- a/CPP/7zip/UI/FileManager/ProgressDialog.cpp +++ b/CPP/7zip/UI/FileManager/ProgressDialog.cpp @@ -2,7 +2,7 @@ #include "StdAfx.h" -#include "Common/IntToString.h" +#include "../../../Common/IntToString.h" #include "resource.h" @@ -19,13 +19,6 @@ static const UINT kTimerElapse = 100; #include "LangUtils.h" #endif -#ifdef LANG -static CIDLangPair kIDLangPairs[] = -{ - { IDCANCEL, 0x02000711 } -}; -#endif - HRESULT CProgressSync::ProcessStopAndPause() { for (;;) @@ -54,15 +47,14 @@ void CProgressDialog::AddToTitle(LPCWSTR s) bool CProgressDialog::OnInit() { - _range = (UInt64)-1; + _range = (UInt64)(Int64)-1; _prevPercentValue = -1; _wasCreated = true; _dialogCreatedEvent.Set(); #ifdef LANG - // LangSetWindowText(HWND(*this), 0x02000C00); - LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + LangSetDlgItemsText(*this, NULL, 0); #endif m_ProgressBar.Attach(GetItem(IDC_PROGRESS1)); @@ -173,7 +165,7 @@ bool CProgressDialog::OnButtonClicked(int buttonID, HWND buttonHWND) 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); + int res = ::MessageBoxW(*this, L"Are you sure you want to cancel?", _title, MB_YESNOCANCEL); _inCancelMessageBox = false; Sync.SetPaused(paused); if (res == IDCANCEL || res == IDNO) diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.h b/CPP/7zip/UI/FileManager/ProgressDialog.h old mode 100755 new mode 100644 index 429ed740..175db017 --- a/CPP/7zip/UI/FileManager/ProgressDialog.h +++ b/CPP/7zip/UI/FileManager/ProgressDialog.h @@ -3,11 +3,11 @@ #ifndef __PROGRESS_DIALOG_H #define __PROGRESS_DIALOG_H -#include "Windows/Synchronization.h" -#include "Windows/Thread.h" +#include "../../../Windows/Synchronization.h" +#include "../../../Windows/Thread.h" -#include "Windows/Control/Dialog.h" -#include "Windows/Control/ProgressBar.h" +#include "../../../Windows/Control/Dialog.h" +#include "../../../Windows/Control/ProgressBar.h" #include "ProgressDialogRes.h" @@ -136,14 +136,14 @@ public: INT_PTR Create(const UString &title, NWindows::CThread &thread, HWND wndParent = 0) { _title = title; - INT_PTR res = CModalDialog::Create(IDD_DIALOG_PROGRESS, wndParent); + INT_PTR res = CModalDialog::Create(IDD_PROGRESS, wndParent); thread.Wait(); return res; } enum { - kCloseMessage = WM_USER + 1 + kCloseMessage = WM_APP + 1 }; virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam); diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.rc b/CPP/7zip/UI/FileManager/ProgressDialog.rc old mode 100755 new mode 100644 index 3a65338f..55d99233 --- a/CPP/7zip/UI/FileManager/ProgressDialog.rc +++ b/CPP/7zip/UI/FileManager/ProgressDialog.rc @@ -4,7 +4,7 @@ #define xc 172 #define yc 44 -IDD_DIALOG_PROGRESS MY_DIALOG +IDD_PROGRESS DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT CAPTION "Progress" BEGIN PUSHBUTTON "Cancel", IDCANCEL, bx, by, bxs, bys diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp old mode 100755 new mode 100644 index a4ff7f58..bccb6e88 --- a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp +++ b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp @@ -2,11 +2,11 @@ #include "StdAfx.h" -#include "Common/IntToString.h" -#include "Common/StringConvert.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" -#include "Windows/Control/Static.h" -#include "Windows/Error.h" +#include "../../../Windows/Control/Static.h" +#include "../../../Windows/ErrorMsg.h" #include "ProgressDialog2.h" #include "DialogSize.h" @@ -21,7 +21,8 @@ extern HINSTANCE g_hInstance; static const UINT_PTR kTimerID = 3; -static const UINT kCloseMessage = WM_USER + 1; +static const UINT kCloseMessage = WM_APP + 1; +// we can't use WM_USER, since WM_USER can be used by standard Windows procedure for Dialog static const UINT kTimerElapse = #ifdef UNDER_CE @@ -31,51 +32,194 @@ static const UINT kTimerElapse = #endif ; +static const UINT kCreateDelay = + #ifdef UNDER_CE + 2500 + #else + 500 + #endif + ; + +static const DWORD kPauseSleepTime = 100; + #include "LangUtils.h" #ifdef LANG -static CIDLangPair kIDLangPairs[] = + +static const UInt32 kLangIDs[] = +{ + IDT_PROGRESS_ELAPSED, + IDT_PROGRESS_REMAINING, + IDT_PROGRESS_TOTAL, + IDT_PROGRESS_SPEED, + IDT_PROGRESS_PROCESSED, + IDT_PROGRESS_RATIO, + IDT_PROGRESS_ERRORS, + IDB_PROGRESS_BACKGROUND, + IDB_PAUSE +}; + +static const UInt32 kLangIDs_Colon[] = { - { 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 }, + IDT_PROGRESS_PACKED, + IDT_PROGRESS_FILES }; + #endif -HRESULT CProgressSync::ProcessStopAndPause() + +#define UNDEFINED_VAL ((UInt64)(Int64)-1) +#define INIT_AS_UNDEFINED(v) v = UNDEFINED_VAL; +#define IS_UNDEFINED_VAL(v) ((v) == UNDEFINED_VAL) +#define IS_DEFINED_VAL(v) ((v) != UNDEFINED_VAL) + +CProgressSync::CProgressSync(): + _stopped(false), _paused(false), + _bytesProgressMode(true), + _totalBytes(UNDEFINED_VAL), _completedBytes(0), + _totalFiles(UNDEFINED_VAL), _curFiles(0), + _inSize(UNDEFINED_VAL), + _outSize(UNDEFINED_VAL), + _isDir(false) + {} + +#define CHECK_STOP if (_stopped) return E_ABORT; if (!_paused) return S_OK; +#define CRITICAL_LOCK NSynchronization::CCriticalSectionLock lock(_cs); + +bool CProgressSync::Get_Paused() +{ + CRITICAL_LOCK + return _paused; +} + +HRESULT CProgressSync::CheckStop() { for (;;) { - if (GetStopped()) - return E_ABORT; - if (!GetPaused()) - break; - ::Sleep(100); + { + CRITICAL_LOCK + CHECK_STOP + } + ::Sleep(kPauseSleepTime); } - return S_OK; } -HRESULT CProgressSync::SetPosAndCheckPaused(UInt64 completed) +HRESULT CProgressSync::ScanProgress(UInt64 numFiles, UInt64 totalSize, const UString &fileName, bool isDir) { - RINOK(ProcessStopAndPause()); - SetPos(completed); - return S_OK; + { + CRITICAL_LOCK + _totalFiles = numFiles; + _totalBytes = totalSize; + _filePath = fileName; + _isDir = isDir; + // _completedBytes = 0; + CHECK_STOP + } + return CheckStop(); +} + +void CProgressSync::Set_NumFilesTotal(UInt64 val) +{ + CRITICAL_LOCK + _totalFiles = val; +} + +void CProgressSync::Set_NumBytesTotal(UInt64 val) +{ + CRITICAL_LOCK + _totalBytes = val; +} + +void CProgressSync::Set_NumFilesCur(UInt64 val) +{ + CRITICAL_LOCK + _curFiles = val; +} + +HRESULT CProgressSync::Set_NumBytesCur(const UInt64 *val) +{ + { + CRITICAL_LOCK + if (val) + _completedBytes = *val; + CHECK_STOP + } + return CheckStop(); +} + +HRESULT CProgressSync::Set_NumBytesCur(UInt64 val) +{ + { + CRITICAL_LOCK + _completedBytes = val; + CHECK_STOP + } + return CheckStop(); +} + +void CProgressSync::Set_Ratio(const UInt64 *inSize, const UInt64 *outSize) +{ + CRITICAL_LOCK + if (inSize) + _inSize = *inSize; + if (outSize) + _outSize = *outSize; +} + +void CProgressSync::Set_TitleFileName(const UString &fileName) +{ + CRITICAL_LOCK + _titleFileName = fileName; +} +void CProgressSync::Set_Status(const UString &s) +{ + CRITICAL_LOCK + _status = s; +} + +void CProgressSync::Set_FilePath(const UString &path, bool isDir) +{ + CRITICAL_LOCK + _filePath = path; + _isDir = isDir; } +void CProgressSync::AddError_Message(const wchar_t *message) +{ + CRITICAL_LOCK + Messages.Add(message); +} + +void CProgressSync::AddError_Message_Name(const wchar_t *message, const wchar_t *name) +{ + UString s; + if (name && *name != 0) + s += name; + if (message && *message != 0 ) + { + if (!s.IsEmpty()) + s += L'\n'; + s += message; + if (!s.IsEmpty() && s.Back() == L'\n') + s.DeleteBack(); + } + AddError_Message(s); +} + +void CProgressSync::AddError_Code_Name(DWORD systemError, const wchar_t *name) +{ + UString s = NError::MyFormatMessage(systemError); + if (systemError == 0) + s = L"Error"; + AddError_Message_Name(s, name); +} + CProgressDialog::CProgressDialog(): _timer(0), CompressingMode(true), MainWindow(0) { + _isDir = false; + + _numMessages = 0; IconID = -1; MessagesDisplayed = false; _wasCreated = false; @@ -100,6 +244,7 @@ CProgressDialog::CProgressDialog(): _timer(0), CompressingMode(true), MainWindow } #ifndef _SFX + CProgressDialog::~CProgressDialog() { SetTaskbarProgressState(TBPF_NOPROGRESS); @@ -110,7 +255,7 @@ void CProgressDialog::AddToTitle(LPCWSTR s) if (MainWindow != 0) { CWindow window(MainWindow); - window.SetText(s + UString(MainTitle)); + window.SetText((UString)s + MainTitle); } } @@ -122,7 +267,7 @@ void CProgressDialog::SetTaskbarProgressState() if (_taskbarList && _hwndForTaskbar) { TBPFLAG tbpFlags; - if (Sync.GetPaused()) + if (Sync.Get_Paused()) tbpFlags = TBPF_PAUSED; else tbpFlags = _errorsWereDisplayed ? TBPF_ERROR: TBPF_NORMAL; @@ -130,21 +275,22 @@ void CProgressDialog::SetTaskbarProgressState() } } -static const int kTitleFileNameSizeLimit = 36; -static const int kCurrentFileNameSizeLimit = 82; +static const unsigned kTitleFileNameSizeLimit = 36; +static const unsigned kCurrentFileNameSizeLimit = 82; -static void ReduceString(UString &s, int size) +static void ReduceString(UString &s, unsigned size) { - if (s.Length() > size) - s = s.Left(size / 2) + UString(L" ... ") + s.Right(size / 2); + if (s.Len() <= size) + return; + s.Delete(size / 2, s.Len() - size); + s.Insert(size / 2, L" ... "); } 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); + ShowItem_Bool(IDT_PROGRESS_ERRORS, enable); + ShowItem_Bool(IDT_PROGRESS_ERRORS_VAL, enable); + ShowItem_Bool(IDL_PROGRESS_MESSAGES, enable); } bool CProgressDialog::OnInit() @@ -153,67 +299,75 @@ bool CProgressDialog::OnInit() if (!_hwndForTaskbar) _hwndForTaskbar = GetParent(); if (!_hwndForTaskbar) - _hwndForTaskbar = (HWND)*this; - - _range = (UInt64)(Int64)-1; - _prevPercentValue = (UInt32)-1; - _prevElapsedSec = (UInt32)-1; - _prevRemainingSec = (UInt32)-1; - _prevSpeed = (UInt32)-1; - _prevMode = kSpeedBytes; + _hwndForTaskbar = *this; + + INIT_AS_UNDEFINED(_progressBar_Range); + INIT_AS_UNDEFINED(_progressBar_Pos); + + INIT_AS_UNDEFINED(_prevPercentValue); + INIT_AS_UNDEFINED(_prevElapsedSec); + INIT_AS_UNDEFINED(_prevRemainingSec); + + INIT_AS_UNDEFINED(_prevSpeed); + _prevSpeed_MoveBits = 0; + _prevTime = ::GetTickCount(); _elapsedTime = 0; + + INIT_AS_UNDEFINED(_totalBytes_Prev); + INIT_AS_UNDEFINED(_processed_Prev); + INIT_AS_UNDEFINED(_packed_Prev); + INIT_AS_UNDEFINED(_ratio_Prev); + _filesStr_Prev.Empty(); + _foreground = true; m_ProgressBar.Attach(GetItem(IDC_PROGRESS1)); - _messageList.Attach(GetItem(IDC_PROGRESS_LIST)); + _messageList.Attach(GetItem(IDL_PROGRESS_MESSAGES)); _messageList.SetUnicodeFormat(); _wasCreated = true; _dialogCreatedEvent.Set(); #ifdef LANG - LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); + LangSetDlgItems_Colon(*this, kLangIDs_Colon, ARRAY_SIZE(kLangIDs_Colon)); #endif - CWindow window(GetItem(IDC_BUTTON_PROGRESS_PRIORITY)); - window.GetText(backgroundString); - backgroundedString = backgroundString; - backgroundedString.Replace(L"&", L""); + CWindow window(GetItem(IDB_PROGRESS_BACKGROUND)); + window.GetText(_background_String); + _backgrounded_String = _background_String; + _backgrounded_String.RemoveChar(L'&'); - window = GetItem(IDC_BUTTON_PAUSE); - window.GetText(pauseString); + window = GetItem(IDB_PAUSE); + window.GetText(_pause_String); - foregroundString = LangStringSpec(IDS_PROGRESS_FOREGROUND, 0x02000C11); - continueString = LangStringSpec(IDS_PROGRESS_CONTINUE, 0x02000C13); - pausedString = LangStringSpec(IDS_PROGRESS_PAUSED, 0x02000C20); + LangString(IDS_PROGRESS_FOREGROUND, _foreground_String); + LangString(IDS_CONTINUE, _continue_String); + LangString(IDS_PROGRESS_PAUSED, _paused_String); SetText(_title); SetPauseText(); SetPriorityText(); _messageList.InsertColumn(0, L"", 30); - - const UString s = LangStringSpec(IDS_MESSAGES_DIALOG_MESSAGE_COLUMN, 0x02000A80); - - _messageList.InsertColumn(1, s, 600); + _messageList.InsertColumn(1, L"", 600); _messageList.SetColumnWidthAuto(0); _messageList.SetColumnWidthAuto(1); - EnableErrorsControls(false); - GetItemSizes(IDCANCEL, buttonSizeX, buttonSizeY); + 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); + HideItem(IDT_PROGRESS_PACKED); + HideItem(IDT_PROGRESS_PACKED_VAL); + HideItem(IDT_PROGRESS_RATIO); + HideItem(IDT_PROGRESS_RATIO_VAL); } if (IconID >= 0) @@ -234,22 +388,35 @@ bool CProgressDialog::OnInit() return CModalDialog::OnInit(); } +static const UINT kIDs[] = +{ + IDT_PROGRESS_ELAPSED, IDT_PROGRESS_ELAPSED_VAL, + IDT_PROGRESS_REMAINING, IDT_PROGRESS_REMAINING_VAL, + IDT_PROGRESS_FILES, IDT_PROGRESS_FILES_VAL, + IDT_PROGRESS_RATIO, IDT_PROGRESS_RATIO_VAL, + IDT_PROGRESS_ERRORS, IDT_PROGRESS_ERRORS_VAL, + + IDT_PROGRESS_TOTAL, IDT_PROGRESS_TOTAL_VAL, + IDT_PROGRESS_SPEED, IDT_PROGRESS_SPEED_VAL, + IDT_PROGRESS_PROCESSED, IDT_PROGRESS_PROCESSED_VAL, + IDT_PROGRESS_PACKED, IDT_PROGRESS_PACKED_VAL +}; + bool CProgressDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) { int sY; int sStep; int mx, my; { - RECT 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; + RECT r; + GetClientRectOfItem(IDT_PROGRESS_ELAPSED, r); + mx = r.left; + my = r.top; + sY = RECT_SIZE_Y(r); + GetClientRectOfItem(IDT_PROGRESS_REMAINING, r); + sStep = r.top - my; } - InvalidateRect(NULL); int xSizeClient = xSize - mx * 2; @@ -262,12 +429,13 @@ bool CProgressDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) _numReduceSymbols = i / 4; } - int yPos = ySize - my - buttonSizeY; + int yPos = ySize - my - _buttonSizeY; - ChangeSubWindowSizeX(GetItem(IDC_PROGRESS_FILE_NAME), xSize - mx * 2); + ChangeSubWindowSizeX(GetItem(IDT_PROGRESS_STATUS), xSize - mx * 2); + ChangeSubWindowSizeX(GetItem(IDT_PROGRESS_FILE_NAME), xSize - mx * 2); ChangeSubWindowSizeX(GetItem(IDC_PROGRESS1), xSize - mx * 2); - int bSizeX = buttonSizeX; + int bSizeX = _buttonSizeX; int mx2 = mx; for (;; mx2--) { @@ -284,11 +452,11 @@ bool CProgressDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) bSizeX = 2; { - RECT rect; - GetClientRectOfItem(IDC_PROGRESS_LIST, rect); - int y = rect.top; + RECT r; + GetClientRectOfItem(IDL_PROGRESS_MESSAGES, r); + int y = r.top; int ySize2 = yPos - my - y; - const int kMinYSize = buttonSizeY + buttonSizeY * 3 / 4; + const int kMinYSize = _buttonSizeY + _buttonSizeY * 3 / 4; int xx = xSize - mx * 2; if (ySize2 < kMinYSize) { @@ -303,11 +471,11 @@ bool CProgressDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) { int xPos = xSize - mx; xPos -= bSizeX; - MoveItem(IDCANCEL, xPos, yPos, bSizeX, buttonSizeY); + MoveItem(IDCANCEL, xPos, yPos, bSizeX, _buttonSizeY); xPos -= (mx2 + bSizeX); - MoveItem(IDC_BUTTON_PAUSE, xPos, yPos, bSizeX, buttonSizeY); + MoveItem(IDB_PAUSE, xPos, yPos, bSizeX, _buttonSizeY); xPos -= (mx2 + bSizeX); - MoveItem(IDC_BUTTON_PROGRESS_PRIORITY, xPos, yPos, bSizeX, buttonSizeY); + MoveItem(IDB_PROGRESS_BACKGROUND, xPos, yPos, bSizeX, _buttonSizeY); } int valueSize; @@ -315,7 +483,7 @@ bool CProgressDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) int padSize; labelSize = Units_To_Pixels_X(MY_PROGRESS_LABEL_UNITS_MIN); - valueSize = Units_To_Pixels_X(MY_PROGRESS_VALUE_UNITS); + valueSize = Units_To_Pixels_X(MY_PROGRESS_VAL_UNITS); padSize = Units_To_Pixels_X(MY_PROGRESS_PAD_UNITS); int requiredSize = (labelSize + valueSize) * 2 + padSize; @@ -337,22 +505,8 @@ bool CProgressDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) 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) + for (int i = 0; i < ARRAY_SIZE(kIDs); i += 2) { int x = mx; const int kNumColumn1Items = 5 * 2; @@ -362,281 +516,371 @@ bool CProgressDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) yPos = my; x = mx + gSize + padSize; } - MoveItem(IDs[i], x, yPos, labelSize, sY); - MoveItem(IDs[i + 1], x + labelSize, yPos, valueSize, sY); + MoveItem(kIDs[i], x, yPos, labelSize, sY); + MoveItem(kIDs[i + 1], x + labelSize, yPos, valueSize, sY); yPos += sStep; } return false; } -void CProgressDialog::OnCancel() { Sync.SetStopped(true); } +void CProgressDialog::OnCancel() { Sync.Set_Stopped(true); } void CProgressDialog::OnOK() { } -static void ConvertSizeToString(UInt64 value, wchar_t *s) +void CProgressDialog::SetProgressRange(UInt64 range) { - 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; - } + if (range == _progressBar_Range) + return; + _progressBar_Range = range; + INIT_AS_UNDEFINED(_progressBar_Pos); + _progressConv.Init(range); + m_ProgressBar.SetRange32(0, _progressConv.Count(range)); } -void CProgressDialog::SetRange(UInt64 range) +void CProgressDialog::SetProgressPos(UInt64 pos) { - _range = range; - _previousPos = (UInt64)(Int64)-1; - _converter.Init(range); - m_ProgressBar.SetRange32(0, _converter.Count(range)); + if (pos >= _progressBar_Range || + pos <= _progressBar_Pos || + pos - _progressBar_Pos >= (_progressBar_Range >> 10)) + { + m_ProgressBar.SetPos(_progressConv.Count(pos)); + if (_taskbarList && _hwndForTaskbar) + _taskbarList->SetProgressValue(_hwndForTaskbar, pos, _progressBar_Range); + _progressBar_Pos = pos; + } } -void CProgressDialog::SetPos(UInt64 pos) +#define UINT_TO_STR_2(val) { s[0] = (wchar_t)('0' + (val) / 10); s[1] = (wchar_t)('0' + (val) % 10); s += 2; } + +void GetTimeString(UInt64 timeValue, wchar_t *s) { - bool redraw = true; - if (pos < _range && pos > _previousPos) + UInt64 hours = timeValue / 3600; + UInt32 seconds = (UInt32)(timeValue - hours * 3600); + UInt32 minutes = seconds / 60; + seconds %= 60; + if (hours > 99) { - if (pos - _previousPos < (_range >> 10)) - redraw = false; + ConvertUInt64ToString(hours, s); + for (; *s != 0; s++); } - if (redraw) + else { - m_ProgressBar.SetPos(_converter.Count(pos)); // Test it for 100% - if (_taskbarList && _hwndForTaskbar) - _taskbarList->SetProgressValue(_hwndForTaskbar, pos, _range); - _previousPos = pos; + UInt32 hours32 = (UInt32)hours; + UINT_TO_STR_2(hours32); } + *s++ = ':'; UINT_TO_STR_2(minutes); + *s++ = ':'; UINT_TO_STR_2(seconds); + *s = 0; } -static void GetTimeString(UInt64 timeValue, TCHAR *s) +static void ConvertSizeToString(UInt64 v, wchar_t *s) { - wsprintf(s, TEXT("%02d:%02d:%02d"), - UInt32(timeValue / 3600), - UInt32((timeValue / 60) % 60), - UInt32(timeValue % 60)); + Byte c = 0; + if (v >= ((UInt64)100000 << 20)) { v >>= 30; c = 'G'; } + else if (v >= ((UInt64)100000 << 10)) { v >>= 20; c = 'M'; } + else if (v >= ((UInt64)100000 << 0)) { v >>= 10; c = 'K'; } + ConvertUInt64ToString(v, s); + if (c != 0) + { + s += MyStringLen(s); + *s++ = ' '; + *s++ = c; + *s++ = 0; + } } -void CProgressDialog::ShowSize(int id, UInt64 value) +void CProgressDialog::ShowSize(int id, UInt64 val, UInt64 &prev) { + if (val == prev) + return; + prev = val; wchar_t s[40]; s[0] = 0; - if (value != (UInt64)(Int64)-1) - ConvertSizeToString(value, s); + if (IS_DEFINED_VAL(val)) + ConvertSizeToString(val, s); SetItemText(id, s); } +static void GetChangedString(const UString &newStr, UString &prevStr, bool &hasChanged) +{ + hasChanged = !(prevStr == newStr); + if (hasChanged) + prevStr = newStr; +} + +static unsigned GetPower32(UInt32 val) +{ + const unsigned kStart = 32; + UInt32 mask = ((UInt32)1 << (kStart - 1)); + for (unsigned i = kStart;; i--) + { + if (i == 0 || (val & mask) != 0) + return i; + mask >>= 1; + } +} + +static unsigned GetPower64(UInt64 val) +{ + UInt32 high = (UInt32)(val >> 32); + if (high == 0) + return GetPower32((UInt32)val); + return GetPower32(high) + 32; + +} + +static UInt64 MyMultAndDiv(UInt64 mult1, UInt64 mult2, UInt64 divider) +{ + unsigned pow1 = GetPower64(mult1); + unsigned pow2 = GetPower64(mult2); + while (pow1 + pow2 > 64) + { + if (pow1 > pow2) { pow1--; mult1 >>= 1; } + else { pow2--; mult2 >>= 1; } + divider >>= 1; + } + UInt64 res = mult1 * mult2; + if (divider != 0) + res /= divider; + return res; +} + void CProgressDialog::UpdateStatInfo(bool showAll) { UInt64 total, completed, totalFiles, completedFiles, inSize, outSize; bool bytesProgressMode; - Sync.GetProgress(total, completed, totalFiles, completedFiles, inSize, outSize, bytesProgressMode); - UInt32 curTime = ::GetTickCount(); + bool titleFileName_Changed; + bool curFilePath_Changed; + bool status_Changed; + unsigned numErrors; + { + NSynchronization::CCriticalSectionLock lock(Sync._cs); + total = Sync._totalBytes; + completed = Sync._completedBytes; + totalFiles = Sync._totalFiles; + completedFiles = Sync._curFiles; + inSize = Sync._inSize; + outSize = Sync._outSize; + bytesProgressMode = Sync._bytesProgressMode; + + GetChangedString(Sync._titleFileName, _titleFileName, titleFileName_Changed); + GetChangedString(Sync._filePath, _filePath, curFilePath_Changed); + GetChangedString(Sync._status, _status, status_Changed); + if (_isDir != Sync._isDir) + { + curFilePath_Changed = true; + _isDir = Sync._isDir; + } + numErrors = Sync.Messages.Size(); + } - UInt64 progressTotal = bytesProgressMode ? total : totalFiles; - UInt64 progressCompleted = bytesProgressMode ? completed : completedFiles; + UInt32 curTime = ::GetTickCount(); - if (progressTotal != _range) - SetRange(progressTotal); - if (progressTotal == (UInt64)(Int64)-1) { - SetPos(0); - SetRange(progressCompleted); + UInt64 progressTotal = bytesProgressMode ? total : totalFiles; + UInt64 progressCompleted = bytesProgressMode ? completed : completedFiles; + + if (IS_UNDEFINED_VAL(progressTotal)) + { + // SetPos(0); + // SetRange(progressCompleted); + } + else + { + if (_progressBar_Pos != 0 || progressCompleted != 0 || + (_progressBar_Range == 0 && progressTotal != 0)) + { + SetProgressRange(progressTotal); + SetProgressPos(progressCompleted); + } + } } - else - SetPos(progressCompleted); - wchar_t s[32] = { 0 }; - if (total != (UInt64)(Int64)-1) - ConvertSizeToString(total, s); - SetItemText(IDC_PROGRESS_TOTAL_VALUE, s); + ShowSize(IDT_PROGRESS_TOTAL_VAL, total, _totalBytes_Prev); _elapsedTime += (curTime - _prevTime); _prevTime = curTime; - - UInt32 elapsedSec = _elapsedTime / 1000; - + UInt64 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; + wchar_t s[40]; + GetTimeString(elapsedSec, s); + SetItemText(IDT_PROGRESS_ELAPSED_VAL, s); } + bool needSetTitle = false; if (elapsedChanged || showAll) { + if (numErrors > _numPostedMessages) { - UInt64 numErrors; - - { - NWindows::NSynchronization::CCriticalSectionLock lock(Sync._cs); - numErrors = Sync.Messages.Size(); - } - if (numErrors > 0) + UpdateMessagesDialog(); + wchar_t s[32]; + ConvertUInt64ToString(numErrors, s); + SetItemText(IDT_PROGRESS_ERRORS_VAL, s); + if (!_errorsWereDisplayed) { - UpdateMessagesDialog(); - TCHAR s[40]; - ConvertUInt64ToString(numErrors, s); - SetItemText(IDC_PROGRESS_ERRORS_VALUE, s); - if (!_errorsWereDisplayed) - { - _errorsWereDisplayed = true; - EnableErrorsControls(true); - SetTaskbarProgressState(); - } + _errorsWereDisplayed = true; + EnableErrorsControls(true); + SetTaskbarProgressState(); } } 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 (IS_UNDEFINED_VAL(total)) { - if (_prevMode != kSpeedMBytes || speedMB != _prevSpeed) + if (IS_DEFINED_VAL(_prevRemainingSec)) { - ConvertUInt64ToString(speedMB, s); - lstrcat(s, TEXT(" MB/s")); - _prevMode = kSpeedMBytes; - _prevSpeed = speedMB; - needRedraw = true; + INIT_AS_UNDEFINED(_prevRemainingSec); + SetItemText(IDT_PROGRESS_REMAINING_VAL, L""); } } - else if (speedKB >= kLimit1) + else { - if (_prevMode != kSpeedKBytes || speedKB != _prevSpeed) + UInt64 remainingTime = 0; + if (completed < total) + remainingTime = MyMultAndDiv(_elapsedTime, total - completed, completed); + UInt64 remainingSec = remainingTime / 1000; + if (remainingSec != _prevRemainingSec) { - ConvertUInt64ToString(speedKB, s); - lstrcat(s, TEXT(" KB/s")); - _prevMode = kSpeedKBytes; - _prevSpeed = speedKB; - needRedraw = true; + _prevRemainingSec = remainingSec; + wchar_t s[40]; + GetTimeString(remainingSec, s); + SetItemText(IDT_PROGRESS_REMAINING_VAL, s); } } - else { - if (_prevMode != kSpeedBytes || speedB != _prevSpeed) + UInt64 elapsedTime = (_elapsedTime == 0) ? 1 : _elapsedTime; + UInt64 v = (completed * 1000) / elapsedTime; + Byte c = 0; + unsigned moveBits = 0; + if (v >= ((UInt64)10000 << 10)) { moveBits = 20; c = 'M'; } + else if (v >= ((UInt64)10000 << 0)) { moveBits = 10; c = 'K'; } + v >>= moveBits; + if (moveBits != _prevSpeed_MoveBits || v != _prevSpeed) { - ConvertUInt64ToString(speedB, s); - lstrcat(s, TEXT(" B/s")); - _prevMode = kSpeedBytes; - _prevSpeed = speedB; - needRedraw = true; + _prevSpeed_MoveBits = moveBits; + _prevSpeed = v; + wchar_t s[40]; + ConvertUInt64ToString(v, s); + unsigned pos = MyStringLen(s); + s[pos++] = ' '; + if (moveBits != 0) + s[pos++] = c; + s[pos++] = 'B'; + s[pos++] = '/'; + s[pos++] = 's'; + s[pos++] = 0; + SetItemText(IDT_PROGRESS_SPEED_VAL, s); } } - 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; + UInt64 percent = 0; + { + if (IS_DEFINED_VAL(total)) + { + percent = completed * 100; + if (total != 0) + percent /= total; + } + } + if (percent != _prevPercentValue) + { + _prevPercentValue = percent; + needSetTitle = true; + } } - TCHAR s[64]; - ConvertUInt64ToString(completedFiles, s); - if (totalFiles != (UInt64)(Int64)-1) { - lstrcat(s, TEXT(" / ")); - ConvertUInt64ToString(totalFiles, s + lstrlen(s)); + wchar_t s[64]; + ConvertUInt64ToString(completedFiles, s); + if (IS_DEFINED_VAL(totalFiles)) + { + wcscat(s, L" / "); + ConvertUInt64ToString(totalFiles, s + wcslen(s)); + } + if (_filesStr_Prev != s) + { + _filesStr_Prev = s; + SetItemText(IDT_PROGRESS_FILES_VAL, 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) + if (IS_UNDEFINED_VAL(unpackSize) && + IS_UNDEFINED_VAL(packSize)) { - ShowSize(IDC_PROGRESS_UNPACKED_VALUE, completed); - SetItemText(IDC_PROGRESS_PACKED_VALUE, L""); + ShowSize(IDT_PROGRESS_PROCESSED_VAL, completed, _processed_Prev); + ShowSize(IDT_PROGRESS_PACKED_VAL, UNDEFINED_VAL, _packed_Prev); } else { - ShowSize(IDC_PROGRESS_UNPACKED_VALUE, unpackSize); - ShowSize(IDC_PROGRESS_PACKED_VALUE, packSize); + ShowSize(IDT_PROGRESS_PROCESSED_VAL, unpackSize, _processed_Prev); + ShowSize(IDT_PROGRESS_PACKED_VAL, packSize, _packed_Prev); - if (packSize != (UInt64)(Int64)-1 && unpackSize != (UInt64)(Int64)-1 && unpackSize != 0) + if (IS_DEFINED_VAL(packSize) && + IS_DEFINED_VAL(unpackSize) && + unpackSize != 0) { + wchar_t s[32]; UInt64 ratio = packSize * 100 / unpackSize; - ConvertUInt64ToString(ratio, s); - lstrcat(s, TEXT("%")); - SetItemText(IDC_PROGRESS_RATIO_VALUE, s); + if (_ratio_Prev != ratio) + { + _ratio_Prev = ratio; + ConvertUInt64ToString(ratio, s); + wcscat(s, L"%"); + SetItemText(IDT_PROGRESS_RATIO_VAL, s); + } } } } + if (needSetTitle || titleFileName_Changed) + SetTitleText(); - UString fileName; - Sync.GetCurrentFileName(fileName); - if (_prevFileName != fileName) + if (status_Changed) + { + UString s = _status; + ReduceString(s, _numReduceSymbols); + SetItemText(IDT_PROGRESS_STATUS, _status); + } + + if (curFilePath_Changed) { - int slashPos = fileName.ReverseFind(WCHAR_PATH_SEPARATOR); UString s1, s2; - if (slashPos >= 0) + if (_isDir) + s1 = _filePath; + else { - s1 = fileName.Left(slashPos + 1); - s2 = fileName.Mid(slashPos + 1); + int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR); + if (slashPos >= 0) + { + s1.SetFrom(_filePath, slashPos + 1); + s2 = _filePath.Ptr(slashPos + 1); + } + else + s2 = _filePath; } - else - s2 = fileName; ReduceString(s1, _numReduceSymbols); ReduceString(s2, _numReduceSymbols); - UString s = s1 + L"\n" + s2; - SetItemText(IDC_PROGRESS_FILE_NAME, s); - _prevFileName == fileName; + s1 += L'\n'; + s1 += s2; + SetItemText(IDT_PROGRESS_FILE_NAME, s1); } } bool CProgressDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */) { - if (Sync.GetPaused()) + if (Sync.Get_Paused()) return true; - CheckNeedClose(); - UpdateStatInfo(false); return true; } @@ -668,19 +912,13 @@ INT_PTR CProgressDialog::Create(const UString &title, NWindows::CThread &thread, CWaitCursor waitCursor; HANDLE h[] = { thread, _createDialogEvent }; - WRes res = WaitForMultipleObjects(sizeof(h) / sizeof(h[0]), h, FALSE, - #ifdef UNDER_CE - 2500 - #else - 1000 - #endif - ); + WRes res = WaitForMultipleObjects(ARRAY_SIZE(h), h, FALSE, kCreateDelay); 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); + res = CModalDialog::Create(SIZED_DIALOG(IDD_PROGRESS), wndParent); } catch(...) { @@ -690,7 +928,7 @@ INT_PTR CProgressDialog::Create(const UString &title, NWindows::CThread &thread, } thread.Wait(); if (!MessagesDisplayed) - MessageBoxW(wndParent, L"Progress Error", L"7-Zip", MB_ICONERROR | MB_OK); + MessageBoxW(wndParent, L"Progress Error", L"7-Zip", MB_ICONERROR); return res; } @@ -703,38 +941,33 @@ bool CProgressDialog::OnExternalCloseMessage() UpdateStatInfo(true); - HideItem(IDC_BUTTON_PROGRESS_PRIORITY); - HideItem(IDC_BUTTON_PAUSE); - SetItemText(IDCANCEL, LangStringSpec(IDS_CLOSE, 0x02000713)); + SetItemText(IDCANCEL, LangString(IDS_CLOSE)); + ::SendMessage(GetItem(IDCANCEL), BM_SETSTYLE, BS_DEFPUSHBUTTON, MAKELPARAM(TRUE, 0)); + HideItem(IDB_PROGRESS_BACKGROUND); + HideItem(IDB_PAUSE); bool thereAreMessages; - UString okMessage; - UString okMessageTitle; - UString errorMessage; - UString errorMessageTitle; + CProgressFinalMessage fm; { - NWindows::NSynchronization::CCriticalSectionLock lock(Sync._cs); - errorMessage = Sync.ErrorMessage; - errorMessageTitle = Sync.ErrorMessageTitle; - okMessage = Sync.OkMessage; - okMessageTitle = Sync.OkMessageTitle; + NSynchronization::CCriticalSectionLock lock(Sync._cs); thereAreMessages = !Sync.Messages.IsEmpty(); + fm = Sync.FinalMessage; } - if (!errorMessage.IsEmpty()) + if (!fm.ErrorMessage.Message.IsEmpty()) { MessagesDisplayed = true; - if (errorMessageTitle.IsEmpty()) - errorMessageTitle = L"7-Zip"; - MessageBoxW(*this, errorMessage, errorMessageTitle, MB_ICONERROR | MB_OK); + if (fm.ErrorMessage.Title.IsEmpty()) + fm.ErrorMessage.Title = L"7-Zip"; + MessageBoxW(*this, fm.ErrorMessage.Message, fm.ErrorMessage.Title, MB_ICONERROR); } else if (!thereAreMessages) { MessagesDisplayed = true; - if (!okMessage.IsEmpty()) + if (!fm.OkMessage.Message.IsEmpty()) { - if (okMessageTitle.IsEmpty()) - okMessageTitle = L"7-Zip"; - MessageBoxW(*this, okMessage, okMessageTitle, MB_OK); + if (fm.OkMessage.Title.IsEmpty()) + fm.OkMessage.Title = L"7-Zip"; + MessageBoxW(*this, fm.OkMessage.Message, fm.OkMessage.Title, MB_OK); } } @@ -751,7 +984,7 @@ bool CProgressDialog::OnExternalCloseMessage() bool CProgressDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) { - switch(message) + switch (message) { case kCloseMessage: { @@ -778,51 +1011,56 @@ bool CProgressDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) void CProgressDialog::SetTitleText() { - UString title; - if (Sync.GetPaused()) + UString s; + if (Sync.Get_Paused()) { - title = pausedString; - title += L' '; + s += _paused_String; + s += L' '; } - if (_prevPercentValue != (UInt32)-1) + if (IS_DEFINED_VAL(_prevPercentValue)) { - wchar_t s[64]; - ConvertUInt64ToString(_prevPercentValue, s); - title += s; - title += L'%'; + wchar_t temp[32]; + ConvertUInt64ToString(_prevPercentValue, temp); + s += temp; + s += L'%'; } if (!_foreground) { - title += L' '; - title += backgroundedString; + s += L' '; + s += _backgrounded_String; } - title += L' '; - UString totalTitle = title + _title; - UString fileName; - Sync.GetTitleFileName(fileName); - if (!fileName.IsEmpty()) + + s += L' '; + #ifndef _SFX { - ReduceString(fileName, kTitleFileNameSizeLimit); - totalTitle += L' '; - totalTitle += fileName; + unsigned len = s.Len(); + s += MainAddTitle; + AddToTitle(s); + s.DeleteFrom(len); } - SetText(totalTitle); - #ifndef _SFX - AddToTitle(title + MainAddTitle); #endif + + s += _title; + if (!_titleFileName.IsEmpty()) + { + UString fileName = _titleFileName; + ReduceString(fileName, kTitleFileNameSizeLimit); + s += L' '; + s += fileName; + } + SetText(s); } void CProgressDialog::SetPauseText() { - SetItemText(IDC_BUTTON_PAUSE, Sync.GetPaused() ? - continueString : pauseString); + SetItemText(IDB_PAUSE, Sync.Get_Paused() ? _continue_String : _pause_String); SetTitleText(); } void CProgressDialog::OnPauseButton() { - bool paused = !Sync.GetPaused(); - Sync.SetPaused(paused); + bool paused = !Sync.Get_Paused(); + Sync.Set_Paused(paused); UInt32 curTime = ::GetTickCount(); if (paused) _elapsedTime += (curTime - _prevTime); @@ -833,9 +1071,9 @@ void CProgressDialog::OnPauseButton() void CProgressDialog::SetPriorityText() { - SetItemText(IDC_BUTTON_PROGRESS_PRIORITY, _foreground ? - backgroundString : - foregroundString); + SetItemText(IDB_PROGRESS_BACKGROUND, _foreground ? + _background_String : + _foreground_String); SetTitleText(); } @@ -843,17 +1081,18 @@ void CProgressDialog::OnPriorityButton() { _foreground = !_foreground; #ifndef UNDER_CE - SetPriorityClass(GetCurrentProcess(), _foreground ? - NORMAL_PRIORITY_CLASS: IDLE_PRIORITY_CLASS); + SetPriorityClass(GetCurrentProcess(), _foreground ? NORMAL_PRIORITY_CLASS: IDLE_PRIORITY_CLASS); #endif SetPriorityText(); } -void CProgressDialog::AddMessageDirect(LPCWSTR message) +void CProgressDialog::AddMessageDirect(LPCWSTR message, bool needNumber) { int itemIndex = _messageList.GetItemCount(); - wchar_t sz[32]; - ConvertInt64ToString(itemIndex, sz); + wchar_t sz[16]; + sz[0] = 0; + if (needNumber) + ConvertUInt32ToString(_numMessages + 1, sz); _messageList.InsertItem(itemIndex, sz); _messageList.SetSubItem(itemIndex, 1, message); } @@ -861,22 +1100,25 @@ void CProgressDialog::AddMessageDirect(LPCWSTR message) void CProgressDialog::AddMessage(LPCWSTR message) { UString s = message; + bool needNumber = true; while (!s.IsEmpty()) { int pos = s.Find(L'\n'); if (pos < 0) break; - AddMessageDirect(s.Left(pos)); - s.Delete(0, pos + 1); + AddMessageDirect(s.Left(pos), needNumber); + needNumber = false; + s.DeleteFrontal(pos + 1); } - AddMessageDirect(s); + AddMessageDirect(s, needNumber); + _numMessages++; } -static unsigned GetNumDigits(UInt32 value) +static unsigned GetNumDigits(UInt32 val) { unsigned i; - for (i = 0; value >= 10; i++) - value /= 10; + for (i = 0; val >= 10; i++) + val /= 10; return i; } @@ -884,14 +1126,19 @@ 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(); + NSynchronization::CCriticalSectionLock lock(Sync._cs); + unsigned num = Sync.Messages.Size(); + if (num > _numPostedMessages) + { + messages.ClearAndReserve(num - _numPostedMessages); + for (unsigned i = _numPostedMessages; i < num; i++) + messages.AddInReserved(Sync.Messages[i]); + _numPostedMessages = num; + } } if (!messages.IsEmpty()) { - for (int i = 0; i < messages.Size(); i++) + FOR_VECTOR (i, messages) AddMessage(messages[i]); if (_numAutoSizeMessages < 256 || GetNumDigits(_numPostedMessages) > GetNumDigits(_numAutoSizeMessages)) { @@ -905,7 +1152,7 @@ void CProgressDialog::UpdateMessagesDialog() bool CProgressDialog::OnButtonClicked(int buttonID, HWND buttonHWND) { - switch(buttonID) + switch (buttonID) { // case IDOK: // if IDCANCEL is not DEFPUSHBUTTON case IDCANCEL: @@ -917,13 +1164,11 @@ bool CProgressDialog::OnButtonClicked(int buttonID, HWND buttonHWND) break; } - bool paused = Sync.GetPaused(); + bool paused = Sync.Get_Paused(); if (!paused) OnPauseButton(); _inCancelMessageBox = true; - int res = ::MessageBoxW(HWND(*this), - LangStringSpec(IDS_PROGRESS_ASK_CANCEL, 0x02000C30), - _title, MB_YESNOCANCEL); + int res = ::MessageBoxW(*this, LangString(IDS_PROGRESS_ASK_CANCEL), _title, MB_YESNOCANCEL); _inCancelMessageBox = false; if (!paused) OnPauseButton(); @@ -939,10 +1184,10 @@ bool CProgressDialog::OnButtonClicked(int buttonID, HWND buttonHWND) break; } - case IDC_BUTTON_PAUSE: + case IDB_PAUSE: OnPauseButton(); return true; - case IDC_BUTTON_PROGRESS_PRIORITY: + case IDB_PROGRESS_BACKGROUND: OnPriorityButton(); return true; } @@ -979,16 +1224,6 @@ HRESULT CProgressThreadVirt::Create(const UString &title, HWND parentWindow) return S_OK; } -UString HResultToMessage(HRESULT errorCode) -{ - UString message; - if (errorCode == E_OUTOFMEMORY) - message = LangStringSpec(IDS_MEM_ERROR, 0x0200060B); - else - message = NError::MyFormatMessageW(errorCode); - return message; -} - static void AddMessageToString(UString &dest, const UString &src) { if (!src.IsEmpty()) @@ -1007,28 +1242,42 @@ void CProgressThreadVirt::Process() catch(const wchar_t *s) { m = s; } catch(const UString &s) { m = s; } catch(const char *s) { m = GetUnicodeString(s); } + catch(int v) + { + wchar_t s[16]; + ConvertUInt32ToString(v, s); + m = L"Error #"; + m += s; + } catch(...) { m = L"Error"; } if (Result != E_ABORT) { if (m.IsEmpty() && Result != S_OK) m = HResultToMessage(Result); } - AddMessageToString(m, ErrorMessage); + AddMessageToString(m, FinalMessage.ErrorMessage.Message); AddMessageToString(m, fs2us(ErrorPath1)); AddMessageToString(m, fs2us(ErrorPath2)); + CProgressSync &sync = ProgressDialog.Sync; + NSynchronization::CCriticalSectionLock lock(sync._cs); if (m.IsEmpty()) { - if (!OkMessage.IsEmpty()) - { - ProgressDialog.Sync.SetOkMessageTitle(OkMessageTitle); - ProgressDialog.Sync.SetOkMessage(OkMessage); - } + if (!FinalMessage.OkMessage.Message.IsEmpty()) + sync.FinalMessage.OkMessage = FinalMessage.OkMessage; } else { - ProgressDialog.Sync.SetErrorMessage(m); + sync.FinalMessage.ErrorMessage.Message = m; if (Result == S_OK) Result = E_FAIL; } } + +UString HResultToMessage(HRESULT errorCode) +{ + if (errorCode == E_OUTOFMEMORY) + return LangString(IDS_MEM_ERROR); + else + return NError::MyFormatMessage(errorCode); +} diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.h b/CPP/7zip/UI/FileManager/ProgressDialog2.h old mode 100755 new mode 100644 index 6bb13603..632d022a --- a/CPP/7zip/UI/FileManager/ProgressDialog2.h +++ b/CPP/7zip/UI/FileManager/ProgressDialog2.h @@ -1,249 +1,184 @@ // ProgressDialog2.h -#ifndef __PROGRESS_DIALOG2_H -#define __PROGRESS_DIALOG2_H +#ifndef __PROGRESS_DIALOG_2_H +#define __PROGRESS_DIALOG_2_H -#include "Common/MyCom.h" +#include "../../../Common/MyCom.h" -#include "Windows/Synchronization.h" -#include "Windows/Thread.h" +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/Synchronization.h" +#include "../../../Windows/Thread.h" -#include "Windows/Control/Dialog.h" -#include "Windows/Control/ListView.h" -#include "Windows/Control/ProgressBar.h" +#include "../../../Windows/Control/Dialog.h" +#include "../../../Windows/Control/ListView.h" +#include "../../../Windows/Control/ProgressBar.h" #include "MyWindowsNew.h" +struct CProgressMessageBoxPair +{ + UString Title; + UString Message; +}; + +struct CProgressFinalMessage +{ + CProgressMessageBoxPair ErrorMessage; + CProgressMessageBoxPair OkMessage; + + bool ThereIsMessage() const { return !ErrorMessage.Message.IsEmpty() || !OkMessage.Message.IsEmpty(); } +}; + class CProgressSync { bool _stopped; bool _paused; - bool _bytesProgressMode; +public: + bool _bytesProgressMode; UInt64 _totalBytes; - UInt64 _curBytes; + UInt64 _completedBytes; UInt64 _totalFiles; UInt64 _curFiles; UInt64 _inSize; UInt64 _outSize; UString _titleFileName; - UString _currentFileName; + UString _status; + UString _filePath; + bool _isDir; -public: UStringVector Messages; - UString ErrorMessage; - UString ErrorMessageTitle; - - UString OkMessage; - UString OkMessageTitle; + CProgressFinalMessage FinalMessage; 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) - {} + CProgressSync(); - bool GetStopped() + bool Get_Stopped() { NWindows::NSynchronization::CCriticalSectionLock lock(_cs); return _stopped; } - void SetStopped(bool value) + void Set_Stopped(bool val) { NWindows::NSynchronization::CCriticalSectionLock lock(_cs); - _stopped = value; + _stopped = val; } - bool GetPaused() - { - NWindows::NSynchronization::CCriticalSectionLock lock(_cs); - return _paused; - } - void SetPaused(bool value) + + bool Get_Paused(); + void Set_Paused(bool val) { NWindows::NSynchronization::CCriticalSectionLock lock(_cs); - _paused = value; + _paused = val; } - void SetBytesProgressMode(bool bytesProgressMode) + + void Set_BytesProgressMode(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; - } + + HRESULT CheckStop(); + HRESULT ScanProgress(UInt64 numFiles, UInt64 totalSize, const UString &fileName, bool isDir = false); - void SetErrorMessageTitle(const UString &title) - { - NWindows::NSynchronization::CCriticalSectionLock lock(_cs); - ErrorMessageTitle = title; - } + void Set_NumFilesTotal(UInt64 val); + void Set_NumBytesTotal(UInt64 val); + void Set_NumFilesCur(UInt64 val); + HRESULT Set_NumBytesCur(const UInt64 *val); + HRESULT Set_NumBytesCur(UInt64 val); + void Set_Ratio(const UInt64 *inSize, const UInt64 *outSize); - bool ThereIsMessage() const - { - return !Messages.IsEmpty() || !ErrorMessage.IsEmpty() || !OkMessage.IsEmpty(); - } -}; + void Set_TitleFileName(const UString &fileName); + void Set_Status(const UString &s); + void Set_FilePath(const UString &path, bool isDir = false); -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); } -}; + void AddError_Message(const wchar_t *message); + void AddError_Message_Name(const wchar_t *message, const wchar_t *name); + void AddError_Code_Name(DWORD systemError, const wchar_t *name); -enum ESpeedMode -{ - kSpeedBytes, - kSpeedKBytes, - kSpeedMBytes + bool ThereIsMessage() const { return !Messages.IsEmpty() || FinalMessage.ThereIsMessage(); } }; class CProgressDialog: public NWindows::NControl::CModalDialog { - UString _prevFileName; - UString _prevTitleName; + UString _titleFileName; + UString _filePath; + UString _status; + bool _isDir; - UString backgroundString; - UString backgroundedString; - UString foregroundString; - UString pauseString; - UString continueString; - UString pausedString; + UString _background_String; + UString _backgrounded_String; + UString _foreground_String; + UString _pause_String; + UString _continue_String; + UString _paused_String; - int buttonSizeX; - int buttonSizeY; + int _buttonSizeX; + int _buttonSizeY; UINT_PTR _timer; UString _title; - CU64ToI32Converter _converter; - UInt64 _previousPos; - UInt64 _range; + + class CU64ToI32Converter + { + unsigned _numShiftBits; + UInt64 _range; + public: + CU64ToI32Converter(): _numShiftBits(0), _range(1) {} + void Init(UInt64 range) + { + _range = range; + // Windows CE doesn't like big number for ProgressBar. + for (_numShiftBits = 0; range >= ((UInt32)1 << 15); _numShiftBits++) + range >>= 1; + } + int Count(UInt64 val) + { + int res = (int)(val >> _numShiftBits); + if (val == _range) + res++; + return res; + } + }; + + CU64ToI32Converter _progressConv; + UInt64 _progressBar_Pos; + UInt64 _progressBar_Range; + NWindows::NControl::CProgressBar m_ProgressBar; NWindows::NControl::CListView _messageList; + + int _numMessages; CMyComPtr _taskbarList; HWND _hwndForTaskbar; - UInt32 _prevPercentValue; UInt32 _prevTime; - UInt32 _elapsedTime; - UInt32 _prevElapsedSec; + UInt64 _elapsedTime; + + UInt64 _prevPercentValue; + UInt64 _prevElapsedSec; UInt64 _prevRemainingSec; - ESpeedMode _prevMode; + + UInt64 _totalBytes_Prev; + UInt64 _processed_Prev; + UInt64 _packed_Prev; + UInt64 _ratio_Prev; + UString _filesStr_Prev; + + unsigned _prevSpeed_MoveBits; UInt64 _prevSpeed; bool _foreground; - int _numReduceSymbols; + unsigned _numReduceSymbols; bool _wasCreated; bool _needClose; - UInt32 _numPostedMessages; + unsigned _numPostedMessages; UInt32 _numAutoSizeMessages; bool _errorsWereDisplayed; @@ -264,8 +199,8 @@ class CProgressDialog: public NWindows::NControl::CModalDialog void UpdateStatInfo(bool showAll); bool OnTimer(WPARAM timerID, LPARAM callback); - void SetRange(UInt64 range); - void SetPos(UInt64 pos); + void SetProgressRange(UInt64 range); + void SetProgressPos(UInt64 pos); virtual bool OnInit(); virtual bool OnSize(WPARAM wParam, int xSize, int ySize); virtual void OnCancel(); @@ -281,13 +216,14 @@ class CProgressDialog: public NWindows::NControl::CModalDialog void OnPauseButton(); void OnPriorityButton(); bool OnButtonClicked(int buttonID, HWND buttonHWND); + bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam); void SetTitleText(); - void ShowSize(int id, UInt64 value); + void ShowSize(int id, UInt64 val, UInt64 &prev); void UpdateMessagesDialog(); - void AddMessageDirect(LPCWSTR message); + void AddMessageDirect(LPCWSTR message, bool needNumber); void AddMessage(LPCWSTR message); bool OnExternalCloseMessage(); @@ -318,12 +254,8 @@ public: _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(); }; @@ -341,9 +273,7 @@ class CProgressThreadVirt FString ErrorPath1; FString ErrorPath2; protected: - UString ErrorMessage; - UString OkMessage; - UString OkMessageTitle; + CProgressFinalMessage FinalMessage; // error if any of HRESULT, ErrorMessage, ErrorPath virtual HRESULT ProcessVirt() = 0; @@ -370,6 +300,9 @@ public: HRESULT Create(const UString &title, HWND parentWindow = 0); CProgressThreadVirt(): Result(E_FAIL), ThreadFinishedOK(false) {} + + CProgressMessageBoxPair &GetMessagePair(bool isError) { return isError ? FinalMessage.ErrorMessage : FinalMessage.OkMessage; } + }; UString HResultToMessage(HRESULT errorCode); diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.rc b/CPP/7zip/UI/FileManager/ProgressDialog2.rc old mode 100755 new mode 100644 index 703dbb1f..4d0e0c7b --- a/CPP/7zip/UI/FileManager/ProgressDialog2.rc +++ b/CPP/7zip/UI/FileManager/ProgressDialog2.rc @@ -2,7 +2,7 @@ #include "../../GuiCommon.rc" #undef DIALOG_ID -#define DIALOG_ID IDD_DIALOG_PROGRESS +#define DIALOG_ID IDD_PROGRESS #define xc 360 #define k 11 #define z1s 16 @@ -19,7 +19,7 @@ #undef k #undef z1s -#define DIALOG_ID IDD_DIALOG_PROGRESS_2 +#define DIALOG_ID IDD_PROGRESS_2 #define m 4 #define k 8 #define z1s 12 @@ -34,8 +34,7 @@ STRINGTABLE DISCARDABLE { IDS_PROGRESS_PAUSED "Paused" IDS_PROGRESS_FOREGROUND "&Foreground" - IDS_PROGRESS_CONTINUE "&Continue" + IDS_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 old mode 100755 new mode 100644 index be5af607..b45d7b49 --- a/CPP/7zip/UI/FileManager/ProgressDialog2Res.h +++ b/CPP/7zip/UI/FileManager/ProgressDialog2Res.h @@ -1,45 +1,48 @@ -#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 IDD_PROGRESS 97 +#define IDD_PROGRESS_2 10097 + +#define IDS_CLOSE 408 +#define IDS_CONTINUE 411 + +#define IDB_PROGRESS_BACKGROUND 444 +#define IDS_PROGRESS_FOREGROUND 445 +#define IDB_PAUSE 446 +#define IDS_PROGRESS_PAUSED 447 +#define IDS_PROGRESS_ASK_CANCEL 448 + +#define IDT_PROGRESS_PACKED 1008 +#define IDT_PROGRESS_FILES 1032 + +#define IDT_PROGRESS_ELAPSED 3900 +#define IDT_PROGRESS_REMAINING 3901 +#define IDT_PROGRESS_TOTAL 3902 +#define IDT_PROGRESS_SPEED 3903 +#define IDT_PROGRESS_PROCESSED 3904 +#define IDT_PROGRESS_RATIO 3905 +#define IDT_PROGRESS_ERRORS 3906 + +#define IDC_PROGRESS1 100 +#define IDL_PROGRESS_MESSAGES 101 +#define IDT_PROGRESS_FILE_NAME 102 +#define IDT_PROGRESS_STATUS 103 + +#define IDT_PROGRESS_PACKED_VAL 110 +#define IDT_PROGRESS_FILES_VAL 111 + +#define IDT_PROGRESS_ELAPSED_VAL 120 +#define IDT_PROGRESS_REMAINING_VAL 121 +#define IDT_PROGRESS_TOTAL_VAL 122 +#define IDT_PROGRESS_SPEED_VAL 123 +#define IDT_PROGRESS_PROCESSED_VAL 124 +#define IDT_PROGRESS_RATIO_VAL 125 +#define IDT_PROGRESS_ERRORS_VAL 126 + #ifdef UNDER_CE -#define MY_PROGRESS_VALUE_UNITS 44 +#define MY_PROGRESS_VAL_UNITS 44 #else -#define MY_PROGRESS_VALUE_UNITS 76 +#define MY_PROGRESS_VAL_UNITS 76 #endif -#define MY_PROGRESS_LABEL_UNITS_MIN 60 +#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 old mode 100755 new mode 100644 index 8eba4148..e9713930 --- a/CPP/7zip/UI/FileManager/ProgressDialog2a.rc +++ b/CPP/7zip/UI/FileManager/ProgressDialog2a.rc @@ -2,9 +2,9 @@ #define bxs 80 #define x0s MY_PROGRESS_LABEL_UNITS_START -#define x1s MY_PROGRESS_VALUE_UNITS +#define x1s MY_PROGRESS_VAL_UNITS #define x2s MY_PROGRESS_LABEL_UNITS_START -#define x3s MY_PROGRESS_VALUE_UNITS +#define x3s MY_PROGRESS_VAL_UNITS #define x1 (m + x0s) #define x3 (xs - m - x3s) @@ -17,10 +17,9 @@ #undef y4 #undef z0 -#undef z0z #undef z1 #undef z2 -#undef z2 +#undef z3 #define y0 m #define y1 (y0 + k) @@ -28,7 +27,9 @@ #define y3 (y2 + k) #define y4 (y3 + k) -#define z2 (y4 + k + 1) +#define z3 (y4 + k + 1) + +#define z2 (z3 + k + 1) #define z2s 24 #define z1 (z2 + z2s) @@ -39,40 +40,41 @@ #define yc (z0 + z0s + bys) -DIALOG_ID MY_RESIZE_DIALOG +DIALOG_ID DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT 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 + DEFPUSHBUTTON "&Background", IDB_PROGRESS_BACKGROUND, bx3, by, bxs, bys + PUSHBUTTON "&Pause", IDB_PAUSE bx2, by, bxs, bys + PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys + + LTEXT "Elapsed time:", IDT_PROGRESS_ELAPSED, m, y0, x0s, 8 + LTEXT "Remaining time:", IDT_PROGRESS_REMAINING, m, y1, x0s, 8 + LTEXT "Files:", IDT_PROGRESS_FILES, m, y2, x0s, 8 + LTEXT "Compression ratio:", IDT_PROGRESS_RATIO, m, y3, x0s, 8 + LTEXT "Errors:", IDT_PROGRESS_ERRORS, m, y4, x0s, 8 + + LTEXT "Total size:", IDT_PROGRESS_TOTAL, x2, y0, x2s, 8 + LTEXT "Speed:", IDT_PROGRESS_SPEED, x2, y1, x2s, 8 + LTEXT "Processed:", IDT_PROGRESS_PROCESSED,x2, y2, x2s, 8 + LTEXT "Compressed size:" , IDT_PROGRESS_PACKED, x2, y3, x2s, 8 + + RTEXT "", IDT_PROGRESS_ELAPSED_VAL, x1, y0, x1s, MY_TEXT_NOPREFIX + RTEXT "", IDT_PROGRESS_REMAINING_VAL, x1, y1, x1s, MY_TEXT_NOPREFIX + RTEXT "", IDT_PROGRESS_FILES_VAL, x1, y2, x1s, MY_TEXT_NOPREFIX + RTEXT "", IDT_PROGRESS_RATIO_VAL, x1, y3, x1s, MY_TEXT_NOPREFIX + RTEXT "", IDT_PROGRESS_ERRORS_VAL, x1, y4, x1s, MY_TEXT_NOPREFIX + + RTEXT "", IDT_PROGRESS_TOTAL_VAL, x3, y0, x3s, MY_TEXT_NOPREFIX + RTEXT "", IDT_PROGRESS_SPEED_VAL, x3, y1, x3s, MY_TEXT_NOPREFIX + RTEXT "", IDT_PROGRESS_PROCESSED_VAL, x3, y2, x3s, MY_TEXT_NOPREFIX + RTEXT "", IDT_PROGRESS_PACKED_VAL, x3, y3, x3s, MY_TEXT_NOPREFIX + + LTEXT "", IDT_PROGRESS_STATUS, m, z3, xc, MY_TEXT_NOPREFIX + CONTROL "", IDT_PROGRESS_FILE_NAME, "Static", SS_NOPREFIX | SS_LEFTNOWORDWRAP, m, z2, xc, z2s + + CONTROL "Progress1", IDC_PROGRESS1, "msctls_progress32", PBS_SMOOTH | WS_BORDER, m, z1, xc, z1s + + CONTROL "List1", IDL_PROGRESS_MESSAGES, "SysListView32", + LVS_REPORT | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, + m, z0, xc, z0s } diff --git a/CPP/7zip/UI/FileManager/ProgressDialogRes.h b/CPP/7zip/UI/FileManager/ProgressDialogRes.h old mode 100755 new mode 100644 index 97e47228..cbf3beb2 --- a/CPP/7zip/UI/FileManager/ProgressDialogRes.h +++ b/CPP/7zip/UI/FileManager/ProgressDialogRes.h @@ -1,3 +1,3 @@ -#define IDD_DIALOG_PROGRESS 500 +#define IDD_PROGRESS 97 -#define IDC_PROGRESS1 1000 +#define IDC_PROGRESS1 100 diff --git a/CPP/7zip/UI/FileManager/PropertyName.cpp b/CPP/7zip/UI/FileManager/PropertyName.cpp old mode 100755 new mode 100644 index 098bc47d..838b6e3f --- a/CPP/7zip/UI/FileManager/PropertyName.cpp +++ b/CPP/7zip/UI/FileManager/PropertyName.cpp @@ -2,109 +2,22 @@ #include "StdAfx.h" -#include "Common/IntToString.h" - -#include "Windows/ResourceString.h" - -#include "../../PropID.h" +#include "../../../Common/IntToString.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 (propID < 1000) { - if (name) - return name; - wchar_t s[16]; - ConvertUInt32ToString(propID, s); - return s; + UString s = LangString(1000 + propID); + if (!s.IsEmpty()) + return s; } - const CPropertyIDNamePair &pair = kPropertyIDNamePairs[index]; - return LangString(pair.ResourceID, pair.LangID); + if (name) + return name; + wchar_t temp[16]; + ConvertUInt32ToString(propID, temp); + return temp; } diff --git a/CPP/7zip/UI/FileManager/PropertyName.h b/CPP/7zip/UI/FileManager/PropertyName.h old mode 100755 new mode 100644 index 95e9dc9b..4f0d6dc1 --- a/CPP/7zip/UI/FileManager/PropertyName.h +++ b/CPP/7zip/UI/FileManager/PropertyName.h @@ -1,9 +1,9 @@ // PropertyName.h -#ifndef __PROPERTYNAME_H -#define __PROPERTYNAME_H +#ifndef __PROPERTY_NAME_H +#define __PROPERTY_NAME_H -#include "Common/MyString.h" +#include "../../../Common/MyString.h" UString GetNameOfProperty(PROPID propID, const wchar_t *name); diff --git a/CPP/7zip/UI/FileManager/PropertyName.rc b/CPP/7zip/UI/FileManager/PropertyName.rc old mode 100755 new mode 100644 index bdd6c8ed..43c4584f --- a/CPP/7zip/UI/FileManager/PropertyName.rc +++ b/CPP/7zip/UI/FileManager/PropertyName.rc @@ -4,57 +4,94 @@ 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_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_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_SPLIT_AFTER "Split After" + IDS_PROP_DICTIONARY_SIZE "Dictionary" + 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_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_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" + IDS_PROP_SYM_LINK "Symbolic Link" + IDS_PROP_ERROR "Error" + 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_PROP_NT_SECURITY "NT Security" + IDS_PROP_ALT_STREAM "Alternate Stream" + IDS_PROP_AUX "Aux" + IDS_PROP_DELETED "Deleted" + IDS_PROP_IS_TREE "Is Tree" + IDS_PROP_SHA1 "SHA-1" + IDS_PROP_SHA256 "SHA-256" + IDS_PROP_ERROR_TYPE "Error Type" + IDS_PROP_NUM_ERRORS "Errors" + IDS_PROP_ERROR_FLAGS "Errors" + IDS_PROP_WARNING_FLAGS "Warnings" + IDS_PROP_WARNING "Warning" + IDS_PROP_NUM_STREAMS "Streams" + IDS_PROP_NUM_ALT_STREAMS "Alternate Streams" + IDS_PROP_ALT_STREAMS_SIZE "Alternate Streams Size" + IDS_PROP_VIRTUAL_SIZE "Virtual Size" + IDS_PROP_UNPACK_SIZE "Unpack Size" + IDS_PROP_TOTAL_PHY_SIZE "Total Physical Size" + IDS_PROP_VOLUME_INDEX "Volume Index" + IDS_PROP_SUBTYPE "SubType" + IDS_PROP_SHORT_COMMENT "Short Comment" + IDS_PROP_CODE_PAGE "Code Page" + IDS_PROP_IS_NOT_ARC_TYPE "Is not archive type" + IDS_PROP_PHY_SIZE_CANT_BE_DETECTED "Physical Size can't be detected" + IDS_PROP_ZEROS_TAIL_IS_ALLOWED "Zeros Tail Is Allowed" + IDS_PROP_TAIL_SIZE "Tail Size" + IDS_PROP_EMB_STUB_SIZE "Embedded Stub Size" + IDS_PROP_NT_REPARSE "Link" + IDS_PROP_HARD_LINK "Hard Link" + IDS_PROP_INODE "iNode" + IDS_PROP_STREAM_ID "Stream ID" END diff --git a/CPP/7zip/UI/FileManager/PropertyNameRes.h b/CPP/7zip/UI/FileManager/PropertyNameRes.h old mode 100755 new mode 100644 index 9cc9f7c5..199aa6da --- a/CPP/7zip/UI/FileManager/PropertyNameRes.h +++ b/CPP/7zip/UI/FileManager/PropertyNameRes.h @@ -1,53 +1,92 @@ -#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 + +#define IDS_PROP_PATH 1003 +#define IDS_PROP_NAME 1004 +#define IDS_PROP_EXTENSION 1005 +#define IDS_PROP_IS_FOLDER 1006 +#define IDS_PROP_SIZE 1007 +#define IDS_PROP_PACKED_SIZE 1008 +#define IDS_PROP_ATTRIBUTES 1009 +#define IDS_PROP_CTIME 1010 +#define IDS_PROP_ATIME 1011 +#define IDS_PROP_MTIME 1012 +#define IDS_PROP_SOLID 1013 +#define IDS_PROP_C0MMENTED 1014 +#define IDS_PROP_ENCRYPTED 1015 +#define IDS_PROP_SPLIT_BEFORE 1016 +#define IDS_PROP_SPLIT_AFTER 1017 +#define IDS_PROP_DICTIONARY_SIZE 1018 +#define IDS_PROP_CRC 1019 +#define IDS_PROP_FILE_TYPE 1020 +#define IDS_PROP_ANTI 1021 +#define IDS_PROP_METHOD 1022 +#define IDS_PROP_HOST_OS 1023 +#define IDS_PROP_FILE_SYSTEM 1024 +#define IDS_PROP_USER 1025 +#define IDS_PROP_GROUP 1026 +#define IDS_PROP_BLOCK 1027 +#define IDS_PROP_COMMENT 1028 +#define IDS_PROP_POSITION 1029 +#define IDS_PROP_PREFIX 1030 +#define IDS_PROP_FOLDERS 1031 +#define IDS_PROP_FILES 1032 +#define IDS_PROP_VERSION 1033 +#define IDS_PROP_VOLUME 1034 +#define IDS_PROP_IS_VOLUME 1035 +#define IDS_PROP_OFFSET 1036 +#define IDS_PROP_LINKS 1037 +#define IDS_PROP_NUM_BLOCKS 1038 +#define IDS_PROP_NUM_VOLUMES 1039 + +#define IDS_PROP_BIT64 1041 +#define IDS_PROP_BIG_ENDIAN 1042 +#define IDS_PROP_CPU 1043 +#define IDS_PROP_PHY_SIZE 1044 +#define IDS_PROP_HEADERS_SIZE 1045 +#define IDS_PROP_CHECKSUM 1046 +#define IDS_PROP_CHARACTS 1047 +#define IDS_PROP_VA 1048 +#define IDS_PROP_ID 1049 +#define IDS_PROP_SHORT_NAME 1050 +#define IDS_PROP_CREATOR_APP 1051 +#define IDS_PROP_SECTOR_SIZE 1052 +#define IDS_PROP_POSIX_ATTRIB 1053 +#define IDS_PROP_SYM_LINK 1054 +#define IDS_PROP_ERROR 1055 +#define IDS_PROP_TOTAL_SIZE 1056 +#define IDS_PROP_FREE_SPACE 1057 +#define IDS_PROP_CLUSTER_SIZE 1058 +#define IDS_PROP_VOLUME_NAME 1059 +#define IDS_PROP_LOCAL_NAME 1060 +#define IDS_PROP_PROVIDER 1061 +#define IDS_PROP_NT_SECURITY 1062 +#define IDS_PROP_ALT_STREAM 1063 +#define IDS_PROP_AUX 1064 +#define IDS_PROP_DELETED 1065 +#define IDS_PROP_IS_TREE 1066 +#define IDS_PROP_SHA1 1067 +#define IDS_PROP_SHA256 1068 +#define IDS_PROP_ERROR_TYPE 1069 +#define IDS_PROP_NUM_ERRORS 1070 +#define IDS_PROP_ERROR_FLAGS 1071 +#define IDS_PROP_WARNING_FLAGS 1072 +#define IDS_PROP_WARNING 1073 +#define IDS_PROP_NUM_STREAMS 1074 +#define IDS_PROP_NUM_ALT_STREAMS 1075 +#define IDS_PROP_ALT_STREAMS_SIZE 1076 +#define IDS_PROP_VIRTUAL_SIZE 1077 +#define IDS_PROP_UNPACK_SIZE 1078 +#define IDS_PROP_TOTAL_PHY_SIZE 1079 +#define IDS_PROP_VOLUME_INDEX 1080 +#define IDS_PROP_SUBTYPE 1081 +#define IDS_PROP_SHORT_COMMENT 1082 +#define IDS_PROP_CODE_PAGE 1083 +#define IDS_PROP_IS_NOT_ARC_TYPE 1084 +#define IDS_PROP_PHY_SIZE_CANT_BE_DETECTED 1085 +#define IDS_PROP_ZEROS_TAIL_IS_ALLOWED 1086 +#define IDS_PROP_TAIL_SIZE 1087 +#define IDS_PROP_EMB_STUB_SIZE 1088 +#define IDS_PROP_NT_REPARSE 1089 +#define IDS_PROP_HARD_LINK 1090 +#define IDS_PROP_INODE 1091 +#define IDS_PROP_STREAM_ID 1092 diff --git a/CPP/7zip/UI/FileManager/RegistryAssociations.cpp b/CPP/7zip/UI/FileManager/RegistryAssociations.cpp old mode 100755 new mode 100644 index 487b6060..ee944350 --- a/CPP/7zip/UI/FileManager/RegistryAssociations.cpp +++ b/CPP/7zip/UI/FileManager/RegistryAssociations.cpp @@ -2,11 +2,11 @@ #include "StdAfx.h" -#include "Common/IntToString.h" -#include "Common/StringConvert.h" -#include "Common/StringToInt.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/StringToInt.h" -#include "Windows/Registry.h" +#include "../../../Windows/Registry.h" #include "RegistryAssociations.h" @@ -69,11 +69,13 @@ bool CShellExtInfo::ReadFromRegistry(HKEY hkey, const CSysString &ext) if (pos >= 0) { const wchar_t *end; - Int64 index = ConvertStringToInt64((const wchar_t *)value + pos + 1, &end); + Int32 index = ConvertStringToInt32((const wchar_t *)value + pos + 1, &end); if (*end == 0) { - IconIndex = (int)index; - IconPath = value.Left(pos); + // 9.31: if there is no icon index, we use -1. Is it OK? + if (pos != (int)value.Len() - 1) + IconIndex = (int)index; + IconPath.SetFrom(value, pos); } } } @@ -85,7 +87,7 @@ bool CShellExtInfo::ReadFromRegistry(HKEY hkey, const CSysString &ext) bool CShellExtInfo::IsIt7Zip() const { UString s = GetUnicodeString(k7zipPrefix); - return (s.CompareNoCase(GetUnicodeString(ProgramKey.Left(s.Length()))) == 0); + return MyStringCompareNoCase_N(GetUnicodeString(ProgramKey), s, s.Len()) == 0; } LONG DeleteShellExtensionInfo(HKEY hkey, const CSysString &ext) @@ -143,7 +145,7 @@ LONG AddShellExtensionInfo(HKEY hkey, { iconPathFull += L','; wchar_t s[16]; - ConvertInt64ToString(iconIndex, s); + ConvertUInt32ToString((UInt32)iconIndex, s); iconPathFull += s; } iconKey.Create(programKey, kDefaultIconKeyName); diff --git a/CPP/7zip/UI/FileManager/RegistryAssociations.h b/CPP/7zip/UI/FileManager/RegistryAssociations.h old mode 100755 new mode 100644 index 0be8244e..975c9d5f --- a/CPP/7zip/UI/FileManager/RegistryAssociations.h +++ b/CPP/7zip/UI/FileManager/RegistryAssociations.h @@ -3,7 +3,7 @@ #ifndef __REGISTRY_ASSOCIATIONS_H #define __REGISTRY_ASSOCIATIONS_H -#include "Common/MyString.h" +#include "../../../Common/MyString.h" namespace NRegistryAssoc { diff --git a/CPP/7zip/UI/FileManager/RegistryPlugins.cpp b/CPP/7zip/UI/FileManager/RegistryPlugins.cpp old mode 100755 new mode 100644 index 54254f1f..ad70db80 --- a/CPP/7zip/UI/FileManager/RegistryPlugins.cpp +++ b/CPP/7zip/UI/FileManager/RegistryPlugins.cpp @@ -2,9 +2,9 @@ #include "StdAfx.h" -#include "Windows/DLL.h" -#include "Windows/FileFind.h" -#include "Windows/PropVariant.h" +#include "../../../Windows/DLL.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/PropVariant.h" #include "IFolder.h" #include "RegistryPlugins.h" @@ -118,7 +118,7 @@ void ReadPluginInfoList(CObjectVector &plugins) void ReadFileFolderPluginInfoList(CObjectVector &plugins) { ReadPluginInfoList(plugins); - for (int i = 0; i < plugins.Size();) + for (unsigned i = 0; i < plugins.Size();) if (plugins[i].Type != kPluginTypeFF) plugins.Delete(i); else diff --git a/CPP/7zip/UI/FileManager/RegistryPlugins.h b/CPP/7zip/UI/FileManager/RegistryPlugins.h old mode 100755 new mode 100644 index 20f2ec34..dfa6de54 --- a/CPP/7zip/UI/FileManager/RegistryPlugins.h +++ b/CPP/7zip/UI/FileManager/RegistryPlugins.h @@ -3,7 +3,7 @@ #ifndef __REGISTRY_PLUGINS_H #define __REGISTRY_PLUGINS_H -#include "Common/MyString.h" +#include "../../../Common/MyString.h" enum EPluginType { diff --git a/CPP/7zip/UI/FileManager/RegistryUtils.cpp b/CPP/7zip/UI/FileManager/RegistryUtils.cpp old mode 100755 new mode 100644 index 6697169b..ffcb5555 --- a/CPP/7zip/UI/FileManager/RegistryUtils.cpp +++ b/CPP/7zip/UI/FileManager/RegistryUtils.cpp @@ -2,9 +2,9 @@ #include "StdAfx.h" -#include "Common/IntToString.h" +#include "../../../Common/IntToString.h" -#include "Windows/Registry.h" +#include "../../../Windows/Registry.h" #include "RegistryUtils.h" @@ -18,6 +18,7 @@ static const TCHAR *kCU_FMPath = REG_PATH_7Z TEXT(STRING_PATH_SEPARATOR) TEXT("F // static const TCHAR *kLM_Path = REG_PATH_7Z TEXT(STRING_PATH_SEPARATOR) TEXT("FM"); static const WCHAR *kLangValueName = L"Lang"; +static const WCHAR *kViewer = L"Viewer"; static const WCHAR *kEditor = L"Editor"; static const WCHAR *kDiff = L"Diff"; static const TCHAR *kShowDots = TEXT("ShowDots"); @@ -33,6 +34,7 @@ static const TCHAR *kSingleClick = TEXT("SingleClick"); // static const TCHAR *kUnderline = TEXT("Underline"); static const TCHAR *kFlatViewName = TEXT("FlatViewArc"); +// static const TCHAR *kShowDeletedFiles = TEXT("ShowDeleted"); static void SaveCuString(LPCTSTR keyPath, LPCWSTR valuePath, LPCWSTR value) { @@ -52,8 +54,8 @@ static void ReadCuString(LPCTSTR keyPath, LPCWSTR valuePath, UString &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 SaveRegEditor(bool useEditor, const UString &path) { SaveCuString(kCU_FMPath, useEditor ? kEditor : kViewer, path); } +void ReadRegEditor(bool useEditor, UString &path) { ReadCuString(kCU_FMPath, useEditor ? kEditor : kViewer, path); } void SaveRegDiff(const UString &path) { SaveCuString(kCU_FMPath, kDiff, path); } void ReadRegDiff(UString &path) { ReadCuString(kCU_FMPath, kDiff, path); } @@ -123,8 +125,8 @@ 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 Save_ShowSystemMenu(bool show) { SaveOption(kShowSystemMenu, show); } +bool Read_ShowSystemMenu(){ return ReadOption(kShowSystemMenu, false); } void SaveFullRow(bool enable) { SaveOption(kFullRow, enable); } bool ReadFullRow() { return ReadOption(kFullRow, false); } @@ -158,3 +160,8 @@ static CSysString GetFlatViewName(UInt32 panelIndex) void SaveFlatView(UInt32 panelIndex, bool enable) { SaveOption(GetFlatViewName(panelIndex), enable); } bool ReadFlatView(UInt32 panelIndex) { return ReadOption(GetFlatViewName(panelIndex), false); } + +/* +void Save_ShowDeleted(bool enable) { SaveOption(kShowDeletedFiles, enable); } +bool Read_ShowDeleted() { return ReadOption(kShowDeletedFiles, false); } +*/ \ No newline at end of file diff --git a/CPP/7zip/UI/FileManager/RegistryUtils.h b/CPP/7zip/UI/FileManager/RegistryUtils.h old mode 100755 new mode 100644 index 3bf06617..678a3375 --- a/CPP/7zip/UI/FileManager/RegistryUtils.h +++ b/CPP/7zip/UI/FileManager/RegistryUtils.h @@ -3,14 +3,14 @@ #ifndef __REGISTRY_UTILS_H #define __REGISTRY_UTILS_H -#include "Common/MyString.h" -#include "Common/Types.h" +#include "../../../Common/MyTypes.h" +#include "../../../Common/MyString.h" void SaveRegLang(const UString &path); void ReadRegLang(UString &path); -void SaveRegEditor(const UString &path); -void ReadRegEditor(UString &path); +void SaveRegEditor(bool useEditor, const UString &path); +void ReadRegEditor(bool useEditor, UString &path); void SaveRegDiff(const UString &path); void ReadRegDiff(UString &path); @@ -21,8 +21,8 @@ bool ReadShowDots(); void SaveShowRealFileIcons(bool show); bool ReadShowRealFileIcons(); -void SaveShowSystemMenu(bool showSystemMenu); -bool ReadShowSystemMenu(); +void Save_ShowSystemMenu(bool showSystemMenu); +bool Read_ShowSystemMenu(); void SaveFullRow(bool enable); bool ReadFullRow(); @@ -50,4 +50,9 @@ bool ReadUnderline(); void SaveFlatView(UInt32 panelIndex, bool enable); bool ReadFlatView(UInt32 panelIndex); +/* +void Save_ShowDeleted(bool enable); +bool Read_ShowDeleted(); +*/ + #endif diff --git a/CPP/7zip/UI/FileManager/RootFolder.cpp b/CPP/7zip/UI/FileManager/RootFolder.cpp old mode 100755 new mode 100644 index a81f94c1..234c51dd --- a/CPP/7zip/UI/FileManager/RootFolder.cpp +++ b/CPP/7zip/UI/FileManager/RootFolder.cpp @@ -2,10 +2,11 @@ #include "StdAfx.h" -#include "Common/StringConvert.h" +#include "../../../Common/StringConvert.h" -#include "Windows/DLL.h" -#include "Windows/PropVariant.h" +#include "../../../Windows/DLL.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/PropVariant.h" #include "../../PropID.h" @@ -22,9 +23,9 @@ using namespace NWindows; -static const STATPROPSTG kProps[] = +static const PROPID kProps[] = { - { NULL, kpidName, VT_BSTR} + kpidName }; UString RootFolder_GetName_Computer(int &iconIndex) @@ -34,19 +35,19 @@ UString RootFolder_GetName_Computer(int &iconIndex) #else iconIndex = GetIconIndexForCSIDL(CSIDL_DRIVES); #endif - return LangString(IDS_COMPUTER, 0x03020300); + return LangString(IDS_COMPUTER); } UString RootFolder_GetName_Network(int &iconIndex) { iconIndex = GetIconIndexForCSIDL(CSIDL_NETWORK); - return LangString(IDS_NETWORK, 0x03020301); + return LangString(IDS_NETWORK); } UString RootFolder_GetName_Documents(int &iconIndex) { iconIndex = GetIconIndexForCSIDL(CSIDL_PERSONAL); - return LangString(IDS_DOCUMENTS, 0x03020302); ; + return LangString(IDS_DOCUMENTS); } enum @@ -123,7 +124,7 @@ UString GetMyDocsPath() us = GetUnicodeString(s2); } #endif - if (us.Length() > 0 && us.Back() != WCHAR_PATH_SEPARATOR) + if (us.Len() > 0 && us.Back() != WCHAR_PATH_SEPARATOR) us += WCHAR_PATH_SEPARATOR; return us; } @@ -169,9 +170,14 @@ STDMETHODIMP CRootFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolde return S_OK; } -static bool AreEqualNames(const UString &name1, const UString &name2) +static bool AreEqualNames(const UString &path, const wchar_t *name) { - return (name1 == name2 || name1 == (name2 + UString(WCHAR_PATH_SEPARATOR))); + unsigned len = MyStringLen(name); + if (len > path.Len() || len + 1 < path.Len()) + return false; + if (len + 1 == path.Len() && path[len] != WCHAR_PATH_SEPARATOR) + return false; + return path.IsPrefixedBy(name); } STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder) @@ -208,22 +214,28 @@ STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resu return S_OK; } - if (name2.Length () < 2) + if (name2.Len() < 2) return E_INVALIDARG; CMyComPtr subFolder; #ifndef UNDER_CE - if (name2.Left(4) == kVolPrefix) + if (name2.IsPrefixedBy(kVolPrefix)) { CFSDrives *folderSpec = new CFSDrives; subFolder = folderSpec; folderSpec->Init(true); } + else if (name2 == NFile::NName::kSuperPathPrefix) + { + CFSDrives *folderSpec = new CFSDrives; + subFolder = folderSpec; + folderSpec->Init(false, true); + } else #endif { - if (name2[name2.Length () - 1] != WCHAR_PATH_SEPARATOR) + if (name2[name2.Len() - 1] != WCHAR_PATH_SEPARATOR) name2 += WCHAR_PATH_SEPARATOR; NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder; subFolder = fsFolderSpec; diff --git a/CPP/7zip/UI/FileManager/RootFolder.h b/CPP/7zip/UI/FileManager/RootFolder.h old mode 100755 new mode 100644 index 21d74db8..e9ef2d8c --- a/CPP/7zip/UI/FileManager/RootFolder.h +++ b/CPP/7zip/UI/FileManager/RootFolder.h @@ -3,7 +3,7 @@ #ifndef __ROOT_FOLDER_H #define __ROOT_FOLDER_H -#include "Common/MyString.h" +#include "../../../Common/MyString.h" #include "IFolder.h" diff --git a/CPP/7zip/UI/FileManager/SettingsPage.cpp b/CPP/7zip/UI/FileManager/SettingsPage.cpp old mode 100755 new mode 100644 index 866b0b2d..7a51e1b7 --- a/CPP/7zip/UI/FileManager/SettingsPage.cpp +++ b/CPP/7zip/UI/FileManager/SettingsPage.cpp @@ -2,10 +2,10 @@ #include "StdAfx.h" -#include "Common/StringConvert.h" +#include "../../../Common/StringConvert.h" #ifndef UNDER_CE -#include "Windows/MemoryLock.h" +#include "../../../Windows/MemoryLock.h" #endif #include "HelpUtils.h" @@ -17,17 +17,16 @@ using namespace NWindows; -static CIDLangPair kIDLangPairs[] = +static const UInt32 kLangIDs[] = { - { 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} + IDX_SETTINGS_SHOW_DOTS, + IDX_SETTINGS_SHOW_REAL_FILE_ICONS, + IDX_SETTINGS_SHOW_SYSTEM_MENU, + IDX_SETTINGS_FULL_ROW, + IDX_SETTINGS_SHOW_GRID, + IDX_SETTINGS_SINGLE_CLICK, + IDX_SETTINGS_ALTERNATIVE_SELECTION, + IDX_SETTINGS_LARGE_PAGES }; static LPCWSTR kEditTopic = L"FM/options.htm#settings"; @@ -36,21 +35,20 @@ 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()); + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); + + CheckButton(IDX_SETTINGS_SHOW_DOTS, ReadShowDots()); + CheckButton(IDX_SETTINGS_SHOW_SYSTEM_MENU, Read_ShowSystemMenu()); + CheckButton(IDX_SETTINGS_SHOW_REAL_FILE_ICONS, ReadShowRealFileIcons()); + CheckButton(IDX_SETTINGS_FULL_ROW, ReadFullRow()); + CheckButton(IDX_SETTINGS_SHOW_GRID, ReadShowGrid()); + CheckButton(IDX_SETTINGS_ALTERNATIVE_SELECTION, ReadAlternativeSelection()); if (IsLargePageSupported()) - CheckButton(IDC_SETTINGS_LARGE_PAGES, ReadLockMemoryEnable()); + CheckButton(IDX_SETTINGS_LARGE_PAGES, ReadLockMemoryEnable()); else - EnableItem(IDC_SETTINGS_LARGE_PAGES, false); - CheckButton(IDC_SETTINGS_SINGLE_CLICK, ReadSingleClick()); - // CheckButton(IDC_SETTINGS_UNDERLINE, ReadUnderline()); + EnableItem(IDX_SETTINGS_LARGE_PAGES, false); + CheckButton(IDX_SETTINGS_SINGLE_CLICK, ReadSingleClick()); + // CheckButton(IDX_SETTINGS_UNDERLINE, ReadUnderline()); // EnableSubItems(); @@ -60,30 +58,30 @@ bool CSettingsPage::OnInit() /* void CSettingsPage::EnableSubItems() { - EnableItem(IDC_SETTINGS_UNDERLINE, IsButtonCheckedBool(IDC_SETTINGS_SINGLE_CLICK)); + EnableItem(IDX_SETTINGS_UNDERLINE, IsButtonCheckedBool(IDX_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)); + SaveShowDots(IsButtonCheckedBool(IDX_SETTINGS_SHOW_DOTS)); + Save_ShowSystemMenu(IsButtonCheckedBool(IDX_SETTINGS_SHOW_SYSTEM_MENU)); + SaveShowRealFileIcons(IsButtonCheckedBool(IDX_SETTINGS_SHOW_REAL_FILE_ICONS)); - SaveFullRow(IsButtonCheckedBool(IDC_SETTINGS_FULL_ROW)); - SaveShowGrid(IsButtonCheckedBool(IDC_SETTINGS_SHOW_GRID)); - SaveAlternativeSelection(IsButtonCheckedBool(IDC_SETTINGS_ALTERNATIVE_SELECTION)); + SaveFullRow(IsButtonCheckedBool(IDX_SETTINGS_FULL_ROW)); + SaveShowGrid(IsButtonCheckedBool(IDX_SETTINGS_SHOW_GRID)); + SaveAlternativeSelection(IsButtonCheckedBool(IDX_SETTINGS_ALTERNATIVE_SELECTION)); #ifndef UNDER_CE if (IsLargePageSupported()) { - bool enable = IsButtonCheckedBool(IDC_SETTINGS_LARGE_PAGES); - NSecurity::EnableLockMemoryPrivilege(enable); + bool enable = IsButtonCheckedBool(IDX_SETTINGS_LARGE_PAGES); + NSecurity::EnablePrivilege_LockMemory(enable); SaveLockMemoryEnable(enable); } #endif - SaveSingleClick(IsButtonCheckedBool(IDC_SETTINGS_SINGLE_CLICK)); - // SaveUnderline(IsButtonCheckedBool(IDC_SETTINGS_UNDERLINE)); + SaveSingleClick(IsButtonCheckedBool(IDX_SETTINGS_SINGLE_CLICK)); + // SaveUnderline(IsButtonCheckedBool(IDX_SETTINGS_UNDERLINE)); return PSNRET_NOERROR; } @@ -97,18 +95,18 @@ bool CSettingsPage::OnButtonClicked(int buttonID, HWND buttonHWND) { switch(buttonID) { - case IDC_SETTINGS_SINGLE_CLICK: + case IDX_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: + case IDX_SETTINGS_SHOW_DOTS: + case IDX_SETTINGS_SHOW_SYSTEM_MENU: + case IDX_SETTINGS_SHOW_REAL_FILE_ICONS: + case IDX_SETTINGS_FULL_ROW: + case IDX_SETTINGS_SHOW_GRID: + case IDX_SETTINGS_ALTERNATIVE_SELECTION: + case IDX_SETTINGS_LARGE_PAGES: Changed(); return true; } diff --git a/CPP/7zip/UI/FileManager/SettingsPage.h b/CPP/7zip/UI/FileManager/SettingsPage.h old mode 100755 new mode 100644 index e5fe6e67..e7e5d73e --- a/CPP/7zip/UI/FileManager/SettingsPage.h +++ b/CPP/7zip/UI/FileManager/SettingsPage.h @@ -1,10 +1,10 @@ // SettingsPage.h -#ifndef __SETTINGSPAGE_H -#define __SETTINGSPAGE_H +#ifndef __SETTINGS_PAGE_H +#define __SETTINGS_PAGE_H -#include "Windows/Control/PropertyPage.h" -#include "Windows/Control/Edit.h" +#include "../../../Windows/Control/PropertyPage.h" +#include "../../../Windows/Control/Edit.h" class CSettingsPage: public NWindows::NControl::CPropertyPage { diff --git a/CPP/7zip/UI/FileManager/SettingsPage.rc b/CPP/7zip/UI/FileManager/SettingsPage.rc old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/SettingsPage2.rc b/CPP/7zip/UI/FileManager/SettingsPage2.rc old mode 100755 new mode 100644 index c920120e..66629612 --- a/CPP/7zip/UI/FileManager/SettingsPage2.rc +++ b/CPP/7zip/UI/FileManager/SettingsPage2.rc @@ -1,24 +1,11 @@ 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 +BEGIN + CONTROL "Show "".."" item", IDX_SETTINGS_SHOW_DOTS, MY_CHECKBOX, m, 8, xc, 10 + CONTROL "Show real file &icons", IDX_SETTINGS_SHOW_REAL_FILE_ICONS, MY_CHECKBOX, m, 22, xc, 10 + CONTROL "Show system &menu", IDX_SETTINGS_SHOW_SYSTEM_MENU, MY_CHECKBOX, m, 36, xc, 10 + CONTROL "&Full row select", IDX_SETTINGS_FULL_ROW, MY_CHECKBOX, m, 50, xc, 10 + CONTROL "Show &grid lines", IDX_SETTINGS_SHOW_GRID, MY_CHECKBOX, m, 64, xc, 10 + CONTROL "&Single-click to open an item", IDX_SETTINGS_SINGLE_CLICK, MY_CHECKBOX, m, 78, xc, 10 + CONTROL "&Alternative selection mode", IDX_SETTINGS_ALTERNATIVE_SELECTION, MY_CHECKBOX, m, 92, xc, 10 + CONTROL "Use &large memory pages", IDX_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 old mode 100755 new mode 100644 index b6c7f5cc..71204597 --- a/CPP/7zip/UI/FileManager/SettingsPageRes.h +++ b/CPP/7zip/UI/FileManager/SettingsPageRes.h @@ -1,13 +1,11 @@ -#define IDD_SETTINGS 543 -#define IDD_SETTINGS_2 643 +#define IDD_SETTINGS 2500 +#define IDD_SETTINGS_2 12500 -#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 +#define IDX_SETTINGS_SHOW_DOTS 2501 +#define IDX_SETTINGS_SHOW_REAL_FILE_ICONS 2502 +#define IDX_SETTINGS_SHOW_SYSTEM_MENU 2503 +#define IDX_SETTINGS_FULL_ROW 2504 +#define IDX_SETTINGS_SHOW_GRID 2505 +#define IDX_SETTINGS_SINGLE_CLICK 2506 +#define IDX_SETTINGS_ALTERNATIVE_SELECTION 2507 +#define IDX_SETTINGS_LARGE_PAGES 2508 diff --git a/CPP/7zip/UI/FileManager/SplitDialog.cpp b/CPP/7zip/UI/FileManager/SplitDialog.cpp old mode 100755 new mode 100644 index 5dca8e48..d35d76c9 --- a/CPP/7zip/UI/FileManager/SplitDialog.cpp +++ b/CPP/7zip/UI/FileManager/SplitDialog.cpp @@ -2,7 +2,7 @@ #include "StdAfx.h" -#include "Windows/FileName.h" +#include "../../../Windows/FileName.h" #ifdef LANG #include "LangUtils.h" @@ -17,10 +17,10 @@ using namespace NWindows; #ifdef LANG -static CIDLangPair kIDLangPairs[] = +static const UInt32 kLangIDs[] = { - { IDC_STATIC_SPLIT_PATH, 0x03020501 }, - { IDC_STATIC_SPLIT_VOLUME, 0x02000D40 }, + IDT_SPLIT_PATH, + IDT_SPLIT_VOLUME }; #endif @@ -28,11 +28,11 @@ static CIDLangPair kIDLangPairs[] = bool CSplitDialog::OnInit() { #ifdef LANG - LangSetWindowText(HWND(*this), 0x03020500); - LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + LangSetWindowText(*this, IDD_SPLIT); + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); #endif - _pathCombo.Attach(GetItem(IDC_COMBO_SPLIT_PATH)); - _volumeCombo.Attach(GetItem(IDC_COMBO_SPLIT_VOLUME)); + _pathCombo.Attach(GetItem(IDC_SPLIT_PATH)); + _volumeCombo.Attach(GetItem(IDC_SPLIT_VOLUME)); if (!FilePath.IsEmpty()) { @@ -62,10 +62,10 @@ bool CSplitDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) 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); + RECT r; + GetClientRectOfItem(IDB_SPLIT_PATH, r); + int bx = RECT_SIZE_X(r); + MoveItem(IDB_SPLIT_PATH, xSize - mx - bx, r.top, bx, RECT_SIZE_Y(r)); ChangeSubWindowSizeX(_pathCombo, xSize - mx - mx - bx - mx); } @@ -79,7 +79,7 @@ bool CSplitDialog::OnButtonClicked(int buttonID, HWND buttonHWND) { switch(buttonID) { - case IDC_BUTTON_SPLIT_PATH: + case IDB_SPLIT_PATH: OnButtonSetPath(); return true; } @@ -91,10 +91,10 @@ 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 title = LangString(IDS_SET_FOLDER); UString resultPath; - if (!MyBrowseForFolder(HWND(*this), title, currentPath, resultPath)) + if (!MyBrowseForFolder(*this, title, currentPath, resultPath)) return; NFile::NName::NormalizeDirPathPrefix(resultPath); _pathCombo.SetCurSel(-1); @@ -109,7 +109,7 @@ void CSplitDialog::OnOK() volumeString.Trim(); if (!ParseVolumeSizes(volumeString, VolumeSizes) || VolumeSizes.Size() == 0) { - ::MessageBoxW(*this, LangString(IDS_INCORRECT_VOLUME_SIZE, 0x02000D41), L"7-Zip", 0); + ::MessageBoxW(*this, LangString(IDS_INCORRECT_VOLUME_SIZE), L"7-Zip", MB_ICONERROR); return; } CModalDialog::OnOK(); diff --git a/CPP/7zip/UI/FileManager/SplitDialog.h b/CPP/7zip/UI/FileManager/SplitDialog.h old mode 100755 new mode 100644 index 33fb64e7..00aae658 --- a/CPP/7zip/UI/FileManager/SplitDialog.h +++ b/CPP/7zip/UI/FileManager/SplitDialog.h @@ -3,8 +3,8 @@ #ifndef __SPLIT_DIALOG_H #define __SPLIT_DIALOG_H -#include "Windows/Control/Dialog.h" -#include "Windows/Control/ComboBox.h" +#include "../../../Windows/Control/Dialog.h" +#include "../../../Windows/Control/ComboBox.h" #include "SplitDialogRes.h" @@ -22,7 +22,7 @@ public: UString Path; CRecordVector VolumeSizes; INT_PTR Create(HWND parentWindow = 0) - { return CModalDialog::Create(IDD_DIALOG_SPLIT, parentWindow); } + { return CModalDialog::Create(IDD_SPLIT, parentWindow); } }; #endif diff --git a/CPP/7zip/UI/FileManager/SplitDialog.rc b/CPP/7zip/UI/FileManager/SplitDialog.rc old mode 100755 new mode 100644 index e977d651..5a026e8a --- a/CPP/7zip/UI/FileManager/SplitDialog.rc +++ b/CPP/7zip/UI/FileManager/SplitDialog.rc @@ -4,13 +4,13 @@ #define xc 288 #define yc 96 -IDD_DIALOG_SPLIT MY_RESIZE_DIALOG +IDD_SPLIT DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT 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 + LTEXT "&Split to:", IDT_SPLIT_PATH, m, m, xc, 8 + COMBOBOX IDC_SPLIT_PATH, m, 20, xc - bxsDots - m, 64, MY_COMBO_WITH_EDIT + PUSHBUTTON "...", IDB_SPLIT_PATH, xs - m - bxsDots, 18, bxsDots, bys, WS_GROUP + LTEXT "Split to &volumes, bytes:", IDT_SPLIT_VOLUME, m, 44, xc, 8 + COMBOBOX IDC_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 old mode 100755 new mode 100644 index a6f06d1c..50584a14 --- a/CPP/7zip/UI/FileManager/SplitDialogRes.h +++ b/CPP/7zip/UI/FileManager/SplitDialogRes.h @@ -1,7 +1,8 @@ -#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 +#define IDD_SPLIT 7300 +#define IDT_SPLIT_PATH 7301 +#define IDT_SPLIT_VOLUME 7302 + +#define IDC_SPLIT_PATH 100 +#define IDB_SPLIT_PATH 101 +#define IDC_SPLIT_VOLUME 102 diff --git a/CPP/7zip/UI/FileManager/SplitUtils.cpp b/CPP/7zip/UI/FileManager/SplitUtils.cpp old mode 100755 new mode 100644 index 8bae0573..b0172a9f --- a/CPP/7zip/UI/FileManager/SplitUtils.cpp +++ b/CPP/7zip/UI/FileManager/SplitUtils.cpp @@ -2,85 +2,86 @@ #include "StdAfx.h" -#include "Common/StringToInt.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++) + for (unsigned i = 0; i < s.Len();) { - UString subString = destStrings[i]; - subString.MakeUpper(); - if (subString.IsEmpty()) - return false; - if (subString == L"-") + wchar_t c = s[i++]; + if (c == L' ') + continue; + if (c == L'-') return true; if (prevIsNumber) { - wchar_t c = subString[0]; - UInt64 &value = values.Back(); prevIsNumber = false; - switch(c) + unsigned numBits = 0; + switch (MyCharLower_Ascii(c)) + { + case 'b': continue; + case 'k': numBits = 10; break; + case 'm': numBits = 20; break; + case 'g': numBits = 30; break; + case 't': numBits = 40; break; + } + if (numBits != 0) { - case L'B': - continue; - case L'K': - value <<= 10; - continue; - case L'M': - value <<= 20; - continue; - case L'G': - value <<= 30; - continue; + UInt64 &val = values.Back(); + if (val >= ((UInt64)1 << (64 - numBits))) + return false; + val <<= numBits; + + for (; i < s.Len(); i++) + if (s[i] == L' ') + break; + continue; } } - const wchar_t *start = subString; + i--; + const wchar_t *start = s.Ptr(i); const wchar_t *end; - UInt64 value = ConvertStringToUInt64(start, &end); + UInt64 val = ConvertStringToUInt64(start, &end); if (start == end) return false; - if (value == 0) + if (val == 0) return false; - values.Add(value); + values.Add(val); prevIsNumber = true; - UString rem = subString.Mid((int)(end - start)); - if (!rem.IsEmpty()) - destStrings.Insert(i + 1, rem); + i += (unsigned)(end - start); } return true; } -void AddVolumeItems(NWindows::NControl::CComboBox &volumeCombo) +void AddVolumeItems(NWindows::NControl::CComboBox &combo) { - 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")); + combo.AddString(TEXT("10M")); + combo.AddString(TEXT("650M - CD")); + combo.AddString(TEXT("700M - CD")); + combo.AddString(TEXT("4092M - FAT")); + combo.AddString(TEXT("4480M - DVD")); // 4489 MiB limit + combo.AddString(TEXT("8128M - DVD DL")); // 8147 MiB limit + combo.AddString(TEXT("23040M - BD")); // 23866 MiB limit + combo.AddString(TEXT("1457664 - 3.5\" floppy")); } -UInt64 GetNumberOfVolumes(UInt64 size, CRecordVector &volSizes) +UInt64 GetNumberOfVolumes(UInt64 size, const CRecordVector &volSizes) { if (size == 0 || volSizes.Size() == 0) return 1; - UInt64 numVolumes = 0; - for (int i = 0; i < volSizes.Size(); i++) + FOR_VECTOR (i, volSizes) { UInt64 volSize = volSizes[i]; - numVolumes++; if (volSize >= size) - return numVolumes; + return i + 1; size -= volSize; } UInt64 volSize = volSizes.Back(); if (volSize == 0) return (UInt64)(Int64)-1; - return numVolumes + (size - 1) / volSize + 1; + return volSizes.Size() + (size - 1) / volSize + 1; } diff --git a/CPP/7zip/UI/FileManager/SplitUtils.h b/CPP/7zip/UI/FileManager/SplitUtils.h old mode 100755 new mode 100644 index 755c707c..641dfe6b --- a/CPP/7zip/UI/FileManager/SplitUtils.h +++ b/CPP/7zip/UI/FileManager/SplitUtils.h @@ -1,15 +1,15 @@ // SplitUtils.h -#ifndef __SPLITUTILS_H -#define __SPLITUTILS_H +#ifndef __SPLIT_UTILS_H +#define __SPLIT_UTILS_H -#include "Common/MyString.h" -#include "Common/Types.h" -#include "Windows/Control/ComboBox.h" +#include "../../../Common/MyTypes.h" +#include "../../../Common/MyString.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); +UInt64 GetNumberOfVolumes(UInt64 size, const CRecordVector &volSizes); #endif diff --git a/CPP/7zip/UI/FileManager/StdAfx.cpp b/CPP/7zip/UI/FileManager/StdAfx.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/StdAfx.h b/CPP/7zip/UI/FileManager/StdAfx.h old mode 100755 new mode 100644 index b09de592..85389112 --- a/CPP/7zip/UI/FileManager/StdAfx.h +++ b/CPP/7zip/UI/FileManager/StdAfx.h @@ -3,21 +3,17 @@ #ifndef __STDAFX_H #define __STDAFX_H -#define _WIN32_WINNT 0x0400 +/* we used 0x0400 for Windows NT supporting (MENUITEMINFOW) + But now menu problem is fixed. So it's OK to use 0x0500 (Windows 2000) */ -// it's for Windows NT supporting (MENUITEMINFOW) -#define WINVER 0x0400 +// #define _WIN32_WINNT 0x0400 +#define _WIN32_WINNT 0x0500 +#define WINVER _WIN32_WINNT + +#include "../../../Common/Common.h" -#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 old mode 100755 new mode 100644 index bddaa971..fb38a735 --- a/CPP/7zip/UI/FileManager/StringUtils.cpp +++ b/CPP/7zip/UI/FileManager/StringUtils.cpp @@ -9,8 +9,8 @@ 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++) + unsigned i; + for (i = 0; i < src.Len(); i++) { wchar_t c = src[i]; if (c == L'\"') @@ -26,43 +26,42 @@ void SplitStringToTwoStrings(const UString &src, UString &dest1, UString &dest2) else dest1 += c; } - dest2 = src.Mid(i); + dest2 = src.Ptr(i); } void SplitString(const UString &srcString, UStringVector &destStrings) { destStrings.Clear(); - UString string; - int len = srcString.Length(); + unsigned len = srcString.Len(); if (len == 0) return; - for (int i = 0; i < len; i++) + UString s; + for (unsigned i = 0; i < len; i++) { wchar_t c = srcString[i]; if (c == L' ') { - if (!string.IsEmpty()) + if (!s.IsEmpty()) { - destStrings.Add(string); - string.Empty(); + destStrings.Add(s); + s.Empty(); } } else - string += c; + s += c; } - if (!string.IsEmpty()) - destStrings.Add(string); + if (!s.IsEmpty()) + destStrings.Add(s); } UString JoinStrings(const UStringVector &srcStrings) { - UString destString; - for (int i = 0; i < srcStrings.Size(); i++) + UString s; + FOR_VECTOR (i, srcStrings) { if (i != 0) - destString += L' '; - destString += srcStrings[i]; + s += L' '; + s += srcStrings[i]; } - return destString; + return s; } - diff --git a/CPP/7zip/UI/FileManager/StringUtils.h b/CPP/7zip/UI/FileManager/StringUtils.h old mode 100755 new mode 100644 index 7f72b764..fc070de1 --- a/CPP/7zip/UI/FileManager/StringUtils.h +++ b/CPP/7zip/UI/FileManager/StringUtils.h @@ -1,9 +1,9 @@ // StringUtils.h -#ifndef __STRINGUTILS_H -#define __STRINGUTILS_H +#ifndef __STRING_UTILS_H +#define __STRING_UTILS_H -#include "Common/MyString.h" +#include "../../../Common/MyString.h" void SplitStringToTwoStrings(const UString &src, UString &dest1, UString &dest2); diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.cpp b/CPP/7zip/UI/FileManager/SysIconUtils.cpp old mode 100755 new mode 100644 index e537621e..2c35c191 --- a/CPP/7zip/UI/FileManager/SysIconUtils.cpp +++ b/CPP/7zip/UI/FileManager/SysIconUtils.cpp @@ -3,9 +3,11 @@ #include "StdAfx.h" #ifndef _UNICODE -#include "Common/StringConvert.h" +#include "../../../Common/StringConvert.h" #endif +#include "../../../Windows/FileDir.h" + #include "SysIconUtils.h" #ifndef _UNICODE @@ -51,13 +53,13 @@ struct CSHGetFileInfoInit static DWORD_PTR MySHGetFileInfoW(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags) { #ifdef _UNICODE - return SHGetFileInfo( + return SHGetFileInfo #else if (g_SHGetFileInfoInit.shGetFileInfoW == 0) return 0; - return g_SHGetFileInfoInit.shGetFileInfoW( + return g_SHGetFileInfoInit.shGetFileInfoW #endif - pszPath, attrib, psfi, cbFileInfo, uFlags); + (pszPath, attrib, psfi, cbFileInfo, uFlags); } DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex) @@ -82,7 +84,8 @@ DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex) } } -DWORD_PTR GetRealIconIndex(const UString &fileName, DWORD attrib, int &iconIndex, UString &typeName) +/* +DWORD_PTR GetRealIconIndex(const UString &fileName, DWORD attrib, int &iconIndex, UString *typeName) { #ifndef _UNICODE if (!g_IsNT) @@ -91,7 +94,8 @@ DWORD_PTR GetRealIconIndex(const UString &fileName, DWORD attrib, int &iconIndex 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); + if (typeName) + *typeName = GetUnicodeString(shellInfo.szTypeName); iconIndex = shellInfo.iIcon; return res; } @@ -102,52 +106,148 @@ DWORD_PTR GetRealIconIndex(const UString &fileName, DWORD attrib, int &iconIndex 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; + if (typeName) + *typeName = shellInfo.szTypeName; iconIndex = shellInfo.iIcon; return res; } } +*/ -int CExtToIconMap::GetIconIndex(DWORD attrib, const UString &fileName, UString &typeName) +static int FindInSorted_Attrib(const CRecordVector &vect, DWORD attrib, int &insertPos) { - int dotPos = fileName.ReverseFind(L'.'); + unsigned left = 0, right = vect.Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + DWORD midAttrib = vect[mid].Attrib; + if (attrib == midAttrib) + return mid; + if (attrib < midAttrib) + right = mid; + else + left = mid + 1; + } + insertPos = left; + return -1; +} + +static int FindInSorted_Ext(const CObjectVector &vect, const wchar_t *ext, int &insertPos) +{ + unsigned left = 0, right = vect.Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + int compare = MyStringCompareNoCase(ext, vect[mid].Ext); + if (compare == 0) + return mid; + if (compare < 0) + right = mid; + else + left = mid + 1; + } + insertPos = left; + return -1; +} + +int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UString *typeName */) +{ + int dotPos = -1; + unsigned i; + for (i = 0;; i++) + { + wchar_t c = fileName[i]; + if (c == 0) + break; + if (c == '.') + dotPos = i; + } + + /* + if (MyStringCompareNoCase(fileName, L"$Recycle.Bin") == 0) + { + char s[256]; + sprintf(s, "SPEC i = %3d, attr = %7x", _attribMap.Size(), attrib); + OutputDebugStringA(s); + OutputDebugStringW(fileName); + } + */ + if ((attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 || dotPos < 0) { - CAttribIconPair pair; - pair.Attrib = attrib; - int index = _attribMap.FindInSorted(pair); + int insertPos = 0; + int index = FindInSorted_Attrib(_attribMap, attrib, insertPos); if (index >= 0) { - typeName = _attribMap[index].TypeName; + // if (typeName) *typeName = _attribMap[index].TypeName; return _attribMap[index].IconIndex; } + CAttribIconPair pair; GetRealIconIndex( #ifdef UNDER_CE - L"\\" + FTEXT("\\") #endif - L"__File__" - , attrib, pair.IconIndex, pair.TypeName); - _attribMap.AddToSorted(pair); - typeName = pair.TypeName; + FTEXT("__DIR__") + , attrib, pair.IconIndex + // , pair.TypeName + ); + + /* + char s[256]; + sprintf(s, "i = %3d, attr = %7x", _attribMap.Size(), attrib); + OutputDebugStringA(s); + */ + + pair.Attrib = attrib; + _attribMap.Insert(insertPos, pair); + // if (typeName) *typeName = pair.TypeName; return pair.IconIndex; } - CExtIconPair pair; - pair.Ext = fileName.Mid(dotPos + 1); - int index = _extMap.FindInSorted(pair); + const wchar_t *ext = fileName + dotPos + 1; + int insertPos = 0; + int index = FindInSorted_Ext(_extMap, ext, insertPos); if (index >= 0) { - typeName = _extMap[index].TypeName; - return _extMap[index].IconIndex; + const CExtIconPair &pa = _extMap[index]; + // if (typeName) *typeName = pa.TypeName; + return pa.IconIndex; + } + + for (i = 0;; i++) + { + wchar_t c = ext[i]; + if (c == 0) + break; + if (c < L'0' || c > L'9') + break; + } + if (i != 0 && ext[i] == 0) + { + // GetRealIconIndex is too slow for big number of split extensions: .001, .002, .003 + if (!SplitIconIndex_Defined) + { + GetRealIconIndex( + #ifdef UNDER_CE + FTEXT("\\") + #endif + FTEXT("__FILE__.001"), 0, SplitIconIndex); + SplitIconIndex_Defined = true; + } + return SplitIconIndex; } - GetRealIconIndex(fileName.Mid(dotPos), attrib, pair.IconIndex, pair.TypeName); - _extMap.AddToSorted(pair); - typeName = pair.TypeName; + + CExtIconPair pair; + pair.Ext = ext; + GetRealIconIndex(us2fs(fileName + dotPos), attrib, pair.IconIndex); + _extMap.Insert(insertPos, pair); + // if (typeName) *typeName = pair.TypeName; return pair.IconIndex; } +/* int CExtToIconMap::GetIconIndex(DWORD attrib, const UString &fileName) { - UString typeName; - return GetIconIndex(attrib, fileName, typeName); + return GetIconIndex(attrib, fileName, NULL); } +*/ \ No newline at end of file diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.h b/CPP/7zip/UI/FileManager/SysIconUtils.h old mode 100755 new mode 100644 index 129de781..20199acb --- a/CPP/7zip/UI/FileManager/SysIconUtils.h +++ b/CPP/7zip/UI/FileManager/SysIconUtils.h @@ -3,40 +3,44 @@ #ifndef __SYS_ICON_UTILS_H #define __SYS_ICON_UTILS_H -#include "Common/MyString.h" +#include "../../../Common/MyString.h" struct CExtIconPair { UString Ext; int IconIndex; - UString TypeName; + // UString TypeName; + + // int Compare(const CExtIconPair &a) const { return MyStringCompareNoCase(Ext, a.Ext); } }; struct CAttribIconPair { DWORD Attrib; int IconIndex; - UString TypeName; -}; + // 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; } + // int Compare(const CAttribIconPair &a) const { return Ext.Compare(a.Ext); } +}; class CExtToIconMap { - CObjectVector _extMap; - CObjectVector _attribMap; public: + CRecordVector _attribMap; + CObjectVector _extMap; + int SplitIconIndex; + int SplitIconIndex_Defined; + + CExtToIconMap(): SplitIconIndex_Defined(false) {} + void Clear() { + SplitIconIndex_Defined = false; _extMap.Clear(); _attribMap.Clear(); } - int GetIconIndex(DWORD attrib, const UString &fileName, UString &typeName); - int GetIconIndex(DWORD attrib, const UString &fileName); + int GetIconIndex(DWORD attrib, const wchar_t *fileName /* , UString *typeName */); + // int GetIconIndex(DWORD attrib, const UString &fileName); }; DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex); diff --git a/CPP/7zip/UI/FileManager/SystemPage.cpp b/CPP/7zip/UI/FileManager/SystemPage.cpp old mode 100755 new mode 100644 index 359656ea..e4ac706d --- a/CPP/7zip/UI/FileManager/SystemPage.cpp +++ b/CPP/7zip/UI/FileManager/SystemPage.cpp @@ -2,10 +2,10 @@ #include "StdAfx.h" -#include "Common/StringConvert.h" +#include "../../../Common/StringConvert.h" -#include "Windows/DLL.h" -#include "Windows/Error.h" +#include "../../../Windows/DLL.h" +#include "../../../Windows/ErrorMsg.h" #include "HelpUtils.h" #include "IFolder.h" @@ -14,10 +14,11 @@ #include "SystemPage.h" #include "SystemPageRes.h" -static const CIDLangPair kIDLangPairs[] = +using namespace NWindows; + +static const UInt32 kLangIDs[] = { - { IDC_SYSTEM_STATIC_ASSOCIATE, 0x03010302} - // { IDC_SYSTEM_SELECT_ALL, 0x03000330} + IDT_SYSTEM_ASSOCIATE }; static LPCWSTR kSystemTopic = L"FM/options.htm#system"; @@ -80,7 +81,7 @@ void CSystemPage::ChangeState(int group, const CIntVector &indices) bool thereAreClearItems = false; int counters[3] = { 0, 0, 0 }; - int i; + unsigned i; for (i = 0; i < indices.Size(); i++) { const CModifiedExtInfo &mi = _items[GetRealIndex(indices[i])].Pair[group]; @@ -125,9 +126,9 @@ void CSystemPage::ChangeState(int group, const CIntVector &indices) bool CSystemPage::OnInit() { - LangSetDlgItemsText((HWND)*this, kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); - _listView.Attach(GetItem(IDC_SYSTEM_LIST_ASSOCIATE)); + _listView.Attach(GetItem(IDL_SYSTEM_ASSOCIATE)); _listView.SetUnicodeFormat(); DWORD newFlags = LVS_EX_FULLROWSELECT; _listView.SetExtendedListViewStyle(newFlags, newFlags); @@ -137,7 +138,7 @@ bool CSystemPage::OnInit() _listView.SetImageList(_imageList, LVSIL_SMALL); - _listView.InsertColumn(0, LangString(IDS_PROP_FILE_TYPE, 0x02000214), 72); + _listView.InsertColumn(0, LangString(IDS_PROP_FILE_TYPE), 72); CSysString s; @@ -172,7 +173,7 @@ bool CSystemPage::OnInit() _extDB.Read(); _items.Clear(); - for (int i = 0; i < _extDB.Exts.Size(); i++) + FOR_VECTOR (i, _extDB.Exts) { const CExtPlugins &extInfo = _extDB.Exts[i]; @@ -215,7 +216,7 @@ bool CSystemPage::OnInit() static UString GetProgramCommand() { - return L"\"" + fs2us(NWindows::NDLL::GetModuleDirPrefix()) + L"7zFM.exe\" \"%1\""; + return L"\"" + fs2us(NDLL::GetModuleDirPrefix()) + L"7zFM.exe\" \"%1\""; } LONG CSystemPage::OnApply() @@ -224,7 +225,7 @@ LONG CSystemPage::OnApply() LONG res = 0; - for (int listIndex = 0; listIndex < _extDB.Exts.Size(); listIndex++) + FOR_VECTOR (listIndex, _extDB.Exts) { int realIndex = GetRealIndex(listIndex); const CExtPlugins &extInfo = _extDB.Exts[realIndex]; @@ -260,7 +261,7 @@ LONG CSystemPage::OnApply() WasChanged = true; #endif if (res != 0) - MessageBoxW(*this, NWindows::NError::MyFormatMessageW(res), L"7-Zip", MB_ICONERROR); + MessageBoxW(*this, NError::MyFormatMessage(res), L"7-Zip", MB_ICONERROR); return PSNRET_NOERROR; } @@ -278,9 +279,9 @@ bool CSystemPage::OnButtonClicked(int buttonID, HWND buttonHWND) _listView.SelectAll(); return true; */ - case IDC_SYSTEM_BUTTON_CURRENT: - case IDC_SYSTEM_BUTTON_ALL: - ChangeState(buttonID == IDC_SYSTEM_BUTTON_CURRENT ? 0 : 1); + case IDB_SYSTEM_CURRENT: + case IDB_SYSTEM_ALL: + ChangeState(buttonID == IDB_SYSTEM_CURRENT ? 0 : 1); return true; } return CPropertyPage::OnButtonClicked(buttonID, buttonHWND); @@ -346,15 +347,15 @@ void CSystemPage::ChangeState(int group) while ((itemIndex = _listView.GetNextSelectedItem(itemIndex)) != -1) indices.Add(itemIndex); if (indices.IsEmpty()) - for (int i = 0; i < _items.Size(); i++) + FOR_VECTOR (i, _items) indices.Add(i); ChangeState(group, indices); } bool CSystemPage::OnListKeyDown(LPNMLVKEYDOWN keyDownInfo) { - bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0; - bool alt = (::GetKeyState(VK_MENU) & 0x8000) != 0; + bool ctrl = IsKeyDown(VK_CONTROL); + bool alt = IsKeyDown(VK_MENU); if (alt) return false; diff --git a/CPP/7zip/UI/FileManager/SystemPage.h b/CPP/7zip/UI/FileManager/SystemPage.h old mode 100755 new mode 100644 index a4b4ab92..0bf6aae7 --- a/CPP/7zip/UI/FileManager/SystemPage.h +++ b/CPP/7zip/UI/FileManager/SystemPage.h @@ -3,9 +3,9 @@ #ifndef __SYSTEM_PAGE_H #define __SYSTEM_PAGE_H -#include "Windows/Control/ImageList.h" -#include "Windows/Control/ListView.h" -#include "Windows/Control/PropertyPage.h" +#include "../../../Windows/Control/ImageList.h" +#include "../../../Windows/Control/ListView.h" +#include "../../../Windows/Control/PropertyPage.h" #include "FilePlugins.h" #include "RegistryAssociations.h" @@ -40,7 +40,7 @@ struct CModifiedExtInfo: public NRegistryAssoc::CShellExtInfo Other = true; if (IsIt7Zip()) { - Other7Zip = (iconPath.CompareNoCase(IconPath) != 0); + Other7Zip = !iconPath.IsEqualToNoCase(IconPath); if (!Other7Zip) { State = kExtState_7Zip; @@ -88,7 +88,11 @@ class CSystemPage: public NWindows::NControl::CPropertyPage NWindows::NControl::CImageList _imageList; NWindows::NControl::CListView _listView; - const HKEY GetHKey(int group) const + const HKEY GetHKey(int + #if NUM_EXT_GROUPS != 1 + group + #endif + ) const { #if NUM_EXT_GROUPS == 1 return HKEY_CLASSES_ROOT; diff --git a/CPP/7zip/UI/FileManager/SystemPage.rc b/CPP/7zip/UI/FileManager/SystemPage.rc old mode 100755 new mode 100644 index 49581c9b..42e72cf1 --- a/CPP/7zip/UI/FileManager/SystemPage.rc +++ b/CPP/7zip/UI/FileManager/SystemPage.rc @@ -4,16 +4,15 @@ #define xc 200 #define yc 250 -IDD_SYSTEM MY_PAGE +IDD_SYSTEM DIALOG 0, 0, xs, ys MY_PAGE_STYLE MY_FONT CAPTION "System" BEGIN - LTEXT "Associate 7-Zip with:", IDC_SYSTEM_STATIC_ASSOCIATE, m, m, xc, 8 - PUSHBUTTON "+", IDC_SYSTEM_BUTTON_CURRENT, 72, m + 12, 40, bys - PUSHBUTTON "+", IDC_SYSTEM_BUTTON_ALL, 140, m + 12, 40, bys - CONTROL "List1", IDC_SYSTEM_LIST_ASSOCIATE, "SysListView32", - LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, - m, m + 32, xc, (yc - m - 32 - 1) -; PUSHBUTTON "Select all", IDC_SYSTEM_SELECT_ALL, m, m + 12, 60, bys + LTEXT "Associate 7-Zip with:", IDT_SYSTEM_ASSOCIATE, m, m, xc, 8 + PUSHBUTTON "+", IDB_SYSTEM_CURRENT, 72, m + 12, 40, bys + PUSHBUTTON "+", IDB_SYSTEM_ALL, 140, m + 12, 40, bys + CONTROL "List1", IDL_SYSTEM_ASSOCIATE, "SysListView32", + LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, + m, m + 32, xc, (yc - m - 32 - 1) END #ifdef UNDER_CE @@ -26,21 +25,14 @@ END #define xc (SMALL_PAGE_SIZE_X + 8) #define yc (128 + 8) -IDD_SYSTEM_2 MY_PAGE +IDD_SYSTEM_2 DIALOG 0, 0, xs, ys MY_PAGE_STYLE MY_FONT CAPTION "System" BEGIN - LTEXT "Associate 7-Zip with:", IDC_SYSTEM_STATIC_ASSOCIATE, m, m, xc, 8 - PUSHBUTTON "+", IDC_SYSTEM_BUTTON_CURRENT, 60, m + 12, 40, bys - CONTROL "List1", IDC_SYSTEM_LIST_ASSOCIATE, "SysListView32", - LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, - m, m + 32, xc, (yc - m - 32 - 1 - 8) -; PUSHBUTTON "Select all", IDC_SYSTEM_SELECT_ALL, m, m + 12, 60, bys + LTEXT "Associate 7-Zip with:", IDT_SYSTEM_ASSOCIATE, m, m, xc, 8 + PUSHBUTTON "+", IDB_SYSTEM_CURRENT, 60, m + 12, 40, bys + CONTROL "List1", IDL_SYSTEM_ASSOCIATE, "SysListView32", + LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, + m, m + 32, xc, (yc - m - 32 - 1 - 8) END #endif - - -STRINGTABLE -BEGIN - IDS_PLUGIN "Plugin" -END diff --git a/CPP/7zip/UI/FileManager/SystemPageRes.h b/CPP/7zip/UI/FileManager/SystemPageRes.h old mode 100755 new mode 100644 index 133996e7..edc576f7 --- a/CPP/7zip/UI/FileManager/SystemPageRes.h +++ b/CPP/7zip/UI/FileManager/SystemPageRes.h @@ -1,10 +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 -#define IDC_SYSTEM_BUTTON_CURRENT 1024 -#define IDC_SYSTEM_BUTTON_ALL 1025 +#define IDD_SYSTEM 2200 +#define IDD_SYSTEM_2 12200 + +#define IDT_SYSTEM_ASSOCIATE 2201 + +#define IDL_SYSTEM_ASSOCIATE 100 +#define IDB_SYSTEM_CURRENT 101 +#define IDB_SYSTEM_ALL 102 diff --git a/CPP/7zip/UI/FileManager/Test.bmp b/CPP/7zip/UI/FileManager/Test.bmp old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/Test2.bmp b/CPP/7zip/UI/FileManager/Test2.bmp old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/FileManager/TextPairs.cpp b/CPP/7zip/UI/FileManager/TextPairs.cpp old mode 100755 new mode 100644 index cc57c0d5..354b479f --- a/CPP/7zip/UI/FileManager/TextPairs.cpp +++ b/CPP/7zip/UI/FileManager/TextPairs.cpp @@ -16,10 +16,10 @@ static bool IsSeparatorChar(wchar_t c) static void RemoveCr(UString &s) { - s.Replace(L"\x0D", L""); + s.RemoveChar(L'\x0D'); } -static UString GetIDString(const wchar_t *srcString, int &finishPos) +static UString GetIDString(const wchar_t *srcString, unsigned &finishPos) { UString result; bool quotes = false; @@ -43,7 +43,7 @@ static UString GetIDString(const wchar_t *srcString, int &finishPos) return result; } -static UString GetValueString(const wchar_t *srcString, int &finishPos) +static UString GetValueString(const wchar_t *srcString, unsigned &finishPos) { UString result; for (finishPos = 0;;) @@ -64,16 +64,16 @@ static UString GetValueString(const wchar_t *srcString, int &finishPos) static bool GetTextPairs(const UString &srcString, CObjectVector &pairs) { pairs.Clear(); - int pos = 0; + unsigned pos = 0; - if (srcString.Length() > 0) + if (srcString.Len() > 0) { if (srcString[0] == kBOM) pos++; } - while (pos < srcString.Length()) + while (pos < srcString.Len()) { - int finishPos; + unsigned finishPos; UString id = GetIDString((const wchar_t *)srcString + pos, finishPos); pos += finishPos; if (id.IsEmpty()) @@ -92,7 +92,8 @@ static bool GetTextPairs(const UString &srcString, CObjectVector &pai } static int ComparePairIDs(const UString &s1, const UString &s2) - { return s1.CompareNoCase(s2); } + { return MyStringCompareNoCase(s1, s2); } + static int ComparePairItems(const CTextPair &p1, const CTextPair &p2) { return ComparePairIDs(p1.ID, p2.ID); } @@ -101,7 +102,7 @@ static int ComparePairItems(void *const *a1, void *const *a2, void * /* param */ void CPairsStorage::Sort() { Pairs.Sort(ComparePairItems, 0); } -int CPairsStorage::FindID(const UString &id, int &insertPos) +int CPairsStorage::FindID(const UString &id, int &insertPos) const { int left = 0, right = Pairs.Size(); while (left != right) @@ -119,7 +120,7 @@ int CPairsStorage::FindID(const UString &id, int &insertPos) return -1; } -int CPairsStorage::FindID(const UString &id) +int CPairsStorage::FindID(const UString &id) const { int pos; return FindID(id, pos); @@ -142,7 +143,7 @@ void CPairsStorage::DeletePair(const UString &id) Pairs.Delete(pos); } -bool CPairsStorage::GetValue(const UString &id, UString &value) +bool CPairsStorage::GetValue(const UString &id, UString &value) const { value.Empty(); int pos = FindID(id); @@ -152,7 +153,7 @@ bool CPairsStorage::GetValue(const UString &id, UString &value) return true; } -UString CPairsStorage::GetValue(const UString &id) +UString CPairsStorage::GetValue(const UString &id) const { int pos = FindID(id); if (pos < 0) @@ -170,9 +171,9 @@ bool CPairsStorage::ReadFromString(const UString &text) return result; } -void CPairsStorage::SaveToString(UString &text) +void CPairsStorage::SaveToString(UString &text) const { - for (int i = 0; i < Pairs.Size(); i++) + FOR_VECTOR (i, Pairs) { const CTextPair &pair = Pairs[i]; bool multiWord = (pair.ID.Find(L' ') >= 0); diff --git a/CPP/7zip/UI/FileManager/TextPairs.h b/CPP/7zip/UI/FileManager/TextPairs.h old mode 100755 new mode 100644 index 2670e030..d27cd97c --- a/CPP/7zip/UI/FileManager/TextPairs.h +++ b/CPP/7zip/UI/FileManager/TextPairs.h @@ -3,7 +3,7 @@ #ifndef __FM_TEXT_PAIRS_H #define __FM_TEXT_PAIRS_H -#include "Common/MyString.h" +#include "../../../Common/MyString.h" struct CTextPair { @@ -14,16 +14,17 @@ struct CTextPair class CPairsStorage { CObjectVector Pairs; - int FindID(const UString &id, int &insertPos); - int FindID(const UString &id); + + int FindID(const UString &id, int &insertPos) const; + int FindID(const UString &id) const; void Sort(); public: void Clear() { Pairs.Clear(); }; bool ReadFromString(const UString &text); - void SaveToString(UString &text); + void SaveToString(UString &text) const; - bool GetValue(const UString &id, UString &value); - UString GetValue(const UString &id); + bool GetValue(const UString &id, UString &value) const; + UString GetValue(const UString &id) const; void AddPair(const CTextPair &pair); void DeletePair(const UString &id); }; diff --git a/CPP/7zip/UI/FileManager/UpdateCallback100.cpp b/CPP/7zip/UI/FileManager/UpdateCallback100.cpp old mode 100755 new mode 100644 index 43dfa4dc..4141f01d --- a/CPP/7zip/UI/FileManager/UpdateCallback100.cpp +++ b/CPP/7zip/UI/FileManager/UpdateCallback100.cpp @@ -7,51 +7,48 @@ STDMETHODIMP CUpdateCallback100Imp::SetNumFiles(UInt64 numFiles) { - ProgressDialog->Sync.SetNumFilesTotal(numFiles); + ProgressDialog->Sync.Set_NumFilesTotal(numFiles); return S_OK; } STDMETHODIMP CUpdateCallback100Imp::SetTotal(UInt64 size) { - ProgressDialog->Sync.SetProgress(size, 0); + ProgressDialog->Sync.Set_NumBytesTotal(size); return S_OK; } -STDMETHODIMP CUpdateCallback100Imp::SetCompleted(const UInt64 *completeValue) +STDMETHODIMP CUpdateCallback100Imp::SetCompleted(const UInt64 *completed) { - RINOK(ProgressDialog->Sync.ProcessStopAndPause()); - if (completeValue != NULL) - ProgressDialog->Sync.SetPos(*completeValue); - return S_OK; + return ProgressDialog->Sync.Set_NumBytesCur(completed); } STDMETHODIMP CUpdateCallback100Imp::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { - ProgressDialog->Sync.SetRatioInfo(inSize, outSize); + ProgressDialog->Sync.Set_Ratio(inSize, outSize); return S_OK; } STDMETHODIMP CUpdateCallback100Imp::CompressOperation(const wchar_t *name) { - ProgressDialog->Sync.SetCurrentFileName(name); + ProgressDialog->Sync.Set_FilePath(name); return S_OK; } STDMETHODIMP CUpdateCallback100Imp::DeleteOperation(const wchar_t *name) { - ProgressDialog->Sync.SetCurrentFileName(name); + ProgressDialog->Sync.Set_FilePath(name); return S_OK; } STDMETHODIMP CUpdateCallback100Imp::OperationResult(Int32 /* operationResult */) { - ProgressDialog->Sync.SetNumFilesCur(++_numFiles); + ProgressDialog->Sync.Set_NumFilesCur(++_numFiles); return S_OK; } STDMETHODIMP CUpdateCallback100Imp::UpdateErrorMessage(const wchar_t *message) { - ProgressDialog->Sync.AddErrorMessage(message); + ProgressDialog->Sync.AddError_Message(message); return S_OK; } @@ -71,7 +68,7 @@ STDMETHODIMP CUpdateCallback100Imp::SetTotal(const UInt64 * /* files */, const U STDMETHODIMP CUpdateCallback100Imp::SetCompleted(const UInt64 * /* files */, const UInt64 * /* bytes */) { - return ProgressDialog->Sync.ProcessStopAndPause(); + return ProgressDialog->Sync.CheckStop(); } STDMETHODIMP CUpdateCallback100Imp::CryptoGetTextPassword(BSTR *password) @@ -81,7 +78,7 @@ STDMETHODIMP CUpdateCallback100Imp::CryptoGetTextPassword(BSTR *password) { CPasswordDialog dialog; ProgressDialog->WaitCreating(); - if (dialog.Create(*ProgressDialog) == IDCANCEL) + if (dialog.Create(*ProgressDialog) != IDOK) return E_ABORT; _password = dialog.Password; _passwordIsDefined = true; diff --git a/CPP/7zip/UI/FileManager/UpdateCallback100.h b/CPP/7zip/UI/FileManager/UpdateCallback100.h old mode 100755 new mode 100644 index aa13320f..944453a1 --- a/CPP/7zip/UI/FileManager/UpdateCallback100.h +++ b/CPP/7zip/UI/FileManager/UpdateCallback100.h @@ -3,7 +3,7 @@ #ifndef __UPDATE_CALLBACK100_H #define __UPDATE_CALLBACK100_H -#include "Common/MyCom.h" +#include "../../../Common/MyCom.h" #include "../../IPassword.h" diff --git a/CPP/7zip/UI/FileManager/ViewSettings.cpp b/CPP/7zip/UI/FileManager/ViewSettings.cpp old mode 100755 new mode 100644 index f11f68d6..9688a4a5 --- a/CPP/7zip/UI/FileManager/ViewSettings.cpp +++ b/CPP/7zip/UI/FileManager/ViewSettings.cpp @@ -1,13 +1,16 @@ -// ViewSettings.h +// ViewSettings.cpp #include "StdAfx.h" + +#include "../../../../C/CpuArch.h" -#include "Common/IntToString.h" -#include "Common/StringConvert.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/Registry.h" +#include "../../../Windows/Synchronization.h" #include "ViewSettings.h" -#include "Windows/Registry.h" -#include "Windows/Synchronization.h" using namespace NWindows; using namespace NRegistry; @@ -27,163 +30,95 @@ 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; -}; +static NSynchronization::CCriticalSection g_CS; + +#define Set32(p, v) SetUi32(((Byte *)p), v) +#define SetBool(p, v) Set32(p, ((v) ? 1 : 0)) +#define Get32(p, dest) dest = GetUi32((const Byte *)p) +#define GetBool(p, dest) dest = (GetUi32(p) != 0); + +/* struct CColumnHeader { UInt32 Version; UInt32 SortID; - Byte Ascending; + UInt32 Ascending; // bool }; */ -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); - } -}; +static const UInt32 kListViewHeaderSize = 3 * 4; +static const UInt32 kColumnInfoSize = 3 * 4; +static const UInt32 kListViewVersion = 1; -class CTempInBufferSpec +void CListViewInfo::Save(const UString &id) const { -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); - } -}; + const UInt32 dataSize = kListViewHeaderSize + kColumnInfoSize * Columns.Size(); + CByteArr buf(dataSize); -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++) + Set32(buf, kListViewVersion); + Set32(buf + 4, SortID); + SetBool(buf + 8, Ascending); + FOR_VECTOR (i, Columns) { - const CColumnInfo &column = columns[i]; - buffer.WriteUInt32(column.PropID); - buffer.WriteBool(column.IsVisible); - buffer.WriteUInt32(column.Width); + const CColumnInfo &column = Columns[i]; + Byte *p = buf + kListViewHeaderSize + i * kColumnInfoSize; + Set32(p, column.PropID); + SetBool(p + 4, column.IsVisible); + Set32(p + 8, column.Width); } { NSynchronization::CCriticalSectionLock lock(g_CS); CKey key; key.Create(HKEY_CURRENT_USER, kCulumnsKeyName); - key.SetValue(GetSystemString(id), (const Byte *)buffer, dataSize); + key.SetValue(GetSystemString(id), (const Byte *)buf, dataSize); } } -void ReadListViewInfo(const UString &id, CListViewInfo &viewInfo) +void CListViewInfo::Read(const UString &id) { - viewInfo.Clear(); - CObjectVector &columns = viewInfo.Columns; - CByteBuffer buffer; + Clear(); + CByteBuffer buf; 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) + if (key.QueryValue(GetSystemString(id), buf, size) != ERROR_SUCCESS) return; } - if (size < kColumnHeaderSize) + if (size < kListViewHeaderSize) return; - CTempInBufferSpec inBuffer; - inBuffer.Size = size; - inBuffer.Buffer = (Byte *)buffer; - inBuffer.Pos = 0; - - - UInt32 version = inBuffer.ReadUInt32(); - if (version != kColumnInfoVersion) + UInt32 version; + Get32(buf, version); + if (version != kListViewVersion) return; - viewInfo.SortID = inBuffer.ReadUInt32(); - viewInfo.Ascending = inBuffer.ReadBool(); + Get32(buf + 4, SortID); + GetBool(buf + 8, Ascending); - size -= kColumnHeaderSize; - if (size % kColumnInfoSpecHeader != 0) + size -= kListViewHeaderSize; + if (size % kColumnInfoSize != 0) return; - int numItems = size / kColumnInfoSpecHeader; - columns.Reserve(numItems); - for(int i = 0; i < numItems; i++) + unsigned numItems = size / kColumnInfoSize; + Columns.ClearAndReserve(numItems); + for (unsigned i = 0; i < numItems; i++) { - CColumnInfo columnInfo; - columnInfo.PropID = inBuffer.ReadUInt32(); - columnInfo.IsVisible = inBuffer.ReadBool(); - columnInfo.Width = inBuffer.ReadUInt32(); - columns.Add(columnInfo); + CColumnInfo column; + const Byte *p = buf + kListViewHeaderSize + i * kColumnInfoSize; + Get32(p, column.PropID); + GetBool(p + 4, column.IsVisible); + Get32(p + 8, column.Width); + Columns.AddInReserved(column); } } -static const UInt32 kWindowPositionHeaderSize = 5 * 4; -static const UInt32 kPanelsInfoHeaderSize = 3 * 4; /* struct CWindowPosition { RECT Rect; - UInt32 Maximized; + UInt32 Maximized; // bool }; struct CPanelsInfo @@ -194,114 +129,125 @@ struct CPanelsInfo }; */ -void SaveWindowSize(const RECT &rect, bool maximized) +static const UInt32 kWindowPositionHeaderSize = 5 * 4; +static const UInt32 kPanelsInfoHeaderSize = 3 * 4; + +void CWindowInfo::Save() const { - 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); + key.Create(HKEY_CURRENT_USER, kCUBasePath); + { + Byte buf[kWindowPositionHeaderSize]; + Set32(buf, rect.left); + Set32(buf + 4, rect.top); + Set32(buf + 8, rect.right); + Set32(buf + 12, rect.bottom); + SetBool(buf + 16, maximized); + key.SetValue(kPositionValueName, buf, kWindowPositionHeaderSize); + } + { + Byte buf[kPanelsInfoHeaderSize]; + Set32(buf, numPanels); + Set32(buf + 4, currentPanel); + Set32(buf + 8, splitterPos); + key.SetValue(kPanelsInfoValueName, buf, kPanelsInfoHeaderSize); + } } -bool ReadWindowSize(RECT &rect, bool &maximized) +static bool QueryBuf(CKey &key, LPCTSTR name, CByteBuffer &buf, UInt32 dataSize) { - 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; + return key.QueryValue(name, buf, size) == ERROR_SUCCESS && size == dataSize; } -void SavePanelsInfo(UInt32 numPanels, UInt32 currentPanel, UInt32 splitterPos) +void CWindowInfo::Read(bool &windowPosDefined, bool &panelInfoDefined) { - CSysString keyName = kCUBasePath; + windowPosDefined = false; + panelInfoDefined = false; 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); + if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS) + return; + CByteBuffer buf; + if (QueryBuf(key, kPositionValueName, buf, kWindowPositionHeaderSize)) + { + Get32(buf, rect.left); + Get32(buf + 4, rect.top); + Get32(buf + 8, rect.right); + Get32(buf + 12, rect.bottom); + GetBool(buf + 16, maximized); + windowPosDefined = true; + } + if (QueryBuf(key, kPanelsInfoValueName, buf, kPanelsInfoHeaderSize)) + { + Get32(buf, numPanels); + Get32(buf + 4, currentPanel); + Get32(buf + 8, splitterPos); + panelInfoDefined = true; + } + return; +} + + +void SaveUi32Val(const TCHAR *name, UInt32 value) +{ + CKey key; + key.Create(HKEY_CURRENT_USER, kCUBasePath); + key.SetValue(name, value); } -bool ReadPanelsInfo(UInt32 &numPanels, UInt32 ¤tPanel, UInt32 &splitterPos) +bool ReadUi32Val(const TCHAR *name, UInt32 &value) { - 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) + if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS) 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; + return key.QueryValue(name, value) == ERROR_SUCCESS; } void SaveToolbarsMask(UInt32 toolbarMask) { - CKey key; - key.Create(HKEY_CURRENT_USER, kCUBasePath); - key.SetValue(kToolbars, toolbarMask); + SaveUi32Val(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) + if (!ReadUi32Val(kToolbars, mask)) return kDefaultToolbarMask; return mask; } -static UString GetPanelPathName(UInt32 panelIndex) +void CListMode::Save() const { - WCHAR panelString[16]; - ConvertUInt32ToString(panelIndex, panelString); - return UString(kPanelPathValueName) + panelString; + UInt32 t = 0; + for (int i = 0; i < 2; i++) + t |= ((Panels[i]) & 0xFF) << (i * 8); + SaveUi32Val(kListMode, t); +} + +void CListMode::Read() +{ + Init(); + UInt32 t; + if (!ReadUi32Val(kListMode, t)) + return; + for (int i = 0; i < 2; i++) + { + Panels[i] = (t & 0xFF); + t >>= 8; + } } +static UString GetPanelPathName(UInt32 panelIndex) +{ + WCHAR s[16]; + ConvertUInt32ToString(panelIndex, s); + return (UString)kPanelPathValueName + s; +} void SavePanelPath(UInt32 panel, const UString &path) { @@ -320,32 +266,6 @@ bool ReadPanelPath(UInt32 panel, UString &path) 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) { @@ -381,8 +301,8 @@ void ReadCopyHistory(UStringVector &folders) void AddUniqueStringToHeadOfList(UStringVector &list, const UString &s) { - for (int i = 0; i < list.Size();) - if (s.CompareNoCase(list[i]) == 0) + for (unsigned i = 0; i < list.Size();) + if (s.IsEqualToNoCase(list[i])) list.Delete(i); else i++; diff --git a/CPP/7zip/UI/FileManager/ViewSettings.h b/CPP/7zip/UI/FileManager/ViewSettings.h old mode 100755 new mode 100644 index b0510813..dbb98dc6 --- a/CPP/7zip/UI/FileManager/ViewSettings.h +++ b/CPP/7zip/UI/FileManager/ViewSettings.h @@ -3,30 +3,24 @@ #ifndef __VIEW_SETTINGS_H #define __VIEW_SETTINGS_H -#include "Common/MyString.h" -#include "Common/Types.h" +#include "../../../Common/MyTypes.h" +#include "../../../Common/MyString.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); -} + bool IsEqual(const CColumnInfo &a) const + { + return PropID == a.PropID && IsVisible == a.IsVisible && Width == a.Width; + } +}; struct CListViewInfo { - CObjectVector Columns; + CRecordVector Columns; PROPID SortID; bool Ascending; @@ -37,52 +31,67 @@ struct CListViewInfo Columns.Clear(); } + /* int FindColumnWithID(PROPID propID) const { - for (int i = 0; i < Columns.Size(); i++) + FOR_VECTOR (i, Columns) 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]) + FOR_VECTOR (i, Columns) + if (!Columns[i].IsEqual(info.Columns[i])) return false; return true; } + + void Save(const UString &id) const; + void Read(const UString &id); }; -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); +struct CWindowInfo +{ + RECT rect; + bool maximized; + + UInt32 numPanels; + UInt32 currentPanel; + UInt32 splitterPos; -void SavePanelsInfo(UInt32 numPanels, UInt32 currentPanel, UInt32 splitterPos); -bool ReadPanelsInfo(UInt32 &numPanels, UInt32 ¤tPanel, UInt32 &splitterPos); + void Save() const; + void Read(bool &windowPosDefined, bool &panelInfoDefined); +}; void SaveToolbarsMask(UInt32 toolbarMask); UInt32 ReadToolbarsMask(); -void SavePanelPath(UInt32 panel, const UString &path); -bool ReadPanelPath(UInt32 panel, UString &path); +const UInt32 kListMode_Report = 3; struct CListMode { UInt32 Panels[2]; - void Init() { Panels[0] = Panels[1] = 3; } + + void Init() { Panels[0] = Panels[1] = kListMode_Report; } CListMode() { Init(); } + + void Save() const ; + void Read(); }; -void SaveListMode(const CListMode &listMode); -void ReadListMode(CListMode &listMode); + + +void SavePanelPath(UInt32 panel, const UString &path); +bool ReadPanelPath(UInt32 panel, UString &path); + void SaveFolderHistory(const UStringVector &folders); void ReadFolderHistory(UStringVector &folders); diff --git a/CPP/7zip/UI/FileManager/makefile b/CPP/7zip/UI/FileManager/makefile old mode 100755 new mode 100644 index eeca66f9..96ae902f --- a/CPP/7zip/UI/FileManager/makefile +++ b/CPP/7zip/UI/FileManager/makefile @@ -1,5 +1,5 @@ PROG = 7zFM.exe -CFLAGS = $(CFLAGS) -I ../../../ \ +CFLAGS = $(CFLAGS) \ -DLANG \ -DNEW_FOLDER_INTERFACE \ -DEXTERNAL_CODECS \ @@ -11,67 +11,9 @@ 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 \ +!include "FM.mak" COMMON_OBJS = \ - $O\CRC.obj \ $O\IntToString.obj \ $O\Lang.obj \ $O\MyString.obj \ @@ -80,45 +22,33 @@ COMMON_OBJS = \ $O\Random.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ - $O\TextConfig.obj \ $O\UTFConvert.obj \ $O\Wildcard.obj \ -WIN_OBJS = \ +WIN_OBJS = $(WIN_OBJS) \ $O\Clipboard.obj \ $O\CommonDialog.obj \ $O\DLL.obj \ - $O\Error.obj \ + $O\ErrorMsg.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ + $O\FileLink.obj \ $O\FileName.obj \ - $O\Memory.obj \ + $O\MemoryGlobal.obj \ $O\MemoryLock.obj \ $O\Menu.obj \ - $O\Process.obj \ + $O\ProcessUtils.obj \ $O\PropVariant.obj \ - $O\PropVariantConversions.obj \ + $O\PropVariantConv.obj \ $O\Registry.obj \ $O\ResourceString.obj \ $O\Shell.obj \ $O\Synchronization.obj \ - $O\Time.obj \ + $O\System.obj \ + $O\TimeUtils.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 \ @@ -128,14 +58,17 @@ WIN_CTRL_OBJS = \ $O\Window2.obj \ 7ZIP_COMMON_OBJS = \ + $O\CreateCoder.obj \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ + $O\FilterCoder.obj \ + $O\LimitedStreams.obj \ + $O\MethodProps.obj \ $O\ProgressUtils.obj \ + $O\PropId.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ - -AR_COMMON_OBJS = \ - $O\OutStreamWithCRC.obj \ + $O\UniqBlocks.obj \ UI_COMMON_OBJS = \ $O\ArchiveExtractCallback.obj \ @@ -145,9 +78,11 @@ UI_COMMON_OBJS = \ $O\DefaultName.obj \ $O\EnumDirItems.obj \ $O\ExtractingFilePath.obj \ + $O\HashCalc.obj \ $O\LoadCodecs.obj \ $O\OpenArchive.obj \ $O\PropIDUtils.obj \ + $O\SetProperties.obj \ $O\SortUtils.obj \ $O\UpdateAction.obj \ $O\UpdateCallback.obj \ @@ -160,64 +95,15 @@ 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 \ +GUI_OBJS = \ + $O\HashGUI.obj \ + +COMPRESS_OBJS = \ + $O\CopyCoder.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" +!include "../../7zip.mak" diff --git a/CPP/7zip/UI/FileManager/resource.h b/CPP/7zip/UI/FileManager/resource.h old mode 100755 new mode 100644 index cdb77edf..55af3555 --- a/CPP/7zip/UI/FileManager/resource.h +++ b/CPP/7zip/UI/FileManager/resource.h @@ -1,164 +1,171 @@ #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_BENCHMARK2 512 -#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 +#define IDR_MENUBAR1 70 +#define IDM_MENU 71 +#define IDR_ACCELERATOR1 72 + +#define IDB_ADD 100 +#define IDB_EXTRACT 101 +#define IDB_TEST 102 +#define IDB_COPY 103 +#define IDB_MOVE 104 +#define IDB_DELETE 105 +#define IDB_INFO 106 + +#define IDB_ADD2 150 +#define IDB_EXTRACT2 151 +#define IDB_TEST2 152 +#define IDB_COPY2 153 +#define IDB_MOVE2 154 +#define IDB_DELETE2 155 +#define IDB_INFO2 156 + +#define IDM_HASH_ALL 101 +#define IDM_CRC32 102 +#define IDM_CRC64 103 +#define IDM_SHA1 104 +#define IDM_SHA256 105 + +#define IDM_OPEN 540 +#define IDM_OPEN_INSIDE 541 +#define IDM_OPEN_OUTSIDE 542 +#define IDM_FILE_VIEW 543 +#define IDM_FILE_EDIT 544 +#define IDM_RENAME 545 +#define IDM_COPY_TO 546 +#define IDM_MOVE_TO 547 +#define IDM_DELETE 548 +#define IDM_SPLIT 549 +#define IDM_COMBINE 550 +#define IDM_PROPERTIES 551 +#define IDM_COMMENT 552 +#define IDM_CRC 553 +#define IDM_DIFF 554 +#define IDM_CREATE_FOLDER 555 +#define IDM_CREATE_FILE 556 +// #define IDM_EXIT 557 +#define IDM_LINK 558 + +#define IDM_SELECT_ALL 600 +#define IDM_DESELECT_ALL 601 +#define IDM_INVERT_SELECTION 602 +#define IDM_SELECT 603 +#define IDM_DESELECT 604 +#define IDM_SELECT_BY_TYPE 605 +#define IDM_DESELECT_BY_TYPE 606 + +#define IDM_VIEW_LARGE_ICONS 700 +#define IDM_VIEW_SMALL_ICONS 701 +#define IDM_VIEW_LIST 702 +#define IDM_VIEW_DETAILS 703 + +#define IDM_VIEW_ARANGE_BY_NAME 710 +#define IDM_VIEW_ARANGE_BY_TYPE 711 +#define IDM_VIEW_ARANGE_BY_DATE 712 +#define IDM_VIEW_ARANGE_BY_SIZE 713 + +#define IDM_VIEW_ARANGE_NO_SORT 730 +#define IDM_VIEW_FLAT_VIEW 731 +#define IDM_VIEW_TWO_PANELS 732 +#define IDM_VIEW_TOOLBARS 733 +#define IDM_OPEN_ROOT_FOLDER 734 +#define IDM_OPEN_PARENT_FOLDER 735 +#define IDM_FOLDERS_HISTORY 736 +#define IDM_VIEW_REFRESH 737 +#define IDM_VIEW_AUTO_REFRESH 738 +// #define IDM_VIEW_SHOW_DELETED 739 +// #define IDM_VIEW_SHOW_STREAMS 740 + +#define IDM_VIEW_ARCHIVE_TOOLBAR 750 +#define IDM_VIEW_STANDARD_TOOLBAR 751 +#define IDM_VIEW_TOOLBARS_LARGE_BUTTONS 752 +#define IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT 753 + +#define IDS_BOOKMARK 801 + +#define IDM_OPTIONS 900 +#define IDM_BENCHMARK 901 +#define IDM_BENCHMARK2 902 + +#define IDM_HELP_CONTENTS 960 +#define IDM_ABOUT 961 + +#define IDS_OPTIONS 2100 + +#define IDS_N_SELECTED_ITEMS 3002 + +#define IDS_FILE_EXIST 3008 +#define IDS_WANT_UPDATE_MODIFIED_FILE 3009 +#define IDS_CANNOT_UPDATE_FILE 3010 +#define IDS_CANNOT_START_EDITOR 3011 +#define IDS_VIRUS 3012 +#define IDS_MESSAGE_UNSUPPORTED_OPERATION_FOR_LONG_PATH_FOLDER 3013 +#define IDS_SELECT_ONE_FILE 3014 +#define IDS_SELECT_FILES 3015 +#define IDS_TOO_MANY_ITEMS 3016 + +#define IDS_COPY 6000 +#define IDS_MOVE 6001 +#define IDS_COPY_TO 6002 +#define IDS_MOVE_TO 6003 +#define IDS_COPYING 6004 +#define IDS_MOVING 6005 +#define IDS_RENAMING 6006 + +#define IDS_OPERATION_IS_NOT_SUPPORTED 6008 +#define IDS_ERROR_RENAMING 6009 +#define IDS_CONFIRM_FILE_COPY 6010 +#define IDS_WANT_TO_COPY_FILES 6011 + +#define IDS_CONFIRM_FILE_DELETE 6100 +#define IDS_CONFIRM_FOLDER_DELETE 6101 +#define IDS_CONFIRM_ITEMS_DELETE 6102 +#define IDS_WANT_TO_DELETE_FILE 6103 +#define IDS_WANT_TO_DELETE_FOLDER 6104 +#define IDS_WANT_TO_DELETE_ITEMS 6105 +#define IDS_DELETING 6106 +#define IDS_ERROR_DELETING 6107 +#define IDS_ERROR_LONG_PATH_TO_RECYCLE 6108 + +#define IDS_CREATE_FOLDER 6300 +#define IDS_CREATE_FILE 6301 +#define IDS_CREATE_FOLDER_NAME 6302 +#define IDS_CREATE_FILE_NAME 6303 +#define IDS_CREATE_FOLDER_DEFAULT_NAME 6304 +#define IDS_CREATE_FILE_DEFAULT_NAME 6305 +#define IDS_CREATE_FOLDER_ERROR 6306 +#define IDS_CREATE_FILE_ERROR 6307 + +#define IDS_COMMENT 6400 +#define IDS_COMMENT2 6401 +#define IDS_SELECT 6402 +#define IDS_DESELECT 6403 +#define IDS_SELECT_MASK 6404 + +#define IDS_PROPERTIES 6600 +#define IDS_FOLDERS_HISTORY 6601 + +#define IDS_COMPUTER 7100 +#define IDS_NETWORK 7101 +#define IDS_DOCUMENTS 7102 +#define IDS_SYSTEM 7103 + +#define IDS_ADD 7200 +#define IDS_EXTRACT 7201 +#define IDS_TEST 7202 +#define IDS_BUTTON_COPY 7203 +#define IDS_BUTTON_MOVE 7204 +#define IDS_BUTTON_DELETE 7205 +#define IDS_BUTTON_INFO 7206 + +#define IDS_SPLITTING 7303 +#define IDS_SPLIT_CONFIRM_TITLE 7304 +#define IDS_SPLIT_CONFIRM_MESSAGE 7305 +#define IDS_SPLIT_VOL_MUST_BE_SMALLER 7306 + +#define IDS_COMBINE 7400 +#define IDS_COMBINE_TO 7401 +#define IDS_COMBINING 7402 +#define IDS_COMBINE_SELECT_ONE_FILE 7403 +#define IDS_COMBINE_CANT_DETECT_SPLIT_FILE 7404 +#define IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART 7405 diff --git a/CPP/7zip/UI/FileManager/resource.rc b/CPP/7zip/UI/FileManager/resource.rc old mode 100755 new mode 100644 index 2952ce5a..61cf33e8 --- a/CPP/7zip/UI/FileManager/resource.rc +++ b/CPP/7zip/UI/FileManager/resource.rc @@ -4,13 +4,12 @@ MY_VERSION_INFO_APP("7-Zip File Manager", "7zFM") - IDR_ACCELERATOR1 ACCELERATORS BEGIN - "N", IDM_CREATE_FILE, VIRTKEY, CONTROL, NOINVERT +// "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 +// VK_F7, IDM_CREATE_FOLDER, VIRTKEY, NOINVERT END @@ -18,9 +17,10 @@ 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 "&Open\tEnter", IDM_OPEN + MENUITEM "Open &Inside\tCtrl+PgDn", IDM_OPEN_INSIDE + MENUITEM "Open O&utside\tShift+Enter", IDM_OPEN_OUTSIDE + MENUITEM "&View\tF3", IDM_FILE_VIEW MENUITEM "&Edit\tF4", IDM_FILE_EDIT MENUITEM SEPARATOR MENUITEM "Rena&me\tF2", IDM_RENAME @@ -28,17 +28,27 @@ BEGIN 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 "&Split file...", IDM_SPLIT + MENUITEM "Com&bine files...", IDM_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 "P&roperties\tAlt+Enter", IDM_PROPERTIES + MENUITEM "Comme&nt...\tCtrl+Z", IDM_COMMENT + // MENUITEM "Calculate checksum", IDM_CRC + POPUP "CRC" + BEGIN + MENUITEM "CRC-32", IDM_CRC32 + MENUITEM "CRC-64", IDM_CRC64 + MENUITEM "SHA-1", IDM_SHA1 + MENUITEM "SHA-256", IDM_SHA256 + MENUITEM "*", IDM_HASH_ALL + END + MENUITEM "Di&ff", IDM_DIFF MENUITEM SEPARATOR MENUITEM "Create Folder\tF7", IDM_CREATE_FOLDER MENUITEM "Create File\tCtrl+N", IDM_CREATE_FILE MENUITEM SEPARATOR + MENUITEM "&Link...", IDM_LINK + MENUITEM SEPARATOR MENUITEM "E&xit\tAlt+F4", IDCLOSE END POPUP "&Edit" @@ -72,16 +82,21 @@ BEGIN 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 "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 + 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 + MENUITEM "Auto Refresh", IDM_VIEW_AUTO_REFRESH + + // MENUITEM "Show NTFS streams", IDM_VIEW_SHOW_STREAMS + // MENUITEM "Show deleted files", IDM_VIEW_SHOW_DELETED + END POPUP "F&avorites" BEGIN @@ -105,7 +120,7 @@ BEGIN MENUITEM "&Contents...\tF1", IDM_HELP_CONTENTS #endif MENUITEM SEPARATOR - MENUITEM "&About 7-Zip...", IDM_ABOUT + MENUITEM "&About 7-Zip...", IDM_ABOUT END END @@ -134,99 +149,89 @@ 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_BOOKMARK "Bookmark" - 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_OPTIONS "Options" - 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_N_SELECTED_ITEMS "{0} object(s) selected" - IDS_SCANNING "Scanning..." + IDS_FILE_EXIST "File {0} is already exist" + 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_VIRUS "The file looks like a virus (the file name contains long spaces in name)." + 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_TOO_MANY_ITEMS "Too many items" - IDS_PROPERTIES "Properties" + IDS_COPY "Copy" + IDS_MOVE "Move" + IDS_COPY_TO "Copy to:" + IDS_MOVE_TO "Move to:" + IDS_COPYING "Copying..." + IDS_MOVING "Moving..." + IDS_RENAMING "Renaming..." - IDS_OPERATION_IS_NOT_SUPPORTED "Operation is not supported." - - IDS_CONFIRM_FILE_DELETE "Confirm File Delete" + IDS_OPERATION_IS_NOT_SUPPORTED "Operation is not supported." + 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_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_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_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_FOLDER_NAME "Folder name:" IDS_CREATE_FILE_NAME "File Name:" - IDS_CREATE_FILE_DEFAULT_NAME "New File" + IDS_CREATE_FOLDER_DEFAULT_NAME "New Folder" + IDS_CREATE_FILE_DEFAULT_NAME "New File" + IDS_CREATE_FOLDER_ERROR "Error Creating Folder" 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 + IDS_COMMENT "Comment" + IDS_COMMENT2 "&Comment:" + IDS_SELECT "Select" + IDS_DESELECT "Deselect" + IDS_SELECT_MASK "Mask:" + IDS_PROPERTIES "Properties" + IDS_FOLDERS_HISTORY "Folders History" + + IDS_COMPUTER "Computer" + IDS_NETWORK "Network" + IDS_DOCUMENTS "Documents" + IDS_SYSTEM "System" + + 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_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" + +END #include "AboutDialog.rc" #include "BrowseDialog.rc" @@ -235,12 +240,12 @@ END #include "EditPage.rc" #include "FoldersPage.rc" #include "LangPage.rc" +#include "LinkDialog.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" diff --git a/CPP/7zip/UI/FileManager/resourceGui.h b/CPP/7zip/UI/FileManager/resourceGui.h old mode 100755 new mode 100644 index 14cedda5..7c1b40e4 --- a/CPP/7zip/UI/FileManager/resourceGui.h +++ b/CPP/7zip/UI/FileManager/resourceGui.h @@ -1,10 +1,15 @@ #define IDI_ICON 1 -#define IDS_INCORRECT_VOLUME_SIZE 95 +#define IDS_MESSAGE_NO_ERRORS 3001 -#define IDS_FILES_COLON 2274 -#define IDS_FOLDERS_COLON 2275 -#define IDS_SIZE_COLON 2276 +#define IDS_PROGRESS_TESTING 3302 +#define IDS_OPENNING 3303 +#define IDS_SCANNING 3304 -#define IDS_PROGRESS_TESTING 4100 -#define IDS_MESSAGE_NO_ERRORS 4200 +#define IDS_CHECKSUM_CALCULATING 7500 +#define IDS_CHECKSUM_INFORMATION 7501 +#define IDS_CHECKSUM_CRC_DATA 7502 +#define IDS_CHECKSUM_CRC_DATA_NAMES 7503 +#define IDS_CHECKSUM_CRC_STREAMS_NAMES 7504 + +#define IDS_INCORRECT_VOLUME_SIZE 7307 diff --git a/CPP/7zip/UI/FileManager/resourceGui.rc b/CPP/7zip/UI/FileManager/resourceGui.rc old mode 100755 new mode 100644 index 2e706ea2..f748e0bd --- a/CPP/7zip/UI/FileManager/resourceGui.rc +++ b/CPP/7zip/UI/FileManager/resourceGui.rc @@ -2,12 +2,18 @@ STRINGTABLE BEGIN - IDS_INCORRECT_VOLUME_SIZE "Incorrect volume size" + IDS_MESSAGE_NO_ERRORS "There are no errors" - IDS_FILES_COLON "Files:" - IDS_FOLDERS_COLON "Folders:" - IDS_SIZE_COLON "Size:" + IDS_PROGRESS_TESTING "Testing" - IDS_PROGRESS_TESTING "Testing" - IDS_MESSAGE_NO_ERRORS "There are no errors" + 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_CHECKSUM_CRC_STREAMS_NAMES "CRC checksum for streams and names:" + + IDS_INCORRECT_VOLUME_SIZE "Incorrect volume size" + + IDS_OPENNING "Opening..." + IDS_SCANNING "Scanning..." END diff --git a/CPP/7zip/UI/GUI/7zG.exe.manifest b/CPP/7zip/UI/GUI/7zG.exe.manifest old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp old mode 100755 new mode 100644 index 8ca87f8f..1f4bcab5 --- a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp @@ -2,13 +2,16 @@ #include "StdAfx.h" -#include "Common/IntToString.h" -#include "Common/MyException.h" -#include "Common/StringConvert.h" +#include "../../../Common/Defs.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/MyException.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/StringToInt.h" -#include "Windows/Error.h" -#include "Windows/System.h" -#include "Windows/Thread.h" +#include "../../../Windows/System.h" +#include "../../../Windows/Thread.h" + +#include "../../Common/MethodProps.h" #include "../FileManager/HelpUtils.h" @@ -30,39 +33,37 @@ using namespace NWindows; UString HResultToMessage(HRESULT errorCode); #ifdef LANG -static CIDLangPair kIDLangPairs[] = +static const UInt32 kLangIDs[] = { - { 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 } + IDT_BENCH_DICTIONARY, + IDT_BENCH_MEMORY, + IDT_BENCH_NUM_THREADS, + IDT_BENCH_SPEED, + IDT_BENCH_RATING_LABEL, + IDT_BENCH_USAGE_LABEL, + IDT_BENCH_RPU_LABEL, + IDG_BENCH_COMPRESSING, + IDG_BENCH_DECOMPRESSING, + IDG_BENCH_TOTAL_RATING, + IDT_BENCH_CURRENT, + IDT_BENCH_RESULTING, + IDT_BENCH_ELAPSED, + IDT_BENCH_PASSES, + IDB_STOP, + IDB_RESTART }; + +static const UInt32 kLangIDs_Colon[] = +{ + IDT_BENCH_SIZE +}; + #endif -const LPCTSTR kProcessingString = TEXT("..."); -const LPCTSTR kMB = TEXT(" MB"); -const LPCTSTR kMIPS = TEXT(" MIPS"); -const LPCTSTR kKBs = TEXT(" KB/s"); +static const LPCTSTR kProcessingString = TEXT("..."); +static const LPCTSTR kMB = TEXT(" MB"); +static const LPCTSTR kMIPS = TEXT(" MIPS"); +static const LPCTSTR kKBs = TEXT(" KB/s"); #ifdef UNDER_CE static const int kMinDicLogSize = 20; @@ -80,15 +81,18 @@ static const UInt32 kMaxDicSize = bool CBenchmarkDialog::OnInit() { #ifdef LANG - LangSetWindowText(HWND(*this), 0x03080000); - LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + LangSetWindowText(*this, IDD_BENCH); + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); + LangSetDlgItems_Colon(*this, kLangIDs_Colon, ARRAY_SIZE(kLangIDs_Colon)); + LangSetDlgItemText(*this, IDT_BENCH_CURRENT2, IDT_BENCH_CURRENT); + LangSetDlgItemText(*this, IDT_BENCH_RESULTING2, IDT_BENCH_RESULTING); #endif Sync.Init(); if (TotalMode) { - _consoleEdit.Attach(GetItem(IDC_BENCHMARK2_EDIT)); + _consoleEdit.Attach(GetItem(IDE_BENCH2_EDIT)); LOGFONT f; memset(&f, 0, sizeof(f)); f.lfHeight = 14; @@ -100,7 +104,8 @@ bool CBenchmarkDialog::OnInit() f.lfQuality = DEFAULT_QUALITY; f.lfPitchAndFamily = FIXED_PITCH; - MyStringCopy(f.lfFaceName, TEXT("")); + // MyStringCopy(f.lfFaceName, TEXT("")); + // f.lfFaceName[0] = 0; _font.Create(&f); if (_font._font) _consoleEdit.SendMessage(WM_SETFONT, (WPARAM)_font._font, TRUE); @@ -111,13 +116,13 @@ bool CBenchmarkDialog::OnInit() numCPUs = 1; numCPUs = MyMin(numCPUs, (UInt32)(1 << 8)); - if (Sync.NumThreads == (UInt32)-1) + if (Sync.NumThreads == (UInt32)(Int32)-1) { Sync.NumThreads = numCPUs; if (Sync.NumThreads > 1) Sync.NumThreads &= ~1; } - m_NumThreads.Attach(GetItem(IDC_BENCHMARK_COMBO_NUM_THREADS)); + m_NumThreads.Attach(GetItem(IDC_BENCH_NUM_THREADS)); int cur = 0; for (UInt32 num = 1; num <= numCPUs * 2;) { @@ -134,7 +139,7 @@ bool CBenchmarkDialog::OnInit() m_NumThreads.SetCurSel(cur); Sync.NumThreads = GetNumberOfThreads(); - m_Dictionary.Attach(GetItem(IDC_BENCHMARK_COMBO_DICTIONARY)); + m_Dictionary.Attach(GetItem(IDC_BENCH_DICTIONARY)); cur = 0; UInt64 ramSize = NSystem::GetRamSize(); @@ -144,7 +149,7 @@ bool CBenchmarkDialog::OnInit() ramSize = kNormalizedCeSize; #endif - if (Sync.DictionarySize == (UInt32)-1) + if (Sync.DictionarySize == (UInt32)(Int32)-1) { int dicSizeLog; for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--) @@ -205,7 +210,7 @@ bool CBenchmarkDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) { int yPos = ySize - my - by; RECT rect; - GetClientRectOfItem(IDC_BENCHMARK2_EDIT, rect); + GetClientRectOfItem(IDE_BENCH2_EDIT, rect); int y = rect.top; int ySize2 = yPos - my - y; const int kMinYSize = 20; @@ -221,54 +226,54 @@ bool CBenchmarkDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) UInt32 CBenchmarkDialog::GetNumberOfThreads() { - return (UInt32)m_NumThreads.GetItemData(m_NumThreads.GetCurSel()); + return (UInt32)m_NumThreads.GetItemData_of_CurSel(); } UInt32 CBenchmarkDialog::OnChangeDictionary() { - UInt32 dictionary = (UInt32)m_Dictionary.GetItemData(m_Dictionary.GetCurSel()); + UInt32 dictionary = (UInt32)m_Dictionary.GetItemData_of_CurSel(); 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); + SetItemText(IDT_BENCH_MEMORY_VAL, 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, + IDT_BENCH_COMPRESS_USAGE1, + IDT_BENCH_COMPRESS_USAGE2, + IDT_BENCH_COMPRESS_SPEED1, + IDT_BENCH_COMPRESS_SPEED2, + IDT_BENCH_COMPRESS_RATING1, + IDT_BENCH_COMPRESS_RATING2, + IDT_BENCH_COMPRESS_RPU1, + IDT_BENCH_COMPRESS_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, + IDT_BENCH_DECOMPR_SPEED1, + IDT_BENCH_DECOMPR_SPEED2, + IDT_BENCH_DECOMPR_RATING1, + IDT_BENCH_DECOMPR_RATING2, + IDT_BENCH_DECOMPR_USAGE1, + IDT_BENCH_DECOMPR_USAGE2, + IDT_BENCH_DECOMPR_RPU1, + IDT_BENCH_DECOMPR_RPU2, - IDC_BENCHMARK_TOTAL_USAGE_VALUE, - IDC_BENCHMARK_TOTAL_RATING_VALUE, - IDC_BENCHMARK_TOTAL_RPU_VALUE + IDT_BENCH_TOTAL_USAGE_VAL, + IDT_BENCH_TOTAL_RATING_VAL, + IDT_BENCH_TOTAL_RPU_VAL }; void CBenchmarkDialog::OnChangeSettings() { - EnableItem(IDC_BUTTON_STOP, true); + EnableItem(IDB_STOP, true); UInt32 dictionary = OnChangeDictionary(); TCHAR s[40] = { TEXT('/'), TEXT(' '), 0 }; ConvertUInt32ToString(NSystem::GetNumberOfProcessors(), s + 2); - SetItemText(IDC_BENCHMARK_HARDWARE_THREADS, s); - for (int i = 0; i < sizeof(g_IDs) / sizeof(g_IDs[0]); i++) + SetItemText(IDT_BENCH_HARDWARE_THREADS, s); + for (int i = 0; i < ARRAY_SIZE(g_IDs); i++) SetItemText(g_IDs[i], kProcessingString); _startTime = GetTickCount(); PrintTime(); @@ -286,7 +291,7 @@ void CBenchmarkDialog::OnRestartButton() void CBenchmarkDialog::OnStopButton() { - EnableItem(IDC_BUTTON_STOP, false); + EnableItem(IDB_STOP, false); Sync.Pause(); } @@ -302,13 +307,7 @@ void CBenchmarkDialog::OnCancel() 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 GetTimeString(UInt64 timeValue, wchar_t *s); void CBenchmarkDialog::PrintTime() { @@ -317,9 +316,9 @@ void CBenchmarkDialog::PrintTime() UInt32 elapsedSec = elapsedTime / 1000; if (elapsedSec != 0 && Sync.WasPaused()) return; - TCHAR s[40]; + WCHAR s[40]; GetTimeString(elapsedSec, s); - SetItemText(IDC_BENCHMARK_ELAPSED_VALUE, s); + SetItemText(IDT_BENCH_ELAPSED_VAL, s); } void CBenchmarkDialog::PrintRating(UInt64 rating, UINT controlID) @@ -347,19 +346,18 @@ void CBenchmarkDialog::PrintResults( if (info.GlobalTime == 0) return; - UInt64 size = info.UnpackSize; TCHAR s[40]; { - UInt64 speed = size * info.GlobalFreq / info.GlobalTime; + UInt64 speed = info.UnpackSize * info.NumIterations * 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); + rating = info.GetDecompressRating(); else - rating = GetCompressRating(dictionarySize, info.GlobalTime, info.GlobalFreq, size * info.NumIterations); + rating = info.GetCompressRating(dictionarySize); PrintRating(rating, ratingID); PrintRating(info.GetRatingPerUsage(rating), rpuID); @@ -391,71 +389,63 @@ bool CBenchmarkDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */) TCHAR s[40]; ConvertUInt64ToString((Sync.ProcessedSize >> 20), s); lstrcat(s, kMB); - SetItemText(IDC_BENCHMARK_SIZE_VALUE, s); + SetItemText(IDT_BENCH_SIZE_VAL, s); ConvertUInt64ToString(Sync.NumPasses, s); - SetItemText(IDC_BENCHMARK_PASSES_VALUE, s); - - /* - ConvertUInt64ToString(Sync.NumErrors, s); - SetItemText(IDC_BENCHMARK_ERRORS_VALUE, s); - */ + SetItemText(IDT_BENCH_PASSES_VAL, 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); + IDT_BENCH_COMPRESS_USAGE1, + IDT_BENCH_COMPRESS_SPEED1, + IDT_BENCH_COMPRESS_RPU1, + IDT_BENCH_COMPRESS_RATING1); } { PrintResults( Sync.DictionarySize, Sync.CompressingInfo, - IDC_BENCHMARK_COMPRESSING_USAGE2, - IDC_BENCHMARK_COMPRESSING_SPEED2, - IDC_BENCHMARK_COMPRESSING_RPU2, - IDC_BENCHMARK_COMPRESSING_RATING2); + IDT_BENCH_COMPRESS_USAGE2, + IDT_BENCH_COMPRESS_SPEED2, + IDT_BENCH_COMPRESS_RPU2, + IDT_BENCH_COMPRESS_RATING2); } { PrintResults( Sync.DictionarySize, Sync.DecompressingInfoTemp, - IDC_BENCHMARK_DECOMPRESSING_USAGE, - IDC_BENCHMARK_DECOMPRESSING_SPEED, - IDC_BENCHMARK_DECOMPRESSING_RPU, - IDC_BENCHMARK_DECOMPRESSING_RATING, + IDT_BENCH_DECOMPR_USAGE1, + IDT_BENCH_DECOMPR_SPEED1, + IDT_BENCH_DECOMPR_RPU1, + IDT_BENCH_DECOMPR_RATING1, true); } { PrintResults( Sync.DictionarySize, Sync.DecompressingInfo, - IDC_BENCHMARK_DECOMPRESSING_USAGE2, - IDC_BENCHMARK_DECOMPRESSING_SPEED2, - IDC_BENCHMARK_DECOMPRESSING_RPU2, - IDC_BENCHMARK_DECOMPRESSING_RATING2, + IDT_BENCH_DECOMPR_USAGE2, + IDT_BENCH_DECOMPR_SPEED2, + IDT_BENCH_DECOMPR_RPU2, + IDT_BENCH_DECOMPR_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); + UInt64 comprRating = Sync.CompressingInfo.GetCompressRating(Sync.DictionarySize); + UInt64 decomprRating = Sync.DecompressingInfo.GetDecompressRating(); + PrintRating((comprRating + decomprRating) / 2, IDT_BENCH_TOTAL_RATING_VAL); PrintRating(( Sync.CompressingInfo.GetRatingPerUsage(comprRating) + - Sync.DecompressingInfo.GetRatingPerUsage(decomprRating)) / 2, IDC_BENCHMARK_TOTAL_RPU_VALUE); + Sync.DecompressingInfo.GetRatingPerUsage(decomprRating)) / 2, IDT_BENCH_TOTAL_RPU_VAL); PrintUsage( (Sync.CompressingInfo.GetUsage() + - Sync.DecompressingInfo.GetUsage()) / 2, IDC_BENCHMARK_TOTAL_USAGE_VALUE); + Sync.DecompressingInfo.GetUsage()) / 2, IDT_BENCH_TOTAL_USAGE_VAL); } } return true; @@ -464,8 +454,8 @@ bool CBenchmarkDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */) bool CBenchmarkDialog::OnCommand(int code, int itemID, LPARAM lParam) { if (code == CBN_SELCHANGE && - (itemID == IDC_BENCHMARK_COMBO_DICTIONARY || - itemID == IDC_BENCHMARK_COMBO_NUM_THREADS)) + (itemID == IDC_BENCH_DICTIONARY || + itemID == IDC_BENCH_NUM_THREADS)) { OnChangeSettings(); return true; @@ -477,10 +467,10 @@ bool CBenchmarkDialog::OnButtonClicked(int buttonID, HWND buttonHWND) { switch(buttonID) { - case IDC_BUTTON_RESTART: + case IDB_RESTART: OnRestartButton(); return true; - case IDC_BUTTON_STOP: + case IDB_STOP: OnStopButton(); return true; } @@ -490,7 +480,7 @@ bool CBenchmarkDialog::OnButtonClicked(int buttonID, HWND buttonHWND) struct CThreadBenchmark { CBenchmarkDialog *BenchmarkDialog; - DECL_EXTERNAL_CODECS_VARS + DECL_EXTERNAL_CODECS_LOC_VARS2; // UInt32 dictionarySize; // UInt32 numThreads; @@ -507,16 +497,23 @@ struct CBenchCallback: public IBenchCallback { UInt32 dictionarySize; CProgressSyncInfo *Sync; + + HRESULT SetFreq(bool showFreq, UInt64 cpuFreq); HRESULT SetEncodeResult(const CBenchInfo &info, bool final); HRESULT SetDecodeResult(const CBenchInfo &info, bool final); }; +HRESULT CBenchCallback::SetFreq(bool /* showFreq */, UInt64 /* cpuFreq */) +{ + return S_OK; +} + 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; + Sync->ProcessedSize = info.UnpackSize * info.NumIterations; if (final && Sync->CompressingInfo.GlobalTime == 0) { (CBenchInfo&)Sync->CompressingInfo = info; @@ -535,13 +532,6 @@ HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final) 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; @@ -642,7 +632,7 @@ HRESULT CThreadBenchmark::Process() props.Add(prop); } } - result = Bench(EXTERNAL_CODECS_VARS + result = Bench(EXTERNAL_CODECS_LOC_VARS BenchmarkDialog->TotalMode ? &callback2 : NULL, BenchmarkDialog->TotalMode ? NULL : &callback, props, 1, false); @@ -660,7 +650,6 @@ HRESULT CThreadBenchmark::Process() { if (result != E_ABORT) { - // sync.NumErrors++; { NSynchronization::CCriticalSectionLock lock(sync.CS); sync.Pause(); @@ -695,27 +684,81 @@ HRESULT CThreadBenchmark::Process() } } +static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop) +{ + const wchar_t *end; + UInt64 result = ConvertStringToUInt64(s, &end); + if (*end != 0 || s.IsEmpty()) + prop = s; + else if (result <= (UInt32)0xFFFFFFFF) + prop = (UInt32)result; + else + prop = result; +} + HRESULT Benchmark( DECL_EXTERNAL_CODECS_LOC_VARS const CObjectVector props, HWND hwndParent) { CThreadBenchmark benchmarker; #ifdef EXTERNAL_CODECS - benchmarker._codecsInfo = codecsInfo; - benchmarker._externalCodecs = *externalCodecs; + benchmarker.__externalCodecs = __externalCodecs; #endif CBenchmarkDialog bd; bd.Props = props; bd.TotalMode = false; - for (int i = 0; i < props.Size(); i++) + bd.Sync.DictionarySize = (UInt32)(Int32)-1; + bd.Sync.NumThreads = (UInt32)(Int32)-1; + + COneMethodInfo method; + + UInt32 numCPUs = 1; + #ifndef _7ZIP_ST + numCPUs = NSystem::GetNumberOfProcessors(); + #endif + UInt32 numThreads = numCPUs; + + FOR_VECTOR (i, props) { const CProperty &prop = props[i]; - if (prop.Name.CompareNoCase(L"m") == 0 && prop.Value == L"*") + UString name = prop.Name; + name.MakeLower_Ascii(); + if (name.IsEqualToNoCase(L"m") && prop.Value == L"*") + { bd.TotalMode = true; + continue; + } + + NCOM::CPropVariant propVariant; + if (!prop.Value.IsEmpty()) + ParseNumberString(prop.Value, propVariant); + if (name.IsPrefixedBy(L"mt")) + { + #ifndef _7ZIP_ST + RINOK(ParseMtProp(name.Ptr(2), propVariant, numCPUs, numThreads)); + if (numThreads != numCPUs) + bd.Sync.NumThreads = numThreads; + #endif + continue; + } + if (name.IsEqualTo("testtime")) + { + // UInt32 testTime = 4; + // RINOK(ParsePropToUInt32(L"", propVariant, testTime)); + continue; + } + RINOK(method.ParseMethodFromPROPVARIANT(name, propVariant)); } - bd.Sync.DictionarySize = (UInt32)-1; - bd.Sync.NumThreads = (UInt32)-1; + + // bool totalBenchMode = (method.MethodName == L"*"); + + { + UInt32 dict; + if (method.Get_DicSize(dict)) + bd.Sync.DictionarySize = dict; + } + benchmarker.BenchmarkDialog = &bd; NWindows::CThread thread; diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.h b/CPP/7zip/UI/GUI/BenchmarkDialog.h old mode 100755 new mode 100644 index b3ab9dcb..82531117 --- a/CPP/7zip/UI/GUI/BenchmarkDialog.h +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.h @@ -3,9 +3,10 @@ #ifndef __BENCHMARK_DIALOG_H #define __BENCHMARK_DIALOG_H -#include "Windows/Synchronization.h" -#include "Windows/Control/ComboBox.h" -#include "Windows/Control/Edit.h" +#include "../../../Windows/Synchronization.h" + +#include "../../../Windows/Control/ComboBox.h" +#include "../../../Windows/Control/Edit.h" #include "../Common/Bench.h" @@ -16,6 +17,16 @@ struct CBenchInfo2 : public CBenchInfo { void Init() { GlobalTime = UserTime = 0; } + + UInt64 GetCompressRating(UInt32 dictSize) const + { + return ::GetCompressRating(dictSize, GlobalTime, GlobalFreq, UnpackSize * NumIterations); + } + + UInt64 GetDecompressRating() const + { + return ::GetDecompressRating(GlobalTime, GlobalFreq, UnpackSize, PackSize, NumIterations); + } }; class CProgressSyncInfo @@ -27,7 +38,6 @@ public: UInt32 DictionarySize; UInt32 NumThreads; UInt64 NumPasses; - // UInt64 NumErrors; NWindows::NSynchronization::CManualResetEvent _startEvent; NWindows::NSynchronization::CCriticalSection CS; @@ -59,7 +69,6 @@ public: DecompressingInfo.Init(); NumPasses = 0; - // NumErrors = 0; Text.Empty(); TextWasChanged = true; @@ -115,7 +124,7 @@ class CBenchmarkDialog: NWindows::NControl::CComboBox m_NumThreads; NWindows::NControl::CEdit _consoleEdit; UINT_PTR _timer; - UINT32 _startTime; + UInt32 _startTime; CMyFont _font; bool OnSize(WPARAM /* wParam */, int xSize, int ySize); @@ -132,7 +141,7 @@ class CBenchmarkDialog: void PrintRating(UInt64 rating, UINT controlID); void PrintUsage(UInt64 usage, UINT controlID); void PrintResults( - UINT32 dictionarySize, + UInt32 dictionarySize, const CBenchInfo2 &info, UINT usageID, UINT speedID, UINT rpuID, UINT ratingID, bool decompressMode = false); @@ -148,7 +157,7 @@ public: INT_PTR Create(HWND wndParent = 0) { BIG_DIALOG_SIZE(332, 228); - return CModalDialog::Create(TotalMode ? IDD_DIALOG_BENCHMARK_TOTAL : SIZED_DIALOG(IDD_DIALOG_BENCHMARK), wndParent); + return CModalDialog::Create(TotalMode ? IDD_BENCH_TOTAL : SIZED_DIALOG(IDD_BENCH), wndParent); } void MessageBoxError(LPCWSTR message) { diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.rc b/CPP/7zip/UI/GUI/BenchmarkDialog.rc old mode 100755 new mode 100644 index 6b17a12a..a31d2f25 --- a/CPP/7zip/UI/GUI/BenchmarkDialog.rc +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.rc @@ -48,69 +48,72 @@ #define GROUP_Y_SIZE 40 #endif -IDD_DIALOG_BENCHMARK DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE | WS_MINIMIZEBOX +IDD_BENCH 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 "&Restart", IDB_RESTART, bx1, m, bxs, bys + PUSHBUTTON "&Stop", IDB_STOP, bx1, m + bys + 6, bxs, bys - PUSHBUTTON "&Help", IDHELP, bx2, by, bxs, bys - PUSHBUTTON "Cancel", IDCANCEL, bx1, by, 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 + LTEXT "&Dictionary size:", IDT_BENCH_DICTIONARY, m, m + 1, g0xs, 8 + COMBOBOX IDC_BENCH_DICTIONARY, g1x, m, g1xs, 140, MY_COMBO + + LTEXT "Memory usage:", IDT_BENCH_MEMORY, gc2x, m + 1, gc2xs, 8 + LTEXT "", IDT_BENCH_MEMORY_VAL, gc2x + gc2xs, m + 1, 40, 8 + + LTEXT "&Number of CPU threads:", IDT_BENCH_NUM_THREADS, m, 28, g0xs, 8 + COMBOBOX IDC_BENCH_NUM_THREADS, g1x, 27, g1xs, 140, MY_COMBO + LTEXT "", IDT_BENCH_HARDWARE_THREADS, gc2x, 28, 40, 8 + + RTEXT "CPU Usage", IDT_BENCH_USAGE_LABEL, xUsage, 54, sUsage, 8 + RTEXT "Speed", IDT_BENCH_SPEED, xSpeed, 54, sSpeed, 8 + RTEXT "Rating / Usage", IDT_BENCH_RPU_LABEL, xRpu, 54, sRpu, 8 + RTEXT "Rating", IDT_BENCH_RATING_LABEL, xRating, 54, sRating, 8 - GROUPBOX "Compressing", IDC_BENCHMARK_COMPRESSING, m, 64, xc, GROUP_Y_SIZE + GROUPBOX "Compressing", IDG_BENCH_COMPRESSING, m, 64, xc, GROUP_Y_SIZE - 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 "Current", IDT_BENCH_CURRENT, g4x, 76, sLabel, 8 + RTEXT "", IDT_BENCH_COMPRESS_USAGE1, xUsage, 76, sUsage, 8 + RTEXT "", IDT_BENCH_COMPRESS_SPEED1, xSpeed, 76, sSpeed, 8 + RTEXT "", IDT_BENCH_COMPRESS_RPU1, xRpu, 76, sRpu, 8 + RTEXT "", IDT_BENCH_COMPRESS_RATING1, 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 + LTEXT "Resulting", IDT_BENCH_RESULTING, g4x, 89, sLabel, 8 + RTEXT "", IDT_BENCH_COMPRESS_USAGE2, xUsage, 89, sUsage, 8 + RTEXT "", IDT_BENCH_COMPRESS_SPEED2, xSpeed, 89, sSpeed, 8 + RTEXT "", IDT_BENCH_COMPRESS_RPU2, xRpu, 89, sRpu, 8 + RTEXT "", IDT_BENCH_COMPRESS_RATING2, xRating, 89, sRating, 8 - GROUPBOX "Decompressing", IDC_BENCHMARK_DECOMPRESSING, m, 111, xc, GROUP_Y_SIZE + GROUPBOX "Decompressing", IDG_BENCH_DECOMPRESSING, m, 111, xc, GROUP_Y_SIZE - 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 "Current", IDT_BENCH_CURRENT2, g4x, 123, sLabel, 8 + RTEXT "", IDT_BENCH_DECOMPR_USAGE1, xUsage, 123, sUsage, 8 + RTEXT "", IDT_BENCH_DECOMPR_SPEED1, xSpeed, 123, sSpeed, 8 + RTEXT "", IDT_BENCH_DECOMPR_RPU1, xRpu, 123, sRpu, 8 + RTEXT "", IDT_BENCH_DECOMPR_RATING1, 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 + LTEXT "Resulting", IDT_BENCH_RESULTING2, g4x, 136, sLabel, 8 + RTEXT "", IDT_BENCH_DECOMPR_USAGE2, xUsage, 136, sUsage, 8 + RTEXT "", IDT_BENCH_DECOMPR_SPEED2, xSpeed, 136, sSpeed, 8 + RTEXT "", IDT_BENCH_DECOMPR_RPU2, xRpu, 136, sRpu, 8 + RTEXT "", IDT_BENCH_DECOMPR_RATING2, xRating, 136, sRating, 8 - GROUPBOX "Total Rating", IDC_BENCHMARK_TOTAL_RATING, xTotalRating, 163, sTotalRating, GROUP_Y_SIZE - 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 + GROUPBOX "Total Rating", IDG_BENCH_TOTAL_RATING, xTotalRating, 163, sTotalRating, GROUP_Y_SIZE + + RTEXT "", IDT_BENCH_TOTAL_USAGE_VAL, xUsage, 181, sUsage, 8 + RTEXT "", IDT_BENCH_TOTAL_RPU_VAL, xRpu, 181, sRpu, 8 + RTEXT "", IDT_BENCH_TOTAL_RATING_VAL, xRating, 181, sRating, 8 - 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 + LTEXT "Elapsed time:", IDT_BENCH_ELAPSED, m, 163, g2xs, 8 + LTEXT "Size:", IDT_BENCH_SIZE, m, 176, g2xs, 8 + LTEXT "Passes:", IDT_BENCH_PASSES, m, 189, g2xs, 8 + + RTEXT "", IDT_BENCH_ELAPSED_VAL, g3x, 163, g3xs, 8 + RTEXT "", IDT_BENCH_SIZE_VAL, g3x, 176, g3xs, 8 + RTEXT "", IDT_BENCH_PASSES_VAL, g3x, 189, g3xs, 8 END #ifdef UNDER_CE @@ -177,57 +180,58 @@ END #define g2xs (g3x - m) -IDD_DIALOG_BENCHMARK_2 DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE | WS_MINIMIZEBOX +IDD_BENCH_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 + PUSHBUTTON "&Restart", IDB_RESTART, bx1, m, bxs, bys + PUSHBUTTON "&Stop", IDB_STOP, bx1, m + bys + m, bxs, bys + + PUSHBUTTON "Cancel", IDCANCEL, bx1, by, 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 "&Dictionary size:", IDT_BENCH_DICTIONARY, m, m, g0xs, 8 + COMBOBOX IDC_BENCH_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 "&Number of CPU threads:", IDT_BENCH_NUM_THREADS, m, 31, g0xs, 8 + COMBOBOX IDC_BENCH_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 "", IDT_BENCH_MEMORY_VAL, m + g1xs + 8, m + 13, xc - bxs - g1xs - 8, 8 + LTEXT "", IDT_BENCH_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 "Current", IDT_BENCH_CURRENT, g4x, 70, sLabel, 8 + RTEXT "", IDT_BENCH_COMPRESS_USAGE1, xUsage, 70, sUsage, 8 + RTEXT "", IDT_BENCH_COMPRESS_RPU1, xRpu, 70, sRpu, 8 + RTEXT "", IDT_BENCH_COMPRESS_RATING1, 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 "Resulting", IDT_BENCH_RESULTING, g4x, 80, sLabel, 8 + RTEXT "", IDT_BENCH_COMPRESS_USAGE2, xUsage, 80, sUsage, 8 + RTEXT "", IDT_BENCH_COMPRESS_RPU2, xRpu, 80, sRpu, 8 + RTEXT "", IDT_BENCH_COMPRESS_RATING2, xRating, 80, sRating, 8 - LTEXT "Compressing", IDC_BENCHMARK_COMPRESSING, m, 60, xc - bxs, 8 + LTEXT "Compressing", IDG_BENCH_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 "Current", IDT_BENCH_CURRENT2, g4x, 104, sLabel, 8 + RTEXT "", IDT_BENCH_DECOMPR_USAGE1, xUsage, 104, sUsage, 8 + RTEXT "", IDT_BENCH_DECOMPR_RPU1, xRpu, 104, sRpu, 8 + RTEXT "", IDT_BENCH_DECOMPR_RATING1, 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 "Resulting", IDT_BENCH_RESULTING2, g4x, 114, sLabel, 8 + RTEXT "", IDT_BENCH_DECOMPR_USAGE2, xUsage, 114, sUsage, 8 + RTEXT "", IDT_BENCH_DECOMPR_RPU2, xRpu, 114, sRpu, 8 + RTEXT "", IDT_BENCH_DECOMPR_RATING2, xRating, 114, sRating, 8 - LTEXT "Decompressing", IDC_BENCHMARK_DECOMPRESSING, m, 94, xc, 8 + LTEXT "Decompressing", IDG_BENCH_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 + RTEXT "", IDT_BENCH_TOTAL_RPU_VAL, xRpu, 140, sRpu, 8 + RTEXT "", IDT_BENCH_TOTAL_RATING_VAL, 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 + LTEXT "Elapsed time:", IDT_BENCH_ELAPSED, m, 130, g2xs, 8 + LTEXT "Size:", IDT_BENCH_SIZE, m, 140, g2xs, 8 + LTEXT "Passes:", IDT_BENCH_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 + RTEXT "", IDT_BENCH_ELAPSED_VAL, g3x, 130, g3xs, 8 + RTEXT "", IDT_BENCH_SIZE_VAL, g3x, 140, g3xs, 8 + RTEXT "", IDT_BENCH_PASSES_VAL, g3x, 150, g3xs, 8 END #endif @@ -237,12 +241,12 @@ END #define xc 360 #define yc 260 -IDD_DIALOG_BENCHMARK_TOTAL MY_RESIZE_DIALOG +IDD_BENCH_TOTAL DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT CAPTION "Benchmark" { - LTEXT "Elapsed time:", IDC_BENCHMARK_ELAPSED, m, m, 58, 8 - RTEXT "00:00:00", IDC_BENCHMARK_ELAPSED_VALUE, m + 58, m, 38, 8 - EDITTEXT IDC_BENCHMARK2_EDIT, m, m + 14, xc, yc - bys - m - 14, ES_MULTILINE | ES_READONLY | ES_AUTOVSCROLL | WS_VSCROLL | WS_HSCROLL - PUSHBUTTON "&Help", IDHELP, bx2, by, bxs, bys - PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys + LTEXT "Elapsed time:", IDT_BENCH_ELAPSED, m, m, 58, 8 + RTEXT "", IDT_BENCH_ELAPSED_VAL, m + 58, m, 38, 8 + EDITTEXT IDE_BENCH2_EDIT, m, m + 14, xc, yc - bys - m - 14, ES_MULTILINE | ES_READONLY | ES_AUTOVSCROLL | WS_VSCROLL | WS_HSCROLL + PUSHBUTTON "&Help", IDHELP, bx2, by, bxs, bys + PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys } diff --git a/CPP/7zip/UI/GUI/BenchmarkDialogRes.h b/CPP/7zip/UI/GUI/BenchmarkDialogRes.h old mode 100755 new mode 100644 index cf009df3..7dd6d031 --- a/CPP/7zip/UI/GUI/BenchmarkDialogRes.h +++ b/CPP/7zip/UI/GUI/BenchmarkDialogRes.h @@ -1,59 +1,62 @@ -#define IDD_DIALOG_BENCHMARK 550 -#define IDD_DIALOG_BENCHMARK_2 650 -#define IDD_DIALOG_BENCHMARK_TOTAL 750 -#define IDD_DIALOG_BENCHMARK_TOTAL_2 750 -#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 - -#define IDC_BENCHMARK2_EDIT 1090 +#define IDD_BENCH 7600 +#define IDD_BENCH_2 17600 +#define IDD_BENCH_TOTAL 7699 + +#define IDE_BENCH2_EDIT 100 + +#define IDC_BENCH_DICTIONARY 101 +#define IDT_BENCH_MEMORY_VAL 102 +#define IDC_BENCH_NUM_THREADS 103 +#define IDT_BENCH_HARDWARE_THREADS 104 + +#define IDT_BENCH_COMPRESS_SPEED1 110 +#define IDT_BENCH_COMPRESS_SPEED2 111 +#define IDT_BENCH_COMPRESS_RATING1 112 +#define IDT_BENCH_COMPRESS_RATING2 113 +#define IDT_BENCH_COMPRESS_USAGE1 114 +#define IDT_BENCH_COMPRESS_USAGE2 115 +#define IDT_BENCH_COMPRESS_RPU1 116 +#define IDT_BENCH_COMPRESS_RPU2 117 + +#define IDT_BENCH_DECOMPR_SPEED1 118 +#define IDT_BENCH_DECOMPR_SPEED2 119 +#define IDT_BENCH_DECOMPR_RATING1 120 +#define IDT_BENCH_DECOMPR_RATING2 121 +#define IDT_BENCH_DECOMPR_USAGE1 122 +#define IDT_BENCH_DECOMPR_USAGE2 123 +#define IDT_BENCH_DECOMPR_RPU1 124 +#define IDT_BENCH_DECOMPR_RPU2 125 + +#define IDT_BENCH_TOTAL_RATING_VAL 130 +#define IDT_BENCH_TOTAL_RPU_VAL 131 +#define IDT_BENCH_TOTAL_USAGE_VAL 133 + +#define IDT_BENCH_ELAPSED_VAL 140 +#define IDT_BENCH_SIZE_VAL 141 +#define IDT_BENCH_PASSES_VAL 142 + + +#define IDB_STOP 442 +#define IDB_RESTART 443 + +#define IDT_BENCH_DICTIONARY 4006 +#define IDT_BENCH_NUM_THREADS 4009 + +#define IDT_BENCH_SIZE 1007 +#define IDT_BENCH_ELAPSED 3900 +#define IDT_BENCH_SPEED 3903 + +#define IDT_BENCH_MEMORY 7601 + +#define IDG_BENCH_COMPRESSING 7602 +#define IDG_BENCH_DECOMPRESSING 7603 +#define IDG_BENCH_TOTAL_RATING 7605 + +#define IDT_BENCH_RATING_LABEL 7604 +#define IDT_BENCH_CURRENT 7606 +#define IDT_BENCH_RESULTING 7607 +#define IDT_BENCH_USAGE_LABEL 7608 +#define IDT_BENCH_RPU_LABEL 7609 +#define IDT_BENCH_PASSES 7610 +#define IDT_BENCH_CURRENT2 (7606+50) +#define IDT_BENCH_RESULTING2 (7607+50) diff --git a/CPP/7zip/UI/GUI/CompressDialog.cpp b/CPP/7zip/UI/GUI/CompressDialog.cpp old mode 100755 new mode 100644 index 2723f515..a2d0ac2b --- a/CPP/7zip/UI/GUI/CompressDialog.cpp +++ b/CPP/7zip/UI/GUI/CompressDialog.cpp @@ -2,12 +2,12 @@ #include "StdAfx.h" -#include "Common/IntToString.h" -#include "Common/StringConvert.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" -#include "Windows/FileDir.h" -#include "Windows/FileName.h" -#include "Windows/System.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/System.h" #include "../FileManager/BrowseDialog.h" #include "../FileManager/FormatUtils.h" @@ -29,81 +29,70 @@ extern bool g_IsNT; #endif #include "CompressDialogRes.h" - -#define MY_SIZE_OF_ARRAY(x) (sizeof(x) / sizeof(x[0])) +#include "ExtractRes.h" #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 }, +static const UInt32 kLangIDs[] = +{ + IDT_COMPRESS_ARCHIVE, + IDT_COMPRESS_UPDATE_MODE, + IDT_COMPRESS_FORMAT, + IDT_COMPRESS_LEVEL, + IDT_COMPRESS_METHOD, + IDT_COMPRESS_DICTIONARY, + IDT_COMPRESS_ORDER, + IDT_COMPRESS_SOLID, + IDT_COMPRESS_THREADS, + IDT_COMPRESS_PARAMETERS, - { 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 } + IDG_COMPRESS_OPTIONS, + IDX_COMPRESS_SFX, + IDX_COMPRESS_SHARED, + IDX_COMPRESS_DEL, + + IDT_COMPRESS_MEMORY, + IDT_COMPRESS_MEMORY_DE, + + IDX_COMPRESS_NT_SYM_LINKS, + IDX_COMPRESS_NT_HARD_LINKS, + IDX_COMPRESS_NT_ALT_STREAMS, + IDX_COMPRESS_NT_SECUR, + + IDG_COMPRESS_ENCRYPTION, + IDT_COMPRESS_ENCRYPTION_METHOD, + IDX_COMPRESS_ENCRYPT_FILE_NAMES, + + IDT_PASSWORD_ENTER, + IDT_PASSWORD_REENTER, + IDX_PASSWORD_SHOW, + + IDT_SPLIT_TO_VOLUMES, + IDT_COMPRESS_PATH_MODE }; #endif using namespace NWindows; using namespace NFile; using namespace NName; -using namespace NDirectory; +using namespace NDir; static const int kHistorySize = 20; static LPCWSTR kExeExt = L".exe"; static LPCWSTR k7zFormat = L"7z"; -struct CLevelInfo +static const UInt32 g_Levels[] = { - 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 } + IDS_METHOD_STORE, + IDS_METHOD_FASTEST, + 0, + IDS_METHOD_FAST, + 0, + IDS_METHOD_NORMAL, + 0, + IDS_METHOD_MAXIMUM, + 0, + IDS_METHOD_ULTRA }; enum EMethodID @@ -132,8 +121,8 @@ static const LPCWSTR kMethodsNames[] = static const EMethodID g_7zMethods[] = { - kLZMA, kLZMA2, + kLZMA, kPPMd, kBZip2 }; @@ -146,7 +135,7 @@ static const EMethodID g_7zSfxMethods[] = kPPMd }; -static EMethodID g_ZipMethods[] = +static const EMethodID g_ZipMethods[] = { kDeflate, kDeflate64, @@ -155,21 +144,27 @@ static EMethodID g_ZipMethods[] = kPPMdZip }; -static EMethodID g_GZipMethods[] = +static const EMethodID g_GZipMethods[] = { kDeflate }; -static EMethodID g_BZip2Methods[] = +static const EMethodID g_BZip2Methods[] = { kBZip2 }; -static EMethodID g_XzMethods[] = +static const EMethodID g_XzMethods[] = { kLZMA2 }; +static const EMethodID g_SwfcMethods[] = +{ + kDeflate + // kLZMA +}; + struct CFormatInfo { LPCWSTR Name; @@ -180,11 +175,12 @@ struct CFormatInfo bool Solid; bool MultiThread; bool SFX; + bool Encrypt; bool EncryptFileNames; }; -#define METHODS_PAIR(x) x, MY_SIZE_OF_ARRAY(x) +#define METHODS_PAIR(x) x, ARRAY_SIZE(x) static const CFormatInfo g_Formats[] = { @@ -224,6 +220,12 @@ static const CFormatInfo g_Formats[] = METHODS_PAIR(g_XzMethods), false, false, true, false, false, false }, + { + L"Swfc", + (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), + METHODS_PAIR(g_SwfcMethods), + false, false, true, false, false, false + }, { L"Tar", (1 << 0), @@ -240,7 +242,7 @@ static const CFormatInfo g_Formats[] = static bool IsMethodSupportedBySfx(int methodID) { - for (int i = 0; i < MY_SIZE_OF_ARRAY(g_7zSfxMethods); i++) + for (int i = 0; i < ARRAY_SIZE(g_7zSfxMethods); i++) if (methodID == g_7zSfxMethods[i]) return true; return false; @@ -260,81 +262,156 @@ static UInt64 GetMaxRamSizeForProgram() return physSize; } + +static const + // NCompressDialog::NUpdateMode::EEnum + int + k_UpdateMode_Vals[] = +{ + NCompressDialog::NUpdateMode::kAdd, + NCompressDialog::NUpdateMode::kUpdate, + NCompressDialog::NUpdateMode::kFresh, + NCompressDialog::NUpdateMode::kSync +}; + +static const UInt32 k_UpdateMode_IDs[] = +{ + IDS_COMPRESS_UPDATE_MODE_ADD, + IDS_COMPRESS_UPDATE_MODE_UPDATE, + IDS_COMPRESS_UPDATE_MODE_FRESH, + IDS_COMPRESS_UPDATE_MODE_SYNC +}; + +static const + // NWildcard::ECensorPathMode + int + k_PathMode_Vals[] = +{ + NWildcard::k_RelatPath, + NWildcard::k_FullPath, + NWildcard::k_AbsPath, +}; + +static const UInt32 k_PathMode_IDs[] = +{ + IDS_PATH_MODE_RELAT, + IDS_EXTRACT_PATHS_FULL, + IDS_EXTRACT_PATHS_ABS +}; + +void AddComboItems(NControl::CComboBox &combo, const UInt32 *langIDs, unsigned numItems, const int *values, int curVal); +bool GetBoolsVal(const CBoolPair &b1, const CBoolPair &b2); + +void CCompressDialog::CheckButton_TwoBools(UINT id, const CBoolPair &b1, const CBoolPair &b2) +{ + CheckButton(id, GetBoolsVal(b1, b2)); +} + +void CCompressDialog::GetButton_Bools(UINT id, CBoolPair &b1, CBoolPair &b2) +{ + bool val = IsButtonCheckedBool(id); + bool oldVal = GetBoolsVal(b1, b2); + if (val != oldVal) + b1.Def = b2.Def = true; + b1.Val = b2.Val = val; +} + + bool CCompressDialog::OnInit() { #ifdef LANG - LangSetWindowText(HWND(*this), 0x02000D00); - LangSetDlgItemsText(HWND(*this), kIDLangPairs, MY_SIZE_OF_ARRAY(kIDLangPairs) ); + LangSetWindowText(*this, IDD_COMPRESS); + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); #endif - _password1Control.Attach(GetItem(IDC_COMPRESS_EDIT_PASSWORD1)); - _password2Control.Attach(GetItem(IDC_COMPRESS_EDIT_PASSWORD2)); + + _password1Control.Attach(GetItem(IDE_COMPRESS_PASSWORD1)); + _password2Control.Attach(GetItem(IDE_COMPRESS_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)); + _encryptionMethod.Attach(GetItem(IDC_COMPRESS_ENCRYPTION_METHOD)); + + m_ArchivePath.Attach(GetItem(IDC_COMPRESS_ARCHIVE)); + m_Format.Attach(GetItem(IDC_COMPRESS_FORMAT)); + m_Level.Attach(GetItem(IDC_COMPRESS_LEVEL)); + m_Method.Attach(GetItem(IDC_COMPRESS_METHOD)); + m_Dictionary.Attach(GetItem(IDC_COMPRESS_DICTIONARY)); + m_Order.Attach(GetItem(IDC_COMPRESS_ORDER)); + m_Solid.Attach(GetItem(IDC_COMPRESS_SOLID)); + m_NumThreads.Attach(GetItem(IDC_COMPRESS_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)); + m_UpdateMode.Attach(GetItem(IDC_COMPRESS_UPDATE_MODE)); + m_PathMode.Attach(GetItem(IDC_COMPRESS_PATH_MODE)); + + m_Volume.Attach(GetItem(IDC_COMPRESS_VOLUME)); + m_Params.Attach(GetItem(IDE_COMPRESS_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); + CheckButton(IDX_PASSWORD_SHOW, m_RegistryInfo.ShowPassword); + CheckButton(IDX_COMPRESS_ENCRYPT_FILE_NAMES, m_RegistryInfo.EncryptHeaders); + + CheckButton_TwoBools(IDX_COMPRESS_NT_SYM_LINKS, Info.SymLinks, m_RegistryInfo.SymLinks); + CheckButton_TwoBools(IDX_COMPRESS_NT_HARD_LINKS, Info.HardLinks, m_RegistryInfo.HardLinks); + CheckButton_TwoBools(IDX_COMPRESS_NT_ALT_STREAMS, Info.AltStreams, m_RegistryInfo.AltStreams); + CheckButton_TwoBools(IDX_COMPRESS_NT_SECUR, Info.NtSecurity, m_RegistryInfo.NtSecurity); 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) + bool needSetMain = (Info.FormatIndex < 0); + FOR_VECTOR(i, ArcIndices) { - m_Format.SetCurSel(index); - Info.FormatIndex = arcIndex; + unsigned arcIndex = ArcIndices[i]; + const CArcInfoEx &ai = (*ArcFormats)[arcIndex]; + int index = (int)m_Format.AddString(ai.Name); + m_Format.SetItemData(index, arcIndex); + if (!needSetMain) + { + if (Info.FormatIndex == (int)arcIndex) + m_Format.SetCurSel(index); + continue; + } + if (i == 0 || ai.Name.IsEqualToNoCase(m_RegistryInfo.ArcType)) + { + m_Format.SetCurSel(index); + Info.FormatIndex = arcIndex; + } } } - SetArchiveName(Info.ArchiveName); + { + UString fileName; + SetArcPathFields(Info.ArcPath, fileName, true); + StartDirPrefix = DirPrefix; + SetArchiveName(fileName); + } SetLevel(); SetParams(); - for (i = 0; i < m_RegistryInfo.ArcPaths.Size() && i < kHistorySize; i++) + for (unsigned 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)); + AddComboItems(m_UpdateMode, k_UpdateMode_IDs, ARRAY_SIZE(k_UpdateMode_IDs), + k_UpdateMode_Vals, Info.UpdateMode); - m_UpdateMode.SetCurSel(0); + AddComboItems(m_PathMode, k_PathMode_IDs, ARRAY_SIZE(k_PathMode_IDs), + k_PathMode_Vals, Info.PathMode); SetSolidBlockSize(); SetNumThreads(); TCHAR s[40] = { TEXT('/'), TEXT(' '), 0 }; ConvertUInt32ToString(NSystem::GetNumberOfProcessors(), s + 2); - SetItemText(IDC_COMPRESS_HARDWARE_THREADS, s); + SetItemText(IDT_COMPRESS_HARDWARE_THREADS, s); + + CheckButton(IDX_COMPRESS_SFX, Info.SFXMode); + CheckButton(IDX_COMPRESS_SHARED, Info.OpenShareForWrite); + CheckButton(IDX_COMPRESS_DEL, Info.DeleteAfterCompressing); - CheckButton(IDC_COMPRESS_SFX, Info.SFXMode); - CheckButton(IDC_COMPRESS_SHARED, Info.OpenShareForWrite); - CheckControlsEnable(); - OnButtonSFX(); + // OnButtonSFX(); SetEncryptionMethod(); SetMemoryUsage(); @@ -344,12 +421,13 @@ bool CCompressDialog::OnInit() return CModalDialog::OnInit(); } +/* namespace NCompressDialog { bool CInfo::GetFullPathName(UString &result) const { #ifndef UNDER_CE - NDirectory::MySetCurrentDirectory(CurrentDirPrefix); + // NDirectory::MySetCurrentDirectory(CurrentDirPrefix); #endif FString resultF; bool res = MyGetFullPathName(us2fs(ArchiveName), resultF); @@ -357,11 +435,12 @@ namespace NCompressDialog return res; } } +*/ void CCompressDialog::UpdatePasswordControl() { bool showPassword = IsShowPasswordChecked(); - TCHAR c = showPassword ? 0: TEXT('*'); + TCHAR c = showPassword ? (TCHAR)0: TEXT('*'); _password1Control.SetPasswordChar(c); _password2Control.SetPasswordChar(c); UString password; @@ -370,27 +449,27 @@ void CCompressDialog::UpdatePasswordControl() _password2Control.GetText(password); _password2Control.SetText(password); - int cmdShow = showPassword ? SW_HIDE : SW_SHOW; - ShowItem(IDC_STATIC_COMPRESS_PASSWORD2, cmdShow); - _password2Control.Show(cmdShow); + ShowItem_Bool(IDT_PASSWORD_REENTER, !showPassword); + _password2Control.Show_Bool(!showPassword); } bool CCompressDialog::OnButtonClicked(int buttonID, HWND buttonHWND) { switch(buttonID) { - case IDC_COMPRESS_BUTTON_SET_ARCHIVE: + case IDB_COMPRESS_SET_ARCHIVE: { OnButtonSetArchive(); return true; } - case IDC_COMPRESS_SFX: + case IDX_COMPRESS_SFX: { + SetMethod(GetMethodID()); OnButtonSFX(); SetMemoryUsage(); return true; } - case IDC_COMPRESS_CHECK_SHOW_PASSWORD: + case IDX_PASSWORD_SHOW: { UpdatePasswordControl(); return true; @@ -409,10 +488,11 @@ void CCompressDialog::CheckSFXControlsEnable() enable = (methodID == -1 || IsMethodSupportedBySfx(methodID)); } if (!enable) - CheckButton(IDC_COMPRESS_SFX, false); - EnableItem(IDC_COMPRESS_SFX, enable); + CheckButton(IDX_COMPRESS_SFX, false); + EnableItem(IDX_COMPRESS_SFX, enable); } +/* void CCompressDialog::CheckVolumeEnable() { bool isSFX = IsSFX(); @@ -420,6 +500,7 @@ void CCompressDialog::CheckVolumeEnable() if (isSFX) m_Volume.SetText(TEXT("")); } +*/ void CCompressDialog::CheckControlsEnable() { @@ -429,46 +510,66 @@ void CCompressDialog::CheckControlsEnable() Info.MultiThreadIsAllowed = multiThreadEnable; Info.EncryptHeadersIsAllowed = fi.EncryptFileNames; - EnableItem(IDC_COMPRESS_COMBO_SOLID, fi.Solid); - EnableItem(IDC_COMPRESS_COMBO_THREADS, multiThreadEnable); + EnableItem(IDC_COMPRESS_SOLID, fi.Solid); + EnableItem(IDC_COMPRESS_THREADS, multiThreadEnable); + CheckSFXControlsEnable(); - CheckVolumeEnable(); - EnableItem(IDC_COMPRESS_ENCRYPTION, fi.Encrypt); + { + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + + ShowItem_Bool(IDX_COMPRESS_NT_SYM_LINKS, ai.Flags_SymLinks()); + ShowItem_Bool(IDX_COMPRESS_NT_HARD_LINKS, ai.Flags_HardLinks()); + ShowItem_Bool(IDX_COMPRESS_NT_ALT_STREAMS, ai.Flags_AltStreams()); + ShowItem_Bool(IDX_COMPRESS_NT_SECUR, ai.Flags_NtSecure()); + + ShowItem_Bool(IDG_COMPRESS_NTFS, + ai.Flags_SymLinks() + || ai.Flags_HardLinks() + || ai.Flags_AltStreams() + || ai.Flags_NtSecure()); + } + // CheckVolumeEnable(); + + EnableItem(IDG_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(IDT_PASSWORD_ENTER, fi.Encrypt); + EnableItem(IDT_PASSWORD_REENTER, fi.Encrypt); + EnableItem(IDE_COMPRESS_PASSWORD1, fi.Encrypt); + EnableItem(IDE_COMPRESS_PASSWORD2, fi.Encrypt); + EnableItem(IDX_PASSWORD_SHOW, 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); + EnableItem(IDT_COMPRESS_ENCRYPTION_METHOD, fi.Encrypt); + EnableItem(IDC_COMPRESS_ENCRYPTION_METHOD, fi.Encrypt); + EnableItem(IDX_COMPRESS_ENCRYPT_FILE_NAMES, fi.EncryptFileNames); - ShowItem(IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES, fi.EncryptFileNames ? SW_SHOW : SW_HIDE); + ShowItem_Bool(IDX_COMPRESS_ENCRYPT_FILE_NAMES, fi.EncryptFileNames); } bool CCompressDialog::IsSFX() { - CWindow sfxButton = GetItem(IDC_COMPRESS_SFX); - return sfxButton.IsEnabled() && IsButtonCheckedBool(IDC_COMPRESS_SFX); + CWindow sfxButton = GetItem(IDX_COMPRESS_SFX); + return sfxButton.IsEnabled() && IsButtonCheckedBool(IDX_COMPRESS_SFX); } -void CCompressDialog::OnButtonSFX() +static int GetExtDotPos(const UString &s) { - SetMethod(GetMethodID()); + int dotPos = s.ReverseFind('.'); + int slashPos = MyMax(s.ReverseFind(WCHAR_PATH_SEPARATOR), s.ReverseFind('/')); + if (dotPos >= 0 && dotPos > slashPos + 1) + return dotPos; + return -1; +} +void CCompressDialog::OnButtonSFX() +{ 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; + int dotPos = GetExtDotPos(fileName); if (IsSFX()) { if (dotPos >= 0) - fileName = fileName.Left(dotPos); + fileName.DeleteFrom(dotPos); fileName += kExeExt; m_ArchivePath.SetText(fileName); } @@ -476,38 +577,92 @@ void CCompressDialog::OnButtonSFX() { if (dotPos >= 0) { - UString ext = fileName.Mid(dotPos); - if (ext.CompareNoCase(kExeExt) == 0) + UString ext = fileName.Ptr(dotPos); + if (ext.IsEqualToNoCase(kExeExt)) { - fileName = fileName.Left(dotPos); + fileName.DeleteFrom(dotPos); m_ArchivePath.SetText(fileName); } } SetArchiveName2(false); // it's for OnInit } - CheckVolumeEnable(); + // CheckVolumeEnable(); } +bool CCompressDialog::GetFinalPath_Smart(UString &resPath) +{ + UString name; + m_ArchivePath.GetText(name); + name.Trim(); + UString tempPath = name; + if (!IsAbsolutePath(name)) + { + UString newDirPrefix = DirPrefix; + if (newDirPrefix.IsEmpty()) + newDirPrefix = StartDirPrefix; + FString resultF; + if (!MyGetFullPathName(us2fs(newDirPrefix + name), resultF)) + return false; + tempPath = fs2us(resultF); + } + if (!SetArcPathFields(tempPath, name, false)) + return false; + FString resultF; + if (!MyGetFullPathName(us2fs(DirPrefix + name), resultF)) + return false; + resPath = fs2us(resultF); + return true; +} + +bool CCompressDialog::SetArcPathFields(const UString &path, UString &name, bool always) +{ + FString resDirPrefix; + FString resFileName; + bool res = GetFullPathAndSplit(us2fs(path), resDirPrefix, resFileName); + if (res) + { + DirPrefix = fs2us(resDirPrefix); + name = fs2us(resFileName); + } + else + { + if (!always) + return false; + DirPrefix.Empty(); + name = path; + } + SetItemText(IDT_COMPRESS_ARCHIVE_FOLDER, DirPrefix); + m_ArchivePath.SetText(name); + return res; +} + +static const wchar_t *k_IncorrectPathMessage = L"Incorrect archive path"; + void CCompressDialog::OnButtonSetArchive() { - UString fileName; - m_ArchivePath.GetText(fileName); - fileName.Trim(); - Info.ArchiveName = fileName; - UString fullFileName; - if (!Info.GetFullPathName(fullFileName)) + UString path; + if (!GetFinalPath_Smart(path)) { - fullFileName = Info.ArchiveName; + ShowErrorMessage(*this, k_IncorrectPathMessage); return; } - UString title = LangString(IDS_COMPRESS_SET_ARCHIVE_DIALOG_TITLE, 0x02000D90); - UString s = LangString(IDS_OPEN_TYPE_ALL_FILES, 0x02000DB1); - s += L" (*.*)"; + + UString title = LangString(IDS_COMPRESS_SET_ARCHIVE_BROWSE); + UString filterDescription = LangString(IDS_OPEN_TYPE_ALL_FILES); + filterDescription += L" (*.*)"; UString resPath; - if (!MyBrowseForFile(HWND(*this), title, fullFileName, s, resPath)) + CurrentDirWasChanged = true; + if (!MyBrowseForFile(*this, title, + // DirPrefix.IsEmpty() ? NULL : (const wchar_t *)DirPrefix, + // NULL, + path, + filterDescription, + NULL, // L"*.*", + resPath)) return; - m_ArchivePath.SetText(resPath); + UString dummyName; + SetArcPathFields(resPath, dummyName, true); } // in ExtractDialog.cpp @@ -515,7 +670,7 @@ extern void AddUniqueString(UStringVector &strings, const UString &srcString); static bool IsAsciiString(const UString &s) { - for (int i = 0; i < s.Length(); i++) + for (unsigned i = 0; i < s.Len(); i++) { wchar_t c = s[i]; if (c < 0x20 || c > 0x7F) @@ -531,16 +686,16 @@ void CCompressDialog::OnOK() { if (!IsAsciiString(Info.Password)) { - ShowErrorMessageHwndRes(*this, IDS_PASSWORD_USE_ASCII, 0x02000B11); + ShowErrorMessageHwndRes(*this, IDS_PASSWORD_USE_ASCII); return; } UString method = GetEncryptionMethodSpec(); - method.MakeUpper(); - if (method.Find(L"AES") == 0) + method.MakeLower_Ascii(); + if (method.Find(L"aes") == 0) { - if (Info.Password.Length() > 99) + if (Info.Password.Len() > 99) { - ShowErrorMessageHwndRes(*this, IDS_PASSWORD_IS_TOO_LONG, 0x02000B12); + ShowErrorMessageHwndRes(*this, IDS_PASSWORD_TOO_LONG); return; } } @@ -551,19 +706,25 @@ void CCompressDialog::OnOK() _password2Control.GetText(password2); if (password2 != Info.Password) { - ShowErrorMessageHwndRes(*this, IDS_PASSWORD_PASSWORDS_DO_NOT_MATCH, 0x02000B10); + ShowErrorMessageHwndRes(*this, IDS_PASSWORD_NOT_MATCH); return; } } SaveOptionsInMem(); UString s; - m_ArchivePath.GetText(s); - s.Trim(); + if (!GetFinalPath_Smart(s)) + { + ShowErrorMessage(*this, k_IncorrectPathMessage); + return; + } + m_RegistryInfo.ArcPaths.Clear(); AddUniqueString(m_RegistryInfo.ArcPaths, s); - Info.ArchiveName = s; - Info.UpdateMode = NCompressDialog::NUpdateMode::EEnum(m_UpdateMode.GetCurSel()); + Info.ArcPath = s; + + Info.UpdateMode = (NCompressDialog::NUpdateMode::EEnum)k_UpdateMode_Vals[m_UpdateMode.GetCurSel()];; + Info.PathMode = (NWildcard::ECensorPathMode)k_PathMode_Vals[m_PathMode.GetCurSel()]; Info.Level = GetLevelSpec(); Info.Dictionary = GetDictionarySpec(); @@ -573,27 +734,45 @@ void CCompressDialog::OnOK() UInt32 solidLogSize = GetBlockSizeSpec(); Info.SolidBlockSize = 0; - if (solidLogSize > 0 && solidLogSize != (UInt32)-1) + if (solidLogSize > 0 && solidLogSize != (UInt32)(Int32)-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); + Info.OpenShareForWrite = IsButtonCheckedBool(IDX_COMPRESS_SHARED); + Info.DeleteAfterCompressing = IsButtonCheckedBool(IDX_COMPRESS_DEL); - m_RegistryInfo.EncryptHeaders = Info.EncryptHeaders = IsButtonCheckedBool(IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES); + m_RegistryInfo.EncryptHeaders = + Info.EncryptHeaders = IsButtonCheckedBool(IDX_COMPRESS_ENCRYPT_FILE_NAMES); + + + GetButton_Bools(IDX_COMPRESS_NT_SYM_LINKS, Info.SymLinks, m_RegistryInfo.SymLinks); + GetButton_Bools(IDX_COMPRESS_NT_HARD_LINKS, Info.HardLinks, m_RegistryInfo.HardLinks); + GetButton_Bools(IDX_COMPRESS_NT_ALT_STREAMS, Info.AltStreams, m_RegistryInfo.AltStreams); + GetButton_Bools(IDX_COMPRESS_NT_SECUR, Info.NtSecurity, m_RegistryInfo.NtSecurity); + + { + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + if (!ai.Flags_SymLinks()) Info.SymLinks.Val = false; + if (!ai.Flags_HardLinks()) Info.HardLinks.Val = false; + if (!ai.Flags_AltStreams()) Info.AltStreams.Val = false; + if (!ai.Flags_NtSecure()) Info.NtSecurity.Val = false; + } 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); + ShowErrorMessageHwndRes(*this, IDS_INCORRECT_VOLUME_SIZE); return; } if (!Info.VolumeSizes.IsEmpty()) @@ -603,7 +782,7 @@ void CCompressDialog::OnOK() { wchar_t s[32]; ConvertUInt64ToString(volumeSize, s); - if (::MessageBoxW(*this, MyFormatNew(IDS_COMPRESS_SPLIT_CONFIRM_MESSAGE, 0x02000D42, s), + if (::MessageBoxW(*this, MyFormatNew(IDS_SPLIT_CONFIRM, s), L"7-Zip", MB_YESNOCANCEL | MB_ICONQUESTION) != IDYES) return; } @@ -617,10 +796,12 @@ void CCompressDialog::OnOK() sTemp.Trim(); AddUniqueString(m_RegistryInfo.ArcPaths, sTemp); } + if (m_RegistryInfo.ArcPaths.Size() > kHistorySize) m_RegistryInfo.ArcPaths.DeleteBack(); - m_RegistryInfo.ArcType = (*ArcFormats)[Info.FormatIndex].Name; + if (Info.FormatIndex >= 0) + m_RegistryInfo.ArcType = (*ArcFormats)[Info.FormatIndex].Name; m_RegistryInfo.ShowPassword = IsShowPasswordChecked(); m_RegistryInfo.Save(); @@ -641,7 +822,26 @@ bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam) { switch(itemID) { - case IDC_COMPRESS_COMBO_FORMAT: + case IDC_COMPRESS_ARCHIVE: + { + // we can 't change m_ArchivePath in that handler ! + DirPrefix.Empty(); + SetItemText(IDT_COMPRESS_ARCHIVE_FOLDER, DirPrefix); + + /* + UString path; + m_ArchivePath.GetText(path); + m_ArchivePath.SetText(L""); + if (IsAbsolutePath(path)) + { + UString fileName; + SetArcPathFields(path, fileName); + SetArchiveName(fileName); + } + */ + return true; + } + case IDC_COMPRESS_FORMAT: { bool isSFX = IsSFX(); SaveOptionsInMem(); @@ -655,7 +855,7 @@ bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam) SetMemoryUsage(); return true; } - case IDC_COMPRESS_COMBO_LEVEL: + case IDC_COMPRESS_LEVEL: { const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; int index = FindRegistryFormatAlways(ai.Name); @@ -668,7 +868,7 @@ bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam) SetMemoryUsage(); return true; } - case IDC_COMPRESS_COMBO_METHOD: + case IDC_COMPRESS_METHOD: { SetDictionary(); SetOrder(); @@ -678,14 +878,14 @@ bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam) SetMemoryUsage(); return true; } - case IDC_COMPRESS_COMBO_DICTIONARY: - case IDC_COMPRESS_COMBO_ORDER: + case IDC_COMPRESS_DICTIONARY: + case IDC_COMPRESS_ORDER: { SetSolidBlockSize(); SetMemoryUsage(); return true; } - case IDC_COMPRESS_COMBO_THREADS: + case IDC_COMPRESS_THREADS: { SetMemoryUsage(); return true; @@ -708,17 +908,17 @@ void CCompressDialog::SetArchiveName2(bool prevWasSFX) UString fileName; m_ArchivePath.GetText(fileName); const CArcInfoEx &prevArchiverInfo = (*ArcFormats)[m_PrevFormat]; - if (prevArchiverInfo.KeepName || Info.KeepName) + if (prevArchiverInfo.Flags_KeepName() || Info.KeepName) { - UString prevExtension = prevArchiverInfo.GetMainExt(); + UString prevExtension; 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); + prevExtension = UString('.') + prevArchiverInfo.GetMainExt(); + const unsigned prevExtensionLen = prevExtension.Len(); + if (fileName.Len() >= prevExtensionLen) + if (StringsAreEqualNoCase(fileName.RightPtr(prevExtensionLen), prevExtension)) + fileName.DeleteFrom(fileName.Len() - prevExtensionLen); } SetArchiveName(fileName); } @@ -733,7 +933,7 @@ void CCompressDialog::SetArchiveName(const UString &name) Info.FormatIndex = GetFormatIndex(); const CArcInfoEx &ai = (*ArcFormats)[Info.FormatIndex]; m_PrevFormat = Info.FormatIndex; - if (ai.KeepName) + if (ai.Flags_KeepName()) { fileName = OriginalFileName; } @@ -741,10 +941,9 @@ void CCompressDialog::SetArchiveName(const UString &name) { 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); + int dotPos = GetExtDotPos(fileName); + if (dotPos >= 0) + fileName.DeleteFrom(dotPos); } } @@ -760,10 +959,10 @@ void CCompressDialog::SetArchiveName(const UString &name) int CCompressDialog::FindRegistryFormat(const UString &name) { - for (int i = 0; i < m_RegistryInfo.Formats.Size(); i++) + FOR_VECTOR (i, m_RegistryInfo.Formats) { const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[i]; - if (name.CompareNoCase(GetUnicodeString(fo.FormatID)) == 0) + if (name.IsEqualToNoCase(GetUnicodeString(fo.FormatID))) return i; } return -1; @@ -783,10 +982,9 @@ int CCompressDialog::FindRegistryFormatAlways(const UString &name) 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) + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + for (unsigned i = 0; i < ARRAY_SIZE(g_Formats); i++) + if (ai.Name.IsEqualToNoCase(g_Formats[i].Name)) return i; return 0; // -1; } @@ -809,22 +1007,22 @@ void CCompressDialog::SetLevel() const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; int index = FindRegistryFormat(ai.Name); - UInt32 level = kNormal; + UInt32 level = 5; if (index >= 0) { const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; - if (fo.Level <= kUltra) + if (fo.Level <= 9) level = fo.Level; else - level = kUltra; + level = 9; } int i; - for (i = 0; i <= kUltra; i++) + for (i = 0; i <= 9; i++) { if ((fi.LevelsMask & (1 << i)) != 0) { - const CLevelInfo &levelInfo = g_Levels[i]; - int index = (int)m_Level.AddString(LangString(levelInfo.ResourceID, levelInfo.LangID)); + UInt32 langID = g_Levels[i]; + int index = (int)m_Level.AddString(LangString(langID)); m_Level.SetItemData(index, i); } } @@ -868,7 +1066,7 @@ void CCompressDialog::SetMethod(int keepMethodId) weUseSameMethod = true; continue; } - if ((defaultMethod.CompareNoCase(method) == 0 || m == 0) && !weUseSameMethod) + if ((defaultMethod.IsEqualToNoCase(method) || m == 0) && !weUseSameMethod) m_Method.SetCurSel(itemIndex); } if (!weUseSameMethod) @@ -881,19 +1079,19 @@ void CCompressDialog::SetMethod(int keepMethodId) bool CCompressDialog::IsZipFormat() { const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; - return (ai.Name.CompareNoCase(L"zip") == 0); + return ai.Name.IsEqualToNoCase(L"zip"); } void CCompressDialog::SetEncryptionMethod() { _encryptionMethod.ResetContent(); const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; - if (ai.Name.CompareNoCase(L"7z") == 0) + if (ai.Name.IsEqualToNoCase(L"7z")) { _encryptionMethod.AddString(TEXT("AES-256")); _encryptionMethod.SetCurSel(0); } - else if (ai.Name.CompareNoCase(L"zip") == 0) + else if (ai.Name.IsEqualToNoCase(L"zip")) { int index = FindRegistryFormat(ai.Name); UString encryptionMethod; @@ -912,7 +1110,7 @@ int CCompressDialog::GetMethodID() { if (m_Method.GetCount() <= 0) return -1; - return (int)(UInt32)m_Method.GetItemData(m_Method.GetCurSel()); + return (int)(UInt32)m_Method.GetItemData_of_CurSel(); } UString CCompressDialog::GetMethodSpec() @@ -930,41 +1128,26 @@ UString CCompressDialog::GetEncryptionMethodSpec() return UString(); UString result; _encryptionMethod.GetText(result); - result.Replace(L"-", L""); + result.RemoveChar(L'-'); return result; } -int CCompressDialog::AddDictionarySize(UInt32 size, bool kilo, bool maga) +void CCompressDialog::AddDictionarySize(UInt32 size) { - UInt32 sizePrint = size; - if (kilo) - sizePrint >>= 10; - else if (maga) - sizePrint >>= 20; + Byte c = 0; + unsigned moveBits = 0; + if ((size & 0xFFFFF) == 0) { moveBits = 20; c = 'M'; } + else if ((size & 0x3FF) == 0) { moveBits = 10; c = 'K'; } 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")); + ConvertUInt32ToString(size >> moveBits, s); + unsigned pos = MyStringLen(s); + s[pos++] = ' '; + if (moveBits != 0) + s[pos++] = c; + s[pos++] = 'B'; + s[pos++] = 0; 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() @@ -972,11 +1155,11 @@ void CCompressDialog::SetDictionary() m_Dictionary.ResetContent(); const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; int index = FindRegistryFormat(ai.Name); - UInt32 defaultDictionary = (UInt32)-1; + UInt32 defaultDictionary = (UInt32)(Int32)-1; if (index >= 0) { const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; - if (fo.Method.CompareNoCase(GetMethodSpec()) == 0) + if (fo.Method.IsEqualToNoCase(GetMethodSpec())) defaultDictionary = fo.Dictionary; } int methodID = GetMethodID(); @@ -990,7 +1173,7 @@ void CCompressDialog::SetDictionary() case kLZMA2: { static const UInt32 kMinDicSize = (1 << 16); - if (defaultDictionary == (UInt32)-1) + if (defaultDictionary == (UInt32)(Int32)-1) { if (level >= 9) defaultDictionary = (1 << 26); else if (level >= 7) defaultDictionary = (1 << 25); @@ -1027,7 +1210,7 @@ void CCompressDialog::SetDictionary() } case kPPMd: { - if (defaultDictionary == (UInt32)-1) + if (defaultDictionary == (UInt32)(Int32)-1) { if (level >= 9) defaultDictionary = (192 << 20); else if (level >= 7) defaultDictionary = ( 64 << 20); @@ -1072,7 +1255,7 @@ void CCompressDialog::SetDictionary() } case kBZip2: { - if (defaultDictionary == (UInt32)-1) + if (defaultDictionary == (UInt32)(Int32)-1) { if (level >= 5) defaultDictionary = (900 << 10); @@ -1092,7 +1275,7 @@ void CCompressDialog::SetDictionary() } case kPPMdZip: { - if (defaultDictionary == (UInt32)-1) + if (defaultDictionary == (UInt32)(Int32)-1) defaultDictionary = (1 << (19 + (level > 8 ? 8 : level))); for (int i = 20; i <= 28; i++) { @@ -1112,14 +1295,14 @@ void CCompressDialog::SetDictionary() UInt32 CCompressDialog::GetComboValue(NWindows::NControl::CComboBox &c, int defMax) { if (c.GetCount() <= defMax) - return (UInt32)-1; - return (UInt32)c.GetItemData(c.GetCurSel()); + return (UInt32)(Int32)-1; + return (UInt32)c.GetItemData_of_CurSel(); } UInt32 CCompressDialog::GetLevel2() { UInt32 level = GetLevel(); - if (level == (UInt32)-1) + if (level == (UInt32)(Int32)-1) level = 5; return level; } @@ -1138,11 +1321,11 @@ void CCompressDialog::SetOrder() m_Order.ResetContent(); const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; int index = FindRegistryFormat(ai.Name); - UInt32 defaultOrder = (UInt32)-1; + UInt32 defaultOrder = (UInt32)(Int32)-1; if (index >= 0) { const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; - if (fo.Method.CompareNoCase(GetMethodSpec()) == 0) + if (fo.Method.IsEqualToNoCase(GetMethodSpec())) defaultOrder = fo.Order; } int methodID = GetMethodID(); @@ -1154,7 +1337,7 @@ void CCompressDialog::SetOrder() case kLZMA: case kLZMA2: { - if (defaultOrder == (UInt32)-1) + if (defaultOrder == (UInt32)(Int32)-1) defaultOrder = (level >= 7) ? 64 : 32; for (int i = 3; i <= 8; i++) for (int j = 0; j < 2; j++) @@ -1169,7 +1352,7 @@ void CCompressDialog::SetOrder() } case kPPMd: { - if (defaultOrder == (UInt32)-1) + if (defaultOrder == (UInt32)(Int32)-1) { if (level >= 9) defaultOrder = 32; @@ -1197,7 +1380,7 @@ void CCompressDialog::SetOrder() case kDeflate: case kDeflate64: { - if (defaultOrder == (UInt32)-1) + if (defaultOrder == (UInt32)(Int32)-1) { if (level >= 9) defaultOrder = 128; @@ -1224,7 +1407,7 @@ void CCompressDialog::SetOrder() } case kPPMdZip: { - if (defaultOrder == (UInt32)-1) + if (defaultOrder == (UInt32)(Int32)-1) defaultOrder = level + 3; for (int i = 2; i <= 16; i++) AddOrder(i); @@ -1260,24 +1443,24 @@ void CCompressDialog::SetSolidBlockSize() return; UInt32 dictionary = GetDictionarySpec(); - if (dictionary == (UInt32)-1) + if (dictionary == (UInt32)(Int32)-1) dictionary = 1; - UInt32 defaultBlockSize = (UInt32)-1; + UInt32 defaultBlockSize = (UInt32)(Int32)-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) + if (fo.Method.IsEqualToNoCase(GetMethodSpec())) defaultBlockSize = fo.BlockLogSize; } - index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_NON_SOLID, 0x02000D14)); + index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_NON_SOLID)); m_Solid.SetItemData(index, (UInt32)kNoSolidBlockSize); m_Solid.SetCurSel(0); - bool needSet = defaultBlockSize == (UInt32)-1; + bool needSet = defaultBlockSize == (UInt32)(Int32)-1; for (int i = 20; i <= 36; i++) { if (needSet && dictionary >= (((UInt64)1 << (i - 7))) && i <= 32) @@ -1290,9 +1473,9 @@ void CCompressDialog::SetSolidBlockSize() int index = (int)m_Solid.AddString(s); m_Solid.SetItemData(index, (UInt32)i); } - index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_SOLID, 0x02000D15)); + index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_SOLID)); m_Solid.SetItemData(index, kSolidBlockSize); - if (defaultBlockSize == (UInt32)-1) + if (defaultBlockSize == (UInt32)(Int32)-1) defaultBlockSize = kSolidBlockSize; if (defaultBlockSize != kNoSolidBlockSize) SetNearestSelectComboBox(m_Solid, defaultBlockSize); @@ -1314,7 +1497,7 @@ void CCompressDialog::SetNumThreads() if (index >= 0) { const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; - if (fo.Method.CompareNoCase(GetMethodSpec()) == 0 && fo.NumThreads != (UInt32)-1) + if (fo.Method.IsEqualToNoCase(GetMethodSpec()) && fo.NumThreads != (UInt32)(Int32)-1) defaultValue = fo.NumThreads; } @@ -1415,7 +1598,7 @@ UInt64 CCompressDialog::GetMemoryUsage(UInt32 dictionary, UInt64 &decompressMemo case kDeflate64: { UInt32 order = GetOrder(); - if (order == (UInt32)-1) + if (order == (UInt32)(Int32)-1) order = 32; if (level >= 7) size += (1 << 20); @@ -1461,8 +1644,8 @@ void CCompressDialog::SetMemoryUsage() { UInt64 decompressMem; UInt64 memUsage = GetMemoryUsage(decompressMem); - PrintMemUsage(IDC_STATIC_COMPRESS_MEMORY_VALUE, memUsage); - PrintMemUsage(IDC_STATIC_COMPRESS_MEMORY_DE_VALUE, decompressMem); + PrintMemUsage(IDT_COMPRESS_MEMORY_VALUE, memUsage); + PrintMemUsage(IDT_COMPRESS_MEMORY_DE_VALUE, decompressMem); } void CCompressDialog::SetParams() @@ -1494,7 +1677,7 @@ void CCompressDialog::SaveOptionsInMem() fo.BlockLogSize = GetBlockSizeSpec(); } -int CCompressDialog::GetFormatIndex() +unsigned CCompressDialog::GetFormatIndex() { - return (int)m_Format.GetItemData(m_Format.GetCurSel()); + return (unsigned)m_Format.GetItemData_of_CurSel(); } diff --git a/CPP/7zip/UI/GUI/CompressDialog.h b/CPP/7zip/UI/GUI/CompressDialog.h old mode 100755 new mode 100644 index 7b0067fa..3463fefc --- a/CPP/7zip/UI/GUI/CompressDialog.h +++ b/CPP/7zip/UI/GUI/CompressDialog.h @@ -3,8 +3,10 @@ #ifndef __COMPRESS_DIALOG_H #define __COMPRESS_DIALOG_H -#include "Windows/Control/ComboBox.h" -#include "Windows/Control/Edit.h" +#include "../../../Common/Wildcard.h" + +#include "../../../Windows/Control/ComboBox.h" +#include "../../../Windows/Control/Edit.h" #include "../Common/LoadCodecs.h" #include "../Common/ZipRegistry.h" @@ -22,12 +24,15 @@ namespace NCompressDialog kAdd, kUpdate, kFresh, - kSynchronize + kSync }; } + struct CInfo { NUpdateMode::EEnum UpdateMode; + NWildcard::ECensorPathMode PathMode; + bool SolidIsSpecified; bool MultiThreadIsAllowed; UInt64 SolidBlockSize; @@ -46,10 +51,16 @@ namespace NCompressDialog bool SFXMode; bool OpenShareForWrite; - + bool DeleteAfterCompressing; - UString ArchiveName; // in: Relative for ; out: abs - FString CurrentDirPrefix; + CBoolPair SymLinks; + CBoolPair HardLinks; + CBoolPair AltStreams; + CBoolPair NtSecurity; + + UString ArcPath; // in: Relative or abs ; out: Relative or abs + + // FString CurrentDirPrefix; bool KeepName; bool GetFullPathName(UString &result) const; @@ -60,7 +71,13 @@ namespace NCompressDialog bool EncryptHeadersIsAllowed; bool EncryptHeaders; - void Init() + CInfo(): + UpdateMode(NCompressDialog::NUpdateMode::kAdd), + PathMode(NWildcard::k_RelatPath), + SFXMode(false), + OpenShareForWrite(false), + DeleteAfterCompressing(false), + FormatIndex(-1) { Level = Dictionary = Order = UInt32(-1); OrderMode = false; @@ -68,10 +85,6 @@ namespace NCompressDialog Options.Empty(); EncryptionMethod.Empty(); } - CInfo() - { - Init(); - } }; } @@ -85,7 +98,10 @@ class CCompressDialog: public NWindows::NControl::CModalDialog NWindows::NControl::CComboBox m_Order; NWindows::NControl::CComboBox m_Solid; NWindows::NControl::CComboBox m_NumThreads; + NWindows::NControl::CComboBox m_UpdateMode; + NWindows::NControl::CComboBox m_PathMode; + NWindows::NControl::CComboBox m_Volume; NWindows::NControl::CDialogChildControl m_Params; @@ -96,6 +112,12 @@ class CCompressDialog: public NWindows::NControl::CModalDialog NCompression::CInfo m_RegistryInfo; int m_PrevFormat; + UString DirPrefix; + UString StartDirPrefix; + + void CheckButton_TwoBools(UINT id, const CBoolPair &b1, const CBoolPair &b2); + void GetButton_Bools(UINT id, CBoolPair &b1, CBoolPair &b2); + void SetArchiveName(const UString &name); int FindRegistryFormat(const UString &name); int FindRegistryFormatAlways(const UString &name); @@ -118,8 +140,7 @@ class CCompressDialog: public NWindows::NControl::CModalDialog void SetEncryptionMethod(); - int AddDictionarySize(UInt32 size, bool kilo, bool maga); - int AddDictionarySize(UInt32 size); + void AddDictionarySize(UInt32 size); void SetDictionary(); @@ -151,27 +172,32 @@ class CCompressDialog: public NWindows::NControl::CModalDialog void SaveOptionsInMem(); void UpdatePasswordControl(); - bool IsShowPasswordChecked() const - { return IsButtonChecked(IDC_COMPRESS_CHECK_SHOW_PASSWORD) == BST_CHECKED; } + bool IsShowPasswordChecked() const { return IsButtonCheckedBool(IDX_PASSWORD_SHOW); } + + unsigned GetFormatIndex(); + bool SetArcPathFields(const UString &path, UString &name, bool always); + bool GetFinalPath_Smart(UString &resPath); - int GetFormatIndex(); public: CObjectVector *ArcFormats; - CRecordVector ArcIndices; + CUIntVector ArcIndices; // can not be empty, must contain Info.FormatIndex, if Info.FormatIndex >= 0 NCompressDialog::CInfo Info; UString OriginalFileName; // for bzip2, gzip2 + bool CurrentDirWasChanged; INT_PTR Create(HWND wndParent = 0) { BIG_DIALOG_SIZE(400, 304); - return CModalDialog::Create(SIZED_DIALOG(IDD_DIALOG_COMPRESS), wndParent); + return CModalDialog::Create(SIZED_DIALOG(IDD_COMPRESS), wndParent); } + CCompressDialog(): CurrentDirWasChanged(false) {}; + protected: void CheckSFXControlsEnable(); - void CheckVolumeEnable(); + // void CheckVolumeEnable(); void CheckControlsEnable(); void OnButtonSetArchive(); diff --git a/CPP/7zip/UI/GUI/CompressDialog.rc b/CPP/7zip/UI/GUI/CompressDialog.rc old mode 100755 new mode 100644 index 5a71b043..6c555a7e --- a/CPP/7zip/UI/GUI/CompressDialog.rc +++ b/CPP/7zip/UI/GUI/CompressDialog.rc @@ -2,7 +2,7 @@ #include "../../GuiCommon.rc" #define xc 400 -#define yc 304 +#define yc 354 #undef gSize #undef gSpace @@ -20,6 +20,11 @@ #define gSize 192 #define gSpace 24 +#define ntSize2 168 +#define ntSizeX (ntSize2 - m - m) +#define ntPosX m + m +#define ntPosY 292 + #define g1xs 88 #define g0xs (gSize - g1xs) #define g1x (m + g0xs) @@ -33,8 +38,9 @@ #define g4xs (xc - gSize - gSpace) #define g4xs2 (g4xs - m - m) -#define yOpt 72 -#define yPsw 128 +#define yOpt 80 + +#define xArcFolderOffs 40 #undef GROUP_Y_SIZE #undef GROUP_Y_SIZE_ENCRYPT @@ -42,81 +48,105 @@ #define GROUP_Y_SIZE 8 #define GROUP_Y_SIZE_ENCRYPT 8 #else -#define GROUP_Y_SIZE 48 +#define GROUP_Y_SIZE 64 #define GROUP_Y_SIZE_ENCRYPT 128 #endif -IDD_DIALOG_COMPRESS MY_DIALOG +#define yPsw (yOpt + GROUP_Y_SIZE + 8) + +IDD_COMPRESS DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT 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 "", IDT_COMPRESS_ARCHIVE_FOLDER, m + xArcFolderOffs, m, xc - xArcFolderOffs, 8 + LTEXT "&Archive:", IDT_COMPRESS_ARCHIVE, m, 12, xArcFolderOffs, 8 + COMBOBOX IDC_COMPRESS_ARCHIVE, m + xArcFolderOffs, 18, xc - bxsDots - 12 - xArcFolderOffs, 126, MY_COMBO_WITH_EDIT + PUSHBUTTON "...", IDB_COMPRESS_SET_ARCHIVE, xs - m - bxsDots, 16, 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 "Archive &format:", IDT_COMPRESS_FORMAT, m, 41, g0xs, 8 + COMBOBOX IDC_COMPRESS_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 &level:", IDT_COMPRESS_LEVEL, m, 62, g0xs, 8 + COMBOBOX IDC_COMPRESS_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 "Compression &method:", IDT_COMPRESS_METHOD, m, 83, g0xs, 8 + COMBOBOX IDC_COMPRESS_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 "&Dictionary size:", IDT_COMPRESS_DICTIONARY, m, 104, g0xs, 8 + COMBOBOX IDC_COMPRESS_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 "&Word size:", IDT_COMPRESS_ORDER, m, 125, g0xs, 8 + COMBOBOX IDC_COMPRESS_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 "&Solid Block size:", IDT_COMPRESS_SOLID, m, 146, g0xs, 8 + COMBOBOX IDC_COMPRESS_SOLID, g1x, 144, g1xs, 140, MY_COMBO - LTEXT "&Number of CPU threads:",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 "&Number of CPU threads:", IDT_COMPRESS_THREADS, m, 167, g0xs, 8 + COMBOBOX IDC_COMPRESS_THREADS, g1x, 165, g1xs - 35, 140, MY_COMBO + RTEXT "", IDT_COMPRESS_HARDWARE_THREADS, g1x + g1xs - 35 + 10, 167, 25, 8 - 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 Compressing:", IDT_COMPRESS_MEMORY, m, 190, g2xs, 8 + RTEXT "", IDT_COMPRESS_MEMORY_VALUE, g3x, 190, g3xs, 8 + + LTEXT "Memory usage for Decompressing:", IDT_COMPRESS_MEMORY_DE, m, 206, g2xs, 8 + RTEXT "", IDT_COMPRESS_MEMORY_DE_VALUE, g3x, 206, g3xs, 8 + + + LTEXT "Split to &volumes, bytes:", IDT_SPLIT_TO_VOLUMES, m, 225, gSize, 8 + COMBOBOX IDC_COMPRESS_VOLUME, m, 237, gSize, 73, MY_COMBO_WITH_EDIT + + LTEXT "&Parameters:", IDT_COMPRESS_PARAMETERS, m, 256, gSize, 8 + EDITTEXT IDE_COMPRESS_PARAMETERS, m, 268, gSize, 14, ES_AUTOHSCROLL + + + GROUPBOX "NTFS", IDG_COMPRESS_NTFS, m, ntPosY, ntSize2, 68 + + CONTROL "Store symbolic links", IDX_COMPRESS_NT_SYM_LINKS, MY_CHECKBOX, + ntPosX, ntPosY + 12, ntSizeX, 10 + CONTROL "Store hard links", IDX_COMPRESS_NT_HARD_LINKS, MY_CHECKBOX, + ntPosX, ntPosY + 26, ntSizeX, 10 + CONTROL "Store alternate data streams", IDX_COMPRESS_NT_ALT_STREAMS, MY_CHECKBOX, + ntPosX, ntPosY + 40, ntSizeX, 10 + CONTROL "Store file security", IDX_COMPRESS_NT_SECUR, MY_CHECKBOX, + ntPosX, ntPosY + 54, ntSizeX, 10 - 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 "&Update mode:", IDT_COMPRESS_UPDATE_MODE, g4x, 41, 80, 8 + COMBOBOX IDC_COMPRESS_UPDATE_MODE, g4x + 84, 39, g4xs - 84, 80, MY_COMBO - 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 "Path mode:", IDT_COMPRESS_PATH_MODE, g4x, 61, 80, 8 + COMBOBOX IDC_COMPRESS_PATH_MODE, g4x + 84, 59, g4xs - 84, 80, MY_COMBO - 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", IDG_COMPRESS_OPTIONS, g4x, yOpt, g4xs, GROUP_Y_SIZE - GROUPBOX "Options",IDC_STATIC_COMPRESS_OPTIONS, g4x, yOpt, g4xs, GROUP_Y_SIZE - CONTROL "Create SF&X archive",IDC_COMPRESS_SFX, MY_CHECKBOX, + CONTROL "Create SF&X archive", IDX_COMPRESS_SFX, MY_CHECKBOX, g4x2, yOpt + 14, g4xs2, 10 - CONTROL "Compress shared files",IDC_COMPRESS_SHARED, MY_CHECKBOX, + CONTROL "Compress shared files", IDX_COMPRESS_SHARED, MY_CHECKBOX, g4x2, yOpt + 30, g4xs2, 10 - - GROUPBOX "Encryption", IDC_COMPRESS_ENCRYPTION, g4x, yPsw, g4xs, GROUP_Y_SIZE_ENCRYPT + CONTROL "Delete files after compression", IDX_COMPRESS_DEL, MY_CHECKBOX, + g4x2, yOpt + 46, g4xs2, 10 + - 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 + GROUPBOX "Encryption", IDG_COMPRESS_ENCRYPTION, g4x, yPsw, g4xs, GROUP_Y_SIZE_ENCRYPT - CONTROL "Show Password",IDC_COMPRESS_CHECK_SHOW_PASSWORD,MY_CHECKBOX, + LTEXT "Enter password:", IDT_PASSWORD_ENTER, g4x2, yPsw + 14, g4xs2, 8 + EDITTEXT IDE_COMPRESS_PASSWORD1, g4x2, yPsw + 26, g4xs2, 14, ES_PASSWORD | ES_AUTOHSCROLL + LTEXT "Reenter password:", IDT_PASSWORD_REENTER, g4x2, yPsw + 46, g4xs2, 8 + EDITTEXT IDE_COMPRESS_PASSWORD2, g4x2, yPsw + 58, g4xs2, 14, ES_PASSWORD | ES_AUTOHSCROLL + + CONTROL "Show Password", IDX_PASSWORD_SHOW, 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 + LTEXT "&Encryption method:", IDT_COMPRESS_ENCRYPTION_METHOD, g4x2, yPsw + 95, 100, 8 + COMBOBOX IDC_COMPRESS_ENCRYPTION_METHOD, g4x2 + 100, yPsw + 93, g4xs2 - 100, 198, MY_COMBO - CONTROL "Encrypt file &names", IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES, MY_CHECKBOX, + CONTROL "Encrypt file &names", IDX_COMPRESS_ENCRYPT_FILE_NAMES, MY_CHECKBOX, g4x2, yPsw + 111, g4xs2, 10 - DEFPUSHBUTTON "OK", IDOK, bx3, by, bxs, bys, WS_GROUP + DEFPUSHBUTTON "OK", IDOK, bx3, by, bxs, bys, WS_GROUP PUSHBUTTON "Cancel", IDCANCEL, bx2, by, bxs, bys - PUSHBUTTON "Help", IDHELP, bx1, by, bxs, bys + PUSHBUTTON "Help", IDHELP, bx1, by, bxs, bys END @@ -131,39 +161,38 @@ END #define yc 160 -IDD_DIALOG_COMPRESS_2 MY_DIALOG +IDD_COMPRESS_2 DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT 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_ARCHIVE, m, m, xc - bxsDots - m, 126, MY_COMBO_WITH_EDIT + PUSHBUTTON "...", IDB_COMPRESS_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_FORMAT, m , 22, 32, 80, MY_COMBO | CBS_SORT + COMBOBOX IDC_COMPRESS_LEVEL, m + 36, 22, 68, 80, MY_COMBO + COMBOBOX IDC_COMPRESS_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 + COMBOBOX IDC_COMPRESS_DICTIONARY, m, 40, 40, 80, MY_COMBO + COMBOBOX IDC_COMPRESS_ORDER, m + 44, 40, 32, 80, MY_COMBO + COMBOBOX IDC_COMPRESS_SOLID, m + 80, 40, 40, 80, MY_COMBO + COMBOBOX IDC_COMPRESS_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 + LTEXT "Split to &volumes, bytes:", IDT_SPLIT_TO_VOLUMES, m, 60, 32, 8 + COMBOBOX IDC_COMPRESS_VOLUME, m + 32, 58, 44, 73, MY_COMBO_WITH_EDIT + LTEXT "&Parameters:", IDT_COMPRESS_PARAMETERS, m + 80, 60, 48, 8 + EDITTEXT IDE_COMPRESS_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 + COMBOBOX IDC_COMPRESS_UPDATE_MODE, m, 76, 88, 80, MY_COMBO + CONTROL "SF&X", IDX_COMPRESS_SFX, MY_CHECKBOX, m + 92, 77, 60, 10 - CONTROL "Compress shared files", IDC_COMPRESS_SHARED, MY_CHECKBOX, m, 94, xc, 10 + CONTROL "Compress shared files", IDX_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 + LTEXT "Enter password:", IDT_PASSWORD_ENTER, m, 112, 60, 8 + EDITTEXT IDE_COMPRESS_PASSWORD1, m + 60, 110, 44, 13, ES_PASSWORD | ES_AUTOHSCROLL + CONTROL "Show Password", IDX_PASSWORD_SHOW, MY_CHECKBOX, m + 108, 112, 44, 10 - 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 + COMBOBOX IDC_COMPRESS_ENCRYPTION_METHOD, m, 128, 48, 198, MY_COMBO + CONTROL "Encrypt file &names", IDX_COMPRESS_ENCRYPT_FILE_NAMES, MY_CHECKBOX, m + 52, 130, 100, 10 OK_CANCEL END @@ -172,26 +201,27 @@ END 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_PASSWORD_NOT_MATCH "Passwords do not match" + IDS_PASSWORD_USE_ASCII "Use only English letters, numbers and special characters (!, #, $, ...) for password." + IDS_PASSWORD_TOO_LONG "Password is too long" - IDS_COMPRESS_NON_SOLID "Non-solid" - IDS_COMPRESS_SOLID "Solid" + IDS_METHOD_STORE "Store" + IDS_METHOD_FASTEST "Fastest" + IDS_METHOD_FAST "Fast" + IDS_METHOD_NORMAL "Normal" + IDS_METHOD_MAXIMUM "Maximum" + IDS_METHOD_ULTRA "Ultra" - IDS_COMPRESS_UPDATE_MODE_ADD "Add and replace files" + 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_COMPRESS_UPDATE_MODE_FRESH "Freshen existing files" + IDS_COMPRESS_UPDATE_MODE_SYNC "Synchronize files" - IDS_OPEN_TYPE_ALL_FILES "All Files" + IDS_OPEN_TYPE_ALL_FILES "All Files" + IDS_COMPRESS_SET_ARCHIVE_BROWSE "Browse" - 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" + IDS_COMPRESS_NON_SOLID "Non-solid" + IDS_COMPRESS_SOLID "Solid" + + IDS_SPLIT_CONFIRM "Specified volume size: {0} bytes.\nAre you sure you want to split archive into such volumes?" END diff --git a/CPP/7zip/UI/GUI/CompressDialogRes.h b/CPP/7zip/UI/GUI/CompressDialogRes.h old mode 100755 new mode 100644 index 2dcdc80e..ff99fa94 --- a/CPP/7zip/UI/GUI/CompressDialogRes.h +++ b/CPP/7zip/UI/GUI/CompressDialogRes.h @@ -1,81 +1,87 @@ -#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 +#define IDD_COMPRESS 4000 +#define IDD_COMPRESS_2 14000 + +#define IDC_COMPRESS_ARCHIVE 100 +#define IDB_COMPRESS_SET_ARCHIVE 101 +#define IDC_COMPRESS_LEVEL 102 +#define IDC_COMPRESS_UPDATE_MODE 103 +#define IDC_COMPRESS_FORMAT 104 +#define IDC_COMPRESS_VOLUME 105 +#define IDC_COMPRESS_METHOD 106 +#define IDC_COMPRESS_DICTIONARY 107 +#define IDC_COMPRESS_ORDER 108 +#define IDC_COMPRESS_SOLID 109 +#define IDC_COMPRESS_THREADS 110 +#define IDE_COMPRESS_PARAMETERS 111 + +#define IDT_COMPRESS_HARDWARE_THREADS 112 +#define IDT_COMPRESS_MEMORY_VALUE 113 +#define IDT_COMPRESS_MEMORY_DE_VALUE 114 + +#define IDG_COMPRESS_NTFS 115 +#define IDC_COMPRESS_PATH_MODE 116 + +#define IDE_COMPRESS_PASSWORD1 120 +#define IDE_COMPRESS_PASSWORD2 121 +#define IDC_COMPRESS_ENCRYPTION_METHOD 122 + +#define IDT_COMPRESS_ARCHIVE_FOLDER 130 + +#define IDT_COMPRESS_PATH_MODE 3410 + +#define IDT_PASSWORD_ENTER 3801 +#define IDT_PASSWORD_REENTER 3802 +#define IDX_PASSWORD_SHOW 3803 +#define IDS_PASSWORD_NOT_MATCH 3804 +#define IDS_PASSWORD_USE_ASCII 3805 +#define IDS_PASSWORD_TOO_LONG 3806 + +#define IDT_COMPRESS_ARCHIVE 4001 +#define IDT_COMPRESS_UPDATE_MODE 4002 +#define IDT_COMPRESS_FORMAT 4003 +#define IDT_COMPRESS_LEVEL 4004 +#define IDT_COMPRESS_METHOD 4005 +#define IDT_COMPRESS_DICTIONARY 4006 +#define IDT_COMPRESS_ORDER 4007 +#define IDT_COMPRESS_SOLID 4008 +#define IDT_COMPRESS_THREADS 4009 +#define IDT_COMPRESS_PARAMETERS 4010 +#define IDG_COMPRESS_OPTIONS 4011 + +#define IDX_COMPRESS_SFX 4012 +#define IDX_COMPRESS_SHARED 4013 + +#define IDG_COMPRESS_ENCRYPTION 4014 +#define IDT_COMPRESS_ENCRYPTION_METHOD 4015 +#define IDX_COMPRESS_ENCRYPT_FILE_NAMES 4016 + +#define IDT_COMPRESS_MEMORY 4017 +#define IDT_COMPRESS_MEMORY_DE 4018 + +#define IDX_COMPRESS_DEL 4019 + +#define IDX_COMPRESS_NT_SYM_LINKS 4040 +#define IDX_COMPRESS_NT_HARD_LINKS 4041 +#define IDX_COMPRESS_NT_ALT_STREAMS 4042 +#define IDX_COMPRESS_NT_SECUR 4043 + +#define IDS_METHOD_STORE 4050 +#define IDS_METHOD_FASTEST 4051 +#define IDS_METHOD_FAST 4052 +#define IDS_METHOD_NORMAL 4053 +#define IDS_METHOD_MAXIMUM 4054 +#define IDS_METHOD_ULTRA 4055 + +#define IDS_COMPRESS_UPDATE_MODE_ADD 4060 +#define IDS_COMPRESS_UPDATE_MODE_UPDATE 4061 +#define IDS_COMPRESS_UPDATE_MODE_FRESH 4062 +#define IDS_COMPRESS_UPDATE_MODE_SYNC 4063 + +#define IDS_COMPRESS_SET_ARCHIVE_BROWSE 4070 +#define IDS_OPEN_TYPE_ALL_FILES 4071 +#define IDS_COMPRESS_NON_SOLID 4072 +#define IDS_COMPRESS_SOLID 4073 + +#define IDT_SPLIT_TO_VOLUMES 7302 +#define IDS_INCORRECT_VOLUME_SIZE 7307 +#define IDS_SPLIT_CONFIRM 7308 diff --git a/CPP/7zip/UI/GUI/Extract.rc b/CPP/7zip/UI/GUI/Extract.rc old mode 100755 new mode 100644 index ad8f9910..defcfcc4 --- a/CPP/7zip/UI/GUI/Extract.rc +++ b/CPP/7zip/UI/GUI/Extract.rc @@ -4,30 +4,49 @@ 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_CANNOT_CREATE_FOLDER "Cannot create folder '{0}'" + IDS_UPDATE_NOT_SUPPORTED "Update operations are not supported for this archive." + IDS_CANT_OPEN_ARCHIVE "Can not open file '{0}' as archive" + IDS_CANT_OPEN_ENCRYPTED_ARCHIVE "Can not open encrypted archive '{0}'. Wrong password?" IDS_UNSUPPORTED_ARCHIVE_TYPE "Unsupported archive type" - IDC_EXTRACT_RADIO_FULL_PATHNAMES "Full pathnames" - IDC_EXTRACT_RADIO_CURRENT_PATHNAMES "Current pathnames" - IDC_EXTRACT_RADIO_NO_PATHNAMES "No pathnames" + IDS_PROGRESS_EXTRACTING "Extracting" + + IDS_EXTRACT_SET_FOLDER "Specify a location for extracted files." + + IDS_EXTRACT_PATHS_FULL "Full pathnames" + IDS_EXTRACT_PATHS_NO "No pathnames" + IDS_EXTRACT_PATHS_ABS "Absolute pathnames" + IDS_PATH_MODE_RELAT "Relative pathnames" + + IDS_EXTRACT_OVERWRITE_ASK "Ask before overwrite" + IDS_EXTRACT_OVERWRITE_WITHOUT_PROMPT "Overwrite without prompt" + IDS_EXTRACT_OVERWRITE_SKIP_EXISTING "Skip existing files" + IDS_EXTRACT_OVERWRITE_RENAME "Auto rename" + IDS_EXTRACT_OVERWRITE_RENAME_EXISTING "Auto rename existing files" + + IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD "Unsupported compression method for '{0}'." + IDS_EXTRACT_MESSAGE_DATA_ERROR "Data error in '{0}'. File is broken" + IDS_EXTRACT_MESSAGE_CRC_ERROR "CRC failed in '{0}'. File is broken." + IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED "Data error in encrypted file '{0}'. Wrong password?" + IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED "CRC failed in encrypted file '{0}'. Wrong password?" + + IDS_EXTRACT_MSG_WRONG_PSW "Wrong password?" + // IDS_EXTRACT_MSG_ENCRYPTED "Encrypted file" + + IDS_EXTRACT_MSG_UNSUPPORTED_METHOD "Unsupported compression method" + IDS_EXTRACT_MSG_DATA_ERROR "Data error" + IDS_EXTRACT_MSG_CRC_ERROR "CRC failed" + IDS_EXTRACT_MSG_UNAVAILABLE_DATA "Unavailable data" + IDS_EXTRACT_MSG_UEXPECTED_END "Unexpected end of data"; + IDS_EXTRACT_MSG_DATA_AFTER_END "There are some data after the end of the payload data" + IDS_EXTRACT_MSG_IS_NOT_ARC "Is not archive" + IDS_EXTRACT_MSG_HEADERS_ERROR "Headers Error" - 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" + IDS_OPEN_MSG_UNAVAILABLE_START "Unavailable start of archive" + IDS_OPEN_MSG_UNCONFIRMED_START "Unconfirmed start of archive" + // IDS_OPEN_MSG_ERROR_FLAGS + 5 "Unexpected end of archive" + // IDS_OPEN_MSG_ERROR_FLAGS + 6 "There are data after the end of archive" + IDS_OPEN_MSG_UNSUPPORTED_FEATURE "Unsupported feature" END diff --git a/CPP/7zip/UI/GUI/ExtractDialog.cpp b/CPP/7zip/UI/GUI/ExtractDialog.cpp old mode 100755 new mode 100644 index 64ae445e..d1ce8255 --- a/CPP/7zip/UI/GUI/ExtractDialog.cpp +++ b/CPP/7zip/UI/GUI/ExtractDialog.cpp @@ -2,28 +2,25 @@ #include "StdAfx.h" -// #include +#include "../../../Common/StringConvert.h" +#include "../../../Common/Wildcard.h" -#include "ExtractDialog.h" - -#include "Common/StringConvert.h" - -#include "Windows/FileName.h" -#include "Windows/FileDir.h" -#include "Windows/ResourceString.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 "ExtractDialog.h" #include "ExtractDialogRes.h" +#include "ExtractRes.h" using namespace NWindows; using namespace NFile; @@ -31,20 +28,20 @@ using namespace NName; extern HINSTANCE g_hInstance; -static CIDLangPair kPathMode_Pairs[] = +static const UInt32 kPathMode_IDs[] = { - { IDC_EXTRACT_RADIO_FULL_PATHNAMES, 0x02000811 }, - // { IDC_EXTRACT_RADIO_CURRENT_PATHNAMES, 0x02000812 }, - { IDC_EXTRACT_RADIO_NO_PATHNAMES, 0x02000813 } + IDS_EXTRACT_PATHS_FULL, + IDS_EXTRACT_PATHS_NO, + IDS_EXTRACT_PATHS_ABS }; -static CIDLangPair kOverwriteMode_Pairs[] = +static const UInt32 kOverwriteMode_IDs[] = { - { 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 } + IDS_EXTRACT_OVERWRITE_ASK, + IDS_EXTRACT_OVERWRITE_WITHOUT_PROMPT, + IDS_EXTRACT_OVERWRITE_SKIP_EXISTING, + IDS_EXTRACT_OVERWRITE_RENAME, + IDS_EXTRACT_OVERWRITE_RENAME_EXISTING }; #ifndef _SFX @@ -54,18 +51,9 @@ static const 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, + NExtract::NPathMode::kFullPaths, + NExtract::NPathMode::kNoPaths, + NExtract::NPathMode::kAbsPaths }; static const @@ -73,68 +61,46 @@ static const // 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 + NExtract::NOverwriteMode::kAsk, + NExtract::NOverwriteMode::kOverwrite, + NExtract::NOverwriteMode::kSkip, + NExtract::NOverwriteMode::kRename, + NExtract::NOverwriteMode::kRenameExisting }; -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 } +static const UInt32 kLangIDs[] = +{ + IDT_EXTRACT_EXTRACT_TO, + IDT_EXTRACT_PATH_MODE, + IDT_EXTRACT_OVERWRITE_MODE, + // IDX_EXTRACT_ALT_STREAMS, + IDX_EXTRACT_NT_SECUR, + IDX_EXTRACT_ELIM_DUP, + IDG_PASSWORD, + IDX_PASSWORD_SHOW }; #endif // static const int kWildcardsButtonIndex = 2; #ifndef NO_REGISTRY -static const int kHistorySize = 8; +static const unsigned kHistorySize = 16; #endif #ifndef _SFX -static void AddComboItems(NWindows::NControl::CComboBox &combo, const CIDLangPair *items, int numItems, const int *values, int curVal) + +// it's used in CompressDialog also +void AddComboItems(NControl::CComboBox &combo, const UInt32 *langIDs, unsigned numItems, const int *values, int curVal) { int curSel = 0; - for (int i = 0; i < numItems; i++) + for (unsigned i = 0; i < numItems; i++) { - UString s = LangString(items[i].ControlID, items[i].LangID); - s.Replace(L"&", L""); + UString s = LangString(langIDs[i]); + s.RemoveChar(L'&'); int index = (int)combo.AddString(s); combo.SetItemData(index, i); if (values[i] == curVal) @@ -142,45 +108,113 @@ static void AddComboItems(NWindows::NControl::CComboBox &combo, const CIDLangPai } combo.SetCurSel(curSel); } + +// it's used in CompressDialog also +bool GetBoolsVal(const CBoolPair &b1, const CBoolPair &b2) +{ + if (b1.Def) return b1.Val; + if (b2.Def) return b2.Val; + return b1.Val; +} + +void CExtractDialog::CheckButton_TwoBools(UINT id, const CBoolPair &b1, const CBoolPair &b2) +{ + CheckButton(id, GetBoolsVal(b1, b2)); +} + +void CExtractDialog::GetButton_Bools(UINT id, CBoolPair &b1, CBoolPair &b2) +{ + bool val = IsButtonCheckedBool(id); + bool oldVal = GetBoolsVal(b1, b2); + if (val != oldVal) + b1.Def = b2.Def = true; + b1.Val = b2.Val = val; +} + #endif bool CExtractDialog::OnInit() { #ifdef LANG - LangSetWindowText(HWND(*this), 0x02000800); - LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + { + UString s; + LangString_OnlyFromLangFile(IDD_EXTRACT, s); + if (s.IsEmpty()) + GetText(s); + if (!ArcPath.IsEmpty()) + { + s += L" : "; + s += ArcPath; + } + SetText(s); + // LangSetWindowText(*this, IDD_EXTRACT); + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); + } #endif + #ifndef _SFX - _passwordControl.Attach(GetItem(IDC_EXTRACT_EDIT_PASSWORD)); + _passwordControl.Attach(GetItem(IDE_EXTRACT_PASSWORD)); _passwordControl.SetText(Password); _passwordControl.SetPasswordChar(TEXT('*')); + _pathName.Attach(GetItem(IDE_EXTRACT_NAME)); #endif - NExtract::CInfo info; - #ifdef NO_REGISTRY - PathMode = NExtract::NPathMode::kFullPathnames; - OverwriteMode = NExtract::NOverwriteMode::kAskBefore; - // info.Paths = NExtract::NPathMode::kFullPathnames; + + PathMode = NExtract::NPathMode::kFullPaths; + OverwriteMode = NExtract::NOverwriteMode::kAsk; + #else - info.Load(); - CheckButton(IDC_EXTRACT_CHECK_SHOW_PASSWORD, info.ShowPassword); + + _info.Load(); + + if (_info.PathMode == NExtract::NPathMode::kCurPaths) + _info.PathMode = NExtract::NPathMode::kFullPaths; + + if (!PathMode_Force && _info.PathMode_Force) + PathMode = _info.PathMode; + if (!OverwriteMode_Force && _info.OverwriteMode_Force) + OverwriteMode = _info.OverwriteMode; + + // CheckButton_TwoBools(IDX_EXTRACT_ALT_STREAMS, AltStreams, _info.AltStreams); + CheckButton_TwoBools(IDX_EXTRACT_NT_SECUR, NtSecurity, _info.NtSecurity); + CheckButton_TwoBools(IDX_EXTRACT_ELIM_DUP, ElimDup, _info.ElimDup); + + CheckButton(IDX_PASSWORD_SHOW, _info.ShowPassword.Val); UpdatePasswordControl(); - PathMode = info.PathMode; - OverwriteMode = info.OverwriteMode; + #endif - _path.Attach(GetItem(IDC_EXTRACT_COMBO_PATH)); + _path.Attach(GetItem(IDC_EXTRACT_PATH)); - _path.SetText(DirectoryPath); + UString pathPrefix = DirPath; + + #ifndef _SFX + if (_info.SplitDest.Val) + { + CheckButton(IDX_EXTRACT_NAME_ENABLE, true); + UString pathName; + SplitPathToParts_Smart(DirPath, pathPrefix, pathName); + if (pathPrefix.IsEmpty()) + pathPrefix = pathName; + else + _pathName.SetText(pathName); + } + else + ShowItem_Bool(IDE_EXTRACT_NAME, false); + + #endif + + _path.SetText(pathPrefix); + #ifndef NO_REGISTRY - for (int i = 0; i < info.Paths.Size() && i < kHistorySize; i++) - _path.AddString(info.Paths[i]); + for (unsigned i = 0; i < _info.Paths.Size() && i < kHistorySize; i++) + _path.AddString(_info.Paths[i]); #endif /* - if (info.Paths.Size() > 0) + if (_info.Paths.Size() > 0) _path.SetCurSel(0); else _path.SetCurSel(-1); @@ -188,22 +222,11 @@ bool CExtractDialog::OnInit() #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); + _pathMode.Attach(GetItem(IDC_EXTRACT_PATH_MODE)); + _overwriteMode.Attach(GetItem(IDC_EXTRACT_OVERWRITE_MODE)); + AddComboItems(_pathMode, kPathMode_IDs, ARRAY_SIZE(kPathMode_IDs), kPathModeButtonsVals, PathMode); + AddComboItems(_overwriteMode, kOverwriteMode_IDs, ARRAY_SIZE(kOverwriteMode_IDs), kOverwriteButtonsVals, OverwriteMode); #endif @@ -213,7 +236,6 @@ bool CExtractDialog::OnInit() // CWindow filesWindow = GetItem(IDC_EXTRACT_RADIO_FILES); // filesWindow.Enable(_enableFilesButton); - // UpdateWildCardState(); NormalizePosition(); return CModalDialog::OnInit(); @@ -222,8 +244,7 @@ bool CExtractDialog::OnInit() #ifndef _SFX void CExtractDialog::UpdatePasswordControl() { - _passwordControl.SetPasswordChar((IsButtonChecked( - IDC_EXTRACT_CHECK_SHOW_PASSWORD) == BST_CHECKED) ? 0: TEXT('*')); + _passwordControl.SetPasswordChar(IsShowPasswordChecked() ? 0 : TEXT('*')); UString password; _passwordControl.GetText(password); _passwordControl.SetText(password); @@ -232,21 +253,16 @@ void CExtractDialog::UpdatePasswordControl() 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: + case IDB_EXTRACT_SET_PATH: OnButtonSetPath(); return true; #ifndef _SFX - case IDC_EXTRACT_CHECK_SHOW_PASSWORD: + case IDX_EXTRACT_NAME_ENABLE: + ShowItem_Bool(IDE_EXTRACT_NAME, IsButtonCheckedBool(IDX_EXTRACT_NAME_ENABLE)); + return true; + case IDX_PASSWORD_SHOW: { UpdatePasswordControl(); return true; @@ -260,9 +276,9 @@ void CExtractDialog::OnButtonSetPath() { UString currentPath; _path.GetText(currentPath); - UString title = LangStringSpec(IDS_EXTRACT_SET_FOLDER, 0x02000881); + UString title = LangString(IDS_EXTRACT_SET_FOLDER); UString resultPath; - if (!MyBrowseForFolder(HWND(*this), title, currentPath, resultPath)) + if (!MyBrowseForFolder(*this, title, currentPath, resultPath)) return; #ifndef NO_REGISTRY _path.SetCurSel(-1); @@ -272,8 +288,8 @@ void CExtractDialog::OnButtonSetPath() void AddUniqueString(UStringVector &list, const UString &s) { - for (int i = 0; i < list.Size(); i++) - if (s.CompareNoCase(list[i]) == 0) + FOR_VECTOR (i, list) + if (s.IsEqualToNoCase(list[i])) return; list.Add(s); } @@ -281,21 +297,53 @@ void AddUniqueString(UStringVector &list, const UString &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())]; + int pathMode2 = kPathModeButtonsVals[_pathMode.GetCurSel()]; + if (PathMode != NExtract::NPathMode::kCurPaths || + pathMode2 != NExtract::NPathMode::kFullPaths) + PathMode = (NExtract::NPathMode::EEnum)pathMode2; + + OverwriteMode = (NExtract::NOverwriteMode::EEnum)kOverwriteButtonsVals[_overwriteMode.GetCurSel()]; // _filesMode = (NExtractionDialog::NFilesMode::EEnum)GetFilesMode(); _passwordControl.GetText(Password); + #endif - NExtract::CInfo info; - info.PathMode = PathMode; - info.OverwriteMode = OverwriteMode; - info.ShowPassword = (IsButtonCheckedBool(IDC_EXTRACT_CHECK_SHOW_PASSWORD)); + #ifndef NO_REGISTRY + + // GetButton_Bools(IDX_EXTRACT_ALT_STREAMS, AltStreams, _info.AltStreams); + GetButton_Bools(IDX_EXTRACT_NT_SECUR, NtSecurity, _info.NtSecurity); + GetButton_Bools(IDX_EXTRACT_ELIM_DUP, ElimDup, _info.ElimDup); + + bool showPassword = IsShowPasswordChecked(); + if (showPassword != _info.ShowPassword.Val) + { + _info.ShowPassword.Def = true; + _info.ShowPassword.Val = showPassword; + } + + if (_info.PathMode != pathMode2) + { + _info.PathMode_Force = true; + _info.PathMode = (NExtract::NPathMode::EEnum)pathMode2; + /* + // we allow kAbsPaths in registry. + if (_info.PathMode == NExtract::NPathMode::kAbsPaths) + _info.PathMode = NExtract::NPathMode::kFullPaths; + */ + } + + if (!OverwriteMode_Force && _info.OverwriteMode != OverwriteMode) + _info.OverwriteMode_Force = true; + _info.OverwriteMode = OverwriteMode; + + + #else + + ElimDup.Val = IsButtonCheckedBool(IDX_EXTRACT_ELIM_DUP); + + #endif UString s; @@ -318,33 +366,49 @@ void CExtractDialog::OnOK() #endif s.Trim(); + NName::NormalizeDirPathPrefix(s); + + #ifndef _SFX + + bool splitDest = IsButtonCheckedBool(IDX_EXTRACT_NAME_ENABLE); + if (splitDest) + { + UString pathName; + _pathName.GetText(pathName); + pathName.Trim(); + s += pathName; + NName::NormalizeDirPathPrefix(s); + } + if (splitDest != _info.SplitDest.Val) + { + _info.SplitDest.Def = true; + _info.SplitDest.Val = splitDest; + } + + #endif + + DirPath = s; + + #ifndef NO_REGISTRY + _info.Paths.Clear(); #ifndef _SFX - AddUniqueString(info.Paths, s); + 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); + AddUniqueString(_info.Paths, sTemp); } - info.Save(); + _info.Save(); #endif + CModalDialog::OnOK(); } -/* -void CExtractDialog::UpdateWildCardState() -{ - // UpdateData(TRUE); - // m_Wildcards.EnableWindow(BoolToBOOL(m_Files == kWildcardsButtonIndex)); -} -*/ - -#ifndef NO_REGISTRY +#ifndef NO_REGISTRY static LPCWSTR kHelpTopic = L"fm/plugins/7-zip/extract.htm"; void CExtractDialog::OnHelp() { diff --git a/CPP/7zip/UI/GUI/ExtractDialog.h b/CPP/7zip/UI/GUI/ExtractDialog.h old mode 100755 new mode 100644 index b0636c72..33349ffc --- a/CPP/7zip/UI/GUI/ExtractDialog.h +++ b/CPP/7zip/UI/GUI/ExtractDialog.h @@ -5,16 +5,17 @@ #include "ExtractDialogRes.h" -#include "Windows/Control/Edit.h" -#include "Windows/Control/ComboBox.h" +#include "../../../Windows/Control/ComboBox.h" +#include "../../../Windows/Control/Edit.h" -#ifndef NO_REGISTRY -#include "../Common/ZipRegistry.h" -#endif #include "../Common/ExtractMode.h" #include "../FileManager/DialogSize.h" +#ifndef NO_REGISTRY +#include "../Common/ZipRegistry.h" +#endif + namespace NExtractionDialog { /* @@ -37,8 +38,9 @@ class CExtractDialog: public NWindows::NControl::CModalDialog #else NWindows::NControl::CComboBox _path; #endif - + #ifndef _SFX + NWindows::NControl::CEdit _pathName; NWindows::NControl::CEdit _passwordControl; NWindows::NControl::CComboBox _pathMode; NWindows::NControl::CComboBox _overwriteMode; @@ -51,24 +53,44 @@ class CExtractDialog: public NWindows::NControl::CModalDialog void OnButtonSetPath(); + void CheckButton_TwoBools(UINT id, const CBoolPair &b1, const CBoolPair &b2); + void GetButton_Bools(UINT id, CBoolPair &b1, CBoolPair &b2); virtual bool OnInit(); virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); virtual void OnOK(); - #ifndef NO_REGISTRY + + #ifndef NO_REGISTRY + virtual void OnHelp(); + + NExtract::CInfo _info; + #endif + + bool IsShowPasswordChecked() const { return IsButtonCheckedBool(IDX_PASSWORD_SHOW); } public: // bool _enableSelectedFilesButton; // bool _enableFilesButton; // NExtractionDialog::NFilesMode::EEnum FilesMode; - UString DirectoryPath; + UString DirPath; + UString ArcPath; + #ifndef _SFX UString Password; #endif + bool PathMode_Force; + bool OverwriteMode_Force; NExtract::NPathMode::EEnum PathMode; NExtract::NOverwriteMode::EEnum OverwriteMode; + #ifndef _SFX + // CBoolPair AltStreams; + CBoolPair NtSecurity; + #endif + + CBoolPair ElimDup; + INT_PTR Create(HWND aWndParent = 0) { #ifdef _SFX @@ -76,8 +98,16 @@ public: #else BIG_DIALOG_SIZE(300, 160); #endif - return CModalDialog::Create(SIZED_DIALOG(IDD_DIALOG_EXTRACT), aWndParent); + return CModalDialog::Create(SIZED_DIALOG(IDD_EXTRACT), aWndParent); } + + CExtractDialog(): + PathMode_Force(false), + OverwriteMode_Force(false) + { + ElimDup.Val = true; + } + }; #endif diff --git a/CPP/7zip/UI/GUI/ExtractDialog.rc b/CPP/7zip/UI/GUI/ExtractDialog.rc old mode 100755 new mode 100644 index ec4c20c2..3728b96d --- a/CPP/7zip/UI/GUI/ExtractDialog.rc +++ b/CPP/7zip/UI/GUI/ExtractDialog.rc @@ -1,8 +1,8 @@ #include "ExtractDialogRes.h" #include "../../GuiCommon.rc" -#define xc 280 -#define yc 128 +#define xc 336 +#define yc 168 #undef g1xs #undef g2x @@ -10,9 +10,9 @@ #undef g2xs #undef g2xs2 -#define g1xs 128 +#define g1xs 160 -#define gSpace 24 +#define gSpace 20 #define g2x (m + g1xs + gSpace) #define g2x2 (g2x + m) #define g2xs (xc - g1xs - gSpace) @@ -25,26 +25,38 @@ #define GROUP_Y_SIZE 56 #endif -IDD_DIALOG_EXTRACT MY_DIALOG +IDD_EXTRACT DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT 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 "E&xtract to:", IDT_EXTRACT_EXTRACT_TO, m, m, xc, 8 + COMBOBOX IDC_EXTRACT_PATH, m, m + 12, xc - bxsDots - 12, 100, MY_COMBO_WITH_EDIT + PUSHBUTTON "...", IDB_EXTRACT_SET_PATH, xs - m - bxsDots, m + 12 - 2, bxsDots, bys, WS_GROUP + + CONTROL "", IDX_EXTRACT_NAME_ENABLE, MY_CHECKBOX, m, m + 34, 12, 10 + EDITTEXT IDE_EXTRACT_NAME, m + 12 + 2, m + 32, g1xs - 12 - 2, 14, ES_AUTOHSCROLL + + LTEXT "Path mode:", IDT_EXTRACT_PATH_MODE, m, m + 52, g1xs, 8 + COMBOBOX IDC_EXTRACT_PATH_MODE, m, m + 64, g1xs, 140, MY_COMBO + + CONTROL "Eliminate duplication of root folder", IDX_EXTRACT_ELIM_DUP, MY_CHECKBOX, + m, m + 84, g1xs, 10 + + LTEXT "Overwrite mode:", IDT_EXTRACT_OVERWRITE_MODE, m, m + 104, g1xs, 8 + COMBOBOX IDC_EXTRACT_OVERWRITE_MODE, m, m + 116, g1xs, 140, MY_COMBO - 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 + GROUPBOX "Password", IDG_PASSWORD, g2x, m + 36, g2xs, GROUP_Y_SIZE + EDITTEXT IDE_EXTRACT_PASSWORD, g2x2, m + 50, g2xs2, 14, ES_PASSWORD | ES_AUTOHSCROLL + CONTROL "Show Password", IDX_PASSWORD_SHOW, MY_CHECKBOX, g2x2, m + 72, g2xs2, 10 - GROUPBOX "Password", IDC_EXTRACT_PASSWORD, g2x, m + 36, g2xs, GROUP_Y_SIZE - 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 +// CONTROL "Restore alternate data streams", IDX_EXTRACT_ALT_STREAMS, MY_CHECKBOX, +// g2x, m + 104, g2xs, 10 + CONTROL "Restore file security", IDX_EXTRACT_NT_SECUR, MY_CHECKBOX, + g2x, m + 104, g2xs, 10 - DEFPUSHBUTTON "OK", IDOK, bx3, by, bxs, bys, WS_GROUP + DEFPUSHBUTTON "OK", IDOK, bx3, by, bxs, bys, WS_GROUP PUSHBUTTON "Cancel", IDCANCEL, bx2, by, bxs, bys - PUSHBUTTON "Help", IDHELP, bx1, by, bxs, bys + PUSHBUTTON "Help", IDHELP, bx1, by, bxs, bys END @@ -63,22 +75,22 @@ END #define g1xs 64 -IDD_DIALOG_EXTRACT_2 MY_DIALOG +IDD_EXTRACT_2 DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT 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 "E&xtract to:", IDT_EXTRACT_EXTRACT_TO, m, m, xc - bxsDots - 8, 8 + COMBOBOX IDC_EXTRACT_PATH, m, m + 12, xc - bxsDots - 8, 100, MY_COMBO_WITH_EDIT + PUSHBUTTON "...", IDB_EXTRACT_SET_PATH, xs - m - bxsDots, m + 12 - 3, bxsDots, bys, WS_GROUP - LTEXT "Path mode:", 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 "Path mode:", IDT_EXTRACT_PATH_MODE, m, m + 36, g1xs, 8 + COMBOBOX IDC_EXTRACT_PATH_MODE, m + g1xs, m + 36, xc - g1xs, 100, MY_COMBO - LTEXT "Overwrite mode:", 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 "Overwrite mode:", IDT_EXTRACT_OVERWRITE_MODE, m, m + 56, g1xs, 8 + COMBOBOX IDC_EXTRACT_OVERWRITE_MODE, m + g1xs, m + 56, xc - g1xs, 100, MY_COMBO - LTEXT "Password", 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 + LTEXT "Password", IDG_PASSWORD, m, m + 76, g1xs, 8 + EDITTEXT IDE_EXTRACT_PASSWORD, m + g1xs, m + 76, xc - g1xs, 14, ES_PASSWORD | ES_AUTOHSCROLL + CONTROL "Show Password", IDX_PASSWORD_SHOW, MY_CHECKBOX, m, m + 92, xc, 10 OK_CANCEL END diff --git a/CPP/7zip/UI/GUI/ExtractDialogRes.h b/CPP/7zip/UI/GUI/ExtractDialogRes.h old mode 100755 new mode 100644 index 38652b29..403a6546 --- a/CPP/7zip/UI/GUI/ExtractDialogRes.h +++ b/CPP/7zip/UI/GUI/ExtractDialogRes.h @@ -1,19 +1,24 @@ -#define IDD_DIALOG_EXTRACT 552 -#define IDD_DIALOG_EXTRACT_2 652 +#define IDD_EXTRACT 3400 +#define IDD_EXTRACT_2 13400 -#define IDC_STATIC_EXTRACT_EXTRACT_TO 1020 -#define IDC_EXTRACT_COMBO_PATH 1021 -#define IDC_EXTRACT_BUTTON_SET_PATH 1022 +#define IDC_EXTRACT_PATH 100 +#define IDB_EXTRACT_SET_PATH 101 +#define IDC_EXTRACT_PATH_MODE 102 +#define IDC_EXTRACT_OVERWRITE_MODE 103 -#define IDC_EXTRACT_COMBO_PATH_MODE 1030 -#define IDC_EXTRACT_COMBO_OVERWRITE_MODE 1031 +#define IDE_EXTRACT_PASSWORD 120 -#define IDC_EXTRACT_PATH_MODE 1040 -#define IDC_EXTRACT_OVERWRITE_MODE 1050 +#define IDE_EXTRACT_NAME 130 +#define IDX_EXTRACT_NAME_ENABLE 131 -#define IDC_EXTRACT_FILES 1060 -#define IDC_EXTRACT_PASSWORD 1100 -#define IDC_EXTRACT_EDIT_PASSWORD 1101 -#define IDC_EXTRACT_CHECK_SHOW_PASSWORD 1102 +#define IDT_EXTRACT_EXTRACT_TO 3401 +#define IDT_EXTRACT_PATH_MODE 3410 +#define IDT_EXTRACT_OVERWRITE_MODE 3420 +#define IDX_EXTRACT_ELIM_DUP 3430 +#define IDX_EXTRACT_NT_SECUR 3431 +// #define IDX_EXTRACT_ALT_STREAMS 3432 + +#define IDX_PASSWORD_SHOW 3803 +#define IDG_PASSWORD 3807 diff --git a/CPP/7zip/UI/GUI/ExtractGUI.cpp b/CPP/7zip/UI/GUI/ExtractGUI.cpp old mode 100755 new mode 100644 index 9d39bffd..b5fbeaec --- a/CPP/7zip/UI/GUI/ExtractGUI.cpp +++ b/CPP/7zip/UI/GUI/ExtractGUI.cpp @@ -2,19 +2,19 @@ #include "StdAfx.h" -#include "Common/IntToString.h" -#include "Common/StringConvert.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" -#include "Windows/Error.h" -#include "Windows/FileDir.h" -#include "Windows/FileFind.h" -#include "Windows/FileName.h" -#include "Windows/Thread.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/Thread.h" #include "../FileManager/ExtractCallback.h" #include "../FileManager/FormatUtils.h" #include "../FileManager/LangUtils.h" #include "../FileManager/resourceGui.h" +#include "../FileManager/OverwriteDialogRes.h" #include "../Common/ArchiveExtractCallback.h" #include "../Common/PropIDUtils.h" @@ -26,34 +26,45 @@ #include "ExtractDialog.h" #include "ExtractGUI.h" +#include "HashGUI.h" + +#include "../FileManager/PropertyNameRes.h" using namespace NWindows; +using namespace NFile; +using namespace NDir; static const wchar_t *kIncorrectOutDir = L"Incorrect output directory path"; #ifndef _SFX -static void AddValuePair(UINT resourceID, UInt32 langID, UInt64 value, UString &s) +static void AddValuePair(UString &s, UINT resourceID, UInt64 value, bool addColon = true) { wchar_t sz[32]; - s += LangString(resourceID, langID); + s += LangString(resourceID); + if (addColon) + s += L':'; s += L' '; ConvertUInt64ToString(value, sz); s += sz; s += L'\n'; } -static void AddSizePair(UINT resourceID, UInt32 langID, UInt64 value, UString &s) +static void AddSizePair(UString &s, UINT resourceID, UInt64 value) { wchar_t sz[32]; - s += LangString(resourceID, langID); - s += L' '; + s += LangString(resourceID); + s += L": "; ConvertUInt64ToString(value, sz); - s += sz; - ConvertUInt64ToString(value >> 20, sz); - s += L" ("; - s += sz; - s += L" MB)"; + s += MyFormatNew(IDS_FILE_SIZE, sz); + // s += sz; + if (value >= (1 << 20)) + { + ConvertUInt64ToString(value >> 20, sz); + s += L" ("; + s += sz; + s += L" MB)"; + } s += L'\n'; } @@ -65,12 +76,16 @@ class CThreadExtracting: public CProgressThreadVirt public: CCodecs *codecs; CExtractCallbackImp *ExtractCallbackSpec; - CIntVector FormatIndices; + const CObjectVector *FormatIndices; + const CIntVector *ExcludedFormatIndices; UStringVector *ArchivePaths; UStringVector *ArchivePathsFull; const NWildcard::CCensorNode *WildcardCensor; const CExtractOptions *Options; + #ifndef _SFX + CHashBundle *HashBundle; + #endif CMyComPtr ExtractCallback; UString Title; }; @@ -78,32 +93,52 @@ public: 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()) + if (HashBundle) + HashBundle->Init(); + #endif + + HRESULT res = Extract(codecs, + *FormatIndices, *ExcludedFormatIndices, + *ArchivePaths, *ArchivePathsFull, + *WildcardCensor, *Options, ExtractCallbackSpec, ExtractCallback, + #ifndef _SFX + HashBundle, + #endif + FinalMessage.ErrorMessage.Message, Stat); + #ifndef _SFX + if (res == S_OK && 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) + AddValuePair(s, IDS_ARCHIVES_COLON, Stat.NumArchives, false); + AddSizePair(s, IDS_PROP_PACKED_SIZE, Stat.PackSize); + + if (!HashBundle) + { + if (Stat.NumFolders != 0) + AddValuePair(s, IDS_PROP_FOLDERS, Stat.NumFolders); + AddValuePair(s, IDS_PROP_FILES, Stat.NumFiles); + AddSizePair(s, IDS_PROP_SIZE, Stat.UnpackSize); + if (Stat.NumAltStreams != 0) + { + s += L'\n'; + AddValuePair(s, IDS_PROP_NUM_ALT_STREAMS, Stat.NumAltStreams); + AddSizePair(s, IDS_PROP_ALT_STREAMS_SIZE, Stat.AltStreams_UnpackSize); + } + } + + if (HashBundle) { - wchar_t temp[16]; - ConvertUInt32ToHex(Stat.CrcSum, temp); - s += L"CRC: "; - s += temp; s += L'\n'; + AddHashBundleRes(s, *HashBundle, UString()); } s += L'\n'; - s += LangString(IDS_MESSAGE_NO_ERRORS, 0x02000608); + s += LangString(IDS_MESSAGE_NO_ERRORS); - OkMessageTitle = Title; - OkMessage = s; + FinalMessage.OkMessage.Title = Title; + FinalMessage.OkMessage.Message = s; } #endif return res; @@ -111,11 +146,15 @@ HRESULT CThreadExtracting::ProcessVirt() HRESULT ExtractGUI( CCodecs *codecs, - const CIntVector &formatIndices, + const CObjectVector &formatIndices, + const CIntVector &excludedFormatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, CExtractOptions &options, + #ifndef _SFX + CHashBundle *hb, + #endif bool showDialog, bool &messageWasDisplayed, CExtractCallbackImp *extractCallback, @@ -125,51 +164,72 @@ HRESULT ExtractGUI( CThreadExtracting extracter; extracter.codecs = codecs; - extracter.FormatIndices = formatIndices; + extracter.FormatIndices = &formatIndices; + extracter.ExcludedFormatIndices = &excludedFormatIndices; if (!options.TestMode) { FString outputDir = options.OutputDir; #ifndef UNDER_CE if (outputDir.IsEmpty()) - NFile::NDirectory::MyGetCurrentDirectory(outputDir); + GetCurrentDir(outputDir); #endif if (showDialog) { CExtractDialog dialog; FString outputDirFull; - if (!NFile::NDirectory::MyGetFullPathName(outputDir, outputDirFull)) + if (!MyGetFullPathName(outputDir, outputDirFull)) { ShowErrorMessage(kIncorrectOutDir); messageWasDisplayed = true; return E_FAIL; } - NFile::NName::NormalizeDirPathPrefix(outputDirFull); - dialog.DirectoryPath = fs2us(outputDirFull); + NName::NormalizeDirPathPrefix(outputDirFull); + + dialog.DirPath = fs2us(outputDirFull); + + dialog.OverwriteMode = options.OverwriteMode; + dialog.OverwriteMode_Force = options.OverwriteMode_Force; + dialog.PathMode = options.PathMode; + dialog.PathMode_Force = options.PathMode_Force; + dialog.ElimDup = options.ElimDup; - // dialog.OverwriteMode = options.OverwriteMode; - // dialog.PathMode = options.PathMode; + if (archivePathsFull.Size() == 1) + dialog.ArcPath = archivePathsFull[0]; + + #ifndef _SFX + // dialog.AltStreams = options.NtOptions.AltStreams; + dialog.NtSecurity = options.NtOptions.NtSecurity; + if (extractCallback->PasswordIsDefined) + dialog.Password = extractCallback->Password; + #endif if (dialog.Create(hwndParent) != IDOK) return E_ABORT; - outputDir = us2fs(dialog.DirectoryPath); + + outputDir = us2fs(dialog.DirPath); + options.OverwriteMode = dialog.OverwriteMode; options.PathMode = dialog.PathMode; + options.ElimDup = dialog.ElimDup; + #ifndef _SFX + // options.NtOptions.AltStreams = dialog.AltStreams; + options.NtOptions.NtSecurity = dialog.NtSecurity; extractCallback->Password = dialog.Password; extractCallback->PasswordIsDefined = !dialog.Password.IsEmpty(); #endif } - if (!NFile::NDirectory::MyGetFullPathName(outputDir, options.OutputDir)) + if (!MyGetFullPathName(outputDir, options.OutputDir)) { ShowErrorMessage(kIncorrectOutDir); messageWasDisplayed = true; return E_FAIL; } - NFile::NName::NormalizeDirPathPrefix(options.OutputDir); + NName::NormalizeDirPathPrefix(options.OutputDir); /* - if(!NFile::NDirectory::CreateComplexDirectory(options.OutputDir)) + if(!CreateComplexDirectory(options.OutputDir)) { UString s = GetUnicodeString(NError::MyFormatMessage(GetLastError())); UString s2 = MyFormatNew(IDS_CANNOT_CREATE_FOLDER, @@ -183,8 +243,7 @@ HRESULT ExtractGUI( */ } - UString title = LangStringSpec(options.TestMode ? IDS_PROGRESS_TESTING : IDS_PROGRESS_EXTRACTING, - options.TestMode ? 0x02000F90: 0x02000890); + UString title = LangString(options.TestMode ? IDS_PROGRESS_TESTING : IDS_PROGRESS_EXTRACTING); extracter.Title = title; extracter.ExtractCallbackSpec = extractCallback; @@ -198,6 +257,9 @@ HRESULT ExtractGUI( extracter.ArchivePathsFull = &archivePathsFull; extracter.WildcardCensor = &wildcardCensor; extracter.Options = &options; + #ifndef _SFX + extracter.HashBundle = hb; + #endif extracter.ProgressDialog.IconID = IDI_ICON; diff --git a/CPP/7zip/UI/GUI/ExtractGUI.h b/CPP/7zip/UI/GUI/ExtractGUI.h old mode 100755 new mode 100644 index b0a692f0..d55b30de --- a/CPP/7zip/UI/GUI/ExtractGUI.h +++ b/CPP/7zip/UI/GUI/ExtractGUI.h @@ -21,11 +21,15 @@ HRESULT ExtractGUI( CCodecs *codecs, - const CIntVector &formatIndices, + const CObjectVector &formatIndices, + const CIntVector &excludedFormatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, CExtractOptions &options, + #ifndef _SFX + CHashBundle *hb, + #endif bool showDialog, bool &messageWasDisplayed, CExtractCallbackImp *extractCallback, diff --git a/CPP/7zip/UI/GUI/ExtractRes.h b/CPP/7zip/UI/GUI/ExtractRes.h old mode 100755 new mode 100644 index 6219edda..48738bbb --- a/CPP/7zip/UI/GUI/ExtractRes.h +++ b/CPP/7zip/UI/GUI/ExtractRes.h @@ -1,29 +1,44 @@ -#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 +#define IDS_MEM_ERROR 3000 + +#define IDS_CANNOT_CREATE_FOLDER 3003 +#define IDS_UPDATE_NOT_SUPPORTED 3004 +#define IDS_CANT_OPEN_ARCHIVE 3005 +#define IDS_CANT_OPEN_ENCRYPTED_ARCHIVE 3006 +#define IDS_UNSUPPORTED_ARCHIVE_TYPE 3007 + +#define IDS_PROGRESS_EXTRACTING 3300 + +#define IDS_EXTRACT_SET_FOLDER 3402 + +#define IDS_EXTRACT_PATHS_FULL 3411 +#define IDS_EXTRACT_PATHS_NO 3412 +#define IDS_EXTRACT_PATHS_ABS 3413 +#define IDS_PATH_MODE_RELAT 3414 + +#define IDS_EXTRACT_OVERWRITE_ASK 3421 +#define IDS_EXTRACT_OVERWRITE_WITHOUT_PROMPT 3422 +#define IDS_EXTRACT_OVERWRITE_SKIP_EXISTING 3423 +#define IDS_EXTRACT_OVERWRITE_RENAME 3424 +#define IDS_EXTRACT_OVERWRITE_RENAME_EXISTING 3425 + +#define IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD 3700 +#define IDS_EXTRACT_MESSAGE_DATA_ERROR 3701 +#define IDS_EXTRACT_MESSAGE_CRC_ERROR 3702 +#define IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED 3703 +#define IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED 3704 + +#define IDS_EXTRACT_MSG_WRONG_PSW 3710 +// #define IDS_EXTRACT_MSG_ENCRYPTED 3711 + +#define IDS_EXTRACT_MSG_UNSUPPORTED_METHOD 3721 +#define IDS_EXTRACT_MSG_DATA_ERROR 3722 +#define IDS_EXTRACT_MSG_CRC_ERROR 3723 +#define IDS_EXTRACT_MSG_UNAVAILABLE_DATA 3724 +#define IDS_EXTRACT_MSG_UEXPECTED_END 3725 +#define IDS_EXTRACT_MSG_DATA_AFTER_END 3726 +#define IDS_EXTRACT_MSG_IS_NOT_ARC 3727 +#define IDS_EXTRACT_MSG_HEADERS_ERROR 3728 + +#define IDS_OPEN_MSG_UNAVAILABLE_START 3763 +#define IDS_OPEN_MSG_UNCONFIRMED_START 3764 +#define IDS_OPEN_MSG_UNSUPPORTED_FEATURE 3768 diff --git a/CPP/7zip/UI/GUI/FM.ico b/CPP/7zip/UI/GUI/FM.ico old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/GUI/GUI.cpp b/CPP/7zip/UI/GUI/GUI.cpp old mode 100755 new mode 100644 index 5b809a63..592f7673 --- a/CPP/7zip/UI/GUI/GUI.cpp +++ b/CPP/7zip/UI/GUI/GUI.cpp @@ -2,18 +2,19 @@ #include "StdAfx.h" -#include "Common/MyInitGuid.h" - #include "../../../../C/Alloc.h" -#include "Common/CommandLineParser.h" -#include "Common/MyException.h" -#include "Common/StringConvert.h" +#include "../../../Common/MyInitGuid.h" + +#include "../../../Common/CommandLineParser.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/MyException.h" +#include "../../../Common/StringConvert.h" -#include "Windows/Error.h" -#include "Windows/NtCheck.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/NtCheck.h" #ifdef _WIN32 -#include "Windows/MemoryLock.h" +#include "../../../Windows/MemoryLock.h" #endif #include "../Common/ArchiveCommandLine.h" @@ -24,6 +25,7 @@ #include "BenchmarkDialog.h" #include "ExtractGUI.h" +#include "HashGUI.h" #include "UpdateGUI.h" #include "ExtractRes.h" @@ -34,25 +36,50 @@ HINSTANCE g_hInstance; #ifndef _UNICODE #endif -#ifdef UNDER_CE -bool g_LVN_ITEMACTIVATE_Support = true; +#ifndef UNDER_CE + +DWORD g_ComCtl32Version; + +static DWORD GetDllVersion(LPCTSTR dllName) +{ + DWORD dwVersion = 0; + HINSTANCE hinstDll = LoadLibrary(dllName); + if (hinstDll) + { + DLLGETVERSIONPROC pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hinstDll, "DllGetVersion"); + if (pDllGetVersion) + { + DLLVERSIONINFO dvi; + ZeroMemory(&dvi, sizeof(dvi)); + dvi.cbSize = sizeof(dvi); + HRESULT hr = (*pDllGetVersion)(&dvi); + if (SUCCEEDED(hr)) + dwVersion = MAKELONG(dvi.dwMinorVersion, dvi.dwMajorVersion); + } + FreeLibrary(hinstDll); + } + return dwVersion; +} + #endif +bool g_LVN_ITEMACTIVATE_Support = true; + static void ErrorMessage(LPCWSTR message) { MessageBoxW(NULL, message, L"7-Zip", MB_ICONERROR | MB_OK); } -static void ErrorLangMessage(UINT resourceID, UInt32 langID) +static void ErrorLangMessage(UINT resourceID) { - ErrorMessage(LangString(resourceID, langID)); + ErrorMessage(LangString(resourceID)); } static const char *kNoFormats = "7-Zip cannot find the code that works with archives."; static int ShowMemErrorMessage() { - ErrorLangMessage(IDS_MEM_ERROR, 0x0200060B); + ErrorLangMessage(IDS_MEM_ERROR); return NExitCode::kMemoryError; } @@ -64,6 +91,12 @@ static int ShowSysErrorMessage(DWORD errorCode) return NExitCode::kFatalError; } +static void ThrowException_if_Error(HRESULT res) +{ + if (res != S_OK) + throw CSystemException(res); +} + static int Main2() { UStringVector commandStrings; @@ -79,52 +112,79 @@ static int Main2() return 0; } - CArchiveCommandLineOptions options; - CArchiveCommandLineParser parser; + CArcCmdLineOptions options; + CArcCmdLineParser parser; parser.Parse1(commandStrings, options); parser.Parse2(options); - #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) + #if defined(_WIN32) && !defined(UNDER_CE) + NSecurity::EnablePrivilege_SymLink(); + #ifdef _7ZIP_LARGE_PAGES if (options.LargePages) - NSecurity::EnableLockMemoryPrivilege(); + NSecurity::EnablePrivilege_LockMemory(); + #endif #endif CCodecs *codecs = new CCodecs; + #ifdef EXTERNAL_CODECS + CExternalCodecs __externalCodecs; + __externalCodecs.GetCodecs = codecs; + __externalCodecs.GetHashers = codecs; + #else CMyComPtr compressCodecsInfo = codecs; - HRESULT result = codecs->Load(); - if (result != S_OK) - throw CSystemException(result); + #endif + codecs->CaseSensitiveChange = options.CaseSensitiveChange; + codecs->CaseSensitive = options.CaseSensitive; + ThrowException_if_Error(codecs->Load()); bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); + if (codecs->Formats.Size() == 0 && - (isExtractGroupCommand || - options.Command.IsFromUpdateGroup())) + (isExtractGroupCommand + + || options.Command.IsFromUpdateGroup())) throw kNoFormats; - CIntVector formatIndices; - if (!codecs->FindFormatForArchiveType(options.ArcType, formatIndices)) + CObjectVector formatIndices; + if (!ParseOpenTypes(*codecs, options.ArcType, formatIndices)) { - ErrorLangMessage(IDS_UNSUPPORTED_ARCHIVE_TYPE, 0x0200060D); + ErrorLangMessage(IDS_UNSUPPORTED_ARCHIVE_TYPE); return NExitCode::kFatalError; } - + + CIntVector excludedFormatIndices; + FOR_VECTOR (k, options.ExcludedArcTypes) + { + CIntVector tempIndices; + if (!codecs->FindFormatForArchiveType(options.ExcludedArcTypes[k], tempIndices) + || tempIndices.Size() != 1) + { + ErrorLangMessage(IDS_UNSUPPORTED_ARCHIVE_TYPE); + return NExitCode::kFatalError; + } + excludedFormatIndices.AddToUniqueSorted(tempIndices[0]); + // excludedFormatIndices.Sort(); + } + + #ifdef EXTERNAL_CODECS + if (isExtractGroupCommand + || options.Command.CommandType == NCommandType::kHash + || options.Command.CommandType == NCommandType::kBenchmark) + ThrowException_if_Error(__externalCodecs.LoadCodecs()); + #endif + 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.Properties); - if (res != S_OK) - throw CSystemException(res); + HRESULT res = Benchmark(EXTERNAL_CODECS_VARS options.Properties); + /* + if (res == S_FALSE) + { + stdStream << "\nDecoding Error\n"; + return NExitCode::kFatalError; + } + */ + ThrowException_if_Error(res); } else if (isExtractGroupCommand) { @@ -139,23 +199,39 @@ static int Main2() ecs->Init(); CExtractOptions eo; + (CExtractOptionsBase &)eo = options.ExtractOptions; + eo.StdInMode = options.StdInMode; 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.TestMode = options.Command.IsTestCommand(); + + #ifndef _SFX eo.Properties = options.Properties; #endif bool messageWasDisplayed = false; - HRESULT result = ExtractGUI(codecs, formatIndices, + + #ifndef _SFX + CHashBundle hb; + CHashBundle *hb_ptr = NULL; + + if (!options.HashMethods.IsEmpty()) + { + hb_ptr = &hb; + ThrowException_if_Error(hb.SetMethods(EXTERNAL_CODECS_VARS options.HashMethods)); + } + #endif + + HRESULT result = ExtractGUI(codecs, + formatIndices, excludedFormatIndices, options.ArchivePathsSorted, options.ArchivePathsFullSorted, - options.WildcardCensor.Pairs.Front().Head, - eo, options.ShowDialog, messageWasDisplayed, ecs); + options.Censor.Pairs.Front().Head, + eo, + #ifndef _SFX + hb_ptr, + #endif + options.ShowDialog, messageWasDisplayed, ecs); if (result != S_OK) { if (result != E_ABORT && messageWasDisplayed) @@ -183,17 +259,21 @@ static int Main2() // callback.StdOutMode = options.UpdateOptions.StdOutMode; callback.Init(); - if (!options.UpdateOptions.Init(codecs, formatIndices, options.ArchiveName)) + if (!options.UpdateOptions.InitFormatIndex(codecs, formatIndices, options.ArchiveName) || + !options.UpdateOptions.SetArcPath(codecs, options.ArchiveName)) { - ErrorLangMessage(IDS_UPDATE_NOT_SUPPORTED, 0x02000601); + ErrorLangMessage(IDS_UPDATE_NOT_SUPPORTED); return NExitCode::kFatalError; } bool messageWasDisplayed = false; HRESULT result = UpdateGUI( - codecs, - options.WildcardCensor, options.UpdateOptions, + codecs, formatIndices, + options.ArchiveName, + options.Censor, + options.UpdateOptions, options.ShowDialog, - messageWasDisplayed, &callback); + messageWasDisplayed, + &callback); if (result != S_OK) { @@ -208,6 +288,27 @@ static int Main2() return NExitCode::kWarning; } } + else if (options.Command.CommandType == NCommandType::kHash) + { + bool messageWasDisplayed = false; + HRESULT result = HashCalcGUI(EXTERNAL_CODECS_VARS + options.Censor, options.HashOptions, messageWasDisplayed); + + 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"; @@ -233,12 +334,17 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, InitCommonControls(); + #ifndef UNDER_CE + g_ComCtl32Version = ::GetDllVersion(TEXT("comctl32.dll")); + g_LVN_ITEMACTIVATE_Support = (g_ComCtl32Version >= MAKELONG(71, 4)); + #endif + // OleInitialize is required for ProgressBar in TaskBar. #ifndef UNDER_CE OleInitialize(NULL); #endif - ReloadLang(); + LoadLangOneTime(); // setlocale(LC_COLLATE, ".ACP"); try @@ -249,9 +355,9 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, { return ShowMemErrorMessage(); } - catch(const CArchiveCommandLineException &e) + catch(const CArcCmdLineException &e) { - ErrorMessage(GetUnicodeString(e)); + ErrorMessage(e); return NExitCode::kUserError; } catch(const CSystemException &systemError) @@ -280,9 +386,16 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, ErrorMessage(GetUnicodeString(s)); return NExitCode::kFatalError; } + catch(int v) + { + wchar_t s[32]; + ConvertUInt32ToString(v, s); + ErrorMessage(UString(L"Error: ") + s); + return NExitCode::kFatalError; + } catch(...) { - ErrorLangMessage(IDS_UNKNOWN_ERROR, 0x0200060C); + ErrorMessage(L"Unknown error"); return NExitCode::kFatalError; } } diff --git a/CPP/7zip/UI/GUI/GUI.dsp b/CPP/7zip/UI/GUI/GUI.dsp old mode 100755 new mode 100644 index 382f592e..1cbdbfd4 --- a/CPP/7zip/UI/GUI/GUI.dsp +++ b/CPP/7zip/UI/GUI/GUI.dsp @@ -45,7 +45,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c -# ADD CPP /nologo /Gz /MD /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 CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" @@ -72,7 +72,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c -# ADD CPP /nologo /Gz /MDd /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 CPP /nologo /Gz /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" @@ -99,7 +99,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c -# ADD CPP /nologo /Gz /MD /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 CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" @@ -127,7 +127,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c -# ADD CPP /nologo /Gz /MDd /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 CPP /nologo /Gz /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" @@ -156,11 +156,11 @@ SOURCE=.\7zG.exe.manifest # End Source File # Begin Source File -SOURCE=.\FM.ico +SOURCE=.\ExtractRes.h # End Source File # Begin Source File -SOURCE=.\resource.h +SOURCE=.\FM.ico # End Source File # Begin Source File @@ -257,7 +257,11 @@ SOURCE=..\Common\ExtractMode.h # End Source File # Begin Source File -SOURCE=..\Common\HandlerLoader.h +SOURCE=..\Common\HashCalc.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\HashCalc.h # End Source File # Begin Source File @@ -397,6 +401,22 @@ SOURCE=.\BenchmarkDialog.h # End Source File # Begin Source File +SOURCE=..\FileManager\BrowseDialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\FileManager\BrowseDialog.h +# End Source File +# Begin Source File + +SOURCE=..\FileManager\ComboDialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\FileManager\ComboDialog.h +# End Source File +# Begin Source File + SOURCE=.\CompressDialog.cpp # End Source File # Begin Source File @@ -515,6 +535,14 @@ SOURCE=..\FileManager\StringUtils.cpp SOURCE=..\FileManager\StringUtils.h # End Source File +# Begin Source File + +SOURCE=..\FileManager\SysIconUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\FileManager\SysIconUtils.h +# End Source File # End Group # Begin Group "Engine" @@ -533,6 +561,14 @@ SOURCE=.\GUI.cpp # End Source File # Begin Source File +SOURCE=.\HashGUI.cpp +# End Source File +# Begin Source File + +SOURCE=.\HashGUI.h +# End Source File +# Begin Source File + SOURCE=.\UpdateCallbackGUI.cpp # End Source File # Begin Source File @@ -585,6 +621,14 @@ SOURCE=..\..\Common\FilterCoder.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\MethodProps.cpp # End Source File # Begin Source File @@ -601,12 +645,32 @@ SOURCE=..\..\Common\ProgressUtils.h # End Source File # Begin Source File +SOURCE=..\..\Common\PropId.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamObjects.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamObjects.h +# End Source File +# Begin Source File + SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\UniqBlocks.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\UniqBlocks.h +# End Source File # End Group # Begin Group "Compress" @@ -714,6 +778,34 @@ SOURCE=..\..\..\..\C\CpuArch.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Sort.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\Sort.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File @@ -727,6 +819,10 @@ SOURCE=..\..\..\..\C\Threads.h # 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 @@ -803,14 +899,6 @@ 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 @@ -891,11 +979,11 @@ SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Error.cpp +SOURCE=..\..\..\Windows\ErrorMsg.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Error.h +SOURCE=..\..\..\Windows\ErrorMsg.h # End Source File # Begin Source File @@ -923,6 +1011,10 @@ SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File +SOURCE=..\..\..\Windows\FileLink.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Windows\FileMapping.h # End Source File # Begin Source File @@ -935,6 +1027,14 @@ 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\MemoryLock.cpp # End Source File # Begin Source File @@ -951,11 +1051,11 @@ SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\PropVariantConversions.cpp +SOURCE=..\..\..\Windows\PropVariantConv.cpp # End Source File # Begin Source File -SOURCE=..\..\..\Windows\PropVariantConversions.h +SOURCE=..\..\..\Windows\PropVariantConv.h # End Source File # Begin Source File @@ -999,7 +1099,11 @@ SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File -SOURCE=..\..\..\Windows\Time.cpp +SOURCE=..\..\..\Windows\TimeUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\TimeUtils.h # End Source File # Begin Source File diff --git a/CPP/7zip/UI/GUI/GUI.dsw b/CPP/7zip/UI/GUI/GUI.dsw old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/GUI/HashGUI.cpp b/CPP/7zip/UI/GUI/HashGUI.cpp new file mode 100644 index 00000000..903e41fc --- /dev/null +++ b/CPP/7zip/UI/GUI/HashGUI.cpp @@ -0,0 +1,278 @@ +// HashGUI.cpp + +#include "StdAfx.h" + +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/ErrorMsg.h" + +#include "../FileManager/FormatUtils.h" +#include "../FileManager/LangUtils.h" +#include "../FileManager/OverwriteDialogRes.h" +#include "../FileManager/ProgressDialog2.h" +#include "../FileManager/ProgressDialog2Res.h" +#include "../FileManager/PropertyNameRes.h" +#include "../FileManager/resourceGUI.h" + +#include "HashGUI.h" + +using namespace NWindows; + +class CHashCallbackGUI: public CProgressThreadVirt, public IHashCallbackUI +{ + UInt64 NumFiles; + UStringVector FailedFiles; + bool _curIsFolder; + UString FirstFileName; + + HRESULT ProcessVirt(); + +public: + const NWildcard::CCensor *censor; + const CHashOptions *options; + + DECL_EXTERNAL_CODECS_LOC_VARS2; + + CHashCallbackGUI() {} + ~CHashCallbackGUI() { } + + INTERFACE_IHashCallbackUI(;) + + void AddErrorMessage(DWORD systemError, const wchar_t *name) + { + ProgressDialog.Sync.AddError_Code_Name(systemError, name); + } +}; + +static void NewLine(UString &s) +{ + s += L'\n'; +} + +static void AddValuePair(UString &s, UINT resourceID, UInt64 value) +{ + s += LangString(resourceID); + s += L": "; + wchar_t sz[32]; + ConvertUInt64ToString(value, sz); + s += sz; + NewLine(s); +} + +static void AddSizeValuePair(UString &s, UINT resourceID, UInt64 value) +{ + s += LangString(resourceID); + s += L": "; + wchar_t sz[32]; + ConvertUInt64ToString(value, sz); + s += MyFormatNew(IDS_FILE_SIZE, sz); + ConvertUInt64ToString(value >> 20, sz); + s += L" ("; + s += sz; + s += L" MB)"; + NewLine(s); +} + +HRESULT CHashCallbackGUI::StartScanning() +{ + CProgressSync &sync = ProgressDialog.Sync; + sync.Set_Status(LangString(IDS_SCANNING)); + return CheckBreak(); +} + +HRESULT CHashCallbackGUI::ScanProgress(UInt64 /* numFolders */, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) +{ + return ProgressDialog.Sync.ScanProgress(numFiles, totalSize, path, isDir); +} + +HRESULT CHashCallbackGUI::CanNotFindError(const wchar_t *name, DWORD systemError) +{ + FailedFiles.Add(name); + AddErrorMessage(systemError, name); + return CheckBreak(); +} + +HRESULT CHashCallbackGUI::FinishScanning() +{ + CProgressSync &sync = ProgressDialog.Sync; + sync.Set_FilePath(L""); + return CheckBreak(); +} + +HRESULT CHashCallbackGUI::CheckBreak() +{ + return ProgressDialog.Sync.CheckStop(); +} + +HRESULT CHashCallbackGUI::SetNumFiles(UInt64 numFiles) +{ + CProgressSync &sync = ProgressDialog.Sync; + sync.Set_NumFilesTotal(numFiles); + return CheckBreak(); +} + +HRESULT CHashCallbackGUI::SetTotal(UInt64 size) +{ + CProgressSync &sync = ProgressDialog.Sync; + sync.Set_NumBytesTotal(size); + return CheckBreak(); +} + +HRESULT CHashCallbackGUI::SetCompleted(const UInt64 *completed) +{ + return ProgressDialog.Sync.Set_NumBytesCur(completed); +} + +HRESULT CHashCallbackGUI::BeforeFirstFile(const CHashBundle & /* hb */) +{ + return S_OK; +} + +HRESULT CHashCallbackGUI::GetStream(const wchar_t *name, bool isFolder) +{ + if (NumFiles == 0) + FirstFileName = name; + _curIsFolder = isFolder; + CProgressSync &sync = ProgressDialog.Sync; + sync.Set_FilePath(name, isFolder); + return CheckBreak(); +} + +HRESULT CHashCallbackGUI::OpenFileError(const wchar_t *name, DWORD systemError) +{ + FailedFiles.Add(name); + // if (systemError == ERROR_SHARING_VIOLATION) + { + AddErrorMessage(systemError, name); + return S_FALSE; + } + // return systemError; +} + +HRESULT CHashCallbackGUI::SetOperationResult(UInt64 /* fileSize */, const CHashBundle & /* hb */, bool /* showHash */) +{ + CProgressSync &sync = ProgressDialog.Sync; + if (!_curIsFolder) + NumFiles++; + sync.Set_NumFilesCur(NumFiles); + return CheckBreak(); +} + +static void AddHashString(UString &s, const CHasherState &h, int digestIndex, const wchar_t *title) +{ + s += title; + s += L' '; + char temp[k_HashCalc_DigestSize_Max * 2 + 4]; + AddHashHexToString(temp, h.Digests[digestIndex], h.DigestSize); + s.AddAsciiStr(temp); + NewLine(s); +} + +static void AddHashResString(UString &s, const CHasherState &h, int digestIndex, UInt32 resID) +{ + UString s2 = LangString(resID); + s2.Replace(L"CRC", h.Name); + AddHashString(s, h, digestIndex, s2); +} + +void AddHashBundleRes(UString &s, const CHashBundle &hb, const UString &firstFileName) +{ + if (hb.NumErrors != 0) + { + AddValuePair(s, IDS_PROP_NUM_ERRORS, hb.NumErrors); + NewLine(s); + } + if (hb.NumFiles == 1 && hb.NumDirs == 0 && !firstFileName.IsEmpty()) + { + s += LangString(IDS_PROP_NAME); + s += L": "; + s += firstFileName; + NewLine(s); + } + else + { + AddValuePair(s, IDS_PROP_FOLDERS, hb.NumDirs); + AddValuePair(s, IDS_PROP_FILES, hb.NumFiles); + } + + AddSizeValuePair(s, IDS_PROP_SIZE, hb.FilesSize); + + if (hb.NumAltStreams != 0) + { + NewLine(s); + AddValuePair(s, IDS_PROP_NUM_ALT_STREAMS, hb.NumAltStreams); + AddSizeValuePair(s, IDS_PROP_ALT_STREAMS_SIZE, hb.AltStreamsSize); + } + + FOR_VECTOR (i, hb.Hashers) + { + NewLine(s); + const CHasherState &h = hb.Hashers[i]; + if (hb.NumFiles == 1 && hb.NumDirs == 0) + { + s += h.Name; + AddHashString(s, h, k_HashCalc_Index_DataSum, L":"); + } + else + { + AddHashResString(s, h, k_HashCalc_Index_DataSum, IDS_CHECKSUM_CRC_DATA); + AddHashResString(s, h, k_HashCalc_Index_NamesSum, IDS_CHECKSUM_CRC_DATA_NAMES); + } + if (hb.NumAltStreams != 0) + { + AddHashResString(s, h, k_HashCalc_Index_StreamsSum, IDS_CHECKSUM_CRC_STREAMS_NAMES); + } + } +} + +HRESULT CHashCallbackGUI::AfterLastFile(const CHashBundle &hb) +{ + UString s; + AddHashBundleRes(s, hb, FirstFileName); + + CProgressSync &sync = ProgressDialog.Sync; + sync.Set_NumFilesCur(hb.NumFiles); + + CProgressMessageBoxPair &pair = GetMessagePair(hb.NumErrors != 0); + pair.Message = s; + LangString(IDS_CHECKSUM_INFORMATION, pair.Title); + + return S_OK; +} + +HRESULT CHashCallbackGUI::ProcessVirt() +{ + NumFiles = 0; + + UString errorInfo; + HRESULT res = HashCalc(EXTERNAL_CODECS_LOC_VARS + *censor, *options, errorInfo, this); + + return res; +} + +HRESULT HashCalcGUI( + DECL_EXTERNAL_CODECS_LOC_VARS + const NWildcard::CCensor &censor, + const CHashOptions &options, + bool &messageWasDisplayed) +{ + CHashCallbackGUI t; + #ifdef EXTERNAL_CODECS + t.__externalCodecs = __externalCodecs; + #endif + t.censor = &censor; + t.options = &options; + + t.ProgressDialog.ShowCompressionInfo = false; + + const UString title = LangString(IDS_CHECKSUM_CALCULATING); + + t.ProgressDialog.MainTitle = L"7-Zip"; // LangString(IDS_APP_TITLE); + t.ProgressDialog.MainAddTitle = title + L' '; + + RINOK(t.Create(title)); + messageWasDisplayed = t.ThreadFinishedOK && t.ProgressDialog.MessagesDisplayed; + return S_OK; +} diff --git a/CPP/7zip/UI/GUI/HashGUI.h b/CPP/7zip/UI/GUI/HashGUI.h new file mode 100644 index 00000000..40340365 --- /dev/null +++ b/CPP/7zip/UI/GUI/HashGUI.h @@ -0,0 +1,16 @@ +// HashGUI.h + +#ifndef __HASH_GUI_H +#define __HASH_GUI_H + +#include "../Common/HashCalc.h" + +HRESULT HashCalcGUI( + DECL_EXTERNAL_CODECS_LOC_VARS + const NWildcard::CCensor &censor, + const CHashOptions &options, + bool &messageWasDisplayed); + +void AddHashBundleRes(UString &s, const CHashBundle &hb, const UString &firstFileName); + +#endif diff --git a/CPP/7zip/UI/GUI/StdAfx.cpp b/CPP/7zip/UI/GUI/StdAfx.cpp old mode 100755 new mode 100644 diff --git a/CPP/7zip/UI/GUI/StdAfx.h b/CPP/7zip/UI/GUI/StdAfx.h old mode 100755 new mode 100644 index 46ea51cf..9e322f96 --- a/CPP/7zip/UI/GUI/StdAfx.h +++ b/CPP/7zip/UI/GUI/StdAfx.h @@ -3,11 +3,17 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include -#include -#include -#include +// #define _WIN32_WINNT 0x0400 +#define _WIN32_WINNT 0x0500 +#define WINVER _WIN32_WINNT -#include "Common/NewHandler.h" +#include "../../../Common/Common.h" + +// #include +#include +#include + +// #define printf(x) NO_PRINTF_(x) +// #define sprintf(x) NO_SPRINTF_(x) #endif diff --git a/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp b/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp old mode 100755 new mode 100644 index 8ec01867..36af147b --- a/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp +++ b/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp @@ -2,13 +2,17 @@ #include "StdAfx.h" -#include "Common/IntToString.h" -#include "Common/StringConvert.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" -#include "Windows/Error.h" -#include "Windows/PropVariant.h" +#include "../../../Windows/PropVariant.h" #include "../FileManager/PasswordDialog.h" +#include "../FileManager/LangUtils.h" + +#include "../FileManager/resourceGUI.h" + +#include "resource2.h" #include "UpdateCallbackGUI.h" @@ -22,67 +26,68 @@ void CUpdateCallbackGUI::Init() 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) +HRESULT CUpdateCallbackGUI::OpenResult(const wchar_t *name, HRESULT result, const wchar_t *errorArcType) { if (result != S_OK) { - AddErrorMessage (UString(L"Error: ") + name + UString(L" is not supported archive")); + UString s; + if (errorArcType) + { + s += L"Can not open the file as ["; + s += errorArcType; + s += L"] archive"; + } + else + s += L"The file is not supported archive"; + ProgressDialog->Sync.AddError_Message_Name(s, name); } return S_OK; } HRESULT CUpdateCallbackGUI::StartScanning() { + CProgressSync &sync = ProgressDialog->Sync; + sync.Set_Status(LangString(IDS_SCANNING)); return S_OK; } HRESULT CUpdateCallbackGUI::CanNotFindError(const wchar_t *name, DWORD systemError) { FailedFiles.Add(name); - AddErrorMessage(name, systemError); + ProgressDialog->Sync.AddError_Code_Name(systemError, name); return S_OK; } HRESULT CUpdateCallbackGUI::FinishScanning() { + CProgressSync &sync = ProgressDialog->Sync; + sync.Set_Status(L""); return S_OK; } HRESULT CUpdateCallbackGUI::StartArchive(const wchar_t *name, bool /* updating */) { - ProgressDialog->Sync.SetTitleFileName(name); + CProgressSync &sync = ProgressDialog->Sync; + sync.Set_Status(LangString(IDS_PROGRESS_COMPRESSING)); + sync.Set_TitleFileName(name); return S_OK; } HRESULT CUpdateCallbackGUI::FinishArchive() { + CProgressSync &sync = ProgressDialog->Sync; + sync.Set_Status(L""); return S_OK; } HRESULT CUpdateCallbackGUI::CheckBreak() { - return ProgressDialog->Sync.ProcessStopAndPause(); + return ProgressDialog->Sync.CheckStop(); } -HRESULT CUpdateCallbackGUI::ScanProgress(UInt64 /* numFolders */, UInt64 numFiles, const wchar_t *path) +HRESULT CUpdateCallbackGUI::ScanProgress(UInt64 /* numFolders */, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) { - ProgressDialog->Sync.SetCurrentFileName(path); - ProgressDialog->Sync.SetNumFilesTotal(numFiles); - return ProgressDialog->Sync.ProcessStopAndPause(); + return ProgressDialog->Sync.ScanProgress(numFiles, totalSize, path, isDir); } HRESULT CUpdateCallbackGUI::Finilize() @@ -92,34 +97,30 @@ HRESULT CUpdateCallbackGUI::Finilize() HRESULT CUpdateCallbackGUI::SetNumFiles(UInt64 numFiles) { - ProgressDialog->Sync.SetNumFilesTotal(numFiles); + ProgressDialog->Sync.Set_NumFilesTotal(numFiles); return S_OK; } HRESULT CUpdateCallbackGUI::SetTotal(UInt64 total) { - ProgressDialog->Sync.SetProgress(total, 0); + ProgressDialog->Sync.Set_NumBytesTotal(total); return S_OK; } -HRESULT CUpdateCallbackGUI::SetCompleted(const UInt64 *completeValue) +HRESULT CUpdateCallbackGUI::SetCompleted(const UInt64 *completed) { - RINOK(CheckBreak()); - if (completeValue != NULL) - ProgressDialog->Sync.SetPos(*completeValue); - return S_OK; + return ProgressDialog->Sync.Set_NumBytesCur(completed); } HRESULT CUpdateCallbackGUI::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { - RINOK(CheckBreak()); - ProgressDialog->Sync.SetRatioInfo(inSize, outSize); - return S_OK; + ProgressDialog->Sync.Set_Ratio(inSize, outSize); + return CheckBreak(); } HRESULT CUpdateCallbackGUI::GetStream(const wchar_t *name, bool /* isAnti */) { - ProgressDialog->Sync.SetCurrentFileName(name); + ProgressDialog->Sync.Set_FilePath(name); return S_OK; } @@ -128,7 +129,7 @@ HRESULT CUpdateCallbackGUI::OpenFileError(const wchar_t *name, DWORD systemError FailedFiles.Add(name); // if (systemError == ERROR_SHARING_VIOLATION) { - AddErrorMessage(name, systemError); + ProgressDialog->Sync.AddError_Code_Name(systemError, name); return S_FALSE; } // return systemError; @@ -137,7 +138,7 @@ HRESULT CUpdateCallbackGUI::OpenFileError(const wchar_t *name, DWORD systemError HRESULT CUpdateCallbackGUI::SetOperationResult(Int32 /* operationResult */) { NumFiles++; - ProgressDialog->Sync.SetNumFilesCur(NumFiles); + ProgressDialog->Sync.Set_NumFilesCur(NumFiles); return S_OK; } @@ -150,7 +151,7 @@ HRESULT CUpdateCallbackGUI::CryptoGetTextPassword2(Int32 *passwordIsDefined, BST { CPasswordDialog dialog; ProgressDialog->WaitCreating(); - if (dialog.Create(*ProgressDialog) == IDCANCEL) + if (dialog.Create(*ProgressDialog) != IDOK) return E_ABORT; Password = dialog.Password; PasswordIsDefined = true; @@ -178,7 +179,7 @@ HRESULT CUpdateCallbackGUI::CloseProgress() HRESULT CUpdateCallbackGUI::Open_CheckBreak() { - return ProgressDialog->Sync.ProcessStopAndPause(); + return ProgressDialog->Sync.CheckStop(); } HRESULT CUpdateCallbackGUI::Open_SetTotal(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */) @@ -189,7 +190,7 @@ HRESULT CUpdateCallbackGUI::Open_SetTotal(const UInt64 * /* numFiles */, const U HRESULT CUpdateCallbackGUI::Open_SetCompleted(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */) { - return ProgressDialog->Sync.ProcessStopAndPause(); + return ProgressDialog->Sync.CheckStop(); } #ifndef _NO_CRYPTO @@ -200,10 +201,10 @@ HRESULT CUpdateCallbackGUI::Open_CryptoGetTextPassword(BSTR *password) return CryptoGetTextPassword2(NULL, password); } -HRESULT CUpdateCallbackGUI::Open_GetPasswordIfAny(UString &password) +HRESULT CUpdateCallbackGUI::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) { - if (PasswordIsDefined) - password = Password; + passwordIsDefined = PasswordIsDefined; + password = Password; return S_OK; } diff --git a/CPP/7zip/UI/GUI/UpdateCallbackGUI.h b/CPP/7zip/UI/GUI/UpdateCallbackGUI.h old mode 100755 new mode 100644 index b5ca154a..21b6f432 --- a/CPP/7zip/UI/GUI/UpdateCallbackGUI.h +++ b/CPP/7zip/UI/GUI/UpdateCallbackGUI.h @@ -33,9 +33,6 @@ public: 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 old mode 100755 new mode 100644 index 406d5bf1..a7af4e94 --- a/CPP/7zip/UI/GUI/UpdateGUI.cpp +++ b/CPP/7zip/UI/GUI/UpdateGUI.cpp @@ -2,16 +2,14 @@ #include "StdAfx.h" -#include "UpdateGUI.h" - -#include "Common/IntToString.h" -#include "Common/StringConvert.h" -#include "Common/StringToInt.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/StringToInt.h" -#include "Windows/Error.h" -#include "Windows/FileDir.h" -#include "Windows/FileName.h" -#include "Windows/Thread.h" +// #include "../../../Windows/Error.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/Thread.h" #include "../Common/WorkDir.h" @@ -28,6 +26,7 @@ using namespace NWindows; using namespace NFile; +using namespace NDir; static CFSTR kDefaultSfxModule = FTEXT("7z.sfx"); static const wchar_t *kSFXExtension = L"exe"; @@ -41,17 +40,21 @@ class CThreadUpdating: public CProgressThreadVirt HRESULT ProcessVirt(); public: CCodecs *codecs; + const CObjectVector *formatIndices; + const UString *cmdArcPath; CUpdateCallbackGUI *UpdateCallbackGUI; - const NWildcard::CCensor *WildcardCensor; + NWildcard::CCensor *WildcardCensor; CUpdateOptions *Options; + bool needSetPath; }; HRESULT CThreadUpdating::ProcessVirt() { CUpdateErrorInfo ei; - HRESULT res = UpdateArchive(codecs, *WildcardCensor, *Options, - ei, UpdateCallbackGUI, UpdateCallbackGUI); - ErrorMessage = ei.Message; + HRESULT res = UpdateArchive(codecs, *formatIndices, *cmdArcPath, + *WildcardCensor, *Options, + ei, UpdateCallbackGUI, UpdateCallbackGUI, needSetPath); + FinalMessage.ErrorMessage.Message = ei.Message; SetErrorPath1(ei.FileName); SetErrorPath2(ei.FileName2); if (ei.SystemError != S_OK && ei.SystemError != E_FAIL && ei.SystemError != E_ABORT) @@ -83,7 +86,7 @@ static bool IsThereMethodOverride(bool is7z, const UString &propertiesString) { UStringVector strings; SplitString(propertiesString, strings); - for (int i = 0; i < strings.Size(); i++) + FOR_VECTOR (i, strings) { const UString &s = strings[i]; if (is7z) @@ -95,7 +98,7 @@ static bool IsThereMethodOverride(bool is7z, const UString &propertiesString) } else { - if (s.Length() > 0) + if (s.Len() > 0) if (s[0] == L'm' && s[1] == L'=') return true; } @@ -108,7 +111,7 @@ static void ParseAndAddPropertires(CObjectVector &properties, { UStringVector strings; SplitString(propertiesString, strings); - for (int i = 0; i < strings.Size(); i++) + FOR_VECTOR (i, strings) { const UString &s = strings[i]; CProperty property; @@ -117,8 +120,8 @@ static void ParseAndAddPropertires(CObjectVector &properties, property.Name = s; else { - property.Name = s.Left(index); - property.Value = s.Mid(index + 1); + property.Name.SetFrom(s, index); + property.Value = s.Ptr(index + 1); } properties.Add(property); } @@ -190,25 +193,61 @@ static void SetOutProperties( AddProp(properties, L"mt", numThreads); } +struct C_UpdateMode_ToAction_Pair +{ + NCompressDialog::NUpdateMode::EEnum UpdateMode; + const NUpdateArchive::CActionSet *ActionSet; +}; + +static const C_UpdateMode_ToAction_Pair g_UpdateMode_Pairs[] = +{ + { NCompressDialog::NUpdateMode::kAdd, &NUpdateArchive::k_ActionSet_Add }, + { NCompressDialog::NUpdateMode::kUpdate, &NUpdateArchive::k_ActionSet_Update }, + { NCompressDialog::NUpdateMode::kFresh, &NUpdateArchive::k_ActionSet_Fresh }, + { NCompressDialog::NUpdateMode::kSync, &NUpdateArchive::k_ActionSet_Sync } +}; + +static int FindActionSet(const NUpdateArchive::CActionSet &actionSet) +{ + for (unsigned i = 0; i < ARRAY_SIZE(g_UpdateMode_Pairs); i++) + if (actionSet.IsEqualTo(*g_UpdateMode_Pairs[i].ActionSet)) + return i; + return -1; +} + +static int FindUpdateMode(NCompressDialog::NUpdateMode::EEnum mode) +{ + for (unsigned i = 0; i < ARRAY_SIZE(g_UpdateMode_Pairs); i++) + if (mode == g_UpdateMode_Pairs[i].UpdateMode) + return i; + return -1; +} + + static HRESULT ShowDialog( CCodecs *codecs, - const NWildcard::CCensor &censor, - CUpdateOptions &options, CUpdateCallbackGUI *callback, HWND hwndParent) + const CObjectVector &censor, + CUpdateOptions &options, + CUpdateCallbackGUI *callback, HWND hwndParent) { if (options.Commands.Size() != 1) throw "It must be one command"; + /* FString currentDirPrefix; #ifndef UNDER_CE { - if (!NDirectory::MyGetCurrentDirectory(currentDirPrefix)) + if (!MyGetCurrentDirectory(currentDirPrefix)) return E_FAIL; NName::NormalizeDirPathPrefix(currentDirPrefix); } #endif + */ bool oneFile = false; NFind::CFileInfo fileInfo; UString name; + + /* if (censor.Pairs.Size() > 0) { const NWildcard::CPair &pair = censor.Pairs[0]; @@ -218,7 +257,7 @@ static HRESULT ShowDialog( if (item.ForFile) { name = pair.Prefix; - for (int i = 0; i < item.PathParts.Size(); i++) + FOR_VECTOR (i, item.PathParts) { if (i > 0) name += WCHAR_PATH_SEPARATOR; @@ -232,41 +271,96 @@ static HRESULT ShowDialog( } } } - + */ + if (censor.Size() > 0) + { + const NWildcard::CCensorPath &cp = censor[0]; + if (cp.Include) + { + { + if (fileInfo.Find(us2fs(cp.Path))) + { + if (censor.Size() == 1) + oneFile = !fileInfo.IsDir(); + } + } + } + } + + + #if defined(_WIN32) && !defined(UNDER_CE) + CCurrentDirRestorer curDirRestorer; + #endif CCompressDialog dialog; NCompressDialog::CInfo &di = dialog.Info; dialog.ArcFormats = &codecs->Formats; - for (int i = 0; i < codecs->Formats.Size(); i++) + + if (options.MethodMode.Type_Defined) + di.FormatIndex = options.MethodMode.Type.FormatIndex; + + FOR_VECTOR (i, codecs->Formats) { 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 (!ai.UpdateEnabled) + continue; + if (!oneFile && ai.Flags_KeepName()) + continue; + if ((int)i != di.FormatIndex) + if (ai.Name.IsEqualToNoCase(L"swfc")) + if (!oneFile || name.Len() < 4 || !StringsAreEqualNoCase(name.RightPtr(4), L".swf")) + continue; + dialog.ArcIndices.Add(i); } - if (dialog.ArcIndices.Size() == 0) + if (dialog.ArcIndices.IsEmpty()) { ShowErrorMessage(L"No Update Engines"); return E_FAIL; } // di.ArchiveName = options.ArchivePath.GetFinalPath(); - di.ArchiveName = options.ArchivePath.GetPathWithoutExt(); - dialog.OriginalFileName = options.ArchivePath.Prefix + fs2us(fileInfo.Name); + di.ArcPath = options.ArchivePath.GetPathWithoutExt(); + dialog.OriginalFileName = fs2us(fileInfo.Name); + + di.PathMode = options.PathMode; - di.CurrentDirPrefix = currentDirPrefix; + // di.CurrentDirPrefix = currentDirPrefix; di.SFXMode = options.SfxMode; di.OpenShareForWrite = options.OpenShareForWrite; + di.DeleteAfterCompressing = options.DeleteAfterCompressing; + + di.SymLinks = options.SymLinks; + di.HardLinks = options.HardLinks; + di.AltStreams = options.AltStreams; + di.NtSecurity = options.NtSecurity; if (callback->PasswordIsDefined) di.Password = callback->Password; di.KeepName = !oneFile; - + + NUpdateArchive::CActionSet &actionSet = options.Commands.Front().ActionSet; + + { + int index = FindActionSet(actionSet); + if (index < 0) + return E_NOTIMPL; + di.UpdateMode = g_UpdateMode_Pairs[index].UpdateMode; + } + if (dialog.Create(hwndParent) != IDOK) return E_ABORT; - + + options.DeleteAfterCompressing = di.DeleteAfterCompressing; + + options.SymLinks = di.SymLinks; + options.HardLinks = di.HardLinks; + options.AltStreams = di.AltStreams; + options.NtSecurity = di.NtSecurity; + + #if defined(_WIN32) && !defined(UNDER_CE) + curDirRestorer.NeedRestore = dialog.CurrentDirWasChanged; + #endif + options.VolumesSizes = di.VolumeSizes; /* if (di.VolumeSizeIsDefined) @@ -275,26 +369,17 @@ static HRESULT ShowDialog( 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; + int index = FindUpdateMode(di.UpdateMode); + if (index < 0) + return E_FAIL; + actionSet = *g_UpdateMode_Pairs[index].ActionSet; } + + options.PathMode = di.PathMode; + const CArcInfoEx &archiverInfo = codecs->Formats[di.FormatIndex]; callback->PasswordIsDefined = (!di.Password.IsEmpty()); if (callback->PasswordIsDefined) @@ -302,7 +387,7 @@ static HRESULT ShowDialog( options.MethodMode.Properties.Clear(); - bool is7z = archiverInfo.Name.CompareNoCase(L"7z") == 0; + bool is7z = archiverInfo.Name.IsEqualToNoCase(L"7z"); bool methodOverride = IsThereMethodOverride(is7z, di.Options); SetOutProperties( @@ -324,14 +409,16 @@ static HRESULT ShowDialog( if (di.SFXMode) options.SfxMode = true; - options.MethodMode.FormatIndex = di.FormatIndex; + options.MethodMode.Type = COpenType(); + options.MethodMode.Type_Defined = true; + options.MethodMode.Type.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); + options.ArchivePath.ParseFromPath(di.ArcPath, k_ArcNameMode_Smart); NWorkDir::CInfo workDirInfo; workDirInfo.Load(); @@ -339,17 +426,19 @@ static HRESULT ShowDialog( if (workDirInfo.Mode != NWorkDir::NMode::kCurrent) { FString fullPath; - NDirectory::MyGetFullPathName(us2fs(di.ArchiveName), fullPath); + MyGetFullPathName(us2fs(di.ArcPath), fullPath); FString namePart; options.WorkingDir = GetWorkDir(workDirInfo, fullPath, namePart); - NDirectory::CreateComplexDirectory(options.WorkingDir); + CreateComplexDir(options.WorkingDir); } return S_OK; } HRESULT UpdateGUI( CCodecs *codecs, - const NWildcard::CCensor &censor, + const CObjectVector &formatIndices, + const UString &cmdArcPath, + NWildcard::CCensor &censor, CUpdateOptions &options, bool showDialog, bool &messageWasDisplayed, @@ -357,9 +446,11 @@ HRESULT UpdateGUI( HWND hwndParent) { messageWasDisplayed = false; + bool needSetPath = true; if (showDialog) { - RINOK(ShowDialog(codecs, censor, options, callback, hwndParent)); + RINOK(ShowDialog(codecs, censor.CensorPaths, options, callback, hwndParent)); + needSetPath = false; } if (options.SfxMode && options.SfxModule.IsEmpty()) { @@ -369,20 +460,24 @@ HRESULT UpdateGUI( CThreadUpdating tu; + tu.needSetPath = needSetPath; + tu.codecs = codecs; + tu.formatIndices = &formatIndices; + tu.cmdArcPath = &cmdArcPath; tu.UpdateCallbackGUI = callback; tu.UpdateCallbackGUI->ProgressDialog = &tu.ProgressDialog; tu.UpdateCallbackGUI->Init(); - UString title = LangString(IDS_PROGRESS_COMPRESSING, 0x02000DC0); + UString title = LangString(IDS_PROGRESS_COMPRESSING); /* if (hwndParent != 0) { tu.ProgressDialog.MainWindow = hwndParent; // tu.ProgressDialog.MainTitle = fileName; - tu.ProgressDialog.MainAddTitle = title + L" "; + tu.ProgressDialog.MainAddTitle = title + L' '; } */ diff --git a/CPP/7zip/UI/GUI/UpdateGUI.h b/CPP/7zip/UI/GUI/UpdateGUI.h old mode 100755 new mode 100644 index c06ec1e7..d1880de0 --- a/CPP/7zip/UI/GUI/UpdateGUI.h +++ b/CPP/7zip/UI/GUI/UpdateGUI.h @@ -21,7 +21,9 @@ HRESULT UpdateGUI( CCodecs *codecs, - const NWildcard::CCensor &censor, + const CObjectVector &formatIndices, + const UString &cmdArcPath2, + NWildcard::CCensor &censor, CUpdateOptions &options, bool showDialog, bool &messageWasDisplayed, diff --git a/CPP/7zip/UI/GUI/makefile b/CPP/7zip/UI/GUI/makefile old mode 100755 new mode 100644 index cd2c2f55..60cfcd4b --- a/CPP/7zip/UI/GUI/makefile +++ b/CPP/7zip/UI/GUI/makefile @@ -1,5 +1,5 @@ PROG = 7zG.exe -CFLAGS = $(CFLAGS) -I ../../../ \ +CFLAGS = $(CFLAGS) \ -DLANG \ -DEXTERNAL_CODECS \ @@ -16,6 +16,7 @@ GUI_OBJS = \ $O\ExtractDialog.obj \ $O\ExtractGUI.obj \ $O\GUI.obj \ + $O\HashGUI.obj \ $O\UpdateCallbackGUI.obj \ $O\UpdateGUI.obj \ @@ -30,27 +31,28 @@ COMMON_OBJS = \ $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\ErrorMsg.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ + $O\FileLink.obj \ $O\FileName.obj \ + $O\FileSystem.obj \ $O\MemoryLock.obj \ $O\PropVariant.obj \ - $O\PropVariantConversions.obj \ + $O\PropVariantConv.obj \ $O\Registry.obj \ $O\ResourceString.obj \ $O\Shell.obj \ $O\Synchronization.obj \ $O\System.obj \ - $O\Time.obj \ + $O\TimeUtils.obj \ $O\Window.obj \ WIN_CTRL_OBJS = \ @@ -63,9 +65,13 @@ WIN_CTRL_OBJS = \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ $O\FilterCoder.obj \ + $O\LimitedStreams.obj \ $O\MethodProps.obj \ $O\ProgressUtils.obj \ + $O\PropId.obj \ + $O\StreamObjects.obj \ $O\StreamUtils.obj \ + $O\UniqBlocks.obj \ UI_COMMON_OBJS = \ $O\ArchiveCommandLine.obj \ @@ -76,6 +82,7 @@ UI_COMMON_OBJS = \ $O\EnumDirItems.obj \ $O\Extract.obj \ $O\ExtractingFilePath.obj \ + $O\HashCalc.obj \ $O\LoadCodecs.obj \ $O\OpenArchive.obj \ $O\PropIDUtils.obj \ @@ -107,60 +114,24 @@ FM_OBJS = \ $O\PasswordDialog.obj \ $O\ProgressDialog2.obj \ -!IFDEF UNDER_CE FM_OBJS = $(FM_OBJS) \ $O\BrowseDialog.obj \ + $O\ComboDialog.obj \ $O\SysIconUtils.obj \ -!ENDIF + +EXPLORER_OBJS = \ + $O\MyMessages.obj \ + +COMPRESS_OBJS = \ + $O\CopyCoder.obj \ C_OBJS = \ $O\Alloc.obj \ $O\CpuArch.obj \ + $O\Sort.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" + +!include "../../7zip.mak" diff --git a/CPP/7zip/UI/GUI/resource.rc b/CPP/7zip/UI/GUI/resource.rc old mode 100755 new mode 100644 index bfc2029b..0f7c6235 --- a/CPP/7zip/UI/GUI/resource.rc +++ b/CPP/7zip/UI/GUI/resource.rc @@ -1,10 +1,10 @@ #include "../../MyVersionInfo.rc" -#include +// #include #include "resource2.rc" #include "../FileManager/resourceGui.rc" -MY_VERSION_INFO_APP("7-Zip GUI", "7zg") +MY_VERSION_INFO(MY_VFT_APP, "7-Zip GUI", "7zg", "7zg.exe") IDI_ICON ICON "FM.ico" @@ -12,10 +12,10 @@ IDI_ICON ICON "FM.ico" 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" +#include "../FileManager/BrowseDialog.rc" +#include "../FileManager/ComboDialog.rc" diff --git a/CPP/7zip/UI/GUI/resource2.h b/CPP/7zip/UI/GUI/resource2.h old mode 100755 new mode 100644 index 4f8b1573..cd882924 --- a/CPP/7zip/UI/GUI/resource2.h +++ b/CPP/7zip/UI/GUI/resource2.h @@ -1,3 +1,2 @@ -#define IDS_COMPRESSED_COLON 2277 -#define IDS_ARCHIVES_COLON 2278 -#define IDS_PROGRESS_COMPRESSING 98 +#define IDS_PROGRESS_COMPRESSING 3301 +#define IDS_ARCHIVES_COLON 3907 diff --git a/CPP/7zip/UI/GUI/resource2.rc b/CPP/7zip/UI/GUI/resource2.rc old mode 100755 new mode 100644 index 542717ee..49534f50 --- a/CPP/7zip/UI/GUI/resource2.rc +++ b/CPP/7zip/UI/GUI/resource2.rc @@ -5,7 +5,6 @@ STRINGTABLE BEGIN - IDS_COMPRESSED_COLON "Compressed size:" - IDS_ARCHIVES_COLON "Archives:" - IDS_PROGRESS_COMPRESSING "Compressing" + IDS_PROGRESS_COMPRESSING "Compressing" + IDS_ARCHIVES_COLON "Archives:" END diff --git a/CPP/7zip/UI/makefile b/CPP/7zip/UI/makefile old mode 100755 new mode 100644 diff --git a/CPP/7zip/makefile b/CPP/7zip/makefile old mode 100755 new mode 100644 diff --git a/CPP/Build.mak b/CPP/Build.mak old mode 100755 new mode 100644 index b3465d44..df600eb8 --- a/CPP/Build.mak +++ b/CPP/Build.mak @@ -1,11 +1,10 @@ LIBS = $(LIBS) oleaut32.lib ole32.lib -!IFDEF CPU -!IFNDEF NO_BUFFEROVERFLOWU -LIBS = $(LIBS) bufferoverflowU.lib -!ENDIF +!IFNDEF MY_NO_UNICODE +CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE !ENDIF +# CFLAGS = $(CFLAGS) -FAsc -Fa$O/Asm/ !IFNDEF O !IFDEF CPU @@ -43,7 +42,7 @@ COMPL_ASM = $(MY_ML) $** $O/$(*B).obj COMPL_ASM = $(MY_ML) -c -Fo$O/ $** !ENDIF -CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -WX -EHsc -Gy -GR- +CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -W4 -WX -EHsc -Gy -GR- !IFDEF MY_STATIC_LINK !IFNDEF MY_SINGLE_THREAD @@ -54,9 +53,12 @@ CFLAGS = $(CFLAGS) -MD !ENDIF !IFDEF NEW_COMPILER -CFLAGS = $(CFLAGS) -W4 -GS- -Zc:forScope +CFLAGS = $(CFLAGS) -GS- -Zc:forScope +!IFNDEF UNDER_CE +CFLAGS = $(CFLAGS) -MP2 +!ENDIF !ELSE -CFLAGS = $(CFLAGS) -W3 +CFLAGS = $(CFLAGS) !ENDIF CFLAGS_O1 = $(CFLAGS) -O1 @@ -72,6 +74,13 @@ LFLAGS = $(LFLAGS) /LARGEADDRESSAWARE LFLAGS = $(LFLAGS) -DLL -DEF:$(DEF_FILE) !ENDIF +MY_SUB_SYS_VER=6.0 +!IFDEF MY_CONSOLE +# LFLAGS = $(LFLAGS) /SUBSYSTEM:console,$(MY_SUB_SYS_VER) +!ELSE +# LFLAGS = $(LFLAGS) /SUBSYSTEM:windows,$(MY_SUB_SYS_VER) +!ENDIF + PROGPATH = $O\$(PROG) COMPL_O1 = $(CC) $(CFLAGS_O1) $** @@ -79,15 +88,27 @@ COMPL_O2 = $(CC) $(CFLAGS_O2) $** COMPL_PCH = $(CC) $(CFLAGS_O1) -Yc"StdAfx.h" -Fp$O/a.pch $** COMPL = $(CC) $(CFLAGS_O1) -Yu"StdAfx.h" -Fp$O/a.pch $** +COMPLB = $(CC) $(CFLAGS_O1) -Yu"StdAfx.h" -Fp$O/a.pch $< +# COMPLB_O2 = $(CC) $(CFLAGS_O2) -Yu"StdAfx.h" -Fp$O/a.pch $< +COMPLB_O2 = $(CC) $(CFLAGS_O2) $< + +CCOMPL_PCH = $(CC) $(CFLAGS_O2) -Yc"Precomp.h" -Fp$O/a.pch $** +CCOMPL_USE = $(CC) $(CFLAGS_O2) -Yu"Precomp.h" -Fp$O/a.pch $** +CCOMPL = $(CC) $(CFLAGS_O2) $** +CCOMPLB = $(CC) $(CFLAGS_O2) $< + + all: $(PROGPATH) clean: - -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch + -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O\*.asm $O: if not exist "$O" mkdir "$O" +$O/Asm: + if not exist "$O/Asm" mkdir "$O/Asm" -$(PROGPATH): $O $(OBJS) $(DEF_FILE) +$(PROGPATH): $O $O/Asm $(OBJS) $(DEF_FILE) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) !IFNDEF NO_DEFAULT_RES diff --git a/CPP/Common/AutoPtr.h b/CPP/Common/AutoPtr.h old mode 100755 new mode 100644 diff --git a/CPP/Common/Buffer.h b/CPP/Common/Buffer.h deleted file mode 100755 index 118fe11f..00000000 --- a/CPP/Common/Buffer.h +++ /dev/null @@ -1,77 +0,0 @@ -// 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 old mode 100755 new mode 100644 diff --git a/CPP/Common/C_FileIO.cpp b/CPP/Common/C_FileIO.cpp old mode 100755 new mode 100644 diff --git a/CPP/Common/C_FileIO.h b/CPP/Common/C_FileIO.h old mode 100755 new mode 100644 index ff7a1a11..cb043311 --- a/CPP/Common/C_FileIO.h +++ b/CPP/Common/C_FileIO.h @@ -6,7 +6,7 @@ #include #include -#include "Types.h" +#include "MyTypes.h" #include "MyWindows.h" #ifdef _WIN32 diff --git a/CPP/Common/ComTry.h b/CPP/Common/ComTry.h old mode 100755 new mode 100644 diff --git a/CPP/Common/CommandLineParser.cpp b/CPP/Common/CommandLineParser.cpp old mode 100755 new mode 100644 index 80b467fc..1bf41736 --- a/CPP/Common/CommandLineParser.cpp +++ b/CPP/Common/CommandLineParser.cpp @@ -4,6 +4,20 @@ #include "CommandLineParser.h" +static bool IsString1PrefixedByString2_NoCase(const wchar_t *u, const char *a) +{ + for (;;) + { + char c = *a; + if (c == 0) + return true; + if (MyCharLower_Ascii(c) != MyCharLower_Ascii(*u)) + return false; + a++; + u++; + } +} + namespace NCommandLineParser { bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2) @@ -11,13 +25,13 @@ 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++) + unsigned i; + for (i = 0; i < src.Len(); i++) { wchar_t c = src[i]; - if (c == L' ' && !quoteMode) + if ((c == L' ' || c == L'\t') && !quoteMode) { - dest2 = src.Mid(i + 1); + dest2 = src.Ptr(i + 1); return i != 0; } if (c == L'\"') @@ -45,21 +59,18 @@ void SplitCommandLine(const UString &s, UStringVector &parts) } -static const wchar_t kSwitchID1 = '-'; -// static const wchar_t kSwitchID2 = '/'; +static const char *kStopSwitchParsing = "--"; -static const wchar_t kSwitchMinus = '-'; -static const wchar_t *kStopSwitchParsing = L"--"; - -static bool IsItSwitchChar(wchar_t c) +static bool inline IsItSwitchChar(wchar_t c) { - return (c == kSwitchID1 /*|| c == kSwitchID2 */); + return (c == '-'); } -CParser::CParser(int numSwitches): - _numSwitches(numSwitches) +CParser::CParser(unsigned numSwitches): + _numSwitches(numSwitches), + _switches(0) { - _switches = new CSwitchResult[_numSwitches]; + _switches = new CSwitchResult[numSwitches]; } CParser::~CParser() @@ -67,163 +78,121 @@ 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) +// if (s) contains switch then function updates switch structures +// out: true, if (s) is a switch bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) { - int len = s.Length(); - if (len == 0) + if (s.IsEmpty() || !IsItSwitchChar(s[0])) return false; - int pos = 0; - if (!IsItSwitchChar(s[pos])) - return false; - while (pos < len) + + unsigned pos = 1; + unsigned switchIndex = 0; + int maxLen = -1; + + for (unsigned i = 0; i < _numSwitches; i++) { - if (IsItSwitchChar(s[pos])) - pos++; - const int kNoLen = -1; - int matchedSwitchIndex = 0; // GCC Warning - int maxLen = kNoLen; - for (int switchIndex = 0; switchIndex < _numSwitches; switchIndex++) + const char *key = switchForms[i].Key; + unsigned switchLen = MyStringLen(key); + if ((int)switchLen <= maxLen || pos + switchLen > s.Len()) + continue; + if (IsString1PrefixedByString2_NoCase((const wchar_t *)s + pos, key)) { - int switchLen = MyStringLen(switchForms[switchIndex].IDString); - if (switchLen <= maxLen || pos + switchLen > len) - continue; + switchIndex = i; + maxLen = switchLen; + } + } - 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) + if (maxLen < 0) + { + ErrorMessage = "Unknown switch:"; + return false; + } + + pos += maxLen; + + CSwitchResult &sw = _switches[switchIndex]; + const CSwitchForm &form = switchForms[switchIndex]; + + if (!form.Multi && sw.ThereIs) + { + ErrorMessage = "Multiple instances for switch:"; + return false; + } + + sw.ThereIs = true; + + int rem = s.Len() - pos; + if (rem < form.MinLen) + { + ErrorMessage = "Too short switch:"; + return false; + } + + sw.WithMinus = false; + sw.PostCharIndex = -1; + + switch (form.Type) + { + case NSwitchType::kMinus: + if (rem != 0) { - matchedSwitchIndex = switchIndex; - maxLen = switchLen; + sw.WithMinus = (s[pos] == '-'); + if (sw.WithMinus) + pos++; } - } - 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: + break; + + case NSwitchType::kChar: + if (rem != 0) + { + wchar_t c = s[pos]; + if (c <= 0x7F) { - 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; + sw.PostCharIndex = FindCharPosInString(form.PostCharSet, (char)c); + if (sw.PostCharIndex >= 0) + pos++; } - case NSwitchType::kSimple: - break; - } + } + break; + + case NSwitchType::kString: + sw.PostStrings.Add((const wchar_t *)s + pos); + return true; + } + if (pos != s.Len()) + { + ErrorMessage = "Too long switch:"; + return false; } 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) +bool CParser::ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings) { - for (int i = 0; i < numCommandForms; i++) + ErrorLine.Empty(); + bool stopSwitch = false; + FOR_VECTOR (i, commandStrings) { - const UString id = commandForms[i].IDString; - if (commandForms[i].PostStringMode) + const UString &s = commandStrings[i]; + if (!stopSwitch) { - if (commandString.Find(id) == 0) + if (s.IsEqualTo(kStopSwitchParsing)) { - postString = commandString.Mid(id.Length()); - return i; + stopSwitch = true; + continue; } - } - else - if (commandString == id) + if (!s.IsEmpty() && IsItSwitchChar(s[0])) { - postString.Empty(); - return i; + if (ParseString(s, switchForms)) + continue; + ErrorLine = s; + return false; } + } + NonSwitchStrings.Add(s); } - return -1; + return true; } - + } diff --git a/CPP/Common/CommandLineParser.h b/CPP/Common/CommandLineParser.h old mode 100755 new mode 100644 index 3d0b41dd..c9fd2956 --- a/CPP/Common/CommandLineParser.h +++ b/CPP/Common/CommandLineParser.h @@ -10,63 +10,54 @@ namespace NCommandLineParser { bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2); void SplitCommandLine(const UString &s, UStringVector &parts); -namespace NSwitchType { +namespace NSwitchType +{ enum EEnum { kSimple, - kPostMinus, - kLimitedPostString, - kUnLimitedPostString, - kPostChar + kMinus, + kString, + kChar }; } struct CSwitchForm { - const wchar_t *IDString; - NSwitchType::EEnum Type; + const char *Key; + Byte Type; bool Multi; - int MinLen; - int MaxLen; - const wchar_t *PostCharSet; + Byte MinLen; + // int MaxLen; + const char *PostCharSet; }; struct CSwitchResult { bool ThereIs; bool WithMinus; - UStringVector PostStrings; int PostCharIndex; + UStringVector PostStrings; + CSwitchResult(): ThereIs(false) {}; }; class CParser { - int _numSwitches; + unsigned _numSwitches; CSwitchResult *_switches; + bool ParseString(const UString &s, const CSwitchForm *switchForms); public: UStringVector NonSwitchStrings; - CParser(int numSwitches); + AString ErrorMessage; + UString ErrorLine; + + CParser(unsigned numSwitches); ~CParser(); - void ParseStrings(const CSwitchForm *switchForms, - const UStringVector &commandStrings); - const CSwitchResult& operator[](size_t index) const; + bool ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings); + const CSwitchResult& operator[](size_t index) const { return _switches[index]; } }; -///////////////////////////////// -// 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/Common.h b/CPP/Common/Common.h new file mode 100644 index 00000000..9dd30f4b --- /dev/null +++ b/CPP/Common/Common.h @@ -0,0 +1,13 @@ +// Common.h + +#ifndef __COMMON_COMMON_H +#define __COMMON_COMMON_H + +#include "../../C/Compiler.h" + +#include "MyWindows.h" +#include "NewHandler.h" + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[1])) + +#endif diff --git a/CPP/Common/CrcReg.cpp b/CPP/Common/CrcReg.cpp new file mode 100644 index 00000000..6f4de495 --- /dev/null +++ b/CPP/Common/CrcReg.cpp @@ -0,0 +1,111 @@ +// CrcReg.cpp + +#include "StdAfx.h" + +#include "../../C/7zCrc.h" +#include "../../C/CpuArch.h" + +#include "../Common/MyCom.h" + +#include "../7zip/ICoder.h" +#include "../7zip/Common/RegisterCodec.h" + +EXTERN_C_BEGIN + +typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table); + +extern CRC_FUNC g_CrcUpdate; + +#ifdef MY_CPU_X86_OR_AMD64 + UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); +#endif + +#ifndef MY_CPU_BE + UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); +#endif + +EXTERN_C_END + +class CCrcHasher: + public IHasher, + public ICompressSetCoderProperties, + public CMyUnknownImp +{ + UInt32 _crc; + CRC_FUNC _updateFunc; + bool SetFunctions(UInt32 tSize); +public: + CCrcHasher(): _crc(CRC_INIT_VAL) { SetFunctions(0); } + + MY_UNKNOWN_IMP1(ICompressSetCoderProperties) + + STDMETHOD_(void, Init)(); + STDMETHOD_(void, Update)(const void *data, UInt32 size); + STDMETHOD_(void, Final)(Byte *digest); + STDMETHOD_(UInt32, GetDigestSize)(); + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); +}; + +STDMETHODIMP_(void) CCrcHasher::Init() +{ + _crc = CRC_INIT_VAL; +} + +STDMETHODIMP_(void) CCrcHasher::Update(const void *data, UInt32 size) +{ + _crc = _updateFunc(_crc, data, size, g_CrcTable); +} + +STDMETHODIMP_(void) CCrcHasher::Final(Byte *digest) +{ + UInt32 val = CRC_GET_DIGEST(_crc); + SetUi32(digest, val); +} + +STDMETHODIMP_(UInt32) CCrcHasher::GetDigestSize() +{ + return 4; +} + +bool CCrcHasher::SetFunctions(UInt32 tSize) +{ + _updateFunc = g_CrcUpdate; + if (tSize == 4) + { + #ifndef MY_CPU_BE + _updateFunc = CrcUpdateT4; + #endif + } + else if (tSize == 8) + { + #ifdef MY_CPU_X86_OR_AMD64 + _updateFunc = CrcUpdateT8; + #else + return false; + #endif + } + return true; +} + +STDMETHODIMP CCrcHasher::SetCoderProperties(const PROPID *propIDs, + const PROPVARIANT *coderProps, UInt32 numProps) +{ + for (UInt32 i = 0; i < numProps; i++) + { + const PROPVARIANT &prop = coderProps[i]; + if (propIDs[i] == NCoderPropID::kDefaultProp) + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + if (!SetFunctions(prop.ulVal)) + return E_NOTIMPL; + } + } + return S_OK; +} + +static IHasher *CreateHasher() { return new CCrcHasher(); } + +static CHasherInfo g_HasherInfo = { CreateHasher, 0x1, L"CRC32", 4 }; + +REGISTER_HASHER(Crc32) diff --git a/CPP/Common/Defs.h b/CPP/Common/Defs.h old mode 100755 new mode 100644 diff --git a/CPP/Common/DynLimBuf.cpp b/CPP/Common/DynLimBuf.cpp new file mode 100644 index 00000000..ad4ab128 --- /dev/null +++ b/CPP/Common/DynLimBuf.cpp @@ -0,0 +1,100 @@ +// Common/DynLimBuf.cpp + +#include "StdAfx.h" + +#ifdef _WIN32 +#include +#include +#else +#include +#endif + +#include "DynLimBuf.h" +#include "MyString.h" + +CDynLimBuf::CDynLimBuf(size_t limit) +{ + _chars = 0; + _pos = 0; + _size = 0; + _sizeLimit = limit; + _error = true; + unsigned size = 1 << 4; + if (size > limit) + size = (unsigned)limit; + _chars = (Byte *)MyAlloc(size); + if (_chars) + { + _size = size; + _error = false; + } +} + +CDynLimBuf & CDynLimBuf::operator+=(char c) +{ + if (_error) + return *this; + if (_size == _pos) + { + size_t n = _sizeLimit - _size; + if (n == 0) + { + _error = true; + return *this; + } + if (n > _size) + n = _size; + + n += _pos; + + Byte *newBuf = (Byte *)MyAlloc(n); + if (!newBuf) + { + _error = true; + return *this; + } + memcpy(newBuf, _chars, _pos); + MyFree(_chars); + _chars = newBuf; + _size = n; + } + _chars[_pos++] = c; + return *this; +} + +CDynLimBuf &CDynLimBuf::operator+=(const char *s) +{ + if (_error) + return *this; + unsigned len = MyStringLen(s); + size_t rem = _sizeLimit - _pos; + if (rem < len) + { + len = (unsigned)rem; + _error = true; + } + if (_size - _pos < len) + { + size_t n = _pos + len; + if (n - _size < _size) + { + size_t n = _sizeLimit; + if (n - _size > _size) + n = _size * 2; + } + + Byte *newBuf = (Byte *)MyAlloc(n); + if (!newBuf) + { + _error = true; + return *this; + } + memcpy(newBuf, _chars, _pos); + MyFree(_chars); + _chars = newBuf; + _size = n; + } + memcpy(_chars + _pos, s, len); + _pos += len; + return *this; +} diff --git a/CPP/Common/DynLimBuf.h b/CPP/Common/DynLimBuf.h new file mode 100644 index 00000000..035fc272 --- /dev/null +++ b/CPP/Common/DynLimBuf.h @@ -0,0 +1,36 @@ +// Common/DynLimBuf.h + +#ifndef __COMMON_DYN_LIM_BUF_H +#define __COMMON_DYN_LIM_BUF_H + +#include + +#include "../../C/Alloc.h" + +#include "MyString.h" + +class CDynLimBuf +{ + Byte *_chars; + size_t _pos; + size_t _size; + size_t _sizeLimit; + bool _error; + + CDynLimBuf(const CDynLimBuf &s); +public: + CDynLimBuf(size_t limit) throw(); + ~CDynLimBuf() { MyFree(_chars); } + + size_t Len() const { return _pos; } + void Empty() { _pos = 0; } + + operator const Byte *() const { return _chars; } + // const char *Ptr() const { return _chars; } + + CDynLimBuf &operator+=(char c) throw(); + CDynLimBuf &operator+=(const char *s) throw(); +}; + + +#endif diff --git a/CPP/Common/DynamicBuffer.h b/CPP/Common/DynamicBuffer.h old mode 100755 new mode 100644 index bf52a742..cd23ad73 --- a/CPP/Common/DynamicBuffer.h +++ b/CPP/Common/DynamicBuffer.h @@ -3,48 +3,56 @@ #ifndef __COMMON_DYNAMIC_BUFFER_H #define __COMMON_DYNAMIC_BUFFER_H -#include "Buffer.h" - -template class CDynamicBuffer: public CBuffer +template class CDynamicBuffer { - void GrowLength(size_t size) + T *_items; + size_t _size; + size_t _pos; + + CDynamicBuffer(const CDynamicBuffer &buffer); + void operator=(const CDynamicBuffer &buffer); + + void Grow(size_t size) { - size_t delta; - 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; + size_t delta = _size >= 64 ? _size : 64; + if (delta < size) + delta = size; + size_t newCap = _size + 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)); + newCap = _size + size; + if (newCap < size) + throw 20120116; } - return *this; + + T *newBuffer = new T[newCap]; + memcpy(newBuffer, _items, _pos * sizeof(T)); + delete []_items; + _items = newBuffer; + _size = newCap; } - void EnsureCapacity(size_t capacity) + +public: + CDynamicBuffer(): _items(0), _size(0), _pos(0) {} + // operator T *() { return _items; }; + operator const T *() const { return _items; }; + ~CDynamicBuffer() { delete []_items; } + + T *GetCurPtrAndGrow(size_t addSize) { - if (this->_capacity < capacity) - GrowLength(capacity - this->_capacity); + size_t rem = _size - _pos; + if (rem < addSize) + Grow(addSize - rem); + T *res = _items + _pos; + _pos += addSize; + return res; } + + const size_t GetPos() const { return _pos; } + + // void Empty() { _pos = 0; } }; -typedef CDynamicBuffer CCharDynamicBuffer; -typedef CDynamicBuffer CWCharDynamicBuffer; typedef CDynamicBuffer CByteDynamicBuffer; #endif diff --git a/CPP/Common/IntToString.cpp b/CPP/Common/IntToString.cpp old mode 100755 new mode 100644 index 013fee52..09156e16 --- a/CPP/Common/IntToString.cpp +++ b/CPP/Common/IntToString.cpp @@ -4,74 +4,143 @@ #include "IntToString.h" -void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base) +#define CONVERT_INT_TO_STR(charType, tempSize) \ + unsigned char temp[tempSize]; unsigned i = 0; \ + while (val >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(val % 10)); val /= 10; } \ + *s++ = (charType)('0' + (unsigned)val); \ + while (i != 0) { i--; *s++ = temp[i]; } \ + *s = 0; + +void ConvertUInt32ToString(UInt32 val, char *s) { - if (base < 2 || base > 36) + CONVERT_INT_TO_STR(char, 16); +} + +void ConvertUInt64ToString(UInt64 val, char *s) +{ + if (val <= (UInt32)0xFFFFFFFF) { - *s = '\0'; + ConvertUInt32ToString((UInt32)val, s); return; } - char temp[72]; - int pos = 0; - do + CONVERT_INT_TO_STR(char, 24); +} + +void ConvertUInt64ToOct(UInt64 val, char *s) +{ + UInt64 v = val; + unsigned i; + for (i = 1;; i++) { - int delta = (int)(value % base); - temp[pos++] = (char)((delta < 10) ? ('0' + delta) : ('a' + (delta - 10))); - value /= base; + v >>= 3; + if (v == 0) + break; } - while (value != 0); + s[i] = 0; do - *s++ = temp[--pos]; - while (pos > 0); - *s = '\0'; + { + unsigned t = (unsigned)(val & 0x7); + val >>= 3; + s[--i] = (char)('0' + t); + } + while (i); } -void ConvertUInt64ToString(UInt64 value, wchar_t *s) +void ConvertUInt32ToHex(UInt32 val, char *s) { - wchar_t temp[32]; - int pos = 0; + UInt32 v = val; + unsigned i; + for (i = 1;; i++) + { + v >>= 4; + if (v == 0) + break; + } + s[i] = 0; do { - temp[pos++] = (wchar_t)(L'0' + (int)(value % 10)); - value /= 10; + unsigned t = (unsigned)((val & 0xF)); + val >>= 4; + s[--i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); } - while (value != 0); + while (i); +} + +void ConvertUInt64ToHex(UInt64 val, char *s) +{ + UInt64 v = val; + unsigned i; + for (i = 1;; i++) + { + v >>= 4; + if (v == 0) + break; + } + s[i] = 0; do - *s++ = temp[--pos]; - while (pos > 0); - *s = L'\0'; + { + unsigned t = (unsigned)((val & 0xF)); + val >>= 4; + s[--i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + } + while (i); } -void ConvertUInt32ToString(UInt32 value, char *s) { ConvertUInt64ToString(value, s); } -void ConvertUInt32ToString(UInt32 value, wchar_t *s) { ConvertUInt64ToString(value, s); } +void ConvertUInt32ToHex8Digits(UInt32 val, char *s) +{ + s[8] = 0; + for (int i = 7; i >= 0; i--) + { + unsigned t = val & 0xF; + val >>= 4; + s[i] = (char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))); + } +} -void ConvertInt64ToString(Int64 value, char *s) +/* +void ConvertUInt32ToHex8Digits(UInt32 val, wchar_t *s) { - if (value < 0) + s[8] = 0; + for (int i = 7; i >= 0; i--) { - *s++ = '-'; - value = -value; + unsigned t = val & 0xF; + val >>= 4; + s[i] = (wchar_t)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))); + } +} +*/ + +void ConvertUInt32ToString(UInt32 val, wchar_t *s) +{ + CONVERT_INT_TO_STR(wchar_t, 16); +} + +void ConvertUInt64ToString(UInt64 val, wchar_t *s) +{ + if (val <= (UInt32)0xFFFFFFFF) + { + ConvertUInt32ToString((UInt32)val, s); + return; } - ConvertUInt64ToString(value, s); + CONVERT_INT_TO_STR(wchar_t, 24); } -void ConvertInt64ToString(Int64 value, wchar_t *s) +void ConvertInt64ToString(Int64 val, char *s) { - if (value < 0) + if (val < 0) { - *s++ = L'-'; - value = -value; + *s++ = '-'; + val = -val; } - ConvertUInt64ToString(value, s); + ConvertUInt64ToString(val, s); } -void ConvertUInt32ToHexWithZeros(UInt32 value, char *s) +void ConvertInt64ToString(Int64 val, wchar_t *s) { - for (int i = 0; i < 8; i++) + if (val < 0) { - int t = value & 0xF; - value >>= 4; - s[7 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + *s++ = L'-'; + val = -val; } - s[8] = '\0'; + ConvertUInt64ToString(val, s); } diff --git a/CPP/Common/IntToString.h b/CPP/Common/IntToString.h old mode 100755 new mode 100644 index 782f930c..69605ab7 --- a/CPP/Common/IntToString.h +++ b/CPP/Common/IntToString.h @@ -3,17 +3,22 @@ #ifndef __COMMON_INT_TO_STRING_H #define __COMMON_INT_TO_STRING_H -#include -#include "Types.h" +#include "MyTypes.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) throw(); +void ConvertUInt64ToString(UInt64 value, char *s) throw(); -void ConvertUInt32ToString(UInt32 value, char *s); -void ConvertUInt32ToString(UInt32 value, wchar_t *s); +void ConvertUInt32ToString(UInt32 value, wchar_t *s) throw(); +void ConvertUInt64ToString(UInt64 value, wchar_t *s) throw(); -void ConvertUInt32ToHexWithZeros(UInt32 value, char *s); +void ConvertUInt64ToOct(UInt64 value, char *s) throw(); + +void ConvertUInt32ToHex(UInt32 value, char *s) throw(); +void ConvertUInt64ToHex(UInt64 value, char *s) throw(); +void ConvertUInt32ToHex8Digits(UInt32 value, char *s) throw(); +// void ConvertUInt32ToHex8Digits(UInt32 value, wchar_t *s) throw(); + +void ConvertInt64ToString(Int64 value, char *s) throw(); +void ConvertInt64ToString(Int64 value, wchar_t *s) throw(); #endif diff --git a/CPP/Common/Lang.cpp b/CPP/Common/Lang.cpp old mode 100755 new mode 100644 index 2339d120..c1638ba0 --- a/CPP/Common/Lang.cpp +++ b/CPP/Common/Lang.cpp @@ -3,54 +3,115 @@ #include "StdAfx.h" #include "Lang.h" -#include "TextConfig.h" +#include "StringToInt.h" +#include "UTFConvert.h" #include "../Windows/FileIO.h" -#include "UTFConvert.h" -#include "Defs.h" -static bool HexStringToNumber(const UString &s, UInt32 &value) +void CLang::Clear() +{ + delete []_text; + _text = 0; + _ids.Clear(); + _offsets.Clear(); +} + +static const wchar_t *kLangSignature = L";!@Lang2@!UTF-8!"; + +bool CLang::OpenFromString(const AString &s2) { - value = 0; + UString s; + if (!ConvertUTF8ToUnicode(s2, s)) + return false; + unsigned i = 0; if (s.IsEmpty()) return false; - for (int i = 0; i < s.Length(); i++) + if (s[0] == 0xFEFF) + i++; + + for (const wchar_t *p = kLangSignature;; 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 + wchar_t c = *p++; + if (c == 0) + break; + if (s[i] != c) return false; - value *= 0x10; - value += a; } - return true; -} + _text = new wchar_t[s.Len() - i + 1]; + wchar_t *text = _text; -static bool WaitNextLine(const AString &s, int &pos) -{ - for (; pos < s.Length(); pos++) - if (s[pos] == 0x0A) - return true; - return false; -} + Int32 id = -100; + UInt32 pos = 0; -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); + while (i < s.Len()) + { + unsigned start = pos; + do + { + wchar_t c = s[i++]; + if (c == '\n') + break; + if (c == '\\') + { + if (i == s.Len()) + return false; + c = s[i++]; + switch (c) + { + case '\n': return false; + case 'n': c = '\n'; break; + case 't': c = '\t'; break; + case '\\': c = '\\'; break; + default: text[pos++] = L'\\'; break; + } + } + text[pos++] = c; + } + while (i < s.Len()); + + { + unsigned j = start; + for (; j < pos; j++) + if (text[j] != ' ') + break; + if (j == pos) + { + id++; + continue; + } + } + if (text[start] == ';') + { + pos = start; + id++; + continue; + } + + text[pos++] = 0; + const wchar_t *end; + UInt32 id32 = ConvertStringToUInt32(text + start, &end); + if (*end == 0) + { + if (id32 > ((UInt32)1 << 30) || (Int32)id32 < id) + return false; + id = (Int32)id32; + pos = start; + continue; + } + + if (id < 0) + return false; + _ids.Add((UInt32)id++); + _offsets.Add(start); + } + + return true; } -bool CLang::Open(CFSTR fileName) +bool CLang::Open(CFSTR fileName, const wchar_t *id) { - _langPairs.Clear(); + Clear(); NWindows::NFile::NIO::CInFile file; if (!file.Open(fileName)) return false; @@ -60,71 +121,38 @@ bool CLang::Open(CFSTR fileName) if (length > (1 << 20)) return false; AString s; - char *p = s.GetBuffer((int)length + 1); + unsigned len = (unsigned)length; + char *p = s.GetBuffer(len); UInt32 processed; - if (!file.Read(p, (UInt32)length, processed)) + if (!file.Read(p, len, 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)) + if (len != processed) return false; - - CObjectVector pairs; - if (!GetTextConfig(s.Mid(pos), pairs)) - return false; - - _langPairs.Reserve(pairs.Size()); - for (int i = 0; i < pairs.Size(); i++) + char *p2 = p; + for (unsigned i = 0; i < len; i++) { - CTextConfigPair textConfigPair = pairs[i]; - CLangPair langPair; - if (!HexStringToNumber(textConfigPair.ID, langPair.Value)) - return false; - langPair.String = textConfigPair.String; - _langPairs.Add(langPair); + char c = p[i]; + if (c == 0) + break; + if (c != 0x0D) + *p2++ = c; } - _langPairs.Sort(CompareLangItems, NULL); - return true; -} - -int CLang::FindItem(UInt32 value) const -{ - int left = 0, right = _langPairs.Size(); - while (left != right) + s.ReleaseBuffer((unsigned)(p2 - p)); + if (OpenFromString(s)) { - UInt32 mid = (left + right) / 2; - UInt32 midValue = _langPairs[mid].Value; - if (value == midValue) - return mid; - if (value < midValue) - right = mid; - else - left = mid + 1; + const wchar_t *s = Get(0); + if (s && wcscmp(s, id) == 0) + return true; } - return -1; + Clear(); + return false; } -bool CLang::GetMessage(UInt32 value, UString &message) const +const wchar_t *CLang::Get(UInt32 id) const { - int index = FindItem(value); + int index = _ids.FindInSorted(id); if (index < 0) - return false; - message = _langPairs[index].String; - return true; + return NULL; + return _text + (size_t)_offsets[index]; } diff --git a/CPP/Common/Lang.h b/CPP/Common/Lang.h old mode 100755 new mode 100644 index 2ce53a0d..2ca2a850 --- a/CPP/Common/Lang.h +++ b/CPP/Common/Lang.h @@ -4,24 +4,20 @@ #define __COMMON_LANG_H #include "MyString.h" -#include "Types.h" - -struct CLangPair -{ - UInt32 Value; - UString String; -}; class CLang { - CObjectVector _langPairs; + wchar_t *_text; + CRecordVector _ids; + CRecordVector _offsets; + + bool OpenFromString(const AString &s); public: - bool Open(CFSTR fileName); - void Clear() { _langPairs.Clear(); } - int FindItem(UInt32 value) const; - bool GetMessage(UInt32 value, UString &message) const; + CLang(): _text(0) {} + ~CLang() { Clear(); }; + bool Open(CFSTR fileName, const wchar_t *id); + void Clear() throw(); + const wchar_t *Get(UInt32 id) const throw(); }; #endif - - diff --git a/CPP/Common/ListFileUtils.cpp b/CPP/Common/ListFileUtils.cpp old mode 100755 new mode 100644 index f9bd18ed..313532ef --- a/CPP/Common/ListFileUtils.cpp +++ b/CPP/Common/ListFileUtils.cpp @@ -2,75 +2,116 @@ #include "StdAfx.h" -#include "MyWindows.h" +#include "../../C/CpuArch.h" + #include "../Windows/FileIO.h" #include "ListFileUtils.h" +#include "MyBuffer.h" #include "StringConvert.h" #include "UTFConvert.h" static const char kQuoteChar = '\"'; -static void RemoveQuote(UString &s) +static void AddName(UStringVector &strings, UString &s) { - if (s.Length() >= 2) - if (s[0] == kQuoteChar && s.Back() == kQuoteChar) - s = s.Mid(1, s.Length() - 2); + s.Trim(); + if (s.Len() >= 2 && s[0] == kQuoteChar && s.Back() == kQuoteChar) + { + s.DeleteBack(); + s.Delete(0); + } + if (!s.IsEmpty()) + strings.Add(s); } -bool ReadNamesFromListFile(CFSTR fileName, UStringVector &resultStrings, UINT codePage) +bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, 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)) + UInt64 fileSize; + if (!file.GetLength(fileSize)) return false; - AString s; - char *p = s.GetBuffer((int)length + 1); - UInt32 processed; - if (!file.Read(p, (UInt32)length, processed)) + if (fileSize >= ((UInt32)1 << 31) - 32) return false; - p[(UInt32)length] = 0; - s.ReleaseBuffer(); - file.Close(); - UString u; - #ifdef CP_UTF8 - if (codePage == CP_UTF8) + if (codePage == MY__CP_UTF16 || codePage == MY__CP_UTF16BE) { - if (!ConvertUTF8ToUnicode(s, u)) + if ((fileSize & 1) != 0) + return false; + CByteArr buf((size_t)fileSize); + UInt32 processed; + if (!file.Read(buf, (UInt32)fileSize, processed)) return false; + if (processed != fileSize) + return false; + file.Close(); + unsigned num = (unsigned)fileSize / 2; + wchar_t *p = u.GetBuffer(num); + if (codePage == MY__CP_UTF16) + for (unsigned i = 0; i < num; i++) + { + wchar_t c = GetUi16(buf + i * 2); + if (c == 0) + return false; + p[i] = c; + } + else + for (unsigned i = 0; i < num; i++) + { + wchar_t c = (wchar_t)GetBe16(buf + i * 2); + if (c == 0) + return false; + p[i] = c; + } + u.ReleaseBuffer(num); } else - #endif - u = MultiByteToUnicodeString(s, codePage); - if (!u.IsEmpty()) { - if (u[0] == 0xFEFF) - u.Delete(0); + AString s; + char *p = s.GetBuffer((unsigned)fileSize); + UInt32 processed; + if (!file.Read(p, (UInt32)fileSize, processed)) + return false; + if (processed != fileSize) + return false; + file.Close(); + p[processed] = 0; + s.ReleaseBuffer(); + if (s.Len() != processed) + return false; + + // #ifdef CP_UTF8 + if (codePage == CP_UTF8) + { + if (!ConvertUTF8ToUnicode(s, u)) + return false; + } + else + // #endif + MultiByteToUnicodeString2(u, s, codePage); } - UString t; - for (int i = 0; i < u.Length(); i++) + const wchar_t kGoodBOM = 0xFEFF; + const wchar_t kBadBOM = 0xFFFE; + + UString s; + unsigned i = 0; + for (; i < u.Len() && u[i] == kGoodBOM; i++); + for (; i < u.Len(); i++) { wchar_t c = u[i]; + if (c == kGoodBOM || c == kBadBOM) + return false; if (c == L'\n' || c == 0xD) { - t.Trim(); - RemoveQuote(t); - if (!t.IsEmpty()) - resultStrings.Add(t); - t.Empty(); + AddName(strings, s); + s.Empty(); } else - t += c; + s += c; } - t.Trim(); - RemoveQuote(t); - if (!t.IsEmpty()) - resultStrings.Add(t); + AddName(strings, s); return true; } diff --git a/CPP/Common/ListFileUtils.h b/CPP/Common/ListFileUtils.h old mode 100755 new mode 100644 index d43bfdfc..e8d833fd --- a/CPP/Common/ListFileUtils.h +++ b/CPP/Common/ListFileUtils.h @@ -4,7 +4,10 @@ #define __COMMON_LIST_FILE_UTILS_H #include "MyString.h" -#include "Types.h" +#include "MyTypes.h" + +#define MY__CP_UTF16 1200 +#define MY__CP_UTF16BE 1201 bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP); diff --git a/CPP/Common/MyBuffer.h b/CPP/Common/MyBuffer.h new file mode 100644 index 00000000..27c188c7 --- /dev/null +++ b/CPP/Common/MyBuffer.h @@ -0,0 +1,237 @@ +// Common/MyBuffer.h + +#ifndef __COMMON_MY_BUFFER_H +#define __COMMON_MY_BUFFER_H + +#include "Defs.h" + +template class CBuffer +{ + T *_items; + size_t _size; + + void CopyToEmpty(const CBuffer &buffer) + { + if (buffer._size > 0) + { + _items = new T[buffer._size]; + memcpy(_items, buffer._items, buffer._size * sizeof(T)); + _size = buffer._size; + } + } +public: + void Free() + { + if (_items) + { + delete []_items; + _items = 0; + } + _size = 0; + } + + CBuffer(): _items(0), _size(0) {}; + CBuffer(size_t size): _items(0), _size(0) { _items = new T[size]; _size = size; } + CBuffer(const CBuffer &buffer): _items(0), _size(0) { CopyToEmpty(buffer); } + ~CBuffer() { delete []_items; } + + operator T *() { return _items; }; + operator const T *() const { return _items; }; + size_t Size() const { return _size; } + + void Alloc(size_t size) + { + if (size != _size) + { + Free(); + if (size != 0) + { + _items = new T[size]; + _size = size; + } + } + } + + void AllocAtLeast(size_t size) + { + if (size > _size) + { + Free(); + _items = new T[size]; + _size = size; + } + } + + void CopyFrom(const T *data, size_t size) + { + Alloc(size); + memcpy(_items, data, size * sizeof(T)); + } + + void ChangeSize_KeepData(size_t newSize, size_t keepSize) + { + if (newSize == _size) + return; + T *newBuffer = NULL; + if (newSize > 0) + { + newBuffer = new T[newSize]; + if (_size > 0) + memcpy(newBuffer, _items, MyMin(MyMin(_size, keepSize), newSize) * sizeof(T)); + } + delete []_items; + _items = newBuffer; + _size = newSize; + } + + CBuffer& operator=(const CBuffer &buffer) + { + Free(); + CopyToEmpty(buffer); + return *this; + } +}; + +template +bool operator==(const CBuffer& b1, const CBuffer& b2) +{ + size_t size1 = b1.Size(); + if (size1 != b2.Size()) + return false; + return memcmp(b1, b2, size1 * sizeof(T)) == 0; +} + +template +bool operator!=(const CBuffer& b1, const CBuffer& b2) +{ + size_t size1 = b1.Size(); + if (size1 == b2.Size()) + return false; + return memcmp(b1, b2, size1 * sizeof(T)) != 0; +} + + +typedef CBuffer CCharBuffer; +typedef CBuffer CWCharBuffer; +typedef CBuffer CByteBuffer; + + +template class CObjArray +{ +protected: + T *_items; +private: + // we disable constructors + CObjArray(const CObjArray &buffer); + void operator=(const CObjArray &buffer); +public: + void Free() + { + delete []_items; + _items = 0; + } + CObjArray(size_t size): _items(0) { if (size != 0) _items = new T[size]; } + CObjArray(): _items(0) {}; + ~CObjArray() { delete []_items; } + + operator T *() { return _items; }; + operator const T *() const { return _items; }; + + void Alloc(size_t newSize) + { + delete []_items; + _items = 0; + _items = new T[newSize]; + } +}; + +typedef CObjArray CByteArr; +typedef CObjArray CBoolArr; +typedef CObjArray CIntArr; + +// #define CRecArray CObjArray + +template class CObjArray2 +{ +// protected: + T *_items; + unsigned _size; + + CObjArray2(const CObjArray2 &buffer); + void operator=(const CObjArray2 &buffer); +public: + + void Free() + { + delete []_items; + _items = 0; + _size = 0; + } + CObjArray2(): _items(0), _size(0) {}; + /* + CObjArray2(const CObjArray2 &buffer): _items(0), _size(0) + { + size_t newSize = buffer._size; + if (newSize > 0) + { + T *newBuffer = new T[newSize];; + _items = newBuffer; + _size = newSize; + const T *src = buffer; + for (size_t i = 0; i < newSize; i++) + newBuffer[i] = src[i]; + } + } + */ + /* + CObjArray2(size_t size): _items(0), _size(0) + { + if (size != 0) + { + _items = new T[size]; + _size = size; + } + } + */ + + ~CObjArray2() { delete []_items; } + + operator T *() { return _items; }; + operator const T *() const { return _items; }; + + unsigned Size() const { return (unsigned)_size; } + bool IsEmpty() const { return _size == 0; } + + // SetSize doesn't keep old items. It allocates new array if size is not equal + void SetSize(unsigned size) + { + if (size == _size) + return; + T *newBuffer = NULL; + if (size > 0) + newBuffer = new T[size]; + delete []_items; + _items = newBuffer; + _size = size; + } + + /* + CObjArray2& operator=(const CObjArray2 &buffer) + { + Free(); + size_t newSize = buffer._size; + if (newSize > 0) + { + T *newBuffer = new T[newSize];; + _items = newBuffer; + _size = newSize; + const T *src = buffer; + for (size_t i = 0; i < newSize; i++) + newBuffer[i] = src[i]; + } + return *this; + } + */ +}; + +#endif diff --git a/CPP/Common/MyCom.h b/CPP/Common/MyCom.h old mode 100755 new mode 100644 index 2f00c258..9e2576e3 --- a/CPP/Common/MyCom.h +++ b/CPP/Common/MyCom.h @@ -1,9 +1,10 @@ // MyCom.h -#ifndef __MYCOM_H -#define __MYCOM_H +#ifndef __MY_COM_H +#define __MY_COM_H #include "MyWindows.h" +#include "NewHandler.h" #ifndef RINOK #define RINOK(x) { HRESULT __result_ = (x); if (__result_ != S_OK) return __result_; } @@ -14,14 +15,9 @@ 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(): _p(NULL) {} + CMyComPtr(T* p) throw() { if ((_p = p) != NULL) p->AddRef(); } + CMyComPtr(const CMyComPtr& lp) throw() { if ((_p = lp._p) != NULL) _p->AddRef(); } ~CMyComPtr() { if (_p) _p->Release(); } void Release() { if (_p) { _p->Release(); _p = NULL; } } operator T*() const { return (T*)_p; } @@ -30,7 +26,7 @@ public: T* operator->() const { return _p; } T* operator=(T* p) { - if (p != 0) + if (p) p->AddRef(); if (_p) _p->Release(); @@ -40,7 +36,6 @@ public: 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(); @@ -70,7 +65,7 @@ public: } */ template - HRESULT QueryInterface(REFGUID iid, Q** pp) const + HRESULT QueryInterface(REFGUID iid, Q** pp) const throw() { return _p->QueryInterface(iid, (void**)pp); } @@ -81,13 +76,14 @@ public: inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr) { *bstr = ::SysAllocString(src); - return (*bstr != 0) ? S_OK : E_OUTOFMEMORY; + return (*bstr != NULL) ? S_OK : E_OUTOFMEMORY; } class CMyComBSTR { -public: BSTR m_str; +public: + CMyComBSTR(): m_str(NULL) {} CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); } // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); } @@ -119,7 +115,7 @@ public: m_str = ::SysAllocString(src); return *this; } - unsigned int Length() const { return ::SysStringLen(m_str); } + // unsigned Len() const { return ::SysStringLen(m_str); } operator BSTR() const { return m_str; } BSTR* operator&() { return &m_str; } BSTR MyCopy() const @@ -143,7 +139,7 @@ public: ::SysFreeString(m_str); m_str = NULL; } - bool operator!() const { return (m_str == NULL); } + bool operator!() const { return (m_str == NULL); } }; ////////////////////////////////////////////////////////// @@ -156,22 +152,22 @@ public: }; #define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \ - (REFGUID iid, void **outObject) { +(REFGUID iid, void **outObject) throw() { *outObject = NULL; -#define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \ - { *outObject = (void *)(i *)this; AddRef(); return S_OK; } +#define MY_QUERYINTERFACE_ENTRY(i) else if (iid == IID_ ## i) \ + { *outObject = (void *)(i *)this; } #define MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) if (iid == IID_IUnknown) \ - { *outObject = (void *)(IUnknown *)(i *)this; AddRef(); return S_OK; } + { *outObject = (void *)(IUnknown *)(i *)this; } #define MY_QUERYINTERFACE_BEGIN2(i) MY_QUERYINTERFACE_BEGIN \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ MY_QUERYINTERFACE_ENTRY(i) -#define MY_QUERYINTERFACE_END return E_NOINTERFACE; } +#define MY_QUERYINTERFACE_END else return E_NOINTERFACE; AddRef(); return S_OK; } #define MY_ADDREF_RELEASE \ -STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \ +STDMETHOD_(ULONG, AddRef)() throw() { return ++__m_RefCount; } \ STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \ return __m_RefCount; delete this; return 0; } @@ -222,4 +218,25 @@ STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \ MY_QUERYINTERFACE_ENTRY(i5) \ ) +#define MY_UNKNOWN_IMP6(i1, i2, i3, i4, i5, i6) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + MY_QUERYINTERFACE_ENTRY(i4) \ + MY_QUERYINTERFACE_ENTRY(i5) \ + MY_QUERYINTERFACE_ENTRY(i6) \ + ) + +#define MY_UNKNOWN_IMP7(i1, i2, i3, i4, i5, i6, i7) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + MY_QUERYINTERFACE_ENTRY(i4) \ + MY_QUERYINTERFACE_ENTRY(i5) \ + MY_QUERYINTERFACE_ENTRY(i6) \ + MY_QUERYINTERFACE_ENTRY(i7) \ + ) + #endif diff --git a/CPP/Common/MyException.h b/CPP/Common/MyException.h old mode 100755 new mode 100644 diff --git a/CPP/Common/MyGuidDef.h b/CPP/Common/MyGuidDef.h old mode 100755 new mode 100644 index 3c52cc07..68745870 --- a/CPP/Common/MyGuidDef.h +++ b/CPP/Common/MyGuidDef.h @@ -3,7 +3,7 @@ #ifndef GUID_DEFINED #define GUID_DEFINED -#include "Types.h" +#include "MyTypes.h" typedef struct { UInt32 Data1; diff --git a/CPP/Common/MyInitGuid.h b/CPP/Common/MyInitGuid.h old mode 100755 new mode 100644 diff --git a/CPP/Common/MyMap.cpp b/CPP/Common/MyMap.cpp old mode 100755 new mode 100644 index 0ee11e8c..db95169e --- a/CPP/Common/MyMap.cpp +++ b/CPP/Common/MyMap.cpp @@ -6,7 +6,7 @@ static const unsigned kNumBitsMax = sizeof(UInt32) * 8; -static UInt32 GetSubBits(UInt32 value, unsigned startPos, unsigned numBits) +static UInt32 GetSubBits(UInt32 value, unsigned startPos, unsigned numBits) throw() { if (startPos == sizeof(value) * 8) return 0; @@ -33,7 +33,7 @@ bool CMap32::Find(UInt32 key, UInt32 &valueRes) const } } - int cur = 0; + unsigned cur = 0; unsigned bitPos = kNumBitsMax; for (;;) { @@ -47,7 +47,7 @@ bool CMap32::Find(UInt32 key, UInt32 &valueRes) const valueRes = n.Values[bit]; return (key == n.Keys[bit]); } - cur = (int)n.Keys[bit]; + cur = (unsigned)n.Keys[bit]; } } @@ -74,7 +74,7 @@ bool CMap32::Set(UInt32 key, UInt32 value) return true; } unsigned i = kNumBitsMax - 1; - for (;GetSubBit(key, i) == GetSubBit(n.Key, i); i--); + for (; GetSubBit(key, i) == GetSubBit(n.Key, i); i--); n.Len = (UInt16)(kNumBitsMax - (1 + i)); unsigned newBit = GetSubBit(key, i); n.Values[newBit] = value; @@ -83,7 +83,7 @@ bool CMap32::Set(UInt32 key, UInt32 value) } } - int cur = 0; + unsigned cur = 0; unsigned bitPos = kNumBitsMax; for (;;) { @@ -117,7 +117,7 @@ bool CMap32::Set(UInt32 key, UInt32 value) return true; } unsigned i = bitPos - 1; - for (;GetSubBit(key, i) == GetSubBit(n.Keys[bit], i); i--); + for (; GetSubBit(key, i) == GetSubBit(n.Keys[bit], i); i--); CNode e2; @@ -135,6 +135,6 @@ bool CMap32::Set(UInt32 key, UInt32 value) Nodes.Add(e2); return false; } - cur = (int)n.Keys[bit]; + cur = (unsigned)n.Keys[bit]; } } diff --git a/CPP/Common/MyMap.h b/CPP/Common/MyMap.h old mode 100755 new mode 100644 index d0dd43f5..cbcbadd6 --- a/CPP/Common/MyMap.h +++ b/CPP/Common/MyMap.h @@ -3,8 +3,8 @@ #ifndef __COMMON_MYMAP_H #define __COMMON_MYMAP_H +#include "MyTypes.h" #include "MyVector.h" -#include "Types.h" class CMap32 { @@ -21,7 +21,7 @@ class CMap32 public: void Clear() { Nodes.Clear(); } - bool Find(UInt32 key, UInt32 &valueRes) const; + bool Find(UInt32 key, UInt32 &valueRes) const throw(); bool Set(UInt32 key, UInt32 value); // returns true, if there is such key already }; diff --git a/CPP/Common/MyString.cpp b/CPP/Common/MyString.cpp old mode 100755 new mode 100644 index dc254eaf..ac407e87 --- a/CPP/Common/MyString.cpp +++ b/CPP/Common/MyString.cpp @@ -4,17 +4,22 @@ #ifdef _WIN32 #include +#include #else #include #endif -#ifndef _UNICODE +#if !defined(_UNICODE) || !defined(USE_UNICODE_FSTRING) #include "StringConvert.h" #endif #include "MyString.h" -const char* MyStringGetNextCharPointer(const char *p) +#define MY_STRING_NEW(_T_, _size_) new _T_[_size_] +// #define MY_STRING_NEW(_T_, _size_) ((_T_ *)my_new((size_t)(_size_) * sizeof(_T_))) + +/* +inline const char* MyStringGetNextCharPointer(const char *p) throw() { #if defined(_WIN32) && !defined(UNDER_CE) return CharNextA(p); @@ -22,16 +27,17 @@ const char* MyStringGetNextCharPointer(const char *p) return p + 1; #endif } +*/ int FindCharPosInString(const char *s, char c) { - for (const char *p = s;;) + for (const char *p = s;; p++) { if (*p == c) return (int)(p - s); if (*p == 0) return -1; - p = MyStringGetNextCharPointer(p); + // MyStringGetNextCharPointer(p); } } @@ -46,55 +52,54 @@ int FindCharPosInString(const wchar_t *s, wchar_t c) } } -#ifdef _WIN32 - -#ifdef _UNICODE - -wchar_t MyCharUpper(wchar_t c) +/* +void MyStringUpper_Ascii(wchar_t *s) { - return (wchar_t)(unsigned int)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); + for (;;) + { + wchar_t c = *s; + if (c == 0) + return; + *s++ = MyCharUpper_Ascii(c); + } } +*/ -/* -wchar_t MyCharLower(wchar_t c) +void MyStringLower_Ascii(wchar_t *s) { - return (wchar_t)(unsigned int)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); + for (;;) + { + wchar_t c = *s; + if (c == 0) + return; + *s++ = MyCharLower_Ascii(c); + } } -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 -*/ +#ifdef _WIN32 -wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); } -wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); } +#ifdef _UNICODE +// wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); } +// wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); } // for WinCE - FString - char -const char *MyStringGetPrevCharPointer(const char * /* base */, const char *p) -{ - return p - 1; -} +// const char *MyStringGetPrevCharPointer(const char * /* base */, const char *p) { return p - 1; } #else -const char * MyStringGetPrevCharPointer(const char *base, const char *p) { return CharPrevA(base, p); } -char * MyStringUpper(char *s) { return CharUpperA(s); } -char * MyStringLower(char *s) { return CharLowerA(s); } +// const char * MyStringGetPrevCharPointer(const char *base, const char *p) throw() { return CharPrevA(base, p); } +// char * MyStringUpper(char *s) { return CharUpperA(s); } +// char * MyStringLower(char *s) { return CharLowerA(s); } -wchar_t MyCharUpper(wchar_t c) +wchar_t MyCharUpper_WIN(wchar_t c) { - if (c == 0) - return 0; - wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); + wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned)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 (wchar_t)(unsigned)(UINT_PTR)res; + const int kBufSize = 4; + char s[kBufSize + 1]; + int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufSize, 0, 0); + if (numChars == 0 || numChars > kBufSize) return c; s[numChars] = 0; ::CharUpperA(s); @@ -102,24 +107,25 @@ wchar_t MyCharUpper(wchar_t c) return c; } -wchar_t MyCharLower(wchar_t c) +/* +wchar_t MyCharLower_WIN(wchar_t c) { - if (c == 0) - return 0; - wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); + wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned)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 (wchar_t)(unsigned)(UINT_PTR)res; + const int kBufSize = 4; + char s[kBufSize + 1]; + int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufSize, 0, 0); + if (numChars == 0 || numChars > kBufSize) return c; s[numChars] = 0; ::CharLowerA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } +*/ +/* wchar_t * MyStringUpper(wchar_t *s) { if (s == 0) @@ -132,7 +138,9 @@ wchar_t * MyStringUpper(wchar_t *s) MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); return s; } +*/ +/* wchar_t * MyStringLower(wchar_t *s) { if (s == 0) @@ -145,68 +153,127 @@ wchar_t * MyStringLower(wchar_t *s) MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); return s; } +*/ #endif -#else +#endif -wchar_t MyCharUpper(wchar_t c) +bool IsString1PrefixedByString2(const char *s1, const char *s2) { - return toupper(c); + for (;;) + { + unsigned char c2 = (unsigned char)*s2++; if (c2 == 0) return true; + unsigned char c1 = (unsigned char)*s1++; if (c1 != c2) return false; + } } -wchar_t * MyStringUpper(wchar_t *s) +bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) { - if (s == 0) - return 0; - for (wchar_t *p = s; *p != 0; p++) - *p = MyCharUpper(*p); - return s; + for (;;) + { + wchar_t c1 = *s1++; + wchar_t c2 = *s2++; + if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2)) return false; + if (c1 == 0) return true; + } } -/* -int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) +// ---------- ASCII ---------- + +bool AString::IsPrefixedBy_Ascii_NoCase(const char *s) const { + const char *s1 = _chars; for (;;) { - wchar_t c1 = *s1++; - wchar_t c2 = *s2++; - wchar_t u1 = MyCharUpper(c1); - wchar_t u2 = MyCharUpper(c2); + char c2 = *s++; + if (c2 == 0) + return true; + char c1 = *s1++; + if (MyCharLower_Ascii(c1) != + MyCharLower_Ascii(c2)) + return false; + } +} - if (u1 < u2) return -1; - if (u1 > u2) return 1; - if (u1 == 0) return 0; +bool UString::IsPrefixedBy_Ascii_NoCase(const char *s) const +{ + const wchar_t *s1 = _chars; + for (;;) + { + char c2 = *s++; + if (c2 == 0) + return true; + wchar_t c1 = *s1++; + if (MyCharLower_Ascii(c1) != + MyCharLower_Ascii(c2)) + return false; } } -*/ -#endif +bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) +{ + for (;;) + { + unsigned char c = *a; + if (c != *u) + return false; + if (c == 0) + return true; + a++; + u++; + } +} -int MyStringCompare(const char *s1, const char *s2) +bool StringsAreEqualNoCase_Ascii(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; + char c1 = *s1++; + char c2 = *s2++; + if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2)) + return false; + if (c1 == 0) + return true; } } -int MyStringCompare(const wchar_t *s1, const wchar_t *s2) +bool StringsAreEqualNoCase_Ascii(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; + if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2)) + return false; + if (c1 == 0) + return true; + } +} + +bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) +{ + for (;;) + { + wchar_t c1 = *s1++; + char c2 = *s2++; + if (c1 != c2 && (c1 > 0x7F || MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))) + return false; + if (c1 == 0) + return true; } } +bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) +{ + for (;;) + { + wchar_t c2 = *s2++; if (c2 == 0) return true; + wchar_t c1 = *s1++; if (c1 != c2) return false; + } +} + +// NTFS order: uses upper case int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) { for (;;) @@ -224,17 +291,894 @@ int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) } } -UString MultiByteToUnicodeString(const AString &srcString, UINT codePage); -AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage); +int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) +{ + for (; num != 0; num--) + { + wchar_t c1 = *s1++; + wchar_t c2 = *s2++; + if (c1 != c2) + { + wchar_t u1 = MyCharUpper(c1); + wchar_t u2 = MyCharUpper(c2); + if (u1 < u2) return -1; + if (u1 > u2) return 1; + } + if (c1 == 0) return 0; + } + return 0; +} + + +// ---------- AString ---------- + +void AString::InsertSpace(unsigned &index, unsigned size) +{ + Grow(size); + MoveItems(index + size, index); +} + +void AString::ReAlloc(unsigned newLimit) +{ + if (newLimit < _len || newLimit >= 0x20000000) throw 20130220; + // MY_STRING_REALLOC(_chars, char, newLimit + 1, _len + 1); + char *newBuf = MY_STRING_NEW(char, newLimit + 1); + memcpy(newBuf, _chars, (size_t)(_len + 1)); \ + MY_STRING_DELETE(_chars); + _chars = newBuf; + + _limit = newLimit; +} + +void AString::SetStartLen(unsigned len) +{ + _chars = 0; + _chars = MY_STRING_NEW(char, len + 1); + _len = len; + _limit = len; +} + +void AString::Grow_1() +{ + unsigned next = _len; + next += next / 2; + next += 16; + next &= ~(unsigned)15; + ReAlloc(next - 1); +} + +void AString::Grow(unsigned n) +{ + unsigned freeSize = _limit - _len; + if (n <= freeSize) + return; + + unsigned next = _len + n; + next += next / 2; + next += 16; + next &= ~(unsigned)15; + ReAlloc(next - 1); +} + +/* +AString::AString(unsigned num, const char *s) +{ + unsigned len = MyStringLen(s); + if (num > len) + num = len; + SetStartLen(num); + memcpy(_chars, s, num); + _chars[num] = 0; +} +*/ + +AString::AString(unsigned num, const AString &s) +{ + if (num > s._len) + num = s._len; + SetStartLen(num); + memcpy(_chars, s._chars, num); + _chars[num] = 0; +} + +AString::AString(const AString &s, char c) +{ + SetStartLen(s.Len() + 1); + char *chars = _chars; + unsigned len = s.Len(); + memcpy(chars, s, len); + chars[len] = c; + chars[len + 1] = 0; +} + +AString::AString(const char *s1, unsigned num1, const char *s2, unsigned num2) +{ + SetStartLen(num1 + num2); + char *chars = _chars; + memcpy(chars, s1, num1); + memcpy(chars + num1, s2, num2 + 1); +} + +AString operator+(const AString &s1, const AString &s2) { return AString(s1, s1.Len(), s2, s2.Len()); } +AString operator+(const AString &s1, const char *s2) { return AString(s1, s1.Len(), s2, MyStringLen(s2)); } +AString operator+(const char *s1, const AString &s2) { return AString(s1, MyStringLen(s1), s2, s2.Len()); } + +AString::AString() +{ + _chars = 0; + _chars = MY_STRING_NEW(char, 4); + _len = 0; + _limit = 4 - 1; + _chars[0] = 0; +} + +AString::AString(char c) +{ + SetStartLen(1); + _chars[0] = c; + _chars[1] = 0; +} + +AString::AString(const char *s) +{ + SetStartLen(MyStringLen(s)); + MyStringCopy(_chars, s); +} + +AString::AString(const AString &s) +{ + SetStartLen(s._len); + MyStringCopy(_chars, s._chars); +} + +AString &AString::operator=(char c) +{ + if (1 > _limit) + { + char *newBuf = MY_STRING_NEW(char, 1 + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = 1; + } + _len = 1; + _chars[0] = c; + _chars[1] = 0; + return *this; +} + +AString &AString::operator=(const char *s) +{ + unsigned len = MyStringLen(s); + if (len > _limit) + { + char *newBuf = MY_STRING_NEW(char, len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + _len = len; + MyStringCopy(_chars, s); + return *this; +} + +AString &AString::operator=(const AString &s) +{ + if (&s == this) + return *this; + unsigned len = s._len; + if (len > _limit) + { + char *newBuf = MY_STRING_NEW(char, len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + _len = len; + MyStringCopy(_chars, s._chars); + return *this; +} + +AString &AString::operator+=(const char *s) +{ + unsigned len = MyStringLen(s); + Grow(len); + MyStringCopy(_chars + _len, s); + _len += len; + return *this; +} + +AString &AString::operator+=(const AString &s) +{ + Grow(s._len); + MyStringCopy(_chars + _len, s._chars); + _len += s._len; + return *this; +} +void AString::SetFrom(const char *s, unsigned len) // no check +{ + if (len > _limit) + { + char *newBuf = MY_STRING_NEW(char, len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + memcpy(_chars, s, len); + _chars[len] = 0; + _len = len; +} + +int AString::Find(const AString &s, unsigned startIndex) const +{ + if (s.IsEmpty()) + return startIndex; + for (; startIndex < _len; startIndex++) + { + unsigned j; + for (j = 0; j < s._len && startIndex + j < _len; j++) + if (_chars[startIndex + j] != s._chars[j]) + break; + if (j == s._len) + return (int)startIndex; + } + return -1; +} + +int AString::ReverseFind(char c) const +{ + if (_len == 0) + return -1; + const char *p = _chars + _len - 1; + for (;;) + { + if (*p == c) + return (int)(p - _chars); + if (p == _chars) + return -1; + p--; // p = GetPrevCharPointer(_chars, p); + } +} + +void AString::TrimLeft() +{ + const char *p = _chars; + for (;; p++) + { + char c = *p; + if (c != ' ' && c != '\n' && c != '\t') + break; + } + unsigned pos = (unsigned)(p - _chars); + if (pos != 0) + { + MoveItems(0, pos); + _len -= pos; + } +} + +void AString::TrimRight() +{ + const char *p = _chars; + int i; + for (i = _len - 1; i >= 0; i--) + { + char c = p[i]; + if (c != ' ' && c != '\n' && c != '\t') + break; + } + i++; + if ((unsigned)i != _len) + { + _chars[i] = 0; + _len = i; + } +} + +void AString::InsertAtFront(char c) +{ + if (_limit == _len) + Grow_1(); + MoveItems(1, 0); + _chars[0] = c; + _len++; +} + +/* +void AString::Insert(unsigned index, char c) +{ + InsertSpace(index, 1); + _chars[index] = c; + _len++; +} +*/ + +void AString::Insert(unsigned index, const char *s) +{ + unsigned num = MyStringLen(s); + if (num != 0) + { + InsertSpace(index, num); + memcpy(_chars + index, s, num); + _len += num; + } +} + +void AString::Insert(unsigned index, const AString &s) +{ + unsigned num = s.Len(); + if (num != 0) + { + InsertSpace(index, num); + memcpy(_chars + index, s, num); + _len += num; + } +} + +void AString::RemoveChar(char ch) +{ + int pos = Find(ch); + if (pos < 0) + return; + const char *src = _chars; + char *dest = _chars + pos; + pos++; + unsigned len = _len; + for (; (unsigned)pos < len; pos++) + { + char c = src[(unsigned)pos]; + if (c != ch) + *dest++ = c; + } + *dest = 0; + _len = (unsigned)(dest - _chars); +} + +// !!!!!!!!!!!!!!! test it if newChar = '\0' +void AString::Replace(char oldChar, char newChar) +{ + if (oldChar == newChar) + return; // 0; + // unsigned number = 0; + int pos = 0; + while ((unsigned)pos < _len) + { + pos = Find(oldChar, pos); + if (pos < 0) + break; + _chars[pos] = newChar; + pos++; + // number++; + } + return; // number; +} + +void AString::Replace(const AString &oldString, const AString &newString) +{ + if (oldString.IsEmpty()) + return; // 0; + if (oldString == newString) + return; // 0; + unsigned oldLen = oldString.Len(); + unsigned newLen = newString.Len(); + // unsigned number = 0; + int pos = 0; + while ((unsigned)pos < _len) + { + pos = Find(oldString, pos); + if (pos < 0) + break; + Delete(pos, oldLen); + Insert(pos, newString); + pos += newLen; + // number++; + } + // return number; +} + +void AString::Delete(unsigned index) +{ + MoveItems(index, index + 1); + _len--; +} + +void AString::Delete(unsigned index, unsigned count) +{ + if (index + count > _len) + count = _len - index; + if (count > 0) + { + MoveItems(index, index + count); + _len -= count; + } +} + +void AString::DeleteFrontal(unsigned num) +{ + if (num != 0) + { + MoveItems(0, num); + _len -= num; + } +} + +/* +AString operator+(const AString &s1, const AString &s2) +{ + AString result(s1); + result += s2; + return result; +} + +AString operator+(const AString &s, const char *chars) +{ + AString result(s); + result += chars; + return result; +} + +AString operator+(const char *chars, const AString &s) +{ + AString result(chars); + result += s; + return result; +} + +AString operator+(const AString &s, char c) +{ + AString result(s); + result += c; + return result; +} +*/ + +/* +AString operator+(char c, const AString &s) +{ + AString result(c); + result += s; + return result; +} +*/ + + + + +// ---------- UString ---------- + +void UString::InsertSpace(unsigned index, unsigned size) +{ + Grow(size); + MoveItems(index + size, index); +} + +void UString::ReAlloc(unsigned newLimit) +{ + if (newLimit < _len || newLimit >= 0x20000000) throw 20130221; + // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, _len + 1); + wchar_t *newBuf = MY_STRING_NEW(wchar_t, newLimit + 1); + wmemcpy(newBuf, _chars, _len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + + _limit = newLimit; +} + +void UString::SetStartLen(unsigned len) +{ + _chars = 0; + _chars = MY_STRING_NEW(wchar_t, len + 1); + _len = len; + _limit = len; +} + +void UString::Grow_1() +{ + unsigned next = _len; + next += next / 2; + next += 16; + next &= ~(unsigned)15; + ReAlloc(next - 1); +} + +void UString::Grow(unsigned n) +{ + unsigned freeSize = _limit - _len; + if (n <= freeSize) + return; + + unsigned next = _len + n; + next += next / 2; + next += 16; + next &= ~(unsigned)15; + ReAlloc(next - 1); +} + + +UString::UString(unsigned num, const wchar_t *s) +{ + unsigned len = MyStringLen(s); + if (num > len) + num = len; + SetStartLen(num); + wmemcpy(_chars, s, num); + _chars[num] = 0; +} + + +UString::UString(unsigned num, const UString &s) +{ + if (num > s._len) + num = s._len; + SetStartLen(num); + wmemcpy(_chars, s._chars, num); + _chars[num] = 0; +} + +UString::UString(const UString &s, wchar_t c) +{ + SetStartLen(s.Len() + 1); + wchar_t *chars = _chars; + unsigned len = s.Len(); + wmemcpy(chars, s, len); + chars[len] = c; + chars[len + 1] = 0; +} + +UString::UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2) +{ + SetStartLen(num1 + num2); + wchar_t *chars = _chars; + wmemcpy(chars, s1, num1); + wmemcpy(chars + num1, s2, num2 + 1); +} + +UString operator+(const UString &s1, const UString &s2) { return UString(s1, s1.Len(), s2, s2.Len()); } +UString operator+(const UString &s1, const wchar_t *s2) { return UString(s1, s1.Len(), s2, MyStringLen(s2)); } +UString operator+(const wchar_t *s1, const UString &s2) { return UString(s1, MyStringLen(s1), s2, s2.Len()); } + +UString::UString() +{ + _chars = 0; + _chars = MY_STRING_NEW(wchar_t, 4); + _len = 0; + _limit = 4 - 1; + _chars[0] = 0; +} + +UString::UString(wchar_t c) +{ + SetStartLen(1); + _chars[0] = c; + _chars[1] = 0; +} + +UString::UString(const wchar_t *s) +{ + SetStartLen(MyStringLen(s)); + MyStringCopy(_chars, s); +} + +UString::UString(const UString &s) +{ + SetStartLen(s._len); + MyStringCopy(_chars, s._chars); +} + +UString &UString::operator=(wchar_t c) +{ + if (1 > _limit) + { + wchar_t *newBuf = MY_STRING_NEW(wchar_t, 1 + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = 1; + } + _len = 1; + _chars[0] = c; + _chars[1] = 0; + return *this; +} + +UString &UString::operator=(const wchar_t *s) +{ + unsigned len = MyStringLen(s); + if (len > _limit) + { + wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + _len = len; + MyStringCopy(_chars, s); + return *this; +} + +UString &UString::operator=(const UString &s) +{ + if (&s == this) + return *this; + unsigned len = s._len; + if (len > _limit) + { + wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + _len = len; + MyStringCopy(_chars, s._chars); + return *this; +} + +UString &UString::operator+=(const wchar_t *s) +{ + unsigned len = MyStringLen(s); + Grow(len); + MyStringCopy(_chars + _len, s); + _len += len; + return *this; +} + +UString &UString::operator+=(const UString &s) +{ + Grow(s._len); + MyStringCopy(_chars + _len, s._chars); + _len += s._len; + return *this; +} + +void UString::SetFrom(const wchar_t *s, unsigned len) // no check +{ + if (len > _limit) + { + wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + wmemcpy(_chars, s, len); + _chars[len] = 0; + _len = len; +} + +void UString::SetFromAscii(const char *s) +{ + unsigned len = MyStringLen(s); + if (len > _limit) + { + wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + wchar_t *chars = _chars; + for (unsigned i = 0; i < len; i++) + chars[i] = s[i]; + chars[len] = 0; + _len = len; +} + +void UString::AddAsciiStr(const char *s) +{ + unsigned len = MyStringLen(s); + Grow(len); + wchar_t *chars = _chars + _len; + for (unsigned i = 0; i < len; i++) + chars[i] = s[i]; + chars[len] = 0; + _len += len; +} + + + +int UString::Find(const UString &s, unsigned startIndex) const +{ + if (s.IsEmpty()) + return startIndex; + for (; startIndex < _len; startIndex++) + { + unsigned j; + for (j = 0; j < s._len && startIndex + j < _len; j++) + if (_chars[startIndex + j] != s._chars[j]) + break; + if (j == s._len) + return (int)startIndex; + } + return -1; +} + +int UString::ReverseFind(wchar_t c) const +{ + if (_len == 0) + return -1; + const wchar_t *p = _chars + _len - 1; + for (;;) + { + if (*p == c) + return (int)(p - _chars); + if (p == _chars) + return -1; + p--; + } +} + +void UString::TrimLeft() +{ + const wchar_t *p = _chars; + for (;; p++) + { + wchar_t c = *p; + if (c != ' ' && c != '\n' && c != '\t') + break; + } + unsigned pos = (unsigned)(p - _chars); + if (pos != 0) + { + MoveItems(0, pos); + _len -= pos; + } +} + +void UString::TrimRight() +{ + const wchar_t *p = _chars; + int i; + for (i = _len - 1; i >= 0; i--) + { + wchar_t c = p[i]; + if (c != ' ' && c != '\n' && c != '\t') + break; + } + i++; + if ((unsigned)i != _len) + { + _chars[i] = 0; + _len = i; + } +} + +void UString::InsertAtFront(wchar_t c) +{ + if (_limit == _len) + Grow_1(); + MoveItems(1, 0); + _chars[0] = c; + _len++; +} + +/* +void UString::Insert(unsigned index, wchar_t c) +{ + InsertSpace(index, 1); + _chars[index] = c; + _len++; +} +*/ + +void UString::Insert(unsigned index, const wchar_t *s) +{ + unsigned num = MyStringLen(s); + if (num != 0) + { + InsertSpace(index, num); + wmemcpy(_chars + index, s, num); + _len += num; + } +} + +void UString::Insert(unsigned index, const UString &s) +{ + unsigned num = s.Len(); + if (num != 0) + { + InsertSpace(index, num); + wmemcpy(_chars + index, s, num); + _len += num; + } +} + +void UString::RemoveChar(wchar_t ch) +{ + int pos = Find(ch); + if (pos < 0) + return; + const wchar_t *src = _chars; + wchar_t *dest = _chars + pos; + pos++; + unsigned len = _len; + for (; (unsigned)pos < len; pos++) + { + wchar_t c = src[(unsigned)pos]; + if (c != ch) + *dest++ = c; + } + *dest = 0; + _len = (unsigned)(dest - _chars); +} + +// !!!!!!!!!!!!!!! test it if newChar = '\0' +void UString::Replace(wchar_t oldChar, wchar_t newChar) +{ + if (oldChar == newChar) + return; // 0; + // unsigned number = 0; + int pos = 0; + while ((unsigned)pos < _len) + { + pos = Find(oldChar, pos); + if (pos < 0) + break; + _chars[pos] = newChar; + pos++; + // number++; + } + return; // number; +} + +void UString::Replace(const UString &oldString, const UString &newString) +{ + if (oldString.IsEmpty()) + return; // 0; + if (oldString == newString) + return; // 0; + unsigned oldLen = oldString.Len(); + unsigned newLen = newString.Len(); + // unsigned number = 0; + int pos = 0; + while ((unsigned)pos < _len) + { + pos = Find(oldString, pos); + if (pos < 0) + break; + Delete(pos, oldLen); + Insert(pos, newString); + pos += newLen; + // number++; + } + // return number; +} + +void UString::Delete(unsigned index) +{ + MoveItems(index, index + 1); + _len--; +} + +void UString::Delete(unsigned index, unsigned count) +{ + if (index + count > _len) + count = _len - index; + if (count > 0) + { + MoveItems(index, index + count); + _len -= count; + } +} + +void UString::DeleteFrontal(unsigned num) +{ + if (num != 0) + { + MoveItems(0, num); + _len -= num; + } +} + + +// ---------------------------------------- + +/* int MyStringCompareNoCase(const char *s1, const char *s2) { - return MyStringCompareNoCase(MultiByteToUnicodeString(s1, CP_ACP), MultiByteToUnicodeString(s2, CP_ACP)); + return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2)); } +*/ static inline UINT GetCurrentCodePage() { - #if defined(UNDER_CE) || !defined(defined) + #if defined(UNDER_CE) || !defined(_WIN32) return CP_ACP; #else return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; @@ -243,6 +1187,8 @@ static inline UINT GetCurrentCodePage() #ifdef USE_UNICODE_FSTRING +#ifndef _UNICODE + AString fs2fas(CFSTR s) { return UnicodeStringToMultiByte(s, GetCurrentCodePage()); @@ -253,6 +1199,8 @@ FString fas2fs(const AString &s) return MultiByteToUnicodeString(s, GetCurrentCodePage()); } +#endif + #else UString fs2us(const FString &s) diff --git a/CPP/Common/MyString.h b/CPP/Common/MyString.h old mode 100755 new mode 100644 index 0312bac6..b70e9a54 --- a/CPP/Common/MyString.h +++ b/CPP/Common/MyString.h @@ -5,552 +5,468 @@ #include -#include "Types.h" +#ifndef _WIN32 +#include +#include +#endif + +#include "MyTypes.h" #include "MyVector.h" -template -inline int MyStringLen(const T *s) +inline unsigned MyStringLen(const char *s) +{ + unsigned i; + for (i = 0; s[i] != 0; i++); + return i; +} + +inline void MyStringCopy(char *dest, const char *src) +{ + while ((*dest++ = *src++) != 0); +} + +inline char *MyStpCpy(char *dest, const char *src) +{ + for (;;) + { + Byte c = *src; + *dest = c; + if (c == 0) + return dest; + src++; + dest++; + } +} + +inline unsigned MyStringLen(const wchar_t *s) { - int i; - for (i = 0; s[i] != '\0'; i++); + unsigned i; + for (i = 0; s[i] != 0; i++); return i; } -template -inline void MyStringCopy(T *dest, const T *src) +inline void MyStringCopy(wchar_t *dest, const wchar_t *src) { while ((*dest++ = *src++) != 0); } -int FindCharPosInString(const char *s, char c); -int FindCharPosInString(const wchar_t *s, wchar_t c); +int FindCharPosInString(const char *s, char c) throw(); +int FindCharPosInString(const wchar_t *s, wchar_t c) throw(); -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 + #ifndef _UNICODE + #define STRING_UNICODE_THROW + #endif +#endif -wchar_t MyCharUpper(wchar_t c); -// wchar_t MyCharLower(wchar_t c); +#ifndef STRING_UNICODE_THROW + #define STRING_UNICODE_THROW throw() +#endif -char *MyStringUpper(char *s); -char *MyStringLower(char *s); +/* +inline char MyCharUpper_Ascii(char c) +{ + if (c >= 'a' && c <= 'z') + return (char)(c - 0x20); + return c; +} +inline wchar_t MyCharUpper_Ascii(wchar_t c) +{ + if (c >= 'a' && c <= 'z') + return (wchar_t)(c - 0x20); + return c; +} +*/ -wchar_t *MyStringUpper(wchar_t *s); -wchar_t *MyStringLower(wchar_t *s); +inline char MyCharLower_Ascii(char c) +{ + if (c >= 'A' && c <= 'Z') + return (char)(c + 0x20); + return c; +} -const char* MyStringGetNextCharPointer(const char *p); -const char* MyStringGetPrevCharPointer(const char *base, const char *p); +inline wchar_t MyCharLower_Ascii(wchar_t c) +{ + if (c >= 'A' && c <= 'Z') + return (wchar_t)(c + 0x20); + return c; +} -////////////////////////////////////// -// Compare +wchar_t MyCharUpper_WIN(wchar_t c) throw(); -int MyStringCompare(const char *s1, const char *s2); -int MyStringCompare(const wchar_t *s1, const wchar_t *s2); +inline wchar_t MyCharUpper(wchar_t c) throw() +{ + if (c < 'a') return c; + if (c <= 'z') return (wchar_t)(c - 0x20); + if (c <= 0x7F) return c; + #ifdef _WIN32 + #ifdef _UNICODE + return (wchar_t)(unsigned)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned)c); + #else + return (wchar_t)MyCharUpper_WIN(c); + #endif + #else + return (wchar_t)towupper(c); + #endif +} -int MyStringCompareNoCase(const char *s1, const char *s2); -int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2); +/* +wchar_t MyCharLower_WIN(wchar_t c) throw(); -template -class CStringBase +inline wchar_t MyCharLower(wchar_t c) throw() { - 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); - } + if (c < 'A') return c; + if (c <= 'Z') return (wchar_t)(c + 0x20); + if (c <= 0x7F) return c; + #ifdef _WIN32 + #ifdef _UNICODE + return (wchar_t)(unsigned)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned)c); + #else + return (wchar_t)MyCharLower_WIN(c); + #endif + #else + return (wchar_t)tolower(c); + #endif +} +*/ - } - void MoveItems(int destIndex, int srcIndex) +// char *MyStringUpper(char *s) throw(); +// char *MyStringLower(char *s) throw(); + +// void MyStringUpper_Ascii(wchar_t *s) throw(); +void MyStringLower_Ascii(wchar_t *s) throw(); +// wchar_t *MyStringUpper(wchar_t *s) STRING_UNICODE_THROW; +// wchar_t *MyStringLower(wchar_t *s) STRING_UNICODE_THROW; + +bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw(); + +bool IsString1PrefixedByString2(const char *s1, const char *s2) throw(); +bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw(); + +int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw(); +int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) throw(); + +// ---------- ASCII ---------- +// char values in ASCII strings must be less then 128 +bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw(); +bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw(); +bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw(); +bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw(); + +#define MY_STRING_DELETE(_p_) delete []_p_; +// #define MY_STRING_DELETE(_p_) my_delete(_p_); + +class AString +{ + char *_chars; + unsigned _len; + unsigned _limit; + + void MoveItems(unsigned dest, unsigned src) { - memmove(_chars + destIndex, _chars + srcIndex, - sizeof(T) * (_length - srcIndex + 1)); + memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(char)); } - 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 InsertSpace(unsigned &index, unsigned size); - 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 ReAlloc(unsigned newLimit); + void SetStartLen(unsigned len); + void Grow_1(); + void Grow(unsigned n); - 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); - } + // AString(unsigned num, const char *s); + AString(unsigned num, const AString &s); + AString(const AString &s, char c); // it's for String + char + AString(const char *s1, unsigned num1, const char *s2, unsigned num2); - void CorrectIndex(int &index) const - { - if (index > _length) - index = _length; - } + friend AString operator+(const AString &s, char c) { return AString(s, c); } ; + // friend AString operator+(char c, const AString &s); // is not supported + + friend AString operator+(const AString &s1, const AString &s2); + friend AString operator+(const AString &s1, const char *s2); + friend AString operator+(const char *s1, const AString &s2); 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; } + AString(); + AString(char c); + AString(const char *s); + AString(const AString &s); + ~AString() { MY_STRING_DELETE(_chars); } - operator const T*() const { return _chars;} + unsigned Len() const { return _len; } + bool IsEmpty() const { return _len == 0; } + void Empty() { _len = 0; _chars[0] = 0; } - T Back() const { return _chars[_length - 1]; } + operator const char *() const { return _chars; } + const char *Ptr() const { return _chars; } + const char *Ptr(unsigned pos) const { return _chars + pos; } + const char *RightPtr(unsigned num) const { return _chars + _len - num; } + char Back() const { return _chars[_len - 1]; } + + void ReplaceOneCharAtPos(unsigned pos, char c) { _chars[pos] = c; } // The minimum size of the character buffer in characters. // This value does not include space for a null terminator. - T* GetBuffer(int minBufLength) + char *GetBuffer(unsigned minBufLen) { - if (minBufLength >= _capacity) - SetCapacity(minBufLength); + if (minBufLen > _limit) + ReAlloc(minBufLen); return _chars; } void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); } - void ReleaseBuffer(int newLength) - { - /* - if (newLength >= _capacity) - throw 282217; - */ - _chars[newLength] = 0; - _length = newLength; - } + void ReleaseBuffer(unsigned newLen) { _len = newLen; _chars[newLen] = 0; } + + AString &operator=(char c); + AString &operator=(const char *s); + AString &operator=(const AString &s); - CStringBase& operator=(T c) + AString &operator+=(char c) { - Empty(); - SetCapacity(1); - _chars[0] = c; - _chars[1] = 0; - _length = 1; + if (_limit == _len) + Grow_1(); + unsigned len = _len; + char *chars = _chars; + chars[len++] = c; + chars[len] = 0; + _len = len; return *this; } - CStringBase& operator=(const T *chars) + + AString &operator+=(const char *s); + AString &operator+=(const AString &s); + + void SetFrom(const char *s, unsigned len); // no check + // AString Mid(unsigned startIndex, unsigned count) const { return AString(count, _chars + startIndex); } + AString Left(unsigned count) const { return AString(count, *this); } + + // void MakeUpper() { MyStringUpper(_chars); } + // void MakeLower() { MyStringLower(_chars); } + + + // int Compare(const char *s) const { return MyStringCompare(_chars, s); } + // int Compare(const AString &s) const { return MyStringCompare(_chars, s._chars); } + // int CompareNoCase(const char *s) const { return MyStringCompareNoCase(_chars, s); } + // int CompareNoCase(const AString &s) const { return MyStringCompareNoCase(_chars, s._chars); } + bool IsPrefixedBy(const char *s) const { return IsString1PrefixedByString2(_chars, s); } + bool IsPrefixedBy_Ascii_NoCase(const char *s) const; + + int Find(char c) const { return FindCharPosInString(_chars, c); } + int Find(char c, unsigned startIndex) const { - Empty(); - int length = MyStringLen(chars); - SetCapacity(length); - MyStringCopy(_chars, chars); - _length = length; - return *this; + int pos = FindCharPosInString(_chars + startIndex, c); + return pos < 0 ? -1 : (int)startIndex + pos; } - CStringBase& operator=(const CStringBase& s) + int ReverseFind(char c) const throw(); + int Find(const AString &s) const { return Find(s, 0); } + int Find(const AString &s, unsigned startIndex) const throw(); + + void TrimLeft() throw(); + void TrimRight() throw(); + void Trim() { - if (&s == this) - return *this; - Empty(); - SetCapacity(s._length); - MyStringCopy(_chars, s._chars); - _length = s._length; - return *this; + TrimRight(); + TrimLeft(); } + + void InsertAtFront(char c); + // void Insert(unsigned index, char c); + void Insert(unsigned index, const char *s); + void Insert(unsigned index, const AString &s); + + void RemoveChar(char ch) throw(); + void Replace(char oldChar, char newChar) throw(); + void Replace(const AString &oldString, const AString &newString); - 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) + void Delete(unsigned index) throw(); + void Delete(unsigned index, unsigned count) throw(); + void DeleteFrontal(unsigned num) throw(); + void DeleteBack() { _chars[--_len] = 0; } + void DeleteFrom(unsigned index) { - GrowLength(s._length); - MyStringCopy(_chars + _length, s._chars); - _length += s._length; - return *this; - } - void Empty() - { - _length = 0; - _chars[0] = 0; + if (index < _len) + { + _len = index; + _chars[index] = 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); - } +bool operator<(const AString &s1, const AString &s2); +bool operator>(const AString &s1, const AString &s2); - void MakeUpper() { MyStringUpper(_chars); } - void MakeLower() { MyStringLower(_chars); } +/* +bool operator==(const AString &s1, const AString &s2); +bool operator==(const AString &s1, const char *s2); +bool operator==(const char *s1, const AString &s2); - int Compare(const CStringBase& s) const - { return MyStringCompare(_chars, s._chars); } +bool operator!=(const AString &s1, const AString &s2); +bool operator!=(const AString &s1, const char *s2); +bool operator!=(const char *s1, const AString &s2); +*/ - int Compare(const T *s) const - { return MyStringCompare(_chars, s); } +inline bool operator==(const AString &s1, const AString &s2) { return s1.Len() == s2.Len() && strcmp(s1, s2) == 0; } +inline bool operator==(const AString &s1, const char *s2) { return strcmp(s1, s2) == 0; } +inline bool operator==(const char *s1, const AString &s2) { return strcmp(s1, s2) == 0; } - int CompareNoCase(const CStringBase& s) const - { return MyStringCompareNoCase(_chars, s._chars); } +inline bool operator!=(const AString &s1, const AString &s2) { return s1.Len() != s2.Len() || strcmp(s1, s2) != 0; } +inline bool operator!=(const AString &s1, const char *s2) { return strcmp(s1, s2) != 0; } +inline bool operator!=(const char *s1, const AString &s2) { return strcmp(s1, s2) != 0; } - 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 FindCharPosInString(_chars, c); } - int Find(T c, int startIndex) const - { - int pos = FindCharPosInString(_chars + startIndex, c); - return pos < 0 ? -1 : pos + startIndex; - } - 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; - } +class UString +{ + wchar_t *_chars; + unsigned _len; + unsigned _limit; - void TrimLeft(T c) - { - const T *p = _chars; - while (c == *p) - p = GetNextCharPointer(p); - Delete(0, p - _chars); - } - private: - CStringBase GetTrimDefaultCharSet() + void MoveItems(unsigned dest, unsigned src) { - CStringBase charSet; - charSet += (T)' '; - charSet += (T)'\n'; - charSet += (T)'\t'; - return charSet; + memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(wchar_t)); } - public: + + void InsertSpace(unsigned index, unsigned size); + + void ReAlloc(unsigned newLimit); + void SetStartLen(unsigned len); + void Grow_1(); + void Grow(unsigned n); + + UString(unsigned num, const wchar_t *s); // for Mid + UString(unsigned num, const UString &s); // for Left + UString(const UString &s, wchar_t c); // it's for String + char + UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2); + + friend UString operator+(const UString &s, wchar_t c) { return UString(s, c); } ; + // friend UString operator+(wchar_t c, const UString &s); // is not supported + + friend UString operator+(const UString &s1, const UString &s2); + friend UString operator+(const UString &s1, const wchar_t *s2); + friend UString operator+(const wchar_t *s1, const UString &s2); + +public: + UString(); + UString(wchar_t c); + UString(const wchar_t *s); + UString(const UString &s); + ~UString() { MY_STRING_DELETE(_chars); } - void TrimLeft() + unsigned Len() const { return _len; } + bool IsEmpty() const { return _len == 0; } + void Empty() { _len = 0; _chars[0] = 0; } + + operator const wchar_t *() const { return _chars; } + const wchar_t *Ptr() const { return _chars; } + const wchar_t *Ptr(unsigned pos) const { return _chars + pos; } + const wchar_t *RightPtr(unsigned num) const { return _chars + _len - num; } + wchar_t Back() const { return _chars[_len - 1]; } + + void ReplaceOneCharAtPos(unsigned pos, wchar_t c) { _chars[pos] = c; } + + // The minimum size of the character buffer in characters. + // This value does not include space for a null terminator. + wchar_t *GetBuffer(unsigned minBufLen) { - TrimLeftWithCharSet(GetTrimDefaultCharSet()); + if (minBufLen > _limit) + ReAlloc(minBufLen); + return _chars; } - void TrimRight() + void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); } + void ReleaseBuffer(unsigned newLen) { _len = newLen; _chars[newLen] = 0; } + + UString &operator=(wchar_t c); + UString &operator=(const wchar_t *s); + UString &operator=(const UString &s); + + UString &operator+=(wchar_t c) { - TrimRightWithCharSet(GetTrimDefaultCharSet()); + if (_limit == _len) + Grow_1(); + unsigned len = _len; + wchar_t *chars = _chars; + chars[len++] = c; + chars[len] = 0; + _len = len; + return *this; } - void TrimRight(T c) + + UString &operator+=(const wchar_t *s); + UString &operator+=(const UString &s); + + void SetFrom(const wchar_t *s, unsigned len); // no check + + void SetFromAscii(const char *s); + void AddAsciiStr(const char *s); + + UString Mid(unsigned startIndex, unsigned count) const { return UString(count, _chars + startIndex); } + UString Left(unsigned count) const { return UString(count, *this); } + + // void MakeUpper() { MyStringUpper(_chars); } + // void MakeUpper() { MyStringUpper_Ascii(_chars); } + // void MakeUpper_Ascii() { MyStringUpper_Ascii(_chars); } + void MakeLower_Ascii() { MyStringLower_Ascii(_chars); } + + bool IsEqualTo(const char *s) const { return StringsAreEqual_Ascii(_chars, s); } + bool IsEqualToNoCase(const wchar_t *s) const { return StringsAreEqualNoCase(_chars, s); } + int Compare(const wchar_t *s) const { return wcscmp(_chars, s); } + // int Compare(const UString &s) const { return MyStringCompare(_chars, s._chars); } + // int CompareNoCase(const wchar_t *s) const { return MyStringCompareNoCase(_chars, s); } + // int CompareNoCase(const UString &s) const { return MyStringCompareNoCase(_chars, s._chars); } + bool IsPrefixedBy(const wchar_t *s) const { return IsString1PrefixedByString2(_chars, s); }; + bool IsPrefixedBy_Ascii_NoCase(const char *s) const; + + int Find(wchar_t c) const { return FindCharPosInString(_chars, c); } + int Find(wchar_t c, unsigned startIndex) const { - 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); - } + int pos = FindCharPosInString(_chars + startIndex, c); + return pos < 0 ? -1 : (int)startIndex + pos; } + int Find(const UString &s) const { return Find(s, 0); } + int Find(const UString &s, unsigned startIndex) const throw(); + int ReverseFind(wchar_t c) const throw(); + + void TrimLeft() throw(); + void TrimRight() throw(); 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; - } + void InsertAtFront(wchar_t c); + // void Insert(unsigned index, wchar_t c); + void Insert(unsigned index, const wchar_t *s); + void Insert(unsigned index, const UString &s); - // !!!!!!!!!!!!!!! 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) + void RemoveChar(wchar_t ch) throw(); + void Replace(wchar_t oldChar, wchar_t newChar) throw(); + void Replace(const UString &oldString, const UString &newString); + + void Delete(unsigned index) throw(); + void Delete(unsigned index, unsigned count) throw(); + void DeleteFrontal(unsigned num) throw(); + void DeleteBack() { _chars[--_len] = 0; } + void DeleteFrom(unsigned index) { - if (index + count > _length) - count = _length - index; - if (count > 0) + if (index < _len) { - MoveItems(index, index + count); - _length -= count; + _len = index; + _chars[index] = 0; } - 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); } +bool operator<(const UString &s1, const UString &s2); +bool operator>(const UString &s1, const UString &s2); -template -bool operator!=(const T *s1, const CStringBase& s2) - { return (s2.Compare(s1) != 0); } +inline bool operator==(const UString &s1, const UString &s2) { return s1.Len() == s2.Len() && wcscmp(s1, s2) == 0; } +inline bool operator==(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) == 0; } +inline bool operator==(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) == 0; } -template -bool operator!=(const CStringBase& s1, const T *s2) - { return (s1.Compare(s2) != 0); } +inline bool operator!=(const UString &s1, const UString &s2) { return s1.Len() != s2.Len() || wcscmp(s1, s2) != 0; } +inline bool operator!=(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) != 0; } +inline bool operator!=(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) != 0; } -typedef CStringBase AString; -typedef CStringBase UString; typedef CObjectVector AStringVector; typedef CObjectVector UStringVector; diff --git a/CPP/Common/MyTypes.h b/CPP/Common/MyTypes.h new file mode 100644 index 00000000..4f52a01d --- /dev/null +++ b/CPP/Common/MyTypes.h @@ -0,0 +1,30 @@ +// Common/MyTypes.h + +#ifndef __COMMON_MY_TYPES_H +#define __COMMON_MY_TYPES_H + +#include "../../C/7zTypes.h" + +typedef int HRes; + +struct CBoolPair +{ + bool Val; + bool Def; + + CBoolPair(): Val(false), Def(false) {} + + void Init() + { + Val = false; + Def = false; + } + + void SetTrueTrue() + { + Val = true; + Def = true; + } +}; + +#endif diff --git a/CPP/Common/MyUnknown.h b/CPP/Common/MyUnknown.h old mode 100755 new mode 100644 diff --git a/CPP/Common/MyVector.cpp b/CPP/Common/MyVector.cpp old mode 100755 new mode 100644 index 3b531768..0b1baf45 --- a/CPP/Common/MyVector.cpp +++ b/CPP/Common/MyVector.cpp @@ -1,87 +1,3 @@ // 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 old mode 100755 new mode 100644 index 781b648b..0d060a93 --- a/CPP/Common/MyVector.h +++ b/CPP/Common/MyVector.h @@ -1,92 +1,247 @@ -// Common/Vector.h +// Common/MyVector.h -#ifndef __COMMON_VECTOR_H -#define __COMMON_VECTOR_H +#ifndef __COMMON_MY_VECTOR_H +#define __COMMON_MY_VECTOR_H -#include "Defs.h" - -class CBaseRecordVector +template +class CRecordVector { - void MoveItems(int destIndex, int srcIndex); -protected: - int _capacity; - int _size; - void *_items; - size_t _itemSize; + T *_items; + unsigned _size; + unsigned _capacity; - 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(); -}; + void MoveItems(unsigned destIndex, unsigned srcIndex) + { + memmove(_items + destIndex, _items + srcIndex, (size_t)(_size - srcIndex) * (size_t)sizeof(T)); + } + + void ReserveOnePosition() + { + if (_size == _capacity) + { + unsigned newCapacity = _capacity + (_capacity >> 2) + 1; + T *p = new T[newCapacity]; + memcpy(p, _items, (size_t)_size * (size_t)sizeof(T)); + delete []_items; + _items = p; + _capacity = newCapacity; + } + } -template -class CRecordVector: public CBaseRecordVector -{ public: - CRecordVector(): CBaseRecordVector(sizeof(T)){}; - CRecordVector(const CRecordVector &v): CBaseRecordVector(sizeof(T)) { *this = v; } - CRecordVector& operator=(const CRecordVector &v) + + CRecordVector(): _items(0), _size(0), _capacity(0) {} + + CRecordVector(const CRecordVector &v): _items(0), _size(0), _capacity(0) + { + unsigned size = v.Size(); + if (size != 0) + { + _items = new T[size]; + _size = size; + _capacity = size; + memcpy(_items, v._items, (size_t)size * (size_t)sizeof(T)); + } + } + + unsigned Size() const { return _size; } + bool IsEmpty() const { return _size == 0; } + + void ConstructReserve(unsigned size) + { + if (size != 0) + { + _items = new T[size]; + _capacity = size; + } + } + + void Reserve(unsigned newCapacity) + { + if (newCapacity > _capacity) + { + T *p = new T[newCapacity]; + memcpy(p, _items, (size_t)_size * (size_t)sizeof(T)); + delete []_items; + _items = p; + _capacity = newCapacity; + } + } + + void ClearAndReserve(unsigned newCapacity) { Clear(); - return (*this += v); + if (newCapacity > _capacity) + { + delete []_items; + _items = NULL; + _capacity = 0; + _items = new T[newCapacity]; + _capacity = newCapacity; + } + } + + void ClearAndSetSize(unsigned newSize) + { + ClearAndReserve(newSize); + _size = newSize; + } + + void ChangeSize_KeepData(unsigned newSize) + { + if (newSize > _capacity) + { + T *p = new T[newSize]; + memcpy(p, _items, (size_t)_size * (size_t)sizeof(T)); + delete []_items; + _items = p; + _capacity = newSize; + } + _size = newSize; + } + + void ReserveDown() + { + if (_size == _capacity) + return; + T *p = NULL; + if (_size != 0) + { + p = new T[_size]; + memcpy(p, _items, (size_t)_size * (size_t)sizeof(T)); + } + delete []_items; + _items = p; + _capacity = _size; + } + + ~CRecordVector() { delete []_items; } + + void ClearAndFree() + { + delete []_items; + _items = NULL; + _size = 0; + _capacity = 0; + } + + void Clear() { _size = 0; } + + void DeleteBack() { _size--; } + + void DeleteFrom(unsigned index) + { + // if (index <= _size) + _size = index; + } + + void DeleteFrontal(unsigned num) + { + if (num != 0) + { + MoveItems(0, num); + _size -= num; + } + } + + void Delete(unsigned index) + { + MoveItems(index, index + 1); + _size -= 1; + } + + /* + void Delete(unsigned index, unsigned num) + { + if (num > 0) + { + MoveItems(index, index + num); + _size -= num; + } + } + */ + + CRecordVector& operator=(const CRecordVector &v) + { + unsigned size = v.Size(); + if (size > _capacity) + { + delete []_items; + _capacity = 0; + _size = 0; + _items = NULL; + _items = new T[size]; + _capacity = size; + } + _size = size; + memcpy(_items, v._items, (size_t)size * (size_t)sizeof(T)); + return *this; } + CRecordVector& operator+=(const CRecordVector &v) { - int size = v.Size(); - Reserve(Size() + size); - for (int i = 0; i < size; i++) - Add(v[i]); + unsigned size = v.Size(); + Reserve(_size + size); + memcpy(_items + _size, v._items, (size_t)size * (size_t)sizeof(T)); + _size += size; return *this; } - int Add(T item) + + unsigned Add(const T item) { ReserveOnePosition(); - ((T *)_items)[_size] = item; + _items[_size] = item; return _size++; } - void Insert(int index, T item) + + void AddInReserved(const T item) { - InsertOneItem(index); - ((T *)_items)[index] = item; + _items[_size++] = 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) + void Insert(unsigned index, const T item) { - T temp = operator[](i); - operator[](i) = operator[](j); - operator[](j) = temp; + ReserveOnePosition(); + MoveItems(index + 1, index); + _items[index] = item; + _size++; } - int FindInSorted(const T& item, int left, int right) const + void MoveToFront(unsigned index) + { + if (index != 0) + { + T temp = _items[index]; + memmove(_items + 1, _items, (size_t)index * (size_t)sizeof(T)); + _items[0] = temp; + } + } + + const T& operator[](unsigned index) const { return _items[index]; } + T& operator[](unsigned index) { return _items[index]; } + const T& Front() const { return _items[0]; } + T& Front() { return _items[0]; } + const T& Back() const { return _items[_size - 1]; } + T& Back() { return _items[_size - 1]; } + + /* + void Swap(unsigned i, unsigned j) + { + T temp = _items[i]; + _items[i] = _items[j]; + _items[j] = temp; + } + */ + + int FindInSorted(const T item, unsigned left, unsigned right) const { while (left != right) { - int mid = (left + right) / 2; - const T& midValue = (*this)[mid]; - if (item == midValue) + unsigned mid = (left + right) / 2; + const T midVal = (*this)[mid]; + if (item == midVal) return mid; - if (item < midValue) + if (item < midVal) right = mid; else left = mid + 1; @@ -94,16 +249,16 @@ public: return -1; } - int FindInSorted(const T& item) const + int FindInSorted2(const T &item, unsigned left, unsigned right) const { - int left = 0, right = Size(); while (left != right) { - int mid = (left + right) / 2; - const T& midValue = (*this)[mid]; - if (item == midValue) + unsigned mid = (left + right) / 2; + const T& midVal = (*this)[mid]; + int comp = item.Compare(midVal); + if (comp == 0) return mid; - if (item < midValue) + if (comp < 0) right = mid; else left = mid + 1; @@ -111,16 +266,45 @@ public: return -1; } - int AddToUniqueSorted(const T& item) + int FindInSorted(const T item) const + { + return FindInSorted(item, 0, _size); + } + + int FindInSorted2(const T &item) const + { + return FindInSorted2(item, 0, _size); + } + + unsigned AddToUniqueSorted(const T item) + { + unsigned left = 0, right = _size; + while (left != right) + { + unsigned mid = (left + right) / 2; + const T midVal = (*this)[mid]; + if (item == midVal) + return mid; + if (item < midVal) + right = mid; + else + left = mid + 1; + } + Insert(right, item); + return right; + } + + unsigned AddToUniqueSorted2(const T &item) { - int left = 0, right = Size(); + unsigned left = 0, right = _size; while (left != right) { - int mid = (left + right) / 2; - const T& midValue = (*this)[mid]; - if (item == midValue) + unsigned mid = (left + right) / 2; + const T& midVal = (*this)[mid]; + int comp = item.Compare(midVal); + if (comp == 0) return mid; - if (item < midValue) + if (comp < 0) right = mid; else left = mid + 1; @@ -129,12 +313,12 @@ public: return right; } - static void SortRefDown(T* p, int k, int size, int (*compare)(const T*, const T*, void *), void *param) + static void SortRefDown(T* p, unsigned k, unsigned size, int (*compare)(const T*, const T*, void *), void *param) { T temp = p[k]; for (;;) { - int s = (k << 1); + unsigned s = (k << 1); if (s > size) break; if (s < size && compare(p + s + 1, p + s, param) > 0) @@ -149,12 +333,12 @@ public: void Sort(int (*compare)(const T*, const T*, void *), void *param) { - int size = _size; + unsigned size = _size; if (size <= 1) return; T* p = (&Front()) - 1; { - int i = size / 2; + unsigned i = size >> 1; do SortRefDown(p, i, size, compare, param); while (--i != 0); @@ -168,6 +352,46 @@ public: } while (size > 1); } + + static void SortRefDown2(T* p, unsigned k, unsigned size) + { + T temp = p[k]; + for (;;) + { + unsigned s = (k << 1); + if (s > size) + break; + if (s < size && p[s + 1].Compare(p[s]) > 0) + s++; + if (temp.Compare(p[s]) >= 0) + break; + p[k] = p[s]; + k = s; + } + p[k] = temp; + } + + void Sort2() + { + unsigned size = _size; + if (size <= 1) + return; + T* p = (&Front()) - 1; + { + unsigned i = size >> 1; + do + SortRefDown2(p, i, size); + while (--i != 0); + } + do + { + T temp = p[size]; + p[size--] = p[1]; + p[1] = temp; + SortRefDown2(p, 1, size); + } + while (size > 1); + } }; typedef CRecordVector CIntVector; @@ -177,76 +401,197 @@ typedef CRecordVector CByteVector; typedef CRecordVector CPointerVector; template -class CObjectVector: public CPointerVector +class CObjectVector { + CPointerVector _v; public: + unsigned Size() const { return _v.Size(); } + bool IsEmpty() const { return _v.IsEmpty(); } + void ReserveDown() { _v.ReserveDown(); } + // void Reserve(unsigned newCapacity) { _v.Reserve(newCapacity); } + void ClearAndReserve(unsigned newCapacity) { Clear(); _v.ClearAndReserve(newCapacity); } + CObjectVector() {}; - ~CObjectVector() { Clear(); }; - CObjectVector(const CObjectVector &v): CPointerVector() { *this = v; } + CObjectVector(const CObjectVector &v) + { + unsigned size = v.Size(); + _v.ConstructReserve(size); + for (unsigned i = 0; i < size; i++) + _v.AddInReserved(new T(v[i])); + } CObjectVector& operator=(const CObjectVector &v) { Clear(); - return (*this += v); + unsigned size = v.Size(); + _v.Reserve(size); + for (unsigned i = 0; i < size; i++) + _v.AddInReserved(new T(v[i])); + return *this; } + CObjectVector& operator+=(const CObjectVector &v) { - int size = v.Size(); - Reserve(Size() + size); - for (int i = 0; i < size; i++) - Add(v[i]); + unsigned size = v.Size(); + _v.Reserve(Size() + size); + for (unsigned i = 0; i < size; i++) + _v.AddInReserved(new T(v[i])); return *this; } - const T& operator[](int index) const { return *((T *)CPointerVector::operator[](index)); } - T& operator[](int index) { return *((T *)CPointerVector::operator[](index)); } - T& Front() { return operator[](0); } + + const T& operator[](unsigned index) const { return *((T *)_v[index]); } + T& operator[](unsigned index) { return *((T *)_v[index]); } const T& Front() const { return operator[](0); } - T& 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) + T& Front() { return operator[](0); } + const T& Back() const { return operator[](_v.Size() - 1); } + T& Back() { return operator[](_v.Size() - 1); } + + void MoveToFront(unsigned index) { _v.MoveToFront(index); } + + unsigned Add(const T& item) { return _v.Add(new T(item)); } + + void AddInReserved(const T& item) { _v.AddInReserved(new T(item)); } + + T& AddNew() + { + T *p = new T; + _v.Add(p); + return *p; + } + + T& AddNewInReserved() + { + T *p = new T; + _v.AddInReserved(p); + return *p; + } + + void Insert(unsigned index, const T& item) { _v.Insert(index, new T(item)); } + + T& InsertNew(unsigned index) + { + T *p = new T; + _v.Insert(index, p); + return *p; + } + + ~CObjectVector() + { + for (unsigned i = _v.Size(); i != 0;) + delete (T *)_v[--i]; + } + + void ClearAndFree() + { + Clear(); + _v.ClearAndFree(); + } + + void Clear() + { + for (unsigned i = _v.Size(); i != 0;) + delete (T *)_v[--i]; + _v.Clear(); + } + + void DeleteFrom(unsigned index) + { + unsigned size = _v.Size(); + for (unsigned i = index; i < size; i++) + delete (T *)_v[i]; + _v.DeleteFrom(index); + } + + void DeleteFrontal(unsigned num) + { + for (unsigned i = 0; i < num; i++) + delete (T *)_v[i]; + _v.DeleteFrontal(num); + } + + void DeleteBack() { - TestIndexAndCorrectNum(index, num); - for (int i = 0; i < num; i++) - delete (T *)(((void **)_items)[index + i]); - CPointerVector::Delete(index, num); + delete (T *)_v[_v.Size() - 1]; + _v.DeleteBack(); } + + void Delete(unsigned index) + { + delete (T *)_v[index]; + _v.Delete(index); + } + + /* + void Delete(unsigned index, unsigned num) + { + for (unsigned i = 0; i < num; i++) + delete (T *)_v[index + i]; + _v.Delete(index, num); + } + */ + + /* int Find(const T& item) const { - for (int i = 0; i < Size(); i++) + unsigned size = Size(); + for (unsigned i = 0; i < size; i++) if (item == (*this)[i]) return i; return -1; } + */ + int FindInSorted(const T& item) const { - int left = 0, right = Size(); + unsigned left = 0, right = Size(); while (left != right) { - int mid = (left + right) / 2; - const T& midValue = (*this)[mid]; - if (item == midValue) + unsigned mid = (left + right) / 2; + const T& midVal = (*this)[mid]; + int comp = item.Compare(midVal); + if (comp == 0) return mid; - if (item < midValue) + if (comp < 0) right = mid; else left = mid + 1; } return -1; } - int AddToSorted(const T& item) + + unsigned AddToUniqueSorted(const T& item) { - int left = 0, right = Size(); + unsigned left = 0, right = Size(); while (left != right) { - int mid = (left + right) / 2; - const T& midValue = (*this)[mid]; - if (item == midValue) + unsigned mid = (left + right) / 2; + const T& midVal = (*this)[mid]; + int comp = item.Compare(midVal); + if (comp == 0) + return mid; + if (comp < 0) + right = mid; + else + left = mid + 1; + } + Insert(right, item); + return right; + } + + /* + unsigned AddToSorted(const T& item) + { + unsigned left = 0, right = Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + const T& midVal = (*this)[mid]; + int comp = item.Compare(midVal); + if (comp == 0) { right = mid + 1; break; } - if (item < midValue) + if (comp < 0) right = mid; else left = mid + 1; @@ -254,13 +599,17 @@ public: Insert(right, item); return right; } + */ void Sort(int (*compare)(void *const *, void *const *, void *), void *param) - { CPointerVector::Sort(compare, param); } + { _v.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); } + { return (*(*((const T **)a1))).Compare(*(*((const T **)a2))); } + + void Sort() { _v.Sort(CompareObjectItems, 0); } }; +#define FOR_VECTOR(_i_, _v_) for (unsigned _i_ = 0; _i_ < (_v_).Size(); _i_++) + #endif diff --git a/CPP/Common/MyWindows.cpp b/CPP/Common/MyWindows.cpp old mode 100755 new mode 100644 index f940fc8a..1d9b1e61 --- a/CPP/Common/MyWindows.cpp +++ b/CPP/Common/MyWindows.cpp @@ -28,7 +28,7 @@ BSTR SysAllocStringByteLen(LPCSTR psz, UINT len) BSTR bstr = (BSTR)((UINT *)p + 1); if (psz) { - memmove(bstr, psz, len); + memcpy(bstr, psz, len); Byte *pb = ((Byte *)bstr) + len; for (unsigned i = 0; i < sizeof(OLECHAR) * 2; i++) pb[i] = 0; @@ -36,6 +36,22 @@ BSTR SysAllocStringByteLen(LPCSTR psz, UINT len) return bstr; } +BSTR SysAllocStringLen(const OLECHAR *sz, UINT len) +{ + int realLen = sizeof(UINT) + len * sizeof(OLECHAR) + sizeof(OLECHAR); + void *p = AllocateForBSTR(realLen); + if (p == 0) + return 0; + *(UINT *)p = len * sizeof(OLECHAR); + BSTR bstr = (BSTR)((UINT *)p + 1); + if (sz) + { + memcpy(bstr, sz, len * sizeof(OLECHAR)); + bstr[len] = 0; + } + return bstr; +} + BSTR SysAllocString(const OLECHAR *sz) { if (sz == 0) @@ -45,9 +61,9 @@ BSTR SysAllocString(const OLECHAR *sz) void *p = AllocateForBSTR(len + sizeof(UINT)); if (p == 0) return 0; - *(UINT *)p = strLen; + *(UINT *)p = strLen * sizeof(OLECHAR); BSTR bstr = (BSTR)((UINT *)p + 1); - memmove(bstr, sz, len); + memcpy(bstr, sz, len); return bstr; } @@ -77,7 +93,7 @@ HRESULT VariantClear(VARIANTARG *prop) return S_OK; } -HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src) +HRESULT VariantCopy(VARIANTARG *dest, const VARIANTARG *src) { HRESULT res = ::VariantClear(dest); if (res != S_OK) diff --git a/CPP/Common/MyWindows.h b/CPP/Common/MyWindows.h old mode 100755 new mode 100644 index 780e1f5d..139a4e8b --- a/CPP/Common/MyWindows.h +++ b/CPP/Common/MyWindows.h @@ -7,6 +7,11 @@ #include +#ifdef UNDER_CE + #undef VARIANT_TRUE + #define VARIANT_TRUE ((VARIANT_BOOL)-1) +#endif + #else #include // for wchar_t @@ -14,6 +19,8 @@ #include "MyGuidDef.h" +#define WINAPI + typedef char CHAR; typedef unsigned char UCHAR; @@ -145,8 +152,6 @@ typedef WORD PROPVAR_PAD1; typedef WORD PROPVAR_PAD2; typedef WORD PROPVAR_PAD3; -#ifdef __cplusplus - typedef struct tagPROPVARIANT { VARTYPE vt; @@ -177,7 +182,7 @@ typedef tagVARIANT VARIANT; typedef VARIANT VARIANTARG; MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop); -MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src); +MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, const VARIANTARG *src); typedef struct tagSTATPROPSTG { @@ -186,9 +191,8 @@ typedef struct tagSTATPROPSTG VARTYPE vt; } STATPROPSTG; -#endif - MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len); +MY_EXTERN_C BSTR SysAllocStringLen(const OLECHAR *sz, UINT len); MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz); MY_EXTERN_C void SysFreeString(BSTR bstr); MY_EXTERN_C UINT SysStringByteLen(BSTR bstr); @@ -199,6 +203,7 @@ MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2); #define CP_ACP 0 #define CP_OEMCP 1 +#define CP_UTF8 65001 typedef enum tagSTREAM_SEEK { diff --git a/CPP/Common/MyXml.cpp b/CPP/Common/MyXml.cpp old mode 100755 new mode 100644 index 8aa9ce8c..31e7b3df --- a/CPP/Common/MyXml.cpp +++ b/CPP/Common/MyXml.cpp @@ -18,52 +18,19 @@ static bool IsSpaceChar(char c) return (c == ' ' || c == '\t' || c == 0x0D || c == 0x0A); } -#define SKIP_SPACES(s, pos) while (IsSpaceChar(s[pos])) pos++; +#define SKIP_SPACES(s) while (IsSpaceChar(*s)) s++; -static bool ReadProperty(const AString &s, int &pos, CXmlProp &prop) +int CXmlItem::FindProp(const AString &propName) const { - 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++) + FOR_VECTOR (i, Props) if (Props[i].Name == propName) return i; return -1; } -AString CXmlItem::GetPropertyValue(const AString &propName) const +AString CXmlItem::GetPropVal(const AString &propName) const { - int index = FindProperty(propName); + int index = FindProp(propName); if (index >= 0) return Props[index].Value; return AString(); @@ -76,7 +43,7 @@ bool CXmlItem::IsTagged(const AString &tag) const int CXmlItem::FindSubTag(const AString &tag) const { - for (int i = 0; i < SubItems.Size(); i++) + FOR_VECTOR (i, SubItems) if (SubItems[i].IsTagged(tag)) return i; return -1; @@ -93,6 +60,17 @@ AString CXmlItem::GetSubString() const return AString(); } +const AString * CXmlItem::GetSubStringPtr() const +{ + if (SubItems.Size() == 1) + { + const CXmlItem &item = SubItems[0]; + if (!item.IsTag) + return &item.Name; + } + return NULL; +} + AString CXmlItem::GetSubStringForTag(const AString &tag) const { int index = FindSubTag(tag); @@ -101,100 +79,169 @@ AString CXmlItem::GetSubStringForTag(const AString &tag) const return AString(); } -bool CXmlItem::ParseItems(const AString &s, int &pos, int numAllowedLevels) +const char * CXmlItem::ParseItem(const char *s, int numAllowedLevels) { - if (numAllowedLevels == 0) - return false; - SubItems.Clear(); - AString finishString = "'); + s++; + // SKIP_SPACES(s); + if (*s != '>') + return NULL; + return s + 1; } - if (s[pos] == '>') + if (*s == '>') { - if (!ParseItems(s, ++pos, numAllowedLevels)) - return false; - AString finishString = AString(""); - if (s.Mid(pos, finishString.Length()) != finishString) - return false; - pos += finishString.Length(); - return true; + s++; + if (numAllowedLevels == 0) + return NULL; + SubItems.Clear(); + for (;;) + { + SKIP_SPACES(s); + if (s[0] == '<' && s[1] == '/') + break; + CXmlItem &item = SubItems.AddNew(); + s = item.ParseItem(s, numAllowedLevels - 1); + if (!s) + return NULL; + } + + s += 2; + unsigned len = Name.Len(); + for (unsigned i = 0; i < len; i++) + if (s[i] != Name[i]) + return NULL; + s += len; + if (s[0] != '>') + return NULL; + return s + 1; } - if (posTemp == pos) - return false; + if (beg == s) + return NULL; - CXmlProp prop; - if (!ReadProperty(s, pos, prop)) - return false; - Props.Add(prop); - posTemp = pos; + // ReadProperty + CXmlProp &prop = Props.AddNew(); + + beg = s; + for (;; s++) + { + char c = *s; + if (!IsValidChar(c)) + break; + } + if (s == beg) + return NULL; + prop.Name.SetFrom(beg, (unsigned)(s - beg)); + + SKIP_SPACES(s); + if (*s != '=') + return NULL; + s++; + SKIP_SPACES(s); + if (*s != '\"') + return NULL; + s++; + + beg = s; + for (;;) + { + char c = *s; + if (c == 0) + return NULL; + if (c == '\"') + break; + s++; + } + prop.Value.SetFrom(beg, (unsigned)(s - beg)); + s++; } } -static bool SkipHeader(const AString &s, int &pos, const AString &startString, const AString &endString) +static bool SkipHeader(const AString &s, int &pos, const char *startString, const char *endString) { - SKIP_SPACES(s, pos); - if (s.Mid(pos, startString.Length()) == startString) + while (IsSpaceChar(s[pos])) + pos++; + if (IsString1PrefixedByString2(s.Ptr(pos), startString)) { - pos = s.Find(endString, pos); + const AString es = endString; + pos = s.Find(es, pos); if (pos < 0) return false; - pos += endString.Length(); - SKIP_SPACES(s, pos); + pos += es.Len(); } return true; } +void CXmlItem::AppendTo(AString &s) const +{ + if (IsTag) + s += '<'; + s += Name; + if (IsTag) + { + FOR_VECTOR (i, Props) + { + const CXmlProp &prop = Props[i]; + s += ' '; + s += prop.Name; + s += '='; + s += '\"'; + s += prop.Value; + s += '\"'; + } + s += '>'; + } + FOR_VECTOR (i, SubItems) + { + const CXmlItem &item = SubItems[i]; + if (i != 0 && !SubItems[i - 1].IsTag) + s += ' '; + item.AppendTo(s); + } + if (IsTag) + { + s += '<'; + s += '/'; + s += Name; + s += '>'; + } +} + bool CXml::Parse(const AString &s) { int pos = 0; @@ -202,8 +249,14 @@ bool CXml::Parse(const AString &s) return false; if (!SkipHeader(s, pos, "")) return false; - if (!Root.ParseItem(s, pos, 1000)) + const char *ptr = Root.ParseItem(s.Ptr(pos), 1000); + if (!ptr || !Root.IsTag) return false; - SKIP_SPACES(s, pos); - return (pos == s.Length() && Root.IsTag); + SKIP_SPACES(ptr); + return *ptr == 0; +} + +void CXml::AppendTo(AString &s) const +{ + Root.AppendTo(s); } diff --git a/CPP/Common/MyXml.h b/CPP/Common/MyXml.h old mode 100755 new mode 100644 index c6e8829a..ae3663c3 --- a/CPP/Common/MyXml.h +++ b/CPP/Common/MyXml.h @@ -1,7 +1,7 @@ // MyXml.h -#ifndef __MYXML_H -#define __MYXML_H +#ifndef __MY_XML_H +#define __MY_XML_H #include "MyString.h" @@ -13,28 +13,31 @@ struct CXmlProp 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; + const char * ParseItem(const char *s, int numAllowedLevels); + + bool IsTagged(const AString &tag) const throw(); + int FindProp(const AString &propName) const throw(); + AString GetPropVal(const AString &propName) const; AString GetSubString() const; - int FindSubTag(const AString &tag) const; + const AString * GetSubStringPtr() const throw(); + int FindSubTag(const AString &tag) const throw(); AString GetSubStringForTag(const AString &tag) const; + + void AppendTo(AString &s) const; }; struct CXml { CXmlItem Root; + bool Parse(const AString &s); + void AppendTo(AString &s) const; }; #endif diff --git a/CPP/Common/NewHandler.cpp b/CPP/Common/NewHandler.cpp old mode 100755 new mode 100644 index aad6e7d1..410f24e9 --- a/CPP/Common/NewHandler.cpp +++ b/CPP/Common/NewHandler.cpp @@ -11,6 +11,32 @@ #ifndef DEBUG_MEMORY_LEAK #ifdef _WIN32 + +/* +void * my_new(size_t size) +{ + // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); + void *p = ::malloc(size); + if (p == 0) + throw CNewException(); + return p; +} + +void my_delete(void *p) throw() +{ + // if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p); + ::free(p); +} + +void * my_Realloc(void *p, size_t newSize, size_t oldSize) +{ + void *newBuf = my_new(newSize); + memcpy(newBuf, p, oldSize); + my_delete(p); + return newBuf; +} +*/ + void * #ifdef _MSC_VER __cdecl @@ -30,18 +56,42 @@ __cdecl #endif operator delete(void *p) throw() { - /* + // if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p); + ::free(p); +} + +/* +void * +#ifdef _MSC_VER +__cdecl +#endif +operator new[](size_t size) +{ + // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); + void *p = ::malloc(size); if (p == 0) - return; - ::HeapFree(::GetProcessHeap(), 0, p); - */ + 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) +#include + +// #pragma init_seg(lib) const int kDebugSize = 1000000; static void *a[kDebugSize]; static int index = 0; @@ -51,10 +101,6 @@ 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; diff --git a/CPP/Common/NewHandler.h b/CPP/Common/NewHandler.h old mode 100755 new mode 100644 index 215ba05f..e3e7422c --- a/CPP/Common/NewHandler.h +++ b/CPP/Common/NewHandler.h @@ -1,16 +1,68 @@ // Common/NewHandler.h -#ifndef __COMMON_NEWHANDLER_H -#define __COMMON_NEWHANDLER_H +#ifndef __COMMON_NEW_HANDLER_H +#define __COMMON_NEW_HANDLER_H + +/* +This file must be included before any code that uses operators "delete" or "new". +Also you must compile and link "NewHandler.cpp", if you use MSVC 6.0. +The operator "new" in MSVC 6.0 doesn't throw exception "bad_alloc". +So we define another version of operator "new" that throws "CNewException" on failure. + +If you use compiler that throws exception in "new" operator (GCC or new version of MSVC), +you can compile without "NewHandler.cpp". So standard exception "bad_alloc" will be used. + +It's still allowed to use redefined version of operator "new" from "NewHandler.cpp" +with any compiler. 7-Zip's code can work with "bad_alloc" and "CNewException" exceptions. +But if you use some additional code (outside of 7-Zip's code), you must check +that redefined version of operator "new" (that throws CNewException) is not +problem for your code. + +Also we declare delete(void *p) throw() that creates smaller code. +*/ + class CNewException {}; +#ifdef WIN32 +// We can compile my_new and my_delete with _fastcall +/* +void * my_new(size_t size); +void my_delete(void *p) throw(); +// void * my_Realloc(void *p, size_t newSize, size_t oldSize); +*/ +#endif + #ifdef _WIN32 + +void * +#ifdef _MSC_VER +__cdecl +#endif +operator new(size_t size); + void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw(); + +#endif + +/* +#ifdef _WIN32 +void * +#ifdef _MSC_VER +__cdecl +#endif +operator new[](size_t size); + +void +#ifdef _MSC_VER +__cdecl +#endif +operator delete[](void *p) throw(); #endif +*/ #endif diff --git a/CPP/Common/Random.cpp b/CPP/Common/Random.cpp old mode 100755 new mode 100644 diff --git a/CPP/Common/Random.h b/CPP/Common/Random.h old mode 100755 new mode 100644 diff --git a/CPP/Common/Sha256Reg.cpp b/CPP/Common/Sha256Reg.cpp new file mode 100644 index 00000000..6adb3cdc --- /dev/null +++ b/CPP/Common/Sha256Reg.cpp @@ -0,0 +1,52 @@ +// Sha256Reg.cpp + +#include "StdAfx.h" + +#include "../../C/Sha256.h" + +#include "../Common/MyCom.h" + +#include "../7zip/ICoder.h" +#include "../7zip/Common/RegisterCodec.h" + +class CSha256Hasher: + public IHasher, + public CMyUnknownImp +{ + CSha256 _sha; +public: + CSha256Hasher() { Init(); }; + + MY_UNKNOWN_IMP + + STDMETHOD_(void, Init)(); + STDMETHOD_(void, Update)(const void *data, UInt32 size); + STDMETHOD_(void, Final)(Byte *digest); + STDMETHOD_(UInt32, GetDigestSize)(); +}; + +STDMETHODIMP_(void) CSha256Hasher::Init() +{ + Sha256_Init(&_sha); +} + +STDMETHODIMP_(void) CSha256Hasher::Update(const void *data, UInt32 size) +{ + Sha256_Update(&_sha, (const Byte *)data, size); +} + +STDMETHODIMP_(void) CSha256Hasher::Final(Byte *digest) +{ + Sha256_Final(&_sha, digest); +} + +STDMETHODIMP_(UInt32) CSha256Hasher::GetDigestSize() +{ + return SHA256_DIGEST_SIZE; +} + +static IHasher *CreateHasher() { return new CSha256Hasher; } + +static CHasherInfo g_HasherInfo = { CreateHasher, 0xA, L"SHA256", SHA256_DIGEST_SIZE }; + +REGISTER_HASHER(Sha256) diff --git a/CPP/Common/StdAfx.h b/CPP/Common/StdAfx.h old mode 100755 new mode 100644 index b8ba1d5c..420f5c32 --- a/CPP/Common/StdAfx.h +++ b/CPP/Common/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -// #include "MyWindows.h" -#include "NewHandler.h" +#include "Common.h" #endif diff --git a/CPP/Common/StdInStream.cpp b/CPP/Common/StdInStream.cpp old mode 100755 new mode 100644 index f3dcb85f..2d28c735 --- a/CPP/Common/StdInStream.cpp +++ b/CPP/Common/StdInStream.cpp @@ -8,12 +8,6 @@ #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"; @@ -42,11 +36,6 @@ bool CStdInStream::Close() return !_streamIsOpen; } -CStdInStream::~CStdInStream() -{ - Close(); -} - AString CStdInStream::ScanStringUntilNewLine(bool allowEOF) { AString s; @@ -59,8 +48,8 @@ AString CStdInStream::ScanStringUntilNewLine(bool allowEOF) break; throw kEOFMessage; } - char c = char(intChar); - if (c == kIllegalChar) + char c = (char)intChar; + if (c == 0) throw kIllegalCharMessage; if (c == kNewLineChar) break; @@ -88,7 +77,7 @@ void CStdInStream::ReadToString(AString &resultString) resultString.Empty(); int c; while ((c = GetChar()) != EOF) - resultString += char(c); + resultString += (char)c; } bool CStdInStream::Eof() @@ -103,5 +92,3 @@ int CStdInStream::GetChar() throw kReadErrorMessage; return c; } - - diff --git a/CPP/Common/StdInStream.h b/CPP/Common/StdInStream.h old mode 100755 new mode 100644 index 0d182cc3..6d9ed670 --- a/CPP/Common/StdInStream.h +++ b/CPP/Common/StdInStream.h @@ -1,29 +1,30 @@ // Common/StdInStream.h -#ifndef __COMMON_STDINSTREAM_H -#define __COMMON_STDINSTREAM_H +#ifndef __COMMON_STD_IN_STREAM_H +#define __COMMON_STD_IN_STREAM_H #include #include "MyString.h" -#include "Types.h" +#include "MyTypes.h" class CStdInStream { - bool _streamIsOpen; FILE *_stream; + bool _streamIsOpen; public: - CStdInStream(): _streamIsOpen(false) {}; - CStdInStream(FILE *stream): _streamIsOpen(false), _stream(stream) {}; - ~CStdInStream(); - bool Open(LPCTSTR fileName); - bool Close(); + CStdInStream(): _stream(0), _streamIsOpen(false) {}; + CStdInStream(FILE *stream): _stream(stream), _streamIsOpen(false) {}; + ~CStdInStream() { Close(); } + + bool Open(LPCTSTR fileName) throw(); + bool Close() throw(); AString ScanStringUntilNewLine(bool allowEOF = false); void ReadToString(AString &resultString); UString ScanUStringUntilNewLine(); - bool Eof(); + bool Eof() throw(); int GetChar(); }; diff --git a/CPP/Common/StdOutStream.cpp b/CPP/Common/StdOutStream.cpp old mode 100755 new mode 100644 index 061a7606..1d6d81a4 --- a/CPP/Common/StdOutStream.cpp +++ b/CPP/Common/StdOutStream.cpp @@ -9,19 +9,14 @@ #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); +CStdOutStream g_StdOut(stdout); +CStdOutStream g_StdErr(stderr); bool CStdOutStream::Open(const char *fileName) { @@ -47,14 +42,9 @@ bool CStdOutStream::Flush() return (fflush(_stream) == 0); } -CStdOutStream::~CStdOutStream () -{ - Close(); -} - -CStdOutStream & CStdOutStream::operator<<(CStdOutStream & (*aFunction)(CStdOutStream &)) +CStdOutStream & CStdOutStream::operator<<(CStdOutStream & (*func)(CStdOutStream &)) { - (*aFunction)(*this); + (*func)(*this); return *this; } @@ -83,22 +73,48 @@ CStdOutStream & CStdOutStream::operator<<(const wchar_t *s) return *this; } +void CStdOutStream::PrintUString(const UString &s, AString &temp) +{ + int codePage = g_CodePage; + if (codePage == -1) + codePage = CP_OEMCP; + if (codePage == CP_UTF8) + ConvertUnicodeToUTF8(s, temp); + else + UnicodeStringToMultiByte2(temp, s, (UINT)codePage); + *this << (const char *)temp; +} + CStdOutStream & CStdOutStream::operator<<(char c) { fputc(c, _stream); return *this; } -CStdOutStream & CStdOutStream::operator<<(int number) +CStdOutStream & CStdOutStream::operator<<(Int32 number) +{ + char s[32]; + ConvertInt64ToString(number, s); + return operator<<(s); +} + +CStdOutStream & CStdOutStream::operator<<(Int64 number) +{ + char s[32]; + ConvertInt64ToString(number, s); + return operator<<(s); +} + +CStdOutStream & CStdOutStream::operator<<(UInt32 number) { - char textString[32]; - ConvertInt64ToString(number, textString); - return operator<<(textString); + char s[16]; + ConvertUInt32ToString(number, s); + return operator<<(s); } CStdOutStream & CStdOutStream::operator<<(UInt64 number) { - char textString[32]; - ConvertUInt64ToString(number, textString); - return operator<<(textString); + char s[32]; + ConvertUInt64ToString(number, s); + return operator<<(s); } diff --git a/CPP/Common/StdOutStream.h b/CPP/Common/StdOutStream.h old mode 100755 new mode 100644 index b0b2c615..42f43938 --- a/CPP/Common/StdOutStream.h +++ b/CPP/Common/StdOutStream.h @@ -1,33 +1,40 @@ // Common/StdOutStream.h -#ifndef __COMMON_STDOUTSTREAM_H -#define __COMMON_STDOUTSTREAM_H +#ifndef __COMMON_STD_OUT_STREAM_H +#define __COMMON_STD_OUT_STREAM_H #include -#include "Types.h" +#include "MyString.h" +#include "MyTypes.h" class CStdOutStream { - bool _streamIsOpen; FILE *_stream; + bool _streamIsOpen; public: - CStdOutStream (): _streamIsOpen(false), _stream(0) {}; - CStdOutStream (FILE *stream): _streamIsOpen(false), _stream(stream) {}; - ~CStdOutStream (); + CStdOutStream(): _stream(0), _streamIsOpen(false) {}; + CStdOutStream(FILE *stream): _stream(stream), _streamIsOpen(false) {}; + ~CStdOutStream() { Close(); } + 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); + bool Open(const char *fileName) throw(); + bool Close() throw(); + bool Flush() throw(); + + CStdOutStream & operator<<(CStdOutStream & (* func)(CStdOutStream &)); + CStdOutStream & operator<<(const char *s) throw(); + CStdOutStream & operator<<(char c) throw(); + CStdOutStream & operator<<(Int32 number) throw(); + CStdOutStream & operator<<(Int64 number) throw(); + CStdOutStream & operator<<(UInt32 number) throw(); + CStdOutStream & operator<<(UInt64 number) throw(); + + CStdOutStream & operator<<(const wchar_t *s); + void PrintUString(const UString &s, AString &temp); }; -CStdOutStream & endl(CStdOutStream & outStream); +CStdOutStream & endl(CStdOutStream & outStream) throw(); extern CStdOutStream g_StdOut; extern CStdOutStream g_StdErr; diff --git a/CPP/Common/StringConvert.cpp b/CPP/Common/StringConvert.cpp old mode 100755 new mode 100644 index 681895b7..0443a06c --- a/CPP/Common/StringConvert.cpp +++ b/CPP/Common/StringConvert.cpp @@ -15,8 +15,8 @@ UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) if (!srcString.IsEmpty()) { int numChars = MultiByteToWideChar(codePage, 0, srcString, - srcString.Length(), resultString.GetBuffer(srcString.Length()), - srcString.Length() + 1); + srcString.Len(), resultString.GetBuffer(srcString.Len()), + srcString.Len() + 1); if (numChars == 0) throw 282228; resultString.ReleaseBuffer(numChars); @@ -24,15 +24,83 @@ UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) return resultString; } +void MultiByteToUnicodeString2(UString &dest, const AString &srcString, UINT codePage) +{ + dest.Empty(); + if (!srcString.IsEmpty()) + { + wchar_t *destBuf = dest.GetBuffer(srcString.Len()); + const char *sp = (const char *)srcString; + unsigned i; + for (i = 0;;) + { + char c = sp[i]; + if ((Byte)c >= 0x80 || c == 0) + break; + destBuf[i++] = (wchar_t)c; + } + + if (i != srcString.Len()) + { + unsigned numChars = MultiByteToWideChar(codePage, 0, sp + i, + srcString.Len() - i, destBuf + i, + srcString.Len() + 1 - i); + if (numChars == 0) + throw 282228; + i += numChars; + } + dest.ReleaseBuffer(i); + } +} + +void UnicodeStringToMultiByte2(AString &dest, const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed) +{ + dest.Empty(); + defaultCharWasUsed = false; + if (!s.IsEmpty()) + { + unsigned numRequiredBytes = s.Len() * 2; + char *destBuf = dest.GetBuffer(numRequiredBytes); + unsigned i; + const wchar_t *sp = (const wchar_t *)s; + for (i = 0;;) + { + wchar_t c = sp[i]; + if (c >= 0x80 || c == 0) + break; + destBuf[i++] = (char)c; + } + defaultCharWasUsed = false; + if (i != s.Len()) + { + BOOL defUsed; + unsigned numChars = WideCharToMultiByte(codePage, 0, sp + i, s.Len() - i, + destBuf + i, numRequiredBytes + 1 - i, + &defaultChar, &defUsed); + defaultCharWasUsed = (defUsed != FALSE); + if (numChars == 0) + throw 282229; + i += numChars; + } + dest.ReleaseBuffer(i); + } +} + +void UnicodeStringToMultiByte2(AString &dest, const UString &srcString, UINT codePage) +{ + bool defaultCharWasUsed; + UnicodeStringToMultiByte2(dest, srcString, codePage, '_', defaultCharWasUsed); +} + AString UnicodeStringToMultiByte(const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed) { AString dest; defaultCharWasUsed = false; if (!s.IsEmpty()) { - int numRequiredBytes = s.Length() * 2; + unsigned numRequiredBytes = s.Len() * 2; BOOL defUsed; - int numChars = WideCharToMultiByte(codePage, 0, s, s.Length(), + int numChars = WideCharToMultiByte(codePage, 0, s, s.Len(), dest.GetBuffer(numRequiredBytes), numRequiredBytes + 1, &defaultChar, &defUsed); defaultCharWasUsed = (defUsed != FALSE); @@ -53,7 +121,7 @@ AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) AString SystemStringToOemString(const CSysString &srcString) { AString result; - CharToOem(srcString, result.GetBuffer(srcString.Length() * 2)); + CharToOem(srcString, result.GetBuffer(srcString.Len() * 2)); result.ReleaseBuffer(); return result; } @@ -64,12 +132,12 @@ AString SystemStringToOemString(const CSysString &srcString) UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; - for (int i = 0; i < srcString.Length(); i++) - resultString += wchar_t(srcString[i]); + for (unsigned i = 0; i < srcString.Len(); i++) + resultString += (wchar_t)srcString[i]; /* if (!srcString.IsEmpty()) { - int numChars = mbstowcs(resultString.GetBuffer(srcString.Length()), srcString, srcString.Length() + 1); + int numChars = mbstowcs(resultString.GetBuffer(srcString.Len()), srcString, srcString.Len() + 1); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } @@ -80,12 +148,12 @@ UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { AString resultString; - for (int i = 0; i < srcString.Length(); i++) - resultString += char(srcString[i]); + for (unsigned i = 0; i < srcString.Len(); i++) + resultString += (char)srcString[i]; /* if (!srcString.IsEmpty()) { - int numRequiredBytes = srcString.Length() * 6 + 1; + int numRequiredBytes = srcString.Len() * 6 + 1; int numChars = wcstombs(resultString.GetBuffer(numRequiredBytes), srcString, numRequiredBytes); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); diff --git a/CPP/Common/StringConvert.h b/CPP/Common/StringConvert.h old mode 100755 new mode 100644 index cd737bec..8eea72ef --- a/CPP/Common/StringConvert.h +++ b/CPP/Common/StringConvert.h @@ -3,15 +3,19 @@ #ifndef __COMMON_STRING_CONVERT_H #define __COMMON_STRING_CONVERT_H -#include "MyWindows.h" #include "MyString.h" -#include "Types.h" +#include "MyWindows.h" UString MultiByteToUnicodeString(const AString &srcString, UINT codePage = CP_ACP); + +// optimized versions that work faster for ASCII strings +void MultiByteToUnicodeString2(UString &dest, const AString &srcString, UINT codePage = CP_ACP); +void UnicodeStringToMultiByte2(AString &dest, const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed); +void UnicodeStringToMultiByte2(AString &dest, const UString &srcString, UINT codePage); + 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) diff --git a/CPP/Common/StringToInt.cpp b/CPP/Common/StringToInt.cpp old mode 100755 new mode 100644 index 15474a42..ea59c0fa --- a/CPP/Common/StringToInt.cpp +++ b/CPP/Common/StringToInt.cpp @@ -4,94 +4,140 @@ #include "StringToInt.h" -UInt64 ConvertStringToUInt64(const char *s, const char **end) +static const UInt32 k_UInt32_max = 0xFFFFFFFF; +static const UInt64 k_UInt64_max = 0xFFFFFFFFFFFFFFFF; + +#define CONVERT_STRING_TO_UINT_FUNC(uintType, charType) \ + uintType ConvertStringTo ## uintType(const charType *s, const charType **end) { \ + if (end) *end = s; \ + uintType res = 0; \ + for (;; s++) { \ + charType c = *s; \ + if (c < '0' || c > '9') { if (end) *end = s; return res; } \ + if (res > (k_ ## uintType ## _max) / 10) return 0; \ + res *= 10; \ + unsigned v = (c - '0'); \ + if (res > (k_ ## uintType ## _max) - v) return 0; \ + res += v; }} + +CONVERT_STRING_TO_UINT_FUNC(UInt32, char) +CONVERT_STRING_TO_UINT_FUNC(UInt32, wchar_t) +CONVERT_STRING_TO_UINT_FUNC(UInt64, char) +CONVERT_STRING_TO_UINT_FUNC(UInt64, wchar_t) + +Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) +{ + if (end) + *end = s; + const wchar_t *s2 = s; + if (*s == '-') + s2++; + if (*s2 == 0) + return 0; + const wchar_t *end2; + UInt32 res = ConvertStringToUInt32(s2, &end2); + if (*s == '-') + { + if (res > ((UInt32)1 << (32 - 1))) + return 0; + } + else if ((res & ((UInt32)1 << (32 - 1))) != 0) + return 0; + if (end) + *end = end2; + if (*s == '-') + return -(Int32)res; + return (Int32)res; +} + +UInt32 ConvertOctStringToUInt32(const char *s, const char **end) { - UInt64 result = 0; - for (;;) + if (end) + *end = s; + UInt32 res = 0; + for (;; s++) { char c = *s; - if (c < '0' || c > '9') + if (c < '0' || c > '7') { - if (end != NULL) + if (end) *end = s; - return result; + return res; } - result *= 10; - result += (c - '0'); - s++; + if ((res & (UInt32)7 << (32 - 3)) != 0) + return 0; + res <<= 3; + res |= (unsigned)(c - '0'); } } UInt64 ConvertOctStringToUInt64(const char *s, const char **end) { - UInt64 result = 0; - for (;;) + if (end) + *end = s; + UInt64 res = 0; + for (;; s++) { char c = *s; if (c < '0' || c > '7') { - if (end != NULL) + if (end) *end = s; - return result; + return res; } - result <<= 3; - result += (c - '0'); - s++; + if ((res & (UInt64)7 << (64 - 3)) != 0) + return 0; + res <<= 3; + res |= (unsigned)(c - '0'); } } -UInt64 ConvertHexStringToUInt64(const char *s, const char **end) +UInt32 ConvertHexStringToUInt32(const char *s, const char **end) { - UInt64 result = 0; - for (;;) + if (end) + *end = s; + UInt32 res = 0; + for (;; s++) { char c = *s; - UInt32 v; + unsigned v; if (c >= '0' && c <= '9') v = (c - '0'); else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A'); else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a'); else { - if (end != NULL) + if (end) *end = s; - return result; + return res; } - result <<= 4; - result |= v; - s++; + if ((res & (UInt32)0xF << (32 - 4)) != 0) + return 0; + res <<= 4; + res |= v; } } - -UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) +UInt64 ConvertHexStringToUInt64(const char *s, const char **end) { - UInt64 result = 0; - for (;;) + if (end) + *end = s; + UInt64 res = 0; + for (;; s++) { - wchar_t c = *s; - if (c < '0' || c > '9') + char c = *s; + unsigned v; + if (c >= '0' && c <= '9') v = (c - '0'); + else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A'); + else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a'); + else { - if (end != NULL) + if (end) *end = s; - return result; + return res; } - result *= 10; - result += (c - '0'); - s++; + if ((res & (UInt64)0xF << (64 - 4)) != 0) + return 0; + res <<= 4; + res |= v; } } - - -Int64 ConvertStringToInt64(const char *s, const char **end) -{ - if (*s == '-') - return -(Int64)ConvertStringToUInt64(s + 1, end); - return ConvertStringToUInt64(s, end); -} - -Int64 ConvertStringToInt64(const wchar_t *s, const wchar_t **end) -{ - if (*s == L'-') - return -(Int64)ConvertStringToUInt64(s + 1, end); - return ConvertStringToUInt64(s, end); -} diff --git a/CPP/Common/StringToInt.h b/CPP/Common/StringToInt.h old mode 100755 new mode 100644 index cd99f17e..5c5d7d7f --- a/CPP/Common/StringToInt.h +++ b/CPP/Common/StringToInt.h @@ -3,14 +3,19 @@ #ifndef __COMMON_STRING_TO_INT_H #define __COMMON_STRING_TO_INT_H -#include "Types.h" +#include "MyTypes.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); +UInt32 ConvertStringToUInt32(const char *s, const char **end) throw(); +UInt64 ConvertStringToUInt64(const char *s, const char **end) throw(); +UInt32 ConvertStringToUInt32(const wchar_t *s, const wchar_t **end) throw(); +UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) throw(); -Int64 ConvertStringToInt64(const char *s, const char **end); -Int64 ConvertStringToInt64(const wchar_t *s, const wchar_t **end); +Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw(); + +UInt32 ConvertOctStringToUInt32(const char *s, const char **end) throw(); +UInt64 ConvertOctStringToUInt64(const char *s, const char **end) throw(); + +UInt32 ConvertHexStringToUInt32(const char *s, const char **end) throw(); +UInt64 ConvertHexStringToUInt64(const char *s, const char **end) throw(); #endif diff --git a/CPP/Common/TextConfig.cpp b/CPP/Common/TextConfig.cpp old mode 100755 new mode 100644 index 34fedeb8..ad368791 --- a/CPP/Common/TextConfig.cpp +++ b/CPP/Common/TextConfig.cpp @@ -3,22 +3,19 @@ #include "StdAfx.h" #include "TextConfig.h" - -#include "Defs.h" #include "UTFConvert.h" -static bool IsDelimitChar(char c) +static inline bool IsDelimitChar(char c) { - return (c == ' ' || c == 0x0A || c == 0x0D || - c == '\0' || c == '\t'); + return (c == ' ' || c == 0x0A || c == 0x0D || c == '\0' || c == '\t'); } -static AString GetIDString(const char *string, int &finishPos) +static AString GetIDString(const char *s, unsigned &finishPos) { AString result; for (finishPos = 0; ; finishPos++) { - char c = string[finishPos]; + char c = s[finishPos]; if (IsDelimitChar(c) || c == '=') break; result += c; @@ -26,89 +23,78 @@ static AString GetIDString(const char *string, int &finishPos) return result; } -static bool WaitNextLine(const AString &string, int &pos) +static bool WaitNextLine(const AString &s, unsigned &pos) { - for (;pos < string.Length(); pos++) - if (string[pos] == 0x0A) + for (; pos < s.Len(); pos++) + if (s[pos] == 0x0A) return true; return false; } -static bool SkipSpaces(const AString &string, int &pos) +static bool SkipSpaces(const AString &s, unsigned &pos) { - for (;pos < string.Length(); pos++) + for (; pos < s.Len(); pos++) { - char c = string[pos]; + char c = s[pos]; if (!IsDelimitChar(c)) { if (c != ';') return true; - if (!WaitNextLine(string, pos)) + if (!WaitNextLine(s, pos)) return false; } } return false; } -bool GetTextConfig(const AString &string, CObjectVector &pairs) +bool GetTextConfig(const AString &s, CObjectVector &pairs) { pairs.Clear(); - int pos = 0; + unsigned pos = 0; ///////////////////// // read strings for (;;) { - if (!SkipSpaces(string, pos)) + if (!SkipSpaces(s, pos)) break; CTextConfigPair pair; - int finishPos; - AString temp = GetIDString(((const char *)string) + pos, finishPos); + unsigned finishPos; + AString temp = GetIDString(((const char *)s) + pos, finishPos); if (!ConvertUTF8ToUnicode(temp, pair.ID)) return false; if (finishPos == 0) return false; pos += finishPos; - if (!SkipSpaces(string, pos)) + if (!SkipSpaces(s, pos)) return false; - if (string[pos] != '=') + if (s[pos] != '=') return false; pos++; - if (!SkipSpaces(string, pos)) + if (!SkipSpaces(s, pos)) return false; - if (string[pos] != '\"') + if (s[pos] != '\"') return false; pos++; AString message; for (;;) { - if (pos >= string.Length()) + if (pos >= s.Len()) return false; - char c = string[pos++]; + char c = s[pos++]; if (c == '\"') break; if (c == '\\') { - char c = string[pos++]; + char c = s[pos++]; switch(c) { - case 'n': - message += '\n'; - break; - case 't': - message += '\t'; - break; - case '\\': - message += '\\'; - break; - case '\"': - message += '\"'; - break; - default: - message += '\\'; - message += c; - break; + case 'n': message += '\n'; break; + case 't': message += '\t'; break; + case '\\': message += '\\'; break; + case '\"': message += '\"'; break; + default: message += '\\'; message += c; break; } } else @@ -123,8 +109,8 @@ bool GetTextConfig(const AString &string, CObjectVector &pairs) int FindTextConfigItem(const CObjectVector &pairs, const UString &id) { - for (int i = 0; i < pairs.Size(); i++) - if (pairs[i].ID.Compare(id) == 0) + FOR_VECTOR (i, pairs) + if (pairs[i].ID == id) return i; return -1; } diff --git a/CPP/Common/TextConfig.h b/CPP/Common/TextConfig.h old mode 100755 new mode 100644 index a25142a7..cae4f17a --- a/CPP/Common/TextConfig.h +++ b/CPP/Common/TextConfig.h @@ -1,9 +1,8 @@ // Common/TextConfig.h -#ifndef __COMMON_TEXTCONFIG_H -#define __COMMON_TEXTCONFIG_H +#ifndef __COMMON_TEXT_CONFIG_H +#define __COMMON_TEXT_CONFIG_H -#include "MyVector.h" #include "MyString.h" struct CTextConfigPair @@ -14,7 +13,7 @@ struct CTextConfigPair bool GetTextConfig(const AString &text, CObjectVector &pairs); -int FindTextConfigItem(const CObjectVector &pairs, const UString &id); +int FindTextConfigItem(const CObjectVector &pairs, const UString &id) throw(); UString GetTextConfigValue(const CObjectVector &pairs, const UString &id); #endif diff --git a/CPP/Common/Types.h b/CPP/Common/Types.h deleted file mode 100755 index 9365b327..00000000 --- a/CPP/Common/Types.h +++ /dev/null @@ -1,11 +0,0 @@ -// 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 old mode 100755 new mode 100644 index 95362430..c4b9404d --- a/CPP/Common/UTFConvert.cpp +++ b/CPP/Common/UTFConvert.cpp @@ -2,18 +2,53 @@ #include "StdAfx.h" +#include "MyTypes.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) +bool CheckUTF8(const char *src) +{ + for (;;) + { + Byte c; + unsigned numAdds; + c = *src++; + if (c == 0) + return true; + + if (c < 0x80) + continue; + if (c < 0xC0) + return false; + for (numAdds = 1; numAdds < 5; numAdds++) + if (c < kUtf8Limits[numAdds]) + break; + UInt32 value = (c - kUtf8Limits[numAdds - 1]); + + do + { + Byte c2 = *src++; + if (c2 < 0x80 || c2 >= 0xC0) + return false; + value <<= 6; + value |= (c2 - 0x80); + } + while (--numAdds); + + if (value >= 0x110000) + return false; + } +} + + +static Bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, size_t srcLen) throw() { size_t destPos = 0, srcPos = 0; for (;;) { Byte c; - int numAdds; + unsigned numAdds; if (srcPos == srcLen) { *destLen = destPos; @@ -46,7 +81,7 @@ static Bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, size_ value <<= 6; value |= (c2 - 0x80); } - while (--numAdds != 0); + while (--numAdds); if (value < 0x10000) { @@ -124,11 +159,9 @@ 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(); + Utf8_To_Utf16(NULL, &destLen, src, src.Len()); + Bool res = Utf8_To_Utf16(dest.GetBuffer((unsigned)destLen), &destLen, src, src.Len()); + dest.ReleaseBuffer((unsigned)destLen); return res ? true : false; } @@ -136,10 +169,8 @@ 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(); + Utf16_To_Utf8(NULL, &destLen, src, src.Len()); + Bool res = Utf16_To_Utf8(dest.GetBuffer((unsigned)destLen), &destLen, src, src.Len()); + dest.ReleaseBuffer((unsigned)destLen); return res ? true : false; } diff --git a/CPP/Common/UTFConvert.h b/CPP/Common/UTFConvert.h old mode 100755 new mode 100644 index 2a14600d..16b02fe4 --- a/CPP/Common/UTFConvert.h +++ b/CPP/Common/UTFConvert.h @@ -1,10 +1,11 @@ // Common/UTFConvert.h -#ifndef __COMMON_UTFCONVERT_H -#define __COMMON_UTFCONVERT_H +#ifndef __COMMON_UTF_CONVERT_H +#define __COMMON_UTF_CONVERT_H #include "MyString.h" +bool CheckUTF8(const char *src) throw(); bool ConvertUTF8ToUnicode(const AString &utfString, UString &resultString); bool ConvertUnicodeToUTF8(const UString &unicodeString, AString &resultString); diff --git a/CPP/Common/Wildcard.cpp b/CPP/Common/Wildcard.cpp old mode 100755 new mode 100644 index 87d44971..182256ab --- a/CPP/Common/Wildcard.cpp +++ b/CPP/Common/Wildcard.cpp @@ -2,8 +2,6 @@ #include "StdAfx.h" -#include "../../C/Types.h" - #include "Wildcard.h" bool g_CaseSensitive = @@ -13,37 +11,43 @@ bool g_CaseSensitive = 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"\"/:<>\\|"; +bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2) +{ + if (g_CaseSensitive) + { + for (;;) + { + wchar_t c2 = *s2++; if (c2 == 0) return true; + wchar_t c1 = *s1++; + if (MyCharUpper(c1) != + MyCharUpper(c2)) + return false; + } + } + for (;;) + { + wchar_t c2 = *s2++; if (c2 == 0) return true; + wchar_t c1 = *s1++; if (c1 != c2) return false; + } +} -static inline bool IsCharDirLimiter(wchar_t c) +int CompareFileNames(const wchar_t *s1, const wchar_t *s2) { - return ( - #ifdef _WIN32 - c == kDirDelimiter1 || - #endif - c == kDirDelimiter2); + if (g_CaseSensitive) + return wcscmp(s1, s2); + return MyStringCompareNoCase(s1, s2); } -int CompareFileNames(const UString &s1, const UString &s2) +#ifndef USE_UNICODE_FSTRING +int CompareFileNames(const char *s1, const char *s2) { if (g_CaseSensitive) - return s1.Compare(s2); - return s1.CompareNoCase(s2); + return wcscmp(fs2us(s1), fs2us(s2)); + return MyStringCompareNoCase(fs2us(s1), fs2us(s2)); } +#endif // ----------------------------------------- // this function compares name with mask @@ -58,7 +62,7 @@ static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name) wchar_t c = *name; if (m == 0) return (c == 0); - if (m == kAnyCharsChar) + if (m == '*') { if (EnhancedMaskTest(mask + 1, name)) return true; @@ -67,7 +71,7 @@ static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name) } else { - if (m == kAnyCharChar) + if (m == '?') { if (c == 0) return false; @@ -87,61 +91,84 @@ static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name) void SplitPathToParts(const UString &path, UStringVector &pathParts) { pathParts.Clear(); - UString name; - int len = path.Length(); + unsigned len = path.Len(); if (len == 0) return; - for (int i = 0; i < len; i++) - { - wchar_t c = path[i]; - if (IsCharDirLimiter(c)) + UString name; + unsigned prev = 0; + for (unsigned i = 0; i < len; i++) + if (IsCharDirLimiter(path[i])) { + name.SetFrom(path.Ptr(prev), i - prev); pathParts.Add(name); - name.Empty(); + prev = i + 1; } - else - name += c; - } + name.SetFrom(path.Ptr(prev), len - prev); pathParts.Add(name); } -void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name) +void SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name) { - int i; - for (i = path.Length() - 1; i >= 0; i--) - if (IsCharDirLimiter(path[i])) + const wchar_t *start = path; + const wchar_t *p = start + path.Len(); + for (; p != start; p--) + if (IsCharDirLimiter(*(p - 1))) break; - dirPrefix = path.Left(i + 1); - name = path.Mid(i + 1); + dirPrefix.SetFrom(path, (unsigned)(p - start)); + name = p; +} + +void SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &name) +{ + const wchar_t *start = path; + const wchar_t *p = start + path.Len(); + if (p != start) + { + if (IsCharDirLimiter(*(p - 1))) + p--; + for (; p != start; p--) + if (IsCharDirLimiter(*(p - 1))) + break; + } + dirPrefix.SetFrom(path, (unsigned)(p - start)); + name = p; } UString ExtractDirPrefixFromPath(const UString &path) { - int i; - for (i = path.Length() - 1; i >= 0; i--) - if (IsCharDirLimiter(path[i])) + const wchar_t *start = path; + const wchar_t *p = start + path.Len(); + for (; p != start; p--) + if (IsCharDirLimiter(*(p - 1))) break; - return path.Left(i + 1); + return path.Left((unsigned)(p - start)); } UString ExtractFileNameFromPath(const UString &path) { - int i; - for (i = path.Length() - 1; i >= 0; i--) - if (IsCharDirLimiter(path[i])) + const wchar_t *start = path; + const wchar_t *p = start + path.Len(); + for (; p != start; p--) + if (IsCharDirLimiter(*(p - 1))) break; - return path.Mid(i + 1); + return p; } -bool CompareWildCardWithName(const UString &mask, const UString &name) +bool DoesWildcardMatchName(const UString &mask, const UString &name) { return EnhancedMaskTest(mask, name); } -bool DoesNameContainWildCard(const UString &path) +bool DoesNameContainWildcard(const UString &path) { - return (path.FindOneOf(kWildCardCharSet) >= 0); + for (unsigned i = 0; i < path.Len(); i++) + { + wchar_t c = path[i]; + if (c == '*' || c == '?') + return true; + } + return false; } @@ -151,22 +178,36 @@ bool DoesNameContainWildCard(const UString &path) namespace NWildcard { +#ifdef _WIN32 +bool IsDriveColonName(const wchar_t *s) +{ + wchar_t c = s[0]; + return c != 0 && s[1] == ':' && s[2] == 0 && (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'); +} +#endif + /* + M = MaskParts.Size(); N = TestNameParts.Size(); File Dir -ForFile req M<=N [N-M, N) - - nonreq M=N [0, M) - +ForFile rec M<=N [N-M, N) - +!ForDir nonrec M=N [0, M) - -ForDir req M 1) @@ -264,7 +340,7 @@ bool CCensorNode::AreThereIncludeItems() const { if (IncludeItems.Size() > 0) return true; - for (int i = 0; i < SubNodes.Size(); i++) + FOR_VECTOR (i, SubNodes) if (SubNodes[i].AreThereIncludeItems()) return true; return false; @@ -273,13 +349,13 @@ bool CCensorNode::AreThereIncludeItems() const 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++) + FOR_VECTOR (i, items) if (items[i].CheckPath(pathParts, isFile)) return true; return false; } -bool CCensorNode::CheckPath(UStringVector &pathParts, bool isFile, bool &include) const +bool CCensorNode::CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const { if (CheckPathCurrent(false, pathParts, isFile)) { @@ -288,30 +364,45 @@ bool CCensorNode::CheckPath(UStringVector &pathParts, bool isFile, bool &include } include = true; bool finded = CheckPathCurrent(true, pathParts, isFile); - if (pathParts.Size() == 1) + 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)) + if (SubNodes[index].CheckPathVect(pathParts2, isFile, include)) return true; } return finded; } -bool CCensorNode::CheckPath(const UString &path, bool isFile, bool &include) const +bool CCensorNode::CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const { UStringVector pathParts; SplitPathToParts(path, pathParts); - return CheckPath(pathParts, isFile, include); + if (CheckPathVect(pathParts, isFile, include)) + { + if (!include || !isAltStream) + return true; + } + if (isAltStream && !pathParts.IsEmpty()) + { + UString &back = pathParts.Back(); + int pos = back.Find(L':'); + if (pos > 0) + { + back.DeleteFrom(pos); + return CheckPathVect(pathParts, isFile, include); + } + } + return false; } -bool CCensorNode::CheckPath(const UString &path, bool isFile) const +bool CCensorNode::CheckPath(bool isAltStream, const UString &path, bool isFile) const { bool include; - if (CheckPath(path, isFile, include)) + if (CheckPath2(isAltStream, path, isFile, include)) return include; return false; } @@ -335,7 +426,7 @@ bool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile } */ -void CCensorNode::AddItem2(bool include, const UString &path, bool recursive) +void CCensorNode::AddItem2(bool include, const UString &path, bool recursive, bool wildcardMatching) { if (path.IsEmpty()) return; @@ -347,13 +438,13 @@ void CCensorNode::AddItem2(bool include, const UString &path, bool recursive) path2.DeleteBack(); forFile = false; } - AddItem(include, path2, recursive, forFile, forFolder); + AddItem(include, path2, recursive, forFile, forFolder, wildcardMatching); } void CCensorNode::ExtendExclude(const CCensorNode &fromNodes) { ExcludeItems += fromNodes.ExcludeItems; - for (int i = 0; i < fromNodes.SubNodes.Size(); i++) + FOR_VECTOR (i, fromNodes.SubNodes) { const CCensorNode &node = fromNodes.SubNodes[i]; int subNodeIndex = FindSubNode(node.Name); @@ -365,13 +456,13 @@ void CCensorNode::ExtendExclude(const CCensorNode &fromNodes) int CCensor::FindPrefix(const UString &prefix) const { - for (int i = 0; i < Pairs.Size(); i++) + FOR_VECTOR (i, Pairs) if (CompareFileNames(Pairs[i].Prefix, prefix) == 0) return i; return -1; } -void CCensor::AddItem(bool include, const UString &path, bool recursive) +void CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &path, bool recursive, bool wildcardMatching) { UStringVector pathParts; if (path.IsEmpty()) @@ -383,40 +474,82 @@ void CCensor::AddItem(bool include, const UString &path, bool recursive) 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 + + UString prefix; + + if (pathMode != k_AbsPath) { - for (int i = 0; i < pathParts.Size(); i++) + const UString &front = pathParts.Front(); + bool isAbs = false; + + if (front.IsEmpty()) + isAbs = true; + else { - const UString &part = pathParts[i]; - if (part == L".." || part == L".") - { + #ifdef _WIN32 + + if (IsDriveColonName(front)) isAbs = true; - break; + else + + #endif + + FOR_VECTOR (i, pathParts) + { + const UString &part = pathParts[i]; + if (part == L".." || part == L".") + { + isAbs = true; + break; + } + } + } + + unsigned numAbsParts = 0; + if (isAbs) + if (pathParts.Size() > 1) + numAbsParts = pathParts.Size() - 1; + else + numAbsParts = 1; + + #ifdef _WIN32 + + // \\?\ case + if (numAbsParts >= 3) + { + if (pathParts[0].IsEmpty() && + pathParts[1].IsEmpty() && + pathParts[2] == L"?") + { + prefix = + WSTRING_PATH_SEPARATOR + WSTRING_PATH_SEPARATOR L"?" + WSTRING_PATH_SEPARATOR; + numAbsParts -= 3; + pathParts.DeleteFrontal(3); } } - } - int numAbsParts = 0; - if (isAbs) - if (pathParts.Size() > 1) - numAbsParts = pathParts.Size() - 1; - else + + #endif + + if (numAbsParts > 1 && pathMode == k_FullPath) 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); + + // We can't ignore wildcard, since we don't allow wildcard in SubNodes[].Name + // if (wildcardMatching) + for (unsigned 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)); @@ -426,16 +559,17 @@ void CCensor::AddItem(bool include, const UString &path, bool recursive) item.ForDir = true; item.ForFile = forFile; item.Recursive = recursive; + item.WildcardMatching = wildcardMatching; Pairs[index].Head.AddItem(include, item); } -bool CCensor::CheckPath(const UString &path, bool isFile) const +bool CCensor::CheckPath(bool isAltStream, const UString &path, bool isFile) const { bool finded = false; - for (int i = 0; i < Pairs.Size(); i++) + FOR_VECTOR (i, Pairs) { bool include; - if (Pairs[i].Head.CheckPath(path, isFile, include)) + if (Pairs[i].Head.CheckPath2(isAltStream, path, isFile, include)) { if (!include) return false; @@ -447,16 +581,35 @@ bool CCensor::CheckPath(const UString &path, bool isFile) const void CCensor::ExtendExclude() { - int i; + unsigned i; for (i = 0; i < Pairs.Size(); i++) if (Pairs[i].Prefix.IsEmpty()) break; if (i == Pairs.Size()) return; - int index = i; + unsigned index = i; for (i = 0; i < Pairs.Size(); i++) if (index != i) Pairs[i].Head.ExtendExclude(Pairs[index].Head); } +void CCensor::AddPathsToCensor(ECensorPathMode censorPathMode) +{ + FOR_VECTOR(i, CensorPaths) + { + const CCensorPath &cp = CensorPaths[i]; + AddItem(censorPathMode, cp.Include, cp.Path, cp.Recursive, cp.WildcardMatching); + } + CensorPaths.Clear(); +} + +void CCensor::AddPreItem(bool include, const UString &path, bool recursive, bool wildcardMatching) +{ + CCensorPath &cp = CensorPaths.AddNew(); + cp.Path = path; + cp.Include = include; + cp.Recursive = recursive; + cp.WildcardMatching = wildcardMatching; +} + } diff --git a/CPP/Common/Wildcard.h b/CPP/Common/Wildcard.h old mode 100755 new mode 100644 index 6d4cbcec..b9971202 --- a/CPP/Common/Wildcard.h +++ b/CPP/Common/Wildcard.h @@ -5,51 +5,90 @@ #include "MyString.h" -int CompareFileNames(const UString &s1, const UString &s2); +int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW; +#ifndef USE_UNICODE_FSTRING + int CompareFileNames(const char *s1, const char *s2); +#endif + +bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2); + +inline bool IsCharDirLimiter(wchar_t c) +{ + return c == WCHAR_PATH_SEPARATOR + #ifdef _WIN32 + || c == L'/' + #endif + ; +} void SplitPathToParts(const UString &path, UStringVector &pathParts); -void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name); +void SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name); +void SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &name); // ignores dir delimiter at the end of (path) + UString ExtractDirPrefixFromPath(const UString &path); UString ExtractFileNameFromPath(const UString &path); -bool DoesNameContainWildCard(const UString &path); -bool CompareWildCardWithName(const UString &mask, const UString &name); + +bool DoesNameContainWildcard(const UString &path); +bool DoesWildcardMatchName(const UString &mask, const UString &name); namespace NWildcard { +#ifdef _WIN32 +// returns true, if name is like "a:", "c:", ... +bool IsDriveColonName(const wchar_t *s); +#endif + + struct CItem { UStringVector PathParts; bool Recursive; bool ForFile; bool ForDir; + bool WildcardMatching; + + #ifdef _WIN32 + bool IsDriveItem() const + { + return PathParts.Size() == 1 && !ForFile && ForDir && IsDriveColonName(PathParts[0]); + } + #endif + + // CItem(): WildcardMatching(true) {} + + bool AreAllAllowed() const; bool CheckPath(const UStringVector &pathParts, bool isFile) const; }; class CCensorNode { CCensorNode *Parent; + bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const; void AddItemSimple(bool include, CItem &item); - bool CheckPath(UStringVector &pathParts, bool isFile, bool &include) const; + bool CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const; public: CCensorNode(): Parent(0) { }; CCensorNode(const UString &name, CCensorNode *parent): Name(name), Parent(parent) { }; - UString Name; + + UString Name; // wildcard is not allowed here CObjectVector SubNodes; CObjectVector IncludeItems; CObjectVector ExcludeItems; + bool AreAllAllowed() const; + 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); + void AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir, bool wildcardMatching); + void AddItem2(bool include, const UString &path, bool recursive, bool wildcardMatching); bool NeedCheckSubDirs() const; bool AreThereIncludeItems() const; - bool CheckPath(const UString &path, bool isFile, bool &include) const; - bool CheckPath(const UString &path, bool isFile) const; + bool CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const; + bool CheckPath(bool isAltStream, const UString &path, bool isFile) const; bool CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const; // bool CheckPathToRoot(const UString &path, bool isFile, bool include) const; @@ -60,21 +99,59 @@ struct CPair { UString Prefix; CCensorNode Head; + CPair(const UString &prefix): Prefix(prefix) { }; }; +enum ECensorPathMode +{ + k_RelatPath, // absolute prefix as Prefix, remain path in Tree + k_FullPath, // drive prefix as Prefix, remain path in Tree + k_AbsPath // full path in Tree +}; + +struct CCensorPath +{ + UString Path; + bool Include; + bool Recursive; + bool WildcardMatching; + + CCensorPath(): + Include(true), + Recursive(false), + WildcardMatching(true) + {} +}; + class CCensor { int FindPrefix(const UString &prefix) const; public: CObjectVector Pairs; + + CObjectVector CensorPaths; + bool AllAreRelative() const { return (Pairs.Size() == 1 && Pairs.Front().Prefix.IsEmpty()); } - void AddItem(bool include, const UString &path, bool recursive); - bool CheckPath(const UString &path, bool isFile) const; + + void AddItem(ECensorPathMode pathMode, bool include, const UString &path, bool recursive, bool wildcardMatching); + bool CheckPath(bool isAltStream, const UString &path, bool isFile) const; void ExtendExclude(); + + void AddPathsToCensor(NWildcard::ECensorPathMode censorPathMode); + void AddPreItem(bool include, const UString &path, bool recursive, bool wildcardMatching); + void AddPreItem(const UString &path) + { + AddPreItem(true, path, false, false); + } + void AddPreItem_Wildcard() + { + AddPreItem(true, L"*", false, true); + } }; + } #endif diff --git a/CPP/Common/XzCrc64Reg.cpp b/CPP/Common/XzCrc64Reg.cpp new file mode 100644 index 00000000..58413797 --- /dev/null +++ b/CPP/Common/XzCrc64Reg.cpp @@ -0,0 +1,54 @@ +// XzCrc64Reg.cpp + +#include "StdAfx.h" + +#include "../../C/CpuArch.h" +#include "../../C/XzCrc64.h" + +#include "../Common/MyCom.h" + +#include "../7zip/ICoder.h" +#include "../7zip/Common/RegisterCodec.h" + +class CXzCrc64Hasher: + public IHasher, + public CMyUnknownImp +{ + UInt64 _crc; +public: + CXzCrc64Hasher(): _crc(CRC64_INIT_VAL) {} + + MY_UNKNOWN_IMP + + STDMETHOD_(void, Init)(); + STDMETHOD_(void, Update)(const void *data, UInt32 size); + STDMETHOD_(void, Final)(Byte *digest); + STDMETHOD_(UInt32, GetDigestSize)(); +}; + +STDMETHODIMP_(void) CXzCrc64Hasher::Init() +{ + _crc = CRC64_INIT_VAL; +} + +STDMETHODIMP_(void) CXzCrc64Hasher::Update(const void *data, UInt32 size) +{ + _crc = Crc64Update(_crc, data, size); +} + +STDMETHODIMP_(void) CXzCrc64Hasher::Final(Byte *digest) +{ + UInt64 val = CRC64_GET_DIGEST(_crc); + SetUi64(digest, val); +} + +STDMETHODIMP_(UInt32) CXzCrc64Hasher::GetDigestSize() +{ + return 8; +} + +static IHasher *CreateHasher() { return new CXzCrc64Hasher; } + +static CHasherInfo g_HasherInfo = { CreateHasher, 0x4, L"CRC64", 8 }; + +REGISTER_HASHER(Crc64) diff --git a/CPP/Windows/COM.cpp b/CPP/Windows/COM.cpp old mode 100755 new mode 100644 diff --git a/CPP/Windows/COM.h b/CPP/Windows/COM.h old mode 100755 new mode 100644 index 506bbbc6..eedcfa9d --- a/CPP/Windows/COM.h +++ b/CPP/Windows/COM.h @@ -3,7 +3,7 @@ #ifndef __WINDOWS_COM_H #define __WINDOWS_COM_H -#include "Common/MyString.h" +#include "../Common/MyString.h" namespace NWindows { namespace NCOM { @@ -63,7 +63,6 @@ HRESULT StringToGUIDA(const char *string, GUID &classID); #define StringToGUID StringToGUIDA #endif - }} #endif diff --git a/CPP/Windows/Clipboard.cpp b/CPP/Windows/Clipboard.cpp old mode 100755 new mode 100644 index e1ff62be..bab9db72 --- a/CPP/Windows/Clipboard.cpp +++ b/CPP/Windows/Clipboard.cpp @@ -6,13 +6,12 @@ #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" -#include "Common/StringConvert.h" +#include "Clipboard.h" +#include "Defs.h" +#include "MemoryGlobal.h" +#include "Shell.h" namespace NWindows { @@ -22,11 +21,6 @@ bool CClipboard::Open(HWND wndNewOwner) return m_Open; } -CClipboard::~CClipboard() -{ - Close(); -} - bool CClipboard::Close() { if (!m_Open) @@ -94,7 +88,7 @@ bool ClipboardGetFileNames(UStringVector &names) } */ -static bool ClipboardSetData(UINT uFormat, const void *data, size_t size) +static bool ClipboardSetData(UINT uFormat, const void *data, size_t size) throw() { NMemory::CGlobal global; if (!global.Alloc(GMEM_DDESHARE | GMEM_MOVEABLE, size)) @@ -121,13 +115,13 @@ bool ClipboardSetText(HWND owner, const UString &s) return false; bool res; - res = ClipboardSetData(CF_UNICODETEXT, (const wchar_t *)s, (s.Length() + 1) * sizeof(wchar_t)); + res = ClipboardSetData(CF_UNICODETEXT, (const wchar_t *)s, (s.Len() + 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)); + res |= ClipboardSetData(CF_TEXT, (const char *)a, (a.Len() + 1) * sizeof(char)); a = UnicodeStringToMultiByte(s, CP_OEMCP); - res |= ClipboardSetData(CF_OEMTEXT, (const char *)a, (a.Length() + 1) * sizeof(char)); + res |= ClipboardSetData(CF_OEMTEXT, (const char *)a, (a.Len() + 1) * sizeof(char)); #endif return res; } diff --git a/CPP/Windows/Clipboard.h b/CPP/Windows/Clipboard.h old mode 100755 new mode 100644 index c80ba5ea..60fedc13 --- a/CPP/Windows/Clipboard.h +++ b/CPP/Windows/Clipboard.h @@ -3,7 +3,7 @@ #ifndef __CLIPBOARD_H #define __CLIPBOARD_H -#include "Common/MyString.h" +#include "../Common/MyString.h" namespace NWindows { @@ -12,9 +12,9 @@ class CClipboard bool m_Open; public: CClipboard(): m_Open(false) {}; - ~CClipboard(); - bool Open(HWND wndNewOwner); - bool Close(); + ~CClipboard() { Close(); } + bool Open(HWND wndNewOwner) throw(); + bool Close() throw(); }; bool ClipboardIsFormatAvailableHDROP(); diff --git a/CPP/Windows/CommonDialog.cpp b/CPP/Windows/CommonDialog.cpp old mode 100755 new mode 100644 index 4ee7412d..6092b050 --- a/CPP/Windows/CommonDialog.cpp +++ b/CPP/Windows/CommonDialog.cpp @@ -7,176 +7,175 @@ #endif #ifndef _UNICODE -#include "Common/StringConvert.h" +#include "../Common/StringConvert.h" #endif -#include "Common/MyCom.h" - -#include "Windows/Defs.h" #include "CommonDialog.h" +#include "Defs.h" #ifndef _UNICODE extern bool g_IsNT; #endif -namespace NWindows{ +namespace NWindows { #ifndef _UNICODE + class CDoubleZeroStringListA { - CRecordVector m_Indexes; - AString m_String; + LPTSTR Buf; + unsigned Size; public: - void Add(LPCSTR s); - void SetForBuffer(LPSTR buffer); + CDoubleZeroStringListA(LPSTR buf, unsigned size): Buf(buf), Size(size) {} + bool Add(LPCSTR s) throw(); + void Finish() { *Buf = 0; } }; -void CDoubleZeroStringListA::Add(LPCSTR s) +bool CDoubleZeroStringListA::Add(LPCSTR s) { - m_String += s; - m_Indexes.Add(m_String.Length()); - m_String += ' '; + unsigned len = MyStringLen(s) + 1; + if (len >= Size) + return false; + MyStringCopy(Buf, s); + Buf += len; + Size -= len; + return true; } -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; + LPWSTR Buf; + unsigned Size; public: - void Add(LPCWSTR s); - void SetForBuffer(LPWSTR buffer); + CDoubleZeroStringListW(LPWSTR buf, unsigned size): Buf(buf), Size(size) {} + bool Add(LPCWSTR s) throw(); + void Finish() { *Buf = 0; } }; -void CDoubleZeroStringListW::Add(LPCWSTR s) +bool CDoubleZeroStringListW::Add(LPCWSTR s) { - m_String += s; - m_Indexes.Add(m_String.Length()); - m_String += L' '; + unsigned len = MyStringLen(s) + 1; + if (len >= Size) + return false; + MyStringCopy(Buf, s); + Buf += len; + Size -= len; + return true; } -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 + +/* if (lpstrFilter == NULL && nFilterIndex == 0) + MSDN : "the system doesn't show any files", + but WinXP-64 shows all files. Why ??? */ + +/* +structures + OPENFILENAMEW + OPENFILENAMEA +contain additional members: +#if (_WIN32_WINNT >= 0x0500) + void *pvReserved; + DWORD dwReserved; + DWORD FlagsEx; +#endif -#define MY_OFN_PROJECT 0x00400000 -#define MY_OFN_SHOW_ALL 0x01000000 +If we compile the source code with (_WIN32_WINNT >= 0x0500), some functions +will not work at NT 4.0, if we use sizeof(OPENFILENAME*). +So we use size of old version of structure. */ + +#if defined(UNDER_CE) || defined(_WIN64) || (_WIN32_WINNT < 0x0500) +// || !defined(WINVER) + #define my_compatib_OPENFILENAMEA_size sizeof(OPENFILENAMEA) + #define my_compatib_OPENFILENAMEW_size sizeof(OPENFILENAMEW) +#else + #define my_compatib_OPENFILENAMEA_size OPENFILENAME_SIZE_VERSION_400A + #define my_compatib_OPENFILENAMEW_size OPENFILENAME_SIZE_VERSION_400W +#endif + +#define CONV_U_To_A(dest, src, temp) AString temp; if (src) { temp = GetSystemString(src); dest = temp; } -bool MyGetOpenFileName(HWND hwnd, LPCWSTR title, LPCWSTR fullFileName, - LPCWSTR s, UString &resPath +bool MyGetOpenFileName(HWND hwnd, LPCWSTR title, + LPCWSTR initialDir, + LPCWSTR filePath, + LPCWSTR filterDescription, + LPCWSTR filter, + UString &resPath #ifdef UNDER_CE , bool openFolder #endif ) { - const int kBufferSize = MAX_PATH * 2; + const unsigned kBufSize = MAX_PATH * 2; + const unsigned kFilterBufSize = MAX_PATH; + if (!filter) + filter = L"*.*"; #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) + CHAR buf[kBufSize]; + MyStringCopy(buf, (const char *)GetSystemString(filePath)); + // OPENFILENAME_NT4A + OPENFILENAMEA p; + memset(&p, 0, sizeof(p)); + p.lStructSize = my_compatib_OPENFILENAMEA_size; + p.hwndOwner = hwnd; + CHAR filterBuf[kFilterBufSize]; { - titleA = GetSystemString(title); - info.lpstrTitle = titleA; + CDoubleZeroStringListA dz(filterBuf, kFilterBufSize); + dz.Add(GetSystemString(filterDescription ? filterDescription : filter)); + dz.Add(GetSystemString(filter)); + dz.Finish(); + p.lpstrFilter = filterBuf; + p.nFilterIndex = 1; } - 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); + p.lpstrFile = buf; + p.nMaxFile = kBufSize; + CONV_U_To_A(p.lpstrInitialDir, initialDir, initialDirA); + CONV_U_To_A(p.lpstrTitle, title, titleA); + p.Flags = OFN_EXPLORER | OFN_HIDEREADONLY; + + bool res = BOOLToBool(::GetOpenFileNameA(&p)); + resPath = GetUnicodeString(buf); return res; } else #endif { - WCHAR 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; + WCHAR buf[kBufSize]; + MyStringCopy(buf, filePath); + // OPENFILENAME_NT4W + OPENFILENAMEW p; + memset(&p, 0, sizeof(p)); + p.lStructSize = my_compatib_OPENFILENAMEW_size; + p.hwndOwner = hwnd; - info.lpstrInitialDir= NULL; - - info.lpstrTitle = title; - - info.Flags = OFN_EXPLORER | OFN_HIDEREADONLY + WCHAR filterBuf[kFilterBufSize]; + { + CDoubleZeroStringListW dz(filterBuf, kFilterBufSize); + dz.Add(filterDescription ? filterDescription : filter); + dz.Add(filter); + dz.Finish(); + p.lpstrFilter = filterBuf; + p.nFilterIndex = 1; + } + + p.lpstrFile = buf; + p.nMaxFile = kBufSize; + p.lpstrInitialDir = initialDir; + p.lpstrTitle = title; + p.Flags = OFN_EXPLORER | OFN_HIDEREADONLY #ifdef UNDER_CE - | (openFolder ? (MY_OFN_PROJECT | MY_OFN_SHOW_ALL) : 0) + | (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; + bool res = BOOLToBool(::GetOpenFileNameW(&p)); + resPath = buf; return res; } } diff --git a/CPP/Windows/CommonDialog.h b/CPP/Windows/CommonDialog.h old mode 100755 new mode 100644 index f24bb5b2..aaf17ac5 --- a/CPP/Windows/CommonDialog.h +++ b/CPP/Windows/CommonDialog.h @@ -3,12 +3,16 @@ #ifndef __WINDOWS_COMMON_DIALOG_H #define __WINDOWS_COMMON_DIALOG_H -#include "Common/MyString.h" +#include "../Common/MyString.h" -namespace NWindows{ +namespace NWindows { -bool MyGetOpenFileName(HWND hwnd, LPCWSTR title, LPCWSTR fullFileName, - LPCWSTR s, UString &resPath +bool MyGetOpenFileName(HWND hwnd, LPCWSTR title, + LPCWSTR initialDir, // can be NULL, so dir prefix in filePath will be used + LPCWSTR filePath, // full path + LPCWSTR filterDescription, // like "All files (*.*)" + LPCWSTR filter, // like "*.exe" + UString &resPath #ifdef UNDER_CE , bool openFolder = false #endif diff --git a/CPP/Windows/Console.cpp b/CPP/Windows/Console.cpp old mode 100755 new mode 100644 diff --git a/CPP/Windows/Console.h b/CPP/Windows/Console.h old mode 100755 new mode 100644 index 99ae90f1..f2e8c293 --- a/CPP/Windows/Console.h +++ b/CPP/Windows/Console.h @@ -3,44 +3,44 @@ #ifndef __WINDOWS_CONSOLE_H #define __WINDOWS_CONSOLE_H -#include "Windows/Defs.h" +#include "Defs.h" -namespace NWindows{ -namespace NConsole{ +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)); } + void Attach(HANDLE handle) { m_Object = handle; }; + bool GetMode(DWORD &mode) + { return BOOLToBool(::GetConsoleMode(m_Object, &mode)); } + bool SetMode(DWORD mode) + { return BOOLToBool(::SetConsoleMode(m_Object, mode)); } }; 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 PeekEvents(PINPUT_RECORD events, DWORD numEvents, DWORD &numEventsRead) + { return BOOLToBool(::PeekConsoleInput(m_Object, events, numEvents, &numEventsRead)); } + bool PeekEvent(INPUT_RECORD &event, DWORD &numEventsRead) + { return PeekEvents(&event, 1, numEventsRead); } + bool ReadEvents(PINPUT_RECORD events, DWORD numEvents, DWORD &numEventsRead) + { return BOOLToBool(::ReadConsoleInput(m_Object, events, numEvents, &numEventsRead)); } + bool ReadEvent(INPUT_RECORD &event, DWORD &numEventsRead) + { return ReadEvents(&event, 1, numEventsRead); } + bool GetNumberOfEvents(DWORD &numEvents) + { return BOOLToBool(::GetNumberOfConsoleInputEvents(m_Object, &numEvents)); } + + bool WriteEvents(const INPUT_RECORD *events, DWORD numEvents, DWORD &numEventsWritten) + { return BOOLToBool(::WriteConsoleInput(m_Object, events, numEvents, &numEventsWritten)); } + bool WriteEvent(const INPUT_RECORD &event, DWORD &numEventsWritten) + { return WriteEvents(&event, 1, numEventsWritten); } - bool Read(LPVOID aBuffer, DWORD aNumberOfCharsToRead, DWORD &aNumberOfCharsRead) - { return BOOLToBool(::ReadConsole(m_Object, aBuffer, aNumberOfCharsToRead, &aNumberOfCharsRead, NULL)); } + bool Read(LPVOID buffer, DWORD numChars, DWORD &numCharsRead) + { return BOOLToBool(::ReadConsole(m_Object, buffer, numChars, &numCharsRead, NULL)); } bool Flush() { return BOOLToBool(::FlushConsoleInputBuffer(m_Object)); } diff --git a/CPP/Windows/Control/ComboBox.cpp b/CPP/Windows/Control/ComboBox.cpp old mode 100755 new mode 100644 index 40d2f865..9b458fe4 --- a/CPP/Windows/Control/ComboBox.cpp +++ b/CPP/Windows/Control/ComboBox.cpp @@ -3,10 +3,10 @@ #include "StdAfx.h" #ifndef _UNICODE -#include "Common/StringConvert.h" +#include "../../Common/StringConvert.h" #endif -#include "Windows/Control/ComboBox.h" +#include "ComboBox.h" #ifndef _UNICODE extern bool g_IsNT; @@ -51,7 +51,7 @@ LRESULT CComboBox::GetLBText(int index, UString &s) if (len == CB_ERR) return len; s = GetUnicodeString(sa); - return s.Length(); + return s.Len(); } #endif diff --git a/CPP/Windows/Control/ComboBox.h b/CPP/Windows/Control/ComboBox.h old mode 100755 new mode 100644 index aa0eb930..8c6fd381 --- a/CPP/Windows/Control/ComboBox.h +++ b/CPP/Windows/Control/ComboBox.h @@ -32,6 +32,8 @@ public: LRESULT SetItemData(int index, LPARAM lParam) { return SendMessage(CB_SETITEMDATA, index, lParam); } LRESULT GetItemData(int index) { return SendMessage(CB_GETITEMDATA, index, 0); } + LRESULT GetItemData_of_CurSel() { return GetItemData(GetCurSel()); } + void ShowDropDown(bool show = true) { SendMessage(CB_SHOWDROPDOWN, show ? TRUE : FALSE, 0); } }; diff --git a/CPP/Windows/Control/CommandBar.h b/CPP/Windows/Control/CommandBar.h old mode 100755 new mode 100644 index 387c5e2d..780211ec --- a/CPP/Windows/Control/CommandBar.h +++ b/CPP/Windows/Control/CommandBar.h @@ -5,7 +5,7 @@ #ifdef UNDER_CE -#include "Windows/Window.h" +#include "../Window.h" namespace NWindows { namespace NControl { @@ -21,7 +21,7 @@ public: // Macros // void Destroy() { CommandBar_Destroy(_window); } - bool AddButtons(int iButton, UINT numButtons, LPTBBUTTON buttons) { return BOOLToBool(SendMessage(TB_ADDBUTTONS, (WPARAM)numButtons, (LPARAM)buttons)); } + // bool AddButtons(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); } diff --git a/CPP/Windows/Control/Dialog.cpp b/CPP/Windows/Control/Dialog.cpp old mode 100755 new mode 100644 index 2695ca54..01bc7d43 --- a/CPP/Windows/Control/Dialog.cpp +++ b/CPP/Windows/Control/Dialog.cpp @@ -2,11 +2,12 @@ #include "StdAfx.h" -#include "Windows/Control/Dialog.h" #ifndef _UNICODE #include "../../Common/StringConvert.h" #endif +#include "Dialog.h" + extern HINSTANCE g_hInstance; #ifndef _UNICODE extern bool g_IsNT; @@ -99,6 +100,55 @@ bool IsDialogSizeOK(int xSize, int ySize) ySize / 8 * y <= wy; } +bool CDialog::GetMargins(int margin, int &x, int &y) +{ + x = margin; + y = margin; + RECT rect; + rect.left = 0; + rect.top = 0; + rect.right = margin; + rect.bottom = margin; + if (!MapRect(&rect)) + return false; + x = rect.right - rect.left; + y = rect.bottom - rect.top; + return true; +} + +int CDialog::Units_To_Pixels_X(int units) +{ + RECT rect; + rect.left = 0; + rect.top = 0; + rect.right = units; + rect.bottom = units; + if (!MapRect(&rect)) + return units * 3 / 2; + return rect.right - rect.left; +} + +bool CDialog::GetItemSizes(int id, int &x, int &y) +{ + RECT rect; + if (!::GetWindowRect(GetItem(id), &rect)) + return false; + x = RECT_SIZE_X(rect); + y = RECT_SIZE_Y(rect); + return true; +} + +void CDialog::GetClientRectOfItem(int id, RECT &rect) +{ + ::GetWindowRect(GetItem(id), &rect); + ScreenToClient(&rect); +} + +bool CDialog::MoveItem(int id, int x, int y, int width, int height, bool repaint) +{ + return BOOLToBool(::MoveWindow(GetItem(id), x, y, width, height, BoolToBOOL(repaint))); +} + void CDialog::NormalizeSize(bool fullNormalize) { RECT workRect; diff --git a/CPP/Windows/Control/Dialog.h b/CPP/Windows/Control/Dialog.h old mode 100755 new mode 100644 index 2b5147e7..b450266b --- a/CPP/Windows/Control/Dialog.h +++ b/CPP/Windows/Control/Dialog.h @@ -3,7 +3,7 @@ #ifndef __WINDOWS_CONTROL_DIALOG_H #define __WINDOWS_CONTROL_DIALOG_H -#include "Windows/Window.h" +#include "../Window.h" namespace NWindows { namespace NControl { @@ -11,7 +11,7 @@ namespace NControl { class CDialog: public CWindow { public: - CDialog(HWND wndow = NULL): CWindow(wndow){}; + CDialog(HWND wnd = NULL): CWindow(wnd){}; virtual ~CDialog() {}; HWND GetItem(int itemID) const @@ -23,6 +23,9 @@ public: bool ShowItem(int itemID, int cmdShow) const { return BOOLToBool(::ShowWindow(GetItem(itemID), cmdShow)); } + bool ShowItem_Bool(int itemID, bool show) const + { return ShowItem(itemID, show ? SW_SHOW: SW_HIDE); } + bool HideItem(int itemID) const { return ShowItem(itemID, SW_HIDE); } bool SetItemText(int itemID, LPCTSTR s) @@ -110,52 +113,11 @@ public: 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))); } + bool GetMargins(int margin, int &x, int &y); + int Units_To_Pixels_X(int units); + bool GetItemSizes(int id, int &x, int &y); + void GetClientRectOfItem(int id, RECT &rect); + bool MoveItem(int id, int x, int y, int width, int height, bool repaint = true); void NormalizeSize(bool fullNormalize = false); void NormalizePosition(); diff --git a/CPP/Windows/Control/Edit.h b/CPP/Windows/Control/Edit.h old mode 100755 new mode 100644 index c4bf5704..17ac9f13 --- a/CPP/Windows/Control/Edit.h +++ b/CPP/Windows/Control/Edit.h @@ -3,7 +3,7 @@ #ifndef __WINDOWS_CONTROL_EDIT_H #define __WINDOWS_CONTROL_EDIT_H -#include "Windows/Window.h" +#include "../Window.h" namespace NWindows { namespace NControl { diff --git a/CPP/Windows/Control/ImageList.cpp b/CPP/Windows/Control/ImageList.cpp old mode 100755 new mode 100644 diff --git a/CPP/Windows/Control/ImageList.h b/CPP/Windows/Control/ImageList.h old mode 100755 new mode 100644 index 127cd1ed..72094399 --- a/CPP/Windows/Control/ImageList.h +++ b/CPP/Windows/Control/ImageList.h @@ -3,7 +3,7 @@ #ifndef __WINDOWS_CONTROL_IMAGELIST_H #define __WINDOWS_CONTROL_IMAGELIST_H -#include "Windows/Defs.h" +#include "../Defs.h" namespace NWindows { namespace NControl { diff --git a/CPP/Windows/Control/ListView.cpp b/CPP/Windows/Control/ListView.cpp old mode 100755 new mode 100644 index 255a17c5..6d916591 --- a/CPP/Windows/Control/ListView.cpp +++ b/CPP/Windows/Control/ListView.cpp @@ -2,7 +2,7 @@ #include "StdAfx.h" -#include "Windows/Control/ListView.h" +#include "ListView.h" #ifndef _UNICODE extern bool g_IsNT; diff --git a/CPP/Windows/Control/ListView.h b/CPP/Windows/Control/ListView.h old mode 100755 new mode 100644 index bebcd9e2..ceb297f8 --- a/CPP/Windows/Control/ListView.h +++ b/CPP/Windows/Control/ListView.h @@ -3,7 +3,7 @@ #ifndef __WINDOWS_CONTROL_LISTVIEW_H #define __WINDOWS_CONTROL_LISTVIEW_H -#include "Windows/Window.h" +#include "../Window.h" #include diff --git a/CPP/Windows/Control/ProgressBar.h b/CPP/Windows/Control/ProgressBar.h old mode 100755 new mode 100644 diff --git a/CPP/Windows/Control/PropertyPage.cpp b/CPP/Windows/Control/PropertyPage.cpp old mode 100755 new mode 100644 index d7eaab17..bbac74ad --- a/CPP/Windows/Control/PropertyPage.cpp +++ b/CPP/Windows/Control/PropertyPage.cpp @@ -2,11 +2,12 @@ #include "StdAfx.h" -#include "Windows/Control/PropertyPage.h" #ifndef _UNICODE #include "../../Common/StringConvert.h" #endif +#include "PropertyPage.h" + extern HINSTANCE g_hInstance; #ifndef _UNICODE extern bool g_IsNT; @@ -53,7 +54,7 @@ INT_PTR MyPropertySheet(const CObjectVector &pagesInfo, HWND hwndPare #endif CRecordVector pagesW; - int i; + unsigned i; #ifndef _UNICODE for (i = 0; i < pagesInfo.Size(); i++) titles.Add(GetSystemString(pagesInfo[i].Title)); diff --git a/CPP/Windows/Control/PropertyPage.h b/CPP/Windows/Control/PropertyPage.h old mode 100755 new mode 100644 diff --git a/CPP/Windows/Control/ReBar.h b/CPP/Windows/Control/ReBar.h old mode 100755 new mode 100644 index 8e11c139..bd475b10 --- a/CPP/Windows/Control/ReBar.h +++ b/CPP/Windows/Control/ReBar.h @@ -3,8 +3,7 @@ #ifndef __WINDOWS_CONTROL_REBAR_H #define __WINDOWS_CONTROL_REBAR_H -#include "Windows/Window.h" -#include "Windows/Defs.h" +#include "../Window.h" namespace NWindows { namespace NControl { @@ -16,9 +15,9 @@ public: { 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) + bool SetBandInfo(unsigned index, LPREBARBANDINFO bandInfo) { return LRESULTToBool(SendMessage(RB_SETBANDINFO, index, (LPARAM)bandInfo)); } - void MaximizeBand(int index, bool ideal) + void MaximizeBand(unsigned index, bool ideal) { SendMessage(RB_MAXIMIZEBAND, index, BoolToBOOL(ideal)); } bool SizeToRect(LPRECT rect) { return LRESULTToBool(SendMessage(RB_SIZETORECT, 0, (LPARAM)rect)); } diff --git a/CPP/Windows/Control/Static.h b/CPP/Windows/Control/Static.h old mode 100755 new mode 100644 diff --git a/CPP/Windows/Control/StatusBar.h b/CPP/Windows/Control/StatusBar.h old mode 100755 new mode 100644 index 8766188b..f3e0d3ef --- a/CPP/Windows/Control/StatusBar.h +++ b/CPP/Windows/Control/StatusBar.h @@ -3,8 +3,7 @@ #ifndef __WINDOWS_CONTROL_STATUSBAR_H #define __WINDOWS_CONTROL_STATUSBAR_H -#include "Windows/Window.h" -#include "Windows/Defs.h" +#include "../Window.h" namespace NWindows { namespace NControl { @@ -14,28 +13,28 @@ 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) + bool SetText(unsigned index, LPCTSTR text, UINT type) { return LRESULTToBool(SendMessage(SB_SETTEXT, index | type, (LPARAM)text)); } - bool SetText(int index, LPCTSTR text) + bool SetText(unsigned 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) + bool SetText(unsigned index, LPCWSTR text, UINT type) { return LRESULTToBool(SendMessage(SB_SETTEXTW, index | type, (LPARAM)text)); } - bool SetText(int index, LPCWSTR text) + bool SetText(unsigned index, LPCWSTR text) { return SetText(index, text, 0); } #endif + + bool SetParts(unsigned numParts, const int *edgePostions) + { return LRESULTToBool(SendMessage(SB_SETPARTS, numParts, (LPARAM)edgePostions)); } + void Simple(bool simple) + { SendMessage(SB_SIMPLE, BoolToBOOL(simple), 0); } }; }} diff --git a/CPP/Windows/Control/StdAfx.h b/CPP/Windows/Control/StdAfx.h old mode 100755 new mode 100644 index ef555ec1..1cbd7fea --- a/CPP/Windows/Control/StdAfx.h +++ b/CPP/Windows/Control/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../Common/MyWindows.h" -#include "../../Common/NewHandler.h" +#include "../../Common/Common.h" #endif diff --git a/CPP/Windows/Control/ToolBar.h b/CPP/Windows/Control/ToolBar.h old mode 100755 new mode 100644 index 262184ae..d579ab7d --- a/CPP/Windows/Control/ToolBar.h +++ b/CPP/Windows/Control/ToolBar.h @@ -3,7 +3,7 @@ #ifndef __WINDOWS_CONTROL_TOOLBAR_H #define __WINDOWS_CONTROL_TOOLBAR_H -#include "Windows/Window.h" +#include "../Window.h" namespace NWindows { namespace NControl { diff --git a/CPP/Windows/Control/Trackbar.h b/CPP/Windows/Control/Trackbar.h old mode 100755 new mode 100644 index 42dc4e40..c6d31112 --- a/CPP/Windows/Control/Trackbar.h +++ b/CPP/Windows/Control/Trackbar.h @@ -3,13 +3,13 @@ #ifndef __WINDOWS_CONTROL_TRACKBAR_H #define __WINDOWS_CONTROL_TRACKBAR_H -#include "Windows/Window.h" -#include "Windows/Defs.h" +#include "../Window.h" +#include "../Defs.h" namespace NWindows { namespace NControl { -class CTrackbar: public CWindow +class CTrackbar1: public CWindow { public: void SetRange(int minimum, int maximum, bool redraw = true) diff --git a/CPP/Windows/Control/Window2.cpp b/CPP/Windows/Control/Window2.cpp old mode 100755 new mode 100644 index e1299048..e6ddb6d0 --- a/CPP/Windows/Control/Window2.cpp +++ b/CPP/Windows/Control/Window2.cpp @@ -3,11 +3,11 @@ #include "StdAfx.h" #ifndef _UNICODE -#include "Common/StringConvert.h" +#include "../../Common/StringConvert.h" #endif -#include "Windows/Control/Window2.h" -// extern HINSTANCE g_hInstance; +#include "Window2.h" + #ifndef _UNICODE extern bool g_IsNT; #endif @@ -26,14 +26,12 @@ namespace NControl { #define MY_START_WM_CREATE WM_NCCREATE #endif -static LRESULT CALLBACK WindowProcedure(HWND aHWND, UINT message, - WPARAM wParam, LPARAM lParam) +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()); + 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) @@ -48,48 +46,42 @@ static LRESULT CALLBACK WindowProcedure(HWND aHWND, UINT message, 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) +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)) + WNDCLASS wc; + if (!::GetClassInfo(instance, className, &wc)) { - // 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) + // wc.style = CS_HREDRAW | CS_VREDRAW; + wc.style = 0; + wc.lpfnWndProc = WindowProcedure; + wc.cbClsExtra = NULL; + wc.cbWndExtra = NULL; + wc.hInstance = instance; + wc.hIcon = NULL; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wc.lpszMenuName = NULL; + wc.lpszClassName = className; + if (::RegisterClass(&wc) == 0) return false; } - return CWindow::CreateEx(exStyle, className, windowName, - style, x, y, width, height, parentWindow, - idOrHMenu, instance, this); + 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 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; + WNDCLASSW wc; + needRegister = ::GetClassInfoW(instance, className, &wc) == 0; } else { @@ -107,26 +99,25 @@ bool CWindow2::CreateEx(DWORD exStyle, LPCWSTR className, } 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) + WNDCLASSW wc; + // wc.style = CS_HREDRAW | CS_VREDRAW; + wc.style = 0; + wc.lpfnWndProc = WindowProcedure; + wc.cbClsExtra = NULL; + wc.cbWndExtra = NULL; + wc.hInstance = instance; + wc.hIcon = NULL; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wc.lpszMenuName = NULL; + wc.lpszClassName = className; + if (MyRegisterClass(&wc) == 0) return false; } - return CWindow::CreateEx(exStyle, className, windowName, - style, x, y, width, height, parentWindow, - idOrHMenu, instance, this); - + 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) diff --git a/CPP/Windows/Control/Window2.h b/CPP/Windows/Control/Window2.h old mode 100755 new mode 100644 index 2af031b8..d744b3e6 --- a/CPP/Windows/Control/Window2.h +++ b/CPP/Windows/Control/Window2.h @@ -3,7 +3,7 @@ #ifndef __WINDOWS_CONTROL_WINDOW2_H #define __WINDOWS_CONTROL_WINDOW2_H -#include "Windows/Window.h" +#include "../Window.h" namespace NWindows { namespace NControl { @@ -15,19 +15,14 @@ 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); + 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); + 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); @@ -47,10 +42,8 @@ public: virtual void OnCancel() {}; */ - LONG_PTR SetMsgResult(LONG_PTR newLongPtr ) - { return SetLongPtr(DWLP_MSGRESULT, newLongPtr); } - LONG_PTR GetMsgResult() const - { return GetLongPtr(DWLP_MSGRESULT); } + LONG_PTR SetMsgResult(LONG_PTR newLongPtr) { return SetLongPtr(DWLP_MSGRESULT, newLongPtr); } + LONG_PTR GetMsgResult() const { return GetLongPtr(DWLP_MSGRESULT); } }; }} diff --git a/CPP/Windows/DLL.cpp b/CPP/Windows/DLL.cpp old mode 100755 new mode 100644 index 81eec692..367d1be1 --- a/CPP/Windows/DLL.cpp +++ b/CPP/Windows/DLL.cpp @@ -93,11 +93,14 @@ bool MyGetModuleFileName(FString &path) FString GetModuleDirPrefix() { FString s; - if (NDLL::MyGetModuleFileName(s)) + if (MyGetModuleFileName(s)) { int pos = s.ReverseFind(FCHAR_PATH_SEPARATOR); if (pos >= 0) - return s.Left(pos + 1); + { + s.DeleteFrom(pos + 1); + return s; + } } return FTEXT(".") FSTRING_PATH_SEPARATOR; } diff --git a/CPP/Windows/DLL.h b/CPP/Windows/DLL.h old mode 100755 new mode 100644 index 9f0f5cd7..f7e5b81b --- a/CPP/Windows/DLL.h +++ b/CPP/Windows/DLL.h @@ -37,9 +37,9 @@ public: return m; } - bool Free(); - bool LoadEx(CFSTR path, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); - bool Load(CFSTR path); + bool Free() throw(); + bool LoadEx(CFSTR path, DWORD flags = LOAD_LIBRARY_AS_DATAFILE) throw(); + bool Load(CFSTR path) throw(); FARPROC GetProc(LPCSTR procName) const { return My_GetProcAddress(_module, procName); } }; diff --git a/CPP/Windows/Defs.h b/CPP/Windows/Defs.h old mode 100755 new mode 100644 diff --git a/CPP/Windows/Error.cpp b/CPP/Windows/Error.cpp deleted file mode 100755 index c02e3b9e..00000000 --- a/CPP/Windows/Error.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// 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 { - -static bool MyFormatMessage(DWORD errorCode, UString &message) -{ - LPVOID msgBuf; - #ifndef _UNICODE - if (!g_IsNT) - { - if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, errorCode, 0, (LPTSTR) &msgBuf, 0, NULL) == 0) - return false; - message = GetUnicodeString((LPCTSTR)msgBuf); - } - else - #endif - { - if (::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, errorCode, 0, (LPWSTR) &msgBuf, 0, NULL) == 0) - return false; - message = (LPCWSTR)msgBuf; - } - ::LocalFree(msgBuf); - return true; -} - -UString MyFormatMessageW(DWORD errorCode) -{ - UString message; - if (!MyFormatMessage(errorCode, message)) - { - wchar_t s[16]; - for (int i = 0; i < 8; i++) - { - int t = errorCode & 0xF; - errorCode >>= 4; - s[7 - i] = (wchar_t)((t < 10) ? ('0' + t) : ('A' + (t - 10))); - } - s[8] = '\0'; - message = (UString)L"Error #" + s; - } - return message; -} - -}} diff --git a/CPP/Windows/Error.h b/CPP/Windows/Error.h deleted file mode 100755 index b7da3ca5..00000000 --- a/CPP/Windows/Error.h +++ /dev/null @@ -1,15 +0,0 @@ -// Windows/Error.h - -#ifndef __WINDOWS_ERROR_H -#define __WINDOWS_ERROR_H - -#include "Common/MyString.h" - -namespace NWindows { -namespace NError { - -UString MyFormatMessageW(DWORD errorCode); - -}} - -#endif diff --git a/CPP/Windows/ErrorMsg.cpp b/CPP/Windows/ErrorMsg.cpp new file mode 100644 index 00000000..7c82537d --- /dev/null +++ b/CPP/Windows/ErrorMsg.cpp @@ -0,0 +1,61 @@ +// Windows/ErrorMsg.h + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "../Common/StringConvert.h" +#endif + +#include "ErrorMsg.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NError { + +static bool MyFormatMessage(DWORD errorCode, UString &message) +{ + LPVOID msgBuf; + #ifndef _UNICODE + if (!g_IsNT) + { + if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, errorCode, 0, (LPTSTR) &msgBuf, 0, NULL) == 0) + return false; + message = GetUnicodeString((LPCTSTR)msgBuf); + } + else + #endif + { + if (::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, errorCode, 0, (LPWSTR) &msgBuf, 0, NULL) == 0) + return false; + message = (LPCWSTR)msgBuf; + } + ::LocalFree(msgBuf); + return true; +} + +UString MyFormatMessage(DWORD errorCode) +{ + UString message; + if (!MyFormatMessage(errorCode, message)) + { + wchar_t s[16]; + for (int i = 0; i < 8; i++) + { + unsigned t = errorCode & 0xF; + errorCode >>= 4; + s[7 - i] = (wchar_t)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + } + s[8] = '\0'; + message = (UString)L"Error #" + s; + } + return message; +} + +}} diff --git a/CPP/Windows/ErrorMsg.h b/CPP/Windows/ErrorMsg.h new file mode 100644 index 00000000..0957c696 --- /dev/null +++ b/CPP/Windows/ErrorMsg.h @@ -0,0 +1,15 @@ +// Windows/ErrorMsg.h + +#ifndef __WINDOWS_ERROR_MSG_H +#define __WINDOWS_ERROR_MSG_H + +#include "../Common/MyString.h" + +namespace NWindows { +namespace NError { + +UString MyFormatMessage(DWORD errorCode); + +}} + +#endif diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp old mode 100755 new mode 100644 index 88215faa..e6751f85 --- a/CPP/Windows/FileDir.cpp +++ b/CPP/Windows/FileDir.cpp @@ -14,21 +14,17 @@ extern bool g_IsNT; #endif +using namespace NWindows; +using namespace NFile; +using namespace NName; + namespace NWindows { namespace NFile { - -// SetCurrentDirectory doesn't support \\?\ prefix - -#ifdef WIN_LONG_PATH -bool GetLongPathBase(CFSTR fileName, UString &res); -bool GetLongPath(CFSTR fileName, UString &res); -#endif - -namespace NDirectory { +namespace NDir { #ifndef UNDER_CE -bool MyGetWindowsDirectory(FString &path) +bool GetWindowsDir(FString &path) { UINT needLength; #ifndef _UNICODE @@ -50,8 +46,7 @@ bool MyGetWindowsDirectory(FString &path) return (needLength > 0 && needLength <= MAX_PATH); } - -bool MyGetSystemDirectory(FString &path) +bool GetSystemDir(FString &path) { UINT needLength; #ifndef _UNICODE @@ -74,7 +69,7 @@ bool MyGetSystemDirectory(FString &path) } #endif -bool SetDirTime(CFSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) +bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) { #ifndef _UNICODE if (!g_IsNT) @@ -83,13 +78,16 @@ bool SetDirTime(CFSTR fileName, const FILETIME *cTime, const FILETIME *aTime, co return false; } #endif - HANDLE hDir = ::CreateFileW(fs2us(fileName), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + + HANDLE hDir = INVALID_HANDLE_VALUE; + IF_USE_MAIN_PATH + hDir = ::CreateFileW(fs2us(path), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); #ifdef WIN_LONG_PATH - if (hDir == INVALID_HANDLE_VALUE) + if (hDir == INVALID_HANDLE_VALUE && USE_SUPER_PATH) { UString longPath; - if (GetLongPath(fileName, longPath)) + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) hDir = ::CreateFileW(longPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } @@ -104,87 +102,131 @@ bool SetDirTime(CFSTR fileName, const FILETIME *cTime, const FILETIME *aTime, co return res; } -#ifdef WIN_LONG_PATH -bool GetLongPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2) +bool SetFileAttrib(CFSTR path, DWORD attrib) { - if (!GetLongPathBase(s1, d1) || - !GetLongPathBase(s2, d2)) - return false; - if (d1.IsEmpty() && d2.IsEmpty()) - return false; - if (d1.IsEmpty()) d1 = fs2us(s1); - if (d2.IsEmpty()) d2 = fs2us(s2); - return true; + #ifndef _UNICODE + if (!g_IsNT) + { + if (::SetFileAttributes(fs2fas(path), attrib)) + return true; + } + else + #endif + { + IF_USE_MAIN_PATH + if (::SetFileAttributesW(fs2us(path), attrib)) + return true; + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH) + { + UString longPath; + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) + return BOOLToBool(::SetFileAttributesW(longPath, attrib)); + } + #endif + } + return false; } -#endif -bool MySetFileAttributes(CFSTR fileName, DWORD fileAttributes) +bool RemoveDir(CFSTR path) { #ifndef _UNICODE if (!g_IsNT) { - if (::SetFileAttributes(fs2fas(fileName), fileAttributes)) + if (::RemoveDirectory(fs2fas(path))) return true; } else #endif { - if (::SetFileAttributesW(fs2us(fileName), fileAttributes)) - return true; + IF_USE_MAIN_PATH + if (::RemoveDirectoryW(fs2us(path))) + return true; #ifdef WIN_LONG_PATH - UString longPath; - if (GetLongPath(fileName, longPath)) - return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); + if (USE_SUPER_PATH) + { + UString longPath; + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) + return BOOLToBool(::RemoveDirectoryW(longPath)); + } #endif } return false; } -bool MyRemoveDirectory(CFSTR path) +bool MyMoveFile(CFSTR oldFile, CFSTR newFile) { #ifndef _UNICODE if (!g_IsNT) { - if (::RemoveDirectory(fs2fas(path))) + if (::MoveFile(fs2fas(oldFile), fs2fas(newFile))) return true; } else #endif { - if (::RemoveDirectoryW(fs2us(path))) - return true; + IF_USE_MAIN_PATH_2(oldFile, newFile) + if (::MoveFileW(fs2us(oldFile), fs2us(newFile))) + return true; #ifdef WIN_LONG_PATH - UString longPath; - if (GetLongPath(path, longPath)) - return BOOLToBool(::RemoveDirectoryW(longPath)); + if (USE_SUPER_PATH_2) + { + UString d1, d2; + if (GetSuperPaths(oldFile, newFile, d1, d2, USE_MAIN_PATH_2)) + return BOOLToBool(::MoveFileW(d1, d2)); + } #endif } return false; } -bool MyMoveFile(CFSTR existFileName, CFSTR newFileName) +#ifndef UNDER_CE + +EXTERN_C_BEGIN +typedef BOOL (WINAPI *Func_CreateHardLinkW)( + LPCWSTR lpFileName, + LPCWSTR lpExistingFileName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes + ); +EXTERN_C_END + +bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName) { #ifndef _UNICODE if (!g_IsNT) { - if (::MoveFile(fs2fas(existFileName), fs2fas(newFileName))) + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return false; + /* + if (::CreateHardLink(fs2fas(newFileName), fs2fas(existFileName), NULL)) return true; + */ } else #endif { - if (::MoveFileW(fs2us(existFileName), fs2us(newFileName))) - return true; + Func_CreateHardLinkW my_CreateHardLinkW = (Func_CreateHardLinkW) + ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW"); + if (!my_CreateHardLinkW) + return false; + IF_USE_MAIN_PATH_2(newFileName, existFileName) + if (my_CreateHardLinkW(fs2us(newFileName), fs2us(existFileName), NULL)) + return true; #ifdef WIN_LONG_PATH - UString d1, d2; - if (GetLongPaths(existFileName, newFileName, d1, d2)) - return BOOLToBool(::MoveFileW(d1, d2)); + if (USE_SUPER_PATH_2) + { + UString d1, d2; + if (GetSuperPaths(newFileName, existFileName, d1, d2, USE_MAIN_PATH_2)) + return BOOLToBool(my_CreateHardLinkW(d1, d2, NULL)); + } #endif } return false; } -bool MyCreateDirectory(CFSTR path) +#endif + +bool CreateDir(CFSTR path) { #ifndef _UNICODE if (!g_IsNT) @@ -195,13 +237,14 @@ bool MyCreateDirectory(CFSTR path) else #endif { - if (::CreateDirectoryW(fs2us(path), NULL)) - return true; + IF_USE_MAIN_PATH + if (::CreateDirectoryW(fs2us(path), NULL)) + return true; #ifdef WIN_LONG_PATH - if (::GetLastError() != ERROR_ALREADY_EXISTS) + if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH) { UString longPath; - if (GetLongPath(path, longPath)) + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) return BOOLToBool(::CreateDirectoryW(longPath, NULL)); } #endif @@ -209,21 +252,22 @@ bool MyCreateDirectory(CFSTR path) return false; } -bool CreateComplexDirectory(CFSTR _aPathName) +bool CreateComplexDir(CFSTR _aPathName) { FString pathName = _aPathName; int pos = pathName.ReverseFind(FCHAR_PATH_SEPARATOR); - if (pos > 0 && pos == pathName.Length() - 1) + if (pos > 0 && (unsigned)pos == pathName.Len() - 1) { - if (pathName.Length() == 3 && pathName[1] == L':') + if (pathName.Len() == 3 && pathName[1] == L':') return true; // Disk folder; pathName.Delete(pos); } - FString pathName2 = pathName; - pos = pathName.Length(); + const FString pathName2 = pathName; + pos = pathName.Len(); + for (;;) { - if (MyCreateDirectory(pathName)) + if (CreateDir(pathName)) break; if (::GetLastError() == ERROR_ALREADY_EXISTS) { @@ -239,156 +283,111 @@ bool CreateComplexDirectory(CFSTR _aPathName) return false; if (pathName[pos - 1] == L':') return false; - pathName = pathName.Left(pos); + pathName.DeleteFrom(pos); } - pathName = pathName2; - while (pos < pathName.Length()) + + while (pos < (int)pathName2.Len()) { - pos = pathName.Find(FCHAR_PATH_SEPARATOR, pos + 1); + pos = pathName2.Find(FCHAR_PATH_SEPARATOR, pos + 1); if (pos < 0) - pos = pathName.Length(); - if (!MyCreateDirectory(pathName.Left(pos))) + pos = pathName2.Len(); + pathName.SetFrom(pathName2, pos); + if (!CreateDir(pathName)) return false; } + return true; } -bool DeleteFileAlways(CFSTR name) +bool DeleteFileAlways(CFSTR path) { - if (!MySetFileAttributes(name, 0)) + if (!SetFileAttrib(path, 0)) return false; #ifndef _UNICODE if (!g_IsNT) { - if (::DeleteFile(fs2fas(name))) + if (::DeleteFile(fs2fas(path))) return true; } else #endif { - if (::DeleteFileW(fs2us(name))) - return true; + IF_USE_MAIN_PATH + if (::DeleteFileW(fs2us(path))) + return true; #ifdef WIN_LONG_PATH - UString longPath; - if (GetLongPath(name, longPath)) - return BOOLToBool(::DeleteFileW(longPath)); + if (USE_SUPER_PATH) + { + UString longPath; + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) + return BOOLToBool(::DeleteFileW(longPath)); + } #endif } return false; } -static bool RemoveDirectorySubItems2(const FString pathPrefix, const NFind::CFileInfo &fileInfo) +bool RemoveDirWithSubItems(const FString &path) { - if (fileInfo.IsDir()) - return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); - return DeleteFileAlways(pathPrefix + fileInfo.Name); -} -bool RemoveDirectoryWithSubItems(const FString &path) -{ - NFind::CFileInfo fileInfo; - FString pathPrefix = path + FCHAR_PATH_SEPARATOR; + bool needRemoveSubItems = true; + { + NFind::CFileInfo fi; + if (!fi.Find(path)) + return false; + if (!fi.IsDir()) + { + ::SetLastError(ERROR_DIRECTORY); + return false; + } + if (fi.HasReparsePoint()) + needRemoveSubItems = false; + } + + if (needRemoveSubItems) { - NFind::CEnumerator enumerator(pathPrefix + FCHAR_ANY_MASK); - while (enumerator.Next(fileInfo)) - if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) + FString s = path; + s += FCHAR_PATH_SEPARATOR; + unsigned prefixSize = s.Len(); + s += FCHAR_ANY_MASK; + NFind::CEnumerator enumerator(s); + NFind::CFileInfo fi; + while (enumerator.Next(fi)) + { + s.DeleteFrom(prefixSize); + s += fi.Name; + if (fi.IsDir()) + { + if (!RemoveDirWithSubItems(s)) + return false; + } + else if (!DeleteFileAlways(s)) return false; + } } - if (!MySetFileAttributes(path, 0)) + + if (!SetFileAttrib(path, 0)) return false; - return MyRemoveDirectory(path); + return RemoveDir(path); } #ifdef UNDER_CE -bool MyGetFullPathName(CFSTR fileName, FString &resFullPath) +bool MyGetFullPathName(CFSTR path, FString &resFullPath) { - resFullPath = fileName; + resFullPath = path; return true; } #else -#ifdef WIN_LONG_PATH - -static FString GetLastPart(CFSTR path) -{ - int i = MyStringLen(path); - for (; i > 0; i--) - { - FChar c = path[i - 1]; - if (c == FCHAR_PATH_SEPARATOR || c == '/') - break; - } - return path + i; -} - -static void AddTrailingDots(CFSTR oldPath, FString &newPath) -{ - int len = MyStringLen(oldPath); - int i; - for (i = len; i > 0 && oldPath[i - 1] == '.'; i--); - if (i == 0 || i == len) - return; - FString oldName = GetLastPart(oldPath); - FString 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(CFSTR fileName, FString &resFullPath) +bool MyGetFullPathName(CFSTR path, FString &resFullPath) { - resFullPath.Empty(); - #ifndef _UNICODE - if (!g_IsNT) - { - TCHAR s[MAX_PATH + 2]; - s[0] = 0; - LPTSTR fileNamePointer = 0; - DWORD needLength = ::GetFullPathName(fs2fas(fileName), MAX_PATH + 1, s, &fileNamePointer); - if (needLength == 0 || needLength > MAX_PATH) - return false; - resFullPath = fas2fs(s); - return true; - } - else - #endif - { - LPWSTR fileNamePointer = 0; - WCHAR s[MAX_PATH + 2]; - s[0] = 0; - DWORD needLength = ::GetFullPathNameW(fs2us(fileName), MAX_PATH + 1, s, &fileNamePointer); - if (needLength == 0) - return false; - if (needLength <= MAX_PATH) - { - resFullPath = us2fs(s); - return true; - } - #ifdef WIN_LONG_PATH - needLength++; - UString temp; - LPWSTR buffer = temp.GetBuffer(needLength + 1); - buffer[0] = 0; - DWORD needLength2 = ::GetFullPathNameW(fs2us(fileName), needLength, buffer, &fileNamePointer); - temp.ReleaseBuffer(); - if (needLength2 > 0 && needLength2 <= needLength) - { - resFullPath = us2fs(temp); - AddTrailingDots(fileName, resFullPath); - return true; - } - #endif - return false; - } + return GetFullPath(path, resFullPath); } -bool MySetCurrentDirectory(CFSTR path) +bool SetCurrentDir(CFSTR path) { + // SetCurrentDirectory doesn't support \\?\ prefix #ifndef _UNICODE if (!g_IsNT) { @@ -401,7 +400,7 @@ bool MySetCurrentDirectory(CFSTR path) } } -bool MyGetCurrentDirectory(FString &path) +bool GetCurrentDir(FString &path) { path.Empty(); DWORD needLength; @@ -428,15 +427,12 @@ bool MyGetCurrentDirectory(FString &path) bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName) { - bool res = MyGetFullPathName(path, resFileName); + bool res = MyGetFullPathName(path, resDirPrefix); if (!res) - resFileName = path; - int pos = resFileName.ReverseFind(FCHAR_PATH_SEPARATOR); - if (pos >= 0) - { - resDirPrefix = resFileName.Left(pos + 1); - resFileName = resFileName.Mid(pos + 1); - } + resDirPrefix = path; + int pos = resDirPrefix.ReverseFind(FCHAR_PATH_SEPARATOR); + resFileName = resDirPrefix.Ptr(pos + 1); + resDirPrefix.DeleteFrom(pos + 1); return res; } @@ -510,7 +506,7 @@ static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COu } else { - if (MyCreateDirectory(path)) + if (CreateDir(path)) return true; } DWORD error = GetLastError(); @@ -580,7 +576,7 @@ bool CTempDir::Remove() { if (!_mustBeDeleted) return true; - _mustBeDeleted = !RemoveDirectoryWithSubItems(_path); + _mustBeDeleted = !RemoveDirWithSubItems(_path); return !_mustBeDeleted; } diff --git a/CPP/Windows/FileDir.h b/CPP/Windows/FileDir.h old mode 100755 new mode 100644 index e43c19bd..02d3e5a5 --- a/CPP/Windows/FileDir.h +++ b/CPP/Windows/FileDir.h @@ -4,27 +4,29 @@ #define __WINDOWS_FILE_DIR_H #include "../Common/MyString.h" + #include "FileIO.h" namespace NWindows { namespace NFile { -namespace NDirectory { - -#ifdef WIN_LONG_PATH -bool GetLongPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2); -#endif +namespace NDir { -bool MyGetWindowsDirectory(FString &path); -bool MyGetSystemDirectory(FString &path); +bool GetWindowsDir(FString &path); +bool GetSystemDir(FString &path); -bool SetDirTime(CFSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); -bool MySetFileAttributes(CFSTR fileName, DWORD fileAttributes); +bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); +bool SetFileAttrib(CFSTR path, DWORD attrib); bool MyMoveFile(CFSTR existFileName, CFSTR newFileName); -bool MyRemoveDirectory(CFSTR path); -bool MyCreateDirectory(CFSTR path); -bool CreateComplexDirectory(CFSTR path); + +#ifndef UNDER_CE +bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName); +#endif + +bool RemoveDir(CFSTR path); +bool CreateDir(CFSTR path); +bool CreateComplexDir(CFSTR path); bool DeleteFileAlways(CFSTR name); -bool RemoveDirectoryWithSubItems(const FString &path); +bool RemoveDirWithSubItems(const FString &path); bool MyGetFullPathName(CFSTR path, FString &resFullPath); bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName); @@ -32,8 +34,8 @@ bool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix); #ifndef UNDER_CE -bool MySetCurrentDirectory(CFSTR path); -bool MyGetCurrentDirectory(FString &resultPath); +bool SetCurrentDir(CFSTR path); +bool GetCurrentDir(FString &resultPath); #endif @@ -67,6 +69,29 @@ public: bool Remove(); }; +#if !defined(UNDER_CE) +class CCurrentDirRestorer +{ + FString _path; +public: + bool NeedRestore; + + CCurrentDirRestorer(): NeedRestore(true) + { + GetCurrentDir(_path); + } + ~CCurrentDirRestorer() + { + if (!NeedRestore) + return; + FString s; + if (GetCurrentDir(s)) + if (s != _path) + SetCurrentDir(_path); + } +}; +#endif + }}} #endif diff --git a/CPP/Windows/FileFind.cpp b/CPP/Windows/FileFind.cpp old mode 100755 new mode 100644 index 081bd9bc..6d81ae85 --- a/CPP/Windows/FileFind.cpp +++ b/CPP/Windows/FileFind.cpp @@ -4,6 +4,7 @@ #include "FileFind.h" #include "FileIO.h" +#include "FileName.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif @@ -12,15 +13,43 @@ extern bool g_IsNT; #endif +using namespace NWindows; +using namespace NFile; +using namespace NName; + +#if defined(_WIN32) && !defined(UNDER_CE) + +EXTERN_C_BEGIN + +typedef enum +{ + My_FindStreamInfoStandard, + My_FindStreamInfoMaxInfoLevel +} MY_STREAM_INFO_LEVELS; + +typedef struct +{ + LARGE_INTEGER StreamSize; + WCHAR cStreamName[MAX_PATH + 36]; +} MY_WIN32_FIND_STREAM_DATA, *MY_PWIN32_FIND_STREAM_DATA; + +typedef WINBASEAPI HANDLE (WINAPI *FindFirstStreamW_Ptr)(LPCWSTR fileName, MY_STREAM_INFO_LEVELS infoLevel, + LPVOID findStreamData, DWORD flags); + +typedef WINBASEAPI BOOL (APIENTRY *FindNextStreamW_Ptr)(HANDLE findStream, LPVOID findStreamData); + +EXTERN_C_END + +#endif + namespace NWindows { namespace NFile { #ifdef SUPPORT_DEVICE_FILE -bool IsDeviceName(CFSTR n); -#endif - -#if defined(WIN_LONG_PATH) -bool GetLongPath(CFSTR fileName, UString &res); +namespace NSystem +{ +bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); +} #endif namespace NFind { @@ -31,7 +60,7 @@ bool CFileInfo::IsDots() const return false; if (Name[0] != FTEXT('.')) return false; - return Name.Length() == 1 || (Name.Length() == 2 && Name[1] == FTEXT('.')); + return Name.Len() == 1 || (Name.Len() == 2 && Name[1] == FTEXT('.')); } #define WIN_FD_TO_MY_FI(fi, fd) \ @@ -40,6 +69,7 @@ bool CFileInfo::IsDots() const fi.ATime = fd.ftLastAccessTime; \ fi.MTime = fd.ftLastWriteTime; \ fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; \ + fi.IsAltStream = false; \ fi.IsDevice = false; /* @@ -50,27 +80,31 @@ bool CFileInfo::IsDots() const #endif */ -static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfo &fi) +static void Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfo &fi) { WIN_FD_TO_MY_FI(fi, fd); fi.Name = us2fs(fd.cFileName); + #if defined(_WIN32) && !defined(UNDER_CE) + // fi.ShortName = us2fs(fd.cAlternateFileName); + #endif } #ifndef _UNICODE -static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } - -static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi) +static void Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi) { WIN_FD_TO_MY_FI(fi, fd); fi.Name = fas2fs(fd.cFileName); + #if defined(_WIN32) && !defined(UNDER_CE) + // fi.ShortName = fas2fs(fd.cAlternateFileName); + #endif } #endif //////////////////////////////// // CFindFile -bool CFindFile::Close() +bool CFindFileBase::Close() { if (_handle == INVALID_HANDLE_VALUE) return true; @@ -80,7 +114,7 @@ bool CFindFile::Close() return true; } -bool CFindFile::FindFirst(CFSTR wildcard, CFileInfo &fi) +bool CFindFile::FindFirst(CFSTR path, CFileInfo &fi) { if (!Close()) return false; @@ -88,27 +122,29 @@ bool CFindFile::FindFirst(CFSTR wildcard, CFileInfo &fi) if (!g_IsNT) { WIN32_FIND_DATAA fd; - _handle = ::FindFirstFileA(fs2fas(wildcard), &fd); + _handle = ::FindFirstFileA(fs2fas(path), &fd); if (_handle == INVALID_HANDLE_VALUE) return false; - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); + Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi); } else #endif { WIN32_FIND_DATAW fd; - _handle = ::FindFirstFileW(fs2us(wildcard), &fd); + + IF_USE_MAIN_PATH + _handle = ::FindFirstFileW(fs2us(path), &fd); #ifdef WIN_LONG_PATH - if (_handle == INVALID_HANDLE_VALUE) + if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH) { UString longPath; - if (GetLongPath(wildcard, longPath)) + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) _handle = ::FindFirstFileW(longPath, &fd); } #endif if (_handle == INVALID_HANDLE_VALUE) return false; - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); + Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi); } return true; } @@ -121,7 +157,7 @@ bool CFindFile::FindNext(CFileInfo &fi) WIN32_FIND_DATAA fd; if (!::FindNextFileA(_handle, &fd)) return false; - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); + Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi); } else #endif @@ -129,11 +165,117 @@ bool CFindFile::FindNext(CFileInfo &fi) WIN32_FIND_DATAW fd; if (!::FindNextFileW(_handle, &fd)) return false; - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); + Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi); + } + return true; +} + +#if defined(_WIN32) && !defined(UNDER_CE) + +//////////////////////////////// +// AltStreams + +static FindFirstStreamW_Ptr g_FindFirstStreamW; +static FindNextStreamW_Ptr g_FindNextStreamW; + +struct CFindStreamLoader +{ + CFindStreamLoader() + { + g_FindFirstStreamW = (FindFirstStreamW_Ptr)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "FindFirstStreamW"); + g_FindNextStreamW = (FindNextStreamW_Ptr)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "FindNextStreamW"); + } +} g_FindStreamLoader; + +bool CStreamInfo::IsMainStream() const +{ + return Name == L"::$DATA"; +}; + +UString CStreamInfo::GetReducedName() const +{ + UString s = Name; + if (s.Len() >= 6) + if (wcscmp(s.RightPtr(6), L":$DATA") == 0) + s.DeleteFrom(s.Len() - 6); + return s; +} + +static void Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(const MY_WIN32_FIND_STREAM_DATA &sd, CStreamInfo &si) +{ + si.Size = sd.StreamSize.QuadPart; + si.Name = sd.cStreamName; +} + +bool CFindStream::FindFirst(CFSTR path, CStreamInfo &si) +{ + if (!Close()) + return false; + if (!g_FindFirstStreamW) + { + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return false; + } + { + MY_WIN32_FIND_STREAM_DATA sd; + IF_USE_MAIN_PATH + _handle = g_FindFirstStreamW(fs2us(path), My_FindStreamInfoStandard, &sd, 0); + if (_handle == INVALID_HANDLE_VALUE) + { + if (::GetLastError() == ERROR_HANDLE_EOF) + return false; + // long name can be tricky for path like ".\dirName". + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH) + { + UString longPath; + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) + _handle = g_FindFirstStreamW(longPath, My_FindStreamInfoStandard, &sd, 0); + } + #endif + } + if (_handle == INVALID_HANDLE_VALUE) + return false; + Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(sd, si); + } + return true; +} + +bool CFindStream::FindNext(CStreamInfo &si) +{ + if (!g_FindNextStreamW) + { + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return false; + } + { + MY_WIN32_FIND_STREAM_DATA sd; + if (!g_FindNextStreamW(_handle, &sd)) + return false; + Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(sd, si); } return true; } +bool CStreamEnumerator::Next(CStreamInfo &si, bool &found) +{ + bool res; + if (_find.IsHandleAllocated()) + res = _find.FindNext(si); + else + res = _find.FindFirst(_filePath, si); + if (res) + { + found = true; + return true; + } + found = false; + return (::GetLastError() == ERROR_HANDLE_EOF); +} + +#endif + + #define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0; void CFileInfoBase::Clear() @@ -143,46 +285,134 @@ void CFileInfoBase::Clear() MY_CLEAR_FILETIME(ATime); MY_CLEAR_FILETIME(MTime); Attrib = 0; + IsAltStream = false; + IsDevice = false; } - -bool CFileInfo::Find(CFSTR wildcard) + +#if defined(_WIN32) && !defined(UNDER_CE) + +static int FindAltStreamColon(CFSTR path) +{ + for (int i = 0;; i++) + { + FChar c = path[i]; + if (c == 0) + return -1; + if (c == ':') + { + if (path[i + 1] == '\\') + if (i == 1 || (i > 1 && path[i - 2] == '\\')) + { + wchar_t c0 = path[i - 1]; + if (c0 >= 'a' && c0 <= 'z' || + c0 >= 'A' && c0 <= 'Z') + continue; + } + return i; + } + } +} + +#endif + +bool CFileInfo::Find(CFSTR path) { #ifdef SUPPORT_DEVICE_FILE - if (IsDeviceName(wildcard)) + if (IsDevicePath(path)) { Clear(); + Name = path + 4; + IsDevice = true; + if (/* path[0] == '\\' && path[1] == '\\' && path[2] == '.' && path[3] == '\\' && */ + path[5] == ':' && path[6] == 0) + { + FChar drive[4] = { path[4], ':', '\\', 0 }; + UInt64 clusterSize, totalSize, freeSize; + if (NSystem::MyGetDiskFreeSpace(drive, clusterSize, totalSize, freeSize)) + { + Size = totalSize; + return true; + } + } + NIO::CInFile inFile; - if (!inFile.Open(wildcard)) + // ::OutputDebugStringW(path); + if (!inFile.Open(path)) return false; - Name = wildcard + 4; - if (inFile.LengthDefined) - Size = inFile.Length; + // ::OutputDebugStringW(L"---"); + if (inFile.SizeDefined) + Size = inFile.Size; return true; } #endif + + #if defined(_WIN32) && !defined(UNDER_CE) + + int colonPos = FindAltStreamColon(path); + if (colonPos >= 0) + { + UString streamName = fs2us(path + (unsigned)colonPos); + FString filePath = path; + filePath.DeleteFrom(colonPos); + streamName += L":$DATA"; // change it!!!! + if (Find(filePath)) + { + // if (IsDir()) + Attrib &= ~FILE_ATTRIBUTE_DIRECTORY; + Size = 0; + CStreamEnumerator enumerator(filePath); + for (;;) + { + CStreamInfo si; + bool found; + if (!enumerator.Next(si, found)) + return false; + if (!found) + { + ::SetLastError(ERROR_FILE_NOT_FOUND); + return false; + } + if (si.Name.IsEqualToNoCase(streamName)) + { + Name += us2fs(si.Name); + Name.DeleteFrom(Name.Len() - 6); + Size = si.Size; + IsAltStream = true; + return true; + } + } + } + } + + #endif + CFindFile finder; - if (finder.FindFirst(wildcard, *this)) + if (finder.FindFirst(path, *this)) return true; #ifdef _WIN32 { DWORD lastError = GetLastError(); - if (lastError == ERROR_BAD_NETPATH || lastError == ERROR_FILE_NOT_FOUND) + if (lastError == ERROR_BAD_NETPATH || + lastError == ERROR_FILE_NOT_FOUND || + lastError == ERROR_INVALID_NAME // for "\\SERVER\shared" paths that are translated to "\\?\UNC\SERVER\shared" + ) { - int len = MyStringLen(wildcard); - if (len > 2 && wildcard[0] == '\\' && wildcard[1] == '\\') + unsigned len = MyStringLen(path); + if (len > 2 && path[0] == '\\' && path[1] == '\\') { - int pos = FindCharPosInString(wildcard + 2, FTEXT('\\')); + int startPos = 2; + if (len > kSuperUncPathPrefixSize && IsSuperUncPath(path)) + startPos = kSuperUncPathPrefixSize; + int pos = FindCharPosInString(path + startPos, FTEXT('\\')); if (pos >= 0) { - pos += 2 + 1; + pos += startPos + 1; len -= pos; - CFSTR remString = wildcard + pos; - int pos2 = FindCharPosInString(remString, FTEXT('\\')); - FString s = wildcard; - if (pos2 < 0 || pos2 == len - 1) + int pos2 = FindCharPosInString(path + pos, FTEXT('\\')); + if (pos2 < 0 || pos2 == (int)len - 1) { - FString s = wildcard; + FString s = path; if (pos2 < 0) { pos2 = len; @@ -192,7 +422,7 @@ bool CFileInfo::Find(CFSTR wildcard) if (finder.FindFirst(s, *this)) if (Name == FTEXT(".")) { - Name = s.Mid(pos, pos2); + Name.SetFrom(s.Ptr(pos), pos2); return true; } ::SetLastError(lastError); @@ -266,20 +496,21 @@ bool CFindChangeNotification::Close() return true; } -HANDLE CFindChangeNotification::FindFirst(CFSTR pathName, bool watchSubtree, DWORD notifyFilter) +HANDLE CFindChangeNotification::FindFirst(CFSTR path, bool watchSubtree, DWORD notifyFilter) { #ifndef _UNICODE if (!g_IsNT) - _handle = ::FindFirstChangeNotification(fs2fas(pathName), BoolToBOOL(watchSubtree), notifyFilter); + _handle = ::FindFirstChangeNotification(fs2fas(path), BoolToBOOL(watchSubtree), notifyFilter); else #endif { - _handle = ::FindFirstChangeNotificationW(fs2us(pathName), BoolToBOOL(watchSubtree), notifyFilter); + IF_USE_MAIN_PATH + _handle = ::FindFirstChangeNotificationW(fs2us(path), BoolToBOOL(watchSubtree), notifyFilter); #ifdef WIN_LONG_PATH if (!IsHandleAllocated()) { UString longPath; - if (GetLongPath(pathName, longPath)) + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); } #endif diff --git a/CPP/Windows/FileFind.h b/CPP/Windows/FileFind.h old mode 100755 new mode 100644 index 97a3b7c2..aaa7499b --- a/CPP/Windows/FileFind.h +++ b/CPP/Windows/FileFind.h @@ -4,7 +4,6 @@ #define __WINDOWS_FILE_FIND_H #include "../Common/MyString.h" -#include "../Common/Types.h" #include "Defs.h" namespace NWindows { @@ -25,14 +24,13 @@ namespace NAttributes 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 IsAltStream; bool IsDevice; /* @@ -43,6 +41,11 @@ public: #endif */ + CFileInfoBase() { Clear(); } + void Clear() throw(); + + void SetAsDir() { Attrib = FILE_ATTRIBUTE_DIRECTORY; } + bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); } bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); } bool IsDir() const { return MatchesMask(FILE_ATTRIBUTE_DIRECTORY); } @@ -60,24 +63,63 @@ public: struct CFileInfo: public CFileInfoBase { FString Name; + #if defined(_WIN32) && !defined(UNDER_CE) + // FString ShortName; + #endif - bool IsDots() const; + bool IsDots() const throw(); bool Find(CFSTR wildcard); }; -class CFindFile +class CFindFileBase { - friend class CEnumerator; +protected: HANDLE _handle; public: bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; } - CFindFile(): _handle(INVALID_HANDLE_VALUE) {} - ~CFindFile() { Close(); } + CFindFileBase(): _handle(INVALID_HANDLE_VALUE) {} + ~CFindFileBase() { Close(); } + bool Close() throw(); +}; + +class CFindFile: public CFindFileBase +{ +public: bool FindFirst(CFSTR wildcard, CFileInfo &fileInfo); bool FindNext(CFileInfo &fileInfo); - bool Close(); }; +#if defined(_WIN32) && !defined(UNDER_CE) + +struct CStreamInfo +{ + UString Name; + UInt64 Size; + + UString GetReducedName() const; + bool IsMainStream() const throw(); +}; + +class CFindStream: public CFindFileBase +{ +public: + bool FindFirst(CFSTR filePath, CStreamInfo &streamInfo); + bool FindNext(CStreamInfo &streamInfo); +}; + +class CStreamEnumerator +{ + CFindStream _find; + FString _filePath; + + bool NextAny(CFileInfo &fileInfo); +public: + CStreamEnumerator(const FString &filePath): _filePath(filePath) {} + bool Next(CStreamInfo &streamInfo, bool &found); +}; + +#endif + bool DoesFileExist(CFSTR name); bool DoesDirExist(CFSTR name); bool DoesFileOrDirExist(CFSTR name); @@ -102,7 +144,7 @@ public: bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE && _handle != 0; } CFindChangeNotification(): _handle(INVALID_HANDLE_VALUE) {} ~CFindChangeNotification() { Close(); } - bool Close(); + bool Close() throw(); HANDLE FindFirst(CFSTR pathName, bool watchSubtree, DWORD notifyFilter); bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); } }; diff --git a/CPP/Windows/FileIO.cpp b/CPP/Windows/FileIO.cpp old mode 100755 new mode 100644 index e8f98747..188f85fe --- a/CPP/Windows/FileIO.cpp +++ b/CPP/Windows/FileIO.cpp @@ -2,88 +2,35 @@ #include "StdAfx.h" +#ifdef SUPPORT_DEVICE_FILE +#include "../../C/Alloc.h" +#endif + #include "FileIO.h" +#include "FileName.h" #ifndef _UNICODE extern bool g_IsNT; #endif +using namespace NWindows; +using namespace NFile; +using namespace NName; + namespace NWindows { namespace NFile { #ifdef SUPPORT_DEVICE_FILE -bool IsDeviceName(CFSTR n) +namespace NSystem { - #ifdef UNDER_CE - int len = (int)MyStringLen(n); - if (len < 5 || len > 5 || memcmp(n, FTEXT("DSK"), 3 * sizeof(FCHAR)) != 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, FTEXT("PhysicalDrive"), 13 * sizeof(FCHAR)) != 0) - return false; - for (int i = 17; i < len; i++) - if (n[i] < '0' || n[i] > '9') - return false; - #endif - return true; -} - -#endif - -#if defined(WIN_LONG_PATH) && defined(_UNICODE) -#define WIN_LONG_PATH2 -#endif - -#ifdef WIN_LONG_PATH -bool GetLongPathBase(CFSTR s, UString &res) -{ - res.Empty(); - int len = MyStringLen(s); - FChar c = s[0]; - if (len < 1 || c == '\\' || c == '.' && (len == 1 || len == 2 && s[1] == '.')) - return true; - UString curDir; - bool isAbs = false; - if (len > 3) - isAbs = (s[1] == ':' && s[2] == '\\' && (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')); - - if (!isAbs) - { - WCHAR temp[MAX_PATH + 2]; - temp[0] = 0; - DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, temp); - if (needLength == 0 || needLength > MAX_PATH) - return false; - curDir = temp; - if (curDir.Back() != L'\\') - curDir += L'\\'; - } - res = UString(L"\\\\?\\") + curDir + fs2us(s); - return true; -} - -bool GetLongPath(CFSTR path, UString &longPath) -{ - if (GetLongPathBase(path, longPath)) - return !longPath.IsEmpty(); - return false; +bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); } #endif namespace NIO { -CFileBase::~CFileBase() { Close(); } - -bool CFileBase::Create(CFSTR fileName, DWORD desiredAccess, +bool CFileBase::Create(CFSTR path, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (!Close()) @@ -96,19 +43,20 @@ bool CFileBase::Create(CFSTR fileName, DWORD desiredAccess, #ifndef _UNICODE if (!g_IsNT) { - _handle = ::CreateFile(fs2fas(fileName), desiredAccess, shareMode, + _handle = ::CreateFile(fs2fas(path), desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); } else #endif { - _handle = ::CreateFileW(fs2us(fileName), desiredAccess, shareMode, + IF_USE_MAIN_PATH + _handle = ::CreateFileW(fs2us(path), desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); #ifdef WIN_LONG_PATH - if (_handle == INVALID_HANDLE_VALUE) + if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH) { UString longPath; - if (GetLongPath(fileName, longPath)) + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) _handle = ::CreateFileW(longPath, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); } @@ -135,9 +83,9 @@ bool CFileBase::GetPosition(UInt64 &position) const bool CFileBase::GetLength(UInt64 &length) const { #ifdef SUPPORT_DEVICE_FILE - if (IsDeviceFile && LengthDefined) + if (IsDeviceFile && SizeDefined) { - length = Length; + length = Size; return true; } #endif @@ -154,95 +102,192 @@ bool CFileBase::GetLength(UInt64 &length) const bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const { #ifdef SUPPORT_DEVICE_FILE - if (IsDeviceFile && LengthDefined && moveMethod == FILE_END) + if (IsDeviceFile && SizeDefined && moveMethod == FILE_END) { - distanceToMove += Length; + distanceToMove += Size; moveMethod = FILE_BEGIN; } #endif - LARGE_INTEGER value; - value.QuadPart = distanceToMove; - value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod); - if (value.LowPart == 0xFFFFFFFF) + LONG high = (LONG)(distanceToMove >> 32); + DWORD low = ::SetFilePointer(_handle, (LONG)(distanceToMove & 0xFFFFFFFF), &high, moveMethod); + if (low == 0xFFFFFFFF) if (::GetLastError() != NO_ERROR) return false; - newPosition = value.QuadPart; + newPosition = (((UInt64)high) << 32) + low; return true; } -bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) +bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) const { return Seek(position, FILE_BEGIN, newPosition); } -bool CFileBase::SeekToBegin() +bool CFileBase::SeekToBegin() const { UInt64 newPosition; return Seek(0, newPosition); } -bool CFileBase::SeekToEnd(UInt64 &newPosition) +bool CFileBase::SeekToEnd(UInt64 &newPosition) const { return Seek(0, FILE_END, newPosition); } -/* -bool CFileBase::GetFileInformation(CByHandleFileInfo &fi) const -{ - BY_HANDLE_FILE_INFORMATION wfi; - if (!::GetFileInformationByHandle(_handle, &wfi)) - return false; - fi.Attrib = wfi.dwFileAttributes; - fi.CTime = wfi.ftCreationTime; - fi.ATime = wfi.ftLastAccessTime; - fi.MTime = wfi.ftLastWriteTime; - fi.Size = (((UInt64)wfi.nFileSizeHigh) << 32) + wfi.nFileSizeLow; - fi.VolumeSerialNumber = wfi.dwVolumeSerialNumber; - fi.NumLinks = wfi.nNumberOfLinks; - fi.FileIndex = (((UInt64)wfi.nFileIndexHigh) << 32) + wfi.nFileIndexLow; - return true; -} -*/ - -///////////////////////// -// CInFile +// ---------- CInFile --------- #ifdef SUPPORT_DEVICE_FILE -void CInFile::GetDeviceLength() + +void CInFile::CorrectDeviceSize() { - if (_handle != INVALID_HANDLE_VALUE && IsDeviceFile) + // maybe we must decrease kClusterSize to 1 << 12, if we want correct size at tail + static const UInt32 kClusterSize = 1 << 14; + UInt64 pos = Size & ~(UInt64)(kClusterSize - 1); + UInt64 realNewPosition; + if (!Seek(pos, realNewPosition)) + return; + Byte *buf = (Byte *)MidAlloc(kClusterSize); + + bool needbackward = true; + + for (;;) { - #ifdef UNDER_CE - LengthDefined = true; - Length = 128 << 20; + UInt32 processed = 0; + // up test is slow for "PhysicalDrive". + // processed size for latest block for "PhysicalDrive0" is 0. + if (!Read1(buf, kClusterSize, processed)) + break; + if (processed == 0) + break; + needbackward = false; + Size = pos + processed; + if (processed != kClusterSize) + break; + pos += kClusterSize; + } + + if (needbackward && pos != 0) + { + pos -= kClusterSize; + for (;;) + { + // break; + if (!Seek(pos, realNewPosition)) + break; + if (!buf) + { + buf = (Byte *)MidAlloc(kClusterSize); + if (!buf) + break; + } + UInt32 processed = 0; + // that code doesn't work for "PhysicalDrive0" + if (!Read1(buf, kClusterSize, processed)) + break; + if (processed != 0) + { + Size = pos + processed; + break; + } + if (pos == 0) + break; + pos -= kClusterSize; + } + } + MidFree(buf); +} - #else - PARTITION_INFORMATION partInfo; - LengthDefined = true; - Length = 0; - if (GetPartitionInfo(&partInfo)) - Length = partInfo.PartitionLength.QuadPart; +void CInFile::CalcDeviceSize(CFSTR s) +{ + SizeDefined = false; + Size = 0; + if (_handle == INVALID_HANDLE_VALUE || !IsDeviceFile) + return; + #ifdef UNDER_CE + + SizeDefined = true; + Size = 128 << 20; + + #else + + PARTITION_INFORMATION partInfo; + bool needCorrectSize = true; + + /* + WinXP 64-bit: + + HDD \\.\PhysicalDrive0 (MBR): + GetPartitionInfo == GeometryEx : corrrect size? (includes tail) + Geometry : smaller than GeometryEx (no tail, maybe correct too?) + MyGetDiskFreeSpace : FAIL + Size correction is slow and block size (kClusterSize) must be small? + + HDD partition \\.\N: (NTFS): + MyGetDiskFreeSpace : Size of NTFS clusters. Same size can be calculated after correction + GetPartitionInfo : size of partition data: NTFS clusters + TAIL; TAIL contains extra empty sectors and copy of first sector of NTFS + Geometry / CdRomGeometry / GeometryEx : size of HDD (not that partition) + + CD-ROM drive (ISO): + MyGetDiskFreeSpace : correct size. Same size can be calculated after correction + Geometry == CdRomGeometry : smaller than corrrect size + GetPartitionInfo == GeometryEx : larger than corrrect size + + Floppy \\.\a: (FAT): + Geometry : correct size. + CdRomGeometry / GeometryEx / GetPartitionInfo / MyGetDiskFreeSpace - FAIL + correction works OK for FAT. + correction works OK for non-FAT, if kClusterSize = 512. + */ + + if (GetPartitionInfo(&partInfo)) + { + Size = partInfo.PartitionLength.QuadPart; + SizeDefined = true; + needCorrectSize = false; + if ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '.' && (s)[3] == '\\' && (s)[5] == ':' && (s)[6] == 0) + { + FChar path[4] = { s[4], ':', '\\', 0 }; + UInt64 clusterSize, totalSize, freeSize; + if (NSystem::MyGetDiskFreeSpace(path, clusterSize, totalSize, freeSize)) + Size = totalSize; + else + needCorrectSize = true; + } + } + + if (!SizeDefined) + { + my_DISK_GEOMETRY_EX geomEx; + SizeDefined = GetGeometryEx(&geomEx); + if (SizeDefined) + Size = geomEx.DiskSize.QuadPart; else { DISK_GEOMETRY geom; - if (!GetGeometry(&geom)) - if (!GetCdRomGeometry(&geom)) - LengthDefined = false; - if (LengthDefined) - Length = geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector; + SizeDefined = GetGeometry(&geom); + if (!SizeDefined) + SizeDefined = GetCdRomGeometry(&geom); + if (SizeDefined) + Size = geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector; } - // SeekToBegin(); - #endif } + + if (needCorrectSize && SizeDefined && Size != 0) + { + CorrectDeviceSize(); + SeekToBegin(); + } + + // SeekToBegin(); + #endif } // ((desiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE)) == 0 && #define MY_DEVICE_EXTRA_CODE \ - IsDeviceFile = IsDeviceName(fileName); \ - GetDeviceLength(); + IsDeviceFile = IsDevicePath(fileName); \ + CalcDeviceSize(fileName); #else #define MY_DEVICE_EXTRA_CODE #endif @@ -305,8 +350,7 @@ bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) return true; } -///////////////////////// -// COutFile +// ---------- COutFile --------- static inline DWORD GetCreationDisposition(bool createAlways) { return createAlways? CREATE_ALWAYS: CREATE_NEW; } @@ -320,6 +364,9 @@ bool COutFile::Open(CFSTR fileName, DWORD creationDisposition) bool COutFile::Create(CFSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } +bool COutFile::CreateAlways(CFSTR fileName, DWORD flagsAndAttributes) + { return Open(fileName, FILE_SHARE_READ, GetCreationDisposition(true), flagsAndAttributes); } + bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); } diff --git a/CPP/Windows/FileIO.h b/CPP/Windows/FileIO.h old mode 100755 new mode 100644 index ecd7af96..7cb5e83f --- a/CPP/Windows/FileIO.h +++ b/CPP/Windows/FileIO.h @@ -3,96 +3,155 @@ #ifndef __WINDOWS_FILE_IO_H #define __WINDOWS_FILE_IO_H -#include "../Common/Types.h" #include "../Common/MyString.h" +#include "../Common/MyBuffer.h" #include "Defs.h" +#define _my_IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) +#define _my_IO_REPARSE_TAG_SYMLINK (0xA000000CL) + +#define _my_SYMLINK_FLAG_RELATIVE 1 + +#define my_FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER +#define my_FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) // REPARSE_DATA_BUFFER + namespace NWindows { namespace NFile { -namespace NIO { -/* -struct CByHandleFileInfo +bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink); + +struct CReparseShortInfo { - UInt64 Size; - FILETIME CTime; - FILETIME ATime; - FILETIME MTime; - DWORD Attrib; - DWORD VolumeSerialNumber; - DWORD NumLinks; - UInt64 FileIndex; + unsigned Offset; + unsigned Size; + + bool Parse(const Byte *p, size_t size); }; -*/ + +struct CReparseAttr +{ + UInt32 Tag; + UInt32 Flags; + UString SubsName; + UString PrintName; + + CReparseAttr(): Tag(0), Flags(0) {} + bool Parse(const Byte *p, size_t size); + + bool IsMountPoint() const { return Tag == _my_IO_REPARSE_TAG_MOUNT_POINT; } // it's Junction + bool IsSymLink() const { return Tag == _my_IO_REPARSE_TAG_SYMLINK; } + bool IsRelative() const { return Flags == _my_SYMLINK_FLAG_RELATIVE; } + // bool IsVolume() const; + + bool IsOkNamePair() const; + UString GetPath() const; +}; + +namespace NIO { + +bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo = NULL); +bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size); class CFileBase { protected: HANDLE _handle; - bool Create(CFSTR fileName, DWORD desiredAccess, + bool Create(CFSTR path, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); +public: + + bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer, DWORD inSize, + LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned, LPOVERLAPPED overlapped = NULL) const + { + return BOOLToBool(::DeviceIoControl(_handle, controlCode, inBuffer, inSize, + outBuffer, outSize, bytesReturned, overlapped)); + } + + bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned) const + { + return DeviceIoControl(controlCode, NULL, 0, outBuffer, outSize, bytesReturned); + } + + bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize) const + { + DWORD bytesReturned; + return DeviceIoControlOut(controlCode, outBuffer, outSize, &bytesReturned); + } + public: #ifdef SUPPORT_DEVICE_FILE bool IsDeviceFile; - bool LengthDefined; - UInt64 Length; + bool SizeDefined; + UInt64 Size; // it can be larger than real available size #endif CFileBase(): _handle(INVALID_HANDLE_VALUE) {}; - ~CFileBase(); + ~CFileBase() { Close(); } - bool Close(); + bool Close() throw(); - bool GetPosition(UInt64 &position) const; - bool GetLength(UInt64 &length) const; + bool GetPosition(UInt64 &position) const throw(); + bool GetLength(UInt64 &length) const throw(); - bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const; - bool Seek(UInt64 position, UInt64 &newPosition); - bool SeekToBegin(); - bool SeekToEnd(UInt64 &newPosition); + bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const throw(); + bool Seek(UInt64 position, UInt64 &newPosition) const throw(); + bool SeekToBegin() const throw(); + bool SeekToEnd(UInt64 &newPosition) const throw(); - // bool GetFileInformation(CByHandleFileInfo &fileInfo) const; + bool GetFileInformation(BY_HANDLE_FILE_INFORMATION *info) const + { return BOOLToBool(GetFileInformationByHandle(_handle, info)); } + + static bool GetFileInformation(CFSTR path, BY_HANDLE_FILE_INFORMATION *info) + { + NIO::CFileBase file; + if (!file.Create(path, 0, FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS)) + return false; + return file.GetFileInformation(info); + } }; +#ifndef UNDER_CE #define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM #define IOCTL_CDROM_GET_DRIVE_GEOMETRY CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_MEDIA_REMOVAL CTL_CODE(IOCTL_CDROM_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS) +// #define IOCTL_CDROM_MEDIA_REMOVAL CTL_CODE(IOCTL_CDROM_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS) + +// IOCTL_DISK_GET_DRIVE_GEOMETRY_EX works since WinXP +#define my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX CTL_CODE(IOCTL_DISK_BASE, 0x0028, METHOD_BUFFERED, FILE_ANY_ACCESS) + +struct my_DISK_GEOMETRY_EX +{ + DISK_GEOMETRY Geometry; + LARGE_INTEGER DiskSize; + BYTE Data[1]; +}; +#endif class CInFile: public CFileBase { #ifdef SUPPORT_DEVICE_FILE - 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 GetGeometryEx(my_DISK_GEOMETRY_EX *res) const + { return DeviceIoControlOut(my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, res, sizeof(*res)); } + bool GetCdRomGeometry(DISK_GEOMETRY *res) const { return DeviceIoControlOut(IOCTL_CDROM_GET_DRIVE_GEOMETRY, res, sizeof(*res)); } bool GetPartitionInfo(PARTITION_INFORMATION *res) { return DeviceIoControlOut(IOCTL_DISK_GET_PARTITION_INFO, LPVOID(res), sizeof(*res)); } + #endif - void GetDeviceLength(); + void CorrectDeviceSize(); + void CalcDeviceSize(CFSTR name); + #endif public: @@ -100,9 +159,19 @@ public: bool OpenShared(CFSTR fileName, bool shareForWrite); bool Open(CFSTR fileName); - bool Read1(void *data, UInt32 size, UInt32 &processedSize); - bool ReadPart(void *data, UInt32 size, UInt32 &processedSize); - bool Read(void *data, UInt32 size, UInt32 &processedSize); + #ifndef UNDER_CE + + bool OpenReparse(CFSTR fileName) + { + return Open(fileName, FILE_SHARE_READ, OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS); + } + + #endif + + bool Read1(void *data, UInt32 size, UInt32 &processedSize) throw(); + bool ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw(); + bool Read(void *data, UInt32 size, UInt32 &processedSize) throw(); }; class COutFile: public CFileBase @@ -111,13 +180,14 @@ public: bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(CFSTR fileName, DWORD creationDisposition); bool Create(CFSTR fileName, bool createAlways); - - 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); + bool CreateAlways(CFSTR fileName, DWORD flagsAndAttributes); + + bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw(); + bool SetMTime(const FILETIME *mTime) throw(); + bool WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw(); + bool Write(const void *data, UInt32 size, UInt32 &processedSize) throw(); + bool SetEndOfFile() throw(); + bool SetLength(UInt64 length) throw(); }; }}} diff --git a/CPP/Windows/FileLink.cpp b/CPP/Windows/FileLink.cpp new file mode 100644 index 00000000..90ffc420 --- /dev/null +++ b/CPP/Windows/FileLink.cpp @@ -0,0 +1,426 @@ +// Windows/FileLink.cpp + +#include "StdAfx.h" + +#include "../../C/CpuArch.h" + +#ifdef SUPPORT_DEVICE_FILE +#include "../../C/Alloc.h" +#endif + +#include "FileDir.h" +#include "FileFind.h" +#include "FileIO.h" +#include "FileName.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NFile { + +using namespace NName; + +/* + Reparse Points (Junctions and Symbolic Links): + struct + { + UInt32 Tag; + UInt16 Size; // not including starting 8 bytes + UInt16 Reserved; // = 0 + + UInt16 SubstituteOffset; // offset in bytes from start of namesChars + UInt16 SubstituteLen; // size in bytes, it doesn't include tailed NUL + UInt16 PrintOffset; // offset in bytes from start of namesChars + UInt16 PrintLen; // size in bytes, it doesn't include tailed NUL + + [UInt32] Flags; // for Symbolic Links only. + + UInt16 namesChars[] + } + + MOUNT_POINT (Junction point): + 1) there is NUL wchar after path + 2) Default Order in table: + Substitute Path + Print Path + 3) pathnames can not contain dot directory names + + SYMLINK: + 1) there is no NUL wchar after path + 2) Default Order in table: + Print Path + Substitute Path +*/ + +/* +static const UInt32 kReparseFlags_Alias = (1 << 29); +static const UInt32 kReparseFlags_HighLatency = (1 << 30); +static const UInt32 kReparseFlags_Microsoft = ((UInt32)1 << 31); + +#define _my_IO_REPARSE_TAG_HSM (0xC0000004L) +#define _my_IO_REPARSE_TAG_HSM2 (0x80000006L) +#define _my_IO_REPARSE_TAG_SIS (0x80000007L) +#define _my_IO_REPARSE_TAG_WIM (0x80000008L) +#define _my_IO_REPARSE_TAG_CSV (0x80000009L) +#define _my_IO_REPARSE_TAG_DFS (0x8000000AL) +#define _my_IO_REPARSE_TAG_DFSR (0x80000012L) +*/ + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) + +#define Set16(p, v) SetUi16(p, v) +#define Set32(p, v) SetUi32(p, v) + +static const wchar_t *k_LinkPrefix = L"\\??\\"; +static const unsigned k_LinkPrefix_Size = 4; + +static const bool IsLinkPrefix(const wchar_t *s) +{ + return IsString1PrefixedByString2(s, k_LinkPrefix); +} + +/* +static const wchar_t *k_VolumePrefix = L"Volume{"; +static const bool IsVolumeName(const wchar_t *s) +{ + return IsString1PrefixedByString2(s, k_VolumePrefix); +} +*/ + +void WriteString(Byte *dest, const wchar_t *path) +{ + for (;;) + { + wchar_t c = *path++; + if (c == 0) + return; + Set16(dest, (UInt16)c); + dest += 2; + } +} + +bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink) +{ + bool isAbs = IsAbsolutePath(path); + if (!isAbs && !isSymLink) + return false; + + bool needPrintName = true; + + if (IsSuperPath(path)) + { + path += kSuperPathPrefixSize; + if (!IsDrivePath(path)) + needPrintName = false; + } + + const unsigned add_Prefix_Len = isAbs ? k_LinkPrefix_Size : 0; + + unsigned len2 = MyStringLen(path) * 2; + const unsigned len1 = len2 + add_Prefix_Len * 2; + if (!needPrintName) + len2 = 0; + + unsigned totalNamesSize = (len1 + len2); + + /* some WIM imagex software uses old scheme for symbolic links. + so we can old scheme for byte to byte compatibility */ + + bool newOrderScheme = isSymLink; + // newOrderScheme = false; + + if (!newOrderScheme) + totalNamesSize += 2 * 2; + + const size_t size = 8 + 8 + (isSymLink ? 4 : 0) + totalNamesSize; + dest.Alloc(size); + memset(dest, 0, size); + const UInt32 tag = isSymLink ? + _my_IO_REPARSE_TAG_SYMLINK : + _my_IO_REPARSE_TAG_MOUNT_POINT; + Byte *p = dest; + Set32(p, tag); + Set16(p + 4, (UInt16)(size - 8)); + Set16(p + 6, 0); + p += 8; + + unsigned subOffs = 0; + unsigned printOffs = 0; + if (newOrderScheme) + subOffs = len2; + else + printOffs = len1 + 2; + + Set16(p + 0, (UInt16)subOffs); + Set16(p + 2, (UInt16)len1); + Set16(p + 4, (UInt16)printOffs); + Set16(p + 6, (UInt16)len2); + + p += 8; + if (isSymLink) + { + UInt32 flags = isAbs ? 0 : _my_SYMLINK_FLAG_RELATIVE; + Set32(p, flags); + p += 4; + } + + if (add_Prefix_Len != 0) + WriteString(p + subOffs, k_LinkPrefix); + WriteString(p + subOffs + add_Prefix_Len * 2, path); + if (needPrintName) + WriteString(p + printOffs, path); + return true; +} + +static void GetString(const Byte *p, unsigned len, UString &res) +{ + wchar_t *s = res.GetBuffer(len); + for (unsigned i = 0; i < len; i++) + s[i] = Get16(p + i * 2); + s[len] = 0; + res.ReleaseBuffer(); +} + +bool CReparseAttr::Parse(const Byte *p, size_t size) +{ + if (size < 8) + return false; + Tag = Get32(p); + UInt32 len = Get16(p + 4); + if (len + 8 > size) + return false; + /* + if ((type & kReparseFlags_Alias) == 0 || + (type & kReparseFlags_Microsoft) == 0 || + (type & 0xFFFF) != 3) + */ + if (Tag != _my_IO_REPARSE_TAG_MOUNT_POINT && + Tag != _my_IO_REPARSE_TAG_SYMLINK) + // return true; + return false; + + if (Get16(p + 6) != 0) // padding + return false; + + p += 8; + size -= 8; + + if (len != size) // do we need that check? + return false; + + if (len < 8) + return false; + unsigned subOffs = Get16(p); + unsigned subLen = Get16(p + 2); + unsigned printOffs = Get16(p + 4); + unsigned printLen = Get16(p + 6); + len -= 8; + p += 8; + + Flags = 0; + if (Tag == _my_IO_REPARSE_TAG_SYMLINK) + { + if (len < 4) + return false; + Flags = Get32(p); + len -= 4; + p += 4; + } + + if ((subOffs & 1) != 0 || subOffs > len || len - subOffs < subLen) + return false; + if ((printOffs & 1) != 0 || printOffs > len || len - printOffs < printLen) + return false; + GetString(p + subOffs, subLen >> 1, SubsName); + GetString(p + printOffs, printLen >> 1, PrintName); + + return true; +} + +bool CReparseShortInfo::Parse(const Byte *p, size_t size) +{ + const Byte *start = p; + Offset= 0; + Size = 0; + if (size < 8) + return false; + UInt32 Tag = Get32(p); + UInt32 len = Get16(p + 4); + if (len + 8 > size) + return false; + /* + if ((type & kReparseFlags_Alias) == 0 || + (type & kReparseFlags_Microsoft) == 0 || + (type & 0xFFFF) != 3) + */ + if (Tag != _my_IO_REPARSE_TAG_MOUNT_POINT && + Tag != _my_IO_REPARSE_TAG_SYMLINK) + // return true; + return false; + + if (Get16(p + 6) != 0) // padding + return false; + + p += 8; + size -= 8; + + if (len != size) // do we need that check? + return false; + + if (len < 8) + return false; + unsigned subOffs = Get16(p); + unsigned subLen = Get16(p + 2); + unsigned printOffs = Get16(p + 4); + unsigned printLen = Get16(p + 6); + len -= 8; + p += 8; + + UInt32 Flags = 0; + if (Tag == _my_IO_REPARSE_TAG_SYMLINK) + { + if (len < 4) + return false; + Flags = Get32(p); + len -= 4; + p += 4; + } + + if ((subOffs & 1) != 0 || subOffs > len || len - subOffs < subLen) + return false; + if ((printOffs & 1) != 0 || printOffs > len || len - printOffs < printLen) + return false; + + Offset = (unsigned)(p - start) + subOffs; + Size = subLen; + return true; +} + +bool CReparseAttr::IsOkNamePair() const +{ + if (IsLinkPrefix(SubsName)) + { + if (!IsDrivePath(SubsName.Ptr(k_LinkPrefix_Size))) + return PrintName.IsEmpty(); + if (wcscmp(SubsName.Ptr(k_LinkPrefix_Size), PrintName) == 0) + return true; + } + return wcscmp(SubsName, PrintName) == 0; +} + +/* +bool CReparseAttr::IsVolume() const +{ + if (!IsLinkPrefix(SubsName)) + return false; + return IsVolumeName(SubsName.Ptr(k_LinkPrefix_Size)); +} +*/ + +UString CReparseAttr::GetPath() const +{ + UString s = SubsName; + if (IsLinkPrefix(s)) + { + s.ReplaceOneCharAtPos(1, '\\'); + if (IsDrivePath(s.Ptr(k_LinkPrefix_Size))) + s.DeleteFrontal(k_LinkPrefix_Size); + } + return s; +} + + +#ifdef SUPPORT_DEVICE_FILE + +namespace NSystem +{ +bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); +} +#endif + +#ifndef UNDER_CE + +namespace NIO { + +bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo) +{ + reparseData.Free(); + CInFile file; + if (!file.OpenReparse(path)) + return false; + + if (fileInfo) + file.GetFileInformation(fileInfo); + + const unsigned kBufSize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE; + CByteArr buf(kBufSize); + DWORD returnedSize; + if (!file.DeviceIoControlOut(my_FSCTL_GET_REPARSE_POINT, buf, kBufSize, &returnedSize)) + return false; + reparseData.CopyFrom(buf, returnedSize); + return true; +} + +static bool CreatePrefixDirOfFile(CFSTR path) +{ + FString path2 = path; + int pos = path2.ReverseFind(FCHAR_PATH_SEPARATOR); + if (pos < 0) + return true; + #ifdef _WIN32 + if (pos == 2 && path2[1] == L':') + return true; // we don't create Disk folder; + #endif + path2.DeleteFrom(pos); + return NDir::CreateComplexDir(path2); +} + +// If there is Reprase data already, it still writes new Reparse data +bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size) +{ + NFile::NFind::CFileInfo fi; + if (fi.Find(path)) + { + if (fi.IsDir() != isDir) + { + ::SetLastError(ERROR_DIRECTORY); + return false; + } + } + else + { + if (isDir) + { + if (!NDir::CreateComplexDir(path)) + return false; + } + else + { + CreatePrefixDirOfFile(path); + COutFile file; + if (!file.Create(path, CREATE_NEW)) + return false; + } + } + + COutFile file; + if (!file.Open(path, + FILE_SHARE_WRITE, + OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS)) + return false; + + DWORD returnedSize; + if (!file.DeviceIoControl(my_FSCTL_SET_REPARSE_POINT, (void *)data, size, NULL, 0, &returnedSize)) + return false; + return true; +} + +} + +#endif + +}} diff --git a/CPP/Windows/FileMapping.cpp b/CPP/Windows/FileMapping.cpp old mode 100755 new mode 100644 diff --git a/CPP/Windows/FileMapping.h b/CPP/Windows/FileMapping.h old mode 100755 new mode 100644 index 3f0ebd74..f90c429f --- a/CPP/Windows/FileMapping.h +++ b/CPP/Windows/FileMapping.h @@ -3,7 +3,7 @@ #ifndef __WINDOWS_FILEMAPPING_H #define __WINDOWS_FILEMAPPING_H -#include "Common/Types.h" +#include "../Common/MyTypes.h" #include "Handle.h" @@ -18,7 +18,11 @@ public: return ::GetLastError(); } - WRes Open(DWORD desiredAccess, LPCTSTR name) + WRes Open(DWORD + #ifndef UNDER_CE + desiredAccess + #endif + , LPCTSTR name) { #ifdef UNDER_CE WRes res = Create(PAGE_READONLY, 0, name); diff --git a/CPP/Windows/FileName.cpp b/CPP/Windows/FileName.cpp old mode 100755 new mode 100644 index 8f464aa8..fdf8845e --- a/CPP/Windows/FileName.cpp +++ b/CPP/Windows/FileName.cpp @@ -4,26 +4,684 @@ #include "FileName.h" +#ifndef _UNICODE +extern bool g_IsNT; +#endif + namespace NWindows { namespace NFile { namespace NName { +#ifndef USE_UNICODE_FSTRING void NormalizeDirPathPrefix(FString &dirPath) { if (dirPath.IsEmpty()) return; - if (dirPath.ReverseFind(FCHAR_PATH_SEPARATOR) != dirPath.Length() - 1) + if (dirPath.Back() != FCHAR_PATH_SEPARATOR) dirPath += FCHAR_PATH_SEPARATOR; } +#endif -#ifndef USE_UNICODE_FSTRING void NormalizeDirPathPrefix(UString &dirPath) { if (dirPath.IsEmpty()) return; - if (dirPath.ReverseFind(WCHAR_PATH_SEPARATOR) != dirPath.Length() - 1) + if (dirPath.Back() != WCHAR_PATH_SEPARATOR) dirPath += WCHAR_PATH_SEPARATOR; } + + +#ifdef _WIN32 + +const wchar_t *kSuperPathPrefix = L"\\\\?\\"; +static const wchar_t *kSuperUncPrefix = L"\\\\?\\UNC\\"; + +#define IS_DEVICE_PATH(s) ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '.' && (s)[3] == '\\') +#define IS_SUPER_PREFIX(s) ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '?' && (s)[3] == '\\') +#define IS_SUPER_OR_DEVICE_PATH(s) ((s)[0] == '\\' && (s)[1] == '\\' && ((s)[2] == '?' || (s)[2] == '.') && (s)[3] == '\\') +#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z') + +#define IS_UNC_WITH_SLASH(s) ( \ + ((s)[0] == 'U' || (s)[0] == 'u') && \ + ((s)[1] == 'N' || (s)[1] == 'n') && \ + ((s)[2] == 'C' || (s)[2] == 'c') && \ + (s)[3] == '\\') + +bool IsDevicePath(CFSTR s) +{ + #ifdef UNDER_CE + + s = s; + return false; + /* + // actually we don't know the way to open device file in WinCE. + unsigned len = MyStringLen(s); + if (len < 5 || len > 5 || memcmp(s, FTEXT("DSK"), 3 * sizeof(FChar)) != 0) + return false; + if (s[4] != ':') + return false; + // for reading use SG_REQ sg; if (DeviceIoControl(dsk, IOCTL_DISK_READ)); + */ + + #else + + if (!IS_DEVICE_PATH(s)) + return false; + unsigned len = MyStringLen(s); + if (len == 6 && s[5] == ':') + return true; + if (len < 18 || len > 22 || memcmp(s + kDevicePathPrefixSize, FTEXT("PhysicalDrive"), 13 * sizeof(FChar)) != 0) + return false; + for (unsigned i = 17; i < len; i++) + if (s[i] < '0' || s[i] > '9') + return false; + return true; + + #endif +} + +bool IsSuperUncPath(CFSTR s) { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); } + +bool IsDrivePath(const wchar_t *s) { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == '\\'; } +bool IsSuperPath(const wchar_t *s) { return IS_SUPER_PREFIX(s); } +bool IsSuperOrDevicePath(const wchar_t *s) { return IS_SUPER_OR_DEVICE_PATH(s); } +// bool IsSuperUncPath(const wchar_t *s) { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); } + +#ifndef USE_UNICODE_FSTRING +bool IsDrivePath(CFSTR s) { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == '\\'; } +bool IsSuperPath(CFSTR s) { return IS_SUPER_PREFIX(s); } +bool IsSuperOrDevicePath(CFSTR s) { return IS_SUPER_OR_DEVICE_PATH(s); } +#endif // USE_UNICODE_FSTRING + +bool IsAbsolutePath(const wchar_t *s) +{ + return s[0] == WCHAR_PATH_SEPARATOR || IsDrivePath(s); +} + +static const unsigned kDrivePrefixSize = 3; /* c:\ */ + +#ifndef USE_UNICODE_FSTRING + +static unsigned GetRootPrefixSize_Of_NetworkPath(CFSTR s) +{ + // Network path: we look "server\path\" as root prefix + int pos = FindCharPosInString(s, '\\'); + if (pos < 0) + return 0; + int pos2 = FindCharPosInString(s + pos + 1, '\\'); + if (pos2 < 0) + return 0; + return pos + pos2 + 2; +} + +static unsigned GetRootPrefixSize_Of_SimplePath(CFSTR s) +{ + if (IsDrivePath(s)) + return kDrivePrefixSize; + if (s[0] != '\\' || s[1] != '\\') + return 0; + unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2); + return (size == 0) ? 0 : 2 + size; +} + +static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s) +{ + if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)) + { + unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize); + return (size == 0) ? 0 : kSuperUncPathPrefixSize + size; + } + // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\" + int pos = FindCharPosInString(s + kSuperPathPrefixSize, FCHAR_PATH_SEPARATOR); + if (pos < 0) + return 0; + return kSuperPathPrefixSize + pos + 1; +} + +unsigned GetRootPrefixSize(CFSTR s) +{ + if (IS_DEVICE_PATH(s)) + return kDevicePathPrefixSize; + if (IsSuperPath(s)) + return GetRootPrefixSize_Of_SuperPath(s); + return GetRootPrefixSize_Of_SimplePath(s); +} + +#endif // USE_UNICODE_FSTRING + +static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s) +{ + // Network path: we look "server\path\" as root prefix + int pos = FindCharPosInString(s, L'\\'); + if (pos < 0) + return 0; + int pos2 = FindCharPosInString(s + pos + 1, L'\\'); + if (pos2 < 0) + return 0; + return pos + pos2 + 2; +} + +static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s) +{ + if (IsDrivePath(s)) + return kDrivePrefixSize; + if (s[0] != '\\' || s[1] != '\\') + return 0; + unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2); + return (size == 0) ? 0 : 2 + size; +} + +static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s) +{ + if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)) + { + unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize); + return (size == 0) ? 0 : kSuperUncPathPrefixSize + size; + } + // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\" + int pos = FindCharPosInString(s + kSuperPathPrefixSize, L'\\'); + if (pos < 0) + return 0; + return kSuperPathPrefixSize + pos + 1; +} + +unsigned GetRootPrefixSize(const wchar_t *s) +{ + if (IS_DEVICE_PATH(s)) + return kDevicePathPrefixSize; + if (IsSuperPath(s)) + return GetRootPrefixSize_Of_SuperPath(s); + return GetRootPrefixSize_Of_SimplePath(s); +} + +#else // _WIN32 + +bool IsAbsolutePath(const wchar_t *s) { return s[0] == WCHAR_PATH_SEPARATOR } + +#ifndef USE_UNICODE_FSTRING +unsigned GetRootPrefixSize(CFSTR s) { return s[0] == CHAR_PATH_SEPRATOR ? 1 : 0; } +#endif +unsigned GetRootPrefixSize(const wchar_t *s) { return s[0] == CHAR_PATH_SEPRATOR ? 1 : 0; } + +#endif // _WIN32 + + +#ifndef UNDER_CE + +static bool GetCurDir(UString &path) +{ + path.Empty(); + DWORD needLength; + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetCurrentDirectory(MAX_PATH + 1, s); + path = fs2us(fas2fs(s)); + } + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, s); + path = s; + } + return (needLength > 0 && needLength <= MAX_PATH); +} + +static bool ResolveDotsFolders(UString &s) +{ + #ifdef _WIN32 + s.Replace(L'/', WCHAR_PATH_SEPARATOR); + #endif + for (int i = 0;;) + { + wchar_t c = s[i]; + if (c == 0) + return true; + if (c == '.' && (i == 0 || s[i - 1] == WCHAR_PATH_SEPARATOR)) + { + wchar_t c1 = s[i + 1]; + if (c1 == '.') + { + wchar_t c2 = s[i + 2]; + if (c2 == WCHAR_PATH_SEPARATOR || c2 == 0) + { + if (i == 0) + return false; + int k = i - 2; + for (; k >= 0; k--) + if (s[k] == WCHAR_PATH_SEPARATOR) + break; + unsigned num; + if (k >= 0) + { + num = i + 2 - k; + i = k; + } + else + { + num = (c2 == 0 ? (i + 2) : (i + 3)); + i = 0; + } + s.Delete(i, num); + continue; + } + } + else + { + if (c1 == WCHAR_PATH_SEPARATOR || c1 == 0) + { + unsigned num = 2; + if (i != 0) + i--; + else if (c1 == 0) + num = 1; + s.Delete(i, num); + continue; + } + } + } + i++; + } +} + +#endif // UNDER_CE + +#define LONG_PATH_DOTS_FOLDERS_PARSING + + +/* +Windows (at least 64-bit XP) can't resolve "." or ".." in paths that start with SuperPrefix \\?\ +To solve that problem we check such path: + - super path contains "." or ".." - we use kSuperPathType_UseOnlySuper + - super path doesn't contain "." or ".." - we use kSuperPathType_UseOnlyMain +*/ +#ifdef LONG_PATH_DOTS_FOLDERS_PARSING +#ifndef UNDER_CE +static bool AreThereDotsFolders(CFSTR s) +{ + for (unsigned i = 0;; i++) + { + FChar c = s[i]; + if (c == 0) + return false; + if (c == '.' && (i == 0 || s[i - 1] == CHAR_PATH_SEPARATOR)) + { + FChar c1 = s[i + 1]; + if (c1 == 0 || c1 == CHAR_PATH_SEPARATOR || + (c1 == '.' && (s[i + 2] == 0 || s[i + 2] == CHAR_PATH_SEPARATOR))) + return true; + } + } +} #endif +#endif // LONG_PATH_DOTS_FOLDERS_PARSING + +#ifdef WIN_LONG_PATH + +/* +Most of Windows versions have problems, if some file or dir name +contains '.' or ' ' at the end of name (Bad Path). +To solve that problem, we always use Super Path ("\\?\" prefix and full path) +in such cases. Note that "." and ".." are not bad names. + +There are 3 cases: + 1) If the path is already Super Path, we use that path + 2) If the path is not Super Path : + 2.1) Bad Path; we use only Super Path. + 2.2) Good Path; we use Main Path. If it fails, we use Super Path. + + NeedToUseOriginalPath returns: + kSuperPathType_UseOnlyMain : Super already + kSuperPathType_UseOnlySuper : not Super, Bad Path + kSuperPathType_UseMainAndSuper : not Super, Good Path +*/ + +int GetUseSuperPathType(CFSTR s) +{ + if (IsSuperOrDevicePath(s)) + { + #ifdef LONG_PATH_DOTS_FOLDERS_PARSING + if ((s)[2] != '.') + if (AreThereDotsFolders(s + kSuperPathPrefixSize)) + return kSuperPathType_UseOnlySuper; + #endif + return kSuperPathType_UseOnlyMain; + } + + for (unsigned i = 0;; i++) + { + FChar c = s[i]; + if (c == 0) + return kSuperPathType_UseMainAndSuper; + if (c == '.' || c == ' ') + { + FChar c2 = s[i + 1]; + if (c2 == 0 || c2 == CHAR_PATH_SEPARATOR) + { + // if it's "." or "..", it's not bad name. + if (c == '.') + { + if (i == 0 || s[i - 1] == CHAR_PATH_SEPARATOR) + continue; + if (s[i - 1] == '.') + { + if (i - 1 == 0 || s[i - 2] == CHAR_PATH_SEPARATOR) + continue; + } + } + return kSuperPathType_UseOnlySuper; + } + } + } +} + + +/* + returns false in two cases: + - if GetCurDir was used, and GetCurDir returned error. + - if we can't resolve ".." name. + if path is ".", "..", res is empty. + if it's Super Path already, res is empty. + for \**** , and if GetCurDir is not drive (c:\), res is empty + for absolute paths, returns true, res is Super path. +*/ + + +static bool GetSuperPathBase(CFSTR s, UString &res) +{ + res.Empty(); + + FChar c = s[0]; + if (c == 0) + return true; + if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0))) + return true; + + if (IsSuperOrDevicePath(s)) + { + #ifdef LONG_PATH_DOTS_FOLDERS_PARSING + + if ((s)[2] == '.') + return true; + + // we will return true here, so we will try to use these problem paths. + + if (!AreThereDotsFolders(s + kSuperPathPrefixSize)) + return true; + + UString temp = fs2us(s); + unsigned fixedSize = GetRootPrefixSize_Of_SuperPath(temp); + if (fixedSize == 0) + return true; + + UString rem = &temp[fixedSize]; + if (!ResolveDotsFolders(rem)) + return true; + + temp.DeleteFrom(fixedSize); + res += temp; + res += rem; + + #endif + + return true; + } + + if (c == CHAR_PATH_SEPARATOR) + { + if (s[1] == CHAR_PATH_SEPARATOR) + { + UString temp = fs2us(s + 2); + unsigned fixedSize = GetRootPrefixSize_Of_NetworkPath(temp); + if (fixedSize == 0) // maybe we must ignore that error to allow short network paths? + return false; + UString rem = &temp[fixedSize]; + if (!ResolveDotsFolders(rem)) + return false; + res += kSuperUncPrefix; + temp.DeleteFrom(fixedSize); + res += temp; + res += rem; + return true; + } + } + else + { + if (IsDrivePath(s)) + { + UString temp = fs2us(s); + UString rem = &temp[kDrivePrefixSize]; + if (!ResolveDotsFolders(rem)) + return true; + res += kSuperPathPrefix; + temp.DeleteFrom(kDrivePrefixSize); + res += temp; + res += rem; + return true; + } + } + + UString curDir; + if (!GetCurDir(curDir)) + return false; + if (curDir.Back() != WCHAR_PATH_SEPARATOR) + curDir += WCHAR_PATH_SEPARATOR; + + unsigned fixedSizeStart = 0; + unsigned fixedSize = 0; + const wchar_t *superMarker = NULL; + if (IsSuperPath(curDir)) + { + fixedSize = GetRootPrefixSize_Of_SuperPath(curDir); + if (fixedSize == 0) + return false; + } + else + { + if (IsDrivePath(curDir)) + { + superMarker = kSuperPathPrefix; + fixedSize = kDrivePrefixSize; + } + else + { + if (curDir[0] != CHAR_PATH_SEPARATOR || curDir[1] != CHAR_PATH_SEPARATOR) + return false; + fixedSizeStart = 2; + fixedSize = GetRootPrefixSize_Of_NetworkPath(&curDir[2]); + if (fixedSize == 0) + return false; + superMarker = kSuperUncPrefix; + } + } + + UString temp; + if (c == CHAR_PATH_SEPARATOR) + { + temp = fs2us(s + 1); + } + else + { + temp += &curDir[fixedSizeStart + fixedSize]; + temp += fs2us(s); + } + if (!ResolveDotsFolders(temp)) + return false; + if (superMarker) + res += superMarker; + res += curDir.Mid(fixedSizeStart, fixedSize); + res += temp; + return true; +} + + +/* + In that case if GetSuperPathBase doesn't return new path, we don't need + to use same path that was used as main path + + GetSuperPathBase superPath.IsEmpty() onlyIfNew + false * * GetCurDir Error + true false * use Super path + true true true don't use any path, we already used mainPath + true true false use main path as Super Path, we don't try mainMath + That case is possible now if GetCurDir returns unknow + type of path (not drive and not network) + + We can change that code if we want to try mainPath, if GetSuperPathBase returns error, + and we didn't try mainPath still. + If we want to work that way, we don't need to use GetSuperPathBase return code. +*/ + +bool GetSuperPath(CFSTR path, UString &superPath, bool onlyIfNew) +{ + if (GetSuperPathBase(path, superPath)) + { + if (superPath.IsEmpty()) + { + // actually the only possible when onlyIfNew == true and superPath is empty + // is case when + + if (onlyIfNew) + return false; + superPath = fs2us(path); + } + return true; + } + return false; +} + +bool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew) +{ + if (!GetSuperPathBase(s1, d1) || + !GetSuperPathBase(s2, d2)) + return false; + if (d1.IsEmpty() && d2.IsEmpty() && onlyIfNew) + return false; + if (d1.IsEmpty()) d1 = fs2us(s1); + if (d2.IsEmpty()) d2 = fs2us(s2); + return true; +} + + +/* +// returns true, if we need additional use with New Super path. +bool GetSuperPath(CFSTR path, UString &superPath) +{ + if (GetSuperPathBase(path, superPath)) + return !superPath.IsEmpty(); + return false; +} +*/ +#endif // WIN_LONG_PATH + +bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res) +{ + res = s; + + #ifdef UNDER_CE + + if (s[0] != CHAR_PATH_SEPARATOR) + { + if (!dirPrefix) + return false; + res = dirPrefix; + res += s; + } + + #else + + unsigned prefixSize = GetRootPrefixSize(s); + if (prefixSize != 0) + { + if (!AreThereDotsFolders(s + prefixSize)) + return true; + + UString rem = fs2us(s + prefixSize); + if (!ResolveDotsFolders(rem)) + return true; // maybe false; + res.DeleteFrom(prefixSize); + res += us2fs(rem); + return true; + } + + /* + FChar c = s[0]; + if (c == 0) + return true; + if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0))) + return true; + if (c == CHAR_PATH_SEPARATOR && s[1] == CHAR_PATH_SEPARATOR) + return true; + if (IsDrivePath(s)) + return true; + */ + + UString curDir; + if (dirPrefix) + curDir = fs2us(dirPrefix); + else + { + if (!GetCurDir(curDir)) + return false; + } + if (!curDir.IsEmpty() && curDir.Back() != WCHAR_PATH_SEPARATOR) + curDir += WCHAR_PATH_SEPARATOR; + + unsigned fixedSize = 0; + + #ifdef _WIN32 + + if (IsSuperPath(curDir)) + { + fixedSize = GetRootPrefixSize_Of_SuperPath(curDir); + if (fixedSize == 0) + return false; + } + else + { + if (IsDrivePath(curDir)) + fixedSize = kDrivePrefixSize; + else + { + if (curDir[0] != WCHAR_PATH_SEPARATOR || curDir[1] != WCHAR_PATH_SEPARATOR) + return false; + fixedSize = GetRootPrefixSize_Of_NetworkPath(&curDir[2]); + if (fixedSize == 0) + return false; + fixedSize += 2; + } + } + + #endif // _WIN32 + + UString temp; + if (s[0] == CHAR_PATH_SEPARATOR) + { + temp = fs2us(s + 1); + } + else + { + temp += curDir.Ptr(fixedSize); + temp += fs2us(s); + } + if (!ResolveDotsFolders(temp)) + return false; + curDir.DeleteFrom(fixedSize); + res = us2fs(curDir); + res += us2fs(temp); + + #endif // UNDER_CE + + return true; +} + +bool GetFullPath(CFSTR path, FString &fullPath) +{ + return GetFullPath(NULL, path, fullPath); +} }}} diff --git a/CPP/Windows/FileName.h b/CPP/Windows/FileName.h old mode 100755 new mode 100644 index 9ee57f9d..04fc79b2 --- a/CPP/Windows/FileName.h +++ b/CPP/Windows/FileName.h @@ -12,6 +12,63 @@ namespace NName { void NormalizeDirPathPrefix(FString &dirPath); // ensures that it ended with '\\', if dirPath is not epmty void NormalizeDirPathPrefix(UString &dirPath); +#ifdef _WIN32 + +extern const wchar_t *kSuperPathPrefix; /* \\?\ */ +const unsigned kDevicePathPrefixSize = 4; +const unsigned kSuperPathPrefixSize = 4; +const unsigned kSuperUncPathPrefixSize = kSuperPathPrefixSize + 4; + +bool IsDevicePath(CFSTR s) throw(); /* \\.\ */ +bool IsSuperUncPath(CFSTR s) throw(); + +bool IsDrivePath(const wchar_t *s) throw(); +bool IsSuperPath(const wchar_t *s) throw(); +bool IsSuperOrDevicePath(const wchar_t *s) throw(); + +#ifndef USE_UNICODE_FSTRING +bool IsDrivePath(CFSTR s) throw(); +bool IsSuperPath(CFSTR s) throw(); +bool IsSuperOrDevicePath(CFSTR s) throw(); +#endif + +#endif // _WIN32 + +bool IsAbsolutePath(const wchar_t *s) throw(); +unsigned GetRootPrefixSize(const wchar_t *s) throw(); + +#ifdef WIN_LONG_PATH + +const int kSuperPathType_UseOnlyMain = 0; +const int kSuperPathType_UseOnlySuper = 1; +const int kSuperPathType_UseMainAndSuper = 2; + +int GetUseSuperPathType(CFSTR s) throw(); +bool GetSuperPath(CFSTR path, UString &longPath, bool onlyIfNew); +bool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew); + +#define USE_MAIN_PATH (__useSuperPathType != kSuperPathType_UseOnlySuper) +#define USE_MAIN_PATH_2 (__useSuperPathType1 != kSuperPathType_UseOnlySuper && __useSuperPathType2 != kSuperPathType_UseOnlySuper) + +#define USE_SUPER_PATH (__useSuperPathType != kSuperPathType_UseOnlyMain) +#define USE_SUPER_PATH_2 (__useSuperPathType1 != kSuperPathType_UseOnlyMain || __useSuperPathType2 != kSuperPathType_UseOnlyMain) + +#define IF_USE_MAIN_PATH int __useSuperPathType = GetUseSuperPathType(path); if (USE_MAIN_PATH) +#define IF_USE_MAIN_PATH_2(x1, x2) \ + int __useSuperPathType1 = GetUseSuperPathType(x1); \ + int __useSuperPathType2 = GetUseSuperPathType(x2); \ + if (USE_MAIN_PATH_2) + +#else + +#define IF_USE_MAIN_PATH +#define IF_USE_MAIN_PATH_2(x1, x2) + +#endif // WIN_LONG_PATH + +bool GetFullPath(CFSTR dirPrefix, CFSTR path, FString &fullPath); +bool GetFullPath(CFSTR path, FString &fullPath); + }}} #endif diff --git a/CPP/Windows/FileSystem.cpp b/CPP/Windows/FileSystem.cpp old mode 100755 new mode 100644 index 8bf595b2..6c1f48a2 --- a/CPP/Windows/FileSystem.cpp +++ b/CPP/Windows/FileSystem.cpp @@ -2,8 +2,10 @@ #include "StdAfx.h" +#ifndef UNDER_CE + #ifndef _UNICODE -#include "Common/StringConvert.h" +#include "../Common/StringConvert.h" #endif #include "FileSystem.h" @@ -67,6 +69,13 @@ UINT MyGetDriveType(CFSTR pathName) } } +typedef BOOL (WINAPI * GetDiskFreeSpaceExA_Pointer)( + LPCSTR lpDirectoryName, // directory name + PULARGE_INTEGER lpFreeBytesAvailable, // bytes available to caller + PULARGE_INTEGER lpTotalNumberOfBytes, // bytes on disk + PULARGE_INTEGER lpTotalNumberOfFreeBytes // free bytes on disk +); + typedef BOOL (WINAPI * GetDiskFreeSpaceExW_Pointer)( LPCWSTR lpDirectoryName, // directory name PULARGE_INTEGER lpFreeBytesAvailable, // bytes available to caller @@ -81,6 +90,15 @@ bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, #ifndef _UNICODE if (!g_IsNT) { + GetDiskFreeSpaceExA_Pointer pGetDiskFreeSpaceEx = (GetDiskFreeSpaceExA_Pointer)GetProcAddress( + GetModuleHandle(TEXT("kernel32.dll")), "GetDiskFreeSpaceExA"); + if (pGetDiskFreeSpaceEx) + { + ULARGE_INTEGER freeBytesToCaller2, totalSize2, freeSize2; + sizeIsDetected = BOOLToBool(pGetDiskFreeSpaceEx(fs2fas(rootPath), &freeBytesToCaller2, &totalSize2, &freeSize2)); + totalSize = totalSize2.QuadPart; + freeSize = freeSize2.QuadPart; + } if (!::GetDiskFreeSpace(fs2fas(rootPath), &numSectorsPerCluster, &bytesPerSector, &numFreeClusters, &numClusters)) return false; } @@ -109,3 +127,5 @@ bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, } }}} + +#endif diff --git a/CPP/Windows/FileSystem.h b/CPP/Windows/FileSystem.h old mode 100755 new mode 100644 index a7a8d1a9..9076ea13 --- a/CPP/Windows/FileSystem.h +++ b/CPP/Windows/FileSystem.h @@ -4,7 +4,7 @@ #define __WINDOWS_FILE_SYSTEM_H #include "../Common/MyString.h" -#include "../Common/Types.h" +#include "../Common/MyTypes.h" namespace NWindows { namespace NFile { diff --git a/CPP/Windows/Handle.h b/CPP/Windows/Handle.h old mode 100755 new mode 100644 diff --git a/CPP/Windows/Memory.cpp b/CPP/Windows/Memory.cpp deleted file mode 100755 index 4c23205e..00000000 --- a/CPP/Windows/Memory.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// 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 deleted file mode 100755 index 1984baf6..00000000 --- a/CPP/Windows/Memory.h +++ /dev/null @@ -1,53 +0,0 @@ -// 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/MemoryGlobal.cpp b/CPP/Windows/MemoryGlobal.cpp new file mode 100644 index 00000000..07b9b249 --- /dev/null +++ b/CPP/Windows/MemoryGlobal.cpp @@ -0,0 +1,36 @@ +// Windows/MemoryGlobal.cpp + +#include "StdAfx.h" + +#include "MemoryGlobal.h" + +namespace NWindows { +namespace NMemory { + +bool CGlobal::Alloc(UINT flags, SIZE_T size) +{ + HGLOBAL newBlock = ::GlobalAlloc(flags, size); + if (newBlock == NULL) + return false; + _global = newBlock; + return true; +} + +bool CGlobal::Free() +{ + if (_global == NULL) + return true; + _global = ::GlobalFree(_global); + return (_global == NULL); +} + +bool CGlobal::ReAlloc(SIZE_T size) +{ + HGLOBAL newBlock = ::GlobalReAlloc(_global, size, GMEM_MOVEABLE); + if (newBlock == NULL) + return false; + _global = newBlock; + return true; +} + +}} diff --git a/CPP/Windows/MemoryGlobal.h b/CPP/Windows/MemoryGlobal.h new file mode 100644 index 00000000..3f44f742 --- /dev/null +++ b/CPP/Windows/MemoryGlobal.h @@ -0,0 +1,53 @@ +// Windows/MemoryGlobal.h + +#ifndef __WINDOWS_MEMORY_GLOBAL_H +#define __WINDOWS_MEMORY_GLOBAL_H + +namespace NWindows { +namespace NMemory { + +class CGlobal +{ + HGLOBAL _global; +public: + CGlobal(): _global(NULL){}; + ~CGlobal() { Free(); } + operator HGLOBAL() const { return _global; }; + void Attach(HGLOBAL hGlobal) + { + Free(); + _global = hGlobal; + } + HGLOBAL Detach() + { + HGLOBAL h = _global; + _global = NULL; + return h; + } + bool Alloc(UINT flags, SIZE_T size) throw(); + bool Free() throw(); + LPVOID Lock() const { return GlobalLock(_global); } + void Unlock() const { GlobalUnlock(_global); } + bool ReAlloc(SIZE_T size) throw(); +}; + +class CGlobalLock +{ + HGLOBAL _global; + LPVOID _ptr; +public: + LPVOID GetPointer() const { return _ptr; } + CGlobalLock(HGLOBAL hGlobal): _global(hGlobal) + { + _ptr = GlobalLock(hGlobal); + }; + ~CGlobalLock() + { + if (_ptr != NULL) + GlobalUnlock(_global); + } +}; + +}} + +#endif diff --git a/CPP/Windows/MemoryLock.cpp b/CPP/Windows/MemoryLock.cpp old mode 100755 new mode 100644 index e0f43099..fa45f760 --- a/CPP/Windows/MemoryLock.cpp +++ b/CPP/Windows/MemoryLock.cpp @@ -1,4 +1,4 @@ -// Common/MemoryLock.cpp +// Windows/MemoryLock.cpp #include "StdAfx.h" @@ -7,75 +7,63 @@ 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( +#define MY_FUNC_SELECT(f) :: ## f #else -static bool EnableLockMemoryPrivilege2(HMODULE hModule, +#define MY_FUNC_SELECT(f) my_ ## f +extern "C" { +typedef BOOL (WINAPI * Func_OpenProcessToken)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle); +typedef BOOL (WINAPI * Func_LookupPrivilegeValue)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID lpLuid); +typedef BOOL (WINAPI * Func_AdjustTokenPrivileges)(HANDLE TokenHandle, BOOL DisableAllPrivileges, + PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength); +} +#define GET_PROC_ADDR(fff, name) Func_ ## fff my_ ## fff = (Func_ ## fff)GetProcAddress(hModule, name) #endif -bool enable) + +bool EnablePrivilege(LPCTSTR privilegeName, bool enable) { + bool res = false; + #ifndef _UNICODE + + HMODULE hModule = ::LoadLibrary(TEXT("Advapi32.dll")); 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; + + GET_PROC_ADDR(OpenProcessToken, "OpenProcessToken"); + GET_PROC_ADDR(LookupPrivilegeValue, "LookupPrivilegeValueA"); + GET_PROC_ADDR(AdjustTokenPrivileges, "AdjustTokenPrivileges"); + + if (my_OpenProcessToken && + my_AdjustTokenPrivileges && + my_LookupPrivilegeValue) + #endif - HANDLE token; - if (! - #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); + HANDLE token; + if (MY_FUNC_SELECT(OpenProcessToken)(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) + { + TOKEN_PRIVILEGES tp; + if (MY_FUNC_SELECT(LookupPrivilegeValue)(NULL, privilegeName, &(tp.Privileges[0].Luid))) + { + tp.PrivilegeCount = 1; + tp.Privileges[0].Attributes = (enable ? SE_PRIVILEGE_ENABLED : 0); + if (MY_FUNC_SELECT(AdjustTokenPrivileges)(token, FALSE, &tp, 0, NULL, NULL)) + res = (GetLastError() == ERROR_SUCCESS); + } + ::CloseHandle(token); + } } - ::CloseHandle(token); - return res; -} + + #ifndef _UNICODE -#ifndef _UNICODE -bool EnableLockMemoryPrivilege(bool enable) -{ - HMODULE hModule = LoadLibrary(TEXT("Advapi32.dll")); - if (hModule == NULL) - return false; - bool res = EnableLockMemoryPrivilege2(hModule, enable); ::FreeLibrary(hModule); + + #endif + return res; } -#endif #endif diff --git a/CPP/Windows/MemoryLock.h b/CPP/Windows/MemoryLock.h old mode 100755 new mode 100644 index 5fe619de..f08e5179 --- a/CPP/Windows/MemoryLock.h +++ b/CPP/Windows/MemoryLock.h @@ -1,13 +1,34 @@ // Windows/MemoryLock.h -#ifndef __WINDOWS_MEMORYLOCK_H -#define __WINDOWS_MEMORYLOCK_H +#ifndef __WINDOWS_MEMORY_LOCK_H +#define __WINDOWS_MEMORY_LOCK_H namespace NWindows { namespace NSecurity { #ifndef UNDER_CE -bool EnableLockMemoryPrivilege(bool enable = true); + + bool EnablePrivilege(LPCTSTR privilegeName, bool enable = true); + +inline bool EnablePrivilege_LockMemory(bool enable = true) +{ + return EnablePrivilege(SE_LOCK_MEMORY_NAME, enable); +} + +inline void EnablePrivilege_SymLink() +{ + /* Probably we do not to set any Privilege for junction points. + But we need them for Symbolic links */ + NSecurity::EnablePrivilege(SE_RESTORE_NAME); + + /* Probably we need only SE_RESTORE_NAME, but there is also + SE_CREATE_SYMBOLIC_LINK_NAME. So we set it also. Do we need it? */ + + NSecurity::EnablePrivilege(TEXT("SeCreateSymbolicLinkPrivilege")); // SE_CREATE_SYMBOLIC_LINK_NAME + + // Do we need to set SE_BACKUP_NAME ? +} + #endif }} diff --git a/CPP/Windows/Menu.cpp b/CPP/Windows/Menu.cpp old mode 100755 new mode 100644 index 675f8623..3834881a --- a/CPP/Windows/Menu.cpp +++ b/CPP/Windows/Menu.cpp @@ -3,9 +3,9 @@ #include "StdAfx.h" #ifndef _UNICODE -#include "Common/StringConvert.h" +#include "../Common/StringConvert.h" #endif -#include "Windows/Menu.h" +#include "Menu.h" #ifndef _UNICODE extern bool g_IsNT; @@ -13,10 +13,31 @@ extern bool g_IsNT; namespace NWindows { +/* +structures + MENUITEMINFOA + MENUITEMINFOW +contain additional member: + #if (WINVER >= 0x0500) + HBITMAP hbmpItem; + #endif +If we compile the source code with (WINVER >= 0x0500), some functions +will not work at NT 4.0, if cbSize is set as sizeof(MENUITEMINFO*). +So we use size of old version of structure. */ + +#if defined(UNDER_CE) || defined(_WIN64) || (WINVER < 0x0500) + #define my_compatib_MENUITEMINFOA_size sizeof(MENUITEMINFOA) + #define my_compatib_MENUITEMINFOW_size sizeof(MENUITEMINFOW) +#else + #define MY_STRUCT_SIZE_BEFORE(structname, member) ((UINT)(UINT_PTR)((LPBYTE)(&((structname*)0)->member) - (LPBYTE)(structname*)0)) + #define my_compatib_MENUITEMINFOA_size MY_STRUCT_SIZE_BEFORE(MENUITEMINFOA, hbmpItem) + #define my_compatib_MENUITEMINFOW_size MY_STRUCT_SIZE_BEFORE(MENUITEMINFOW, hbmpItem) +#endif + static void ConvertItemToSysForm(const CMenuItem &item, MENUITEMINFOW &si) { ZeroMemory(&si, sizeof(si)); - si.cbSize = sizeof(si); + si.cbSize = my_compatib_MENUITEMINFOW_size; // sizeof(si); si.fMask = item.fMask; si.fType = item.fType; si.fState = item.fState; @@ -31,7 +52,7 @@ static void ConvertItemToSysForm(const CMenuItem &item, MENUITEMINFOW &si) static void ConvertItemToSysForm(const CMenuItem &item, MENUITEMINFOA &si) { ZeroMemory(&si, sizeof(si)); - si.cbSize = sizeof(si); + si.cbSize = my_compatib_MENUITEMINFOA_size; // sizeof(si); si.fMask = item.fMask; si.fType = item.fType; si.fState = item.fState; diff --git a/CPP/Windows/Menu.h b/CPP/Windows/Menu.h old mode 100755 new mode 100644 index 2563b911..75f840d0 --- a/CPP/Windows/Menu.h +++ b/CPP/Windows/Menu.h @@ -3,8 +3,9 @@ #ifndef __WINDOWS_MENU_H #define __WINDOWS_MENU_H -#include "Common/MyString.h" -#include "Windows/Defs.h" +#include "../Common/MyString.h" + +#include "Defs.h" namespace NWindows { diff --git a/CPP/Windows/NationalTime.cpp b/CPP/Windows/NationalTime.cpp old mode 100755 new mode 100644 diff --git a/CPP/Windows/NationalTime.h b/CPP/Windows/NationalTime.h old mode 100755 new mode 100644 diff --git a/CPP/Windows/Net.cpp b/CPP/Windows/Net.cpp old mode 100755 new mode 100644 index b0a18732..47079f37 --- a/CPP/Windows/Net.cpp +++ b/CPP/Windows/Net.cpp @@ -2,11 +2,13 @@ #include "StdAfx.h" +#include "../Common/MyBuffer.h" + #ifndef _UNICODE -#include "Common/StringConvert.h" +#include "../Common/StringConvert.h" #endif -#include "Windows/Net.h" +#include "Net.h" #ifndef _UNICODE extern bool g_IsNT; @@ -202,9 +204,8 @@ DWORD CEnum::NextW(LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize) DWORD CEnum::Next(CResource &resource) { - CByteBuffer byteBuffer; const DWORD kBufferSize = 16384; - byteBuffer.SetCapacity(kBufferSize); + CByteArr byteBuffer(kBufferSize); LPNETRESOURCE lpnrLocal = (LPNETRESOURCE) (BYTE *)(byteBuffer); ZeroMemory(lpnrLocal, kBufferSize); DWORD bufferSize = kBufferSize; @@ -223,9 +224,8 @@ DWORD CEnum::Next(CResourceW &resource) { if (g_IsNT) { - CByteBuffer byteBuffer; const DWORD kBufferSize = 16384; - byteBuffer.SetCapacity(kBufferSize); + CByteArr byteBuffer(kBufferSize); LPNETRESOURCEW lpnrLocal = (LPNETRESOURCEW) (BYTE *)(byteBuffer); ZeroMemory(lpnrLocal, kBufferSize); DWORD bufferSize = kBufferSize; @@ -248,9 +248,8 @@ DWORD CEnum::Next(CResourceW &resource) DWORD GetResourceParent(const CResource &resource, CResource &parentResource) { - CByteBuffer byteBuffer; const DWORD kBufferSize = 16384; - byteBuffer.SetCapacity(kBufferSize); + CByteArr byteBuffer(kBufferSize); LPNETRESOURCE lpnrLocal = (LPNETRESOURCE) (BYTE *)(byteBuffer); ZeroMemory(lpnrLocal, kBufferSize); DWORD bufferSize = kBufferSize; @@ -268,9 +267,8 @@ DWORD GetResourceParent(const CResourceW &resource, CResourceW &parentResource) { if (g_IsNT) { - CByteBuffer byteBuffer; const DWORD kBufferSize = 16384; - byteBuffer.SetCapacity(kBufferSize); + CByteArr byteBuffer(kBufferSize); LPNETRESOURCEW lpnrLocal = (LPNETRESOURCEW) (BYTE *)(byteBuffer); ZeroMemory(lpnrLocal, kBufferSize); DWORD bufferSize = kBufferSize; @@ -293,9 +291,8 @@ DWORD GetResourceParent(const CResourceW &resource, CResourceW &parentResource) DWORD GetResourceInformation(const CResource &resource, CResource &destResource, CSysString &systemPathPart) { - CByteBuffer byteBuffer; const DWORD kBufferSize = 16384; - byteBuffer.SetCapacity(kBufferSize); + CByteArr byteBuffer(kBufferSize); LPNETRESOURCE lpnrLocal = (LPNETRESOURCE) (BYTE *)(byteBuffer); ZeroMemory(lpnrLocal, kBufferSize); DWORD bufferSize = kBufferSize; @@ -318,9 +315,8 @@ DWORD GetResourceInformation(const CResourceW &resource, { if (g_IsNT) { - CByteBuffer byteBuffer; const DWORD kBufferSize = 16384; - byteBuffer.SetCapacity(kBufferSize); + CByteArr byteBuffer(kBufferSize); LPNETRESOURCEW lpnrLocal = (LPNETRESOURCEW) (BYTE *)(byteBuffer); ZeroMemory(lpnrLocal, kBufferSize); DWORD bufferSize = kBufferSize; diff --git a/CPP/Windows/Net.h b/CPP/Windows/Net.h old mode 100755 new mode 100644 index c88b6113..7b60b1b4 --- a/CPP/Windows/Net.h +++ b/CPP/Windows/Net.h @@ -3,8 +3,7 @@ #ifndef __WINDOWS_NET_H #define __WINDOWS_NET_H -#include "Common/Buffer.h" -#include "Common/MyString.h" +#include "../Common/MyString.h" namespace NWindows { namespace NNet { diff --git a/CPP/Windows/NtCheck.h b/CPP/Windows/NtCheck.h old mode 100755 new mode 100644 diff --git a/CPP/Windows/Process.cpp b/CPP/Windows/Process.cpp deleted file mode 100755 index 9bcee7d5..00000000 --- a/CPP/Windows/Process.cpp +++ /dev/null @@ -1,81 +0,0 @@ -// 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 deleted file mode 100755 index 5b01c377..00000000 --- a/CPP/Windows/Process.h +++ /dev/null @@ -1,100 +0,0 @@ -// 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 old mode 100755 new mode 100644 diff --git a/CPP/Windows/ProcessMessages.h b/CPP/Windows/ProcessMessages.h old mode 100755 new mode 100644 diff --git a/CPP/Windows/ProcessUtils.cpp b/CPP/Windows/ProcessUtils.cpp new file mode 100644 index 00000000..9b833e54 --- /dev/null +++ b/CPP/Windows/ProcessUtils.cpp @@ -0,0 +1,86 @@ +// ProcessUtils.cpp + +#include "StdAfx.h" + +#include "../Common/StringConvert.h" + +#include "ProcessUtils.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { + +#ifndef UNDER_CE +static UString GetQuotedString(const UString &s) +{ + UString s2 = L'\"'; + s2 += s; + s2 += L'\"'; + return s2; +} +#endif + +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/ProcessUtils.h b/CPP/Windows/ProcessUtils.h new file mode 100644 index 00000000..caf9a303 --- /dev/null +++ b/CPP/Windows/ProcessUtils.h @@ -0,0 +1,100 @@ +// Windows/ProcessUtils.h + +#ifndef __WINDOWS_PROCESS_UTILS_H +#define __WINDOWS_PROCESS_UTILS_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/PropVariant.cpp b/CPP/Windows/PropVariant.cpp old mode 100755 new mode 100644 index 90212e08..caa4c319 --- a/CPP/Windows/PropVariant.cpp +++ b/CPP/Windows/PropVariant.cpp @@ -2,13 +2,43 @@ #include "StdAfx.h" -#include "PropVariant.h" - #include "../Common/Defs.h" +#include "PropVariant.h" + namespace NWindows { namespace NCOM { +HRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) +{ + p->bstrVal = ::SysAllocStringLen(0, numChars); + if (!p->bstrVal) + { + p->vt = VT_ERROR; + p->scode = E_OUTOFMEMORY; + return E_OUTOFMEMORY; + } + p->vt = VT_BSTR; + return S_OK; +} + +HRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) +{ + UINT len = (UINT)strlen(s); + p->bstrVal = ::SysAllocStringByteLen(0, (UINT)len * sizeof(OLECHAR)); + if (!p->bstrVal) + { + p->vt = VT_ERROR; + p->scode = E_OUTOFMEMORY; + return E_OUTOFMEMORY; + } + p->vt = VT_BSTR; + BSTR dest = p->bstrVal; + for (UINT i = 0; i <= len; i++) + dest[i] = s[i]; + return S_OK; +} + CPropVariant::CPropVariant(const PROPVARIANT &varSrc) { vt = VT_EMPTY; @@ -67,7 +97,6 @@ CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc) return *this; } - CPropVariant& CPropVariant::operator=(const char *s) { InternalClear(); @@ -100,22 +129,40 @@ CPropVariant& CPropVariant::operator=(bool bSrc) return *this; } +BSTR CPropVariant::AllocBstr(unsigned numChars) +{ + if (vt != VT_EMPTY) + InternalClear(); + vt = VT_BSTR; + wReserved1 = 0; + bstrVal = ::SysAllocStringLen(0, numChars); + if (bstrVal == NULL) + { + throw kMemException; + // vt = VT_ERROR; + // scode = E_OUTOFMEMORY; + } + return bstrVal; +} + #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(Int16, VT_I2, iVal) SET_PROP_FUNC(Int32, VT_I4, lVal) SET_PROP_FUNC(UInt32, VT_UI4, ulVal) SET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart) +SET_PROP_FUNC(Int64, VT_I8, hVal.QuadPart) SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime) -static HRESULT MyPropVariantClear(PROPVARIANT *prop) +HRESULT PropVariant_Clear(PROPVARIANT *prop) throw() { - switch(prop->vt) + switch (prop->vt) { + case VT_EMPTY: case VT_UI1: case VT_I1: case VT_I2: @@ -134,14 +181,21 @@ static HRESULT MyPropVariantClear(PROPVARIANT *prop) case VT_DATE: prop->vt = VT_EMPTY; prop->wReserved1 = 0; + prop->wReserved2 = 0; + prop->wReserved3 = 0; + prop->uhVal.QuadPart = 0; return S_OK; } return ::VariantClear((VARIANTARG *)prop); + // return ::PropVariantClear(prop); + // PropVariantClear can clear VT_BLOB. } HRESULT CPropVariant::Clear() { - return MyPropVariantClear(this); + if (vt == VT_EMPTY) + return S_OK; + return PropVariant_Clear(this); } HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) @@ -184,9 +238,12 @@ HRESULT CPropVariant::Attach(PROPVARIANT *pSrc) HRESULT CPropVariant::Detach(PROPVARIANT *pDest) { - HRESULT hr = MyPropVariantClear(pDest); - if (FAILED(hr)) - return hr; + if (pDest->vt != VT_EMPTY) + { + HRESULT hr = PropVariant_Clear(pDest); + if (FAILED(hr)) + return hr; + } memcpy(pDest, this, sizeof(PROPVARIANT)); vt = VT_EMPTY; return S_OK; @@ -194,6 +251,8 @@ HRESULT CPropVariant::Detach(PROPVARIANT *pDest) HRESULT CPropVariant::InternalClear() { + if (vt == VT_EMPTY) + return S_OK; HRESULT hr = Clear(); if (FAILED(hr)) { @@ -233,9 +292,7 @@ int CPropVariant::Compare(const CPropVariant &a) 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); + case VT_BSTR: return 0; // Not implemented default: return 0; } } diff --git a/CPP/Windows/PropVariant.h b/CPP/Windows/PropVariant.h old mode 100755 new mode 100644 index d018034e..70907c88 --- a/CPP/Windows/PropVariant.h +++ b/CPP/Windows/PropVariant.h @@ -1,29 +1,73 @@ // Windows/PropVariant.h -#ifndef __WINDOWS_PROPVARIANT_H -#define __WINDOWS_PROPVARIANT_H +#ifndef __WINDOWS_PROP_VARIANT_H +#define __WINDOWS_PROP_VARIANT_H +#include "../Common/MyTypes.h" #include "../Common/MyWindows.h" -#include "../Common/Types.h" namespace NWindows { namespace NCOM { +HRESULT PropVariant_Clear(PROPVARIANT *p) throw(); + +HRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) throw(); +HRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw(); + +inline void PropVarEm_Set_UInt32(PROPVARIANT *p, UInt32 v) throw() +{ + p->vt = VT_UI4; + p->ulVal = v; +} + +inline void PropVarEm_Set_UInt64(PROPVARIANT *p, UInt64 v) throw() +{ + p->vt = VT_UI8; + p->uhVal.QuadPart = v; +} + +inline void PropVarEm_Set_FileTime64(PROPVARIANT *p, UInt64 v) throw() +{ + p->vt = VT_FILETIME; + p->filetime.dwLowDateTime = (DWORD)v; + p->filetime.dwHighDateTime = (DWORD)(v >> 32); +} + +inline void PropVarEm_Set_Bool(PROPVARIANT *p, bool b) throw() +{ + p->vt = VT_BOOL; + p->boolVal = (b ? VARIANT_TRUE : VARIANT_FALSE); +} + + class CPropVariant : public tagPROPVARIANT { public: - CPropVariant() { vt = VT_EMPTY; wReserved1 = 0; } - ~CPropVariant() { Clear(); } + CPropVariant() + { + vt = VT_EMPTY; + wReserved1 = 0; + // wReserved2 = 0; + // wReserved3 = 0; + // uhVal.QuadPart = 0; + bstrVal = 0; + } + ~CPropVariant() throw() { Clear(); } CPropVariant(const PROPVARIANT &varSrc); CPropVariant(const CPropVariant &varSrc); CPropVariant(BSTR bstrSrc); CPropVariant(LPCOLESTR lpszSrc); CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); }; CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; } - CPropVariant(Int16 value) { vt = VT_I2; wReserved1 = 0; iVal = value; } - CPropVariant(Int32 value) { vt = VT_I4; wReserved1 = 0; lVal = value; } + +private: + CPropVariant(Int16 value); // { vt = VT_I2; wReserved1 = 0; iVal = value; } + CPropVariant(Int32 value); // { vt = VT_I4; wReserved1 = 0; lVal = value; } + +public: CPropVariant(UInt32 value) { vt = VT_UI4; wReserved1 = 0; ulVal = value; } CPropVariant(UInt64 value) { vt = VT_UI8; wReserved1 = 0; uhVal.QuadPart = value; } + CPropVariant(Int64 value) { vt = VT_I8; wReserved1 = 0; hVal.QuadPart = value; } CPropVariant(const FILETIME &value) { vt = VT_FILETIME; wReserved1 = 0; filetime = value; } CPropVariant& operator=(const CPropVariant &varSrc); @@ -31,24 +75,31 @@ public: 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(); + + CPropVariant& operator=(bool bSrc) throw(); + CPropVariant& operator=(Byte value) throw(); + +private: + CPropVariant& operator=(Int16 value) throw(); + +public: + CPropVariant& operator=(Int32 value) throw(); + CPropVariant& operator=(UInt32 value) throw(); + CPropVariant& operator=(UInt64 value) throw(); + CPropVariant& operator=(Int64 value) throw(); + CPropVariant& operator=(const FILETIME &value) throw(); + + BSTR AllocBstr(unsigned numChars); + + HRESULT Clear() throw(); + HRESULT Copy(const PROPVARIANT *pSrc) throw(); + HRESULT Attach(PROPVARIANT *pSrc) throw(); + HRESULT Detach(PROPVARIANT *pDest) throw(); + + HRESULT InternalClear() throw(); void InternalCopy(const PROPVARIANT *pSrc); - int Compare(const CPropVariant &a1); + int Compare(const CPropVariant &a) throw(); }; }} diff --git a/CPP/Windows/PropVariantConv.cpp b/CPP/Windows/PropVariantConv.cpp new file mode 100644 index 00000000..95891dd9 --- /dev/null +++ b/CPP/Windows/PropVariantConv.cpp @@ -0,0 +1,99 @@ +// PropVariantConvert.cpp + +#include "StdAfx.h" + +#include "../Common/IntToString.h" + +#include "Defs.h" +#include "PropVariantConv.h" + +#define UINT_TO_STR_2(c, val) { s[0] = (c); s[1] = (char)('0' + (val) / 10); s[2] = (char)('0' + (val) % 10); s += 3; } + +bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime, bool includeSeconds) +{ + SYSTEMTIME st; + if (!BOOLToBool(FileTimeToSystemTime(&ft, &st))) + { + *s = 0; + return false; + } + unsigned val = st.wYear; + if (val >= 10000) + { + *s++ = (char)('0' + val / 10000); + val %= 10000; + } + { + s[3] = (char)('0' + val % 10); val /= 10; + s[2] = (char)('0' + val % 10); val /= 10; + s[1] = (char)('0' + val % 10); + s[0] = (char)('0' + val / 10); + s += 4; + } + UINT_TO_STR_2('-', st.wMonth); + UINT_TO_STR_2('-', st.wDay); + if (includeTime) + { + UINT_TO_STR_2(' ', st.wHour); + UINT_TO_STR_2(':', st.wMinute); + if (includeSeconds) + UINT_TO_STR_2(':', st.wSecond); + } + *s = 0; + return true; +} + +void ConvertFileTimeToString(const FILETIME &ft, wchar_t *dest, bool includeTime, bool includeSeconds) +{ + char s[32]; + ConvertFileTimeToString(ft, s, includeTime, includeSeconds); + for (unsigned i = 0;; i++) + { + unsigned char c = s[i]; + dest[i] = c; + if (c == 0) + return; + } +} + +void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) +{ + *dest = 0; + switch (prop.vt) + { + case VT_EMPTY: return; + case VT_BSTR: dest[0] = '?'; dest[1] = 0; return; + case VT_UI1: ConvertUInt32ToString(prop.bVal, dest); return; + case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return; + case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return; + case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return; + case VT_FILETIME: ConvertFileTimeToString(prop.filetime, dest, true, true); return; + // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return; + case VT_I2: ConvertInt64ToString(prop.iVal, dest); return; + case VT_I4: ConvertInt64ToString(prop.lVal, dest); return; + case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return; + case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? '+' : '-'; dest[1] = 0; return; + default: dest[0] = '?'; dest[1] = ':'; ConvertUInt64ToString(prop.vt, dest + 2); + } +} + +void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) +{ + *dest = 0; + switch (prop.vt) + { + case VT_EMPTY: return; + case VT_BSTR: dest[0] = '?'; dest[1] = 0; return; + case VT_UI1: ConvertUInt32ToString(prop.bVal, dest); return; + case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return; + case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return; + case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return; + case VT_FILETIME: ConvertFileTimeToString(prop.filetime, dest, true, true); return; + // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return; + case VT_I2: ConvertInt64ToString(prop.iVal, dest); return; + case VT_I4: ConvertInt64ToString(prop.lVal, dest); return; + case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return; + case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? '+' : '-'; dest[1] = 0; return; + default: dest[0] = '?'; dest[1] = ':'; ConvertUInt32ToString(prop.vt, dest + 2); + } +} diff --git a/CPP/Windows/PropVariantConv.h b/CPP/Windows/PropVariantConv.h new file mode 100644 index 00000000..5d26357f --- /dev/null +++ b/CPP/Windows/PropVariantConv.h @@ -0,0 +1,30 @@ +// Windows/PropVariantConv.h + +#ifndef __PROP_VARIANT_CONV_H +#define __PROP_VARIANT_CONV_H + +#include "../Common/MyTypes.h" + +// provide at least 32 bytes for buffer including zero-end +bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime = true, bool includeSeconds = true) throw(); +void ConvertFileTimeToString(const FILETIME &ft, wchar_t *s, bool includeTime = true, bool includeSeconds = true) throw(); + +// provide at least 32 bytes for buffer including zero-end +// don't send VT_BSTR to these functions +void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw(); +void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) throw(); + +inline bool ConvertPropVariantToUInt64(const PROPVARIANT &prop, UInt64 &value) +{ + switch (prop.vt) + { + case VT_UI8: value = (UInt64)prop.uhVal.QuadPart; return true; + case VT_UI4: value = prop.ulVal; return true; + case VT_UI2: value = prop.uiVal; return true; + case VT_UI1: value = prop.bVal; return true; + case VT_EMPTY: return false; + default: throw 151199; + } +} + +#endif diff --git a/CPP/Windows/PropVariantConversions.cpp b/CPP/Windows/PropVariantConversions.cpp deleted file mode 100755 index 2d8456cd..00000000 --- a/CPP/Windows/PropVariantConversions.cpp +++ /dev/null @@ -1,105 +0,0 @@ -// 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 deleted file mode 100755 index 3de4dedb..00000000 --- a/CPP/Windows/PropVariantConversions.h +++ /dev/null @@ -1,14 +0,0 @@ -// 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 old mode 100755 new mode 100644 index f10b4ef2..92b355a4 --- a/CPP/Windows/PropVariantUtils.cpp +++ b/CPP/Windows/PropVariantUtils.cpp @@ -2,24 +2,21 @@ #include "StdAfx.h" +#include "../Common/IntToString.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); + char sz[16]; + sz[0] = '0'; + sz[1] = 'x'; + ConvertUInt32ToHex(v, sz + 2); return sz; } -void StringToProp(const AString &s, NCOM::CPropVariant &prop) -{ - prop = MultiByteToUnicodeString(s); -} - AString TypePairToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 value) { AString s; @@ -34,12 +31,12 @@ AString TypePairToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 val return s; } - void PairToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 value, NCOM::CPropVariant &prop) { - StringToProp(TypePairToString(pairs, num, value), prop); + prop = TypePairToString(pairs, num, value); } + AString TypeToString(const char *table[], unsigned num, UInt32 value) { if (value < num) @@ -49,10 +46,37 @@ AString TypeToString(const char *table[], unsigned num, UInt32 value) void TypeToProp(const char *table[], unsigned num, UInt32 value, NCOM::CPropVariant &prop) { - StringToProp(TypeToString(table, num, value), prop); + prop = TypeToString(table, num, value); } +AString FlagsToString(const char **names, unsigned num, UInt32 flags) +{ + AString s; + for (unsigned i = 0; i < num; i++) + { + UInt32 flag = (UInt32)1 << i; + if ((flags & flag) != 0) + { + const char *name = names[i]; + if (name != 0 && name[0] != 0) + { + if (!s.IsEmpty()) + s += ' '; + s += name; + flags &= ~flag; + } + } + } + if (flags != 0) + { + if (!s.IsEmpty()) + s += ' '; + s += GetHex(flags); + } + return s; +} + AString FlagsToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags) { AString s; @@ -82,5 +106,5 @@ AString FlagsToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags) void FlagsToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags, NCOM::CPropVariant &prop) { - StringToProp(FlagsToString(pairs, num, flags), prop); + prop = FlagsToString(pairs, num, flags); } diff --git a/CPP/Windows/PropVariantUtils.h b/CPP/Windows/PropVariantUtils.h old mode 100755 new mode 100644 index 5582aaff..c9946144 --- a/CPP/Windows/PropVariantUtils.h +++ b/CPP/Windows/PropVariantUtils.h @@ -3,7 +3,8 @@ #ifndef __PROP_VARIANT_UTILS_H #define __PROP_VARIANT_UTILS_H -#include "Common/MyString.h" +#include "../Common/MyString.h" + #include "PropVariant.h" struct CUInt32PCharPair @@ -12,18 +13,18 @@ struct CUInt32PCharPair const char *Name; }; -void StringToProp(const AString &s, NWindows::NCOM::CPropVariant &prop); AString TypePairToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 value); void PairToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 value, NWindows::NCOM::CPropVariant &prop); +AString FlagsToString(const char **names, unsigned num, UInt32 flags); AString FlagsToString(const 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) +#define PAIR_TO_PROP(pairs, value, prop) PairToProp(pairs, ARRAY_SIZE(pairs), value, prop) +#define FLAGS_TO_PROP(pairs, value, prop) FlagsToProp(pairs, ARRAY_SIZE(pairs), value, prop) +#define TYPE_TO_PROP(table, value, prop) TypeToProp(table, ARRAY_SIZE(table), value, prop) #endif diff --git a/CPP/Windows/Registry.cpp b/CPP/Windows/Registry.cpp old mode 100755 new mode 100644 index 8b25375d..72685fe6 --- a/CPP/Windows/Registry.cpp +++ b/CPP/Windows/Registry.cpp @@ -3,9 +3,9 @@ #include "StdAfx.h" #ifndef _UNICODE -#include "Common/StringConvert.h" +#include "../Common/StringConvert.h" #endif -#include "Windows/Registry.h" +#include "Registry.h" #ifndef _UNICODE extern bool g_IsNT; @@ -139,7 +139,7 @@ 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)); + (const BYTE *)(const TCHAR *)value, (value.Len() + 1) * sizeof(TCHAR)); } */ @@ -193,8 +193,8 @@ LONG CKey::QueryValue(LPCTSTR name, UInt32 &value) 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))); + MYASSERT((res != ERROR_SUCCESS) || (type == REG_DWORD)); + MYASSERT((res != ERROR_SUCCESS) || (count == sizeof(UInt32))); return res; } @@ -229,7 +229,7 @@ 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)); + MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ)); return res; } @@ -252,7 +252,7 @@ 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)); + MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ)); return res; } LONG CKey::QueryValue(LPCWSTR name, UString &value) @@ -284,7 +284,7 @@ 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)); + MYASSERT((res != ERROR_SUCCESS) || (type == REG_BINARY)); return res; } @@ -296,7 +296,7 @@ LONG CKey::QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize) LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&dataSize); if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) return res; - value.SetCapacity(dataSize); + value.Alloc(dataSize); return QueryValue(name, (BYTE *)value, dataSize); } @@ -324,17 +324,16 @@ LONG CKey::EnumKeys(CSysStringVector &keyNames) LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings) { UInt32 numChars = 0; - int i; + unsigned i; for (i = 0; i < strings.Size(); i++) - numChars += strings[i].Length() + 1; - CBuffer buffer; - buffer.SetCapacity(numChars); - int pos = 0; + numChars += strings[i].Len() + 1; + CBuffer buffer(numChars); + unsigned 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; + pos += s.Len() + 1; } return SetValue(valueName, buffer, numChars * sizeof(wchar_t)); } @@ -350,9 +349,9 @@ LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings) 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); + unsigned numChars = dataSize / sizeof(wchar_t); UString s; - for (int i = 0; i < numChars; i++) + for (unsigned i = 0; i < numChars; i++) { wchar_t c = data[i]; if (c == 0) diff --git a/CPP/Windows/Registry.h b/CPP/Windows/Registry.h old mode 100755 new mode 100644 index f0561e68..32ee10b0 --- a/CPP/Windows/Registry.h +++ b/CPP/Windows/Registry.h @@ -3,9 +3,8 @@ #ifndef __WINDOWS_REGISTRY_H #define __WINDOWS_REGISTRY_H -#include "Common/Buffer.h" -#include "Common/MyString.h" -#include "Common/Types.h" +#include "../Common/MyBuffer.h" +#include "../Common/MyString.h" namespace NWindows { namespace NRegistry { @@ -32,49 +31,49 @@ public: 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); + LPDWORD disposition = NULL) throw(); + LONG Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask = KEY_ALL_ACCESS) throw(); - LONG Close(); + LONG Close() throw(); - LONG DeleteSubKey(LPCTSTR subKeyName); - LONG RecurseDeleteKey(LPCTSTR subKeyName); + LONG DeleteSubKey(LPCTSTR subKeyName) throw(); + LONG RecurseDeleteKey(LPCTSTR subKeyName) throw(); - LONG DeleteValue(LPCTSTR name); + LONG DeleteValue(LPCTSTR name) throw(); #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, UInt32 value) throw(); + LONG SetValue(LPCTSTR valueName, bool value) throw(); + LONG SetValue(LPCTSTR valueName, LPCTSTR value) throw(); // LONG SetValue(LPCTSTR valueName, const CSysString &value); #ifndef _UNICODE LONG SetValue(LPCWSTR name, LPCWSTR value); // LONG SetValue(LPCWSTR name, const UString &value); #endif - LONG SetValue(LPCTSTR name, const void *value, UInt32 size); + LONG SetValue(LPCTSTR name, const void *value, UInt32 size) throw(); - LONG SetValue_Strings(LPCTSTR valueName, const UStringVector &strings); + LONG SetValue_Strings(LPCTSTR valueName, const UStringVector &strings) throw(); LONG GetValue_Strings(LPCTSTR valueName, UStringVector &strings); - LONG SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value); + LONG SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) throw(); - LONG QueryValue(LPCTSTR name, UInt32 &value); - LONG QueryValue(LPCTSTR name, bool &value); - LONG QueryValue(LPCTSTR name, LPTSTR value, UInt32 &dataSize); + LONG QueryValue(LPCTSTR name, UInt32 &value) throw(); + LONG QueryValue(LPCTSTR name, bool &value) throw(); + LONG QueryValue(LPCTSTR name, LPTSTR value, UInt32 &dataSize) throw(); LONG QueryValue(LPCTSTR name, CSysString &value); - LONG GetValue_IfOk(LPCTSTR name, UInt32 &value); - LONG GetValue_IfOk(LPCTSTR name, bool &value); + LONG GetValue_IfOk(LPCTSTR name, UInt32 &value) throw(); + LONG GetValue_IfOk(LPCTSTR name, bool &value) throw(); #ifndef _UNICODE LONG QueryValue(LPCWSTR name, LPWSTR value, UInt32 &dataSize); LONG QueryValue(LPCWSTR name, UString &value); #endif - LONG QueryValue(LPCTSTR name, void *value, UInt32 &dataSize); + LONG QueryValue(LPCTSTR name, void *value, UInt32 &dataSize) throw(); LONG QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize); LONG EnumKeys(CSysStringVector &keyNames); diff --git a/CPP/Windows/ResourceString.cpp b/CPP/Windows/ResourceString.cpp old mode 100755 new mode 100644 index 781f03b3..eb28bd3b --- a/CPP/Windows/ResourceString.cpp +++ b/CPP/Windows/ResourceString.cpp @@ -2,11 +2,12 @@ #include "StdAfx.h" -#include "Windows/ResourceString.h" #ifndef _UNICODE -#include "Common/StringConvert.h" +#include "../Common/StringConvert.h" #endif +#include "ResourceString.h" + extern HINSTANCE g_hInstance; #ifndef _UNICODE extern bool g_IsNT; @@ -14,14 +15,16 @@ extern bool g_IsNT; namespace NWindows { -CSysString MyLoadString(HINSTANCE hInstance, UINT resourceID) +#ifndef _UNICODE + +static CSysString MyLoadStringA(HINSTANCE hInstance, UINT resourceID) { CSysString s; - int size = 256; + int size = 128; int len; do { - size += 256; + size <<= 1; len = ::LoadString(hInstance, resourceID, s.GetBuffer(size - 1), size); } while (size - len <= 1); @@ -29,36 +32,72 @@ CSysString MyLoadString(HINSTANCE hInstance, UINT resourceID) return s; } -CSysString MyLoadString(UINT resourceID) +#endif + +static const int kStartSize = 256; + +static void MyLoadString2(HINSTANCE hInstance, UINT resourceID, UString &s) { - return MyLoadString(g_hInstance, resourceID); + int size = kStartSize; + int len; + do + { + size <<= 1; + len = ::LoadStringW(hInstance, resourceID, s.GetBuffer(size - 1), size); + } + while (size - len <= 1); + s.ReleaseBuffer(); } -#ifndef _UNICODE -UString MyLoadStringW(HINSTANCE hInstance, UINT resourceID) +// NT4 doesn't support LoadStringW(,,, 0) to get pointer to resource string. So we don't use it. + +UString MyLoadString(UINT resourceID) { - if (g_IsNT) + #ifndef _UNICODE + if (!g_IsNT) + return GetUnicodeString(MyLoadStringA(g_hInstance, resourceID)); + else + #endif { - UString s; - int size = 256; - int len; - do { - size += 256; - len = ::LoadStringW(hInstance, resourceID, s.GetBuffer(size - 1), size); + wchar_t s[kStartSize]; + s[0] = 0; + int len = ::LoadStringW(g_hInstance, resourceID, s, kStartSize); + if (kStartSize - len > 1) + return s; } - while (size - len <= 1); - s.ReleaseBuffer(); - return s; + UString dest; + MyLoadString2(g_hInstance, resourceID, dest); + return dest; } - return GetUnicodeString(MyLoadString(hInstance, resourceID)); } -UString MyLoadStringW(UINT resourceID) +void MyLoadString(HINSTANCE hInstance, UINT resourceID, UString &dest) { - return MyLoadStringW(g_hInstance, resourceID); + dest.Empty(); + #ifndef _UNICODE + if (!g_IsNT) + MultiByteToUnicodeString2(dest, MyLoadStringA(hInstance, resourceID)); + else + #endif + { + { + wchar_t s[kStartSize]; + s[0] = 0; + int len = ::LoadStringW(hInstance, resourceID, s, kStartSize); + if (kStartSize - len > 1) + { + dest = s; + return; + } + } + MyLoadString2(hInstance, resourceID, dest); + } } -#endif +void MyLoadString(UINT resourceID, UString &dest) +{ + MyLoadString(g_hInstance, resourceID, dest); +} } diff --git a/CPP/Windows/ResourceString.h b/CPP/Windows/ResourceString.h old mode 100755 new mode 100644 index ac9c5cd5..f0bdabf4 --- a/CPP/Windows/ResourceString.h +++ b/CPP/Windows/ResourceString.h @@ -1,21 +1,15 @@ // Windows/ResourceString.h -#ifndef __WINDOWS_RESOURCESTRING_H -#define __WINDOWS_RESOURCESTRING_H +#ifndef __WINDOWS_RESOURCE_STRING_H +#define __WINDOWS_RESOURCE_STRING_H -#include "Common/MyString.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 +UString MyLoadString(UINT resourceID); +void MyLoadString(HINSTANCE hInstance, UINT resourceID, UString &dest); +void MyLoadString(UINT resourceID, UString &dest); } diff --git a/CPP/Windows/Security.cpp b/CPP/Windows/Security.cpp deleted file mode 100755 index 6f5bcad3..00000000 --- a/CPP/Windows/Security.cpp +++ /dev/null @@ -1,179 +0,0 @@ -// 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 deleted file mode 100755 index ba66de44..00000000 --- a/CPP/Windows/Security.h +++ /dev/null @@ -1,167 +0,0 @@ -// 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/SecurityUtils.cpp b/CPP/Windows/SecurityUtils.cpp new file mode 100644 index 00000000..99ac04bc --- /dev/null +++ b/CPP/Windows/SecurityUtils.cpp @@ -0,0 +1,179 @@ +// Windows/SecurityUtils.cpp + +#include "StdAfx.h" + +#include "SecurityUtils.h" + +namespace NWindows { +namespace NSecurity { + +/* +bool MyLookupAccountSid(LPCTSTR systemName, PSID sid, + CSysString &accountName, CSysString &domainName, PSID_NAME_USE sidNameUse) +{ + DWORD accountNameSize = 0, domainNameSize = 0; + + if (!::LookupAccountSid(systemName, sid, + accountName.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/SecurityUtils.h b/CPP/Windows/SecurityUtils.h new file mode 100644 index 00000000..8966dfd3 --- /dev/null +++ b/CPP/Windows/SecurityUtils.h @@ -0,0 +1,167 @@ +// Windows/SecurityUtils.h + +#ifndef __WINDOWS_SECURITY_UTILS_H +#define __WINDOWS_SECURITY_UTILS_H + +#include + +#include "Defs.h" + +namespace NWindows { +namespace NSecurity { + +class CAccessToken +{ + HANDLE _handle; +public: + CAccessToken(): _handle(NULL) {}; + ~CAccessToken() { Close(); } + bool Close() + { + if (_handle == NULL) + return true; + bool res = BOOLToBool(::CloseHandle(_handle)); + if (res) + _handle = NULL; + return res; + } + + bool OpenProcessToken(HANDLE processHandle, DWORD desiredAccess) + { + Close(); + return BOOLToBool(::OpenProcessToken(processHandle, desiredAccess, &_handle)); + } + + /* + bool OpenThreadToken(HANDLE threadHandle, DWORD desiredAccess, bool openAsSelf) + { + Close(); + return BOOLToBool(::OpenTreadToken(threadHandle, desiredAccess, BoolToBOOL(anOpenAsSelf), &_handle)); + } + */ + + bool AdjustPrivileges(bool disableAllPrivileges, PTOKEN_PRIVILEGES newState, + DWORD bufferLength, PTOKEN_PRIVILEGES previousState, PDWORD returnLength) + { return BOOLToBool(::AdjustTokenPrivileges(_handle, BoolToBOOL(disableAllPrivileges), + newState, bufferLength, previousState, returnLength)); } + + bool AdjustPrivileges(bool disableAllPrivileges, PTOKEN_PRIVILEGES newState) + { return AdjustPrivileges(disableAllPrivileges, newState, 0, NULL, NULL); } + + bool AdjustPrivileges(PTOKEN_PRIVILEGES newState) + { return AdjustPrivileges(false, newState); } + +}; + +#ifndef _UNICODE +typedef NTSTATUS (NTAPI *LsaOpenPolicyP)(PLSA_UNICODE_STRING SystemName, + PLSA_OBJECT_ATTRIBUTES ObjectAttributes, ACCESS_MASK DesiredAccess, PLSA_HANDLE PolicyHandle); +typedef NTSTATUS (NTAPI *LsaCloseP)(LSA_HANDLE ObjectHandle); +typedef NTSTATUS (NTAPI *LsaAddAccountRightsP)(LSA_HANDLE PolicyHandle, + PSID AccountSid, PLSA_UNICODE_STRING UserRights, ULONG CountOfRights ); +#define MY_STATUS_NOT_IMPLEMENTED ((NTSTATUS)0xC0000002L) +#endif + +struct CPolicy +{ +protected: + LSA_HANDLE _handle; + #ifndef _UNICODE + HMODULE hModule; + #endif +public: + operator LSA_HANDLE() const { return _handle; } + CPolicy(): _handle(NULL) + { + #ifndef _UNICODE + hModule = GetModuleHandle(TEXT("Advapi32.dll")); + #endif + }; + ~CPolicy() { Close(); } + + NTSTATUS Open(PLSA_UNICODE_STRING systemName, PLSA_OBJECT_ATTRIBUTES objectAttributes, + ACCESS_MASK desiredAccess) + { + #ifndef _UNICODE + if (hModule == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + LsaOpenPolicyP lsaOpenPolicy = (LsaOpenPolicyP)GetProcAddress(hModule, "LsaOpenPolicy"); + if (lsaOpenPolicy == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + #endif + + Close(); + return + #ifdef _UNICODE + ::LsaOpenPolicy + #else + lsaOpenPolicy + #endif + (systemName, objectAttributes, desiredAccess, &_handle); + } + + NTSTATUS Close() + { + if (_handle == NULL) + return 0; + + #ifndef _UNICODE + if (hModule == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + LsaCloseP lsaClose = (LsaCloseP)GetProcAddress(hModule, "LsaClose"); + if (lsaClose == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + #endif + + NTSTATUS res = + #ifdef _UNICODE + ::LsaClose + #else + lsaClose + #endif + (_handle); + _handle = NULL; + return res; + } + + NTSTATUS EnumerateAccountsWithUserRight(PLSA_UNICODE_STRING userRights, + PLSA_ENUMERATION_INFORMATION *enumerationBuffer, PULONG countReturned) + { return LsaEnumerateAccountsWithUserRight(_handle, userRights, (void **)enumerationBuffer, countReturned); } + + NTSTATUS EnumerateAccountRights(PSID sid, PLSA_UNICODE_STRING* userRights, PULONG countOfRights) + { return ::LsaEnumerateAccountRights(_handle, sid, userRights, countOfRights); } + + NTSTATUS LookupSids(ULONG count, PSID* sids, + PLSA_REFERENCED_DOMAIN_LIST* referencedDomains, PLSA_TRANSLATED_NAME* names) + { return LsaLookupSids(_handle, count, sids, referencedDomains, names); } + + NTSTATUS AddAccountRights(PSID accountSid, PLSA_UNICODE_STRING userRights, ULONG countOfRights) + { + #ifndef _UNICODE + if (hModule == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + LsaAddAccountRightsP lsaAddAccountRights = (LsaAddAccountRightsP)GetProcAddress(hModule, "LsaAddAccountRights"); + if (lsaAddAccountRights == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + #endif + + return + #ifdef _UNICODE + ::LsaAddAccountRights + #else + lsaAddAccountRights + #endif + (_handle, accountSid, userRights, countOfRights); + } + NTSTATUS AddAccountRights(PSID accountSid, PLSA_UNICODE_STRING userRights) + { return AddAccountRights(accountSid, userRights, 1); } + + NTSTATUS RemoveAccountRights(PSID accountSid, bool allRights, PLSA_UNICODE_STRING userRights, ULONG countOfRights) + { return LsaRemoveAccountRights(_handle, accountSid, (BOOLEAN)(allRights ? TRUE : FALSE), userRights, countOfRights); } +}; + +bool AddLockMemoryPrivilege(); + +}} + +#endif diff --git a/CPP/Windows/Shell.cpp b/CPP/Windows/Shell.cpp old mode 100755 new mode 100644 index 010449fb..2eb1a960 --- a/CPP/Windows/Shell.cpp +++ b/CPP/Windows/Shell.cpp @@ -2,13 +2,13 @@ #include "StdAfx.h" -#include "Common/MyCom.h" +#include "../Common/MyCom.h" #ifndef _UNICODE -#include "Common/StringConvert.h" +#include "../Common/StringConvert.h" #endif -#include "Windows/COM.h" -#include "Windows/Shell.h" +#include "COM.h" +#include "Shell.h" #ifndef _UNICODE extern bool g_IsNT; @@ -111,11 +111,10 @@ UString CDrop::QueryFileName(UINT fileIndex) void CDrop::QueryFileNames(UStringVector &fileNames) { - fileNames.Clear(); UINT numFiles = QueryCountOfFiles(); - fileNames.Reserve(numFiles); + fileNames.ClearAndReserve(numFiles); for (UINT i = 0; i < numFiles; i++) - fileNames.Add(QueryFileName(i)); + fileNames.AddInReserved(QueryFileName(i)); } @@ -140,8 +139,8 @@ bool BrowseForFolder(HWND, LPCTSTR, UINT, LPCTSTR, CSysString &) return false; } -bool BrowseForFolder(HWND owner, LPCTSTR title, - LPCTSTR initialFolder, CSysString &resultPath) +bool BrowseForFolder(HWND /* owner */, LPCTSTR /* title */, + LPCTSTR /* initialFolder */, CSysString & /* resultPath */) { /* // SHBrowseForFolder doesn't work before CE 6.0 ? diff --git a/CPP/Windows/Shell.h b/CPP/Windows/Shell.h old mode 100755 new mode 100644 index d2b39acf..4bff18cf --- a/CPP/Windows/Shell.h +++ b/CPP/Windows/Shell.h @@ -6,8 +6,9 @@ #include #include -#include "Common/MyString.h" -#include "Windows/Defs.h" +#include "../Common/MyString.h" + +#include "Defs.h" namespace NWindows{ namespace NShell{ diff --git a/CPP/Windows/StdAfx.h b/CPP/Windows/StdAfx.h old mode 100755 new mode 100644 index 8b383c5b..1766dfa8 --- a/CPP/Windows/StdAfx.h +++ b/CPP/Windows/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../Common/MyWindows.h" -#include "../Common/NewHandler.h" +#include "../Common/Common.h" #endif diff --git a/CPP/Windows/Synchronization.cpp b/CPP/Windows/Synchronization.cpp old mode 100755 new mode 100644 diff --git a/CPP/Windows/Synchronization.h b/CPP/Windows/Synchronization.h old mode 100755 new mode 100644 diff --git a/CPP/Windows/System.cpp b/CPP/Windows/System.cpp old mode 100755 new mode 100644 diff --git a/CPP/Windows/System.h b/CPP/Windows/System.h old mode 100755 new mode 100644 index e0067158..4133a7b3 --- a/CPP/Windows/System.h +++ b/CPP/Windows/System.h @@ -3,7 +3,7 @@ #ifndef __WINDOWS_SYSTEM_H #define __WINDOWS_SYSTEM_H -#include "../Common/Types.h" +#include "../Common/MyTypes.h" namespace NWindows { namespace NSystem { diff --git a/CPP/Windows/Thread.h b/CPP/Windows/Thread.h old mode 100755 new mode 100644 diff --git a/CPP/Windows/Time.cpp b/CPP/Windows/Time.cpp deleted file mode 100755 index 2cb028f9..00000000 --- a/CPP/Windows/Time.cpp +++ /dev/null @@ -1,203 +0,0 @@ -// 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 kUnixTimeOffset = - (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear)); -static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond; - -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 = (kUnixTimeOffset + (UInt64)unixTime) * kNumTimeQuantumsInSecond; - ft.dwLowDateTime = (DWORD)v; - ft.dwHighDateTime = (DWORD)(v >> 32); -} - -bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &ft) -{ - Int64 v = (Int64)kUnixTimeOffset + unixTime; - if (unixTime < 0) - { - if (v < 0) - { - ft.dwLowDateTime = ft.dwHighDateTime = 0; - return false; - } - } - else - { - if (v < unixTime || v > kNumSecondsInFileTime) - { - ft.dwLowDateTime = ft.dwHighDateTime = (UInt32)(Int32)-1; - return false; - } - } - UInt64 v2 = (UInt64)v * kNumTimeQuantumsInSecond; - ft.dwLowDateTime = (DWORD)v2; - ft.dwHighDateTime = (DWORD)(v2 >> 32); - return true; -} - -Int64 FileTimeToUnixTime64(const FILETIME &ft) -{ - UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; - return (Int64)(winTime / kNumTimeQuantumsInSecond) - kUnixTimeOffset; -} - -bool FileTimeToUnixTime(const FILETIME &ft, UInt32 &unixTime) -{ - UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; - winTime /= kNumTimeQuantumsInSecond; - if (winTime < kUnixTimeOffset) - { - unixTime = 0; - return false; - } - winTime -= kUnixTimeOffset; - if (winTime > 0xFFFFFFFF) - { - unixTime = 0xFFFFFFFF; - return false; - } - unixTime = (UInt32)winTime; - return true; -} - -bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, - unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) -{ - 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 deleted file mode 100755 index 537b80e6..00000000 --- a/CPP/Windows/Time.h +++ /dev/null @@ -1,23 +0,0 @@ -// 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 UnixTime64ToFileTime(Int64 unixTime, FILETIME &fileTime); -bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime); -Int64 FileTimeToUnixTime64(const FILETIME &ft); -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/TimeUtils.cpp b/CPP/Windows/TimeUtils.cpp new file mode 100644 index 00000000..0b50845b --- /dev/null +++ b/CPP/Windows/TimeUtils.cpp @@ -0,0 +1,209 @@ +// Windows/TimeUtils.cpp + +#include "StdAfx.h" + +#include "Defs.h" +#include "TimeUtils.h" + +namespace NWindows { +namespace NTime { + +static const UInt32 kNumTimeQuantumsInSecond = 10000000; +static const UInt32 kFileTimeStartYear = 1601; +static const UInt32 kDosTimeStartYear = 1980; +static const UInt32 kUnixTimeStartYear = 1970; +static const UInt64 kUnixTimeOffset = + (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear)); +static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond; + +bool DosTimeToFileTime(UInt32 dosTime, FILETIME &ft) +{ + #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 = (kUnixTimeOffset + (UInt64)unixTime) * kNumTimeQuantumsInSecond; + ft.dwLowDateTime = (DWORD)v; + ft.dwHighDateTime = (DWORD)(v >> 32); +} + +bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &ft) +{ + Int64 v = (Int64)kUnixTimeOffset + unixTime; + if (unixTime < 0) + { + if (v < 0) + { + ft.dwLowDateTime = ft.dwHighDateTime = 0; + return false; + } + } + else + { + if (v < unixTime || v > kNumSecondsInFileTime) + { + ft.dwLowDateTime = ft.dwHighDateTime = (UInt32)(Int32)-1; + return false; + } + } + UInt64 v2 = (UInt64)v * kNumTimeQuantumsInSecond; + ft.dwLowDateTime = (DWORD)v2; + ft.dwHighDateTime = (DWORD)(v2 >> 32); + return true; +} + +Int64 FileTimeToUnixTime64(const FILETIME &ft) +{ + UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; + return (Int64)(winTime / kNumTimeQuantumsInSecond) - kUnixTimeOffset; +} + +bool FileTimeToUnixTime(const FILETIME &ft, UInt32 &unixTime) +{ + UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; + winTime /= kNumTimeQuantumsInSecond; + if (winTime < kUnixTimeOffset) + { + unixTime = 0; + return false; + } + winTime -= kUnixTimeOffset; + if (winTime > 0xFFFFFFFF) + { + unixTime = 0xFFFFFFFF; + return false; + } + unixTime = (UInt32)winTime; + return true; +} + +bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, + unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) +{ + 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) +{ + // Both variants provide same low resolution on WinXP: about 15 ms. + // But GetSystemTimeAsFileTime is much faster. + + #ifdef UNDER_CE + SYSTEMTIME st; + GetSystemTime(&st); + SystemTimeToFileTime(&st, &ft); + #else + GetSystemTimeAsFileTime(&ft); + #endif +} + +}} diff --git a/CPP/Windows/TimeUtils.h b/CPP/Windows/TimeUtils.h new file mode 100644 index 00000000..2967214e --- /dev/null +++ b/CPP/Windows/TimeUtils.h @@ -0,0 +1,23 @@ +// Windows/TimeUtils.h + +#ifndef __WINDOWS_TIME_UTILS_H +#define __WINDOWS_TIME_UTILS_H + +#include "../Common/MyTypes.h" + +namespace NWindows { +namespace NTime { + +bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime) throw(); +bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime) throw(); +void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime) throw(); +bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &fileTime) throw(); +bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime) throw(); +Int64 FileTimeToUnixTime64(const FILETIME &ft) throw(); +bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, + unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw(); +void GetCurUtcFileTime(FILETIME &ft) throw(); + +}} + +#endif diff --git a/CPP/Windows/Window.cpp b/CPP/Windows/Window.cpp old mode 100755 new mode 100644 index 3ad29e6d..f1d4d95b --- a/CPP/Windows/Window.cpp +++ b/CPP/Windows/Window.cpp @@ -3,9 +3,9 @@ #include "StdAfx.h" #ifndef _UNICODE -#include "Common/StringConvert.h" +#include "../Common/StringConvert.h" #endif -#include "Windows/Window.h" +#include "Window.h" #ifndef _UNICODE extern bool g_IsNT; diff --git a/CPP/Windows/Window.h b/CPP/Windows/Window.h old mode 100755 new mode 100644 index 729b0f24..2446499a --- a/CPP/Windows/Window.h +++ b/CPP/Windows/Window.h @@ -3,8 +3,27 @@ #ifndef __WINDOWS_WINDOW_H #define __WINDOWS_WINDOW_H +#include "../Common/MyString.h" + #include "Defs.h" -#include "Common/MyString.h" + +#ifndef UNDER_CE + +#define MY__WM_CHANGEUISTATE 0x0127 +#define MY__WM_UPDATEUISTATE 0x0128 +#define MY__WM_QUERYUISTATE 0x0129 + +// LOWORD(wParam) values in WM_*UISTATE +#define MY__UIS_SET 1 +#define MY__UIS_CLEAR 2 +#define MY__UIS_INITIALIZE 3 + +// HIWORD(wParam) values in WM_*UISTATE +#define MY__UISF_HIDEFOCUS 0x1 +#define MY__UISF_HIDEACCEL 0x2 +#define MY__UISF_ACTIVE 0x4 + +#endif namespace NWindows { @@ -142,6 +161,8 @@ public: bool GetClientRect(LPRECT rect) { return BOOLToBool(::GetClientRect(_window, rect)); } bool Show(int cmdShow) { return BOOLToBool(::ShowWindow(_window, cmdShow)); } + bool Show_Bool(bool show) { return Show(show ? SW_SHOW: SW_HIDE); } + #ifndef UNDER_CE bool SetPlacement(CONST WINDOWPLACEMENT *placement) { return BOOLToBool(::SetWindowPlacement(_window, placement)); } bool GetPlacement(WINDOWPLACEMENT *placement) { return BOOLToBool(::GetWindowPlacement(_window, placement)); } @@ -255,7 +276,8 @@ public: #define RECT_SIZE_X(r) ((r).right - (r).left) #define RECT_SIZE_Y(r) ((r).bottom - (r).top) +inline bool IsKeyDown(int virtKey) { return (::GetKeyState(virtKey) & 0x8000) != 0; } + } #endif - diff --git a/DOC/7zC.txt b/DOC/7zC.txt old mode 100755 new mode 100644 index 5d5d06d7..d929b254 --- a/DOC/7zC.txt +++ b/DOC/7zC.txt @@ -1,4 +1,4 @@ -7z ANSI-C Decoder 4.62 +7z ANSI-C Decoder 9.24 ---------------------- 7z ANSI-C provides 7z/LZMA decoding. @@ -112,14 +112,9 @@ SzArEx_Open function allocates and frees temporary structures by "allocTemp" fun 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); - } - } + + Use SzArEx_GetFileNameUtf16 function. Look example code in C\Util\7z\7zMain.c file. + Extracting code: ~~~~~~~~~~~~~~~~ diff --git a/DOC/7zFormat.txt b/DOC/7zFormat.txt old mode 100755 new mode 100644 diff --git a/DOC/7zip.hhp b/DOC/7zip.hhp old mode 100755 new mode 100644 index c171d255..5f412bff --- a/DOC/7zip.hhp +++ b/DOC/7zip.hhp @@ -21,15 +21,17 @@ general\7z.htm cmdline\index.htm cmdline\syntax.htm cmdline\exit_codes.htm -cmdline\commands\update.htm +cmdline\commands\add.htm +cmdline\commands\bench.htm cmdline\commands\delete.htm cmdline\commands\extract.htm cmdline\commands\extract_full.htm +cmdline\commands\update.htm +cmdline\commands\hash.htm cmdline\commands\index.htm cmdline\commands\list.htm +cmdline\commands\rename.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 @@ -37,7 +39,6 @@ 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 @@ -46,11 +47,19 @@ cmdline\switches\output_dir.htm cmdline\switches\overwrite.htm cmdline\switches\password.htm cmdline\switches\recurse.htm +cmdline\switches\sa.htm +cmdline\switches\scc.htm +cmdline\switches\scrc.htm +cmdline\switches\sdel.htm cmdline\switches\sfx.htm cmdline\switches\shared.htm +cmdline\switches\sni.htm +cmdline\switches\sns.htm +cmdline\switches\spf.htm cmdline\switches\ssc.htm cmdline\switches\stdin.htm cmdline\switches\stdout.htm +cmdline\switches\stl.htm cmdline\switches\stop_switch.htm cmdline\switches\type.htm cmdline\switches\update.htm diff --git a/DOC/7zip.inf b/DOC/7zip.inf old mode 100755 new mode 100644 index 9dfded19..e3b63a10 --- a/DOC/7zip.inf +++ b/DOC/7zip.inf @@ -10,8 +10,8 @@ AppName = "7-Zip" InstallDir = %CE1%\%AppName% [Strings] -AppVer = "9.22" -AppDate = "2011-04-18" +AppVer = "9.23" +AppDate = "2011-06-17" [CEDevice] ; ProcessorType = 2577 ; ARM diff --git a/DOC/7zip.nsi b/DOC/7zip.nsi old mode 100755 new mode 100644 index 23010b8c..a805c949 --- a/DOC/7zip.nsi +++ b/DOC/7zip.nsi @@ -2,8 +2,8 @@ ;Defines !define VERSION_MAJOR 9 -!define VERSION_MINOR 22 -!define VERSION_POSTFIX_FULL "beta" +!define VERSION_MINOR 34 +!define VERSION_POSTFIX_FULL " alpha" !ifdef WIN64 !ifdef IA64 !define VERSION_SYS_POSTFIX_FULL " for Windows IA-64" @@ -108,6 +108,7 @@ Section !endif # delete old unwanted files + Delete $INSTDIR\7zFMn.exe Delete $INSTDIR\7zgn.exe Delete $INSTDIR\7zn.exe @@ -116,6 +117,8 @@ Section Delete $INSTDIR\7-zipn.dll Delete $INSTDIR\7zipDoc.txt Delete $INSTDIR\file_id.diz + Delete $INSTDIR\7zip_pad.xml + Delete $INSTDIR\copying.txt Delete $INSTDIR\Codecs\7zAES.dll Delete $INSTDIR\Codecs\AES.dll @@ -154,33 +157,29 @@ Section Delete $INSTDIR\Lang\no.txt # install files - SetOutPath "$INSTDIR" + + SetOutPath $INSTDIR File descript.ion File History.txt File License.txt File readme.txt + File 7-zip.chm # File 7-zip.dll - # File 7-zipn.dll + + File 7z.dll File 7zFM.exe + File 7zG.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 an.txt File ar.txt File ast.txt File az.txt @@ -206,6 +205,7 @@ Section File fr.txt File fur.txt File fy.txt + File ga.txt File gl.txt File gu.txt File he.txt @@ -219,6 +219,7 @@ Section File it.txt File ja.txt File ka.txt + File kaa.txt File kk.txt File ko.txt File ku.txt @@ -229,6 +230,8 @@ Section File lv.txt File mk.txt File mn.txt + File mng.txt + File mng2.txt File mr.txt File ms.txt File ne.txt @@ -268,7 +271,7 @@ Section Delete "$SMPROGRAMS\7-Zip\${FM_LINK}" Delete "$SMPROGRAMS\7-Zip\${HELP_LINK}" - RMDir "$SMPROGRAMS\7-Zip" + RMDir $SMPROGRAMS\7-Zip # set "all users" mode @@ -279,54 +282,57 @@ Section 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 + SetOutPath $INSTDIR + + 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 + CreateShortCut "$SMPROGRAMS\7-Zip\${FM_LINK}" $INSTDIR\7zFM.exe + CreateShortCut "$SMPROGRAMS\7-Zip\${HELP_LINK}" $INSTDIR\7-zip.chm - noScErrors: +noScErrors: # store install folder - WriteRegStr HKLM "Software\7-Zip" "Path32" $INSTDIR - WriteRegStr HKLM "Software\7-Zip" "Path" $INSTDIR - WriteRegStr HKCU "Software\7-Zip" "Path32" $INSTDIR - WriteRegStr HKCU "Software\7-Zip" "Path" $INSTDIR + + WriteRegStr HKLM Software\7-Zip Path32 $INSTDIR + WriteRegStr HKLM Software\7-Zip Path $INSTDIR + WriteRegStr HKCU Software\7-Zip Path32 $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 "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 + DeleteRegValue HKCR "CLSID\${CLSID_CONTEXT_MENU}\InprocServer32" "InprocServer32" 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 "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" + 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" + 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 !ifdef WIN64 ExecWait 'regsvr32 /s "$INSTDIR\7-zip.dll"' @@ -346,10 +352,13 @@ Function .onInit FunctionEnd */ + + + ;-------------------------------- ;Uninstaller Section -Section "Uninstall" +Section Uninstall ExecWait 'regsvr32 /u /s "$INSTDIR\7-zip.dll"' @@ -358,28 +367,19 @@ Section "Uninstall" 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 $INSTDIR\7-zip.chm - Delete /REBOOTOK $INSTDIR\7-zip.dll + Delete $INSTDIR\7z.dll Delete $INSTDIR\7zFM.exe + Delete $INSTDIR\7zG.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\an.txt Delete $INSTDIR\Lang\ar.txt Delete $INSTDIR\Lang\ast.txt Delete $INSTDIR\Lang\az.txt @@ -405,6 +405,7 @@ Section "Uninstall" Delete $INSTDIR\Lang\fr.txt Delete $INSTDIR\Lang\fur.txt Delete $INSTDIR\Lang\fy.txt + Delete $INSTDIR\Lang\ga.txt Delete $INSTDIR\Lang\gl.txt Delete $INSTDIR\Lang\gu.txt Delete $INSTDIR\Lang\he.txt @@ -418,6 +419,7 @@ Section "Uninstall" Delete $INSTDIR\Lang\it.txt Delete $INSTDIR\Lang\ja.txt Delete $INSTDIR\Lang\ka.txt + Delete $INSTDIR\Lang\kaa.txt Delete $INSTDIR\Lang\kk.txt Delete $INSTDIR\Lang\ko.txt Delete $INSTDIR\Lang\ku.txt @@ -428,6 +430,8 @@ Section "Uninstall" Delete $INSTDIR\Lang\lv.txt Delete $INSTDIR\Lang\mk.txt Delete $INSTDIR\Lang\mn.txt + Delete $INSTDIR\Lang\mng.txt + Delete $INSTDIR\Lang\mng2.txt Delete $INSTDIR\Lang\mr.txt Delete $INSTDIR\Lang\ms.txt Delete $INSTDIR\Lang\ne.txt @@ -465,6 +469,7 @@ Section "Uninstall" RMDir $INSTDIR\Lang + Delete /REBOOTOK $INSTDIR\7-zip.dll Delete $INSTDIR\Uninstall.exe RMDir $INSTDIR @@ -477,7 +482,7 @@ Section "Uninstall" Delete "$SMPROGRAMS\7-Zip\${FM_LINK}" Delete "$SMPROGRAMS\7-Zip\${HELP_LINK}" - RMDir "$SMPROGRAMS\7-Zip" + RMDir $SMPROGRAMS\7-Zip # IfErrors 0 noScErrors @@ -485,66 +490,66 @@ Section "Uninstall" Delete "$SMPROGRAMS\7-Zip\${FM_LINK}" Delete "$SMPROGRAMS\7-Zip\${HELP_LINK}" - RMDir "$SMPROGRAMS\7-Zip" + RMDir $SMPROGRAMS\7-Zip # noScErrors: # delete registry entries - DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\7-Zip" + 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 HKLM Software\7-Zip + DeleteRegKey HKCU Software\7-Zip - DeleteRegKey HKCR "CLSID\${CLSID_CONTEXT_MENU}" + 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 *\shellex\ContextMenuHandlers\7-Zip + DeleteRegKey HKCR Directory\shellex\ContextMenuHandlers\7-Zip + DeleteRegKey HKCR Folder\shellex\ContextMenuHandlers\7-Zip - DeleteRegKey HKCR "Drive\shellex\DragDropHandlers\7-Zip" - DeleteRegKey HKCR "Directory\shellex\DragDropHandlers\7-Zip" - DeleteRegKey HKCR "Folder\shellex\DragDropHandlers\7-Zip" + DeleteRegKey HKCR Drive\shellex\DragDropHandlers\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.fat" - 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.ntfs" - DeleteRegKey HKCR "7-Zip.rar" - DeleteRegKey HKCR "7-Zip.rpm" - DeleteRegKey HKCR "7-Zip.split" - DeleteRegKey HKCR "7-Zip.squashfs" - 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.txz" - DeleteRegKey HKCR "7-Zip.vhd" - DeleteRegKey HKCR "7-Zip.wim" - DeleteRegKey HKCR "7-Zip.xar" - DeleteRegKey HKCR "7-Zip.xz" - DeleteRegKey HKCR "7-Zip.z" - DeleteRegKey HKCR "7-Zip.zip" + 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.fat + 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.ntfs + DeleteRegKey HKCR 7-Zip.rar + DeleteRegKey HKCR 7-Zip.rpm + DeleteRegKey HKCR 7-Zip.split + DeleteRegKey HKCR 7-Zip.squashfs + 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.txz + DeleteRegKey HKCR 7-Zip.vhd + DeleteRegKey HKCR 7-Zip.wim + DeleteRegKey HKCR 7-Zip.xar + DeleteRegKey HKCR 7-Zip.xz + DeleteRegKey HKCR 7-Zip.z + DeleteRegKey HKCR 7-Zip.zip SectionEnd diff --git a/DOC/7zip.wxs b/DOC/7zip.wxs old mode 100755 new mode 100644 index 26a25947..3154a324 --- a/DOC/7zip.wxs +++ b/DOC/7zip.wxs @@ -1,7 +1,7 @@ - + @@ -206,10 +206,6 @@ Value="Apartment" /> - - - - @@ -218,6 +214,10 @@ + + + + @@ -244,6 +244,7 @@ + @@ -269,6 +270,7 @@ + @@ -282,6 +284,7 @@ + @@ -292,6 +295,8 @@ + + diff --git a/DOC/License.txt b/DOC/License.txt old mode 100755 new mode 100644 diff --git a/DOC/Methods.txt b/DOC/Methods.txt old mode 100755 new mode 100644 index f52e7c31..ede83041 --- a/DOC/Methods.txt +++ b/DOC/Methods.txt @@ -1,4 +1,4 @@ -7-Zip method IDs (9.18) +7-Zip method IDs (9.24) ----------------------- Each compression or crypto method in 7z has unique binary value (ID). @@ -103,24 +103,22 @@ List of defined IDs 06.. - Crypto - 00 - - 01 - AES - 0x - AES-128 - 4x - AES-192 - 8x - AES-256 - Cx - AES - x0 - ECB - x1 - CBC - x2 - CFB - x3 - OFB + F0 - Ciphers without hashing algo - 07 - Reserved - 0F - Reserved + 01 - AES + 0x - AES-128 + 4x - AES-192 + 8x - AES-256 + Cx - AES - F0 - Misc Ciphers (Real Ciphers without hashing algo) + x0 - ECB + x1 - CBC + x2 - CFB + x3 - OFB + x4 - CTR - F1 - Misc Ciphers (Combine) + F1 - Combine Ciphers 01 - Zip 01 - Main Zip crypto algo 03 - RAR @@ -129,24 +127,6 @@ List of defined IDs 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 old mode 100755 new mode 100644 diff --git a/DOC/history.txt b/DOC/history.txt old mode 100755 new mode 100644 index 64ce04ae..27a0e6c4 --- a/DOC/history.txt +++ b/DOC/history.txt @@ -1,6 +1,18 @@ Sources history of the 7-Zip ---------------------------- +9.31 2012-10-31 +------------------------- +- InBuffer.h : CInBuffer uses ISequentialInStream *_stream; instead of CMyComPtr + OutBuffer.h: COutBuffer uses ISequentialOutStream *_stream; instead of CMyComPtr + + +9.26 2011-04-11 +------------------------- +- The BUG was fixed: multi-threaded ZIP stored file size that was at scan stage, + So if the file was changed after scan, the Unpack Size field was incorrect + + 9.21 2011-04-11 ------------------------- - New class FString for file names at file systems. diff --git a/DOC/lzma.txt b/DOC/lzma.txt old mode 100755 new mode 100644 index 77e5b616..8bd4bf94 --- a/DOC/lzma.txt +++ b/DOC/lzma.txt @@ -1,4 +1,4 @@ -LZMA SDK 9.22 +LZMA SDK 9.31 ------------- LZMA SDK provides the documentation, samples, header files, libraries, @@ -451,8 +451,16 @@ 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 +Compile files: + Types.h + Threads.h + LzmaEnc.h + LzmaEnc.c + LzFind.h + LzFind.c + LzFindMt.h + LzFindMt.c + LzHash.h Memory Requirements: - (dictSize * 11.5 + 6 MB) + state_size @@ -472,7 +480,7 @@ Single-call Compression with callbacks Check C/LzmaUtil/LzmaUtil.c as example, -When to use: file->file decompressing +When to use: file->file compressing 1) you must implement callback structures for interfaces: ISeqInStream @@ -543,8 +551,8 @@ 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, +SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); Return code: diff --git a/DOC/readme.txt b/DOC/readme.txt old mode 100755 new mode 100644 index cc138f67..ec0d4716 --- a/DOC/readme.txt +++ b/DOC/readme.txt @@ -1,9 +1,9 @@ -7-Zip 9.22 Sources +7-Zip 9.32 Sources ------------------ 7-Zip is a file archiver for Windows. -7-Zip Copyright (C) 1999-2010 Igor Pavlov. +7-Zip Copyright (C) 1999-2013 Igor Pavlov. License Info diff --git a/DOC/unRarLicense.txt b/DOC/unRarLicense.txt old mode 100755 new mode 100644 -- cgit v1.2.3