Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2014-11-23 03:00:00 +0300
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:16:51 +0300
commitf08f4dcc3c02464c17753b3feafcfe5243b9e236 (patch)
treeb0e1b15bc5368d92dff422e8ec0818564a2b00b8
parent83f8ddcc5b2161e1e3c49666265257fca8aeb12c (diff)
9.349.34
-rw-r--r--[-rwxr-xr-x]Asm/arm/7zCrcOpt.asm0
-rw-r--r--[-rwxr-xr-x]Asm/x86/7zAsm.asm28
-rw-r--r--[-rwxr-xr-x]Asm/x86/7zCrcOpt.asm0
-rw-r--r--[-rwxr-xr-x]Asm/x86/AesOpt.asm0
-rw-r--r--Asm/x86/XzCrc64Opt.asm205
-rw-r--r--[-rwxr-xr-x]C/7z.h175
-rw-r--r--[-rwxr-xr-x]C/7zAlloc.c2
-rw-r--r--[-rwxr-xr-x]C/7zAlloc.h0
-rw-r--r--C/7zArcIn.c1839
-rw-r--r--[-rwxr-xr-x]C/7zBuf.c6
-rw-r--r--[-rwxr-xr-x]C/7zBuf.h12
-rw-r--r--[-rwxr-xr-x]C/7zBuf2.c5
-rw-r--r--[-rwxr-xr-x]C/7zCrc.c6
-rw-r--r--[-rwxr-xr-x]C/7zCrc.h4
-rw-r--r--[-rwxr-xr-x]C/7zCrcOpt.c4
-rw-r--r--[-rwxr-xr-x]C/7zDec.c109
-rw-r--r--[-rwxr-xr-x]C/7zFile.c2
-rw-r--r--[-rwxr-xr-x]C/7zFile.h4
-rwxr-xr-xC/7zIn.c1402
-rw-r--r--[-rwxr-xr-x]C/7zStream.c6
-rw-r--r--[-rwxr-xr-x]C/7zTypes.h (renamed from C/Types.h)14
-rw-r--r--[-rwxr-xr-x]C/7zVersion.h10
-rw-r--r--[-rwxr-xr-x]C/7zVersion.rc0
-rw-r--r--[-rwxr-xr-x]C/Aes.c4
-rw-r--r--[-rwxr-xr-x]C/Aes.h4
-rw-r--r--[-rwxr-xr-x]C/AesOpt.c4
-rw-r--r--[-rwxr-xr-x]C/Alloc.c6
-rw-r--r--[-rwxr-xr-x]C/Alloc.h0
-rw-r--r--[-rwxr-xr-x]C/Bcj2.c2
-rw-r--r--[-rwxr-xr-x]C/Bcj2.h12
-rw-r--r--[-rwxr-xr-x]C/Bra.c2
-rw-r--r--[-rwxr-xr-x]C/Bra.h12
-rw-r--r--[-rwxr-xr-x]C/Bra86.c99
-rw-r--r--[-rwxr-xr-x]C/BraIA64.c4
-rw-r--r--[-rwxr-xr-x]C/BwtSort.c6
-rw-r--r--[-rwxr-xr-x]C/BwtSort.h12
-rw-r--r--C/Compiler.h28
-rw-r--r--[-rwxr-xr-x]C/CpuArch.c26
-rw-r--r--[-rwxr-xr-x]C/CpuArch.h14
-rw-r--r--[-rwxr-xr-x]C/Delta.c2
-rw-r--r--[-rwxr-xr-x]C/Delta.h12
-rw-r--r--[-rwxr-xr-x]C/HuffEnc.c2
-rw-r--r--[-rwxr-xr-x]C/HuffEnc.h12
-rw-r--r--[-rwxr-xr-x]C/LzFind.c2
-rw-r--r--[-rwxr-xr-x]C/LzFind.h12
-rw-r--r--[-rwxr-xr-x]C/LzFindMt.c12
-rw-r--r--[-rwxr-xr-x]C/LzFindMt.h10
-rw-r--r--[-rwxr-xr-x]C/LzHash.h0
-rw-r--r--[-rwxr-xr-x]C/Lzma2Dec.c2
-rw-r--r--[-rwxr-xr-x]C/Lzma2Dec.h10
-rw-r--r--[-rwxr-xr-x]C/Lzma2Enc.c22
-rw-r--r--[-rwxr-xr-x]C/Lzma2Enc.h10
-rw-r--r--[-rwxr-xr-x]C/Lzma86.h4
-rw-r--r--[-rwxr-xr-x]C/Lzma86Dec.c0
-rw-r--r--[-rwxr-xr-x]C/Lzma86Enc.c2
-rw-r--r--[-rwxr-xr-x]C/LzmaDec.c44
-rw-r--r--[-rwxr-xr-x]C/LzmaDec.h12
-rw-r--r--[-rwxr-xr-x]C/LzmaEnc.c12
-rw-r--r--[-rwxr-xr-x]C/LzmaEnc.h6
-rw-r--r--[-rwxr-xr-x]C/LzmaLib.c0
-rw-r--r--[-rwxr-xr-x]C/LzmaLib.h12
-rw-r--r--[-rwxr-xr-x]C/MtCoder.c2
-rw-r--r--[-rwxr-xr-x]C/MtCoder.h0
-rw-r--r--[-rwxr-xr-x]C/Ppmd.h3
-rw-r--r--[-rwxr-xr-x]C/Ppmd7.c2
-rw-r--r--[-rwxr-xr-x]C/Ppmd7.h0
-rw-r--r--[-rwxr-xr-x]C/Ppmd7Dec.c2
-rw-r--r--[-rwxr-xr-x]C/Ppmd7Enc.c2
-rw-r--r--[-rwxr-xr-x]C/Ppmd8.c25
-rw-r--r--[-rwxr-xr-x]C/Ppmd8.h0
-rw-r--r--[-rwxr-xr-x]C/Ppmd8Dec.c2
-rw-r--r--[-rwxr-xr-x]C/Ppmd8Enc.c2
-rw-r--r--C/Precomp.h10
-rw-r--r--[-rwxr-xr-x]C/RotateDefs.h8
-rw-r--r--[-rwxr-xr-x]C/Sha256.c2
-rw-r--r--[-rwxr-xr-x]C/Sha256.h4
-rw-r--r--[-rwxr-xr-x]C/Sort.c70
-rw-r--r--[-rwxr-xr-x]C/Sort.h18
-rw-r--r--[-rwxr-xr-x]C/Threads.c27
-rw-r--r--[-rwxr-xr-x]C/Threads.h26
-rw-r--r--[-rwxr-xr-x]C/Util/7z/7z.dsp33
-rw-r--r--[-rwxr-xr-x]C/Util/7z/7z.dsw0
-rw-r--r--[-rwxr-xr-x]C/Util/7z/7zMain.c151
-rw-r--r--C/Util/7z/Precomp.c4
-rw-r--r--C/Util/7z/Precomp.h10
-rw-r--r--[-rwxr-xr-x]C/Util/7z/makefile10
-rw-r--r--[-rwxr-xr-x]C/Util/7z/makefile.gcc10
-rw-r--r--[-rwxr-xr-x]C/Util/Lzma/LzmaUtil.c4
-rw-r--r--[-rwxr-xr-x]C/Util/Lzma/LzmaUtil.dsp4
-rw-r--r--[-rwxr-xr-x]C/Util/Lzma/LzmaUtil.dsw0
-rw-r--r--[-rwxr-xr-x]C/Util/Lzma/makefile0
-rw-r--r--[-rwxr-xr-x]C/Util/Lzma/makefile.gcc0
-rw-r--r--[-rwxr-xr-x]C/Util/LzmaLib/LzmaLib.def0
-rw-r--r--[-rwxr-xr-x]C/Util/LzmaLib/LzmaLib.dsp8
-rw-r--r--[-rwxr-xr-x]C/Util/LzmaLib/LzmaLib.dsw0
-rw-r--r--[-rwxr-xr-x]C/Util/LzmaLib/LzmaLibExports.c0
-rw-r--r--[-rwxr-xr-x]C/Util/LzmaLib/makefile0
-rw-r--r--[-rwxr-xr-x]C/Util/LzmaLib/resource.rc0
-rw-r--r--C/Util/SfxSetup/Precomp.c4
-rw-r--r--C/Util/SfxSetup/Precomp.h10
-rw-r--r--[-rwxr-xr-x]C/Util/SfxSetup/SfxSetup.c47
-rw-r--r--[-rwxr-xr-x]C/Util/SfxSetup/SfxSetup.dsp23
-rw-r--r--[-rwxr-xr-x]C/Util/SfxSetup/SfxSetup.dsw0
-rw-r--r--[-rwxr-xr-x]C/Util/SfxSetup/makefile4
-rw-r--r--[-rwxr-xr-x]C/Util/SfxSetup/makefile_con5
-rw-r--r--[-rwxr-xr-x]C/Util/SfxSetup/resource.rc0
-rw-r--r--[-rwxr-xr-x]C/Util/SfxSetup/setup.icobin1078 -> 1078 bytes
-rw-r--r--[-rwxr-xr-x]C/Xz.c2
-rw-r--r--[-rwxr-xr-x]C/Xz.h31
-rw-r--r--[-rwxr-xr-x]C/XzCrc64.c89
-rw-r--r--[-rwxr-xr-x]C/XzCrc64.h4
-rw-r--r--C/XzCrc64Opt.c69
-rw-r--r--[-rwxr-xr-x]C/XzDec.c30
-rw-r--r--[-rwxr-xr-x]C/XzEnc.c8
-rw-r--r--[-rwxr-xr-x]C/XzEnc.h0
-rw-r--r--[-rwxr-xr-x]C/XzIn.c4
-rw-r--r--CPP/7zip/7zip.mak240
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Aes.mak0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7z.dsp16
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7z.dsw0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zCompressionMode.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zCompressionMode.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zDecode.cpp123
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zDecode.h9
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zEncode.cpp94
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zEncode.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zExtract.cpp46
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zFolderInStream.cpp4
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zFolderInStream.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zFolderOutStream.cpp2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zFolderOutStream.h6
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zHandler.cpp701
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zHandler.h25
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zHandlerOut.cpp378
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zHeader.cpp5
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zHeader.h10
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zIn.cpp1364
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zIn.h333
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zItem.h208
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zOut.cpp463
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zOut.h207
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zProperties.cpp48
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zProperties.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zRegister.cpp23
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zSpecStream.cpp10
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zSpecStream.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zUpdate.cpp503
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/7zUpdate.h40
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/StdAfx.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/StdAfx.h3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/makefile43
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/7z/resource.rc0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/ApmHandler.cpp113
-rw-r--r--CPP/7zip/Archive/ArHandler.cpp857
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Archive.def0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Archive2.def4
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/ArchiveExports.cpp64
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/ArjHandler.cpp636
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Bz2Handler.cpp253
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Cab/CabBlockInStream.cpp191
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Cab/CabBlockInStream.h31
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Cab/CabHandler.cpp512
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Cab/CabHandler.h11
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Cab/CabHeader.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Cab/CabHeader.h23
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Cab/CabIn.cpp446
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Cab/CabIn.h129
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Cab/CabItem.h29
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Cab/CabRegister.cpp14
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Cab/StdAfx.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Chm/ChmHandler.cpp118
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Chm/ChmHandler.h8
-rwxr-xr-xCPP/7zip/Archive/Chm/ChmHeader.cpp24
-rwxr-xr-xCPP/7zip/Archive/Chm/ChmHeader.h28
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Chm/ChmIn.cpp275
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Chm/ChmIn.h46
-rwxr-xr-xCPP/7zip/Archive/Chm/ChmRegister.cpp13
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Chm/StdAfx.h2
-rwxr-xr-xCPP/7zip/Archive/Com/ComHandler.cpp239
-rwxr-xr-xCPP/7zip/Archive/Com/ComHandler.h28
-rwxr-xr-xCPP/7zip/Archive/Com/ComIn.cpp389
-rwxr-xr-xCPP/7zip/Archive/Com/ComIn.h119
-rwxr-xr-xCPP/7zip/Archive/Com/ComRegister.cpp13
-rw-r--r--CPP/7zip/Archive/ComHandler.cpp875
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/CoderMixer.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/CoderMixer.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/CoderMixer2.cpp70
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/CoderMixer2.h19
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/CoderMixer2MT.cpp56
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/CoderMixer2MT.h12
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/CoderMixer2ST.cpp4
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/CoderMixer2ST.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/CoderMixerMT.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/CoderMixerMT.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/CrossThreadProgress.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/CrossThreadProgress.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/DummyOutStream.cpp19
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/DummyOutStream.h7
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/FindSignature.cpp12
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/FindSignature.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/HandlerOut.cpp36
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/HandlerOut.h14
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/InStreamWithCRC.cpp32
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/InStreamWithCRC.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/ItemNameUtils.cpp37
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/ItemNameUtils.h7
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/MultiStream.cpp43
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/MultiStream.h6
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/OutStreamWithCRC.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/OutStreamWithCRC.h1
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/OutStreamWithSha1.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/OutStreamWithSha1.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/ParseProperties.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/ParseProperties.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Common/StdAfx.h3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/CpioHandler.cpp834
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/CramfsHandler.cpp283
-rwxr-xr-xCPP/7zip/Archive/DebHandler.cpp413
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/DeflateProps.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/DeflateProps.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/DllExports.cpp2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/DllExports2.cpp26
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/DmgHandler.cpp1294
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/ElfHandler.cpp793
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/FatHandler.cpp120
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/FlvHandler.cpp253
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/GzHandler.cpp662
-rwxr-xr-xCPP/7zip/Archive/Hfs/HfsHandler.cpp243
-rwxr-xr-xCPP/7zip/Archive/Hfs/HfsHandler.h26
-rwxr-xr-xCPP/7zip/Archive/Hfs/HfsIn.cpp480
-rwxr-xr-xCPP/7zip/Archive/Hfs/HfsIn.h154
-rwxr-xr-xCPP/7zip/Archive/Hfs/HfsRegister.cpp13
-rw-r--r--CPP/7zip/Archive/HfsHandler.cpp1874
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/IArchive.h327
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/7z.icobin4710 -> 4710 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/arj.icobin3638 -> 3638 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/bz2.icobin3638 -> 3638 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/cab.icobin3638 -> 3638 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/cpio.icobin3638 -> 3638 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/deb.icobin3638 -> 3638 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/dmg.icobin3638 -> 3638 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/fat.icobin3638 -> 3638 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/gz.icobin3638 -> 3638 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/hfs.icobin3638 -> 3638 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/iso.icobin3638 -> 3638 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/lzh.icobin3638 -> 3638 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/lzma.icobin3638 -> 3638 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/ntfs.icobin3638 -> 3638 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/rar.icobin3638 -> 3638 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/rpm.icobin3638 -> 3638 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/split.icobin3638 -> 3638 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/squashfs.icobin3638 -> 3638 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/tar.icobin3638 -> 3638 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/vhd.icobin3638 -> 3638 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/wim.icobin3638 -> 3638 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/xar.icobin3638 -> 3638 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/xz.icobin3638 -> 3638 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/z.icobin3638 -> 3638 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Icons/zip.icobin3638 -> 3638 bytes
-rw-r--r--CPP/7zip/Archive/IhexHandler.cpp500
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Iso/IsoHandler.cpp194
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Iso/IsoHandler.h3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Iso/IsoHeader.cpp12
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Iso/IsoHeader.h9
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Iso/IsoIn.cpp197
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Iso/IsoIn.h88
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Iso/IsoItem.h62
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Iso/IsoRegister.cpp14
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Iso/StdAfx.h3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/LzhHandler.cpp111
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/LzmaHandler.cpp323
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/MachoHandler.cpp640
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/MbrHandler.cpp36
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/MslzHandler.cpp308
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/MubHandler.cpp180
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Nsis/NsisDecode.cpp221
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Nsis/NsisDecode.h41
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Nsis/NsisHandler.cpp643
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Nsis/NsisHandler.h25
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Nsis/NsisIn.cpp6343
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Nsis/NsisIn.h423
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Nsis/NsisRegister.cpp15
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Nsis/StdAfx.h3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/NtfsHandler.cpp1478
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/PeHandler.cpp1967
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/PpmdHandler.cpp55
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Rar/RarHandler.cpp1287
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Rar/RarHandler.h79
-rwxr-xr-xCPP/7zip/Archive/Rar/RarHeader.cpp21
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Rar/RarHeader.h69
-rwxr-xr-xCPP/7zip/Archive/Rar/RarIn.cpp478
-rwxr-xr-xCPP/7zip/Archive/Rar/RarIn.h123
-rwxr-xr-xCPP/7zip/Archive/Rar/RarItem.cpp55
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Rar/RarItem.h40
-rwxr-xr-xCPP/7zip/Archive/Rar/RarRegister.cpp13
-rwxr-xr-xCPP/7zip/Archive/Rar/RarVolumeInStream.cpp78
-rwxr-xr-xCPP/7zip/Archive/Rar/RarVolumeInStream.h49
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Rar/StdAfx.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Rar/StdAfx.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/RpmHandler.cpp821
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/SplitHandler.cpp275
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/SquashfsHandler.cpp240
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/StdAfx.h3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/SwfHandler.cpp651
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Tar/StdAfx.h3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Tar/TarHandler.cpp388
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Tar/TarHandler.h32
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Tar/TarHandlerOut.cpp71
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Tar/TarHeader.cpp12
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Tar/TarHeader.h65
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Tar/TarIn.cpp239
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Tar/TarIn.h11
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Tar/TarItem.h23
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Tar/TarOut.cpp230
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Tar/TarOut.h18
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Tar/TarRegister.cpp22
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Tar/TarUpdate.cpp129
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Tar/TarUpdate.h1
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Udf/StdAfx.h3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Udf/UdfHandler.cpp170
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Udf/UdfHandler.h11
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Udf/UdfIn.cpp393
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Udf/UdfIn.h54
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Udf/UdfRegister.cpp6
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/UefiHandler.cpp419
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/VhdHandler.cpp517
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Wim/StdAfx.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Wim/WimHandler.cpp817
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Wim/WimHandler.h99
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Wim/WimHandlerOut.cpp1753
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Wim/WimIn.cpp1099
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Wim/WimIn.h355
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Wim/WimRegister.cpp23
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/XarHandler.cpp365
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/XzHandler.cpp661
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/ZHandler.cpp148
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/StdAfx.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipAddCommon.cpp49
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipAddCommon.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipCompressionMode.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipHandler.cpp531
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipHandler.h10
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipHandlerOut.cpp151
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipHeader.cpp36
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipHeader.h264
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipIn.cpp1323
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipIn.h178
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipItem.cpp109
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipItem.h226
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipItemEx.h34
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipOut.cpp331
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipOut.h68
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipRegister.cpp27
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipUpdate.cpp296
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipUpdate.h19
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/makefile0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Asm.mak2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Alone/Alone.dsp121
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Alone/Alone.dsw0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Alone/StdAfx.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Alone/StdAfx.h3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Alone/afxres.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Alone/makefile114
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Alone/resource.rc0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Alone7z/StdAfx.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Alone7z/StdAfx.h3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Alone7z/makefile104
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Alone7z/resource.rc0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Fm/FM.dsp126
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Fm/FM.dsw0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Fm/StdAfx.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Fm/StdAfx.h15
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Fm/makefile476
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Fm/resource.rc0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Format7z/StdAfx.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Format7z/StdAfx.h3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Format7z/makefile53
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Format7z/resource.rc0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Format7zExtract/StdAfx.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Format7zExtract/StdAfx.h3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Format7zExtract/makefile49
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Format7zExtract/resource.rc0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Format7zExtractR/StdAfx.h3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Format7zExtractR/makefile43
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Format7zExtractR/resource.rc0
-rw-r--r--CPP/7zip/Bundles/Format7zF/Arc.mak275
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Format7zF/Format7z.dsp230
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Format7zF/Format7z.dsw0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Format7zF/StdAfx.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Format7zF/StdAfx.h3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Format7zF/makefile362
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Format7zF/resource.rc0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Format7zR/StdAfx.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Format7zR/StdAfx.h3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Format7zR/makefile45
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/Format7zR/resource.rc0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp77
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp8
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/LzmaCon/StdAfx.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/LzmaCon/StdAfx.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/LzmaCon/makefile38
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/LzmaCon/makefile.gcc4
-rw-r--r--CPP/7zip/Bundles/LzmaCon/resource.rc3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXCon/7z.icobin1078 -> 1078 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXCon/SFXCon.dsp42
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXCon/SFXCon.dsw0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXCon/SfxCon.cpp (renamed from CPP/7zip/Bundles/SFXCon/Main.cpp)156
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXCon/StdAfx.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXCon/StdAfx.h3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXCon/makefile66
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXCon/resource.rc0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp (renamed from CPP/7zip/Bundles/SFXSetup/ExtractCallback.cpp)29
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.h (renamed from CPP/7zip/Bundles/SFXSetup/ExtractCallback.h)16
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp35
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXSetup/ExtractEngine.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp30
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp (renamed from CPP/7zip/Bundles/SFXSetup/Main.cpp)91
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXSetup/StdAfx.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXSetup/StdAfx.h7
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXSetup/makefile66
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXSetup/resource.h10
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXSetup/resource.rc8
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXSetup/setup.icobin1078 -> 1078 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXWin/7z.icobin1078 -> 1078 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXWin/SFXWin.dsp80
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXWin/SFXWin.dsw0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXWin/SfxWin.cpp (renamed from CPP/7zip/Bundles/SFXWin/Main.cpp)109
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXWin/StdAfx.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXWin/StdAfx.h6
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXWin/makefile84
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXWin/resource.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/SFXWin/resource.rc31
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Bundles/makefile0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/CWrappers.cpp18
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/CWrappers.h33
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/CreateCoder.cpp215
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/CreateCoder.h41
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/FilePathAutoRename.cpp10
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/FilePathAutoRename.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/FileStreams.cpp157
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/FileStreams.h28
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/FilterCoder.cpp20
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/FilterCoder.h22
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/InBuffer.cpp120
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/InBuffer.h99
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/InMemStream.cpp2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/InMemStream.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/InOutTempBuffer.cpp4
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/InOutTempBuffer.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/LimitedStreams.cpp253
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/LimitedStreams.h138
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/LockedStream.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/LockedStream.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/MemBlocks.cpp4
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/MemBlocks.h4
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/MethodId.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/MethodId.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/MethodProps.cpp131
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/MethodProps.h5
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/OffsetStream.cpp12
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/OffsetStream.h7
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/OutBuffer.cpp47
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/OutBuffer.h35
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/OutMemStream.cpp10
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/OutMemStream.h9
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/ProgressMt.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/ProgressMt.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/ProgressUtils.cpp2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/ProgressUtils.h0
-rw-r--r--CPP/7zip/Common/PropId.cpp99
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/RegisterArc.h47
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/RegisterCodec.h26
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/StdAfx.h3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/StreamBinder.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/StreamBinder.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/StreamObjects.cpp61
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/StreamObjects.h29
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/StreamUtils.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/StreamUtils.h12
-rw-r--r--CPP/7zip/Common/UniqBlocks.cpp56
-rw-r--r--CPP/7zip/Common/UniqBlocks.h30
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/VirtThread.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Common/VirtThread.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/ArjDecoder1.cpp2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/ArjDecoder1.h7
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/ArjDecoder2.cpp3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/ArjDecoder2.h7
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/BZip2Const.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/BZip2Crc.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/BZip2Crc.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/BZip2Decoder.cpp318
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/BZip2Decoder.h87
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/BZip2Encoder.cpp38
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/BZip2Encoder.h77
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/BZip2Register.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/Bcj2Coder.cpp172
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/Bcj2Coder.h55
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/Bcj2Register.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/BcjCoder.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/BcjCoder.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/BcjRegister.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/BitlDecoder.cpp4
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/BitlDecoder.h119
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/BitlEncoder.h49
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/BitmDecoder.h48
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/BitmEncoder.h37
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/BranchCoder.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/BranchCoder.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/BranchMisc.cpp42
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/BranchMisc.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/BranchRegister.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/ByteSwap.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/Codec.def0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/CodecExports.cpp179
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/CopyCoder.cpp21
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/CopyCoder.h1
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/CopyRegister.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/Deflate64Register.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/DeflateConst.h21
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/DeflateDecoder.cpp135
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/DeflateDecoder.h56
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/DeflateEncoder.cpp60
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/DeflateEncoder.h18
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/DeflateRegister.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/DeltaFilter.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/DllExports2Compress.cpp (renamed from CPP/7zip/Compress/DllExports2.cpp)0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/DllExportsCompress.cpp (renamed from CPP/7zip/Compress/DllExports.cpp)16
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/HuffmanDecoder.h6
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/ImplodeDecoder.cpp23
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/ImplodeDecoder.h5
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp6
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/ImplodeHuffmanDecoder.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/LzOutWindow.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/LzOutWindow.h30
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/LzhDecoder.cpp8
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/LzhDecoder.h5
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/Lzma2Decoder.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/Lzma2Decoder.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/Lzma2Encoder.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/Lzma2Encoder.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/Lzma2Register.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/LzmaDecoder.cpp16
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/LzmaDecoder.h6
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/LzmaEncoder.cpp9
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/LzmaEncoder.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/LzmaRegister.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/Lzx.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/Lzx86Converter.cpp56
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/Lzx86Converter.h25
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/LzxDecoder.cpp12
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/LzxDecoder.h48
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/Mtf8.h16
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/PpmdDecoder.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/PpmdDecoder.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/PpmdEncoder.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/PpmdEncoder.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/PpmdRegister.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/PpmdZip.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/PpmdZip.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/QuantumDecoder.cpp11
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/QuantumDecoder.h23
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/RangeCoder.h26
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/RangeCoderBit.h16
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/Rar1Decoder.cpp10
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/Rar1Decoder.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/Rar2Decoder.cpp8
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/Rar2Decoder.h6
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/Rar3Decoder.cpp104
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/Rar3Decoder.h76
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/Rar3Vm.cpp146
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/Rar3Vm.h28
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/RarCodecsRegister.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/ShrinkDecoder.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/ShrinkDecoder.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/StdAfx.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/ZDecoder.cpp118
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/ZDecoder.h26
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/ZlibDecoder.cpp25
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/ZlibDecoder.h33
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/ZlibEncoder.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/ZlibEncoder.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/makefile0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crc.mak0
-rw-r--r--CPP/7zip/Crc64.mak8
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/7zAes.cpp22
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/7zAes.h10
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/7zAesRegister.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/Codec.def0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/HmacSha1.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/HmacSha1.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/MyAes.cpp78
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/MyAes.h26
-rw-r--r--CPP/7zip/Crypto/MyAesReg.cpp19
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/Pbkdf2HmacSha1.h3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/RandGen.cpp10
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/RandGen.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/Rar20Crypto.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/Rar20Crypto.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/RarAes.cpp16
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/RarAes.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/Sha1.cpp18
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/Sha1.h3
-rw-r--r--CPP/7zip/Crypto/Sha1Reg.cpp55
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/StdAfx.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/WzAes.cpp13
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/WzAes.h5
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/ZipCrypto.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/ZipCrypto.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/ZipStrong.cpp23
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Crypto/ZipStrong.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/GuiCommon.rc19
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Guid.txt26
-rw-r--r--[-rwxr-xr-x]CPP/7zip/ICoder.h25
-rw-r--r--[-rwxr-xr-x]CPP/7zip/IDecl.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/IPassword.h3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/IProgress.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/IStream.h43
-rw-r--r--[-rwxr-xr-x]CPP/7zip/MyVersion.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/MyVersionInfo.rc0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/PropID.h66
-rw-r--r--[-rwxr-xr-x]CPP/7zip/SubBuild.mak0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Agent/Agent.cpp1184
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Agent/Agent.h109
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Agent/AgentOut.cpp207
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Agent/AgentProxy.cpp565
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Agent/AgentProxy.h107
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Agent/ArchiveFolder.cpp29
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp14
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Agent/ArchiveFolderOut.cpp197
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Agent/IFolderArchive.h15
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp15
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Agent/UpdateCallbackAgent.h5
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Client7z/Client7z.cpp174
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Client7z/Client7z.dsp21
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Client7z/Client7z.dsw0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Client7z/StdAfx.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Client7z/StdAfx.h3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Client7z/makefile25
-rw-r--r--CPP/7zip/UI/Client7z/resource.rc3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/ArchiveCommandLine.cpp1065
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/ArchiveCommandLine.h73
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/ArchiveExtractCallback.cpp965
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/ArchiveExtractCallback.h194
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/ArchiveName.cpp24
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/ArchiveName.h9
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/ArchiveOpenCallback.cpp38
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/ArchiveOpenCallback.h28
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/Bench.cpp1480
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/Bench.h8
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/CompressCall.cpp111
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/CompressCall.h10
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/CompressCall2.cpp148
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/DefaultName.cpp6
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/DefaultName.h6
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/DirItem.h83
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/EnumDirItems.cpp624
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/EnumDirItems.h16
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/ExitCode.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/Extract.cpp362
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/Extract.h52
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/ExtractMode.h40
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/ExtractingFilePath.cpp110
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/ExtractingFilePath.h12
-rw-r--r--CPP/7zip/UI/Common/HashCalc.cpp361
-rw-r--r--CPP/7zip/UI/Common/HashCalc.h107
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/IFileExtractCallback.h32
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/LoadCodecs.cpp712
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/LoadCodecs.h167
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/OpenArchive.cpp3102
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/OpenArchive.h350
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/PropIDUtils.cpp547
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/PropIDUtils.h13
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/Property.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/SetProperties.cpp25
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/SetProperties.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/SortUtils.cpp17
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/SortUtils.h8
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/StdAfx.h5
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/TempFiles.cpp6
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/TempFiles.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/Update.cpp998
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/Update.h129
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/UpdateAction.cpp10
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/UpdateAction.h23
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/UpdateCallback.cpp448
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/UpdateCallback.h59
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/UpdatePair.cpp203
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/UpdatePair.h4
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/UpdateProduce.cpp21
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/UpdateProduce.h15
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/WorkDir.cpp12
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/WorkDir.h8
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/ZipRegistry.cpp97
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Common/ZipRegistry.h21
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Console/BenchCon.cpp2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Console/BenchCon.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Console/Console.dsp157
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Console/Console.dsw0
-rw-r--r--CPP/7zip/UI/Console/Console.mak35
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Console/ConsoleClose.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Console/ConsoleClose.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Console/ExtractCallbackConsole.cpp245
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Console/ExtractCallbackConsole.h42
-rw-r--r--CPP/7zip/UI/Console/HashCon.cpp274
-rw-r--r--CPP/7zip/UI/Console/HashCon.h26
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Console/List.cpp1218
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Console/List.h15
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Console/Main.cpp799
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Console/MainAr.cpp17
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Console/OpenCallbackConsole.cpp6
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Console/OpenCallbackConsole.h7
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Console/PercentPrinter.cpp4
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Console/PercentPrinter.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Console/StdAfx.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Console/StdAfx.h3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Console/UpdateCallbackConsole.cpp39
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Console/UpdateCallbackConsole.h57
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Console/UserInputUtils.cpp41
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Console/UserInputUtils.h6
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Console/makefile87
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Console/resource.rc0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Explorer/7-zip.dll.manifest0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Explorer/ContextMenu.cpp532
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Explorer/ContextMenu.h17
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Explorer/ContextMenuFlags.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Explorer/DllExportsExplorer.cpp (renamed from CPP/7zip/UI/Explorer/DllExports.cpp)14
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Explorer/Explorer.def0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Explorer/Explorer.dsp22
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Explorer/Explorer.dsw0
-rw-r--r--CPP/7zip/UI/Explorer/MenuLogo.bmpbin0 -> 114 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Explorer/MyMessages.cpp35
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Explorer/MyMessages.h22
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Explorer/OptionsDialog.cpp2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Explorer/OptionsDialog.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Explorer/RegistryContextMenu.cpp7
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Explorer/RegistryContextMenu.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Explorer/StdAfx.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Explorer/StdAfx.h20
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Explorer/makefile41
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Explorer/resource.h41
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Explorer/resource.rc0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Explorer/resource2.rc19
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/ExtractEngine.cpp59
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/ExtractEngine.h8
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/Far.cpp (renamed from CPP/7zip/UI/Far/Main.cpp)37
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/Far.def0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/Far.dsp112
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/Far.dsw0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/FarPlugin.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/FarUtils.cpp40
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/FarUtils.h13
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/Messages.h94
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/OverwriteDialogFar.cpp (renamed from CPP/7zip/UI/Far/OverwriteDialog.cpp)27
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/OverwriteDialogFar.h (renamed from CPP/7zip/UI/Far/OverwriteDialog.h)10
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/Plugin.cpp236
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/Plugin.h10
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/PluginCommon.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/PluginDelete.cpp19
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/PluginRead.cpp75
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/PluginWrite.cpp237
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/ProgressBox.cpp7
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/ProgressBox.h8
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/StdAfx.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/StdAfx.h8
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/UpdateCallbackFar.cpp (renamed from CPP/7zip/UI/Far/UpdateCallback100.cpp)7
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/UpdateCallbackFar.h (renamed from CPP/7zip/UI/Far/UpdateCallback100.h)12
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/makefile61
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Far/resource.rc0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/7zFM.exe.manifest0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/7zipLogo.icobin9150 -> 9150 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/AboutDialog.cpp46
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/AboutDialog.h7
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/AboutDialog.rc16
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/AboutDialogRes.h14
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/Add.bmpbin982 -> 982 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/Add2.bmpbin406 -> 406 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/App.cpp284
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/App.h55
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/AppState.h41
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/BrowseDialog.cpp968
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/BrowseDialog.h80
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/BrowseDialog.rc24
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/BrowseDialogRes.h13
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/ClassDefs.cpp3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/ComboDialog.cpp18
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/ComboDialog.h7
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/ComboDialog.rc9
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/ComboDialogRes.h6
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/Copy.bmpbin982 -> 982 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/Copy2.bmpbin406 -> 406 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/CopyDialog.cpp44
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/CopyDialog.h6
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/CopyDialog.rc13
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/CopyDialogRes.h12
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/Delete.bmpbin982 -> 982 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/Delete2.bmpbin406 -> 406 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/DialogSize.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/EditPage.cpp51
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/EditPage.h5
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/EditPage.rc0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/EditPage2.rc17
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/EditPageRes.h21
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/EnumFormatEtc.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/EnumFormatEtc.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/Extract.bmpbin982 -> 982 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/Extract2.bmpbin406 -> 406 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/ExtractCallback.cpp644
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/ExtractCallback.h217
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/FM.cpp334
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/FM.dsp263
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/FM.dsw0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/FM.icobin4846 -> 4846 bytes
-rw-r--r--CPP/7zip/UI/FileManager/FM.mak81
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/FSDrives.cpp172
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/FSDrives.h18
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/FSFolder.cpp901
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/FSFolder.h138
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/FSFolderCopy.cpp253
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp22
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/FileFolderPluginOpen.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/FilePlugins.cpp8
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/FilePlugins.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/FoldersPage.cpp40
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/FoldersPage.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/FoldersPage.rc0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/FoldersPage2.rc16
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/FoldersPageRes.h21
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/FormatUtils.cpp20
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/FormatUtils.h14
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/HelpUtils.cpp6
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/HelpUtils.h6
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/IFolder.h59
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/Info.bmpbin982 -> 982 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/Info2.bmpbin406 -> 406 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/LangPage.cpp85
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/LangPage.h5
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/LangPage.rc10
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/LangPageRes.h12
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/LangUtils.cpp280
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/LangUtils.h31
-rw-r--r--CPP/7zip/UI/FileManager/LinkDialog.cpp342
-rw-r--r--CPP/7zip/UI/FileManager/LinkDialog.h33
-rw-r--r--CPP/7zip/UI/FileManager/LinkDialog.rc36
-rw-r--r--CPP/7zip/UI/FileManager/LinkDialogRes.h21
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/ListViewDialog.cpp16
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/ListViewDialog.h6
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/ListViewDialog.rc4
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/ListViewDialogRes.h4
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/MenuPage.cpp84
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/MenuPage.h4
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/MenuPage.rc2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/MenuPage2.rc15
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/MenuPageRes.h14
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/MessagesDialog.cpp46
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/MessagesDialog.h8
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/MessagesDialog.rc4
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/MessagesDialogRes.h6
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/Move.bmpbin982 -> 982 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/Move2.bmpbin406 -> 406 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/MyCom2.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/MyLoadMenu.cpp352
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/MyLoadMenu.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/MyWindowsNew.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/NetFolder.cpp21
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/NetFolder.h4
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/OpenCallback.cpp57
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/OpenCallback.h13
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/OptionsDialog.cpp19
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/OverwriteDialog.cpp112
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/OverwriteDialog.h6
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/OverwriteDialog.rc57
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/OverwriteDialogRes.h29
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/Panel.cpp240
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/Panel.h212
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PanelCopy.cpp199
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PanelCrc.cpp427
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PanelDrag.cpp95
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PanelFolderChange.cpp107
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PanelItemOpen.cpp431
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PanelItems.cpp444
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PanelKey.cpp30
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PanelListNotify.cpp407
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PanelMenu.cpp174
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PanelOperations.cpp265
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PanelSelect.cpp57
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PanelSort.cpp147
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PanelSplitFile.cpp183
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PasswordDialog.cpp26
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PasswordDialog.h11
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PasswordDialog.rc8
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PasswordDialogRes.h9
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PluginInterface.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PluginLoader.h8
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PluginsPage.cpp22
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PluginsPage.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PluginsPage.rc0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PluginsPageRes.h8
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/ProgramLocation.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/ProgramLocation.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/ProgressDialog.cpp16
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/ProgressDialog.h12
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/ProgressDialog.rc2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/ProgressDialog2.cpp995
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/ProgressDialog2.h307
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/ProgressDialog2.rc7
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/ProgressDialog2Res.h81
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/ProgressDialog2a.rc80
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/ProgressDialogRes.h4
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PropertyName.cpp107
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PropertyName.h6
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PropertyName.rc135
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/PropertyNameRes.h143
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/RegistryAssociations.cpp20
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/RegistryAssociations.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/RegistryPlugins.cpp8
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/RegistryPlugins.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/RegistryUtils.cpp19
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/RegistryUtils.h17
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/RootFolder.cpp40
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/RootFolder.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/SettingsPage.cpp86
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/SettingsPage.h8
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/SettingsPage.rc0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/SettingsPage2.rc31
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/SettingsPageRes.h22
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/SplitDialog.cpp32
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/SplitDialog.h6
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/SplitDialog.rc12
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/SplitDialogRes.h13
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/SplitUtils.cpp87
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/SplitUtils.h14
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/StdAfx.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/StdAfx.h18
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/StringUtils.cpp35
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/StringUtils.h6
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/SysIconUtils.cpp156
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/SysIconUtils.h30
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/SystemPage.cpp41
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/SystemPage.h14
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/SystemPage.rc34
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/SystemPageRes.h18
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/Test.bmpbin982 -> 982 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/Test2.bmpbin406 -> 406 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/TextPairs.cpp29
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/TextPairs.h13
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/UpdateCallback100.cpp25
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/UpdateCallback100.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/ViewSettings.cpp360
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/ViewSettings.h67
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/makefile162
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/resource.h331
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/resource.rc195
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/resourceGui.h17
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/FileManager/resourceGui.rc18
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/7zG.exe.manifest0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/BenchmarkDialog.cpp313
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/BenchmarkDialog.h25
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/BenchmarkDialog.rc188
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/BenchmarkDialogRes.h121
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/CompressDialog.cpp719
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/CompressDialog.h64
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/CompressDialog.rc206
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/CompressDialogRes.h168
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/Extract.rc63
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/ExtractDialog.cpp360
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/ExtractDialog.h48
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/ExtractDialog.rc68
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/ExtractDialogRes.h31
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/ExtractGUI.cpp158
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/ExtractGUI.h6
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/ExtractRes.h73
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/FM.icobin4846 -> 4846 bytes
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/GUI.cpp229
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/GUI.dsp144
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/GUI.dsw0
-rw-r--r--CPP/7zip/UI/GUI/HashGUI.cpp278
-rw-r--r--CPP/7zip/UI/GUI/HashGUI.h16
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/StdAfx.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/StdAfx.h16
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp93
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/UpdateCallbackGUI.h3
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/UpdateGUI.cpp219
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/UpdateGUI.h4
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/makefile73
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/resource.rc8
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/resource2.h5
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/GUI/resource2.rc5
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/makefile0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/makefile0
-rw-r--r--[-rwxr-xr-x]CPP/Build.mak39
-rw-r--r--[-rwxr-xr-x]CPP/Common/AutoPtr.h0
-rwxr-xr-xCPP/Common/Buffer.h77
-rw-r--r--[-rwxr-xr-x]CPP/Common/CRC.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/Common/C_FileIO.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/Common/C_FileIO.h2
-rw-r--r--[-rwxr-xr-x]CPP/Common/ComTry.h0
-rw-r--r--[-rwxr-xr-x]CPP/Common/CommandLineParser.cpp267
-rw-r--r--[-rwxr-xr-x]CPP/Common/CommandLineParser.h49
-rw-r--r--CPP/Common/Common.h13
-rw-r--r--CPP/Common/CrcReg.cpp111
-rw-r--r--[-rwxr-xr-x]CPP/Common/Defs.h0
-rw-r--r--CPP/Common/DynLimBuf.cpp100
-rw-r--r--CPP/Common/DynLimBuf.h36
-rw-r--r--[-rwxr-xr-x]CPP/Common/DynamicBuffer.h72
-rw-r--r--[-rwxr-xr-x]CPP/Common/IntToString.cpp149
-rw-r--r--[-rwxr-xr-x]CPP/Common/IntToString.h23
-rw-r--r--[-rwxr-xr-x]CPP/Common/Lang.cpp204
-rw-r--r--[-rwxr-xr-x]CPP/Common/Lang.h24
-rw-r--r--[-rwxr-xr-x]CPP/Common/ListFileUtils.cpp117
-rw-r--r--[-rwxr-xr-x]CPP/Common/ListFileUtils.h5
-rw-r--r--CPP/Common/MyBuffer.h237
-rw-r--r--[-rwxr-xr-x]CPP/Common/MyCom.h63
-rw-r--r--[-rwxr-xr-x]CPP/Common/MyException.h0
-rw-r--r--[-rwxr-xr-x]CPP/Common/MyGuidDef.h2
-rw-r--r--[-rwxr-xr-x]CPP/Common/MyInitGuid.h0
-rw-r--r--[-rwxr-xr-x]CPP/Common/MyMap.cpp14
-rw-r--r--[-rwxr-xr-x]CPP/Common/MyMap.h4
-rw-r--r--[-rwxr-xr-x]CPP/Common/MyString.cpp1110
-rw-r--r--[-rwxr-xr-x]CPP/Common/MyString.h842
-rw-r--r--CPP/Common/MyTypes.h30
-rw-r--r--[-rwxr-xr-x]CPP/Common/MyUnknown.h0
-rw-r--r--[-rwxr-xr-x]CPP/Common/MyVector.cpp84
-rw-r--r--[-rwxr-xr-x]CPP/Common/MyVector.h575
-rw-r--r--[-rwxr-xr-x]CPP/Common/MyWindows.cpp24
-rw-r--r--[-rwxr-xr-x]CPP/Common/MyWindows.h15
-rw-r--r--[-rwxr-xr-x]CPP/Common/MyXml.cpp265
-rw-r--r--[-rwxr-xr-x]CPP/Common/MyXml.h23
-rw-r--r--[-rwxr-xr-x]CPP/Common/NewHandler.cpp64
-rw-r--r--[-rwxr-xr-x]CPP/Common/NewHandler.h56
-rw-r--r--[-rwxr-xr-x]CPP/Common/Random.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/Common/Random.h0
-rw-r--r--CPP/Common/Sha256Reg.cpp52
-rw-r--r--[-rwxr-xr-x]CPP/Common/StdAfx.h3
-rw-r--r--[-rwxr-xr-x]CPP/Common/StdInStream.cpp19
-rw-r--r--[-rwxr-xr-x]CPP/Common/StdInStream.h21
-rw-r--r--[-rwxr-xr-x]CPP/Common/StdOutStream.cpp58
-rw-r--r--[-rwxr-xr-x]CPP/Common/StdOutStream.h41
-rw-r--r--[-rwxr-xr-x]CPP/Common/StringConvert.cpp90
-rw-r--r--[-rwxr-xr-x]CPP/Common/StringConvert.h10
-rw-r--r--[-rwxr-xr-x]CPP/Common/StringToInt.cpp148
-rw-r--r--[-rwxr-xr-x]CPP/Common/StringToInt.h19
-rw-r--r--[-rwxr-xr-x]CPP/Common/TextConfig.cpp74
-rw-r--r--[-rwxr-xr-x]CPP/Common/TextConfig.h7
-rwxr-xr-xCPP/Common/Types.h11
-rw-r--r--[-rwxr-xr-x]CPP/Common/UTFConvert.cpp59
-rw-r--r--[-rwxr-xr-x]CPP/Common/UTFConvert.h5
-rw-r--r--[-rwxr-xr-x]CPP/Common/Wildcard.cpp385
-rw-r--r--[-rwxr-xr-x]CPP/Common/Wildcard.h101
-rw-r--r--CPP/Common/XzCrc64Reg.cpp54
-rw-r--r--[-rwxr-xr-x]CPP/Windows/COM.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/Windows/COM.h3
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Clipboard.cpp24
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Clipboard.h8
-rw-r--r--[-rwxr-xr-x]CPP/Windows/CommonDialog.cpp239
-rw-r--r--[-rwxr-xr-x]CPP/Windows/CommonDialog.h12
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Console.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Console.h50
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Control/ComboBox.cpp6
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Control/ComboBox.h2
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Control/CommandBar.h4
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Control/Dialog.cpp52
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Control/Dialog.h58
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Control/Edit.h2
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Control/ImageList.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Control/ImageList.h2
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Control/ListView.cpp2
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Control/ListView.h2
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Control/ProgressBar.h0
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Control/PropertyPage.cpp5
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Control/PropertyPage.h0
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Control/ReBar.h7
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Control/Static.h0
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Control/StatusBar.h21
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Control/StdAfx.h3
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Control/ToolBar.h2
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Control/Trackbar.h6
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Control/Window2.cpp101
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Control/Window2.h25
-rw-r--r--[-rwxr-xr-x]CPP/Windows/DLL.cpp7
-rw-r--r--[-rwxr-xr-x]CPP/Windows/DLL.h6
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Defs.h0
-rwxr-xr-xCPP/Windows/Error.h15
-rw-r--r--[-rwxr-xr-x]CPP/Windows/ErrorMsg.cpp (renamed from CPP/Windows/Error.cpp)11
-rw-r--r--CPP/Windows/ErrorMsg.h15
-rw-r--r--[-rwxr-xr-x]CPP/Windows/FileDir.cpp352
-rw-r--r--[-rwxr-xr-x]CPP/Windows/FileDir.h55
-rw-r--r--[-rwxr-xr-x]CPP/Windows/FileFind.cpp317
-rw-r--r--[-rwxr-xr-x]CPP/Windows/FileFind.h62
-rw-r--r--[-rwxr-xr-x]CPP/Windows/FileIO.cpp293
-rw-r--r--[-rwxr-xr-x]CPP/Windows/FileIO.h176
-rw-r--r--CPP/Windows/FileLink.cpp426
-rw-r--r--[-rwxr-xr-x]CPP/Windows/FileMapping.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/Windows/FileMapping.h8
-rw-r--r--[-rwxr-xr-x]CPP/Windows/FileName.cpp664
-rw-r--r--[-rwxr-xr-x]CPP/Windows/FileName.h57
-rw-r--r--[-rwxr-xr-x]CPP/Windows/FileSystem.cpp22
-rw-r--r--[-rwxr-xr-x]CPP/Windows/FileSystem.h2
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Handle.h0
-rwxr-xr-xCPP/Windows/Memory.h53
-rw-r--r--[-rwxr-xr-x]CPP/Windows/MemoryGlobal.cpp (renamed from CPP/Windows/Memory.cpp)16
-rw-r--r--CPP/Windows/MemoryGlobal.h53
-rw-r--r--[-rwxr-xr-x]CPP/Windows/MemoryLock.cpp98
-rw-r--r--[-rwxr-xr-x]CPP/Windows/MemoryLock.h27
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Menu.cpp29
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Menu.h5
-rw-r--r--[-rwxr-xr-x]CPP/Windows/NationalTime.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/Windows/NationalTime.h0
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Net.cpp24
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Net.h3
-rw-r--r--[-rwxr-xr-x]CPP/Windows/NtCheck.h0
-rw-r--r--[-rwxr-xr-x]CPP/Windows/ProcessMessages.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/Windows/ProcessMessages.h0
-rw-r--r--[-rwxr-xr-x]CPP/Windows/ProcessUtils.cpp (renamed from CPP/Windows/Process.cpp)11
-rw-r--r--[-rwxr-xr-x]CPP/Windows/ProcessUtils.h (renamed from CPP/Windows/Process.h)6
-rw-r--r--[-rwxr-xr-x]CPP/Windows/PropVariant.cpp83
-rw-r--r--[-rwxr-xr-x]CPP/Windows/PropVariant.h97
-rw-r--r--CPP/Windows/PropVariantConv.cpp99
-rw-r--r--CPP/Windows/PropVariantConv.h30
-rwxr-xr-xCPP/Windows/PropVariantConversions.cpp105
-rwxr-xr-xCPP/Windows/PropVariantConversions.h14
-rw-r--r--[-rwxr-xr-x]CPP/Windows/PropVariantUtils.cpp50
-rw-r--r--[-rwxr-xr-x]CPP/Windows/PropVariantUtils.h11
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Registry.cpp33
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Registry.h41
-rw-r--r--[-rwxr-xr-x]CPP/Windows/ResourceString.cpp85
-rw-r--r--[-rwxr-xr-x]CPP/Windows/ResourceString.h18
-rw-r--r--[-rwxr-xr-x]CPP/Windows/SecurityUtils.cpp (renamed from CPP/Windows/Security.cpp)4
-rw-r--r--[-rwxr-xr-x]CPP/Windows/SecurityUtils.h (renamed from CPP/Windows/Security.h)6
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Shell.cpp17
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Shell.h5
-rw-r--r--[-rwxr-xr-x]CPP/Windows/StdAfx.h3
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Synchronization.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Synchronization.h0
-rw-r--r--[-rwxr-xr-x]CPP/Windows/System.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/Windows/System.h2
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Thread.h0
-rwxr-xr-xCPP/Windows/Time.h23
-rw-r--r--[-rwxr-xr-x]CPP/Windows/TimeUtils.cpp (renamed from CPP/Windows/Time.cpp)14
-rw-r--r--CPP/Windows/TimeUtils.h23
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Window.cpp4
-rw-r--r--[-rwxr-xr-x]CPP/Windows/Window.h26
-rw-r--r--[-rwxr-xr-x]DOC/7zC.txt13
-rw-r--r--[-rwxr-xr-x]DOC/7zFormat.txt0
-rw-r--r--[-rwxr-xr-x]DOC/7zip.hhp17
-rw-r--r--[-rwxr-xr-x]DOC/7zip.inf4
-rw-r--r--[-rwxr-xr-x]DOC/7zip.nsi203
-rw-r--r--[-rwxr-xr-x]DOC/7zip.wxs15
-rw-r--r--[-rwxr-xr-x]DOC/License.txt0
-rw-r--r--[-rwxr-xr-x]DOC/Methods.txt46
-rw-r--r--[-rwxr-xr-x]DOC/copying.txt0
-rw-r--r--[-rwxr-xr-x]DOC/history.txt12
-rw-r--r--[-rwxr-xr-x]DOC/lzma.txt20
-rw-r--r--[-rwxr-xr-x]DOC/readme.txt4
-rw-r--r--[-rwxr-xr-x]DOC/unRarLicense.txt0
1158 files changed, 75824 insertions, 34455 deletions
diff --git a/Asm/arm/7zCrcOpt.asm b/Asm/arm/7zCrcOpt.asm
index 6001d8e3..6001d8e3 100755..100644
--- a/Asm/arm/7zCrcOpt.asm
+++ b/Asm/arm/7zCrcOpt.asm
diff --git a/Asm/x86/7zAsm.asm b/Asm/x86/7zAsm.asm
index 3e42ab45..3707e90c 100755..100644
--- 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
index 724b9b2c..724b9b2c 100755..100644
--- a/Asm/x86/7zCrcOpt.asm
+++ b/Asm/x86/7zCrcOpt.asm
diff --git a/Asm/x86/AesOpt.asm b/Asm/x86/AesOpt.asm
index 21466712..21466712 100755..100644
--- a/Asm/x86/AesOpt.asm
+++ b/Asm/x86/AesOpt.asm
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
index 01c4cac6..ca4a2233 100755..100644
--- 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
index 964b28db..97cea299 100755..100644
--- 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
index 3344e937..3344e937 100755..100644
--- a/C/7zAlloc.h
+++ b/C/7zAlloc.h
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 <string.h>
+
+#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 <stdio.h>
+
+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
index 14e7f4e2..089a5c4f 100755..100644
--- 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
index e9f2f316..65f1d7a7 100755..100644
--- 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
index 8d17e0dc..e14e65f4 100755..100644
--- 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 <string.h>
+
#include "7zBuf.h"
void DynBuf_Construct(CDynBuf *p)
diff --git a/C/7zCrc.c b/C/7zCrc.c
index cd94201b..503e3591 100755..100644
--- 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
index 38e3e5fb..8fd57958 100755..100644
--- 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
index a8d42a80..ce132b5d 100755..100644
--- 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
index b6d80995..2c7c2cd0 100755..100644
--- 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 <string.h>
@@ -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
index a66c9e9d..041e5b15 100755..100644
--- 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
index 84538c03..658987ed 100755..100644
--- 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 <stdio.h>
#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 <string.h>
-
-#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<CBuf> &dataVector,
- CObjectVector<CSzFileItem> &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
index 0ebb7b5f..88f9c42b 100755..100644
--- 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 <string.h>
-#include "Types.h"
+#include "7zTypes.h"
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType)
{
diff --git a/C/Types.h b/C/7zTypes.h
index 7732c240..778413ef 100755..100644
--- a/C/Types.h
+++ b/C/7zTypes.h
@@ -1,15 +1,15 @@
-/* Types.h -- Basic types
-2010-10-09 : Igor Pavlov : Public domain */
+/* 7zTypes.h -- Basic types
+2013-11-12 : Igor Pavlov : Public domain */
#ifndef __7Z_TYPES_H
#define __7Z_TYPES_H
-#include <stddef.h>
-
#ifdef _WIN32
-#include <windows.h>
+/* #include <windows.h> */
#endif
+#include <stddef.h>
+
#ifndef EXTERN_C_BEGIN
#ifdef __cplusplus
#define EXTERN_C_BEGIN extern "C" {
@@ -43,7 +43,8 @@ EXTERN_C_BEGIN
typedef int SRes;
#ifdef _WIN32
-typedef DWORD WRes;
+/* typedef DWORD WRes; */
+typedef unsigned WRes;
#else
typedef int WRes;
#endif
@@ -116,6 +117,7 @@ typedef int Bool;
#else
+#define MY_NO_INLINE
#define MY_CDECL
#define MY_FAST_CALL
diff --git a/C/7zVersion.h b/C/7zVersion.h
index 5a83e5f7..e0fa2412 100755..100644
--- 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
index e520995d..e520995d 100755..100644
--- a/C/7zVersion.rc
+++ b/C/7zVersion.rc
diff --git a/C/Aes.c b/C/Aes.c
index e7221cd2..6c49dc98 100755..100644
--- 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
index c9b0677c..64979b5b 100755..100644
--- 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
index 60cfd86d..10a8fb25 100755..100644
--- 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
index 358a7b52..a9a69575 100755..100644
--- 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 <windows.h>
diff --git a/C/Alloc.h b/C/Alloc.h
index b8e41436..b8e41436 100755..100644
--- a/C/Alloc.h
+++ b/C/Alloc.h
diff --git a/C/Bcj2.c b/C/Bcj2.c
index 20199ce5..4e81cdc2 100755..100644
--- 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
index dbc05414..1db8ea0a 100755..100644
--- 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
index 2e47b141..cdb94569 100755..100644
--- 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
index 5748c1c0..855e37a6 100755..100644
--- 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
index 1ee0e709..6db15e7e 100755..100644
--- 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
index 0b4ee85b..fa60356b 100755..100644
--- 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
index 20730507..f5c61769 100755..100644
--- 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
index ce5598f0..7e989a99 100755..100644
--- 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
index 260cc1f4..d7f8b1d8 100755..100644
--- 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 <intrin.h>
+#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 <windows.h>
static Bool CPU_Sys_Is_SSE_Supported()
{
OSVERSIONINFO vi;
diff --git a/C/CpuArch.h b/C/CpuArch.h
index e3d7af2e..4fee0093 100755..100644
--- 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 <stdlib.h>
+
#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
index 2b327f15..e3edd21e 100755..100644
--- 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
index 0d4cd627..2fa54ad6 100755..100644
--- 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
index 561c7e5d..db41e8d2 100755..100644
--- 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
index 9cf4bfde..92b6878d 100755..100644
--- 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
index e3ecb054..262b395b 100755..100644
--- 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 <string.h>
#include "LzFind.h"
diff --git a/C/LzFind.h b/C/LzFind.h
index 010c4b92..706143d2 100755..100644
--- 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
index aa41ed98..ea600bb5 100755..100644
--- 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
index b985af5f..6a7095b0 100755..100644
--- 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
index f3e89966..f3e89966 100755..100644
--- a/C/LzHash.h
+++ b/C/LzHash.h
diff --git a/C/Lzma2Dec.c b/C/Lzma2Dec.c
index f3a6b821..502a1588 100755..100644
--- a/C/Lzma2Dec.c
+++ b/C/Lzma2Dec.c
@@ -3,6 +3,8 @@
/* #define SHOW_DEBUG_INFO */
+#include "Precomp.h"
+
#ifdef SHOW_DEBUG_INFO
#include <stdio.h>
#endif
diff --git a/C/Lzma2Dec.h b/C/Lzma2Dec.h
index 6bc07bbc..367daf6b 100755..100644
--- 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
index e97597f6..0c8e02e9 100755..100644
--- 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 <stdio.h> */
#include <string.h>
@@ -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
index 28352558..f409f184 100755..100644
--- 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
index 6acbd888..bebed5cb 100755..100644
--- 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
index fe772609..fe772609 100755..100644
--- a/C/Lzma86Dec.c
+++ b/C/Lzma86Dec.c
diff --git a/C/Lzma86Enc.c b/C/Lzma86Enc.c
index 2ea4ac2d..16467149 100755..100644
--- 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
index 8c1a1486..42c90bdb 100755..100644
--- 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
index bf7f084b..cc44daef 100755..100644
--- 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
index ef26e0cf..fc7d358a 100755..100644
--- 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 <string.h>
@@ -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
index b8d9ce77..cffe220b 100755..100644
--- 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
index 02a51185..02a51185 100755..100644
--- a/C/LzmaLib.c
+++ b/C/LzmaLib.c
diff --git a/C/LzmaLib.h b/C/LzmaLib.h
index 76c99ce7..88fa87d3 100755..100644
--- 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
index 946fbbc7..616f0b41 100755..100644
--- 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 <stdio.h>
#include "MtCoder.h"
diff --git a/C/MtCoder.h b/C/MtCoder.h
index f0f06da2..f0f06da2 100755..100644
--- a/C/MtCoder.h
+++ b/C/MtCoder.h
diff --git a/C/Ppmd.h b/C/Ppmd.h
index 9cbc4664..4356dd1d 100755..100644
--- 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
index 060d86d2..bb5d175e 100755..100644
--- 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 <memory.h>
#include "Ppmd7.h"
diff --git a/C/Ppmd7.h b/C/Ppmd7.h
index 96521c31..96521c31 100755..100644
--- a/C/Ppmd7.h
+++ b/C/Ppmd7.h
diff --git a/C/Ppmd7Dec.c b/C/Ppmd7Dec.c
index 68438d5c..04b4b09e 100755..100644
--- 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
index 8247757d..51c19c9f 100755..100644
--- 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
index 9187a88e..ac8a8354 100755..100644
--- 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 <memory.h>
#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
index 7dcfc916..7dcfc916 100755..100644
--- a/C/Ppmd8.h
+++ b/C/Ppmd8.h
diff --git a/C/Ppmd8Dec.c b/C/Ppmd8Dec.c
index c54e02ab..317bd651 100755..100644
--- 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
index 8da727eb..5e389be4 100755..100644
--- 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
index c3a1385c..1b83e5ea 100755..100644
--- 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 <stdlib.h>
+
+// #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
index eb4fc61f..db0c7061 100755..100644
--- 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
index 530f513e..3f455dbc 100755..100644
--- 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
index 388d2289..e1097e38 100755..100644
--- 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
index 65dfc6f6..2e2963a2 100755..100644
--- 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
index 7af1da2e..d71e13a4 100755..100644
--- 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 <process.h>
@@ -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
index d0ddd80e..9b3e1c55 100755..100644
--- 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 <windows.h>
#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/Util/7z/7z.dsp b/C/Util/7z/7z.dsp
index 21dd5995..92818667 100755..100644
--- 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
index 848d13cb..848d13cb 100755..100644
--- a/C/Util/7z/7z.dsw
+++ b/C/Util/7z/7z.dsw
diff --git a/C/Util/7z/7zMain.c b/C/Util/7z/7zMain.c
index 9496dc07..609a578e 100755..100644
--- 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 <stdio.h>
#include <string.h>
#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
index 96edda42..9009da83 100755..100644
--- 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
index 364c6474..46018201 100755..100644
--- 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
index 09a749af..7c30fdc7 100755..100644
--- 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 <stdio.h>
#include <stdlib.h>
diff --git a/C/Util/Lzma/LzmaUtil.dsp b/C/Util/Lzma/LzmaUtil.dsp
index d10af8b4..43b8e176 100755..100644
--- 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
index c52eaf6d..c52eaf6d 100755..100644
--- a/C/Util/Lzma/LzmaUtil.dsw
+++ b/C/Util/Lzma/LzmaUtil.dsw
diff --git a/C/Util/Lzma/makefile b/C/Util/Lzma/makefile
index afac0716..afac0716 100755..100644
--- a/C/Util/Lzma/makefile
+++ b/C/Util/Lzma/makefile
diff --git a/C/Util/Lzma/makefile.gcc b/C/Util/Lzma/makefile.gcc
index 67aa8b17..67aa8b17 100755..100644
--- a/C/Util/Lzma/makefile.gcc
+++ b/C/Util/Lzma/makefile.gcc
diff --git a/C/Util/LzmaLib/LzmaLib.def b/C/Util/LzmaLib/LzmaLib.def
index 8bc6add9..8bc6add9 100755..100644
--- a/C/Util/LzmaLib/LzmaLib.def
+++ b/C/Util/LzmaLib/LzmaLib.def
diff --git a/C/Util/LzmaLib/LzmaLib.dsp b/C/Util/LzmaLib/LzmaLib.dsp
index 7d8d386f..3421de83 100755..100644
--- 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
index 6faf3336..6faf3336 100755..100644
--- a/C/Util/LzmaLib/LzmaLib.dsw
+++ b/C/Util/LzmaLib/LzmaLib.dsw
diff --git a/C/Util/LzmaLib/LzmaLibExports.c b/C/Util/LzmaLib/LzmaLibExports.c
index 845545db..845545db 100755..100644
--- a/C/Util/LzmaLib/LzmaLibExports.c
+++ b/C/Util/LzmaLib/LzmaLibExports.c
diff --git a/C/Util/LzmaLib/makefile b/C/Util/LzmaLib/makefile
index 74103bb0..74103bb0 100755..100644
--- a/C/Util/LzmaLib/makefile
+++ b/C/Util/LzmaLib/makefile
diff --git a/C/Util/LzmaLib/resource.rc b/C/Util/LzmaLib/resource.rc
index 674832e0..674832e0 100755..100644
--- a/C/Util/LzmaLib/resource.rc
+++ b/C/Util/LzmaLib/resource.rc
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
index c3c56b1e..32fb56ed 100755..100644
--- 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
index 39f876d4..5ce7195b 100755..100644
--- 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
index ea231112..ea231112 100755..100644
--- a/C/Util/SfxSetup/SfxSetup.dsw
+++ b/C/Util/SfxSetup/SfxSetup.dsw
diff --git a/C/Util/SfxSetup/makefile b/C/Util/SfxSetup/makefile
index ce1fbc9d..5b519807 100755..100644
--- 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
index 8e1a050d..492191f5 100755..100644
--- 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
index 0c1637f2..0c1637f2 100755..100644
--- a/C/Util/SfxSetup/resource.rc
+++ b/C/Util/SfxSetup/resource.rc
diff --git a/C/Util/SfxSetup/setup.ico b/C/Util/SfxSetup/setup.ico
index dbb6ca8b..dbb6ca8b 100755..100644
--- a/C/Util/SfxSetup/setup.ico
+++ b/C/Util/SfxSetup/setup.ico
Binary files differ
diff --git a/C/Xz.c b/C/Xz.c
index 18caba2c..fbc732a8 100755..100644
--- 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
index 0f7a822c..a8296730 100755..100644
--- 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
index 0369554b..aa812548 100755..100644
--- 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
index 0e8efd7e..08dbc330 100755..100644
--- 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 <stddef.h>
-#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
index 113e2cdf..25e4d0eb 100755..100644
--- 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
index 56cfd579..835cb63b 100755..100644
--- 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 <stdlib.h>
#include <string.h>
@@ -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
index c3c19eca..c3c19eca 100755..100644
--- a/C/XzEnc.h
+++ b/C/XzEnc.h
diff --git a/C/XzIn.c b/C/XzIn.c
index 4ba87a2c..4f418638 100755..100644
--- 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 <string.h>
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
index c5a58f28..c5a58f28 100755..100644
--- a/CPP/7zip/Aes.mak
+++ b/CPP/7zip/Aes.mak
diff --git a/CPP/7zip/Archive/7z/7z.dsp b/CPP/7zip/Archive/7z/7z.dsp
index 0484228d..53913f77 100755..100644
--- 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
index 702a86c7..702a86c7 100755..100644
--- a/CPP/7zip/Archive/7z/7z.dsw
+++ b/CPP/7zip/Archive/7z/7z.dsw
diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.cpp b/CPP/7zip/Archive/7z/7zCompressionMode.cpp
index 6774fc48..6774fc48 100755..100644
--- a/CPP/7zip/Archive/7z/7zCompressionMode.cpp
+++ b/CPP/7zip/Archive/7z/7zCompressionMode.cpp
diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.h b/CPP/7zip/Archive/7z/7zCompressionMode.h
index 5cde97c3..5cde97c3 100755..100644
--- a/CPP/7zip/Archive/7z/7zCompressionMode.h
+++ b/CPP/7zip/Archive/7z/7zCompressionMode.h
diff --git a/CPP/7zip/Archive/7z/7zDecode.cpp b/CPP/7zip/Archive/7z/7zDecode.cpp
index 425a3415..7f0e45d1 100755..100644
--- 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<ISequentialInStream> > 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<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;
- lockedStreamImpSpec->Init(&lockedInStream, startPos);
- startPos += packSizes[j];
-
- CLimitedSequentialInStream *streamSpec = new
- CLimitedSequentialInStream;
+ lockedStreamImpSpec->Init(&lockedInStream, startPos + packPositions[j]);
+ CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
CMyComPtr<ISequentialInStream> 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<const UInt64 *> packSizesPointers;
- CRecordVector<const UInt64 *> unpackSizesPointers;
- packSizesPointers.Reserve(numInStreams);
- unpackSizesPointers.Reserve(numOutStreams);
+ CObjArray<UInt64> packSizes(numInStreams);
+ CObjArray<const UInt64 *> packSizesPointers(numInStreams);
+ CObjArray<const UInt64 *> unpackSizesPointers(numOutStreams);
UInt32 j;
+
for (j = 0; j < numOutStreams; j++, unpackStreamIndex++)
- unpackSizesPointers.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<ISequentialInStream *> inStreamPointers;
- inStreamPointers.Reserve(inStreams.Size());
- for (i = 0; i < inStreams.Size(); i++)
- inStreamPointers.Add(inStreams[i]);
+ unsigned num = inStreams.Size();
+ CObjArray<ISequentialInStream *> inStreamPointers(num);
+ for (i = 0; i < num; i++)
+ inStreamPointers[i] = inStreams[i];
ISequentialOutStream *outStreamPointer = outStream;
- return _mixerCoder->Code(&inStreamPointers.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
index d8a424a3..1361772c 100755..100644
--- 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
index 614f9913..36ff5177 100755..100644
--- 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<CMethodId> 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<ICompressCoder> encoder;
CMyComPtr<ICompressCoder2> encoder2;
@@ -100,7 +99,7 @@ HRESULT CEncoder::CreateMixerCoder(
/*
CMyComPtr<ICryptoResetSalt> 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<UInt64> &coderUnpackSizes,
+ UInt64 &unpackSize,
ISequentialOutStream *outStream,
CRecordVector<UInt64> &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<CInOutTempBuffer> inOutTempBuffers;
CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs;
CObjectVector<CMyComPtr<ISequentialOutStream> > 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<const UInt64 *> sizePointers;
for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++)
@@ -203,17 +203,24 @@ HRESULT CEncoder::Encode(
CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2;
CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
- CSequentialOutStreamSizeCount *outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
- CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec;
+ CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL;
+ CMyComPtr<ISequentialOutStream> outStreamSizeCount;
inStreamSizeCountSpec->Init(inStream);
- outStreamSizeCountSpec->SetStream(outStream);
- outStreamSizeCountSpec->Init();
CRecordVector<ISequentialInStream *> inStreamPointers;
CRecordVector<ISequentialOutStream *> 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<ICryptoResetInitVector> resetInitVector;
_mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);
- if (resetInitVector != NULL)
+ if (resetInitVector)
{
resetInitVector->ResetInitVector();
}
CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
_mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
- if (writeCoderProperties != NULL)
+ if (writeCoderProperties)
{
CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream;
CMyComPtr<ISequentialOutStream> 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
index 4909a6e8..8e20bdb5 100755..100644
--- 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<UInt64> &coderUnpackSizes,
+ UInt64 &unpackSize,
ISequentialOutStream *outStream,
CRecordVector<UInt64> &packSizes,
ICompressProgressInfo *compressProgress);
diff --git a/CPP/7zip/Archive/7z/7zExtract.cpp b/CPP/7zip/Archive/7z/7zExtract.cpp
index d55f38e1..6d2c5b06 100755..100644
--- 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<IArchiveExtractCallback> 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<ICompressProgressInfo> 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<ICryptoGetTextPassword> 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
index edd276bc..3f420a51 100755..100644
--- 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
index 6df3672a..4ed4b2dd 100755..100644
--- 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
index 22c4600e..847f65bf 100755..100644
--- 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
index f9bb1af4..cc2d7734 100755..100644
--- a/CPP/7zip/Archive/7z/7zFolderOutStream.h
+++ b/CPP/7zip/Archive/7z/7zFolderOutStream.h
@@ -19,12 +19,12 @@ class CFolderOutStream:
{
COutStreamWithCRC *_crcStreamSpec;
CMyComPtr<ISequentialOutStream> _crcStream;
- const CArchiveDatabaseEx *_db;
+ const CDbEx *_db;
const CBoolVector *_extractStatuses;
CMyComPtr<IArchiveExtractCallback> _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
index 93d4f51e..82983419 100755..100644
--- 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<UInt64> 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<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;
@@ -415,31 +653,30 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
#ifndef _NO_CRYPTO
CMyComPtr<ICryptoGetTextPassword> 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
index 247b55f7..dad943e0 100755..100644
--- 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<IInStream> _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<UInt64> _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
index dd73ee84..2f6a4c37 100755..100644
--- 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<CTreeFolder> &treeFolders, int cur, int curSortIndex)
+{
+ CTreeFolder &tf = treeFolders[cur];
+ tf.SortIndex = curSortIndex++;
+ for (int i = 0; i < tf.SubFolders.Size(); i++)
+ curSortIndex = FillSortIndex(treeFolders, tf.SubFolders[i], curSortIndex);
+ tf.SortIndexEnd = curSortIndex;
+ return curSortIndex;
+}
+
+static int FindSubFolder(const CObjectVector<CTreeFolder> &treeFolders, int cur, const UString &name, int &insertPos)
+{
+ const CIntVector &subFolders = treeFolders[cur].SubFolders;
+ int left = 0, right = subFolders.Size();
+ insertPos = -1;
+ for (;;)
+ {
+ if (left == right)
+ {
+ insertPos = left;
+ return -1;
+ }
+ int mid = (left + right) / 2;
+ int midFolder = subFolders[mid];
+ int compare = CompareFileNames(name, treeFolders[midFolder].Name);
+ if (compare == 0)
+ return midFolder;
+ if (compare < 0)
+ right = mid;
+ else
+ left = mid + 1;
+ }
+}
+
+static int AddFolder(CObjectVector<CTreeFolder> &treeFolders, int cur, const UString &name)
+{
+ int insertPos;
+ int folderIndex = FindSubFolder(treeFolders, cur, name, insertPos);
+ if (folderIndex < 0)
+ {
+ folderIndex = treeFolders.Size();
+ CTreeFolder &newFolder = treeFolders.AddNew();
+ newFolder.Parent = cur;
+ newFolder.Name = name;
+ treeFolders[cur].SubFolders.Insert(insertPos, folderIndex);
+ }
+ // else if (treeFolders[folderIndex].IsAltStreamFolder != isAltStreamFolder) throw 1123234234;
+ return folderIndex;
+}
+*/
+
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
IArchiveUpdateCallback *updateCallback)
{
COM_TRY_BEGIN
- const 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<IArchiveGetRawProps> getRawProps;
+ updateCallback->QueryInterface(IID_IArchiveGetRawProps, (void **)&getRawProps);
+
+ CUniqBlocks secureBlocks;
+ secureBlocks.AddUniq(NULL, 0);
+
+ CObjectVector<CTreeFolder> treeFolders;
+ {
+ CTreeFolder folder;
+ folder.Parent = -1;
+ treeFolders.Add(folder);
+ }
+ */
+
CObjectVector<CUpdateItem> updateItems;
-
+
+ bool need_CTime = (Write_CTime.Def && Write_CTime.Val);
+ bool need_ATime = (Write_ATime.Def && Write_ATime.Val);
+ bool need_MTime = (Write_MTime.Def && Write_MTime.Val || !Write_MTime.Def);
+ 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<ICryptoGetTextPassword2> getPassword2;
updateCallback->QueryInterface(IID_ICryptoGetTextPassword2, (void **)&getPassword2);
+ methodMode.PasswordIsDefined = false;
+ methodMode.Password.Empty();
if (getPassword2)
{
CMyComBSTR password;
Int32 passwordIsDefined;
RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password));
methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);
- if (methodMode.PasswordIsDefined)
+ 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<ICryptoGetTextPassword> getPassword;
updateCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getPassword);
+ /*
+ if (secureBlocks.Sorted.Size() > 1)
+ {
+ secureBlocks.GetReverseMap();
+ for (int i = 0; i < updateItems.Size(); i++)
+ {
+ int &secureIndex = updateItems[i].SecureIndex;
+ secureIndex = secureBlocks.BufIndexToSortedIndex[secureIndex];
+ }
+ }
+ */
+
res = Update(
EXTERNAL_CODECS_VARS
#ifdef _7Z_VOL
@@ -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
index 5b5f2fb3..acff2fdd 100755..100644
--- 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
index 30622b90..d72fdefa 100755..100644
--- 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
index fd751a74..d84cf0b0 100755..100644
--- 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<CByteBuffer> *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<CByteBuffer> *dataVector)
@@ -173,13 +162,22 @@ void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *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<UInt32> &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<UInt64> &packSizes,
- CBoolVector &packCRCsDefined,
- CRecordVector<UInt32> &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<CByteBuffer> *dataVector,
- CObjectVector<CFolder> &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<bool> InStreamUsed;
+ CRecordVector<bool> 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<UInt32> 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<CFolder> &folders,
- CRecordVector<CNum> &numUnpackStreamsInFolders,
+ CFolders &folders,
CRecordVector<UInt64> &unpackSizes,
- CBoolVector &digestsDefined,
- CRecordVector<UInt32> &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<UInt32> 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<CByteBuffer> *dataVector,
UInt64 &dataOffset,
- CRecordVector<UInt64> &packSizes,
- CBoolVector &packCRCsDefined,
- CRecordVector<UInt32> &packCRCs,
- CObjectVector<CFolder> &folders,
- CRecordVector<CNum> &numUnpackStreamsInFolders,
+ CFolders &folders,
CRecordVector<UInt64> &unpackSizes,
- CBoolVector &digestsDefined,
- CRecordVector<UInt32> &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<CByteBuffer> &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<CByteBuffer> &dataVector
- #ifndef _NO_CRYPTO
- , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined
- #endif
+ _7Z_DECODER_CRYPRO_VARS_DECL
)
{
- CRecordVector<UInt64> packSizes;
- CBoolVector packCRCsDefined;
- CRecordVector<UInt32> packCRCs;
- CObjectVector<CFolder> folders;
-
- CRecordVector<CNum> numUnpackStreamsInFolders;
+ CFolders folders;
CRecordVector<UInt64> unpackSizes;
- CBoolVector digestsDefined;
- CRecordVector<UInt32> 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<ISequentialOutStream> 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<UInt64> unpackSizes;
- CBoolVector digestsDefined;
- CRecordVector<UInt32> 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
index 4305a8c5..1836a06b 100755..100644
--- 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<UInt64> IDs;
+
+ CParsedMethods(): Lzma2Prop(0), LzmaDic(0) {}
+};
+
+struct CFolders
+{
+ CNum NumPackStreams;
+ CNum NumFolders;
+
+ CObjArray<UInt64> PackPositions; // NumPackStreams + 1
+ // CUInt32DefVector PackCRCs; // we don't use PackCRCs now
+
+ CUInt32DefVector FolderCRCs; // NumFolders
+ CObjArray<CNum> NumUnpackStreamsVector; // NumFolders
+
+ CObjArray<UInt64> CoderUnpackSizes; // including unpack sizes of bind coders
+ CObjArray<CNum> FoToCoderUnpackSizes; // NumFolders + 1
+ CObjArray<CNum> FoStartPackStreamIndex; // NumFolders + 1
+ CObjArray<Byte> FoToMainUnpackSizeIndex; // NumFolders
+ CObjArray<size_t> FoCodersDataOffset; // NumFolders + 1
+ CByteBuffer CodersData;
+
+ CParsedMethods ParsedMethods;
+
+ void ParseFolderInfo(unsigned folderIndex, CFolder &folder) const;
+
+ 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<CFileItem> Files;
+
+ CUInt64DefVector CTime;
+ CUInt64DefVector ATime;
+ CUInt64DefVector MTime;
+ CUInt64DefVector StartPos;
+ CRecordVector<bool> IsAnti;
+ /*
+ CRecordVector<bool> IsAux;
+ CByteBuffer SecureBuf;
+ CRecordVector<UInt32> SecureIDs;
+ */
+
+ CByteBuffer NamesBuf;
+ CObjArray<size_t> 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<UInt64> FileInfoPopIDs;
+
void Clear()
{
+ StartPosition = 0;
+ StartPositionAfterHeader = 0;
+ DataStartPosition = 0;
+ DataStartPosition2 = 0;
FileInfoPopIDs.Clear();
}
};
-struct CArchiveDatabaseEx: public CArchiveDatabase
+struct CDbEx: public CDatabase
{
- CInArchiveInfo ArchiveInfo;
- CRecordVector<UInt64> PackStreamStartPositions;
- CRecordVector<CNum> FolderStartPackStreamIndex;
+ CInArchiveInfo ArcInfo;
CRecordVector<CNum> FolderStartFileIndex;
CRecordVector<CNum> FileIndexToFolderIndexMap;
UInt64 HeadersSize;
UInt64 PhySize;
+ /*
+ CRecordVector<size_t> SecureOffsets;
+ bool IsTree;
+ bool ThereAreAltStreams;
+ */
+
+ bool IsArc;
+ bool PhySizeWasConfirmed;
+
+ bool ThereIsHeaderError;
+ bool UnexpectedEnd;
+ // bool UnsupportedVersion;
+
+ bool StartHeaderWasRecovered;
+ bool UnsupportedFeatureWarning;
+ bool UnsupportedFeatureError;
+
+ /*
+ void ClearSecureEx()
+ {
+ ClearSecure();
+ SecureOffsets.Clear();
+ }
+ */
+
void Clear()
{
- 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<IInStream> _stream;
- CObjectVector<CInByte2> _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<UInt32> &digests);
+ void ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs);
- void ReadPackInfo(
- UInt64 &dataOffset,
- CRecordVector<UInt64> &packSizes,
- CBoolVector &packCRCsDefined,
- CRecordVector<UInt32> &packCRCs);
+ void ReadPackInfo(CFolders &f);
void ReadUnpackInfo(
const CObjectVector<CByteBuffer> *dataVector,
- CObjectVector<CFolder> &folders);
+ CFolders &folders);
void ReadSubStreamsInfo(
- const CObjectVector<CFolder> &folders,
- CRecordVector<CNum> &numUnpackStreamsInFolders,
+ CFolders &folders,
CRecordVector<UInt64> &unpackSizes,
- CBoolVector &digestsDefined,
- CRecordVector<UInt32> &digests);
+ CUInt32DefVector &digests);
void ReadStreamsInfo(
const CObjectVector<CByteBuffer> *dataVector,
UInt64 &dataOffset,
- CRecordVector<UInt64> &packSizes,
- CBoolVector &packCRCsDefined,
- CRecordVector<UInt32> &packCRCs,
- CObjectVector<CFolder> &folders,
- CRecordVector<CNum> &numUnpackStreamsInFolders,
+ CFolders &folders,
CRecordVector<UInt64> &unpackSizes,
- CBoolVector &digestsDefined,
- CRecordVector<UInt32> &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<CByteBuffer> &dataVector,
- CUInt64DefVector &v, int numFiles);
+ CUInt64DefVector &v, unsigned numItems);
HRESULT ReadAndDecodePackedStreams(
DECL_EXTERNAL_CODECS_LOC_VARS
UInt64 baseOffset, UInt64 &dataOffset,
CObjectVector<CByteBuffer> &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
index 34f10775..02a86196 100755..100644
--- 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<CCoderInfo> Coders;
- CRecordVector<CBindPair> BindPairs;
- CRecordVector<CNum> PackStreams;
- CRecordVector<UInt64> 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<CCoderInfo> Coders;
+ CObjArray2<CBindPair> BindPairs;
+ CObjArray2<CNum> 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<UInt32> Vals;
+
+ void ClearAndSetSize(unsigned newSize)
+ {
+ Defs.ClearAndSetSize(newSize);
+ Vals.ClearAndSetSize(newSize);
+ }
+
+ void Clear()
+ {
+ Defs.Clear();
+ Vals.Clear();
+ }
+
+ void ReserveDown()
+ {
+ Defs.ReserveDown();
+ Vals.ReserveDown();
+ }
+
+ bool ValidAndDefined(unsigned i) const { return i < Defs.Size() && Defs[i]; }
};
struct CUInt64DefVector
{
- CRecordVector<UInt64> Values;
- CRecordVector<bool> Defined;
+ CBoolVector Defs;
+ CRecordVector<UInt64> 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<UInt64> PackSizes;
- CRecordVector<bool> PackCRCsDefined;
- CRecordVector<UInt32> PackCRCs;
- CObjectVector<CFolder> Folders;
- CRecordVector<CNum> NumUnpackStreamsVector;
- CObjectVector<CFileItem> Files;
-
- CUInt64DefVector CTime;
- CUInt64DefVector ATime;
- CUInt64DefVector MTime;
- CUInt64DefVector StartPos;
- CRecordVector<bool> 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
index 0c8aa7e8..9ff97595 100755..100644
--- 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<bool> &digestsDefined,
- const CRecordVector<UInt32> &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<UInt64> &packSizes,
- const CRecordVector<bool> &packCRCsDefined,
- const CRecordVector<UInt32> &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<CFolder> &folders)
+void COutArchive::WriteUnpackInfo(const CObjectVector<CFolder> &folders, const COutFolders &outFolders)
{
if (folders.IsEmpty())
return;
@@ -394,44 +381,29 @@ void COutArchive::WriteUnpackInfo(const CObjectVector<CFolder> &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<bool> unpackCRCsDefined;
- CRecordVector<UInt32> 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<CFolder> &folders,
- const CRecordVector<CNum> &numUnpackStreamsInFolders,
+void COutArchive::WriteSubStreamsInfo(const CObjectVector<CFolder> &folders,
+ const COutFolders &outFolders,
const CRecordVector<UInt64> &unpackSizes,
- const CRecordVector<bool> &digestsDefined,
- const CRecordVector<UInt32> &digests)
+ const CUInt32DefVector &digests)
{
+ const CRecordVector<CNum> &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<bool> digestsDefined2;
- CRecordVector<UInt32> 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<UInt64> &packSizes, CObjectVector<CFolder> &folders)
+ CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders)
{
CBufInStream *streamSpec = new CBufInStream;
CMyComPtr<ISequentialInStream> 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<UInt64> unpackSizes;
- CRecordVector<bool> digestsDefined;
- CRecordVector<UInt32> 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<UInt64> packSizes;
CObjectVector<CFolder> 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<bool>(), CRecordVector<UInt32>());
- 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
index 7b1b528e..cead4bce 100755..100644
--- 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<CNum> NumUnpackStreamsVector;
+ CRecordVector<UInt64> 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<UInt64> PackSizes;
+ CUInt32DefVector PackCRCs;
+ CObjectVector<CFolder> Folders;
+
+ CRecordVector<CFileItem> Files;
+ UStringVector Names;
+ CUInt64DefVector CTime;
+ CUInt64DefVector ATime;
+ CUInt64DefVector MTime;
+ CUInt64DefVector StartPos;
+ CRecordVector<bool> IsAnti;
+
+ /*
+ CRecordVector<bool> IsAux;
+
+ CByteBuffer SecureBuf;
+ CRecordVector<UInt32> SecureSizes;
+ CRecordVector<UInt32> SecureIDs;
+
+ void ClearSecure()
+ {
+ SecureBuf.Free();
+ SecureSizes.Clear();
+ SecureIDs.Clear();
+ }
+ */
+
+ void Clear()
+ {
+ OutFoldersClear();
+
+ PackSizes.Clear();
+ PackCRCs.Clear();
+ Folders.Clear();
+
+ Files.Clear();
+ Names.Clear();
+ CTime.Clear();
+ ATime.Clear();
+ MTime.Clear();
+ StartPos.Clear();
+ 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<bool> &digestsDefined,
- const CRecordVector<UInt32> &hashDigests);
+ void WritePropBoolVector(Byte id, const CBoolVector &boolVector);
+
+ void WriteHashDigests(const CUInt32DefVector &digests);
void WritePackInfo(
UInt64 dataOffset,
const CRecordVector<UInt64> &packSizes,
- const CRecordVector<bool> &packCRCsDefined,
- const CRecordVector<UInt32> &packCRCs);
+ const CUInt32DefVector &packCRCs);
- void WriteUnpackInfo(const CObjectVector<CFolder> &folders);
+ void WriteUnpackInfo(
+ const CObjectVector<CFolder> &folders,
+ const COutFolders &outFolders);
void WriteSubStreamsInfo(
const CObjectVector<CFolder> &folders,
- const CRecordVector<CNum> &numUnpackStreamsInFolders,
+ const COutFolders &outFolders,
const CRecordVector<UInt64> &unpackSizes,
- const CRecordVector<bool> &digestsDefined,
- const CRecordVector<UInt32> &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<UInt64> &packSizes, CObjectVector<CFolder> &folders);
+ CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &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
index fd4af49c..5ed36947 100755..100644
--- 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<UInt64> &src,
CRecordVector<UInt64> &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<UInt64> &src,
static void RemoveOneItem(CRecordVector<UInt64> &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<UInt64> &src, UInt32 item)
static void InsertToHead(CRecordVector<UInt64> &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<UInt64> &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<UInt64> fileInfoPopIDs = _db.ArchiveInfo.FileInfoPopIDs;
+ CRecordVector<UInt64> fileInfoPopIDs = _db.ArcInfo.FileInfoPopIDs;
RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream);
RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile);
+ /*
+ RemoveOneItem(fileInfoPopIDs, NID::kParent);
+ RemoveOneItem(fileInfoPopIDs, NID::kNtSecure);
+ */
+
+ COPY_ONE_ITEM(kName);
+ COPY_ONE_ITEM(kAnti);
+ COPY_ONE_ITEM(kSize);
+ COPY_ONE_ITEM(kPackInfo);
+ COPY_ONE_ITEM(kCTime);
+ COPY_ONE_ITEM(kMTime);
+ COPY_ONE_ITEM(kATime);
+ COPY_ONE_ITEM(kWinAttrib);
+ COPY_ONE_ITEM(kCRC);
+ COPY_ONE_ITEM(kComment);
- 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
index 66181795..66181795 100755..100644
--- a/CPP/7zip/Archive/7z/7zProperties.h
+++ b/CPP/7zip/Archive/7z/7zProperties.h
diff --git a/CPP/7zip/Archive/7z/7zRegister.cpp b/CPP/7zip/Archive/7z/7zRegister.cpp
index 6e9bf6b9..37ea29d3 100755..100644
--- 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
index 06969636..8e45d987 100755..100644
--- 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
index 2e26efd5..2e26efd5 100755..100644
--- a/CPP/7zip/Archive/7z/7zSpecStream.h
+++ b/CPP/7zip/Archive/7z/7zSpecStream.h
diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp
index e63b09d2..96befa23 100755..100644
--- 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<CUpdateItem> &updateItems = *(const CObjectVector<CUpdateItem> *)param;
const CUpdateItem &u1 = updateItems[*p1];
const CUpdateItem &u2 = updateItems[*p2];
+ // NonAnti < Anti
+ if (u1.IsAnti != u2.IsAnti)
+ return (u1.IsAnti ? 1 : -1);
if (u1.IsDir != u2.IsDir)
- 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<CTreeFolder> *TreeFolders;
+ bool SortByType;
+};
+
+/*
+ we sort files in such order:
+ - Dir.NonAnti (name sorted)
+ - alt streams
+ - Dirs
+ - Dir.Anti (reverse name sorted)
+*/
+
+
static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param)
{
const CRefItem &a1 = *p1;
const CRefItem &a2 = *p2;
const CUpdateItem &u1 = *a1.UpdateItem;
const CUpdateItem &u2 = *a2.UpdateItem;
- 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<UInt32> 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<ISequentialOutStream> _crcStream;
- const CArchiveDatabaseEx *_db;
+ const CDbEx *_db;
const CBoolVector *_extractStatuses;
CMyComPtr<ISequentialOutStream> _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<ISequentialOutStream> Fos;
UInt64 StartPos;
- const UInt64 *PackSizes;
- const CFolder *Folder;
+ const CFolders *Folders;
+ int FolderIndex;
#ifndef _NO_CRYPTO
- CMyComPtr<ICryptoGetTextPassword> GetTextPassword;
+ CMyComPtr<ICryptoGetTextPassword> 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<CUpdateItem> &updateItems,
+ // const CObjectVector<CTreeFolder> &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<IOutStream> 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<int> fileIndexToUpdateIndexMap;
+ CIntArr fileIndexToUpdateIndexMap;
CRecordVector<CFolderRepack> 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<CSolidGroup> 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<int> 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<ISequentialInStream> 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<CRefItem> 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<UInt32> indices;
- indices.Reserve(numFiles);
+ CObjArray<UInt32> 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<ISequentialInStream> 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<int> 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
index 31e36224..d00276e0 100755..100644
--- 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<CUpdateItem> &updateItems,
+ // const CObjectVector<CTreeFolder> &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
index d0feea85..d0feea85 100755..100644
--- a/CPP/7zip/Archive/7z/StdAfx.cpp
+++ b/CPP/7zip/Archive/7z/StdAfx.cpp
diff --git a/CPP/7zip/Archive/7z/StdAfx.h b/CPP/7zip/Archive/7z/StdAfx.h
index 2e4be10b..2854ff3e 100755..100644
--- 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
index 0abb3756..19982112 100755..100644
--- 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
index f79dac08..f79dac08 100755..100644
--- a/CPP/7zip/Archive/7z/resource.rc
+++ b/CPP/7zip/Archive/7z/resource.rc
diff --git a/CPP/7zip/Archive/ApmHandler.cpp b/CPP/7zip/Archive/ApmHandler.cpp
index a3b5e19b..04cd06fa 100755..100644
--- 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<IInStream> _stream;
CRecordVector<CItem> _items;
-
- int _blockSizeLog;
+ CMyComPtr<IInStream> _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<IInStream> 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<CItem> _items;
+ CMyComPtr<IInStream> _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<ICompressCoder> copyCoder = copyCoderSpec;
+
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(extractCallback, false);
+
+ CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+ CMyComPtr<ISequentialInStream> inStream(streamSpec);
+ streamSpec->SetStream(_stream);
+
+ for (i = 0; i < numItems; i++)
+ {
+ lps->InSize = lps->OutSize = currentTotalSize;
+ RINOK(lps->SetCur());
+ CMyComPtr<ISequentialOutStream> 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
index 55b530b2..55b530b2 100755..100644
--- a/CPP/7zip/Archive/Archive.def
+++ b/CPP/7zip/Archive/Archive.def
diff --git a/CPP/7zip/Archive/Archive2.def b/CPP/7zip/Archive/Archive2.def
index 885d39d1..66feb41d 100755..100644
--- 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
index c7908b59..c7d6611b 100755..100644
--- 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
index 4dd686ec..ad44c62a 100755..100644
--- 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<CItem> _items;
+ CMyComPtr<IInStream> _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<CItem> _items;
- CMyComPtr<IInStream> _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
index 49ae8c79..704cdc73 100755..100644
--- 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<IInStream> _stream;
CMyComPtr<ISequentialInStream> _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(&currentTotalPacked));
+
+ // RINOK(extractCallback->SetCompleted(&packSize));
+
CMyComPtr<ISequentialOutStream> 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<ICompressCoder> 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<ICompressCoder> decoder = decoderSpec;
decoderSpec->SetInStream(_seqStream);
#ifndef _7ZIP_ST
@@ -172,43 +236,104 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CMyComPtr<ICompressProgressInfo> 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
index 12c73eb5..cebec610 100755..100644
--- 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
index 1db3835b..b795ed97 100755..100644
--- 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<ISequentialInStream> _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
index fd707fe5..22bc93a0 100755..100644
--- a/CPP/7zip/Archive/Cab/CabHandler.cpp
+++ b/CPP/7zip/Archive/Cab/CabHandler.cpp
@@ -2,15 +2,17 @@
#include "StdAfx.h"
+// #include <stdio.h>
+
#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<Byte> 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<CFolder> &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<IArchiveOpenCallback> 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<IArchiveOpenVolumeCallback> openVolumeCallback;
callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
@@ -236,96 +347,169 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
CMyComPtr<IInStream> 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<IArchiveExtractCallback> m_ExtractCallback;
bool m_TestMode;
@@ -379,7 +563,7 @@ public:
void Init(
const CMvDatabaseEx *database,
const CRecordVector<bool> *extractStatuses,
- int startIndex,
+ unsigned startIndex,
UInt64 folderSize,
IArchiveExtractCallback *extractCallback,
bool testMode);
@@ -393,7 +577,7 @@ public:
void CFolderOutStream::Init(
const CMvDatabaseEx *database,
const CRecordVector<bool> *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
index 1edcd11e..6f44b875 100755..100644
--- 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
index 0cba1b0b..0cba1b0b 100755..100644
--- a/CPP/7zip/Archive/Cab/CabHeader.cpp
+++ b/CPP/7zip/Archive/Cab/CabHeader.cpp
diff --git a/CPP/7zip/Archive/Cab/CabHeader.h b/CPP/7zip/Archive/Cab/CabHeader.h
index 0f0d2af3..9ec0760a 100755..100644
--- 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
index c0bffa2d..c499f05f 100755..100644
--- 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 <stdio.h>
+
+#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<ISequentialInStream> 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
index 1e9b188b..4fdab77b 100755..100644
--- 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<CFolder> Folders;
+ CRecordVector<CFolder> Folders;
CObjectVector<CItem> 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<CDatabaseEx> Volumes;
CRecordVector<CMvItem> Items;
- CRecordVector<int> StartFolderOfVol;
- CRecordVector<int> FolderStartFileIndex;
-
+ CRecordVector<int> StartFolderOfVol; // can be negative
+ CRecordVector<unsigned> 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
index 63a1e856..eda62bda 100755..100644
--- 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
index 15fe4099..acad4c4a 100755..100644
--- 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
index e7fb6986..2854ff3e 100755..100644
--- 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
index a9e334b0..c67ded28 100755..100644
--- 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<IArchiveOpenCallback> _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
index 440c50f1..884f391b 100755..100644
--- 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<IInStream> 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
index d52b9ba6..9b0bb199 100755..100644
--- 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 <stdio.h>
+
+#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<ISequentialInStream> 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 &section = 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
index 4b1ac7a6..70764ab9 100755..100644
--- 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<CItem> 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<UInt64> 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<ISequentialInStream> 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
index e7fb6986..2854ff3e 100755..100644
--- 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<ICompressCoder> copyCoder = copyCoderSpec;
-
- CLocalProgress *lps = new CLocalProgress;
- CMyComPtr<ICompressProgressInfo> 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<ISequentialOutStream> 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<ISequentialInStream> 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<ISequentialInStream> 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<IInStream> _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<CItem> Items;
- CRecordVector<CRef> 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<UInt32> MiniSids;
+
+ HRESULT AddNode(int parent, UInt32 did);
+public:
+
+ CObjArray<UInt32> Fat;
+ UInt32 FatSize;
+
+ CObjArray<UInt32> Mat;
+ UInt32 MatSize;
+
+ CObjectVector<CItem> Items;
+ CRecordVector<CRef> 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<UInt32> 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<IInStream> _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<ICompressCoder> copyCoder = copyCoderSpec;
+
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> 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<ISequentialOutStream> 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<ISequentialInStream> 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<ISequentialInStream> 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
index a19f0457..a19f0457 100755..100644
--- a/CPP/7zip/Archive/Common/CoderMixer.cpp
+++ b/CPP/7zip/Archive/Common/CoderMixer.cpp
diff --git a/CPP/7zip/Archive/Common/CoderMixer.h b/CPP/7zip/Archive/Common/CoderMixer.h
index 6379dd80..6379dd80 100755..100644
--- a/CPP/7zip/Archive/Common/CoderMixer.h
+++ b/CPP/7zip/Archive/Common/CoderMixer.h
diff --git a/CPP/7zip/Archive/Common/CoderMixer2.cpp b/CPP/7zip/Archive/Common/CoderMixer2.cpp
index 0b06a489..13019d1f 100755..100644
--- 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<UInt64> &sizes,
+void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,
CRecordVector<const UInt64 *> &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
index a03722d6..50e7077a 100755..100644
--- 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<UInt64> &sizes,
+ CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems);
+
struct CCoderInfo2
{
CMyComPtr<ICompressCoder> Coder;
@@ -151,7 +154,9 @@ struct CCoderInfo2
CRecordVector<const UInt64 *> InSizePointers;
CRecordVector<const UInt64 *> 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
index 87686e85..5288fbc1 100755..100644
--- 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<UInt64> &sizes,
- CRecordVector<const UInt64 *> &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
index 81bb3f0b..ba475cec 100755..100644
--- 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<ISequentialInStream*> InStreamPointers;
+ CRecordVector<ISequentialOutStream*> OutStreamPointers;
+
+public:
HRESULT Result;
CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;
CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;
- CRecordVector<ISequentialInStream*> InStreamPointers;
- CRecordVector<ISequentialOutStream*> 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<CStreamBinder> _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
index a21ca0c0..a94ba115 100755..100644
--- 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
index d35655ba..d35655ba 100755..100644
--- a/CPP/7zip/Archive/Common/CoderMixer2ST.h
+++ b/CPP/7zip/Archive/Common/CoderMixer2ST.h
diff --git a/CPP/7zip/Archive/Common/CoderMixerMT.cpp b/CPP/7zip/Archive/Common/CoderMixerMT.cpp
index 96ea76a3..96ea76a3 100755..100644
--- a/CPP/7zip/Archive/Common/CoderMixerMT.cpp
+++ b/CPP/7zip/Archive/Common/CoderMixerMT.cpp
diff --git a/CPP/7zip/Archive/Common/CoderMixerMT.h b/CPP/7zip/Archive/Common/CoderMixerMT.h
index 9491a965..9491a965 100755..100644
--- a/CPP/7zip/Archive/Common/CoderMixerMT.h
+++ b/CPP/7zip/Archive/Common/CoderMixerMT.h
diff --git a/CPP/7zip/Archive/Common/CrossThreadProgress.cpp b/CPP/7zip/Archive/Common/CrossThreadProgress.cpp
index a974b54c..a974b54c 100755..100644
--- a/CPP/7zip/Archive/Common/CrossThreadProgress.cpp
+++ b/CPP/7zip/Archive/Common/CrossThreadProgress.cpp
diff --git a/CPP/7zip/Archive/Common/CrossThreadProgress.h b/CPP/7zip/Archive/Common/CrossThreadProgress.h
index 7e0b1053..7e0b1053 100755..100644
--- a/CPP/7zip/Archive/Common/CrossThreadProgress.h
+++ b/CPP/7zip/Archive/Common/CrossThreadProgress.h
diff --git a/CPP/7zip/Archive/Common/DummyOutStream.cpp b/CPP/7zip/Archive/Common/DummyOutStream.cpp
index 54bcfec1..7c4f5487 100755..100644
--- 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
index 13d5b62c..b5a51fc0 100755..100644
--- 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
index 15aa6cea..e9a0f032 100755..100644
--- 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
index e15af573..e15af573 100755..100644
--- a/CPP/7zip/Archive/Common/FindSignature.h
+++ b/CPP/7zip/Archive/Common/FindSignature.h
diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp
index 7e6f4602..18ad5580 100755..100644
--- 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
index d3c9a237..40a4a698 100755..100644
--- 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
index 569a56f3..3f4dd3b8 100755..100644
--- 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
index 31b761e4..31b761e4 100755..100644
--- a/CPP/7zip/Archive/Common/InStreamWithCRC.h
+++ b/CPP/7zip/Archive/Common/InStreamWithCRC.h
diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/CPP/7zip/Archive/Common/ItemNameUtils.cpp
index cc476fad..7cd3037b 100755..100644
--- 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
index 5eafacb1..d0dc76a4 100755..100644
--- 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
index 04d11caf..5bf0bef9 100755..100644
--- 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<ISequentialOutStream> _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
index 3fceb7cc..2a1a4a43 100755..100644
--- 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
index f955c225..f955c225 100755..100644
--- a/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
+++ b/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
diff --git a/CPP/7zip/Archive/Common/OutStreamWithCRC.h b/CPP/7zip/Archive/Common/OutStreamWithCRC.h
index 115b442a..09b899bb 100755..100644
--- 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
index 0526c1b1..0526c1b1 100755..100644
--- a/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp
+++ b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp
diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.h b/CPP/7zip/Archive/Common/OutStreamWithSha1.h
index 3bbfbbe1..3bbfbbe1 100755..100644
--- a/CPP/7zip/Archive/Common/OutStreamWithSha1.h
+++ b/CPP/7zip/Archive/Common/OutStreamWithSha1.h
diff --git a/CPP/7zip/Archive/Common/ParseProperties.cpp b/CPP/7zip/Archive/Common/ParseProperties.cpp
index 63e4f3ef..63e4f3ef 100755..100644
--- a/CPP/7zip/Archive/Common/ParseProperties.cpp
+++ b/CPP/7zip/Archive/Common/ParseProperties.cpp
diff --git a/CPP/7zip/Archive/Common/ParseProperties.h b/CPP/7zip/Archive/Common/ParseProperties.h
index 1038a8c0..1038a8c0 100755..100644
--- a/CPP/7zip/Archive/Common/ParseProperties.h
+++ b/CPP/7zip/Archive/Common/ParseProperties.h
diff --git a/CPP/7zip/Archive/Common/StdAfx.h b/CPP/7zip/Archive/Common/StdAfx.h
index 2e4be10b..2854ff3e 100755..100644
--- 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
index 0f32ef66..9c1271c4 100755..100644
--- 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<IInStream> 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<CItemEx> _items;
+ CObjectVector<CItem> _items;
CMyComPtr<IInStream> _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<ISequentialOutStream> _stream;
+ UInt64 _size;
+ UInt32 _crc;
+ bool _calculate;
+public:
+ MY_UNKNOWN_IMP
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+ void SetStream(ISequentialOutStream *stream) { _stream = stream; }
+ void ReleaseStream() { _stream.Release(); }
+ void Init(bool calculate = true)
+ {
+ _size = 0;
+ _calculate = calculate;
+ _crc = 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<ISequentialInStream> inStream(streamSpec);
streamSpec->SetStream(_stream);
+ COutStreamWithSum *outStreamSumSpec = new COutStreamWithSum;
+ CMyComPtr<ISequentialOutStream> 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
index a55e3743..3764f1af 100755..100644
--- 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<ICompressCoder> _zlibDecoder;
-
+
CBufInStream *_inStreamSpec;
CMyComPtr<ISequentialInStream> _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 = "!<arch>\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<IInStream> 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<CItem> _items;
- CMyComPtr<IInStream> _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<ICompressCoder> copyCoder = copyCoderSpec;
-
- CLocalProgress *lps = new CLocalProgress;
- CMyComPtr<ICompressProgressInfo> progress = lps;
- lps->Init(extractCallback, false);
-
- CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
- CMyComPtr<ISequentialInStream> inStream(streamSpec);
- streamSpec->SetStream(_stream);
-
- for (i = 0; i < numItems; i++)
- {
- lps->InSize = lps->OutSize = currentTotalSize;
- RINOK(lps->SetCur());
- CMyComPtr<ISequentialOutStream> 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
index ca3dc6f5..ca3dc6f5 100755..100644
--- a/CPP/7zip/Archive/DeflateProps.cpp
+++ b/CPP/7zip/Archive/DeflateProps.cpp
diff --git a/CPP/7zip/Archive/DeflateProps.h b/CPP/7zip/Archive/DeflateProps.h
index 9fd2c2e9..9fd2c2e9 100755..100644
--- a/CPP/7zip/Archive/DeflateProps.h
+++ b/CPP/7zip/Archive/DeflateProps.h
diff --git a/CPP/7zip/Archive/DllExports.cpp b/CPP/7zip/Archive/DllExports.cpp
index 6c72dea7..fa40d024 100755..100644
--- 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
index ad14ff06..beb758a2 100755..100644
--- 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
index 5040d518..7166f2ce 100755..100644
--- 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 <stdio.h>
#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<CBlock> 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<IInStream> _inStream;
-
- AString _xml;
CObjectVector<CFile> _files;
- CRecordVector<int> _fileIndices;
+ bool _masterCrcError;
+
+ UInt64 _startPos;
+ UInt64 _phySize;
+
+ #ifdef DMG_SHOW_RAW
+ CObjectVector<CExtraFile> _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<CMethodStat> Stats;
CRecordVector<UInt32> Types;
+ CRecordVector<UInt32> 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<ISequentialOutStream> outCrcStream = outCrcStreamSpec;
+ outCrcStreamSpec->SetStream(realOutStream);
+ bool needCrc = false;
+ outCrcStreamSpec->Init(needCrc);
+
CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream;
CMyComPtr<ISequentialOutStream> 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<CChunk> _chunks;
+
+ NCompress::NBZip2::CDecoder *bzip2CoderSpec;
+ CMyComPtr<ICompressCoder> bzip2Coder;
+
+ NCompress::NZlib::CDecoder *zlibCoderSpec;
+ CMyComPtr<ICompressCoder> zlibCoder;
+
+ CAdcDecoder *adcCoderSpec;
+ CMyComPtr<ICompressCoder> adcCoder;
+
+ CBufPtrSeqOutStream *outStreamSpec;
+ CMyComPtr<ISequentialOutStream> outStream;
+
+ CLimitedSequentialInStream *limitedStreamSpec;
+ CMyComPtr<ISequentialInStream> inStream;
+
+public:
+ CMyComPtr<IInStream> 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<CBlock> &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<ISequentialInStream> 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
index c4ad78e9..1736219f 100755..100644
--- 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<CSegment> _segments;
+ CRecordVector<CSection> _sections;
+ CByteBuffer _namesData;
CMyComPtr<IInStream> _inStream;
- CObjectVector<CSegment> _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 &section = _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 &sect = _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<ISequentialOutStream> 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
index 1c374a44..51064a1a 100755..100644
--- 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
index a22c29e3..3bb4620b 100755..100644
--- 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<IInStream> _stream;
CObjectVector<CItem2> _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<CItem> 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<CItem> 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
index ede6b01b..69b3c3be 100755..100644
--- a/CPP/7zip/Archive/GzHandler.cpp
+++ b/CPP/7zip/Archive/GzHandler.cpp
@@ -2,13 +2,16 @@
#include "StdAfx.h"
+// #include <stdio.h>
+
#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<IInStream> _stream;
CMyComPtr<ICompressCoder> _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<IArchiveOpenCallback> Callback;
+public:
+ UInt64 Offset;
+ MY_UNKNOWN_IMP1(ICompressProgressInfo)
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+ void Init(IArchiveOpenCallback *callback) { Callback = callback; }
+};
+
+STDMETHODIMP CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */)
+{
+ if (Callback)
{
- 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(&currentTotalPacked));
+ // if (_stream) extractCallback->SetTotal(_packSize);
+ // UInt64 currentTotalPacked = 0;
+ // RINOK(extractCallback->SetCompleted(&currentTotalPacked));
CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
@@ -473,71 +678,166 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CMyComPtr<ICompressProgressInfo> 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<ICompressCoder> 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<IArchiveOpenCallback> _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(&currentTotalSize));
- Int32 index = allFilesMode ? i : indices[i];
- const CItem &item = _db.Items[index];
- currentItemSize = 0;
- if (!item.IsDir())
- currentItemSize = item.Size;
-
- CMyComPtr<ISequentialOutStream> 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<IInStream> _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<CIdExtents> *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<CExtent> 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<CIdExtents> FileExtents;
- // CObjectVector<CIdExtents> ResExtents;
- CRecordVector<CIdIndexPair> IdToIndexMap;
-
- HRESULT LoadExtentFile(IInStream *inStream);
- HRESULT LoadCatalog(IInStream *inStream, CProgressVirt *progress);
-
- HRESULT ReadFile(const CFork &fork, CByteBuffer &buf, IInStream *inStream);
-public:
- CVolHeader Header;
- CObjectVector<CItem> 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<CExtent> Extents;
+};
+
+struct CFork
+{
+ UInt64 Size;
+ UInt32 NumBlocks;
+ // UInt32 ClumpSize;
+ CRecordVector<CExtent> 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<CIdExtents> &items, UInt32 id);
+ bool UpgradeAndTest(const CObjectVector<CIdExtents> &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<CIdIndexPair> &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<CIdExtents> &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<CIdExtents> &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<CIdExtents> *overflowExtentsArray);
+ HRESULT LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpenCallback *progress);
+ HRESULT LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents> *overflowExtentsArray, IInStream *inStream, IArchiveOpenCallback *progress);
+ bool Parse_decmpgfs(const CAttr &attr, CItem &item, bool &skip);
+public:
+ CRecordVector<CRef> Refs;
+ CObjectVector<CItem> Items;
+ CObjectVector<CAttr> 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<CIdExtents> *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<CIdExtents> &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<CIdExtents> *overflowExtentsArray, IInStream *inStream, IArchiveOpenCallback *progress)
+{
+ unsigned reserveSize = (unsigned)(Header.NumFolders + 1 + Header.NumFiles);
+ Items.ClearAndReserve(reserveSize);
+ Refs.ClearAndReserve(reserveSize);
+
+ CRecordVector<CIdIndexPair> 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<CIdExtents> 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<IInStream> _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<ISequentialInStream> 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<ISequentialInStream> 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<ICompressCoder> _zlibDecoder;
+
+ for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
+ {
+ RINOK(extractCallback->SetCompleted(&currentTotalSize));
+ UInt32 index = allFilesMode ? i : indices[i];
+ const CRef &ref = Refs[index];
+ const CItem &item = Items[ref.ItemIndex];
+ currentItemSize = Get_UnpackSize_of_Ref(ref);
+
+ CMyComPtr<ISequentialOutStream> 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<ISequentialInStream> 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<ISequentialInStream> 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
index 85320276..63e16ac3 100755..100644
--- 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
index 319753a1..319753a1 100755..100644
--- a/CPP/7zip/Archive/Icons/7z.ico
+++ b/CPP/7zip/Archive/Icons/7z.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/arj.ico b/CPP/7zip/Archive/Icons/arj.ico
index c0f8b141..c0f8b141 100755..100644
--- a/CPP/7zip/Archive/Icons/arj.ico
+++ b/CPP/7zip/Archive/Icons/arj.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/bz2.ico b/CPP/7zip/Archive/Icons/bz2.ico
index f22abebc..f22abebc 100755..100644
--- a/CPP/7zip/Archive/Icons/bz2.ico
+++ b/CPP/7zip/Archive/Icons/bz2.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/cab.ico b/CPP/7zip/Archive/Icons/cab.ico
index c96c0f01..c96c0f01 100755..100644
--- a/CPP/7zip/Archive/Icons/cab.ico
+++ b/CPP/7zip/Archive/Icons/cab.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/cpio.ico b/CPP/7zip/Archive/Icons/cpio.ico
index 9abaabc7..9abaabc7 100755..100644
--- a/CPP/7zip/Archive/Icons/cpio.ico
+++ b/CPP/7zip/Archive/Icons/cpio.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/deb.ico b/CPP/7zip/Archive/Icons/deb.ico
index 97a08654..97a08654 100755..100644
--- a/CPP/7zip/Archive/Icons/deb.ico
+++ b/CPP/7zip/Archive/Icons/deb.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/dmg.ico b/CPP/7zip/Archive/Icons/dmg.ico
index 7d63b09f..7d63b09f 100755..100644
--- a/CPP/7zip/Archive/Icons/dmg.ico
+++ b/CPP/7zip/Archive/Icons/dmg.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/fat.ico b/CPP/7zip/Archive/Icons/fat.ico
index 7503d933..7503d933 100755..100644
--- a/CPP/7zip/Archive/Icons/fat.ico
+++ b/CPP/7zip/Archive/Icons/fat.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/gz.ico b/CPP/7zip/Archive/Icons/gz.ico
index d402a698..d402a698 100755..100644
--- a/CPP/7zip/Archive/Icons/gz.ico
+++ b/CPP/7zip/Archive/Icons/gz.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/hfs.ico b/CPP/7zip/Archive/Icons/hfs.ico
index bf2c1986..bf2c1986 100755..100644
--- a/CPP/7zip/Archive/Icons/hfs.ico
+++ b/CPP/7zip/Archive/Icons/hfs.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/iso.ico b/CPP/7zip/Archive/Icons/iso.ico
index b3e3ac2f..b3e3ac2f 100755..100644
--- a/CPP/7zip/Archive/Icons/iso.ico
+++ b/CPP/7zip/Archive/Icons/iso.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/lzh.ico b/CPP/7zip/Archive/Icons/lzh.ico
index 84dab49c..84dab49c 100755..100644
--- a/CPP/7zip/Archive/Icons/lzh.ico
+++ b/CPP/7zip/Archive/Icons/lzh.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/lzma.ico b/CPP/7zip/Archive/Icons/lzma.ico
index 2de2c249..2de2c249 100755..100644
--- a/CPP/7zip/Archive/Icons/lzma.ico
+++ b/CPP/7zip/Archive/Icons/lzma.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/ntfs.ico b/CPP/7zip/Archive/Icons/ntfs.ico
index 6b2aeb00..6b2aeb00 100755..100644
--- a/CPP/7zip/Archive/Icons/ntfs.ico
+++ b/CPP/7zip/Archive/Icons/ntfs.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/rar.ico b/CPP/7zip/Archive/Icons/rar.ico
index 2918d294..2918d294 100755..100644
--- a/CPP/7zip/Archive/Icons/rar.ico
+++ b/CPP/7zip/Archive/Icons/rar.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/rpm.ico b/CPP/7zip/Archive/Icons/rpm.ico
index cdeb8d1b..cdeb8d1b 100755..100644
--- a/CPP/7zip/Archive/Icons/rpm.ico
+++ b/CPP/7zip/Archive/Icons/rpm.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/split.ico b/CPP/7zip/Archive/Icons/split.ico
index 65723ff3..65723ff3 100755..100644
--- a/CPP/7zip/Archive/Icons/split.ico
+++ b/CPP/7zip/Archive/Icons/split.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/squashfs.ico b/CPP/7zip/Archive/Icons/squashfs.ico
index b802d942..b802d942 100755..100644
--- a/CPP/7zip/Archive/Icons/squashfs.ico
+++ b/CPP/7zip/Archive/Icons/squashfs.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/tar.ico b/CPP/7zip/Archive/Icons/tar.ico
index 6835885b..6835885b 100755..100644
--- a/CPP/7zip/Archive/Icons/tar.ico
+++ b/CPP/7zip/Archive/Icons/tar.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/vhd.ico b/CPP/7zip/Archive/Icons/vhd.ico
index 33bed3c9..33bed3c9 100755..100644
--- a/CPP/7zip/Archive/Icons/vhd.ico
+++ b/CPP/7zip/Archive/Icons/vhd.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/wim.ico b/CPP/7zip/Archive/Icons/wim.ico
index 887975e6..887975e6 100755..100644
--- a/CPP/7zip/Archive/Icons/wim.ico
+++ b/CPP/7zip/Archive/Icons/wim.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/xar.ico b/CPP/7zip/Archive/Icons/xar.ico
index 281aa7dc..281aa7dc 100755..100644
--- a/CPP/7zip/Archive/Icons/xar.ico
+++ b/CPP/7zip/Archive/Icons/xar.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/xz.ico b/CPP/7zip/Archive/Icons/xz.ico
index bc07a7eb..bc07a7eb 100755..100644
--- a/CPP/7zip/Archive/Icons/xz.ico
+++ b/CPP/7zip/Archive/Icons/xz.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/z.ico b/CPP/7zip/Archive/Icons/z.ico
index 2db53583..2db53583 100755..100644
--- a/CPP/7zip/Archive/Icons/z.ico
+++ b/CPP/7zip/Archive/Icons/z.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/zip.ico b/CPP/7zip/Archive/Icons/zip.ico
index 2af46066..2af46066 100755..100644
--- a/CPP/7zip/Archive/Icons/zip.ico
+++ b/CPP/7zip/Archive/Icons/zip.ico
Binary files differ
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<CBlock> _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<ICompressProgressInfo> 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<ISequentialOutStream> 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
index f040b033..fc984048 100755..100644
--- 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<ISequentialInStream> inStream(streamSpec);
streamSpec->SetStream(_stream);
- CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream;
- CMyComPtr<ISequentialOutStream> 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<ISequentialInStream> 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
index 1dcade8f..1923784d 100755..100644
--- 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
index b3e418bb..1cd2516c 100755..100644
--- 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
index 9702d70a..ce21b0ff 100755..100644
--- 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
index 7ed618d2..ba12acae 100755..100644
--- 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
index f9c6f640..614b3744 100755..100644
--- 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<IInStream> _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<CRef> Refs;
CObjectVector<CVolumeDescriptor> VolDescs;
int MainVolDescIndex;
UInt32 BlockSize;
CObjectVector<CBootInitialEntry> BootEntries;
+
+ bool IsArc;
+ bool UnexpectedEnd;
+ bool HeadersError;
bool IncorrectBigEndian;
+ bool TooDeepDirs;
+ bool SelfLinkedDirs;
+ CRecordVector<UInt32> 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
index f39c2f5d..b6ae21b7 100755..100644
--- 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
index 67a09c76..c6f4a521 100755..100644
--- 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
index 2e4be10b..2854ff3e 100755..100644
--- 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
index 194de47e..74f713f6 100755..100644
--- 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<CItemEx> _items;
CMyComPtr<IInStream> _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
index 778c2fd8..d1e19677 100755..100644
--- 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<ICompressCoder> _lzmaDecoder;
CMyComPtr<ISequentialOutStream> _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<IInStream> _stream;
CMyComPtr<ISequentialInStream> _seqStream;
+
+ bool _isArc;
+ bool _needSeekToStart;
+ bool _dataAfterEnd;
+ bool _needMoreInput;
+
+ bool _packSize_Defined;
+ bool _unpackSize_Defined;
+ bool _numStreams_Defined;
+
+ bool _unsupported;
+ bool _dataError;
+
+ UInt64 _packSize;
+ UInt64 _unpackSize;
+ UInt64 _numStreams;
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<IArchiveOpenCallback> Callback;
+public:
+ UInt64 Offset;
+
+ MY_UNKNOWN_IMP1(ICompressProgressInfo)
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+ void Init(IArchiveOpenCallback *callback) { Callback = callback; }
+};
+
+STDMETHODIMP CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */)
+{
+ if (Callback)
+ {
+ 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<ICompressProgressInfo> 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
index a6261f34..11ff9703 100755..100644
--- 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<IInStream> _inStream;
CObjectVector<CSegment> _segments;
CObjectVector<CSection> _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 &sect = _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 &sect = _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
index b6d79182..309bc286 100755..100644
--- 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
index 67495e76..cb124c40 100755..100644
--- 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<IInStream> _stream;
- UInt32 _size;
+ CMyComPtr<IInStream> _inStream;
+ CMyComPtr<ISequentialInStream> _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<IArchiveOpenVolumeCallback> 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<IArchiveOpenVolumeCallback> 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<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ?
@@ -225,32 +312,81 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> 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
index 5ebda099..39f8de27 100755..100644
--- 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<IInStream> _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
index 0845f965..bb73d273 100755..100644
--- 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<ISequentialInStream> > 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<ICompressCoder> coder;
- RINOK(CreateCoder(
- EXTERNAL_CODECS_LOC_VARS
- k_BCJ_X86, coder, false));
- if (!coder)
- return E_NOTIMPL;
+ CFilterCoder *coderSpec = new CFilterCoder;
+ CMyComPtr<ICompressCoder> 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<ICompressSetDecoderProperties2> 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<ISequentialInStream> 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
index 36aeb2b1..2ccaaf65 100755..100644
--- 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<ISequentialInStream> _filterInStream;
CMyComPtr<ISequentialInStream> _codecInStream;
CMyComPtr<ISequentialInStream> _decoderInStream;
+ NCompress::NLzma::CDecoder *_lzmaDecoder;
+
public:
+ CMyComPtr<IInStream> 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
index 4058bd2a..868ca6cb 100755..100644
--- 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<ICompressProgressInfo> 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(&currentTotalSize));
+ lps->InSize = curTotalPacked;
+ lps->OutSize = curTotalUnpacked;
+ if (_archive.IsSolid)
+ lps->OutSize += _archive.Decoder.StreamPos;
+
+ curPacked = 0;
+ curUnpacked = 0;
+ RINOK(lps->SetCur());
+
+ // RINOK(extractCallback->SetCompleted(&currentTotalSize));
CMyComPtr<ISequentialOutStream> 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
index 6de493df..1eb8b731 100755..100644
--- 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<IInStream> _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
index 40756008..71791c03 100755..100644
--- 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_";
+
+#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
+
+
+/* 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
-Byte CInArchive::ReadByte()
+ 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. */
+
+
+enum
{
- if (_posInData >= _size)
- throw 1;
- return _data[_posInData++];
+ 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
+
+ // 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
+
+ // 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
+
+ EW_SECTIONSET, // Get*, Set*
+ EW_INSTTYPESET, // InstTypeSetText, InstTypeGetText, SetCurInstType, GetCurInstType
+
+ // 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
+
+ // The following IDs are not IDs in real order.
+ // We just need some IDs to translate eny extended layout to main layout.
+
+ EW_LOG, // LogSet, LogText
+
+ // Park
+ EW_FINDPROC, // FindProc
+
+ EW_GETFONTVERSION, // GetFontVersion
+ EW_GETFONTNAME, // GetFontName
+
+ kNumCmds
+};
+
+static const unsigned kNumAdditionalParkCmds = 3;
+
+struct CCommandInfo
+{
+ Byte NumParams;
+};
+
+static const CCommandInfo k_Commands[kNumCmds] =
+{
+ { 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
+
+ { 2 }, // "Log" }, // LogSet, LogText
+ // Park
+ { 2 }, // "FindProc" },
+ { 2 }, // "GetFontVersion" },
+ { 2 }, // "GetFontName" }
+};
+
+#ifdef NSIS_SCRIPT
+
+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[] =
+{
+ "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 void UIntToString(AString &s, UInt32 v)
+{
+ char sz[16];
+ ConvertUInt32ToString(v, sz);
+ s += sz;
}
-UInt32 CInArchive::ReadUInt32()
+#ifdef NSIS_SCRIPT
+
+void CInArchive::Add_UInt(UInt32 v)
{
- UInt32 value = 0;
- for (int i = 0; i < 4; i++)
- value |= ((UInt32)(ReadByte()) << (8 * i));
- return value;
+ char sz[16];
+ ConvertUInt32ToString(v, sz);
+ Script += sz;
}
-void CInArchive::ReadBlockHeader(CBlockHeader &bh)
+static void Add_SignedInt(CDynLimBuf &s, Int32 v)
{
- bh.Offset = ReadUInt32();
- bh.Num = ReadUInt32();
+ char sz[32];
+ ConvertInt64ToString(v, sz);
+ s += sz;
}
-#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
+static void Add_Hex(CDynLimBuf &s, UInt32 v)
+{
+ char sz[16];
+ sz[0] = '0';
+ sz[1] = 'x';
+ ConvertUInt32ToHex(v, sz + 2);
+ s += sz;
+}
-static int CompareItems(void *const *p1, void *const *p2, void * /* param */)
+static UInt32 GetUi16Str_Len(const Byte *p)
{
- const CItem &i1 = **(CItem **)p1;
- const CItem &i2 = **(CItem **)p2;
- RINOZ(MyCompare(i1.Pos, i2.Pos));
- if (i1.IsUnicode)
+ const Byte *pp = p;
+ for (; *pp != 0 || *(pp + 1) != 0; pp += 2);
+ return (UInt32)((pp - p) >> 1);
+}
+
+void CInArchive::AddLicense(UInt32 param, Int32 langID)
+{
+ Space();
+ if (param >= NumStringChars ||
+ param + 1 >= NumStringChars)
+ {
+ Script += kErrorStr;
+ return;
+ }
+ strUsed[param] = 1;
+
+ 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;
+ }
+ }
+ }
+ AString fileName = "[LICENSE]";
+ if (langID >= 0)
+ {
+ fileName += "\\license-";
+ // LangId_To_String(fileName, langID);
+ UIntToString(fileName, langID);
+ }
+ else if (++_numRootLicenses > 1)
{
- RINOZ(i1.PrefixU.Compare(i2.PrefixU));
- RINOZ(i1.NameU.Compare(i2.NameU));
+ 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
{
- RINOZ(i1.PrefixA.Compare(i2.PrefixA));
- RINOZ(i1.NameA.Compare(i2.NameA));
+ sz += 2;
+ UInt32 len = GetUi16Str_Len(sz);
+ lic.Size = len * 2;
+ if (isRTF)
+ {
+ 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;
+ }
}
- return 0;
}
-static AString UIntToString(UInt32 v)
+#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[] =
{
- char sz[32];
- ConvertUInt64ToString(v, sz);
- return sz;
+ "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)
+{
+ if (index < 20)
+ {
+ if (index >= 10)
+ {
+ res += 'R';
+ index -= 10;
+ }
+ UIntToString(res, index);
+ }
+ else
+ {
+ unsigned numInternalVars = GET_NUM_INTERNAL_VARS;
+ if (index < numInternalVars)
+ {
+ if (IsNsis225 && index >= kVar_EXEPATH)
+ index += 2;
+ res += kVarStrings[index - 20];
+ }
+ else
+ {
+ res += '_';
+ UIntToString(res, index - numInternalVars);
+ res += '_';
+ }
+ }
}
-static AString IntToString(Int32 v)
+void CInArchive::GetVar(AString &res, UInt32 index)
{
- char sz[32];
- ConvertInt64ToString(v, sz);
- return sz;
+ res += '$';
+ GetVar2(res, index);
+}
+
+#ifdef NSIS_SCRIPT
+
+void CInArchive::Add_Var(UInt32 index)
+{
+ _tempString_for_GetVar.Empty();
+ GetVar(_tempString_for_GetVar, index);
+ Script += _tempString_for_GetVar;
+}
+
+void CInArchive::AddParam_Var(UInt32 index)
+{
+ Space();
+ Add_Var(index);
+}
+
+void CInArchive::AddParam_UInt(UInt32 value)
+{
+ Space();
+ Add_UInt(value);
+}
+
+#endif
+
+
+#define NS_CODE_SKIP 252
+#define NS_CODE_VAR 253
+#define NS_CODE_SHELL 254
+#define NS_CODE_LANG 255
+
+#define NS_3_CODE_LANG 1
+#define NS_3_CODE_SHELL 2
+#define NS_3_CODE_VAR 3
+#define NS_3_CODE_SKIP 4
+
+#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)
+{
+ for (;;)
+ {
+ unsigned c16 = Get16(p16); p16 += 2;
+ unsigned c = (Byte)(*p8++);
+ if (c16 != c)
+ return false;
+ if (c == 0)
+ return true;
+ }
+}
+
+void CInArchive::GetShellString(AString &s, unsigned index1, unsigned index2)
+{
+ // zeros are not allowed here.
+ // if (index1 == 0 || index2 == 0) throw 333;
+
+ if ((index1 & 0x80) != 0)
+ {
+ 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
+ {
+ 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;
+ }
+
+ 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
+
+void CInArchive::Add_LangStr_Simple(UInt32 id)
+{
+ Script += "LSTR_";
+ Add_UInt(id);
+}
+
+#endif
+
+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)
+{
+ Raw_AString.Empty();
+
+ if (NsisType != k_NsisType_Nsis3)
+ {
+ for (;;)
+ {
+ 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;
+ }
+ }
+
+ // NSIS-3 ANSI
+ for (;;)
+ {
+ Byte c = *s++;
+ if (c <= NS_3_CODE_SKIP)
+ {
+ if (c == 0)
+ return;
+ Byte c0 = *s++;
+ if (c0 == 0)
+ return;
+ if (c != NS_3_CODE_SKIP)
+ {
+ Byte c1 = *s++;
+ if (c1 == 0)
+ return;
+
+ if (c == NS_3_CODE_SHELL)
+ GetShellString(Raw_AString, c0, c1);
+ else
+ {
+ 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);
+ }
+ continue;
+ }
+ c = c0;
+ }
+ Raw_AString += (char)c;
+ }
+}
+
+#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))
+ {
+ 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(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;
+ }
+ 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)
+ {
+ 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;
+ }
+ }
}
-AString CInArchive::ReadStringA(UInt32 pos) const
+#endif
+
+void CInArchive::GetNsisString_Unicode_Raw(const Byte *p)
{
- AString s;
- if (pos >= _size)
- return IntToString((Int32)pos);
- UInt32 offset = GetOffset() + _stringsPos + pos;
+ 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 (;;)
{
- if (offset >= _size)
- break; // throw 1;
- char c = _data[offset++];
+ unsigned c = Get16(p);
+ p += 2;
+ if (c > NS_3_CODE_SKIP)
+ {
+ Raw_UString += (wchar_t)c;
+ continue;
+ }
if (c == 0)
break;
- s += c;
+
+ 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;
}
- return s;
}
-UString CInArchive::ReadStringU(UInt32 pos) const
+#ifdef NSIS_SCRIPT
+
+static const Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+void CInArchive::GetNsisString_Unicode(AString &res, const Byte *p)
{
- 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));
+ unsigned c = Get16(p);
+ p += 2;
if (c == 0)
break;
- s += c;
+ 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);
}
- return s;
}
-/*
-static AString ParsePrefix(const AString &prefix)
+#endif
+
+void CInArchive::ReadString2_Raw(UInt32 pos)
{
- AString res = prefix;
- if (prefix.Length() >= 3)
+ Raw_AString.Empty();
+ Raw_UString.Empty();
+ if ((Int32)pos < 0)
+ Add_LangStr(Raw_AString, -((Int32)pos + 1));
+ else if (pos >= NumStringChars)
{
- 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);
+ Raw_AString += kErrorStr;
+ // UIntToString(Raw_AString, pos);
}
- return res;
+ 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;
}
-*/
-#define SYSREGKEY "Software\\Microsoft\\Windows\\CurrentVersion"
+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;
+}
-/*
-# 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
-*/
+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;
+}
-struct CCommandPair
+static const char *g_WinAttrib[] =
{
- int NumParams;
- const char *Name;
+ "READONLY"
+ , "HIDDEN"
+ , "SYSTEM"
+ , NULL
+ , "DIRECTORY"
+ , "ARCHIVE"
+ , "DEVICE"
+ , "NORMAL"
+ , "TEMPORARY"
+ , "SPARSE_FILE"
+ , "REPARSE_POINT"
+ , "COMPRESSED"
+ , "OFFLINE"
+ , "NOT_CONTENT_INDEXED"
+ , "ENCRYPTED"
+ , NULL
+ , "VIRTUAL"
};
-enum
+#define FLAGS_DELIMITER '|'
+
+static void FlagsToString2(CDynLimBuf &s, const char **table, unsigned num, UInt32 flags)
{
- // 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, val1<val2, val1>val2, unsigned?]
- EW_INTOP, // IntOp: 4 [output, input1, input2, op] where op: 0=add, 1=sub, 2=mul, 3=div, 4=bor, 5=band, 6=bxor, 7=bnot input1, 8=lnot input1, 9=lor, 10=land], 11=1%2
-
- // 30
- EW_INTFMT, // IntFmt: [output, format, input]
- EW_PUSHPOP, // Push/Pop/Exchange: 3 [variable/string, ?pop:push, ?exch]
- EW_FINDWINDOW, // FindWindow: 5, [outputvar, window class,window name, window_parent, window_after]
- EW_SENDMESSAGE, // SendMessage: 6 [output, hwnd, msg, wparam, lparam, [wparamstring?1:0 | lparamstring?2:0 | timeout<<2]
- EW_ISWINDOW, // IsWindow: 3 [hwnd, jump_if_window, jump_if_notwindow]
- EW_GETDLGITEM, // GetDlgItem: 3: [outputvar, dialog, item_id]
- EW_SETCTLCOLORS, // SerCtlColors: 3: [hwnd, pointer to struct colors]
- EW_SETBRANDINGIMAGE, // SetBrandingImage: 1: [Bitmap file]
- EW_CREATEFONT, // CreateFont: 5: [handle output, face name, height, weight, flags]
- EW_SHOWWINDOW, // ShowWindow: 2: [hwnd, show state]
-
- // 40
- EW_SHELLEXEC, // ShellExecute program: 4, [shell action, complete commandline, parameters, showwindow]
- EW_EXECUTE, // Execute program: 3,[complete command line,waitflag,>=0?output errorcode]
- EW_GETFILETIME, // GetFileTime; 3 [file highout lowout]
- EW_GETDLLVERSION, // GetDLLVersion: 3 [file highout lowout]
- EW_REGISTERDLL, // Register DLL: 3,[DLL file name, string ptr of function to call, text to put in display (<0 if none/pass parms), 1 - no unload, 0 - unload]
- EW_CREATESHORTCUT, // Make Shortcut: 5, [link file, target file, parameters, icon file, iconindex|show mode<<8|hotkey<<16]
- EW_COPYFILES, // CopyFiles: 3 [source mask, destination location, flags]
- EW_REBOOT, // Reboot: 0
- EW_WRITEINI, // Write INI String: 4, [Section, Name, Value, INI File]
- EW_READINISTR, // ReadINIStr: 4 [output, section, name, ini_file]
-
- // 50
- EW_DELREG, // DeleteRegValue/DeleteRegKey: 4, [root key(int), KeyName, ValueName, delkeyonlyifempty]. ValueName is -1 if delete key
- EW_WRITEREG, // Write Registry value: 5, [RootKey(int),KeyName,ItemName,ItemData,typelen]
- // typelen=1 for str, 2 for dword, 3 for binary, 0 for expanded str
- EW_READREGSTR, // ReadRegStr: 5 [output, rootkey(int), keyname, itemname, ==1?int::str]
- EW_REGENUM, // RegEnum: 5 [output, rootkey, keyname, index, ?key:value]
- EW_FCLOSE, // FileClose: 1 [handle]
- EW_FOPEN, // FileOpen: 4 [name, openmode, createmode, outputhandle]
- EW_FPUTS, // FileWrite: 3 [handle, string, ?int:string]
- EW_FGETS, // FileRead: 4 [handle, output, maxlen, ?getchar:gets]
- EW_FSEEK, // FileSeek: 4 [handle, offset, mode, >=0?positionoutput]
- EW_FINDCLOSE, // FindClose: 1 [handle]
-
- // 60
- EW_FINDNEXT, // FindNext: 2 [output, handle]
- EW_FINDFIRST, // FindFirst: 2 [filespec, output, handleoutput]
- EW_WRITEUNINSTALLER, // WriteUninstaller: 3 [name, offset, icon_size]
- EW_LOG, // LogText: 2 [0, text] / LogSet: [1, logstate]
- EW_SECTIONSET, // SectionSetText: 3: [idx, 0, text]
- // SectionGetText: 3: [idx, 1, output]
- // SectionSetFlags: 3: [idx, 2, flags]
- // SectionGetFlags: 3: [idx, 3, output]
- EW_INSTTYPESET, // InstTypeSetFlags: 3: [idx, 0, flags]
- // InstTypeGetFlags: 3: [idx, 1, output]
- // instructions not actually implemented in exehead, but used in compiler.
- EW_GETLABELADDR, // both of these get converted to EW_ASSIGNVAR
- EW_GETFUNCTIONADDR,
+ 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);
+}
- EW_LOCKWINDOW
+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"
};
-#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" }
+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"
};
-#endif
+#define MY__MB_ICONSTOP (1 << 4)
-static const char *kShellStrings[] =
+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)
{
- "",
- "",
-
- "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"
+ 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,
};
-static const int kNumShellStrings = sizeof(kShellStrings) / sizeof(kShellStrings[0]);
+// 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 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
+#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
*/
-static const char *kVarStrings[] =
+// 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[] =
{
- "CMDLINE",
- "INSTDIR",
- "OUTDIR",
- "EXEDIR",
- "LANGUAGE",
- "TEMP",
- "PLUGINSDIR",
- "EXEPATH", // test it
- "EXEFILE", // test it
- "HWNDPARENT",
- "_CLICK",
- "_OUTDIR"
+ "Text"
+ , "InstTypes"
+ , "Flags"
+ , "Code"
+ , "CodeSize"
+ , "Size" // size in KB
};
-static const int kNumVarStrings = sizeof(kVarStrings) / sizeof(kVarStrings[0]);
+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)
-static AString GetVar(UInt32 index)
+bool CInArchive::PrintSectionBegin(const CSection &sect, unsigned index)
{
- AString res = "$";
- if (index < 10)
- res += UIntToString(index);
- else if (index < 20)
+ AString name;
+ if (sect.Flags & SF_BOLD)
+ name += '!';
+ AString s2;
+ ReadString2(s2, sect.Name);
+ if (!IsInstaller)
{
- res += "R";
- res += UIntToString(index - 10);
+ if (!StringsAreEqualNoCase_Ascii(s2, "uninstall"))
+ name += "un.";
}
- else if (index < 20 + kNumVarStrings)
- res += kVarStrings[index - 20];
+ 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)
{
- res += "[";
- res += UIntToString(index);
- res += "]";
+ // probably we must show AddSize, only if there is additional size.
+ Tab();
+ AddCommentAndString("AddSize");
+ AddParam_UInt(sect.SizeKB);
+ AddLF();
}
- return res;
+
+ 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;
}
-#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
+void CInArchive::PrintSectionEnd()
+{
+ AddStringLF("SectionEnd");
+ AddLF();
+}
+
+// static const unsigned kOnFuncShift = 4;
-static AString GetShellString(int index)
+void CInArchive::ClearLangComment()
{
- AString res = "$";
- if (index < kNumShellStrings)
+ 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())
{
- const char *sz = kShellStrings[index];
- if (sz[0] != 0)
- return res + sz;
+ 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();
}
- res += "SHELL[";
- res += UIntToString(index);
- res += "]";
- return res;
+ AddLF();
}
-// Based on Dave Laundon's simplified process_string
-AString GetNsisString(const AString &s)
+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)
{
- AString res;
- for (int i = 0; i < s.Length();)
{
- unsigned char nVarIdx = s[i++];
- if (nVarIdx > NS_CODES_START && i + 2 <= s.Length())
+ UInt32 v = param & 0xF;
+ Script += " MB_";
+ if (v < ARRAY_SIZE(k_MB_Buttons))
+ Script += k_MB_Buttons[v];
+ else
{
- int nData = s[i++] & 0x7F;
- unsigned char c1 = s[i++];
- nData |= (((int)(c1 & 0x7F)) << 7);
+ 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 (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";
+ 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;
}
- else if (nVarIdx == NS_SKIP_CODE)
+
+ if (a >= EW_SECTIONSET && LogCmdIsEnabled)
{
- if (i < s.Length())
- res += s[i++];
+ if (a == EW_SECTIONSET)
+ return EW_LOG;
+ return a - 1;
}
- else // Normal char
- res += (char)nVarIdx;
+ if (a == EW_FPUTWS)
+ return EW_FINDPROC;
+ // if (a > EW_FPUTWS) return 0;
}
- return res;
+ return a;
}
-UString GetNsisString(const UString &s)
+void CInArchive::FindBadCmd(const CBlockHeader &bh, const Byte *p)
{
- UString res;
- for (int i = 0; i < s.Length();)
+ BadCmd = -1;
+
+ for (UInt32 kkk = 0; kkk < bh.Num; kkk++, p += kCmdSize)
{
- wchar_t nVarIdx = s[i++];
- if (nVarIdx > NS_UN_CODES_START && nVarIdx <= NS_UN_CODES_END)
+ 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)
{
- if (i == s.Length())
+ BadCmd = id;
+ continue;
+ }
+ for (i = 6; i != 0; i--)
+ {
+ UInt32 param = Get32(p + i * 4);
+ if (param != 0)
break;
- int nData = s[i++] & 0x7FFF;
+ }
+ if (id == EW_FINDPROC && i == 0)
+ {
+ BadCmd = id;
+ continue;
+ }
+ if (k_Commands[id].NumParams < i)
+ BadCmd = id;
+ }
+}
- 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";
+/* 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 if (nVarIdx == NS_UN_SKIP_CODE)
+ else
{
- if (i == s.Length())
- break;
- res += s[i++];
+ 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);
}
- else // Normal char
- res += (char)nVarIdx;
}
- return res;
}
-AString CInArchive::ReadString2A(UInt32 pos) const
+Int32 CInArchive::GetVarIndex(UInt32 strPos) const
{
- return GetNsisString(ReadStringA(pos));
+ 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);
}
-UString CInArchive::ReadString2U(UInt32 pos) const
+Int32 CInArchive::GetVarIndex(UInt32 strPos, UInt32 &resOffset) const
{
- return GetNsisString(ReadStringU(pos));
+ 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;
}
-AString CInArchive::ReadString2(UInt32 pos) const
+Int32 CInArchive::GetVarIndexFinished(UInt32 strPos, Byte endChar, UInt32 &resOffset) const
{
+ resOffset = 0;
+ Int32 varIndex = GetVarIndex(strPos);
+ if (varIndex < 0)
+ return varIndex;
if (IsUnicode)
- return UnicodeStringToMultiByte(ReadString2U(pos));
+ {
+ if (NumStringChars - strPos < 3 * 2)
+ return -1;
+ const Byte *p = _data + _stringsPos + strPos * 2;
+ if (Get16(p + 4) != endChar)
+ return -1;
+ resOffset = 3;
+ }
else
- return ReadString2A(pos);
+ {
+ if (NumStringChars - strPos < 4)
+ return -1;
+ const Byte *p = _data + _stringsPos + strPos;
+ if (p[3] != endChar)
+ return -1;
+ resOffset = 4;
+ }
+ return varIndex;
}
-AString CInArchive::ReadString2Qw(UInt32 pos) const
+bool CInArchive::IsVarStr(UInt32 strPos, UInt32 varIndex) const
{
- return "\"" + ReadString2(pos) + "\"";
+ if (varIndex > (UInt32)0x7FFF)
+ return false;
+ UInt32 resOffset;
+ return GetVarIndexFinished(strPos, 0, resOffset) == (Int32)varIndex;
}
-#define DEL_DIR 1
-#define DEL_RECURSE 2
-#define DEL_REBOOT 4
-// #define DEL_SIMPLE 8
+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')
-static const int kNumEntryParams = 6;
+// 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);
+}
-struct CEntry
+void CInArchive::SetItemName(CItem &item, UInt32 strPos)
{
- UInt32 Which;
- UInt32 Params[kNumEntryParams];
- AString GetParamsString(int numParams);
- CEntry()
+ ReadString2_Raw(strPos);
+ bool isAbs = IsAbsolutePathVar(strPos);
+ if (IsUnicode)
{
- Which = 0;
- for (UInt32 j = 0; j < kNumEntryParams; j++)
- Params[j] = 0;
+ 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;
+ }
+}
-AString CEntry::GetParamsString(int numParams)
+HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
{
- AString s;
- for (int i = 0; i < numParams; i++)
+ #ifdef NSIS_SCRIPT
+ CDynLimBuf &s = Script;
+
+ CObjArray<UInt32> labels;
+ labels.Alloc(bh.Num);
+ memset(labels, 0, bh.Num * sizeof(UInt32));
+
{
- s += " ";
- UInt32 v = Params[i];
- if (v > 0xFFF00000)
- s += IntToString((Int32)Params[i]);
+ 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
- s += UIntToString(Params[i]);
+ {
+
+ 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();
+ }
+ }
}
- return s;
-}
-#ifdef NSIS_SCRIPT
+ CObjArray<CSection> Sections;
-static AString GetRegRootID(UInt32 val)
-{
- const char *s;
- switch(val)
{
- case 0: s = "SHCTX"; break;
- case 0x80000000: s = "HKCR"; break;
- case 0x80000001: s = "HKCU"; break;
- case 0x80000002: s = "HKLM"; break;
- case 0x80000003: s = "HKU"; break;
- case 0x80000004: s = "HKPD"; break;
- case 0x80000005: s = "HKCC"; break;
- case 0x80000006: s = "HKDD"; break;
- case 0x80000050: s = "HKPT"; break;
- case 0x80000060: s = "HKPN"; break;
- default:
- return UIntToString(val); break;
+ 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 &section = Sections[i];
+ section.Parse(p);
+ if (section.StartCmdIndex < bh.Num)
+ labels[section.StartCmdIndex] |= CMD_REF_Section;
+ }
+ }
}
- return s;
-}
-#endif
+ #endif
-HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
-{
- _posInData = bh.Offset + GetOffset();
- AString prefixA;
- UString prefixU;
- for (UInt32 i = 0; i < bh.Num; i++)
+ 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)
{
- CEntry e;
- e.Which = ReadUInt32();
- for (UInt32 j = 0; j < kNumEntryParams; j++)
- e.Params[j] = ReadUInt32();
+ 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
- if (e.Which != EW_PUSHPOP && e.Which < sizeof(kCommandPairs) / sizeof(kCommandPairs[0]))
+
+ bool IsSectionGroup = false;
+ while (curSectionIndex < bhSections.Num)
{
- const CCommandPair &pair = kCommandPairs[e.Which];
- Script += pair.Name;
+ const CSection &sect = 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 (e.Which)
+ switch (commandId)
{
case EW_CREATEDIR:
{
- if (IsUnicode)
+ bool isSetOutPath = (params[1] != 0);
+
+ if (isSetOutPath)
{
- prefixU.Empty();
- prefixU = ReadString2U(e.Params[0]);
+ 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);
+ }
}
- else
+
+ #ifdef NSIS_SCRIPT
+ s += isSetOutPath ? "SetOutPath" : "CreateDirectory";
+ AddParam(params[0]);
+ #endif
+
+ break;
+ }
+
+
+ case EW_ASSIGNVAR:
+ {
+ if (params[0] == spec_outdir_VarIndex)
{
- prefixA.Empty();
- prefixA = ReadString2A(e.Params[0]);
+ 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
- Script += " ";
- if (IsUnicode)
- Script += UnicodeStringToMultiByte(prefixU);
- else
- Script += prefixA;
+
+ 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;
- item.IsUnicode = IsUnicode;
- if (IsUnicode)
+ 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
+
{
- item.PrefixU = prefixU;
- item.NameU = ReadString2U(e.Params[1]);
+ 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);
+ }
}
- else
+
{
- item.PrefixA = prefixA;
- item.NameA = ReadString2A(e.Params[1]);
+ 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;
+ }
}
- /* 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)
+
+ 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
{
- /*
- if (item.Pos == Items.Back().Pos)
- continue;
- */
+ // 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;
+ }
+ }
+ }
+ }
}
- Items.Add(item);
- #ifdef NSIS_SCRIPT
- Script += " ";
+ /* UInt32 allowIgnore = params[5]; */
+ break;
+ }
- if (IsUnicode)
- Script += UnicodeStringToMultiByte(item.NameU);
- else
- Script += item.NameA;
+ 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 &sect = 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:
{
- Script += " ";
- Script += ReadString2(e.Params[0]);
- Script += " ";
- Script += UIntToString(e.Params[1]);
+ AddParam(params[0]);
break;
}
- case EW_SETFILEATTRIBUTES:
+
+ case EW_CHDETAILSVIEW:
{
- Script += " ";
- Script += ReadString2(e.Params[0]);
- Script += " ";
- Script += UIntToString(e.Params[1]);
+ 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:
{
- Script += " ";
- Script += ReadString2(e.Params[0]);
- Script += " ";
- Script += UIntToString(e.Params[1]);
- Script += " ";
- Script += UIntToString(e.Params[2]);
+ AddParam(params[0]);
+ Add_GotoVars2(&params[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(&params[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:
{
- Script += " ";
- Script += ReadString2(e.Params[0]);
- Script += " ";
- Script += ReadString2(e.Params[1]);
- Script += " ";
- Script += UIntToString(e.Params[2]);
+ 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:
{
- Script += " ";
- Script += ReadString2(e.Params[0]);
- Script += " ";
- Script += ReadString2(e.Params[1]);
- Script += " ";
- Script += UIntToString(e.Params[2]);
+ if (params[2] == 0)
+ s += " /SHORT";
+ AddParam_Var(params[1]);
+ AddParam(params[0]);
break;
}
+
case EW_SEARCHPATH:
+ case EW_STRLEN:
{
- Script += " ";
- Script += ReadString2(e.Params[0]);
- Script += " ";
- Script += ReadString2(e.Params[1]);
+ AddParam_Var(params[0]);
+ AddParam(params[1]);
break;
}
+
case EW_GETTEMPFILENAME:
{
- AString s;
- Script += " ";
- Script += ReadString2(e.Params[0]);
- Script += " ";
- Script += ReadString2(e.Params[1]);
+ AddParam_Var(params[0]);
+ AString temp;
+ ReadString2(temp, params[1]);
+ if (temp != "$TEMP")
+ SpaceQuStr(temp);
break;
}
case EW_DELETEFILE:
{
- UInt64 flag = e.Params[1];
- if (flag != 0)
+ 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]);
{
- Script += " ";
- if (flag == DEL_REBOOT)
- Script += "/REBOOTOK";
- else
- Script += UIntToString(e.Params[1]);
+ UInt32 buttonID = (params[0] >> 21); // NSIS 2.06+
+ if (buttonID != 0)
+ {
+ s += " /SD";
+ Add_ButtonID(buttonID);
+ }
}
- Script += " ";
- Script += ReadString2(e.Params[0]);
+ 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:
{
- UInt64 flag = e.Params[1];
- if (flag != 0)
+ 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(&params[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() == '%')
{
- if ((flag & DEL_REBOOT) != 0)
- Script += " /REBOOTOK";
- if ((flag & DEL_RECURSE) != 0)
- Script += " /r";
+ temp.DeleteBack();
+ temp.Delete(0);
}
- Script += " ";
- Script += ReadString2(e.Params[0]);
+ SpaceQuStr(temp);
break;
}
- case EW_STRLEN:
+
+ case EW_INTCMP:
{
- Script += " ";
- Script += GetVar(e.Params[0]);;
- Script += " ";
- Script += ReadString2Qw(e.Params[1]);
+ 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_ASSIGNVAR:
+
+ case EW_INTOP:
{
- 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())
+ 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;
+ }
+
+ 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
+ {
+ 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)
{
- Script += " ";
- Script += startOffset;
+ 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_STRCMP:
+
+ case EW_FINDWINDOW:
{
- Script += " ";
+ AddParam_Var(params[0]);
+ AddParam(params[1]);
+ AddOptionalParams(params + 2, 3);
+ break;
+ }
- Script += " ";
- Script += ReadString2Qw(e.Params[0]);
+ 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);
- Script += " ";
- Script += ReadString2Qw(e.Params[1]);
+ 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);
+ }
- for (int j = 2; j < 5; j++)
+ if ((Int32)params[0] >= 0)
+ AddParam_Var(params[0]);
+
+ spec >>= 2;
+ if (spec != 0)
{
- Script += " ";
- Script += UIntToString(e.Params[j]);
+ s += " /TIMEOUT=";
+ Add_UInt(spec);
}
break;
}
- case EW_INTCMP:
+
+ case EW_ISWINDOW:
{
- if (e.Params[5] != 0)
- Script += "U";
+ AddParam(params[0]);
+ Add_GotoVars2(&params[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;
+ }
- Script += " ";
- Script += ReadString2(e.Params[0]);
- Script += " ";
- Script += ReadString2(e.Params[1]);
+ const Byte *p2 = _data + bhCtlColors.Offset + offset;
+ CNsis_CtlColors colors;
+ colors.Parse(p2);
- for (int i = 2; i < 5; i++)
+ 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)
{
- Script += " ";
- Script += UIntToString(e.Params[i]);
+ 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_INTOP:
+
+ case EW_SETBRANDINGIMAGE:
{
- 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;
- }
+ 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
{
- Script += p1;
- Script += " ";
- Script += op;
- Script += " ";
- Script += ReadString2(e.Params[2]);
+ 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_PUSHPOP:
+ case EW_SHELLEXEC:
{
- int isPop = (e.Params[1] != 0);
- if (isPop)
+ AddParams(params, 2);
+ if (params[2] != 0 || params[3] != MY__SW_SHOWNORMAL)
{
- Script += "Pop";
- Script += " ";
- Script += GetVar(e.Params[0]);;
+ 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
{
- int isExch = (e.Params[2] != 0);
- if (isExch)
+ if (func == "DllUnregisterServer")
{
- Script += "Exch";
+ s += "UnRegDLL";
+ printFunc = false;
}
else
{
- Script += "Push";
- Script += " ";
- Script += ReadString2(e.Params[0]);
+ s += "RegDLL";
+ if (func == "DllRegisterServer")
+ printFunc = false;
}
+ AddParam(params[0]);
}
+ if (printFunc)
+ SpaceQuStr(func);
break;
}
- case EW_SENDMESSAGE:
+ case EW_CREATESHORTCUT:
{
- // 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]);
+ 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);
- Script += " ";
- // if (spec & 2)
- Script += IntToString(e.Params[4]);
- // else
- // Script += ReadString2(e.Params[4]);
+ UInt32 modKey = spec >> 24;
+ UInt32 key = (spec >> 16) & 0xFF;
- if ((Int32)e.Params[0] >= 0)
+ if (modKey == 0 && key == 0)
{
- Script += " ";
- Script += GetVar(e.Params[1]);
+ if (numParams < 6)
+ break;
+ Space();
+ AddQuotes();
}
-
- spec >>= 2;
- if (spec != 0)
+ else
{
- Script += " /TIMEOUT=";
- Script += IntToString(spec);
+ 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_GETDLGITEM:
+ case EW_COPYFILES:
{
- Script += " ";
- Script += GetVar(e.Params[0]);;
- Script += " ";
- Script += ReadString2(e.Params[1]);
- Script += " ";
- Script += ReadString2(e.Params[2]);
+ 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_REGISTERDLL:
+ case EW_REBOOT:
{
- Script += " ";
- Script += ReadString2(e.Params[0]);
- Script += " ";
- Script += ReadString2(e.Params[1]);
- Script += " ";
- Script += UIntToString(e.Params[2]);
+ if (params[0] != 0xbadf00d)
+ s += " ; Corrupted ???";
+ else if (kkk + 1 < bh.Num && GetCmd(Get32(p + kCmdSize)) == EW_QUIT)
+ endCommentIndex = kkk + 2;
break;
}
- case EW_CREATESHORTCUT:
+ case EW_WRITEINI:
{
- AString s;
-
- Script += " ";
- Script += ReadString2Qw(e.Params[0]);
+ 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;
+ }
- Script += " ";
- Script += ReadString2Qw(e.Params[1]);
+ case EW_READINISTR:
+ {
+ AddParam_Var(params[0]);
+ AddParam(params[3]); // FileName
+ AddParams(params +1, 2); // Section, EntryName
+ break;
+ }
- for (int j = 2; j < 5; j++)
+ case EW_DELREG:
+ {
+ // NSIS 2.00 used another scheme!
+
+ if (params[4] == 0)
+ s += "Value";
+ else
{
- Script += " ";
- Script += UIntToString(e.Params[j]);
+ s += "Key";
+ if (params[4] & 2)
+ s += " /ifempty";
}
+ AddRegRoot(params[1]);
+ AddParam(params[2]);
+ AddOptionalParam(params[3]);
break;
}
- /*
- case EW_DELREG:
+ case EW_WRITEREG:
{
- AString keyName, valueName;
- keyName = ReadString2(e.Params[1]);
- bool isValue = (e.Params[2] != -1);
- if (isValue)
+ const char *s2 = 0;
+ switch (params[4])
{
- valueName = ReadString2(e.Params[2]);
- Script += "Key";
+ 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
- Script += "Value";
- Script += " ";
- Script += UIntToString(e.Params[0]);
- Script += " ";
- Script += keyName;
- if (isValue)
{
- Script += " ";
- Script += valueName;
+ // 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";
+ }
}
- Script += " ";
- Script += UIntToString(e.Params[3]);
break;
}
- */
- case EW_WRITEREG:
+ case EW_READREGSTR:
+ {
+ s += (params[4] == 1) ? "DWORD" : "Str";
+ AddParam_Var(params[0]);
+ AddRegRoot(params[1]);
+ AddParams(params + 2, 2);
+ break;
+ }
+
+ case EW_REGENUM:
+ {
+ 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:
{
- AString s;
- switch(e.Params[4])
+ 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)
{
- 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;
+ Space();
+ s += cc;
+ break;
}
- Script += s;
- Script += " ";
- Script += GetRegRootID(e.Params[0]);
- Script += " ";
- AString keyName, valueName;
- keyName = ReadString2Qw(e.Params[1]);
- Script += keyName;
- Script += " ";
+ 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";
- valueName = ReadString2Qw(e.Params[2]);
- Script += valueName;
- Script += " ";
+ 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;
+ }
- valueName = ReadString2Qw(e.Params[3]);
- Script += valueName;
- Script += " ";
+ case EW_FPUTS:
+ case EW_FPUTWS:
+ {
+ 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_FGETS:
+ case EW_FGETWS:
+ {
+ 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_WRITEUNINSTALLER:
+ case EW_FSEEK:
{
- Script += " ";
- Script += ReadString2(e.Params[0]);
- for (int j = 1; j < 3; j++)
+ 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)
{
- Script += " ";
- Script += UIntToString(e.Params[j]);
+ if (params[3] == 0) s += " SET"; // FILE_BEGIN
+ AddParam_Var(params[1]);
}
break;
}
- default:
+ case EW_FINDNEXT:
+ {
+ AddParam_Var(params[1]);
+ AddParam_Var(params[0]);
+ break;
+ }
+
+ case EW_FINDFIRST:
+ {
+ AddParam_Var(params[1]);
+ AddParam_Var(params[0]);
+ AddParam(params[2]);
+ break;
+ }
+
+ case EW_LOG:
{
- int numParams = kNumEntryParams;
- if (e.Which < sizeof(kCommandPairs) / sizeof(kCommandPairs[0]))
+ if (params[0] != 0)
{
- const CCommandPair &pair = kCommandPairs[e.Which];
- // Script += pair.Name;
- numParams = pair.NumParams;
+ s += "Set ";
+ s += (params[1] == 0) ? "off" : "on";
}
else
{
- Script += "Unknown";
- Script += UIntToString(e.Which);
+ s += "Text";
+ AddParam(params[1]);
}
- Script += e.GetParamsString(numParams);
+ }
+
+ case EW_SECTIONSET:
+ {
+ if ((Int32)params[2] >= 0)
+ {
+ 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
+ }
+ break;
+ }
+
+ case EW_INSTTYPESET:
+ {
+ 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 (params[2] == 0)
+ s2 = "GetCurInstType";
+ else
+ {
+ s2 = "SetCurInstType";
+ numQwParams = 1;
+ }
+ }
+ s += s2;
+ AddParams(params, numQwParams);
+ if (params[2] == 0)
+ AddParam_Var(params[1]);
+ break;
+ }
+
+ case EW_LOCKWINDOW:
+ {
+ s += (params[0] == 0) ? " on" : " off";
+ break;
+ }
+
+ case EW_FINDPROC:
+ {
+ AddParam_Var(params[0]);
+ AddParam(params[1]);
+ break;
+ }
+
+ default:
+ {
+ numSkipParams = 0;
}
#endif
}
+
#ifdef NSIS_SCRIPT
- Script += kCrLf;
+
+ unsigned numParams = kNumCommandParams;
+
+ 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);
+ }
+ }
+
+ NewLine();
+
#endif
}
+ #ifdef NSIS_SCRIPT
+
+ if (sectionIsOpen)
+ {
+ if (curSectionIndex < bhSections.Num)
+ {
+ const CSection &sect = Sections[curSectionIndex];
+ if (sect.StartCmdIndex + sect.NumCommands + 1 == kkk)
+ {
+ PrintSectionEnd();
+ sectionIsOpen = false;
+ // lastSectionEndCmd = kkk;
+ curSectionIndex++;
+ }
+ }
+ }
+
+ while (curSectionIndex < bhSections.Num)
+ {
+ const CSection &sect = 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;
+}
+
+HRESULT CInArchive::SortItems()
+{
{
- Items.Sort(CompareItems, 0);
- int i;
- // if (IsSolid)
- for (i = 0; i + 1 < Items.Size();)
+ Items.Sort(CompareItems, (void *)this);
+ unsigned i;
+
+ for (i = 0; i + 1 < Items.Size(); i++)
{
- 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);
+ const CItem &i1 = Items[i];
+ const CItem &i2 = Items[i + 1];
+ if (i1.Pos != i2.Pos)
+ continue;
+
+ if (IsUnicode)
+ {
+ if (i1.NameU != i2.NameU) continue;
+ if (i1.Prefix != i2.Prefix)
+ {
+ if (i1.Prefix < 0 || i2.Prefix < 0) continue;
+ if (UPrefixes[i1.Prefix] != UPrefixes[i2.Prefix]) continue;
+ }
+ }
else
- i++;
+ {
+ if (i1.NameA != i2.NameA) continue;
+ if (i1.Prefix != i2.Prefix)
+ {
+ if (i1.Prefix < 0 || i2.Prefix < 0) continue;
+ if (APrefixes[i1.Prefix] != APrefixes[i2.Prefix]) continue;
+ }
+ }
+ Items.Delete(i + 1);
+ i--;
}
+
for (i = 0; i < Items.Size(); i++)
{
CItem &item = Items[i];
UInt32 curPos = item.Pos + 4;
- for (int nextIndex = i + 1; nextIndex < Items.Size(); nextIndex++)
+ for (unsigned nextIndex = i + 1; nextIndex < Items.Size(); nextIndex++)
{
UInt32 nextPos = Items[nextIndex].Pos;
if (curPos <= nextPos)
{
- item.EstimatedSizeIsDefined = true;
+ item.EstimatedSize_Defined = true;
item.EstimatedSize = nextPos - curPos;
break;
}
}
}
+
if (!IsSolid)
{
for (i = 0; i < Items.Size(); i++)
{
CItem &item = Items[i];
RINOK(_stream->Seek(GetPosOfNonSolidItem(i), STREAM_SEEK_SET, NULL));
- const UInt32 kSigSize = 4 + 1 + 5;
+ 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 & 0x80000000) != 0)
+ if ((size & kMask_IsCompressed) != 0)
{
item.IsCompressed = true;
- // is compressed;
- size &= ~0x80000000;
+ size &= ~kMask_IsCompressed;
if (Method == NMethodType::kLZMA)
{
if (processedSize < 9)
return S_FALSE;
+ /*
if (FilterFlag)
item.UseFilter = (sig[4] != 0);
- item.DictionarySize = Get32(sig + 5 + (FilterFlag ? 1 : 0));
+ */
+ item.DictionarySize = Get32(sig + 4 + 1 + (FilterFlag ? 1 : 0));
}
}
else
{
item.IsCompressed = false;
item.Size = size;
- item.SizeIsDefined = true;
+ item.Size_Defined = true;
}
item.CompressedSize = size;
- item.CompressedSizeIsDefined = true;
+ item.CompressedSize_Defined = true;
}
}
}
return S_OK;
}
+// 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.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);
+ // ???? 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;
- UInt32 pos = GetOffset() + _stringsPos;
- int numZeros0 = 0;
- int numZeros1 = 0;
- int i;
- const int kBlockSize = 256;
- for (i = 0; i < kBlockSize; i++)
- {
- if (pos >= _size || pos + 1 >= _size)
- break;
- char c0 = _data[pos++];
- char c1 = _data[pos++];
- wchar_t c = (c0 | ((wchar_t)c1 << 8));
+ if (_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 (c >= NS_UN_CODES_START && c < NS_UN_CODES_END)
+ }
+
+ 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)
{
- if (pos >= _size || pos + 1 >= _size)
- break;
- pos += 2;
- numZeros1++;
+ 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);
+ }
+ }
+
+ unsigned paramsOffset = 4 + 8 * 8;
+ if (bhPages.Offset == 276)
+ paramsOffset -= 8;
+
+ const Byte *p2 = p + paramsOffset;
+
+ {
+ 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();
+ }
+ }
+
+
+ {
+ 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)
+ {
+ Add_ColorParam(bg_color1);
+ Add_ColorParam(bg_color2);
+ if (bg_textcolor != (UInt32)(Int32)-1)
+ Add_ColorParam(bg_textcolor);
+ }
+ AddLF();
+ }
+ }
+
+ {
+ 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();
+ }
+ }
+
+ 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();
+ }
+
+ 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();
+
+ if (licenseLangIndex >= 0)
+ {
+ for (UInt32 i = 0; i < bhLangTables.Num; i++)
+ {
+ const Byte *p = _data + bhLangTables.Offset + langtable_size * i;
+ LANGID langID = Get16(p);
+ UInt32 val = Get32(p + 10 + licenseLangIndex * 4);
+ if (val != 0)
+ {
+ Script += "LicenseLangString ";
+ Add_LangStr_Simple(licenseLangIndex);
+ AddParam_UInt(langID);
+ AddLicense(val, langID);
+ noParseStringIndexes.AddToUniqueSorted(val);
+ NewLine();
+ }
+ }
+ 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;
+ {
+ UInt32 v = Get32(p + 10 + 0 * 4);
+ if (v != 0 && (langID == 1033 || brandingText == 0))
+ brandingText = v;
+ }
+ {
+ UInt32 v = Get32(p + 10 + 1 * 4);
+ if (v != 0 && (langID == 1033 || caption == 0))
+ caption = v;
+ }
+ {
+ UInt32 v = Get32(p + 10 + 2 * 4);
+ if (v != 0 && (langID == 1033 || name == 0))
+ name = v;
+ }
+ }
+
+ if (name != 0)
{
- if (c0 == 0 && c1 != 0)
- numZeros0++;
- if (c1 == 0)
- numZeros1++;
+ Script += "Name";
+ AddParam(name);
+ NewLine();
+
+ ReadString2(Name, name);
+ }
+
+ /*
+ if (caption != 0)
+ {
+ Script += "Caption";
+ AddParam(caption);
+ NewLine();
+ }
+ */
+
+ if (brandingText != 0)
+ {
+ Script += "BrandingText";
+ AddParam(brandingText);
+ NewLine();
+
+ ReadString2(BrandingText, brandingText);
}
- // printf("\nnumZeros0 = %2x %2x", _data[pos + 0], _data[pos + 1]);
+
+ for (i = 0; i < bhLangTables.Num; 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++)
+ {
+ UInt32 val = Get32(p + 10 + j * 4);
+ if (val != 0)
+ {
+ if ((Int32)j != licenseLangIndex)
+ {
+ Script += "LangString ";
+ Add_LangStr_Simple(j);
+ AddParam_UInt(langID);
+ AddParam(val);
+ AddLF();
+ }
+ }
+ }
+ AddLF();
+ }
+ ClearLangComment();
}
- IsUnicode = (numZeros1 > numZeros0 * 3 + kBlockSize / 16);
- // printf("\nnumZeros0 = %3d numZeros1 = %3d", numZeros0, numZeros1);
- return ReadEntries(bhEntries);
+
+ {
+ 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();
+ }
+ }
+
+ onFuncOffset = paramsOffset + 40;
+ numOnFunc = ARRAY_SIZE(kOnFunc);
+ if (bhPages.Offset == 276)
+ numOnFunc--;
+ p2 += 40 + numOnFunc * 4;
+
+ #define NSIS_MAX_INST_TYPES 32
+
+ AddLF();
+
+ 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 (i != 0 && bhPages.Offset < 300)
+ break;
+ 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();
+ }
+
+ 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 += "!!! ";
+ {
+ Add_UInt(i);
+ AddParam(i);
+ NewLine();
+ }
+ if (IsUnicode)
+ i += GetUi16Str_Len((const Byte *)_data + _stringsPos + i * 2);
+ else
+ i += (UInt32)strlen((const char *)(const Byte *)_data + _stringsPos + i);
+ i++;
+ }
+ 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)
+ {
+ RINOK(_stream->Seek(DataStreamOffset, STREAM_SEEK_SET, NULL));
+ }
+ else
{
- _headerIsCompressed = ((compressedHeaderSize & 0x80000000) != 0);
- if (_headerIsCompressed)
- compressedHeaderSize &= ~0x80000000;
+ _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;
+ }
+
+ StartOffset = pos;
+ UInt32 peSize = 0;
+
+ if (pePos != (UInt64)(Int64)-1)
+ {
+ UInt64 peSize64 = (pos - pePos);
+ if (peSize64 < (1 << 20))
+ {
+ peSize = (UInt32)peSize64;
+ StartOffset = pePos;
+ }
}
- if (position > maxSize)
+
+ 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
index 7ca719e4..3acd9ee5 100755..100644
--- 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<IInStream> _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<CItem> 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<UInt32> langStrIDs;
+ UInt32 numOnFunc;
+ UInt32 onFuncOffset;
+ // CRecordVector<UInt32> OnFuncs;
+ unsigned _numRootLicenses;
+ CRecordVector<UInt32> 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<IInStream> _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<CItem> 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<CLicenseFile> 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 &sect, 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
index 41dedb0d..b363bdec 100755..100644
--- 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
index 2e4be10b..2854ff3e 100755..100644
--- 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
index 505486fc..dfe5eade 100755..100644
--- 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<CExtent> &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<CExtent> &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<CExtent> &extents, UInt64 numClustersMax, int compressionUnit) const
+bool CAttr::ParseExtents(CRecordVector<CExtent> &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<CExtent> &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<IInStream> Stream;
UInt64 Size;
UInt64 InitializedSize;
- int BlockSizeLog;
- int CompressionUnit;
+ unsigned BlockSizeLog;
+ unsigned CompressionUnit;
bool InUse;
CRecordVector<CExtent> 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<CAttr> &attrs,
- int attrIndex, int attrIndexLim, UInt64 numPhysClusters, CRecordVector<CExtent> &Extents)
+static HRESULT DataParseExtents(unsigned clusterSizeLog, const CObjectVector<CAttr> &attrs,
+ unsigned attrIndex, unsigned attrIndexLim, UInt64 numPhysClusters, CRecordVector<CExtent> &Extents)
{
CExtent e;
e.Virt = 0;
@@ -887,12 +920,12 @@ static HRESULT DataParseExtents(int clusterSizeLog, const CObjectVector<CAttr> &
(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<CAttr> &
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<CAttr> DataAttrs;
CObjectVector<CFileNameAttr> FileNames;
CRecordVector<CDataRef> 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<CAttr> *attrs);
+ bool Parse(Byte *p, unsigned sectorSizeLog, UInt32 numSectors, UInt32 recNumber, CObjectVector<CAttr> *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<CAttr> *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<CItem> Items;
+ CRecordVector<CItem> Items;
CObjectVector<CMftRec> Recs;
CMyComPtr<IInStream> InStream;
+ CHeader Header;
+ unsigned RecSizeLog;
+ UInt64 PhySize;
+
IArchiveOpenCallback *OpenCallback;
CByteBuffer ByteBuf;
CObjectVector<CAttr> VolAttrs;
+ CByteBuffer SecurData;
+ CRecordVector<size_t> 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<IInStream> 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<CAttr> 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<CAttr> *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<IInStream> 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<ICompressCoder> 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<IInStream> 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
index e5946969..08bcd062 100755..100644
--- a/CPP/7zip/Archive/PeHandler.cpp
+++ b/CPP/7zip/Archive/PeHandler.cpp
@@ -2,15 +2,17 @@
#include "StdAfx.h"
+// #include <stdio.h>
+
#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;
-#define PE_SIG 0x00004550
-#define PE_OptHeader_Magic_32 0x10B
-#define PE_OptHeader_Magic_64 0x20B
+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;
+ }
+ }
+
+ 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<IInStream> _stream;
CObjectVector<CSection> _sections;
UInt32 _peOffset;
CHeader _header;
- COptHeader _optHeader;
UInt32 _totalSize;
- UInt32 _totalSizeLimited;
Int32 _mainSubfile;
+ CRecordVector<CMixItem> _mixItems;
CRecordVector<CResItem> _items;
CObjectVector<CStringItem> _strings;
+ CObjectVector<CByteBuffer_WithLang> _versionFiles;
+ UString _versionFullString;
+ UString _versionShortString;
+ UString _originalFilename;
+ CObjectVector<CStringKeyValue> _versionKeys;
CByteBuffer _buf;
bool _oneLang;
- UString _resourceFileName;
+ UString _resourcesPrefix;
CUsedBitmap _usedRes;
bool _parseResources;
+ bool _checksumError;
- CRecordVector<CMixItem> _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<CTableItem> &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 &sect, 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 &sect = _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 &sect = _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<CTableItem> &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<CTableItem> &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,22 +1309,584 @@ 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();
+ }
+ }
+ if (size == pos)
+ return true;
+
+ // Some rare case files have additional ZERO.
+ if (size == pos + 2 && Get16(src + pos) == 0)
+ return true;
+
+ return false;
+}
+
+
+// ---------- VERSION ----------
+
+static const UInt32 kMy_VS_FFI_SIGNATURE = 0xFEEF04BD;
+
+struct CMy_VS_FIXEDFILEINFO
+{
+ // 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<CStringKeyValue> &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<CStringKeyValue> &v, const UString &key)
+{
+ FOR_VECTOR (i, v)
+ if (v[i].Key == key)
+ return i;
+ return -1;
+}
+
+static void AddToUniqueUStringVector(CObjectVector<CStringKeyValue> &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<CStringKeyValue> &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;
}
}
- return (size == pos);
+ 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;
+ }
}
-HRESULT CHandler::OpenResources(int sectionIndex, IInStream *stream, IArchiveOpenCallback *callback)
+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<CStringKeyValue> &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 &sect = _sections[sectionIndex];
size_t fileSize = sect.PSize; // Maybe we need sect.VSize here !!!
@@ -1143,13 +1897,13 @@ HRESULT CHandler::OpenResources(int sectionIndex, IInStream *stream, IArchiveOpe
if (callback)
RINOK(callback->SetTotal(NULL, &fileSize64));
RINOK(stream->Seek(sect.Pa, STREAM_SEEK_SET, NULL));
- _buf.SetCapacity(fileSize);
+ _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 << 20));
+ 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<CTableItem> 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 &sect = _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 &sect = _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 &sect = _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<CSection> 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 &sect = _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 &sect2 = _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<ICompressProgressInfo> 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<ISequentialInStream> 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<CSection> _items;
CMyComPtr<IInStream> _stream;
- CObjectVector<CSection> _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
index 9b2ef048..70e9ffac 100755..100644
--- 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<ISequentialInStream> _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
index 5d072d34..c4adee41 100755..100644
--- 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<wchar_t> _unicodeNameBuffer;
+ CByteBuffer _comment;
+ CByteBuffer m_FileHeaderData;
+ NHeader::NBlock::CBlock m_BlockHeader;
+ NCrypto::NRar29::CDecoder *m_RarAESSpec;
+ CMyComPtr<ICompressFilter> m_RarAES;
+ CBuffer<Byte> 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<IInStream> 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<CArc> *_archives;
+ const CObjectVector<CItem> *_items;
+ CRefItem _refItem;
+ unsigned _curIndex;
+ UInt32 _crc;
+ bool _fileIsOpen;
+ CMyComPtr<ISequentialInStream> _stream;
+
+ HRESULT OpenStream();
+ HRESULT CloseStream();
+public:
+ void Init(const CObjectVector<CArc> *archives,
+ const CObjectVector<CItem> *items,
+ const CRefItem &refItem);
+
+ CRecordVector<UInt32> CRCs;
+};
+
+
+ISequentialInStream* CArc::CreateLimitedStream(UInt64 offset, UInt64 size) const
+{
+ CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+ CMyComPtr<ISequentialInStream> inStream(streamSpec);
+ Stream->Seek(offset, STREAM_SEEK_SET, NULL);
+ streamSpec->SetStream(Stream);
+ streamSpec->Init(size);
+ return inStream.Detach();
+}
+
+void CFolderInStream::Init(
+ const CObjectVector<CArc> *archives,
+ const CObjectVector<CItem> *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<int> importantIndexes;
CRecordVector<bool> 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<ISequentialInStream> 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
index 79266827..81191be9 100755..100644
--- 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<IInStream> 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<CRefItem> _refItems;
- CObjectVector<CItemEx> _items;
- CObjectVector<CInArchive> _archives;
- NArchive::NRar::CInArchiveInfo _archiveInfo;
- AString _errorMessage;
+ CObjectVector<CItem> _items;
+ CObjectVector<CArc> _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
index 5c21a2ac..b518338a 100755..100644
--- 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<ISequentialInStream> 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<IInStream> m_Stream;
-
- UInt64 m_StreamStartPosition;
-
- CInArchiveInfo _header;
- CDynamicBuffer<char> m_NameBuffer;
- CDynamicBuffer<wchar_t> _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<Byte> m_FileHeaderData;
-
- NHeader::NBlock::CBlock m_BlockHeader;
-
- NCrypto::NRar29::CDecoder *m_RarAESSpec;
- CMyComPtr<ICompressFilter> 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<Byte> 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
index 4aa4d866..56d25f2c 100755..100644
--- 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<CInArchive> *archives,
- const CObjectVector<CItemEx> *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<CInArchive> *_archives;
- const CObjectVector<CItemEx> *_items;
- CRefItem _refItem;
- int _curIndex;
- UInt32 _crc;
- bool _fileIsOpen;
- CMyComPtr<ISequentialInStream> _stream;
-
- HRESULT OpenStream();
- HRESULT CloseStream();
-public:
- void Init(CObjectVector<CInArchive> *archives,
- const CObjectVector<CItemEx> *items,
- const CRefItem &refItem);
-
- CRecordVector<UInt32> CRCs;
-};
-
-}}
-
-#endif
diff --git a/CPP/7zip/Archive/Rar/StdAfx.cpp b/CPP/7zip/Archive/Rar/StdAfx.cpp
index d0feea85..d0feea85 100755..100644
--- a/CPP/7zip/Archive/Rar/StdAfx.cpp
+++ b/CPP/7zip/Archive/Rar/StdAfx.cpp
diff --git a/CPP/7zip/Archive/Rar/StdAfx.h b/CPP/7zip/Archive/Rar/StdAfx.h
index e7fb6986..2854ff3e 100755..100644
--- 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
index 1d31d451..220bc650 100755..100644
--- 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<IInStream> _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<ISequentialOutStream> 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<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
+ NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
+ CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> 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
index 5d84de4e..19dc1b47 100755..100644
--- 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<CMyComPtr<IInStream> > _streams;
CRecordVector<UInt64> _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<IArchiveOpenVolumeCallback> volumeCallback;
+ callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&volumeCallback);
+ if (!volumeCallback)
+ return S_FALSE;
+
+ UString name;
{
- CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
- CMyComPtr<IArchiveOpenCallback> 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<IInStream> 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<IInStream> 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<ICompressProgressInfo> 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<ISequentialInStream> 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
index efaffed1..617a1d66 100755..100644
--- 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<IInStream> _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<CTempItem> 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
index ef555ec1..1cbd7fea 100755..100644
--- 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
index d7d9537e..7cfea330 100755..100644
--- 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<IInStream> _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<IArchiveOpenCallback> Callback;
+public:
+ UInt64 Offset;
+ MY_UNKNOWN_IMP1(ICompressProgressInfo)
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+ void Init(IArchiveOpenCallback *callback) { Callback = callback; }
+};
+
+STDMETHODIMP CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */)
+{
+ if (Callback)
+ {
+ 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<ICompressCoder> _decoder = _decoderSpec;
-
CDummyOutStream *outStreamSpec = new CDummyOutStream;
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
outStreamSpec->SetStream(realOutStream);
@@ -176,24 +336,73 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CMyComPtr<ICompressProgressInfo> 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<ICompressCoder> _decoder;
+
+ CMyComPtr<ISequentialInStream> 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<ISequentialInStream> fileInStream;
RINOK(updateCallback->GetStream(0, &fileInStream));
+ /*
+ CDummyOutStream *outStreamSpec = new CDummyOutStream;
+ CMyComPtr<ISequentialOutStream> 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<ICompressCoder> encoder;
+ CMyComPtr<IOutStream> 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<ISequentialOutStream> 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<ICompressProgressInfo> progress = lps;
lps->Init(updateCallback, true);
- NCompress::NZlib::CEncoder *encoderSpec = new NCompress::NZlib::CEncoder;
- CMyComPtr<ICompressCoder> 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<CTag> _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<ISequentialOutStream> 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
index 2e4be10b..2854ff3e 100755..100644
--- 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
index 251afdb7..fc7de5ae 100755..100644
--- 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<IArchiveOpenVolumeCallback> 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<ISequentialInStream> 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<IUnknown> HandlerRef;
+ unsigned ItemIndex;
+ CRecordVector<UInt64> 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<IInStream> 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<IInStream> 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
index 9251edf6..23854767 100755..100644
--- 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<CItemEx> _items;
CMyComPtr<IInStream> _stream;
CMyComPtr<ISequentialInStream> _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<ICompressCoder> 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
index b0ec63d1..b909e96c 100755..100644
--- 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<CUpdateItem> 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
index 3275b284..70be09f3 100755..100644
--- 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
index a212ae03..df594d81 100755..100644
--- 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
index b6e5e0f5..1584a520 100755..100644
--- 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
index a5491ebe..a67b1dbd 100755..100644
--- 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
index 3584a7ce..805a2e7c 100755..100644
--- a/CPP/7zip/Archive/Tar/TarItem.h
+++ b/CPP/7zip/Archive/Tar/TarItem.h
@@ -40,28 +40,41 @@ struct CItem
CRecordVector<CSparseBlock> 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
index 6e699e28..51081e8b 100755..100644
--- 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
index ef837869..ee9b965e 100755..100644
--- 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<ISequentialOutStream> 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
index e21c0aac..9e0f6f21 100755..100644
--- 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
index fb123169..fdbce395 100755..100644
--- 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<NArchive::NTar::CItemEx> &inputItems,
const CObjectVector<CUpdateItem> &updateItems,
+ UINT codePage,
IArchiveUpdateCallback *updateCallback)
{
COutArchive outArchive;
outArchive.Create(outStream);
+ outArchive.Pos = 0;
+
+ CMyComPtr<IOutStream> 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<ISequentialInStream> 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<IStreamGetProps> 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
index 3f889739..c2393416 100755..100644
--- 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<CItemEx> &inputItems,
const CObjectVector<CUpdateItem> &updateItems,
+ UINT codePage,
IArchiveUpdateCallback *updateCallback);
}}
diff --git a/CPP/7zip/Archive/Udf/StdAfx.h b/CPP/7zip/Archive/Udf/StdAfx.h
index 2e4be10b..2854ff3e 100755..100644
--- 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
index c7085272..6aa53ea9 100755..100644
--- 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<IInStream> Stream;
- CRecordVector<CSeekExtent> 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<ISequentialInStream> 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
index f513727d..da44b232 100755..100644
--- 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
index d2a2884f..3053a0c1 100755..100644
--- 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 <stdio.h>
+#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
index 46b9a7e8..23693a71 100755..100644
--- 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<IInStream> _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<CPartition> Partitions;
CObjectVector<CLogVol> LogVols;
CObjectVector<CItem> Items;
CObjectVector<CFile> 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
index 1b08d120..ed32f12e 100755..100644
--- 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
index 88739d8f..2aaf7d8f 100755..100644
--- a/CPP/7zip/Archive/UefiHandler.cpp
+++ b/CPP/7zip/Archive/UefiHandler.cpp
@@ -4,8 +4,6 @@
// #define SHOW_DEBUG_INFO
-// #include <stdio.h>
-
#ifdef SHOW_DEBUG_INFO
#include <stdio.h>
#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<UInt32> 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
index 9d1c928e..5268bd0b 100755..100644
--- 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<IInStream> Stream;
CMyComPtr<IInStream> 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<IArchiveOpenVolumeCallback> openVolumeCallback;
if (openArchiveCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback) != S_OK)
- return S_FALSE;
+ {
+ // return S_FALSE;
+ }
CMyComPtr<IInStream> 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<ISequentialInStream> 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<ISequentialInStream> 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
index e7fb6986..2854ff3e 100755..100644
--- 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
index eaad1e7c..6f0b10e2 100755..100644
--- 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<IArchiveOpenVolumeCallback> 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<IInStream> 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<ISequentialOutStream> 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
index aa92069a..416e11ca 100755..100644
--- 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<IInStream> 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<CImageInfo> 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<CVolume> _volumes;
- CObjectVector<CXml> _xmls;
- int _nameLenForStreams;
+ CObjectVector<CWimXml> _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
index 85f0771c..149989d1 100755..100644
--- a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp
+++ b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp
@@ -2,17 +2,23 @@
#include "StdAfx.h"
+// #include <stdio.h>
+
#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<CSha1Hash> 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<CAltStream> AltStreams;
+
+ CByteBuffer Reparse;
- CUpdateItem(): HashIndex(-1) {}
+ 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<CMetaItem> &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;
+}
+
+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<CDir> Dirs;
- CIntVector Files;
-
- CDir(): Index(-1) {}
- bool IsLeaf() const { return Index >= 0; }
- UInt64 GetNumDirs() const;
- UInt64 GetNumFiles() const;
- CDir* AddDir(CObjectVector<CUpdateItem> &items, const UString &name, int index);
+ CUIntVector Files; // indexes in MetaItems[]
+
+ CDir(): MetaIndex(-1) {}
+ unsigned GetNumDirs() const;
+ unsigned GetNumFiles() const;
+ UInt64 GetTotalSize(const CObjectVector<CMetaItem> &metaItems) const;
+ bool FindDir(const CObjectVector<CMetaItem> &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<CUpdateItem> &items, const UString &name, int index)
+UInt64 CDir::GetTotalSize(const CObjectVector<CMetaItem> &metaItems) const
{
- int left = 0, right = Dirs.Size();
+ 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<CMetaItem> &items, const UString &name, unsigned &index)
+{
+ 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);
+
+ unsigned shortNameLen = item.ShortName.Len() * 2;
+ unsigned shortNameLen2 = (shortNameLen == 0 ? 2 : shortNameLen + 4);
- size_t totalLen = ((kDirRecordSize + fileNameLen2 + 6) & ~7);
- if (p)
+ 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<CSha1Hash> &digests,
- CUpdateItem &defaultDirItem,
- CObjectVector<CUpdateItem> &updateItems, Byte *dest, size_t &pos)
+static size_t WriteItem(const CRecordVector<CSha1Hash> &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)
{
- const CUpdateItem &ui = updateItems[tree.Files[i]];
- pos += WriteItem(ui, dest ? dest + pos : NULL,
- ui.HashIndex >= 0 ? digests[ui.HashIndex].Hash : NULL);
+ 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
+ {
+ 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<CSha1Hash> *Hashes;
+ CObjectVector<CMetaItem> MetaItems;
+ CRecordVector<CUpdateItem> 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)
{
- s += "<";
+ 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 += name;
- s += ">";
+ s += '>';
s += value;
- s += "</";
+ s += '<';
+ s += '/';
s += name;
- 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 void AddTagUInt64(AString &s, const char *name, UInt64 value)
+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 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 void AddTag_Time_2(CXmlItem &item, const FILETIME &ft)
+{
+ 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 AString TimeToXml(FILETIME &ft)
+static void AddTag_String_IfEmpty(CXmlItem &parentItem, const char *name, const char *value)
{
- 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;
+ 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,24 +670,607 @@ void CHeader::SetDefaultFields(bool useLZX)
IntegrityResource.Clear();
}
-static HRESULT UpdateArchive(ISequentialOutStream *seqOutStream,
- CDir &rootFolder,
- CObjectVector<CUpdateItem> &updateItems,
- IArchiveUpdateCallback *callback)
+static void AddTrees(CObjectVector<CDir> &trees, CObjectVector<CMetaItem> &metaItems, const CMetaItem &ri, int curTreeIndex)
{
+ while (curTreeIndex >= (int)trees.Size())
+ trees.AddNew().Dirs.AddNew().MetaIndex = metaItems.Add(ri);
+}
+
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 numItems, IArchiveUpdateCallback *callback)
+{
+ COM_TRY_BEGIN
+
+ if (ThereIsError())
+ return E_NOTIMPL;
+
+ bool isUpdate = (_volumes.Size() != 0);
+ int defaultImageIndex = _defaultImageNumber - 1;
+ bool showImageNumber;
+
+ 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;
+ }
+
+ if (defaultImageIndex >= kNumImagesMax)
+ return E_NOTIMPL;
+
CMyComPtr<IOutStream> outStream;
- RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream));
+ RINOK(outSeqStream->QueryInterface(IID_IOutStream, (void **)&outStream));
if (!outStream)
return E_NOTIMPL;
+ if (!callback)
+ return E_FAIL;
+
+ CDb db;
+ CObjectVector<CDir> trees;
+
+ 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;
+
+
+ // ---------- Detect changed images ----------
+
+ unsigned i;
+ CBoolVector isChangedImage;
+ {
+ CUIntVector numUnchangedItemsInImage;
+ for (i = 0; i < _db.Images.Size(); i++)
+ {
+ 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)
+ {
+ if (indexInArchive >= _db.SortedItems.Size())
+ continue;
+ const CItem &item = _db.Items[_db.SortedItems[indexInArchive]];
+ if (newData == 0)
+ {
+ if (item.ImageIndex >= 0)
+ numUnchangedItemsInImage[item.ImageIndex]++;
+ }
+ else
+ {
+ // oldProps & newData. Current version of 7-Zip doesn't use it
+ if (item.ImageIndex >= 0)
+ isChangedImage[item.ImageIndex] = true;
+ }
+ }
+ 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];
+ }
+
+ if (defaultImageIndex >= 0)
+ {
+ for (i = 0; i < _db.Images.Size(); i++)
+ if ((int)i != defaultImageIndex)
+ isChangedImage[i] = false;
+ }
+
+ CMyComPtr<IArchiveGetRawProps> getRawProps;
+ callback->QueryInterface(IID_IArchiveGetRawProps, (void **)&getRawProps);
+
+ CMyComPtr<IArchiveGetRootProps> getRootProps;
+ callback->QueryInterface(IID_IArchiveGetRootProps, (void **)&getRootProps);
+
+ CObjectVector<CUniqBlocks> secureBlocks;
+
+ if (!showImageNumber && (getRootProps || isUpdate) &&
+ (
+ defaultImageIndex >= (int)isChangedImage.Size()
+ || defaultImageIndex < 0 // test it
+ || isChangedImage[defaultImageIndex]
+ ))
+ {
+ // 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;
+ }
+
+ // ---------- Request Metadata for changed items ----------
+
+ UString fileName;
+
+ for (i = 0; i < numItems; i++)
+ {
+ CUpdateItem ui;
+ UInt32 indexInArchive;
+ 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(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;
+ }
+
+ bool isAltStream = false;
+ {
+ NCOM::CPropVariant prop;
+ 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;
+ }
+
+ 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;
+ 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;
+ }
+
+ {
+ 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 = NULL;
+ bool isRootImageDir = false;
+ fileName.Empty();
+
+ int imageIndex;
+
+ if (!showImageNumber)
+ {
+ 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 == ':')
+ {
+ 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
+ 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;
+ }
+
+ 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;
- int i;
- for (i = 0; i < updateItems.Size(); i++)
- complexity += updateItems[i].Size;
+ 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
+ {
+ 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;
+ }
+ }
+
+ 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<ICompressCoder> copyCoder = copyCoderSpec;
@@ -382,44 +1280,233 @@ static HRESULT UpdateArchive(ISequentialOutStream *seqOutStream,
complexity = 0;
- bool useCompression = false;
+ // bool useResourceCompression = false;
+ // use useResourceCompression only if CHeader::Flags compression is also set
CHeader header;
- header.SetDefaultFields(useCompression);
+ 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<ISequentialInStream> inShaStream = inShaStreamSpec;
+
+ CLimitedSequentialInStream *inStreamLimitedSpec = NULL;
+ CMyComPtr<CLimitedSequentialInStream> 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<CStreamInfo> streams;
- UInt64 curPos = kHeaderSizeMax;
- UInt64 unpackTotalSize = 0;
- for (i = 0; i < updateItems.Size(); i++)
+
+ // ---------- 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());
- CUpdateItem &ui = updateItems[i];
- if (ui.IsDir || ui.Size == 0)
- continue;
+ 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;
+ }
+ }
- CInStreamWithSha1 *inShaStreamSpec = new CInStreamWithSha1;
- CMyComPtr<ISequentialInStream> inShaStream = inShaStreamSpec;
+ 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<ISequentialInStream> fileInStream;
+ HRESULT res = callback->GetStream(ui.CallbackIndex, &fileInStream);
+ if (res == S_FALSE)
{
- CMyComPtr<ISequentialInStream> fileInStream;
- HRESULT res = callback->GetStream(i, &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<IStreamGetProps2> 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
{
- RINOK(res);
inShaStreamSpec->SetStream(fileInStream);
fileInStream.Release();
inShaStreamSpec->Init();
UInt64 offsetBlockSize = 0;
- if (useCompression)
+ /*
+ if (useResourceCompression)
{
- for (UInt64 t = kChunkSize; t < ui.Size; t += kChunkSize)
+ for (UInt64 t = kChunkSize; t < size; t += kChunkSize)
{
Byte buf[8];
SetUi32(buf, (UInt32)t);
@@ -427,94 +1514,180 @@ static HRESULT UpdateArchive(ISequentialOutStream *seqOutStream,
offsetBlockSize += 4;
}
}
-
+ */
+
RINOK(copyCoder->Code(inShaStream, outStream, NULL, NULL, progress));
- ui.Size = copyCoderSpec->TotalSize;
-
- CSha1Hash hash;
- unpackTotalSize += ui.Size;
- UInt64 packSize = offsetBlockSize + ui.Size;
- inShaStreamSpec->Final(hash.Hash);
- int index = hashes.AddUnique(hash);
- if (index >= 0)
- {
- ui.HashIndex = index;
- streams[index].RefCount++;
- outStream->Seek(-(Int64)packSize, STREAM_SEEK_CUR, &curPos);
- outStream->SetSize(curPos);
- }
- else
+ size = copyCoderSpec->TotalSize;
+
+ if (size != 0)
{
- 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)
+ 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.Hash, kHashSize);
- streams.Add(s);
- curPos += packSize;
+ */
+ 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 += ui.Size;
- RINOK(callback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
}
+ fileInStream.Release();
+ complexity += size;
+ RINOK(callback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
}
- 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;
+ while (secureBlocks.Size() < numNewImages)
+ secureBlocks.AddNew();
- 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);
+ // ---------- Write Images ----------
+ for (i = 0; i < numNewImages; i++)
{
- NCrypto::NSha1::CContext sha;
- sha.Init();
- sha.Update((const Byte *)meta, pos);
- CSha1Hash digest;
- sha.Final(digest.Hash);
+ 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;
+ }
- 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;
+ 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<CByteBuffer> &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];
@@ -524,116 +1697,70 @@ static HRESULT UpdateArchive(ISequentialOutStream *seqOutStream,
}
AString xml = "<WIM>";
- AddTagUInt64(xml, "TOTALBYTES", curPos);
- xml += "<IMAGE INDEX=\"1\"><NAME>1</NAME>";
- 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 += "</IMAGE></WIM>";
-
- size_t xmlSize = (xml.Length() + 1) * 2;
- meta.SetCapacity(xmlSize);
- Set16((Byte *)meta, 0xFEFF);
- for (i = 0; i < xml.Length(); i++)
- Set16((Byte *)meta + 2 + i * 2, xml[i]);
- RINOK(WriteStream(outStream, (const Byte *)meta, xmlSize));
- meta.Free();
-
- header.XmlResource.UnpackSize = header.XmlResource.PackSize = xmlSize;
- header.XmlResource.Offset = curPos;
- header.XmlResource.Flags = NResourceFlags::kMetadata;
-
- outStream->Seek(0, STREAM_SEEK_SET, NULL);
- header.WriteTo(buf);
- return WriteStream(outStream, buf, kHeaderSizeMax);
-}
-
-STDMETHODIMP COutHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
- IArchiveUpdateCallback *callback)
-{
- COM_TRY_BEGIN
- CObjectVector<CUpdateItem> updateItems;
- CDir tree;
- tree.Dirs.Add(CDir());
- CDir &rootFolder = tree.Dirs.Back();
-
- for (UInt32 i = 0; i < numItems; i++)
+ AddTagUInt64_ToString(xml, "TOTALBYTES", curPos);
+ for (i = 0; i < trees.Size(); i++)
{
- CUpdateItem ui;
- Int32 newData, newProps;
- UInt32 indexInArchive;
- if (!callback)
- return E_FAIL;
- RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));
+ CDir &tree = trees[i];
+ CXmlItem item;
+ if (_xmls.Size() == 1)
{
- NCOM::CPropVariant prop;
- RINOK(callback->GetProperty(i, kpidIsDir, &prop));
- if (prop.vt == VT_EMPTY)
- ui.IsDir = false;
- else if (prop.vt != VT_BOOL)
- return E_INVALIDARG;
- else
- ui.IsDir = (prop.boolVal != VARIANT_FALSE);
- }
-
- {
- NCOM::CPropVariant prop;
- RINOK(callback->GetProperty(i, kpidAttrib, &prop));
- if (prop.vt == VT_EMPTY)
- ui.Attrib = (ui.IsDir ? FILE_ATTRIBUTE_DIRECTORY : 0);
- else if (prop.vt != VT_UI4)
- return E_INVALIDARG;
- else
- ui.Attrib = prop.ulVal;
- }
-
- RINOK(GetTime(callback, i, kpidCTime, ui.CTime));
- RINOK(GetTime(callback, i, kpidATime, ui.ATime));
- RINOK(GetTime(callback, i, kpidMTime, ui.MTime));
-
- {
- NCOM::CPropVariant prop;
- RINOK(callback->GetProperty(i, kpidSize, &prop));
- if (prop.vt != VT_UI8)
- return E_INVALIDARG;
- ui.Size = prop.uhVal.QuadPart;
+ 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];
+ }
}
-
- UString path;
- NCOM::CPropVariant prop;
- RINOK(callback->GetProperty(i, kpidPath, &prop));
- if (prop.vt == VT_BSTR)
- path = prop.bstrVal;
- else if (prop.vt != VT_EMPTY)
- return E_INVALIDARG;
-
- CDir *curItem = &rootFolder;
- int len = path.Length();
- UString fileName;
- for (int j = 0; j < len; j++)
+ if (i >= isChangedImage.Size() || isChangedImage[i])
{
- wchar_t c = path[j];
- if (c == WCHAR_PATH_SEPARATOR || c == L'/')
+ char temp[16];
+ if (item.Name.IsEmpty())
{
- curItem = curItem->AddDir(updateItems, fileName, -1);
- fileName.Empty();
+ ConvertUInt32ToString(i + 1, temp);
+ item.Name = "IMAGE";
+ item.IsTag = true;
+ CXmlProp &prop = item.Props.AddNew();
+ prop.Name = "INDEX";
+ prop.Value = temp;
}
- else
- fileName += c;
+
+ 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);
}
- ui.Name = fileName;
- updateItems.Add(ui);
- if (ui.IsDir)
- curItem->AddDir(updateItems, fileName, (int)i);
- else
- curItem->Files.Add(i);
+ item.AppendTo(xml);
}
- return UpdateArchive(outStream, tree, updateItems, callback);
+ xml += "</WIM>";
+
+ 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
index c210804d..cec037cc 100755..100644
--- a/CPP/7zip/Archive/Wim/WimIn.cpp
+++ b/CPP/7zip/Archive/Wim/WimIn.cpp
@@ -2,13 +2,17 @@
#include "StdAfx.h"
+// #include <stdio.h>
+
#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<ISequentialOutStream> 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<UInt64> 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<CStreamInfo> &streams = *(const CRecordVector<CStreamInfo> *)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<CStreamInfo> &streams = *(const CRecordVector<CStreamInfo> *)param;
return memcmp(streams[*p1].Hash, streams[*p2].Hash, kHashSize);
}
static int FindId(const CRecordVector<CStreamInfo> &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<CStreamInfo> &streams,
}
static int FindHash(const CRecordVector<CStreamInfo> &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<CStreamInfo> &streams,
return -1;
}
-static int CompareItems(const int *a1, const int *a2, void *param)
+bool CDatabase::ItemHasStream(const CItem &item) const
{
- const CObjectVector<CItem> &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<CItem> &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<bool> 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<CVolume> &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
index da3e28a5..4b7c6d95 100755..100644
--- 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<UInt32> 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<CImageInfo> 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<IInStream> 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<CStreamInfo> Streams;
- CObjectVector<CItem> Items;
- CIntVector SortedItems;
- int NumImages;
- bool SkipRoot;
- bool ShowImageNumber;
+ CRecordVector<CStreamInfo> DataStreams;
+
+ CRecordVector<CStreamInfo> MetaStreams;
+
+ CRecordVector<CItem> Items;
+ CObjectVector<CByteBuffer> ReparseItems;
+ CIntVector ItemToReparse; // from index_in_Items to index_in_ReparseItems
+ // -1 means no reparse;
+
+ CObjectVector<CImage> 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<CVolume> &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
index 8da91436..35d78314 100755..100644
--- 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
index e7d88b6c..918ef736 100755..100644
--- 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<IInStream> _inStream;
AString _xml;
CObjectVector<CFile> _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<CFile> &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<CFile> &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<CFile> &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<ICompressCoder> 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
index 8383488b..0de58a44 100755..100644
--- 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<ICompressProgressInfo> 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<IInStream> _stream;
CMyComPtr<ISequentialInStream> _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(&currentTotalPacked));
- CMyComPtr<ISequentialOutStream> realOutStream;
- Int32 askMode = testMode ?
- NExtract::NAskMode::kTest :
- NExtract::NAskMode::kExtract;
-
- RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
-
- if (!testMode && !realOutStream)
- return S_OK;
-
- extractCallback->PrepareOperation(askMode);
-
- if (_stream)
- {
- RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL));
- }
-
- CLocalProgress *lps = new CLocalProgress;
- CMyComPtr<ICompressProgressInfo> 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(&currentTotalPacked));
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ Int32 askMode = testMode ?
+ NExtract::NAskMode::kTest :
+ NExtract::NAskMode::kExtract;
+
+ RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
+
+ if (!testMode && !realOutStream)
+ return S_OK;
+
+ extractCallback->PrepareOperation(askMode);
+
+ 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
index 49b76a11..459f3e35 100755..100644
--- 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<IInStream> _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<IArchiveOpenCallback> 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<ICompressProgressInfo> compressProgress = compressProgressSpec;
+ compressProgressSpec->Init(openCallback);
+
+ NCompress::NZ::CDecoder *decoderSpec = new NCompress::NZ::CDecoder;
+ CMyComPtr<ICompressCoder> decoder = decoderSpec;
+
+ CDummyOutStream *outStreamSpec = new CDummyOutStream;
+ CMyComPtr<ISequentialOutStream> 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<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, true);
- RINOK(_stream->Seek(_streamStartPosition + kSignatureSize, STREAM_SEEK_SET, NULL));
+ RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));
- CMyComPtr<ICompressCoder> decoder;
NCompress::NZ::CDecoder *decoderSpec = new NCompress::NZ::CDecoder;
- decoder = decoderSpec;
-
- HRESULT result = decoderSpec->SetDecoderProperties2(&_properties, 1);
+ CMyComPtr<ICompressCoder> 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
index e7fb6986..2854ff3e 100755..100644
--- 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
index f77e4f23..9a0d7515 100755..100644
--- 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<ISequentialInStream> inCrcStream;
{
CMyComPtr<IInStream> 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
index e4c02db3..e4c02db3 100755..100644
--- a/CPP/7zip/Archive/Zip/ZipAddCommon.h
+++ b/CPP/7zip/Archive/Zip/ZipAddCommon.h
diff --git a/CPP/7zip/Archive/Zip/ZipCompressionMode.h b/CPP/7zip/Archive/Zip/ZipCompressionMode.h
index 893daaab..86548d95 100755..100644
--- 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
index 2281ed5b..f556068c 100755..100644
--- 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<IArchiveOpenCallback> _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<ICompressProgressInfo> 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
index 33cf6fdc..7f1d2eba 100755..100644
--- 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
index dd1ca136..ae58cbe2 100755..100644
--- 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<CUpdateItem> 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
index ce8c1e4f..1391cdf4 100755..100644
--- 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
index e930488f..345fbf56 100755..100644
--- 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 <stdio.h>
-#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<CItemEx> &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<CItemEx> &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<CItemEx> &items, CProgressVirt *progress, UInt64 &cdOffset, int &numCdItems)
+static HRESULT FindItem(const CObjectVector<CItemEx> &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<CItemEx> &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<CItemEx> &items, CProgressVirt *progress)
+HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &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<CItemEx> 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<CItemEx> &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<CItemEx> &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<ISequentialInStream> 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<IInStream> 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
index 0565339a..f6b349b1 100755..100644
--- 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<IInStream> 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<CItemEx> &items, UInt64 cdOffset, UInt64 cdSize, CProgressVirt *progress);
HRESULT ReadCd(CObjectVector<CItemEx> &items, UInt64 &cdOffset, UInt64 &cdSize, CProgressVirt *progress);
- HRESULT ReadLocalsAndCd(CObjectVector<CItemEx> &items, CProgressVirt *progress, UInt64 &cdOffset, int &numCdItems);
+ HRESULT ReadLocals(CObjectVector<CItemEx> &localItems, CProgressVirt *progress);
+
+ HRESULT ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *progress);
public:
CInArchiveInfo ArcInfo;
+
+ bool IsArc;
bool IsZip64;
- bool IsOkHeaders;
-
+ bool HeadersError;
+ bool HeadersWarning;
+ bool ExtraMinorError;
+ bool UnexpectedEnd;
+ bool NoCentralDir;
+
+ CMyComPtr<IInStream> Stream;
+
+ void Close();
+ HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
HRESULT ReadHeaders(CObjectVector<CItemEx> &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
index ad89f558..ae88944d 100755..100644
--- 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
index 5efd433a..d50c3ae9 100755..100644
--- 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<CExtraSubBlock> 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
index aa82143e..2a1ba2c4 100755..100644
--- 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<CItem> &items, const CByteBuffer *comment)
+void COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &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<IOutStream> 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
index 2f6349e5..eaaa0320 100755..100644
--- 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<IOutStream> 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<CItem> &items, const CByteBuffer *comment);
+ void WriteLocalHeader_And_SeekToNextFile(const CLocalItem &item)
+ {
+ WriteLocalHeader(item);
+ SeekToCurPos();
+ }
+
+ void WriteCentralDir(const CObjectVector<CItemOut> &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
index 3e7aade8..545e76c6 100755..100644
--- 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
index a91364be..2978e387 100755..100644
--- 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<ISequentialOutStream> 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<CLimitedSequentialInStream> 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<ICompressCodecsInfo> _codecsInfo;
- const CObjectVector<CCodecInfoEx> *_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<CThreadInfo> 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<CItemEx> &inputItems,
const CObjectVector<CUpdateItem> &updateItems,
const CCompressionMethodMode *options,
@@ -410,26 +404,29 @@ static HRESULT Update2St(
CAddCommon compressor(*options);
- CObjectVector<CItem> items;
+ CObjectVector<CItemOut> 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<IOutStream> 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<CItemEx> &inputItems,
const CObjectVector<CUpdateItem> &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<CItem> items;
+ CObjectVector<CItemOut> items;
CMtProgressMixer *mtProgressMixerSpec = new CMtProgressMixer;
CMyComPtr<ICompressProgressInfo> 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<IOutStream> 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<CItemEx> &inputItems,
const CObjectVector<CUpdateItem> &updateItems,
ISequentialOutStream *seqOutStream,
- CInArchive *inArchive,
+ CInArchive *inArchive, bool removeSfx,
CCompressionMethodMode *compressionMethodMode,
IArchiveUpdateCallback *updateCallback)
{
+ if (inArchive)
+ {
+ if (!inArchive->CanUpdate())
+ return E_NOTIMPL;
+ }
+
+
CMyComPtr<IOutStream> outStream;
{
CMyComPtr<IOutStream> 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<ISequentialInStream> 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<IInStream> 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
index eee16738..747c07bc 100755..100644
--- 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<CItemEx> &inputItems,
const CObjectVector<CUpdateItem> &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
index 7512ad56..7512ad56 100755..100644
--- a/CPP/7zip/Archive/makefile
+++ b/CPP/7zip/Archive/makefile
diff --git a/CPP/7zip/Asm.mak b/CPP/7zip/Asm.mak
index 4ab94f15..4f77dddf 100755..100644
--- 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
index 5e0e3e51..017a3f1b 100755..100644
--- 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
index 65eca43f..65eca43f 100755..100644
--- a/CPP/7zip/Bundles/Alone/Alone.dsw
+++ b/CPP/7zip/Bundles/Alone/Alone.dsw
diff --git a/CPP/7zip/Bundles/Alone/StdAfx.cpp b/CPP/7zip/Bundles/Alone/StdAfx.cpp
index d0feea85..d0feea85 100755..100644
--- a/CPP/7zip/Bundles/Alone/StdAfx.cpp
+++ b/CPP/7zip/Bundles/Alone/StdAfx.cpp
diff --git a/CPP/7zip/Bundles/Alone/StdAfx.h b/CPP/7zip/Bundles/Alone/StdAfx.h
index 2e4be10b..2854ff3e 100755..100644
--- 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
index c2fadd4a..c2fadd4a 100755..100644
--- a/CPP/7zip/Bundles/Alone/afxres.h
+++ b/CPP/7zip/Bundles/Alone/afxres.h
diff --git a/CPP/7zip/Bundles/Alone/makefile b/CPP/7zip/Bundles/Alone/makefile
index a99c61ec..15139714 100755..100644
--- 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
index fc9063c1..fc9063c1 100755..100644
--- a/CPP/7zip/Bundles/Alone/resource.rc
+++ b/CPP/7zip/Bundles/Alone/resource.rc
diff --git a/CPP/7zip/Bundles/Alone7z/StdAfx.cpp b/CPP/7zip/Bundles/Alone7z/StdAfx.cpp
index d0feea85..d0feea85 100755..100644
--- a/CPP/7zip/Bundles/Alone7z/StdAfx.cpp
+++ b/CPP/7zip/Bundles/Alone7z/StdAfx.cpp
diff --git a/CPP/7zip/Bundles/Alone7z/StdAfx.h b/CPP/7zip/Bundles/Alone7z/StdAfx.h
index 2e4be10b..2854ff3e 100755..100644
--- 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
index 8de884f7..9f7ef516 100755..100644
--- 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
index b3fb079a..b3fb079a 100755..100644
--- a/CPP/7zip/Bundles/Alone7z/resource.rc
+++ b/CPP/7zip/Bundles/Alone7z/resource.rc
diff --git a/CPP/7zip/Bundles/Fm/FM.dsp b/CPP/7zip/Bundles/Fm/FM.dsp
index dded8b1d..1f214b33 100755..100644
--- a/CPP/7zip/Bundles/Fm/FM.dsp
+++ b/CPP/7zip/Bundles/Fm/FM.dsp
@@ -45,7 +45,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /Gz /MD /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
index 1c955d95..1c955d95 100755..100644
--- a/CPP/7zip/Bundles/Fm/FM.dsw
+++ b/CPP/7zip/Bundles/Fm/FM.dsw
diff --git a/CPP/7zip/Bundles/Fm/StdAfx.cpp b/CPP/7zip/Bundles/Fm/StdAfx.cpp
index d0feea85..d0feea85 100755..100644
--- a/CPP/7zip/Bundles/Fm/StdAfx.cpp
+++ b/CPP/7zip/Bundles/Fm/StdAfx.cpp
diff --git a/CPP/7zip/Bundles/Fm/StdAfx.h b/CPP/7zip/Bundles/Fm/StdAfx.h
index b09de592..d2301e48 100755..100644
--- 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 <windows.h>
-#include <stdio.h>
#include <commctrl.h>
#include <ShlObj.h>
-#include <limits.h>
-#include <tchar.h>
#include <shlwapi.h>
-// #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
index b8f9133f..fd211a1d 100755..100644
--- 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
index dd2058a1..dd2058a1 100755..100644
--- a/CPP/7zip/Bundles/Fm/resource.rc
+++ b/CPP/7zip/Bundles/Fm/resource.rc
diff --git a/CPP/7zip/Bundles/Format7z/StdAfx.cpp b/CPP/7zip/Bundles/Format7z/StdAfx.cpp
index d0feea85..d0feea85 100755..100644
--- a/CPP/7zip/Bundles/Format7z/StdAfx.cpp
+++ b/CPP/7zip/Bundles/Format7z/StdAfx.cpp
diff --git a/CPP/7zip/Bundles/Format7z/StdAfx.h b/CPP/7zip/Bundles/Format7z/StdAfx.h
index 2e4be10b..2854ff3e 100755..100644
--- 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
index 3b04c5e7..01e63e67 100755..100644
--- 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
index 2f2b42ae..2f2b42ae 100755..100644
--- a/CPP/7zip/Bundles/Format7z/resource.rc
+++ b/CPP/7zip/Bundles/Format7z/resource.rc
diff --git a/CPP/7zip/Bundles/Format7zExtract/StdAfx.cpp b/CPP/7zip/Bundles/Format7zExtract/StdAfx.cpp
index d0feea85..d0feea85 100755..100644
--- a/CPP/7zip/Bundles/Format7zExtract/StdAfx.cpp
+++ b/CPP/7zip/Bundles/Format7zExtract/StdAfx.cpp
diff --git a/CPP/7zip/Bundles/Format7zExtract/StdAfx.h b/CPP/7zip/Bundles/Format7zExtract/StdAfx.h
index 2e4be10b..2854ff3e 100755..100644
--- 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
index 5598adc2..86a76e3d 100755..100644
--- 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
index 6a654615..6a654615 100755..100644
--- a/CPP/7zip/Bundles/Format7zExtract/resource.rc
+++ b/CPP/7zip/Bundles/Format7zExtract/resource.rc
diff --git a/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp b/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp
index d0feea85..d0feea85 100755..100644
--- a/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp
+++ b/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp
diff --git a/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h b/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h
index 2e4be10b..2854ff3e 100755..100644
--- 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
index e953af90..7241b37c 100755..100644
--- 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
index 149f58c4..149f58c4 100755..100644
--- a/CPP/7zip/Bundles/Format7zExtractR/resource.rc
+++ b/CPP/7zip/Bundles/Format7zExtractR/resource.rc
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
index 5bf1277d..40f45455 100755..100644
--- a/CPP/7zip/Bundles/Format7zF/Format7z.dsp
+++ b/CPP/7zip/Bundles/Format7zF/Format7z.dsp
@@ -43,7 +43,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 1
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /Gr /MT /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
index 324dab1f..324dab1f 100755..100644
--- a/CPP/7zip/Bundles/Format7zF/Format7z.dsw
+++ b/CPP/7zip/Bundles/Format7zF/Format7z.dsw
diff --git a/CPP/7zip/Bundles/Format7zF/StdAfx.cpp b/CPP/7zip/Bundles/Format7zF/StdAfx.cpp
index d0feea85..d0feea85 100755..100644
--- a/CPP/7zip/Bundles/Format7zF/StdAfx.cpp
+++ b/CPP/7zip/Bundles/Format7zF/StdAfx.cpp
diff --git a/CPP/7zip/Bundles/Format7zF/StdAfx.h b/CPP/7zip/Bundles/Format7zF/StdAfx.h
index 2e4be10b..2854ff3e 100755..100644
--- 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
index 2601f1d6..97318dc6 100755..100644
--- 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
index 1caf7301..1caf7301 100755..100644
--- a/CPP/7zip/Bundles/Format7zF/resource.rc
+++ b/CPP/7zip/Bundles/Format7zF/resource.rc
diff --git a/CPP/7zip/Bundles/Format7zR/StdAfx.cpp b/CPP/7zip/Bundles/Format7zR/StdAfx.cpp
index d0feea85..d0feea85 100755..100644
--- a/CPP/7zip/Bundles/Format7zR/StdAfx.cpp
+++ b/CPP/7zip/Bundles/Format7zR/StdAfx.cpp
diff --git a/CPP/7zip/Bundles/Format7zR/StdAfx.h b/CPP/7zip/Bundles/Format7zR/StdAfx.h
index 2e4be10b..2854ff3e 100755..100644
--- 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
index d7ffcea1..555654bc 100755..100644
--- 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
index a8baa596..a8baa596 100755..100644
--- a/CPP/7zip/Bundles/Format7zR/resource.rc
+++ b/CPP/7zip/Bundles/Format7zR/resource.rc
diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
index e0f4dcba..d321e454 100755..100644
--- 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
index 6111aa7e..47f36c84 100755..100644
--- 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
index e62c9d2f..e62c9d2f 100755..100644
--- a/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw
+++ b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw
diff --git a/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp b/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp
index d0feea85..d0feea85 100755..100644
--- a/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp
+++ b/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp
diff --git a/CPP/7zip/Bundles/LzmaCon/StdAfx.h b/CPP/7zip/Bundles/LzmaCon/StdAfx.h
index e7fb6986..2854ff3e 100755..100644
--- 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
index 35d031af..54919f73 100755..100644
--- 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
index 0f9f498c..42e52246 100755..100644
--- 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
index 47ffb781..47ffb781 100755..100644
--- a/CPP/7zip/Bundles/SFXCon/7z.ico
+++ b/CPP/7zip/Bundles/SFXCon/7z.ico
Binary files differ
diff --git a/CPP/7zip/Bundles/SFXCon/SFXCon.dsp b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp
index e355d6e1..092fedcd 100755..100644
--- 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
index 27bf7e6d..27bf7e6d 100755..100644
--- a/CPP/7zip/Bundles/SFXCon/SFXCon.dsw
+++ b/CPP/7zip/Bundles/SFXCon/SFXCon.dsw
diff --git a/CPP/7zip/Bundles/SFXCon/Main.cpp b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp
index 3e9a8162..c8837f9d 100755..100644
--- a/CPP/7zip/Bundles/SFXCon/Main.cpp
+++ b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp
@@ -2,16 +2,16 @@
#include "StdAfx.h"
-#include "Common/MyInitGuid.h"
+#include "../../../Common/MyInitGuid.h"
-#include "Common/CommandLineParser.h"
-#include "Common/MyException.h"
+#include "../../../Common/CommandLineParser.h"
+#include "../../../Common/MyException.h"
#ifdef _WIN32
-#include "Windows/DLL.h"
-#include "Windows/FileDir.h"
+#include "../../../Windows/DLL.h"
+#include "../../../Windows/FileDir.h"
#endif
-#include "Windows/FileName.h"
+#include "../../../Windows/FileName.h"
#include "../../UI/Common/ExitCode.h"
#include "../../UI/Common/Extract.h"
@@ -24,6 +24,7 @@
using namespace NWindows;
using namespace NFile;
+using namespace NDir;
using namespace NCommandLineParser;
#ifdef _WIN32
@@ -54,7 +55,7 @@ namespace NRecursedType {
enum EEnum
{
kRecursed,
- kWildCardOnlyRecursed,
+ kWildcardOnlyRecursed,
kNonRecursed
};
}
@@ -65,7 +66,7 @@ static const wchar_t *kRecursedPostCharSet = L"0-";
namespace NRecursedPostCharIndex {
enum EEnum
{
- kWildCardRecursionOnly = 0,
+ kWildcardRecursionOnly = 0,
kNoRecursion = 1
};
}
@@ -77,35 +78,16 @@ static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must
static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>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
+ { "?", NSwitchType::kSimple },
+ { "H", NSwitchType::kSimple },
+ { "BD", NSwitchType::kSimple },
+ { "Y", NSwitchType::kSimple },
+ { "P", NSwitchType::kString, false, 1 },
+ { "O", NSwitchType::kString, false, 1 },
};
-}
-
-static const CCommandForm commandForms[kNumCommandForms] =
-{
- { L"T", false },
- // { "E", false },
- { L"X", false },
- { L"L", false }
-};
+static const int kNumCommandForms = 3;
static const NRecursedType::EEnum kCommandRecursedDefault[kNumCommandForms] =
{
@@ -137,7 +119,7 @@ static const char *kHelpString =
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 char *kIncorrectWildcardInCommandLine = "Incorrect wildcard in command line";
// static const CSysString kFileIsNotArchiveMessageBefore = "File \"";
// static const CSysString kFileIsNotArchiveMessageAfter = "\" is not archive";
@@ -146,13 +128,40 @@ static const char *kIncorrectWildCardInCommandLine = "Incorrect wildcard in com
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];
@@ -175,19 +184,6 @@ static void PrintHelpAndExit() // yyy
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
@@ -195,16 +191,16 @@ static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor,
const UString &name, bool include, NRecursedType::EEnum type)
{
/*
- if (!IsWildCardFilePathLegal(name))
+ if (!IsWildcardFilePathLegal(name))
return false;
*/
- bool isWildCard = DoesNameContainWildCard(name);
+ bool isWildcard = DoesNameContainWildcard(name);
bool recursed = false;
switch (type)
{
- case NRecursedType::kWildCardOnlyRecursed:
- recursed = isWildCard;
+ case NRecursedType::kWildcardOnlyRecursed:
+ recursed = isWildcard;
break;
case NRecursedType::kRecursed:
recursed = true;
@@ -213,22 +209,22 @@ static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor,
recursed = false;
break;
}
- wildcardCensor.AddItem(include, name, recursed);
+ wildcardCensor.AddPreItem(include, name, recursed, true);
return true;
}
-void AddCommandLineWildCardToCensor(NWildcard::CCensor &wildcardCensor,
+void AddCommandLineWildcardToCensor(NWildcard::CCensor &wildcardCensor,
const UString &name, bool include, NRecursedType::EEnum type)
{
if (!AddNameToCensor(wildcardCensor, name, include, type))
- ShowMessageAndThrowException(kIncorrectWildCardInCommandLine, NExitCode::kUserError);
+ ShowMessageAndThrowException(kIncorrectWildcardInCommandLine, NExitCode::kUserError);
}
void AddToCensorFromNonSwitchesStrings(NWildcard::CCensor &wildcardCensor,
const UStringVector & /* nonSwitchStrings */, NRecursedType::EEnum type,
- bool /* thereAreSwitchIncludeWildCards */)
+ bool /* thereAreSwitchIncludeWildcards */)
{
- AddCommandLineWildCardToCensor(wildcardCensor, kUniversalWildcard, true, type);
+ AddCommandLineWildcardToCensor(wildcardCensor, kUniversalWildcard, true, type);
}
@@ -269,7 +265,7 @@ int Main2(
{
FString path;
NDLL::MyGetModuleFileName(path);
- if (!NDirectory::MyGetFullPathName(path, arcPath))
+ if (!MyGetFullPathName(path, arcPath))
{
g_StdOut << "GetFullPathName Error";
return NExitCode::kFatalError;
@@ -320,10 +316,11 @@ int Main2(
NWildcard::CCensor wildcardCensor;
- bool thereAreSwitchIncludeWildCards;
- thereAreSwitchIncludeWildCards = false;
+ bool thereAreSwitchIncludeWildcards;
+ thereAreSwitchIncludeWildcards = false;
+
AddToCensorFromNonSwitchesStrings(wildcardCensor, nonSwitchStrings, recursedType,
- thereAreSwitchIncludeWildCards);
+ thereAreSwitchIncludeWildcards);
bool yesToAll = parser[NKey::kYes].ThereIs;
@@ -346,6 +343,9 @@ int Main2(
NName::NormalizeDirPathPrefix(outputDir);
}
+
+ wildcardCensor.AddPathsToCensor(NWildcard::k_RelatPath);
+
{
UStringVector v1, v2;
v1.Add(fs2us(arcPath));
@@ -388,21 +388,23 @@ int Main2(
CExtractOptions eo;
eo.StdOutMode = false;
- eo.PathMode = NExtract::NPathMode::kFullPathnames;
+ eo.YesToAll = yesToAll;
eo.TestMode = command.CommandType == NCommandType::kTest;
+ eo.PathMode = NExtract::NPathMode::kFullPaths;
eo.OverwriteMode = yesToAll ?
- NExtract::NOverwriteMode::kWithoutPrompt :
- NExtract::NOverwriteMode::kAskBefore;
+ NExtract::NOverwriteMode::kOverwrite :
+ NExtract::NOverwriteMode::kAsk;
eo.OutputDir = outputDir;
- eo.YesToAll = yesToAll;
UString errorMessage;
CDecompressStat stat;
- HRESULT result = DecompressArchives(
- codecs, CIntVector(),
+ HRESULT result = Extract(
+ codecs, CObjectVector<COpenType>(), CIntVector(),
v1, v2,
wildcardCensorHead,
- eo, &openCallback, ecs, errorMessage, stat);
+ eo, &openCallback, ecs,
+ // NULL, // hash
+ errorMessage, stat);
if (!errorMessage.IsEmpty())
{
(*g_StdStream) << endl << "Error: " << errorMessage;;
@@ -410,10 +412,10 @@ int Main2(
result = E_FAIL;
}
- if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0)
+ if (ecs->NumArcsWithError != 0 || ecs->NumFileErrors != 0)
{
- if (ecs->NumArchiveErrors != 0)
- (*g_StdStream) << endl << "Archive Errors: " << ecs->NumArchiveErrors << endl;
+ 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;
@@ -424,16 +426,20 @@ int Main2(
else
{
UInt64 numErrors = 0;
+ UInt64 numWarnings = 0;
HRESULT result = ListArchives(
- codecs, CIntVector(),
- false,
+ codecs, CObjectVector<COpenType>(), CIntVector(),
+ false, // stdInMode
v1, v2,
+ true, // processAltStreams
+ false, // showAltStreams
wildcardCensorHead,
- true, false,
+ true, // enableHeaders
+ false, // techMode
#ifndef _NO_CRYPTO
passwordEnabled, password,
#endif
- numErrors);
+ numErrors, numWarnings);
if (numErrors > 0)
{
g_StdOut << endl << "Errors: " << numErrors;
diff --git a/CPP/7zip/Bundles/SFXCon/StdAfx.cpp b/CPP/7zip/Bundles/SFXCon/StdAfx.cpp
index d0feea85..d0feea85 100755..100644
--- a/CPP/7zip/Bundles/SFXCon/StdAfx.cpp
+++ b/CPP/7zip/Bundles/SFXCon/StdAfx.cpp
diff --git a/CPP/7zip/Bundles/SFXCon/StdAfx.h b/CPP/7zip/Bundles/SFXCon/StdAfx.h
index 2e4be10b..2854ff3e 100755..100644
--- 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
index c92236bf..dd795b0b 100755..100644
--- 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
index 58331b81..58331b81 100755..100644
--- a/CPP/7zip/Bundles/SFXCon/resource.rc
+++ b/CPP/7zip/Bundles/SFXCon/resource.rc
diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractCallback.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp
index 9b733da0..9fe98fc0 100755..100644
--- a/CPP/7zip/Bundles/SFXSetup/ExtractCallback.cpp
+++ b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp
@@ -1,18 +1,19 @@
-// ExtractCallback.h
+// ExtractCallbackSfx.h
#include "StdAfx.h"
-#include "Common/Wildcard.h"
+#include "../../../Common/Wildcard.h"
-#include "Windows/FileDir.h"
-#include "Windows/FileFind.h"
-#include "Windows/FileName.h"
-#include "Windows/PropVariant.h"
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileFind.h"
+#include "../../../Windows/FileName.h"
+#include "../../../Windows/PropVariant.h"
-#include "ExtractCallback.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";
@@ -78,10 +79,10 @@ STDMETHODIMP CExtractCallbackImp::SetCompleted(const UInt64 *completeValue)
void CExtractCallbackImp::CreateComplexDirectory(const UStringVector &dirPathParts)
{
FString fullPath = _directoryPath;
- for (int i = 0; i < dirPathParts.Size(); i++)
+ FOR_VECTOR (i, dirPathParts)
{
fullPath += us2fs(dirPathParts[i]);
- NDirectory::MyCreateDirectory(fullPath);
+ CreateDir(fullPath);
fullPath += FCHAR_PATH_SEPARATOR;
}
}
@@ -161,16 +162,16 @@ STDMETHODIMP CExtractCallbackImp::GetStream(UInt32 index,
_diskFilePath = fullProcessedPath;
if (isAnti)
- NDirectory::MyRemoveDirectory(_diskFilePath);
+ RemoveDir(_diskFilePath);
else
- NDirectory::SetDirTime(_diskFilePath, NULL, NULL, &_processedFileInfo.MTime);
+ SetDirTime(_diskFilePath, NULL, NULL, &_processedFileInfo.MTime);
return S_OK;
}
NFind::CFileInfo fileInfo;
if (fileInfo.Find(fullProcessedPath))
{
- if (!NDirectory::DeleteFileAlways(fullProcessedPath))
+ if (!DeleteFileAlways(fullProcessedPath))
{
_message = kCantDeleteFile;
return E_FAIL;
@@ -216,7 +217,7 @@ STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 resultEOperationResul
_outFileStream.Release();
switch(resultEOperationResult)
{
- case NArchive::NExtract::NOperationResult::kUnSupportedMethod:
+ case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
_message = kUnsupportedMethod;
break;
default:
@@ -232,6 +233,6 @@ STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 resultEOperationResul
}
_outFileStream.Release();
if (_extractMode)
- NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attributes);
+ SetFileAttrib(_diskFilePath, _processedFileInfo.Attributes);
return S_OK;
}
diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractCallback.h b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.h
index 128988f9..cfbc5c07 100755..100644
--- a/CPP/7zip/Bundles/SFXSetup/ExtractCallback.h
+++ b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.h
@@ -1,17 +1,19 @@
-// ExtractCallback.h
+// ExtractCallbackSfx.h
-#ifndef __EXTRACT_CALLBACK_H
-#define __EXTRACT_CALLBACK_H
+#ifndef __EXTRACT_CALLBACK_SFX_H
+#define __EXTRACT_CALLBACK_SFX_H
#include "resource.h"
-#include "Windows/ResourceString.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
@@ -70,11 +72,7 @@ public:
{
ProgressDialog.Create(title, thread, 0);
{
- #ifdef LANG
- ProgressDialog.SetText(LangLoadString(IDS_PROGRESS_EXTRACTING, 0x02000890));
- #else
- ProgressDialog.SetText(NWindows::MyLoadStringW(IDS_PROGRESS_EXTRACTING));
- #endif
+ ProgressDialog.SetText(LangString(IDS_PROGRESS_EXTRACTING));
}
ProgressDialog.Show(SW_SHOWNORMAL);
diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp
index 8f830de5..ba41fd1a 100755..100644
--- 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<COpenType> incl;
+ CIntVector excl;
+ COpenOptions options;
+ options.codecs = Codecs;
+ options.types = &incl;
+ options.excludedFormats = &excl;
+ 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
index 295d77b9..295d77b9 100755..100644
--- a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h
+++ b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h
diff --git a/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp
index 68fe84d6..3a8ae36b 100755..100644
--- 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
index f563b21f..f563b21f 100755..100644
--- a/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw
+++ b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw
diff --git a/CPP/7zip/Bundles/SFXSetup/Main.cpp b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
index 008c0e42..20bde9e9 100755..100644
--- a/CPP/7zip/Bundles/SFXSetup/Main.cpp
+++ b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
@@ -2,19 +2,20 @@
#include "StdAfx.h"
-#include "Common/MyInitGuid.h"
+#include "../../../Common/MyInitGuid.h"
-#include "Common/CommandLineParser.h"
-#include "Common/StringConvert.h"
-#include "Common/TextConfig.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 "../../../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"
@@ -23,6 +24,8 @@
#include "resource.h"
using namespace NWindows;
+using namespace NFile;
+using namespace NDir;
HINSTANCE g_hInstance;
@@ -34,7 +37,7 @@ static bool ReadDataString(CFSTR fileName, LPCSTR startID,
LPCSTR endID, AString &stringResult)
{
stringResult.Empty();
- NFile::NIO::CInFile inFile;
+ NIO::CInFile inFile;
if (!inFile.Open(fileName))
return false;
const int kBufferSize = (1 << 12);
@@ -105,19 +108,20 @@ public:
} 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;
+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
@@ -143,10 +147,10 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
switches.Trim();
bool assumeYes = false;
- if (switches.Left(2).CompareNoCase(UString(L"-y")) == 0)
+ if (MyStringCompareNoCase_N(switches, L"-y", 2) == 0)
{
assumeYes = true;
- switches = switches.Mid(2);
+ switches = switches.Ptr(2);
switches.Trim();
}
@@ -173,7 +177,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
UString friendlyName = GetTextConfigValue(pairs, L"Title");
UString installPrompt = GetTextConfigValue(pairs, L"BeginPrompt");
UString progress = GetTextConfigValue(pairs, L"Progress");
- if (progress.CompareNoCase(L"no") == 0)
+ if (progress.IsEqualToNoCase(L"no"))
showProgress = false;
int index = FindTextConfigItem(pairs, L"Directory");
if (index >= 0)
@@ -188,11 +192,11 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
#ifdef _SHELL_EXECUTE
executeFile = GetTextConfigValue(pairs, L"ExecuteFile");
- executeParameters = GetTextConfigValue(pairs, L"ExecuteParameters") + switches;
+ executeParameters = GetTextConfigValue(pairs, L"ExecuteParameters");
#endif
}
- NFile::NDirectory::CTempDir tempDir;
+ CTempDir tempDir;
if (!tempDir.Create(kTempDirPrefix))
{
if (!assumeYes)
@@ -209,7 +213,8 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
return 1;
}
- FString tempDirPath = tempDir.GetPath();
+ const FString tempDirPath = tempDir.GetPath();
+ // tempDirPath = L"M:\\1\\"; // to test low disk space
{
bool isCorrupt = false;
UString errorMessage;
@@ -222,11 +227,15 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
{
if (result == S_FALSE || isCorrupt)
{
- errorMessage = NWindows::MyLoadStringW(IDS_EXTRACTION_ERROR_MESSAGE);
+ NWindows::MyLoadString(IDS_EXTRACTION_ERROR_MESSAGE, errorMessage);
result = E_FAIL;
}
- if (result != E_ABORT && !errorMessage.IsEmpty())
- ::MessageBoxW(0, errorMessage, NWindows::MyLoadStringW(IDS_EXTRACTION_ERROR_TITLE), MB_ICONERROR);
+ if (result != E_ABORT)
+ {
+ if (errorMessage.IsEmpty())
+ errorMessage = NError::MyFormatMessage(result);
+ ::MessageBoxW(0, errorMessage, NWindows::MyLoadString(IDS_EXTRACTION_ERROR_TITLE), MB_ICONERROR);
+ }
}
return 1;
}
@@ -234,7 +243,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
#ifndef UNDER_CE
CCurrentDirRestorer currentDirRestorer;
- if (!NFile::NDirectory::MySetCurrentDirectory(tempDir.GetPath()))
+ if (!SetCurrentDir(tempDirPath))
return 1;
#endif
@@ -255,7 +264,11 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
execInfo.lpFile = filePath;
if (!switches.IsEmpty())
+ {
+ if (!executeParameters.IsEmpty())
+ executeParameters += L' ';
executeParameters += switches;
+ }
CSysString parametersSys = GetSystemString(executeParameters);
if (parametersSys.IsEmpty())
@@ -282,7 +295,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
if (appLaunched.IsEmpty())
{
appLaunched = L"setup.exe";
- if (!NFile::NFind::DoesFileExist(us2fs(appLaunched)))
+ if (!NFind::DoesFileExist(us2fs(appLaunched)))
{
if (!assumeYes)
ShowErrorMessage(L"Can not find setup.exe");
@@ -292,10 +305,12 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
{
FString s2 = tempDirPath;
- NFile::NName::NormalizeDirPathPrefix(s2);
+ 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())
@@ -322,7 +337,11 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
if (createResult == 0)
{
if (!assumeYes)
- ShowLastErrorMessage();
+ {
+ // 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);
diff --git a/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp b/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp
index d0feea85..d0feea85 100755..100644
--- a/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp
+++ b/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp
diff --git a/CPP/7zip/Bundles/SFXSetup/StdAfx.h b/CPP/7zip/Bundles/SFXSetup/StdAfx.h
index 19ece34b..37bbd0c3 100755..100644
--- 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 <commctrl.h>
+// #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
index 9136e432..ac5c6aa4 100755..100644
--- 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
index 58cd13cb..d5f440bb 100755..100644
--- 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
index 8ccdcf2c..47e1b762 100755..100644
--- 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
index bb455be1..bb455be1 100755..100644
--- a/CPP/7zip/Bundles/SFXSetup/setup.ico
+++ b/CPP/7zip/Bundles/SFXSetup/setup.ico
Binary files differ
diff --git a/CPP/7zip/Bundles/SFXWin/7z.ico b/CPP/7zip/Bundles/SFXWin/7z.ico
index 47ffb781..47ffb781 100755..100644
--- a/CPP/7zip/Bundles/SFXWin/7z.ico
+++ b/CPP/7zip/Bundles/SFXWin/7z.ico
Binary files differ
diff --git a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp
index 9cd7e8d2..55dbe377 100755..100644
--- 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
index a9926c71..a9926c71 100755..100644
--- a/CPP/7zip/Bundles/SFXWin/SFXWin.dsw
+++ b/CPP/7zip/Bundles/SFXWin/SFXWin.dsw
diff --git a/CPP/7zip/Bundles/SFXWin/Main.cpp b/CPP/7zip/Bundles/SFXWin/SfxWin.cpp
index bd72fc08..ee57d445 100755..100644
--- a/CPP/7zip/Bundles/SFXWin/Main.cpp
+++ b/CPP/7zip/Bundles/SFXWin/SfxWin.cpp
@@ -2,17 +2,19 @@
#include "StdAfx.h"
-#include "Common/MyInitGuid.h"
+#include <Shlwapi.h>
-#include "Common/CommandLineParser.h"
-#include "Common/StringConvert.h"
+#include "../../../Common/MyInitGuid.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 "../../../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"
@@ -24,12 +26,41 @@
#include "../../UI/GUI/ExtractGUI.h"
#include "../../UI/GUI/ExtractRes.h"
+using namespace NWindows;
+using namespace NFile;
+using namespace NDir;
+
HINSTANCE g_hInstance;
-#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 const wchar_t *kUnknownExceptionMessage = L"ERROR: Unknown Error!";
void ErrorMessageForHRESULT(HRESULT res)
@@ -43,6 +74,11 @@ int APIENTRY WinMain2()
#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;
@@ -56,28 +92,39 @@ int APIENTRY WinMain2()
commandStrings.Delete(0);
#endif
- for (int i = 0; i < commandStrings.Size(); i++)
+ FOR_VECTOR (i, commandStrings)
{
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)
+ if (s.Len() > 1 && s[0] == '-')
{
- password = s.Mid(2);
+ 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;
- NWindows::NDLL::MyGetModuleFileName(path);
+ NDLL::MyGetModuleFileName(path);
FString fullPath;
- if (!NWindows::NFile::NDirectory::MyGetFullPathName(path, fullPath))
+ if (!MyGetFullPathName(path, fullPath))
{
ShowErrorMessage(L"Error 1329484");
return 1;
@@ -109,7 +156,7 @@ int APIENTRY WinMain2()
CExtractOptions eo;
FString dirPrefix;
- if (!NWindows::NFile::NDirectory::GetOnlyDirPrefix(path, dirPrefix))
+ if (!GetOnlyDirPrefix(path, dirPrefix))
{
ShowErrorMessage(L"Error 1329485");
return 1;
@@ -118,19 +165,21 @@ int APIENTRY WinMain2()
eo.OutputDir = outputFolderDefined ? outputFolder : dirPrefix;
eo.YesToAll = assumeYes;
eo.OverwriteMode = assumeYes ?
- NExtract::NOverwriteMode::kWithoutPrompt :
- NExtract::NOverwriteMode::kAskBefore;
- eo.PathMode = NExtract::NPathMode::kFullPathnames;
+ 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);
+ wildcardCensor.AddItem(true, L"*", true, true, true, true);
bool messageWasDisplayed = false;
- result = ExtractGUI(codecs, CIntVector(), v1, v2,
+ result = ExtractGUI(codecs,
+ CObjectVector<COpenType>(), CIntVector(),
+ v1, v2,
wildcardCensor, eo, (assumeYes ? false: true), messageWasDisplayed, ecs);
if (result == S_OK)
diff --git a/CPP/7zip/Bundles/SFXWin/StdAfx.cpp b/CPP/7zip/Bundles/SFXWin/StdAfx.cpp
index d0feea85..d0feea85 100755..100644
--- a/CPP/7zip/Bundles/SFXWin/StdAfx.cpp
+++ b/CPP/7zip/Bundles/SFXWin/StdAfx.cpp
diff --git a/CPP/7zip/Bundles/SFXWin/StdAfx.h b/CPP/7zip/Bundles/SFXWin/StdAfx.h
index c5f7231f..975a17e8 100755..100644
--- 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 <commctrl.h>
#include <ShlObj.h>
+// #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
index 458ac665..d6e1de78 100755..100644
--- 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
index 99878ee6..30fe2030 100755..100644
--- 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
index 35234cae..91292b2f 100755..100644
--- 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
index e3b4b88f..e3b4b88f 100755..100644
--- a/CPP/7zip/Bundles/makefile
+++ b/CPP/7zip/Bundles/makefile
diff --git a/CPP/7zip/Common/CWrappers.cpp b/CPP/7zip/Common/CWrappers.cpp
index ef21228e..e67f5bc4 100755..100644
--- 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
index 80a8a1b6..acadc170 100755..100644
--- 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
index cc82a0db..c586561d 100755..100644
--- 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<CCodecInfoEx> &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<CCodecInfoEx> *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<CCodecInfoEx> *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<CMethodId> &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<IHasher> &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
index bf0e96a3..50a68ce1 100755..100644
--- 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<CCodecInfoEx> &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<ICompressCodecsInfo> GetCodecs;
+ CMyComPtr<IHashers> GetHashers;
+
+ CObjectVector<CCodecInfoEx> Codecs;
+ CObjectVector<CHasherInfoEx> Hashers;
+
+ HRESULT LoadCodecs();
+};
-#define DECL_EXTERNAL_CODECS_VARS CMyComPtr<ICompressCodecsInfo> _codecsInfo; CObjectVector<CCodecInfoEx> _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<CCodecInfoEx> *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<CMethodId> &methods);
HRESULT CreateCoder(
DECL_EXTERNAL_CODECS_LOC_VARS
@@ -95,4 +118,10 @@ HRESULT CreateFilter(
CMyComPtr<ICompressFilter> &filter,
bool encode);
+HRESULT CreateHasher(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId,
+ UString &name,
+ CMyComPtr<IHasher> &hacher);
+
#endif
diff --git a/CPP/7zip/Common/FilePathAutoRename.cpp b/CPP/7zip/Common/FilePathAutoRename.cpp
index 495f886b..958360fa 100755..100644
--- 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
index eee0aba7..7b576591 100755..100644
--- 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
index a8be8aa4..374336d8 100755..100644
--- 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
index bb2b1d41..971366e9 100755..100644
--- 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
index 69673527..578a3193 100755..100644
--- 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
index 8132a6dd..2b8f142f 100755..100644
--- 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<ICryptoSetPassword> _setPassword;
+ CMyComPtr<ICryptoProperties> _cryptoProperties;
#ifndef EXTRACT_ONLY
CMyComPtr<ICompressSetCoderProperties> _SetCoderProperties;
CMyComPtr<ICompressWriteCoderProperties> _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
index ad4f8825..8edefa31 100755..100644
--- 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
index 75625bfd..4b8662bb 100755..100644
--- 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<ISequentialInStream> _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
index 38c5c92c..d88c2d8a 100755..100644
--- 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
index ec493977..ec493977 100755..100644
--- a/CPP/7zip/Common/InMemStream.h
+++ b/CPP/7zip/Common/InMemStream.h
diff --git a/CPP/7zip/Common/InOutTempBuffer.cpp b/CPP/7zip/Common/InOutTempBuffer.cpp
index 442374da..be65ba32 100755..100644
--- 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
index bdf937de..256d7242 100755..100644
--- 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
index 1837e320..de236040 100755..100644
--- 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<ISequentialInStream> streamTemp = streamSpec;
+ streamSpec->SetStream(inStream);
+ RINOK(streamSpec->InitAndSeek(pos, size));
+ streamSpec->SeekToStart();
+ *resStream = streamTemp.Detach();
+ return S_OK;
+}
+
STDMETHODIMP CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
- if (processedSize != 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<ISequentialInStream> 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
index 2cbe18e4..a9378491 100755..100644
--- 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<IInStream> Stream;
UInt64 StartOffset;
UInt64 Size;
- int BlockSizeLog;
+ unsigned BlockSizeLog;
CRecordVector<UInt32> 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<IInStream> Stream;
+ CRecordVector<CSeekExtent> Extents;
+
+ MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+ void ReleaseStream() { Stream.Release(); }
+
+ void Init()
+ {
+ _virtPos = 0;
+ _phyPos = 0;
+ _needStartSeek = true;
+ }
+};
class CLimitedSequentialOutStream:
public ISequentialOutStream,
@@ -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<IInStream> Stream;
+ UInt64 Offset;
+
+ void Init()
+ {
+ _virtPos = 0;
+ }
+
+ MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+
+ HRESULT SeekToStart() { return Stream->Seek(Offset, STREAM_SEEK_SET, NULL); }
+};
+
+class CLimitedCachedInStream:
+ public IInStream,
+ public CMyUnknownImp
+{
+ CMyComPtr<IInStream> _stream;
+ UInt64 _virtPos;
+ UInt64 _physPos;
+ UInt64 _size;
+ UInt64 _startOffset;
+
+ const Byte *_cache;
+ size_t _cacheSize;
+ size_t _cachePhyPos;
+
+
+ HRESULT SeekToPhys() { return _stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }
+public:
+ CByteBuffer Buffer;
+
+ void SetStream(IInStream *stream) { _stream = stream; }
+ void SetCache(size_t cacheSize, size_t cachePos)
+ {
+ _cache = Buffer;
+ _cacheSize = cacheSize;
+ _cachePhyPos = cachePos;
+ }
+
+ HRESULT InitAndSeek(UInt64 startOffset, UInt64 size)
+ {
+ _startOffset = startOffset;
+ _physPos = startOffset;
+ _virtPos = 0;
+ _size = size;
+ return SeekToPhys();
+ }
+
+ MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+
+ HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); }
+};
+
+class CTailOutStream:
+ public IOutStream,
+ public CMyUnknownImp
+{
+ UInt64 _virtPos;
+ UInt64 _virtSize;
+public:
+ CMyComPtr<IOutStream> Stream;
+ UInt64 Offset;
+
+ virtual ~CTailOutStream() {}
+
+ MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStream)
+
+ void Init()
+ {
+ _virtPos = 0;
+ _virtSize = 0;
+ }
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+ STDMETHOD(SetSize)(UInt64 newSize);
+};
+
#endif
diff --git a/CPP/7zip/Common/LockedStream.cpp b/CPP/7zip/Common/LockedStream.cpp
index f05601cb..f05601cb 100755..100644
--- a/CPP/7zip/Common/LockedStream.cpp
+++ b/CPP/7zip/Common/LockedStream.cpp
diff --git a/CPP/7zip/Common/LockedStream.h b/CPP/7zip/Common/LockedStream.h
index 486e4220..486e4220 100755..100644
--- a/CPP/7zip/Common/LockedStream.h
+++ b/CPP/7zip/Common/LockedStream.h
diff --git a/CPP/7zip/Common/MemBlocks.cpp b/CPP/7zip/Common/MemBlocks.cpp
index a5b93b5e..eb0cc39a 100755..100644
--- 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
index e1058ae3..ec56c14d 100755..100644
--- 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
index 1566c97c..1566c97c 100755..100644
--- a/CPP/7zip/Common/MethodId.cpp
+++ b/CPP/7zip/Common/MethodId.cpp
diff --git a/CPP/7zip/Common/MethodId.h b/CPP/7zip/Common/MethodId.h
index 54ebc9f7..28b615fc 100755..100644
--- 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
index e15a3cc8..f1c34ada 100755..100644
--- a/CPP/7zip/Common/MethodProps.cpp
+++ b/CPP/7zip/Common/MethodProps.cpp
@@ -10,12 +10,12 @@ using namespace NWindows;
bool StringToBool(const UString &s, bool &res)
{
- if (s.IsEmpty() || s.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 &param, 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 &param = 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
index 0bdddc6b..18672bde 100755..100644
--- 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
index c5e4e6da..368d39b6 100755..100644
--- 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
index de9d06dd..9074a24e 100755..100644
--- 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
index 2e5debd8..df254f27 100755..100644
--- 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
index 62e77caa..3bdfb87c 100755..100644
--- 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<ISequentialOutStream> _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
index 2e92886b..768c2d45 100755..100644
--- 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
index b47f339e..0a892c52 100755..100644
--- 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
index 319bd241..319bd241 100755..100644
--- a/CPP/7zip/Common/ProgressMt.cpp
+++ b/CPP/7zip/Common/ProgressMt.cpp
diff --git a/CPP/7zip/Common/ProgressMt.h b/CPP/7zip/Common/ProgressMt.h
index 26079d4e..26079d4e 100755..100644
--- a/CPP/7zip/Common/ProgressMt.h
+++ b/CPP/7zip/Common/ProgressMt.h
diff --git a/CPP/7zip/Common/ProgressUtils.cpp b/CPP/7zip/Common/ProgressUtils.cpp
index f24ff6b6..bac45c1c 100755..100644
--- 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
index bae5395c..bae5395c 100755..100644
--- a/CPP/7zip/Common/ProgressUtils.h
+++ b/CPP/7zip/Common/ProgressUtils.h
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
index bc2a034f..edc3abdd 100755..100644
--- 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
index 786b4a4c..4222a305 100755..100644
--- 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
index ef555ec1..1cbd7fea 100755..100644
--- 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
index 7a4c0ed2..7a4c0ed2 100755..100644
--- a/CPP/7zip/Common/StreamBinder.cpp
+++ b/CPP/7zip/Common/StreamBinder.cpp
diff --git a/CPP/7zip/Common/StreamBinder.h b/CPP/7zip/Common/StreamBinder.h
index f3fb5322..f3fb5322 100755..100644
--- a/CPP/7zip/Common/StreamBinder.h
+++ b/CPP/7zip/Common/StreamBinder.h
diff --git a/CPP/7zip/Common/StreamObjects.cpp b/CPP/7zip/Common/StreamObjects.cpp
index 1b6b0af0..480cb2db 100755..100644
--- 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<ISequentialInStream> 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<IUnknown> ref = referenceBuf;
+ referenceBuf->Buf.CopyFrom((const Byte *)data, size);
+
+ CBufInStream *inStreamSpec = new CBufInStream;
+ CMyComPtr<ISequentialInStream> 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
index 8cd95c70..d0c86b56 100755..100644
--- 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
index 049e4aa1..049e4aa1 100755..100644
--- a/CPP/7zip/Common/StreamUtils.cpp
+++ b/CPP/7zip/Common/StreamUtils.cpp
diff --git a/CPP/7zip/Common/StreamUtils.h b/CPP/7zip/Common/StreamUtils.h
index f1cfd184..ae914c00 100755..100644
--- 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<CByteBuffer> 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
index 77e3c1ac..77e3c1ac 100755..100644
--- a/CPP/7zip/Common/VirtThread.cpp
+++ b/CPP/7zip/Common/VirtThread.cpp
diff --git a/CPP/7zip/Common/VirtThread.h b/CPP/7zip/Common/VirtThread.h
index ebee158c..ebee158c 100755..100644
--- a/CPP/7zip/Common/VirtThread.h
+++ b/CPP/7zip/Common/VirtThread.h
diff --git a/CPP/7zip/Compress/ArjDecoder1.cpp b/CPP/7zip/Compress/ArjDecoder1.cpp
index 2c354e1e..2eaa591c 100755..100644
--- 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
index 17939daf..dd12e445 100755..100644
--- 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
index 365993bc..4903605c 100755..100644
--- 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
index cf00975d..cf544d9e 100755..100644
--- a/CPP/7zip/Compress/ArjDecoder2.h
+++ b/CPP/7zip/Compress/ArjDecoder2.h
@@ -23,12 +23,6 @@ class CCoder :
CLzOutWindow m_OutWindowStream;
NBitm::CDecoder<CInBuffer> 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
index 62427aa6..62427aa6 100755..100644
--- a/CPP/7zip/Compress/BZip2Const.h
+++ b/CPP/7zip/Compress/BZip2Const.h
diff --git a/CPP/7zip/Compress/BZip2Crc.cpp b/CPP/7zip/Compress/BZip2Crc.cpp
index 4e4741f4..4e4741f4 100755..100644
--- a/CPP/7zip/Compress/BZip2Crc.cpp
+++ b/CPP/7zip/Compress/BZip2Crc.cpp
diff --git a/CPP/7zip/Compress/BZip2Crc.h b/CPP/7zip/Compress/BZip2Crc.h
index 876945b5..1b5755b5 100755..100644
--- 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
index cb1f981a..3798421e 100755..100644
--- 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<CInBuffer> *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<CInBuffer> *m_InStream)
-{
- return m_InStream->ReadBits(1);
-}
+ NumBlocks++;
-static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder<CInBuffer> *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<CInBuffer> *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<CInBuffer> *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<CInBuffer> *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<CInBuffer> *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<CInBuffer> *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<CInBuffer> *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<CInBuffer> *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<CInBuffer> *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
index e6dec1ea..2c28c5a1 100755..100644
--- 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<kMaxHuffmanLen, kMaxAlphaSize> 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<ISequentialInStream> InStreamRef;
+ NBitm::CDecoder<CInBuffer> 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<CInBuffer> 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<CInBuffer> 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
index 6dafc45f..2bdbe989 100755..100644
--- 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
index 5aa8a786..6b04eca1 100755..100644
--- 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
index ef14204b..ef14204b 100755..100644
--- a/CPP/7zip/Compress/BZip2Register.cpp
+++ b/CPP/7zip/Compress/BZip2Register.cpp
diff --git a/CPP/7zip/Compress/Bcj2Coder.cpp b/CPP/7zip/Compress/Bcj2Coder.cpp
index 684da5ab..2d737e8a 100755..100644
--- 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<ICompressGetSubStreamSize> 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
index 79a713f1..d2b3bda3 100755..100644
--- 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<kNumMoveBits> _statusEncoder[256 + 2];
+ NRangeCoder::CEncoder _rc;
+ NRangeCoder::CBitEncoder<kNumMoveBits> _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<kNumMoveBits> _statusDecoder[256 + 2];
+ NRangeCoder::CDecoder _rc;
+ NRangeCoder::CBitDecoder<kNumMoveBits> _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
index 8eb1e736..8eb1e736 100755..100644
--- a/CPP/7zip/Compress/Bcj2Register.cpp
+++ b/CPP/7zip/Compress/Bcj2Register.cpp
diff --git a/CPP/7zip/Compress/BcjCoder.cpp b/CPP/7zip/Compress/BcjCoder.cpp
index 0e34ef48..0e34ef48 100755..100644
--- a/CPP/7zip/Compress/BcjCoder.cpp
+++ b/CPP/7zip/Compress/BcjCoder.cpp
diff --git a/CPP/7zip/Compress/BcjCoder.h b/CPP/7zip/Compress/BcjCoder.h
index 0754bcd2..0754bcd2 100755..100644
--- a/CPP/7zip/Compress/BcjCoder.h
+++ b/CPP/7zip/Compress/BcjCoder.h
diff --git a/CPP/7zip/Compress/BcjRegister.cpp b/CPP/7zip/Compress/BcjRegister.cpp
index 648ad8e0..648ad8e0 100755..100644
--- a/CPP/7zip/Compress/BcjRegister.cpp
+++ b/CPP/7zip/Compress/BcjRegister.cpp
diff --git a/CPP/7zip/Compress/BitlDecoder.cpp b/CPP/7zip/Compress/BitlDecoder.cpp
index 78665be8..516b0932 100755..100644
--- 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
index ff373bac..27be1716 100755..100644
--- 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 TInByte>
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 TInByte>
class CDecoder: public CBaseDecoder<TInByte>
{
- UInt32 m_NormalValue;
+ UInt32 _normalValue;
public:
void Init()
{
CBaseDecoder<TInByte>::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
index 7de57545..22b83545 100755..100644
--- 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
index 4369b452..fef20e06 100755..100644
--- 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 TInByte>
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
index a85dbff8..05079ace 100755..100644
--- a/CPP/7zip/Compress/BitmEncoder.h
+++ b/CPP/7zip/Compress/BitmEncoder.h
@@ -8,41 +8,40 @@
template<class TOutByte>
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
index 43170952..43170952 100755..100644
--- a/CPP/7zip/Compress/BranchCoder.cpp
+++ b/CPP/7zip/Compress/BranchCoder.cpp
diff --git a/CPP/7zip/Compress/BranchCoder.h b/CPP/7zip/Compress/BranchCoder.h
index 0e3a5c4e..0e3a5c4e 100755..100644
--- a/CPP/7zip/Compress/BranchCoder.h
+++ b/CPP/7zip/Compress/BranchCoder.h
diff --git a/CPP/7zip/Compress/BranchMisc.cpp b/CPP/7zip/Compress/BranchMisc.cpp
index 423b723a..239f2513 100755..100644
--- 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
index 81198b21..81198b21 100755..100644
--- a/CPP/7zip/Compress/BranchMisc.h
+++ b/CPP/7zip/Compress/BranchMisc.h
diff --git a/CPP/7zip/Compress/BranchRegister.cpp b/CPP/7zip/Compress/BranchRegister.cpp
index 380828c6..380828c6 100755..100644
--- a/CPP/7zip/Compress/BranchRegister.cpp
+++ b/CPP/7zip/Compress/BranchRegister.cpp
diff --git a/CPP/7zip/Compress/ByteSwap.cpp b/CPP/7zip/Compress/ByteSwap.cpp
index 645b6ffc..645b6ffc 100755..100644
--- a/CPP/7zip/Compress/ByteSwap.cpp
+++ b/CPP/7zip/Compress/ByteSwap.cpp
diff --git a/CPP/7zip/Compress/Codec.def b/CPP/7zip/Compress/Codec.def
index ebf73a3b..ebf73a3b 100755..100644
--- a/CPP/7zip/Compress/Codec.def
+++ b/CPP/7zip/Compress/Codec.def
diff --git a/CPP/7zip/Compress/CodecExports.cpp b/CPP/7zip/Compress/CodecExports.cpp
index 4ff1c0fc..726d35fc 100755..100644
--- 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
index f71692a7..f0863202 100755..100644
--- 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<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
+ CMyComPtr<ICompressCoder> copyCoder = new CCopyCoder;
return copyCoder->Code(inStream, outStream, NULL, NULL, progress);
}
+HRESULT CopyStream_ExactSize(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 size, ICompressProgressInfo *progress)
+{
+ NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
+ CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+ RINOK(copyCoder->Code(inStream, outStream, NULL, &size, progress));
+ return copyCoderSpec->TotalSize == size ? S_OK : E_FAIL;
+}
+
}
diff --git a/CPP/7zip/Compress/CopyCoder.h b/CPP/7zip/Compress/CopyCoder.h
index c5445ccf..5e0bb643 100755..100644
--- 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
index efb9b9e9..efb9b9e9 100755..100644
--- a/CPP/7zip/Compress/CopyRegister.cpp
+++ b/CPP/7zip/Compress/CopyRegister.cpp
diff --git a/CPP/7zip/Compress/Deflate64Register.cpp b/CPP/7zip/Compress/Deflate64Register.cpp
index 509e675a..509e675a 100755..100644
--- a/CPP/7zip/Compress/Deflate64Register.cpp
+++ b/CPP/7zip/Compress/Deflate64Register.cpp
diff --git a/CPP/7zip/Compress/DeflateConst.h b/CPP/7zip/Compress/DeflateConst.h
index 00e5ab8b..c3ae5719 100755..100644
--- 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
index 2848cd81..5285e143 100755..100644
--- 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
index 56ab2bea..856a5771 100755..100644
--- 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<ISequentialInStream> m_InStreamRef;
NBitl::CDecoder<CInBuffer> m_InBitStream;
NCompress::NHuffman::CDecoder<kNumHuffmanBits, kFixedMainTableSize> m_MainDecoder;
NCompress::NHuffman::CDecoder<kNumHuffmanBits, kFixedDistTableSize> 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
index 813b6de4..392ee93d 100755..100644
--- 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
index f25d802e..d8e88f89 100755..100644
--- 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<ISequentialInStream> 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
index 45f55219..45f55219 100755..100644
--- a/CPP/7zip/Compress/DeflateRegister.cpp
+++ b/CPP/7zip/Compress/DeflateRegister.cpp
diff --git a/CPP/7zip/Compress/DeltaFilter.cpp b/CPP/7zip/Compress/DeltaFilter.cpp
index d8378a60..d8378a60 100755..100644
--- a/CPP/7zip/Compress/DeltaFilter.cpp
+++ b/CPP/7zip/Compress/DeltaFilter.cpp
diff --git a/CPP/7zip/Compress/DllExports2.cpp b/CPP/7zip/Compress/DllExports2Compress.cpp
index 286ef08b..286ef08b 100755..100644
--- a/CPP/7zip/Compress/DllExports2.cpp
+++ b/CPP/7zip/Compress/DllExports2Compress.cpp
diff --git a/CPP/7zip/Compress/DllExports.cpp b/CPP/7zip/Compress/DllExportsCompress.cpp
index 6af7e5ec..8b37c899 100755..100644
--- a/CPP/7zip/Compress/DllExports.cpp
+++ b/CPP/7zip/Compress/DllExportsCompress.cpp
@@ -1,4 +1,4 @@
-// DllExports.cpp
+// DllExportsCompress.cpp
#include "StdAfx.h"
@@ -8,8 +8,8 @@
#include "../Common/RegisterCodec.h"
-static const unsigned int kNumCodecsMax = 32;
-unsigned int g_NumCodecs = 0;
+static const unsigned kNumCodecsMax = 48;
+unsigned g_NumCodecs = 0;
const CCodecInfo *g_Codecs[kNumCodecsMax];
void RegisterCodec(const CCodecInfo *codecInfo)
{
@@ -17,6 +17,15 @@ void RegisterCodec(const CCodecInfo *codecInfo)
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(
@@ -42,4 +51,3 @@ 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
index 82a1e6f2..21f96f0d 100755..100644
--- 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
index f84a013c..e1d68a43 100755..100644
--- 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
index 7ea1553e..5876ecac 100755..100644
--- 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
index 64345e08..2170326e 100755..100644
--- 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
index 6120a35a..6120a35a 100755..100644
--- a/CPP/7zip/Compress/ImplodeHuffmanDecoder.h
+++ b/CPP/7zip/Compress/ImplodeHuffmanDecoder.h
diff --git a/CPP/7zip/Compress/LzOutWindow.cpp b/CPP/7zip/Compress/LzOutWindow.cpp
index df46295b..df46295b 100755..100644
--- a/CPP/7zip/Compress/LzOutWindow.cpp
+++ b/CPP/7zip/Compress/LzOutWindow.cpp
diff --git a/CPP/7zip/Compress/LzOutWindow.h b/CPP/7zip/Compress/LzOutWindow.h
index d8d13c22..507aa7f4 100755..100644
--- 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
index 6f9b5065..ad6e873a 100755..100644
--- 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
index ed631e20..a805f9f9 100755..100644
--- a/CPP/7zip/Compress/LzhDecoder.h
+++ b/CPP/7zip/Compress/LzhDecoder.h
@@ -56,11 +56,12 @@ class CCoder :
CHuffmanDecoder<kNumDistanceSymbols> m_PHuffmanDecoder;
CHuffmanDecoder<kNumCSymbols> 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
index 322015e2..322015e2 100755..100644
--- a/CPP/7zip/Compress/Lzma2Decoder.cpp
+++ b/CPP/7zip/Compress/Lzma2Decoder.cpp
diff --git a/CPP/7zip/Compress/Lzma2Decoder.h b/CPP/7zip/Compress/Lzma2Decoder.h
index fd7ca2f3..fd7ca2f3 100755..100644
--- a/CPP/7zip/Compress/Lzma2Decoder.h
+++ b/CPP/7zip/Compress/Lzma2Decoder.h
diff --git a/CPP/7zip/Compress/Lzma2Encoder.cpp b/CPP/7zip/Compress/Lzma2Encoder.cpp
index 5e4c71be..5e4c71be 100755..100644
--- a/CPP/7zip/Compress/Lzma2Encoder.cpp
+++ b/CPP/7zip/Compress/Lzma2Encoder.cpp
diff --git a/CPP/7zip/Compress/Lzma2Encoder.h b/CPP/7zip/Compress/Lzma2Encoder.h
index f0fb74d3..f0fb74d3 100755..100644
--- a/CPP/7zip/Compress/Lzma2Encoder.h
+++ b/CPP/7zip/Compress/Lzma2Encoder.h
diff --git a/CPP/7zip/Compress/Lzma2Register.cpp b/CPP/7zip/Compress/Lzma2Register.cpp
index cace871e..cace871e 100755..100644
--- a/CPP/7zip/Compress/Lzma2Register.cpp
+++ b/CPP/7zip/Compress/Lzma2Register.cpp
diff --git a/CPP/7zip/Compress/LzmaDecoder.cpp b/CPP/7zip/Compress/LzmaDecoder.cpp
index b7c260bd..a7ee31ba 100755..100644
--- 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
index d28a4634..754eaa3f 100755..100644
--- 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
index 80e12f18..484d0452 100755..100644
--- 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
index 904c0002..3ed067f1 100755..100644
--- 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
index 96ed0bae..96ed0bae 100755..100644
--- a/CPP/7zip/Compress/LzmaRegister.cpp
+++ b/CPP/7zip/Compress/LzmaRegister.cpp
diff --git a/CPP/7zip/Compress/Lzx.h b/CPP/7zip/Compress/Lzx.h
index 09ab7f07..09ab7f07 100755..100644
--- a/CPP/7zip/Compress/Lzx.h
+++ b/CPP/7zip/Compress/Lzx.h
diff --git a/CPP/7zip/Compress/Lzx86Converter.cpp b/CPP/7zip/Compress/Lzx86Converter.cpp
index 9e53f18a..3a63057a 100755..100644
--- 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
index 9f110c29..1e531d1a 100755..100644
--- 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<ISequentialOutStream> 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
index 924229e9..acf3b037 100755..100644
--- 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
index 73a05061..62d5b488 100755..100644
--- 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<ISequentialInStream> 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
index d15dd4a5..5d49fe44 100755..100644
--- 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
index c02f44f1..c02f44f1 100755..100644
--- a/CPP/7zip/Compress/PpmdDecoder.cpp
+++ b/CPP/7zip/Compress/PpmdDecoder.cpp
diff --git a/CPP/7zip/Compress/PpmdDecoder.h b/CPP/7zip/Compress/PpmdDecoder.h
index 8ebcd700..8ebcd700 100755..100644
--- a/CPP/7zip/Compress/PpmdDecoder.h
+++ b/CPP/7zip/Compress/PpmdDecoder.h
diff --git a/CPP/7zip/Compress/PpmdEncoder.cpp b/CPP/7zip/Compress/PpmdEncoder.cpp
index 5bf83529..5bf83529 100755..100644
--- a/CPP/7zip/Compress/PpmdEncoder.cpp
+++ b/CPP/7zip/Compress/PpmdEncoder.cpp
diff --git a/CPP/7zip/Compress/PpmdEncoder.h b/CPP/7zip/Compress/PpmdEncoder.h
index fb74cf57..fb74cf57 100755..100644
--- a/CPP/7zip/Compress/PpmdEncoder.h
+++ b/CPP/7zip/Compress/PpmdEncoder.h
diff --git a/CPP/7zip/Compress/PpmdRegister.cpp b/CPP/7zip/Compress/PpmdRegister.cpp
index 9f59fcdd..9f59fcdd 100755..100644
--- a/CPP/7zip/Compress/PpmdRegister.cpp
+++ b/CPP/7zip/Compress/PpmdRegister.cpp
diff --git a/CPP/7zip/Compress/PpmdZip.cpp b/CPP/7zip/Compress/PpmdZip.cpp
index 036f3c72..036f3c72 100755..100644
--- a/CPP/7zip/Compress/PpmdZip.cpp
+++ b/CPP/7zip/Compress/PpmdZip.cpp
diff --git a/CPP/7zip/Compress/PpmdZip.h b/CPP/7zip/Compress/PpmdZip.h
index e15a060d..e15a060d 100755..100644
--- a/CPP/7zip/Compress/PpmdZip.h
+++ b/CPP/7zip/Compress/PpmdZip.h
diff --git a/CPP/7zip/Compress/QuantumDecoder.cpp b/CPP/7zip/Compress/QuantumDecoder.cpp
index 63da32cc..b184dfb6 100755..100644
--- 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
index a5f78358..c18ea2aa 100755..100644
--- 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<ISequentialInStream> 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
index 1eb2a6d4..0b0d44ae 100755..100644
--- 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
index b5a1830d..0eddd558 100755..100644
--- 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 <int numMoveBits>
+template <unsigned numMoveBits>
class CBitModel
{
public:
@@ -39,7 +39,7 @@ public:
void Init() { Prob = kBitModelTotal / 2; }
};
-template <int numMoveBits>
+template <unsigned numMoveBits>
class CBitEncoder: public CBitModel<numMoveBits>
{
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 <int numMoveBits>
+template <unsigned numMoveBits>
class CBitDecoder: public CBitModel<numMoveBits>
{
public:
diff --git a/CPP/7zip/Compress/Rar1Decoder.cpp b/CPP/7zip/Compress/Rar1Decoder.cpp
index eadca7b3..8eb904df 100755..100644
--- 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
index f7c08b38..630f0893 100755..100644
--- 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
index 4e669bd6..1773939c 100755..100644
--- 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
index 61a8b4da..44b262c1 100755..100644
--- 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
index dde7c6de..3c70e1c0 100755..100644
--- 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<Byte> &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
index 99b647dc..77379858 100755..100644
--- 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<ISequentialOutStream> _outStream;
+ ISequentialOutStream *_outStream;
NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> m_MainDecoder;
NHuffman::CDecoder<kNumHuffmanBits, kDistTableSize> m_DistDecoder;
NHuffman::CDecoder<kNumHuffmanBits, kAlignTableSize> 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
index 74051dd7..5b113bfa 100755..100644
--- 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
index c02534c6..55842b90 100755..100644
--- 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<CCommand> Commands;
#ifdef RARVM_STANDARD_FILTERS
int StandardFilterIndex;
#endif
CRecordVector<Byte> 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<Byte> &outGlobalData);
diff --git a/CPP/7zip/Compress/RarCodecsRegister.cpp b/CPP/7zip/Compress/RarCodecsRegister.cpp
index e3f6a05c..e3f6a05c 100755..100644
--- a/CPP/7zip/Compress/RarCodecsRegister.cpp
+++ b/CPP/7zip/Compress/RarCodecsRegister.cpp
diff --git a/CPP/7zip/Compress/ShrinkDecoder.cpp b/CPP/7zip/Compress/ShrinkDecoder.cpp
index a89d323c..a89d323c 100755..100644
--- a/CPP/7zip/Compress/ShrinkDecoder.cpp
+++ b/CPP/7zip/Compress/ShrinkDecoder.cpp
diff --git a/CPP/7zip/Compress/ShrinkDecoder.h b/CPP/7zip/Compress/ShrinkDecoder.h
index 9bbecd41..9bbecd41 100755..100644
--- a/CPP/7zip/Compress/ShrinkDecoder.h
+++ b/CPP/7zip/Compress/ShrinkDecoder.h
diff --git a/CPP/7zip/Compress/StdAfx.h b/CPP/7zip/Compress/StdAfx.h
index 99a8aa46..1cbd7fea 100755..100644
--- 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
index e28c6451..7308bc0b 100755..100644
--- a/CPP/7zip/Compress/ZDecoder.cpp
+++ b/CPP/7zip/Compress/ZDecoder.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+// #include <stdio.h>
+
#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
index 2bd83a17..19acd498 100755..100644
--- 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
index 90d6715d..8f3a63cb 100755..100644
--- 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
index 95c11002..8c5e73b0 100755..100644
--- a/CPP/7zip/Compress/ZlibDecoder.h
+++ b/CPP/7zip/Compress/ZlibDecoder.h
@@ -16,13 +16,15 @@ class COutStreamWithAdler:
{
CMyComPtr<ISequentialOutStream> _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
index 09235c33..09235c33 100755..100644
--- a/CPP/7zip/Compress/ZlibEncoder.cpp
+++ b/CPP/7zip/Compress/ZlibEncoder.cpp
diff --git a/CPP/7zip/Compress/ZlibEncoder.h b/CPP/7zip/Compress/ZlibEncoder.h
index 621cc1d0..621cc1d0 100755..100644
--- a/CPP/7zip/Compress/ZlibEncoder.h
+++ b/CPP/7zip/Compress/ZlibEncoder.h
diff --git a/CPP/7zip/Compress/makefile b/CPP/7zip/Compress/makefile
index e981319d..e981319d 100755..100644
--- a/CPP/7zip/Compress/makefile
+++ b/CPP/7zip/Compress/makefile
diff --git a/CPP/7zip/Crc.mak b/CPP/7zip/Crc.mak
index 7f2552c1..7f2552c1 100755..100644
--- a/CPP/7zip/Crc.mak
+++ b/CPP/7zip/Crc.mak
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
index b686fb61..548c674b 100755..100644
--- 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
index 79d723fa..560af5c2 100755..100644
--- 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<CKeyInfo> 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
index 5e57748f..5e57748f 100755..100644
--- a/CPP/7zip/Crypto/7zAesRegister.cpp
+++ b/CPP/7zip/Crypto/7zAesRegister.cpp
diff --git a/CPP/7zip/Crypto/Codec.def b/CPP/7zip/Crypto/Codec.def
index ebf73a3b..ebf73a3b 100755..100644
--- a/CPP/7zip/Crypto/Codec.def
+++ b/CPP/7zip/Crypto/Codec.def
diff --git a/CPP/7zip/Crypto/HmacSha1.cpp b/CPP/7zip/Crypto/HmacSha1.cpp
index a66d6271..a66d6271 100755..100644
--- a/CPP/7zip/Crypto/HmacSha1.cpp
+++ b/CPP/7zip/Crypto/HmacSha1.cpp
diff --git a/CPP/7zip/Crypto/HmacSha1.h b/CPP/7zip/Crypto/HmacSha1.h
index d7181329..d7181329 100755..100644
--- a/CPP/7zip/Crypto/HmacSha1.h
+++ b/CPP/7zip/Crypto/HmacSha1.h
diff --git a/CPP/7zip/Crypto/MyAes.cpp b/CPP/7zip/Crypto/MyAes.cpp
index 70a7dccf..52eaab7a 100755..100644
--- 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
index 60b13845..99a17fef 100755..100644
--- 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
index cbbdec89..cbbdec89 100755..100644
--- a/CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp
+++ b/CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp
diff --git a/CPP/7zip/Crypto/Pbkdf2HmacSha1.h b/CPP/7zip/Crypto/Pbkdf2HmacSha1.h
index bb90e121..6560b8d1 100755..100644
--- a/CPP/7zip/Crypto/Pbkdf2HmacSha1.h
+++ b/CPP/7zip/Crypto/Pbkdf2HmacSha1.h
@@ -5,7 +5,8 @@
#define __CRYPTO_PBKDF2_HMAC_SHA1_H
#include <stddef.h>
-#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
index 3a8c9fbd..0ed65a30 100755..100644
--- 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
index cfdcd60d..cfdcd60d 100755..100644
--- a/CPP/7zip/Crypto/RandGen.h
+++ b/CPP/7zip/Crypto/RandGen.h
diff --git a/CPP/7zip/Crypto/Rar20Crypto.cpp b/CPP/7zip/Crypto/Rar20Crypto.cpp
index c2df0e52..c2df0e52 100755..100644
--- a/CPP/7zip/Crypto/Rar20Crypto.cpp
+++ b/CPP/7zip/Crypto/Rar20Crypto.cpp
diff --git a/CPP/7zip/Crypto/Rar20Crypto.h b/CPP/7zip/Crypto/Rar20Crypto.h
index b9648f59..1b6d6024 100755..100644
--- 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
index b0f00ea8..e8f716d9 100755..100644
--- 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
index 119cc233..9d9ee127 100755..100644
--- 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
index 82ca986c..2f284071 100755..100644
--- 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
index 1bad1f91..df9477d8 100755..100644
--- a/CPP/7zip/Crypto/Sha1.h
+++ b/CPP/7zip/Crypto/Sha1.h
@@ -6,7 +6,8 @@
#define __CRYPTO_SHA1_H
#include <stddef.h>
-#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
index 99a8aa46..1cbd7fea 100755..100644
--- 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
index 08a1818c..4194c02f 100755..100644
--- 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
index f37fe644..980be8b3 100755..100644
--- 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
index baaaf98e..baaaf98e 100755..100644
--- a/CPP/7zip/Crypto/ZipCrypto.cpp
+++ b/CPP/7zip/Crypto/ZipCrypto.cpp
diff --git a/CPP/7zip/Crypto/ZipCrypto.h b/CPP/7zip/Crypto/ZipCrypto.h
index 6f104beb..51b9e301 100755..100644
--- 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
index 1554b348..a8765c26 100755..100644
--- 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
index 151677ea..e3a43000 100755..100644
--- 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
index 736f94da..6b26ddd8 100755..100644
--- a/CPP/7zip/GuiCommon.rc
+++ b/CPP/7zip/GuiCommon.rc
@@ -1,7 +1,12 @@
-#include <winnt.h>
-#include <WinUser.h>
+#include <windows.h>
+
+// #include <winnt.h>
+// #include <WinUser.h>
+
+// for Windows CE:
#include <CommCtrl.h>
+
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
index 0db316a5..8ded1f96 100755..100644
--- 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
index b43997d4..74ee0e45 100755..100644
--- 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
index 8316eb3a..8316eb3a 100755..100644
--- a/CPP/7zip/IDecl.h
+++ b/CPP/7zip/IDecl.h
diff --git a/CPP/7zip/IPassword.h b/CPP/7zip/IPassword.h
index 3ca7b090..7ea45537 100755..100644
--- 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
index d6093f17..a270e693 100755..100644
--- 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
index 165e8baa..bf8dc4ca 100755..100644
--- 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
index 2e657393..952333a8 100755..100644
--- 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
index fab66860..fab66860 100755..100644
--- a/CPP/7zip/MyVersionInfo.rc
+++ b/CPP/7zip/MyVersionInfo.rc
diff --git a/CPP/7zip/PropID.h b/CPP/7zip/PropID.h
index 8f888526..cd56663e 100755..100644
--- 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
index f86ce436..f86ce436 100755..100644
--- a/CPP/7zip/SubBuild.mak
+++ b/CPP/7zip/SubBuild.mak
diff --git a/CPP/7zip/UI/Agent/Agent.cpp b/CPP/7zip/UI/Agent/Agent.cpp
index c11bd490..e4f46f0a 100755..100644
--- 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<IFolderFolder> 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<IFolderFolder> 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<IFolderFolder> 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<IArchiveExtractCallback> 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<COpenType> types;
+ if (!ParseOpenTypes(*_codecs, arcFormat, types))
return S_FALSE;
- RINOK(_archiveLink.Open(_codecs, formatIndices, false, inStream, _archiveFilePath, openArchiveCallback));
+ /*
+ CObjectVector<COptionalOpenProperties> 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<COpenType> 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<IFolderFolder> 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<IArchiveExtractCallback> 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
index cc92b0dd..e06f8576 100755..100644
--- 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<IFolderFolder> _parentFolder;
CMyComPtr<IInFolderArchive> _agent;
CAgent *_agentSpec;
CRecordVector<CProxyItem> _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<UString> 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
index 17f5443a..3fd25670 100755..100644
--- 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<CArcItem> &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<CArcItem> &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<CArcItem> *_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<DWORD> 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<IOutArchive> 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<CUpdatePair2> 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<ISetProperties> 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<IArchiveUpdateCallback> 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<CUpdatePair2> updatePairs;
CUpdateCallbackAgent updateCallbackAgent;
updateCallbackAgent.SetCallback(updateCallback100);
@@ -366,7 +448,12 @@ HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream,
CMyComPtr<IArchiveUpdateCallback> 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<DWORD> 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
index ce9b3bfb..a31a904b 100755..100644
--- 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<unsigned> &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(&currentItemIndex));
}
- 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<unsigned> &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<unsigned> &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(&currentItemIndex));
+ }
+
+ 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
index dcf52f04..1755d444 100755..100644
--- 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<CProxyFolder> Folders;
+ int Parent;
+ CRecordVector<unsigned> Folders;
CObjectVector<CProxyFile> 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<CProxyFolder> 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<unsigned> 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<CProxyFolder2> Folders; // Folders[0] - is root folder
+ CObjArray<CProxyFile2> 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
index 237afa05..81291f44 100755..100644
--- 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<IFolderArchiveExtractCallback> 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
index 3a16a667..13d94bdf 100755..100644
--- 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
index 656602cb..003f6d98 100755..100644
--- 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<IOutStream> 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<IArchiveOpenCallback> openCallback;
@@ -85,12 +163,11 @@ HRESULT CAgentFolder::CommonUpdateOperation(
RINOK(_agentSpec->ReOpen(openCallback));
}
- ////////////////////////////
// Restore FolderItem;
CMyComPtr<IFolderFolder> archiveFolder;
RINOK(_agentSpec->BindToRootFolder(&archiveFolder));
- for (int i = 0; i < pathParts.Size(); i++)
+ FOR_VECTOR (i, pathParts)
{
CMyComPtr<IFolderFolder> 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<IFolderArchiveUpdateCallback> updateCallback100;
if (progress)
@@ -190,11 +277,11 @@ STDMETHODIMP CAgentFolder::CreateFolder(const wchar_t *name, IProgress *progress
CMyComPtr<IProgress> 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<IProgress> 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
index 2357af31..0f87cb55 100755..100644
--- 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
index 3687c3d0..cfdacb2f 100755..100644
--- 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
index 1d5ed17a..3707a93c 100755..100644
--- 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
index d181843d..0c7ae1c9 100755..100644
--- 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 <stdio.h>
+
+#include "../../../Common/Defs.h"
+#include "../../../Common/MyInitGuid.h"
+
+#include "../../../Common/IntToString.h"
+#include "../../../Common/StringConvert.h"
+
+#include "../../../Windows/DLL.h"
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileFind.h"
+#include "../../../Windows/FileName.h"
+#include "../../../Windows/NtCheck.h"
+#include "../../../Windows/PropVariant.h"
+#include "../../../Windows/PropVariantConv.h"
#include "../../Common/FileStreams.h"
#include "../../Archive/IArchive.h"
#include "../../IPassword.h"
-#include "../../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<CDirItem> 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<IOutStream> 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
index 542e2852..8ad7fb13 100755..100644
--- 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
index 598a6d3f..598a6d3f 100755..100644
--- a/CPP/7zip/UI/Client7z/Client7z.dsw
+++ b/CPP/7zip/UI/Client7z/Client7z.dsw
diff --git a/CPP/7zip/UI/Client7z/StdAfx.cpp b/CPP/7zip/UI/Client7z/StdAfx.cpp
index d0feea85..d0feea85 100755..100644
--- a/CPP/7zip/UI/Client7z/StdAfx.cpp
+++ b/CPP/7zip/UI/Client7z/StdAfx.cpp
diff --git a/CPP/7zip/UI/Client7z/StdAfx.h b/CPP/7zip/UI/Client7z/StdAfx.h
index b23436e9..2854ff3e 100755..100644
--- 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 <windows.h>
-#include <stdio.h>
+#include "../../../Common/Common.h"
#endif
diff --git a/CPP/7zip/UI/Client7z/makefile b/CPP/7zip/UI/Client7z/makefile
index 0ff8e72f..99a6d494 100755..100644
--- 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
index 85ec17b4..4d5c7023 100755..100644
--- 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 <stdio.h>
-#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 <@|!><N>ame must be
static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>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<CRenamePair> *renamePairs,
+ const UString &oldName, const UString &newName, NRecursedType::EEnum type,
+ bool wildcardMatching)
+{
+ CRenamePair &pair = renamePairs->AddNew();
+ pair.OldName = oldName;
+ pair.NewName = newName;
+ pair.RecursedType = type;
+ pair.WildcardParsing = wildcardMatching;
+
+ if (!pair.Prepare())
+ {
+ UString val;
+ val += pair.OldName;
+ 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<CRenamePair> *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<CRenamePair> *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<NWildcard::CItem> &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<CProperty> &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<DWORD> 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
index 96646d60..22e3d4bf 100755..100644
--- 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<CProperty> 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
index 9c9c0422..c365d66f 100755..100644
--- 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<UInt32> *realIndices)
+{
+ _hardLinks.Clear();
+
+ if (!_arc->Ask_INode)
+ return S_OK;
+
+ IInArchive *archive = _arc->Archive;
+ CRecordVector<CHardLinkNode> &hardIDs = _hardLinks.IDs;
+
+ {
+ UInt32 numItems;
+ if (realIndices)
+ numItems = realIndices->Size();
+ else
+ {
+ RINOK(archive->GetNumberOfItems(&numItems));
+ }
-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<ISequentialOutStream> 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<ISequentialOutStream> 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<ISequentialOutStream> 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<ISequentialOutStream> 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<ISequentialOutStream> 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<CExtrRefSortPair> 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
index cee7c5b6..ed41ba8d 100755..100644
--- 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<ISequentialOutStream> _stream;
+ UInt64 _size;
+ bool _calculate;
+public:
+ IHashCalc *_hash;
+
+ MY_UNKNOWN_IMP
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+ void SetStream(ISequentialOutStream *stream) { _stream = stream; }
+ void ReleaseStream() { _stream.Release(); }
+ void Init(bool calculate = true)
+ {
+ InitCRC();
+ _size = 0;
+ _calculate = calculate;
+ }
+ void EnableCalc(bool calculate) { _calculate = calculate; }
+ void InitCRC() { _hash->InitForNewFile(); }
+ UInt64 GetSize() const { return _size; }
+};
+
+#endif
+
+struct CExtractNtOptions
+{
+ CBoolPair NtSecurity;
+ CBoolPair SymLinks;
+ CBoolPair HardLinks;
+ CBoolPair AltStreams;
+ bool ReplaceColonForAltStream;
+ bool WriteToAltStreamIfColon;
+
+ 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<CHardLinkNode> IDs;
+ CObjectVector<FString> 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<IFolderArchiveExtractCallback> _extractCallback2;
CMyComPtr<ICompressProgressInfo> _compressProgress;
CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword;
FString _directoryPath;
+ FString _directoryPathFull;
NExtract::NPathMode::EEnum _pathMode;
NExtract::NOverwriteMode::EEnum _overwriteMode;
+ #ifndef _SFX
+
+ CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback;
+ CGetProp *GetProp_Spec;
+ CMyComPtr<IGetProp> GetProp;
+
+ #endif
+
FString _diskFilePath;
UString _filePath;
UInt64 _position;
bool _isSplit;
+ bool _isAltStream;
bool _extractMode;
@@ -69,25 +186,39 @@ class CArchiveExtractCallback:
COutFileStream *_outFileStreamSpec;
CMyComPtr<ISequentialOutStream> _outFileStream;
- COutStreamWithCRC *_crcStreamSpec;
- CMyComPtr<ISequentialOutStream> _crcStream;
+ #ifndef _SFX
+
+ COutStreamWithHash *_hashStreamSpec;
+ CMyComPtr<ISequentialOutStream> _hashStream;
+ bool _hashStreamWasUsed;
+
+ #endif
UStringVector _removePathParts;
+ bool _use_baseParentFolder_mode;
+ UInt32 _baseParentFolder;
bool _stdOutMode;
bool _testMode;
- bool _crcMode;
bool _multiArchives;
CMyComPtr<ICompressProgressInfo> _localProgress;
UInt64 _packTotal;
UInt64 _unpTotal;
+ FStringVector _extractedFolderPaths;
+ CRecordVector<UInt32> _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<UInt32> *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
index 17947dce..dcf6590e 100755..100644
--- 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
index 9513fb2b..99ba086c 100755..100644
--- 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
index be20940c..e698f56f 100755..100644
--- 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<IArchiveOpenCallback> 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<IInStream> 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
index afada4a6..8627de00 100755..100644
--- 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<UInt64> FileSizes;
+
IOpenCallbackUI *Callback;
CMyComPtr<IArchiveOpenCallback> 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
index 5adfcc20..1b10ee26 100755..100644
--- 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<ICompressCoder> encoder;
+ CMyComPtr<ICompressCoder> _encoder;
+ CMyComPtr<ICompressFilter> _encoderFilter;
CBenchProgressInfo *progressInfoSpec[2];
CMyComPtr<ICompressProgressInfo> 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<ICompressCoder> decoders[2];
+ CMyComPtr<ICompressCoder> _decoders[2];
+ CMyComPtr<ICompressFilter> _decoderFilter;
+
HRESULT Results[2];
CBenchmarkOutStream *outStreamSpec;
CMyComPtr<ISequentialOutStream> outStream;
@@ -586,8 +649,14 @@ struct CEncoderInfo
UInt32 kBufferSize;
UInt32 compressedSize;
CBenchRandomGenerator rg;
+ CBenchBuffer rgCopy; // it must be 16-byte aligned !!!
CBenchmarkOutStream *propStreamSpec;
CMyComPtr<ISequentialOutStream> 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<IUnknown> coder;
+ if (_encoderFilter)
+ coder = _encoderFilter;
+ else
+ coder = _encoder;
{
CMyComPtr<ICompressSetCoderProperties> 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<ICompressWriteCoderProperties> writeCoderProps;
- encoder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProps);
+ coder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProps);
if (writeCoderProps)
{
RINOK(writeCoderProps->WriteCoderProperties(propStream));
}
+
+ {
+ CMyComPtr<ICryptoSetPassword> sp;
+ coder.QueryInterface(IID_ICryptoSetPassword, &sp);
+ if (sp)
+ {
+ RINOK(sp->CryptoSetPassword(_psw, sizeof(_psw)));
+
+ // we must call encoding one time to calculate password key for key cache.
+ // it must be after WriteCoderProperties!
+ CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;
+ CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
+ Byte temp[16];
+ memset(temp, 0, sizeof(temp));
+ inStreamSpec->Init(temp, sizeof(temp));
+
+ CCrcOutStream *outStreamSpec = new CCrcOutStream;
+ CMyComPtr<ISequentialOutStream> 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<ICryptoProperties> cp;
+ CMyComPtr<IUnknown> coder;
+ if (_encoderFilter)
+ coder = _encoderFilter;
+ else
+ coder = _encoder;
+ coder.QueryInterface(IID_ICryptoProperties, &cp);
CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;
CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
- 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)));
+ }
- RINOK(encoder->Code(inStream, outStream, 0, 0, progressInfo[0]));
- compressedSize = outStreamSpec->Pos;
- encoder.Release();
+ 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]));
+ }
+
+ 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<ISequentialInStream> inStream = inStreamSpec;
- CMyComPtr<ICompressCoder> &decoder = decoders[decoderIndex];
+ CMyComPtr<ICompressCoder> &decoder = _decoders[decoderIndex];
+ CMyComPtr<IUnknown> coder;
+ if (_decoderFilter)
+ {
+ if (decoderIndex != 0)
+ return E_FAIL;
+ coder = _decoderFilter;
+ }
+ else
+ coder = decoder;
CMyComPtr<ICompressSetDecoderProperties2> 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<ICompressSetCoderMt> 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<ICompressSetCoderProperties> scp;
+ coder.QueryInterface(IID_ICompressSetCoderProperties, &scp);
+ if (scp)
{
- if (printCallback)
+ UInt64 reduceSize = _uncompressedDataSize;
+ RINOK(_method.SetCoderProps(scp, &reduceSize));
+ }
+
+ CMyComPtr<ICryptoProperties> cp;
+ coder.QueryInterface(IID_ICryptoProperties, &cp);
+
+ if (setDecProps)
+ {
+ RINOK(setDecProps->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos));
+ }
+
+ {
+ CMyComPtr<ICryptoSetPassword> sp;
+ coder.QueryInterface(IID_ICryptoSetPassword, &sp);
+ if (sp)
+ {
+ RINOK(sp->CryptoSetPassword(_psw, sizeof(_psw)));
+ }
+ }
+
+ UInt64 prev = 0;
+
+ if (cp)
+ {
+ RINOK(cp->SetKey(_key, sizeof(_key)));
+ RINOK(cp->SetInitVector(_iv, sizeof(_iv)));
+ }
+
+ for (UInt64 i = 0; i < NumIterations; i++)
+ {
+ if (printCallback && pi->BenchInfo.UnpackSize - prev > (1 << 20))
{
RINOK(printCallback->CheckBreak());
+ prev = pi->BenchInfo.UnpackSize;
}
+
inStreamSpec->Init(outStreamSpec->Buffer, compressedSize);
crcOutStreamSpec->Init();
- if (setDecProps)
+ UInt64 outSize = kBufferSize;
+ crcOutStreamSpec->CalcCrc = ((i & 0x7F) == 0 || CheckCrc_Dec);
+ if (_decoderFilter)
{
- RINOK(setDecProps->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos));
+ 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));
}
- UInt64 outSize = kBufferSize;
- RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex]));
- if (CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc)
+ else
+ {
+ RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex]));
+ }
+ if (crcOutStreamSpec->CalcCrc && CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc)
return S_FALSE;
pi->BenchInfo.UnpackSize += kBufferSize;
pi->BenchInfo.PackSize += compressedSize;
}
decoder.Release();
+ _decoderFilter.Release();
return S_OK;
}
@@ -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<ICompressCoder2> coder2;
+ RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodId,
+ encoder._encoderFilter, encoder._encoder, coder2, true, false));
+ if (!encoder._encoder && !encoder._encoderFilter)
return E_NOTIMPL;
+ // encoder._encoderFilter.Release(); // we can disable filter to check the speed of FilterCoder.
+
+ 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<ICompressCoder2> coder2de;
+ CMyComPtr<ICompressCoder> &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<IHasher> 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()
+ void SetSum(const CTotalBenchRes &r1, const CTotalBenchRes &r2)
{
- if (NumIterations == 0)
- return;
- Rating /= NumIterations;
- Usage /= NumIterations;
- RPU /= NumIterations;
- NumIterations = 1;
- }
- void SetMid(const CTotalBenchRes &r1, const CTotalBenchRes &r2)
- {
- Rating = (r1.Rating + r2.Rating) / 2;
- Usage = (r1.Usage + r2.Usage) / 2;
- RPU = (r1.RPU + r2.RPU) / 2;
- NumIterations = (r1.NumIterations + r2.NumIterations) / 2;
+ 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)
+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 PrintChars(IBenchPrintCallback &f, char c, int size)
{
- PrintNumber(f, rating / 1000000, 6);
+ char s[256];
+ memset(s, (Byte)c, size);
+ s[size] = 0;
+ f.Print(s);
}
-static void PrintResults(IBenchPrintCallback &f, UInt64 usage, UInt64 rpu, UInt64 rating)
+static void PrintSpaces(IBenchPrintCallback &f, int size)
{
- PrintNumber(f, (usage + 5000) / 10000, 5);
- PrintRating(f, rpu);
- PrintRating(f, rating);
+ PrintChars(f, ' ', size);
}
-static void PrintResults(IBenchPrintCallback &f, const CBenchInfo &info, UInt64 rating, CTotalBenchRes &res)
+static void PrintResults(IBenchPrintCallback &f, UInt64 usage, UInt64 rpu, UInt64 rating, bool showFreq, UInt64 cpuFreq)
{
- UInt64 speed = MyMultDiv64(info.UnpackSize, info.GlobalTime, info.GlobalFreq);
- PrintNumber(f, speed / 1024, 7);
+ 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, bool showFreq, UInt64 cpuFreq, CTotalBenchRes *res)
+{
+ UInt64 speed = info.GetSpeed(info.UnpackSize * info.NumIterations);
+ if (f)
+ {
+ if (speed != 0)
+ PrintNumber(*f, speed / 1024, kFieldSize_Speed);
+ else
+ PrintSpaces(*f, 1 + kFieldSize_Speed);
+ }
UInt64 usage = info.GetUsage();
UInt64 rpu = info.GetRatingPerUsage(rating);
- 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)
{
- AString s2 = s;
- for (unsigned len = (unsigned)strlen(s); len < size; len++)
- s2 += ' ';
- Print(s2);
+ f.Print(s);
+ int numSpaces = size - MyStringLen(s);
+ if (numSpaces > 0)
+ PrintSpaces(f, numSpaces);
+}
+
+void PrintRight(IBenchPrintCallback &f, const char *s, unsigned size)
+{
+ int numSpaces = size - MyStringLen(s);
+ if (numSpaces > 0)
+ PrintSpaces(f, numSpaces);
+ f.Print(s);
}
static HRESULT TotalBench(
- DECL_EXTERNAL_CODECS_LOC_VARS
- 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;
+ 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<ICompressSetCoderProperties> scp;
+ info.Hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp);
+ if (scp)
+ {
+ UInt64 reduceSize = 1;
+ RINOK(method.SetCoderProps(scp, &reduceSize));
+ }
+
+ Byte *data = buf + (size_t)bufferSize * i;
+ info.Callback = _file;
+ info.Data = data;
+ info.NumIterations = numIterations;
+ info.Size = bufferSize;
+ /* info.Crc = */ RandGenCrc(data, bufferSize, RG);
+ info.CheckSumDefined = false;
+ if (checkSum)
+ {
+ info.CheckSum = *checkSum;
+ info.CheckSumDefined = (checkSum && (i == 0));
+ }
+ }
+ progressInfoSpec.SetStartTime();
+ for (i = 0; i < numThreads; i++)
+ {
+ CCrcInfo &info = threads.Items[i];
+ RINOK(info.Thread.Create(CrcThreadFunction, &info));
+ threads.NumThreads++;
+ }
+ threads.WaitAll();
+ for (i = 0; i < numThreads; i++)
+ {
+ RINOK(threads.Items[i].Res);
+ }
+ }
+ else
+ #endif
+ {
+ /* UInt32 crc = */ RandGenCrc(buf, bufferSize, RG);
+ progressInfoSpec.SetStartTime();
+ CMyComPtr<IHasher> hasher;
+ UString name;
+ RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS hashID, name, hasher));
+ if (!hasher)
+ return E_NOTIMPL;
+ CMyComPtr<ICompressSetCoderProperties> scp;
+ hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp);
+ if (scp)
+ {
+ UInt64 reduceSize = 1;
+ RINOK(method.SetCoderProps(scp, &reduceSize));
+ }
+ RINOK(CrcBig(buf, bufferSize, numIterations, checkSum, hasher, _file));
+ }
+ CBenchInfo info;
+ progressInfoSpec.SetFinishTime(info);
+
+ UInt64 unpSize = numIterations * bufferSize;
+ UInt64 unpSizeThreads = unpSize * numThreads;
+ info.UnpackSize = unpSizeThreads;
+ info.PackSize = unpSizeThreads;
+ info.NumIterations = 1;
+
+ if (_file)
+ {
+ {
+ UInt64 numCommands = unpSizeThreads * complexity / 256;
+ UInt64 rating = info.GetSpeed(numCommands);
+ PrintResults(_file, info, 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;
}
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<CProperty> props,
+ const CObjectVector<CProperty> &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
index 46146e24..b123675b 100755..100644
--- 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<CProperty> props,
+ const CObjectVector<CProperty> &props,
UInt32 numIterations,
bool multiDict
);
diff --git a/CPP/7zip/UI/Common/CompressCall.cpp b/CPP/7zip/UI/Common/CompressCall.cpp
index eb20d5cc..f5407b03 100755..100644
--- 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 &params,
- 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 &params,
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 &params)
{
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 &params)
+static void ExtractGroupCommand(const UStringVector &arcPaths, UString &params, 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
index f777b9f2..c71c21f7 100755..100644
--- 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
index ab483d2f..bd27f37b 100755..100644
--- 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<IUnknown> compressCodecsInfo = codecs; \
- result = codecs->Load(); \
- if (result != S_OK) \
- throw CSystemException(result);
+ CMyComPtr<ICompressCodecsInfo> compressCodecsInfo = codecs; \
+ ThrowException_if_Error(codecs->Load());
+
+#ifdef EXTERNAL_CODECS
+#define LOAD_EXTERNAL_CODECS \
+ CExternalCodecs __externalCodecs; \
+ __externalCodecs.GetCodecs = codecs; \
+ __externalCodecs.GetHashers = codecs; \
+ ThrowException_if_Error(__externalCodecs.LoadCodecs());
+
+#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<COpenType> 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<IFolderArchiveExtractCallback> 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<COpenType> 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<CCodecInfoEx> 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<CProperty> 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
index 4335e273..ce0b327b 100755..100644
--- 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
index 9764ff87..df164560 100755..100644
--- 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
index 6d6dc673..4bb62b0e 100755..100644
--- 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<CDirItem> Items;
- int GetNumFolders() const { return Prefixes.Size(); }
- UString GetPhyPath(int index) const;
- UString GetLogPath(int index) const;
+ bool SymLinks;
+
+ bool ScanAltStreams;
+ FStringVector ErrorPaths;
+ CRecordVector<DWORD> 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<DWORD> &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<DWORD> &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
index 8c83a9fb..955f459c 100755..100644
--- 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<CDirItem> &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<DWORD> &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<DWORD> &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<DWORD> &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<DWORD> &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<DWORD> &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<bool> needEnterVector;
+ unsigned i;
+
for (i = 0; i < curNode.IncludeItems.Size(); i++)
{
const NWildcard::CItem &item = curNode.IncludeItems[i];
const UString &name = item.PathParts.Front();
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<DWORD> &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
index c96c7b9e..803a64e7 100755..100644
--- 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<CDirItem> &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<DWORD> &errorCodes);
+ IEnumDirItemCallback *callback);
#endif
diff --git a/CPP/7zip/UI/Common/ExitCode.h b/CPP/7zip/UI/Common/ExitCode.h
index b6d7d4df..b6d7d4df 100755..100644
--- a/CPP/7zip/UI/Common/ExitCode.h
+++ b/CPP/7zip/UI/Common/ExitCode.h
diff --git a/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp
index 81186772..891cc7d8 100755..100644
--- a/CPP/7zip/UI/Common/Extract.cpp
+++ b/CPP/7zip/UI/Common/Extract.cpp
@@ -2,11 +2,13 @@
#include "StdAfx.h"
-#include <stdio.h>
+#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<UInt32> realIndices;
+
+ UStringVector removePathParts;
+
+ FString outDir = options.OutputDir;
+ UString replaceName = arc.DefaultName;
+
+ if (arcLink.Arcs.Size() > 1)
+ {
+ // Most "pe" archives have same name of archive subfile "[0]" or ".rsrc_1".
+ // So it extracts different archives to one folder.
+ // We will use top level archive name
+ const CArc &arc0 = arcLink.Arcs[0];
+ if (StringsAreEqualNoCase_Ascii(codecs->Formats[arc0.FormatIndex].Name, "pe"))
+ replaceName = arc0.DefaultName;
+ }
+
+ outDir.Replace(FSTRING_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<COpenType> &types,
+ const CIntVector &excludedFormats,
UStringVector &arcPaths, UStringVector &arcPathsFull,
const NWildcard::CCensorNode &wildcardCensor,
const CExtractOptions &options,
IOpenCallbackUI *openCallback,
IExtractCallbackUI *extractCallback,
+ #ifndef _SFX
+ IHashCalc *hash,
+ #endif
UString &errorMessage,
CDecompressStat &stat)
{
stat.Clear();
- int i;
UInt64 totalPackSize = 0;
- CRecordVector<UInt64> archiveSizes;
+ CRecordVector<UInt64> 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<IArchiveExtractCallback> ec(extractCallbackSpec);
+
+ CBoolArr skipArcs(numArcs);
+ for (i = 0; i < numArcs; i++)
+ skipArcs[i] = false;
+
+ CArchiveExtractCallback *ecs = new CArchiveExtractCallback;
+ CMyComPtr<IArchiveExtractCallback> 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<COpenType> 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
index 2904a0ab..e6bd5cb7 100755..100644
--- 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<CProperty> 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<COpenType> &types,
+ const CIntVector &excludedFormats,
UStringVector &archivePaths, UStringVector &archivePathsFull,
const NWildcard::CCensorNode &wildcardCensor,
const CExtractOptions &options,
IOpenCallbackUI *openCallback,
IExtractCallbackUI *extractCallback,
+ #ifndef _SFX
+ IHashCalc *hash,
+ #endif
UString &errorMessage,
CDecompressStat &stat);
diff --git a/CPP/7zip/UI/Common/ExtractMode.h b/CPP/7zip/UI/Common/ExtractMode.h
index b448fb30..c2e43f6a 100755..100644
--- 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
index 25494d0e..37e15013 100755..100644
--- 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
index da28bfc2..751248a9 100755..100644
--- 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<CMethodId> ids;
+ CObjectVector<COneMethodInfo> methods;
+
+ unsigned i;
+ for (i = 0; i < names.Size(); i++)
+ {
+ COneMethodInfo m;
+ RINOK(m.ParseMethodFromString(names[i]));
+
+ if (m.MethodName.IsEmpty())
+ m.MethodName = k_DefaultHashMethod;
+
+ if (m.MethodName == L"*")
+ {
+ CRecordVector<CMethodId> 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<IHasher> 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<ICompressSetCoderProperties> scp;
+ hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp);
+ if (scp)
+ {
+ RINOK(m.SetCoderProps(scp, NULL));
+ }
+ }
+ UInt32 digestSize = hasher->GetDigestSize();
+ if (digestSize > k_HashCalc_DigestSize_Max)
+ return E_NOTIMPL;
+ CHasherState &h = Hashers.AddNew();
+ h.Hasher = hasher;
+ h.Name = name;
+ h.DigestSize = digestSize;
+ for (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<ISequentialInStream> inStream;
+ UString path;
+ bool isDir = false;
+ bool isAltStream = false;
+ if (options.StdInMode)
+ {
+ inStream = new CStdInFileStream;
+ }
+ else
+ {
+ CInFileStream *inStreamSpec = new CInFileStream;
+ inStream = inStreamSpec;
+ const CDirItem &dirItem = dirItems.Items[i];
+ isDir = dirItem.IsDir();
+ isAltStream = dirItem.IsAltStream;
+ path = dirItems.GetLogPath(i);
+ if (!isDir)
+ {
+ 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<IHasher> 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<CHasherState> 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
index e8dcdce5..7bb85279 100755..100644
--- 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
index cb4f83ee..285b6588 100755..100644
--- 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<CByteBuffer> &signatures)
+{
+ signatures.Clear();
+ while (size > 0)
+ {
+ unsigned len = *data++;
+ size--;
+ if (len > size)
+ return false;
+ signatures.AddNew().CopyFrom(data, len);
+ data += len;
+ size -= len;
+ }
+ return true;
+}
+
+#endif // _SFX
+
+#ifdef EXTERNAL_CODECS
static FString GetBaseFolderPrefixFromRegistry()
{
@@ -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<ICompressCoder> &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
index f5963ed6..5a54d365 100755..100644
--- 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<CArcExtInfo> 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<CByteBuffer> 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<IHashers> 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<CCodecLib> Libs;
- CObjectVector<CDllCodecInfo> Codecs;
+ CRecordVector<CDllCodecInfo> Codecs;
+ CRecordVector<CDllHasherInfo> Hashers;
#ifdef NEW_FOLDER_INTERFACE
CCodecIcons InternalIcons;
@@ -159,6 +196,16 @@ public:
public:
CObjectVector<CArcInfoEx> 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<IInArchive> &archive) const
+ int GetHasherLibIndex(UInt32 index);
+ UInt64 GetHasherId(UInt32 index);
+ UString GetHasherName(UInt32 index);
+ UInt32 GetHasherDigestSize(UInt32 index);
+
+ #endif
+
+ HRESULT CreateInArchive(unsigned formatIndex, CMyComPtr<IInArchive> &archive) const
{
const CArcInfoEx &ai = Formats[formatIndex];
#ifdef EXTERNAL_CODECS
if (ai.LibIndex < 0)
#endif
{
+ COM_TRY_BEGIN
archive = ai.CreateInArchive();
return S_OK;
+ COM_TRY_END
}
#ifdef EXTERNAL_CODECS
return CreateArchiveHandler(ai, (void **)&archive, false);
#endif
}
- HRESULT CreateOutArchive(int formatIndex, CMyComPtr<IOutArchive> &archive) const
+
+ #ifndef _SFX
+
+ HRESULT CreateOutArchive(unsigned formatIndex, CMyComPtr<IOutArchive> &archive) const
{
const CArcInfoEx &ai = Formats[formatIndex];
#ifdef EXTERNAL_CODECS
if (ai.LibIndex < 0)
#endif
{
+ COM_TRY_BEGIN
archive = ai.CreateOutArchive();
return S_OK;
+ COM_TRY_END
}
#ifdef EXTERNAL_CODECS
return CreateArchiveHandler(ai, (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<ICompressCoder> &coder) const;
- #endif
-
+ #endif // _SFX
};
#endif
diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp
index 60d2f6f5..ac077660 100755..100644
--- a/CPP/7zip/UI/Common/OpenArchive.cpp
+++ b/CPP/7zip/UI/Common/OpenArchive.cpp
@@ -2,27 +2,455 @@
#include "StdAfx.h"
-#include "Common/Wildcard.h"
+// #define SHOW_DEBUG_INFO
-#include "Windows/FileDir.h"
-#include "Windows/PropVariant.h"
+#ifdef SHOW_DEBUG_INFO
+#include <stdio.h>
+#endif
+
+#include "../../../../C/CpuArch.h"
+
+#include "../../../Common/ComTry.h"
+#include "../../../Common/IntToString.h"
+#include "../../../Common/StringConvert.h"
+#include "../../../Common/StringToInt.h"
+#include "../../../Common/Wildcard.h"
+
+#include "../../../Windows/FileDir.h"
#include "../../Common/FileStreams.h"
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/ProgressUtils.h"
#include "../../Common/StreamUtils.h"
+#include "../../Compress/CopyCoder.h"
+
#include "DefaultName.h"
#include "OpenArchive.h"
+#ifndef _SFX
+#include "SetProperties.h"
+#endif
+
+#ifdef SHOW_DEBUG_INFO
+#define PRF(x) x
+#else
+#define PRF(x)
+#endif
+
+// increase it, if you need to support larger SFX stubs
+static const UInt64 kMaxCheckStartPosition = 1 << 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<CParseItem> _items;
+ UInt64 _maxEndOffset;
+ CMyComPtr<IInStream> _stream;
+
+ MY_UNKNOWN_IMP2(
+ IInArchive,
+ IInArchiveGetStream)
+
+ INTERFACE_IInArchive(;)
+ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+
+ UInt64 GetLastEnd() const
+ {
+ if (_items.IsEmpty())
+ return 0;
+ const CParseItem &back = _items.Back();
+ return back.Offset + back.Size;
+ }
+
+ void AddUnknownItem(UInt64 next);
+ int FindInsertPos(const CParseItem &item);
+ 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;
+ }
+ }
+}
-HRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result)
+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<ICompressProgressInfo> progress = lps;
+ lps->Init(extractCallback, false);
+
+ CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+ CMyComPtr<ISequentialInStream> inStream(streamSpec);
+ streamSpec->SetStream(_stream);
+
+ CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream;
+ CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+
+ NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
+ CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+ for (i = 0; i < numItems; i++)
+ {
+ lps->InSize = totalSize;
+ lps->OutSize = totalSize;
+ RINOK(lps->SetCur());
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ Int32 askMode = testMode ?
+ NExtract::NAskMode::kTest :
+ NExtract::NAskMode::kExtract;
+ Int32 index = allFilesMode ? i : indices[i];
+ const CParseItem &item = _items[index];
+
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+ UInt64 unpackSize = item.Size;
+ totalSize += unpackSize;
+ bool skipMode = false;
+ if (!testMode && !realOutStream)
+ continue;
+ RINOK(extractCallback->PrepareOperation(askMode));
+
+ outStreamSpec->SetStream(realOutStream);
+ realOutStream.Release();
+ outStreamSpec->Init(skipMode ? 0 : unpackSize, true);
+
+ Int32 opRes = NExtract::NOperationResult::kOK;
+ RINOK(_stream->Seek(item.Offset, STREAM_SEEK_SET, NULL));
+ streamSpec->Init(unpackSize);
+ RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
+
+ if (outStreamSpec->GetRem() != 0)
+ opRes = NExtract::NOperationResult::kDataError;
+ outStreamSpec->ReleaseStream();
+ RINOK(extractCallback->SetOperationResult(opRes));
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+ COM_TRY_BEGIN
+ const CParseItem &item = _items[index];
+ return CreateLimitedInStream(_stream, item.Offset, item.Size, stream);
+ COM_TRY_END
+}
+
+}}
+
+#endif
+
+HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result)
{
NCOM::CPropVariant prop;
result = false;
- RINOK(archive->GetProperty(index, propID, &prop));
+ RINOK(arc->GetProperty(index, propID, &prop));
if (prop.vt == VT_BOOL)
result = VARIANT_BOOLToBool(prop.boolVal);
else if (prop.vt != VT_EMPTY)
@@ -30,13 +458,208 @@ HRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID,
return S_OK;
}
-HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result)
+HRESULT Archive_IsItem_Folder(IInArchive *arc, UInt32 index, bool &result)
{
- return GetArchiveItemBoolProp(archive, index, kpidIsDir, 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(arc->GetArchiveProperty(propid, &prop));
+ if (prop.vt == VT_BOOL)
+ result = VARIANT_BOOLToBool(prop.boolVal);
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ return S_OK;
+}
+
+static HRESULT Archive_GetArcProp_UInt(IInArchive *arc, PROPID propid, UInt64 &result, bool &defined)
+{
+ defined = false;
+ NCOM::CPropVariant prop;
+ RINOK(arc->GetArchiveProperty(propid, &prop));
+ switch (prop.vt)
+ {
+ case VT_UI4: result = prop.ulVal; defined = true; break;
+ case VT_I4: result = 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
+{
+ 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;
@@ -104,6 +764,7 @@ HRESULT CArc::GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const
}
#ifndef _SFX
+
static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size)
{
for (size_t i = 0; i < size; i++)
@@ -111,296 +772,2022 @@ static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size)
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<CByteBuffer> &sigs = ai.Signatures;
+ FOR_VECTOR (k, sigs)
+ {
+ const CByteBuffer &sig = sigs[k];
+ if (sig.Size() == 0 && dataSize == 0 ||
+ sig.Size() != 0 && sig.Size() <= dataSize &&
+ TestSignature(data, sig, sig.Size()))
+ {
+ orderIndices2.Add(index);
+ orderIndices[i] = -1;
+ break;
+ }
+ }
+ }
+}
+
#endif
#ifdef UNDER_CE
-static const int kNumHashBytes = 1;
-#define HASH_VAL(buf, pos) ((buf)[pos])
+ static const unsigned 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))
+ static const unsigned kNumHashBytes = 2;
+ #define HASH_VAL(buf, pos) ((buf)[pos] | ((UInt32)(buf)[pos + 1] << 8))
#endif
-HRESULT CArc::OpenStream(
- CCodecs *codecs,
- int formatIndex,
- IInStream *stream,
- ISequentialInStream *seqStream,
- IArchiveOpenCallback *callback)
+#ifndef _SFX
+
+static bool IsExeExt(const UString &ext)
{
- Archive.Release();
+ 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<IArchiveOpenCallback> Callback;
+ UInt64 Files;
+ UInt64 Offset;
+
+ #ifndef _NO_CRYPTO
+ CMyComPtr<ICryptoGetTextPassword> 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<IInArchive> &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<ISetCompressCodecsInfo> setCompressCodecsInfo;
+ archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
+ if (setCompressCodecsInfo)
+ {
+ RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(op.codecs));
+ }
+ }
+ #endif
+
+ // OutputDebugStringW(ai.Name);
+ // OutputDebugStringW(L"a3");
+
+ #ifndef _SFX
+ const CArcInfoEx &ai = op.codecs->Formats[formatIndex];
+ if (ai.Flags_PreArc())
+ {
+ /* we notify parsers that extract executables, that they don't need
+ to open archive, if there is tail after executable (for SFX cases) */
+ CMyComPtr<IArchiveAllowTail> allowTail;
+ archive.QueryInterface(IID_IArchiveAllowTail, (void **)&allowTail);
+ if (allowTail)
+ allowTail->AllowTail(BoolToInt(true));
+ }
+ if (op.props)
+ {
+ /*
+ FOR_VECTOR (y, op.props)
+ {
+ const COptionalOpenProperties &optProps = (*op.props)[y];
+ if (optProps.FormatName.IsEmpty() || optProps.FormatName.CompareNoCase(ai.Name) == 0)
+ {
+ RINOK(SetProperties(archive, optProps.Props));
+ break;
+ }
+ }
+ */
+ RINOK(SetProperties(archive, *op.props));
+ }
+ #endif
+ return S_OK;
+}
+
+#ifndef _SFX
+
+static HRESULT ReadParseItemProps(IInArchive *archive, const CArcInfoEx &ai, NArchive::NParser::CParseItem &pi)
+{
+ pi.Extension = ai.GetMainExt();
+ pi.FileTime_Defined = false;
+ pi.ArcType = ai.Name;
+
+ RINOK(Archive_GetArcBoolProp(archive, kpidIsNotArcType, pi.IsNotArcType));
+
+ // RINOK(Archive_GetArcBoolProp(archive, kpidIsSelfExe, pi.IsSelfExe));
+ pi.IsSelfExe = ai.Flags_PreArc();
+
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetArchiveProperty(kpidMTime, &prop));
+ if (prop.vt == VT_FILETIME)
+ {
+ pi.FileTime_Defined = true;
+ pi.FileTime = prop.filetime;
+ }
+ }
+
+ if (!pi.FileTime_Defined)
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetArchiveProperty(kpidCTime, &prop));
+ if (prop.vt == VT_FILETIME)
+ {
+ pi.FileTime_Defined = true;
+ pi.FileTime = prop.filetime;
+ }
+ }
+
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetArchiveProperty(kpidName, &prop));
+ if (prop.vt == VT_BSTR)
+ {
+ pi.Name = 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<IArchiveOpenCallback> Callback;
+ UInt64 Files;
+ UInt64 Offset;
+
+ MY_UNKNOWN_IMP2(IArchiveExtractCallback, ICompressProgressInfo)
+ INTERFACE_IArchiveExtractCallback(;)
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+ void Init(IArchiveOpenCallback *callback)
+ {
+ Callback = callback;
+ Files = 0;
+ Offset = 0;
+ }
+};
+
+STDMETHODIMP CExtractCallback_To_OpenCallback::SetTotal(UInt64 /* size */)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallback_To_OpenCallback::SetCompleted(const UInt64 * /* completeValue */)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallback_To_OpenCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */)
+{
+ if (Callback)
+ {
+ UInt64 value = Offset;
+ if (inSize)
+ value += *inSize;
+ return Callback->SetCompleted(&Files, &value);
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallback_To_OpenCallback::GetStream(UInt32 /* index */, ISequentialOutStream **outStream, Int32 /* askExtractMode */)
+{
+ *outStream = 0;
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallback_To_OpenCallback::PrepareOperation(Int32 /* askExtractMode */)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallback_To_OpenCallback::SetOperationResult(Int32 /* operationResult */)
+{
+ return S_OK;
+}
+
+static HRESULT OpenArchiveSpec(IInArchive *archive, bool needPhySize,
+ IInStream *stream, const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openCallback,
+ IArchiveExtractCallback *extractCallback)
+{
+ /*
+ if (needPhySize)
+ {
+ CMyComPtr<IArchiveOpen2> open2;
+ archive->QueryInterface(IID_IArchiveOpen2, (void **)&open2);
+ if (open2)
+ return open2->ArcOpen2(stream, kOpenFlags_RealPhySize, openCallback);
+ }
+ */
+ RINOK(archive->Open(stream, maxCheckStartPosition, openCallback));
+ if (needPhySize)
+ {
+ bool phySize_Defined = false;
+ UInt64 phySize = 0;
+ RINOK(Archive_GetArcProp_UInt(archive, kpidPhySize, phySize, phySize_Defined));
+ if (phySize_Defined)
+ return S_OK;
+
+ bool phySizeCantBeDetected = false;;
+ RINOK(Archive_GetArcBoolProp(archive, kpidPhySizeCantBeDetected, phySizeCantBeDetected));
+
+ if (!phySizeCantBeDetected)
+ {
+ RINOK(archive->Extract(0, (UInt32)(Int32)-1, BoolToInt(true), extractCallback));
+ }
+ }
+ return S_OK;
+}
+
+static int FindFormatForArchiveType(CCodecs *codecs, CIntVector orderIndices, const char *name)
+{
+ FOR_VECTOR (i, orderIndices)
+ if (StringsAreEqualNoCase_Ascii(codecs->Formats[orderIndices[i]].Name, name))
+ return i;
+ return -1;
+}
+
+#endif
+
+HRESULT CArc::OpenStream2(const COpenOptions &op)
+{
+ // fprintf(stdout, "\nOpen: %S", Path); fflush(stdout);
+
+ Archive.Release();
+ GetRawProps.Release();
+ GetRootProps.Release();
+
+ ErrorInfo.ClearErrors();
+ ErrorInfo.ErrorFormatIndex = -1;
+
+ IsParseArc = false;
+ ArcStreamOffset = 0;
+
+ // OutputDebugStringW(L"1");
+ // OutputDebugStringW(Path);
+
const UString fileName = ExtractFileNameFromPath(Path);
UString extension;
{
int dotPos = fileName.ReverseFind(L'.');
if (dotPos >= 0)
- extension = fileName.Mid(dotPos + 1);
+ 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];
- 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 (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 (!stream)
+ 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)
{
- if (numFinded != 1)
- return E_NOTIMPL;
- orderIndices.DeleteFrom(1);
+ RINOK(op.stream->Seek(0, STREAM_SEEK_END, &fileSize));
+ RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));
}
+ FileSize = fileSize;
+
#ifndef _SFX
- if (orderIndices.Size() >= 2 && (numFinded == 0 || extension.CompareNoCase(L"exe") == 0))
+
+ CBoolArr skipFrontalFormat(op.codecs->Formats.Size());
+ {
+ FOR_VECTOR(i, op.codecs->Formats)
+ skipFrontalFormat[i] = false;
+ }
+
+ #endif
+
+ const COpenType &mode = op.openType;
+
+
+
+
+
+ if (mode.CanReturnArc)
{
- CIntVector orderIndices2;
+ // ---------- 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<IInArchive> archive;
+
+ RINOK(PrepareToOpen(op, FormatIndex, archive));
+ if (!archive)
+ continue;
+
+ HRESULT result;
+ if (op.stream)
+ {
+ UInt64 searchLimit = (!exactOnly && searchMarkerInHandler) ? maxStartOffset: 0;
+ result = archive->Open(op.stream, &searchLimit, op.callback);
+ }
+ else
+ {
+ CMyComPtr<IArchiveOpenSeq> openSeq;
+ archive.QueryInterface(IID_IArchiveOpenSeq, (void **)&openSeq);
+ if (!openSeq)
+ return E_NOTIMPL;
+ result = openSeq->OpenSeq(op.seqStream);
+ }
+
+ RINOK(ReadBasicProps(archive, 0, result));
+
+ if (result == S_FALSE)
+ {
+ bool isArc = ErrorInfo.IsArc_After_NonOpen();
+
+ #ifndef _SFX
+ // if it's archive, we allow another open attempt for parser
+ if (!mode.CanReturnParser || !isArc)
+ skipFrontalFormat[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<IInArchive> handler = handlerSpec;
+
+ CExtractCallback_To_OpenCallback *extractCallback_To_OpenCallback_Spec = new CExtractCallback_To_OpenCallback;
+ CMyComPtr<IArchiveExtractCallback> extractCallback_To_OpenCallback = extractCallback_To_OpenCallback_Spec;
+ extractCallback_To_OpenCallback_Spec->Init(op.callback);
+
+ {
+ // ---------- Check all possible START archives ----------
+ // this code is better for full file archives than Parser's code.
+
CByteBuffer byteBuffer;
- 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;
+ 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;
- 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)
+ 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;
- UInt32 v = HASH_VAL(sig, 0);
- prevs[i] = hash[v];
- hash[v] = (Byte)i;
+ }
+
+ 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);
}
- processedSize -= (kNumHashBytes - 1);
- for (UInt32 pos = 0; pos < processedSize; pos++)
+ if (splitIndex >= 0)
+ sortedFormats.Insert(0, splitIndex);
+
+ for (i = 0; i < sortedFormats.Size(); i++)
{
- 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
+ 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<IInArchive> archive;
+ RINOK(PrepareToOpen(op, FormatIndex, archive));
+ if (!archive)
+ continue;
+
+ PRF(printf("\nSorted Open %S", (const wchar_t *)ai.Name));
+ HRESULT result;
{
- 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()))
+ 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
{
- orderIndices2.Add(index);
- orderIndices[i] = 0xFF;
- *ptr = prevs[i];
+ 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;
}
- else
- ptr = &prevs[i];
- i = *ptr;
}
- while (i != 0xFF);
+
+ 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);
}
-
- for (i = 0; i < orderIndices.Size(); i++)
+ }
+
+
+
+
+
+ // ---------- PARSER ----------
+
+ CUIntVector arc2sig; // formatIndex to signatureIndex
+ CUIntVector sig2arc; // signatureIndex to formatIndex;
+ {
+ unsigned sum = 0;
+ FOR_VECTOR (i, op.codecs->Formats)
{
- int val = orderIndices[i];
- if (val != 0xFF)
- orderIndices2.Add(val);
+ arc2sig.Add(sum);
+ const CObjectVector<CByteBuffer> &sigs = op.codecs->Formats[i].Signatures;
+ sum += sigs.Size();
+ FOR_VECTOR (k, sigs)
+ sig2arc.Add(i);
}
- 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)
+ CArchiveOpenCallback_Offset *openCallback_Offset_Spec = new CArchiveOpenCallback_Offset;
+ CMyComPtr<IArchiveOpenCallback> 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;
- orderIndices.Delete(i--);
- orderIndices.Insert(0, index);
- break;
+ }
+ 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 (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 (!thereAreHandlersForSearch)
{
- if (orderIndices[i] == isoIndex) iIso = i;
- if (orderIndices[i] == udfIndex) iUdf = i;
+ // openOnlyFullArc = true;
+ // canReturnTailArc = true;
}
- if (iUdf > iIso && iIso >= 0)
+
+ RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));
+
+ CLimitedCachedInStream *limitedStreamSpec = new CLimitedCachedInStream;
+ CMyComPtr<IInStream> limitedStream = limitedStreamSpec;
+ limitedStreamSpec->SetStream(op.stream);
+
+ openCallback_Offset_Spec->Callback = op.callback;
+
+ #ifndef _NO_CRYPTO
+ if (op.callback)
{
- orderIndices[iUdf] = isoIndex;
- orderIndices[iIso] = udfIndex;
+ openCallback_Offset_Spec->Callback.QueryInterface(IID_ICryptoGetTextPassword, &openCallback_Offset_Spec->GetTextPassword);
}
- }
+ #endif
- #endif
- }
+ RINOK(op.callback->SetTotal(NULL, &fileSize));
+ CByteBuffer &byteBuffer = limitedStreamSpec->Buffer;
+ byteBuffer.Alloc(kBufSize);
- for (int i = 0; i < orderIndices.Size(); i++)
- {
- if (stream)
+ 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)
{
- RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
+ NArchive::NParser::CParseItem &pi = handlerSpec->_items[0];
+ if (!pi.LenIsUnknown && pi.Offset == 0)
+ pos = pi.Size;
}
- CMyComPtr<IInArchive> archive;
- FormatIndex = orderIndices[i];
- RINOK(codecs->CreateInArchive(FormatIndex, archive));
- if (!archive)
- continue;
-
- #ifdef EXTERNAL_CODECS
+ for (;;)
{
- CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
- archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
- if (setCompressCodecsInfo)
+ // 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)
{
- RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs));
+ 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<IInArchive> archive;
+ RINOK(PrepareToOpen(op, index, archive));
+ if (!archive)
+ return E_FAIL;
+
+ // OutputDebugStringW(ai.Name);
+
+ UInt64 rem = fileSize - startArcPos;
+
+ UInt64 arcStreamOffset = 0;
+
+ if (ai.Flags_UseGlobalOffset())
+ {
+ limitedStreamSpec->InitAndSeek(0, fileSize);
+ limitedStream->Seek(startArcPos, STREAM_SEEK_SET, NULL);
+ }
+ else
+ {
+ limitedStreamSpec->InitAndSeek(startArcPos, rem);
+ arcStreamOffset = startArcPos;
+ }
+
+ UInt64 maxCheckStartPosition = 0;
+ 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();
+ }
+ }
+
+
+ if (isOpen && mode.CanReturnArc && phySizeDefined)
+ {
+ // if (pi.Offset + pi.Size >= fileSize)
+ bool openCur = false;
+
+ bool thereIsTail = ErrorInfo.ThereIsTail;
+ if (thereIsTail && mode.ZerosTailIsAllowed)
+ {
+ RINOK(CheckZerosTail(op, arcStreamOffset + Offset + PhySize));
+ if (ErrorInfo.IgnoreTail)
+ thereIsTail = false;
+ }
+
+ if (pi.Offset != 0)
+ {
+ if (!pi.IsNotArcType)
+ if (thereIsTail)
+ openCur = specFlags.CanReturnMid;
+ else
+ openCur = specFlags.CanReturnTail;
+ }
+ else
+ {
+ if (!thereIsTail)
+ openCur = true;
+ else
+ openCur = specFlags.CanReturnFrontal;
+
+
+ if (formatIndex >= -2)
+ openCur = true;
+ }
+ if (formatIndex < 0 && pi.IsSelfExe /* && mode.SkipSfxStub */)
+ openCur = false;
+
+ // We open file as SFX, if there is front archive or first archive is "Self Executable"
+ if (!openCur && !pi.IsSelfExe && !thereIsTail &&
+ (!pi.IsNotArcType || pi.Offset == 0))
+ {
+ if (handlerSpec->_items.IsEmpty())
+ {
+ if (specFlags.CanReturnTail)
+ openCur = true;
+ }
+ else if (handlerSpec->_items.Size() == 1)
+ {
+ if (handlerSpec->_items[0].IsSelfExe)
+ {
+ if (mode.SpecUnknownExt.CanReturnTail)
+ openCur = true;
+ }
+ }
+ }
+
+ if (openCur)
+ {
+ InStream = op.stream;
+ Archive = archive;
+ FormatIndex = index;
+ ArcStreamOffset = arcStreamOffset;
+ return S_OK;
+ }
+ }
+
+ /*
+ if (openOnlyFullArc)
+ {
+ ErrorInfo.ClearErrors();
+ return S_FALSE;
+ }
+ */
+
+ pi.FormatIndex = index;
+
+ // printf("\nAdd offset = %d", (int)pi.Offset);
+ handlerSpec->AddItem(pi);
+ wasOpen = true;
+ break;
}
+ // ---------- End of Open Loop for Current Pos ----------
+
+ if (!wasOpen)
+ pos++;
+ needCheckStartOpen = (nextNeedCheckStartOpen && wasOpen);
}
- #endif
+ // ---------- End of Main Scan Loop ----------
- // OutputDebugStringW(codecs->Formats[FormatIndex].Name);
+ /*
+ if (handlerSpec->_items.Size() == 1)
+ {
+ const NArchive::NParser::CParseItem &pi = handlerSpec->_items[0];
+ if (pi.Size == fileSize && pi.Offset == 0)
+ {
+ Archive = archive;
+ FormatIndex2 = pi.FormatIndex;
+ return S_OK;
+ }
+ }
+ */
- HRESULT result;
- if (stream)
- result = archive->Open(stream, &kMaxCheckStartPosition, callback);
- else
+ if (mode.CanReturnParser)
{
- CMyComPtr<IArchiveOpenSeq> openSeq;
- archive.QueryInterface(IID_IArchiveOpenSeq, (void **)&openSeq);
- if (!openSeq)
- return E_NOTIMPL;
- result = openSeq->OpenSeq(seqStream);
+ 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;
+ }
}
+ }
- if (result == S_FALSE)
- continue;
- RINOK(result);
+ #endif
+
+ if (!Archive)
+ return S_FALSE;
+ return S_OK;
+}
+
+HRESULT CArc::OpenStream(const COpenOptions &op)
+{
+ RINOK(OpenStream2(op));
+ // PrintNumber("op.formatIndex 3", op.formatIndex);
+ if (Archive)
+ {
+ GetRawProps.Release();
+ GetRootProps.Release();
+ Archive->QueryInterface(IID_IArchiveGetRawProps, (void **)&GetRawProps);
+ Archive->QueryInterface(IID_IArchiveGetRootProps, (void **)&GetRootProps);
+
+ RINOK(Archive_GetArcBoolProp(Archive, kpidIsTree, IsTree));
+ RINOK(Archive_GetArcBoolProp(Archive, kpidIsDeleted, Ask_Deleted));
+ RINOK(Archive_GetArcBoolProp(Archive, kpidIsAltStream, Ask_AltStream));
+ RINOK(Archive_GetArcBoolProp(Archive, kpidIsAux, Ask_Aux));
+ RINOK(Archive_GetArcBoolProp(Archive, kpidINode, Ask_INode));
+
+ 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<IInStream> fileStream;
CMyComPtr<ISequentialInStream> 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<IArchiveKeepModeForNextOpen> 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<IArchiveOpenSetSubArchiveName> 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 = &excl;
+ op2.stdInMode = false;
+ op2.stream = subStream;
+ op2.filePath = arc2.Path;
+ op2.callback = op.callback;
+ op2.callbackSpec = op.callbackSpec;
+
+
+ HRESULT result = arc2.OpenStream(op2);
+ resSpec = (op.types->Size() == 0 ? S_OK : S_FALSE);
if (result == S_FALSE)
+ {
+ NonOpen_ErrorInfo = arc2.ErrorInfo;
+ NonOpen_ArcPath = arc2.Path;
break;
+ }
RINOK(result);
RINOK(arc.GetItemMTime(mainSubfile, arc2.MTime, arc2.MTimeDefined));
Arcs.Add(arc2);
}
IsOpen = !Arcs.IsEmpty();
- return 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<IInStream> stream2;
+ Int64 globalOffset = GetGlobalOffset();
+ if (globalOffset <= 0)
+ stream2 = op.stream;
+ else
+ {
+ CTailInStream *tailStreamSpec = new CTailInStream;
+ stream2 = tailStreamSpec;
+ tailStreamSpec->Stream = op.stream;
+ tailStreamSpec->Offset = globalOffset;
+ tailStreamSpec->Init();
+ RINOK(tailStreamSpec->SeekToStart());
+ }
+
+ // There are archives with embedded STUBs (like ZIP), so we must support signature scanning
+ // But for another archives we can use 0 here. So the code can be fixed !!!
+ UInt64 maxStartPosition = kMaxCheckStartPosition;
+ HRESULT res = Archive->Open(stream2, &maxStartPosition, op.callback);
+
+ if (res == S_OK)
+ {
+ RINOK(ReadBasicProps(Archive, globalOffset, res));
+ ArcStreamOffset = globalOffset;
+ if (ArcStreamOffset != 0)
+ InStream = op.stream;
+ }
+ return res;
+}
+
+
+HRESULT CArchiveLink::ReOpen(COpenOptions &op)
{
if (Arcs.Size() > 1)
return E_NOTIMPL;
- if (Arcs.Size() == 0)
- return Open2(codecs, CIntVector(), false, NULL, filePath, 0);
+ CObjectVector<COpenType> inc;
+ CIntVector excl;
+
+ op.types = &inc;
+ op.excludedFormats = &excl;
+ op.stdInMode = false;
+ op.stream = NULL;
+ if (Arcs.Size() == 0) // ???
+ return Open2(op, NULL);
CMyComPtr<IArchiveOpenCallback> openCallbackNew;
- SetCallback(us2fs(filePath), NULL, callback, openCallbackNew);
+ SetCallback(us2fs(op.filePath), NULL, op.callback, openCallbackNew);
CInFileStream *fileStreamSpec = new CInFileStream;
CMyComPtr<IInStream> 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<COpenType> &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
index 25f739e3..aab6669d 100755..100644
--- 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<CProperty> Props;
+};
+*/
+
+#ifdef _SFX
+#define OPEN_PROPS_DECL
+#else
+#define OPEN_PROPS_DECL const CObjectVector<CProperty> *props;
+// #define OPEN_PROPS_DECL , const CObjectVector<COptionalOpenProperties> *props
+#endif
+
+struct COpenSpecFlags
+{
+ // bool CanReturnFull;
+ bool CanReturnFrontal;
+ bool CanReturnTail;
+ bool CanReturnMid;
+
+ bool CanReturn_NonStart() const { return CanReturnTail || CanReturnMid; }
+
+ COpenSpecFlags():
+ // CanReturnFull(true),
+ CanReturnFrontal(false),
+ CanReturnTail(false),
+ CanReturnMid(false)
+ {}
+};
+
+struct COpenType
+{
+ int FormatIndex;
+
+ COpenSpecFlags SpecForcedType;
+ COpenSpecFlags SpecMainType;
+ COpenSpecFlags SpecWrongExt;
+ COpenSpecFlags SpecUnknownExt;
+
+ bool Recursive;
+
+ bool CanReturnArc;
+ bool CanReturnParser;
+ bool EachPos;
+
+ // bool SkipSfxStub;
+ // bool ExeAsUnknown;
+
+ bool ZerosTailIsAllowed;
+
+ bool MaxStartOffset_Defined;
+ UInt64 MaxStartOffset;
+
+ const COpenSpecFlags &GetSpec(bool isForced, bool isMain, bool isUnknown) const
+ {
+ return isForced ? SpecForcedType : (isMain ? SpecMainType : (isUnknown ? SpecUnknownExt : SpecWrongExt));
+ }
+
+ COpenType():
+ FormatIndex(-1),
+ Recursive(true),
+ EachPos(false),
+ CanReturnArc(true),
+ CanReturnParser(false),
+ // SkipSfxStub(true),
+ // ExeAsUnknown(true),
+ ZerosTailIsAllowed(false),
+ MaxStartOffset_Defined(false),
+ MaxStartOffset(0)
+ {
+ SpecForcedType.CanReturnFrontal = true;
+ SpecForcedType.CanReturnTail = true;
+ SpecForcedType.CanReturnMid = true;
+
+ SpecMainType.CanReturnFrontal = true;
+
+ SpecUnknownExt.CanReturnTail = true; // for sfx
+ SpecUnknownExt.CanReturnMid = true;
+ SpecUnknownExt.CanReturnFrontal = true; // for alt streams of sfx with pad
+
+ // ZerosTailIsAllowed = true;
+ }
+};
+
+struct COpenOptions
+{
+ CCodecs *codecs;
+ COpenType openType;
+ const CObjectVector<COpenType> *types;
+ const CIntVector *excludedFormats;
+
+ IInStream *stream;
+ ISequentialInStream *seqStream;
+ IArchiveOpenCallback *callback;
+ COpenCallbackImp *callbackSpec;
+ OPEN_PROPS_DECL
+ // bool openOnlySpecifiedByExtension,
+
+ bool stdInMode;
+ UString filePath;
+
+ COpenOptions():
+ codecs(NULL),
+ types(NULL),
+ excludedFormats(NULL),
+ stream(NULL),
+ seqStream(NULL),
+ callback(NULL),
+ callbackSpec(NULL),
+ stdInMode(false)
+ {}
+
+};
+
+UInt32 GetOpenArcErrorFlags(const NWindows::NCOM::CPropVariant &prop, bool *isDefinedProp = NULL);
+
+struct CArcErrorInfo
+{
+ bool ThereIsTail;
+ bool UnexpecedEnd;
+ bool IgnoreTail; // all are zeros
+ // bool NonZerosTail;
+ bool ErrorFlags_Defined;
+ UInt32 ErrorFlags;
+ UInt32 WarningFlags;
+ int ErrorFormatIndex; // - 1 means no Error.
+ // if FormatIndex == ErrorFormatIndex, the archive is open with offset
+ UInt64 TailSize;
+
+ /* if CArc is Open OK with some format:
+ - ErrorFormatIndex shows error format index, if extension is incorrect
+ - other variables show message and warnings of archive that is open */
+
+ UString ErrorMessage;
+ UString WarningMessage;
+
+ // call IsArc_After_NonOpen only if Open returns S_FALSE
+ bool IsArc_After_NonOpen() const
+ {
+ return (ErrorFlags_Defined && (ErrorFlags & kpv_ErrorFlags_IsNotArc) == 0);
+ }
+
+
+ CArcErrorInfo():
+ ThereIsTail(false),
+ UnexpecedEnd(false),
+ IgnoreTail(false),
+ // NonZerosTail(false),
+ ErrorFlags_Defined(false),
+ ErrorFlags(0),
+ WarningFlags(0),
+ ErrorFormatIndex(-1),
+ TailSize(0)
+ {}
+
+ void ClearErrors();
+
+ void ClearErrors_Full()
+ {
+ ErrorFormatIndex = -1;
+ ClearErrors();
+ }
+
+ bool IsThereErrorOrWarning() const
+ {
+ return ErrorFlags != 0
+ || WarningFlags != 0
+ || NeedTailWarning()
+ || UnexpecedEnd
+ || !ErrorMessage.IsEmpty()
+ || !WarningMessage.IsEmpty();
+ }
+
+ bool AreThereErrors() const { return ErrorFlags != 0 || UnexpecedEnd; }
+ bool AreThereWarnings() const { return WarningFlags != 0 || NeedTailWarning(); }
-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<IInArchive> &archive);
+ HRESULT CheckZerosTail(const COpenOptions &op, UInt64 offset);
+ HRESULT OpenStream2(const COpenOptions &options);
+
+public:
CMyComPtr<IInArchive> Archive;
+ CMyComPtr<IInStream> InStream;
+ // we use InStream in 2 cases (ArcStreamOffset != 0):
+ // 1) if we use additional cache stream
+ // 2) we reopen sfx archive with CTailInStream
+
+ CMyComPtr<IArchiveGetRawProps> GetRawProps;
+ CMyComPtr<IArchiveGetRootProps> GetRootProps;
+
+ CArcErrorInfo ErrorInfo; // for OK archives
+ CArcErrorInfo NonOpen_ErrorInfo; // ErrorInfo for mainArchive (false OPEN)
+
UString Path;
+ UString filePath;
UString DefaultName;
- int FormatIndex;
+ 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<IInStream> &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<COpenType> &types);
+
#endif
diff --git a/CPP/7zip/UI/Common/PropIDUtils.cpp b/CPP/7zip/UI/Common/PropIDUtils.cpp
index dacaca5f..6e91efd8 100755..100644
--- 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
index ca14d091..3ee2981d 100755..100644
--- 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
index 8b57a2a6..8b57a2a6 100755..100644
--- a/CPP/7zip/UI/Common/Property.h
+++ b/CPP/7zip/UI/Common/Property.h
diff --git a/CPP/7zip/UI/Common/SetProperties.cpp b/CPP/7zip/UI/Common/SetProperties.cpp
index ac9b59a3..c3de5d5a 100755..100644
--- 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<CProperty> &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<CProperty> &propert
values[i] = propVariant;
}
CRecordVector<const wchar_t *> 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
index 892f1a21..892f1a21 100755..100644
--- a/CPP/7zip/UI/Common/SetProperties.h
+++ b/CPP/7zip/UI/Common/SetProperties.h
diff --git a/CPP/7zip/UI/Common/SortUtils.cpp b/CPP/7zip/UI/Common/SortUtils.cpp
index 061e7773..b7e422a2 100755..100644
--- 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
index e1522461..8e42e068 100755..100644
--- 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
index 9a8e7d21..2854ff3e 100755..100644
--- 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
index c799c7bf..0c13ae15 100755..100644
--- 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
index 5dcda5b6..4099e655 100755..100644
--- 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
index e740e8a7..2e095b06 100755..100644
--- 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<IOutStream> Stream;
@@ -58,7 +83,7 @@ class COutMultiVolStream:
UInt64 Pos;
UInt64 RealSize;
};
- CObjectVector<CSubStreamInfo> Streams;
+ CObjectVector<CAltStreamInfo> Streams;
public:
// CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
CRecordVector<UInt64> 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<IOutStream> 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<COpenType> &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<CArcItem> &arcItems,
- bool shareForWrite,
- bool stdInMode,
- /* const UString & stdInFileName, */
- bool stdOutMode,
+ Byte *processedItemsStatuses,
const CDirItems &dirItems,
- bool sfxMode,
- const FString &sfxModule,
- const CRecordVector<UInt64> &volumesSizes,
+ const CDirItem *parentDirItem,
CTempFiles &tempFiles,
CUpdateErrorInfo &errorInfo,
IUpdateCallbackUI *callback)
{
CMyComPtr<IOutArchive> outArchive;
- if (archive != NULL)
+ int formatIndex = options.MethodMode.Type.FormatIndex;
+ if (arc)
{
- CMyComPtr<IInArchive> archive2 = archive;
+ formatIndex = arc->FormatIndex;
+ if (formatIndex < 0)
+ return E_NOTIMPL;
+ CMyComPtr<IInArchive> archive2 = arc->Archive;
HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive);
if (result != S_OK)
throw kUpdateIsNotSupoorted;
}
else
{
- RINOK(codecs->CreateOutArchive(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<CUpdatePair2> 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<CUpdatePair> 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<IArchiveUpdateCallback> 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<IOutStream> outSeekStream;
CMyComPtr<ISequentialOutStream> 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<IInStream> 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<ISequentialOutStream> 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<ISequentialOutStream> tailStream;
+
+ if (options.SfxMode || !arc || arc->ArcStreamOffset == 0)
+ tailStream = outStream;
+ else
+ {
+ // Int64 globalOffset = arc->GetGlobalOffset();
+ RINOK(arc->InStream->Seek(0, STREAM_SEEK_SET, NULL));
+ RINOK(NCompress::CopyStream_ExactSize(arc->InStream, outStream, arc->ArcStreamOffset, NULL));
+ if (options.StdOutMode)
+ tailStream = outStream;
+ else
+ {
+ CTailOutStream *tailStreamSpec = new CTailOutStream;
+ tailStream = tailStreamSpec;
+ tailStreamSpec->Stream = outSeekStream;
+ tailStreamSpec->Offset = arc->ArcStreamOffset;
+ tailStreamSpec->Init();
+ }
+ }
+
+
+ HRESULT result = outArchive->UpdateItems(tailStream, updatePairs2.Size(), updateCallback);
callback->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<CArcItem> &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<CArcItem> &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 <mapi.h>
+
+#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<COpenType> &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<COpenType> 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 = &excl;
+ 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<DWORD> 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<CArcItem> 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<CRefSortPair> 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
index 43a3c0fd..68e51d85 100755..100644
--- 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<CProperty> 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<CUpdateArchiveCommand> 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<CRenamePair> RenamePairs;
+
+ bool InitFormatIndex(const CCodecs *codecs, const CObjectVector<COpenType> &types, const UString &arcPath);
+ bool SetArcPath(const CCodecs *codecs, const UString &arcPath);
CUpdateOptions():
UpdateArchiveItself(true),
@@ -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<COpenType> &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
index 879a49c5..a80db721 100755..100644
--- 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
index 0ac1c108..28dd28c3 100755..100644
--- 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
index 21146bb0..6be832b8 100755..100644
--- 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<ISequentialInStream> 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<ISequentialInStream> 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
index 09f1c0d3..3372e628 100755..100644
--- 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<CKeyKeyValPair> _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<UInt64> VolumesSizes;
FString VolName;
FString VolExt;
@@ -62,14 +89,34 @@ public:
bool ShareForWrite;
bool StdInMode;
+
const CDirItems *DirItems;
+ const CDirItem *ParentDirItem;
+
const CObjectVector<CArcItem> *ArcItems;
const CRecordVector<CUpdatePair2> *UpdatePairs;
const UStringVector *NewNames;
CMyComPtr<IInArchive> Archive;
+ CMyComPtr<IArchiveGetRawProps> GetRawProps;
+ CMyComPtr<IArchiveGetRootProps> 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
index a43a9e77..aad4a402 100755..100644
--- a/CPP/7zip/UI/Common/UpdatePair.cpp
+++ b/CPP/7zip/UI/Common/UpdatePair.cpp
@@ -4,10 +4,9 @@
#include <time.h>
-#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<CArcItem> &arcItems = *(const CObjectVector<CArcItem> *)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<CUpdatePair> &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
index 3a332649..296d3b09 100755..100644
--- 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
index c21db3b2..3089d73c 100755..100644
--- a/CPP/7zip/UI/Common/UpdateProduce.cpp
+++ b/CPP/7zip/UI/Common/UpdateProduce.cpp
@@ -14,17 +14,17 @@ void UpdateProduce(
CRecordVector<CUpdatePair2> &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
index e18648cd..b919965d 100755..100644
--- 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
index 1ecb5b54..9ad617f7 100755..100644
--- 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
index 79ea2b9d..75850a92 100755..100644
--- 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<IOutStream> OutStream;
diff --git a/CPP/7zip/UI/Common/ZipRegistry.cpp b/CPP/7zip/UI/Common/ZipRegistry.cpp
index d2aec4c6..4c48bd70 100755..100644
--- 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
index 6d8b7c13..cd2ea67d 100755..100644
--- 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<CFormatOptions> 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
index d0e43222..596f447b 100755..100644
--- 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<CProperty> props, UInt32 numIterations, FILE *f)
+ const CObjectVector<CProperty> &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
index 73972186..c9da1de3 100755..100644
--- 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<CProperty> props, UInt32 numIterations, FILE *f);
+ const CObjectVector<CProperty> &props, UInt32 numIterations, FILE *f);
#endif
diff --git a/CPP/7zip/UI/Console/Console.dsp b/CPP/7zip/UI/Console/Console.dsp
index 7c1719da..c75f4b6e 100755..100644
--- a/CPP/7zip/UI/Console/Console.dsp
+++ b/CPP/7zip/UI/Console/Console.dsp
@@ -44,7 +44,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /Gz /MD /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
@@ -841,5 +930,37 @@ InputName=7zCrcOpt
# 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
# End Project
diff --git a/CPP/7zip/UI/Console/Console.dsw b/CPP/7zip/UI/Console/Console.dsw
index 0d93da2f..0d93da2f 100755..100644
--- a/CPP/7zip/UI/Console/Console.dsw
+++ b/CPP/7zip/UI/Console/Console.dsw
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
index 5acae942..5acae942 100755..100644
--- a/CPP/7zip/UI/Console/ConsoleClose.cpp
+++ b/CPP/7zip/UI/Console/ConsoleClose.cpp
diff --git a/CPP/7zip/UI/Console/ConsoleClose.h b/CPP/7zip/UI/Console/ConsoleClose.h
index 9019c4ce..9019c4ce 100755..100644
--- a/CPP/7zip/UI/Console/ConsoleClose.h
+++ b/CPP/7zip/UI/Console/ConsoleClose.h
diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
index af379861..d3366a39 100755..100644
--- 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
index e42ca6f4..9a0afdc9 100755..100644
--- 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<CHasherState> &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<CHasherState> &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<CHasherState> &hashers);
+ void PrintResultLine(UInt64 fileSize,
+ const CObjectVector<CHasherState> &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
index 7de2379a..52770c8e 100755..100644
--- 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<CFieldInfo> _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<COpenType> &types,
+ const CIntVector &excludedFormats,
bool stdInMode,
UStringVector &arcPaths, UStringVector &arcPathsFull,
+ bool processAltStreams, bool showAltStreams,
const NWildcard::CCensorNode &wildcardCensor,
bool enableHeaders, bool techMode,
#ifndef _NO_CRYPTO
bool &passwordEnabled, UString &password,
#endif
- UInt64 &numErrors)
+ #ifndef _SFX
+ const CObjectVector<CProperty> *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<COptionalOpenProperties> optPropsVector;
+ COptionalOpenProperties &optProps = optPropsVector.AddNew();
+ optProps.Props = *props;
+ */
+
+ COpenOptions options;
+ #ifndef _SFX
+ options.props = props;
+ #endif
+ options.codecs = codecs;
+ options.types = &types;
+ options.excludedFormats = &excludedFormats;
+ options.stdInMode = stdInMode;
+ options.stream = NULL;
+ options.filePath = 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
index 97d9fb15..462c4710 100755..100644
--- 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<COpenType> &types,
+ const CIntVector &excludedFormats,
bool stdInMode,
UStringVector &archivePaths, UStringVector &archivePathsFull,
+ bool processAltStreams, bool showAltStreams,
const NWildcard::CCensorNode &wildcardCensor,
bool enableHeaders, bool techMode,
#ifndef _NO_CRYPTO
bool &passwordEnabled, UString &password,
#endif
- UInt64 &errors);
+ #ifndef _SFX
+ const CObjectVector<CProperty> *props,
+ #endif
+ UInt64 &errors,
+ UInt64 &numWarnings);
#endif
-
diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp
index f5a70397..0038dba4 100755..100644
--- a/CPP/7zip/UI/Console/Main.cpp
+++ b/CPP/7zip/UI/Console/Main.cpp
@@ -2,24 +2,31 @@
#include "StdAfx.h"
+#include <Psapi.h>
+
#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"
"<Commands>\n"
- " a: Add files to archive\n"
- " b: Benchmark\n"
- " d: Delete files from archive\n"
- " e: Extract files from archive (without using directory names)\n"
- " 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"
"<Switches>\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<IUnknown> 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<COpenType> types;
+ if (!ParseOpenTypes(*codecs, options.ArcType, types))
throw kUnsupportedArcTypeMessage;
+ CIntVector excludedFormats;
+ FOR_VECTOR (k, options.ExcludedArcTypes)
+ {
+ CIntVector tempIndices;
+ if (!codecs->FindFormatForArchiveType(options.ExcludedArcTypes[k], tempIndices)
+ || tempIndices.Size() != 1)
+ throw kUnsupportedArcTypeMessage;
+ excludedFormats.AddToUniqueSorted(tempIndices[0]);
+ // excludedFormats.Sort();
+ }
+
+
+ #ifdef EXTERNAL_CODECS
+ if (isExtractGroupCommand
+ || options.Command.CommandType == NCommandType::kHash
+ || options.Command.CommandType == NCommandType::kBenchmark)
+ ThrowException_if_Error(__externalCodecs.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<CCodecInfoEx> 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
index 25f4bd0d..1cb01689 100755..100644
--- 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
index 7dba2ad5..f64fd493 100755..100644
--- 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
index c002e6a7..5828af99 100755..100644
--- 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
index 786db1bc..f2889957 100755..100644
--- 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
index d970cc4b..509bab5f 100755..100644
--- 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
index d0feea85..d0feea85 100755..100644
--- a/CPP/7zip/UI/Console/StdAfx.cpp
+++ b/CPP/7zip/UI/Console/StdAfx.cpp
diff --git a/CPP/7zip/UI/Console/StdAfx.h b/CPP/7zip/UI/Console/StdAfx.h
index 2e4be10b..2854ff3e 100755..100644
--- 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
index 7f337319..749021c4 100755..100644
--- 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
index 5ffe3eb7..77e0e178 100755..100644
--- 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<HRESULT> FailedCodes;
@@ -59,4 +43,33 @@ public:
CRecordVector<HRESULT> 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
index 75468009..a0d4af38 100755..100644
--- 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
index 8b5232b3..16f04580 100755..100644
--- 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
index f100f635..efabf91c 100755..100644
--- 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
index 6e09bb96..6e09bb96 100755..100644
--- a/CPP/7zip/UI/Console/resource.rc
+++ b/CPP/7zip/UI/Console/resource.rc
diff --git a/CPP/7zip/UI/Explorer/7-zip.dll.manifest b/CPP/7zip/UI/Explorer/7-zip.dll.manifest
index cba1c5df..cba1c5df 100755..100644
--- a/CPP/7zip/UI/Explorer/7-zip.dll.manifest
+++ b/CPP/7zip/UI/Explorer/7-zip.dll.manifest
diff --git a/CPP/7zip/UI/Explorer/ContextMenu.cpp b/CPP/7zip/UI/Explorer/ContextMenu.cpp
index 4bdc397a..29ad4945 100755..100644
--- 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
index 76337b19..b314bb38 100755..100644
--- 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<CCommandMapItem> _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
index 2f9d94d4..f739cdc6 100755..100644
--- 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/DllExportsExplorer.cpp
index 4f649f59..478f6e97 100755..100644
--- a/CPP/7zip/UI/Explorer/DllExports.cpp
+++ b/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp
@@ -8,18 +8,18 @@
#include "StdAfx.h"
-#include "Common/MyInitGuid.h"
+#include "../../../Common/MyInitGuid.h"
#include <ShlGuid.h>
#include <OleCtl.h>
-#include "Common/ComTry.h"
-#include "Common/StringConvert.h"
+#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 "../../../Windows/DLL.h"
+#include "../../../Windows/ErrorMsg.h"
+#include "../../../Windows/NtCheck.h"
+#include "../../../Windows/Registry.h"
#include "../FileManager/IFolder.h"
#include "../FileManager/LangUtils.h"
diff --git a/CPP/7zip/UI/Explorer/Explorer.def b/CPP/7zip/UI/Explorer/Explorer.def
index 034a269d..034a269d 100755..100644
--- a/CPP/7zip/UI/Explorer/Explorer.def
+++ b/CPP/7zip/UI/Explorer/Explorer.def
diff --git a/CPP/7zip/UI/Explorer/Explorer.dsp b/CPP/7zip/UI/Explorer/Explorer.dsp
index 158390bb..80aaf464 100755..100644
--- 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
index beb8df7b..beb8df7b 100755..100644
--- a/CPP/7zip/UI/Explorer/Explorer.dsw
+++ b/CPP/7zip/UI/Explorer/Explorer.dsw
diff --git a/CPP/7zip/UI/Explorer/MenuLogo.bmp b/CPP/7zip/UI/Explorer/MenuLogo.bmp
new file mode 100644
index 00000000..906a6c5c
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/MenuLogo.bmp
Binary files differ
diff --git a/CPP/7zip/UI/Explorer/MyMessages.cpp b/CPP/7zip/UI/Explorer/MyMessages.cpp
index 62ac42ec..70c2a460 100755..100644
--- 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
index 10da975b..d5822f45 100755..100644
--- 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
index 90a0c0dc..c9531fae 100755..100644
--- 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<NControl::CPageInfo> 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
index ac51f6e3..ac51f6e3 100755..100644
--- a/CPP/7zip/UI/Explorer/OptionsDialog.h
+++ b/CPP/7zip/UI/Explorer/OptionsDialog.h
diff --git a/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp b/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp
index 656d0bfa..da6ecf38 100755..100644
--- 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
index 139526a8..139526a8 100755..100644
--- a/CPP/7zip/UI/Explorer/RegistryContextMenu.h
+++ b/CPP/7zip/UI/Explorer/RegistryContextMenu.h
diff --git a/CPP/7zip/UI/Explorer/StdAfx.cpp b/CPP/7zip/UI/Explorer/StdAfx.cpp
index 2550270c..2550270c 100755..100644
--- a/CPP/7zip/UI/Explorer/StdAfx.cpp
+++ b/CPP/7zip/UI/Explorer/StdAfx.cpp
diff --git a/CPP/7zip/UI/Explorer/StdAfx.h b/CPP/7zip/UI/Explorer/StdAfx.h
index e1fe42f2..5e4dc640 100755..100644
--- 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 <windows.h>
-#include <CommCtrl.h>
-#include <shlobj.h>
-#include <tchar.h>
+#include "../../../Common/Common.h"
-#include <stddef.h>
-#include <string.h>
-#include <wchar.h>
-
-#include <shlguid.h>
-
-#include "Common/NewHandler.h"
+#include <ShlObj.h>
#endif
diff --git a/CPP/7zip/UI/Explorer/makefile b/CPP/7zip/UI/Explorer/makefile
index 89cbc642..5a16ffd5 100755..100644
--- 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
index 3ddda8f0..8bb82108 100755..100644
--- 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
index 80018b45..80018b45 100755..100644
--- a/CPP/7zip/UI/Explorer/resource.rc
+++ b/CPP/7zip/UI/Explorer/resource.rc
diff --git a/CPP/7zip/UI/Explorer/resource2.rc b/CPP/7zip/UI/Explorer/resource2.rc
index 08bc82bf..c07148fd 100755..100644
--- a/CPP/7zip/UI/Explorer/resource2.rc
+++ b/CPP/7zip/UI/Explorer/resource2.rc
@@ -2,26 +2,17 @@
STRINGTABLE
BEGIN
+ IDS_CONTEXT_FOLDER "<Folder>"
+ IDS_CONTEXT_ARCHIVE "<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 "<Folder>"
- IDS_CONTEXT_ARCHIVE "<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
index b18eed59..4384c6ec 100755..100644
--- 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
index 5676103a..f57602a9 100755..100644
--- 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/Main.cpp b/CPP/7zip/UI/Far/Far.cpp
index 7b58d0ca..38fed101 100755..100644
--- a/CPP/7zip/UI/Far/Main.cpp
+++ b/CPP/7zip/UI/Far/Far.cpp
@@ -2,12 +2,12 @@
#include "StdAfx.h"
-#include "Common/MyInitGuid.h"
+#include "../../../Common/MyInitGuid.h"
-#include "Common/StringConvert.h"
+#include "../../../Common/StringConvert.h"
-#include "Windows/FileDir.h"
-#include "Windows/NtCheck.h"
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/NtCheck.h"
#include "../../Common/FileStreams.h"
@@ -18,6 +18,8 @@
#include "ProgressBox.h"
using namespace NWindows;
+using namespace NFile;
+using namespace NDir;
using namespace NFar;
static const char *kCommandPrefix = "7-zip";
@@ -87,7 +89,7 @@ class COpenArchiveCallback:
DWORD m_PrevTickCount;
- NWindows::NFile::NFind::CFileInfo _fileInfo;
+ NFind::CFileInfo _fileInfo;
public:
bool PasswordIsDefined;
UString Password;
@@ -161,7 +163,8 @@ void COpenArchiveCallback::ShowMessage()
UInt64 total = 0, cur = 0;
bool curIsDefined = false, totalIsDefined = false;
- char message[256] = { 0 };
+ char message[256];
+ message[0] = 0;
if (_numFilesCurDefined)
ConvertUInt64ToStringAligned(_numFilesCur, message, 5);
@@ -267,7 +270,7 @@ STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, IInStream **in
STDMETHODIMP COpenArchiveCallback::GetProperty(PROPID propID, PROPVARIANT *value)
{
- NWindows::NCOM::CPropVariant prop;
+ NCOM::CPropVariant prop;
switch(propID)
{
case kpidName: prop = GetUnicodeString(_fileInfo.Name, CP_OEMCP); break;
@@ -294,7 +297,7 @@ HRESULT GetPassword(UString &password)
{ DI_PSWEDIT, 5, 3, 70, 3, true, false, 0, true, -1, "", NULL }
};
- const int kNumItems = sizeof(initItems)/sizeof(initItems[0]);
+ const int kNumItems = ARRAY_SIZE(initItems);
FarDialogItem dialogItems[kNumItems];
g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumItems);
@@ -336,8 +339,8 @@ static HANDLE MyOpenFilePluginW(const wchar_t *name)
FString normalizedName = us2fs(name);
normalizedName.Trim();
FString fullName;
- NFile::NDirectory::MyGetFullPathName(normalizedName, fullName);
- NFile::NFind::CFileInfo fileInfo;
+ MyGetFullPathName(normalizedName, fullName);
+ NFind::CFileInfo fileInfo;
if (!fileInfo.Find(fullName))
return INVALID_HANDLE_VALUE;
if (fileInfo.IsDir())
@@ -361,7 +364,7 @@ static HANDLE MyOpenFilePluginW(const wchar_t *name)
openArchiveCallbackSpec->Init();
{
FString dirPrefix, fileName;
- NFile::NDirectory::GetFullPathAndSplit(fullName, dirPrefix, fileName);
+ GetFullPathAndSplit(fullName, dirPrefix, fileName);
openArchiveCallbackSpec->LoadFileInfo(dirPrefix, fileName);
}
@@ -449,10 +452,12 @@ EXTERN_C HANDLE WINAPI OpenPlugin(int openFrom, INT_PTR item)
AString fileName = (const char *)item;
if(fileName.IsEmpty())
return INVALID_HANDLE_VALUE;
- if (fileName.Length() >= 2 &&
+ if (fileName.Len() >= 2 &&
fileName[0] == '\"' && fileName.Back() == '\"')
- fileName = fileName.Mid(1, fileName.Length() - 2);
-
+ {
+ fileName.DeleteBack();
+ fileName.DeleteFrontal(1);
+ }
return MyOpenFilePlugin(fileName);
}
if(openFrom == OPEN_PLUGINSMENU)
@@ -542,7 +547,7 @@ EXTERN_C void WINAPI GetPluginInfo(struct PluginInfo *info)
static const char *pluginCfgStrings[1];
pluginCfgStrings[0] = g_StartupInfo.GetMsgString(NMessageID::kOpenArchiveMenuString);
info->PluginConfigStrings = (char **)pluginCfgStrings;
- info->PluginConfigStringsNumber = sizeof(pluginCfgStrings) / sizeof(pluginCfgStrings[0]);
+ info->PluginConfigStringsNumber = ARRAY_SIZE(pluginCfgStrings);
info->CommandPrefix = (char *)kCommandPrefix;
MY_TRY_END1("GetPluginInfo");
}
@@ -564,7 +569,7 @@ EXTERN_C int WINAPI Configure(int /* itemNumber */)
{ 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];
diff --git a/CPP/7zip/UI/Far/Far.def b/CPP/7zip/UI/Far/Far.def
index 39f3a5e2..39f3a5e2 100755..100644
--- a/CPP/7zip/UI/Far/Far.def
+++ b/CPP/7zip/UI/Far/Far.def
diff --git a/CPP/7zip/UI/Far/Far.dsp b/CPP/7zip/UI/Far/Far.dsp
index 394977bb..bd50fd93 100755..100644
--- a/CPP/7zip/UI/Far/Far.dsp
+++ b/CPP/7zip/UI/Far/Far.dsp
@@ -43,7 +43,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 1
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FAR_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /Gz /MD /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
index f4ef0801..f4ef0801 100755..100644
--- a/CPP/7zip/UI/Far/Far.dsw
+++ b/CPP/7zip/UI/Far/Far.dsw
diff --git a/CPP/7zip/UI/Far/FarPlugin.h b/CPP/7zip/UI/Far/FarPlugin.h
index d9ea6dca..a6185a1d 100755..100644
--- 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
index 9f55e8e5..14343522 100755..100644
--- 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<FarMenuItem> 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
index a4887c9a..1a5a49c7 100755..100644
--- 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/Messages.h b/CPP/7zip/UI/Far/Messages.h
index fc3723af..e6972392 100755..100644
--- 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/OverwriteDialogFar.cpp
index 5be6a5f9..a7fb495e 100755..100644
--- a/CPP/7zip/UI/Far/OverwriteDialog.cpp
+++ b/CPP/7zip/UI/Far/OverwriteDialogFar.cpp
@@ -1,20 +1,20 @@
-// OverwriteDialog.cpp
+// OverwriteDialogFar.cpp
#include "StdAfx.h"
#include <stdio.h>
-#include "OverwriteDialog.h"
+#include "../../../Common/StringConvert.h"
+#include "../../../Common/IntToString.h"
-#include "Common/StringConvert.h"
-
-#include "Windows/FileName.h"
-#include "Windows/Defs.h"
-#include "Windows/PropVariantConversions.h"
+#include "../../../Windows/FileName.h"
+#include "../../../Windows/PropVariantConv.h"
#include "FarUtils.h"
#include "Messages.h"
+#include "OverwriteDialogFar.h"
+
using namespace NWindows;
using namespace NFar;
@@ -33,8 +33,9 @@ void SetFileInfoStrings(const CFileInfo &fileInfo,
if (fileInfo.SizeIsDefined)
{
- sprintf(buffer, "%I64u ", fileInfo.Size);
+ ConvertUInt64ToString(fileInfo.Size, buffer);
fileInfoStrings.Size = buffer;
+ fileInfoStrings.Size += ' ';
fileInfoStrings.Size += g_StartupInfo.GetMsgString(NMessageID::kOverwriteBytes);
}
else
@@ -48,10 +49,11 @@ void SetFileInfoStrings(const CFileInfo &fileInfo,
{
if (!FileTimeToLocalFileTime(&fileInfo.Time, &localFileTime))
throw 4190402;
- UString timeString = ConvertFileTimeToString(localFileTime);
+ char timeString[32];
+ ConvertFileTimeToString(localFileTime, timeString);
fileInfoStrings.Time = g_StartupInfo.GetMsgString(NMessageID::kOverwriteModifiedOn);
- fileInfoStrings.Time += " ";
- fileInfoStrings.Time += UnicodeStringToMultiByte(timeString, CP_OEMCP);
+ fileInfoStrings.Time += ' ';
+ fileInfoStrings.Time += timeString;
}
}
@@ -97,7 +99,7 @@ NResult::EEnum Execute(const CFileInfo &oldFileInfo, const CFileInfo &newFileInf
{ DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kOverwriteCancel, NULL, NULL }
};
- const int kNumDialogItems = sizeof(initItems) / sizeof(initItems[0]);
+ const int kNumDialogItems = ARRAY_SIZE(initItems);
FarDialogItem aDialogItems[kNumDialogItems];
g_StartupInfo.InitDialogItems(initItems, aDialogItems, kNumDialogItems);
int anAskCode = g_StartupInfo.ShowDialog(kXSize, kYSize,
@@ -109,4 +111,3 @@ NResult::EEnum Execute(const CFileInfo &oldFileInfo, const CFileInfo &newFileInf
}
}
-
diff --git a/CPP/7zip/UI/Far/OverwriteDialog.h b/CPP/7zip/UI/Far/OverwriteDialogFar.h
index a0842e78..34947436 100755..100644
--- a/CPP/7zip/UI/Far/OverwriteDialog.h
+++ b/CPP/7zip/UI/Far/OverwriteDialogFar.h
@@ -1,10 +1,10 @@
-// OverwriteDialog.h
+// OverwriteDialogFar.h
-#ifndef OVERWRITEDIALOG_H
-#define OVERWRITEDIALOG_H
+#ifndef __OVERWRITE_DIALOG_FAR_H
+#define __OVERWRITE_DIALOG_FAR_H
-#include "Common/MyString.h"
-#include "Common/Types.h"
+#include "../../../Common/MyString.h"
+#include "../../../Common/MyTypes.h"
namespace NOverwriteDialog {
diff --git a/CPP/7zip/UI/Far/Plugin.cpp b/CPP/7zip/UI/Far/Plugin.cpp
index 8bdfb10d..bebd47de 100755..100644
--- 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<CArchiveItemProperty> 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<FarDialogItem> dialogItems;
- dialogItems.Reserve(numDialogItems);
- for (i = 0; i < numDialogItems; i++)
- dialogItems.Add(FarDialogItem());
- g_StartupInfo.InitDialogItems(&initDialogItems.Front(),
- &dialogItems.Front(), numDialogItems);
+ CObjArray<FarDialogItem> 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
index c4122c45..f01dc435 100755..100644
--- 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
index ce1a18bb..ce1a18bb 100755..100644
--- a/CPP/7zip/UI/Far/PluginCommon.cpp
+++ b/CPP/7zip/UI/Far/PluginCommon.cpp
diff --git a/CPP/7zip/UI/Far/PluginDelete.cpp b/CPP/7zip/UI/Far/PluginDelete.cpp
index 3a3df300..1adf91a7 100755..100644
--- a/CPP/7zip/UI/Far/PluginDelete.cpp
+++ b/CPP/7zip/UI/Far/PluginDelete.cpp
@@ -2,9 +2,11 @@
#include "StdAfx.h"
+#include <stdio.h>
+
#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<UINT32> indices;
- indices.Reserve(numItems);
+ CObjArray<UInt32> 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
index a4450064..6e77a9d5 100755..100644
--- 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<IArchiveFolder> 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<int> realIndices;
if (!decompressAllItems)
GetRealIndexes(panelItems, itemsNumber, realIndices);
*/
- CRecordVector<UINT32> indices;
- indices.Reserve(itemsNumber);
+ CObjArray<UInt32> 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
index e02f4d80..e36f3911 100755..100644
--- a/CPP/7zip/UI/Far/PluginWrite.cpp
+++ b/CPP/7zip/UI/Far/PluginWrite.cpp
@@ -2,13 +2,15 @@
#include "StdAfx.h"
+#include <stdio.h>
+
#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<ISetProperties> 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<const wchar_t *> 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<IFolderFolder> 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<const wchar_t *> fileNamePointers;
- fileNamePointers.Reserve(numItems);
+ fileNames.AddInReserved(MultiByteToUnicodeString(panelItems[i].FindData.cFileName, CP_OEMCP));
+ CObjArray<const wchar_t *> fileNamePointers(numItems);
for (i = 0; i < numItems; i++)
- fileNamePointers.Add(fileNames[i]);
+ fileNamePointers[i] = fileNames[i];
CMyComPtr<IOutFolderArchive> 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<PluginPanelItem> &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<PluginPanelItem> &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<PluginPanelItem> &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<PluginPanelItem> &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<PluginPanelItem> &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<PluginPanelItem> &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<PluginPanelItem> &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<PluginPanelItem> &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<PluginPanelItem> &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<PluginPanelItem> &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<PluginPanelItem> &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<PluginPanelItem> &pluginPanelItems)
*/
}
- CRecordVector<const wchar_t *> fileNamePointers;
- fileNamePointers.Reserve(fileNames.Size());
+ CObjArray<const wchar_t *> 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<PluginPanelItem> &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<PluginPanelItem> &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
index b13b0b51..3ad0560a 100755..100644
--- a/CPP/7zip/UI/Far/ProgressBox.cpp
+++ b/CPP/7zip/UI/Far/ProgressBox.cpp
@@ -4,9 +4,10 @@
#include <stdio.h>
-#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
index 2bada8e9..9c26763d 100755..100644
--- 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
index d0feea85..d0feea85 100755..100644
--- a/CPP/7zip/UI/Far/StdAfx.cpp
+++ b/CPP/7zip/UI/Far/StdAfx.cpp
diff --git a/CPP/7zip/UI/Far/StdAfx.h b/CPP/7zip/UI/Far/StdAfx.h
index ae0e328a..3bff655e 100755..100644
--- 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 <windows.h>
-#include <stdio.h>
+// #define _CRT_SECURE_NO_DEPRECATE
+// #include <windows.h>
+// #include <stdio.h>
-#include "Common/NewHandler.h"
+#include "../../../Common/Common.h"
#endif
diff --git a/CPP/7zip/UI/Far/UpdateCallback100.cpp b/CPP/7zip/UI/Far/UpdateCallbackFar.cpp
index 0785f55b..f2877888 100755..100644
--- a/CPP/7zip/UI/Far/UpdateCallback100.cpp
+++ b/CPP/7zip/UI/Far/UpdateCallbackFar.cpp
@@ -1,12 +1,11 @@
-// UpdateCallback.h
+// UpdateCallbackFar.cpp
#include "StdAfx.h"
-#include "UpdateCallback100.h"
+#include "../../../Common/StringConvert.h"
-#include "Common/Defs.h"
-#include "Common/StringConvert.h"
#include "FarUtils.h"
+#include "UpdateCallbackFar.h"
using namespace NFar;
diff --git a/CPP/7zip/UI/Far/UpdateCallback100.h b/CPP/7zip/UI/Far/UpdateCallbackFar.h
index bfe8419a..b2980f21 100755..100644
--- a/CPP/7zip/UI/Far/UpdateCallback100.h
+++ b/CPP/7zip/UI/Far/UpdateCallbackFar.h
@@ -1,14 +1,14 @@
-// UpdateCallback.h
+// UpdateCallbackFar.h
-#ifndef __UPDATE_CALLBACK_H
-#define __UPDATE_CALLBACK_H
+#ifndef __UPDATE_CALLBACK_FAR_H
+#define __UPDATE_CALLBACK_FAR_H
-#include "Common/MyCom.h"
-
-#include "../Agent/IFolderArchive.h"
+#include "../../../Common/MyCom.h"
#include "../../IPassword.h"
+#include "../Agent/IFolderArchive.h"
+
#include "ProgressBox.h"
class CUpdateCallback100Imp:
diff --git a/CPP/7zip/UI/Far/makefile b/CPP/7zip/UI/Far/makefile
index 0d6f8d68..2c32d533 100755..100644
--- 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
index a5c2e2f3..a5c2e2f3 100755..100644
--- a/CPP/7zip/UI/Far/resource.rc
+++ b/CPP/7zip/UI/Far/resource.rc
diff --git a/CPP/7zip/UI/FileManager/7zFM.exe.manifest b/CPP/7zip/UI/FileManager/7zFM.exe.manifest
index e8237451..e8237451 100755..100644
--- a/CPP/7zip/UI/FileManager/7zFM.exe.manifest
+++ b/CPP/7zip/UI/FileManager/7zFM.exe.manifest
diff --git a/CPP/7zip/UI/FileManager/7zipLogo.ico b/CPP/7zip/UI/FileManager/7zipLogo.ico
index 973241c8..973241c8 100755..100644
--- a/CPP/7zip/UI/FileManager/7zipLogo.ico
+++ b/CPP/7zip/UI/FileManager/7zipLogo.ico
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/AboutDialog.cpp b/CPP/7zip/UI/FileManager/AboutDialog.cpp
index edfa98ba..10d76671 100755..100644
--- 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
index c8a4ea9b..39fd3ba7 100755..100644
--- 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
index fcf2ae6e..6953c141 100755..100644
--- 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
index f7dd0602..b4165580 100755..100644
--- 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
index a8577fc7..a8577fc7 100755..100644
--- a/CPP/7zip/UI/FileManager/Add.bmp
+++ b/CPP/7zip/UI/FileManager/Add.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/Add2.bmp b/CPP/7zip/UI/FileManager/Add2.bmp
index 252fc253..252fc253 100755..100644
--- a/CPP/7zip/UI/FileManager/Add2.bmp
+++ b/CPP/7zip/UI/FileManager/Add2.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/App.cpp b/CPP/7zip/UI/FileManager/App.cpp
index 5f31f607..51c8d2db 100755..100644
--- 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<UInt32> &indices)
@@ -473,11 +467,11 @@ UString CPanel::GetItemsInfoString(const CRecordVector<UInt32> &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<UInt32> &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<UInt32> &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
index 2af63b47..c775cc2e 100755..100644
--- 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<IDropTarget> _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
index 374cf04f..cc887150 100755..100644
--- 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
index 1c350064..32db8f8f 100755..100644
--- 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 <commdlg.h>
+#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<CFileInfo> _files;
+
+ CExtToIconMap _extToIconMap;
+ int _sortIndex;
+ bool _ascending;
+ bool _showDots;
+ UString _topDirPrefix; // we don't open parent of that folder
+ UString DirPrefix;
+
+ virtual bool OnInit();
+ virtual bool OnSize(WPARAM wParam, int xSize, int ySize);
+ virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam);
+ virtual bool OnNotify(UINT controlID, LPNMHDR header);
+ virtual bool OnKeyDown(LPNMLVKEYDOWN keyDownInfo);
+ virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
+ virtual void OnOK();
+
+ void Post_RefreshPathEdit() { 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<CFileInfo> 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
index f597d1c3..77c749b5 100755..100644
--- 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<NWindows::NFile::NFind::CFileInfo> _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
index 4d7ec288..04a6ad61 100755..100644
--- 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
index 79f0efdb..aff84ec9 100755..100644
--- 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
index 9fec3d92..b092a9ed 100755..100644
--- 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
index c3cc08e7..729743e8 100755..100644
--- 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
index ff111b19..29b28b5b 100755..100644
--- 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
index 6789347a..fddb7484 100755..100644
--- 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
index 7f37cb93..a044797e 100755..100644
--- 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
index 0f28a324..0f28a324 100755..100644
--- a/CPP/7zip/UI/FileManager/Copy.bmp
+++ b/CPP/7zip/UI/FileManager/Copy.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/Copy2.bmp b/CPP/7zip/UI/FileManager/Copy2.bmp
index ba88ded0..ba88ded0 100755..100644
--- a/CPP/7zip/UI/FileManager/Copy2.bmp
+++ b/CPP/7zip/UI/FileManager/Copy2.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/CopyDialog.cpp b/CPP/7zip/UI/FileManager/CopyDialog.cpp
index 8cbaf41f..76441215 100755..100644
--- 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
index 2c22d700..30fde71f 100755..100644
--- 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
index 922dddc4..73d3ea80 100755..100644
--- 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
index 4944de84..85f5a39a 100755..100644
--- 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
index d1004d82..d1004d82 100755..100644
--- a/CPP/7zip/UI/FileManager/Delete.bmp
+++ b/CPP/7zip/UI/FileManager/Delete.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/Delete2.bmp b/CPP/7zip/UI/FileManager/Delete2.bmp
index 60e08c6a..60e08c6a 100755..100644
--- a/CPP/7zip/UI/FileManager/Delete2.bmp
+++ b/CPP/7zip/UI/FileManager/Delete2.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/DialogSize.h b/CPP/7zip/UI/FileManager/DialogSize.h
index f4dd1c32..504541bd 100755..100644
--- 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
index 3b38a3a5..627088b9 100755..100644
--- 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);
}
{
@@ -44,8 +56,13 @@ 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
index fbe3c23c..c11e613b 100755..100644
--- 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
index f5618d04..f5618d04 100755..100644
--- a/CPP/7zip/UI/FileManager/EditPage.rc
+++ b/CPP/7zip/UI/FileManager/EditPage.rc
diff --git a/CPP/7zip/UI/FileManager/EditPage2.rc b/CPP/7zip/UI/FileManager/EditPage2.rc
index 6b500d27..2d6554fb 100755..100644
--- 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
index 3b958311..017d7024 100755..100644
--- 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
index 291ea1f1..291ea1f1 100755..100644
--- a/CPP/7zip/UI/FileManager/EnumFormatEtc.cpp
+++ b/CPP/7zip/UI/FileManager/EnumFormatEtc.cpp
diff --git a/CPP/7zip/UI/FileManager/EnumFormatEtc.h b/CPP/7zip/UI/FileManager/EnumFormatEtc.h
index 6c476f1a..6c476f1a 100755..100644
--- a/CPP/7zip/UI/FileManager/EnumFormatEtc.h
+++ b/CPP/7zip/UI/FileManager/EnumFormatEtc.h
diff --git a/CPP/7zip/UI/FileManager/Extract.bmp b/CPP/7zip/UI/FileManager/Extract.bmp
index 0aeba923..0aeba923 100755..100644
--- a/CPP/7zip/UI/FileManager/Extract.bmp
+++ b/CPP/7zip/UI/FileManager/Extract.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/Extract2.bmp b/CPP/7zip/UI/FileManager/Extract2.bmp
index a7e57753..a7e57753 100755..100644
--- a/CPP/7zip/UI/FileManager/Extract2.bmp
+++ b/CPP/7zip/UI/FileManager/Extract2.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.cpp b/CPP/7zip/UI/FileManager/ExtractCallback.cpp
index 90076ebb..ed4bb884 100755..100644
--- 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<ISequentialOutStream> outStreamLoc;
+
+ if (VirtFileSystem && askExtractMode == NArchive::NExtract::NAskMode::kExtract)
+ {
+ CVirtFile &file = VirtFileSystemSpec->AddNewFile();
+ _newVirtFileWasAdded = true;
+ file.Name = name;
+ file.IsDir = IntToBool(isDir);
+ file.IsAltStream = _isAltStream;
+ file.Size = 0;
+
+ RINOK(GetTime(getProp, kpidCTime, file.CTime, file.CTimeDefined));
+ RINOK(GetTime(getProp, kpidATime, file.ATime, file.ATimeDefined));
+ RINOK(GetTime(getProp, kpidMTime, file.MTime, file.MTimeDefined));
+
+ NCOM::CPropVariant prop;
+ RINOK(getProp->GetProp(kpidAttrib, &prop));
+ if (prop.vt == VT_UI4)
+ {
+ file.Attrib = prop.ulVal;
+ file.AttribDefined = true;
+ }
+ // else if (isDir) file.Attrib = FILE_ATTRIBUTE_DIRECTORY;
+
+ file.ExpectedSize = 0;
+ if (sizeDefined)
+ file.ExpectedSize = size;
+ outStreamLoc = VirtFileSystem;
+ }
+
+ if (_hashStream)
+ {
+ {
+ _hashStreamSpec->SetStream(outStreamLoc);
+ outStreamLoc = _hashStream;
+ _hashStreamSpec->Init(true);
+ _hashStreamWasUsed = true;
+ }
+ }
+
+ if (outStreamLoc)
+ *outStream = outStreamLoc.Detach();
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CExtractCallbackImp::PrepareOperation7(Int32 askExtractMode)
+{
+ COM_TRY_BEGIN
+ _needUpdateStat = (
+ askExtractMode == NArchive::NExtract::NAskMode::kExtract ||
+ askExtractMode == NArchive::NExtract::NAskMode::kTest);
+
+ /*
+ _extractMode = false;
+ switch (askExtractMode)
+ {
+ case NArchive::NExtract::NAskMode::kExtract:
+ if (_testMode)
+ askExtractMode = NArchive::NExtract::NAskMode::kTest;
+ else
+ _extractMode = true;
+ break;
+ };
+ */
+ return SetCurrentFilePath2(_filePath);
+ COM_TRY_END
+}
+
+STDMETHODIMP CExtractCallbackImp::SetOperationResult7(Int32 opRes, 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
index 19c29e77..71e48e5e 100755..100644
--- 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<ISequentialOutStream> _outFileStream;
+public:
+ CObjectVector<CVirtFile> Files;
+ UInt64 MaxTotalAllocSize;
+ FString DirPrefix;
+
+ CVirtFile &AddNewFile()
+ {
+ if (!Files.IsEmpty())
+ {
+ MaxTotalAllocSize -= Files.Back().Data.Size();
+ }
+ return Files.AddNew();
+ }
+ HRESULT CloseMemFile()
+ {
+ if (_fileMode)
+ {
+ return FlushToDisk(true);
+ }
+ CVirtFile &file = Files.Back();
+ if (file.Data.Size() != file.Size)
+ {
+ file.Data.ReAlloc_KeepData((size_t)file.Size, (size_t)file.Size);
+ }
+ return S_OK;
+ }
+
+ bool IsStreamInMem() const
+ {
+ if (_fileMode)
+ return false;
+ if (Files.Size() < 1 || Files[0].IsAltStream || Files[0].IsDir)
+ return false;
+ return true;
+ }
+ size_t GetMemStreamWrittenSize() const { return _pos; }
+
+ CVirtFileSystem(): _outFileStreamSpec(NULL), MaxTotalAllocSize((UInt64)0 - 1) {}
+
+ void Init()
+ {
+ _totalAllocSize = 0;
+ _fileMode = false;
+ _pos = 0;
+ _numFlushed = 0;
+ _fileIsOpen = false;
+ }
+
+ HRESULT CloseFile(const FString &path);
+ HRESULT FlushToDisk(bool closeLast);
+ size_t GetPos() const { return _pos; }
+
+ MY_UNKNOWN_IMP
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+#endif
+
class CExtractCallbackImp:
- public IExtractCallbackUI,
+ 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<ISequentialOutStream> _hashStream;
+ IHashCalc *_hashCalc; // it's for stat in Test operation
+ #endif
+
public:
+
+ #ifndef _SFX
+ CVirtFileSystem *VirtFileSystemSpec;
+ CMyComPtr<ISequentialOutStream> VirtFileSystem;
+ #endif
+
+ bool ProcessAltStreams;
+
+ bool StreamMode;
+
CProgressDialog *ProgressDialog;
#ifndef _SFX
UInt64 NumFolders;
@@ -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
index 147a1fb7..537103ae 100755..100644
--- 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
index 3f3cd77c..4a7f16a6 100755..100644
--- 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
index 1c955d95..1c955d95 100755..100644
--- a/CPP/7zip/UI/FileManager/FM.dsw
+++ b/CPP/7zip/UI/FileManager/FM.dsw
diff --git a/CPP/7zip/UI/FileManager/FM.ico b/CPP/7zip/UI/FileManager/FM.ico
index 3a0a34da..3a0a34da 100755..100644
--- a/CPP/7zip/UI/FileManager/FM.ico
+++ b/CPP/7zip/UI/FileManager/FM.ico
Binary files differ
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
index 823b0826..84639de7 100755..100644
--- 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<IFolderFolder> 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
index a0cfd9be..a8e25d7d 100755..100644
--- 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<CDriveInfo> _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
index e4cb9f27..a8541eb2 100755..100644
--- 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<IFolderFolder> 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<IFolderFolder> 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<IFolderFolder> subFolder;
- RINOK(BindToFolder(index, &subFolder));
- CMyComPtr<IFolderReload> aFolderReload;
- subFolder.QueryInterface(&aFolderReload);
- aFolderReload->Reload();
- UInt32 numItems;
- RINOK(subFolder->GetNumberOfItems(&numItems));
- CMyComPtr<IFolderGetItemFullSize> 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
index 13e9e018..cb0d4ec2 100755..100644
--- 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<CDirItem> 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<CDirItem *> _refs;
-
+
+ CObjectVector<CDirItem> Files;
+ FStringVector Folders;
+ // CObjectVector<CAltStream> Streams;
CMyComPtr<IFolderFolder> _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
index c31498c7..0ef3c724 100755..100644
--- a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp
+++ b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp
@@ -4,11 +4,14 @@
#include <Winbase.h>
-#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
index d29ac44c..2d3b1d92 100755..100644
--- 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
index 593880e9..593880e9 100755..100644
--- a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.h
+++ b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.h
diff --git a/CPP/7zip/UI/FileManager/FilePlugins.cpp b/CPP/7zip/UI/FileManager/FilePlugins.cpp
index b81850fd..556c54fd 100755..100644
--- 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
index 43b05f92..43b05f92 100755..100644
--- a/CPP/7zip/UI/FileManager/FilePlugins.h
+++ b/CPP/7zip/UI/FileManager/FilePlugins.h
diff --git a/CPP/7zip/UI/FileManager/FoldersPage.cpp b/CPP/7zip/UI/FileManager/FoldersPage.cpp
index b7366fed..8c0b5a0c 100755..100644
--- 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
index d8456a40..7aaa80f7 100755..100644
--- 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
index fb48ee6e..fb48ee6e 100755..100644
--- a/CPP/7zip/UI/FileManager/FoldersPage.rc
+++ b/CPP/7zip/UI/FileManager/FoldersPage.rc
diff --git a/CPP/7zip/UI/FileManager/FoldersPage2.rc b/CPP/7zip/UI/FileManager/FoldersPage2.rc
index 0b73ec9f..9b9276ef 100755..100644
--- 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
index 896f197a..ba9ab73e 100755..100644
--- 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
index 98bb043e..2143c3f1 100755..100644
--- 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
index 70a44434..993e8033 100755..100644
--- 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
index 3128cb28..fb6fcdd0 100755..100644
--- a/CPP/7zip/UI/FileManager/HelpUtils.cpp
+++ b/CPP/7zip/UI/FileManager/HelpUtils.cpp
@@ -4,8 +4,10 @@
#include <HtmlHelp.h>
-#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
index 2a7b85af..52b1418a 100755..100644
--- 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
index d6cce88f..60991a71 100755..100644
--- 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
index d769a661..d769a661 100755..100644
--- a/CPP/7zip/UI/FileManager/Info.bmp
+++ b/CPP/7zip/UI/FileManager/Info.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/Info2.bmp b/CPP/7zip/UI/FileManager/Info2.bmp
index af724d27..af724d27 100755..100644
--- a/CPP/7zip/UI/FileManager/Info2.bmp
+++ b/CPP/7zip/UI/FileManager/Info2.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/LangPage.cpp b/CPP/7zip/UI/FileManager/LangPage.cpp
index 85829368..54253295 100755..100644
--- 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<CLangEx> 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
index e58f5098..589941b2 100755..100644
--- 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
index 327b33e2..5aeaf406 100755..100644
--- 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
index eb704dbf..d7a39d75 100755..100644
--- 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
index 20f4655b..15d68f43 100755..100644
--- 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<CLangEx> &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<CLangEx> 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
index d11082f6..509a5ae3 100755..100644
--- 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<CLangEx> &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<UInt32> 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
index b3e989c4..78c9562a 100755..100644
--- 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
index 6be51c7e..b7ba3830 100755..100644
--- 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
index 8f963bf1..14d3b2e6 100755..100644
--- 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
index aaa6521f..9abdb9d2 100755..100644
--- 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
index c3e013b5..0784f92c 100755..100644
--- 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
index 5005ea9c..1363687f 100755..100644
--- 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
index 791a1c08..626f415e 100755..100644
--- 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
index 1862aa06..442d1bdd 100755..100644
--- 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
index f1220bfd..91f75710 100755..100644
--- 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
index 05aa823f..41248277 100755..100644
--- 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
index 1304d516..5c017eb4 100755..100644
--- 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
index fb2f0f7d..49b73e84 100755..100644
--- 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
index 39d49f57..c8fffff6 100755..100644
--- 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
index eb5f20f9..eb5f20f9 100755..100644
--- a/CPP/7zip/UI/FileManager/Move.bmp
+++ b/CPP/7zip/UI/FileManager/Move.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/Move2.bmp b/CPP/7zip/UI/FileManager/Move2.bmp
index 58679eff..58679eff 100755..100644
--- a/CPP/7zip/UI/FileManager/Move2.bmp
+++ b/CPP/7zip/UI/FileManager/Move2.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/MyCom2.h b/CPP/7zip/UI/FileManager/MyCom2.h
index 98b1d708..224a838d 100755..100644
--- 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
index b16e8948..401e48ef 100755..100644
--- 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
index 53e9d0ef..53e9d0ef 100755..100644
--- a/CPP/7zip/UI/FileManager/MyLoadMenu.h
+++ b/CPP/7zip/UI/FileManager/MyLoadMenu.h
diff --git a/CPP/7zip/UI/FileManager/MyWindowsNew.h b/CPP/7zip/UI/FileManager/MyWindowsNew.h
index 3e081a96..3e081a96 100755..100644
--- a/CPP/7zip/UI/FileManager/MyWindowsNew.h
+++ b/CPP/7zip/UI/FileManager/MyWindowsNew.h
diff --git a/CPP/7zip/UI/FileManager/NetFolder.cpp b/CPP/7zip/UI/FileManager/NetFolder.cpp
index 07387328..f3d531ab 100755..100644
--- 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
index 9962845c..151dd096 100755..100644
--- 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
index 95daf37a..d5afb2da 100755..100644
--- 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
index a0c0167e..c952d7b0 100755..100644
--- 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
index a1ef1b1d..fa2ab922 100755..100644
--- 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<NControl::CPageInfo> 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
index 5f072daf..a657bc90 100755..100644
--- 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
index f760611e..da7fa55f 100755..100644
--- 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
index 8961d28b..29f99122 100755..100644
--- 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
index 3bc6900d..b480ba16 100755..100644
--- 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
index ebbe12b9..d63bdc17 100755..100644
--- a/CPP/7zip/UI/FileManager/Panel.cpp
+++ b/CPP/7zip/UI/FileManager/Panel.cpp
@@ -4,13 +4,13 @@
#include <Windowsx.h>
-#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<UInt32> &indices, UStringVector &paths)
+void CPanel::GetFilePaths(const CRecordVector<UInt32> &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<UInt32> &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<IArchiveFolder> 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
index e33a37a2..a9cf6023 100755..100644
--- 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<CItemProperty>
{
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<UInt32> &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<CFolderLink> _parentFolders;
NWindows::NDLL::CLibrary _library;
+
CMyComPtr<IFolderFolder> _folder;
+ CMyComPtr<IFolderCompare> _folderCompare;
+ CMyComPtr<IFolderGetItemName> _folderGetItemName;
+ CMyComPtr<IArchiveGetRawProps> _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<IFolderGetSystemIconIndex> _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<UInt32> &indices, UStringVector &paths);
+ void GetFilePaths(const CRecordVector<UInt32> &indices, UStringVector &paths, bool allowFolders = false);
void ExtractArchives();
void TestArchives();
- HRESULT CopyTo(const CRecordVector<UInt32> &indices, const UString &folder,
- bool moveMode, bool showErrorMessages, UStringVector *messages,
+ HRESULT CopyTo(CCopyToOptions &options,
+ const CRecordVector<UInt32> &indices,
+ UStringVector *messages,
bool &usePassword, UString &password);
- HRESULT CopyTo(const CRecordVector<UInt32> &indices, const UString &folder,
- bool moveMode, bool showErrorMessages, UStringVector *messages)
+ HRESULT CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &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
index 8c27ef2f..d11368cf 100755..100644
--- 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<IFolderOperations> FolderOperations;
CRecordVector<UInt32> Indices;
- UString DestPath;
CExtractCallbackImp *ExtractCallbackSpec;
CMyComPtr<IFolderOperationsExtractCallback> 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<IFolderSetReplaceAltStreamCharsMode> iReplace;
+ FolderOperations.QueryInterface(IID_IFolderSetReplaceAltStreamCharsMode, &iReplace);
+ if (iReplace)
+ {
+ RINOK(iReplace->SetReplaceAltStreamCharsMode(ReplaceAltStreamChars ? 1 : 0));
+ }
+ */
+
+ if (options->testMode)
+ {
+ CMyComPtr<IArchiveFolder> archiveFolder;
+ FolderOperations.QueryInterface(IID_IArchiveFolder, &archiveFolder);
+ if (!archiveFolder)
+ return E_NOTIMPL;
+ CMyComPtr<IFolderArchiveExtractCallback> 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<UInt32> &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<UInt32> &indices,
+ UStringVector *messages,
bool &usePassword, UString &password)
{
CMyComPtr<IFolderOperations> 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<UInt32> &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<IUnknown> 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<UInt32> &indices, const UString &fold
password = extracter.ExtractCallbackSpec->Password;
}
}
+
RefreshTitleAlways();
return res;
}
@@ -108,6 +218,7 @@ struct CThreadUpdate
CMyComPtr<IFolderArchiveUpdateCallback> 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<IFolderOperations> 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
index 2dd5e7ce..ab93ecba 100755..100644
--- 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<NFind::CEnumerator> 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<UInt32> 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<IUnknown> 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
index 02bccc03..9434d156 100755..100644
--- a/CPP/7zip/UI/FileManager/PanelDrag.cpp
+++ b/CPP/7zip/UI/FileManager/PanelDrag.cpp
@@ -6,12 +6,13 @@
#include <winuserm.h>
#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<UInt32> 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
index 995124be..83993bb1 100755..100644
--- 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<IFolderFolder> 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
index 6c4309c6..39585cb2 100755..100644
--- a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
+++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
@@ -4,16 +4,16 @@
#include <tlhelp32.h>
-#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<IGetFolderArcProps> getFolderArcProps;
_folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps);
+ _thereAreDeletedItems = false;
if (getFolderArcProps)
{
CMyComPtr<IFolderArcProps> 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<IFolderOperations> 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<HANDLE> handles;
CRecordVector<int> 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<ISequentialOutStream> 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<IFolderOperations> 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<ISequentialOutStream> 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<IInStream> 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
index daa150c6..b8cc6269 100755..100644
--- 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<UInt32> 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<IFolderSetFlatMode> folderSetFlatMode;
- _folder.QueryInterface(IID_IFolderSetFlatMode, &folderSetFlatMode);
- if (folderSetFlatMode)
- folderSetFlatMode->SetFlatMode(BoolToInt(_flatMode));
+ {
+ CMyComPtr<IFolderSetFlatMode> folderSetFlatMode;
+ _folder.QueryInterface(IID_IFolderSetFlatMode, &folderSetFlatMode);
+ if (folderSetFlatMode)
+ folderSetFlatMode->SetFlatMode(BoolToInt(_flatMode));
+ }
+ /*
+ {
+ CMyComPtr<IFolderSetShowNtfsStreamsMode> 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<IFolderGetSystemIconIndex> folderGetSystemIconIndex;
if (!IsFSFolder() || _showRealFileIcons)
_folder.QueryInterface(IID_IFolderGetSystemIconIndex, &folderGetSystemIconIndex);
+ if (!IsFSFolder())
+ {
+ CMyComPtr<IGetFolderArcProps> getFolderArcProps;
+ _folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps);
+ _thereAreDeletedItems = false;
+ if (getFolderArcProps)
+ {
+ CMyComPtr<IFolderArcProps> 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<wchar_t *>((const wchar_t *)correctedName);
}
else
- item.pszText = const_cast<wchar_t *>((const wchar_t *)itemName);
+ */
+ {
+ // item.pszText = const_cast<wchar_t *>((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<UInt32> &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<UInt32> &indices) const
@@ -528,16 +724,45 @@ void CPanel::GetOperatedListViewIndices(CRecordVector<UInt32> &indices) const
}
*/
-void CPanel::EditItem()
+void CPanel::EditItem(bool useEditor)
{
+ if (!useEditor)
+ {
+ CMyComPtr<IFolderCalcItemFullSize> calcItemFullSize;
+ _folder.QueryInterface(IID_IFolderCalcItemFullSize, &calcItemFullSize);
+ if (calcItemFullSize)
+ {
+ bool needRefresh = false;
+ CRecordVector<UInt32> 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<IFolderWasChanged> 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
index 8e3eaaa1..db8e3311 100755..100644
--- 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
index f28311a4..7be6aa62 100755..100644
--- 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<UInt32> 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
index badf531b..d6dcf6c1 100755..100644
--- 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<IGetFolderArcProps> 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<UInt32> 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<LPITEMIDLIST> 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<const wchar_t *> 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<UInt32> 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
index 9c109d0d..4633aead 100755..100644
--- 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<UInt32> 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<CHAR> 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<WCHAR> 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<UInt32> &indices)
-{
CMyComPtr<IFolderOperations> 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<IFolderOperations> 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<IFolderOperations> 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<IFolderOperations> 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<IFolderOperations> 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
index b31c2e9d..a40997c2 100755..100644
--- 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
index 5ac04800..2ca29a15 100755..100644
--- 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
index ba0bedf8..ce15fcc5 100755..100644
--- 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<UInt32> 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<UInt32> 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
index 92826a1f..6ead39c3 100755..100644
--- 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
index 1d903249..339ebdaf 100755..100644
--- 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
index 2328ac56..90c57efa 100755..100644
--- 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
index e0b42661..1fe32e10 100755..100644
--- 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
index 72711fde..3ce5fa8e 100755..100644
--- a/CPP/7zip/UI/FileManager/PluginInterface.h
+++ b/CPP/7zip/UI/FileManager/PluginInterface.h
@@ -11,7 +11,7 @@
PLUGIN_INTERFACE(IInitContextMenu, 0x00)
{
- STDMETHOD(InitContextMenu)(const wchar_t *folder, const wchar_t **names, UINT32 numFiles) PURE;
+ STDMETHOD(InitContextMenu)(const wchar_t *folder, const wchar_t **names, UInt32 numFiles) PURE;
};
PLUGIN_INTERFACE(IPluginOptionsCallback, 0x01)
diff --git a/CPP/7zip/UI/FileManager/PluginLoader.h b/CPP/7zip/UI/FileManager/PluginLoader.h
index cb7d4d7c..fed38d65 100755..100644
--- 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
index 0eeec9d6..39671b75 100755..100644
--- 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<IPluginOptions> 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<IPluginOptionsCallback> 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
index 1dcd62d2..1dcd62d2 100755..100644
--- a/CPP/7zip/UI/FileManager/PluginsPage.h
+++ b/CPP/7zip/UI/FileManager/PluginsPage.h
diff --git a/CPP/7zip/UI/FileManager/PluginsPage.rc b/CPP/7zip/UI/FileManager/PluginsPage.rc
index 18e5dfc8..18e5dfc8 100755..100644
--- a/CPP/7zip/UI/FileManager/PluginsPage.rc
+++ b/CPP/7zip/UI/FileManager/PluginsPage.rc
diff --git a/CPP/7zip/UI/FileManager/PluginsPageRes.h b/CPP/7zip/UI/FileManager/PluginsPageRes.h
index ca07ca5c..81196d3c 100755..100644
--- 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
index 50ca5ca5..50ca5ca5 100755..100644
--- a/CPP/7zip/UI/FileManager/ProgramLocation.cpp
+++ b/CPP/7zip/UI/FileManager/ProgramLocation.cpp
diff --git a/CPP/7zip/UI/FileManager/ProgramLocation.h b/CPP/7zip/UI/FileManager/ProgramLocation.h
index 6bfb711e..6bfb711e 100755..100644
--- a/CPP/7zip/UI/FileManager/ProgramLocation.h
+++ b/CPP/7zip/UI/FileManager/ProgramLocation.h
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.cpp b/CPP/7zip/UI/FileManager/ProgressDialog.cpp
index cdb8399e..6c185769 100755..100644
--- 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
index 429ed740..175db017 100755..100644
--- 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
index 3a65338f..55d99233 100755..100644
--- 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
index a4ff7f58..bccb6e88 100755..100644
--- 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
index 6bb13603..632d022a 100755..100644
--- 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<ITaskbarList3> _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
index 703dbb1f..4d0e0c7b 100755..100644
--- 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
index be5af607..b45d7b49 100755..100644
--- 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
index 8eba4148..e9713930 100755..100644
--- 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
index 97e47228..cbf3beb2 100755..100644
--- 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
index 098bc47d..838b6e3f 100755..100644
--- 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
index 95e9dc9b..4f0d6dc1 100755..100644
--- 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
index bdd6c8ed..43c4584f 100755..100644
--- 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
index 9cc9f7c5..199aa6da 100755..100644
--- 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
index 487b6060..ee944350 100755..100644
--- 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
index 0be8244e..975c9d5f 100755..100644
--- 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
index 54254f1f..ad70db80 100755..100644
--- 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<CPluginInfo> &plugins)
void ReadFileFolderPluginInfoList(CObjectVector<CPluginInfo> &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
index 20f2ec34..dfa6de54 100755..100644
--- 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
index 6697169b..ffcb5555 100755..100644
--- 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
index 3bf06617..678a3375 100755..100644
--- 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
index a81f94c1..234c51dd 100755..100644
--- 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<IFolderFolder> 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
index 21d74db8..e9ef2d8c 100755..100644
--- 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
index 866b0b2d..7a51e1b7 100755..100644
--- 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
index e5fe6e67..e7e5d73e 100755..100644
--- 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
index 3e4a611e..3e4a611e 100755..100644
--- a/CPP/7zip/UI/FileManager/SettingsPage.rc
+++ b/CPP/7zip/UI/FileManager/SettingsPage.rc
diff --git a/CPP/7zip/UI/FileManager/SettingsPage2.rc b/CPP/7zip/UI/FileManager/SettingsPage2.rc
index c920120e..66629612 100755..100644
--- 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
index b6c7f5cc..71204597 100755..100644
--- 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
index 5dca8e48..d35d76c9 100755..100644
--- 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
index 33fb64e7..00aae658 100755..100644
--- 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<UInt64> 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
index e977d651..5a026e8a 100755..100644
--- 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
index a6f06d1c..50584a14 100755..100644
--- 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
index 8bae0573..b0172a9f 100755..100644
--- 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<UInt64> &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<UInt64> &volSizes)
+UInt64 GetNumberOfVolumes(UInt64 size, const CRecordVector<UInt64> &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
index 755c707c..641dfe6b 100755..100644
--- 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<UInt64> &values);
void AddVolumeItems(NWindows::NControl::CComboBox &volumeCombo);
-
-UInt64 GetNumberOfVolumes(UInt64 size, CRecordVector<UInt64> &volSizes);
+UInt64 GetNumberOfVolumes(UInt64 size, const CRecordVector<UInt64> &volSizes);
#endif
diff --git a/CPP/7zip/UI/FileManager/StdAfx.cpp b/CPP/7zip/UI/FileManager/StdAfx.cpp
index d0feea85..d0feea85 100755..100644
--- a/CPP/7zip/UI/FileManager/StdAfx.cpp
+++ b/CPP/7zip/UI/FileManager/StdAfx.cpp
diff --git a/CPP/7zip/UI/FileManager/StdAfx.h b/CPP/7zip/UI/FileManager/StdAfx.h
index b09de592..85389112 100755..100644
--- 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 <windows.h>
-#include <stdio.h>
#include <commctrl.h>
#include <ShlObj.h>
-#include <limits.h>
-#include <tchar.h>
#include <shlwapi.h>
-// #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
index bddaa971..fb38a735 100755..100644
--- 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
index 7f72b764..fc070de1 100755..100644
--- 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
index e537621e..2c35c191 100755..100644
--- 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<CAttribIconPair> &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<CExtIconPair> &vect, const wchar_t *ext, int &insertPos)
+{
+ unsigned left = 0, right = vect.Size();
+ while (left != right)
+ {
+ unsigned mid = (left + right) / 2;
+ int compare = MyStringCompareNoCase(ext, vect[mid].Ext);
+ if (compare == 0)
+ return mid;
+ if (compare < 0)
+ right = mid;
+ else
+ left = mid + 1;
+ }
+ insertPos = left;
+ return -1;
+}
+
+int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UString *typeName */)
+{
+ int dotPos = -1;
+ unsigned i;
+ for (i = 0;; i++)
+ {
+ wchar_t c = fileName[i];
+ if (c == 0)
+ break;
+ if (c == '.')
+ dotPos = i;
+ }
+
+ /*
+ if (MyStringCompareNoCase(fileName, L"$Recycle.Bin") == 0)
+ {
+ char s[256];
+ sprintf(s, "SPEC i = %3d, attr = %7x", _attribMap.Size(), attrib);
+ OutputDebugStringA(s);
+ OutputDebugStringW(fileName);
+ }
+ */
+
if ((attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 || dotPos < 0)
{
- 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
index 129de781..20199acb 100755..100644
--- 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<CExtIconPair> _extMap;
- CObjectVector<CAttribIconPair> _attribMap;
public:
+ CRecordVector<CAttribIconPair> _attribMap;
+ CObjectVector<CExtIconPair> _extMap;
+ int SplitIconIndex;
+ int SplitIconIndex_Defined;
+
+ CExtToIconMap(): SplitIconIndex_Defined(false) {}
+
void Clear()
{
+ SplitIconIndex_Defined = false;
_extMap.Clear();
_attribMap.Clear();
}
- int GetIconIndex(DWORD attrib, const 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
index 359656ea..e4ac706d 100755..100644
--- 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
index a4b4ab92..0bf6aae7 100755..100644
--- 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
index 49581c9b..42e72cf1 100755..100644
--- 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
index 133996e7..edc576f7 100755..100644
--- 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
index ef85ba23..ef85ba23 100755..100644
--- a/CPP/7zip/UI/FileManager/Test.bmp
+++ b/CPP/7zip/UI/FileManager/Test.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/Test2.bmp b/CPP/7zip/UI/FileManager/Test2.bmp
index 99b7dbf0..99b7dbf0 100755..100644
--- a/CPP/7zip/UI/FileManager/Test2.bmp
+++ b/CPP/7zip/UI/FileManager/Test2.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/TextPairs.cpp b/CPP/7zip/UI/FileManager/TextPairs.cpp
index cc57c0d5..354b479f 100755..100644
--- 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<CTextPair> &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<CTextPair> &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
index 2670e030..d27cd97c 100755..100644
--- 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<CTextPair> 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
index 43dfa4dc..4141f01d 100755..100644
--- 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
index aa13320f..944453a1 100755..100644
--- 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
index f11f68d6..9688a4a5 100755..100644
--- 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<CColumnInfo> &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<CColumnInfo> &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 &currentPanel, 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
index b0510813..dbb98dc6 100755..100644
--- 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<CColumnInfo> Columns;
+ CRecordVector<CColumnInfo> 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 &currentPanel, 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
index eeca66f9..96ae902f 100755..100644
--- 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
index cdb77edf..55af3555 100755..100644
--- 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
index 2952ce5a..61cf33e8 100755..100644
--- 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
index 14cedda5..7c1b40e4 100755..100644
--- 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
index 2e706ea2..f748e0bd 100755..100644
--- 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
index 68c6047e..68c6047e 100755..100644
--- a/CPP/7zip/UI/GUI/7zG.exe.manifest
+++ b/CPP/7zip/UI/GUI/7zG.exe.manifest
diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp
index 8ca87f8f..1f4bcab5 100755..100644
--- 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<CProperty> 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
index b3ab9dcb..82531117 100755..100644
--- 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
index 6b17a12a..a31d2f25 100755..100644
--- 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
index cf009df3..7dd6d031 100755..100644
--- 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
index 2723f515..a2d0ac2b 100755..100644
--- 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[] =
{
@@ -225,6 +221,12 @@ static const CFormatInfo g_Formats[] =
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),
0, 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
index 7b0067fa..3463fefc 100755..100644
--- 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<CArcInfoEx> *ArcFormats;
- CRecordVector<int> 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
index 5a71b043..6c555a7e 100755..100644
--- 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
index 2dcdc80e..ff99fa94 100755..100644
--- 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
index ad8f9910..defcfcc4 100755..100644
--- 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
index 64ae445e..d1ce8255 100755..100644
--- a/CPP/7zip/UI/GUI/ExtractDialog.cpp
+++ b/CPP/7zip/UI/GUI/ExtractDialog.cpp
@@ -2,28 +2,25 @@
#include "StdAfx.h"
-// #include <HtmlHelp.h>
+#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
index b0636c72..33349ffc 100755..100644
--- 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
index ec4c20c2..3728b96d 100755..100644
--- 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
index 38652b29..403a6546 100755..100644
--- 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
index 9d39bffd..b5fbeaec 100755..100644
--- 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<COpenType> *FormatIndices;
+ const CIntVector *ExcludedFormatIndices;
UStringVector *ArchivePaths;
UStringVector *ArchivePathsFull;
const NWildcard::CCensorNode *WildcardCensor;
const CExtractOptions *Options;
+ #ifndef _SFX
+ CHashBundle *HashBundle;
+ #endif
CMyComPtr<IExtractCallbackUI> 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<COpenType> &formatIndices,
+ const CIntVector &excludedFormatIndices,
UStringVector &archivePaths,
UStringVector &archivePathsFull,
const NWildcard::CCensorNode &wildcardCensor,
CExtractOptions &options,
+ #ifndef _SFX
+ CHashBundle *hb,
+ #endif
bool showDialog,
bool &messageWasDisplayed,
CExtractCallbackImp *extractCallback,
@@ -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
index b0a692f0..d55b30de 100755..100644
--- 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<COpenType> &formatIndices,
+ const CIntVector &excludedFormatIndices,
UStringVector &archivePaths,
UStringVector &archivePathsFull,
const NWildcard::CCensorNode &wildcardCensor,
CExtractOptions &options,
+ #ifndef _SFX
+ CHashBundle *hb,
+ #endif
bool showDialog,
bool &messageWasDisplayed,
CExtractCallbackImp *extractCallback,
diff --git a/CPP/7zip/UI/GUI/ExtractRes.h b/CPP/7zip/UI/GUI/ExtractRes.h
index 6219edda..48738bbb 100755..100644
--- 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
index 3a0a34da..3a0a34da 100755..100644
--- a/CPP/7zip/UI/GUI/FM.ico
+++ b/CPP/7zip/UI/GUI/FM.ico
Binary files differ
diff --git a/CPP/7zip/UI/GUI/GUI.cpp b/CPP/7zip/UI/GUI/GUI.cpp
index 5b809a63..592f7673 100755..100644
--- 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<IUnknown> 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<COpenType> 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<CCodecInfoEx> 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
index 382f592e..1cbdbfd4 100755..100644
--- a/CPP/7zip/UI/GUI/GUI.dsp
+++ b/CPP/7zip/UI/GUI/GUI.dsp
@@ -45,7 +45,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c
-# ADD CPP /nologo /Gz /MD /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
index 85d33484..85d33484 100755..100644
--- a/CPP/7zip/UI/GUI/GUI.dsw
+++ b/CPP/7zip/UI/GUI/GUI.dsw
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
index d0feea85..d0feea85 100755..100644
--- a/CPP/7zip/UI/GUI/StdAfx.cpp
+++ b/CPP/7zip/UI/GUI/StdAfx.cpp
diff --git a/CPP/7zip/UI/GUI/StdAfx.h b/CPP/7zip/UI/GUI/StdAfx.h
index 46ea51cf..9e322f96 100755..100644
--- 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 <windows.h>
-#include <commctrl.h>
-#include <shlobj.h>
-#include <stdio.h>
+// #define _WIN32_WINNT 0x0400
+#define _WIN32_WINNT 0x0500
+#define WINVER _WIN32_WINNT
-#include "Common/NewHandler.h"
+#include "../../../Common/Common.h"
+
+// #include <commctrl.h>
+#include <ShlObj.h>
+#include <shlwapi.h>
+
+// #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
index 8ec01867..36af147b 100755..100644
--- 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
index b5ca154a..21b6f432 100755..100644
--- 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
index 406d5bf1..a7af4e94 100755..100644
--- 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<COpenType> *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<CProperty> &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<CProperty> &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<NWildcard::CCensorPath> &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<COpenType> &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
index c06ec1e7..d1880de0 100755..100644
--- 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<COpenType> &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
index cd2c2f55..60cfcd4b 100755..100644
--- 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
index bfc2029b..0f7c6235 100755..100644
--- a/CPP/7zip/UI/GUI/resource.rc
+++ b/CPP/7zip/UI/GUI/resource.rc
@@ -1,10 +1,10 @@
#include "../../MyVersionInfo.rc"
-#include <winnt.h>
+// #include <winnt.h>
#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
index 4f8b1573..cd882924 100755..100644
--- 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
index 542717ee..49534f50 100755..100644
--- 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
index 1b0cdbe1..1b0cdbe1 100755..100644
--- a/CPP/7zip/UI/makefile
+++ b/CPP/7zip/UI/makefile
diff --git a/CPP/7zip/makefile b/CPP/7zip/makefile
index 9d31e6bd..9d31e6bd 100755..100644
--- a/CPP/7zip/makefile
+++ b/CPP/7zip/makefile
diff --git a/CPP/Build.mak b/CPP/Build.mak
index b3465d44..df600eb8 100755..100644
--- 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
index 006d3155..006d3155 100755..100644
--- a/CPP/Common/AutoPtr.h
+++ b/CPP/Common/AutoPtr.h
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 T> 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 <class T>
-bool operator==(const CBuffer<T>& b1, const CBuffer<T>& 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 <class T>
-bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2)
-{
- return !(b1 == b2);
-}
-
-typedef CBuffer<char> CCharBuffer;
-typedef CBuffer<wchar_t> CWCharBuffer;
-typedef CBuffer<unsigned char> CByteBuffer;
-
-#endif
diff --git a/CPP/Common/CRC.cpp b/CPP/Common/CRC.cpp
index 9a9f81fb..9a9f81fb 100755..100644
--- a/CPP/Common/CRC.cpp
+++ b/CPP/Common/CRC.cpp
diff --git a/CPP/Common/C_FileIO.cpp b/CPP/Common/C_FileIO.cpp
index 7c629390..7c629390 100755..100644
--- a/CPP/Common/C_FileIO.cpp
+++ b/CPP/Common/C_FileIO.cpp
diff --git a/CPP/Common/C_FileIO.h b/CPP/Common/C_FileIO.h
index ff7a1a11..cb043311 100755..100644
--- a/CPP/Common/C_FileIO.h
+++ b/CPP/Common/C_FileIO.h
@@ -6,7 +6,7 @@
#include <stdio.h>
#include <sys/types.h>
-#include "Types.h"
+#include "MyTypes.h"
#include "MyWindows.h"
#ifdef _WIN32
diff --git a/CPP/Common/ComTry.h b/CPP/Common/ComTry.h
index fb4ef045..fb4ef045 100755..100644
--- a/CPP/Common/ComTry.h
+++ b/CPP/Common/ComTry.h
diff --git a/CPP/Common/CommandLineParser.cpp b/CPP/Common/CommandLineParser.cpp
index 80b467fc..1bf41736 100755..100644
--- 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
index 3d0b41dd..c9fd2956 100755..100644
--- 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
index dad3ae8f..dad3ae8f 100755..100644
--- a/CPP/Common/Defs.h
+++ b/CPP/Common/Defs.h
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 <windows.h>
+#include <wchar.h>
+#else
+#include <ctype.h>
+#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 <string.h>
+
+#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
index bf52a742..cd23ad73 100755..100644
--- 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 T> class CDynamicBuffer: public CBuffer<T>
+template <class T> 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<T>() {};
- CDynamicBuffer(const CDynamicBuffer &buffer): CBuffer<T>(buffer) {};
- CDynamicBuffer(size_t size): CBuffer<T>(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<char> CCharDynamicBuffer;
-typedef CDynamicBuffer<wchar_t> CWCharDynamicBuffer;
typedef CDynamicBuffer<unsigned char> CByteDynamicBuffer;
#endif
diff --git a/CPP/Common/IntToString.cpp b/CPP/Common/IntToString.cpp
index 013fee52..09156e16 100755..100644
--- 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
index 782f930c..69605ab7 100755..100644
--- 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 <stddef.h>
-#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
index 2339d120..c1638ba0 100755..100644
--- 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<CTextConfigPair> 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
index 2ce53a0d..2ca2a850 100755..100644
--- 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<CLangPair> _langPairs;
+ wchar_t *_text;
+ CRecordVector<UInt32> _ids;
+ CRecordVector<UInt32> _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
index f9bd18ed..313532ef 100755..100644
--- 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
index d43bfdfc..e8d833fd 100755..100644
--- 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 T> class CBuffer
+{
+ T *_items;
+ size_t _size;
+
+ void CopyToEmpty(const CBuffer &buffer)
+ {
+ if (buffer._size > 0)
+ {
+ _items = new T[buffer._size];
+ memcpy(_items, buffer._items, buffer._size * sizeof(T));
+ _size = buffer._size;
+ }
+ }
+public:
+ void Free()
+ {
+ 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 <class T>
+bool operator==(const CBuffer<T>& b1, const CBuffer<T>& b2)
+{
+ size_t size1 = b1.Size();
+ if (size1 != b2.Size())
+ return false;
+ return memcmp(b1, b2, size1 * sizeof(T)) == 0;
+}
+
+template <class T>
+bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2)
+{
+ size_t size1 = b1.Size();
+ if (size1 == b2.Size())
+ return false;
+ return memcmp(b1, b2, size1 * sizeof(T)) != 0;
+}
+
+
+typedef CBuffer<char> CCharBuffer;
+typedef CBuffer<wchar_t> CWCharBuffer;
+typedef CBuffer<unsigned char> CByteBuffer;
+
+
+template <class T> 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<unsigned char> CByteArr;
+typedef CObjArray<bool> CBoolArr;
+typedef CObjArray<int> CIntArr;
+
+// #define CRecArray CObjArray
+
+template <class T> 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
index 2f00c258..9e2576e3 100755..100644
--- 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<T>& lp)
- {
- if ((_p = lp._p) != NULL)
- _p->AddRef();
- }
+ CMyComPtr(): _p(NULL) {}
+ CMyComPtr(T* p) throw() { if ((_p = p) != NULL) p->AddRef(); }
+ CMyComPtr(const CMyComPtr<T>& 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<T>& 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 <class Q>
- 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
index f0ad1115..f0ad1115 100755..100644
--- a/CPP/Common/MyException.h
+++ b/CPP/Common/MyException.h
diff --git a/CPP/Common/MyGuidDef.h b/CPP/Common/MyGuidDef.h
index 3c52cc07..68745870 100755..100644
--- 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
index d6a48698..d6a48698 100755..100644
--- a/CPP/Common/MyInitGuid.h
+++ b/CPP/Common/MyInitGuid.h
diff --git a/CPP/Common/MyMap.cpp b/CPP/Common/MyMap.cpp
index 0ee11e8c..db95169e 100755..100644
--- 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
index d0dd43f5..cbcbadd6 100755..100644
--- 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
index dc254eaf..ac407e87 100755..100644
--- a/CPP/Common/MyString.cpp
+++ b/CPP/Common/MyString.cpp
@@ -4,17 +4,22 @@
#ifdef _WIN32
#include <windows.h>
+#include <wchar.h>
#else
#include <ctype.h>
#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
index 0312bac6..b70e9a54 100755..100644
--- a/CPP/Common/MyString.h
+++ b/CPP/Common/MyString.h
@@ -5,552 +5,468 @@
#include <string.h>
-#include "Types.h"
+#ifndef _WIN32
+#include <wctype.h>
+#include <wchar.h>
+#endif
+
+#include "MyTypes.h"
#include "MyVector.h"
-template <class T>
-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 <class T>
-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 T>
-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<T> 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<T> 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 <class T>
-CStringBase<T> operator+(const CStringBase<T>& s1, const CStringBase<T>& s2)
-{
- CStringBase<T> result(s1);
- result += s2;
- return result;
-}
-
-template <class T>
-CStringBase<T> operator+(const CStringBase<T>& s, T c)
-{
- CStringBase<T> result(s);
- result += c;
- return result;
-}
-
-template <class T>
-CStringBase<T> operator+(T c, const CStringBase<T>& s)
-{
- CStringBase<T> result(c);
- result += s;
- return result;
-}
-
-template <class T>
-CStringBase<T> operator+(const CStringBase<T>& s, const T * chars)
-{
- CStringBase<T> result(s);
- result += chars;
- return result;
-}
-
-template <class T>
-CStringBase<T> operator+(const T * chars, const CStringBase<T>& s)
-{
- CStringBase<T> result(chars);
- result += s;
- return result;
-}
-
-template <class T>
-bool operator==(const CStringBase<T>& s1, const CStringBase<T>& s2)
- { return (s1.Compare(s2) == 0); }
-
-template <class T>
-bool operator<(const CStringBase<T>& s1, const CStringBase<T>& s2)
- { return (s1.Compare(s2) < 0); }
-
-template <class T>
-bool operator==(const T *s1, const CStringBase<T>& s2)
- { return (s2.Compare(s1) == 0); }
-
-template <class T>
-bool operator==(const CStringBase<T>& s1, const T *s2)
- { return (s1.Compare(s2) == 0); }
-
-template <class T>
-bool operator!=(const CStringBase<T>& s1, const CStringBase<T>& s2)
- { return (s1.Compare(s2) != 0); }
+bool operator<(const UString &s1, const UString &s2);
+bool operator>(const UString &s1, const UString &s2);
-template <class T>
-bool operator!=(const T *s1, const CStringBase<T>& 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 <class T>
-bool operator!=(const CStringBase<T>& 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<char> AString;
-typedef CStringBase<wchar_t> UString;
typedef CObjectVector<AString> AStringVector;
typedef CObjectVector<UString> 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
index e9e8666b..e9e8666b 100755..100644
--- a/CPP/Common/MyUnknown.h
+++ b/CPP/Common/MyUnknown.h
diff --git a/CPP/Common/MyVector.cpp b/CPP/Common/MyVector.cpp
index 3b531768..0b1baf45 100755..100644
--- a/CPP/Common/MyVector.cpp
+++ b/CPP/Common/MyVector.cpp
@@ -1,87 +1,3 @@
// Common/MyVector.cpp
#include "StdAfx.h"
-
-#include <string.h>
-
-#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
index 781b648b..0d060a93 100755..100644
--- 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 T>
+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 T>
-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<int> CIntVector;
@@ -177,76 +401,197 @@ typedef CRecordVector<unsigned char> CByteVector;
typedef CRecordVector<void *> CPointerVector;
template <class T>
-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
index f940fc8a..1d9b1e61 100755..100644
--- 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
index 780e1f5d..139a4e8b 100755..100644
--- a/CPP/Common/MyWindows.h
+++ b/CPP/Common/MyWindows.h
@@ -7,6 +7,11 @@
#include <windows.h>
+#ifdef UNDER_CE
+ #undef VARIANT_TRUE
+ #define VARIANT_TRUE ((VARIANT_BOOL)-1)
+#endif
+
#else
#include <stddef.h> // 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
index 8aa9ce8c..31e7b3df 100755..100644
--- 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 = "</";
+ SKIP_SPACES(s);
+
+ const char *beg = s;
for (;;)
{
- SKIP_SPACES(s, pos);
-
- if (s.Mid(pos, finishString.Length()) == finishString)
- return true;
-
- CXmlItem item;
- if (!item.ParseItem(s, pos, numAllowedLevels - 1))
- return false;
- SubItems.Add(item);
+ char c;
+ c = *s; if (c == 0 || c == '<') break; s++;
+ c = *s; if (c == 0 || c == '<') break; s++;
}
-}
-
-bool CXmlItem::ParseItem(const AString &s, int &pos, int numAllowedLevels)
-{
- SKIP_SPACES(s, pos);
-
- int pos2 = s.Find('<', pos);
- if (pos2 < 0)
- return false;
- if (pos2 != pos)
+ if (*s == 0)
+ return NULL;
+ if (s != beg)
{
IsTag = false;
- Name += s.Mid(pos, pos2 - pos);
- pos = pos2;
- return true;
+ Name.SetFrom(beg, (unsigned)(s - beg));
+ return s;
}
+
IsTag = true;
- pos++;
- SKIP_SPACES(s, pos);
+ s++;
+ SKIP_SPACES(s);
- for (; pos < s.Length(); pos++)
- {
- char c = s[pos];
- if (!IsValidChar(c))
+ beg = s;
+ for (;; s++)
+ if (!IsValidChar(*s))
break;
- Name += c;
- }
- if (Name.IsEmpty() || pos == s.Length())
- return false;
+ if (s == beg || *s == 0)
+ return NULL;
+ Name.SetFrom(beg, (unsigned)(s - beg));
- int posTemp = pos;
for (;;)
{
- SKIP_SPACES(s, pos);
- if (s[pos] == '/')
+ beg = s;
+ SKIP_SPACES(s);
+ if (*s == '/')
{
- pos++;
- // SKIP_SPACES(s, pos);
- return (s[pos++] == '>');
+ 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("</") + Name + 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, "<!DOCTYPE", ">"))
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
index c6e8829a..ae3663c3 100755..100644
--- 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<CXmlProp> Props;
CObjectVector<CXmlItem> 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
index aad6e7d1..410f24e9 100755..100644
--- 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 <stdio.h>
+
+// #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
index 215ba05f..e3e7422c 100755..100644
--- 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
index 4bd3fcf9..4bd3fcf9 100755..100644
--- a/CPP/Common/Random.cpp
+++ b/CPP/Common/Random.cpp
diff --git a/CPP/Common/Random.h b/CPP/Common/Random.h
index ffef20d1..ffef20d1 100755..100644
--- a/CPP/Common/Random.h
+++ b/CPP/Common/Random.h
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
index b8ba1d5c..420f5c32 100755..100644
--- 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
index f3dcb85f..2d28c735 100755..100644
--- 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
index 0d182cc3..6d9ed670 100755..100644
--- 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 <stdio.h>
#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
index 061a7606..1d6d81a4 100755..100644
--- 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
index b0b2c615..42f43938 100755..100644
--- 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 <stdio.h>
-#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
index 681895b7..0443a06c 100755..100644
--- 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
index cd737bec..8eea72ef 100755..100644
--- 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
index 15474a42..ea59c0fa 100755..100644
--- 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
index cd99f17e..5c5d7d7f 100755..100644
--- 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
index 34fedeb8..ad368791 100755..100644
--- 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<CTextConfigPair> &pairs)
+bool GetTextConfig(const AString &s, CObjectVector<CTextConfigPair> &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<CTextConfigPair> &pairs)
int FindTextConfigItem(const CObjectVector<CTextConfigPair> &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
index a25142a7..cae4f17a 100755..100644
--- 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<CTextConfigPair> &pairs);
-int FindTextConfigItem(const CObjectVector<CTextConfigPair> &pairs, const UString &id);
+int FindTextConfigItem(const CObjectVector<CTextConfigPair> &pairs, const UString &id) throw();
UString GetTextConfigValue(const CObjectVector<CTextConfigPair> &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
index 95362430..c4b9404d 100755..100644
--- 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
index 2a14600d..16b02fe4 100755..100644
--- 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
index 87d44971..182256ab 100755..100644
--- 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<N [0, M) ... [N-M-1, N-1) same as ForBoth-File
- nonreq [0, M) same as ForBoth-File
+ForDir rec M<N [0, M) ... [N-M-1, N-1) same as ForBoth-File
+!ForFile nonrec [0, M) same as ForBoth-File
-ForBoth req m<=N [0, M) ... [N-M, N) same as ForBoth-File
- nonreq [0, M) same as ForBoth-File
+ForFile rec m<=N [0, M) ... [N-M, N) same as ForBoth-File
+ForDir nonrec [0, M) same as ForBoth-File
*/
+bool CItem::AreAllAllowed() const
+{
+ return ForFile && ForDir && WildcardMatching && PathParts.Size() == 1 && PathParts.Front() == L"*";
+}
+
bool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const
{
if (!isFile && !ForDir)
@@ -176,36 +217,62 @@ bool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const
return false;
int start = 0;
int finish = 0;
+
if (isFile)
{
- if (!ForDir && !Recursive && delta !=0)
- return false;
+ if (!ForDir)
+ {
+ if (Recursive)
+ start = delta;
+ else if (delta !=0)
+ return false;
+ }
if (!ForFile && delta == 0)
return false;
- if (!ForDir && Recursive)
- start = delta;
}
+
if (Recursive)
{
finish = delta;
if (isFile && !ForFile)
finish = delta - 1;
}
+
for (int d = start; d <= finish; d++)
{
- int i;
+ unsigned i;
for (i = 0; i < PathParts.Size(); i++)
- if (!CompareWildCardWithName(PathParts[i], pathParts[i + d]))
- break;
+ {
+ if (WildcardMatching)
+ {
+ if (!DoesWildcardMatchName(PathParts[i], pathParts[i + d]))
+ break;
+ }
+ else
+ {
+ if (CompareFileNames(PathParts[i], pathParts[i + d]) != 0)
+ break;
+ }
+ }
if (i == PathParts.Size())
return true;
}
return false;
}
+bool CCensorNode::AreAllAllowed() const
+{
+ if (!Name.IsEmpty() ||
+ !SubNodes.IsEmpty() ||
+ !ExcludeItems.IsEmpty() ||
+ IncludeItems.Size() != 1)
+ return false;
+ return IncludeItems.Front().AreAllAllowed();
+}
+
int CCensorNode::FindSubNode(const UString &name) const
{
- for (int i = 0; i < SubNodes.Size(); i++)
+ FOR_VECTOR (i, SubNodes)
if (CompareFileNames(SubNodes[i].Name, name) == 0)
return i;
return -1;
@@ -223,11 +290,19 @@ void CCensorNode::AddItem(bool include, CItem &item)
{
if (item.PathParts.Size() <= 1)
{
+ if (item.PathParts.Size() != 0 && item.WildcardMatching)
+ {
+ if (!DoesNameContainWildcard(item.PathParts.Front()))
+ item.WildcardMatching = false;
+ }
AddItemSimple(include, item);
return;
}
const UString &front = item.PathParts.Front();
- if (DoesNameContainWildCard(front))
+
+ // We can't ignore wildcard, since we don't allow wildcard in SubNodes[].Name
+ // if (item.Wildcard)
+ if (DoesNameContainWildcard(front))
{
AddItemSimple(include, item);
return;
@@ -239,19 +314,20 @@ void CCensorNode::AddItem(bool include, CItem &item)
SubNodes[index].AddItem(include, item);
}
-void CCensorNode::AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir)
+void CCensorNode::AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir, bool wildcardMatching)
{
CItem item;
SplitPathToParts(path, item.PathParts);
item.Recursive = recursive;
item.ForFile = forFile;
item.ForDir = forDir;
+ item.WildcardMatching = wildcardMatching;
AddItem(include, item);
}
bool CCensorNode::NeedCheckSubDirs() const
{
- for (int i = 0; i < IncludeItems.Size(); i++)
+ FOR_VECTOR (i, IncludeItems)
{
const CItem &item = IncludeItems[i];
if (item.Recursive || item.PathParts.Size() > 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<CItem> &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
index 6d4cbcec..b9971202 100755..100644
--- 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<CCensorNode> SubNodes;
CObjectVector<CItem> IncludeItems;
CObjectVector<CItem> 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<CPair> Pairs;
+
+ CObjectVector<NWildcard::CCensorPath> 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
index a746de12..a746de12 100755..100644
--- a/CPP/Windows/COM.cpp
+++ b/CPP/Windows/COM.cpp
diff --git a/CPP/Windows/COM.h b/CPP/Windows/COM.h
index 506bbbc6..eedcfa9d 100755..100644
--- 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
index e1ff62be..bab9db72 100755..100644
--- a/CPP/Windows/Clipboard.cpp
+++ b/CPP/Windows/Clipboard.cpp
@@ -6,13 +6,12 @@
#include <winuserm.h>
#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
index c80ba5ea..60fedc13 100755..100644
--- 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
index 4ee7412d..6092b050 100755..100644
--- 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<int> 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<int> 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
index f24bb5b2..aaf17ac5 100755..100644
--- 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
index 7773fee2..7773fee2 100755..100644
--- a/CPP/Windows/Console.cpp
+++ b/CPP/Windows/Console.cpp
diff --git a/CPP/Windows/Console.h b/CPP/Windows/Console.h
index 99ae90f1..f2e8c293 100755..100644
--- 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
index 40d2f865..9b458fe4 100755..100644
--- 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
index aa0eb930..8c6fd381 100755..100644
--- 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
index 387c5e2d..780211ec 100755..100644
--- 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
index 2695ca54..01bc7d43 100755..100644
--- 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
index 2b5147e7..b450266b 100755..100644
--- 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
index c4bf5704..17ac9f13 100755..100644
--- 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
index 16a46fa4..16a46fa4 100755..100644
--- a/CPP/Windows/Control/ImageList.cpp
+++ b/CPP/Windows/Control/ImageList.cpp
diff --git a/CPP/Windows/Control/ImageList.h b/CPP/Windows/Control/ImageList.h
index 127cd1ed..72094399 100755..100644
--- 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
index 255a17c5..6d916591 100755..100644
--- 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
index bebcd9e2..ceb297f8 100755..100644
--- 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 <commctrl.h>
diff --git a/CPP/Windows/Control/ProgressBar.h b/CPP/Windows/Control/ProgressBar.h
index 4591880a..4591880a 100755..100644
--- a/CPP/Windows/Control/ProgressBar.h
+++ b/CPP/Windows/Control/ProgressBar.h
diff --git a/CPP/Windows/Control/PropertyPage.cpp b/CPP/Windows/Control/PropertyPage.cpp
index d7eaab17..bbac74ad 100755..100644
--- 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<CPageInfo> &pagesInfo, HWND hwndPare
#endif
CRecordVector<PROPSHEETPAGEW> 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
index 4e7e088e..4e7e088e 100755..100644
--- a/CPP/Windows/Control/PropertyPage.h
+++ b/CPP/Windows/Control/PropertyPage.h
diff --git a/CPP/Windows/Control/ReBar.h b/CPP/Windows/Control/ReBar.h
index 8e11c139..bd475b10 100755..100644
--- 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
index cb3126dd..cb3126dd 100755..100644
--- a/CPP/Windows/Control/Static.h
+++ b/CPP/Windows/Control/Static.h
diff --git a/CPP/Windows/Control/StatusBar.h b/CPP/Windows/Control/StatusBar.h
index 8766188b..f3e0d3ef 100755..100644
--- 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
index ef555ec1..1cbd7fea 100755..100644
--- 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
index 262184ae..d579ab7d 100755..100644
--- 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
index 42dc4e40..c6d31112 100755..100644
--- 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
index e1299048..e6ddb6d0 100755..100644
--- 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
index 2af031b8..d744b3e6 100755..100644
--- 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
index 81eec692..367d1be1 100755..100644
--- 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
index 9f0f5cd7..f7e5b81b 100755..100644
--- 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
index 281c40c3..281c40c3 100755..100644
--- a/CPP/Windows/Defs.h
+++ b/CPP/Windows/Defs.h
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/Error.cpp b/CPP/Windows/ErrorMsg.cpp
index c02e3b9e..7c82537d 100755..100644
--- a/CPP/Windows/Error.cpp
+++ b/CPP/Windows/ErrorMsg.cpp
@@ -1,12 +1,13 @@
-// Windows/Error.h
+// Windows/ErrorMsg.h
#include "StdAfx.h"
-#include "Windows/Error.h"
#ifndef _UNICODE
-#include "Common/StringConvert.h"
+#include "../Common/StringConvert.h"
#endif
+#include "ErrorMsg.h"
+
#ifndef _UNICODE
extern bool g_IsNT;
#endif
@@ -39,7 +40,7 @@ static bool MyFormatMessage(DWORD errorCode, UString &message)
return true;
}
-UString MyFormatMessageW(DWORD errorCode)
+UString MyFormatMessage(DWORD errorCode)
{
UString message;
if (!MyFormatMessage(errorCode, message))
@@ -47,7 +48,7 @@ UString MyFormatMessageW(DWORD errorCode)
wchar_t s[16];
for (int i = 0; i < 8; i++)
{
- int t = errorCode & 0xF;
+ unsigned t = errorCode & 0xF;
errorCode >>= 4;
s[7 - i] = (wchar_t)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
}
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
index 88215faa..e6751f85 100755..100644
--- 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
index e43c19bd..02d3e5a5 100755..100644
--- 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
index 081bd9bc..6d81ae85 100755..100644
--- 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
index 97a3b7c2..aaa7499b 100755..100644
--- 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
index e8f98747..188f85fe 100755..100644
--- 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
index ecd7af96..7cb5e83f 100755..100644
--- 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
index 55048fdb..55048fdb 100755..100644
--- a/CPP/Windows/FileMapping.cpp
+++ b/CPP/Windows/FileMapping.cpp
diff --git a/CPP/Windows/FileMapping.h b/CPP/Windows/FileMapping.h
index 3f0ebd74..f90c429f 100755..100644
--- 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
index 8f464aa8..fdf8845e 100755..100644
--- 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
index 9ee57f9d..04fc79b2 100755..100644
--- 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
index 8bf595b2..6c1f48a2 100755..100644
--- 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
index a7a8d1a9..9076ea13 100755..100644
--- 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
index bb7cb705..bb7cb705 100755..100644
--- a/CPP/Windows/Handle.h
+++ b/CPP/Windows/Handle.h
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/Memory.cpp b/CPP/Windows/MemoryGlobal.cpp
index 4c23205e..07b9b249 100755..100644
--- a/CPP/Windows/Memory.cpp
+++ b/CPP/Windows/MemoryGlobal.cpp
@@ -1,8 +1,8 @@
-// Windows/Memory.cpp
+// Windows/MemoryGlobal.cpp
#include "StdAfx.h"
-#include "Windows/Memory.h"
+#include "MemoryGlobal.h"
namespace NWindows {
namespace NMemory {
@@ -12,24 +12,24 @@ bool CGlobal::Alloc(UINT flags, SIZE_T size)
HGLOBAL newBlock = ::GlobalAlloc(flags, size);
if (newBlock == NULL)
return false;
- m_MemoryHandle = newBlock;
+ _global = newBlock;
return true;
}
bool CGlobal::Free()
{
- if (m_MemoryHandle == NULL)
+ if (_global == NULL)
return true;
- m_MemoryHandle = ::GlobalFree(m_MemoryHandle);
- return (m_MemoryHandle == NULL);
+ _global = ::GlobalFree(_global);
+ return (_global == NULL);
}
bool CGlobal::ReAlloc(SIZE_T size)
{
- HGLOBAL newBlock = ::GlobalReAlloc(m_MemoryHandle, size, GMEM_MOVEABLE);
+ HGLOBAL newBlock = ::GlobalReAlloc(_global, size, GMEM_MOVEABLE);
if (newBlock == NULL)
return false;
- m_MemoryHandle = newBlock;
+ _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
index e0f43099..fa45f760 100755..100644
--- 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
index 5fe619de..f08e5179 100755..100644
--- 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
index 675f8623..3834881a 100755..100644
--- 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
index 2563b911..75f840d0 100755..100644
--- 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
index c231d3ce..c231d3ce 100755..100644
--- a/CPP/Windows/NationalTime.cpp
+++ b/CPP/Windows/NationalTime.cpp
diff --git a/CPP/Windows/NationalTime.h b/CPP/Windows/NationalTime.h
index 86e014bf..86e014bf 100755..100644
--- a/CPP/Windows/NationalTime.h
+++ b/CPP/Windows/NationalTime.h
diff --git a/CPP/Windows/Net.cpp b/CPP/Windows/Net.cpp
index b0a18732..47079f37 100755..100644
--- 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
index c88b6113..7b60b1b4 100755..100644
--- 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
index e56318f0..e56318f0 100755..100644
--- a/CPP/Windows/NtCheck.h
+++ b/CPP/Windows/NtCheck.h
diff --git a/CPP/Windows/ProcessMessages.cpp b/CPP/Windows/ProcessMessages.cpp
index 0f48aee2..0f48aee2 100755..100644
--- a/CPP/Windows/ProcessMessages.cpp
+++ b/CPP/Windows/ProcessMessages.cpp
diff --git a/CPP/Windows/ProcessMessages.h b/CPP/Windows/ProcessMessages.h
index 63f8ec8a..63f8ec8a 100755..100644
--- a/CPP/Windows/ProcessMessages.h
+++ b/CPP/Windows/ProcessMessages.h
diff --git a/CPP/Windows/Process.cpp b/CPP/Windows/ProcessUtils.cpp
index 9bcee7d5..9b833e54 100755..100644
--- a/CPP/Windows/Process.cpp
+++ b/CPP/Windows/ProcessUtils.cpp
@@ -1,10 +1,10 @@
-// Process.cpp
+// ProcessUtils.cpp
#include "StdAfx.h"
#include "../Common/StringConvert.h"
-#include "Process.h"
+#include "ProcessUtils.h"
#ifndef _UNICODE
extern bool g_IsNT;
@@ -12,10 +12,15 @@ extern bool g_IsNT;
namespace NWindows {
+#ifndef UNDER_CE
static UString GetQuotedString(const UString &s)
{
- return UString(L'\"') + s + UString(L'\"');
+ UString s2 = L'\"';
+ s2 += s;
+ s2 += L'\"';
+ return s2;
}
+#endif
WRes CProcess::Create(LPCWSTR imageName, const UString &params, LPCWSTR curDir)
{
diff --git a/CPP/Windows/Process.h b/CPP/Windows/ProcessUtils.h
index 5b01c377..caf9a303 100755..100644
--- a/CPP/Windows/Process.h
+++ b/CPP/Windows/ProcessUtils.h
@@ -1,7 +1,7 @@
-// Windows/Process.h
+// Windows/ProcessUtils.h
-#ifndef __WINDOWS_PROCESS_H
-#define __WINDOWS_PROCESS_H
+#ifndef __WINDOWS_PROCESS_UTILS_H
+#define __WINDOWS_PROCESS_UTILS_H
#include <psapi.h>
diff --git a/CPP/Windows/PropVariant.cpp b/CPP/Windows/PropVariant.cpp
index 90212e08..caa4c319 100755..100644
--- 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
index d018034e..70907c88 100755..100644
--- 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
index f10b4ef2..92b355a4 100755..100644
--- 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
index 5582aaff..c9946144 100755..100644
--- 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
index 8b25375d..72685fe6 100755..100644
--- 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<wchar_t> buffer;
- buffer.SetCapacity(numChars);
- int pos = 0;
+ numChars += strings[i].Len() + 1;
+ CBuffer<wchar_t> 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
index f0561e68..32ee10b0 100755..100644
--- 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
index 781f03b3..eb28bd3b 100755..100644
--- 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
index ac9c5cd5..f0bdabf4 100755..100644
--- 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/SecurityUtils.cpp
index 6f5bcad3..99ac04bc 100755..100644
--- a/CPP/Windows/Security.cpp
+++ b/CPP/Windows/SecurityUtils.cpp
@@ -1,8 +1,8 @@
-// Windows/Security.cpp
+// Windows/SecurityUtils.cpp
#include "StdAfx.h"
-#include "Security.h"
+#include "SecurityUtils.h"
namespace NWindows {
namespace NSecurity {
diff --git a/CPP/Windows/Security.h b/CPP/Windows/SecurityUtils.h
index ba66de44..8966dfd3 100755..100644
--- a/CPP/Windows/Security.h
+++ b/CPP/Windows/SecurityUtils.h
@@ -1,7 +1,7 @@
-// Windows/Security.h
+// Windows/SecurityUtils.h
-#ifndef __WINDOWS_SECURITY_H
-#define __WINDOWS_SECURITY_H
+#ifndef __WINDOWS_SECURITY_UTILS_H
+#define __WINDOWS_SECURITY_UTILS_H
#include <NTSecAPI.h>
diff --git a/CPP/Windows/Shell.cpp b/CPP/Windows/Shell.cpp
index 010449fb..2eb1a960 100755..100644
--- 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
index d2b39acf..4bff18cf 100755..100644
--- a/CPP/Windows/Shell.h
+++ b/CPP/Windows/Shell.h
@@ -6,8 +6,9 @@
#include <windows.h>
#include <shlobj.h>
-#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
index 8b383c5b..1766dfa8 100755..100644
--- 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
index 5f86d1eb..5f86d1eb 100755..100644
--- a/CPP/Windows/Synchronization.cpp
+++ b/CPP/Windows/Synchronization.cpp
diff --git a/CPP/Windows/Synchronization.h b/CPP/Windows/Synchronization.h
index dc695f6f..dc695f6f 100755..100644
--- a/CPP/Windows/Synchronization.h
+++ b/CPP/Windows/Synchronization.h
diff --git a/CPP/Windows/System.cpp b/CPP/Windows/System.cpp
index 4bc8d2a3..4bc8d2a3 100755..100644
--- a/CPP/Windows/System.cpp
+++ b/CPP/Windows/System.cpp
diff --git a/CPP/Windows/System.h b/CPP/Windows/System.h
index e0067158..4133a7b3 100755..100644
--- 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
index 16a509d4..16a509d4 100755..100644
--- a/CPP/Windows/Thread.h
+++ b/CPP/Windows/Thread.h
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/Time.cpp b/CPP/Windows/TimeUtils.cpp
index 2cb028f9..0b50845b 100755..100644
--- a/CPP/Windows/Time.cpp
+++ b/CPP/Windows/TimeUtils.cpp
@@ -1,10 +1,9 @@
-// Windows/Time.cpp
+// Windows/TimeUtils.cpp
#include "StdAfx.h"
-#include "Windows/Defs.h"
-
-#include "Time.h"
+#include "Defs.h"
+#include "TimeUtils.h"
namespace NWindows {
namespace NTime {
@@ -195,9 +194,16 @@ bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day,
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
index 3ad29e6d..f1d4d95b 100755..100644
--- 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
index 729b0f24..2446499a 100755..100644
--- 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
index 5d5d06d7..d929b254 100755..100644
--- 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
index 55b52b1b..55b52b1b 100755..100644
--- a/DOC/7zFormat.txt
+++ b/DOC/7zFormat.txt
diff --git a/DOC/7zip.hhp b/DOC/7zip.hhp
index c171d255..5f412bff 100755..100644
--- 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
index 9dfded19..e3b63a10 100755..100644
--- 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
index 23010b8c..a805c949 100755..100644
--- 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
index 26a25947..3154a324 100755..100644
--- a/DOC/7zip.wxs
+++ b/DOC/7zip.wxs
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<?define VerMajor = "9" ?>
-<?define VerMinor = "22" ?>
+<?define VerMinor = "34" ?>
<?define VerBuild = "00" ?>
<?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?>
<?define MmHex = "0$(var.VerMajor)$(var.VerMinor)" ?>
@@ -206,10 +206,6 @@
Value="Apartment" />
</Component>
- <Component Id="CmdLine" Guid="$(var.CompCmdLine)" DiskId="1" Win64="$(var.Is64)">
- <File Id="_7z.exe" Name="7z.exe" />
- </Component>
-
<Component Id="Gui" Guid="$(var.CompGui)" DiskId="1" Win64="$(var.Is64)">
<File Id="_7zG.exe" Name="7zG.exe" />
</Component>
@@ -218,6 +214,10 @@
<File Id="_7z.dll" Name="7z.dll" />
</Component>
+ <Component Id="CmdLine" Guid="$(var.CompCmdLine)" DiskId="1" Win64="$(var.Is64)">
+ <File Id="_7z.exe" Name="7z.exe" />
+ </Component>
+
<Component Id="GuiSfx" Guid="$(var.CompGuiSfx)" DiskId="1" Win64="$(var.Is64)">
<File Id="_7z.sfx" Name="7z.sfx" />
</Component>
@@ -244,6 +244,7 @@
<Component Id="Lang" Guid="$(var.CompLang)" DiskId="1" Win64="$(var.Is64)">
<File Id="en.ttt" Name="en.ttt" />
<File Id="af.txt" Name="af.txt" />
+ <File Id="an.txt" Name="an.txt" />
<File Id="ar.txt" Name="ar.txt" />
<File Id="ast.txt" Name="ast.txt" />
<File Id="az.txt" Name="az.txt" />
@@ -269,6 +270,7 @@
<File Id="fr.txt" Name="fr.txt" />
<File Id="fur.txt" Name="fur.txt" />
<File Id="fy.txt" Name="fy.txt" />
+ <File Id="ga.txt" Name="ga.txt" />
<File Id="gl.txt" Name="gl.txt" />
<File Id="gu.txt" Name="gu.txt" />
<File Id="he.txt" Name="he.txt" />
@@ -282,6 +284,7 @@
<File Id="it.txt" Name="it.txt" />
<File Id="ja.txt" Name="ja.txt" />
<File Id="ka.txt" Name="ka.txt" />
+ <File Id="kaa.txt" Name="kaa.txt" />
<File Id="kk.txt" Name="kk.txt" />
<File Id="ko.txt" Name="ko.txt" />
<File Id="ku.txt" Name="ku.txt" />
@@ -292,6 +295,8 @@
<File Id="lv.txt" Name="lv.txt" />
<File Id="mk.txt" Name="mk.txt" />
<File Id="mn.txt" Name="mn.txt" />
+ <File Id="mng.txt" Name="mng.txt" />
+ <File Id="mng2.txt" Name="mng2.txt" />
<File Id="mr.txt" Name="mr.txt" />
<File Id="ms.txt" Name="ms.txt" />
<File Id="ne.txt" Name="ne.txt" />
diff --git a/DOC/License.txt b/DOC/License.txt
index a6a72185..a6a72185 100755..100644
--- a/DOC/License.txt
+++ b/DOC/License.txt
diff --git a/DOC/Methods.txt b/DOC/Methods.txt
index f52e7c31..ede83041 100755..100644
--- 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
index 4c389012..4c389012 100755..100644
--- a/DOC/copying.txt
+++ b/DOC/copying.txt
diff --git a/DOC/history.txt b/DOC/history.txt
index 64ce04ae..27a0e6c4 100755..100644
--- 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<ISequentialInStream>
+ OutBuffer.h: COutBuffer uses ISequentialOutStream *_stream; instead of CMyComPtr<ISequentialOutStream>
+
+
+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
index 77e5b616..8bd4bf94 100755..100644
--- 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
index cc138f67..ec0d4716 100755..100644
--- 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
index 5f78b728..5f78b728 100755..100644
--- a/DOC/unRarLicense.txt
+++ b/DOC/unRarLicense.txt